Special-audit.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <template>
  2. <el-dialog v-model="state.dialogVisible" draggable title="特提审批" width="50%" append-to-body destroy-on-close @close="close">
  3. <div class="collapse-container">
  4. <el-form label-width="110px" ref="ruleFormRef" :model="state.ruleForm">
  5. <el-row :gutter="35">
  6. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  7. <el-form-item label="工单编码" class="mb5"> {{ state.detail?.order?.no }} </el-form-item>
  8. </el-col>
  9. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  10. <el-form-item label="工单标题" class="mb5"> {{ state.detail?.order?.title }} </el-form-item>
  11. </el-col>
  12. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  13. <el-form-item label="申请人" class="mb5"> {{ state.detail?.creatorName }} </el-form-item>
  14. </el-col>
  15. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  16. <el-form-item label="申请部门" class="mb5"> {{ state.detail?.creatorOrgName }} </el-form-item>
  17. </el-col>
  18. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  19. <el-form-item label="申请时间" class="mb5"> {{ formatDate(state.detail?.creationTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  20. </el-col>
  21. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  22. <el-form-item label="特提原因" class="mb5">
  23. {{ state.detail?.cause }}
  24. </el-form-item>
  25. </el-col>
  26. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  27. <el-form-item label="特提理由" class="mb5">
  28. {{ state.detail?.reason }}
  29. </el-form-item>
  30. </el-col>
  31. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  32. <el-form-item label="附件" class="mb5">
  33. <annex-list name="特提附件" readonly classify="特提申请" v-model="state.detail.files" />
  34. </el-form-item>
  35. </el-col>
  36. <el-divider />
  37. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
  38. <el-form-item label="审批结果" prop="isPass" :rules="[{ required: true, message: '请选择审批结果', trigger: 'change' }]">
  39. <el-radio-group v-model="state.ruleForm.isPass">
  40. <el-radio :label="true">同意</el-radio>
  41. <el-radio :label="false">不同意</el-radio>
  42. </el-radio-group>
  43. </el-form-item>
  44. </el-col>
  45. <template v-if="state.ruleForm.isPass">
  46. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  47. <el-form-item label="特提节点" prop="nextStepCode" :rules="[{ required: true, message: '请选择特提节点', trigger: 'change' }]">
  48. <el-select v-model="state.ruleForm.nextStepCode" placeholder="请选择特提节点" class="w100" @change="selectTrace">
  49. <el-option v-for="item in steps" :value="item.key" :key="item.key" :label="item.value"> </el-option>
  50. </el-select>
  51. </el-form-item>
  52. </el-col>
  53. <template v-if="state.ruleForm.nextStepCode">
  54. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
  55. <el-form-item label="办理时限" prop="timeLimit" :rules="[{ required: true, message: '请输入办理时限', trigger: 'blur' }]">
  56. <el-row :gutter="10" class="w100">
  57. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  58. <el-input-number
  59. placeholder="办理时限"
  60. v-model="state.ruleForm.timeLimit"
  61. controls-position="right"
  62. class="w100"
  63. :min="1"
  64. :max="99"
  65. ></el-input-number>
  66. </el-col>
  67. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-loading="state.loading">
  68. <el-form-item
  69. label=""
  70. label-width="0"
  71. prop="timeLimitUnit"
  72. :rules="[{ required: true, message: '请选择办理时限单位', trigger: 'change' }]"
  73. >
  74. <el-select v-model="state.ruleForm.timeLimitUnit" placeholder="办理时限单位">
  75. <el-option v-for="item in specialTimeType" :value="item.key" :key="item.key" :label="item.value" />
  76. </el-select>
  77. </el-form-item>
  78. </el-col>
  79. </el-row>
  80. </el-form-item>
  81. </el-col>
  82. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  83. <el-form-item label="办理对象" prop="nextHandlers" :rules="[{ required: true, message: '请选择办理对象', trigger: 'change' }]">
  84. <el-select-v2
  85. v-model="state.ruleForm.nextHandlers"
  86. :options="stepsItems"
  87. placeholder="请选择办理对象"
  88. class="w100"
  89. multiple
  90. clearable
  91. collapse-tags
  92. collapse-tags-tooltip
  93. filterable
  94. value-key="key"
  95. />
  96. </el-form-item>
  97. </el-col>
  98. </template>
  99. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  100. <el-form-item label="" prop="alterTime">
  101. <el-checkbox v-model="state.ruleForm.alterTime" label="无需计算期满时间" />
  102. </el-form-item>
  103. </el-col>
  104. </template>
  105. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  106. <el-form-item label="审批意见" prop="opinion" :rules="[{ required: true, message: '请填写特提审批意见', trigger: 'blur' }]">
  107. <el-input v-model="state.ruleForm.opinion" type="textarea" :autosize="{ minRows: 6, maxRows: 10 }" placeholder="请填写特提审批意见" />
  108. </el-form-item>
  109. </el-col>
  110. </el-row>
  111. </el-form>
  112. </div>
  113. <template #footer>
  114. <span class="dialog-footer">
  115. <el-button @click="closeDialog" class="default-button">取 消</el-button>
  116. <el-button type="primary" @click="onAudit(ruleFormRef)" :loading="state.loading">审 批</el-button>
  117. </span>
  118. </template>
  119. </el-dialog>
  120. </template>
  121. <script setup lang="ts" name="SpecialDialogAudit">
  122. import { defineAsyncComponent, reactive, ref } from 'vue';
  123. import { ElMessage, FormInstance } from 'element-plus';
  124. import { storeToRefs } from 'pinia';
  125. import { useUserInfo } from '@/stores/userInfo';
  126. import { formatDate } from '@/utils/formatTime';
  127. import { specialApplyBase, specialApprove, specialDetail } from '@/api/business/special';
  128. import { transformFile } from '@/utils/tools';
  129. import { orderTimeConfig } from '@/api/business/order';
  130. // 引入组件
  131. const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue'));
  132. // 定义子组件向父组件传值/事件
  133. const emit = defineEmits(['updateList']);
  134. // 定义变量内容
  135. const state = reactive<any>({
  136. dialogVisible: false, // 是否显示弹窗
  137. loading: false, // 是否显示加载
  138. ruleForm: {
  139. nextStepCode: null, // 特提节点
  140. nextHandlers: [], // 处理对象
  141. timeLimitUnit: 2, // 期满时间单位
  142. orgId: null, // 部门id
  143. orgName: null, // 部门名称
  144. alterTime: false, // 是否修改期满时间
  145. opinion: '', // 审批意见
  146. isPass: true, // 是否通过
  147. },
  148. detail: {}, // 详情信息
  149. workflowId: null, // 工作流id
  150. });
  151. const ruleFormRef = ref<RefType>();
  152. const storesUserInfo = useUserInfo();
  153. const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
  154. const steps = ref<EmptyArrayType>([]); // 特提节点
  155. const stepsItems = ref<EmptyArrayType>([]); // 处理对象
  156. const specialTimeType = ref<EmptyArrayType>([]); // 期满时间单位
  157. // 打开弹窗
  158. const openDialog = async (val: any) => {
  159. state.loading = true;
  160. state.dialogVisible = true;
  161. state.workflowId = val.workflowId;
  162. try {
  163. const [baseRes, detailRes] = await Promise.all([specialApplyBase(val.workflowId), specialDetail(val.id)]);
  164. steps.value = baseRes.result?.step?.steps ?? [];
  165. specialTimeType.value = baseRes.result.specialTimeType ?? [];
  166. state.detail = detailRes.result;
  167. state.detail.files = transformFile(detailRes.result.files);
  168. state.ruleForm.nextStepCode = detailRes.result.nextStepCode;
  169. state.ruleForm.nextStepName = detailRes.result.nextStepName;
  170. selectTrace(detailRes.result.nextStepCode);
  171. state.ruleForm.nextHandlers = detailRes.result.nextHandlers;
  172. state.ruleForm.alterTime = detailRes.result.alterTime;
  173. } catch (e) {
  174. console.log(e);
  175. } finally {
  176. state.loading = false;
  177. }
  178. };
  179. // 关闭弹窗
  180. const closeDialog = () => {
  181. state.dialogVisible = false;
  182. };
  183. const close = () => {
  184. ruleFormRef.value?.clearValidate();
  185. ruleFormRef.value?.resetFields();
  186. steps.value = [];
  187. stepsItems.value = [];
  188. };
  189. // 选择节点确定处理对象
  190. const selectTrace = (val: any) => {
  191. const step = steps.value.find((item) => item.key === val);
  192. state.ruleForm.nextStepName = step?.value;
  193. ruleFormRef.value?.resetFields('nextHandlers');
  194. stepsItems.value = step?.items ?? [];
  195. stepsItems.value = stepsItems.value.map((item: any) => {
  196. return {
  197. value: {
  198. ...item,
  199. },
  200. label: item.value,
  201. };
  202. });
  203. state.ruleForm.flowDirection = step?.flowDirection;
  204. queryHandleTime();
  205. };
  206. // 查询办理时限
  207. const queryHandleTime = () => {
  208. if (state.ruleForm.alterTime) return;
  209. state.loading = true;
  210. orderTimeConfig({ acceptTypeCode: state.detail.order?.acceptTypeCode, FlowDirection: state.ruleForm.flowDirection })
  211. .then((res) => {
  212. state.ruleForm.timeLimit = res.result.count ?? 0; // 办理时限
  213. state.ruleForm.timeLimitUnit = res.result.timeType ?? ''; // 办理时限单位
  214. })
  215. .finally(() => {
  216. state.loading = false;
  217. });
  218. };
  219. // 审批
  220. const onAudit = (formEl: FormInstance | undefined) => {
  221. if (!formEl) return;
  222. formEl.validate((valid: boolean) => {
  223. if (!valid) return;
  224. state.loading = true;
  225. let request: {};
  226. if (state.ruleForm.isPass) {
  227. request = {
  228. id: state.detail.id,
  229. orderId: state.detail.orderId,
  230. timeLimit: state.ruleForm.timeLimit,
  231. timeLimitUnit: state.ruleForm.timeLimitUnit,
  232. cause: state.detail.cause,
  233. opinion: state.ruleForm.opinion,
  234. workflowId: state.workflowId,
  235. state: 1, // 审核结果 0 待审核 1 审核通过 2 审核不通过
  236. nextStepCode: state.ruleForm.nextStepCode,
  237. nextStepName: state.ruleForm.nextStepName,
  238. nextHandlers: state.ruleForm.nextHandlers,
  239. };
  240. } else {
  241. request = {
  242. id: state.detail.id,
  243. orderId: state.detail.orderId,
  244. cause: state.detail.cause,
  245. opinion: state.ruleForm.opinion,
  246. workflowId: state.workflowId,
  247. state: 2, // 审核结果 0 待审核 1 审核通过 2 审核不通过
  248. };
  249. }
  250. specialApprove(request)
  251. .then(() => {
  252. state.loading = false;
  253. closeDialog();
  254. emit('updateList');
  255. ElMessage.success('操作成功');
  256. })
  257. .catch(() => {
  258. state.loading = false;
  259. });
  260. });
  261. };
  262. defineExpose({
  263. openDialog,
  264. closeDialog,
  265. });
  266. </script>