更新
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 { |   .ai-card__body { | ||||||
|     height: calc(100% - 72px); |     height: calc(100% - 72px); | ||||||
|     padding: 0 20px 0; |     padding: 0 20px 0; | ||||||
|     overflow-y: auto; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   &.panel, &.headerPanel { |   &.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"> |   <ai-detail class="audit"> | ||||||
|     <template slot="content"> |     <template slot="content"> | ||||||
|       <ai-card title="基本信息"> |       <ai-card title="基本信息"> | ||||||
|  |         <ai-product-drop-down v-if="info" :params="info" slot="right"></ai-product-drop-down> | ||||||
|         <template #content> |         <template #content> | ||||||
|           <ai-wrapper |           <div class="flex"> | ||||||
|             label-width="120px"> |             <ai-avatar v-model="info.imgUrl" :editable="false" :preview="true"/> | ||||||
|             <ai-info-item label="名称"   :value="info.name"></ai-info-item> |             <ai-wrapper | ||||||
|             <ai-info-item label="显示顺序"   :value="info.showIndex"></ai-info-item> |               label-width="120px" class="fill"> | ||||||
|             <ai-info-item label="创建时间"   :value="info.createTime" ></ai-info-item> |               <ai-info-item label="价格:"   :value="'$' + info.price"></ai-info-item> | ||||||
|           </ai-wrapper> |               <ai-info-item label="销量:"   :value="info.saleTotal"></ai-info-item> | ||||||
|  |             </ai-wrapper> | ||||||
|  |           </div> | ||||||
|         </template> |         </template> | ||||||
|       </ai-card> |       </ai-card> | ||||||
|       <ai-card title="趋势信息"> |       <ai-card title="趋势信息"> | ||||||
| @@ -20,11 +23,15 @@ | |||||||
|   </ai-detail> |   </ai-detail> | ||||||
| </template> | </template> | ||||||
| <script> | <script> | ||||||
| import { Message } from "element-ui" | import AiProductDropDown from './AiProductDropDown.vue' | ||||||
|  | import { DualAxes } from '@antv/g2plot' | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|   name: "AiProductDetail", |   name: "AiProductDetail", | ||||||
|   props: ['params'], |   props: ['params'], | ||||||
|  |   components: { | ||||||
|  |     AiProductDropDown | ||||||
|  |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|       info: {} |       info: {} | ||||||
| @@ -33,7 +40,6 @@ export default { | |||||||
|   computed: { |   computed: { | ||||||
|   }, |   }, | ||||||
|   created() { |   created() { | ||||||
|     console.log(this.params.goodsId) |  | ||||||
|     this.getInfo() |     this.getInfo() | ||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
| @@ -44,6 +50,32 @@ export default { | |||||||
|         } |         } | ||||||
|       }).then(res => { |       }).then(res => { | ||||||
|         this.info = res.data |         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', |           path: 'keywordTrack', | ||||||
|           name: '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.productName = leftData.productName; | ||||||
|   rightData.materialMultiLanguages = leftData.productLocalExtAttr.materialMultiLanguages; |   rightData.materialMultiLanguages = leftData.productLocalExtAttr.materialMultiLanguages; | ||||||
|   rightData.productI18nReqs = leftData.productI18nList; |  | ||||||
|   rightData.productPropertyReqs = []; |   rightData.productPropertyReqs = []; | ||||||
|   for (let i = 0; i < leftData.productPropertyList.length; i++) { |   for (let i = 0; i < leftData.productPropertyList.length; i++) { | ||||||
|     rightData.productPropertyReqs.push({ |     rightData.productPropertyReqs.push({ | ||||||
| @@ -121,9 +120,18 @@ export function transform(leftData) { | |||||||
|       imageUrl: leftData.outerPackageImages[i].imageUrl |       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.productOuterPackageReq = leftData.productWhExtAttr.productOuterPackage; | ||||||
|   rightData.sensitiveTransNormalFileReqs = leftData.productWhExtAttr.sensitiveTransNormalFiles; |   rightData.sensitiveTransNormalFileReqs = leftData.productWhExtAttr.sensitiveTransNormalFiles; | ||||||
|   rightData.productGuideFileI18nReqs = leftData.productGuideFileI18nList; |  | ||||||
|   rightData.productSaleExtAttrReq = {}; |   rightData.productSaleExtAttrReq = {}; | ||||||
|   rightData.productDraftId = ""; |   rightData.productDraftId = ""; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -60,44 +60,16 @@ | |||||||
|       width="790px" |       width="790px" | ||||||
|       customFooter |       customFooter | ||||||
|       @close="handleClose"> |       @close="handleClose"> | ||||||
|       <el-form class="ai-form" :model="form" label-width="140px" ref="form"> |       <ai-copy-from-temu v-if="copyFromDlgShow" @onClose="handleClose" @onSuccess="handleSuccess"></ai-copy-from-temu> | ||||||
|         <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-dialog> |     </ai-dialog> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import {sendChromeAPIMessage, sendChromeWebReqMessage} from '@/api/chromeApi' | import AiCopyFromTemu from "@/components/AiCopyFromTemu.vue"; | ||||||
| import { Message } from 'element-ui' |  | ||||||
|  |  | ||||||
|   export default { |   export default { | ||||||
|     name: 'NiubiCopy', |     name: 'NiubiCopy', | ||||||
|  |     components: {AiCopyFromTemu}, | ||||||
|  |  | ||||||
|     data () { |     data () { | ||||||
|       return { |       return { | ||||||
| @@ -107,29 +79,7 @@ import { Message } from 'element-ui' | |||||||
|           type: '', |           type: '', | ||||||
|           mallId: '' |           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: [ |         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), }, |           { 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: [], |         tableData: [], | ||||||
|         total: 0, |         total: 0, | ||||||
|  |  | ||||||
|         copyFromDlgShow: false, |         copyFromDlgShow: false, | ||||||
|         form: { |  | ||||||
|           url: '', |  | ||||||
|           type: 1,  // 默认从temu复制 |  | ||||||
|           targetMallId: '', |  | ||||||
|           targetCatId: [] |  | ||||||
|         }, |  | ||||||
|         goods: {}, |  | ||||||
|         sku: {}, |  | ||||||
|         productDetail: {} |  | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| @@ -168,188 +108,16 @@ import { Message } from 'element-ui' | |||||||
|             this.total = res.data.total |             this.total = res.data.total | ||||||
|         }) |         }) | ||||||
|       }, |       }, | ||||||
|  |       beforeCopy() { | ||||||
|       // 添加模板 |         this.copyFromDlgShow = true | ||||||
|  |       }, | ||||||
|       handleClose() { |       handleClose() { | ||||||
|         this.copyFromDlgShow = false |         this.copyFromDlgShow = false | ||||||
|       }, |       }, | ||||||
|       beforeCopy() { |       // 添加模板成功 | ||||||
|         this.form.type = 1 |       handleSuccess() { | ||||||
|         this.form.url = '' |         this.copyFromDlgShow = false | ||||||
|         this.copyFromDlgShow = true |         this.getList() | ||||||
|       }, |  | ||||||
|       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.getList() |  | ||||||
|           } |  | ||||||
|         }) |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
							
								
								
									
										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-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 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> |                 </div> | ||||||
|                 <el-dropdown @command="handleClick" style="float: right;"> |                 <ai-product-drop-down :params="item" :isShowDetail="true" @onGoDetail="goDetail(item.goodsId)" style="float: right;"></ai-product-drop-down> | ||||||
|                   <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> |  | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
|           </el-card> |           </el-card> | ||||||
| @@ -34,24 +24,27 @@ | |||||||
|       </template> |       </template> | ||||||
|     </ai-list> |     </ai-list> | ||||||
|  |  | ||||||
|     <el-dialog |     <div class="productDetail"> | ||||||
|       title="商品详情" |       <el-dialog | ||||||
|       :visible="isShowDetailDlg" |         title="商品详情" | ||||||
|       :close-on-click-modal="false" |         :visible="isShowDetailDlg" | ||||||
|       width="1400" |         :close-on-click-modal="false" | ||||||
|       :before-close="handleClose"> |         width="80%" | ||||||
|       <ai-product-detail v-if="isShowDetailDlg" :params="detailParams"/> |         :before-close="handleClose"> | ||||||
|     </el-dialog> |         <ai-product-detail v-if="isShowDetailDlg" :params="detailParams"/> | ||||||
|  |       </el-dialog> | ||||||
|  |     </div> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script> | <script> | ||||||
| import AiProductDetail from "@/components/AiProductDetail.vue"; | import AiProductDetail from "@/components/AiProductDetail.vue"; | ||||||
|  | import AiProductDropDown from '@/components/AiProductDropDown.vue'; | ||||||
|  |  | ||||||
|   export default { |   export default { | ||||||
|     name: 'DetailPage', |     name: 'DetailPage', | ||||||
|     props: ['params'], |     props: ['params'], | ||||||
|     components: {AiProductDetail}, |     components: {AiProductDetail, AiProductDropDown}, | ||||||
|     data () { |     data () { | ||||||
|       return { |       return { | ||||||
|         monitorId: '', |         monitorId: '', | ||||||
| @@ -121,26 +114,22 @@ import AiProductDetail from "@/components/AiProductDetail.vue"; | |||||||
|       handleClose() { |       handleClose() { | ||||||
|         this.isShowDetailDlg = false |         this.isShowDetailDlg = false | ||||||
|       }, |       }, | ||||||
|       handleClick (e) { |       goDetail (goodsId) { | ||||||
|         if (e.type === 'detail') { |         this.detailParams = {goodsId: goodsId} | ||||||
|           this.detailParams = {goodsId: e.goodsId} |         this.isShowDetailDlg = true | ||||||
|           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> | </script> | ||||||
|  |  | ||||||
| <style scoped lang="scss"> | <style scoped lang="scss"> | ||||||
|  | .productDetail { | ||||||
|  |   :deep(.el-dialog) { | ||||||
|  |       height: 78vh; | ||||||
|  |       overflow: auto; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| .time { | .time { | ||||||
|     font-size: 13px; |     font-size: 13px; | ||||||
|     color: #999; |     color: #999; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user