Files
moc/src/views/my/myTask/index.vue
T

616 lines
35 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
import { tagTextColor, tagBgColor, tagBorderColor } from '@/utils/common';
import { systemConfigApi, editSystemConfigApi } from '@/service/api/system';
import { myTasksListApi, myTasksWithdrawApi, myTasksCloseApi } from '@/service/api/myTasks';
const themeStore = useThemeStore();
const { routerPushByKey } = useRouterPush();
const loading = ref<boolean>(false);
// 当前行
const currentRow = ref<any>(null);
// 进度抽屉
const progressDrawer = ref<boolean>(false);
// 撤回弹框
const revokeModal = ref<boolean>(false);
const revokeSaving = ref<boolean>(false);
// 撤回原因
const revokeReason = ref<string>("");
// 处置申请弹框
const disposalModal = ref<boolean>(false);
// 变更类型
const typeList = ref<any[]>([]);
// 变更等级
const levelList = ref<any[]>([]);
// 提醒天数
const remindDays = ref<number>(0);
const remindInfo = ref<any>(null);
// 源数据
const dataSource = ref<any>(null);
// 列表
const list = ref<any[]>([]);
// 数量统计
const tabCount = ref<Record<string, number>>({
"all": 0,
"approval": 0,
"apply": 0,
"reject": 0,
});
// 选项卡
const currentTab = ref<string>("all");
// 选项卡切换
const tabChange = (k: string) => {
currentTab.value = k;
// 全部
if(k === "all"){
list.value = resetGrouped([...dataSource.value.my_applications,...dataSource.value.todo]);
}
// 待我审批
if(k === "approval"){
list.value = resetGrouped([...dataSource.value.todo]);
}
// 我的申请
if(k === "apply"){
list.value = resetGrouped([...dataSource.value.my_applications]);
}
// 驳回处理
if(k === "reject"){
const arr = [...dataSource.value.my_applications,...dataSource.value.todo];
const rejectedList = arr.filter((item: any) => item.status === "REJECTED");
list.value = resetGrouped(rejectedList);
}
};
// 处置申请跳转
const jumpTo = (act: string) => {
routerPushByKey("details_disposal",{ query: { id: currentRow.value?.change_id.toString(),type:act } });
}
// 打开详情、修改重报
const openDetail = (c: any,type:string = '') => {
console.log(c)
if(type==='detail'){
routerPushByKey("details_index",{ query: { id: c.change_id.toString(),status:c.status.toString() || '' } });
}
if(type==='edit'){
routerPushByKey("my_initiatechange",{ query: { id: c.change_id.toString() } });
}
};
// 打开资料关闭
const openDocClose = (c: any) => {
currentRow.value = c;
routerPushByKey("details_closedoc",{ query: { id: c.change_id.toString() } });
};
// 打开处置申请
const openDisposal = (c: any,) => {
currentRow.value = c;
disposalModal.value = true;
};
// 关闭变更
const closeChange = async (c: any) => {
const {error} = await myTasksCloseApi(c?.change_id);
if(!error){
window.$message?.success(`关闭变更成功`);
getList();
}
};
// 打开进度
const openProgress = (c: any) => {
currentRow.value = c;
progressDrawer.value = true;
};
// 打开撤回
const openWithdraw = (c: any) => {
revokeReason.value = "";
currentRow.value = c;
revokeModal.value = true;
};
// 撤回确认
const revokeSave = async () => {
if (!revokeReason.value) {
return window.$message?.warning("请填写撤回理由");
}
revokeSaving.value = true;
const {error} = await myTasksWithdrawApi(currentRow.value?.change_id,{reason:revokeReason.value});
if(!error){
revokeModal.value = false;
window.$message?.success(`撤回成功,申请退回草稿箱,审批记录保留可查,修改后可重新提交`);
getList();
}
revokeSaving.value = false;
};
// 匹配变更等级
const getChangeLevel = (level:number) => {
const changeLevel = levelList.value.find((item:any) => item.value == level);
return changeLevel || null;
}
// 按 status 归纳
const resetGrouped = (data:any) => {
const grouped = Object.values(
data.reduce((acc:any, item:any) => {
const key = item.status;
if (!acc[key]) {
acc[key] = { status: key, items: [] };
}
acc[key].items.push(item);
return acc;
}, {})
);
return grouped;
}
// 获取列表数据
const getList = async () => {
loading.value = true;
const {data,error} = await myTasksListApi();
if(!error){
dataSource.value = data;
tabChange(currentTab.value);
// 统计数量
// 全部
tabCount.value["all"] = [...dataSource.value.my_applications,...dataSource.value.todo].length;
// 待我审批
tabCount.value["approval"] = [...dataSource.value.todo].length;
// 我的申请
tabCount.value["apply"] = [...dataSource.value.my_applications].length;
// 驳回处理
const arr = [...dataSource.value.my_applications,...dataSource.value.todo];
const rejectedList = arr.filter((item: any) => item.status === "REJECTED");
tabCount.value["reject"] = rejectedList.length;
}
loading.value = false;
};
// 获取配置
const getConfig = async () => {
loading.value = true;
const {data,error} = await systemConfigApi();
if(!error){
// 解析 临时变更临期提醒
const remindDaysGroup = data.find((group:{group_key:string}) => group.group_key === 'change_remind');
if (remindDaysGroup) {
remindDaysGroup?.items.forEach((item:any) => {
if(item.item_key === 'temp_due_remind_days'){
remindInfo.value = item;
remindDays.value = Number(item.value);
}
})
}
// 解析 变更类型设置
const changeTypeGroup = data.find((group:{group_key:string}) => group.group_key === 'change_type');
if (changeTypeGroup) {
typeList.value = changeTypeGroup.items;
}
// 解析 变更等级设置
const changeLevelGroup = data.find((group:{group_key:string}) => group.group_key === 'change_level');
if (changeLevelGroup) {
levelList.value = changeLevelGroup.items;
}
getList();
}
loading.value = false;
};
// 更新提醒天数
const updateRemindDays = async () => {
const {error} = await editSystemConfigApi(remindInfo.value?.id,{
label: remindInfo.value?.label,
color: remindInfo.value?.color,
remark: remindInfo.value?.remark,
value: remindDays.value,
});
}
onMounted(() => {
getConfig();
});
</script>
<template>
<NSpace vertical :size="16">
<NSpin :show="loading" size="small">
<!-- 我的任务 -->
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<div
class="h-100% flex flex-wrap items-center gap-2 border border-slate-200 px-3 py-2 mb-3"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<div @click="tabChange('all')"
class="flex items-center gap-1.5 px-3 py-1.5 text-sm cursor-pointer select-none"
:style="{
borderRadius: themeStore.themeRadius + 'px',
'--theme-color': themeStore.themeColor,
}"
:class="currentTab === 'all' ? 'bg-[var(--theme-color)] font-medium text-white' : 'text-slate-600 hover:bg-slate-100'">
全部
<NTag size="tiny" round :type="currentTab === 'all' ?'default':'primary'">{{tabCount["all"]}}</NTag>
</div>
<div @click="tabChange('approval')"
class="flex items-center gap-1.5 px-3 py-1.5 text-sm cursor-pointer select-none"
:style="{
borderRadius: themeStore.themeRadius + 'px',
'--theme-color': themeStore.themeColor,
}"
:class="currentTab === 'approval' ? 'bg-[var(--theme-color)] font-medium text-white' : 'text-slate-600 hover:bg-slate-100'">
待我审批
<NTag size="tiny" round :type="currentTab === 'approval' ?'default':'primary'">{{tabCount["approval"]}}</NTag>
</div>
<div @click="tabChange('apply')"
class="flex items-center gap-1.5 px-3 py-1.5 text-sm cursor-pointer select-none"
:style="{
borderRadius: themeStore.themeRadius + 'px',
'--theme-color': themeStore.themeColor,
}"
:class="currentTab === 'apply' ? 'bg-[var(--theme-color)] font-medium text-white' : 'text-slate-600 hover:bg-slate-100'">
我的申请
<NTag size="tiny" round :type="currentTab === 'apply' ?'default':'primary'">{{tabCount["apply"]}}</NTag>
</div>
<div @click="tabChange('reject')"
class="flex items-center gap-1.5 px-3 py-1.5 text-sm cursor-pointer select-none"
:style="{
borderRadius: themeStore.themeRadius + 'px',
'--theme-color': themeStore.themeColor,
}"
:class="currentTab === 'reject' ? 'bg-[var(--theme-color)] font-medium text-white' : 'text-slate-600 hover:bg-slate-100'">
驳回处理
<NTag size="tiny" round :type="currentTab === 'reject' ?'default':'error'">{{tabCount["reject"]}}</NTag>
</div>
</div>
<!-- 临时变更临期提醒 -->
<div
class="flex flex-wrap items-center gap-2 border border-slate-200 px-3 py-2 text-xs text-slate-400 mb-3"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<Icon icon="lets-icons:clock" class="size-16px text-amber-600" />
临时变更临期提醒到期前
<NInputNumber v-model:value="remindDays" :min="1" size="tiny" placeholder="" :show-button="false" class="text-11px w-14 text-center" @blur="updateRemindDays" />
天提醒可设置)· 超期红色临期琥珀色标识
<span class="ml-auto">
{{tabCount["all"]}} · 点击行内按钮办理各阶段业务
</span>
</div>
<div class="space-y-2 scroll">
<div class="flex flex-col gap-3">
<div v-if="list.length===0" class="text-center text-slate-400">
暂无数据
</div>
<div
class="border border-slate-200 p-4"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
v-for="(item,index) in list"
:key="index"
>
<!-- 审批中 -->
<div v-if="item.status==='APPROVING'" class="flex items-center gap-2">
<Icon icon="ant-design:clock-circle-outlined" class="size-16px" :style="{ color: themeStore.otherColor.warning }" />
<p class="text-13px font-700" :style="{ color: themeStore.otherColor.warning }">审批中</p>
<p class="text-11px text-#94a3b8"> {{item.items.length}} · 审批流程推进中 · 可查看进度或撤回</p>
</div>
<!-- 已通过 -->
<div v-if="item.status==='APPROVED'" class="flex items-center gap-2">
<Icon icon="ix:success" class="size-16px" :style="{ color: themeStore.otherColor.success }" />
<p class="text-13px font-700" :style="{ color: themeStore.otherColor.success }">审批通过</p>
<p class="text-11px text-#94a3b8"> {{item.items.length}} · 待实施 / 待验收 / 待关闭 · 处置申请与资料关闭在行内办理</p>
</div>
<!-- 已驳回 -->
<div v-if="item.status==='REJECTED'" class="flex items-center gap-2">
<Icon icon="system-uicons:reset" class="size-16px" :style="{ color: themeStore.otherColor.error }" />
<p class="text-13px font-700" :style="{ color: themeStore.otherColor.error }">驳回处理</p>
<p class="text-11px text-#94a3b8">{{item.items.length}} 项待处理</p>
</div>
<div v-if="item.items.length===0" class="text-center text-slate-400 mt-3 border-t pt-4 text-xs">
暂无数据
</div>
<div v-if="item.items && item.items.length" class="flex flex-col gap-3 mt-3">
<div v-for="c in item.items" :key="c.change_no"
class="flex flex-wrap items-center gap-3 border px-4 py-3"
:class="c.overdue_status===2 ? 'border-red-200 bg-[#FFF2F0]' : c.overdue_status===1 ? 'border-amber-200 bg-amber-50/40' : ''"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<!-- 左区 -->
<!-- 审批中/已通过 -->
<div v-if="item.status==='APPROVING' || item.status==='APPROVED'" class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<!-- 变更编号 -->
<span class="font-mono text-[11px] text-slate-400">{{ c.change_no }}</span>
<!-- 变更等级 -->
<NTag
size="small"
:color="{
color: tagBgColor(getChangeLevel(c.change_level)?.color),
textColor: tagTextColor(getChangeLevel(c.change_level)?.color),
borderColor: tagBorderColor(getChangeLevel(c.change_level)?.color),
}"
>{{getChangeLevel(c.change_level)?.label}}</NTag>
<!-- 变更时限 -->
<NTag v-if="c.duration_type===2" size="small" type="warning">临时</NTag>
<NTag v-if="c.duration_type===1" size="small" type="primary">永久</NTag>
<NTag v-if="c.urgent===1" size="small" type="error">紧急</NTag>
<!-- 超期/临期/延期 -->
<NTag v-if="c.overdue_status===2" size="small" type="error">已超期 {{ c.overdue_days }} </NTag>
<NTag v-if="c.overdue_status===1" size="small" type="warning">临期 · {{ c.overdue_days }} </NTag>
<NTag v-if="c.extend_count" size="small">已延期 {{ c.extend_count }} </NTag>
<!-- 变更状态 -->
<NTag v-if="c.status==='APPROVING'" size="small" type="warning">审批中</NTag>
<NTag v-if="c.status==='APPROVED'" size="small" type="success">已通过</NTag>
</div>
<div class="mt-1 flex flex-wrap items-baseline gap-x-2">
<span class="text-sm font-medium text-slate-800">{{ c.title }}</span>
<span v-if="c.apply_time" class="text-[11px] text-slate-400">申请 {{ c.apply_time.slice(0, 16) }}</span>
</div>
<!-- 当前节点与会签成员进度状态更新时间跟在审核人员名字后面 -->
<div class="mt-1 flex flex-wrap items-center gap-1.5 text-[11px]">
<span class="text-slate-400">当前节点</span>
<span class="font-medium text-slate-600">{{ c.step_name }}</span>
<div v-if="c.current_step_members && c.current_step_members.length" class="flex items-center gap-1">
<div v-for="(m, mi) in c.current_step_members" :key="mi">
<NTag v-if="m.status==='PENDING'" size="small" type="warning">
<div class="flex items-center">
<Icon icon="tabler:clock" />{{ m.user_name }}
</div>
</NTag>
<NTag v-else size="small" type="success">
<div class="flex items-center">
<Icon icon="ix:success" />{{ m.user_name }}
</div>
</NTag>
</div>
</div>
<span v-if="c.status_changed_at" class="text-slate-400">状态更新 {{ c.status_changed_at.slice(0, 16) }}</span>
</div>
</div>
<!-- 驳回处理 -->
<NTag v-if="item.status==='REJECTED'" size="small" type="error">
<div class="flex items-center">
<Icon icon="system-uicons:reset" />驳回处理
</div>
</NTag>
<div v-if="item.status==='REJECTED'" class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-medium text-slate-800">{{ c.title }}</span>
<span class="font-mono text-[11px] text-slate-400">{{ c.change_no }}</span>
</div>
<p class="px-2 py-1 text-xs border border-red-100 bg-red-50/60 px-2 py-1 text-red-600 rounded-md mt-1">
驳回原因{{ c.reject_comment }}
</p>
<span v-if="c.rejected_at" class="text-11px text-slate-400">驳回于 {{ c.rejected_at.slice(0, 16) }}</span>
</div>
<!-- 右区 -->
<!-- 审批中 -->
<div v-if="c.status === 'APPROVING'" class="flex gap-1.5">
<NButton class="text-xs" text type="primary" @click="openDetail(c,'detail')">详情</NButton>
<NButton class="text-xs" text type="warning" @click="openProgress(c)">进度</NButton>
<NButton class="text-xs" text type="error" @click="openWithdraw(c)">撤回</NButton>
</div>
<!-- 审批通过 -->
<div v-if="c.status === 'APPROVED'" class="flex gap-1.5">
<NButton class="text-xs" text type="primary" @click="openDetail(c,'detail')">详情</NButton>
<NButton class="text-xs" text type="warning" @click="openProgress(c)">进度</NButton>
<NButton class="text-xs" text type="primary" @click="openDisposal(c)">处置申请</NButton>
<NButton class="text-xs" text type="error" @click="openDocClose(c)">资料关闭</NButton>
</div>
<!-- 驳回处理 -->
<div v-if="c.status === 'REJECTED'" class="flex gap-1.5">
<NButton class="text-xs" text type="primary" @click="openDetail(c,'detail')">详情</NButton>
<NButton class="text-xs" text type="warning" @click="openProgress(c)">进度</NButton>
<NButton class="text-xs" text type="primary" @click="openDetail(c,'edit')">修改重报</NButton>
<NPopconfirm
positive-text="确定"
:positiveButtonProps="{ size: 'tiny' }"
:negativeButtonProps="{ size: 'tiny' }"
@positive-click="closeChange(c)"
>
<template #trigger>
<NButton class="text-xs" text type="error">关闭变更</NButton>
</template>
确定关闭该变更吗
</NPopconfirm>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 进度弹框 -->
<NDrawer v-model:show="progressDrawer" :width="502" placement="right">
<NDrawerContent title="变更进度">
<div class="rounded-lg border bg-slate-50/60 px-3 py-2.5">
<div class="text-sm font-semibold text-slate-800">{{ currentRow?.title }}</div>
<div class="mt-1.5 flex flex-wrap items-center gap-1.5 text-[11px] text-slate-400">
<span class="font-mono">{{ currentRow?.change_no }}</span>
<NTag v-if="currentRow?.status==='APPROVING'" size="small" type="warning">审批中</NTag>
<NTag v-if="currentRow?.status==='APPROVED'" size="small" type="success">已通过</NTag>
<NTag v-if="currentRow?.status==='IMPLEMENTED'" size="small" type="warning">待验收</NTag>
<NTag v-if="currentRow?.status==='ACCEPTED'" size="small" type="error">待关闭</NTag>
<NTag v-if="currentRow?.status==='REJECTED'" size="small" type="error">已驳回</NTag>
<NTag v-if="currentRow?.status==='CLOSED'" size="small" type="error">已关闭</NTag>
<NTag v-if="currentRow?.status==='WITHDRAWN'" size="small" type="error">已撤回</NTag>
<span v-if="currentRow?.overdue_status===2" class="font-medium text-red-500">超期 {{ currentRow?.overdue_days }} </span>
</div>
<div v-if="currentRow?.dept || currentRow?.applicant" class="mt-1 text-[11px] text-slate-400">{{ [currentRow?.dept, currentRow?.applicant].filter(Boolean).join(' · ') }}</div>
<div v-if="currentRow?.meta" class="mt-1 text-[11px] text-slate-400">{{ currentRow?.meta }}</div>
</div>
<div class="mt-4">
<div v-for="(s, i) in currentRow?.approval_records" :key="s.id" class="flex gap-3">
<div class="flex flex-col items-center">
<span class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full border-2 border-[#7CC242] bg-[#7CC242] text-white">
<Icon icon="ix:success" />
</span>
<span
v-if="Number(i) < Number(currentRow?.approval_records?.length) - 1"
class="w-0.5 flex-1"
:class="Number(i) < Number(currentRow?.approval_records?.length) ? 'bg-[#7CC242]' : 'bg-slate-200'"
></span>
</div>
<div class="pb-5">
<p class="text-sm">{{ s.action }}</p>
<span class="mt-0.5 text-[11px] text-slate-400">{{s.finished_at?.slice(0, 16)}}</span>
</div>
</div>
</div>
<div v-if="currentRow?.duration_type === 2" class="rounded-lg border border-amber-200 bg-amber-50/50 px-3 py-2 text-[11px] leading-5 text-amber-700">
临时变更计划恢复 {{ currentRow?.restore_deadline ?? '—' }} · 恢复 / 延期 / 转永久请在详情页中操作
</div>
</NDrawerContent>
</NDrawer>
<!-- 撤回弹框 -->
<NModal
v-model:show="revokeModal"
preset="card"
:auto-focus="false"
:style="{ width: '450px', height: 'auto' }"
:segmented="{ content: true, footer: true }"
>
<template #header>
<h3 class="text-sm font-bold text-slate-800">撤回变更申请</h3>
</template>
<template #default>
<div class="rounded-lg bg-slate-50 px-3 py-2 text-xs leading-5 text-slate-500">
变更编号 {{ currentRow?.id }}撤回后申请退回草稿状态已产生的审批记录保留可查修改内容后可重新提交重新提交按新申请计
</div>
<NInput
class="mt-3"
v-model:value="revokeReason"
type="textarea"
:rows="3"
placeholder="撤回理由(必填):如补充材料、变更范围调整、需重新组织风险分析…"
/>
</template>
<template #footer>
<div class="flex justify-end gap-[10px]">
<NButton size="small" @click="revokeModal = false">取消</NButton>
<NButton size="small" type="primary" :loading="revokeSaving" @click="revokeSave">保存</NButton>
</div>
</template>
</NModal>
<!-- 处置申请弹框 -->
<NModal
v-model:show="disposalModal"
preset="card"
:auto-focus="false"
:style="{ width: '700px', height: 'auto' }"
:segmented="{ content: true, footer: false }"
>
<template #header>
<div class="flex items-center gap-2 flex-wrap">
<h3 class="text-base font-semibold text-slate-800">处置申请 · {{ currentRow?.title }}</h3>
<span class="shrink-0 border-slate-200 bg-slate-100 font-mono text-xs text-slate-600 px-1.5 py-0.5 border rounded-md">编号{{ currentRow?.change_no }}</span>
</div>
</template>
<template #default>
<div class="rounded-lg border bg-white px-4 py-3">
<div class="flex flex-wrap items-center gap-2">
<!-- 变更等级 -->
<NTag
size="small"
:color="{
color: tagBgColor(getChangeLevel(currentRow?.change_level)?.color),
textColor: tagTextColor(getChangeLevel(currentRow?.change_level)?.color),
borderColor: tagBorderColor(getChangeLevel(currentRow?.change_level)?.color),
}"
>{{getChangeLevel(currentRow?.change_level)?.label}}</NTag>
<!-- 变更时限 -->
<NTag v-if="currentRow?.duration_type===2" size="small" type="warning">临时</NTag>
<NTag v-if="currentRow?.duration_type===1" size="small" type="primary">永久</NTag>
<NTag v-if="currentRow?.urgent===1" size="small" type="error">紧急</NTag>
<!-- 变更状态 -->
<NTag v-if="currentRow?.status==='APPROVING'" size="small" type="warning">审批中</NTag>
<NTag v-if="currentRow?.status==='APPROVED'" size="small" type="success">已通过</NTag>
<span v-if="currentRow?.apply_time" class="text-[11px] text-slate-400">申请 {{ currentRow?.apply_time.slice(0, 16) }}</span>
<!-- 超期/临期/延期 -->
<NTag v-if="currentRow?.overdue_status===2" size="small" type="error">已超期 {{ currentRow?.overdue_days }} </NTag>
<NTag v-if="currentRow?.overdue_status===1" size="small" type="warning">临期 · {{ currentRow?.overdue_days }} </NTag>
<NTag v-if="currentRow?.extend_count" size="small">已延期 {{ currentRow?.extend_count }} </NTag>
</div>
</div>
<!-- 处置选项 -->
<div class="rounded-lg border bg-white mt-3">
<div class="border-b px-4 py-2.5 text-sm font-bold text-slate-800">
选择处置方式
<span class="ml-2 text-[11px] font-normal text-slate-400">申请恢复所有变更可发起申请延期 / 申请转为永久仅临时变更可用</span>
</div>
<div class="divide-y">
<!-- 未实施情况说明 -->
<div class="flex flex-wrap items-center gap-3 px-4 py-3.5">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold text-slate-800">未实施情况说明</span>
</div>
<div class="mt-0.5 text-[11px] leading-4 text-slate-400">审批通过后变更未实施填写情况说明未实施原因现场维持原状确认),知会原审批人后直接转入关闭流程</div>
</div>
<NButton size="small" type="primary" @click="jumpTo('unExecute')">
发起<Icon icon="formkit:right" class="size-12px text-white ml-1" />
</NButton>
</div>
<!-- 未投用情况说明 -->
<div class="flex flex-wrap items-center gap-3 px-4 py-3.5">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold text-slate-800">未投用情况说明</span>
</div>
<div class="mt-0.5 text-[11px] leading-4 text-slate-400">变更已实施完成但未正式投用填写情况说明含现场状态与后续安排),知会原审批人后直接转入关闭流程</div>
</div>
<NButton size="small" type="primary" @click="jumpTo('unUse')">
发起<Icon icon="formkit:right" class="size-12px text-white ml-1" />
</NButton>
</div>
<!-- 申请恢复 -->
<div class="flex flex-wrap items-center gap-3 px-4 py-3.5">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold text-slate-800">申请恢复</span>
</div>
<div class="mt-0.5 text-[11px] leading-4 text-slate-400">投用后申请恢复原状生成恢复操作票执行类单据随单归档无需另行审批),现场恢复并拍照确认后纳入归档</div>
</div>
<NButton size="small" type="primary" @click="jumpTo('recover')">
发起<Icon icon="formkit:right" class="size-12px text-white ml-1" />
</NButton>
</div>
<!-- 申请延期 -->
<div v-if="currentRow?.duration_type===2" class="flex flex-wrap items-center gap-3 px-4 py-3.5">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold text-slate-800">申请延期</span>
</div>
<div class="mt-0.5 text-[11px] leading-4 text-slate-400">临时变更到期前申请延期子单走属地 + 主管部门简化审批通过后回写原单到期时间 · 至多延期 1 </div>
</div>
<NButton size="small" type="primary" @click="jumpTo('delay')">
发起<Icon icon="formkit:right" class="size-12px text-white ml-1" />
</NButton>
</div>
<!-- 申请转为永久 -->
<div v-if="currentRow?.duration_type===2" class="flex flex-wrap items-center gap-3 px-4 py-3.5">
<div class="min-w-0 flex-1">
<div class="flex flex-wrap items-center gap-2">
<span class="text-sm font-semibold text-slate-800">申请转为永久</span>
</div>
<div class="mt-0.5 text-[11px] leading-4 text-slate-400">临时运行一个验证周期效果稳定后转永久按永久变更补齐风险评估与完整审批链通过后原临时变更自动关闭</div>
</div>
<NButton size="small" type="primary" @click="jumpTo('transform')">
发起<Icon icon="formkit:right" class="size-12px text-white ml-1" />
</NButton>
</div>
</div>
</div>
</template>
</NModal>
</NCard>
</NSpin>
</NSpace>
</template>
<style scoped>
</style>
<style scoped lang="scss">
.scroll {
height: calc(100vh - 260px);
overflow-y: auto;
}
</style>