476 lines
13 KiB
Vue
Raw Normal View History

2025-12-08 20:03:34 +08:00
<template>
<BasicLayout>
<view class="p-15">
<!-- 积分标准 -->
<view class="jf-info-section">
<view class="section-title">积分标准</view>
<view class="info-item">
<text class="label">积分项目</text>
<text class="value title-bold">{{ jfInfo.jfTypeName || '-' }}</text>
</view>
<view class="info-block">
<text class="block-label">检查标准</text>
<text class="block-value multi-text">{{ jfInfo.ruleStandard || '-' }}</text>
</view>
<view class="info-block">
<text class="block-label">业绩积分</text>
<view v-if="formattedScoreConfig.length" class="score-config-wrapper">
<view
v-for="(category, catIdx) in formattedScoreConfig"
:key="catIdx"
class="score-config-category"
>
<view v-if="category.category" class="category-title">{{ category.category }}</view>
<view v-if="!category.hasMultipleGrades" class="score-config-table">
<view class="table-header">
<view class="table-cell header-cell">级别</view>
<view class="table-cell header-cell">分值</view>
</view>
<view v-for="(row, idx) in category.rows" :key="idx" class="table-row">
<view class="table-cell">{{ row.level }}</view>
<view class="table-cell score-cell">{{ row.scores }}</view>
</view>
</view>
<view v-else class="score-config-table">
<view class="table-header">
<view class="table-cell header-cell">级别</view>
<view class="table-cell header-cell">一等奖</view>
<view class="table-cell header-cell">二等奖</view>
<view class="table-cell header-cell">三等奖</view>
</view>
<view v-for="(row, idx) in category.rows" :key="idx" class="table-row">
<view class="table-cell">{{ row.level }}</view>
<view class="table-cell score-cell">{{ Array.isArray(row.scores) ? (row.scores[0] || '') : '' }}</view>
<view class="table-cell score-cell">{{ Array.isArray(row.scores) ? (row.scores[1] || '') : '' }}</view>
<view class="table-cell score-cell">{{ Array.isArray(row.scores) ? (row.scores[2] || '') : '' }}</view>
</view>
</view>
</view>
</view>
<view v-else class="block-value placeholder">暂无配置</view>
</view>
</view>
<!-- 获奖情况 -->
<view class="jf-info-section">
<view class="section-title">获奖情况</view>
<view class="info-item">
<text class="label">考核教师</text>
<text class="value title-bold">{{ jfInfo.jsmx || '-' }}</text>
</view>
<view class="info-item">
<text class="label">荣誉名称</text>
<text class="value">{{ jfInfo.rymc || '-' }}</text>
</view>
<view class="info-item">
<text class="label">获奖类型</text>
<text class="value">{{ jfInfo.hjlx || '-' }}</text>
</view>
<view class="info-item">
<text class="label">颁奖单位</text>
<text class="value multi-text">{{ jfInfo.bjdw || '-' }}</text>
</view>
<view class="info-item">
<text class="label">获奖时间</text>
<text class="value">{{ formatYearMonth(jfInfo.hjtime) }}</text>
</view>
<view class="info-item">
<text class="label">类别</text>
<text class="value">{{ jfInfo.category || '-' }}</text>
</view>
<view class="info-item">
<text class="label">级别</text>
<text class="value">{{ jfInfo.level || '-' }}</text>
</view>
<view class="info-item" v-if="jfInfo.grade">
<text class="label">等级</text>
<text class="value">{{ jfInfo.grade }}</text>
</view>
<view class="info-item">
<text class="label">分值</text>
<text class="value score-value">{{ jfInfo.score ?? '-' }}</text>
</view>
</view>
<!-- 证书预览 -->
<BasicFilePreview
v-if="jfInfo.fileUrl"
:file-url="jfInfo.fileUrl"
:file-name="jfInfo.fileName"
:file-format="jfInfo.fileFormat"
class="mb-0"
/>
</view>
<!-- 审批流程展示 -->
<LcglSp :yw-id="jfId" yw-type="JF" />
<template #bottom>
<YwConfirm
v-if="showButton"
:spApi="jfSpApi"
:stopApi="jfStopApi"
:transferApi="jfTransferApi"
:params="spParams"
:showXt="false"
:showReject="true"
:showTransfer="true"
:showApprove="true"
:showReturn="false"
:showStop="true"
:showXtDk="false"
/>
</template>
</BasicLayout>
</template>
<script setup lang="ts">
import { onLoad } from "@dcloudio/uni-app";
import { ref, computed } from "vue";
import dayjs from "dayjs";
import BasicLayout from "@/components/BasicLayout/Layout.vue";
import LcglSp from "@/components/LcglSp/index.vue";
import YwConfirm from "@/pages/components/YwConfirm/index.vue";
import BasicFilePreview from "@/components/BasicFile/preview.vue";
import { jfFlowByIdApi, jfSpApi, jfTransferApi, jfStopApi } from "@/api/base/server";
import { useDataStore } from "@/store/modules/data";
const { getXxts } = useDataStore();
const jfId = ref<string>("");
const jfInfo = ref<any>({});
const showButton = ref<boolean>(false);
const spParams = computed(() => ({
xxtsId: getXxts?.id,
ywId: jfId.value
}));
// 时间格式化
const formatTime = (time: any) => {
if (!time) return "-";
return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
};
const formatYearMonth = (time: any) => {
if (!time) return "-";
return dayjs(time).format("YYYY-MM");
};
// ===== 业绩积分展示格式化(与 MyScoreDetail 同步) =====
const defaultLevels = [
{ levelCode: 'national', levelName: '国', key: 'levelNational' },
{ levelCode: 'province', levelName: '省', key: 'levelProvince' },
{ levelCode: 'city', levelName: '市', key: 'levelCity' },
{ levelCode: 'district', levelName: '区', key: 'levelDistrict' },
{ levelCode: 'school_district', levelName: '学区/街道', key: 'levelSchoolDistrict' },
{ levelCode: 'school', levelName: '校', key: 'levelSchool' },
];
interface ScoreConfigRow {
level: string;
scores: string | number[]; // 单个分值用字符串,多个分值用数组
hasMultipleGrades: boolean; // 是否有多个等级
}
interface ScoreConfigCategory {
category?: string;
rows: ScoreConfigRow[];
hasMultipleGrades: boolean; // 整个类别是否有多个等级
}
const formatScores = (scores: number[]): { display: string | number[], hasMultiple: boolean } => {
if (!scores || scores.length === 0) {
return { display: '', hasMultiple: false };
}
const validScores = scores.filter(s => s > 0);
if (validScores.length === 0) {
return { display: '', hasMultiple: false };
}
if (validScores.length === 1) {
return { display: String(validScores[0]), hasMultiple: false };
}
return { display: validScores, hasMultiple: true };
};
const formatScoreConfig = (config: any): ScoreConfigCategory[] => {
if (!config) return [];
try {
let configObj = config;
if (typeof config === "string") {
try {
configObj = JSON.parse(config);
} catch {
return [];
}
}
const result: ScoreConfigCategory[] = [];
if (configObj.categories && Array.isArray(configObj.categories)) {
configObj.categories.forEach((cat: any) => {
const categoryName = cat.category || '';
const rows: ScoreConfigRow[] = [];
let categoryHasMultiple = false;
defaultLevels.forEach(level => {
const scores = cat[level.key] as number[];
if (scores && scores.length > 0) {
const formatted = formatScores(scores);
if (formatted.display) {
if (formatted.hasMultiple) {
categoryHasMultiple = true;
}
rows.push({
level: level.levelName,
scores: formatted.display,
hasMultipleGrades: formatted.hasMultiple
});
}
}
});
if (rows.length > 0) {
result.push({
category: categoryName,
rows: rows,
hasMultipleGrades: categoryHasMultiple
});
}
});
} else if (configObj.category && configObj.levels) {
const rows: ScoreConfigRow[] = [];
let categoryHasMultiple = false;
configObj.levels.forEach((level: any) => {
if (level.scores && level.scores.length > 0) {
const formatted = formatScores(level.scores);
if (formatted.display) {
if (formatted.hasMultiple) {
categoryHasMultiple = true;
}
const levelName = level.levelName || level.levelCode || '';
rows.push({
level: levelName,
scores: formatted.display,
hasMultipleGrades: formatted.hasMultiple
});
}
}
});
if (rows.length > 0) {
result.push({
category: configObj.category,
rows: rows,
hasMultipleGrades: categoryHasMultiple
});
}
}
return result;
} catch {
return [];
}
};
const formattedScoreConfig = computed(() => formatScoreConfig(jfInfo.value?.scoreConfig));
// 读取流程详情
const getJfInfo = async () => {
try {
const res: any = await jfFlowByIdApi({ id: jfId.value });
if (res && res.resultCode === 1 && res.result) {
jfInfo.value = res.result.jfInfo || {};
const spResult = jfInfo.value?.spResult;
// 当流程已完成且待办状态关闭时,不显示审批按钮
if (spResult && spResult !== "A" && getXxts && getXxts.dbZt === "A") {
showButton.value = false;
} else {
showButton.value = true;
}
} else {
showButton.value = false;
}
} catch (error) {
console.error("获取积分流程失败:", error);
showButton.value = false;
}
};
onLoad((options: any) => {
if (options && options.id) {
jfId.value = options.id;
getJfInfo();
} else {
uni.showToast({ title: "缺少积分ID", icon: "none" });
setTimeout(() => uni.navigateBack(), 1500);
}
});
</script>
<style scoped lang="scss">
.p-15 {
padding: 15px;
}
.jf-info-section {
margin-bottom: 20px;
padding: 15px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
border-bottom: 2px solid #007aff;
padding-bottom: 5px;
}
.info-item {
display: flex;
margin-bottom: 12px;
.label {
width: 110rpx;
color: #666;
font-size: 28rpx;
}
.value {
flex: 1;
color: #333;
font-size: 28rpx;
&.title-bold {
font-weight: bold;
font-size: 32rpx;
}
&.score-value {
color: #f56c6c;
font-weight: 600;
}
}
}
.info-block {
margin-top: 12px;
.block-label {
display: inline-block;
font-size: 28rpx;
font-weight: 600;
color: #303133;
padding-bottom: 6rpx;
border-bottom: 2rpx solid #e4e7ed;
}
.block-value {
display: block;
margin-top: 8rpx;
font-size: 28rpx;
color: #606266;
&.multi-text {
white-space: pre-wrap;
word-break: break-word;
line-height: 1.6;
}
&.placeholder {
color: #999;
}
}
.score-config-wrapper {
width: 100%;
margin-top: 8rpx;
}
.score-config-category {
margin-top: 16rpx;
&:first-child {
margin-top: 8rpx;
}
.category-title {
font-size: 28rpx;
font-weight: 600;
color: #409eff;
margin-bottom: 12rpx;
padding: 8rpx 12rpx;
background-color: #ecf5ff;
border-radius: 6rpx;
border-left: 4rpx solid #409eff;
}
.score-config-table {
border: 1rpx solid #dcdfe6;
border-radius: 8rpx;
overflow: hidden;
.table-header {
display: flex;
background-color: #f5f7fa;
border-bottom: 1rpx solid #dcdfe6;
}
.table-row {
display: flex;
border-bottom: 1rpx solid #ebeef5;
&:last-child {
border-bottom: none;
}
}
.table-cell {
padding: 16rpx 12rpx;
font-size: 26rpx;
text-align: center;
border-right: 1rpx solid #ebeef5;
&:first-child {
width: 120rpx;
border-right: 1rpx solid #ebeef5;
}
&:nth-child(2):last-child {
flex: 1;
border-right: none;
}
&:nth-child(2):not(:last-child),
&:nth-child(3),
&:nth-child(4) {
flex: 1;
min-width: 100rpx;
}
&:last-child {
border-right: none;
}
&.header-cell {
font-weight: bold;
color: #303133;
background-color: #f5f7fa;
}
&.score-cell {
color: #409eff;
font-weight: 500;
}
}
}
}
}
</style>