admin.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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"> </cSearch>
  6. </el-col>
  7. <el-col :span="24" class="two">
  8. <cButton :isAdd="false"> </cButton>
  9. </el-col>
  10. <el-col :span="24" class="thr">
  11. <cTable :fields="fields" :opera="opera" :list="list" @query="search" :total="total" @edit="toEdit" @del="toDel" @status="toStatus"> </cTable>
  12. </el-col>
  13. </el-col>
  14. </el-row>
  15. <cDialog :dialog="dialog" @toClose="toClose">
  16. <el-col :span="24" class="dialog_one" v-if="dialog.type == '1'">
  17. <cForm :span="24" :fields="formFields" :form="form" :rules="{}" @save="toSave" label-width="auto">
  18. <template #status>
  19. <el-radio v-for="i in statusList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
  20. </template>
  21. <template #has_connect>
  22. <el-option v-for="i in hasConnectList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  23. </template>
  24. <template #way>
  25. <el-option v-for="i in wayList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  26. </template>
  27. <template #files>
  28. <cUpload model="files" :limit="5" url="/files/zdlyjszy/achieve/upload" :list="form.files" listType="picture-card" @change="onUpload"></cUpload>
  29. </template>
  30. <template #achieve>
  31. <el-select v-model="form.achieve" filterable remote reserve-keyword placeholder="请输入成果名称" :remote-method="getAchieve" :loading="loading">
  32. <el-option v-for="item in achieveList" :key="item._id" :label="item.name" :value="item._id" />
  33. </el-select>
  34. </template>
  35. </cForm>
  36. </el-col>
  37. <el-col :span="24" class="dialog_one" v-if="dialog.type == '2'">
  38. <el-row justify="center">
  39. <el-col :span="24">
  40. <el-steps :space="200" finish-status="success">
  41. <el-step title="审核中" :status="getStepStatus(0)" />
  42. <el-step title="报名中" :status="getStepStatus(1)" />
  43. <el-step title="公开交易中" :status="getStepStatus(2)" />
  44. <el-step title="已结束" :status="getStepStatus(3)" />
  45. </el-steps>
  46. </el-col>
  47. </el-row>
  48. <cForm :span="24" :fields="formFields" :form="form" :rules="{}" @save="toSave" label-width="auto" :disabled="true" :isSave="false">
  49. <template #status>
  50. <el-radio v-for="i in statusList" :key="i._id" :label="i.value">{{ i.label }}</el-radio>
  51. </template>
  52. <template #has_connect>
  53. <el-option v-for="i in hasConnectList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  54. </template>
  55. <template #way>
  56. <el-option v-for="i in wayList" :key="i._id" :label="i.label" :value="i.value"></el-option>
  57. </template>
  58. <template #files>
  59. <cUpload model="files" :limit="5" url="/files/zdlyjszy/achieve/upload" :list="form.files" listType="picture-card" @change="onUpload"></cUpload>
  60. </template>
  61. <template #achieve>
  62. <el-select v-model="form.achieve" filterable remote reserve-keyword placeholder="请输入成果名称" :remote-method="getAchieve" :loading="loading">
  63. <el-option v-for="item in achieveList" :key="item._id" :label="item.name" :value="item._id" />
  64. </el-select>
  65. </template>
  66. </cForm>
  67. <el-row justify="center">
  68. <el-col :span="4">
  69. <el-button :disabled="false" type="warning" @click="toBack" v-if="form.status !== '0'">上一步</el-button>
  70. </el-col>
  71. <el-col :span="4">
  72. <el-button :disabled="false" type="success" @click="toNext" v-if="form.status !== '3'">下一步</el-button>
  73. </el-col>
  74. </el-row>
  75. </el-col>
  76. </cDialog>
  77. </template>
  78. <script setup lang="ts">
  79. import { ref, Ref, onMounted, inject } from 'vue';
  80. // NeedChange
  81. import { NegotiateStore } from '@/stores/core/trade/negotiate';
  82. import { AchieveStore } from '@/stores/core/achieve';
  83. import { DictDataStore } from '@/stores/system/dictData';
  84. import type { IQueryResult } from '@/util/types.util';
  85. import { cloneDeep, get, isObject } from 'lodash';
  86. import baseStore from '@/stores/counter';
  87. const user = ref(baseStore.state.user);
  88. onMounted(async () => {
  89. loading.value = true;
  90. await searchOther();
  91. await search({ skip, limit });
  92. loading.value = false;
  93. });
  94. const loading: Ref<any> = ref(false);
  95. // NeedChange
  96. const store = NegotiateStore();
  97. const dictDataStore = DictDataStore();
  98. const achieveStore = AchieveStore();
  99. const $checkRes = inject('$checkRes') as Function;
  100. // #region 字典
  101. // NeedChange
  102. const statusList: Ref<any> = ref([]);
  103. const hasConnectList: Ref<any> = ref([]);
  104. const wayList: Ref<any> = ref([]);
  105. const searchOther = async () => {
  106. const statusResult: IQueryResult = await dictDataStore.query({ code: 'negotiateStatus' });
  107. if ($checkRes(statusResult)) {
  108. statusList.value = statusResult.data;
  109. }
  110. const hasConnectResult: IQueryResult = await dictDataStore.query({ code: 'hasConnect' });
  111. if ($checkRes(hasConnectResult)) {
  112. hasConnectList.value = hasConnectResult.data;
  113. }
  114. const outWayResult: IQueryResult = await dictDataStore.query({ code: 'outWay' });
  115. if ($checkRes(outWayResult)) {
  116. wayList.value = outWayResult.data;
  117. }
  118. };
  119. // #endregion
  120. // #region 查询相关
  121. let list: Ref<any> = ref([]);
  122. let total: Ref<number> = ref(0);
  123. let skip = 0;
  124. let limit = inject('$limit') as number;
  125. let searchForm: Ref<any> = ref({});
  126. const search = async (e: { skip: number; limit: number }) => {
  127. const info = { skip: e.skip, limit: e.limit, ...searchForm.value };
  128. const res: IQueryResult = await store.query(info);
  129. if ($checkRes(res)) {
  130. list.value = res.data;
  131. total.value = res.total;
  132. }
  133. };
  134. const toSearch = (query) => {
  135. searchForm.value = query;
  136. search({ skip, limit });
  137. };
  138. const achieveList: Ref<any> = ref([]);
  139. const getAchieve = async (data) => {
  140. const res = await achieveStore.query({ name: data });
  141. if ($checkRes(res)) {
  142. achieveList.value = res.data;
  143. }
  144. };
  145. // #endregion
  146. // #region 表格及操作
  147. // NeedChange
  148. let fields: Ref<any[]> = ref([
  149. { label: '成果', model: 'achieve.name' },
  150. { label: '专利号', model: 'no', isSearch: true },
  151. { label: '联系邮箱', model: 'email' },
  152. { label: '出让方式', model: 'way', format: (i) => getDict(i, 'way') },
  153. { label: '拟定价格', model: 'money' },
  154. { label: '公告开始时间', model: 'start_time' },
  155. { label: '公告结束时间', model: 'end_time' },
  156. { label: '状态', model: 'status', format: (i) => getDict(i, 'status') }
  157. ]);
  158. // 操作
  159. let opera: Ref<any[]> = ref([
  160. { label: '修改', method: 'edit', display: (i) => i.status === '0' },
  161. { label: '流程管理', method: 'status' },
  162. { label: '删除', method: 'del', confirm: true, type: 'danger', display: (i) => i.status === '0' }
  163. ]);
  164. const getDict = (data, model) => {
  165. let list;
  166. switch (model) {
  167. case 'status':
  168. list = statusList.value;
  169. break;
  170. case 'way':
  171. list = wayList.value;
  172. break;
  173. default:
  174. break;
  175. }
  176. const res = list.find((f) => f.value == data);
  177. return get(res, 'label');
  178. };
  179. const toAdd = () => {
  180. formFields.value = formFieldsForCreate;
  181. // 所属人是自己,需要把自己的id放进去
  182. form.value = { ...cloneDeep(defaultForm) };
  183. dialog.value.show = true;
  184. };
  185. const toEdit = async (data) => {
  186. formFields.value = formFieldsForUpdate;
  187. // 需要将成果放到achieveList中,如果这个数据中的成果是id,就得去库里查询
  188. const achieve = cloneDeep(data.achieve);
  189. if (isObject(achieve)) achieveList.value = [achieve];
  190. form.value = { ...data };
  191. dialog.value.show = true;
  192. };
  193. const toStatus = async (data) => {
  194. formFields.value = formFieldsForUpdate;
  195. // 需要将成果放到achieveList中,如果这个数据中的成果是id,就得去库里查询
  196. const achieve = cloneDeep(data.achieve);
  197. if (isObject(achieve)) achieveList.value = [achieve];
  198. form.value = { ...data };
  199. dialog.value.show = true;
  200. dialog.value.type = '2';
  201. };
  202. const toNext = async () => {
  203. const data = cloneDeep(form.value);
  204. // 进行下一步
  205. let status = data.status;
  206. switch (data.status) {
  207. case '0':
  208. status = '1';
  209. break;
  210. case '1':
  211. status = '2';
  212. break;
  213. case '2':
  214. status = '3';
  215. break;
  216. default:
  217. break;
  218. }
  219. const res = await store.update({ _id: data._id, status });
  220. if ($checkRes(res, true)) {
  221. search({ skip: 0, limit });
  222. toClose();
  223. }
  224. };
  225. const toBack = async () => {
  226. const data = cloneDeep(form.value);
  227. // 返回上一步
  228. let status = data.status;
  229. switch (data.status) {
  230. case '3':
  231. status = '2';
  232. break;
  233. case '2':
  234. status = '1';
  235. break;
  236. case '1':
  237. status = '0';
  238. break;
  239. default:
  240. break;
  241. }
  242. const res = await store.update({ _id: data._id, status });
  243. if ($checkRes(res, true)) {
  244. search({ skip: 0, limit });
  245. toClose();
  246. }
  247. };
  248. // #endregion
  249. // #region 常规接口
  250. const toSave = async () => {
  251. const data = cloneDeep(form.value);
  252. let res: IQueryResult;
  253. if (get(data, '_id')) res = await store.update(data);
  254. else res = await store.create(data);
  255. if ($checkRes(res, true)) {
  256. search({ skip: 0, limit });
  257. toClose();
  258. }
  259. };
  260. const toDel = async (data) => {
  261. const res = await store.del(data._id);
  262. if ($checkRes(res, true)) {
  263. search({ skip: 0, limit });
  264. }
  265. };
  266. // #endregion
  267. // #region 表单及操作
  268. // NeedChange
  269. const defaultForm = { status: '0' };
  270. const formFields: Ref<any> = ref();
  271. const dialog: Ref<any> = ref({ title: '数据信息', show: false, type: '1' });
  272. const form: Ref<any> = ref({ file: [] });
  273. const formFieldsForCreate = [
  274. { label: '交易成果', model: 'achieve', custom: true },
  275. { label: '专利号', model: 'no' },
  276. { label: '联系邮箱', model: 'email' },
  277. { label: '受让方是否是成果完成人或者其利害关系人', model: 'has_connect', type: 'select' },
  278. { label: '出让方式', model: 'way', type: 'select' },
  279. { label: '公示备注', model: 'public_remark', type: 'textarea' },
  280. { label: '拟定价格', model: 'money' },
  281. { label: '公告开始时间', model: 'start_time', type: 'datetime' },
  282. { label: '公告结束时间', model: 'end_time', type: 'datetime' }
  283. // { label: '状态', model: 'status', type: 'radio' }
  284. ];
  285. const formFieldsForUpdate = [
  286. { label: '交易成果', model: 'achieve', custom: true },
  287. { label: '专利号', model: 'no' },
  288. { label: '联系邮箱', model: 'email' },
  289. { label: '受让方是否是成果完成人或者其利害关系人', model: 'has_connect', type: 'select' },
  290. { label: '出让方式', model: 'way', type: 'select' },
  291. { label: '公示备注', model: 'public_remark', type: 'textarea' },
  292. { label: '拟定价格', model: 'money' },
  293. { label: '公告开始时间', model: 'start_time', type: 'datetime' },
  294. { label: '公告结束时间', model: 'end_time', type: 'datetime' }
  295. // { label: '状态', model: 'status', type: 'radio' }
  296. ];
  297. // 关闭弹框
  298. const toClose = () => {
  299. form.value = {};
  300. achieveList.value = [];
  301. dialog.value.show = false;
  302. dialog.value.type = '1';
  303. };
  304. const onUpload = (e: { model: string; value: Array<[]> }) => {
  305. const { model, value } = e;
  306. form.value[model] = value;
  307. };
  308. const getStepStatus = (step) => {
  309. const nowStatus = form.value.status;
  310. const numStatus = parseInt(nowStatus);
  311. if (step > numStatus) return 'wait';
  312. else if (step < numStatus) return 'success';
  313. else {
  314. if (step === 3) return 'success';
  315. else return 'process';
  316. }
  317. };
  318. // #endregion
  319. </script>
  320. <style scoped></style>