feat(gxmu): 审核流的审核意见改为必填项

通过/拒绝审核时审核意见为空或仅空白字符将被拦截,提交前去除首尾空格,输入框限制 500 字并显示字数。
This commit is contained in:
2026-11-01 17:06:13 +08:00
parent c81e24c977
commit 3888438694
@@ -15,7 +15,9 @@
<a-tag>{{ moduleName || module || '-' }}</a-tag> <a-tag>{{ moduleName || module || '-' }}</a-tag>
<span>业务ID:</span> <span>业务ID:</span>
<a-tag>{{ pk ?? '-' }}</a-tag> <a-tag>{{ pk ?? '-' }}</a-tag>
<a-button size="small" :loading="loading" @click="loadData">刷新</a-button> <a-button size="small" :loading="loading" @click="loadData"
>刷新</a-button
>
</a-space> </a-space>
<div v-if="flowList.length" class="flow-wrap"> <div v-if="flowList.length" class="flow-wrap">
@@ -23,7 +25,9 @@
<a-step v-for="item in flowList" :key="item.id"> <a-step v-for="item in flowList" :key="item.id">
<template #title> <template #title>
<div class="flow-title"> <div class="flow-title">
<span>{{ item.user?.realName || item.user?.username || '未分配审核人' }}</span> <span>{{
item.user?.realName || item.user?.username || '未分配审核人'
}}</span>
<a-tag :color="getStatusColor(item.status)"> <a-tag :color="getStatusColor(item.status)">
{{ getStatusText(item.status) }} {{ getStatusText(item.status) }}
</a-tag> </a-tag>
@@ -31,13 +35,27 @@
</template> </template>
<template #description> <template #description>
<div class="flow-desc"> <div class="flow-desc">
<div>创建时间:{{ toDateString(item.createTime, 'yyyy-MM-dd HH:mm:ss') }}</div> <div
>创建时间:{{
toDateString(item.createTime, 'yyyy-MM-dd HH:mm:ss')
}}</div
>
<div v-if="item.content">审核意见:{{ item.content }}</div> <div v-if="item.content">审核意见:{{ item.content }}</div>
<a-space v-if="canReview(item)" style="margin-top: 12px"> <a-space v-if="canReview(item)" style="margin-top: 12px">
<a-button type="primary" size="small" :loading="submitting" @click="openActionModal('approve', item)"> <a-button
type="primary"
size="small"
:loading="submitting"
@click="openActionModal('approve', item)"
>
通过 通过
</a-button> </a-button>
<a-button danger size="small" :loading="submitting" @click="openActionModal('reject', item)"> <a-button
danger
size="small"
:loading="submitting"
@click="openActionModal('reject', item)"
>
拒绝 拒绝
</a-button> </a-button>
</a-space> </a-space>
@@ -56,13 +74,20 @@
:confirm-loading="submitting" :confirm-loading="submitting"
@ok="submitReview" @ok="submitReview"
> >
<a-form layout="vertical"> <a-form
<a-form-item label="审核意见(非必填)"> ref="actionFormRef"
layout="vertical"
:model="actionForm"
:rules="actionRules"
>
<a-form-item label="审核意见" name="content">
<a-textarea <a-textarea
v-model:value="actionContent" v-model:value="actionForm.content"
:rows="4" :rows="4"
:maxlength="500"
show-count
allow-clear allow-clear
placeholder="请输入审核意见" placeholder="请输入审核意见(必填)"
/> />
</a-form-item> </a-form-item>
</a-form> </a-form>
@@ -71,8 +96,9 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref, watch } from 'vue'; import { computed, reactive, ref, watch } from 'vue';
import { Empty, message } from 'ant-design-vue'; import { Empty, message } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue/es/form';
import { toDateString } from 'ele-admin-pro'; import { toDateString } from 'ele-admin-pro';
import { listReviewList, updateReviewList } from '@/api/gxmu/reviewList'; import { listReviewList, updateReviewList } from '@/api/gxmu/reviewList';
import type { ReviewList } from '@/api/gxmu/reviewList/model'; import type { ReviewList } from '@/api/gxmu/reviewList/model';
@@ -98,9 +124,26 @@ const submitting = ref(false);
const flowList = ref<ReviewList[]>([]); const flowList = ref<ReviewList[]>([]);
const actionVisible = ref(false); const actionVisible = ref(false);
const actionType = ref<'approve' | 'reject'>('approve'); const actionType = ref<'approve' | 'reject'>('approve');
const actionContent = ref(''); const actionFormRef = ref<FormInstance | null>(null);
const actionForm = reactive<{ content: string }>({ content: '' });
const actionTarget = ref<ReviewList | null>(null); const actionTarget = ref<ReviewList | null>(null);
// 审核意见必填(仅空白字符视为未填写)
const actionRules = {
content: [
{
required: true,
validator: (_rule: unknown, value: string) => {
const text = (value || '').trim();
return text
? Promise.resolve()
: Promise.reject(new Error('请输入审核意见'));
},
trigger: 'blur'
}
]
};
const currentStepIndex = computed(() => { const currentStepIndex = computed(() => {
const pendingIndex = flowList.value.findIndex((item) => item.status === 0); const pendingIndex = flowList.value.findIndex((item) => item.status === 0);
if (pendingIndex >= 0) { if (pendingIndex >= 0) {
@@ -160,28 +203,32 @@ const openActionModal = (type: 'approve' | 'reject', item: ReviewList) => {
} }
actionType.value = type; actionType.value = type;
actionTarget.value = item; actionTarget.value = item;
actionContent.value = ''; actionForm.content = '';
actionVisible.value = true; actionVisible.value = true;
}; };
const submitReview = () => { const submitReview = () => {
if (!actionTarget.value?.id) { const target = actionTarget.value;
if (!target?.id) {
actionVisible.value = false; actionVisible.value = false;
return; return;
} }
if (!canReview(actionTarget.value)) { if (!canReview(target)) {
actionVisible.value = false; actionVisible.value = false;
message.error('当前记录不是由你审核'); message.error('当前记录不是由你审核');
return; return;
} }
actionFormRef.value
?.validate()
.then(() => {
submitting.value = true; submitting.value = true;
updateReviewList({ return updateReviewList({
id: actionTarget.value.id, id: target.id,
status: actionType.value === 'approve' ? 1 : 2, status: actionType.value === 'approve' ? 1 : 2,
module: actionTarget.value.module, module: target.module,
pk: actionTarget.value.pk, pk: target.pk,
sortNumber: actionTarget.value.sortNumber, sortNumber: target.sortNumber,
content: actionContent.value || undefined content: actionForm.content.trim()
}) })
.then((msg) => { .then((msg) => {
message.success(msg); message.success(msg);
@@ -195,6 +242,8 @@ const submitReview = () => {
.finally(() => { .finally(() => {
submitting.value = false; submitting.value = false;
}); });
})
.catch(() => {});
}; };
watch( watch(
@@ -206,7 +255,7 @@ watch(
flowList.value = []; flowList.value = [];
actionVisible.value = false; actionVisible.value = false;
actionTarget.value = null; actionTarget.value = null;
actionContent.value = ''; actionForm.content = '';
} }
}, },
{ immediate: true } { immediate: true }