index.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <template>
  2. <el-row>
  3. <el-col :span="24" class="main animate__animated animate__backInRight" v-loading="loading">
  4. <el-col :span="24" class="one">
  5. <cSearch :is_title="false" :is_search="true" :fields="fields" @search="toSearch">
  6. <template #type>
  7. <el-option v-for="i in serviceTypeList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  8. </template>
  9. <template #way>
  10. <el-option v-for="i in wayList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  11. </template>
  12. </cSearch>
  13. </el-col>
  14. <el-col :span="24" class="two">
  15. <cButton @toAdd="toAdd"> </cButton>
  16. </el-col>
  17. <el-col :span="24" class="thr">
  18. <cTable :fields="fields" :opera="opera" :list="list" @query="search" :total="total" @edit="toEdit" @del="toDel" @changeUse="toChangeUse"> </cTable>
  19. </el-col>
  20. </el-col>
  21. </el-row>
  22. <cDialog :dialog="dialog" @toClose="toClose">
  23. <el-col :span="24" class="dialog_one" v-if="dialog.type == '1'">
  24. <cForm :span="24" :fields="formFields" :form="form" :rules="{}" @save="toSave" label-width="auto">
  25. <template #status>
  26. <el-radio v-for="i in statusList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
  27. </template>
  28. <template #type>
  29. <el-option v-for="i in serviceTypeList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  30. </template>
  31. <template #way>
  32. <el-option v-for="i in wayList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  33. </template>
  34. <template #area>
  35. <el-option v-for="i in areaList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  36. </template>
  37. <template #tags>
  38. <el-row>
  39. <el-col :span="24">
  40. <el-button size="small" @click="addTags" type="primary">添加标签</el-button>
  41. </el-col>
  42. <el-col :span="24">
  43. <el-table border stripe :data="form.tags" height="20vh">
  44. <el-table-column align="center" label="标签文案">
  45. <template v-slot="{ row }">
  46. <el-input v-model="row.label" />
  47. </template>
  48. </el-table-column>
  49. <el-table-column align="center" label="标签级别">
  50. <template v-slot="{ row }">
  51. <el-select v-model="row.type">
  52. <el-option label="低" value="primary">
  53. <el-link type="primary">低</el-link>
  54. </el-option>
  55. <el-option label="中" value="warning">
  56. <el-link type="warning">中</el-link>
  57. </el-option>
  58. <el-option label="高" value="danger">
  59. <el-link type="danger">高</el-link>
  60. </el-option>
  61. </el-select>
  62. </template>
  63. </el-table-column>
  64. <el-table-column align="center" label="删除">
  65. <template v-slot="{ $index }">
  66. <el-link type="danger" @click="toDelTag($index)">删除</el-link>
  67. </template>
  68. </el-table-column>
  69. </el-table>
  70. </el-col>
  71. </el-row>
  72. </template>
  73. </cForm>
  74. </el-col>
  75. </cDialog>
  76. </template>
  77. <script setup lang="ts">
  78. import { ref, Ref, onMounted, inject } from 'vue';
  79. // NeedChange
  80. import { ServiceStore } from '@/stores/core/service';
  81. import { DictDataStore } from '@/stores/system/dictData';
  82. import type { IQueryResult } from '@/util/types.util';
  83. import { cloneDeep, get, isArray, isString } from 'lodash';
  84. import baseStore from '@/stores/counter';
  85. const user = ref(baseStore.state.user);
  86. onMounted(async () => {
  87. loading.value = true;
  88. await searchOther();
  89. await search({ skip, limit });
  90. loading.value = false;
  91. });
  92. const loading: Ref<any> = ref(false);
  93. // NeedChange
  94. const store = ServiceStore();
  95. const dictDataStore = DictDataStore();
  96. const $checkRes = inject('$checkRes') as Function;
  97. // #region 字典
  98. // NeedChange
  99. const statusList: Ref<any> = ref([]);
  100. const serviceTypeList: Ref<any> = ref([]);
  101. const wayList: Ref<any> = ref([]);
  102. const areaList: Ref<any> = ref([]);
  103. const searchOther = async () => {
  104. const statusResult: IQueryResult = await dictDataStore.query({ code: 'serviceStatus' });
  105. if ($checkRes(statusResult)) {
  106. statusList.value = statusResult.data;
  107. }
  108. const serviceTypeResult: IQueryResult = await dictDataStore.query({ code: 'serviceType' });
  109. if ($checkRes(serviceTypeResult)) {
  110. serviceTypeList.value = serviceTypeResult.data;
  111. }
  112. const serviceWayResult: IQueryResult = await dictDataStore.query({ code: 'serviceWay' });
  113. if ($checkRes(serviceWayResult)) {
  114. wayList.value = serviceWayResult.data;
  115. }
  116. const areaResult: IQueryResult = await dictDataStore.query({ code: 'serviceArea' });
  117. if ($checkRes(areaResult)) {
  118. areaList.value = areaResult.data;
  119. }
  120. };
  121. // #endregion
  122. // #region 查询相关
  123. let list: Ref<any> = ref([]);
  124. let total: Ref<number> = ref(0);
  125. let skip = 0;
  126. let limit = inject('$limit') as number;
  127. let searchForm: Ref<any> = ref({});
  128. const search = async (e: { skip: number; limit: number }) => {
  129. const info = { skip: e.skip, limit: e.limit, ...searchForm.value, owner: user.value._id };
  130. const res: IQueryResult = await store.query(info);
  131. if (res.errcode == '0') {
  132. list.value = res.data;
  133. total.value = res.total;
  134. }
  135. };
  136. const toSearch = (query) => {
  137. searchForm.value = query;
  138. search({ skip, limit });
  139. };
  140. const toChangeUse = async (data) => {
  141. let status = '0';
  142. switch (data.status) {
  143. case '0':
  144. status = '1';
  145. break;
  146. case '1':
  147. status = '0';
  148. break;
  149. default:
  150. break;
  151. }
  152. const udata = { _id: data._id, status };
  153. const res = await store.update(udata);
  154. if ($checkRes(res, true)) {
  155. search({ skip: 0, limit });
  156. }
  157. };
  158. // #endregion
  159. // #region 表格及操作
  160. // NeedChange
  161. let fields: Ref<any[]> = ref([
  162. { label: '服务标题', model: 'title', isSearch: true },
  163. { label: '服务类型', model: 'type', isSearch: true, type: 'selectMult', format: (i) => getDict(i, 'type') },
  164. { label: '服务方式', model: 'way', isSearch: true, type: 'selectMult', format: (i) => getDict(i, 'way') },
  165. { label: '服务地区', model: 'area', format: (i) => getDict(i, 'area') },
  166. { label: '价格', model: 'money' },
  167. { label: '服务状态', model: 'status', format: (i) => getDict(i, 'status') }
  168. ]);
  169. // 操作
  170. let opera: Ref<any[]> = ref([
  171. { label: '修改', method: 'edit' },
  172. { label: '禁用', method: 'changeUse', type: 'warning', confirm: true, confirmWord: '您确定禁用该服务?', display: (i) => i.status === '0' },
  173. { label: '启用', method: 'changeUse', type: 'success', confirm: true, confirmWord: '您确定启用该服务?', display: (i) => i.status === '1' },
  174. { label: '删除', method: 'del', confirm: true, type: 'danger' }
  175. ]);
  176. const getDict = (data, model) => {
  177. let list;
  178. switch (model) {
  179. case 'status':
  180. list = statusList.value;
  181. break;
  182. case 'type':
  183. list = serviceTypeList.value;
  184. break;
  185. case 'way':
  186. list = wayList.value;
  187. break;
  188. case 'area':
  189. list = areaList.value;
  190. break;
  191. default:
  192. break;
  193. }
  194. if (!list) return;
  195. if (isString(data)) {
  196. const res = list.find((f) => f.value == data);
  197. return get(res, 'label');
  198. } else if (isArray(data)) {
  199. const arr = [];
  200. for (const i of data) {
  201. const res = list.find((f) => f.value == data);
  202. if (res) arr.push(get(res, 'label'));
  203. }
  204. }
  205. };
  206. const toAdd = () => {
  207. formFields.value = formFieldsForCreate;
  208. // 所属人是自己,需要把自己的id放进去
  209. form.value = { ...cloneDeep(defaultForm), owner: user.value._id };
  210. dialog.value.show = true;
  211. };
  212. const toEdit = (data) => {
  213. formFields.value = formFieldsForUpdate;
  214. form.value = { ...data };
  215. dialog.value.show = true;
  216. };
  217. // #endregion
  218. // #region 常规接口
  219. const toSave = async () => {
  220. const data = cloneDeep(form.value);
  221. let res: IQueryResult;
  222. if (get(data, '_id')) res = await store.update(data);
  223. else res = await store.create(data);
  224. if ($checkRes(res, true)) {
  225. search({ skip: 0, limit });
  226. toClose();
  227. }
  228. };
  229. const toDel = async (data) => {
  230. const res = await store.del(data._id);
  231. if ($checkRes(res, true)) {
  232. search({ skip: 0, limit });
  233. }
  234. };
  235. // #endregion
  236. // #region 表单及操作
  237. // NeedChange
  238. const defaultForm = { status: '0', tags: [] };
  239. const formFields: Ref<any> = ref();
  240. const dialog: Ref<any> = ref({ title: '数据信息', show: false, type: '1' });
  241. const form: Ref<any> = ref({ file: [] });
  242. const formFieldsForCreate = [
  243. { label: '服务标题', model: 'title' },
  244. { label: '服务类型', model: 'type', type: 'select' },
  245. { label: '标签', model: 'tags', custom: true },
  246. { label: '服务方式', model: 'way', type: 'select' },
  247. { label: '服务地区', model: 'area', type: 'select' },
  248. { label: '价格', model: 'money' },
  249. { label: '服务描述', model: 'desc', type: 'textarea' }
  250. ];
  251. const formFieldsForUpdate = [
  252. { label: '服务标题', model: 'title' },
  253. { label: '服务类型', model: 'type', type: 'select' },
  254. { label: '标签', model: 'tags', custom: true },
  255. { label: '服务方式', model: 'way', type: 'select' },
  256. { label: '服务地区', model: 'area', type: 'select' },
  257. { label: '价格', model: 'money' },
  258. { label: '服务描述', model: 'desc', type: 'textarea' }
  259. ];
  260. const addTags = () => {
  261. form.value.tags.push({ type: 'primary' });
  262. };
  263. const toDelTag = (index) => {
  264. form.value.tags.splice(index, 1);
  265. };
  266. // 关闭弹框
  267. const toClose = () => {
  268. form.value = {};
  269. dialog.value.show = false;
  270. };
  271. // #endregion
  272. </script>
  273. <style scoped></style>