mirror of
https://github.com/m-xlsea/ruoyi-plus-soybean.git
synced 2025-09-23 23:39:47 +08:00
Compare commits
4 Commits
9b60512165
...
1eb0a3dac2
Author | SHA1 | Date | |
---|---|---|---|
1eb0a3dac2 | |||
bc44d2cddc | |||
b07729edd1 | |||
9ef0bd416e |
2
.env.dev
2
.env.dev
@ -15,6 +15,8 @@ VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
|
|||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT=Y
|
VITE_APP_ENCRYPT=Y
|
||||||
|
# AES 加密头标识
|
||||||
|
VITE_HEADER_FLAG=encrypt-key
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
|
@ -12,6 +12,8 @@ VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
|
|||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT=Y
|
VITE_APP_ENCRYPT=Y
|
||||||
|
# AES 加密头标识
|
||||||
|
VITE_HEADER_FLAG=encrypt-key
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
|
@ -12,6 +12,8 @@ VITE_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e
|
|||||||
|
|
||||||
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
# 接口加密功能开关(如需关闭 后端也必须对应关闭)
|
||||||
VITE_APP_ENCRYPT=Y
|
VITE_APP_ENCRYPT=Y
|
||||||
|
# AES 加密头标识
|
||||||
|
VITE_HEADER_FLAG=encrypt-key
|
||||||
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
# 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
|
||||||
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
VITE_APP_RSA_PUBLIC_KEY='MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
|
||||||
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
# 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
|
||||||
|
1290
pnpm-lock.yaml
generated
1290
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -260,7 +260,7 @@ watch(visible, () => {
|
|||||||
size="medium"
|
size="medium"
|
||||||
:title="props.title"
|
:title="props.title"
|
||||||
>
|
>
|
||||||
<TableSiderLayout :sider-title="$t('page.system.dept.title')">
|
<TableSiderLayout class="bg-gray-50 p-2" :sider-title="$t('page.system.dept.title')">
|
||||||
<template #header-extra>
|
<template #header-extra>
|
||||||
<NButton size="small" text class="h-18px" @click.stop="() => handleResetTreeData()">
|
<NButton size="small" text class="h-18px" @click.stop="() => handleResetTreeData()">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
|
@ -165,7 +165,7 @@ defineExpose({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDivider />
|
<NDivider />
|
||||||
<div>
|
<div class="h-full">
|
||||||
<NTabs v-model:value="activeTab" type="segment" animated>
|
<NTabs v-model:value="activeTab" type="segment" animated>
|
||||||
<NTabPane display-directive="show" bar-width="100px" name="image" tab="流程图">
|
<NTabPane display-directive="show" bar-width="100px" name="image" tab="流程图">
|
||||||
<FlowPreview v-if="instanceId" :instance-id="instanceId" />
|
<FlowPreview v-if="instanceId" :instance-id="instanceId" />
|
||||||
|
@ -177,12 +177,24 @@ watch(visible, () => {
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<NSpace justify="end" :size="16">
|
<NSpace justify="end" :size="16">
|
||||||
<NButton v-if="isWaiting" type="primary" @click="openTransferModal">转办</NButton>
|
<NButton v-if="isWaiting" :loading="loading" type="primary" @click="openTransferModal">转办</NButton>
|
||||||
<NButton v-if="isWaiting && isTicketOrSignInstance" type="primary" @click="openAddSignatureModal">加签</NButton>
|
<NButton
|
||||||
<NButton v-if="isWaiting && isTicketOrSignInstance" type="primary" @click="openReduceSignatureModal">
|
v-if="isWaiting && isTicketOrSignInstance"
|
||||||
|
:loading="loading"
|
||||||
|
type="primary"
|
||||||
|
@click="openAddSignatureModal"
|
||||||
|
>
|
||||||
|
加签
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
v-if="isWaiting && isTicketOrSignInstance"
|
||||||
|
:loading="loading"
|
||||||
|
type="primary"
|
||||||
|
@click="openReduceSignatureModal"
|
||||||
|
>
|
||||||
减签
|
减签
|
||||||
</NButton>
|
</NButton>
|
||||||
<NButton v-if="isWaiting" type="error" @click="handleTerminate">终止</NButton>
|
<NButton v-if="isWaiting" :loading="loading" type="error" @click="handleTerminate">终止</NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
<!-- 转办用户选择器 -->
|
<!-- 转办用户选择器 -->
|
||||||
|
@ -133,7 +133,7 @@ async function getTask() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
task.value = data;
|
task.value = data;
|
||||||
task.value.buttonList.forEach(item => {
|
task.value.buttonList?.forEach(item => {
|
||||||
buttonPerm[item.code as keyof ButtonPerm] = item.show!;
|
buttonPerm[item.code as keyof ButtonPerm] = item.show!;
|
||||||
});
|
});
|
||||||
endBtnLoading();
|
endBtnLoading();
|
||||||
|
95
src/components/workflow/flow-urge-modal.vue
Normal file
95
src/components/workflow/flow-urge-modal.vue
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, watch } from 'vue';
|
||||||
|
import { messageTypeOptions } from '@/constants/workflow';
|
||||||
|
import { fetchTaskUrge } from '@/service/api/workflow';
|
||||||
|
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'FlowUrgeModal'
|
||||||
|
});
|
||||||
|
|
||||||
|
const { createRequiredRule } = useFormRules();
|
||||||
|
const { formRef, validate } = useNaiveForm();
|
||||||
|
interface Props {
|
||||||
|
taskIds: CommonType.IdType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'submit'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
default: false
|
||||||
|
});
|
||||||
|
|
||||||
|
type Model = Api.Workflow.TaskUrgeOperateParams;
|
||||||
|
const model = reactive(createDefaultModel());
|
||||||
|
|
||||||
|
function createDefaultModel(): Model {
|
||||||
|
return {
|
||||||
|
taskIdList: props.taskIds,
|
||||||
|
messageType: ['1'],
|
||||||
|
message: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type RuleKey = Extract<keyof Model, 'taskIdList' | 'messageType' | 'message'>;
|
||||||
|
|
||||||
|
const rules: Record<RuleKey, App.Global.FormRule> = {
|
||||||
|
taskIdList: createRequiredRule('任务ID不能为空'),
|
||||||
|
messageType: createRequiredRule('消息提醒不能为空'),
|
||||||
|
message: createRequiredRule('消息内容不能为空')
|
||||||
|
};
|
||||||
|
|
||||||
|
function closeDrawer() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (visible.value) {
|
||||||
|
Object.assign(model, createDefaultModel());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
await validate();
|
||||||
|
const { error } = await fetchTaskUrge(model);
|
||||||
|
if (error) return;
|
||||||
|
window.$message?.success('催办成功');
|
||||||
|
closeDrawer();
|
||||||
|
emit('submit');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NModal v-model:show="visible" preset="card" class="w-800px" title="催办" :native-scrollbar="false" closable>
|
||||||
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
|
<NFormItem label="消息提醒" path="messageType">
|
||||||
|
<NCheckboxGroup v-model:value="model.messageType">
|
||||||
|
<NSpace item-style="display: flex;">
|
||||||
|
<NCheckbox
|
||||||
|
v-for="item in messageTypeOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:disabled="item.value === '1'"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</NSpace>
|
||||||
|
</NCheckboxGroup>
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem label="消息呢用" path="message">
|
||||||
|
<NInput v-model:value="model.message" type="textarea" />
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
<template #footer>
|
||||||
|
<NSpace justify="end" :size="16">
|
||||||
|
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||||
|
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
</NModal>
|
||||||
|
</template>
|
@ -122,3 +122,21 @@ export function fetchGetCopyTask(data: Api.Workflow.TaskSearchParams) {
|
|||||||
params: data
|
params: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 修改办理人 */
|
||||||
|
export function fetchTaskAssignee(taskIds: CommonType.IdType[], userId: CommonType.IdType) {
|
||||||
|
return request<boolean>({
|
||||||
|
url: `/workflow/task/updateAssignee/${userId}`,
|
||||||
|
method: 'put',
|
||||||
|
data: taskIds
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 任务催办 */
|
||||||
|
export function fetchTaskUrge(data: Api.Workflow.TaskUrgeOperateParams) {
|
||||||
|
return request<boolean>({
|
||||||
|
url: '/workflow/task/urgeTask',
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { decrypt, encrypt } from '@/utils/jsencrypt';
|
|||||||
import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared';
|
import { getAuthorization, handleExpiredRequest, showErrorMsg } from './shared';
|
||||||
import type { RequestInstanceState } from './type';
|
import type { RequestInstanceState } from './type';
|
||||||
|
|
||||||
const encryptHeader = 'encrypt-key';
|
const encryptHeader = import.meta.env.VITE_HEADER_FLAG || 'encrypt-key';
|
||||||
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
const isHttpProxy = import.meta.env.DEV && import.meta.env.VITE_HTTP_PROXY === 'Y';
|
||||||
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
const { baseURL } = getServiceBaseURL(import.meta.env, isHttpProxy);
|
||||||
|
|
||||||
@ -48,6 +48,14 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
|||||||
isBackendSuccess(response) {
|
isBackendSuccess(response) {
|
||||||
// when the backend response code is "0000"(default), it means the request is success
|
// when the backend response code is "0000"(default), it means the request is success
|
||||||
// to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file
|
// to change this logic by yourself, you can modify the `VITE_SERVICE_SUCCESS_CODE` in `.env` file
|
||||||
|
if (import.meta.env.VITE_APP_ENCRYPT === 'Y' && response.headers[encryptHeader]) {
|
||||||
|
const keyStr = response.headers[encryptHeader];
|
||||||
|
const data = String(response.data);
|
||||||
|
const base64Str = decrypt(keyStr);
|
||||||
|
const aesKey = decryptBase64(base64Str.toString());
|
||||||
|
const decryptData = decryptWithAes(data, aesKey);
|
||||||
|
response.data = JSON.parse(decryptData);
|
||||||
|
}
|
||||||
return String(response.data.code) === import.meta.env.VITE_SERVICE_SUCCESS_CODE;
|
return String(response.data.code) === import.meta.env.VITE_SERVICE_SUCCESS_CODE;
|
||||||
},
|
},
|
||||||
async onBackendFail(response, instance) {
|
async onBackendFail(response, instance) {
|
||||||
@ -125,23 +133,6 @@ export const request = createFlatRequest<App.Service.Response, RequestInstanceSt
|
|||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
transformBackendResponse(response) {
|
transformBackendResponse(response) {
|
||||||
if (import.meta.env.VITE_APP_ENCRYPT === 'Y') {
|
|
||||||
// 加密后的 AES 秘钥
|
|
||||||
const keyStr = response.headers[encryptHeader];
|
|
||||||
// 加密
|
|
||||||
if (keyStr && keyStr !== '') {
|
|
||||||
const data = String(response.data);
|
|
||||||
// 请求体 AES 解密
|
|
||||||
const base64Str = decrypt(keyStr);
|
|
||||||
// base64 解码 得到请求头的 AES 秘钥
|
|
||||||
const aesKey = decryptBase64(base64Str.toString());
|
|
||||||
// aesKey 解码 data
|
|
||||||
const decryptData = decryptWithAes(data, aesKey);
|
|
||||||
// 将结果 (得到的是 JSON 字符串) 转为 JSON
|
|
||||||
response.data = JSON.parse(decryptData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 二进制数据则直接返回
|
// 二进制数据则直接返回
|
||||||
if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
|
if (response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer') {
|
||||||
return response.data;
|
return response.data;
|
||||||
|
17
src/typings/api/workflow.api.d.ts
vendored
17
src/typings/api/workflow.api.d.ts
vendored
@ -219,7 +219,7 @@ declare namespace Api {
|
|||||||
/** 业务编码 */
|
/** 业务编码 */
|
||||||
businessCode: string;
|
businessCode: string;
|
||||||
/** 业务名称 */
|
/** 业务名称 */
|
||||||
businessName: string;
|
businessTitle: string;
|
||||||
/** 节点类型 */
|
/** 节点类型 */
|
||||||
nodeType: WorkflowNodeType;
|
nodeType: WorkflowNodeType;
|
||||||
/** 节点编码 */
|
/** 节点编码 */
|
||||||
@ -370,11 +370,22 @@ declare namespace Api {
|
|||||||
flowCode: string;
|
flowCode: string;
|
||||||
/** 流程版本号 */
|
/** 流程版本号 */
|
||||||
version: string;
|
version: string;
|
||||||
|
/** 业务编码 */
|
||||||
|
businessCode: string;
|
||||||
|
/** 业务名称 */
|
||||||
|
businessTitle: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
/** 任务列表 */
|
/** 任务列表 */
|
||||||
type TaskList = Common.PaginatingQueryRecord<Task>;
|
type TaskList = Common.PaginatingQueryRecord<Task>;
|
||||||
|
|
||||||
|
/** 任务催办操作参数 */
|
||||||
|
type TaskUrgeOperateParams = CommonType.RecordNullable<{
|
||||||
|
taskIdList: CommonType.IdType[];
|
||||||
|
messageType: MessageType[];
|
||||||
|
message: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
/** 任务操作类型 */
|
/** 任务操作类型 */
|
||||||
type TaskOperateType = 'delegateTask' | 'transferTask' | 'addSignature' | 'reductionSignature' | 'stopTask';
|
type TaskOperateType = 'delegateTask' | 'transferTask' | 'addSignature' | 'reductionSignature' | 'stopTask';
|
||||||
|
|
||||||
@ -463,6 +474,10 @@ declare namespace Api {
|
|||||||
runDuration: string;
|
runDuration: string;
|
||||||
/** 附件 */
|
/** 附件 */
|
||||||
attachmentList: Api.System.Oss[];
|
attachmentList: Api.System.Oss[];
|
||||||
|
/** 业务编码 */
|
||||||
|
businessCode: string;
|
||||||
|
/** 业务名称 */
|
||||||
|
businessTitle: string;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
/** 历史任务列表 */
|
/** 历史任务列表 */
|
||||||
|
3
src/typings/components.d.ts
vendored
3
src/typings/components.d.ts
vendored
@ -29,6 +29,7 @@ declare module 'vue' {
|
|||||||
FlowInterveneModal: typeof import('./../components/workflow/flow-intervene-modal.vue')['default']
|
FlowInterveneModal: typeof import('./../components/workflow/flow-intervene-modal.vue')['default']
|
||||||
FlowPreview: typeof import('./../components/workflow/flow-preview.vue')['default']
|
FlowPreview: typeof import('./../components/workflow/flow-preview.vue')['default']
|
||||||
FlowTaskApprovalModal: typeof import('./../components/workflow/flow-task-approval-modal.vue')['default']
|
FlowTaskApprovalModal: typeof import('./../components/workflow/flow-task-approval-modal.vue')['default']
|
||||||
|
FlowUrgeModal: typeof import('./../components/workflow/flow-urge-modal.vue')['default']
|
||||||
FormTip: typeof import('./../components/custom/form-tip.vue')['default']
|
FormTip: typeof import('./../components/custom/form-tip.vue')['default']
|
||||||
FullScreen: typeof import('./../components/common/full-screen.vue')['default']
|
FullScreen: typeof import('./../components/common/full-screen.vue')['default']
|
||||||
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
|
||||||
@ -45,6 +46,8 @@ declare module 'vue' {
|
|||||||
'IconMaterialSymbols:add': typeof import('~icons/material-symbols/add')['default']
|
'IconMaterialSymbols:add': typeof import('~icons/material-symbols/add')['default']
|
||||||
'IconMaterialSymbols:deleteOutline': typeof import('~icons/material-symbols/delete-outline')['default']
|
'IconMaterialSymbols:deleteOutline': typeof import('~icons/material-symbols/delete-outline')['default']
|
||||||
'IconMaterialSymbols:downloadRounded': typeof import('~icons/material-symbols/download-rounded')['default']
|
'IconMaterialSymbols:downloadRounded': typeof import('~icons/material-symbols/download-rounded')['default']
|
||||||
|
'IconMaterialSymbols:driveFileRenameOutlineOutline': typeof import('~icons/material-symbols/drive-file-rename-outline-outline')['default']
|
||||||
|
'IconMaterialSymbols:editDocument': typeof import('~icons/material-symbols/edit-document')['default']
|
||||||
'IconMaterialSymbols:imageOutline': typeof import('~icons/material-symbols/image-outline')['default']
|
'IconMaterialSymbols:imageOutline': typeof import('~icons/material-symbols/image-outline')['default']
|
||||||
'IconMaterialSymbols:refreshRounded': typeof import('~icons/material-symbols/refresh-rounded')['default']
|
'IconMaterialSymbols:refreshRounded': typeof import('~icons/material-symbols/refresh-rounded')['default']
|
||||||
'IconMaterialSymbols:syncOutline': typeof import('~icons/material-symbols/sync-outline')['default']
|
'IconMaterialSymbols:syncOutline': typeof import('~icons/material-symbols/sync-outline')['default']
|
||||||
|
1
src/typings/vite-env.d.ts
vendored
1
src/typings/vite-env.d.ts
vendored
@ -114,6 +114,7 @@ declare namespace Env {
|
|||||||
readonly VITE_DEVTOOLS_LAUNCH_EDITOR?: import('vite-plugin-vue-devtools').VitePluginVueDevToolsOptions['launchEditor'];
|
readonly VITE_DEVTOOLS_LAUNCH_EDITOR?: import('vite-plugin-vue-devtools').VitePluginVueDevToolsOptions['launchEditor'];
|
||||||
readonly VITE_APP_CLIENT_ID?: string;
|
readonly VITE_APP_CLIENT_ID?: string;
|
||||||
readonly VITE_APP_ENCRYPT?: CommonType.YesOrNo;
|
readonly VITE_APP_ENCRYPT?: CommonType.YesOrNo;
|
||||||
|
readonly VITE_HEADER_FLAG?: string;
|
||||||
readonly VITE_APP_RSA_PUBLIC_KEY?: string;
|
readonly VITE_APP_RSA_PUBLIC_KEY?: string;
|
||||||
readonly VITE_APP_RSA_PRIVATE_KEY?: string;
|
readonly VITE_APP_RSA_PRIVATE_KEY?: string;
|
||||||
readonly VITE_APP_WEBSOCKET: CommonType.YesOrNo;
|
readonly VITE_APP_WEBSOCKET: CommonType.YesOrNo;
|
||||||
|
@ -74,7 +74,7 @@ const baseColumns = ref<NaiveUI.TableColumn<Api.Workflow.Instance>[]>([
|
|||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'businessName',
|
key: 'businessTitle',
|
||||||
title: '业务名称',
|
title: '业务名称',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 120
|
width: 120
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { computed, ref, shallowRef, watch } from 'vue';
|
import { computed, ref, shallowRef, watch } from 'vue';
|
||||||
import { NButton, NDivider, NEmpty, NInput, NRadioButton, NRadioGroup, NTag } from 'naive-ui';
|
import { NButton, NDivider, NEmpty, NInput, NRadioButton, NRadioGroup, NTag } from 'naive-ui';
|
||||||
import { useBoolean, useLoading } from '@sa/hooks';
|
import { useBoolean, useLoading } from '@sa/hooks';
|
||||||
import { fetchGetAllFinishedTask, fetchGetAllWaitingTask } from '@/service/api/workflow/task';
|
import { fetchGetAllFinishedTask, fetchGetAllWaitingTask, fetchTaskAssignee } from '@/service/api/workflow/task';
|
||||||
import { fetchGetCategoryTree } from '@/service/api/workflow/category';
|
import { fetchGetCategoryTree } from '@/service/api/workflow/category';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||||
@ -28,6 +28,8 @@ useDict('wf_task_status');
|
|||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
const { bool: viewVisible, setTrue: showViewDrawer } = useBoolean();
|
const { bool: viewVisible, setTrue: showViewDrawer } = useBoolean();
|
||||||
const { bool: interveneVisible, setTrue: showInterveneDrawer } = useBoolean();
|
const { bool: interveneVisible, setTrue: showInterveneDrawer } = useBoolean();
|
||||||
|
const { bool: urgeVisible, setTrue: showUrgeModal } = useBoolean();
|
||||||
|
const { bool: assigneeVisible, setTrue: showAssigneeModal } = useBoolean();
|
||||||
const dynamicComponent = shallowRef();
|
const dynamicComponent = shallowRef();
|
||||||
|
|
||||||
const waitingStatus = ref<boolean>(true);
|
const waitingStatus = ref<boolean>(true);
|
||||||
@ -38,6 +40,8 @@ const waitingStatusOptions = ref<WaitingStatusOption[]>([
|
|||||||
|
|
||||||
const commonColumns: NaiveUI.TableColumn<Api.Workflow.TaskOrHisTask>[] = [
|
const commonColumns: NaiveUI.TableColumn<Api.Workflow.TaskOrHisTask>[] = [
|
||||||
{ type: 'selection', align: 'center', width: 50 },
|
{ type: 'selection', align: 'center', width: 50 },
|
||||||
|
{ key: 'businessCode', title: '业务编码', align: 'center', width: 120 },
|
||||||
|
{ key: 'businessTitle', title: '业务名称', align: 'center', width: 120 },
|
||||||
{ key: 'flowName', title: '流程定义名称', align: 'center', width: 120 },
|
{ key: 'flowName', title: '流程定义名称', align: 'center', width: 120 },
|
||||||
{ key: 'flowCode', title: '流程定义编码', align: 'center', width: 120 },
|
{ key: 'flowCode', title: '流程定义编码', align: 'center', width: 120 },
|
||||||
{
|
{
|
||||||
@ -232,6 +236,14 @@ function handleIntervene(row: Api.Workflow.Task) {
|
|||||||
assigneeNames.value = row.assigneeNames?.split(',') || [];
|
assigneeNames.value = row.assigneeNames?.split(',') || [];
|
||||||
showInterveneDrawer();
|
showInterveneDrawer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleAssigneeConfirm(userIds: CommonType.IdType[]) {
|
||||||
|
const { error } = await fetchTaskAssignee(checkedRowKeys.value, userIds[0]);
|
||||||
|
if (error) return;
|
||||||
|
window.$message?.success('修改办理人成功');
|
||||||
|
assigneeVisible.value = false;
|
||||||
|
await getData();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -291,7 +303,36 @@ function handleIntervene(row: Api.Workflow.Task) {
|
|||||||
:show-delete="false"
|
:show-delete="false"
|
||||||
:show-export="false"
|
:show-export="false"
|
||||||
@refresh="getData"
|
@refresh="getData"
|
||||||
></TableHeaderOperation>
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<NButton
|
||||||
|
v-if="waitingStatus"
|
||||||
|
:disabled="checkedRowKeys.length === 0"
|
||||||
|
size="small"
|
||||||
|
type="warning"
|
||||||
|
ghost
|
||||||
|
@click="showAssigneeModal"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<icon-material-symbols:drive-file-rename-outline-outline class="text-icon" />
|
||||||
|
</template>
|
||||||
|
修改办理人
|
||||||
|
</NButton>
|
||||||
|
<NButton
|
||||||
|
v-if="waitingStatus"
|
||||||
|
:disabled="checkedRowKeys.length === 0"
|
||||||
|
size="small"
|
||||||
|
type="success"
|
||||||
|
ghost
|
||||||
|
@click="showUrgeModal"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<SvgIcon local-icon="bell" class="text-16px" />
|
||||||
|
</template>
|
||||||
|
催办
|
||||||
|
</NButton>
|
||||||
|
</template>
|
||||||
|
</TableHeaderOperation>
|
||||||
</template>
|
</template>
|
||||||
<NDataTable
|
<NDataTable
|
||||||
v-model:checked-row-keys="checkedRowKeys"
|
v-model:checked-row-keys="checkedRowKeys"
|
||||||
@ -314,6 +355,10 @@ function handleIntervene(row: Api.Workflow.Task) {
|
|||||||
:assignee-names="assigneeNames"
|
:assignee-names="assigneeNames"
|
||||||
@refresh="getData"
|
@refresh="getData"
|
||||||
/>
|
/>
|
||||||
|
<!-- 催办 -->
|
||||||
|
<FlowUrgeModal v-model:visible="urgeVisible" :task-ids="checkedRowKeys" @submit="getData" />
|
||||||
|
<!-- 修改办理人 -->
|
||||||
|
<UserSelectModal v-model:visible="assigneeVisible" @confirm="handleAssigneeConfirm" />
|
||||||
</NCard>
|
</NCard>
|
||||||
</div>
|
</div>
|
||||||
</TableSiderLayout>
|
</TableSiderLayout>
|
||||||
|
@ -51,6 +51,18 @@ const {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 64
|
width: 64
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '业务编码',
|
||||||
|
key: 'businessCode',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '业务名称',
|
||||||
|
key: 'businessTitle',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '流程定义名称',
|
title: '流程定义名称',
|
||||||
key: 'flowName',
|
key: 'flowName',
|
||||||
|
@ -51,6 +51,18 @@ const {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 64
|
width: 64
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '业务编码',
|
||||||
|
key: 'businessCode',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '业务名称',
|
||||||
|
key: 'businessTitle',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '流程定义名称',
|
title: '流程定义名称',
|
||||||
key: 'flowName',
|
key: 'flowName',
|
||||||
|
@ -51,6 +51,18 @@ const {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
width: 64
|
width: 64
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '业务编码',
|
||||||
|
key: 'businessCode',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '业务名称',
|
||||||
|
key: 'businessTitle',
|
||||||
|
align: 'center',
|
||||||
|
width: 120
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '流程定义名称',
|
title: '流程定义名称',
|
||||||
key: 'flowName',
|
key: 'flowName',
|
||||||
|
Reference in New Issue
Block a user