文 件上传
This commit is contained in:
		| @@ -10,15 +10,16 @@ | |||||||
|     "@antv/g2plot": "^2.4.25", |     "@antv/g2plot": "^2.4.25", | ||||||
|     "axios": "^1.4.0", |     "axios": "^1.4.0", | ||||||
|     "core-js": "^3.8.3", |     "core-js": "^3.8.3", | ||||||
|  |     "crypto-js": "^4.0.0", | ||||||
|     "dayjs": "^1.11.9", |     "dayjs": "^1.11.9", | ||||||
|     "element-ui": "^2.15.13", |     "element-ui": "^2.15.13", | ||||||
|  |     "spark-md5": "^3.0.2", | ||||||
|     "v-viewer": "^1.6.4", |     "v-viewer": "^1.6.4", | ||||||
|     "vue": "^2.6.14", |     "vue": "^2.6.14", | ||||||
|     "vue-cropper": "^0.6.4", |     "vue-cropper": "^0.6.4", | ||||||
|     "vue-json-excel": "^0.3.0", |     "vue-json-excel": "^0.3.0", | ||||||
|     "vue-qr": "^4.0.9", |     "vue-qr": "^4.0.9", | ||||||
|     "vue-router": "^3.2.0", |     "vue-router": "^3.2.0", | ||||||
|     "crypto-js": "^4.0.0", |  | ||||||
|     "vuex": "^3.4.0", |     "vuex": "^3.4.0", | ||||||
|     "vuex-persistedstate": "^4.1.0" |     "vuex-persistedstate": "^4.1.0" | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| function init() { | function init() { | ||||||
|     if (window.location.href.startsWith('https://www.aliexpress.us/item/')) { |     if (window.location.href.startsWith('https://www.aliexpress.com/item/')) { | ||||||
|         const popup = document.createElement("div") |         const popup = document.createElement("div") | ||||||
|         popup.innerText = "下载图片" |         popup.innerText = "下载图片" | ||||||
|         const styles = { |         const styles = { | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								public/rules_3.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								public/rules_3.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | [ | ||||||
|  |     { | ||||||
|  |         "id": 12, | ||||||
|  |         "priority": 1, | ||||||
|  |         "action": { | ||||||
|  |             "type": "modifyHeaders", | ||||||
|  |             "requestHeaders": [ | ||||||
|  |                 { | ||||||
|  |                     "header": "Origin", | ||||||
|  |                     "operation": "set", | ||||||
|  |                     "value": "https://www.aliexpress.com" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "header": "Referer", | ||||||
|  |                     "operation": "set", | ||||||
|  |                     "value": "https://www.aliexpress.com" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         "condition": { | ||||||
|  |             "urlFilter": "||aeproductsourcesite.alicdn.com" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | ] | ||||||
							
								
								
									
										24
									
								
								public/rules_4.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								public/rules_4.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | [ | ||||||
|  |     { | ||||||
|  |         "id": 12, | ||||||
|  |         "priority": 1, | ||||||
|  |         "action": { | ||||||
|  |             "type": "modifyHeaders", | ||||||
|  |             "requestHeaders": [ | ||||||
|  |                 { | ||||||
|  |                     "header": "Origin", | ||||||
|  |                     "operation": "set", | ||||||
|  |                     "value": "https://kuajing.pinduoduo.com" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "header": "Referer", | ||||||
|  |                     "operation": "set", | ||||||
|  |                     "value": "https://kuajing.pinduoduo.com" | ||||||
|  |                 } | ||||||
|  |             ] | ||||||
|  |         }, | ||||||
|  |         "condition": { | ||||||
|  |             "urlFilter": "||kuajing-file.pinduoduo.com" | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | ] | ||||||
| @@ -7,7 +7,9 @@ import {genAnti} from "@/api/genAnti"; | |||||||
|  */ |  */ | ||||||
| export async function sendChromeAPIMessage(message) { | export async function sendChromeAPIMessage(message) { | ||||||
|     message.type = 'api' |     message.type = 'api' | ||||||
|  |     if (!message.url.startsWith('http')) { | ||||||
|         message.url = "https://kuajing.pinduoduo.com/" + message.url; |         message.url = "https://kuajing.pinduoduo.com/" + message.url; | ||||||
|  |     } | ||||||
|     message.anti = message.anti || false |     message.anti = message.anti || false | ||||||
|     if (message.needMallId) { |     if (message.needMallId) { | ||||||
|         // 如果参数中没有携带MallId,则从state中获取 |         // 如果参数中没有携带MallId,则从state中获取 | ||||||
| @@ -53,6 +55,19 @@ export async function sendChromeWebReqMessage(message) { | |||||||
|     }) |     }) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 向Chrome发送消息 | ||||||
|  |  * @param message 消息 | ||||||
|  |  */ | ||||||
|  | export async function sendSheinAPIMessage(message) { | ||||||
|  |     message.type = 'sheinApi' | ||||||
|  |     message.url = "https://www.shein.com/" + message.url; | ||||||
|  |     return new Promise((resolve) => { | ||||||
|  |         // @ts-ignore | ||||||
|  |         chrome.runtime.sendMessage(message, resolve) | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 向Chrome发送消息 |  * 向Chrome发送消息 | ||||||
|  * @param message 消息 |  * @param message 消息 | ||||||
|   | |||||||
							
								
								
									
										375
									
								
								src/components/AiCopyFromAliExpress.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										375
									
								
								src/components/AiCopyFromAliExpress.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,375 @@ | |||||||
|  | <template> | ||||||
|  |     <div> | ||||||
|  |         <el-alert | ||||||
|  |           title="采集一个商品添加进草稿箱,将消耗50金币" | ||||||
|  |           type="success" | ||||||
|  |           :closable="false"> | ||||||
|  |         </el-alert> | ||||||
|  |         <el-form class="ai-form" :model="form" label-width="150px" ref="form"> | ||||||
|  |             <el-form-item v-if="!isMultiCopy" label="商品地址:" style="width: 100%;" prop="url" :rules="[{ required: true, message: '请输入商品地址', trigger: 'blur' }]"> | ||||||
|  |               <el-input type="textarea" :rows="5" v-model="form.url"></el-input> | ||||||
|  |             </el-form-item> | ||||||
|  |             <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 $store.state.mallList" | ||||||
|  |                 :key="item.mallId" | ||||||
|  |                 :label="item.mallName" | ||||||
|  |                 :value="item.mallId"> | ||||||
|  |                 </el-option> | ||||||
|  |             </el-select> | ||||||
|  |             </el-form-item> | ||||||
|  |             <el-form-item label="商品分类:" style="width: 100%;" prop="targetCatId" :rules="[{ required: true, message: '请选择商品分类', trigger: 'blur' }]"> | ||||||
|  |             <ai-lazy-cascader  | ||||||
|  |               style="width: 380px"  | ||||||
|  |               v-model="form.targetCatId"  | ||||||
|  |               filterable | ||||||
|  |               :props="props"></ai-lazy-cascader> | ||||||
|  |             </el-form-item> | ||||||
|  |         </el-form> | ||||||
|  |         <div class="bottom flex-center"> | ||||||
|  |             <el-button @click="$emit('onClose')">取 消</el-button> | ||||||
|  |             <el-button type="primary" @click="toAddToDraft" :loading="isCopying">确定</el-button> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import {sendChromeAPIMessage, sendTemuAPIMessage, sendChromeWebReqMessage} from '@/api/chromeApi' | ||||||
|  | import AiLazyCascader from "@/components/AiLazyCascader.vue" | ||||||
|  | import { getImageMd5 } from "@/utils/image.js" | ||||||
|  | import { Message } from 'element-ui' | ||||||
|  | import { MessageBox } from 'element-ui'; | ||||||
|  |  | ||||||
|  | export default { | ||||||
|  |     name: 'AiCopyFromTemu', | ||||||
|  |     props: ['params', 'isMultiCopy'], | ||||||
|  |     components: {AiLazyCascader}, | ||||||
|  |     data() { | ||||||
|  |         return { | ||||||
|  |             props: { | ||||||
|  |                 value: 'catId', | ||||||
|  |                 label: 'catName', | ||||||
|  |                 lazy: true, | ||||||
|  |                 lazyLoad (value, resolve) { | ||||||
|  |                     sendChromeAPIMessage({ | ||||||
|  |                         url: 'bg-anniston-mms/category/children/list', | ||||||
|  |                         needMallId: true, | ||||||
|  |                         data: { | ||||||
|  |                             parentCatId: value || '' | ||||||
|  |                         } | ||||||
|  |                     }).then(res => { | ||||||
|  |                         if (res.errorCode === 1000000) { | ||||||
|  |                             resolve(res.result.categoryNodeVOS.map(v => { | ||||||
|  |                             return { | ||||||
|  |                                 ...v, | ||||||
|  |                                 leaf: v.isLeaf | ||||||
|  |                             } | ||||||
|  |                             })) | ||||||
|  |                         } | ||||||
|  |                     }) | ||||||
|  |                 }, | ||||||
|  |                 lazySearch(queryString, resolve) { | ||||||
|  |                   sendChromeAPIMessage({ | ||||||
|  |                     url: 'bg-anniston-mms/category/search', | ||||||
|  |                     needMallId: true, | ||||||
|  |                     data: { | ||||||
|  |                       searchText: queryString || '' | ||||||
|  |                     } | ||||||
|  |                   }).then(res => { | ||||||
|  |                     if (res.errorCode === 1000000) { | ||||||
|  |                       resolve(res.result.categoryPaths.map(v => { | ||||||
|  |                         let value = [] | ||||||
|  |                         let label = [] | ||||||
|  |                         for (let i = 1; i <= 10; i++ ) { | ||||||
|  |                           if (v['cat'+i+'NodeVO']) { | ||||||
|  |                             value.push(v['cat'+i+'NodeVO'].catId) | ||||||
|  |                             label.push(v['cat'+i+'NodeVO'].catName) | ||||||
|  |                           } | ||||||
|  |                         } | ||||||
|  |                         return { | ||||||
|  |                           catId: value, | ||||||
|  |                           catName: label | ||||||
|  |                         } | ||||||
|  |                       })) | ||||||
|  |                     } | ||||||
|  |                   }) | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             form: { | ||||||
|  |                 url: '', | ||||||
|  |                 type: 2,  // 默认从temu复制 | ||||||
|  |                 targetMallId: '', | ||||||
|  |                 targetCatId: [] | ||||||
|  |             }, | ||||||
|  |             goods: {}, | ||||||
|  |             sku: {}, | ||||||
|  |             productDetail: {}, | ||||||
|  |             isCopying: false, | ||||||
|  |             goodsId: '', | ||||||
|  |             currentUrl: '', | ||||||
|  |             goodsProperty: [], | ||||||
|  |             catId: null, | ||||||
|  |             currentIndex: 0, | ||||||
|  |             successList: [] | ||||||
|  |         } | ||||||
|  |     }, | ||||||
|  |     created () { | ||||||
|  |       if (this.params?.url) { | ||||||
|  |         this.form.url = this.params.url | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     methods: { | ||||||
|  |       toAddToDraft() { | ||||||
|  |         this.$refs.form.validate((valid) => { | ||||||
|  |           if (valid) { | ||||||
|  |             this.currentUrl = this.form.url | ||||||
|  |             this.addToDraft() | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       async addToDraft() { | ||||||
|  |         this.isCopying = true | ||||||
|  |         let res = await sendChromeWebReqMessage({ | ||||||
|  |           type: 'aliexpress', | ||||||
|  |           url: this.currentUrl, | ||||||
|  |         }) | ||||||
|  |         if (res.indexOf("runParams") == -1) { | ||||||
|  |           Message.error("请检查地址是否正确,或者“速卖通”网站是否出现滑动条") | ||||||
|  |           return | ||||||
|  |         } | ||||||
|  |         let str = res.substring(res.indexOf("runParams")) | ||||||
|  |         str = str.substring(0, str.indexOf("<\/script>")) | ||||||
|  |         str = str.substring(str.indexOf("{")) | ||||||
|  |         str = str.substring(0, str.lastIndexOf("}")) | ||||||
|  |         str = str.substring(str.indexOf('data')) | ||||||
|  |         str = str.substring(5) | ||||||
|  |  | ||||||
|  |         console.log(str) | ||||||
|  |  | ||||||
|  |         let res2 = await getImageMd5('https://ae01.alicdn.com/kf/S654a8881c4e84117b3ea74c563ff61b4Q.jpg') | ||||||
|  |         //console.log(res2) | ||||||
|  |  | ||||||
|  |         let obj = JSON.parse(str) | ||||||
|  |  | ||||||
|  |         /*let res1 = await sendChromeWebReqMessage({ | ||||||
|  |           type: 'aliexpress', | ||||||
|  |           url: obj.productDescComponent.descriptionUrl, | ||||||
|  |         }) | ||||||
|  |  | ||||||
|  |         res1 = res1.substring(0, res1.indexOf("<script>")) | ||||||
|  |         let str1 = res1.replace(/<img[^>]+src="([^">]+)"[^>]+>/g, '$1\n').replace(/<.*?>/g, '[||]') | ||||||
|  |         let arr = str1.split('[||]') | ||||||
|  |         for (let i = 0; i < arr.length; i++) { | ||||||
|  |             console.log(arr[i]) | ||||||
|  |         }*/ | ||||||
|  |  | ||||||
|  |          | ||||||
|  |            | ||||||
|  |       }, | ||||||
|  |       async createDraft(data) { | ||||||
|  |         let catId = null; | ||||||
|  |         if (this.form.isSameCategory) { | ||||||
|  |          catId = this.catId;  | ||||||
|  |         } else { | ||||||
|  |           catId = this.form.targetCatId[this.form.targetCatId.length - 1] | ||||||
|  |         } | ||||||
|  |         let res = await sendChromeAPIMessage({ | ||||||
|  |           url: 'bg-visage-mms/product/draft/add', | ||||||
|  |           needMallId: true, | ||||||
|  |           mallId: this.form.targetMallId, | ||||||
|  |           data: { | ||||||
|  |             catId: catId | ||||||
|  |         }}) | ||||||
|  |          | ||||||
|  |         if (res.errorCode == 1000000) { | ||||||
|  |           let draftId = res.result.productDraftId | ||||||
|  |           let content = data | ||||||
|  |           let i = 0 | ||||||
|  |           if (this.form.isSameCategory) { | ||||||
|  |             let res2 = await this.$http.post('/api/innerCategory/fullById',null , { | ||||||
|  |               params: { | ||||||
|  |                 id: catId | ||||||
|  |               } | ||||||
|  |             }) | ||||||
|  |             for (; i < res2.data.length; i++) { | ||||||
|  |               content['cat' + (i+1) + 'Id'] = res2.data[i] | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             let res3 = await sendChromeAPIMessage({ | ||||||
|  |               url: 'bg-anniston-mms/category/template/query', | ||||||
|  |               needMallId: true, | ||||||
|  |               mallId: this.form.targetMallId, | ||||||
|  |               data: { | ||||||
|  |                 catId: catId, | ||||||
|  |                 productCreateTime: null, | ||||||
|  |                 langList: [ | ||||||
|  |                   "en" | ||||||
|  |                 ] | ||||||
|  |             }}) | ||||||
|  |             content.productPropertyReqs = [] | ||||||
|  |             for (let j = 0; j < this.goodsProperty.length; j++) { | ||||||
|  |               let temp = {} | ||||||
|  |  | ||||||
|  |               for (let k = 0; k < res3.result.properties.length; k++) { | ||||||
|  |                 if (this.goodsProperty[j].key == res3.result.properties[k].lang2Name.en) { | ||||||
|  |                   temp.templatePid = res3.result.properties[k].templatePid | ||||||
|  |                   temp.pid = res3.result.properties[k].pid | ||||||
|  |                   temp.refPid = res3.result.properties[k].refPid | ||||||
|  |                   temp.propName = res3.result.properties[k].name | ||||||
|  |                   for (let x = 0; x < this.goodsProperty[j].values.length; x++) { | ||||||
|  |                     if (null == res3.result.properties[k].values) break | ||||||
|  |                     for (let l = 0; l < res3.result.properties[k].values.length; l++) { | ||||||
|  |                       if (res3.result.properties[k].values[l].lang2Value.en == this.goodsProperty[j].values[x]) { | ||||||
|  |                         temp.vid = res3.result.properties[k].values[l].vid | ||||||
|  |                         temp.propValue = res3.result.properties[k].values[l].value | ||||||
|  |                         temp.valueUnit = '' | ||||||
|  |                         temp.valueExtendInfo = '' | ||||||
|  |                         temp.controlType = res3.result.properties[k].values[l].controlType | ||||||
|  |  | ||||||
|  |                         content.productPropertyReqs.push({...temp}) | ||||||
|  |                         break | ||||||
|  |                       } | ||||||
|  |                     } | ||||||
|  |                   } | ||||||
|  |  | ||||||
|  |                 } | ||||||
|  |               } | ||||||
|  |             } | ||||||
|  |           } else { | ||||||
|  |             for (; i < this.form.targetCatId.length; i++) { | ||||||
|  |               content['cat' + (i+1) + 'Id'] = this.form.targetCatId[i] | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |           for (; i < 10; i++) { | ||||||
|  |             content['cat' + (i+1) + 'Id'] = '' | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           content.productDraftId = draftId | ||||||
|  |  | ||||||
|  |           this.createProduct(content) | ||||||
|  |         } else { | ||||||
|  |           setTimeout(() => { | ||||||
|  |             this.createDraft(data) | ||||||
|  |           }, 500) | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       createProduct(content) { | ||||||
|  |         sendChromeAPIMessage({ | ||||||
|  |           url: 'bg-visage-mms/product/draft/save', | ||||||
|  |           needMallId: true, | ||||||
|  |           mallId: this.form.targetMallId, | ||||||
|  |           data: { | ||||||
|  |             ...content | ||||||
|  |         }}).then((res) => { | ||||||
|  |           if (res.errorCode == 1000000) { | ||||||
|  |             this.successList.push(this.currentUrl) | ||||||
|  |             this.saveInfo() | ||||||
|  |             if (this.isMultiCopy) { | ||||||
|  |               this.currentIndex ++ | ||||||
|  |               if (this.currentIndex == this.params.urlList.length) { | ||||||
|  |                 this.isCopying = false | ||||||
|  |                 this.$emit('onSuccess') | ||||||
|  |                 MessageBox.alert(`成功添加${this.successList.length}个商品进入草稿箱`) | ||||||
|  |               } else { | ||||||
|  |                 this.currentUrl = this.params.urlList[this.currentIndex] | ||||||
|  |                 this.execAddToDraft() | ||||||
|  |               } | ||||||
|  |             } else { | ||||||
|  |               this.isCopying = false | ||||||
|  |               Message.success("成功添加到草稿箱") | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |           } else { | ||||||
|  |             setTimeout(() => { | ||||||
|  |               this.createProduct(content) | ||||||
|  |             }, 500) | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       getSpecIdNew(data) { | ||||||
|  |         return sendChromeAPIMessage({ | ||||||
|  |           url: 'bg-anniston-mms/sku/spec/byName/queryOrAdd', | ||||||
|  |           needMallId: true, | ||||||
|  |           mallId: this.form.targetMallId, | ||||||
|  |           data: { | ||||||
|  |             parentSpecId: data.spec_key_id, | ||||||
|  |             specName: data.spec_value | ||||||
|  |         }}).then((res) => { | ||||||
|  |           if (res.errorCode == 1000000) { | ||||||
|  |             return res | ||||||
|  |           } else { | ||||||
|  |             this.getSpecIdNew(data) | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       getSpecId(data) { | ||||||
|  |         return sendChromeAPIMessage({ | ||||||
|  |           url: 'bg-anniston-mms/sku/spec/byName/queryOrAdd', | ||||||
|  |           needMallId: true, | ||||||
|  |           mallId: this.form.targetMallId, | ||||||
|  |           data: { | ||||||
|  |             parentSpecId: data.specKeyId, | ||||||
|  |             specName: data.specValue | ||||||
|  |         }}).then((res) => { | ||||||
|  |           if (res.errorCode == 1000000) { | ||||||
|  |             return res | ||||||
|  |           } else { | ||||||
|  |             this.getSpecId(data) | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       saveInfo() { | ||||||
|  |         let mallInfo = this.$store.state.mallList.filter(item => { | ||||||
|  |           return item.mallId == this.form.targetMallId | ||||||
|  |         }) | ||||||
|  |         this.$http.post('/api/copyProduct/add', { | ||||||
|  |             mallId: mallInfo[0].mallId, | ||||||
|  |             mallName: mallInfo[0].mallName, | ||||||
|  |             url: this.currentUrl, | ||||||
|  |             type: this.form.type | ||||||
|  |           }).then(res1 => { | ||||||
|  |           if (res1.code == 0) { | ||||||
|  |             this.$store.dispatch('getUserInfo') | ||||||
|  |             if (!this.isMultiCopy) { | ||||||
|  |               this.$emit('onSuccess') | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       parseURL(url) {  | ||||||
|  |         let a = document.createElement('a');  | ||||||
|  |         a.href = url;  | ||||||
|  |         return {  | ||||||
|  |           source: url,  | ||||||
|  |           protocol: a.protocol.replace(':',''),  | ||||||
|  |           host: a.hostname,  | ||||||
|  |           port: a.port,  | ||||||
|  |           query: a.search,  | ||||||
|  |           params: (function(){  | ||||||
|  |             var ret = {},  | ||||||
|  |             seg = a.search.replace(/^\?/,'').split('&'),  | ||||||
|  |             len = seg.length, i = 0, s;  | ||||||
|  |             for (;i<len;i++) {  | ||||||
|  |                 if (!seg[i]) { continue; }  | ||||||
|  |                  s = seg[i].split('=');  | ||||||
|  |                  ret[s[0]] = s[1];  | ||||||
|  |              }  | ||||||
|  |              return ret;  | ||||||
|  |           })(),  | ||||||
|  |           file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],  | ||||||
|  |           hash: a.hash.replace('#',''),  | ||||||
|  |           path: a.pathname.replace(/^([^\/])/,'/$1'),  | ||||||
|  |           relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],  | ||||||
|  |           segments: a.pathname.replace(/^\//,'').split('/')  | ||||||
|  |         };  | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | .bottom { | ||||||
|  |     justify-content: center; | ||||||
|  |   } | ||||||
|  | </style> | ||||||
| @@ -6,12 +6,6 @@ | |||||||
|           :closable="false"> |           :closable="false"> | ||||||
|         </el-alert> |         </el-alert> | ||||||
|         <el-form class="ai-form" :model="form" label-width="150px" ref="form"> |         <el-form class="ai-form" :model="form" label-width="150px" ref="form"> | ||||||
|             <el-form-item label="来源:" style="width: 100%;" prop="type" :rules="[{ required: true, message: '请选择来源', trigger: 'blur' }]"> |  | ||||||
|             <el-radio-group v-model="form.type" size="medium"> |  | ||||||
|                 <el-radio :label="1">TEMU</el-radio> |  | ||||||
|                 <!--<el-radio :label="2">速卖通</el-radio>--> |  | ||||||
|             </el-radio-group> |  | ||||||
|             </el-form-item> |  | ||||||
|             <el-form-item v-if="!isMultiCopy" label="商品地址:" style="width: 100%;" prop="url" :rules="[{ required: true, message: '请输入商品地址', trigger: 'blur' }]"> |             <el-form-item v-if="!isMultiCopy" label="商品地址:" style="width: 100%;" prop="url" :rules="[{ required: true, message: '请输入商品地址', trigger: 'blur' }]"> | ||||||
|               <el-input type="textarea" :rows="5" v-model="form.url"></el-input> |               <el-input type="textarea" :rows="5" v-model="form.url"></el-input> | ||||||
|             </el-form-item> |             </el-form-item> | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
|             <ai-wrapper |             <ai-wrapper | ||||||
|               label-width="120px" class="fill"> |               label-width="120px" class="fill"> | ||||||
|               <ai-info-item label="价格:"   :value="'$' + info.price"></ai-info-item> |               <ai-info-item label="价格:"   :value="'$' + info.price"></ai-info-item> | ||||||
|               <ai-info-item label="销量:"   :value="info.saleTotal"></ai-info-item> |               <ai-info-item label="销量/评论数:"   :value="info.saleTotal"></ai-info-item> | ||||||
|             </ai-wrapper> |             </ai-wrapper> | ||||||
|           </div> |           </div> | ||||||
|         </template> |         </template> | ||||||
|   | |||||||
| @@ -9,14 +9,14 @@ | |||||||
|         <el-dropdown-item v-if="isShowAddFavorite" :command="beforeAddFavorite(params.goodsId, params.monitorId)">加入收藏</el-dropdown-item> |         <el-dropdown-item v-if="isShowAddFavorite" :command="beforeAddFavorite(params.goodsId, params.monitorId)">加入收藏</el-dropdown-item> | ||||||
|         <el-dropdown-item v-if="isShowDelFavorite" :command="beforeDelFavorite(params.id)">取消收藏</el-dropdown-item> |         <el-dropdown-item v-if="isShowDelFavorite" :command="beforeDelFavorite(params.id)">取消收藏</el-dropdown-item> | ||||||
|         <el-dropdown-item divided v-if="isShowGroup" :command="beforeAddGroup(params.goodsId)">加入分组</el-dropdown-item> |         <el-dropdown-item divided v-if="isShowGroup" :command="beforeAddGroup(params.goodsId)">加入分组</el-dropdown-item> | ||||||
|         <el-dropdown-item divided :command="beforeCopy(params.url)">商品采集</el-dropdown-item> |         <el-dropdown-item divided v-if="!isHideCopy" :command="beforeCopy(params.url)">商品采集</el-dropdown-item> | ||||||
|         <el-dropdown-item divided :command="beforeGoWeb(params.url)">访问商品</el-dropdown-item> |         <el-dropdown-item divided :command="beforeGoWeb(params.url)">访问商品</el-dropdown-item> | ||||||
|         <el-dropdown-item :command="beforeGoMal(params.mallId)">访问店铺</el-dropdown-item> |         <el-dropdown-item :command="beforeGoMal(params.mallId)">访问店铺</el-dropdown-item> | ||||||
|       </el-dropdown-menu> |       </el-dropdown-menu> | ||||||
|     </el-dropdown> |     </el-dropdown> | ||||||
|  |  | ||||||
|     <ai-dialog |     <ai-dialog | ||||||
|       title="复制" |       title="商品采集" | ||||||
|       :visible.sync="copyFromDlgShow" |       :visible.sync="copyFromDlgShow" | ||||||
|       :close-on-click-modal="false" |       :close-on-click-modal="false" | ||||||
|       width="790px" |       width="790px" | ||||||
| @@ -60,7 +60,7 @@ import { Message } from 'element-ui' | |||||||
| export default { | export default { | ||||||
|   name: "AiProductDropDown", |   name: "AiProductDropDown", | ||||||
|   components: {AiCopyFromTemu}, |   components: {AiCopyFromTemu}, | ||||||
|   props: ['params', 'isShowDetail', 'isShowAddFavorite', 'isShowDelFavorite', 'isShowGroup'], |   props: ['params', 'source', 'isShowDetail', 'isShowAddFavorite', 'isShowDelFavorite', 'isShowGroup', 'isHideCopy'], | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       info: {}, |       info: {}, | ||||||
| @@ -111,7 +111,11 @@ export default { | |||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|       } else if (e.type == 'goMall') { |       } else if (e.type == 'goMall') { | ||||||
|  |         if (e.mallId.startsWith('http')) { | ||||||
|  |           window.open(e.mallId, '_blank'); | ||||||
|  |         } else { | ||||||
|           window.open('https://www.temu.com/mall.html?mall_id=' + e.mallId, '_blank'); |           window.open('https://www.temu.com/mall.html?mall_id=' + e.mallId, '_blank'); | ||||||
|  |         } | ||||||
|       } else if (e.type == 'goWeb') { |       } else if (e.type == 'goWeb') { | ||||||
|         if (e.url.startsWith('http')) { |         if (e.url.startsWith('http')) { | ||||||
|           window.open(e.url, '_blank'); |           window.open(e.url, '_blank'); | ||||||
|   | |||||||
| @@ -5,20 +5,44 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { | |||||||
|   if (request.type == 'api') { |   if (request.type == 'api') { | ||||||
|     new Promise((resolve) => { |     new Promise((resolve) => { | ||||||
|       let headers = {}; |       let headers = {}; | ||||||
|  |       let data = null; | ||||||
|       if (request.needMallId) { |       if (request.needMallId) { | ||||||
|         headers.Mallid = request.mallId; |         headers.Mallid = request.mallId; | ||||||
|       } |       } | ||||||
|       if (request.anti) { |       if (request.anti) { | ||||||
|         headers["Anti-Content"] = request.anti |         headers["Anti-Content"] = request.anti | ||||||
|       } |       } | ||||||
|  |       if (!request.isFormData) { | ||||||
|         headers['Content-Type'] = 'application/json'; |         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] | ||||||
|  |           if (Array.isArray(value)) { | ||||||
|  |             value.forEach((subValue, i) => { | ||||||
|  |               formData.append(key + `[${i}]`, subValue) | ||||||
|  |             }) | ||||||
|  |           } else { | ||||||
|  |             if (key == 'image') { | ||||||
|  |               let blob = new Blob([request.data[key]], {type: 'application/png'}) | ||||||
|  |               // formData.append(key,  new Blob([request.data[key]], {type: 'application/png'})) | ||||||
|  |               formData.append(key,  blob) | ||||||
|  |             } else { | ||||||
|  |               formData.append(key, request.data[key]) | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |         data = formData | ||||||
|  |       } | ||||||
|       headers.cookie = getCookie(); |       headers.cookie = getCookie(); | ||||||
|       Promise.resolve().then(() => fetch(request.url, { |       Promise.resolve().then(() => fetch(request.url, { | ||||||
|         'headers': headers, |         'headers': headers, | ||||||
|         'method': 'POST', |         'method': 'POST', | ||||||
|         'referrerPolicy': 'no-referrer', |         'referrerPolicy': 'no-referrer', | ||||||
|         'credentials': 'include', |         'credentials': 'include', | ||||||
|         'body': JSON.stringify(request.data), |         'body': data, | ||||||
|         'mode': 'cors' |         'mode': 'cors' | ||||||
|       })).then((res) => { |       })).then((res) => { | ||||||
|         resolve(res.json()); |         resolve(res.json()); | ||||||
| @@ -111,6 +135,24 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { | |||||||
|         }); |         }); | ||||||
|       }); |       }); | ||||||
|     }).then(sendResponse); |     }).then(sendResponse); | ||||||
|  |   } else if (request.type == 'sheinApi') { | ||||||
|  |     new Promise((resolve) => { | ||||||
|  |       let headers = {}; | ||||||
|  |       headers['Content-Type'] = 'application/json'; | ||||||
|  |       headers.cookie = getSheinCookie() | ||||||
|  |       request.params = formatParams(request.params) | ||||||
|  | 		  let _url = request.url + (request.params ? ('?' + request.params) : '') | ||||||
|  |       Promise.resolve().then(() => fetch(_url, { | ||||||
|  |         'headers': headers, | ||||||
|  |         'method': request.method, | ||||||
|  |         'referrerPolicy': 'no-referrer', | ||||||
|  |         'credentials': 'include', | ||||||
|  |         'body': JSON.stringify(request.data), | ||||||
|  |         'mode': 'cors' | ||||||
|  |       })).then((res) => { | ||||||
|  |         resolve(res.json()); | ||||||
|  |       }); | ||||||
|  |     }).then(sendResponse); | ||||||
|   } else if (request.type == 'notify') { |   } else if (request.type == 'notify') { | ||||||
|     chrome.notifications.create( |     chrome.notifications.create( | ||||||
|         "" + Math.random(), { |         "" + Math.random(), { | ||||||
| @@ -183,8 +225,8 @@ function getTemuCookie() { | |||||||
|   return cStr; |   return cStr; | ||||||
| } | } | ||||||
|  |  | ||||||
| function getAliexpressCookie() { | function getSheinCookie() { | ||||||
|   const url = new URL("https://www.aliexpress.us/"); |   const url = new URL("https://www.shein.com/"); | ||||||
|   let cStr = ''; |   let cStr = ''; | ||||||
|   chrome.cookies.getAll({domain: url.host}, (cookie) => { |   chrome.cookies.getAll({domain: url.host}, (cookie) => { | ||||||
|     cookie.map((c) => { |     cookie.map((c) => { | ||||||
| @@ -193,3 +235,23 @@ function getAliexpressCookie() { | |||||||
|   }); |   }); | ||||||
|   return cStr; |   return cStr; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | function getAliexpressCookie() { | ||||||
|  |   const url = new URL("https://www.aliexpress.com/"); | ||||||
|  |   let cStr = ''; | ||||||
|  |   chrome.cookies.getAll({domain: url.host}, (cookie) => { | ||||||
|  |     cookie.map((c) => { | ||||||
|  |       cStr += c.name + '=' + c.value + ';'; | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   return cStr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function formatParams(data) { | ||||||
|  |   const arr = [] | ||||||
|  |   for (let name in data) { | ||||||
|  |     arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name])) | ||||||
|  |   } | ||||||
|  |   return arr.join("&") | ||||||
|  | } | ||||||
| @@ -14,10 +14,13 @@ | |||||||
|   "action": { |   "action": { | ||||||
|   }, |   }, | ||||||
|   "host_permissions": [ |   "host_permissions": [ | ||||||
|  |     "*://*.jjcp52.com/", | ||||||
|     "*://*.pinduoduo.com/", |     "*://*.pinduoduo.com/", | ||||||
|     "*://*.temu.com/", |     "*://*.temu.com/", | ||||||
|     "*://*.aliexpress.us/", |     "*://*.aliexpress.com/", | ||||||
|     "*://*.amazon.com/" |     "*://*.alicdn.com/", | ||||||
|  |     "*://*.amazon.com/", | ||||||
|  |     "*://*.shein.com/" | ||||||
|   ], |   ], | ||||||
|   "permissions": [ |   "permissions": [ | ||||||
|     "cookies", |     "cookies", | ||||||
| @@ -35,12 +38,16 @@ | |||||||
|       "id": "1", |       "id": "1", | ||||||
|       "enabled": true, |       "enabled": true, | ||||||
|       "path": "rules_1.json" |       "path": "rules_1.json" | ||||||
|  |     },{ | ||||||
|  |       "id": "3", | ||||||
|  |       "enabled": true, | ||||||
|  |       "path": "rules_3.json" | ||||||
|     }] |     }] | ||||||
|   }, |   }, | ||||||
|   "content_scripts": [ |   "content_scripts": [ | ||||||
|     { |     { | ||||||
|       "matches": [ |       "matches": [ | ||||||
|         "*://*.aliexpress.us/item/*", |         "*://*.aliexpress.com/item/*", | ||||||
|         "*://*.amazon.com/*" |         "*://*.amazon.com/*" | ||||||
|       ], |       ], | ||||||
|       "js": [ |       "js": [ | ||||||
| @@ -51,7 +58,7 @@ | |||||||
|   "web_accessible_resources": [ |   "web_accessible_resources": [ | ||||||
|     { |     { | ||||||
|       "resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ], |       "resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ], | ||||||
|       "matches": [ "*://*.aliexpress.us/*", "*://*.amazon.com/*" ] |       "matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*" ] | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -14,10 +14,13 @@ | |||||||
|   "action": { |   "action": { | ||||||
|   }, |   }, | ||||||
|   "host_permissions": [ |   "host_permissions": [ | ||||||
|  |     "*://*.jjcp52.com/", | ||||||
|     "*://*.pinduoduo.com/", |     "*://*.pinduoduo.com/", | ||||||
|     "*://*.temu.com/", |     "*://*.temu.com/", | ||||||
|     "*://*.aliexpress.us/", |     "*://*.aliexpress.com/", | ||||||
|     "*://*.amazon.com/" |     "*://*.alicdn.com/", | ||||||
|  |     "*://*.amazon.com/", | ||||||
|  |     "*://*.shein.com/" | ||||||
|   ], |   ], | ||||||
|   "permissions": [ |   "permissions": [ | ||||||
|     "cookies", |     "cookies", | ||||||
| @@ -35,12 +38,20 @@ | |||||||
|       "id": "1", |       "id": "1", | ||||||
|       "enabled": true, |       "enabled": true, | ||||||
|       "path": "rules_1.json" |       "path": "rules_1.json" | ||||||
|  |     },{ | ||||||
|  |       "id": "3", | ||||||
|  |       "enabled": true, | ||||||
|  |       "path": "rules_3.json" | ||||||
|  |     },{ | ||||||
|  |       "id": "4", | ||||||
|  |       "enabled": true, | ||||||
|  |       "path": "rules_4.json" | ||||||
|     }] |     }] | ||||||
|   }, |   }, | ||||||
|   "content_scripts": [ |   "content_scripts": [ | ||||||
|     { |     { | ||||||
|       "matches": [ |       "matches": [ | ||||||
|         "*://*.aliexpress.us/item/*", |         "*://*.aliexpress.com/item/*", | ||||||
|         "*://*.amazon.com/*" |         "*://*.amazon.com/*" | ||||||
|       ], |       ], | ||||||
|       "js": [ |       "js": [ | ||||||
| @@ -51,7 +62,7 @@ | |||||||
|   "web_accessible_resources": [ |   "web_accessible_resources": [ | ||||||
|     { |     { | ||||||
|       "resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ], |       "resources": [ "js/download.js","js/jszip.min.js","js/FileSaver.js" ], | ||||||
|       "matches": [ "*://*.aliexpress.us/*", "*://*.amazon.com/*" ] |       "matches": [ "*://*.aliexpress.com/*", "*://*.amazon.com/*" ] | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
|   | |||||||
| @@ -72,6 +72,11 @@ const router = new VueRouter({ | |||||||
|           name: 'niubiCopy', |           name: 'niubiCopy', | ||||||
|           component: () => import('../view/selection/NiubiCopy.vue') |           component: () => import('../view/selection/NiubiCopy.vue') | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |           path: 'aliExpressCopy', | ||||||
|  |           name: 'aliExpressCopy', | ||||||
|  |           component: () => import('../view/selection/AliExpressCopy.vue') | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|           path: 'storeTrack', |           path: 'storeTrack', | ||||||
|           name: 'storeTrack', |           name: 'storeTrack', | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								src/utils/image.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/utils/image.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | import SparkMd5 from 'spark-md5' | ||||||
|  |  | ||||||
|  | export function getImageMd5(imageUrl) { | ||||||
|  |     /*return new Promise((resolve, reject) => { | ||||||
|  |         fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象 | ||||||
|  |           .then((blobData) => { | ||||||
|  |             const reader = new FileReader(); | ||||||
|  |              | ||||||
|  |             // 读取Blob对象的内容 | ||||||
|  |             reader.onloadend = function() { | ||||||
|  |                 let spark = new SparkMd5() | ||||||
|  |                 spark.appendBinary(this.result);  | ||||||
|  |                 let md5 = spark.end() | ||||||
|  |                 console.log(md5) | ||||||
|  |                 console.log(this.result) | ||||||
|  |  | ||||||
|  |                 //resolve({md5, imageData: new File([blobData], 'test.jpeg', {type: blobData.type})}); | ||||||
|  |                 resolve({md5, imageData: this.result}); | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             reader.readAsBinaryString(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法 | ||||||
|  |  | ||||||
|  |              | ||||||
|  |           }) | ||||||
|  |  | ||||||
|  |     });*/ | ||||||
|  |  | ||||||
|  |     return new Promise((resolve, reject) => { | ||||||
|  |         fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象 | ||||||
|  |           .then((blobData) => { | ||||||
|  |             const reader = new FileReader(); | ||||||
|  |              | ||||||
|  |             // 读取Blob对象的内容 | ||||||
|  |             reader.onloadend = function() { | ||||||
|  |                 let spark = new SparkMd5.ArrayBuffer() | ||||||
|  |                 spark.append(this.result);  | ||||||
|  |                 let md5 = spark.end() | ||||||
|  |  | ||||||
|  |                 //resolve({md5, imageData: new File([blobData], 'test.jpeg', {type: blobData.type})}); | ||||||
|  |                 resolve({md5, imageData: this.result}); | ||||||
|  |             }; | ||||||
|  |              | ||||||
|  |             reader.readAsArrayBuffer(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法 | ||||||
|  |  | ||||||
|  |              | ||||||
|  |           }) | ||||||
|  |  | ||||||
|  |     }); | ||||||
|  | } | ||||||
| @@ -81,6 +81,7 @@ | |||||||
|               <span slot="title">选品采集</span> |               <span slot="title">选品采集</span> | ||||||
|             </template> |             </template> | ||||||
|             <el-menu-item index="/niubiCopy">商品采集</el-menu-item> |             <el-menu-item index="/niubiCopy">商品采集</el-menu-item> | ||||||
|  |             <el-menu-item index="/aliExpressCopy">速卖通采集</el-menu-item> | ||||||
|             <el-submenu index="/track" style="padding-left: 15px;"> |             <el-submenu index="/track" style="padding-left: 15px;"> | ||||||
|               <template slot="title"> |               <template slot="title"> | ||||||
|                 <span slot="title">选品跟踪</span> |                 <span slot="title">选品跟踪</span> | ||||||
|   | |||||||
							
								
								
									
										168
									
								
								src/view/selection/AliExpressCopy.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								src/view/selection/AliExpressCopy.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <ai-list class="list"> | ||||||
|  |       <ai-title | ||||||
|  |         slot="title" | ||||||
|  |         title="速卖通采集" | ||||||
|  |         tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态" | ||||||
|  |         isShowBottomBorder> | ||||||
|  |       </ai-title> | ||||||
|  |       <template slot="content"> | ||||||
|  |         <div class="content"> | ||||||
|  |           <ai-search-bar> | ||||||
|  |             <template #left> | ||||||
|  |               <div class="search-item"> | ||||||
|  |                 <label style="width:80px">店铺:</label> | ||||||
|  |                 <el-select v-model="search.mallId" :clearable="true" @change="search.current =1, getList()" 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> | ||||||
|  |             </template> | ||||||
|  |             <template #right> | ||||||
|  |               <el-button type="primary" @click="search.current =1, getList()">查询</el-button> | ||||||
|  |             </template> | ||||||
|  |           </ai-search-bar> | ||||||
|  |           <ai-search-bar> | ||||||
|  |             <template #left> | ||||||
|  |               <el-button type="button" :class="'el-button el-button--primary'" @click="beforeCopy()">开始采集</el-button> | ||||||
|  |             </template> | ||||||
|  |           </ai-search-bar> | ||||||
|  |           <ai-table | ||||||
|  |             :tableData="tableData" | ||||||
|  |             :col-configs="colConfigs" | ||||||
|  |             :total="total" | ||||||
|  |             style="margin-top: 8px;" | ||||||
|  |             :current.sync="search.current" :size.sync="search.size" | ||||||
|  |             @getList="getList"> | ||||||
|  |             <el-table-column slot="url" label="商品地址" align="left"> | ||||||
|  |               <template slot-scope="scope"> | ||||||
|  |                 <div v-if="scope.row.url.startsWith('http')"><a class="el-link el-link--primary" :href="scope.row.url" target="_blank">{{ scope.row.url }}</a></div> | ||||||
|  |                 <div v-else><a class="el-link el-link--primary" :href="'https://www.temu.com/goods.html?goods_id=' + scope.row.url" target="_blank">{{ scope.row.url }}</a></div> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |             <el-table-column slot="type" label="来源" width="100px" align="left"> | ||||||
|  |               <template slot-scope="scope"> | ||||||
|  |                 速卖通 | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |           </ai-table> | ||||||
|  |         </div> | ||||||
|  |       </template> | ||||||
|  |     </ai-list> | ||||||
|  |  | ||||||
|  |     <ai-dialog | ||||||
|  |       title="采集" | ||||||
|  |       :visible.sync="copyFromDlgShow" | ||||||
|  |       :close-on-click-modal="false" | ||||||
|  |       width="790px" | ||||||
|  |       customFooter | ||||||
|  |       @close="handleClose"> | ||||||
|  |       <ai-copy-from-ali-express v-if="copyFromDlgShow" @onClose="handleClose" @onSuccess="handleSuccess"></ai-copy-from-ali-express> | ||||||
|  |     </ai-dialog> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import AiCopyFromAliExpress from "@/components/AiCopyFromAliExpress.vue"; | ||||||
|  | import {sendChromeAPIMessage} from '@/api/chromeApi' | ||||||
|  | import { getImageMd5 } from "@/utils/image.js" | ||||||
|  |   export default { | ||||||
|  |     name: 'NiubiCopy', | ||||||
|  |     components: {AiCopyFromAliExpress}, | ||||||
|  |  | ||||||
|  |     data () { | ||||||
|  |       return { | ||||||
|  |         search: { | ||||||
|  |           current: 1, | ||||||
|  |           size: 10, | ||||||
|  |           type: '2', | ||||||
|  |           mallId: '' | ||||||
|  |         }, | ||||||
|  |          | ||||||
|  |         colConfigs: [ | ||||||
|  |           { slot: 'url', label: '商品地址', align: 'left' }, | ||||||
|  |           { slot: 'type', label: '来源', width: '100px', align: 'left'}, | ||||||
|  |           { prop: 'mallName', label: '店铺名称', width: '200px', align: 'left'}, | ||||||
|  |           { prop: 'createTime', label: '复制时间', width: '180px'} | ||||||
|  |         ], | ||||||
|  |         tableData: [], | ||||||
|  |         total: 0, | ||||||
|  |         copyFromDlgShow: false, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     created () { | ||||||
|  |       this.getList() | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     methods: { | ||||||
|  |       async getList () { | ||||||
|  |         let res2 = await getImageMd5('http://temu.jjcp52.com/dist/test.png') | ||||||
|  |         console.log(res2) | ||||||
|  |          | ||||||
|  |         let res3 = await sendChromeAPIMessage({ | ||||||
|  |           url: 'marvel-mms/cn/api/kiana/gmp/bg/phoenix/api/material/create', | ||||||
|  |           needMallId: true, | ||||||
|  |           mallId: '634418212443160', | ||||||
|  |           data: { | ||||||
|  |             folderId: 0, | ||||||
|  |             createDetailList: [ | ||||||
|  |               { | ||||||
|  |                 materialType: 1, | ||||||
|  |                 materialMd5: res2.md5, | ||||||
|  |                 materialName: "test.png" | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |         let res4 = await sendChromeAPIMessage({ | ||||||
|  |           url: 'galerie/business/get_signature?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag', | ||||||
|  |           needMallId: true, | ||||||
|  |           mallId: '634418212443160', | ||||||
|  |           data: { | ||||||
|  |             bucket_tag: "product-material-tag" | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |  | ||||||
|  |         let res5 = await sendChromeAPIMessage({ | ||||||
|  |           url: 'https://kuajing-file.pinduoduo.com/api/galerie/v3/store_image?sdk_version=js-0.0.16-alpha.0&tag_name=product-material-tag', | ||||||
|  |           isFormData: true, | ||||||
|  |           data: { | ||||||
|  |             url_width_height: true, | ||||||
|  |             image: new Uint8Array(res2.imageData), | ||||||
|  |             upload_sign: res4.result.signature | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |         console.log(res5) | ||||||
|  |  | ||||||
|  |         this.$http.post('/api/copyProduct/myPage',null,{ | ||||||
|  |             params: { | ||||||
|  |                 ...this.search | ||||||
|  |             } | ||||||
|  |         }).then(res => { | ||||||
|  |             this.tableData = res.data.records | ||||||
|  |             this.total = res.data.total | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       beforeCopy() { | ||||||
|  |         this.copyFromDlgShow = true | ||||||
|  |       }, | ||||||
|  |       handleClose() { | ||||||
|  |         this.copyFromDlgShow = false | ||||||
|  |       }, | ||||||
|  |       // 添加模板成功 | ||||||
|  |       handleSuccess() { | ||||||
|  |         this.copyFromDlgShow = false | ||||||
|  |         this.getList() | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | </style> | ||||||
| @@ -3,7 +3,7 @@ | |||||||
|     <ai-list class="list"> |     <ai-list class="list"> | ||||||
|       <ai-title |       <ai-title | ||||||
|         slot="title" |         slot="title" | ||||||
|         title="智能复制" |         title="商品采集" | ||||||
|         tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态" |         tips="请先在当前浏览器登录“拼多多跨境卖家中心”,期间保持登录状态" | ||||||
|         isShowBottomBorder> |         isShowBottomBorder> | ||||||
|       </ai-title> |       </ai-title> | ||||||
| @@ -11,10 +11,6 @@ | |||||||
|         <div class="content"> |         <div class="content"> | ||||||
|           <ai-search-bar> |           <ai-search-bar> | ||||||
|             <template #left> |             <template #left> | ||||||
|               <div class="search-item"> |  | ||||||
|                 <label style="width:80px">来源:</label> |  | ||||||
|                 <ai-select :selectList="$dict.getDict('copy_from')" :clearable="true" v-model="search.type" @change="search.current =1, getList()"></ai-select> |  | ||||||
|               </div> |  | ||||||
|               <div class="search-item"> |               <div class="search-item"> | ||||||
|                 <label style="width:80px">店铺:</label> |                 <label style="width:80px">店铺:</label> | ||||||
|                 <el-select v-model="search.mallId" :clearable="true" @change="search.current =1, getList()" placeholder="请选择店铺" size="small"> |                 <el-select v-model="search.mallId" :clearable="true" @change="search.current =1, getList()" placeholder="请选择店铺" size="small"> | ||||||
| @@ -33,7 +29,7 @@ | |||||||
|           </ai-search-bar> |           </ai-search-bar> | ||||||
|           <ai-search-bar> |           <ai-search-bar> | ||||||
|             <template #left> |             <template #left> | ||||||
|               <el-button type="button" :class="'el-button el-button--primary'" @click="beforeCopy()">开始复制</el-button> |               <el-button type="button" :class="'el-button el-button--primary'" @click="beforeCopy()">开始采集</el-button> | ||||||
|             </template> |             </template> | ||||||
|           </ai-search-bar> |           </ai-search-bar> | ||||||
|           <ai-table |           <ai-table | ||||||
| @@ -49,13 +45,18 @@ | |||||||
|                 <div v-else><a class="el-link el-link--primary" :href="'https://www.temu.com/goods.html?goods_id=' + scope.row.url" target="_blank">{{ scope.row.url }}</a></div> |                 <div v-else><a class="el-link el-link--primary" :href="'https://www.temu.com/goods.html?goods_id=' + scope.row.url" target="_blank">{{ scope.row.url }}</a></div> | ||||||
|               </template> |               </template> | ||||||
|             </el-table-column> |             </el-table-column> | ||||||
|  |             <el-table-column slot="type" label="来源" width="100px" align="left"> | ||||||
|  |               <template slot-scope="scope"> | ||||||
|  |                 TEMU | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|           </ai-table> |           </ai-table> | ||||||
|         </div> |         </div> | ||||||
|       </template> |       </template> | ||||||
|     </ai-list> |     </ai-list> | ||||||
|  |  | ||||||
|     <ai-dialog |     <ai-dialog | ||||||
|       title="复制" |       title="采集" | ||||||
|       :visible.sync="copyFromDlgShow" |       :visible.sync="copyFromDlgShow" | ||||||
|       :close-on-click-modal="false" |       :close-on-click-modal="false" | ||||||
|       width="790px" |       width="790px" | ||||||
| @@ -77,13 +78,13 @@ import AiCopyFromTemu from "@/components/AiCopyFromTemu.vue"; | |||||||
|         search: { |         search: { | ||||||
|           current: 1, |           current: 1, | ||||||
|           size: 10, |           size: 10, | ||||||
|           type: '', |           type: '1', | ||||||
|           mallId: '' |           mallId: '' | ||||||
|         }, |         }, | ||||||
|          |          | ||||||
|         colConfigs: [ |         colConfigs: [ | ||||||
|           { slot: 'url', label: '商品地址', align: 'left' }, |           { slot: 'url', label: '商品地址', align: 'left' }, | ||||||
|           { prop: 'type', label: '来源', width: '100px', align: 'left',format: v => this.$dict.getLabel('copy_from', v), }, |           { slot: 'type', label: '来源', width: '100px', align: 'left'}, | ||||||
|           { prop: 'mallName', label: '店铺名称', width: '200px', align: 'left'}, |           { prop: 'mallName', label: '店铺名称', width: '200px', align: 'left'}, | ||||||
|           { prop: 'createTime', label: '复制时间', width: '180px'} |           { prop: 'createTime', label: '复制时间', width: '180px'} | ||||||
|         ], |         ], | ||||||
| @@ -94,7 +95,6 @@ import AiCopyFromTemu from "@/components/AiCopyFromTemu.vue"; | |||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     created () { |     created () { | ||||||
|       this.$dict.load('copy_from'); |  | ||||||
|       this.getList() |       this.getList() | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ | |||||||
| <script> | <script> | ||||||
|   import List from './components/List.vue' |   import List from './components/List.vue' | ||||||
|   import Detail from './components/Detail.vue' |   import Detail from './components/Detail.vue' | ||||||
|  |   import SheinDetail from './components/SheinDetail.vue' | ||||||
|  |  | ||||||
|   export default { |   export default { | ||||||
|     name: 'StoreTrack', |     name: 'StoreTrack', | ||||||
| @@ -18,7 +19,8 @@ | |||||||
|  |  | ||||||
|     components: { |     components: { | ||||||
|       List, |       List, | ||||||
|       Detail |       Detail, | ||||||
|  |       SheinDetail | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     data () { |     data () { | ||||||
| @@ -35,6 +37,11 @@ | |||||||
|           this.params = data.params |           this.params = data.params | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (data.type === 'SheinDetail') { | ||||||
|  |           this.component = 'SheinDetail' | ||||||
|  |           this.params = data.params | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if (data.type === 'List') { |         if (data.type === 'List') { | ||||||
|           this.component = 'List' |           this.component = 'List' | ||||||
|           this.params = data.params |           this.params = data.params | ||||||
|   | |||||||
| @@ -32,14 +32,22 @@ | |||||||
|                   <el-button type="text" @click="deleteMonitor(row.id)">删除</el-button> |                   <el-button type="text" @click="deleteMonitor(row.id)">删除</el-button> | ||||||
|                   <el-button type="text" @click="toUpdateMonitor(row)">修改</el-button> |                   <el-button type="text" @click="toUpdateMonitor(row)">修改</el-button> | ||||||
|                   <el-button type="text" @click="renew(row.id)">续费</el-button> |                   <el-button type="text" @click="renew(row.id)">续费</el-button> | ||||||
|                   <el-button type="text" @click="toDetail(row.id, row.content)">详情</el-button> |                   <el-button type="text" @click="toDetail(row.id, row.content, row.source)">详情</el-button> | ||||||
|                   <el-button type="text" @click="toBegin(row)">采集数据</el-button> |                   <el-button type="text" @click="toBegin(row)">采集数据</el-button> | ||||||
|                 </div> |                 </div> | ||||||
|               </template> |               </template> | ||||||
|             </el-table-column> |             </el-table-column> | ||||||
|             <el-table-column slot="content" label="店铺ID" show-overflow-tooltip align="center"> |             <el-table-column slot="content" label="店铺ID" show-overflow-tooltip align="center"> | ||||||
|               <template slot-scope="{ row }"> |               <template slot-scope="{ row }"> | ||||||
|                 <div><a class="el-link el-link--primary" :href="'https://www.temu.com/mall.html?mall_id=' + row.content" target="_blank">{{ row.content }}</a></div> |                 <div> | ||||||
|  |                   <a class="el-link el-link--primary" v-if="row.source == '0'" :href="'https://www.temu.com/mall.html?mall_id=' + row.content" target="_blank">{{ row.content }}</a> | ||||||
|  |                   <a class="el-link el-link--primary" v-else-if="row.source == '1'" :href="'https://www.shein.com/store/home?store_code=' + row.content" target="_blank">{{ row.content }}</a> | ||||||
|  |                 </div> | ||||||
|  |               </template> | ||||||
|  |             </el-table-column> | ||||||
|  |             <el-table-column slot="source" label="来源" show-overflow-tooltip align="center"> | ||||||
|  |               <template slot-scope="{ row }"> | ||||||
|  |                 {{ row.source == '0' ? 'TEMU': '希音' }} | ||||||
|               </template> |               </template> | ||||||
|             </el-table-column> |             </el-table-column> | ||||||
|           </ai-table> |           </ai-table> | ||||||
| @@ -66,6 +74,12 @@ | |||||||
|           :rules="[{ required: true, message: '请输入店铺ID', trigger: 'blur' }]"> |           :rules="[{ required: true, message: '请输入店铺ID', trigger: 'blur' }]"> | ||||||
|           <el-input placeholder="请输入店铺ID" v-model="form.mallId"></el-input> |           <el-input placeholder="请输入店铺ID" v-model="form.mallId"></el-input> | ||||||
|         </el-form-item> |         </el-form-item> | ||||||
|  |         <el-form-item label="来源" style="width: 100%;" prop="source" :rules="[{ required: true, message: '请选择来源', trigger: 'blur' }]"> | ||||||
|  |           <el-radio-group v-model="form.source" size="medium"> | ||||||
|  |               <el-radio :label="0">TEMU</el-radio> | ||||||
|  |               <el-radio :label="1">希音</el-radio> | ||||||
|  |           </el-radio-group> | ||||||
|  |         </el-form-item> | ||||||
|         <el-form-item |         <el-form-item | ||||||
|           prop="remark" |           prop="remark" | ||||||
|           label="备注" |           label="备注" | ||||||
| @@ -93,6 +107,12 @@ | |||||||
|           :rules="[{ required: true, message: '请输入店铺ID', trigger: 'blur' }]"> |           :rules="[{ required: true, message: '请输入店铺ID', trigger: 'blur' }]"> | ||||||
|           <el-input placeholder="请输入店铺ID" disabled v-model="updateForm.mallId"></el-input> |           <el-input placeholder="请输入店铺ID" disabled v-model="updateForm.mallId"></el-input> | ||||||
|         </el-form-item> |         </el-form-item> | ||||||
|  |         <el-form-item label="来源:" style="width: 100%;" prop="type" :rules="[{ required: true, message: '请选择来源', trigger: 'blur' }]"> | ||||||
|  |           <el-radio-group disabled v-model="updateForm.source" size="medium"> | ||||||
|  |               <el-radio :label="0">TEMU</el-radio> | ||||||
|  |               <el-radio :label="1">希音</el-radio> | ||||||
|  |           </el-radio-group> | ||||||
|  |         </el-form-item> | ||||||
|         <el-form-item |         <el-form-item | ||||||
|           prop="remark" |           prop="remark" | ||||||
|           label="备注" |           label="备注" | ||||||
| @@ -109,7 +129,7 @@ | |||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import {sendTemuAPIMessage} from '@/api/chromeApi' | import {sendTemuAPIMessage, sendSheinAPIMessage} from '@/api/chromeApi' | ||||||
|  |  | ||||||
|   export default { |   export default { | ||||||
|     name: 'List', |     name: 'List', | ||||||
| @@ -127,6 +147,7 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|           { prop: 'remark', label: '备注', align: 'left'}, |           { prop: 'remark', label: '备注', align: 'left'}, | ||||||
|           { prop: 'lastUpdateTime', label: '最后一次更新时间', align: 'left' }, |           { prop: 'lastUpdateTime', label: '最后一次更新时间', align: 'left' }, | ||||||
|           { prop: 'status', label: '状态', align: 'left', format: v => this.$dict.getLabel('monitor_status', v), }, |           { prop: 'status', label: '状态', align: 'left', format: v => this.$dict.getLabel('monitor_status', v), }, | ||||||
|  |           { slot: 'source', label: '来源', align: 'left' }, | ||||||
|           { prop: 'expireTime', label: '失效时间', align: 'left' }, |           { prop: 'expireTime', label: '失效时间', align: 'left' }, | ||||||
|           { prop: 'createTime', label: '添加时间', width: '180px', fixed: 'right'} |           { prop: 'createTime', label: '添加时间', width: '180px', fixed: 'right'} | ||||||
|         ], |         ], | ||||||
| @@ -135,6 +156,7 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|  |  | ||||||
|         form: { |         form: { | ||||||
|           mallId: '', |           mallId: '', | ||||||
|  |           source: 0, | ||||||
|           remark: '' |           remark: '' | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
| @@ -143,6 +165,7 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|         updateForm: { |         updateForm: { | ||||||
|           id: '', |           id: '', | ||||||
|           mallId: '', |           mallId: '', | ||||||
|  |           source: '', | ||||||
|           remark: '' |           remark: '' | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
| @@ -182,7 +205,7 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|           if (valid) { |           if (valid) { | ||||||
|             this.$http.post('/api/monitor/check',null, {params: {type: 1}}).then(res => { |             this.$http.post('/api/monitor/check',null, {params: {type: 1}}).then(res => { | ||||||
|               if (res.code == 0) { |               if (res.code == 0) { | ||||||
|                 this.$http.post(`/api/monitor/add`, {content: this.form.mallId, remark: this.form.remark, type: this.search.type}).then(res => { |                 this.$http.post(`/api/monitor/add`, {content: this.form.mallId, source: this.form.source, remark: this.form.remark, type: this.search.type}).then(res => { | ||||||
|                   if (res.code == 0) { |                   if (res.code == 0) { | ||||||
|                     this.$message.success('添加成功!') |                     this.$message.success('添加成功!') | ||||||
|                     this.$store.dispatch('getUserInfo') |                     this.$store.dispatch('getUserInfo') | ||||||
| @@ -198,6 +221,7 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|       toUpdateMonitor (obj) { |       toUpdateMonitor (obj) { | ||||||
|         this.updateObj = obj |         this.updateObj = obj | ||||||
|         this.updateForm.mallId = obj.content |         this.updateForm.mallId = obj.content | ||||||
|  |         this.updateForm.source = obj.source | ||||||
|         this.updateForm.remark = obj.remark |         this.updateForm.remark = obj.remark | ||||||
|         this.isUpdateDlgShow = true |         this.isUpdateDlgShow = true | ||||||
|       }, |       }, | ||||||
| @@ -248,6 +272,7 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|  |  | ||||||
|             let data = {} |             let data = {} | ||||||
|             data.monitorId = item.id |             data.monitorId = item.id | ||||||
|  |             data.source = item.source | ||||||
|             data.details = [] |             data.details = [] | ||||||
|  |  | ||||||
|             this.beginCollect(item, data, index) |             this.beginCollect(item, data, index) | ||||||
| @@ -289,7 +314,8 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|           }) |           }) | ||||||
|         }) |         }) | ||||||
|       }, |       }, | ||||||
|       toDetail (id, content) { |       toDetail (id, content, source) { | ||||||
|  |         if (source == '0') { | ||||||
|           this.$emit('change', { |           this.$emit('change', { | ||||||
|             type: 'Detail', |             type: 'Detail', | ||||||
|             params: { |             params: { | ||||||
| @@ -297,6 +323,16 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|               content: content |               content: content | ||||||
|             } |             } | ||||||
|           }) |           }) | ||||||
|  |         } else { | ||||||
|  |           this.$emit('change', { | ||||||
|  |             type: 'SheinDetail', | ||||||
|  |             params: { | ||||||
|  |               id: id || '', | ||||||
|  |               content: content | ||||||
|  |             } | ||||||
|  |           }) | ||||||
|  |         } | ||||||
|  |          | ||||||
|       }, |       }, | ||||||
|       addStore() { |       addStore() { | ||||||
|         this.form.mallId = '' |         this.form.mallId = '' | ||||||
| @@ -313,7 +349,15 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|  |  | ||||||
|         this.beginCollect(row, data, 0) |         this.beginCollect(row, data, 0) | ||||||
|       },  |       },  | ||||||
|  |        | ||||||
|       beginCollect(row, reqData, index) { |       beginCollect(row, reqData, index) { | ||||||
|  |         if (row.source == '0') { | ||||||
|  |           this.beginTemuCollect(row, reqData, index) | ||||||
|  |         } else if (row.source == '1') { | ||||||
|  |           this.beginSheinCollect(row, reqData, index) | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       beginTemuCollect(row, reqData, index) { | ||||||
|         sendTemuAPIMessage({ |         sendTemuAPIMessage({ | ||||||
|           url: 'api/bg/circle/c/mall/newGoodsList', |           url: 'api/bg/circle/c/mall/newGoodsList', | ||||||
|           anti: true, |           anti: true, | ||||||
| @@ -371,6 +415,60 @@ import {sendTemuAPIMessage} from '@/api/chromeApi' | |||||||
|               this.$message.error("采集失败,请检查https://www.temu.com是否能正常访问") |               this.$message.error("采集失败,请检查https://www.temu.com是否能正常访问") | ||||||
|             } |             } | ||||||
|           }) |           }) | ||||||
|  |       }, | ||||||
|  |       async beginSheinCollect(row, reqData, index) { | ||||||
|  |         let res = await sendSheinAPIMessage({ | ||||||
|  |           url: 'api/store/items/get', | ||||||
|  |           method: 'GET', | ||||||
|  |           params: { | ||||||
|  |             _ver: '1.1.8', | ||||||
|  |             _lang: 'en', | ||||||
|  |             scene_id: '10188', | ||||||
|  |             rule_poskey: "shoprecommend", | ||||||
|  |             requestType: "pageChange", | ||||||
|  |             search_type: "store", | ||||||
|  |             store_code: row.content, | ||||||
|  |             viewed_goods: '', | ||||||
|  |             limit: 120, | ||||||
|  |             page: this.pageNo | ||||||
|  |         }}) | ||||||
|  |         if (this.isBatchCollect && (index+1) == this.selectRows.length) { | ||||||
|  |           this.isLoading = false | ||||||
|  |           this.isBatchCollect = false | ||||||
|  |         } else { | ||||||
|  |           this.isLoading = false | ||||||
|  |         } | ||||||
|  |         if (res.goods && res.goods.length > 0) { | ||||||
|  |           res.goods.map(item => { | ||||||
|  |             let total = 0 | ||||||
|  |             if (item.pretreatInfo?.sellingPointUniversalLabels) { | ||||||
|  |               total = item.pretreatInfo.sellingPointUniversalLabels[0].starComment?.comment_num || 0 | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             reqData.details.push({ | ||||||
|  |               url: 'https://www.shein.com/'+item.goods_url_name.replace(/ /g, '-')+'-p-'+item.goods_id+'-cat-'+item.cat_id+'.html', | ||||||
|  |               price: item.salePrice.amount, | ||||||
|  |               saleTotal: total, | ||||||
|  |               goodsId: item.goods_id, | ||||||
|  |               imgUrl: 'https:'+item.goods_img, | ||||||
|  |               mallId: item.store_code | ||||||
|  |             }) | ||||||
|  |           }) | ||||||
|  |  | ||||||
|  |           if (res.goods.length == this.pageSize) { | ||||||
|  |             this.pageNo = this.pageNo + 1 | ||||||
|  |             this.beginCollect(row, reqData, index) | ||||||
|  |           } else { | ||||||
|  |             this.isLoading = false | ||||||
|  |             this.$http.post('/api/monitorDetail/addDetails', reqData | ||||||
|  |             ).then(res => { | ||||||
|  |               if (res.code == 0) { | ||||||
|  |                 this.$message.success('店铺ID【' + row.content + '】数据采集成功!') | ||||||
|  |                 this.getList() | ||||||
|  |               } | ||||||
|  |             }) | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										302
									
								
								src/view/selection/storetrack/components/SheinDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								src/view/selection/storetrack/components/SheinDetail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,302 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <ai-list class="list"> | ||||||
|  |       <ai-title | ||||||
|  |         slot="title" | ||||||
|  |         :title="'店铺ID(' + `${content}` + ')商品列表'" | ||||||
|  |         isShowBottomBorder isShowBack @onBackClick="cancel(false)"> | ||||||
|  |       </ai-title> | ||||||
|  |       <template slot="content"> | ||||||
|  |         <ai-search-bar> | ||||||
|  |           <template #left> | ||||||
|  |               <label style="width:80px">排序方式:</label> | ||||||
|  |               <el-select v-model="search.orderBy" :clearable="true" @change="search.current =1, getList()" placeholder="请选择排序方式" size="small"> | ||||||
|  |                 <el-option | ||||||
|  |                   v-for="item in orderBys" | ||||||
|  |                   :key="item.value" | ||||||
|  |                   :label="item.label" | ||||||
|  |                   :value="item.value"> | ||||||
|  |                 </el-option> | ||||||
|  |               </el-select> | ||||||
|  |               <label style="width:80px">价格区间:</label> | ||||||
|  |               <el-input :clearable="true" size="small" style="width: 80px" v-model="search.priceBegin" ></el-input> | ||||||
|  |               ~ | ||||||
|  |               <el-input :clearable="true" size="small" style="width: 80px" v-model="search.priceEnd" ></el-input> | ||||||
|  |               <label style="width:80px">评论数区间:</label> | ||||||
|  |               <el-input :clearable="true" size="small" style="width: 80px" v-model="search.saleBegin" ></el-input> | ||||||
|  |               ~ | ||||||
|  |               <el-input :clearable="true" size="small" style="width: 80px" v-model="search.saleEnd" ></el-input> | ||||||
|  |               <label style="width:100px">仅显示最新:</label> | ||||||
|  |               <ai-select :selectList="$dict.getDict('mall_yesno')" v-model="search.isNew"></ai-select> | ||||||
|  |               <label style="width:100px">仅显示下架:</label> | ||||||
|  |               <ai-select :selectList="$dict.getDict('mall_yesno')" v-model="search.isOff"></ai-select> | ||||||
|  |           </template> | ||||||
|  |           <template #right> | ||||||
|  |             <el-button type="primary" @click="search.current =1, getList()">查询</el-button> | ||||||
|  |           </template> | ||||||
|  |         </ai-search-bar> | ||||||
|  |         <div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; gap: 16px;"> | ||||||
|  |           <el-card v-for="item in tableData" :key="item.id" :body-style="{ padding: '0px', margin: '5px' }"> | ||||||
|  |             <div :class="[{'img-background': item.isSelect}, 'img-box']" v-if="item.isOff == '1'"> | ||||||
|  |               <div> | ||||||
|  |                 <el-image :src="item.imgUrl" class="mask image" :preview-src-list="[item.imgUrl]" /> | ||||||
|  |               </div> | ||||||
|  |               <span class="icon-box"> | ||||||
|  |                 <img style="width: 50px; height: 50px" src="../../../../assets/off.png"> | ||||||
|  |               </span> | ||||||
|  |             </div> | ||||||
|  |             <span class="nav-label labelBadge" v-else> | ||||||
|  |               <span class="ii" v-if="item.isNew == 1">新</span> | ||||||
|  |               <el-image :src="item.imgUrl" class="image" :preview-src-list="[item.imgUrl]" /> | ||||||
|  |             </span> | ||||||
|  |             <div style="padding: 14px;"> | ||||||
|  |               <div class="bottom clearfix"> | ||||||
|  |                 <div style="margin-bottom: 5px;"> | ||||||
|  |                   <div style="display: inline; margin-left: 5px;">${{ item.price }}<sub style="margin-left: 2px;" v-html="getPricePercent(item.priceChange)"></sub></div> | ||||||
|  |                   <div style="display: inline; margin-right: 5px; float: right;">{{ item.saleTotal }}<sub style="margin-left: 2px;" v-html="getSalePercent(item.saleChange)"></sub></div> | ||||||
|  |                 </div> | ||||||
|  |                 <div> | ||||||
|  |                   <div v-if="search.orderBy == '5'" style="display: inline">近3次日均评论数: <span style="color: red; font-weight: bold">{{ item.days3AverageSale }}</span></div> | ||||||
|  |                   <div v-else-if="search.orderBy == '6'" style="display: inline">近7次日均评论数: <span style="color: red; font-weight: bold">{{ item.days7AverageSale }}</span></div> | ||||||
|  |                   <div v-else-if="search.orderBy == '7'" style="display: inline">近15次日均评论数: <span style="color: red; font-weight: bold">{{ item.days15AverageSale }}</span></div> | ||||||
|  |                   <div v-else style="display: inline">日均评论数: <span style="color: red; font-weight: bold">{{ item.averageSale }}</span></div> | ||||||
|  |                     <ai-product-drop-down :params="item" :isHideCopy="true" :isShowDetail="true" :isShowAddFavorite="true" :isShowDelFavorite="false" @onGoDetail="goDetail(item.goodsId, item.monitorId)" style="float: right;"></ai-product-drop-down> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </el-card> | ||||||
|  |           <el-pagination | ||||||
|  |             layout="prev, pager, next" | ||||||
|  |             style="position: absolute; bottom: 0px; right: 40px;" | ||||||
|  |             :total="total" | ||||||
|  |             :page-size.sync="search.size" | ||||||
|  |             :current-page.sync="search.current" | ||||||
|  |             @current-change="getList"> | ||||||
|  |           </el-pagination> | ||||||
|  |         </div> | ||||||
|  |       </template> | ||||||
|  |     </ai-list> | ||||||
|  |  | ||||||
|  |     <div class="productDetail"> | ||||||
|  |       <el-dialog | ||||||
|  |         title="商品详情" | ||||||
|  |         :visible="isShowDetailDlg" | ||||||
|  |         :close-on-click-modal="false" | ||||||
|  |         width="80%" | ||||||
|  |         :before-close="handleClose"> | ||||||
|  |         <ai-product-detail v-if="isShowDetailDlg" :params="detailParams"/> | ||||||
|  |       </el-dialog> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  | import AiProductDetail from "@/components/AiProductDetail.vue"; | ||||||
|  | import AiProductDropDown from '@/components/AiProductDropDown.vue'; | ||||||
|  |  | ||||||
|  |   export default { | ||||||
|  |     name: 'DetailPage', | ||||||
|  |     props: ['params'], | ||||||
|  |     components: {AiProductDetail, AiProductDropDown}, | ||||||
|  |     data () { | ||||||
|  |       return { | ||||||
|  |         monitorId: '', | ||||||
|  |         content: '', | ||||||
|  |         search: { | ||||||
|  |           current: 1, | ||||||
|  |           type: '1', | ||||||
|  |           size: 120, | ||||||
|  |           orderBy: '', | ||||||
|  |           priceBegin: '', | ||||||
|  |           priceEnd: '', | ||||||
|  |           saleBegin: '', | ||||||
|  |           saleEnd: '', | ||||||
|  |           isNew: '', | ||||||
|  |           isOff: '' | ||||||
|  |         }, | ||||||
|  |         orderBys: [{ | ||||||
|  |           value: '0', | ||||||
|  |           label: '按评论数涨辐排序' | ||||||
|  |         },{ | ||||||
|  |           value: '1', | ||||||
|  |           label: '按价格涨辐排序' | ||||||
|  |         },{ | ||||||
|  |           value: '2', | ||||||
|  |           label: '按评论数排序' | ||||||
|  |         },{ | ||||||
|  |           value: '3', | ||||||
|  |           label: '按价格排序' | ||||||
|  |         },{ | ||||||
|  |           value: '4', | ||||||
|  |           label: '按日均评论数排序' | ||||||
|  |         },{ | ||||||
|  |           value: '5', | ||||||
|  |           label: '按近3次采集平均评论数排序' | ||||||
|  |         },{ | ||||||
|  |           value: '6', | ||||||
|  |           label: '按近7次采集平均评论数排序' | ||||||
|  |         },{ | ||||||
|  |           value: '7', | ||||||
|  |           label: '按近15次采集平均评论数排序' | ||||||
|  |         }], | ||||||
|  |         tableData: [], | ||||||
|  |         total: 0, | ||||||
|  |         isShowDetailDlg: false, | ||||||
|  |         detailParams: {} | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     created () { | ||||||
|  |       this.$dict.load('mall_yesno'); | ||||||
|  |       this.monitorId = this.params.id | ||||||
|  |       this.content = this.params.content | ||||||
|  |       this.getList() | ||||||
|  |     }, | ||||||
|  |  | ||||||
|  |     methods: { | ||||||
|  |       getList () { | ||||||
|  |         this.$http.post('/api/monitorDetail/myPageNew',null,{ | ||||||
|  |           params: { | ||||||
|  |             monitorId: this.monitorId, | ||||||
|  |             ...this.search | ||||||
|  |           } | ||||||
|  |         }).then(res => { | ||||||
|  |           res.data.records = res.data.records.map(item => { | ||||||
|  |             item.mallId = 'https://www.shein.com/store/home?store_code=' + item.mallId | ||||||
|  |             return item | ||||||
|  |           }) | ||||||
|  |           this.tableData = res.data.records | ||||||
|  |           this.total = res.data.total | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       cancel (isRefresh) { | ||||||
|  |         this.$emit('change', { | ||||||
|  |           type: 'List', | ||||||
|  |           isRefresh: !!isRefresh | ||||||
|  |         }) | ||||||
|  |       }, | ||||||
|  |       getPricePercent(data) { | ||||||
|  |         if (data < 0) { | ||||||
|  |           return '<div style="display: inline; color: green">↓' + data + '%</div>' | ||||||
|  |         } else if (data > 0) { | ||||||
|  |           return '<div style="display: inline; color: red">↑' + data + '%</div>' | ||||||
|  |         } | ||||||
|  |         return '' | ||||||
|  |       }, | ||||||
|  |       getSalePercent(data) { | ||||||
|  |         if (data < 0) { | ||||||
|  |           return '<div style="display: inline; color: green">↓' + data + '%</div>' | ||||||
|  |         } else if (data > 0) { | ||||||
|  |           return '<div style="display: inline; color: red">↑' + data + '%</div>' | ||||||
|  |         } | ||||||
|  |         return '' | ||||||
|  |       }, | ||||||
|  |       handleClose() { | ||||||
|  |         this.isShowDetailDlg = false | ||||||
|  |       }, | ||||||
|  |       goDetail (goodsId, monitorId) { | ||||||
|  |         this.detailParams = {goodsId: goodsId, monitorId: monitorId} | ||||||
|  |         this.isShowDetailDlg = true | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | .productDetail { | ||||||
|  |   :deep(.el-dialog) { | ||||||
|  |       height: 78vh; | ||||||
|  |       overflow: auto; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
|  | .time { | ||||||
|  |     font-size: 13px; | ||||||
|  |     color: #999; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   .bottom { | ||||||
|  |     margin-top: 13px; | ||||||
|  |     line-height: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .button { | ||||||
|  |     padding: 0; | ||||||
|  |     float: right; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .image { | ||||||
|  |     width: 100%; | ||||||
|  |     display: block; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   .clearfix:before, | ||||||
|  |   .clearfix:after { | ||||||
|  |       display: table; | ||||||
|  |       content: ""; | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   .clearfix:after { | ||||||
|  |       clear: both | ||||||
|  |   } | ||||||
|  |   .el-dropdown-link { | ||||||
|  |     cursor: pointer; | ||||||
|  |     color: #409EFF; | ||||||
|  |   } | ||||||
|  |   .el-icon-arrow-down { | ||||||
|  |     font-size: 12px; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /*徽标*/ | ||||||
|  | .labelBadge { | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .ii { | ||||||
|  |     background: #f00; | ||||||
|  |     border-radius: 50%; | ||||||
|  |     width: 20px; | ||||||
|  |     height: 20px; | ||||||
|  |     top: -3px; | ||||||
|  |     right: -5px; | ||||||
|  |     position: absolute; | ||||||
|  |     text-align: center; | ||||||
|  |     color: #FFF; | ||||||
|  |     z-index: 999; | ||||||
|  |     font-size: 14px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .img-box { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   //父级设置 相对定位,让 icon设置绝对定位时能够以该父级为准。 | ||||||
|  |   position: relative; | ||||||
|  |   // icon 设置 绝对定位 让其固定在你想要的合适位置。 样式可调整,自己定位即可。 | ||||||
|  |   .icon-box { | ||||||
|  |     position: absolute; | ||||||
|  |     top: 35%; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .mask { | ||||||
|  |   background-color: #000; | ||||||
|  |   opacity: 0.6; | ||||||
|  |  | ||||||
|  |   .el-image__inner { | ||||||
|  |     opacity: 0.6; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ::v-deep .mask > img { | ||||||
|  |   opacity: 0.6; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .el-icon { | ||||||
|  |   display: inline-block; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | </style> | ||||||
| @@ -298,12 +298,15 @@ | |||||||
|           Message.error("请选择备货单") |           Message.error("请选择备货单") | ||||||
|           return |           return | ||||||
|         } |         } | ||||||
|  |         console.log(this.arr) | ||||||
|         this.arr.map(item => { |         this.arr.map(item => { | ||||||
|           let temp = this.choosedList.filter(i => { |           let temp = this.choosedList.filter(i => { | ||||||
|             return i.subPurchaseOrderSn == item.subPurchaseOrderSn |             return i.subPurchaseOrderBasicVO?.subPurchaseOrderSn == item.subPurchaseOrderBasicVO.subPurchaseOrderSn | ||||||
|           }) |           }) | ||||||
|  |           console.log(temp) | ||||||
|           if (temp.length == 0) { |           if (temp.length == 0) { | ||||||
|             this.choosedList.push(item) |             this.choosedList.push(item) | ||||||
|  |             console.log(this.choosedList) | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|         Message.success("添加成功,可继续添加") |         Message.success("添加成功,可继续添加") | ||||||
|   | |||||||
| @@ -6823,6 +6823,11 @@ source-map@~0.5.1: | |||||||
|   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" |   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" | ||||||
|   integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== |   integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== | ||||||
|  |  | ||||||
|  | spark-md5@^3.0.2: | ||||||
|  |   version "3.0.2" | ||||||
|  |   resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.2.tgz#7952c4a30784347abcee73268e473b9c0167e3fc" | ||||||
|  |   integrity sha512-wcFzz9cDfbuqe0FZzfi2or1sgyIrsDwmPwfZC4hiNidPdPINjeUwNfv5kldczoEAcjl9Y1L3SM7Uz2PUEQzxQw== | ||||||
|  |  | ||||||
| spdx-correct@^3.0.0: | spdx-correct@^3.0.0: | ||||||
|   version "3.2.0" |   version "3.2.0" | ||||||
|   resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" |   resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user