更新
This commit is contained in:
		
							
								
								
									
										68
									
								
								src/components/AiAvatar.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/components/AiAvatar.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| <template> | ||||
|     <section class="AiAvatar"> | ||||
|       <el-row type="flex" v-if="type=='rect'"> | ||||
|         <div class="image-box"> | ||||
|           <el-image :src="value" :preview-src-list="preview?[value]:null"/> | ||||
|         </div> | ||||
|       </el-row> | ||||
|       <el-avatar v-else-if="type=='circle'" :src="value"> | ||||
|         <slot v-if="!value"/> | ||||
|       </el-avatar> | ||||
|     </section> | ||||
|   </template> | ||||
|    | ||||
|   <script> | ||||
|   export default { | ||||
|     name: "AiAvatar", | ||||
|     model: { | ||||
|       prop: "value", | ||||
|       event: "change" | ||||
|     }, | ||||
|     props: { | ||||
|       value: {type: String, default: ""}, | ||||
|       preview: {type: Boolean, default: true}, | ||||
|       type: {default: "rect"} | ||||
|     }, | ||||
|     data() { | ||||
|       return { | ||||
|       } | ||||
|     }, | ||||
|     methods: { | ||||
|     } | ||||
|   } | ||||
|   </script> | ||||
|    | ||||
|   <style lang="scss" scoped> | ||||
|   .AiAvatar { | ||||
|     font-size: 12px; | ||||
|     line-height: initial; | ||||
|    | ||||
|     .iconProfile_Picture { | ||||
|       color: #89b; | ||||
|     } | ||||
|    | ||||
|     :deep(.el-avatar) { | ||||
|       background: #26f; | ||||
|     } | ||||
|    | ||||
|     .image-box { | ||||
|       width: 104px !important; | ||||
|       height: 120px; | ||||
|       text-align: center; | ||||
|       background-color: #f5f5f5; | ||||
|       border: 1px solid rgba(208, 212, 220, 1); | ||||
|       border-radius: 2px; | ||||
|       padding: 0; | ||||
|    | ||||
|       .iconfont { | ||||
|         font-size: 32px | ||||
|       } | ||||
|    | ||||
|       .el-image { | ||||
|         width: 100%; | ||||
|         height: 100%; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   </style> | ||||
|    | ||||
| @@ -44,7 +44,6 @@ | ||||
|   .ai-card__body { | ||||
|     height: calc(100% - 72px); | ||||
|     padding: 0 20px 0; | ||||
|     overflow-y: auto; | ||||
|   } | ||||
|  | ||||
|   &.panel, &.headerPanel { | ||||
|   | ||||
							
								
								
									
										264
									
								
								src/components/AiCopyFromTemu.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								src/components/AiCopyFromTemu.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,264 @@ | ||||
| <template> | ||||
|     <div> | ||||
|         <el-form class="ai-form" :model="form" label-width="140px" 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 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' }]"> | ||||
|             <el-cascader style="width: 380px" v-model="form.targetCatId" :props="props"></el-cascader> | ||||
|             </el-form-item> | ||||
|         </el-form> | ||||
|         <div class="bottom flex-center"> | ||||
|             <el-button @click="$emit('onClose')">取 消</el-button> | ||||
|             <el-button type="primary" @click="addToDraft">确定</el-button> | ||||
|         </div> | ||||
|     </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {sendChromeAPIMessage, sendChromeWebReqMessage} from '@/api/chromeApi' | ||||
| import { Message } from 'element-ui' | ||||
|  | ||||
| export default { | ||||
|     name: 'AiCopyFromTemu', | ||||
|     props: ['params'], | ||||
|     data() { | ||||
|         return { | ||||
|             props: { | ||||
|                 value: 'catId', | ||||
|                 label: 'catName', | ||||
|                 lazy: true, | ||||
|                 lazyLoad (node, resolve) { | ||||
|                     sendChromeAPIMessage({ | ||||
|                         url: 'bg-anniston-mms/category/children/list', | ||||
|                         needMallId: true, | ||||
|                         data: { | ||||
|                             parentCatId: node.value || '' | ||||
|                         } | ||||
|                     }).then(res => { | ||||
|                         if (res.errorCode === 1000000) { | ||||
|                             resolve(res.result.categoryNodeVOS.map(v => { | ||||
|                             return { | ||||
|                                 ...v, | ||||
|                                 leaf: v.isLeaf | ||||
|                             } | ||||
|                             })) | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
|             }, | ||||
|             form: { | ||||
|                 url: '', | ||||
|                 type: 1,  // 默认从temu复制 | ||||
|                 targetMallId: '', | ||||
|                 targetCatId: [] | ||||
|             }, | ||||
|             goods: {}, | ||||
|             sku: {}, | ||||
|             productDetail: {} | ||||
|         } | ||||
|     }, | ||||
|     created () { | ||||
|         console.log(this.params?.url) | ||||
|         if (this.params?.url) { | ||||
|             this.form.url = this.params.url | ||||
|         } | ||||
|     }, | ||||
|     methods: { | ||||
|         async addToDraft() { | ||||
|             this.$refs.form.validate((valid) => { | ||||
|             if (valid) { | ||||
|                 this.$http.post('/api/copyProduct/check',null, {params: {type: 0}}).then(res => { | ||||
|                     if (res.code == 0) { | ||||
|                         let source | ||||
|                         if (this.form.type == '1') { | ||||
|                             source = 'temu' | ||||
|                         } else if (this.form.type == '2') { | ||||
|                             source = 'aliexpress' | ||||
|                         } | ||||
|                         sendChromeWebReqMessage({ | ||||
|                             type: source, | ||||
|                             url: this.form.url, | ||||
|                         }).then((res) => { | ||||
|                             if (this.form.type == '1') { | ||||
|                                 if (res.indexOf("rawData") == -1) { | ||||
|                                     Message.error("请检查地址是否正确,或者“TEMU”网站是否出现图形验证码") | ||||
|                                     return | ||||
|                                 } | ||||
|                                 let str = res.substring(res.indexOf("rawData")) | ||||
|                                 str = str.substring(0, str.indexOf("<\/script>")) | ||||
|                                 str = str.substring(str.indexOf("{")) | ||||
|                                 str = str.substring(0, str.lastIndexOf("}")) | ||||
|                                 str = str + "}" | ||||
|  | ||||
|                                 let goodsObj = JSON.parse(str) | ||||
|                                 this.goods = goodsObj.store.goods | ||||
|                                 this.sku = goodsObj.store.sku | ||||
|                                 this.productDetail = goodsObj.store.productDetail | ||||
|  | ||||
|                                 let specIds = [] | ||||
|                                 this.sku.forEach(item => { | ||||
|                                     item.specs.forEach(item1 => { | ||||
|                                         let flag = false | ||||
|                                         specIds.forEach(item2 => { | ||||
|                                         if (item2.specValue == item1.specValue) { | ||||
|                                             flag = true | ||||
|                                         } | ||||
|                                         }) | ||||
|                                         if (!flag) { | ||||
|                                         specIds.push({specKeyId: item1.specKeyId, specValue: item1.specValue}) | ||||
|                                         } | ||||
|                                     }) | ||||
|                                 }) | ||||
|  | ||||
|                                 Promise.all(specIds.map(item => this.getSpecId(item).then(res => { | ||||
|                                     this.sku.forEach(item1 => { | ||||
|                                         item1.specs.forEach(item2 => { | ||||
|                                             if (item2.specValue == item.specValue) { | ||||
|                                                 item2.specValueId = res.result.specId | ||||
|                                             } | ||||
|                                         }) | ||||
|                                     }) | ||||
|                                     return 0 | ||||
|                                 }))).then(() => { | ||||
|                                     this.$http.post('/api/copyProduct/translate',{type: 1, goods: this.goods, sku: this.sku, productDetail: this.productDetail}).then(res => { | ||||
|                                         if (res.code == 0) { | ||||
|                                             this.createDraft(res.data) | ||||
|                                         } | ||||
|                                     }) | ||||
|                                 }) | ||||
|                             } else if (this.form.type == '2') { | ||||
|                                 /*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) | ||||
|  | ||||
|                                 let obj = JSON.parse(str) | ||||
|  | ||||
|                                 sendChromeWebReqMessage({ | ||||
|                                 type: source, | ||||
|                                 url: obj.productDescComponent.descriptionUrl, | ||||
|                                 }).then((res1) => { | ||||
|                                 res1 = res1.substring(0, res1.indexOf("<script>")) | ||||
|                                 let str = res1.replace(/<img[^>]+src="([^">]+)"[^>]+>/g, '$1\n').replace(/<.*?>/g, '[||]') | ||||
|                                 let arr = str.split('[||]') | ||||
|                                 for (let i = 0; i < arr.length; i++) { | ||||
|                                     console.log(arr[i]) | ||||
|                                 } | ||||
|                                 })*/ | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|         }) | ||||
|       }, | ||||
|       createDraft(data) { | ||||
|         sendChromeAPIMessage({ | ||||
|           url: 'bg-visage-mms/product/draft/add', | ||||
|           needMallId: true, | ||||
|           mallId: this.form.targetMallId, | ||||
|           data: { | ||||
|             catId: this.form.targetCatId[this.form.targetCatId.length - 1] | ||||
|         }}).then((res) => { | ||||
|           if (res.errorCode == 1000000) { | ||||
|             let draftId = res.result.productDraftId | ||||
|             let content = data | ||||
|             let i = 0 | ||||
|             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) { | ||||
|             Message.success("成功添加到草稿箱") | ||||
|             this.saveInfo() | ||||
|           } else { | ||||
|             setTimeout(() => { | ||||
|               this.createProduct(content) | ||||
|             }, 500) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       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.form.url, | ||||
|             type: this.form.type | ||||
|           }).then(res1 => { | ||||
|           if (res1.code == 0) { | ||||
|             this.$store.dispatch('getUserInfo') | ||||
|             this.$emit('onSuccess') | ||||
|           } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .bottom { | ||||
|     justify-content: center; | ||||
|   } | ||||
| </style> | ||||
| @@ -2,13 +2,16 @@ | ||||
|   <ai-detail class="audit"> | ||||
|     <template slot="content"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <ai-product-drop-down v-if="info" :params="info" slot="right"></ai-product-drop-down> | ||||
|         <template #content> | ||||
|           <div class="flex"> | ||||
|             <ai-avatar v-model="info.imgUrl" :editable="false" :preview="true"/> | ||||
|             <ai-wrapper | ||||
|             label-width="120px"> | ||||
|             <ai-info-item label="名称"   :value="info.name"></ai-info-item> | ||||
|             <ai-info-item label="显示顺序"   :value="info.showIndex"></ai-info-item> | ||||
|             <ai-info-item label="创建时间"   :value="info.createTime" ></ai-info-item> | ||||
|               label-width="120px" class="fill"> | ||||
|               <ai-info-item label="价格:"   :value="'$' + info.price"></ai-info-item> | ||||
|               <ai-info-item label="销量:"   :value="info.saleTotal"></ai-info-item> | ||||
|             </ai-wrapper> | ||||
|           </div> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <ai-card title="趋势信息"> | ||||
| @@ -20,11 +23,15 @@ | ||||
|   </ai-detail> | ||||
| </template> | ||||
| <script> | ||||
| import { Message } from "element-ui" | ||||
| import AiProductDropDown from './AiProductDropDown.vue' | ||||
| import { DualAxes } from '@antv/g2plot' | ||||
|  | ||||
| export default { | ||||
|   name: "AiProductDetail", | ||||
|   props: ['params'], | ||||
|   components: { | ||||
|     AiProductDropDown | ||||
|   }, | ||||
|   data() { | ||||
|     return { | ||||
|       info: {} | ||||
| @@ -33,7 +40,6 @@ export default { | ||||
|   computed: { | ||||
|   }, | ||||
|   created() { | ||||
|     console.log(this.params.goodsId) | ||||
|     this.getInfo() | ||||
|   }, | ||||
|   methods: { | ||||
| @@ -44,6 +50,32 @@ export default { | ||||
|         } | ||||
|       }).then(res => { | ||||
|         this.info = res.data | ||||
|  | ||||
|         const dualAxes = new DualAxes('chart', { | ||||
|           data: [this.info.priceAndSale, this.info.priceAndSale], | ||||
|           xField: '日期', | ||||
|           yField: ['价格', '销量'], | ||||
|           geometryOptions: [ | ||||
|             { | ||||
|               geometry: 'line', | ||||
|               color: '#5B8FF9', | ||||
|             }, | ||||
|             { | ||||
|               geometry: 'line', | ||||
|               color: '#5AD8A6', | ||||
|             } | ||||
|           ], | ||||
|           smooth: true, | ||||
|           // @TODO 后续会换一种动画方式 | ||||
|           animation: { | ||||
|             appear: { | ||||
|               animation: 'path-in', | ||||
|               duration: 5000, | ||||
|             }, | ||||
|           }, | ||||
|         }); | ||||
|  | ||||
|         dualAxes.render(); | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
|   | ||||
							
								
								
									
										80
									
								
								src/components/AiProductDropDown.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/components/AiProductDropDown.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <el-dropdown @command="handleClick"> | ||||
|       <span class="el-dropdown-link"> | ||||
|         操作<i class="el-icon-arrow-down el-icon--right"></i> | ||||
|       </span> | ||||
|       <el-dropdown-menu slot="dropdown"> | ||||
|         <el-dropdown-item v-if="isShowDetail" :command="beforeGoDetail(params.goodsId)">查看详情</el-dropdown-item> | ||||
|         <el-dropdown-item divided :command="beforeCopy(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-menu> | ||||
|     </el-dropdown> | ||||
|  | ||||
|     <ai-dialog | ||||
|       title="复制" | ||||
|       :visible.sync="copyFromDlgShow" | ||||
|       :close-on-click-modal="false" | ||||
|       width="790px" | ||||
|       customFooter | ||||
|       :append-to-body="true" | ||||
|       @close="handleClose"> | ||||
|       <ai-copy-from-temu v-if="copyFromDlgShow" :params="temuParams" @onClose="handleClose" @onSuccess="handleSuccess"></ai-copy-from-temu> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
| <script> | ||||
| import AiCopyFromTemu from "./AiCopyFromTemu.vue"; | ||||
| export default { | ||||
|   name: "AiProductDropDown", | ||||
|   components: {AiCopyFromTemu}, | ||||
|   props: ['params', 'isShowDetail'], | ||||
|   data() { | ||||
|     return { | ||||
|       info: {}, | ||||
|       copyFromDlgShow: false, | ||||
|       temuParams: {} | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|   }, | ||||
|   created() { | ||||
|   }, | ||||
|   methods: { | ||||
|     handleClick(e) { | ||||
|       if (e.type == 'detail') { | ||||
|         this.$emit('onGoDetail') | ||||
|       } else if (e.type == 'copy') { | ||||
|         this.temuParams = {url: 'https://www.temu.com/' + e.url} | ||||
|         this.copyFromDlgShow = true | ||||
|       } else if (e.type == 'goMall') { | ||||
|         window.open('https://www.temu.com/mall.html?mall_id=' + e.mallId, '_blank'); | ||||
|       } else if (e.type == 'goWeb') { | ||||
|         console.log(e.url) | ||||
|         window.open('https://www.temu.com/' + e.url, '_blank'); | ||||
|       } | ||||
|     }, | ||||
|     beforeGoDetail(goodsId) { | ||||
|       return {type: 'detail', goodsId: goodsId} | ||||
|     }, | ||||
|     beforeCopy(url) { | ||||
|       return {type: 'copy', url: url} | ||||
|     }, | ||||
|     beforeGoMal(mallId) { | ||||
|       return {type: 'goMall', mallId: mallId} | ||||
|     }, | ||||
|     beforeGoWeb (url) { | ||||
|       return {type: 'goWeb', url: url} | ||||
|     }, | ||||
|     handleClose() { | ||||
|       this.copyFromDlgShow = false | ||||
|     }, | ||||
|     handleSuccess() { | ||||
|       this.copyFromDlgShow = false | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
| @@ -75,7 +75,7 @@ const router = new VueRouter({ | ||||
|         { | ||||
|           path: 'keywordTrack', | ||||
|           name: 'keywordTrack', | ||||
|           component: () => import('../view/selection/KeywordTrack.vue') | ||||
|           component: () => import('../view/selection/keywordtrack/Index.vue') | ||||
|         }, | ||||
|  | ||||
|         { | ||||
|   | ||||
| @@ -16,7 +16,6 @@ export function transform(leftData) { | ||||
|   // 普通属性 | ||||
|   rightData.productName = leftData.productName; | ||||
|   rightData.materialMultiLanguages = leftData.productLocalExtAttr.materialMultiLanguages; | ||||
|   rightData.productI18nReqs = leftData.productI18nList; | ||||
|   rightData.productPropertyReqs = []; | ||||
|   for (let i = 0; i < leftData.productPropertyList.length; i++) { | ||||
|     rightData.productPropertyReqs.push({ | ||||
| @@ -121,9 +120,18 @@ export function transform(leftData) { | ||||
|       imageUrl: leftData.outerPackageImages[i].imageUrl | ||||
|     }) | ||||
|   } | ||||
|   if (leftData.productGuideFileI18nList) { | ||||
|     rightData.productGuideFileI18nReqs = leftData.productGuideFileI18nList.map(item => { | ||||
|       return {fileName: item.fileName, | ||||
|         fileUrl: item.fileUrl, | ||||
|         language: item.language, | ||||
|         languages: item.languages} | ||||
|     }); | ||||
|   } else { | ||||
|     rightData.productGuideFileI18nReqs = [] | ||||
|   } | ||||
|   rightData.productOuterPackageReq = leftData.productWhExtAttr.productOuterPackage; | ||||
|   rightData.sensitiveTransNormalFileReqs = leftData.productWhExtAttr.sensitiveTransNormalFiles; | ||||
|   rightData.productGuideFileI18nReqs = leftData.productGuideFileI18nList; | ||||
|   rightData.productSaleExtAttrReq = {}; | ||||
|   rightData.productDraftId = ""; | ||||
|  | ||||
|   | ||||
| @@ -60,44 +60,16 @@ | ||||
|       width="790px" | ||||
|       customFooter | ||||
|       @close="handleClose"> | ||||
|       <el-form class="ai-form" :model="form" label-width="140px" 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 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' }]"> | ||||
|           <el-cascader style="width: 380px" v-model="form.targetCatId" :props="props"></el-cascader> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <div class="dialog-footer" slot="footer"> | ||||
|         <el-button @click="copyFromDlgShow = false">取 消</el-button> | ||||
|         <el-button type="primary" @click="addToDraft">确定</el-button> | ||||
|       </div> | ||||
|       <ai-copy-from-temu v-if="copyFromDlgShow" @onClose="handleClose" @onSuccess="handleSuccess"></ai-copy-from-temu> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {sendChromeAPIMessage, sendChromeWebReqMessage} from '@/api/chromeApi' | ||||
| import { Message } from 'element-ui' | ||||
|  | ||||
| import AiCopyFromTemu from "@/components/AiCopyFromTemu.vue"; | ||||
|   export default { | ||||
|     name: 'NiubiCopy', | ||||
|     components: {AiCopyFromTemu}, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
| @@ -107,29 +79,7 @@ import { Message } from 'element-ui' | ||||
|           type: '', | ||||
|           mallId: '' | ||||
|         }, | ||||
|         props: { | ||||
|           value: 'catId', | ||||
|           label: 'catName', | ||||
|           lazy: true, | ||||
|           lazyLoad (node, resolve) { | ||||
|             sendChromeAPIMessage({ | ||||
|               url: 'bg-anniston-mms/category/children/list', | ||||
|               needMallId: true, | ||||
|               data: { | ||||
|                 parentCatId: node.value || '' | ||||
|               } | ||||
|             }).then(res => { | ||||
|               if (res.errorCode === 1000000) { | ||||
|                 resolve(res.result.categoryNodeVOS.map(v => { | ||||
|                   return { | ||||
|                     ...v, | ||||
|                     leaf: v.isLeaf | ||||
|                   } | ||||
|                 })) | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }, | ||||
|          | ||||
|         colConfigs: [ | ||||
|           { slot: 'url', label: '商品地址', align: 'left' }, | ||||
|           { prop: 'type', label: '来源', width: '100px', align: 'left',format: v => this.$dict.getLabel('copy_from', v), }, | ||||
| @@ -138,17 +88,7 @@ import { Message } from 'element-ui' | ||||
|         ], | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
|  | ||||
|         copyFromDlgShow: false, | ||||
|         form: { | ||||
|           url: '', | ||||
|           type: 1,  // 默认从temu复制 | ||||
|           targetMallId: '', | ||||
|           targetCatId: [] | ||||
|         }, | ||||
|         goods: {}, | ||||
|         sku: {}, | ||||
|         productDetail: {} | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @@ -168,189 +108,17 @@ import { Message } from 'element-ui' | ||||
|             this.total = res.data.total | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       // 添加模板 | ||||
|       beforeCopy() { | ||||
|         this.copyFromDlgShow = true | ||||
|       }, | ||||
|       handleClose() { | ||||
|         this.copyFromDlgShow = false | ||||
|       }, | ||||
|       beforeCopy() { | ||||
|         this.form.type = 1 | ||||
|         this.form.url = '' | ||||
|         this.copyFromDlgShow = true | ||||
|       }, | ||||
|       async addToDraft() { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.$http.post('/api/copyProduct/check',null, {params: {type: 0}}).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 let source | ||||
|                 if (this.form.type == '1') { | ||||
|                   source = 'temu' | ||||
|                 } else if (this.form.type == '2') { | ||||
|                   source = 'aliexpress' | ||||
|                 } | ||||
|                 sendChromeWebReqMessage({ | ||||
|                   type: source, | ||||
|                   url: this.form.url, | ||||
|                 }).then((res) => { | ||||
|                   if (this.form.type == '1') { | ||||
|                     if (res.indexOf("rawData") == -1) { | ||||
|                       Message.error("请检查地址是否正确,或者“TEMU”网站是否出现图形验证码") | ||||
|                       return | ||||
|                     } | ||||
|                     let str = res.substring(res.indexOf("rawData")) | ||||
|                     str = str.substring(0, str.indexOf("<\/script>")) | ||||
|                     str = str.substring(str.indexOf("{")) | ||||
|                     str = str.substring(0, str.lastIndexOf("}")) | ||||
|                     str = str + "}" | ||||
|  | ||||
|                     let goodsObj = JSON.parse(str) | ||||
|                     this.goods = goodsObj.store.goods | ||||
|                     this.sku = goodsObj.store.sku | ||||
|                     this.productDetail = goodsObj.store.productDetail | ||||
|  | ||||
|                     let specIds = [] | ||||
|                     this.sku.forEach(item => { | ||||
|                       item.specs.forEach(item1 => { | ||||
|                         let flag = false | ||||
|                         specIds.forEach(item2 => { | ||||
|                           if (item2.specValue == item1.specValue) { | ||||
|                             flag = true | ||||
|                           } | ||||
|                         }) | ||||
|                         if (!flag) { | ||||
|                           specIds.push({specKeyId: item1.specKeyId, specValue: item1.specValue}) | ||||
|                         } | ||||
|                       }) | ||||
|                     }) | ||||
|  | ||||
|                     Promise.all(specIds.map(item => this.getSpecId(item).then(res => { | ||||
|                       this.sku.forEach(item1 => { | ||||
|                         item1.specs.forEach(item2 => { | ||||
|                           if (item2.specValue == item.specValue) { | ||||
|                             item2.specValueId = res.result.specId | ||||
|                           } | ||||
|                         }) | ||||
|                       }) | ||||
|                       return 0 | ||||
|                     }))).then(() => { | ||||
|                       this.$http.post('/api/copyProduct/translate',{type: 1, goods: this.goods, sku: this.sku, productDetail: this.productDetail}).then(res => { | ||||
|                         if (res.code == 0) { | ||||
|                           this.createDraft(res.data) | ||||
|                         } | ||||
|                       }) | ||||
|                     }) | ||||
|                   } else if (this.form.type == '2') { | ||||
|                     /*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) | ||||
|  | ||||
|                     let obj = JSON.parse(str) | ||||
|  | ||||
|                     sendChromeWebReqMessage({ | ||||
|                       type: source, | ||||
|                       url: obj.productDescComponent.descriptionUrl, | ||||
|                     }).then((res1) => { | ||||
|                       res1 = res1.substring(0, res1.indexOf("<script>")) | ||||
|                       let str = res1.replace(/<img[^>]+src="([^">]+)"[^>]+>/g, '$1\n').replace(/<.*?>/g, '[||]') | ||||
|                       let arr = str.split('[||]') | ||||
|                       for (let i = 0; i < arr.length; i++) { | ||||
|                         console.log(arr[i]) | ||||
|                       } | ||||
|                     })*/ | ||||
|                   } | ||||
|                 }) | ||||
|               } | ||||
|             }) | ||||
|              | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       createDraft(data) { | ||||
|         sendChromeAPIMessage({ | ||||
|           url: 'bg-visage-mms/product/draft/add', | ||||
|           needMallId: true, | ||||
|           mallId: this.form.targetMallId, | ||||
|           data: { | ||||
|             catId: this.form.targetCatId[this.form.targetCatId.length - 1] | ||||
|         }}).then((res) => { | ||||
|           if (res.errorCode == 1000000) { | ||||
|             let draftId = res.result.productDraftId | ||||
|             let content = data | ||||
|             let i = 0 | ||||
|             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) { | ||||
|             Message.success("成功添加到草稿箱") | ||||
|             this.saveInfo() | ||||
|           } else { | ||||
|             setTimeout(() => { | ||||
|               this.createProduct(content) | ||||
|             }, 500) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       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.form.url, | ||||
|             type: this.form.type | ||||
|           }).then(res1 => { | ||||
|           if (res1.code == 0) { | ||||
|             this.$store.dispatch('getUserInfo') | ||||
|       // 添加模板成功 | ||||
|       handleSuccess() { | ||||
|         this.copyFromDlgShow = false | ||||
|         this.getList() | ||||
|       } | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|   | ||||
							
								
								
									
										57
									
								
								src/view/selection/keywordtrack/Index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/view/selection/keywordtrack/Index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <template> | ||||
|   <div style="height: 100%;"> | ||||
|     <transition name="fade-transform" mode="out-in"> | ||||
|       <keep-alive :include="['List']"> | ||||
|         <component ref="component" :is="component" @change="onChange" :params="params"></component> | ||||
|       </keep-alive> | ||||
|     </transition> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import List from './components/List.vue' | ||||
|   import Detail from './components/Detail.vue' | ||||
|  | ||||
|   export default { | ||||
|     name: 'KeywordTrack', | ||||
|     label: '关键字跟踪', | ||||
|  | ||||
|     components: { | ||||
|       List, | ||||
|       Detail | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         component: 'List', | ||||
|         params: {} | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onChange (data) { | ||||
|         if (data.type === 'Detail') { | ||||
|           this.component = 'Detail' | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'List') { | ||||
|           this.component = 'List' | ||||
|           this.params = data.params | ||||
|  | ||||
|           this.$nextTick(() => { | ||||
|             if (data.isRefresh) { | ||||
|               setTimeout(() => { | ||||
|                 this.$refs.component.getList() | ||||
|               }, 600) | ||||
|             } | ||||
|           }) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
|  | ||||
							
								
								
									
										169
									
								
								src/view/selection/keywordtrack/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/view/selection/keywordtrack/components/Detail.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <ai-list class="list"> | ||||
|       <ai-title | ||||
|         slot="title" | ||||
|         title="商品列表" | ||||
|         isShowBottomBorder isShowBack @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|       <template slot="content"> | ||||
|         <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' }"> | ||||
|             <img :src="item.imgUrl" class="image"> | ||||
|             <div style="padding: 14px;"> | ||||
|               <div class="bottom clearfix"> | ||||
|                 <div style="margin-bottom: 5px;"> | ||||
|                   <div style="display: inline; margin-left: 5px;">${{ item.priceAndSale[0].price }}<sub style="margin-left: 2px;" v-html="getPricePercent(item.priceAndSale)"></sub></div> | ||||
|                   <div style="display: inline; margin-right: 5px; float: right;">{{ item.priceAndSale[0].sale_total }}<sub style="margin-left: 2px;" v-html="getSalePercent(item.priceAndSale)"></sub></div> | ||||
|                 </div> | ||||
|                 <ai-product-drop-down :params="item" :isShowDetail="true" @onGoDetail="goDetail(item.goodsId)" style="float: right;"></ai-product-drop-down> | ||||
|               </div> | ||||
|             </div> | ||||
|           </el-card> | ||||
|         </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: '', | ||||
|         search: { | ||||
|           current: 1, | ||||
|           type: '1', | ||||
|           size: 120 | ||||
|         }, | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
|         isShowDetailDlg: false, | ||||
|         detailParams: {} | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.monitorId = this.params.id | ||||
|       this.getList() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.$http.post('/api/monitorDetail/myPage',null,{ | ||||
|           params: { | ||||
|             monitorId: this.monitorId, | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then(res => { | ||||
|           this.tableData = res.data.records | ||||
|           this.total = res.data.total | ||||
|         }) | ||||
|       }, | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'List', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       }, | ||||
|       getPricePercent(data) { | ||||
|         if (data.length == 2) { | ||||
|           let a = (data[0].price - data[1].price) / data[1].price | ||||
|           if (a < 0) { | ||||
|             return '<div style="display: inline; color: green">↓' + (a*100).toFixed(2) + '%</div>' | ||||
|           } else if (a == 0) { | ||||
|             return '' | ||||
|           } else if (a > 0) { | ||||
|             return '<div style="display: inline; color: red">↑' + (a*100).toFixed(2) + '%</div>' | ||||
|           } | ||||
|         } else { | ||||
|           return '' | ||||
|         } | ||||
|       }, | ||||
|       getSalePercent(data) { | ||||
|         if (data.length == 2) { | ||||
|           let a = (data[0].sale_total - data[1].sale_total) / data[1].sale_total | ||||
|           if (a < 0) { | ||||
|             return '<div style="display: inline; color: green">↓' + (a*100).toFixed(2) + '%</div>' | ||||
|           } else if (a == 0) { | ||||
|             return '' | ||||
|           } else if (a > 0) { | ||||
|             return '<div style="display: inline; color: red">↑' + (a*100).toFixed(2) + '%</div>' | ||||
|           } | ||||
|         } else { | ||||
|           return '' | ||||
|         } | ||||
|       }, | ||||
|       handleClose() { | ||||
|         this.isShowDetailDlg = false | ||||
|       }, | ||||
|       goDetail (goodsId) { | ||||
|         this.detailParams = {goodsId: goodsId} | ||||
|         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; | ||||
|   } | ||||
| </style> | ||||
							
								
								
									
										241
									
								
								src/view/selection/keywordtrack/components/List.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								src/view/selection/keywordtrack/components/List.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,241 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <ai-list class="list"> | ||||
|       <ai-title | ||||
|         slot="title" | ||||
|         title="关键字跟踪" | ||||
|         isShowBottomBorder> | ||||
|       </ai-title> | ||||
|       <template slot="content"> | ||||
|         <div class="content"> | ||||
|           <ai-search-bar> | ||||
|             <template #left> | ||||
|               <el-button type="button" :class="'el-button el-button--primary'" @click="addStore()">添加关键字</el-button> | ||||
|             </template> | ||||
|             <template #right> | ||||
|               <el-button size="small" circle icon="el-icon-refresh-right" @click="getList()"></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="options" label="操作" width="200px" show-overflow-tooltip align="center" fixed="right"> | ||||
|               <template slot-scope="{ row }"> | ||||
|                 <div class="table-options"> | ||||
|                   <el-button type="text" @click="deleteMonitor(row.id)">删除</el-button> | ||||
|                   <el-button type="text" @click="renew(row.id)">续费</el-button> | ||||
|                   <el-button type="text" @click="toDetail(row.id)">详情</el-button> | ||||
|                   <el-button type="text" @click="toBegin(row)">采集数据</el-button> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </div> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|  | ||||
|     <ai-dialog | ||||
|       title="添加店铺" | ||||
|       :visible.sync="isDlgShow" | ||||
|       :close-on-click-modal="false" | ||||
|       width="790px" | ||||
|       customFooter | ||||
|       @close="isDlgShow = false"> | ||||
|       <el-form class="ai-form" :model="form" label-width="120px" ref="form"> | ||||
|         <el-form-item | ||||
|           prop="content" | ||||
|           label="关键字" | ||||
|           :rules="[{ required: true, message: '请输入关键字', trigger: 'blur' }]"> | ||||
|           <el-input placeholder="请输入关键字" v-model="form.content"></el-input> | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|       <div class="dialog-footer" slot="footer"> | ||||
|         <el-button @click="isDlgShow = false">取 消</el-button> | ||||
|         <el-button type="primary" @click="saveStore">确定</el-button> | ||||
|       </div> | ||||
|     </ai-dialog> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import {sendTemuAPIMessage} from '@/api/chromeApi' | ||||
|  | ||||
|   export default { | ||||
|     name: 'List', | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         search: { | ||||
|           current: 1, | ||||
|           type: '0', | ||||
|           size: 10 | ||||
|         }, | ||||
|         colConfigs: [ | ||||
|           { prop: 'content', label: '关键字', align: 'left' }, | ||||
|           { prop: 'lastUpdateTime', label: '最后一次更新时间', align: 'left' }, | ||||
|           { prop: 'status', label: '状态', align: 'left', format: v => this.$dict.getLabel('monitor_status', v), }, | ||||
|           { prop: 'expireTime', label: '失效时间', align: 'left' }, | ||||
|           { prop: 'createTime', label: '添加时间', width: '180px', fixed: 'right'} | ||||
|         ], | ||||
|         tableData: [], | ||||
|         total: 0, | ||||
|  | ||||
|         form: { | ||||
|           content: '' | ||||
|         }, | ||||
|  | ||||
|         isDlgShow: false, | ||||
|         detailsVo: {}, | ||||
|         pageNo: 1, | ||||
|         pageSize: 120 | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.$dict.load('monitor_status'); | ||||
|       this.getList() | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.$http.post('/api/monitor/myPage',null,{ | ||||
|             params: { | ||||
|                 ...this.search | ||||
|             } | ||||
|         }).then(res => { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|         }) | ||||
|       }, | ||||
|       saveStore () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.$http.post('/api/monitor/check',null, {params: {type: 0}}).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$http.post(`/api/monitor/add`, {content: this.form.content, type: this.search.type}).then(res => { | ||||
|                   if (res.code == 0) { | ||||
|                     this.$message.success('添加成功!') | ||||
|                     this.$store.dispatch('getUserInfo') | ||||
|                     this.getList() | ||||
|                     this.isDlgShow = false | ||||
|                   } | ||||
|                 }) | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       renew(id) { | ||||
|         this.$confirm('确定要续费?', '温馨提示', { | ||||
|           type: 'warning' | ||||
|         }).then(() => { | ||||
|           this.$http.post('/api/monitor/renew',null, { | ||||
|             params: { | ||||
|               id: id | ||||
|             } | ||||
|           } | ||||
|           ).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('续费成功!') | ||||
|               this.$store.dispatch('getUserInfo') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|       deleteMonitor(id) { | ||||
|         this.$confirm('确定要删除?', '温馨提示', { | ||||
|           type: 'warning' | ||||
|         }).then(() => { | ||||
|           this.$http.post('/api/monitor/del',null, { | ||||
|             params: { | ||||
|               id: id | ||||
|             } | ||||
|           } | ||||
|           ).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|       toDetail (id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'Detail', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       addStore() { | ||||
|         this.form.content = '' | ||||
|         this.isDlgShow = true | ||||
|       }, | ||||
|       toBegin(row) { | ||||
|         this.detailsVo = {} | ||||
|         this.detailsVo.monitorId = row.id | ||||
|         this.detailsVo.details = [] | ||||
|         this.pageNo = 1 | ||||
|  | ||||
|         this.beginCollect(row) | ||||
|       },  | ||||
|       beginCollect(row) { | ||||
|         sendTemuAPIMessage({ | ||||
|           url: 'api/poppy/v1/search?scene=search', | ||||
|           anti: true, | ||||
|           data:  | ||||
|           { | ||||
|             "scene": "search", | ||||
|             "offset": (this.pageNo-1) * this.pageSize, | ||||
|             "pageSize": 120, | ||||
|             "query": row.content, | ||||
|             "filterItems": "0:1", | ||||
|             "searchMethod": "suggest" | ||||
|           }}).then((res) => { | ||||
|             if (res.success) { | ||||
|               res.result.data.goods_list.map(item => { | ||||
|                 console.log(item.sales_tip_text[0]) | ||||
|                 let total = 0 | ||||
|                 if (item.sales_tip_text[0]) { | ||||
|                   total = item.sales_tip_text[0] | ||||
|                   total = total.replace('+', '') | ||||
|                   if (total.indexOf('K') != -1) { | ||||
|                     total = total.replace('K', '') | ||||
|                     total = total * 1000 | ||||
|                   } else if (total.indexOf('M') != -1) { | ||||
|                     total = total.replace('M', '') | ||||
|                     total = total * 1000000 | ||||
|                   } | ||||
|                 } | ||||
|                 this.detailsVo.details.push({ | ||||
|                   url: item.link_url, | ||||
|                   price: item.price_info.price_schema, | ||||
|                   saleTotal: total, | ||||
|                   goodsId: item.goods_id, | ||||
|                   imgUrl: item.thumb_url, | ||||
|                   mallId: item.mall_id | ||||
|                 }) | ||||
|               }) | ||||
|               console.log(this.detailsVo) | ||||
|  | ||||
|               this.$http.post('/api/monitorDetail/addDetails',this.detailsVo | ||||
|               ).then(res => { | ||||
|                 if (res.code == 0) { | ||||
|                   this.$message.success('关键字【' + row.content + '】数据采集成功!') | ||||
|                   this.getList() | ||||
|                 } | ||||
|               }) | ||||
|             } | ||||
|           }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| </style> | ||||
| @@ -16,17 +16,7 @@ | ||||
|                   <div style="display: inline; margin-left: 5px;">${{ item.priceAndSale[0].price }}<sub style="margin-left: 2px;" v-html="getPricePercent(item.priceAndSale)"></sub></div> | ||||
|                   <div style="display: inline; margin-right: 5px; float: right;">{{ item.priceAndSale[0].sale_total }}<sub style="margin-left: 2px;" v-html="getSalePercent(item.priceAndSale)"></sub></div> | ||||
|                 </div> | ||||
|                 <el-dropdown @command="handleClick" style="float: right;"> | ||||
|                   <span class="el-dropdown-link"> | ||||
|                     操作<i class="el-icon-arrow-down el-icon--right"></i> | ||||
|                   </span> | ||||
|                   <el-dropdown-menu slot="dropdown"> | ||||
|                     <el-dropdown-item :command="beforeGoDetail(item.goodsId)">查看详情</el-dropdown-item> | ||||
|                     <el-dropdown-item divided command="copy">复制商品</el-dropdown-item> | ||||
|                     <el-dropdown-item divided command="copy">访问商品</el-dropdown-item> | ||||
|                     <el-dropdown-item command="copy">访问店铺</el-dropdown-item> | ||||
|                   </el-dropdown-menu> | ||||
|                 </el-dropdown> | ||||
|                 <ai-product-drop-down :params="item" :isShowDetail="true" @onGoDetail="goDetail(item.goodsId)" style="float: right;"></ai-product-drop-down> | ||||
|               </div> | ||||
|             </div> | ||||
|           </el-card> | ||||
| @@ -34,24 +24,27 @@ | ||||
|       </template> | ||||
|     </ai-list> | ||||
|  | ||||
|     <div class="productDetail"> | ||||
|       <el-dialog | ||||
|         title="商品详情" | ||||
|         :visible="isShowDetailDlg" | ||||
|         :close-on-click-modal="false" | ||||
|       width="1400" | ||||
|         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}, | ||||
|     components: {AiProductDetail, AiProductDropDown}, | ||||
|     data () { | ||||
|       return { | ||||
|         monitorId: '', | ||||
| @@ -121,26 +114,22 @@ import AiProductDetail from "@/components/AiProductDetail.vue"; | ||||
|       handleClose() { | ||||
|         this.isShowDetailDlg = false | ||||
|       }, | ||||
|       handleClick (e) { | ||||
|         if (e.type === 'detail') { | ||||
|           this.detailParams = {goodsId: e.goodsId} | ||||
|       goDetail (goodsId) { | ||||
|         this.detailParams = {goodsId: goodsId} | ||||
|         this.isShowDetailDlg = true | ||||
|         } else if (e === 'pwd') { | ||||
|           this.$router.push('changePwd') | ||||
|         } else if (e === 'message') { | ||||
|           this.$router.push('message') | ||||
|         } else if (e === 'coin') { | ||||
|           this.$router.push('coinFlow') | ||||
|         } | ||||
|       }, | ||||
|       beforeGoDetail(goodsId) { | ||||
|         return {type: 'detail', goodsId: goodsId} | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
| .productDetail { | ||||
|   :deep(.el-dialog) { | ||||
|       height: 78vh; | ||||
|       overflow: auto; | ||||
|   } | ||||
|  | ||||
| } | ||||
| .time { | ||||
|     font-size: 13px; | ||||
|     color: #999; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user