Order-publish.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. <template>
  2. <el-dialog v-model="state.dialogVisible" draggable :title="dialogTitle" ref="dialogRef" append-to-body destroy-on-close @close="close">
  3. <div class="collapse-container">
  4. <el-form label-width="100px" ref="ruleFormRef" :model="state.ruleForm" v-loading="state.loading">
  5. <el-row :gutter="10" class="w100">
  6. <template v-if="isZGZFW">
  7. <el-divider content-position="left">
  8. <el-text tag="b" size="large"> 中国政府网 </el-text>
  9. </el-divider>
  10. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  11. <el-form-item label="是否公开" prop="proPublishState" :rules="[{ required: false, message: '请选择是否公开', trigger: 'change' }]">
  12. <el-radio-group v-model="state.ruleForm.proPublishState" :disabled="disabled">
  13. <el-radio :value="true">公开</el-radio>
  14. <el-radio :value="false">不公开</el-radio>
  15. </el-radio-group>
  16. </el-form-item>
  17. </el-col>
  18. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  19. <el-form-item label="反馈人电话" prop="feedBackPhone" :rules="[{ required: false, message: '请填写反馈人电话', trigger: 'blur' }]">
  20. <el-input placeholder="请填写反馈人电话" v-model="state.ruleForm.feedBackPhone" clearable :disabled="disabled"></el-input>
  21. </el-form-item>
  22. </el-col>
  23. <el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24" v-if="!state.ruleForm.proPublishState">
  24. <el-form-item label="不公开原因" prop="noPubReason" :rules="[{ required: true, message: '请填写不公开原因', trigger: 'blur' }]">
  25. <el-input
  26. type="textarea"
  27. placeholder="请填写不公开原因"
  28. :autosize="{ minRows: 6, maxRows: 10 }"
  29. v-model="state.ruleForm.noPubReason"
  30. :disabled="disabled"
  31. ></el-input>
  32. </el-form-item>
  33. </el-col>
  34. <el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24" v-if="state.ruleForm.proPublishState">
  35. <el-form-item label="答复口径" prop="answerContent" :rules="[{ required: true, message: '请填写答复口径', trigger: 'blur' }]">
  36. <el-input
  37. type="textarea"
  38. placeholder="请填写答复口径"
  39. :autosize="{ minRows: 6, maxRows: 10 }"
  40. v-model="state.ruleForm.answerContent"
  41. :disabled="disabled"
  42. ></el-input>
  43. </el-form-item>
  44. </el-col>
  45. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  46. <el-form-item label="是否联系" prop="isContact" :rules="[{ required: true, message: '请选择是否联系', trigger: 'change' }]">
  47. <el-radio-group v-model="state.ruleForm.isContact" :disabled="disabled">
  48. <el-radio :value="true">是</el-radio>
  49. <el-radio :value="false">否</el-radio>
  50. </el-radio-group>
  51. </el-form-item>
  52. </el-col>
  53. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  54. <el-form-item label="是否评价" prop="isVisited" :rules="[{ required: true, message: '请选择是否评价', trigger: 'change' }]">
  55. <el-radio-group v-model="state.ruleForm.isVisited" :disabled="disabled">
  56. <el-radio :value="true">是</el-radio>
  57. <el-radio :value="false">否</el-radio>
  58. </el-radio-group>
  59. </el-form-item>
  60. </el-col>
  61. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  62. <el-form-item
  63. label="网民评价"
  64. prop="netizen"
  65. :rules="[{ required: state.ruleForm.isVisited, message: '请选择网民评价', trigger: 'change' }]"
  66. >
  67. <el-radio-group v-model="state.ruleForm.netizen" :disabled="disabled">
  68. <el-radio :value="item.key" v-for="item in netizenEvaluateType" :key="item.key">{{ item.value }}</el-radio>
  69. </el-radio-group>
  70. </el-form-item>
  71. </el-col>
  72. <el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24">
  73. <el-form-item
  74. label="评价内容"
  75. prop="evaluateContent"
  76. :rules="[{ required: state.ruleForm.netizen === '0' && state.ruleForm.isVisited, message: '请填写评价内容', trigger: 'blur' }]"
  77. >
  78. <el-input
  79. type="textarea"
  80. placeholder="请填写评价内容"
  81. :autosize="{ minRows: 6, maxRows: 10 }"
  82. v-model="state.ruleForm.evaluateContent"
  83. :disabled="disabled"
  84. ></el-input>
  85. </el-form-item>
  86. </el-col>
  87. <el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24">
  88. <el-form-item label="备注" prop="remark" :rules="[{ required: false, message: '请填写备注', trigger: 'blur' }]">
  89. <el-input
  90. type="textarea"
  91. placeholder="请填写备注"
  92. :autosize="{ minRows: 6, maxRows: 10 }"
  93. v-model="state.ruleForm.remark"
  94. :disabled="disabled"
  95. ></el-input>
  96. </el-form-item>
  97. </el-col>
  98. </template>
  99. <el-divider content-position="left">
  100. <el-text tag="b" size="large"> 市工单发布内容 </el-text>
  101. </el-divider>
  102. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  103. <el-form-item label="工单标题"> {{ state.publishDetail.orderTitle }} </el-form-item>
  104. </el-col>
  105. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  106. <el-form-item label="整改后标题" prop="arrangeTitle" :rules="[{ required: false, message: '请填写整改后标题', trigger: 'blur' }]">
  107. <el-input placeholder="请填写整改后标题" v-model="state.ruleForm.arrangeTitle" clearable :disabled="disabled"></el-input>
  108. </el-form-item>
  109. </el-col>
  110. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  111. <el-form-item label="工单内容" class="formatted-text"> {{ state.publishDetail.content }} </el-form-item>
  112. </el-col>
  113. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  114. <el-form-item label="整改后内容" prop="arrangeContent" :rules="[{ required: false, message: '请填写整改后内容', trigger: 'blur' }]">
  115. <el-input
  116. placeholder="请填写整改后内容"
  117. type="textarea"
  118. :autosize="{ minRows: 6, maxRows: 10 }"
  119. v-model="state.ruleForm.arrangeContent"
  120. :disabled="disabled"
  121. show-word-limit
  122. :maxlength="5000"
  123. ></el-input>
  124. </el-form-item>
  125. </el-col>
  126. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  127. <el-form-item label="办理结果" class="formatted-text"> {{ state.publishDetail.actualOpinion }}</el-form-item>
  128. </el-col>
  129. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  130. <el-form-item label="整改后结果" prop="arrangeOpinion" :rules="[{ required: false, message: '请填写整改后内容', trigger: 'blur' }]">
  131. <el-input
  132. type="textarea"
  133. :placeholder="arrangeOpinionPlaceholder"
  134. :autosize="{ minRows: 6, maxRows: 10 }"
  135. v-model="state.ruleForm.arrangeOpinion"
  136. :disabled="disabled"
  137. show-word-limit
  138. :maxlength="arrangeOpinionMaxLength"
  139. ></el-input>
  140. </el-form-item>
  141. </el-col>
  142. <!-- 省工单是否可以选择意愿是否公开 -->
  143. <el-col v-if="isProvincePublic">
  144. <el-form-item label="诉求人意愿是否公开" label-width="140px">
  145. {{ state.publishDetail.isPublic ? '是' : '否' }}
  146. </el-form-item>
  147. </el-col>
  148. <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  149. <el-form-item label="是否公开" prop="publishState">
  150. <el-radio-group v-model="state.ruleForm.publishState" :disabled="publishDisabled" @change="selectPublishState">
  151. <el-radio :value="false">否</el-radio>
  152. <el-radio :value="true">是</el-radio>
  153. </el-radio-group>
  154. </el-form-item>
  155. </el-col>
  156. <!-- 省工单是否可以选择意愿是否公开 -->
  157. <template v-if="isProvincePublic">
  158. <el-col v-if="!state.ruleForm.publishState">
  159. <el-form-item label="不公开理由" prop="noPubReason" :rules="[{ required: true, message: '请填写不公开理由', trigger: 'blur' }]">
  160. <el-input
  161. type="textarea"
  162. placeholder="请填写不公开理由"
  163. :autosize="{ minRows: 6, maxRows: 10 }"
  164. v-model="state.ruleForm.noPubReason"
  165. :disabled="disabled"
  166. ></el-input>
  167. </el-form-item>
  168. </el-col>
  169. <el-col v-if="state.ruleForm.publishState">
  170. <el-form-item label="" prop="isOpenReview" :rules="[{ required: true, message: '请填写不公开理由', trigger: 'blur' }]">
  171. <el-checkbox v-model="state.ruleForm.isOpenReview" disabled>已开展保密审查</el-checkbox>
  172. </el-form-item>
  173. </el-col>
  174. </template>
  175. <!-- 工单标记 随手拍特殊需求 发布时必填 -->
  176. <el-col v-if="isSnapshot">
  177. <el-form-item label="工单标记" prop="snapshotLabel" :rules="[{ required: true, message: '请选择工单标记', trigger: 'change' }]">
  178. <el-select
  179. v-model="state.ruleForm.snapshotLabel"
  180. multiple
  181. collapse-tags
  182. collapse-tags-tooltip
  183. :max-collapse-tags="5"
  184. placeholder="请选择工单标记"
  185. value-key="dicDataValue"
  186. clearable
  187. @change="handleSnapshotLabel"
  188. >
  189. <el-option
  190. v-for="item in snapshotLabel"
  191. :key="item.dicDataValue"
  192. :label="item.dicDataName"
  193. :value="item"
  194. :disabled="disabled"
  195. class="w100"
  196. />
  197. </el-select>
  198. </el-form-item>
  199. </el-col>
  200. <!-- <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
  201. <el-form-item label="处理结果" prop="resolve" :rules="[{ required: true, message: '请选择处理结果', trigger: 'change' }]">
  202. <el-radio-group v-model="state.ruleForm.resolve" :disabled="disabled">
  203. <el-radio :value="true">已得到解决</el-radio>
  204. <el-radio :value="false">未得到解决</el-radio>
  205. </el-radio-group>
  206. </el-form-item>
  207. </el-col>-->
  208. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
  209. <el-form-item label="实际办理部门">
  210. {{ state.publishDetail.actualHandleOrgName?.value }}
  211. </el-form-item>
  212. </el-col>
  213. <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" v-if="idNamesArray.length">
  214. <el-form-item label="需回访部门" prop="idNames" :rules="[{ required: false, message: '请选择需回访部门', trigger: 'blur' }]">
  215. <el-checkbox-group v-model="state.ruleForm.idNames" :disabled="disabled">
  216. <el-checkbox :value="item" v-for="item in idNamesArray" :key="item.key">{{ item.value }}</el-checkbox>
  217. </el-checkbox-group>
  218. </el-form-item>
  219. </el-col>
  220. </el-row>
  221. </el-form>
  222. </div>
  223. <template #footer v-if="!disabled">
  224. <span class="dialog-footer">
  225. <el-button @click="closeDialog" class="default-button" :loading="state.loading">取 消</el-button>
  226. <el-button type="primary" @click="onReturn" title="业务信件退回" v-auth="'business:publish:return'" :loading="state.loading">
  227. 退回
  228. </el-button>
  229. <el-button
  230. type="primary"
  231. @click="onRedo"
  232. title="业务信件重办"
  233. v-auth="'business:publish:redo'"
  234. :loading="state.loading"
  235. v-if="['ZiGong', 'LuZhou'].includes(themeConfig.appScope)"
  236. >
  237. 重办
  238. </el-button>
  239. <el-button type="primary" @click="onPublish(ruleFormRef)" v-if="!disabled" :loading="state.loading">发布</el-button>
  240. </span>
  241. </template>
  242. </el-dialog>
  243. <!-- 工单退回 -->
  244. <order-publish-return ref="orderPublishReturnRef" @updateList="updateList" />
  245. <order-publish-redo ref="orderPublishRedoRef" @updateList="updateList" />
  246. </template>
  247. <script setup lang="ts" name="orderPublishDetail">
  248. import { computed, reactive, ref, defineAsyncComponent } from 'vue';
  249. import { ElMessage, FormInstance } from 'element-plus';
  250. import { baseData, publishOrderDetail } from '@/api/business/publish';
  251. import { publishOrder } from '@/api/todo/publish';
  252. import { useThemeConfig } from '@/stores/themeConfig';
  253. import { storeToRefs } from 'pinia';
  254. import { useAppConfig } from '@/stores/appConfig';
  255. const OrderPublishReturn = defineAsyncComponent(() => import('@/views/business/publish/components/Order-publish-return.vue')); // 工单退回
  256. const OrderPublishRedo = defineAsyncComponent(() => import('@/views/business/publish/components/Order-publish-redo.vue')); // 工单重办
  257. // 定义子组件向父组件传值/事件
  258. const emit = defineEmits(['updateList']);
  259. // 定义变量内容
  260. const state = reactive<any>({
  261. dialogVisible: false, // 是否显示弹窗
  262. loading: false, // 是否显示加载
  263. ruleForm: {
  264. proPublishState: false, // 是否公开
  265. isContact: true, // 是否联系
  266. isVisited: true, // 是否评价
  267. feedBackPhone: '', // 反馈人电话
  268. noPubReason: '', // 不公开原因
  269. answerContent: '', // 答复口径
  270. arrangeContent: '', // 整改后内容
  271. arrangeOpinion: '', // 整改后结果
  272. idNames: [], // 需回访部门
  273. publishState: false, // 门户是否公开
  274. resolve: null, // 处理结果
  275. snapshotLabel: [],
  276. isOpenReview: null, // 是否开展保密审查
  277. },
  278. orderDetail: {}, // 工单详情
  279. publishDetail: {}, // 发布详情
  280. });
  281. const ruleFormRef = ref<RefType>(); // 表单ref
  282. const idNamesArray = ref<EmptyArrayType>([]); // 部门列表
  283. const disabled = ref<boolean>(false); //是否查看详情
  284. const dialogTitle = ref<string>('发布详情'); // 弹窗标题
  285. const netizenEvaluateType = ref<EmptyArrayType>([]);
  286. const storesThemeConfig = useThemeConfig();
  287. const { themeConfig } = storeToRefs(storesThemeConfig);
  288. /*
  289. * @param row 工单详情
  290. * @param isDisabled 是否查看详情
  291. * @description 打开弹窗
  292. * */
  293. const isSnapshot = ref<boolean>(false); // 是否是随手拍
  294. const snapshotLabel = ref<EmptyArrayType>([]); // 工单标记多选框
  295. const publishDisabled = ref<boolean>(false); // 是否公开禁用
  296. const isProvincePublic = ref<boolean>(false); // 省工单是否可以选择意愿是否公开
  297. const openDialog = async (row: any, isDisabled: boolean = false) => {
  298. disabled.value = isDisabled;
  299. state.loading = true;
  300. state.dialogVisible = true;
  301. try {
  302. if (isDisabled) {
  303. state.orderDetail = row.order ?? {};
  304. const [response, res] = await Promise.all([publishOrderDetail(row.id), baseData(state.orderDetail.id)]);
  305. state.ruleForm = response.result ?? {};
  306. isSnapshot.value = response.result.isSnapshot ?? false;
  307. snapshotLabel.value = res.result?.snapshotLabel ?? [];
  308. state.ruleForm.netizen = response.result?.netizenEvaluate?.key;
  309. state.publishDetail = res.result ?? {};
  310. idNamesArray.value = res.result?.idNames ?? [];
  311. netizenEvaluateType.value = res.result?.netizenEvaluateType ?? [];
  312. dialogTitle.value = '发布详情';
  313. state.loading = false;
  314. } else {
  315. state.orderDetail = row ?? {};
  316. const res = await baseData(state.orderDetail.id);
  317. state.publishDetail = res.result ?? {};
  318. isSnapshot.value = res.result.isSnapshot ?? false;
  319. snapshotLabel.value = res.result?.snapshotLabel ?? [];
  320. state.ruleForm.arrangeTitle = state.publishDetail.orderTitle;
  321. state.ruleForm.arrangeContent = state.publishDetail.content;
  322. state.ruleForm.arrangeOpinion = state.publishDetail.actualOpinion;
  323. idNamesArray.value = res.result?.idNames ?? [];
  324. netizenEvaluateType.value = res.result?.netizenEvaluateType ?? [];
  325. dialogTitle.value = '工单发布';
  326. isProvincePublic.value = res.result?.isProvincePublic;
  327. publishDisabled.value = res.result?.isProvincePublic === false; // 诉求人意愿是否公开 否 禁用是否公开按钮
  328. state.loading = false;
  329. state.dialogVisible = true;
  330. }
  331. } catch (e) {
  332. console.log(e);
  333. state.loading = false;
  334. }
  335. };
  336. // 中国政府网特殊字段
  337. const isZGZFW = computed(() => {
  338. return state.orderDetail.receiveProvinceNo?.includes('ZGZFW');
  339. });
  340. // 选择是否公开
  341. const selectPublishState = (val: any) => {
  342. state.ruleForm.isOpenReview = !!val;
  343. // 如果选了否需要吧不公开理由清空
  344. if (!val) {
  345. state.ruleForm.noPubReason = null;
  346. }
  347. };
  348. // 关闭弹窗
  349. const closeDialog = () => {
  350. state.dialogVisible = false;
  351. };
  352. const close = () => {
  353. ruleFormRef.value.clearValidate();
  354. ruleFormRef.value.resetFields();
  355. };
  356. // 选择工单标记、
  357. const handleSnapshotLabel = (val: any) => {
  358. state.ruleForm.snapshotLabels = val.map((item: any) => {
  359. return {
  360. key: item.dicDataValue,
  361. value: item.dicDataName,
  362. };
  363. });
  364. };
  365. // 发布
  366. const onPublish = (formEl: FormInstance | undefined) => {
  367. if (!formEl) return;
  368. formEl.validate((valid: boolean) => {
  369. if (!valid) return;
  370. state.loading = true;
  371. let idNames: EmptyArrayType;
  372. state.ruleForm.netizenEvaluate = netizenEvaluateType.value.find((item) => item.key === state.ruleForm.netizen);
  373. if (state.ruleForm.idNames.length > 0) {
  374. // 如果选择了部门
  375. idNames = [...state.ruleForm.idNames];
  376. } else {
  377. idNames = [{ key: state.publishDetail.actualHandleOrgName?.key, value: state.publishDetail.actualHandleOrgName?.value }];
  378. }
  379. const request = {
  380. ...state.ruleForm,
  381. idNames,
  382. id: state.orderDetail.id,
  383. };
  384. publishOrder(request)
  385. .then(() => {
  386. ElMessage.success('发布成功');
  387. state.loading = false;
  388. closeDialog();
  389. emit('updateList');
  390. })
  391. .catch(() => {
  392. state.loading = false;
  393. });
  394. });
  395. };
  396. // 退回
  397. const orderPublishReturnRef = ref<RefType>(); // 工单退回ref
  398. const onReturn = () => {
  399. orderPublishReturnRef.value.openDialog(state.orderDetail);
  400. };
  401. // 重办
  402. const orderPublishRedoRef = ref<RefType>();
  403. const onRedo = () => {
  404. orderPublishRedoRef.value.openDialog(state.orderDetail);
  405. };
  406. // 重办和退回成功
  407. const updateList = () => {
  408. closeDialog();
  409. emit('updateList');
  410. };
  411. const appConfigStore = useAppConfig();
  412. const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
  413. // 限制 *国办工单FINISH_NOTE超出一千字
  414. const arrangeOpinionMaxLength = computed(() => {
  415. if (state.orderDetail.receiveProvinceNo?.includes('GJZWFWPT')) {
  416. return AppConfigInfo.value.nationalPlatformWordLimit;
  417. } else {
  418. return 5000;
  419. }
  420. });
  421. // 提示
  422. const arrangeOpinionPlaceholder = computed(() => {
  423. if (state.orderDetail.receiveProvinceNo?.includes('GJZWFWPT')) {
  424. return `请填写整改后办件结果(国家政务服务平台不超过${AppConfigInfo.value.nationalPlatformWordLimit}字)`;
  425. } else {
  426. return '请填写整改后办件结果';
  427. }
  428. });
  429. defineExpose({
  430. openDialog,
  431. closeDialog,
  432. });
  433. </script>