123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- <template>
- <div id="goods">
- <span v-show="view === 'list'">
- <el-row>
- <el-col
- :span="24"
- class="main animate__animated animate__backInRight"
- v-loading="loadings"
- element-loading-text="拼命加载中"
- element-loading-spinner="el-icon-loading"
- >
- <el-col :span="24" class="one"> <span>商品管理</span> </el-col>
- <data-search :fields="searchFields" v-model="searchInfo" @query="toSearch">
- <template #status>
- <el-option v-for="i in goodsStatusList" :key="i.value" :label="i.label" :value="i.value"></el-option>
- </template>
- <template #tags="{ item }">
- <el-cascader
- v-model="searchInfo[item.model]"
- :options="tagsList"
- :props="propss"
- clearable
- filterable
- :show-all-levels="false"
- @change="changeTags"
- ></el-cascader>
- </template>
- </data-search>
- <data-btn :fields="btnList" @add="toAdd"></data-btn>
- <data-table
- ref="dataTable"
- :fields="fields"
- :opera="opera"
- :data="list"
- :total="total"
- @query="search"
- @edit="toEdit"
- @puton="toPuton"
- @delete="toDelete"
- @spec="toSpec"
- @copy="toCopy"
- >
- <template #source="{ row }">
- <span style="color: blue; cursor: pointer" @click="toUrl(row.url)">
- {{ row.source }}
- </span>
- </template>
- </data-table>
- </el-col>
- </el-row>
- </span>
- <el-row v-if="view === 'info'">
- <el-col :span="24" style="margin: 0 0 10px 0">
- <el-col :span="2">
- <el-button type="primary" size="mini" @click="toBack()">返回</el-button>
- </el-col>
- <el-col :span="2">
- <el-button type="primary" size="mini" @click="toSave(form)">保存</el-button>
- </el-col>
- </el-col>
- <el-col :span="24">
- <data-form :fields="infoFields" :rules="rules" v-model="form" labelWidth="150px" @save="toSave">
- <template #tags="{ item }">
- <el-cascader v-model="form[item.model]" :options="tagsList" :props="props" clearable filterable :show-all-levels="false"></el-cascader>
- </template>
- <template #act_tags>
- <el-option v-for="i in act_tagsList" :key="i.value" :label="i.label" :value="i.value">
- {{ i.label }}{{ i.show_goods === '0' ? '(商品脚标)' : '' }}
- </el-option>
- </template>
- <template #status>
- <el-option v-for="i in goodsStatusList" :key="i.value" :label="i.label" :value="i.value"></el-option>
- </template>
- <template #is_cashBack>
- <el-option v-for="i in statusList" :key="i.value" :label="i.label" :value="i.value"></el-option>
- </template>
- <template #cb_config>
- <el-form :model="cb_config" ref="cb_config" label-width="180px" @save="toSave" v-if="form.is_cashBack == '0'">
- <el-col :span="24">
- <el-form-item label="返现金额类型" prop="back_type">
- <el-select v-model="cb_config.back_type" clearable filterable placeholder="请选择返现金额类型" size="small" style="width: 100%">
- <el-option v-for="i in typeList" :key="i.value" :label="i.label" :value="i.value"> </el-option>
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="24" v-if="cb_config.back_type == 'fixed'">
- <el-form-item label="具体返现金额设置" prop="money">
- <el-input v-model="cb_config.money" placeholder="请输入金额" type="number" size="small"></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="24" v-if="cb_config.back_type == 'percent'">
- <el-form-item label="具体返现金额设置" prop="money">
- <el-input v-model="cb_config.money" placeholder="请输入百分比" type="number" size="small"></el-input>
- </el-form-item>
- </el-col>
- </el-form>
- </template>
- <template #brief>
- <editor v-model="form.brief" url="/files/point/goods/upload" />
- </template>
- </data-form>
- </el-col>
- </el-row>
- </div>
- </template>
- <script>
- const _ = require('lodash');
- import methodsUtil from '@/util/opera';
- import { mapState, createNamespacedHelpers } from 'vuex';
- const { mapActions: goods } = createNamespacedHelpers('goods');
- const { mapActions: goodsSpec } = createNamespacedHelpers('goodsSpec');
- const { mapActions: goodsTags } = createNamespacedHelpers('goodsTags');
- const { mapActions: dictData } = createNamespacedHelpers('dictData');
- const { mapActions: actTags } = createNamespacedHelpers('actTags');
- export default {
- name: 'index',
- props: {},
- components: {
- editor: () => import('@/components/editor.vue'),
- },
- data: function () {
- return {
- loadings: true,
- view: 'list',
- fields: [
- { label: '商品名称', model: 'name', showTip: false },
- // { label: '店铺名称', model: 'shop.name' },
- { label: '商品分类', model: 'tags', format: (i) => this.getTags(i) },
- { label: '活动标签', model: 'act_tags', format: (i) => this.getAct_tags(i) },
- { label: '商品状态', model: 'status', format: (i) => this.getStatus(i) },
- { label: '供应商', model: 'source', custom: true },
- { label: '排序', model: 'sort' },
- ],
- opera: [
- { label: '修改', method: 'edit' },
- { label: '上架', method: 'puton', display: (i) => i.status == '0', type: 'success' },
- { label: '下架', method: 'puton', display: (i) => i.status == '1', type: 'warning' },
- { label: '库存管理', method: 'spec' },
- { label: '复制', method: 'copy' },
- { label: '删除', method: 'delete', confirm: true, type: 'danger' },
- ],
- btnList: [{ label: '添加', method: 'add' }],
- searchFields: [
- { label: '商品名称', model: 'name' },
- { label: '规格名称', model: 'spec_name' },
- { label: '商品状态', model: 'status', type: 'select' },
- { label: '商品分类', model: 'tags', custom: true },
- { label: '供应商', model: 'source' },
- ],
- searchInfo: {},
- list: [],
- total: 0,
- // info部分
- infoFields: [
- { label: '商品名称', model: 'name' },
- { label: '商品分类', model: 'tags', custom: true },
- { label: '活动标签', model: 'act_tags', type: 'selectMany' },
- { label: '简短简介', model: 'shot_brief', maxLength: 50 },
- { label: '预计发货时间', model: 'send_time' },
- // { label: '商品状态', model: 'status', type: 'select' },
- { label: '商品来源', model: 'source' },
- { label: '网址', model: 'url' },
- { label: '排序', model: 'sort', type: 'number' },
- { label: '是否返现', model: 'is_cashBack', type: 'select' },
- { label: '返现设置', model: 'cb_config', custom: true },
- { label: '商品图片', model: 'file', type: 'upload', url: '/files/point/goods/upload' },
- { label: '商品介绍', model: 'brief', custom: true },
- ],
- rules: {},
- form: {},
- // 返现设置
- cb_config: {},
- // 商品分类
- tagsList: [],
- props: { multiple: true, label: 'label', value: 'code' },
- propss: { multiple: false, label: 'label', value: 'code' },
- // 活动标签
- act_tagsList: [],
- goodsStatusList: [],
- // 是否返现
- statusList: [],
- // 返现金额类型
- typeList: [{ label: '固定金额' }, { label: '百分比' }],
- // 查询条件
- searchQuery: {},
- };
- },
- created() {
- this.searchOthers();
- let route = JSON.parse(sessionStorage.getItem(this.$route.path));
- if (route) {
- this.search(route);
- this.$nextTick(() => {
- this.$refs.dataTable.setPage(route);
- });
- } else this.search();
- },
- methods: {
- ...dictData({ getDict: 'query' }),
- ...actTags({ actQuery: 'query' }),
- ...goodsTags(['tree']),
- ...goods(['copy', 'query', 'delete', 'fetch', 'update', 'create']),
- ...goodsSpec({ specQuery: 'query' }),
- ...methodsUtil,
- toSearch() {
- this.$refs.dataTable.resetPage();
- let res = this.$refs.dataTable.getPageConfig();
- this.search(res);
- },
- // 查询
- async search({ skip = 0, limit = this.$limit, ...others } = {}) {
- let query = { skip, limit, ...others, shop: this.user.shop.id };
- if (Object.keys(this.searchInfo).length > 0) query = { ...query, ...this.searchInfo };
- const res = await this.query(query);
- if (this.$checkRes(res)) {
- this.$set(this, `list`, res.data);
- this.$set(this, `total`, res.total);
- this.$set(this, `searchQuery`, query);
- sessionStorage.removeItem(this.$route.path);
- }
- this.loadings = false;
- },
- toUrl(url) {
- if (url) window.open(url, '_blank');
- else this.$message.error('该商品还未添加来源网址,无法跳转');
- },
- // 去编辑
- async toEdit({ data }) {
- const res = await this.fetch(data._id);
- if (this.$checkRes(res)) {
- this.$set(this, `form`, res.data);
- if (res.data.cb_config) this.cb_config = res.data.cb_config;
- this.view = 'info';
- } else this.$message.error('未找到指定数据');
- },
- // 添加自定义
- initAddData() {
- const obj = { status: '1', shop: _.get(this.user.shop, '_id') };
- this.$set(this, 'form', obj);
- },
- // 商品分类查询
- changeTags(value) {
- let tags = _.last(value);
- this.$set(this.searchInfo, `tags`, tags);
- },
- // 复制
- async toCopy({ data }) {
- this.$confirm('是否确认复制该商品?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning',
- }).then(async () => {
- let res;
- res = await this.copy(data._id);
- if (this.$checkRes(res)) {
- this.$message({ type: `success`, message: `复制成功` });
- this.toBack();
- }
- });
- },
- // 保存
- async toSave({ data }) {
- let res;
- if (data == '' || data == undefined) {
- let form = this.form;
- form.cb_config = this.cb_config;
- form.cb_config.money = Number(form.cb_config.money);
- if (form.id) res = await this.update(form);
- else res = await this.create(form);
- } else {
- data.cb_config = this.cb_config;
- data.cb_config.money = Number(data.cb_config.money);
- if (data.id) res = await this.update(data);
- else res = await this.create(data);
- }
- if (this.$checkRes(res)) {
- this.$message({ type: `success`, message: `维护信息成功` });
- this.toBack();
- }
- },
- // 执行返回
- toBack() {
- this.form = {};
- this.view = 'list';
- this.search(this.searchQuery);
- },
- // 上架
- async toPuton({ data }) {
- const res = await this.specQuery({ goods: data._id });
- if (this.$checkRes(res)) {
- if (res.total > 0) {
- this.$confirm('是否确认上架/下架该商品?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning',
- }).then(async () => {
- if (data.status == '1') data.status = '0';
- else data.status = '1';
- let res;
- if (data._id) res = await this.update(data);
- if (this.$checkRes(res)) this.$message({ type: `success`, message: `修改成功` });
- this.search(this.searchQuery);
- });
- } else {
- this.$message({ type: `warning`, message: `该商品没有规格,不允许上架` });
- }
- }
- },
- // 库存管理
- toSpec({ data }) {
- sessionStorage.setItem(this.$route.path, JSON.stringify(this.searchQuery));
- this.$router.push({ path: `/selfShop/spec/${data._id}` });
- },
- // 查询其他信息
- async searchOthers() {
- // 商品分类
- let res = await this.tree();
- if (this.$checkRes(res)) this.$set(this, `tagsList`, res.data);
- // 商品状态
- res = await this.getDict({ code: 'goods_status' });
- if (this.$checkRes(res)) this.$set(this, `goodsStatusList`, res.data);
- // 活动标签
- res = await this.actQuery();
- if (this.$checkRes(res)) this.$set(this, `act_tagsList`, res.data);
- // 是否返现
- res = await this.getDict({ code: 'use' });
- if (this.$checkRes(res)) this.$set(this, `statusList`, res.data);
- // 返现金额类型
- res = await this.getDict({ code: 'cashBack_type' });
- if (this.$checkRes(res)) this.$set(this, `typeList`, res.data);
- },
- // 商品状态
- getStatus(data) {
- const res = this.goodsStatusList.find((f) => f.value === data);
- if (res) return res.label;
- return '';
- },
- // 活动标签
- getAct_tags(data) {
- const arr = [];
- for (const val of data) {
- const r = this.act_tagsList.find((f) => f.value === val);
- if (r) arr.push(r.label);
- }
- return arr.join(';');
- },
- // 商品分类
- getTags(data) {
- let list = this.tagsList;
- const getChildren = (list) =>
- list.map((i) => {
- if (i.children) return getChildren(i.children);
- return i;
- });
- list = _.flattenDeep(getChildren(list));
- const arr = [];
- for (const ts of data) {
- const last = _.last(ts);
- const r = list.find((f) => f.code === last);
- if (r) arr.push(r.label);
- }
- return arr.join(';');
- },
- },
- computed: {
- ...mapState(['user']),
- },
- };
- </script>
- <style lang="less" scoped>
- .main {
- .one {
- margin: 0 0 10px 0;
- span:nth-child(1) {
- font-size: 20px;
- font-weight: 700;
- margin-right: 10px;
- }
- }
- }
- .el-col {
- margin: 10px 0;
- }
- </style>
|