数字平昌
This commit is contained in:
		| @@ -0,0 +1,106 @@ | ||||
| <template> | ||||
|   <ai-list v-if="!isShowDetail"> | ||||
|     <template slot="title"> | ||||
|       <ai-title title="积分超市" :isShowBottomBorder="false"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="tabs"> | ||||
|       <el-tabs v-model="currIndex"> | ||||
|         <el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label"> | ||||
|           <component :ref="String(i)" v-if="currIndex == i" :is="tab.comp" @change="onChange" lazy :instance="instance" :dict="dict" :permissions="permissions"/> | ||||
|         </el-tab-pane> | ||||
|       </el-tabs> | ||||
|     </template> | ||||
|   </ai-list> | ||||
|   <AddGoods v-else-if="componentName === 'AddGoods'" :params="params" :instance="instance" :dict="dict" @change="onChange"></AddGoods> | ||||
|   <AddStore v-else-if="componentName === 'AddStore'" :params="params" :instance="instance" :dict="dict" @change="onChange"></AddStore> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import AddGoods from './components/addGoods' | ||||
|   import AddStore from './components/AddStore' | ||||
|   import StoreList from './components/StoreList' | ||||
|   import GoodsList from './components/GoodsList' | ||||
|   import { mapState } from 'vuex' | ||||
|  | ||||
|   export default { | ||||
|     name: 'AppIntegratingSupermarket', | ||||
|     label: '积分超市', | ||||
|  | ||||
|     components: { | ||||
|       GoodsList, | ||||
|       StoreList, | ||||
|       AddGoods, | ||||
|       AddStore | ||||
|     }, | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|       ...mapState(['user']), | ||||
|  | ||||
|       tabs () { | ||||
|         const tabList = [ | ||||
|           {label: '商品信息', name: 'GoodsList', comp: GoodsList, permission: ''}, | ||||
|           {label: '店铺管理', name: 'StoreList', comp: StoreList, permission: ''} | ||||
|         ].filter(item => { | ||||
|           return true | ||||
|         }) | ||||
|  | ||||
|         return tabList | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         activeName: 'GoodsList', | ||||
|         currIndex: '0', | ||||
|         componentName: '', | ||||
|         params: {}, | ||||
|         isShowDetail: false | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       onAreaChange () { | ||||
|         if (this.currIndex === '0') { | ||||
|           this.$nextTick(() => { | ||||
|             this.$refs[this.currIndex][0].getList() | ||||
|           }) | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       onChange (data) { | ||||
|         if (data.type === 'GoodsList') { | ||||
|           this.componentName = 'GoodsList' | ||||
|           this.isShowDetail = false | ||||
|           this.params = data.params | ||||
|         } | ||||
|         if (data.type === 'StoreList') { | ||||
|           this.componentName = 'StoreList' | ||||
|           this.isShowDetail = false | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'AddGoods') { | ||||
|           this.componentName = 'AddGoods' | ||||
|           this.isShowDetail = true | ||||
|           this.params = data.params | ||||
|         } | ||||
|  | ||||
|         if (data.type === 'AddStore') { | ||||
|           this.componentName = 'AddStore' | ||||
|           this.isShowDetail = true | ||||
|           this.params = data.params | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| </style> | ||||
| @@ -0,0 +1,507 @@ | ||||
| <template> | ||||
|   <ai-detail class="appgoods"> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="id ? '编辑店铺' : '添加店铺'" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <template #content> | ||||
|           <el-form class="ai-form" :model="form" label-width="120px" ref="form"> | ||||
|             <el-form-item style="width: 100%" label="店铺名称" prop="title" :rules="[{required: true, message: '请输入店铺名称', trigger: 'blur'}]"> | ||||
|               <el-input type="input" size="small" v-model="form.title" clearable placeholder="请输入店铺名称" :maxlength="50" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%" label="店铺类型" prop="type" :rules="[{required: true, message: '请选择店铺类型', trigger: 'change'}]"> | ||||
|               <ai-select | ||||
|                 v-model="form.type" | ||||
|                 placeholder="请选择店铺类型" | ||||
|                 :selectList="dict.getDict('integralSSType')"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="可见范围" label-width="120px"  prop="serviceType" :rules="[{required: true, message: '请选择可见范围', trigger: 'change'}]"> | ||||
|               <el-radio-group v-model="form.serviceType" @change="form.girdList = [], girdList = [], form.visibleNames = ''"> | ||||
|                 <el-radio label="0">不限</el-radio> | ||||
|                 <el-radio label="1">仅指定网格可见</el-radio> | ||||
|               </el-radio-group> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="选择网格" v-if="form.serviceType === '1'" style="width: 100%;" label-width="120px"  prop="visibleNames" :rules="[{ required: true, message: '请选择网格', trigger: 'change' }]"> | ||||
|               <ai-picker | ||||
|                 :instance="instance" | ||||
|                 multiple | ||||
|                 dialogTitle="选择网格" | ||||
|                 :ops="{label: 'girdName', id: 'girdCode'}" | ||||
|                 pageTitle="网格" | ||||
|                 :action="'/app/appgirdinfo/girdList?idType=1'" | ||||
|                 v-model="form.girdList" | ||||
|                 @pick="onPick" | ||||
|                 @change="onSelcetChange"> | ||||
|                 <div class="AppAnnounceDetail-select"> | ||||
|                   <el-input size="small" class="AppAnnounceDetail-select__input" placeholder="请选择..." disabled v-model="form.visibleNames"></el-input> | ||||
|                   <div class="select-left" v-if="form.girdList.length"> | ||||
|                     <span v-for="(item, index) in girdList" :key="index" v-if="index < 9">{{ item.girdName }}</span> | ||||
|                     <em v-if="girdList.length > 9">等{{ girdList.length }}个</em> | ||||
|                   </div> | ||||
|                   <i v-if="!form.girdList.length">请选择</i> | ||||
|                   <div class="select-right">{{ form.girdList.length ? '重新选择' : '选择' }}</div> | ||||
|                 </div> | ||||
|               </ai-picker> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <ai-card title="商品列表"> | ||||
|         <template #right> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" @click="showList">选择商品</el-button> | ||||
|         </template> | ||||
|         <template #content> | ||||
|           <ai-table | ||||
|             :tableData="form.goodsList" | ||||
|             :isShowPagination="false" | ||||
|             :col-configs="chooseColConfigs" | ||||
|             @getList="() => {}"> | ||||
|             <el-table-column | ||||
|               label="商品" | ||||
|               slot="goods" | ||||
|               align="left" | ||||
|               width="300"> | ||||
|               <template v-slot="{ row }"> | ||||
|                 <div class="goods"> | ||||
|                   <ai-uploader | ||||
|                     :disabled="true" | ||||
|                     :instance="instance" | ||||
|                     :value="[{url: row.goods.picUrl}]" | ||||
|                     :limit="1"> | ||||
|                   </ai-uploader> | ||||
|                   <p>{{ row.goods.title }}</p> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column | ||||
|               label="兑换所需积分" | ||||
|               slot="integralPrice" | ||||
|               align="center" | ||||
|               width="140"> | ||||
|               <template v-slot="{ row }"> | ||||
|                 <el-input-number style="width: 120px;" :precision="2" size="small" type="input" v-model="row.integralPrice" :min="0" placeholder="请输入"></el-input-number> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column | ||||
|               label="兑换后补差价金额" | ||||
|               slot="payMoney" | ||||
|               align="center" | ||||
|               width="150"> | ||||
|               <template v-slot="{ row }"> | ||||
|                 <el-input-number style="width: 120px;" :precision="2" size="small" type="input" v-if="row.goods.type !== '0'" :min="0" v-model="row.payMoney" clearable placeholder="请输入"></el-input-number> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column | ||||
|               label="库存" | ||||
|               slot="stock" | ||||
|               align="center" | ||||
|               width="140"> | ||||
|               <template v-slot="{ row }"> | ||||
|                 <el-input-number style="width: 120px;" :precision="0" size="small" type="input" v-model="row.stock" :min="0" clearable placeholder="请输入"></el-input-number> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|             <el-table-column label="操作" slot="options" align="center" width="180" fixed="right"> | ||||
|               <template v-slot="{ row, $index }"> | ||||
|                 <div class="table-options"> | ||||
|                   <el-button v-if="row.id" type="text" :title="row.status === '0' ? '上架' : '下架'" @click="changeStatus(row.status, $index)">{{ row.status === '0' ? '上架' : '下架' }}</el-button> | ||||
|                   <el-button type="text" title="删除" @click="remove($index)">删除</el-button> | ||||
|                   <el-button type="text" title="复制链接" v-if="row.goods.type === '1'" @click="copy(row.goods.jdUrl)">复制链接</el-button> | ||||
|                 </div> | ||||
|               </template> | ||||
|             </el-table-column> | ||||
|           </ai-table> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|       <ai-dialog | ||||
|         title="选择商品" | ||||
|         :visible.sync="isShow" | ||||
|         :destroyOnClose="true" | ||||
|         @confirm="onConfirm" | ||||
|         width="1080px"> | ||||
|         <ai-search-bar> | ||||
|           <template slot="left"> | ||||
|             <ai-select | ||||
|               v-model="search.type" | ||||
|               @change="(search.current = 1), getList()" | ||||
|               placeholder="请选择商品类型" | ||||
|               :selectList="dict.getDict('integralSGType')"> | ||||
|             </ai-select> | ||||
|             <ai-select | ||||
|               v-model="search.status" | ||||
|               @change="(search.current = 1), getList()" | ||||
|               placeholder="请选择状态" | ||||
|               :selectList="dict.getDict('integralSGStatus')"> | ||||
|             </ai-select> | ||||
|           </template> | ||||
|           <template slot="right"> | ||||
|             <el-input | ||||
|               v-model="search.title" | ||||
|               class="search-input" | ||||
|               size="small" | ||||
|               v-throttle="() => {search.current = 1, getList()}" | ||||
|               placeholder="请输入商品名称" | ||||
|               clearable | ||||
|               @clear="search.current = 1, search.title = '', getList()" | ||||
|               suffix-icon="iconfont iconSearch"> | ||||
|             </el-input> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
|         <ai-table | ||||
|           ref="aiTable" | ||||
|           style="margin-top: 8px;" | ||||
|           :tableData="tableData" | ||||
|           :col-configs="colConfigs" | ||||
|           :total="total" | ||||
|           :current.sync="search.current" | ||||
|           :size.sync="search.size" | ||||
|           @selection-change="handleSelectionChange" | ||||
|           @getList="getList"> | ||||
|           <el-table-column | ||||
|             label="商品" | ||||
|             slot="goods" | ||||
|             align="left" | ||||
|             width="300"> | ||||
|             <template v-slot="{ row }"> | ||||
|               <div class="goods"> | ||||
|                 <ai-uploader | ||||
|                   :disabled="true" | ||||
|                   :instance="instance" | ||||
|                   :value="[{url: row.picUrl}]" | ||||
|                   :limit="1"> | ||||
|                 </ai-uploader> | ||||
|                 <p>{{ row.title }}</p> | ||||
|               </div> | ||||
|             </template> | ||||
|           </el-table-column> | ||||
|         </ai-table> | ||||
|       </ai-dialog> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'AddStore', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         isShow: false, | ||||
|         form: { | ||||
|           title: '', | ||||
|           type: '', | ||||
|           serviceType: '0', | ||||
|           visibleNames: '', | ||||
|           girdList: [], | ||||
|           goodsList: [] | ||||
|         }, | ||||
|         girdList: [], | ||||
|         id: '', | ||||
|         search: { | ||||
|           type: '', | ||||
|           title: '', | ||||
|           current: 1, | ||||
|           status: '', | ||||
|           size: 10 | ||||
|         }, | ||||
|         total: 0, | ||||
|         tableData: [], | ||||
|         chooseColConfigs: [ | ||||
|           { slot: 'goods' }, | ||||
|           { prop: 'goods',  label: '商品类型', align: 'center', format: v => this.dict.getLabel('integralSGType', v.type) }, | ||||
|           { slot: 'integralPrice' }, | ||||
|           { slot: 'payMoney' }, | ||||
|           { prop: 'goods',  label: '商品链接', align: 'center', format: v => v.jdUrl }, | ||||
|           { slot: 'stock' }, | ||||
|           { prop: 'status', width: 90,  label: '状态', align: 'center', format: v => this.dict.getLabel('integralSGStatus', v) || '已上架' } | ||||
|         ], | ||||
|         colConfigs: [ | ||||
|           { type: 'selection',  label: '', align: 'left' }, | ||||
|           { prop: 'serialNumber',  label: '商品ID', align: 'center' }, | ||||
|           { slot: 'goods', align: 'center' }, | ||||
|           { prop: 'type',  label: '商品类型', align: 'center', format: v => this.dict.getLabel('integralSGType', v) }, | ||||
|           { prop: 'onlineTime',  label: '上架时间', align: 'center' }, | ||||
|           { prop: 'status', width: 90,  label: '状态', align: 'center', format: v => this.dict.getLabel('integralSGStatus', v) } | ||||
|         ], | ||||
|         chooseList: [] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.dict.load('integralSGType', 'integralSGStatus').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|  | ||||
|       if (this.params && this.params.id) { | ||||
|         this.id = this.params.id | ||||
|         this.getInfo(this.params.id) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appintegralsupermarketgoods/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       copy (url) { | ||||
|         let oInput = document.createElement('input') | ||||
|         oInput.value = url | ||||
|         document.body.appendChild(oInput) | ||||
|         oInput.select() | ||||
|         document.execCommand('Copy') | ||||
|         this.$message({ | ||||
|           message: '已复制', | ||||
|           type: 'success' | ||||
|         }) | ||||
|         oInput.remove() | ||||
|       }, | ||||
|  | ||||
|       changeStatus (status, index) { | ||||
|         this.$confirm(`确定${status === '0' ? '上架' : '下架'}该商品?`).then(() => { | ||||
|           this.$set(this.form.goodsList[index], 'status', status === '0' ? '1' : '0') | ||||
|           this.$message.success(`${status === '0' ? '上架' : '下架'}成功`) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       handleSelectionChange (e) { | ||||
|         this.chooseList = e | ||||
|       }, | ||||
|  | ||||
|       remove (index) { | ||||
|         this.$confirm('确定删除该商品吗?').then(() => { | ||||
|           this.form.goodsList.splice(index, 1) | ||||
|           this.$message.success('删除成功!') | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       showList () { | ||||
|         this.isShow = true | ||||
|  | ||||
|         // this.$nextTick(() => { | ||||
|         //   if (this.form.goodsList.length) { | ||||
|         //     this.form.goodsList.map(v => v.goods).forEach(v => { | ||||
|         //       if (this.tableData.filter(e => e.id === v.id).length) { | ||||
|         //         this.$refs.aiTable.toggleRowSelection(this.tableData.filter(e => e.id === v.id)[0], true) | ||||
|         //       } | ||||
|         //     }) | ||||
|         //   } | ||||
|         // }) | ||||
|       }, | ||||
|  | ||||
|       onConfirm () { | ||||
|         this.isShow = false | ||||
|         let list = this.chooseList.filter(v => { | ||||
|           return this.form.goodsList.map(e => e.goodsId).indexOf(v.id) === -1 | ||||
|         }).map(v => { | ||||
|           return { | ||||
|             goods: { | ||||
|               ...v | ||||
|             }, | ||||
|             goodsId: v.id, | ||||
|             integralPrice: undefined, | ||||
|             payMoney: undefined, | ||||
|             stock: undefined, | ||||
|             status: v.status | ||||
|           } | ||||
|         }) | ||||
|  | ||||
|         this.form.goodsList = [ | ||||
|           ...this.form.goodsList , | ||||
|           ...list | ||||
|         ] | ||||
|       }, | ||||
|  | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`/app/appintegralsupermarketshop/queryDetailById?id=${id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.form = { | ||||
|               ...res.data, | ||||
|               visibleNames: '1', | ||||
|               girdList: res.data.serviceType === '1' ? res.data.visibleConfig.map(v => v.visibleId) : [] | ||||
|             } | ||||
|  | ||||
|             this.girdList = res.data.visibleConfig.map(v => { | ||||
|               return { | ||||
|                 girdCode: v.visibleId, | ||||
|                 girdName: v.visibleName | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       onPick (e) { | ||||
|         this.girdList = e | ||||
|       }, | ||||
|  | ||||
|       onSelcetChange (e) { | ||||
|         if (e.length) { | ||||
|           this.form.visibleNames = '1' | ||||
|         } else { | ||||
|           this.form.visibleNames = '' | ||||
|           this.form.girdList = [] | ||||
|         } | ||||
|       }, | ||||
|  | ||||
|       confirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             if (!this.form.goodsList.length) { | ||||
|               return this.$message.error('请选择商品') | ||||
|             } | ||||
|  | ||||
|             for (let i = 0; i < this.form.goodsList.length; i++) { | ||||
|               if (!this.form.goodsList[i].integralPrice) { | ||||
|                 return this.$message.error('请输入兑换所需积分') | ||||
|               } | ||||
|               if (!this.form.goodsList[i].payMoney && this.form.goodsList[i].goods.type === '1') { | ||||
|                 return this.$message.error('请输入兑换后补差价金额') | ||||
|               } | ||||
|               if (!this.form.goodsList[i].stock) { | ||||
|                 return this.$message.error('请输入库存') | ||||
|               } | ||||
|             } | ||||
|  | ||||
|             this.instance.post(`/app/appintegralsupermarketshop/addOrUpdate`, { | ||||
|               ...this.form, | ||||
|               id: this.params.id || '', | ||||
|               visibleConfig: this.form.serviceType === '1' ? this.girdList.map(v => { | ||||
|                 return { | ||||
|                   visibleId: v.girdCode, | ||||
|                   visibleName: v.girdName | ||||
|                 } | ||||
|               }) : [] | ||||
|             }).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel(true) | ||||
|                 }, 600) | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'GoodsList', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .appgoods { | ||||
|     .goods { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       width: 250px; | ||||
|       height: 120px; | ||||
|     } | ||||
|     .AppAnnounceDetail-select { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       min-height: 32px; | ||||
|       line-height: 1; | ||||
|       background: #F5F5F5; | ||||
|       border-radius: 4px; | ||||
|       border: 1px solid #D0D4DC; | ||||
|       cursor: pointer; | ||||
|       overflow: hidden; | ||||
|       transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1); | ||||
|  | ||||
|       &:hover { | ||||
|         border-color: #26f; | ||||
|       } | ||||
|  | ||||
|       & > i { | ||||
|         flex: 1; | ||||
|         height: 100%; | ||||
|         line-height: 32px; | ||||
|         padding: 0 12px; | ||||
|         color: #888888; | ||||
|         font-size: 14px; | ||||
|         font-style: normal; | ||||
|         border-right: 1px solid #D0D4DC; | ||||
|         background: #fff; | ||||
|       } | ||||
|  | ||||
|       .AppAnnounceDetail-select__input { | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         top: 0; | ||||
|         z-index: -1; | ||||
|         opacity: 0; | ||||
|         height: 100%; | ||||
|       } | ||||
|  | ||||
|       .select-right { | ||||
|         height: 100%; | ||||
|         padding: 0 12px; | ||||
|         color: #222222; | ||||
|         font-size: 12px; | ||||
|         cursor: pointer; | ||||
|         transition: all ease 0.3s; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.5; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .select-left { | ||||
|         display: flex; | ||||
|         flex-wrap: wrap; | ||||
|         flex: 1; | ||||
|         padding: 5px 0 0px 12px; | ||||
|         border-right: 1px solid #D0D4DC; | ||||
|         border-radius: 4px 0 0 4px; | ||||
|         background: #fff; | ||||
|  | ||||
|         em { | ||||
|           height: 22px; | ||||
|           line-height: 22px; | ||||
|           margin: 0 4px 5px 0; | ||||
|           color: #222222; | ||||
|           font-size: 12px; | ||||
|           font-style: normal; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           height: 22px; | ||||
|           line-height: 22px; | ||||
|           margin: 0 4px 5px 0; | ||||
|           padding: 0 8px; | ||||
|           font-size: 12px; | ||||
|           color: #222222; | ||||
|           background: #F3F4F7; | ||||
|           border-radius: 2px; | ||||
|           border: 1px solid #D0D4DC; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -0,0 +1,214 @@ | ||||
| <template> | ||||
|   <ai-list isTabs class="GoodsList"> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar> | ||||
|         <template slot="left"> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加</el-button> | ||||
|           <ai-select | ||||
|             v-model="search.type" | ||||
|             @change="(search.current = 1), getList()" | ||||
|             placeholder="请选择商品类型" | ||||
|             :selectList="dict.getDict('integralSGType')"> | ||||
|           </ai-select> | ||||
|           <ai-select | ||||
|             v-model="search.status" | ||||
|             @change="(search.current = 1), getList()" | ||||
|             placeholder="请选择类型" | ||||
|             :selectList="dict.getDict('integralSGStatus')"> | ||||
|           </ai-select> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input | ||||
|             v-model="search.title" | ||||
|             class="search-input" | ||||
|             size="small" | ||||
|             v-throttle="() => {search.current = 1, getList()}" | ||||
|             placeholder="请输入商品名称" | ||||
|             clearable | ||||
|             @clear="search.current = 1, search.title = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         style="margin-top: 8px;" | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column | ||||
|           label="商品" | ||||
|           slot="goods" | ||||
|           align="left" | ||||
|           width="450"> | ||||
|           <template v-slot="{ row }"> | ||||
|             <div class="goods"> | ||||
|               <!-- <ai-uploader class="upload" | ||||
|                 :disabled="true" | ||||
|                 :instance="instance" | ||||
|                 :value="[{url: row.picUrl}]" | ||||
|                 :limit="1"> | ||||
|                 <span class="type" :class="`type`+row.type">{{$dict.getLabel('integralSGType', row.type)}}</span> | ||||
|               </ai-uploader> --> | ||||
|               <div class="img-content"> | ||||
|                 <img :src="row.picUrl" alt="" v-viewer> | ||||
|                 <span class="type" :class="`type`+row.type">{{$dict.getLabel('integralSGType', row.type)}}</span> | ||||
|               </div> | ||||
|                | ||||
|               <p>{{ row.title }}</p> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" slot="options" align="center" width="210" fixed="right"> | ||||
|           <template v-slot="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" title="编辑" @click="toAdd(row.id)">编辑</el-button> | ||||
|               <el-button type="text" :title="row.status === '0' ? '上架' : '下架'" @click="changeStatus(row)">{{ row.status === '0' ? '上架' : '下架' }}</el-button> | ||||
|               <el-button type="text" title="删除" @click="remove(row.id)">删除</el-button> | ||||
|               <el-button type="text" title="复制链接" v-if="row.type === '1'" @click="copy(row.jdUrl)">复制链接</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import Viewer from 'v-viewer' | ||||
|   import Vue from 'vue' | ||||
|   Vue.use(Viewer) | ||||
|   export default { | ||||
|     name: 'GoodsList', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         search: { | ||||
|           type: '', | ||||
|           title: '', | ||||
|           current: 1, | ||||
|           status: '', | ||||
|           size: 10 | ||||
|         }, | ||||
|         total: 0, | ||||
|         tableData: [], | ||||
|         colConfigs: [ | ||||
|           { prop: 'serialNumber',  label: '商品ID', align: 'left' }, | ||||
|           { slot: 'goods', align: 'center' }, | ||||
|           { prop: 'type',  label: '商品类型', align: 'center', format: v => this.dict.getLabel('integralSGType', v) }, | ||||
|           { prop: 'onlineTime',  label: '上架时间', align: 'center' }, | ||||
|           { prop: 'status',  label: '状态', align: 'center', format: v => this.dict.getLabel('integralSGStatus', v) } | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.dict.load('integralSGType', 'integralSGStatus').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appintegralsupermarketgoods/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toAdd (id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'AddGoods', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       copy (url) { | ||||
|         let oInput = document.createElement('input') | ||||
|         oInput.value = url | ||||
|         document.body.appendChild(oInput) | ||||
|         oInput.select() | ||||
|         document.execCommand('Copy') | ||||
|         this.$message({ | ||||
|           message: '已复制', | ||||
|           type: 'success' | ||||
|         }) | ||||
|         oInput.remove() | ||||
|       }, | ||||
|  | ||||
|       remove (id) { | ||||
|         this.$confirm('确定删除该商品吗?').then(() => { | ||||
|           this.instance.post(`/app/appintegralsupermarketgoods/delete?id=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       changeStatus (row) { | ||||
|         this.$confirm(`确定${row.status === '0' ? '上架' : '下架'}该商品?`).then(() => { | ||||
|           this.instance.post(`/app/appintegralsupermarketgoods/online?id=${row.id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success(`${row.status === '0' ? '上架' : '下架'}成功`) | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .GoodsList { | ||||
|     .goods { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|     } | ||||
|     .img-content { | ||||
|       position: relative; | ||||
|       margin-right: 8px; | ||||
|       img { | ||||
|         width: 120px; | ||||
|         height: 120px; | ||||
|         cursor: pointer; | ||||
|       } | ||||
|     } | ||||
|     .type { | ||||
|       position: absolute; | ||||
|       top: 0; | ||||
|       left: 0; | ||||
|       width: 120px; | ||||
|       text-align: center; | ||||
|       color: #fff; | ||||
|       z-index: 999; | ||||
|     } | ||||
|     .type1 { | ||||
|       background-color: #E64E39; | ||||
|     } | ||||
|     .type0 { | ||||
|       background-color: #FF6900; | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
| @@ -0,0 +1,159 @@ | ||||
| <template> | ||||
|   <ai-list isTabs class="order_management"> | ||||
|     <template slot="content"> | ||||
|       <ai-search-bar> | ||||
|         <template slot="left"> | ||||
|           <el-button type="primary" icon="iconfont iconAdd" @click="toAdd('')">添加</el-button> | ||||
|           <ai-select | ||||
|             v-model="search.type" | ||||
|             @change="(search.current = 1), getList()" | ||||
|             placeholder="请选择店铺类型" | ||||
|             :selectList="dict.getDict('integralSSType')"> | ||||
|           </ai-select> | ||||
|           <ai-select | ||||
|             v-model="search.status" | ||||
|             @change="(search.current = 1), getList()" | ||||
|             placeholder="请选择状态" | ||||
|             :selectList="dict.getDict('integralSSStatus')"> | ||||
|           </ai-select> | ||||
|         </template> | ||||
|         <template slot="right"> | ||||
|           <el-input | ||||
|             v-model="search.title" | ||||
|             class="search-input" | ||||
|             size="small" | ||||
|             v-throttle="() => {search.current = 1, getList()}" | ||||
|             placeholder="请输入店铺名称" | ||||
|             clearable | ||||
|             @clear="search.current = 1, search.title = '', getList()" | ||||
|             suffix-icon="iconfont iconSearch"> | ||||
|           </el-input> | ||||
|         </template> | ||||
|       </ai-search-bar> | ||||
|       <ai-table | ||||
|         style="margin-top: 8px;" | ||||
|         :tableData="tableData" | ||||
|         :col-configs="colConfigs" | ||||
|         :total="total" | ||||
|         :current.sync="search.current" | ||||
|         :size.sync="search.size" | ||||
|         @getList="getList"> | ||||
|         <el-table-column label="网格店铺服务网格" slot="grid" align="center"> | ||||
|           <template v-slot="{ row }"> | ||||
|             <span>{{ row.type === '0' ? (row.visibleNames ? row.visibleNames : row.serviceType === '0' ? '不限' : '-') : '-'  }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="居民店铺服务地区" slot="area" align="center"> | ||||
|           <template v-slot="{ row }"> | ||||
|             <span>{{ row.type === '1' ? (row.visibleNames ? row.visibleNames : row.serviceType === '0' ? '不限' : '-') : '-'  }}</span> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|         <el-table-column label="操作" slot="options" align="center" width="160" fixed="right"> | ||||
|           <template v-slot="{ row }"> | ||||
|             <div class="table-options"> | ||||
|               <el-button type="text" title="编辑" @click="toAdd(row.id)">编辑</el-button> | ||||
|               <el-button type="text" :title="row.status === '0' ? '启用' : '停用'" @click="changeStatus(row)">{{ row.status === '0' ? '启用' : '停用' }}</el-button> | ||||
|               <el-button type="text" title="删除" @click="remove(row.id)">删除</el-button> | ||||
|             </div> | ||||
|           </template> | ||||
|         </el-table-column> | ||||
|       </ai-table> | ||||
|     </template> | ||||
|   </ai-list> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'GoodsList', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
|     }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         search: { | ||||
|           type: '', | ||||
|           title: '', | ||||
|           current: 1, | ||||
|           status: '', | ||||
|           size: 10 | ||||
|         }, | ||||
|         total: 0, | ||||
|         tableData: [], | ||||
|         shopList: [], | ||||
|         colConfigs: [ | ||||
|           { prop: 'serialNumber',  label: '店铺ID', align: 'left' }, | ||||
|           { prop: 'title', label: '店铺名称', align: 'center' }, | ||||
|           { prop: 'type',  label: '店铺类型', align: 'center', format: v => this.dict.getLabel('integralSSType', v) }, | ||||
|           { slot: 'grid',  label: '网格店铺服务网格', align: 'center' }, | ||||
|           { slot: 'area',  label: '居民店铺服务地区', align: 'center' }, | ||||
|           { prop: 'goodsCount',  label: '店铺商品数', align: 'center' }, | ||||
|           { prop: 'status',  label: '状态', align: 'center', format: v => this.dict.getLabel('integralSSStatus', v) } | ||||
|         ] | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     computed: { | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       this.dict.load('integralSSType', 'integralSSStatus', 'integralSSSType').then(() => { | ||||
|         this.getList() | ||||
|       }) | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getList () { | ||||
|         this.instance.post(`/app/appintegralsupermarketshop/list`, null, { | ||||
|           params: { | ||||
|             ...this.search | ||||
|           } | ||||
|         }).then((res) => { | ||||
|           if (res.code == 0) { | ||||
|             this.tableData = res.data.records | ||||
|             this.total = res.data.total | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       toAdd (id) { | ||||
|         this.$emit('change', { | ||||
|           type: 'AddStore', | ||||
|           params: { | ||||
|             id: id || '' | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       remove (id) { | ||||
|         this.$confirm('确定删除该商品吗?').then(() => { | ||||
|           this.instance.post(`/app/appintegralsupermarketshop/delete?id=${id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success('删除成功!') | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       changeStatus (row) { | ||||
|         this.$confirm(`确定${row.status === '0' ? '启用' : '停用'}该商铺?`).then(() => { | ||||
|           this.instance.post(`/app/appintegralsupermarketshop/enable?id=${row.id}`).then(res => { | ||||
|             if (res.code == 0) { | ||||
|               this.$message.success(`${row.status === '0' ? '启用' : '停用'}成功`) | ||||
|               this.getList() | ||||
|             } | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   .order_management { | ||||
|   } | ||||
| </style> | ||||
| @@ -0,0 +1,220 @@ | ||||
| <template> | ||||
|   <ai-detail class="appgoods"> | ||||
|     <template slot="title"> | ||||
|       <ai-title :title="id ? '编辑商品' : '添加商品'" isShowBack isShowBottomBorder @onBackClick="cancel(false)"> | ||||
|       </ai-title> | ||||
|     </template> | ||||
|     <template slot="content"> | ||||
|       <ai-card title="基本信息"> | ||||
|         <template #content> | ||||
|           <el-form class="ai-form" :model="form" label-width="120px" ref="form"> | ||||
|             <el-form-item style="width: 100%" label="商品名称" prop="title" :rules="[{required: true, message: '请输入商品名称', trigger: 'blur'}]"> | ||||
|               <el-input type="input" size="small" v-model="form.title" clearable placeholder="请输入商品名称" :maxlength="50" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%" label="商品类型" prop="type" :rules="[{required: true, message: '请选择商品类型', trigger: 'change'}]"> | ||||
|               <ai-select | ||||
|                 v-model="form.type" | ||||
|                 placeholder="请选择商品类型" | ||||
|                 :selectList="dict.getDict('integralSGType')"> | ||||
|               </ai-select> | ||||
|             </el-form-item> | ||||
|             <el-form-item  style="width: 100%" label="商品类型说明" prop="typeExplain"> | ||||
|               <el-input type="input" size="small" v-model="form.typeExplain" clearable placeholder="请输入商品类型说明" maxlength="50" show-word-limit></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item style="width: 100%" label="商品图片" prop="picUrl" :rules="[{required: true, message: '请选择商品图片', trigger: 'change'}]"> | ||||
|               <ai-uploader | ||||
|                 :instance="instance" | ||||
|                 isShowTip | ||||
|                 isCrop | ||||
|                 :cropOps="{ | ||||
|                   fixedNumber: [1, 1] | ||||
|                 }" | ||||
|                 v-model="form.picUrl" | ||||
|                 :limit="1"> | ||||
|                 <template slot="tips"> | ||||
|                   <p>建议尺寸:400*400,支持上传jpg/png格式图片,最多上传一张,单个图片大小不超过10M</p> | ||||
|                 </template> | ||||
|               </ai-uploader> | ||||
|             </el-form-item> | ||||
|             <el-form-item label="零售价格" prop="retailPrice" :rules="[{required: true, message: '请输入零售价格', trigger: 'change'}]"> | ||||
|               <el-input-number style="width: 200px;" size="small" :precision="2" type="input" v-model="form.retailPrice" clearable placeholder="请输入零售价格" :min="0"></el-input-number> | ||||
|             </el-form-item> | ||||
|             <el-form-item v-if="form.type === '1'" label="商品链接" prop="jdUrl" :rules="[{required: true, message: '请输入商品链接', trigger: 'blur'}]"> | ||||
|               <el-input type="input" size="small" v-model="form.jdUrl" clearable placeholder="请输入商品链接"></el-input> | ||||
|             </el-form-item> | ||||
|             <el-form-item  style="width: 100%" label="商品描述" prop="description"> | ||||
|               <el-input type="textarea" :rows="4" size="small" v-model="form.description" clearable placeholder="请输入商品描述"></el-input> | ||||
|             </el-form-item> | ||||
|           </el-form> | ||||
|         </template> | ||||
|       </ai-card> | ||||
|     </template> | ||||
|     <template #footer> | ||||
|       <el-button @click="cancel">取消</el-button> | ||||
|       <el-button type="primary" @click="confirm">提交</el-button> | ||||
|     </template> | ||||
|   </ai-detail> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   export default { | ||||
|     name: 'Add', | ||||
|  | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       params: Object | ||||
|     }, | ||||
|  | ||||
|     data () { | ||||
|       return { | ||||
|         form: { | ||||
|           typeExplain: '', | ||||
|           title: '', | ||||
|           description: '', | ||||
|           jdUrl: '', | ||||
|           retailPrice: undefined, | ||||
|           picUrl: [] | ||||
|         }, | ||||
|         girdList: [], | ||||
|         cropOps: { | ||||
|           width: '800px', | ||||
|           height: '800px' | ||||
|         }, | ||||
|         id: '' | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     created () { | ||||
|       if (this.params && this.params.id) { | ||||
|         this.id = this.params.id | ||||
|         this.getInfo(this.params.id) | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|     methods: { | ||||
|       getInfo (id) { | ||||
|         this.instance.post(`/app/appintegralsupermarketgoods/queryDetailById?id=${id}`).then(res => { | ||||
|           if (res.code === 0) { | ||||
|             this.form = res.data | ||||
|             this.form.picUrl = [{ | ||||
|               url: res.data.picUrl | ||||
|             }] | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       confirm () { | ||||
|         this.$refs.form.validate((valid) => { | ||||
|           if (valid) { | ||||
|             this.instance.post(`/app/appintegralsupermarketgoods/addOrUpdate`, { | ||||
|               ...this.form, | ||||
|               picUrl: this.form.picUrl[0].url, | ||||
|               id: this.params.id || '' | ||||
|             }).then(res => { | ||||
|               if (res.code == 0) { | ||||
|                 this.$message.success('提交成功') | ||||
|                 setTimeout(() => { | ||||
|                   this.cancel(true) | ||||
|                 }, 600) | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|  | ||||
|       cancel (isRefresh) { | ||||
|         this.$emit('change', { | ||||
|           type: 'GoodsList', | ||||
|           isRefresh: !!isRefresh | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="scss"> | ||||
|   .appgoods { | ||||
|     .AppAnnounceDetail-select { | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       min-height: 32px; | ||||
|       line-height: 1; | ||||
|       background: #F5F5F5; | ||||
|       border-radius: 4px; | ||||
|       border: 1px solid #D0D4DC; | ||||
|       cursor: pointer; | ||||
|       overflow: hidden; | ||||
|       transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1); | ||||
|  | ||||
|       &:hover { | ||||
|         border-color: #26f; | ||||
|       } | ||||
|  | ||||
|       & > i { | ||||
|         flex: 1; | ||||
|         height: 100%; | ||||
|         line-height: 32px; | ||||
|         padding: 0 12px; | ||||
|         color: #888888; | ||||
|         font-size: 14px; | ||||
|         font-style: normal; | ||||
|         border-right: 1px solid #D0D4DC; | ||||
|         background: #fff; | ||||
|       } | ||||
|  | ||||
|       .AppAnnounceDetail-select__input { | ||||
|         position: absolute; | ||||
|         left: 0; | ||||
|         top: 0; | ||||
|         z-index: -1; | ||||
|         opacity: 0; | ||||
|         height: 100%; | ||||
|       } | ||||
|  | ||||
|       .select-right { | ||||
|         height: 100%; | ||||
|         padding: 0 12px; | ||||
|         color: #222222; | ||||
|         font-size: 12px; | ||||
|         cursor: pointer; | ||||
|         transition: all ease 0.3s; | ||||
|  | ||||
|         &:hover { | ||||
|           opacity: 0.5; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .select-left { | ||||
|         display: flex; | ||||
|         flex-wrap: wrap; | ||||
|         flex: 1; | ||||
|         padding: 5px 0 0px 12px; | ||||
|         border-right: 1px solid #D0D4DC; | ||||
|         border-radius: 4px 0 0 4px; | ||||
|         background: #fff; | ||||
|  | ||||
|         em { | ||||
|           height: 22px; | ||||
|           line-height: 22px; | ||||
|           margin: 0 4px 5px 0; | ||||
|           color: #222222; | ||||
|           font-size: 12px; | ||||
|           font-style: normal; | ||||
|         } | ||||
|  | ||||
|         span { | ||||
|           height: 22px; | ||||
|           line-height: 22px; | ||||
|           margin: 0 4px 5px 0; | ||||
|           padding: 0 8px; | ||||
|           font-size: 12px; | ||||
|           color: #222222; | ||||
|           background: #F3F4F7; | ||||
|           border-radius: 2px; | ||||
|           border: 1px solid #D0D4DC; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user