index.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <template>
  2. <div id="index">
  3. <el-row>
  4. <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
  5. <el-col :span="24" class="one">
  6. <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch"> </cSearch>
  7. </el-col>
  8. <el-col :span="24" class="two">
  9. <cButton @toAdd="toAdd()"> </cButton>
  10. </el-col>
  11. <el-col :span="24" class="thr">
  12. <cTable :fields="fields" :opera="opera" :list="list" @query="search" :total="total" @spec="toSpec"
  13. @edit="toEdit" @del="toDel"> </cTable>
  14. </el-col>
  15. </el-col>
  16. </el-row>
  17. <cDialog :dialog="dialog" @toClose="toClose">
  18. <template v-slot:info>
  19. <el-col :span="24" class="dialog_one" v-if="dialog.type == '1'">
  20. <cForm :span="24" :fields="formFields" :form="form" :rules="rules" @save="onSubmit">
  21. <template #file>
  22. <cUpload :model="`${'file'}`" :limit="6" listType="picture" url="/files/material/goods/upload" accept="*"
  23. :list="form.file" @change="onUpload"></cUpload>
  24. </template>
  25. <template #supplier_id>
  26. <el-option v-for="i in supplierList" :key="i._id" :label="i.name" :value="i._id"></el-option>
  27. </template>
  28. <template #type>
  29. <el-option v-for="i in typeList" :key="i.value" :label="i.label" :value="i.value"></el-option>
  30. </template>
  31. <template #is_use>
  32. <el-radio v-for="i in is_useList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
  33. </template>
  34. </cForm>
  35. </el-col>
  36. </template>
  37. </cDialog>
  38. </div>
  39. </template>
  40. <script lang="ts" setup>
  41. // 基础
  42. import _ from 'lodash';
  43. import type { FormRules } from 'element-plus';
  44. import type { Ref } from 'vue';
  45. import { ref, onMounted, getCurrentInstance, reactive } from 'vue';
  46. import { ElMessage } from 'element-plus';
  47. import { useRouter } from 'vue-router';
  48. // 接口
  49. import { GoodStore } from '@/stores/good/goods'; //
  50. import { UserStore } from '@/stores/users/user';
  51. import { DictDataStore } from '@/stores/dict/dictData'; // 字典表
  52. import type { IQueryResult } from '@/util/types.util';
  53. const dictAxios = DictDataStore();
  54. const userAxios = UserStore();
  55. const goodAxios = GoodStore();
  56. // 路由
  57. const router = useRouter();
  58. const { proxy } = getCurrentInstance() as any;
  59. // 加载中
  60. const loading = ref(false);
  61. // 列表数据
  62. let list: Ref<any> = ref([]);
  63. let total: Ref<number> = ref(0);
  64. let skip = 0;
  65. let limit: number = proxy.$limit;
  66. let fields: Ref<any[]> = ref([
  67. { label: '商品名称', model: 'name', isSearch: true },
  68. { label: '销售数量', model: 'sell_num' },
  69. { label: '供应商', model: 'supplier_id', format: (i: any) => getDict(i, 'supplier_id') },
  70. { label: '类型', model: 'type', format: (i: any) => getDict(i, 'type') },
  71. { label: '是否使用', model: 'is_use', format: (i: any) => getDict(i, 'is_use') }
  72. ]);
  73. // 操作
  74. let opera: Ref<any[]> = ref([
  75. { label: '商品规格', method: 'spec' },
  76. { label: '修改', method: 'edit' },
  77. { label: '删除', method: 'del', confirm: true, type: 'danger' }
  78. ]);
  79. // 弹框
  80. const dialog: Ref<{ type: string; show: boolean; title: string }> = ref({ type: '1', show: false, title: '信息管理' });
  81. let form: Ref<{ file: Array<any> }> = ref({ file: [] });
  82. // 表单
  83. let formFields: Ref<any[]> = ref([
  84. { label: '商品名称', model: 'name' },
  85. { label: '销售数量', model: 'sell_num' },
  86. { label: '供应商', model: 'supplier_id', type: 'select' },
  87. { label: '类型', model: 'type', type: 'select' },
  88. { label: '简介', model: 'brief', type: 'textarea' },
  89. { label: '图片', model: 'file', custom: true },
  90. { label: '是否使用', model: 'is_use', type: 'radio' }
  91. ]);
  92. const rules = reactive<FormRules>({
  93. name: [{ required: true, message: '商品名称', trigger: 'blur' }],
  94. supplier_id: [{ required: true, message: '供应商', trigger: 'blur' }],
  95. type: [{ required: true, message: '类型', trigger: 'blur' }]
  96. });
  97. // 查询数据
  98. let searchForm: Ref<any> = ref({});
  99. // 字典表
  100. let is_useList: Ref<any> = ref([]);
  101. let typeList: Ref<any> = ref([]);
  102. let supplierList: Ref<any> = ref([]);
  103. onMounted(async () => {
  104. loading.value = true;
  105. await searchOther();
  106. await search({ skip, limit });
  107. loading.value = false;
  108. });
  109. // 查询
  110. const search = async (e: { skip: number; limit: number }) => {
  111. const { skip, limit } = e;
  112. const condition = _.cloneDeep(searchForm.value);
  113. let info = { limit: limit, skip: skip, ...condition };
  114. let res: IQueryResult = await goodAxios.query(info);
  115. if (res.errcode == 0) {
  116. list.value = res.data;
  117. total.value = res.total;
  118. }
  119. };
  120. const toSearch = (query: any) => {
  121. searchForm.value = query;
  122. search({ skip, limit });
  123. };
  124. const getDict = (value: any, model: any) => {
  125. if (model == 'is_use') {
  126. if (value) {
  127. let data = is_useList.value.find((i: any) => i.value == value);
  128. if (data) return data.label;
  129. else return '暂无';
  130. }
  131. } else if (model == 'type') {
  132. if (value) {
  133. let data = typeList.value.find((i: any) => i.value == value);
  134. if (data) return data.label;
  135. else return '暂无';
  136. }
  137. } else {
  138. if (value) {
  139. let data = supplierList.value.find((i: any) => i._id == value);
  140. if (data) return data.name;
  141. else return '暂无';
  142. }
  143. }
  144. };
  145. // 上传图片
  146. const onUpload = (e: { model: string; value: Array<[]> }) => {
  147. const { value } = e;
  148. form.value.file = value;
  149. };
  150. // 商品规格
  151. const toSpec = (data: any) => {
  152. router.push({ path: '/spec/index', query: { id: data._id } });
  153. };
  154. // 新增
  155. const toAdd = () => {
  156. dialog.value = { title: '信息管理', show: true, type: '1' };
  157. };
  158. // 修改
  159. const toEdit = async (data: any) => {
  160. let res: IQueryResult = await goodAxios.fetch(data._id);
  161. if (res.errcode == 0) {
  162. form.value = res.data as { file: [] };
  163. dialog.value = { title: '信息管理', show: true, type: '1' };
  164. }
  165. };
  166. // 提交
  167. const onSubmit = async (data: any) => {
  168. let res: IQueryResult;
  169. if (data._id) res = await goodAxios.update(data);
  170. else res = await goodAxios.create(data);
  171. if (res.errcode == 0) {
  172. ElMessage({ type: `success`, message: `维护信息成功` });
  173. toClose();
  174. }
  175. };
  176. // 删除
  177. const toDel = async (data: any) => {
  178. let res: IQueryResult = await goodAxios.del(data._id);
  179. if (res.errcode == 0) {
  180. ElMessage({ type: `success`, message: `刪除信息成功` });
  181. search({ skip, limit });
  182. }
  183. };
  184. // 弹框关闭
  185. const toClose = () => {
  186. form.value = { file: [] };
  187. searchForm.value = {};
  188. dialog.value = { title: '信息管理', show: false, type: '1' };
  189. search({ skip, limit });
  190. };
  191. // 查询其他信息
  192. const searchOther = async () => {
  193. let res: IQueryResult;
  194. res = await dictAxios.query({ type: 'goods_type', is_use: '0' });
  195. if (res.errcode == 0) typeList.value = res.data;
  196. res = await dictAxios.query({ type: 'is_use' });
  197. if (res.errcode == 0) is_useList.value = res.data;
  198. res = await userAxios.query({ role: 'cs', is_use: '0' });
  199. if (res.errcode == 0) supplierList.value = res.data;
  200. };
  201. </script>
  202. <style lang="scss" scoped>
  203. .main {
  204. .two {
  205. margin: 0 0 10px 0;
  206. }
  207. }
  208. </style>