Pārlūkot izejas kodu

refactor:551 市州通用-支持异步处理批量延期申请

zhangchong 4 dienas atpakaļ
vecāks
revīzija
9de6f3bef9

+ 44 - 0
src/api/todo/delay.ts

@@ -15,6 +15,28 @@ export const delayList = (params: object) => {
 		params,
 	});
 };
+/**
+ * @description 查询延期待审批
+ * @param {object} params
+ */
+export const delayApprovalList = (params: object) => {
+	return request({
+		url: `/api/v1/OrderDelay/waited`,
+		method: 'get',
+		params,
+	});
+};
+/**
+ * @description 查询延期待审批总数
+ * @param {object} params
+ */
+export const delayApprovalCount = (params: object) => {
+	return request({
+		url: `/api/v1/OrderDelay/waited/count`,
+		method: 'get',
+		params,
+	});
+};
 /**
  * @description 延期工单待办列表导出
  * @param {object} data
@@ -32,3 +54,25 @@ export const waitDelayListExport = (data: object) => {
 		}
 	);
 };
+/**
+ * @description 延期审批 单个
+ * @param {object} data
+ */
+export const delayApproval = (data: object) => {
+	return request({
+		url: `/api/v1/OrderDelay/review`,
+		method: 'post',
+		data,
+	});
+};
+/**
+ * @description 延期审批批量
+ * @param {object} data
+ */
+export const delayApprovalBatch = (data: object) => {
+	return request({
+		url: `/api/v1/OrderDelay/batch-review`,
+		method: 'post',
+		data,
+	});
+};

+ 25 - 10
src/views/business/delay/audit.vue

@@ -51,12 +51,17 @@
 					@checkbox-change="selectChangeEvent"
 					auto-resize
 					show-overflow
-					:print-config="{}"
 					:scrollY="{ enabled: true, gt: 100 }"
 					id="businessDelayAudit"
 					:custom-config="{
 						storage: true,
 					}"
+					:checkboxConfig="{
+						checkMethod: ({ row }) => {
+							// 批量审批中不可选中
+							return row.delayState !== 9;
+						},
+					}"
 					showHeaderOverflow
 					:params="{ exportMethod: waitDelayListExport, exportParams: requestParams }"
 				>
@@ -260,7 +265,7 @@
 import { computed, defineAsyncComponent, onMounted, reactive, ref } from 'vue';
 import { FormInstance } from 'element-plus';
 import { formatDate } from '@/utils/formatTime';
-import { delayList, waitDelayListExport } from '@/api/todo/delay';
+import { delayApprovalCount, delayApprovalList, waitDelayListExport } from '@/api/todo/delay';
 import { orderBaseData } from '@/api/business/order';
 import Other from '@/utils/other';
 import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
@@ -278,7 +283,7 @@ const state = reactive<any>({
 		PageIndex: 1,
 		PageSize: 20,
 		IsApply: 'false', // 待办/已办
-		No:null, // 工单编码
+		No: null, // 工单编码
 		Title: null, // 工单标题
 		IsProvince: null, // 是否省工单
 		Channel: null, // 来源渠道
@@ -291,11 +296,11 @@ const state = reactive<any>({
 		OrgLevelOneName: null, // 一级部门
 		CurrentHandleOrgName: null, // 接办部门
 		jbTime: [], // 接办时间
-		CurrentHandleTimeStart:null, // 接办时间开始
-		CurrentHandleTimeEnd:null, // 接办时间结束
+		CurrentHandleTimeStart: null, // 接办时间开始
+		CurrentHandleTimeEnd: null, // 接办时间结束
 		sqTime: [], // 延期申请时间
-		ApplyTimeStart : null, // 延期申请时间开始
-		ApplyTimeEnd : null, // 延期申请时间结束
+		ApplyTimeStart: null, // 延期申请时间开始
+		ApplyTimeEnd: null, // 延期申请时间结束
 		ApplyName: null, // 延期申请人
 		ApplyOrgName: null, // 延期申请部门
 		DelayNum: null, // 延期申请时限
@@ -336,10 +341,9 @@ const queryList = () => {
 	requestParams.value.BeforeDelayStart = state.queryParams.sqqTime === null ? null : state.queryParams.sqqTime[0]; // 申请前期满时间
 	requestParams.value.BeforeDelayEnd = state.queryParams.sqqTime === null ? null : state.queryParams.sqqTime[1];
 	Reflect.deleteProperty(requestParams.value, 'sqqTime'); // 删除无用的参数
-	delayList(requestParams.value)
+	delayApprovalList(requestParams.value)
 		.then((res: any) => {
-			state.tableData = res.result?.items ?? [];
-			state.total = res.result?.total ?? 0;
+			state.tableData = res.result;
 			tableRef.value.clearCheckboxRow();
 			checkTable.value = [];
 			state.loading = false;
@@ -350,9 +354,18 @@ const queryList = () => {
 			state.loading = false;
 		});
 };
+// 查询总数
+const getTotal = () => {
+	delayApprovalCount(requestParams.value)
+		.then((res) => {
+			state.total = res.result ?? 0;
+		})
+		.catch(() => {});
+};
 // 切换tab 查询列表
 const handleClick = () => {
 	handleQuery();
+	getTotal();
 };
 /** 重置按钮操作 */
 const drawerRuleFormRef = ref();
@@ -363,6 +376,7 @@ const resetQuery = (formEl: FormInstance | undefined) => {
 	formEl.resetFields();
 	ruleFormRef.value?.resetFields();
 	queryList();
+	getTotal();
 };
 // 延期详情
 const delayDetailRef = ref<RefType>();
@@ -416,6 +430,7 @@ const getBaseData = async () => {
 const tableRef = ref<RefType>();
 onMounted(() => {
 	queryList();
+	getTotal();
 	if (tableRef.value && toolbarRef.value) {
 		tableRef.value.connect(toolbarRef.value);
 	}

+ 12 - 16
src/views/business/delay/components/Delay-audit-batch.vue

@@ -409,8 +409,9 @@ import { useUserInfo } from '@/stores/userInfo';
 import { storeToRefs } from 'pinia';
 import { commonEnum } from '@/utils/constants';
 import { orderAssignParams, orderTimeConfig } from '@/api/business/order';
-import { delayApproveParams, delayBatchApprove } from '@/api/business/delay';
+import { delayApproveParams } from '@/api/business/delay';
 import { useAppConfig } from '@/stores/appConfig';
+import { delayApprovalBatch } from '@/api/todo/delay';
 
 // 引入组件
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
@@ -471,9 +472,8 @@ const appConfigStore = useAppConfig();
 const { AppConfigInfo } = storeToRefs(appConfigStore); // 系统配置信息
 
 // 打开弹窗
-const delayId = ref<EmptyArrayType>([]);
+const delayWithStepIds = ref<EmptyArrayType>([]);
 const openDialog = async (val: any) => {
-	console.log(val);
 	selectNext.value = {};
 	currentParams.value = {};
 	state.ruleForm.nextHandlers = [];
@@ -483,7 +483,12 @@ const openDialog = async (val: any) => {
 	state.loading = true;
 	state.dialogVisible = true;
 	try {
-		delayId.value = val.map((item: any) => item.id);
+		delayWithStepIds.value = val.map((item: any) => {
+			return {
+				stepId: item.stepId,
+				delayId: item.id,
+			};
+		});
 		state.ruleForm.workflowId = state.workflowId = val[0].workflowId ?? ''; // 流程id 默认取第一个
 		state.orderDetail = val[0].order ?? {}; // 工单详情
 
@@ -612,9 +617,7 @@ const countersignDisabled = computed(() => {
 	return !(state.ruleForm.nextHandlers.length === 1);
 });
 // 是否发起会签
-const changeStartCountersign = () => {
-
-};
+const changeStartCountersign = () => {};
 
 // 是否展示办理对象 (结束节点不展示: next.stepType===2 表示为结束节点,下一环节为派单组时 next.businessType === 1,办理对象下拉框隐藏:AppConfigInfo.value.isAverageSendOrder= true 表示开启了平均派单 )
 const showHandlers = computed(() => {
@@ -877,21 +880,14 @@ const onSubmit = (formEl: FormInstance | undefined) => {
 		}
 		const request = {
 			nextWorkflow: submitObj,
-			// files: handleFiles.value,
-			delayId: delayId.value,
+			delayWithStepIds: delayWithStepIds.value,
 			isPass: state.ruleForm.isPass,
 		};
-		delayBatchApprove(request)
+		delayApprovalBatch(request)
 			.then((res: any) => {
 				emit('updateList');
 				state.loading = false;
 				closeDialog();
-				ElNotification({
-					title: '提示',
-					type: 'info',
-					dangerouslyUseHTMLString: true, // 允许使用 HTML 内容
-					message: res.result,
-				});
 			})
 			.catch((err: any) => {
 				console.log(err, 'err');

+ 7 - 6
src/views/business/delay/components/Delay-audit.vue

@@ -157,7 +157,8 @@ import { commonEnum } from '@/utils/constants';
 import { useAppConfig } from '@/stores/appConfig';
 import { storeToRefs } from 'pinia';
 import other from '@/utils/other';
-import { delayApproveModify, delayApproveParams, delayBatchApprove, delayDetail } from '@/api/business/delay';
+import { delayApproveModify, delayApproveParams, delayDetail } from '@/api/business/delay';
+import { delayApproval } from '@/api/todo/delay';
 
 const AnnexList = defineAsyncComponent(() => import('@/components/AnnexList/index.vue')); // 附件列表
 const CommonAdvice = defineAsyncComponent(() => import('@/components/CommonAdvice/index.vue')); // 常用意见
@@ -366,14 +367,14 @@ const onSubmit = (formEl: FormInstance | undefined) => {
 		if (!valid) return;
 		state.loading = true;
 		let submitObj = other.deepClone(state.ruleForm);
-
 		const request = {
-			nextWorkflow: submitObj,
-			files: handleFiles.value,
-			delayId: [currentRow.value.id],
+			nextWorkflow: {
+				...submitObj,
+				files: handleFiles.value,
+			},
 			isPass: state.ruleForm.isPass,
 		};
-		delayBatchApprove(request)
+		delayApproval(request)
 			.then(() => {
 				afterSubmit('updateList', true);
 			})

+ 0 - 1
src/views/business/delay/index.vue

@@ -56,7 +56,6 @@
 					height="auto"
 					auto-resize
 					show-overflow
-					:print-config="{}"
 					:scrollY="{ enabled: true, gt: 100 }"
 					id="orderDelay"
 					:custom-config="{

+ 37 - 0
src/views/business/publish/components/Order-publish-edit.vue

@@ -110,6 +110,30 @@
               </el-radio-group>
             </el-form-item>
           </el-col>-->
+					<!--	工单标记 随手拍特殊需求 发布时必填	-->
+					<el-col v-if="isSnapshot">
+						<el-form-item label="工单标记" prop="snapshotLabel" :rules="[{ required: true, message: '请选择工单标记', trigger: 'change' }]">
+							<el-select
+								v-model="state.ruleForm.snapshotLabel"
+								multiple
+								collapse-tags
+								collapse-tags-tooltip
+								:max-collapse-tags="5"
+								placeholder="请选择工单标记"
+								value-key="dicDataValue"
+								clearable
+								@change="handleSnapshotLabel"
+							>
+								<el-option
+									v-for="item in snapshotLabel"
+									:key="item.dicDataValue"
+									:label="item.dicDataName"
+									:value="item"
+									class="w100"
+								/>
+							</el-select>
+						</el-form-item>
+					</el-col>
 					<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
 						<el-form-item label="实际办理部门">
 							{{ state.publishDetail.actualHandleOrgName?.value }}
@@ -159,6 +183,8 @@ const idNamesArray = ref<EmptyArrayType>([]); // 部门列表
  * @param row 工单详情
  * @description 打开弹窗
  * */
+const isSnapshot = ref<boolean>(false); // 是否是随手拍
+const snapshotLabel = ref<EmptyArrayType>([]); // 工单标记多选框
 const openDialog = async (row: any) => {
 	state.loading = true;
   state.dialogVisible = true;
@@ -168,6 +194,8 @@ const openDialog = async (row: any) => {
 		state.ruleForm = response.result ?? {};
 		state.publishDetail = res.result ?? {};
 		idNamesArray.value = res.result?.idNames ?? [];
+		isSnapshot.value = response.result.isSnapshot ?? false;
+		snapshotLabel.value = res.result?.snapshotLabel ?? [];
 		state.loading = false;
 	} catch (e) {
 		state.loading = false;
@@ -186,6 +214,15 @@ const close = () => {
 	ruleFormRef.value.clearValidate();
 	ruleFormRef.value.resetFields();
 };
+// 选择工单标记、
+const handleSnapshotLabel = (val: any) => {
+	state.ruleForm.snapshotLabels = val.map((item: any) => {
+		return {
+			key: item.dicDataValue,
+			value: item.dicDataName,
+		};
+	});
+};
 // 发布
 const onPublish = (formEl: FormInstance | undefined) => {
 	if (!formEl) return;

+ 17 - 2
src/views/business/publish/components/Order-publish.vue

@@ -141,12 +141,23 @@
 					</el-col>
 					<el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
 						<el-form-item label="门户是否公开" prop="publishState">
-							<el-radio-group v-model="state.ruleForm.publishState" :disabled="disabled">
+							<el-radio-group v-model="state.ruleForm.publishState" :disabled="disabled && publishDisabled" @change="selectPublishState">
 								<el-radio :value="false">不公开</el-radio>
 								<el-radio :value="true">公开</el-radio>
 							</el-radio-group>
 						</el-form-item>
 					</el-col>
+					<!--					<el-col :xs="24" :sm="12" :md="24" :lg="24" :xl="24" v-if="!state.ruleForm.publishState">
+						<el-form-item label="不公开理由" prop="noPubReason" :rules="[{ required: true, message: '请填写不公开理由', trigger: 'blur' }]">
+							<el-input
+								type="textarea"
+								placeholder="请填写不公开理由"
+								:autosize="{ minRows: 6, maxRows: 10 }"
+								v-model="state.ruleForm.noPubReason"
+								:disabled="disabled"
+							></el-input>
+						</el-form-item>
+					</el-col>-->
 					<!--	工单标记 随手拍特殊需求 发布时必填	-->
 					<el-col v-if="isSnapshot">
 						<el-form-item label="工单标记" prop="snapshotLabel" :rules="[{ required: true, message: '请选择工单标记', trigger: 'change' }]">
@@ -267,6 +278,7 @@ const { themeConfig } = storeToRefs(storesThemeConfig);
  * */
 const isSnapshot = ref<boolean>(false); // 是否是随手拍
 const snapshotLabel = ref<EmptyArrayType>([]); // 工单标记多选框
+const publishDisabled = ref<boolean>(false); // 是否公开禁用
 const openDialog = async (row: any, isDisabled: boolean = false) => {
 	disabled.value = isDisabled;
 	state.loading = true;
@@ -282,7 +294,6 @@ const openDialog = async (row: any, isDisabled: boolean = false) => {
 			state.publishDetail = res.result ?? {};
 			idNamesArray.value = res.result?.idNames ?? [];
 			netizenEvaluateType.value = res.result?.netizenEvaluateType ?? [];
-
 			dialogTitle.value = '发布详情';
 			state.loading = false;
 		} else {
@@ -309,6 +320,10 @@ const openDialog = async (row: any, isDisabled: boolean = false) => {
 const isZGZFW = computed(() => {
 	return state.orderDetail.receiveProvinceNo?.includes('ZGZFW');
 });
+// 选择是否公开
+const selectPublishState = (val: any) => {
+	console.log(val, '1');
+};
 // 关闭弹窗
 const closeDialog = () => {
 	state.dialogVisible = false;

+ 54 - 59
src/views/examTrain/exam/practice/index.vue

@@ -1,77 +1,72 @@
 <template>
 	<div class="plan-index-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-            <vxe-toolbar
-                ref="toolbarRef"
-                :loading="state.tableLoading"
-                custom
-                :refresh="{
-                    queryMethod: handleQuery,
-                }"
-            >
-                <template #buttons>
-                    <el-button type="primary" @click="onAdd" v-auth="'practice:index:add'" :loading="state.tableLoading">
-                        <SvgIcon name="ele-Plus" class="mr10" />新增练习
-                    </el-button>
-                </template>
-            </vxe-toolbar>
-            <div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
-                <vxe-table
-                    border
-                    :loading="state.tableLoading"
-                    :data="state.tableData"
-                    :column-config="{ resizable: true }"
-                    :row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
-                    ref="tableRef"
-                    height="auto"
-                    auto-resize
-                    show-overflow
-                    :print-config="{}"
-                    :scrollY="{ enabled: true, gt: 100 }"
-                    id="examTrainExamPractice"
-                    :custom-config="{ storage: true }"
-                    showHeaderOverflow
-                >
-                    <vxe-column field="code" title="练习流水号" width="200"></vxe-column>
-                    <vxe-column field="count" title="出题数量" width="150"></vxe-column>
-                    <vxe-column field="practiceTime" title="练习时间" min-width="160">
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.tableLoading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+			>
+				<template #buttons>
+					<el-button type="primary" @click="onAdd" v-auth="'practice:index:add'" :loading="state.tableLoading">
+						<SvgIcon name="ele-Plus" class="mr10" />新增练习
+					</el-button>
+				</template>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.tableLoading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30, useKey: true }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:print-config="{}"
+					:scrollY="{ enabled: true, gt: 100 }"
+					id="examTrainExamPractice"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+				>
+					<vxe-column field="code" title="练习流水号" width="200"></vxe-column>
+					<vxe-column field="count" title="出题数量" width="150"></vxe-column>
+					<vxe-column field="practiceTime" title="练习时间" min-width="160">
 						<template #default="{ row }">
 							{{ formatDate(row.practiceTime, 'YYYY-mm-dd HH:MM:SS') }}
 						</template>
 					</vxe-column>
-                    <vxe-column title="操作" fixed="right" width="120" align="center" :show-overflow="false">
-                        <template #default="{ row }">
-                            <el-button link type="primary" @click="onView(row)" title="查看" v-auth="'practice:index:view'">
-                                查看
-                            </el-button>
-                        </template>
-                    </vxe-column>
-                </vxe-table>
-            </div>
-            <pagination
-                @pagination="queryList"
-                :total="state.total"
-                v-model:current-page="state.queryParams.PageIndex"
-                v-model:page-size="state.queryParams.PageSize"
-                :disabled="state.tableLoading"
-            />
+					<vxe-column title="操作" fixed="right" width="120" align="center" :show-overflow="false">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onView(row)" title="查看" v-auth="'practice:index:view'"> 查看 </el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
+				:total="state.total"
+				v-model:current-page="state.queryParams.PageIndex"
+				v-model:page-size="state.queryParams.PageSize"
+				:disabled="state.tableLoading"
+			/>
 		</div>
-        <practice-add ref="practiceAddRef" @choose="onOpenExam" />
+		<practice-add ref="practiceAddRef" @choose="onOpenExam" />
 		<practice-exam ref="practiceExamRef" @updateList="queryList" />
 		<practice-view ref="practiceViewRef" />
 	</div>
 </template>
 
 <script lang="tsx" setup name="examTrainExamPractice">
-import { ref, reactive, onMounted, defineAsyncComponent, computed } from 'vue';
-import { ElMessageBox, ElMessage } from 'element-plus';
+import { ref, reactive, onMounted, defineAsyncComponent } from 'vue';
 import { useRouter } from 'vue-router';
-import type { FormInstance } from 'element-plus';
 import { formatDate } from '@/utils/formatTime';
 import 'splitpanes/dist/splitpanes.css';
 import Other from '@/utils/other';
-import { downloadFileByStream } from '@/utils/tools';
-import {getPracticeData} from '@/api/examTrain/practice';
+import { getPracticeData } from '@/api/examTrain/practice';
 
 // 引入组件
 const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
@@ -117,10 +112,10 @@ const onAdd = () => {
 	practiceAddRef.value.openDialog(state.tableData.value);
 };
 const practiceExamRef = ref<RefType>(); // 练习ref
-const onOpenExam = (practiceId) => {
-    console.log(practiceId);
+const onOpenExam = (practiceId: string) => {
+	queryList();
 	practiceExamRef.value.openDialog(practiceId);
-}
+};
 // 打开查看弹窗
 const practiceViewRef = ref<RefType>(); // 修改ref
 const onView = (row: any) => {