<!--
|
OA / 审批管理 / 审批处理
|
差旅/费用报销使用报销详情 + 审批列表 approve 接口
|
-->
|
<template>
|
<view class="oa-detail-page">
|
<PageHeader :title="pageTitle"
|
@back="goBack" />
|
|
<scroll-view v-if="displayReady"
|
class="oa-detail-scroll"
|
scroll-y
|
:show-scrollbar="false">
|
<ReimburseInstanceDetailBody v-if="isReimburse"
|
:reimburse-row="reimburseRow"
|
:module-key="detailModuleKey" />
|
|
<ApproveInstanceDetailBody v-else
|
:row="row"
|
:module-key="detailModuleKey" />
|
|
<view class="section-card opinion-card">
|
<view class="section-head">
|
<text class="section-title">审批意见</text>
|
</view>
|
<view class="opinion-wrap">
|
<up-textarea v-model="approveOpinion"
|
placeholder="通过可留空;驳回请填写具体原因"
|
maxlength="500"
|
count
|
height="100"
|
border="surround" />
|
</view>
|
</view>
|
</scroll-view>
|
|
<view v-else
|
class="oa-empty">
|
<up-empty mode="data"
|
:text="loading ? '加载中' : '未获取到审批数据'" />
|
</view>
|
|
<view v-if="displayReady"
|
class="oa-page-footer">
|
<text class="oa-footer-btn btn-default"
|
:class="{ 'is-disabled': submitting }"
|
@click="goBack">取消</text>
|
<text class="oa-footer-btn btn-danger"
|
:class="{ 'is-disabled': submitting }"
|
@click="submitApprove('rejected')">驳回</text>
|
<text class="oa-footer-btn btn-success"
|
:class="{ 'is-disabled': submitting }"
|
@click="submitApprove('approved')">通过</text>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { computed, ref } from "vue";
|
import { onLoad } from "@dcloudio/uni-app";
|
import PageHeader from "@/components/PageHeader.vue";
|
import ApproveInstanceDetailBody from "./_components/ApproveInstanceDetailBody.vue";
|
import ReimburseInstanceDetailBody from "../../ReimburseManage/_components/ReimburseInstanceDetailBody.vue";
|
import { approveApprovalInstance } from "@/api/oa/approvalInstance.js";
|
import {
|
buildApproveInstanceDto,
|
canApproveInstance,
|
loadInstanceRow,
|
} from "../../_utils/approveListUtils.js";
|
import { inferModuleKeyFromRow } from "../../_utils/approvalModuleApplyExtras.js";
|
import {
|
inferReimburseModuleKeyFromInstance,
|
isReimburseApprovalInstance,
|
loadReimburseDetailForInstance,
|
} from "../../_utils/reimburseApproveBridge.js";
|
import { getApprovalModuleConfig } from "../../_utils/approvalModuleRegistry.js";
|
|
const row = ref(null);
|
const reimburseRow = ref(null);
|
const loading = ref(false);
|
const approveOpinion = ref("");
|
const submitting = ref(false);
|
|
const isReimburse = computed(() => isReimburseApprovalInstance(row.value));
|
|
const detailModuleKey = computed(() => {
|
if (isReimburse.value) {
|
return (
|
reimburseRow.value?.moduleKey ||
|
inferReimburseModuleKeyFromInstance(row.value)
|
);
|
}
|
return inferModuleKeyFromRow(row.value);
|
});
|
|
const pageTitle = computed(() => {
|
if (isReimburse.value) {
|
const label = getApprovalModuleConfig(detailModuleKey.value)?.label || "报销";
|
return `${label}审批`;
|
}
|
return "审批处理";
|
});
|
|
const displayReady = computed(() =>
|
isReimburse.value ? Boolean(reimburseRow.value) : Boolean(row.value)
|
);
|
|
const goBack = () => uni.navigateBack();
|
|
const submitApprove = uiResult => {
|
if (!row.value?.id || submitting.value) return;
|
|
if (uiResult === "rejected" && !(approveOpinion.value || "").trim()) {
|
uni.showToast({ title: "驳回时请填写审批意见", icon: "none" });
|
return;
|
}
|
|
submitting.value = true;
|
const dto = buildApproveInstanceDto(
|
row.value.id,
|
uiResult,
|
approveOpinion.value
|
);
|
|
approveApprovalInstance(dto)
|
.then(() => {
|
uni.showToast({
|
title: uiResult === "approved" ? "已通过" : "已驳回",
|
icon: "success",
|
});
|
setTimeout(() => {
|
const pages = getCurrentPages();
|
const prevRoute = pages[pages.length - 2]?.route || "";
|
const delta = prevRoute.includes("approve-list/detail") ? 2 : 1;
|
uni.navigateBack({ delta });
|
}, 400);
|
})
|
.catch(() => {
|
uni.showToast({ title: "审批操作失败", icon: "none" });
|
})
|
.finally(() => {
|
submitting.value = false;
|
});
|
};
|
|
onLoad(async options => {
|
if (!options?.id) {
|
uni.showToast({ title: "缺少审批 ID", icon: "none" });
|
setTimeout(goBack, 500);
|
return;
|
}
|
const cached = loadInstanceRow(options.id);
|
if (!cached) {
|
uni.showToast({ title: "请从列表进入", icon: "none" });
|
setTimeout(goBack, 500);
|
return;
|
}
|
if (!canApproveInstance(cached)) {
|
uni.showToast({ title: "当前审批无需您处理", icon: "none" });
|
setTimeout(goBack, 500);
|
return;
|
}
|
row.value = cached;
|
if (isReimburseApprovalInstance(cached)) {
|
loading.value = true;
|
try {
|
const { reimburseRow: mapped } = await loadReimburseDetailForInstance(cached);
|
reimburseRow.value = mapped;
|
} catch {
|
uni.showToast({ title: "加载报销详情失败", icon: "none" });
|
} finally {
|
loading.value = false;
|
}
|
}
|
});
|
</script>
|
|
<style scoped lang="scss">
|
@import "../../_styles/oa-approval-list.scss";
|
</style>
|