index.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <template>
  2. <div id="goods">
  3. <template v-if="view === 'list'">
  4. <data-search :fields="searchFields" v-model="searchInfo" @query="search">
  5. <template #status>
  6. <el-option v-for="i in goodsStatusList" :key="i.value" :label="i.label" :value="i.value"></el-option>
  7. </template>
  8. </data-search>
  9. <data-btn :fields="btnList" @add="toAdd"></data-btn>
  10. <data-table
  11. ref="dataTable"
  12. :fields="fields"
  13. :opera="opera"
  14. :data="list"
  15. :total="total"
  16. :limit="limit"
  17. @query="search"
  18. @edit="toEdit"
  19. @puton="toPuton"
  20. @lower="toLower"
  21. @delete="toDelete"
  22. @spec="toSpec"
  23. ></data-table>
  24. </template>
  25. <template v-else>
  26. <el-row>
  27. <el-col :span="24">
  28. <el-button icon="el-icon-back" size="mini" @click="toBack()">返回</el-button>
  29. </el-col>
  30. <el-col :span="24">
  31. <data-form :fields="infoFields" :rules="rules" v-model="form" labelWidth="150px" @save="toSave">
  32. <template #tags="{ item }">
  33. <el-cascader v-model="form[item.model]" :options="tagsList" :props="props" clearable filterable :show-all-levels="false"></el-cascader>
  34. </template>
  35. <template #act_tags>
  36. <el-option v-for="i in act_tagsList" :key="i.value" :label="i.label" :value="i.value"></el-option>
  37. </template>
  38. <template #status>
  39. <el-option v-for="i in goodsStatusList" :key="i.value" :label="i.label" :value="i.value"></el-option>
  40. </template>
  41. <template #brief>
  42. <editor v-model="form.brief" url="/files/point/goods/upload" />
  43. </template>
  44. </data-form>
  45. </el-col>
  46. </el-row>
  47. </template>
  48. </div>
  49. </template>
  50. <script>
  51. const _ = require('lodash');
  52. import methodsUtil from '@/util/opera';
  53. import { mapState, createNamespacedHelpers } from 'vuex';
  54. const { mapActions: selfShop } = createNamespacedHelpers('selfShop');
  55. const { mapActions: goods } = createNamespacedHelpers('goods');
  56. const { mapActions: goodsTags } = createNamespacedHelpers('goodsTags');
  57. const { mapActions: dictData } = createNamespacedHelpers('dictData');
  58. export default {
  59. name: 'index',
  60. props: {},
  61. components: { editor: () => import('@/components/editor.vue') },
  62. data: function () {
  63. return {
  64. view: 'list',
  65. fields: [
  66. { label: '商品名称', model: 'name' },
  67. { label: '店铺名称', model: 'shop.name' },
  68. { label: '商品分类', model: 'tags', format: (i) => this.getTags(i) },
  69. { label: '活动标签', model: 'act_tags', format: (i) => this.getAct_tags(i) },
  70. { label: '商品状态', model: 'status', format: (i) => this.getStatus(i) },
  71. ],
  72. opera: [
  73. { label: '修改', method: 'edit' },
  74. { label: '上架', method: 'puton' },
  75. { label: '下架', method: 'lower' },
  76. { label: '库存管理', method: 'spec' },
  77. { label: '删除', method: 'delete', confirm: true, type: 'danger' },
  78. ],
  79. btnList: [{ label: '添加', method: 'add' }],
  80. searchFields: [
  81. { label: '商品名称', model: 'name' },
  82. { label: '商品状态', model: 'status', type: 'select' },
  83. ],
  84. searchInfo: {},
  85. list: [],
  86. total: 0,
  87. limit: 10,
  88. // info部分
  89. infoFields: [
  90. { label: '商品名称', model: 'name' },
  91. { label: '商品分类', model: 'tags', custom: true },
  92. { label: '活动标签', model: 'act_tags', type: 'selectMany' },
  93. { label: '简短简介', model: 'shot_brief', maxLength: 50 },
  94. { label: '预计发货时间', model: 'send_time' },
  95. { label: '商品状态', model: 'status', type: 'select' },
  96. { label: '商品来源', model: 'source' },
  97. { label: '网址', model: 'url' },
  98. { label: '排序', model: 'sort', type: 'number' },
  99. { label: '商品图片', model: 'file', type: 'upload', url: '/files/point/goods/upload' },
  100. { label: '商品介绍', model: 'brief', custom: true },
  101. ],
  102. rules: {},
  103. form: {},
  104. // 商品分类
  105. tagsList: [],
  106. props: { multiple: true, label: 'label', value: 'code' },
  107. // 活动标签
  108. act_tagsList: [],
  109. goodsStatusList: [],
  110. shop: {},
  111. };
  112. },
  113. created() {
  114. this.searchOthers();
  115. this.search();
  116. },
  117. methods: {
  118. ...dictData({ getDict: 'query' }),
  119. ...goodsTags(['tree']),
  120. ...selfShop(['getInfo', 'getGoods', 'goodsCreate']),
  121. ...goods(['delete', 'fetch', 'update', 'create']),
  122. ...methodsUtil,
  123. async search({ skip = 0, limit = this.limit, ...others } = {}) {
  124. let query = { skip, limit, ...others };
  125. if (Object.keys(this.searchInfo).length > 0) query = { ...query, ...this.searchInfo };
  126. const res = await this.getGoods(query);
  127. if (this.$checkRes(res)) {
  128. this.$set(this, `list`, res.data);
  129. this.$set(this, `total`, res.total);
  130. }
  131. },
  132. initAddData() {
  133. const obj = {
  134. status: '1',
  135. shop: _.get(this.shop, '_id'),
  136. };
  137. this.$set(this, 'form', obj);
  138. },
  139. async searchOthers() {
  140. let res = await this.tree();
  141. if (this.$checkRes(res)) this.$set(this, `tagsList`, res.data);
  142. res = await this.getDict({ code: 'goods_status' });
  143. if (this.$checkRes(res)) this.$set(this, `goodsStatusList`, res.data);
  144. res = await this.getInfo();
  145. if (this.$checkRes(res)) this.$set(this, `shop`, res.data);
  146. res = await this.getDict({ code: 'act_tags' });
  147. if (this.$checkRes(res)) this.$set(this, `act_tagsList`, res.data);
  148. },
  149. getStatus(data) {
  150. const res = this.goodsStatusList.find((f) => f.value === data);
  151. if (res) return res.label;
  152. return '';
  153. },
  154. getAct_tags(data) {
  155. const arr = [];
  156. for (const val of data) {
  157. const r = this.act_tagsList.find((f) => f.value === val);
  158. if (r) arr.push(r.label);
  159. }
  160. return arr.join(';');
  161. },
  162. getTags(data) {
  163. let list = this.tagsList;
  164. const getChildren = (list) =>
  165. list.map((i) => {
  166. if (i.children) return getChildren(i.children);
  167. return i;
  168. });
  169. list = _.flattenDeep(getChildren(list));
  170. const arr = [];
  171. for (const ts of data) {
  172. const last = _.last(ts);
  173. const r = list.find((f) => f.code === last);
  174. if (r) arr.push(r.label);
  175. }
  176. return arr.join(';');
  177. },
  178. // 上架
  179. async toPuton({ data }) {
  180. this.$confirm('是否确认上架该商品?', '提示', {
  181. confirmButtonText: '确定',
  182. cancelButtonText: '取消',
  183. type: 'warning',
  184. }).then(async () => {
  185. data.status = '1';
  186. let res;
  187. if (data.id) res = await this.update(data);
  188. if (this.$checkRes(res)) {
  189. this.$message({ type: `success`, message: `上架成功` });
  190. }
  191. this.search();
  192. });
  193. },
  194. // 下架
  195. async toLower({ data }) {
  196. this.$confirm('是否确认下架该商品?', '提示', {
  197. confirmButtonText: '确定',
  198. cancelButtonText: '取消',
  199. type: 'warning',
  200. }).then(async () => {
  201. data.status = '0';
  202. let res;
  203. if (data._id) res = await this.update(data);
  204. if (this.$checkRes(res)) {
  205. console.log(res.data);
  206. this.$message({ type: `success`, message: `下架成功` });
  207. }
  208. this.search();
  209. });
  210. },
  211. toSpec({ data }) {
  212. this.$router.push({ path: `/selfShop/spec/${data._id}` });
  213. },
  214. },
  215. };
  216. </script>
  217. <style lang="less" scoped></style>