index.vue 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. <template>
  2. <div>
  3. <el-dialog
  4. v-model="state.dialogVisible"
  5. draggable
  6. :title="state.dialogTitle"
  7. ref="dialogRef"
  8. @mouseup="mouseup"
  9. :style="'transform: ' + state.transform + ';'"
  10. append-to-body
  11. destroy-on-close
  12. :show-close="false"
  13. :close-on-click-modal="false"
  14. :close-on-press-escape="false"
  15. @close="close"
  16. >
  17. <el-steps :active="activeStep" align-center finish-status="success" class="mb20" v-if="showStepsArr.includes(state.processType)">
  18. <el-step title="业务表单" />
  19. <el-step title="流程表单" />
  20. </el-steps>
  21. <div v-show="activeStep === 0">
  22. <el-form :model="state.delayForm" label-width="110px" ref="delayFormRef" v-if="state.processType === '延期申请'">
  23. <el-row :gutter="10">
  24. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  25. <el-form-item label="工单编码"> {{ state.orderDetail.no }} </el-form-item>
  26. </el-col>
  27. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  28. <el-form-item label="工单标题"> {{ state.orderDetail.title }} </el-form-item>
  29. </el-col>
  30. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  31. <el-form-item label="申请人"> {{ userInfos.name }} </el-form-item>
  32. </el-col>
  33. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  34. <el-form-item label="申请部门"> {{ userInfos.orgName }} </el-form-item>
  35. </el-col>
  36. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  37. <el-form-item label="申请时间"> {{ formatDate(Date(), 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  38. </el-col>
  39. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  40. <el-form-item label="当前期满时间"> {{ formatDate(state.orderDetail.expiredTime, 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  41. </el-col>
  42. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12" v-loading="state.loading">
  43. <el-form-item label="延期申请数量" prop="timeLimitCount" :rules="[{ required: true, message: '请输入延期申请数量', trigger: 'blur' }]">
  44. <el-row :gutter="10">
  45. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  46. <el-input-number
  47. placeholder="延期申请数量"
  48. v-model="state.delayForm.timeLimitCount"
  49. controls-position="right"
  50. class="w100"
  51. @input="computeTime"
  52. ></el-input-number>
  53. </el-col>
  54. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-loading="state.loading">
  55. <el-form-item
  56. label=""
  57. label-width="0"
  58. prop="timeLimitUnit"
  59. :rules="[{ required: true, message: '请选择延期申请单位', trigger: 'change' }]"
  60. >
  61. <el-select v-model="state.delayForm.timeLimitUnit" placeholder="延期申请单位" @change="computeTime">
  62. <el-option v-for="item in timeTypeOptions" :value="item.key" :key="item.key" :label="item.value" />
  63. </el-select>
  64. </el-form-item>
  65. </el-col>
  66. </el-row>
  67. </el-form-item>
  68. </el-col>
  69. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  70. <el-form-item label="延期后期满时间"> {{ state.delayForm.endTime }} </el-form-item>
  71. </el-col>
  72. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  73. <el-form-item label="申请理由" prop="content" :rules="[{ required: true, message: '请填写延期申请理由', trigger: 'blur' }]">
  74. <common-advice
  75. @chooseAdvice="chooseAdviceDelay"
  76. v-model="state.delayForm.content"
  77. placeholder="请填写延期申请理由"
  78. :loading="state.loading"
  79. :commonEnum="commonEnum.Delay"
  80. />
  81. </el-form-item>
  82. </el-col>
  83. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  84. <el-form-item label="附件">
  85. <annex-list name="延期附件" ref="annexListRef" :businessId="state.orderDetail.id" classify="延期上传" />
  86. </el-form-item>
  87. </el-col>
  88. </el-row>
  89. </el-form>
  90. <el-form :model="state.discernForm" label-width="110px" ref="discernFormRef" v-if="state.processType === '甄别申请'">
  91. <el-row :gutter="10">
  92. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  93. <el-form-item label="工单编码"> {{ state.orderDetail.no }} </el-form-item>
  94. </el-col>
  95. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  96. <el-form-item label="工单标题"> {{ state.orderDetail.title }} </el-form-item>
  97. </el-col>
  98. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  99. <el-form-item label="申请人"> {{ userInfos.name }} </el-form-item>
  100. </el-col>
  101. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  102. <el-form-item label="申请部门"> {{ userInfos.orgName }} </el-form-item>
  103. </el-col>
  104. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  105. <el-form-item label="申请时间"> {{ formatDate(Date(), 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  106. </el-col>
  107. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  108. <el-form-item label="申请类型" prop="type" :rules="[{ required: true, message: '请选择申请类型', trigger: 'change' }]">
  109. <el-select v-model="state.discernForm.type" placeholder="请选择申请类型" class="w100" value-key="dicDataValue">
  110. <el-option v-for="item in screenTypeOptions" :value="item" :key="item.dicDataValue" :label="item.dicDataName" />
  111. </el-select>
  112. </el-form-item>
  113. </el-col>
  114. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  115. <el-form-item label="申请理由" prop="content" :rules="[{ required: true, message: '请填写甄别申请理由', trigger: 'blur' }]">
  116. <common-advice
  117. @chooseAdvice="chooseAdviceDiscern"
  118. v-model="state.discernForm.content"
  119. placeholder="请填写甄别申请理由"
  120. :loading="state.loading"
  121. :commonEnum="commonEnum.Discriminate"
  122. />
  123. </el-form-item>
  124. </el-col>
  125. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  126. <el-form-item label="附件">
  127. <annex-list name="甄别附件" ref="annexListRef" :businessId="state.orderDetail.id" classify="甄别上传" />
  128. </el-form-item>
  129. </el-col>
  130. </el-row>
  131. </el-form>
  132. <el-form :model="state.redoForm" label-width="110px" ref="redoFormRef" v-if="state.processType === '工单重办'">
  133. <el-row :gutter="10">
  134. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  135. <el-form-item label="工单编码"> {{ state.orderDetail.no }} </el-form-item>
  136. </el-col>
  137. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  138. <el-form-item label="工单标题"> {{ state.orderDetail.title }} </el-form-item>
  139. </el-col>
  140. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  141. <el-form-item label="申请人"> {{ userInfos.name }} </el-form-item>
  142. </el-col>
  143. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  144. <el-form-item label="申请部门"> {{ userInfos.orgName }} </el-form-item>
  145. </el-col>
  146. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  147. <el-form-item label="申请时间"> {{ formatDate(Date(), 'YYYY-mm-dd HH:MM:SS') }} </el-form-item>
  148. </el-col>
  149. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  150. <el-form-item label="重办理由" prop="orderRedoReason" :rules="[{ required: true, message: '请选择重办理由', trigger: 'change' }]">
  151. <el-select v-model="state.redoForm.orderRedoReason" placeholder="请选择重办理由" clearable class="w100">
  152. <el-option v-for="item in orderRedoReasonOptions" :value="item.key" :key="item.key" :label="item.value" />
  153. </el-select>
  154. </el-form-item>
  155. </el-col>
  156. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  157. <el-form-item label="重办意见" prop="redoOpinion" :rules="[{ required: true, message: '请填写重办意见', trigger: 'blur' }]">
  158. <common-advice
  159. @chooseAdvice="chooseAdviceRedo"
  160. v-model="state.redoForm.redoOpinion"
  161. placeholder="请填写重办意见"
  162. :loading="state.loading"
  163. :commonEnum="commonEnum.OrderCirculation"
  164. />
  165. </el-form-item>
  166. </el-col>
  167. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  168. <el-form-item label="附件">
  169. <annex-list name="重办附件" ref="annexListRedoRef" :businessId="state.orderDetail.id" classify="重办上传" />
  170. </el-form-item>
  171. </el-col>
  172. </el-row>
  173. </el-form>
  174. <el-form :model="state.circularForm" label-width="110px" ref="circularFormRef" v-if="state.processType === '新增通知'">
  175. <el-row :gutter="10">
  176. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  177. <el-form-item label="通知类型" prop="circularObj" :rules="[{ required: true, message: '请选择通知类型型', trigger: 'change' }]">
  178. <el-select
  179. v-model="state.circularForm.circularObj"
  180. placeholder="请选择通知类型型"
  181. value-key="dicDataValue"
  182. class="w100"
  183. @change="
  184. (e) => {
  185. state.circularForm.circularTypeId = e.dicDataValue;
  186. state.circularForm.circularTypeName = e.dicDataName;
  187. }
  188. "
  189. >
  190. <el-option v-for="item in circularTypeOptions" :value="item" :key="item.dicDataValue" :label="item.dicDataName" />
  191. </el-select>
  192. </el-form-item>
  193. </el-col>
  194. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  195. <el-form-item label="通知标题" prop="title" :rules="[{ required: true, message: '请输入通知标题', trigger: 'blur' }]">
  196. <el-input v-model="state.circularForm.title" placeholder="请输入通知标题" clearable show-word-limit maxlength="200"></el-input>
  197. </el-form-item>
  198. </el-col>
  199. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  200. <el-form-item label="必须阅读" prop="isMustRead" :rules="[{ required: true, message: '请选择必须阅读', trigger: 'change' }]">
  201. <el-radio-group v-model="state.circularForm.isMustRead">
  202. <el-radio :label="true">是</el-radio>
  203. <el-radio :label="false">否</el-radio>
  204. </el-radio-group>
  205. </el-form-item>
  206. </el-col>
  207. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  208. <el-form-item label="失效时间" prop="lostEfficacyTime" :rules="[{ required: true, message: '请选择失效时间', trigger: 'change' }]">
  209. <el-date-picker
  210. v-model="state.circularForm.lostEfficacyTime"
  211. type="datetime"
  212. placeholder="请选择失效时间"
  213. value-format="YYYY-MM-DD[T]HH:mm:ss"
  214. class="w100"
  215. />
  216. </el-form-item>
  217. </el-col>
  218. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  219. <el-form-item label="来源单位" prop="sourceOrgId" :rules="[{ required: true, message: '请选择来源单位', trigger: 'change' }]">
  220. <el-cascader
  221. :options="orgsOptions"
  222. filterable
  223. :props="{ value: 'id', label: 'name', emitPath: false, checkStrictly: true }"
  224. placeholder="请选择来源单位"
  225. class="w100"
  226. v-model="state.circularForm.sourceOrgId"
  227. ref="orgRef"
  228. @change="changeOrg('circularForm')"
  229. >
  230. </el-cascader>
  231. </el-form-item>
  232. </el-col>
  233. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  234. <el-form-item label="通知内容" prop="content" :rules="[{ required: true, message: '请输入通知内容', trigger: 'blur' }]">
  235. <editor v-model:get-html="state.circularForm.content" placeholder="请输入通知内容" height="450px" />
  236. </el-form-item>
  237. </el-col>
  238. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  239. <el-form-item label="通知对象" prop="circularType" :rules="[{ required: true, message: '请选择通知对象', trigger: 'change' }]">
  240. <el-select v-model="state.circularForm.circularType" placeholder="请选择通知对象" class="w100">
  241. <el-option v-for="item in circularTypeEnum" :value="item.key" :key="item.key" :label="item.value" />
  242. </el-select>
  243. </el-form-item>
  244. </el-col>
  245. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="state.circularForm.circularType === 1">
  246. <el-divider content-position="left">
  247. <span>选择通知人</span>
  248. </el-divider>
  249. <div class="flex-center-align mb10">
  250. <el-input v-model="state.searchContent" placeholder="请输入搜索内容" class="w100">
  251. <template #prefix>
  252. <SvgIcon name="ele-Search" />
  253. </template>
  254. </el-input>
  255. </div>
  256. <el-table :data="tables" @selection-change="handleSelectionChange" max-height="500" ref="multipleTableRef" row-key="id">
  257. <el-table-column type="selection" label="请选择" width="40" :reserve-selection="true" align="center"/>
  258. <el-table-column prop="name" label="姓名" show-overflow-tooltip width="170"></el-table-column>
  259. <el-table-column prop="userName" label="账号" show-overflow-tooltip width="170"></el-table-column>
  260. <el-table-column prop="organization.name" label="所属部门" show-overflow-tooltip width="190"></el-table-column>
  261. <el-table-column prop="staffNo" label="工号" show-overflow-tooltip width="120"></el-table-column>
  262. <el-table-column prop="organization.orgTypeText" label="部门类别" show-overflow-tooltip></el-table-column>
  263. <template #empty>
  264. <Empty />
  265. </template>
  266. </el-table>
  267. </el-col>
  268. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" v-if="state.circularForm.circularType === 2">
  269. <el-form-item label="选择部门" prop="org" :rules="[{ required: true, message: '请选择部门', trigger: 'change' }]">
  270. <el-tree-select
  271. :props="{ label: 'name' }"
  272. node-key="id"
  273. class="w100"
  274. ref="treeSelectRef"
  275. v-model="state.circularForm.org"
  276. :data="circularOrgOptions"
  277. multiple
  278. :render-after-expand="false"
  279. show-checkbox
  280. check-strictly
  281. default-expand-all
  282. filterable
  283. @check="selectOrg"
  284. collapse-tags
  285. collapse-tags-tooltip
  286. placeholder="请选择部门"
  287. />
  288. </el-form-item>
  289. </el-col>
  290. </el-row>
  291. </el-form>
  292. <el-form :model="state.bulletinForm" label-width="110px" ref="bulletinFormRef" v-if="state.processType === '新增公告'">
  293. <el-row :gutter="10">
  294. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  295. <el-form-item label="公告类型" prop="bulletinObj" :rules="[{ required: true, message: '请选择公告类型', trigger: 'change' }]">
  296. <el-select
  297. v-model="state.bulletinForm.bulletinObj"
  298. placeholder="请选择公告类型"
  299. value-key="dicDataValue"
  300. class="w100"
  301. @change="
  302. (e) => {
  303. state.bulletinForm.bulletinTypeId = e.dicDataValue;
  304. state.bulletinForm.bulletinTypeName = e.dicDataName;
  305. }
  306. "
  307. >
  308. <el-option v-for="item in bulletinTypeOptions" :value="item" :key="item.dicDataValue" :label="item.dicDataName" />
  309. </el-select>
  310. </el-form-item>
  311. </el-col>
  312. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  313. <el-form-item label="公告标题" prop="title" :rules="[{ required: true, message: '请输入公告标题', trigger: 'blur' }]">
  314. <el-input v-model="state.bulletinForm.title" placeholder="请输入公告标题" clearable show-word-limit maxlength="200"></el-input>
  315. </el-form-item>
  316. </el-col>
  317. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  318. <el-form-item label="失效时间" prop="loseEfficacyTime" :rules="[{ required: true, message: '请选择失效时间', trigger: 'change' }]">
  319. <el-date-picker
  320. v-model="state.bulletinForm.loseEfficacyTime"
  321. type="datetime"
  322. placeholder="请选择失效时间"
  323. value-format="YYYY-MM-DD[T]HH:mm:ss"
  324. class="w100"
  325. />
  326. </el-form-item>
  327. </el-col>
  328. <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12">
  329. <el-form-item label="来源单位" prop="sourceOrgId" :rules="[{ required: true, message: '请选择来源单位', trigger: 'change' }]">
  330. <el-cascader
  331. :options="orgsOptions"
  332. filterable
  333. :props="{ value: 'id', label: 'name', emitPath: false, checkStrictly: true }"
  334. placeholder="请选择来源单位"
  335. class="w100"
  336. v-model="state.bulletinForm.sourceOrgId"
  337. ref="orgRef"
  338. @change="changeOrg('bulletinForm')"
  339. >
  340. </el-cascader>
  341. </el-form-item>
  342. </el-col>
  343. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  344. <el-form-item label="公告范围" prop="pushRangesArray" :rules="[{ required: true, message: '请选择公告范围', trigger: 'change' }]">
  345. <el-checkbox-group v-model="state.bulletinForm.pushRangesArray">
  346. <el-checkbox :label="item" v-for="item in pushRangesOptions" :key="item.dicDataValue">{{ item.dicDataName }}</el-checkbox>
  347. </el-checkbox-group>
  348. </el-form-item>
  349. </el-col>
  350. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  351. <el-form-item label="公告内容" prop="content" :rules="[{ required: true, message: '请输入公告内容', trigger: 'blur' }]">
  352. <editor v-model:get-html="state.bulletinForm.content" placeholder="请输入公告内容" height="450px" />
  353. </el-form-item>
  354. </el-col>
  355. </el-row>
  356. </el-form>
  357. </div>
  358. <el-form :model="state.ruleForm" label-width="100px" ref="ruleFormRef" v-show="activeStep === 1">
  359. <el-row :gutter="10">
  360. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="!returnArr.includes(state.processType)">
  361. <el-form-item label="下一环节" prop="nextStepCode" :rules="[{ required: true, message: '请选择下一环节', trigger: 'change' }]">
  362. <el-select v-model="state.ruleForm.nextStepCode" placeholder="请选择下一环节" class="w100" @change="selectNextStep">
  363. <el-option v-for="item in state.nextStepOptions" :key="item.key" :label="item.value" :value="item.key" />
  364. </el-select>
  365. </el-form-item>
  366. </el-col>
  367. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="!returnArr.includes(state.processType)">
  368. <el-form-item label="处理人" prop="nextHandlers" :rules="[{ required: false, message: '请选择处理人', trigger: 'change' }]">
  369. <el-select
  370. v-model="state.ruleForm.nextHandlers"
  371. multiple
  372. filterable
  373. placeholder="请选择处理人"
  374. class="w100"
  375. @change="selectHandlers"
  376. value-key="key"
  377. clearable
  378. collapse-tags
  379. collapse-tags-tooltip
  380. >
  381. <el-option v-for="item in state.handlerOptions" :key="item.key" :label="item.value" :value="item" />
  382. </el-select>
  383. </el-form-item>
  384. </el-col>
  385. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="showMainHandler">
  386. <el-form-item label="主办" prop="nextMainHandler" :rules="[{ required: false, message: '请选择主办', trigger: 'change' }]">
  387. <el-select v-model="state.ruleForm.nextMainHandler" placeholder="请选择主办" class="w100" filterable>
  388. <el-option v-for="item in state.handlerMainOptions" :key="item.key" :label="item.value" :value="item.key" />
  389. </el-select>
  390. </el-form-item>
  391. </el-col>
  392. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  393. <el-form-item label="短信通知" prop="isSms">
  394. <el-checkbox v-model="state.ruleForm.isSms" label="短信通知" />
  395. </el-form-item>
  396. </el-col>
  397. <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  398. <el-form-item label="省延期申请" prop="applyDelayProvince">
  399. <el-checkbox v-model="state.ruleForm.applyDelayProvince" label="省延期申请" />
  400. </el-form-item>
  401. </el-col>-->
  402. <!-- 办理流程展示期满时间 -->
  403. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12" v-if="handelArr.includes(state.processType)">
  404. <el-form-item label="期满时间" prop="expiredTime" :rules="[{ required: true, message: '请选择期满时间', trigger: 'change' }]">
  405. <el-date-picker
  406. v-model="state.ruleForm.expiredTime"
  407. type="datetime"
  408. placeholder="请选择期满时间"
  409. value-format="YYYY-MM-DD[T]HH:mm:ss"
  410. class="w100"
  411. />
  412. </el-form-item>
  413. </el-col>
  414. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  415. <el-form-item label="发起会签" prop="isStartCountersign" :rules="[{ required: false, message: '请选择发起会签', trigger: 'change' }]">
  416. <el-switch v-model="state.ruleForm.isStartCountersign" inline-prompt active-text="是" inactive-text="否" :disabled="!showMainHandler" />
  417. </el-form-item>
  418. </el-col>
  419. <!-- 汇总节点需要输入 -->
  420. <template v-if="isCollect">
  421. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  422. <el-form-item label="办理人姓名" prop="realHandlerName" :rules="[{ required: true, message: '请填写办理人姓名', trigger: 'blur' }]">
  423. <el-input v-model="state.ruleForm.realHandlerName" placeholder="请填写办理人姓名" clearable> </el-input>
  424. </el-form-item>
  425. </el-col>
  426. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  427. <el-form-item label="办理人电话" prop="realHandlerPhone" :rules="[{ required: true, message: '请填写办理人电话', trigger: 'blur' }]">
  428. <el-input v-model="state.ruleForm.realHandlerPhone" placeholder="请填写办理人电话" clearable> </el-input>
  429. </el-form-item>
  430. </el-col>
  431. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  432. <el-form-item label="沟通方式" prop="realCommunicationMode" :rules="[{ required: true, message: '请选择沟通方式', trigger: 'change' }]">
  433. <el-select v-model="state.ruleForm.realCommunicationMode" placeholder="请选择沟通方式" class="w100">
  434. <el-option v-for="item in communicationModeOptions" :key="item.key" :label="item.value" :value="item.key" />
  435. </el-select>
  436. </el-form-item>
  437. </el-col>
  438. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  439. <el-form-item label="沟通时间" prop="realCommunicationTime" :rules="[{ required: true, message: '请选择沟通时间', trigger: 'change' }]">
  440. <el-date-picker
  441. v-model="state.ruleForm.realCommunicationTime"
  442. type="datetime"
  443. placeholder="请选择沟通时间"
  444. value-format="YYYY-MM-DD[T]HH:mm:ss"
  445. class="w100"
  446. />
  447. </el-form-item>
  448. </el-col>
  449. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  450. <el-form-item
  451. label="沟通地点"
  452. prop="realCommunicationAddress"
  453. :rules="[{ required: true, message: '请填写沟通地点', trigger: 'blur' }]"
  454. >
  455. <el-input v-model="state.ruleForm.realCommunicationAddress" placeholder="请填写沟通地点" clearable> </el-input>
  456. </el-form-item>
  457. </el-col>
  458. </template>
  459. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  460. <el-form-item
  461. :label="state.inputPlaceholder"
  462. prop="opinion"
  463. :rules="[{ required: true, message: `请填写${state.inputPlaceholder}`, trigger: 'blur' }]"
  464. >
  465. <common-advice
  466. @chooseAdvice="chooseAdvice"
  467. v-model="state.ruleForm.opinion"
  468. :placeholder="'请填写' + state.inputPlaceholder"
  469. :loading="state.loading"
  470. :commonEnum="commonEnum.OrderCirculation"
  471. />
  472. </el-form-item>
  473. </el-col>
  474. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  475. <el-form-item label="附件" prop="additions" :rules="[{ required: false, message: '请填写诉求内容', trigger: 'change' }]">
  476. <annex-list :name="state.annexName" ref="annexListRef" :businessId="state.orderDetail.id" :classify="state.classify" />
  477. </el-form-item>
  478. </el-col>
  479. </el-row>
  480. </el-form>
  481. <template #footer>
  482. <span class="dialog-footer">
  483. <el-button @click="closeDialog" class="default-button">取 消</el-button>
  484. <el-button
  485. class="default-button"
  486. @click="onPrevious"
  487. :loading="state.loading"
  488. v-if="activeStep === 1 && showStepsArr.includes(state.processType)"
  489. >上一步</el-button
  490. >
  491. <el-button
  492. class="default-button"
  493. @click="onNext"
  494. :loading="state.loading"
  495. v-if="activeStep === 0 && showStepsArr.includes(state.processType)"
  496. >下一步</el-button
  497. >
  498. <el-button
  499. type="primary"
  500. @click="onReject(ruleFormRef)"
  501. :loading="state.loading"
  502. v-if="activeStep === 1 && canReject"
  503. >驳 回</el-button
  504. >
  505. <el-button type="primary" @click="onSubmit(ruleFormRef)" :loading="state.loading" v-if="activeStep === 1">{{ canReject ? '同意' : '提交' }}</el-button>
  506. </span>
  507. </template>
  508. </el-dialog>
  509. </div>
  510. </template>
  511. <script setup lang="ts" name="processApproval">
  512. import {computed, defineAsyncComponent, nextTick, reactive, ref, watchEffect} from 'vue';
  513. import {ElMessage, ElMessageBox, FormInstance} from 'element-plus';
  514. import other from '/@/utils/other';
  515. import {formatDate} from '/@/utils/formatTime';
  516. import {useUserInfo} from '/@/stores/userInfo';
  517. import {storeToRefs} from 'pinia';
  518. import {commonEnum} from '/@/utils/constants';
  519. import {orderFlowParams, orderStartFlow} from '/@/api/business/order';
  520. import {workflowNext, workflowNextSteps, workflowPrevious, workflowRecall, workflowRecallParams, workflowRedoParams,workflowReject} from '/@/api/system/workflow';
  521. import {redoApply, redoBaseData} from '/@/api/business/redo';
  522. import {delayApply, delayCalcEndTime, workflowDelayParams ,delayBaseData} from '/@/api/business/delay';
  523. import {discernApply, screenBaseData, workflowDiscernParams} from '/@/api/business/discern';
  524. import {debounce} from '/@/utils/tools';
  525. import {bulletinAdd, bulletinAddBaseData, circularAdd, circularAddBaseData, getAllUsers, workflowBulletinParams, workflowCircularParams} from '/@/api/auxiliary/notice';
  526. import {getCanUseOrg} from '/@/api/system/user';
  527. import {KnowledgeAdd, KnowledgeAddStartFlowParams, KnowledgeDeleteStartFlowParams, KnowledgeDel, KnowledgeUpdate, KnowledgeUpdateStartFlowParams} from "/@/api/knowledge";
  528. // 引入组件
  529. const CommonAdvice = defineAsyncComponent(() => import('/@/components/CommonAdvice/index.vue')); // 常用意见
  530. const AnnexList = defineAsyncComponent(() => import('/@/components/AnnexList/index.vue')); // 附件列表
  531. const Editor = defineAsyncComponent(() => import('/@/components/Editor/index.vue')); // 富文本编辑器
  532. // 定义子组件向父组件传值/事件
  533. const emit = defineEmits(['orderProcessSuccess', 'orderProcessFailed']);
  534. // 定义变量内容
  535. const state = reactive<any>({
  536. dialogVisible: false, // 弹窗显示隐藏
  537. ruleForm: {
  538. //流程表单
  539. opinion: '', // 意见
  540. nextStepCode: '', // 下一节点
  541. nextStepName:'', // 下一节点名称
  542. backToCountersignEnd: false, // 是否回到会签结束节点
  543. nextHandlers: [], // 下一节点处理人
  544. nextMainHandler: '', // 主办人
  545. isSms: false, // 是否短信通知
  546. isStartCountersign: false, // 是否发起会签
  547. },
  548. delayForm: {
  549. //延期申请表单
  550. timeLimitCount: null, // 延期申请数量
  551. content: '', // 延期申请理由
  552. timeLimitUnit: '', // 延期申请单位
  553. },
  554. discernForm: {
  555. // 甄别表单
  556. content: '', // 甄别理由
  557. },
  558. redoForm: {
  559. // 重办表单
  560. content: '', // 重办理由
  561. },
  562. circularForm: {
  563. // 通知表单
  564. circularObj: '', // 通知类型
  565. circularTypeId: '', // 通知类型
  566. circularTypeName: '', // 通知类型
  567. title: '', // 通知标题
  568. isMustRead: false, // 必须阅读
  569. lostEfficacyTime: '', // 失效时间
  570. sourceOrgId: '', // 来源单位
  571. content: '', // 文档内容
  572. circularType: '', // 通知对象
  573. sourceOrg: [], // 来源单位
  574. org: [], // 通知对象 部门
  575. },
  576. searchContent: '', // 搜索内容
  577. bulletinForm: {
  578. // 公告表单
  579. bulletinObj: '', // 公告类型
  580. bulletinType: '', // 公告类型
  581. bulletinTypeName: '', // 公告类型
  582. title: '', // 公告标题
  583. loseEfficacyTime: '', // 失效时间
  584. sourceOrgId: '', // 来源单位
  585. pushRangesArray: [], // 公告范围
  586. content: '', // 文档内容
  587. sourceOrg: [], // 来源单位
  588. },
  589. nextStepOptions: [], // 下一节点
  590. handlerOptions: [], // 处理人
  591. transform: 'translate(0px, 0px)', // 滚动条位置
  592. fileList: [], // 附件列表
  593. loading: false, // 提交按钮loading
  594. processType: 'next', // 流程状态
  595. workflowId: '', // 流程id
  596. handlerClassifies: [], //撤回处理人
  597. handlerMainOptions: [], // 主办人
  598. handleId: '', // 流程处理ID
  599. dialogTitle: '', // 弹窗标题
  600. annexName: '', // 附件标题
  601. inputPlaceholder: '', // 意见提示
  602. orderDetail: {}, // 工单详情
  603. });
  604. const ruleFormRef = ref<RefType>(); //表单组件
  605. const storesUserInfo = useUserInfo();
  606. const { userInfos } = storeToRefs(storesUserInfo); // 用户信息
  607. const showStepsArr = ['延期申请', '甄别申请', '工单重办', '新增通知', '新增公告']; // 显示步骤条的流程
  608. const handelArr = ['工单办理', '甄别审批']; // 处于办理状态的流程 (如果是汇总节点 需要填写处理人等 办理流程才有期满时间)
  609. const returnArr = ['工单退回']; // 退回流程 (退回流程不需要展示其他 只需要填写意见和附件即可)
  610. const communicationModeOptions = ref<EmptyArrayType>([]); // 沟通方式
  611. const timeTypeOptions = ref<EmptyArrayType>([]); // 延期申请单位
  612. const orderRedoReasonOptions = ref<EmptyArrayType>([]); // 重办理由
  613. const screenTypeOptions = ref<EmptyArrayType>([]); // 甄别类型
  614. const bulletinTypeOptions = ref<EmptyArrayType>([]); // 公告类型
  615. const circularTypeOptions = ref<EmptyArrayType>([]); // 通知类型]
  616. const circularTypeEnum = ref<EmptyArrayType>([]); // 通知对象
  617. const pushRangesOptions = ref<EmptyArrayType>([]); // 公告范围
  618. const orgsOptions = ref<EmptyArrayType>([]); // 来源单位
  619. const circularOrgOptions = ref<EmptyArrayType>([]); // 通知对象 部门
  620. const userTables = ref<EmptyArrayType>([]); // 通知对象 个人
  621. const canReject = ref<boolean>(false); // 是否可以驳回
  622. const handleResult = (res: any) => {
  623. state.nextStepOptions = res.result.steps; //处理人选择内容
  624. canReject.value = res.result.canReject ?? false; // 是否可以驳回
  625. // state.handleId = res.result.id; //流程ID
  626. communicationModeOptions.value = res.result.communicationModeOptions ?? []; // 沟通方式
  627. if (handelArr.includes(state.processType)) {
  628. // 办理才有期满时间
  629. state.ruleForm.expiredTime = res.result.expiredTime ?? null; // 期满时间
  630. }
  631. if (state.nextStepOptions.length === 1) {
  632. // 下一节点是否只有一个 默认选中第一个
  633. state.ruleForm.nextStepCode = state.nextStepOptions[0].key; // 下一节点code
  634. state.ruleForm.nextStepName = state.nextStepOptions[0].value; // 下一节点name
  635. selectNextStep(state.nextStepOptions[0].key); // 查询流程下一节点参数
  636. isCollect.value = state.nextStepOptions[0].inputRealHandler // 需要填入其他参数
  637. state.ruleForm.backToCountersignEnd = state.nextStepOptions[0].backToCountersignEnd ?? false; // 是否回到会签结束节点
  638. } else {
  639. state.ruleForm.nextStepCode = '';
  640. state.ruleForm.nextStepName = '';
  641. isCollect.value = false;
  642. }
  643. };
  644. // 打开弹窗
  645. const openDialog = async (val: any) => {
  646. console.log(val);
  647. const { id, processType, extra, orderDetail } = val;
  648. state.ruleForm.workflowId = state.workflowId = id ?? ''; // 流程id
  649. state.processType = processType ?? '办理流程'; // 业务类型
  650. state.orderDetail = orderDetail ?? {}; // 工单详情
  651. const { dialogTitle, inputPlaceholder, annexName, classify } = extra ?? {};
  652. state.dialogTitle = dialogTitle ?? '提交流程'; // 流程标题
  653. state.annexName = annexName ?? '办理附件'; // 附件标题
  654. state.classify = classify ?? '办理上传'; // 附件分类
  655. state.inputPlaceholder = inputPlaceholder ?? '办理意见'; // 意见提示
  656. switch (state.processType) {
  657. case '工单发起': //开始流程
  658. const [orderStartWorkflowResponse] = await Promise.all([orderFlowParams()]); //获取开启流程参数
  659. handleResult(orderStartWorkflowResponse);
  660. break;
  661. case '工单撤回': // 撤回流程
  662. const [workflowRecallResponse] = await Promise.all([workflowRecallParams(state.workflowId)]); //获取开启流程参数
  663. handleResult(workflowRecallResponse);
  664. break;
  665. case '延期申请': // 延期申请
  666. const [workflowDelayResponse,responseDelay] = await Promise.all([workflowDelayParams(),delayBaseData()]); //获取开启流程参数
  667. timeTypeOptions.value = responseDelay.result?.timeType ?? []; // 延期时间单位
  668. handleResult(workflowDelayResponse);
  669. break;
  670. case '甄别申请': // 甄别申请
  671. const [workflowDiscernResponse, responseDiscern] = await Promise.all([workflowDiscernParams(), screenBaseData()]); //获取开启流程参数
  672. screenTypeOptions.value = responseDiscern.result?.screenType ?? []; // 甄别理由
  673. handleResult(workflowDiscernResponse);
  674. break;
  675. case '工单重办': // 工单重办
  676. const [workflowRedoResponse, responseRedo] = await Promise.all([workflowRedoParams(state.workflowId), redoBaseData()]); //获取开启流程参数
  677. orderRedoReasonOptions.value = responseRedo.result?.orderRedoReasonOptions ?? []; // 重办理由
  678. handleResult(workflowRedoResponse);
  679. break;
  680. case '工单退回': // 退回流程
  681. break;
  682. case '工单办理': // 工单办理
  683. const [workflowNextStepsResponse] = await Promise.all([workflowNextSteps(state.workflowId)]); // 获取下一节点和下一节点参数
  684. handleResult(workflowNextStepsResponse);
  685. break;
  686. case '新增通知':
  687. const [workflowCircularResponse, circularResponse, orgResponse,userResponse] = await Promise.all([
  688. workflowCircularParams(),
  689. circularAddBaseData(),
  690. getCanUseOrg(),
  691. getAllUsers()
  692. ]); // 新增通知开启流程参数
  693. circularTypeOptions.value = circularResponse.result?.circularType ?? [];
  694. orgsOptions.value = circularResponse.result?.orgsOptions ?? [];
  695. circularTypeEnum.value = circularResponse.result?.circularTypeEnum ?? [];
  696. circularOrgOptions.value = orgResponse.result ?? [];
  697. userTables.value = userResponse.result ?? [];
  698. handleResult(workflowCircularResponse);
  699. break;
  700. case '新增公告':
  701. const [workflowBulletinResponse, responseAnnounce] = await Promise.all([workflowBulletinParams(), bulletinAddBaseData()]); // 新增公告开启流程参数
  702. bulletinTypeOptions.value = responseAnnounce.result?.bulletinType ?? [];
  703. pushRangesOptions.value = responseAnnounce.result?.pushRanges ?? [];
  704. orgsOptions.value = responseAnnounce.result?.orgsOptions ?? [];
  705. handleResult(workflowBulletinResponse);
  706. break;
  707. case '新增知识':
  708. const [KnowledgeAddStartFlowResponse] = await Promise.all([KnowledgeAddStartFlowParams()]); // 知识库新增参数
  709. handleResult(KnowledgeAddStartFlowResponse);
  710. break;
  711. case '更新知识':
  712. const [KnowledgeUpdateResponse] = await Promise.all([KnowledgeUpdateStartFlowParams()]); // 知识库更新参数
  713. handleResult(KnowledgeUpdateResponse);
  714. break;
  715. case '删除知识':
  716. const [KnowledgeDeleteResponse] = await Promise.all([KnowledgeDeleteStartFlowParams()]); // 知识库删除参数
  717. handleResult(KnowledgeDeleteResponse);
  718. break;
  719. default: // 默认下一流程 工单办理
  720. // 获取下一节点和下一节点参数
  721. const [nextResponse] = await Promise.all([workflowNextSteps(state.workflowId)]);
  722. handleResult(nextResponse);
  723. break;
  724. }
  725. state.dialogVisible = true;
  726. await nextTick(() => {
  727. restForm(ruleFormRef.value);
  728. });
  729. };
  730. // 上一部
  731. const onPrevious = () => {
  732. activeStep.value = 0;
  733. };
  734. const delayFormRef = ref<RefType>(); //延期申请表单组件
  735. const discernFormRef = ref<RefType>(); //甄别申请表单组件
  736. const redoFormRef = ref<RefType>(); //重办表单组件
  737. const circularFormRef = ref<RefType>(); //通知表单组件
  738. const bulletinFormRef = ref<RefType>(); //公告表单组件
  739. // 下一步
  740. const onNext = () => {
  741. switch (state.processType) {
  742. case '延期申请':
  743. delayFormRef.value?.validate((valid: boolean) => {
  744. if (!valid) return;
  745. activeStep.value = 1;
  746. });
  747. break;
  748. case '甄别申请': // 甄别申请
  749. discernFormRef.value?.validate((valid: boolean) => {
  750. if (!valid) return;
  751. activeStep.value = 1;
  752. });
  753. break;
  754. case '工单重办':
  755. redoFormRef.value?.validate((valid: boolean) => {
  756. if (!valid) return;
  757. activeStep.value = 1;
  758. });
  759. break;
  760. case '新增通知':
  761. circularFormRef.value?.validate((valid: boolean) => {
  762. if (!valid) return;
  763. activeStep.value = 1;
  764. });
  765. break;
  766. case '新增公告':
  767. bulletinFormRef.value?.validate((valid: boolean) => {
  768. if (!valid) return;
  769. activeStep.value = 1;
  770. });
  771. break;
  772. default: // 默认下一流程
  773. activeStep.value = 1;
  774. break;
  775. }
  776. };
  777. const activeStep = ref(0); //步骤条
  778. watchEffect(() => {
  779. if (state.dialogVisible) {
  780. activeStep.value = showStepsArr.includes(state.processType) ? 0 : 1;
  781. }
  782. });
  783. // 流程选择下一环节
  784. const isCollect = ref(false); // 是否是汇总节点(汇总需要填入其他参数)
  785. const selectNextStep = (val: any) => {
  786. ruleFormRef.value?.resetFields('nextHandlers');
  787. ruleFormRef.value?.resetFields('nextMainHandler');
  788. const next = state.nextStepOptions.find((item: any) => item.key === val);
  789. const items = next.items; //获取下一节点
  790. state.ruleForm.nextStepName = next.value; // 下一节点name
  791. state.ruleForm.backToCountersignEnd = next.backToCountersignEnd ?? false; // 是否回到会签结束节点
  792. state.handlerOptions = items ?? [];
  793. isCollect.value = next.inputRealHandler; // 是否需要填入其他参数
  794. };
  795. // 选择处理人
  796. const selectHandlers = () => {
  797. ruleFormRef.value?.resetFields('nextMainHandler');
  798. if (state.ruleForm.nextHandlers.length > 1) {
  799. state.ruleForm.nextMainHandler = state.ruleForm.nextHandlers[0].key;
  800. }
  801. };
  802. const showMainHandler = computed(() => {
  803. return state.ruleForm.nextHandlers.length > 1;
  804. });
  805. // 主办从处理人中选择
  806. state.handlerMainOptions = computed(() => {
  807. return state.ruleForm.nextHandlers;
  808. });
  809. // 设置抽屉
  810. const dialogRef = ref<RefType>();
  811. const mouseup = () => {
  812. state.transform = dialogRef.value.dialogContentRef.$el.style.transform;
  813. };
  814. // 关闭弹窗
  815. const closeDialog = () => {
  816. state.dialogVisible = false;
  817. };
  818. // 重置表单方法
  819. const restForm = (formEl: FormInstance | undefined) => {
  820. if (!formEl) return;
  821. state.ruleForm.opinion = '';
  822. state.delayForm.endTime = '';
  823. formEl.resetFields();
  824. formEl.clearValidate();
  825. };
  826. // 选择常用意见 填入填写框 办理
  827. const chooseAdvice = (item: any) => {
  828. state.ruleForm.opinion += item.content;
  829. };
  830. // 选择常用意见 填入填写框 延期
  831. const chooseAdviceDelay = (item: any) => {
  832. state.delayForm.content += item.content;
  833. };
  834. // 计算期满时间
  835. const computeTime = debounce(() => {
  836. if (!state.delayForm.timeLimitCount || !state.delayForm.timeLimitUnit) return;
  837. let request = {
  838. delayNum: state.delayForm.timeLimitCount,
  839. delayUnit: state.delayForm.timeLimitUnit,
  840. beginTime: state.orderDetail.expiredTime,
  841. };
  842. state.loading = true;
  843. delayCalcEndTime(request)
  844. .then((res: any) => {
  845. state.delayForm.endTime = formatDate(res.result.endTime, 'YYYY-mm-dd HH:MM:SS');
  846. state.loading = false;
  847. })
  848. .catch(() => {
  849. state.delayForm.endTime = '';
  850. state.loading = false;
  851. });
  852. }, 300);
  853. // 选择常用意见 填入填写框 甄别
  854. const chooseAdviceDiscern = (item: any) => {
  855. state.discernForm.content += item.content;
  856. };
  857. // 选择常用意见 填入填写框 重办
  858. const chooseAdviceRedo = (item: any) => {
  859. state.redoForm.redoOpinion += item.content;
  860. };
  861. const orgRef = ref<RefType>(); //来源单位
  862. const changeOrg = (type: string) => {
  863. const currentNode = orgRef.value.getCheckedNodes();
  864. state[type].sourceOrgName = currentNode[0].label;
  865. };
  866. // 选择部门
  867. const treeSelectRef = ref<RefType>();
  868. const selectOrgArray = ref<EmptyArrayType>([]);
  869. const selectOrg = () => {
  870. selectOrgArray.value = treeSelectRef.value.getCheckedNodes();
  871. };
  872. const tables = computed(() => {
  873. // 模糊搜索
  874. if (!state.searchContent) return userTables.value;
  875. // filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
  876. // 注意: filter() 不会对空数组进行检测。
  877. // 注意: filter() 不会改变原始数组。
  878. return userTables.value.filter((data: any) => {
  879. // some() 方法用于检测数组中的元素是否满足指定条件;
  880. // some() 方法会依次执行数组的每个元素:
  881. // 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测;
  882. // 如果没有满足条件的元素,则返回false。
  883. // 注意: some() 不会对空数组进行检测。
  884. // 注意: some() 不会改变原始数组。
  885. return Object.keys(data).some((key) => {
  886. // indexOf() 返回某个指定的字符在某个字符串中首次出现的位置,如果没有找到就返回-1;
  887. // 该方法对大小写敏感!所以之前需要toLowerCase()方法将所有查询到内容变为小写。
  888. return String(data[key]).toLowerCase().indexOf(state.searchContent) > -1;
  889. });
  890. });
  891. });
  892. // 选择用户(账号)
  893. const multipleSelection = ref<any[]>([]); // 选中的数据
  894. const multipleTableRef = ref<RefType>(); // 表格ref
  895. const handleSelectionChange = (row: any) => {
  896. if (row) {
  897. multipleSelection.value = row;
  898. }
  899. };
  900. const afterSubmit = (emitType?: 'orderProcessSuccess' | 'orderProcessFailed', showMessage?: boolean) => {
  901. state.loading = false;
  902. closeDialog();
  903. if (showMessage) ElMessage.success('操作成功');
  904. if (emitType) emit(emitType);
  905. };
  906. const close = () => {
  907. restForm(ruleFormRef.value);
  908. restForm(delayFormRef.value);
  909. restForm(discernFormRef.value);
  910. restForm(redoFormRef.value);
  911. restForm(circularFormRef.value);
  912. restForm(bulletinFormRef.value);
  913. };
  914. // 提交
  915. const onSubmit = (formEl: FormInstance | undefined) => {
  916. if (!formEl) return;
  917. formEl.validate((valid: boolean) => {
  918. if (!valid) return;
  919. const isAuditText = canReject.value ? '同意' : '提交';
  920. ElMessageBox.confirm(`确认${isAuditText}?`, '提示', {
  921. confirmButtonText: '确认',
  922. cancelButtonText: '取消',
  923. type: 'warning',
  924. draggable: true,
  925. cancelButtonClass: 'default-button',
  926. autofocus: false,
  927. })
  928. .then(() => {
  929. state.loading = true;
  930. let submitObj = other.deepClone(state.ruleForm);
  931. if (submitObj.nextHandlers && submitObj.nextHandlers.length) {
  932. if (submitObj.nextHandlers.length === 1) {
  933. submitObj.nextMainHandler = submitObj.nextHandlers[0].key;
  934. }
  935. }
  936. submitObj.stepExpiredTime = submitObj.expiredTime; //节点过期时间
  937. switch (state.processType) {
  938. case '工单发起':
  939. const request = {
  940. data: { ...state.orderDetail },
  941. workflow: submitObj,
  942. };
  943. orderStartFlow(request)
  944. .then(() => {
  945. afterSubmit('orderProcessSuccess', true);
  946. })
  947. .catch(() => {
  948. afterSubmit('orderProcessFailed');
  949. });
  950. break;
  951. case '工单撤回':
  952. workflowRecall(submitObj)
  953. .then(() => {
  954. afterSubmit('orderProcessSuccess', true);
  955. })
  956. .catch(() => {
  957. afterSubmit('orderProcessFailed');
  958. });
  959. break;
  960. case '延期申请':
  961. const requestDelay = {
  962. data: {
  963. orderId: state.orderDetail.id,
  964. delayNum: state.delayForm.timeLimitCount,
  965. delayUnit: state.delayForm.timeLimitUnit,
  966. delayReason: state.delayForm.content,
  967. },
  968. workflow: submitObj,
  969. };
  970. delayApply(requestDelay)
  971. .then(() => {
  972. afterSubmit('orderProcessSuccess', true);
  973. })
  974. .catch(() => {
  975. afterSubmit('orderProcessFailed');
  976. });
  977. break;
  978. case '甄别申请':
  979. const requestDiscern = {
  980. data: {
  981. no: state.orderDetail.no,
  982. visitId: state.orderDetail.visitId,
  983. visitDetailId: state.orderDetail.visitDetailId,
  984. orderId: state.orderDetail.id,
  985. typeDicId: state.discernForm.type.dicDataValue,
  986. typeDicName: state.discernForm.type.dicDataName,
  987. content: state.discernForm.content,
  988. },
  989. workflow: submitObj,
  990. };
  991. discernApply(requestDiscern)
  992. .then(() => {
  993. afterSubmit('orderProcessSuccess', true);
  994. })
  995. .catch(() => {
  996. afterSubmit('orderProcessFailed');
  997. });
  998. break;
  999. case '工单重办':
  1000. const requestRedo = {
  1001. data: {
  1002. orderId: state.orderDetail.id,
  1003. orderRedoReason: state.redoForm.orderRedoReason,
  1004. redoOpinion: state.redoForm.redoOpinion,
  1005. },
  1006. workflow: submitObj,
  1007. };
  1008. redoApply(requestRedo)
  1009. .then(() => {
  1010. afterSubmit('orderProcessSuccess', true);
  1011. })
  1012. .catch(() => {
  1013. afterSubmit('orderProcessFailed');
  1014. });
  1015. break;
  1016. case '工单退回':
  1017. workflowPrevious(submitObj)
  1018. .then(() => {
  1019. afterSubmit('orderProcessSuccess', true);
  1020. })
  1021. .catch(() => {
  1022. afterSubmit('orderProcessFailed');
  1023. });
  1024. break;
  1025. case '工单办理': // 工单办理流程
  1026. workflowNext(submitObj)
  1027. .then(() => {
  1028. afterSubmit('orderProcessSuccess', true);
  1029. })
  1030. .catch(() => {
  1031. afterSubmit('orderProcessFailed');
  1032. });
  1033. break;
  1034. case '新增通知':
  1035. if(state.circularForm.circularType === 1 && !multipleSelection.value.length){
  1036. ElMessage.error('请选择通知人');
  1037. return;
  1038. }
  1039. let circularReadGroups:EmptyArrayType;
  1040. if(state.circularForm.circularType === 1){ //个人
  1041. circularReadGroups = multipleSelection.value.map((item:any) => {
  1042. return {
  1043. userId: item.id,
  1044. userName: item.name,
  1045. };
  1046. });
  1047. }else if(state.circularForm.circularType === 2){ // 部门
  1048. circularReadGroups = selectOrgArray.value.map((item:any) => {
  1049. return {
  1050. orgId: item.id,
  1051. orgName: item.name,
  1052. };
  1053. });
  1054. }
  1055. const circularRequest = {
  1056. data: { ...state.circularForm,circularReadGroups:circularReadGroups },
  1057. workflow: submitObj,
  1058. };
  1059. circularAdd(circularRequest)
  1060. .then(() => {
  1061. afterSubmit('orderProcessSuccess', true);
  1062. })
  1063. .catch(() => {
  1064. afterSubmit('orderProcessFailed');
  1065. });
  1066. break;
  1067. case '新增公告':
  1068. const pushRanges = state.bulletinForm.pushRangesArray.map((item: any) => {
  1069. return {
  1070. key: item.dicDataValue,
  1071. value: item.dicDataName,
  1072. };
  1073. });
  1074. const bulletinRequest = {
  1075. data: { ...state.bulletinForm, pushRanges },
  1076. workflow: submitObj,
  1077. };
  1078. bulletinAdd(bulletinRequest)
  1079. .then(() => {
  1080. afterSubmit('orderProcessSuccess', true);
  1081. })
  1082. .catch(() => {
  1083. afterSubmit('orderProcessFailed');
  1084. });
  1085. break;
  1086. case '新增知识':
  1087. const KnowledgeAddRequest = {
  1088. data: { ...state.orderDetail },
  1089. workflow: submitObj,
  1090. };
  1091. KnowledgeAdd(KnowledgeAddRequest)
  1092. .then(() => {
  1093. afterSubmit('orderProcessSuccess', true);
  1094. })
  1095. .catch(() => {
  1096. afterSubmit('orderProcessFailed');
  1097. });
  1098. break;
  1099. case '更新知识':
  1100. const KnowledgeUpdateRequest = {
  1101. data: { ...state.orderDetail },
  1102. workflow: submitObj,
  1103. };
  1104. KnowledgeUpdate(KnowledgeUpdateRequest)
  1105. .then(() => {
  1106. afterSubmit('orderProcessSuccess', true);
  1107. })
  1108. .catch(() => {
  1109. afterSubmit('orderProcessFailed');
  1110. });
  1111. break;
  1112. case '删除知识':
  1113. const KnowledgeRemoveRequest = {
  1114. data: { ...state.orderDetail },
  1115. workflow: submitObj,
  1116. };
  1117. KnowledgeDel(KnowledgeRemoveRequest)
  1118. .then(() => {
  1119. afterSubmit('orderProcessSuccess', true);
  1120. })
  1121. .catch(() => {
  1122. afterSubmit('orderProcessFailed');
  1123. });
  1124. break;
  1125. default: // 默认工单办理
  1126. workflowNext(submitObj)
  1127. .then(() => {
  1128. afterSubmit('orderProcessSuccess', true);
  1129. })
  1130. .catch(() => {
  1131. afterSubmit('orderProcessFailed');
  1132. });
  1133. break;
  1134. }
  1135. })
  1136. .catch(() => {});
  1137. });
  1138. };
  1139. // 否决
  1140. const onReject = (formEl: FormInstance | undefined) => {
  1141. if (!formEl) return;
  1142. formEl.validate((valid: boolean) => {
  1143. if (!valid) return;
  1144. ElMessageBox.confirm(`确认驳回?`, '提示', {
  1145. confirmButtonText: '确认',
  1146. cancelButtonText: '取消',
  1147. type: 'warning',
  1148. draggable: true,
  1149. cancelButtonClass: 'default-button',
  1150. autofocus: false,
  1151. })
  1152. .then(() => {
  1153. state.loading = true;
  1154. const request = {
  1155. opinion: state.ruleForm.opinion,
  1156. workflowId: state.workflowId,
  1157. }
  1158. workflowReject(request)
  1159. .then(() => {
  1160. afterSubmit('orderProcessSuccess', true);
  1161. })
  1162. .catch(() => {
  1163. afterSubmit('orderProcessFailed');
  1164. });
  1165. })
  1166. .catch(() => {});
  1167. });
  1168. };
  1169. // 暴露变量
  1170. defineExpose({
  1171. openDialog,
  1172. closeDialog,
  1173. });
  1174. </script>