approval.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. <template>
  2. <div class="p-2">
  3. <el-card shadow="always" style="height: 50px">
  4. <div style="display: flex; justify-content: space-between">
  5. <div>
  6. <!-- <el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>-->
  7. <!-- <el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button>-->
  8. <el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen"> 审批
  9. </el-button>
  10. <el-button v-if="itemPushBase && itemPushBase.id && itemPushBase.status !== 'draft'" type="primary"
  11. @click="handleApprovalRecord">
  12. 流程进度
  13. </el-button>
  14. </div>
  15. <div>
  16. <el-button style="float: right" @click="goBack()">返回</el-button>
  17. </div>
  18. </div>
  19. </el-card>
  20. <!-- push base -->
  21. <el-card shadow="always" class="custom-card">
  22. <div v-if="loading" class="loading-text">数据加载中...</div>
  23. <div v-else class="card-content">
  24. <div class="info-item">
  25. <strong>名称:</strong>
  26. <el-text>{{ itemPushBase.name }}</el-text>
  27. </div>
  28. <div class="info-item">
  29. <strong>类型:</strong>
  30. <el-text v-for="dict in smsb_push_type" :key="dict.value" :label="dict.label" :value="dict.value">
  31. <div v-if="parseInt(dict.value) === itemPushBase.itemType">
  32. {{ dict.label }}
  33. </div>
  34. </el-text>
  35. </div>
  36. <div class="info-item">
  37. <strong>优先级:</strong>
  38. <el-text v-for="dict in smsb_push_level" :key="dict.value" :label="dict.label" :value="dict.value">
  39. <div v-if="parseInt(dict.value) === itemPushBase.level">
  40. {{ dict.label }}
  41. </div>
  42. </el-text>
  43. </div>
  44. <div class="info-item">
  45. <strong>发布时间:</strong>
  46. <el-text>{{ itemPushBase.createTime }}</el-text>
  47. </div>
  48. <div class="info-item">
  49. <strong>发布人:</strong>
  50. <el-text>{{ itemPushBase.createUser }}</el-text>
  51. </div>
  52. <div class="info-item">
  53. <strong>状态:</strong>
  54. <el-text v-for="dict in smsb_push_state" :key="dict.value" :label="dict.label" :value="dict.value">
  55. <div v-if="dict.value === itemPushBase.status">
  56. {{ dict.label }}
  57. </div>
  58. </el-text>
  59. </div>
  60. </div>
  61. </el-card>
  62. <!-- deviceList timeList sourceList -->
  63. <el-card shadow="always" class="custom-card" style="height: 70vh; overflow-y: auto; margin-top: 10px">
  64. <div class="card-section">
  65. <!-- 第一部分 时间排期 -->
  66. <div class="section-content">
  67. <div v-for="(item, index) in timeList" :key="index">{{ item.start }} - {{ item.end }}</div>
  68. </div>
  69. <!-- 第二部分内容 -->
  70. <div class="section-content">
  71. <el-table v-loading="loading" :data="deviceList">
  72. <el-table-column label="设备名称" align="left" prop="name" :show-overflow-tooltip="true" />
  73. </el-table>
  74. </div>
  75. <!-- 第三部分内容 -->
  76. <div class="section-content">
  77. <el-table v-loading="loading" :data="sourceList">
  78. <el-table-column label="原名" align="left" prop="originalName" width="150" :show-overflow-tooltip="true" />
  79. <el-table-column label="类型" align="center" prop="type" width="80">
  80. <template #default="scope">
  81. <dict-tag :options="smsb_source_type" :value="scope.row.type" />
  82. </template>
  83. </el-table-column>
  84. <el-table-column label="大小" align="center" prop="size" />
  85. <el-table-column label="截图" align="center" prop="screenshot">
  86. <template #default="scope">
  87. <image-preview :src="scope.row.screenshot" style="width: 40px; height: 40px; cursor: pointer" />
  88. </template>
  89. </el-table-column>
  90. </el-table>
  91. </div>
  92. </div>
  93. </el-card>
  94. <!-- 提交组件 -->
  95. <SubmitVerifySmsb ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" />
  96. <!-- 审批记录 -->
  97. <approvalRecordSmsb ref="approvalRecordRef" />
  98. </div>
  99. </template>
  100. <script setup name="Leave" lang="ts">
  101. import { addLeave, updateLeave } from '@/api/workflow/leave';
  102. import { LeaveVO } from '@/api/workflow/leave/types';
  103. import { startWorkFlow } from '@/api/workflow/task';
  104. import SubmitVerifySmsb from '@/views/smsb/itemReview/submitVerifySmsb.vue';
  105. import ApprovalRecordSmsb from '@/views/smsb/itemReview/approvalRecordSmsb.vue';
  106. import { AxiosResponse } from 'axios';
  107. import { StartProcessBo } from '@/api/workflow/workflowCommon/types';
  108. import { getItemPushReview } from '@/api/smsb/source/item_push';
  109. import { ItemPushForm, ItemPushQuery, ItemPushTimeRangeVO, ItemPushVO } from '@/api/smsb/source/item_push_type';
  110. import { DeviceVO } from '@/api/smsb/device/device_type';
  111. import { MinioDataVO } from '@/api/smsb/source/minioData_type';
  112. import { ElTable } from 'element-plus';
  113. const { proxy } = getCurrentInstance() as ComponentInternalInstance;
  114. const { smsb_push_type, smsb_push_level, smsb_push_state, smsb_source_type } = toRefs<any>(
  115. proxy?.useDict('smsb_push_type', 'smsb_push_level', 'smsb_push_state', 'smsb_source_type')
  116. );
  117. const approvalButtonShow = ref(false);
  118. const buttonLoading = ref(false);
  119. const loading = ref(true);
  120. //路由参数
  121. const routeParams = ref<Record<string, any>>({});
  122. const itemPushBase = ref<ItemPushVO>();
  123. const deviceList = ref<DeviceVO[]>([]);
  124. const sourceList = ref<MinioDataVO[]>([]);
  125. const timeList = ref<ItemPushTimeRangeVO[]>([]);
  126. //提交组件
  127. const submitVerifyRef = ref<InstanceType<typeof SubmitVerifySmsb>>();
  128. //审批记录组件
  129. const approvalRecordRef = ref<InstanceType<typeof ApprovalRecordSmsb>>();
  130. const itemPushFormRef = ref<ElFormInstance>();
  131. const submitFormData = ref<StartProcessBo>({
  132. businessKey: '',
  133. tableName: '',
  134. variables: {}
  135. });
  136. const taskVariables = ref<Record<string, any>>({});
  137. const initFormData: ItemPushForm = {
  138. name: undefined,
  139. level: undefined,
  140. itemType: undefined,
  141. deviceIds: undefined,
  142. itemIds: undefined,
  143. dateRange: undefined,
  144. weekDays: ['1', '2', '3', '4', '5', '6', '7'],
  145. timeRange: [],
  146. status: undefined
  147. };
  148. const data = reactive<PageData<ItemPushForm, ItemPushQuery>>({
  149. form: { ...initFormData },
  150. queryParams: {
  151. pageNum: 1,
  152. pageSize: 10
  153. },
  154. rules: {}
  155. });
  156. const { form, rules } = toRefs(data);
  157. /** 表单重置 */
  158. const reset = () => {
  159. form.value = { ...initFormData };
  160. };
  161. /** 获取详情 */
  162. const getInfo = () => {
  163. loading.value = true;
  164. buttonLoading.value = false;
  165. nextTick(async () => {
  166. const res = await getItemPushReview(routeParams.value.id);
  167. itemPushBase.value = res.data;
  168. deviceList.value = res.data.deviceList;
  169. sourceList.value = res.data.resourceList;
  170. timeList.value = res.data.timeList;
  171. loading.value = false;
  172. buttonLoading.value = false;
  173. if (itemPushBase.value.status && itemPushBase.value.status === 'waiting') {
  174. approvalButtonShow.value = true;
  175. } else {
  176. approvalButtonShow.value = false;
  177. }
  178. });
  179. };
  180. /** 提交按钮 */
  181. const submitForm = (status: string) => {
  182. try {
  183. itemPushFormRef.value?.validate(async (valid: boolean) => {
  184. if (valid) {
  185. buttonLoading.value = true;
  186. let res: AxiosResponse<LeaveVO>;
  187. if (form.value.id) {
  188. res = await updateLeave(form.value);
  189. } else {
  190. res = await addLeave(form.value);
  191. }
  192. form.value = res.data;
  193. if (status === 'draft') {
  194. buttonLoading.value = false;
  195. proxy?.$modal.msgSuccess('暂存成功');
  196. proxy.$tab.closePage(proxy.$route);
  197. proxy.$router.go(-1);
  198. } else {
  199. await handleStartWorkFlow(res.data);
  200. }
  201. }
  202. });
  203. } finally {
  204. buttonLoading.value = false;
  205. goBack();
  206. }
  207. };
  208. //提交申请
  209. const handleStartWorkFlow = async (data: LeaveVO) => {
  210. try {
  211. submitFormData.value.tableName = 'test_leave';
  212. submitFormData.value.businessKey = data.id;
  213. //流程变量
  214. taskVariables.value = {
  215. entity: data,
  216. leaveDays: data.leaveDays,
  217. userList: ['1', '3'],
  218. userList2: ['1', '3']
  219. };
  220. submitFormData.value.variables = taskVariables.value;
  221. const resp = await startWorkFlow(submitFormData.value);
  222. if (submitVerifyRef.value) {
  223. buttonLoading.value = false;
  224. submitVerifyRef.value.openDialog(resp.data.taskId);
  225. }
  226. } finally {
  227. buttonLoading.value = false;
  228. }
  229. };
  230. //审批记录
  231. const handleApprovalRecord = () => {
  232. approvalRecordRef.value.init(itemPushBase.value.id);
  233. };
  234. //提交回调
  235. const submitCallback = async () => {
  236. await proxy.$tab.closePage(proxy.$route);
  237. proxy.$router.push('/source/review');
  238. };
  239. //返回
  240. const goBack = () => {
  241. proxy.$tab.closePage(proxy.$route);
  242. proxy.$router.go(-1);
  243. };
  244. //审批
  245. const approvalVerifyOpen = async () => {
  246. submitVerifyRef.value.openDialog(routeParams.value.taskId);
  247. };
  248. //校验提交按钮是否显示
  249. const submitButtonShow = computed(() => {
  250. return (
  251. routeParams.value.type === 'add' ||
  252. (routeParams.value.type === 'update' &&
  253. form.value.status &&
  254. (form.value.status === 'draft' || form.value.status === 'cancel' || form.value.status === 'back'))
  255. );
  256. });
  257. //校验审批按钮是否显示
  258. /*const approvalButtonShow = computed(() => {
  259. return routeParams.value.type === 'approval';
  260. });*/
  261. onMounted(() => {
  262. nextTick(async () => {
  263. routeParams.value = proxy.$route.query;
  264. reset();
  265. loading.value = false;
  266. if (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval') {
  267. getInfo();
  268. }
  269. });
  270. });
  271. </script>
  272. <style scoped>
  273. .custom-card {
  274. margin-top: 20px;
  275. border-radius: 8px;
  276. }
  277. .card-content {
  278. display: flex;
  279. flex-wrap: wrap;
  280. justify-content: space-between;
  281. }
  282. .info-item {
  283. flex: 1 1 16%;
  284. /* 每个项目至少占容器的16%,允许伸缩 */
  285. margin: 5px 0;
  286. box-sizing: border-box;
  287. padding-right: 10px;
  288. /* 避免内容重叠 */
  289. }
  290. .info-item strong {
  291. display: block;
  292. /* 将 strong 标签换行,以便内容更易读 */
  293. }
  294. .loading-text {
  295. padding: 10px;
  296. text-align: center;
  297. font-size: 14px;
  298. color: #909399;
  299. }
  300. .card-section {
  301. display: flex;
  302. flex: 1;
  303. overflow-y: auto;
  304. }
  305. .section-content {
  306. flex: 1;
  307. padding: 10px;
  308. border-right: 1px solid #ebeef5;
  309. /* 可选:添加分隔线 */
  310. }
  311. .section-content:last-child {
  312. border-right: none;
  313. /* 移除最后一个元素的分隔线 */
  314. }
  315. </style>