@@ -55,7 +55,6 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
data = JSON.stringify(request.data)
|
||||
} else {
|
||||
console.log(request.data)
|
||||
const formData = new FormData();
|
||||
Object.keys(request.data).forEach(key => {
|
||||
const value = request.data[key]
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
"declarativeNetRequest",
|
||||
"declarativeNetRequestWithHostAccess",
|
||||
"declarativeNetRequestFeedback",
|
||||
"activeTab"
|
||||
"activeTab",
|
||||
"fileSystemProvider"
|
||||
],
|
||||
"declarative_net_request": {
|
||||
"rule_resources": [
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 3,
|
||||
"name": "TEMU助手",
|
||||
"description": "TEMU助手 - 自动化提高生产效率",
|
||||
"version": "3.3.0",
|
||||
"version": "3.3.1",
|
||||
"background": {
|
||||
"service_worker": "/background.js"
|
||||
},
|
||||
@@ -32,7 +32,8 @@
|
||||
"declarativeNetRequest",
|
||||
"declarativeNetRequestWithHostAccess",
|
||||
"declarativeNetRequestFeedback",
|
||||
"activeTab"
|
||||
"activeTab",
|
||||
"fileSystemProvider"
|
||||
],
|
||||
"declarative_net_request": {
|
||||
"rule_resources": [
|
||||
|
||||
@@ -110,6 +110,11 @@ const router = new VueRouter({
|
||||
name: 'copyProductAliExpress',
|
||||
component: () => import('../view/product/CopyProductAliExpress.vue')
|
||||
},
|
||||
{
|
||||
path: 'batchUpload',
|
||||
name: 'batchUpload',
|
||||
component: () => import('../view/product/BatchUpload.vue')
|
||||
},
|
||||
{
|
||||
path: 'niubiCopy',
|
||||
name: 'niubiCopy',
|
||||
@@ -222,6 +227,11 @@ const router = new VueRouter({
|
||||
name: 'logisticFee',
|
||||
component: () => import('../view/sale/LogisticFee.vue')
|
||||
},
|
||||
{
|
||||
path: 'billStat',
|
||||
name: 'billStat',
|
||||
component: () => import('../view/sale/ExportBillStatTemu.vue')
|
||||
},
|
||||
{
|
||||
path: 'costManageShein',
|
||||
name: 'costManageShein',
|
||||
@@ -272,6 +282,12 @@ const router = new VueRouter({
|
||||
name: 'purchaseOrderListShein',
|
||||
component: () => import('../view/shein/PurchaseOrderListShein.vue')
|
||||
},
|
||||
{
|
||||
path: 'syncDataTemu',
|
||||
name: 'syncDataTemu',
|
||||
component: () => import('../view/data/SyncDataTemu.vue')
|
||||
},
|
||||
|
||||
// {
|
||||
// path: 'statistics',
|
||||
// name: 'statistics',
|
||||
@@ -338,6 +354,14 @@ const router = new VueRouter({
|
||||
title: '注册'
|
||||
},
|
||||
component: () => import('../view/login/Register.vue')
|
||||
},
|
||||
{
|
||||
path: '/forget',
|
||||
name: 'forget',
|
||||
meta: {
|
||||
title: '注册'
|
||||
},
|
||||
component: () => import('../view/login/Forget.vue')
|
||||
}
|
||||
],
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
|
||||
@@ -19,8 +19,29 @@ export function getImageMd5(imageUrl) {
|
||||
});
|
||||
}
|
||||
|
||||
export async function uploadImage(folderId, imageUrl, mallId) {
|
||||
let res1 = await getImageMd5(imageUrl)
|
||||
export function getImageMd5Local(file) {
|
||||
return new Promise((resolve) => {
|
||||
var reader = new FileReader()
|
||||
// 读取Blob对象的内容
|
||||
reader.onloadend = function () {
|
||||
/*const spark = new SparkMd5.ArrayBuffer()
|
||||
console.log(reader.result)
|
||||
spark.append(reader.result);*/
|
||||
const md5 = SparkMd5.hash(reader.result)
|
||||
resolve({md5, fileName: file.name});
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
})
|
||||
}
|
||||
|
||||
export async function uploadImage(folderId, imageUrl, mallId, local = false) {
|
||||
let res1
|
||||
if (local) {
|
||||
res1 = await getImageMd5Local(imageUrl)
|
||||
imageUrl = URL.createObjectURL(imageUrl)
|
||||
} else {
|
||||
res1 = await getImageMd5(imageUrl)
|
||||
}
|
||||
let detailList = []
|
||||
detailList.push({
|
||||
materialMd5: res1.md5,
|
||||
@@ -35,6 +56,7 @@ export async function uploadImage(folderId, imageUrl, mallId) {
|
||||
createDetailList: detailList,
|
||||
folderId: folderId
|
||||
}})
|
||||
await sleepSync(200)
|
||||
|
||||
if (res2.success) {
|
||||
if (res2.result.responseDetailList[0].alreadyExists) {
|
||||
@@ -48,6 +70,7 @@ export async function uploadImage(folderId, imageUrl, mallId) {
|
||||
bucket_tag: "product-material-tag"
|
||||
}
|
||||
})
|
||||
await sleepSync(200)
|
||||
|
||||
let res4 = await sendChromeAPIMessage({
|
||||
url: 'https://file.kuajingmaihuo.com/api/galerie/v3/store_image?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag',
|
||||
@@ -58,6 +81,7 @@ export async function uploadImage(folderId, imageUrl, mallId) {
|
||||
upload_sign: res3.result.signature
|
||||
}
|
||||
})
|
||||
await sleepSync(200)
|
||||
|
||||
let res5 = await sendChromeAPIMessage({
|
||||
url: 'marvel-mms/cn/api/kiana/gmp/bg/phoenix/api/material/edit',
|
||||
@@ -76,3 +100,7 @@ export async function uploadImage(folderId, imageUrl, mallId) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function sleepSync(milliseconds) {
|
||||
return new Promise(resolve => setTimeout(resolve, milliseconds));
|
||||
}
|
||||
@@ -26,7 +26,8 @@ export function transform(leftData) {
|
||||
propName: leftData.productPropertyList[i].propName,
|
||||
refPid: leftData.productPropertyList[i].refPid,
|
||||
vid: leftData.productPropertyList[i].vid,
|
||||
controlType: 1,
|
||||
controlType: leftData.productPropertyList[i].controlType || 1,
|
||||
numberInputValue: leftData.productPropertyList[i].numberInputValue || "",
|
||||
pid: leftData.productPropertyList[i].pid,
|
||||
templatePid: leftData.productPropertyList[i].templatePid,
|
||||
valueExtendInfo: leftData.productPropertyList[i].valueExtendInfo
|
||||
@@ -65,7 +66,7 @@ export function transform(leftData) {
|
||||
rightSkcItem.previewImgUrls = leftSkc[i].previewImgUrls;
|
||||
rightSkcItem.productSkcCarouselImageI18nReqs = leftSkc[i].productSkcCarouselImageI18nVOList;
|
||||
rightSkcItem.extCode = leftSkc[i].extCode;
|
||||
rightSkcItem.mainProductSkuSpecReqs = [
|
||||
rightSkcItem.mainProductSkuSpecReqs = leftSkc[i].mainProductSkuSpec || [
|
||||
{
|
||||
"parentSpecId": 0,
|
||||
"parentSpecName": "",
|
||||
@@ -83,6 +84,12 @@ export function transform(leftData) {
|
||||
rightSkuItem.extCode = leftSkuItem.extCode;
|
||||
rightSkuItem.supplierPrice = leftSkuItem.supplierPrice;
|
||||
rightSkuItem.currencyType = leftSkuItem.currencyType;
|
||||
rightSkuItem.productSkuSuggestedPriceReq = leftSkuItem.productSkuSuggestedPrice;
|
||||
rightSkuItem.productSkuMultiPackReq = leftSkuItem.productSkuMultiPack;
|
||||
if (rightSkuItem.productSkuMultiPackReq) {
|
||||
delete rightSkuItem.productSkuMultiPackReq.productSkuNetContent
|
||||
}
|
||||
rightSkuItem.productSkuMultiPackReq.productSkuNetContentReq = {}
|
||||
rightSkuItem.productSkuSpecReqs = leftSkuItem.productSkuSpecList;
|
||||
productSpecPropertyReqs.push({
|
||||
"parentSpecId": leftSkuItem.productSkuSpecList[0].parentSpecId,
|
||||
@@ -127,6 +134,7 @@ export function transform(leftData) {
|
||||
rightData.materialImgUrl = leftData.materialImgUrl;
|
||||
rightData.goodsLayerDecorationReqs = leftData.goodsLayerDecorationVOList;
|
||||
rightData.sizeTemplateIds = !leftData.sizeTemplateIds ? []: leftData.sizeTemplateIds;
|
||||
rightData.sizeTemplateId = leftData.sizeTemplateId || 0;
|
||||
rightData.showSizeTemplateIds = !leftData.showSizeTemplateIds ? []: leftData.showSizeTemplateIds;
|
||||
rightData.goodsModelReqs = !leftData.goodsModelList ? []: leftData.goodsModelList;
|
||||
rightData.productWhExtAttrReq = {
|
||||
@@ -139,6 +147,9 @@ export function transform(leftData) {
|
||||
rightData.productCarouseVideoReqList = leftData.carouseVideoVOList;
|
||||
rightData.goodsAdvantageLabelTypes = leftData.goodsAdvantageLabelVOList;
|
||||
rightData.productDetailVideoReqList = leftData.detailVideoVOList;
|
||||
if (leftData.productSpecPropertyVOS) {
|
||||
rightData.productSpecPropertyReqs = leftData.productSpecPropertyVOS
|
||||
}
|
||||
rightData.productOuterPackageImageReqs = [];
|
||||
for (let i = 0;i < leftData.outerPackageImages.length; i++) {
|
||||
rightData.productOuterPackageImageReqs.push({
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="sign">签到</el-button>
|
||||
<!--<el-button type="button" :class="'el-button el-button--primary'" @click="openFolder">打开文件夹</el-button>-->
|
||||
<el-tooltip class="item" effect="dark" content="用户激活" placement="top">
|
||||
<div class="left" @click="toActive">
|
||||
<span>会员信息:</span>
|
||||
@@ -72,6 +73,7 @@
|
||||
<el-menu-item index="/productList">商品列表</el-menu-item>
|
||||
<el-menu-item index="/copyProduct">商品复制</el-menu-item>
|
||||
<el-menu-item index="/findSeller">查找买手</el-menu-item>
|
||||
<!--<el-menu-item index="/batchUpload">批量上品</el-menu-item>-->
|
||||
<el-menu-item v-if="$store.state.userInfo.phone == '18610967550' || $store.state.userInfo.phone == '18571466720'" index="/draft">
|
||||
草稿箱管理
|
||||
</el-menu-item>
|
||||
@@ -138,6 +140,7 @@
|
||||
<el-menu-item index="/afterSaleDeductStat">售后赔付统计</el-menu-item>
|
||||
<el-menu-item index="/priceAdjustment">调价管理</el-menu-item>
|
||||
<el-menu-item index="/logisticFee">物流统计</el-menu-item>
|
||||
<el-menu-item index="/billStat">账务明细统计</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-submenu index="/shein">
|
||||
<template slot="title">
|
||||
@@ -159,6 +162,13 @@
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/saleStatShein">商家账单统计</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-submenu index="/dataManager" v-if="$store.state.userInfo.phone == '18571466720'">
|
||||
<template slot="title">
|
||||
<i class="el-icon-s-data"></i>
|
||||
<span slot="title">数据管理</span>
|
||||
</template>
|
||||
<el-menu-item index="/syncDataTemu">数据同步(TEMU)</el-menu-item>
|
||||
</el-submenu>
|
||||
<el-menu-item index="/info">
|
||||
<i class="el-icon-info"></i>
|
||||
<span slot="title">弹窗消息</span>
|
||||
@@ -359,6 +369,30 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
async openFolder() {
|
||||
console.log(22)
|
||||
let fileList = []
|
||||
const res = await window.showDirectoryPicker({})
|
||||
const detalAction = async (obj) => {
|
||||
if (obj.entries) {
|
||||
const dirs = obj.entries()
|
||||
for await (const entry of dirs) {
|
||||
if (entry[1].entries) {
|
||||
detalAction(entry[1])
|
||||
} else {
|
||||
fileList.push({
|
||||
name: entry[0],
|
||||
path: obj.name,
|
||||
fileHandle: entry[1],
|
||||
file: await entry[1].getFile()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
await detalAction(res);
|
||||
console.log("--fileList--", fileList)
|
||||
},
|
||||
gotoKefu() {
|
||||
window.open('https://work.weixin.qq.com/kfid/kfcaa4208f661131eba', '_blank')
|
||||
},
|
||||
|
||||
@@ -232,6 +232,11 @@ import BiVueMindmap from "bi-vue-mindmap";
|
||||
parentId: "01010104",
|
||||
title: "物流统计:对应“履约服务账单->明细->缴费记录”,以及“发货单列表->物流计费重核实”,统计一段时期内物流费用,以及货物重量,物流费用分布"
|
||||
},
|
||||
{
|
||||
id: "0101010408",
|
||||
parentId: "01010104",
|
||||
title: "账务明细统计:对应“账户资金->对账中心->账务明细”,真实统计一段时间内的实际收入,以及各种类型的支出,汇总统计"
|
||||
},
|
||||
{
|
||||
id: "01010105",
|
||||
parentId: "010101",
|
||||
|
||||
359
src/view/data/SyncDataTemu.vue
Normal file
359
src/view/data/SyncDataTemu.vue
Normal file
@@ -0,0 +1,359 @@
|
||||
<template>
|
||||
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="数据同步(TEMU)"
|
||||
isShowBottomBorder>
|
||||
</ai-title>
|
||||
|
||||
<template slot="content">
|
||||
<el-card class="box-card">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>店铺列表</span>
|
||||
</div>
|
||||
<div>
|
||||
<el-checkbox :indeterminate="isMallIndeterminate" v-model="checkAllMall" @change="handleCheckAllMallChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;"></div>
|
||||
<el-checkbox-group v-model="checkMallList" @change="handleCheckedMallChange">
|
||||
<el-checkbox v-for="mall in $store.state.mallList" style="width: 300px; margin-right: 0px" :label="mall.mallId" :key="mall.mallId">{{mall.isSemiManagedMall ? mall.mallName + '(半托管)': mall.mallName}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card class="box-card" style="margin-top: 5px;">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>同步操作</span>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<label style="width:90px">时间范围:</label>
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
:picker-options="pickerOptions">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<br>
|
||||
<el-checkbox :indeterminate="isOptionIndeterminate" v-model="checkAllOptions" @change="handleCheckAllOptionChange">全选</el-checkbox>
|
||||
<div style="margin: 15px 0;"></div>
|
||||
<el-checkbox-group v-model="checkOptionList" @change="handleCheckedOptionChange">
|
||||
<el-checkbox v-for="option in options" style="width: 300px; margin-right: 0px" :label="option.value" :key="option.value">{{option.label}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</el-card>
|
||||
<div style="display: grid; grid-template-columns: 1fr; gap: 16px; margin-top: 10px;">
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="sync()">同步</el-button>
|
||||
<!--<el-button type="button" :class="'el-button el-button--primary'" @click="toSyncWaitDeliveryOrder()">同步“待仓库收货”发货单</el-button>
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="toSyncDeliveryOrder()">同步历史发货单</el-button>
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="toBeginCollectResource()">采集资源位</el-button>-->
|
||||
</div>
|
||||
<el-card class="box-card" style="margin-top: 5px;">
|
||||
<div slot="header" class="clearfix">
|
||||
<span>日志输出</span>
|
||||
</div>
|
||||
<div id="log-container" v-html="logsContent" style="height: 500px; background-color: black; overflow-y: scroll; border: 1px solid #000; padding: 5px; color: white"></div>
|
||||
</el-card>
|
||||
</template>
|
||||
</ai-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Message } from 'element-ui'
|
||||
import {sendChromeAPIMessage} from '@/api/chromeApi'
|
||||
import {timestampToTime} from '@/utils/date'
|
||||
|
||||
export default {
|
||||
name: 'SyncDataTemu',
|
||||
|
||||
data () {
|
||||
return {
|
||||
isLoading: false,
|
||||
categoryList: [],
|
||||
checkAllMall: false,
|
||||
checkAllOptions: false,
|
||||
checkMallList: [],
|
||||
checkOptionList: [],
|
||||
isMallIndeterminate: false,
|
||||
isOptionIndeterminate: false,
|
||||
mallList: [],
|
||||
currentIndex: 0,
|
||||
pageSize: 100,
|
||||
pageNo: 1,
|
||||
syncProductData: [],
|
||||
deliveryOrderList: [],
|
||||
|
||||
currentWaitDeliveryIndex: 0,
|
||||
waitDeliveryData: [],
|
||||
|
||||
options: [
|
||||
{label: '同步已上架商品列表', value: 0},
|
||||
{label: '同步今日待收货发货单', value: 1},
|
||||
{label: '同步今日销售数据', value: 2},
|
||||
{label: '同步SKU历史销售数据', value: 3}
|
||||
],
|
||||
|
||||
dateRange: [new Date(), new Date()],
|
||||
pickerOptions: {
|
||||
disabledDate(time) {
|
||||
return time.getTime() > Date.now()
|
||||
}
|
||||
},
|
||||
|
||||
logsList: [],
|
||||
|
||||
reqListData: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
computed: {
|
||||
logsContent() {
|
||||
return this.logsList.join('<br>')
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCheckAllMallChange(val) {
|
||||
if (val) {
|
||||
this.checkMallList = this.mallList.map(item => {
|
||||
return item.mallId
|
||||
})
|
||||
} else {
|
||||
this.checkMallList = []
|
||||
}
|
||||
this.isMallIndeterminate = false;
|
||||
},
|
||||
handleCheckedMallChange(value) {
|
||||
let checkedCount = value.length;
|
||||
this.checkAllMall = checkedCount === this.mallList.length;
|
||||
this.isMallIndeterminate = checkedCount > 0 && checkedCount < this.mallList.length;
|
||||
},
|
||||
handleCheckAllOptionChange(val) {
|
||||
if (val) {
|
||||
this.checkOptionList = this.options.map(item => {
|
||||
return item.value
|
||||
})
|
||||
} else {
|
||||
this.checkOptionList = []
|
||||
}
|
||||
this.isOptionIndeterminate = false;
|
||||
},
|
||||
handleCheckedOptionChange(value) {
|
||||
let checkedCount = value.length;
|
||||
this.checkAllOptions = checkedCount === this.options.length;
|
||||
this.isOptionIndeterminate = checkedCount > 0 && checkedCount < this.options.length;
|
||||
},
|
||||
async sync() {
|
||||
if (this.checkMallList.length == 0) {
|
||||
Message.error("请选择要同步的店铺")
|
||||
return
|
||||
}
|
||||
if (this.checkOptionList.length == 0) {
|
||||
Message.error("请选择要同步的操作")
|
||||
return
|
||||
}
|
||||
this.isLoading = true
|
||||
for (let i = 0; i < this.checkOptionList.length; i++) {
|
||||
this.pageNo = 1
|
||||
if (this.checkOptionList[i] == 0) { // 同步商品
|
||||
for (let j = 0; j < this.checkMallList.length; j++) {
|
||||
let mallInfo = this.$store.state.mallList.filter(item => {
|
||||
return item.mallId == this.checkMallList[j]
|
||||
})
|
||||
let mallName = mallInfo[0].mallName
|
||||
this.syncProductData = []
|
||||
await this.syncProduct(this.checkMallList[j], mallName)
|
||||
}
|
||||
}
|
||||
if (this.checkOptionList[i] == 1) { // 同步待发货发货单
|
||||
for (let j = 0; j < this.checkMallList.length; j++) {
|
||||
let mallInfo = this.$store.state.mallList.filter(item => {
|
||||
return item.mallId == this.checkMallList[j]
|
||||
})
|
||||
let mallName = mallInfo[0].mallName
|
||||
this.deliveryOrderList = []
|
||||
await this.syncDeliveryOrder(this.checkMallList[i], mallName)
|
||||
}
|
||||
}
|
||||
if (this.checkOptionList[i] == 2) { // 同步今日销售数据
|
||||
for (let j = 0; j < this.checkMallList.length; j++) {
|
||||
this.reqListData = []
|
||||
await this.syncTodaySaleData(this.checkMallList[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
this.isLoading = false
|
||||
},
|
||||
async syncProduct(mallId, mallName) {
|
||||
let res = await sendChromeAPIMessage({url: 'bg-visage-mms/product/skc/pageQuery',
|
||||
anti:true,
|
||||
needMallId: true,
|
||||
mallId: mallId,
|
||||
data: {
|
||||
pageSize: this.pageSize,
|
||||
page: this.pageNo,
|
||||
skcSiteStatus: 1
|
||||
}
|
||||
})
|
||||
if (res.errorCode == 1000000) {
|
||||
res.result.pageItems.map(item => {
|
||||
let temp = {
|
||||
mallId: mallId,
|
||||
mallName: mallName,
|
||||
productName: item.productName,
|
||||
spu: item.productId,
|
||||
skc: item.productSkcId,
|
||||
skcCode: item.extCode,
|
||||
createTime: timestampToTime(item.createdAt)
|
||||
}
|
||||
|
||||
item.productSkuSummaries.map(item1 => {
|
||||
let temp1 = {
|
||||
...temp,
|
||||
skuCode: item1.extCode,
|
||||
sku: item1.productSkuId,
|
||||
mainPic: item1.thumbUrl,
|
||||
price: item1.supplierPrice /100
|
||||
}
|
||||
let specArr = item1.productSkuSpecList.map(item2 => {
|
||||
return item2.specName
|
||||
})
|
||||
temp1.skuSpec = specArr.join(',')
|
||||
|
||||
this.syncProductData.push(temp1)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
if (res.result.pageItems.length == this.pageSize) {
|
||||
this.pageNo ++
|
||||
await this.syncProduct(mallId, mallName)
|
||||
} else {
|
||||
this.$http.post('/api/stock/product/addBatch', this.syncProductData
|
||||
).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.logs(mallName, '已上架商品', true)
|
||||
} else {
|
||||
this.logs(mallName, '已上架商品', false)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.logs(mallName, '已上架商品', false)
|
||||
}
|
||||
},
|
||||
async syncDeliveryOrder(mallId, mallName) {
|
||||
let now = new Date()
|
||||
now.setHours(0, 0, 0, 0)
|
||||
let start = now.getTime()
|
||||
let end = start + 86400*1000 - 1000
|
||||
|
||||
let res = await sendChromeAPIMessage({url: 'bgSongbird-api/supplier/deliverGoods/management/pageQueryDeliveryBatch',
|
||||
anti:true,
|
||||
needMallId: true,
|
||||
mallId: mallId,
|
||||
data: {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
productLabelCodeStyle: 0,
|
||||
onlyTaxWarehouseWaitApply: false,
|
||||
deliverTimeFrom: start,
|
||||
deliverTimeTo: end,
|
||||
status: 1
|
||||
}
|
||||
})
|
||||
if (res.errorCode == 1000000) {
|
||||
res.result.list.map(item => {
|
||||
let temp = {
|
||||
mallId: mallId,
|
||||
mallName: mallName,
|
||||
subWarehouseName: item.subWarehouseName,
|
||||
expressCompany: item.expressCompany,
|
||||
deliveryOrderSn: item.deliveryOrderSn
|
||||
}
|
||||
|
||||
item.deliveryOrderList.map(item1 => {
|
||||
temp = {
|
||||
...temp,
|
||||
productName: item1.subPurchaseOrderBasicVO.productName,
|
||||
skc: item1.productSkcId,
|
||||
skcCode: item1.skcExtCode,
|
||||
isFirst: item1.subPurchaseOrderBasicVO.isFirst ? 1: 0
|
||||
}
|
||||
|
||||
item1.packageDetailList.map(item2 => {
|
||||
temp = {
|
||||
...temp,
|
||||
sku: item2.productSkuId,
|
||||
num: item2.skuNum
|
||||
}
|
||||
})
|
||||
this.deliveryOrderList.push(temp)
|
||||
})
|
||||
})
|
||||
|
||||
if (res.result.list.length == this.pageSize) {
|
||||
this.pageNo ++
|
||||
await this.syncDeliveryOrder(mallId, mallName)
|
||||
} else {
|
||||
this.$http.post('/api/stock/orderInfo/addBatch', this.deliveryOrderList
|
||||
).then(res => {
|
||||
if (res.code == 0) {
|
||||
this.logs(mallName, '今日待收货发货单', true)
|
||||
} else {
|
||||
this.logs(mallName, '今日待收货发货单', false)
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.logs(mallName, '今日待收货发货单', false)
|
||||
}
|
||||
},
|
||||
async syncTodaySaleData(mallId) {
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'marvel-mms/cn/api/kiana/venom/sales/management/list',
|
||||
needMallId: true,
|
||||
mallId: mallId,
|
||||
data: {
|
||||
pageNo: this.pageNo,
|
||||
pageSize: this.pageSize,
|
||||
isLack: 0,
|
||||
priceAdjustRecentDays: 7
|
||||
}})
|
||||
if (res.errorCode == 1000000) {
|
||||
for(let i = 0;i < res.result.subOrderList.length; i++) {
|
||||
let item = res.result.subOrderList[i]
|
||||
for(let j = 0;j < item.skuQuantityDetailList.length; j++) {
|
||||
this.reqListData.push({
|
||||
mallId: mallId,
|
||||
sku: item.skuQuantityDetailList[j].productSkuId,
|
||||
saleNum: item.skuQuantityDetailList[j].todaySaleVolume,
|
||||
salePrice: item.skuQuantityDetailList[j].supplierPrice / 100
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pageSize == res.result.subOrderList.length) {
|
||||
this.pageNo ++
|
||||
await this.syncTodaySaleData(mallId)
|
||||
} else {
|
||||
await this.$http.post('http://192.168.1.199:8080/jeecg-boot/eshop/saleManage/addBatch', this.reqListData)
|
||||
}
|
||||
}
|
||||
},
|
||||
logs(mallName, subject, flag) {
|
||||
if (flag) {
|
||||
this.logsList.unshift(`【${mallName}】${subject}<b style='color: green'>同步成功</b>`)
|
||||
} else {
|
||||
this.logsList.unshift(`【${mallName}】${subject}<b style='color: red'>同步失败</b>`)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
380
src/view/login/Forget.vue
Normal file
380
src/view/login/Forget.vue
Normal file
@@ -0,0 +1,380 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<div class="body">
|
||||
<div class="middle">
|
||||
<div class="right">
|
||||
<div class="tab">
|
||||
<h2 class="active" @click="currIndex = 0">找回密码</h2>
|
||||
</div>
|
||||
<el-form :model="form" label-position="top" ref="form" label-width="100px" class="form">
|
||||
<el-form-item
|
||||
prop="phone"
|
||||
:rules="[{ required: true, message: '请输入手机号', trigger: 'blur' }, { validator: phoneReg, trigger: 'blur' }]">
|
||||
<el-input maxlength="11" placeholder="请输入手机号" v-model="form.phone"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="password"
|
||||
:rules="[{ required: true, message: '请输入密码', trigger: 'blur' }]">
|
||||
<el-input placeholder="请输入密码" type="password" v-model="form.password"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="repassword"
|
||||
:rules="[{ required: true, message: '请再次输入密码', trigger: 'blur' }]">
|
||||
<el-input placeholder="请再次输入密码" type="password" v-model="form.repassword"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="code" :rules="[{ required: true, message: '请输入验证码', trigger: 'blur' }]">
|
||||
<div class="code-item">
|
||||
<el-input style="width: 300px;" maxlength="4" placeholder="请输入验证码" v-model="form.code"></el-input>
|
||||
<span @click="getCode" :loading="btnLoading">{{ isStart ? time + ' S' : '发送验证码' }}</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-button type="primary" style="width: 100%" @click="login" :loading="btnLoading">重置设置</el-button>
|
||||
</el-form>
|
||||
<div class="login-footer">
|
||||
<div class="left">
|
||||
<i class="hover" @click="$router.back()">返回登录</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CryptoJS from 'crypto-js'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
password: '',
|
||||
repassword: '',
|
||||
code: '',
|
||||
phone: ''
|
||||
},
|
||||
phoneReg: (rule, value, callback) => {
|
||||
if (/^1[0-9]{10,10}$/.test(value)) {
|
||||
return callback()
|
||||
}
|
||||
|
||||
callback(new Error('手机号格式错误'))
|
||||
},
|
||||
timer: null,
|
||||
time: 60,
|
||||
isSend: false,
|
||||
isStart: false,
|
||||
isLoading: false,
|
||||
currIndex: 0,
|
||||
btnLoading: false,
|
||||
loginType: '0'
|
||||
}
|
||||
},
|
||||
|
||||
mounted () {
|
||||
},
|
||||
|
||||
methods: {
|
||||
login () {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.form.password != this.form.repassword) {
|
||||
this.$message.success('两次密码输入不一致');
|
||||
return;
|
||||
}
|
||||
this.btnLoading = true
|
||||
this.$http.post(`/api/malluser/forget`, null, {
|
||||
params: {
|
||||
...this.form
|
||||
}
|
||||
}, {
|
||||
headers: {
|
||||
Authorization: 'Basic cGM6cGM='
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success('注册成功')
|
||||
|
||||
setTimeout(() => {
|
||||
this.$router.replace('/login')
|
||||
}, 500)
|
||||
}
|
||||
|
||||
this.btnLoading = false
|
||||
}).catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
},
|
||||
encryptPhone (phone) {
|
||||
const u = navigator.userAgent
|
||||
const isIos = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
|
||||
var key = 'thanks,temulll11'
|
||||
var iv = CryptoJS.enc.Latin1.parse(key)
|
||||
var encrypted = CryptoJS.AES.encrypt(phone, iv, {
|
||||
iv: iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.ZeroPadding
|
||||
})
|
||||
|
||||
if (isIos) {
|
||||
return encodeURIComponent(encrypted.toString())
|
||||
} else {
|
||||
return encrypted.toString()
|
||||
}
|
||||
},
|
||||
|
||||
getCode () {
|
||||
if (this.isSend) {
|
||||
return this.$message.error('验证码已发送')
|
||||
}
|
||||
|
||||
this.$refs.form.validateField('phone', e => {
|
||||
if (!e) {
|
||||
let phone = this.encryptPhone(this.form.phone)
|
||||
this.isSend = true
|
||||
this.btnLoading = true
|
||||
this.$http.post(`/api/sms/getRegSmsCodeNew?phone=${phone}`, {}, {
|
||||
withoutToken: true
|
||||
}).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.$message.success('验证码发送成功')
|
||||
this.isStart = true
|
||||
this.timer = setInterval(() => {
|
||||
if (this.time === 0) {
|
||||
this.isSend = false
|
||||
this.isStart = false
|
||||
this.time = 60
|
||||
clearInterval(this.timer)
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
this.time = this.time - 1
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
this.btnLoading = false
|
||||
this.isSend = false
|
||||
}).catch(() => {
|
||||
this.isSend = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onChange (e) {
|
||||
this.$emit('change', e)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
|
||||
.body {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
background-color: #cdc8c8;
|
||||
// background: url(../../assets/images/login/login.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.middle {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 11;
|
||||
width: 1280px;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
& > .left {
|
||||
padding-top: 42px;
|
||||
font-family: MicrosoftYaHei;
|
||||
|
||||
p {
|
||||
line-height: 24px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 13px;
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
& > .right {
|
||||
width: 500px;
|
||||
padding: 63px 40px 42px;
|
||||
box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.06);
|
||||
background: #fff;
|
||||
border-radius: 16px;
|
||||
backdrop-filter: blur(6px);
|
||||
overflow: hidden;
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
margin-bottom: 36px;
|
||||
padding-bottom: 17px;
|
||||
border-bottom: 1px solid #DCDFE6;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 81px;
|
||||
height: 2px;
|
||||
background: #1FBAD6;
|
||||
content: ' ';
|
||||
transition: all ease-in-out 0.3s;
|
||||
}
|
||||
|
||||
&.tab-active:after {
|
||||
transform: translateX(138px);
|
||||
}
|
||||
|
||||
h2 {
|
||||
width: 81px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
font-family: SJsuqian;
|
||||
color: #000000;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: all ease 0.4s;
|
||||
|
||||
&.active, &:hover {
|
||||
color: #1FBAD6;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-right: 58px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-type {
|
||||
font-size: 14px;
|
||||
font-family: SJsuqian;
|
||||
text-align: center;
|
||||
color: #54657D;
|
||||
cursor: pointer;
|
||||
transition: all ease-in-out 0.4s;
|
||||
|
||||
&:hover {
|
||||
color: #1FBAD6;
|
||||
}
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 21px;
|
||||
margin-bottom: 38px;
|
||||
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
font-family: SJsuqian;
|
||||
color: #54657D;
|
||||
}
|
||||
|
||||
i {
|
||||
font-family: SJsuqian;
|
||||
color: #1FBAD6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .el-form {
|
||||
.el-input__inner {
|
||||
height: 48px;
|
||||
border-color: #DCDFE6;
|
||||
background-color: transparent;
|
||||
|
||||
&:focus, &:hover {
|
||||
border-color: #1FBAD6;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item.is-error .el-input__inner, .el-form-item.is-error .el-input__inner:focus, .el-form-item.is-error .el-textarea__inner, .el-form-item.is-error .el-textarea__inner:focus {
|
||||
border-color: #F56C6C;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
height: 48px;
|
||||
margin-top: 28px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.code-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
|
||||
span {
|
||||
width: 110px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
border-radius: 4px;
|
||||
transition: all cubic-bezier(0.215, 0.61, 0.355, 1) 0.3s;
|
||||
border: 1px solid #DCDFE6;
|
||||
|
||||
&:hover {
|
||||
border-color: #1FBAD6;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copyright {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
left: 50%;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
letter-spacing: 1px;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -24,9 +24,16 @@
|
||||
<span>没有账号?</span>
|
||||
<i class="hover" @click="$router.push('/register')">立即注册</i>
|
||||
</div>
|
||||
<div class="left" style="margin-left: 10px;">
|
||||
<span>忘记密码?</span>
|
||||
<i class="hover" @click="$router.push('/forget')">找回密码</i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="kefu" @click="gotoKefu">
|
||||
<label slot="reference" class="topBtn" title="联系客服"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -139,6 +146,9 @@
|
||||
|
||||
onChange (e) {
|
||||
this.$emit('change', e)
|
||||
},
|
||||
gotoKefu() {
|
||||
window.open('https://work.weixin.qq.com/kfid/kfcaa4208f661131eba', '_blank')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,4 +358,30 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#kefu {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
bottom: 40px;
|
||||
z-index: 999;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
#kefu .topBtn {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 40px 40px;
|
||||
-webkit-animation: wobble 250ms infinite;
|
||||
animation: wobble 250ms infinite;
|
||||
background-image: url('data:image/svg+xml;%20charset=utf8,%3Csvg%20t%3D%221575450105478%22%20class%3D%22icon%22%20viewBox%3D%220%200%201220%201024%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20p-id%3D%222883%22%20width%3D%2248%22%20height%3D%2248%22%3E%3Cpath%20d%3D%22M609.524%20103.522c-222.89%200-403.712%20178.472-403.712%20398.78%200%20220.31%20180.823%20398.782%20403.712%20398.782%20222.889%200%20403.712-178.473%20403.712-398.781%200-220.309-180.823-398.781-403.712-398.781v48.762c196.1%200%20354.95%20156.785%20354.95%20350.019s-158.85%20350.019-354.95%20350.019-354.95-156.785-354.95-350.02c0-193.233%20158.85-350.018%20354.95-350.018v-48.762z%22%20fill%3D%22%231296db%22%20p-id%3D%222884%22%3E%3C%2Fpath%3E%3Cpath%20d%3D%22M786.578%20916.34c166.45-69.217%20278.408-231.055%20278.408-414.035%200-248.026-203.847-449.219-455.457-449.219-251.619%200-455.457%20201.188-455.457%20449.22%200%2055.397%2010.152%20109.367%2029.718%20159.975%204.855%2012.56-1.39%2026.677-13.949%2031.533-12.56%204.855-26.677-1.39-31.532-13.949a490.396%20490.396%200%200%201-3.042-8.078c-1.85%200.077-3.711%200.116-5.581%200.116C58.06%20671.903%200%20614.597%200%20543.903c0-65.005%2049.09-118.69%20112.68-126.91C153.65%20182.56%20360.56%204.324%20609.528%204.324c248.962%200%20455.877%20178.24%20496.85%20412.67%2063.583%208.225%20112.669%2061.907%20112.669%20126.909%200%2070.694-58.06%20128-129.686%20128-1.89%200-3.771-0.04-5.642-0.119-47.536%20129.702-148.34%20235.841-279.493%20290.027-1.161%2033.464-29.012%2060.24-63.2%2060.24-34.925%200-63.237-27.944-63.237-62.416%200-34.471%2028.312-62.415%2063.237-62.415%2017.892%200%2034.048%207.333%2045.551%2019.12z%22%20fill%3D%22%231296db%22%20p-id%3D%222885%22%3E%3C%2Fpath%3E%3Cpath%20d%3D%22M609.528%20611.405c-58.933%200-112.056-10.644-158.472-28.342-16.123-6.147-30.211-12.702-42.138-19.208-6.926-3.777-11.447-6.59-13.437-7.972-19.24-13.373-44.428%205.446-37.059%2027.688%2035.296%20106.527%20136.054%20179.913%20251.106%20179.913%20115.05%200%20215.796-73.384%20251.092-179.913%207.37-22.243-17.82-41.062-37.06-27.687-1.99%201.383-6.51%204.195-13.434%207.972-11.926%206.505-26.012%2013.06-42.133%2019.207-46.413%2017.698-99.533%2028.342-158.465%2028.342z%22%20fill%3D%22%231296db%22%20p-id%3D%222886%22%3E%3C%2Fpath%3E%3C%2Fsvg%3E');
|
||||
}
|
||||
</style>
|
||||
|
||||
305
src/view/product/BatchUpload.vue
Normal file
305
src/view/product/BatchUpload.vue
Normal file
@@ -0,0 +1,305 @@
|
||||
<template>
|
||||
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="批量上品"
|
||||
:tips="`上传一件商品将消耗${coin}金币`"
|
||||
isShowBottomBorder>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<el-form :model="form" ref="form" label-width="180px" class="form">
|
||||
<el-divider content-position="left">模板来源</el-divider>
|
||||
<el-form-item label="模板店铺来源" style="width: 100%;" prop="sourceMallId" :rules="[{ required: true, message: '请选择模板店铺来源', trigger: 'blur' }]">
|
||||
<el-select style="width: 380px" v-model="form.sourceMallId" placeholder="请选择模板店铺来源">
|
||||
<el-option
|
||||
v-for="item in mallList"
|
||||
:key="item.mallId"
|
||||
:label="item.mallName"
|
||||
:value="item.mallId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
prop="sourceSpuId"
|
||||
label="模板SPU ID:"
|
||||
style="width: 480px"
|
||||
:rules="[{ required: true, message: '请输入模板SPU ID', trigger: 'blur' }]">
|
||||
<el-input size="small" placeholder="请输入模板SPU ID" v-model="form.sourceSpuId"></el-input>
|
||||
</el-form-item>
|
||||
<el-divider content-position="left">目标店铺</el-divider>
|
||||
<el-form-item label="店铺" style="width: 100%;" prop="targetMallId" :rules="[{ required: true, message: '请选择目标店铺', trigger: 'blur' }]">
|
||||
<el-select style="width: 380px" v-model="form.targetMallId" placeholder="请选择目标店铺">
|
||||
<el-option
|
||||
v-for="item in mallList"
|
||||
:key="item.mallId"
|
||||
:label="item.mallName"
|
||||
:value="item.mallId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="openFolder">选择文件夹</el-button>
|
||||
</el-form>
|
||||
</template>
|
||||
</ai-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Message } from 'element-ui'
|
||||
import {sendChromeAPIMessage} from '@/api/chromeApi'
|
||||
import {timestampToTime} from '@/utils/date'
|
||||
import {transform} from '@/utils/product'
|
||||
import { createFolderApi } from "@/utils/folder.js"
|
||||
import { uploadImage } from "@/utils/image.js"
|
||||
import { formatDate } from "@/utils/date.js"
|
||||
|
||||
export default {
|
||||
name: 'BatchUpload',
|
||||
|
||||
data () {
|
||||
return {
|
||||
form: {
|
||||
sourceMallId: '',
|
||||
sourceSpuId: '',
|
||||
targetMallId: ''
|
||||
},
|
||||
content: null,
|
||||
mallObj: null,
|
||||
folderId: null,
|
||||
successCount: 0,
|
||||
mainPicList: [],
|
||||
mainPicUrl: null,
|
||||
detailPicList: [],
|
||||
coin: 150,
|
||||
colConfigs: [
|
||||
{ slot: 'productName', label: '商品名称', width: '180px', align: 'left', fixed: 'left' },
|
||||
{ prop: 'category', label: '分类', width: '140px', align: 'left', fixed: 'left' },
|
||||
{ prop: 'productId', label: 'SPU ID', width: '120px', align: 'left' },
|
||||
{ prop: 'productSkcId', label: 'SKC ID', width: '120px', align: 'left' },
|
||||
{ prop: 'productSkuId', label: 'SKU ID', width: '120px', align: 'left' },
|
||||
{ prop: 'skcSiteStatus', label: '是否在售', width: '120px', align: 'left' },
|
||||
{ prop: 'extCode', label: 'SKC货号', width: '100px', align: 'left' },
|
||||
{ prop: 'skuExtCode', label: 'SKU货号', width: '160px', align: 'left' },
|
||||
{ prop: 'specName', label: 'SKU属性', width: '100px', align: 'left' },
|
||||
{ prop: 'skuStockQuantity', label: '库存', width: '100px', align: 'left' },
|
||||
{ prop: 'productCertAuditStatus', label: '资质上传状态', width: '120px', align: 'left' },
|
||||
{ prop: 'certPunishType', label: '合规下架风险', width: '120px', align: 'left' },
|
||||
{ prop: 'supplierPrice', label: '申报价格(CNY)', width: '180px', align: 'left' },
|
||||
{ prop: 'todaySalesVolume', label: '今日销量', width: '100px', align: 'left' },
|
||||
{ prop: 'createdAt', label: '上架时间', width: '160px', align: 'left' }
|
||||
],
|
||||
isLoading: false,
|
||||
tableData: [],
|
||||
currentIndex: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
mallList () {
|
||||
const filteredData = this.$store.state.mallList.filter(item => {
|
||||
return item.isSemiManagedMall == false
|
||||
})
|
||||
|
||||
return filteredData
|
||||
}
|
||||
},
|
||||
created () {
|
||||
},
|
||||
methods: {
|
||||
async openFolder() {
|
||||
this.$refs.form.validate(async (valid) => {
|
||||
if (valid) {
|
||||
let res1 = await sendChromeAPIMessage({
|
||||
url: 'bg-visage-mms/product/query',
|
||||
needMallId: true,
|
||||
mallId: this.form.sourceMallId,
|
||||
data: {
|
||||
productEditTaskUid: '',
|
||||
productId: this.form.sourceSpuId
|
||||
}})
|
||||
if (res1.errorCode == 1000000) {
|
||||
this.content = JSON.parse(transform(res1.result))
|
||||
this.mallObj = this.$store.state.mallList.filter(item => {
|
||||
return item.mallId == this.form.targetMallId
|
||||
})
|
||||
}
|
||||
this.successCount = 0
|
||||
this.mainPicList = []
|
||||
this.detailPicList = []
|
||||
this.folderId = await createFolderApi(formatDate(new Date()).split('-'), this.form.targetMallId)
|
||||
|
||||
const res = await window.showDirectoryPicker({})
|
||||
await this.dealAction("", res)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
async dealAction (root, obj) {
|
||||
console.log(obj)
|
||||
if (obj.entries) {
|
||||
let dirs = obj.entries()
|
||||
if (root == "") {
|
||||
let length = 0
|
||||
for await (const temp of dirs) {
|
||||
length ++
|
||||
}
|
||||
if (this.$store.state.userInfo.coin < length * this.coin) {
|
||||
Message.error("金币不足,请先充值金币")
|
||||
return
|
||||
}
|
||||
}
|
||||
if (root == '') {
|
||||
dirs = obj.entries()
|
||||
for await (const entry of dirs) {
|
||||
/*if (entry[1].kind == 'file') {
|
||||
let prefix = entry[0].split('.').pop()
|
||||
if (prefix == 'png' || prefix == 'jpg' || prefix == 'jpeg') {
|
||||
let file = await entry[1].getFile()
|
||||
let img = await uploadImage(this.folderId, file, this.form.targetMallId, true)
|
||||
this.mainPicUrl = img
|
||||
this.$sleepSync(500)
|
||||
}
|
||||
} else {*/
|
||||
if (entry[1].kind == 'directory') {
|
||||
await this.dealAction(obj.name + "/" + entry[0], entry[1])
|
||||
}
|
||||
//}
|
||||
}
|
||||
} else {
|
||||
this.mainPicList = []
|
||||
this.detailPicList = []
|
||||
await this.toUploadProduct(root, obj)
|
||||
}
|
||||
}
|
||||
},
|
||||
async toUploadProduct(root, obj) {
|
||||
const dirs = obj.entries()
|
||||
for await (const entry of dirs) {
|
||||
if (entry[1].kind == 'file') {
|
||||
let prefix = entry[0].split('.').pop()
|
||||
if (prefix == 'png' || prefix == 'jpg' || prefix == 'jpeg') {
|
||||
let file = await entry[1].getFile()
|
||||
let img = await uploadImage(this.folderId, file, this.form.targetMallId, true)
|
||||
this.mainPicUrl = img
|
||||
this.$sleepSync(200)
|
||||
}
|
||||
} else if (entry[0] != '详情图' && entry[1].kind == 'directory') {
|
||||
let tempList = await this.getPictureList(root + '/' + entry[0], entry[1])
|
||||
this.mainPicList.push({color: entry[0], imgList: tempList})
|
||||
} else if (entry[0] == '详情图' && entry[1].kind == 'directory') {
|
||||
this.detailPicList = await this.getPictureList(root + '/' + entry[0], entry[1])
|
||||
}
|
||||
|
||||
}
|
||||
if (this.mainPicList.length >= 0 && this.detailPicList.length >= 0) {
|
||||
await this.beginAddToDraft(obj.name)
|
||||
this.$sleepSync(200)
|
||||
}
|
||||
|
||||
},
|
||||
async getPictureList(root, obj) {
|
||||
const dirs = obj.entries()
|
||||
let images = []
|
||||
for await (const entry of dirs) {
|
||||
if (entry[1].kind == 'file') {
|
||||
let prefix = entry[0].split('.').pop()
|
||||
if (prefix == 'png' || prefix == 'jpg' || prefix == 'jpeg') {
|
||||
let file = await entry[1].getFile()
|
||||
let img = await uploadImage(this.folderId, file, this.form.targetMallId, true)
|
||||
if (null == img) {
|
||||
|
||||
} else {
|
||||
images.push({
|
||||
name: entry[0].split('.')[0],
|
||||
url: img
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
images.sort((a, b) => {
|
||||
if (!isNaN(a.name) && !isNaN(b.name)) {
|
||||
return (Number(a.name) - Number(b.name))
|
||||
} else {
|
||||
return a.name - b.name
|
||||
}
|
||||
})
|
||||
|
||||
return images
|
||||
},
|
||||
async beginAddToDraft(name) {
|
||||
let category = null
|
||||
let i = 1
|
||||
while(true) {
|
||||
if (!this.content['cat'+i+'Id']) {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
category = this.content['cat'+(i-1)+'Id']
|
||||
let data = {catId: category}
|
||||
this.content.personalizationSwitch = this.content.personalizationSwitch || 0
|
||||
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'bg-visage-mms/product/draft/add',
|
||||
needMallId: true,
|
||||
mallId: this.form.targetMallId,
|
||||
data: data})
|
||||
if (res.errorCode == 1000000) {
|
||||
let draftId = res.result.productDraftId
|
||||
this.content.productDraftId = draftId
|
||||
|
||||
// 变化部分
|
||||
this.content.productName = name
|
||||
this.content.materialImgUrl = this.mainPicList[0].imgList[0].url
|
||||
|
||||
for (let i = 0; i < this.content.productSkcReqs.length; i++) {
|
||||
for (let j = 0; j < this.mainPicList.length; j++) {
|
||||
if (this.content.productSkcReqs[i].mainProductSkuSpecReqs[0].specName == this.mainPicList[j].color) {
|
||||
this.content.productSkcReqs[i].previewImgUrls = this.mainPicList[j].imgList
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let res1 = await sendChromeAPIMessage({
|
||||
url: 'bg-visage-mms/product/draft/save',
|
||||
needMallId: true,
|
||||
mallId: this.form.targetMallId,
|
||||
data: {
|
||||
...this.content
|
||||
}})
|
||||
if (res1.errorCode == 1000000) {
|
||||
Message.success("商品【" + name + "】成功添加到草稿箱")
|
||||
} else {
|
||||
Message.error(res1.errorMsg)
|
||||
}
|
||||
} else {
|
||||
Message.error("【拼多多】" + res.errorMsg)
|
||||
}
|
||||
|
||||
await this.$sleepSync(500)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list {
|
||||
.title-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > div:first-child {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
::v-deep.ai-list {
|
||||
.ai-list__content--right-wrapper {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
padding: 0!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -295,14 +295,18 @@ import { saveAs } from 'file-saver'
|
||||
this.costDlgShow = true
|
||||
},
|
||||
importConfirm() {
|
||||
this.isLoading = true
|
||||
this.$refs.costForm.validate((valid) => {
|
||||
const data = new FormData()
|
||||
data.append('file', this.costForm.file[0].raw);
|
||||
this.$http.post(`/api/skuCost/importStock`, data).then(res => {
|
||||
if (res.code === 0) {
|
||||
this.costDlgShow = false
|
||||
this.isLoading = false
|
||||
this.$message.success('导入成功')
|
||||
this.getList()
|
||||
} else {
|
||||
this.isLoading = false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
428
src/view/sale/ExportBillStatTemu.vue
Normal file
428
src/view/sale/ExportBillStatTemu.vue
Normal file
@@ -0,0 +1,428 @@
|
||||
<template>
|
||||
<ai-list class="list" v-loading="isLoading" element-loading-text="拼命加载中" element-loading-spinner="el-icon-loading">
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="账务明细统计"
|
||||
tips="数据来源于“账户资金->对账中心->账务明细”"
|
||||
isShowBottomBorder>
|
||||
<template #rightBtn>
|
||||
<div class="title-right">
|
||||
<div>
|
||||
<label style="width:90px">时间选择:</label>
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd">
|
||||
</el-date-picker>
|
||||
</div>
|
||||
<div>
|
||||
<label style="width:90px">店铺:</label>
|
||||
<el-select v-model="mallId" placeholder="请选择" size="small">
|
||||
<el-option
|
||||
v-for="item in $store.state.mallList"
|
||||
:key="item.mallId"
|
||||
:label="item.mallName"
|
||||
:value="item.mallId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-button type="button" :class="'el-button el-button--primary'" @click="toBeginStat">开始统计</el-button>
|
||||
<el-button type="primary" icon="el-icon-download" @click="downloadPicture">下载图片</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
<div id="app-content">
|
||||
<ai-card title="数据概览" style="padding-bottom: 40px;">
|
||||
<el-divider content-position="center">收入概览</el-divider>
|
||||
<div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value-style="{color: 'red'}"
|
||||
:value="transIncome + nonSllerDuty"
|
||||
title="总收入"
|
||||
>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="transIncome"
|
||||
title="交易收入"
|
||||
>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:value="nonSllerDuty"
|
||||
:precision="2"
|
||||
title="非商责平台售后补贴金额"
|
||||
>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-divider content-position="center">支出概览</el-divider>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value-style="{color: 'red'}"
|
||||
:value="logisticAmount+customerOutcome+afterSaleAmount+eprAmount+withdrawAmount"
|
||||
title="总支出"
|
||||
></el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="logisticAmount"
|
||||
title="仓储综合服务费"
|
||||
></el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="customerOutcome"
|
||||
title="消费者退款金额"
|
||||
></el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="afterSaleAmount"
|
||||
title="消费者及履约保障-售后问题"
|
||||
>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="eprAmount"
|
||||
title="合规EPR物流包装环保费"
|
||||
>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="4">
|
||||
<div>
|
||||
<el-card shadow="always" class="amountItem">
|
||||
<el-statistic
|
||||
group-separator=","
|
||||
:precision="2"
|
||||
:value="withdrawAmount"
|
||||
title="提现"
|
||||
>
|
||||
</el-statistic>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</ai-card>
|
||||
</div>
|
||||
<ai-dialog
|
||||
title="提示"
|
||||
:visible.sync="isTipDlgShow"
|
||||
:close-on-click-modal="false"
|
||||
width="790px"
|
||||
customFooter
|
||||
@close="isDlgShow = false">
|
||||
<div style="display: block;height: 30px;">卖家中心出现图形验证码,请前往卖家中心“账户资金->对账中心->账务明细”,随机选择一条数据,点击“查看详情”,处理验证码</div>
|
||||
<div class="dialog-footer" slot="footer">
|
||||
<el-button @click="isTipDlgShow = false">取消</el-button>
|
||||
<el-button style="width: 180px;" @click="toGoon">已验证,继续统计</el-button>
|
||||
<el-button type="primary" @click="gotoValid">前往验证</el-button>
|
||||
</div>
|
||||
</ai-dialog>
|
||||
</template>
|
||||
|
||||
|
||||
</ai-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {sendChromeAPIMessage } from '@/api/chromeApi'
|
||||
import { Message } from 'element-ui'
|
||||
import html2canvas from 'html2canvas'
|
||||
|
||||
export default {
|
||||
name: 'ExportBillStatTemu',
|
||||
|
||||
data () {
|
||||
return {
|
||||
mallId: null,
|
||||
dateRange: null,
|
||||
|
||||
transIncome: 0.0,
|
||||
customerOutcome: 0.0,
|
||||
nonSllerDuty: 0.0,
|
||||
afterSaleAmount: 0.0,
|
||||
logisticAmount: 0.0,
|
||||
eprAmount: 0.0,
|
||||
withdrawAmount: 0.0,
|
||||
|
||||
currentPage: 1,
|
||||
pageSize: 100,
|
||||
flowList: [],
|
||||
currentIndex: 0,
|
||||
|
||||
isTipDlgShow: false,
|
||||
|
||||
isLoading: false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
methods: {
|
||||
toBeginStat() {
|
||||
if (!this.dateRange) {
|
||||
Message.error("请选择统计时间范围")
|
||||
return
|
||||
}
|
||||
if (!this.mallId) {
|
||||
Message.error("请选择店铺")
|
||||
return
|
||||
}
|
||||
this.$userCheck(this.mallId).then(async () => {
|
||||
this.currentPage = 1
|
||||
this.flowList = []
|
||||
this.isLoading = true
|
||||
|
||||
this.transIncome = 0.0
|
||||
this.customerOutcome = 0.0
|
||||
this.nonSllerDuty = 0.0
|
||||
this.afterSaleAmount = 0.0
|
||||
this.logisticAmount = 0.0
|
||||
this.eprAmount = 0.0
|
||||
this.withdrawAmount = 0.0
|
||||
this.currentIndex = 0
|
||||
|
||||
await this.beginStat()
|
||||
this.nonSllerDuty = Math.round(this.nonSllerDuty * 100) / 100
|
||||
this.isLoading = false
|
||||
}).catch((err) => {
|
||||
this.mallId = ''
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
async beginStat() {
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'api/merchant/fund/detail/pageSearch',
|
||||
needMallId: true,
|
||||
mallId: this.mallId,
|
||||
data: {
|
||||
moneyChangeTypeList: [],
|
||||
fundType: [],
|
||||
beginTime: this.dateRange[0].getTime(),
|
||||
endTime: this.dateRange[1].getTime() + 86400*1000 - 1,
|
||||
pageSize: this.pageSize,
|
||||
pageNum: this.currentPage
|
||||
}})
|
||||
if (res.errorCode == 1000000) {
|
||||
this.flowList = this.flowList.concat(res.result.resultList)
|
||||
|
||||
if (res.result.resultList.length == this.pageSize) {
|
||||
this.currentPage ++
|
||||
await this.beginStat()
|
||||
} else {
|
||||
this.currentIndex = 0
|
||||
await this.stat()
|
||||
}
|
||||
}
|
||||
},
|
||||
async stat() {
|
||||
for (; this.currentIndex < this.flowList.length; this.currentIndex++) {
|
||||
if (this.isTipDlgShow) {
|
||||
this.currentIndex --
|
||||
break
|
||||
}
|
||||
if (this.flowList[this.currentIndex].fundType == 100) { // 结算
|
||||
await this.$sleepSync(300)
|
||||
await this.querySattement(this.flowList[this.currentIndex])
|
||||
} else if (this.flowList[this.currentIndex].fundType == 200) { // 提现
|
||||
this.withdrawAmount += this.flowList[this.currentIndex].originAmount / 100
|
||||
} else if (this.flowList[this.currentIndex].fundType == 400 && this.flowList[this.currentIndex].bizType == "deduct_risk_punish") { // 消费者及履约保障-售后问题
|
||||
this.afterSaleAmount += Number(this.flowList[this.currentIndex].amount.replace('¥', ''))
|
||||
} else if (this.flowList[this.currentIndex].fundType == 400 && this.flowList[this.currentIndex].bizType == "deduct_storage_service_fee") { // 仓储综合服务费
|
||||
this.logisticAmount += Number(this.flowList[this.currentIndex].amount.replace('¥', ''))
|
||||
} else if (this.flowList[this.currentIndex].fundType == 400 && this.flowList[this.currentIndex].bizType == "deduct_epr") { // 合规EPR物流包装环保费
|
||||
this.eprAmount += Number(this.flowList[this.currentIndex].amount.replace('¥', ''))
|
||||
}
|
||||
}
|
||||
},
|
||||
async toGoon() {
|
||||
this.isTipDlgShow = false
|
||||
this.isLoading = true
|
||||
await this.stat()
|
||||
},
|
||||
async querySattement(obj) {
|
||||
let res = await sendChromeAPIMessage({
|
||||
url: 'api/merchant/fund/detail/item',
|
||||
needMallId: true,
|
||||
mallId: this.mallId,
|
||||
anti: true,
|
||||
data: {
|
||||
fundType: obj.fundType,
|
||||
batchId: obj.transSn,
|
||||
createdTime: obj.createTime
|
||||
}})
|
||||
if (res.errorCode == 1000000) {
|
||||
for (let i = 0; i < res.result.length; i++) {
|
||||
if (res.result[i].fundItemType == 1) { // 交易收入
|
||||
this.transIncome += Number(res.result[i].amount)
|
||||
} else if (res.result[i].fundItemType == 3) { // 消费者退款金额
|
||||
this.customerOutcome += Number(res.result[i].amount)
|
||||
} else if (res.result[i].fundItemType == 5) { // 非商责平台售后补贴金额
|
||||
this.nonSllerDuty += Number(res.result[i].amount)
|
||||
}
|
||||
}
|
||||
} else if (res.error_code == '54001') {
|
||||
this.isLoading = false
|
||||
this.isTipDlgShow = true
|
||||
}
|
||||
},
|
||||
async downloadPicture() {
|
||||
try {
|
||||
const element = document.getElementById('app-content');
|
||||
const canvas = await html2canvas(element);
|
||||
// 创建一个图片元素
|
||||
const img = new Image();
|
||||
img.src = canvas.toDataURL('image/png');
|
||||
// 添加到body中以便下载
|
||||
document.body.appendChild(img);
|
||||
// 触发下载
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none'
|
||||
a.href = img.src;
|
||||
a.download = '账务明细统计.png';
|
||||
a.click();
|
||||
document.body.removeChild(img);
|
||||
} catch (error) {
|
||||
console.error('Error saving image:', error);
|
||||
}
|
||||
},
|
||||
gotoValid() {
|
||||
window.open("https://seller.kuajingmaihuo.com/labor/bill", '_blank')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.list {
|
||||
.title-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
& > div:first-child {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
::v-deep.ai-list {
|
||||
.ai-list__content--right-wrapper {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
padding: 0!important;
|
||||
}
|
||||
}
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 24px;
|
||||
|
||||
.item {
|
||||
flex: 1;
|
||||
margin-right: 20px;
|
||||
padding: 16px 24px;
|
||||
background: #FFF;
|
||||
box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15);
|
||||
border-radius: 4px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&:nth-of-type(1) {
|
||||
color: #2266ff;
|
||||
}
|
||||
|
||||
&:nth-of-type(2) {
|
||||
color: #f8b426;
|
||||
}
|
||||
&:nth-of-type(3) {
|
||||
color: #21aa99;
|
||||
}
|
||||
&:nth-of-type(4) {
|
||||
color: #F46;
|
||||
}
|
||||
&:nth-of-type(5) {
|
||||
color: #11A265;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 30px;
|
||||
font-size: 16px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
p {
|
||||
font-weight: 600;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.like {
|
||||
cursor: pointer;
|
||||
font-size: 25px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.amountItem {
|
||||
margin: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -376,7 +376,7 @@ import { DualAxes } from '@antv/g2plot'
|
||||
computed: {
|
||||
topSaleAmountSkcList() {
|
||||
const list = Object.assign([], this.skcList)
|
||||
list.sort((a, b) => b.amount - a.amount)
|
||||
list.sort((a, b) => b.saleAmount - a.saleAmount)
|
||||
return list.slice(0, 10)
|
||||
},
|
||||
topSaleProfitSkcList() {
|
||||
@@ -805,7 +805,7 @@ import { DualAxes } from '@antv/g2plot'
|
||||
const a = document.createElement('a');
|
||||
a.style.display = 'none'
|
||||
a.href = img.src;
|
||||
a.download = '近60天销售统计.png';
|
||||
a.download = '销售统计.png';
|
||||
a.click();
|
||||
document.body.removeChild(img);
|
||||
} catch (error) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<ai-title
|
||||
slot="title"
|
||||
title="物流统计"
|
||||
tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态"
|
||||
tips="数据来源于“履约服务账单->明细->缴费记录"
|
||||
isShowBottomBorder>
|
||||
</ai-title>
|
||||
<template slot="content">
|
||||
|
||||
@@ -255,16 +255,26 @@ import { saveAs } from 'file-saver'
|
||||
}
|
||||
},
|
||||
async getPriceInfo(skcList) {
|
||||
let res = await sendGeiwohuoAPIMessage({
|
||||
url: `idms/goods-skc/price`,
|
||||
method: 'POST',
|
||||
data: skcList})
|
||||
if (res.code == '0') {
|
||||
for (let key in res.info) {
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
if (key == this.list[i].sku) {
|
||||
this.list[i].price = res.info[key]
|
||||
break
|
||||
let i = 0, len = 100
|
||||
while(i < skcList.length) {
|
||||
let tempSkcList = []
|
||||
for (; i < skcList.length; i++) {
|
||||
tempSkcList.push(skcList[i])
|
||||
if (tempSkcList.length % len == 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
let res = await sendGeiwohuoAPIMessage({
|
||||
url: `idms/goods-skc/price`,
|
||||
method: 'POST',
|
||||
data: tempSkcList})
|
||||
if (res.code == '0') {
|
||||
for (let key in res.info) {
|
||||
for (let i = 0; i < this.list.length; i++) {
|
||||
if (key == this.list[i].sku) {
|
||||
this.list[i].price = res.info[key]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,6 +323,7 @@ import { saveAs } from 'file-saver'
|
||||
this.costDlgShow = true
|
||||
},
|
||||
importConfirm() {
|
||||
this.isLoading = true
|
||||
this.$refs.costForm.validate((valid) => {
|
||||
const data = new FormData()
|
||||
data.append('file', this.costForm.file[0].raw);
|
||||
@@ -322,8 +333,10 @@ import { saveAs } from 'file-saver'
|
||||
this.$message.success('导入成功')
|
||||
this.currentPage = 1
|
||||
this.list = []
|
||||
this.isLoading = true
|
||||
this.isLoading = false
|
||||
this.getList()
|
||||
} else {
|
||||
this.isLoading = false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -199,7 +199,7 @@ import { saveAs } from 'file-saver'
|
||||
for(let i = 0;i < res.info.data.length; i++) {
|
||||
let item = res.info.data[i];
|
||||
let data = {
|
||||
orderNo: item.orderId,
|
||||
orderNo: item.sellerOrderNo,
|
||||
supplierCode: item.goods.supplierCode,
|
||||
statusName: item.statusName,
|
||||
skc: item.goods.skcName,
|
||||
|
||||
@@ -490,6 +490,8 @@
|
||||
Message.error("店铺【" + mallInfo.mallName + "】未设置默认发货地址,将无法自动创建发货单")
|
||||
}
|
||||
break
|
||||
} else if (res.error_msg == '没权限访问') {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,7 +614,23 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.getList(data, mallId, mallName, currentPage)
|
||||
if (res.error_msg == '没权限访问') {
|
||||
if (this.loadMode == 1) {
|
||||
this.loadMallIndex ++
|
||||
if (this.loadMallIndex < this.mallList.length) {
|
||||
this.getList(data, this.mallList[this.loadMallIndex].mallId, this.mallList[this.loadMallIndex].mallName, 1)
|
||||
} else {
|
||||
this.isLoading = false
|
||||
this.isDlgLoading = false
|
||||
Message.success("所有店铺备货单已加载完成")
|
||||
}
|
||||
} else {
|
||||
this.isLoading = false
|
||||
this.isDlgLoading = false
|
||||
}
|
||||
} else {
|
||||
this.getList(data, mallId, mallName, currentPage)
|
||||
}
|
||||
}
|
||||
},
|
||||
remove(sn) {
|
||||
|
||||
@@ -153,7 +153,6 @@ import { saveAs } from 'file-saver'
|
||||
url: 'bg-visage-mms/labelcode/pageQuery',
|
||||
needMallId: true,
|
||||
mallId: this.form.mallId,
|
||||
anti: true,
|
||||
data: this.reqData}).then((res) => {
|
||||
if (res.errorCode == 1000000) {
|
||||
for(let i = 0;i < res.result.pageItems.length; i++) {
|
||||
|
||||
@@ -194,14 +194,16 @@ import { saveAs } from 'file-saver'
|
||||
for(let i = 0;i < res.result.deliveryOrderDetails.length; i++) {
|
||||
let item = res.result.deliveryOrderDetails[i]
|
||||
|
||||
let specArr = item.secondarySpecVOList.map(item => {
|
||||
return item.specName
|
||||
})
|
||||
let spec = specArr.join(',')
|
||||
|
||||
for(let j = 0; j < this.list.length; j++) {
|
||||
if (this.list[j].productSkuId == item.productSkuId) {
|
||||
this.list[j].specName = spec
|
||||
if (item.secondarySpecVOList) {
|
||||
let specArr = item.secondarySpecVOList.map(item => {
|
||||
return item.specName
|
||||
})
|
||||
let spec = specArr.join(',')
|
||||
|
||||
for(let j = 0; j < this.list.length; j++) {
|
||||
if (this.list[j].productSkuId == item.productSkuId) {
|
||||
this.list[j].specName = spec
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user