Merge branch 'wxd' into hebing
# Conflicts: # src/components/workbench/TaskManagement.vue
This commit is contained in:
2
.env
2
.env
@@ -1,5 +1,5 @@
|
|||||||
# 网站主标题
|
# 网站主标题
|
||||||
VITE_GLOBAL_TITLE= 'PIGX ADMIN'
|
VITE_GLOBAL_TITLE= '投资管理门户'
|
||||||
|
|
||||||
# footer
|
# footer
|
||||||
VITE_FOOTER_TITLE= '©2025 pig4cloud.com'
|
VITE_FOOTER_TITLE= '©2025 pig4cloud.com'
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<script setup lang="ts" name="StrengthMeter">
|
<script setup lang="ts" name="StrengthMeter">
|
||||||
import { verifyPasswordStrength } from '/@/utils/toolsValidate';
|
import { verifyPasswordStrength } from '/@/utils/toolsValidate';
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
value: {
|
modelValue: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
showInput: {
|
showInput: {
|
||||||
@@ -28,7 +28,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['score', 'change', 'update:value']);
|
const emit = defineEmits(['score', 'change', 'update:modelValue']);
|
||||||
|
|
||||||
// 计算密码强度
|
// 计算密码强度
|
||||||
const getPasswordStrength = computed(() => {
|
const getPasswordStrength = computed(() => {
|
||||||
@@ -47,13 +47,13 @@ const handleChange = (e: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
innerValueRef.value = props.value || '';
|
innerValueRef.value = props.modelValue || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => unref(innerValueRef),
|
() => unref(innerValueRef),
|
||||||
(val) => {
|
(val) => {
|
||||||
emit('update:value', val);
|
emit('update:modelValue', val);
|
||||||
emit('change', val);
|
emit('change', val);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item :label="t('progressReport.form.completionRate')" required prop="completionRate">
|
<el-form-item :label="t('progressReport.form.completionRate')" required prop="completionRate">
|
||||||
<el-input v-model="formData.completionRate"
|
<el-input v-model="formData.completionRate"
|
||||||
:placeholder="t('progressReport.form.completionRatePlaceholder')">
|
:placeholder="t('progressReport.form.completionRatePlaceholder')" disabled>
|
||||||
<template #append>%</template>
|
<template #append>%</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -107,13 +107,14 @@
|
|||||||
<div style="flex: 1;">
|
<div style="flex: 1;">
|
||||||
<el-form-item style="height: 82px;" :label="t('progressReport.form.reportYear')">
|
<el-form-item style="height: 82px;" :label="t('progressReport.form.reportYear')">
|
||||||
<el-date-picker v-model="formData.annualReport" type="year" value-format="YYYY"
|
<el-date-picker v-model="formData.annualReport" type="year" value-format="YYYY"
|
||||||
:placeholder="t('progressReport.form.selectYearPlaceholder')" style="width: 100%" />
|
:placeholder="t('progressReport.form.selectYearPlaceholder')" style="width: 100%"
|
||||||
|
@change="handleYearChange" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item style="height: 82px;"
|
<el-form-item style="height: 82px;"
|
||||||
:label="t('progressReport.form.currentYearPlannedInvestment')" required
|
:label="t('progressReport.form.currentYearPlannedInvestment')" required
|
||||||
prop="annualPlannedInvestment">
|
prop="annualPlannedInvestment">
|
||||||
<el-input v-model="formData.annualPlannedInvestment"
|
<el-input v-model="formData.annualPlannedInvestment"
|
||||||
:placeholder="t('progressReport.form.inputPlaceholder')">
|
:placeholder="t('progressReport.form.inputPlaceholder')" disabled>
|
||||||
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
|
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -128,7 +129,7 @@
|
|||||||
<el-form-item style="height: 82px;"
|
<el-form-item style="height: 82px;"
|
||||||
:label="t('progressReport.form.investmentCompletionRate')">
|
:label="t('progressReport.form.investmentCompletionRate')">
|
||||||
<el-input v-model="formData.investmentCompletionRate"
|
<el-input v-model="formData.investmentCompletionRate"
|
||||||
:placeholder="t('progressReport.form.inputPlaceholder')">
|
:placeholder="t('progressReport.form.inputPlaceholder')" disabled>
|
||||||
<template #append>%</template>
|
<template #append>%</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -141,7 +142,7 @@
|
|||||||
<div style="flex: 1;">
|
<div style="flex: 1;">
|
||||||
<el-form-item style="height: 82px;" :label="t('progressReport.form.plannedPaymentAmount')">
|
<el-form-item style="height: 82px;" :label="t('progressReport.form.plannedPaymentAmount')">
|
||||||
<el-input v-model="formData.plannedPayment"
|
<el-input v-model="formData.plannedPayment"
|
||||||
:placeholder="t('progressReport.form.inputPlaceholder')">
|
:placeholder="t('progressReport.form.inputPlaceholder')" disabled>
|
||||||
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
|
<template #append>{{ t('progressReport.form.unitSuffix') }}</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -155,7 +156,7 @@
|
|||||||
<el-form-item style="height: 82px;"
|
<el-form-item style="height: 82px;"
|
||||||
:label="t('progressReport.form.plannedAmountPaymentCompletionRate')">
|
:label="t('progressReport.form.plannedAmountPaymentCompletionRate')">
|
||||||
<el-input v-model="formData.investmentPlanCompletionRate"
|
<el-input v-model="formData.investmentPlanCompletionRate"
|
||||||
:placeholder="t('progressReport.form.inputPlaceholder')">
|
:placeholder="t('progressReport.form.inputPlaceholder')" disabled>
|
||||||
<template #append>%</template>
|
<template #append>%</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -273,6 +274,10 @@ const emit = defineEmits<{
|
|||||||
(e: 'update:modelValue', value: InvestmentProjectProgress): void;
|
(e: 'update:modelValue', value: InvestmentProjectProgress): void;
|
||||||
}>();
|
}>();
|
||||||
const useForm = ref<FormInstance | undefined>()
|
const useForm = ref<FormInstance | undefined>()
|
||||||
|
|
||||||
|
// 获取当前年份
|
||||||
|
const currentYear = String(new Date().getFullYear());
|
||||||
|
|
||||||
const defaultForm = reactive<InvestmentProjectProgress>({
|
const defaultForm = reactive<InvestmentProjectProgress>({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
projectName: '',
|
projectName: '',
|
||||||
@@ -285,7 +290,7 @@ const defaultForm = reactive<InvestmentProjectProgress>({
|
|||||||
completionRate: undefined,
|
completionRate: undefined,
|
||||||
cumulativePaymentToDate: undefined,
|
cumulativePaymentToDate: undefined,
|
||||||
paymentCompletionRate: undefined,
|
paymentCompletionRate: undefined,
|
||||||
annualReport: undefined,
|
annualReport: currentYear, // 默认当前年度
|
||||||
annualPlannedInvestment: undefined,
|
annualPlannedInvestment: undefined,
|
||||||
ytdRemainingInvestment: undefined,
|
ytdRemainingInvestment: undefined,
|
||||||
investmentCompletionRate: undefined,
|
investmentCompletionRate: undefined,
|
||||||
@@ -308,6 +313,12 @@ const defaultForm = reactive<InvestmentProjectProgress>({
|
|||||||
deptId: ''
|
deptId: ''
|
||||||
})
|
})
|
||||||
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
|
const formData = reactive<InvestmentProjectProgress>({ ...defaultForm, ...props.modelValue });
|
||||||
|
|
||||||
|
// 确保汇报年度有默认值
|
||||||
|
if (!formData.annualReport) {
|
||||||
|
formData.annualReport = currentYear;
|
||||||
|
}
|
||||||
|
|
||||||
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
|
const projectNameData = ref<ProjectPlanApplyFormItem[]>([]);
|
||||||
// 获取当前日期作为汇报时间
|
// 获取当前日期作为汇报时间
|
||||||
const reportTime = computed(() => {
|
const reportTime = computed(() => {
|
||||||
@@ -333,6 +344,17 @@ const getProjectNameList = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
getProjectNameList();
|
getProjectNameList();
|
||||||
|
|
||||||
|
// 项目总计划支付额(所有年度计划支付额度的和)
|
||||||
|
const totalPlannedPayment = ref<number>(0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目选择改变
|
||||||
|
* @param {string | number} value - 选中的项目ID
|
||||||
|
*/
|
||||||
|
// 当前选中的项目
|
||||||
|
const currentSelectedProject = ref<ProjectPlanApplyFormItem | null>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目选择改变
|
* 项目选择改变
|
||||||
* @param {string | number} value - 选中的项目ID
|
* @param {string | number} value - 选中的项目ID
|
||||||
@@ -344,11 +366,190 @@ const handelSelectChange = (value: string | number) => {
|
|||||||
);
|
);
|
||||||
// 如果找到了对应的项目,则更新实施单位字段
|
// 如果找到了对应的项目,则更新实施单位字段
|
||||||
if (selectedProject) {
|
if (selectedProject) {
|
||||||
|
currentSelectedProject.value = selectedProject;
|
||||||
formData.implementingBody = selectedProject.projectMainEntity || selectedProject.projectOwnerUnit || '';
|
formData.implementingBody = selectedProject.projectMainEntity || selectedProject.projectOwnerUnit || '';
|
||||||
formData.projectName = selectedProject.projectName || '';
|
formData.projectName = selectedProject.projectName || '';
|
||||||
formData.deptId = String(selectedProject.deptId);
|
formData.deptId = String(selectedProject.deptId);
|
||||||
|
|
||||||
|
// 从项目中获取项目总投资金额
|
||||||
|
const projectTotalAmount = selectedProject.projectTotalAmount || selectedProject.totalInvestment;
|
||||||
|
if (projectTotalAmount) {
|
||||||
|
formData.projectTotalAmount = Number(projectTotalAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算项目总计划支付额(所有年度计划支付额度的和)
|
||||||
|
const investmentEntities = selectedProject.projectInvestmentEntities || [];
|
||||||
|
let totalPayment = 0;
|
||||||
|
investmentEntities.forEach((entity: any) => {
|
||||||
|
const paymentAmount = Number(entity.plannedPaymentAmount) || 0;
|
||||||
|
totalPayment += paymentAmount;
|
||||||
|
});
|
||||||
|
totalPlannedPayment.value = totalPayment;
|
||||||
|
|
||||||
|
// 根据当前选中的年份更新本年度计划投资额和计划支付额
|
||||||
|
updateAnnualPlanData(formData.annualReport as string, investmentEntities);
|
||||||
|
|
||||||
|
// 触发完成率计算
|
||||||
|
calculateCompletionRates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 年份变化处理
|
||||||
|
* @param {string} year - 选中的年份
|
||||||
|
*/
|
||||||
|
const handleYearChange = (year: string) => {
|
||||||
|
if (currentSelectedProject.value) {
|
||||||
|
const investmentEntities = currentSelectedProject.value.projectInvestmentEntities || [];
|
||||||
|
updateAnnualPlanData(year, investmentEntities);
|
||||||
|
// 重新计算本年度完成率
|
||||||
|
calculateAnnualCompletionRates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新本年度计划投资额和计划支付额
|
||||||
|
* @param {string} year - 年份
|
||||||
|
* @param {any[]} investmentEntities - 投资计划实体列表
|
||||||
|
*/
|
||||||
|
const updateAnnualPlanData = (year: string, investmentEntities: any[]) => {
|
||||||
|
// 查找当前年份对应的投资计划
|
||||||
|
const currentYearPlan = investmentEntities.find((entity: any) =>
|
||||||
|
entity.plannedInvestmentYear === year ||
|
||||||
|
String(entity.plannedInvestmentYear) === year
|
||||||
|
);
|
||||||
|
|
||||||
|
if (currentYearPlan) {
|
||||||
|
// 设置本年度计划投资额
|
||||||
|
formData.annualPlannedInvestment = Number(currentYearPlan.plannedImageAmount) || 0;
|
||||||
|
// 设置本年度计划支付额
|
||||||
|
formData.plannedPayment = Number(currentYearPlan.plannedPaymentAmount) || 0;
|
||||||
|
} else {
|
||||||
|
// 如果没有找到当前年份的计划,清空数据
|
||||||
|
formData.annualPlannedInvestment = 0;
|
||||||
|
formData.plannedPayment = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算总投资完成率和总支付完成率
|
||||||
|
*/
|
||||||
|
const calculateCompletionRates = () => {
|
||||||
|
// 总投资完成率 = 项目开始截至本月末累计完成投资 / 项目总投资金额 * 100
|
||||||
|
const cumulativeInvestment = Number(formData.cumulativeInvestmentToDate) || 0;
|
||||||
|
const projectTotal = Number(formData.projectTotalAmount) || 0;
|
||||||
|
|
||||||
|
if (projectTotal > 0) {
|
||||||
|
const rate = (cumulativeInvestment / projectTotal) * 100;
|
||||||
|
formData.completionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.completionRate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总支付完成率 = 项目开始截至本月末累计完成支付额 / 项目总计划支付额 * 100
|
||||||
|
const cumulativePayment = Number(formData.cumulativePaymentToDate) || 0;
|
||||||
|
const totalPayment = totalPlannedPayment.value || 0;
|
||||||
|
|
||||||
|
if (totalPayment > 0) {
|
||||||
|
const rate = (cumulativePayment / totalPayment) * 100;
|
||||||
|
formData.paymentCompletionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.paymentCompletionRate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同时计算本年度完成率
|
||||||
|
calculateAnnualCompletionRates();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算本年度投资完成率和支付完成率
|
||||||
|
*/
|
||||||
|
const calculateAnnualCompletionRates = () => {
|
||||||
|
// 本年度投资完成率 = 本企业本年度截至本月末完成投资 / 本年度计划投资额 * 100
|
||||||
|
const ytdInvestment = Number(formData.ytdRemainingInvestment) || 0;
|
||||||
|
const annualPlannedInvestment = Number(formData.annualPlannedInvestment) || 0;
|
||||||
|
|
||||||
|
if (annualPlannedInvestment > 0) {
|
||||||
|
const rate = (ytdInvestment / annualPlannedInvestment) * 100;
|
||||||
|
formData.investmentCompletionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.investmentCompletionRate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 本年度支付完成率 = 本企业本年度支付完成额 / 本年度计划支付额 * 100
|
||||||
|
const actualPayment = Number(formData.actualPayment) || 0;
|
||||||
|
const plannedPayment = Number(formData.plannedPayment) || 0;
|
||||||
|
|
||||||
|
if (plannedPayment > 0) {
|
||||||
|
const rate = (actualPayment / plannedPayment) * 100;
|
||||||
|
formData.investmentPlanCompletionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.investmentPlanCompletionRate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听累计完成投资和项目总投资金额变化,自动计算总投资完成率
|
||||||
|
watch(
|
||||||
|
[() => formData.cumulativeInvestmentToDate, () => formData.projectTotalAmount],
|
||||||
|
() => {
|
||||||
|
const cumulativeInvestment = Number(formData.cumulativeInvestmentToDate) || 0;
|
||||||
|
const projectTotal = Number(formData.projectTotalAmount) || 0;
|
||||||
|
|
||||||
|
if (projectTotal > 0) {
|
||||||
|
const rate = (cumulativeInvestment / projectTotal) * 100;
|
||||||
|
formData.completionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.completionRate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听累计完成支付额变化,自动计算总支付完成率(可编辑,仅作为默认值)
|
||||||
|
watch(
|
||||||
|
() => formData.cumulativePaymentToDate,
|
||||||
|
() => {
|
||||||
|
const cumulativePayment = Number(formData.cumulativePaymentToDate) || 0;
|
||||||
|
const totalPayment = totalPlannedPayment.value || 0;
|
||||||
|
|
||||||
|
if (totalPayment > 0) {
|
||||||
|
const rate = (cumulativePayment / totalPayment) * 100;
|
||||||
|
formData.paymentCompletionRate = Number(rate.toFixed(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听本年度完成投资额变化,自动计算本年度投资完成率
|
||||||
|
watch(
|
||||||
|
() => formData.ytdRemainingInvestment,
|
||||||
|
() => {
|
||||||
|
const ytdInvestment = Number(formData.ytdRemainingInvestment) || 0;
|
||||||
|
const annualPlannedInvestment = Number(formData.annualPlannedInvestment) || 0;
|
||||||
|
|
||||||
|
if (annualPlannedInvestment > 0) {
|
||||||
|
const rate = (ytdInvestment / annualPlannedInvestment) * 100;
|
||||||
|
formData.investmentCompletionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.investmentCompletionRate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 监听本年度完成支付额变化,自动计算本年度支付完成率
|
||||||
|
watch(
|
||||||
|
() => formData.actualPayment,
|
||||||
|
() => {
|
||||||
|
const actualPayment = Number(formData.actualPayment) || 0;
|
||||||
|
const plannedPayment = Number(formData.plannedPayment) || 0;
|
||||||
|
|
||||||
|
if (plannedPayment > 0) {
|
||||||
|
const rate = (actualPayment / plannedPayment) * 100;
|
||||||
|
formData.investmentPlanCompletionRate = Number(rate.toFixed(2));
|
||||||
|
} else {
|
||||||
|
formData.investmentPlanCompletionRate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页码大小改变
|
* 页码大小改变
|
||||||
* @param {number} pageSize - 新的页码大小
|
* @param {number} pageSize - 新的页码大小
|
||||||
@@ -384,6 +585,10 @@ watch(
|
|||||||
if (typeof newVal.annualReport === 'number') newVal.annualReport = newVal.annualReport.toString()
|
if (typeof newVal.annualReport === 'number') newVal.annualReport = newVal.annualReport.toString()
|
||||||
Object.assign(formData, defaultForm, newVal);
|
Object.assign(formData, defaultForm, newVal);
|
||||||
}
|
}
|
||||||
|
// 确保汇报年度有默认值
|
||||||
|
if (!formData.annualReport) {
|
||||||
|
formData.annualReport = currentYear;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true }
|
{ immediate: true, deep: true }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<div class="task-management">
|
<div class="task-management">
|
||||||
<div class="task-header">
|
<div class="task-header">
|
||||||
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
<el-tabs v-model="activeTab" @tab-change="handleTabChange">
|
||||||
<el-tab-pane :label="t('workbench.task.pendingReview') + ` (${pendingCount})`" name="pending"
|
<el-tab-pane :label="t('workbench.task.pendingReview') + ` (${pendingTotal})`" name="pending"
|
||||||
class="task-tab-pane">
|
class="task-tab-pane">
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="t('workbench.task.saved')" name="saved"></el-tab-pane>
|
<el-tab-pane :label="t('workbench.task.saved')" name="saved"></el-tab-pane>
|
||||||
@@ -49,6 +49,28 @@ const activeTab = ref('pending');
|
|||||||
const tableData = ref<any[]>([]);
|
const tableData = ref<any[]>([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const pendingTotal = ref(0);
|
||||||
|
/**
|
||||||
|
* 根据任务名称判断类型
|
||||||
|
* @param name 任务名称
|
||||||
|
* @returns 任务类型
|
||||||
|
*/
|
||||||
|
const getTaskType = (name: string): string => {
|
||||||
|
if (name.includes('投资申报') || name.includes('项目投资')) {
|
||||||
|
return 'investment';
|
||||||
|
}
|
||||||
|
if (name.includes('专家') || name.includes('专家登记')) {
|
||||||
|
return 'expert';
|
||||||
|
}
|
||||||
|
if (name.includes('投资储备') || name.includes('储备')) {
|
||||||
|
return 'reserve';
|
||||||
|
}
|
||||||
|
if (name.includes('合作单位') || name.includes('合作')) {
|
||||||
|
return 'cooperation';
|
||||||
|
}
|
||||||
|
// 默认类型
|
||||||
|
return 'default';
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据类型获取审批页面路由
|
* 根据类型获取审批页面路由
|
||||||
@@ -59,7 +81,7 @@ const loading = ref(false);
|
|||||||
const getApprovalRoute = (type: string, taskId: string): string => {
|
const getApprovalRoute = (type: string, taskId: string): string => {
|
||||||
const routeMap: Record<string, string> = {
|
const routeMap: Record<string, string> = {
|
||||||
investment: '/invMid/planApplyExamine/index', // 投资申报审批
|
investment: '/invMid/planApplyExamine/index', // 投资申报审批
|
||||||
expert: '/workbench/expertApproval/index', // 专家登记审批
|
expert: '/investment/expertApplyExamine/index', // 专家信息登记审批
|
||||||
reserve: '/workbench/reserveApproval/index', // 投资储备审批
|
reserve: '/workbench/reserveApproval/index', // 投资储备审批
|
||||||
cooperation: '/workbench/cooperationApproval/index', // 合作单位审批
|
cooperation: '/workbench/cooperationApproval/index', // 合作单位审批
|
||||||
default: '/workbench/approvalDetail', // 默认审批详情页
|
default: '/workbench/approvalDetail', // 默认审批详情页
|
||||||
@@ -73,41 +95,32 @@ const getApprovalRoute = (type: string, taskId: string): string => {
|
|||||||
* @param row 行数据
|
* @param row 行数据
|
||||||
*/
|
*/
|
||||||
const handleRowClick = (row: any) => {
|
const handleRowClick = (row: any) => {
|
||||||
console.log(row);
|
const taskType = row.type || getTaskType(row.name);
|
||||||
const taskId = row.taskId || row.id;
|
const taskId = row.taskId || row.id;
|
||||||
const route = getApprovalRoute(row.flowType, taskId);
|
const route = getApprovalRoute(taskType, taskId);
|
||||||
const routePath = examineDict[row.flowType]
|
|
||||||
if (!routePath){
|
|
||||||
useMessage().error('未定义的审批类型!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.log(routePath)
|
|
||||||
// 跳转到对应的审批页面
|
// 跳转到对应的审批页面
|
||||||
router.push({
|
router.push({
|
||||||
path: routePath,
|
path: route.split('?')[0],
|
||||||
query: {
|
query: {
|
||||||
processInstanceId: row.processInstanceId,
|
id: taskId,
|
||||||
|
type: taskType,
|
||||||
tab: activeTab.value, // 传递当前标签页信息,用于返回时定位
|
tab: activeTab.value, // 传递当前标签页信息,用于返回时定位
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
// request('admin/sys/code/list',{
|
const getQueryMineTask = (): Promise<any> => {
|
||||||
// method:'get',
|
return new Promise((resolve, reject) => {
|
||||||
// }).then(res=>{
|
|
||||||
// console.log('test',res)
|
|
||||||
// })
|
|
||||||
const getQueryMineTask = () =>{
|
|
||||||
return new Promise((resolve, reject) =>{
|
|
||||||
queryMineTask({
|
queryMineTask({
|
||||||
title: '',
|
title: '',
|
||||||
processName: '',
|
processName: '',
|
||||||
taskTime: undefined,
|
taskTime: undefined,
|
||||||
flowType: '',
|
flowType: '',
|
||||||
size:5,
|
size: 5,
|
||||||
current: 1
|
current: 1
|
||||||
}).then(res=>{
|
}).then(res => {
|
||||||
resolve(res)
|
resolve(res)
|
||||||
}).catch(err=>{
|
}).catch(err => {
|
||||||
reject(err)
|
reject(err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -135,6 +148,7 @@ const loadData = async (tab: string) => {
|
|||||||
if (tab === 'pending') {
|
if (tab === 'pending') {
|
||||||
const response = await getQueryMineTask()
|
const response = await getQueryMineTask()
|
||||||
res = response?.data?.records
|
res = response?.data?.records
|
||||||
|
pendingTotal.value = response?.data?.total || 0
|
||||||
}
|
}
|
||||||
if (tab === 'myInitiated') {
|
if (tab === 'myInitiated') {
|
||||||
const response = await getQueryMineStarted()
|
const response = await getQueryMineStarted()
|
||||||
|
|||||||
@@ -415,6 +415,6 @@ export const yesOrNo:Enums[] = [
|
|||||||
* 级别
|
* 级别
|
||||||
* */
|
* */
|
||||||
export const level:Enums[] = [
|
export const level:Enums[] = [
|
||||||
{label:'一级',value:'1'},
|
{label:'一级',value:'national'},
|
||||||
{label:'二级',value:'2'},
|
{label:'二级',value:'provincial'},
|
||||||
]
|
]
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="layout-navbars-breadcrumb-user pr15" :style="{ flex: layoutUserFlexNum }">
|
<div class="layout-navbars-breadcrumb-user pr15" :style="{ flex: layoutUserFlexNum }">
|
||||||
<el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange">
|
<!-- <el-dropdown :show-timeout="70" :hide-timeout="50" trigger="click" @command="onLanguageChange">
|
||||||
<div class="layout-navbars-breadcrumb-user-icon">
|
<div class="layout-navbars-breadcrumb-user-icon">
|
||||||
<i class="iconfont" :class="state.disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'" :title="$t('user.title1')"></i>
|
<i class="iconfont" :class="state.disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'" :title="$t('user.title1')"></i>
|
||||||
</div>
|
</div>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<el-dropdown-item command="en" :disabled="state.disabledI18n === 'en'">English</el-dropdown-item>
|
<el-dropdown-item command="en" :disabled="state.disabledI18n === 'en'">English</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown> -->
|
||||||
<div class="layout-navbars-breadcrumb-user-icon" @click="onLockClick">
|
<div class="layout-navbars-breadcrumb-user-icon" @click="onLockClick">
|
||||||
<el-icon :title="$t('layout.threeLockScreenTime')">
|
<el-icon :title="$t('layout.threeLockScreenTime')">
|
||||||
<ele-Lock />
|
<ele-Lock />
|
||||||
|
|||||||
@@ -255,11 +255,11 @@ export function verifyPasswordPowerful(val: string) {
|
|||||||
export function verifyPasswordStrength(val: string) {
|
export function verifyPasswordStrength(val: string) {
|
||||||
let v = '0';
|
let v = '0';
|
||||||
// 弱:纯数字,纯字母,纯特殊字符
|
// 弱:纯数字,纯字母,纯特殊字符
|
||||||
if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.*]+){6,100}$/.test(val)) v = '1';
|
if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\.\*_]+){6,100}$/.test(val)) v = '1';
|
||||||
// 中:字母+数字,字母+特殊字符,数字+特殊字符
|
// 中:字母+数字,字母+特殊字符,数字+特殊字符
|
||||||
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,100}$/.test(val)) v = '2';
|
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.\*_]+$)[a-zA-Z\d!@#$%^&\.\*_]{6,100}$/.test(val)) v = '2';
|
||||||
// 强:字母+数字+特殊字符
|
// 强:字母+数字+特殊字符
|
||||||
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.*]+$)(?![\d!@#$%^&\.*]+$)[a-zA-Z\d!@#$%^&\.*]{6,100}$/.test(val))
|
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\.\*_]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\.\*_]+$)(?![\d!@#$%^&\.\*_]+$)[a-zA-Z\d!@#$%^&\.\*_]{6,100}$/.test(val))
|
||||||
v = '3';
|
v = '3';
|
||||||
// 返回结果
|
// 返回结果
|
||||||
return v;
|
return v;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row>
|
<!-- <el-row>
|
||||||
<div class="mb8" style="width: 100%">
|
<div class="mb8" style="width: 100%">
|
||||||
<el-button v-auth="'sys_user_add'" icon="folder-add" type="primary" @click="userDialogRef.openDialog()">
|
<el-button v-auth="'sys_user_add'" icon="folder-add" type="primary" @click="userDialogRef.openDialog()">
|
||||||
{{ $t('common.addBtn') }}
|
{{ $t('common.addBtn') }}
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
style="float: right"
|
style="float: right"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-row>
|
</el-row> -->
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="state.loading"
|
v-loading="state.loading"
|
||||||
:data="state.dataList"
|
:data="state.dataList"
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
{{ $t('common.editBtn') }}
|
{{ $t('common.editBtn') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 删除用户 -->
|
<!-- 删除用户 -->
|
||||||
<el-tooltip :content="$t('sysuser.deleteDisabledTip')" :disabled="scope.row.userId !== '1'" placement="top">
|
<!-- <el-tooltip :content="$t('sysuser.deleteDisabledTip')" :disabled="scope.row.userId !== '1'" placement="top">
|
||||||
<span style="margin-left: 12px">
|
<span style="margin-left: 12px">
|
||||||
<el-button
|
<el-button
|
||||||
icon="delete"
|
icon="delete"
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
>{{ $t('common.delBtn') }}
|
>{{ $t('common.delBtn') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-tooltip>
|
</el-tooltip> -->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|||||||
@@ -65,7 +65,7 @@
|
|||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="24" class="mb20">
|
<el-col :span="24" class="mb20">
|
||||||
<el-form-item label="原密码" prop="password">
|
<el-form-item label="原密码" prop="password">
|
||||||
<el-input v-model="passwordFormData.password" :type="showPassword ? 'text' : 'password'" placeholder="请输入密码" clearable type="password">
|
<el-input v-model="passwordFormData.password" :type="showPassword ? 'text' : 'password'" placeholder="请输入密码" clearable>
|
||||||
<template #suffix>
|
<template #suffix>
|
||||||
<i
|
<i
|
||||||
class="iconfont el-input__icon login-content-password"
|
class="iconfont el-input__icon login-content-password"
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="第三方账号">
|
<!-- <el-tab-pane label="第三方账号">
|
||||||
<template #label>
|
<template #label>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-4">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M7.864 4.243A7.5 7.5 0 0 1 19.5 10.5c0 2.92-.556 5.709-1.568 8.268M5.742 6.364A7.465 7.465 0 0 0 4.5 10.5a7.464 7.464 0 0 1-1.15 3.993m1.989 3.559A11.209 11.209 0 0 0 8.25 10.5a3.75 3.75 0 1 1 7.5 0c0 .527-.021 1.049-.064 1.565M12 10.5a14.94 14.94 0 0 1-3.6 9.75m6.633-4.596a18.666 18.666 0 0 1-2.485 5.33" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M7.864 4.243A7.5 7.5 0 0 1 19.5 10.5c0 2.92-.556 5.709-1.568 8.268M5.742 6.364A7.465 7.465 0 0 0 4.5 10.5a7.464 7.464 0 0 1-1.15 3.993m1.989 3.559A11.209 11.209 0 0 0 8.25 10.5a3.75 3.75 0 1 1 7.5 0c0 .527-.021 1.049-.064 1.565M12 10.5a14.94 14.94 0 0 1-3.6 9.75m6.633-4.596a18.666 18.666 0 0 1-2.485 5.33" />
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-tab-pane>
|
</el-tab-pane> -->
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -150,12 +150,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column v-if="isUpdate" prop="expertStatus" min-width="120" :label="t('expertApply.table.expertStatus')">
|
<el-table-column v-if="isUpdate" prop="externalStatus" min-width="120" :label="t('expertApply.table.externalStatus')">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-select v-model="scope.row.expertStatus" :placeholder="t('expertApply.table.selectPlaceholder')"
|
<el-select v-model="scope.row.externalStatus" :placeholder="t('expertApply.table.selectPlaceholder')"
|
||||||
style="width: 100%;">
|
style="width: 100%;">
|
||||||
<el-option :label="t('expertApply.expertStatusOptions.normal')" value="normal" />
|
<el-option :label="t('expertApply.externalStatusOptions.normal')" value="normal" />
|
||||||
<el-option :label="t('expertApply.expertStatusOptions.invalid')" value="invalid" />
|
<el-option :label="t('expertApply.externalStatusOptions.invalid')" value="invalid" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -232,8 +232,7 @@ const createEmptyExpert = () => ({
|
|||||||
attachments: '',
|
attachments: '',
|
||||||
evidences: '',
|
evidences: '',
|
||||||
level: '',
|
level: '',
|
||||||
expertStatus: 'normal',
|
externalStatus: 'normal',
|
||||||
externalStatus: '',
|
|
||||||
attachmentUrl: '',
|
attachmentUrl: '',
|
||||||
testimonyMaterials: '',
|
testimonyMaterials: '',
|
||||||
createBy: '',
|
createBy: '',
|
||||||
@@ -269,7 +268,7 @@ const onExpertSelected = (row: any) => {
|
|||||||
target.professionalTitle = row?.professionalTitle ?? target.professionalTitle;
|
target.professionalTitle = row?.professionalTitle ?? target.professionalTitle;
|
||||||
target.workUnit = row?.workUnit ?? target.workUnit;
|
target.workUnit = row?.workUnit ?? target.workUnit;
|
||||||
target.level = row?.level ?? target.level;
|
target.level = row?.level ?? target.level;
|
||||||
target.expertStatus = row?.expertStatus ?? target.expertStatus;
|
target.externalStatus = row?.externalStatus ?? target.externalStatus;
|
||||||
target.attachments = row?.attachmentUrl ? JSON.parse(row.attachmentUrl) : []
|
target.attachments = row?.attachmentUrl ? JSON.parse(row.attachmentUrl) : []
|
||||||
target.evidences = row?.testimonyMaterials ? JSON.parse(row.testimonyMaterials) : []
|
target.evidences = row?.testimonyMaterials ? JSON.parse(row.testimonyMaterials) : []
|
||||||
};
|
};
|
||||||
@@ -314,8 +313,7 @@ const toSubmitExpert = (expert: ReturnType<typeof createEmptyExpert>) => ({
|
|||||||
attachmentUrl: JSON.stringify(expert.attachments),
|
attachmentUrl: JSON.stringify(expert.attachments),
|
||||||
testimonyMaterials: JSON.stringify(expert.evidences),
|
testimonyMaterials: JSON.stringify(expert.evidences),
|
||||||
level: expert.level || '',
|
level: expert.level || '',
|
||||||
expertStatus: expert.expertStatus || 'normal',
|
externalStatus: expert.externalStatus || 'normal',
|
||||||
externalStatus: expert.externalStatus || '',
|
|
||||||
createBy: expert.createBy || '',
|
createBy: expert.createBy || '',
|
||||||
createTime: expert.createTime || '',
|
createTime: expert.createTime || '',
|
||||||
updateBy: expert.updateBy || '',
|
updateBy: expert.updateBy || '',
|
||||||
@@ -463,7 +461,7 @@ watch(()=>tempId.value,()=>{
|
|||||||
professionalTitle: item.professionalTitle,
|
professionalTitle: item.professionalTitle,
|
||||||
workUnit: item.workUnit,
|
workUnit: item.workUnit,
|
||||||
level: item.level,
|
level: item.level,
|
||||||
expertStatus: item.expertStatus || 'normal',
|
externalStatus: item.externalStatus || 'normal',
|
||||||
attachments: item.attachmentUrl ? JSON.parse(item.attachmentUrl) : [],
|
attachments: item.attachmentUrl ? JSON.parse(item.attachmentUrl) : [],
|
||||||
evidences: item.testimonyMaterials ? JSON.parse(item.testimonyMaterials) : []
|
evidences: item.testimonyMaterials ? JSON.parse(item.testimonyMaterials) : []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
<span>{{ level.find((item:any) => item.value === row.level)?.label || '--' }}</span>
|
<span>{{ level.find((item:any) => item.value === row.level)?.label || '--' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="t('expertLibrary.table.status')" prop="externalStatus" min-width="120"
|
<el-table-column :label="t('expertApply.table.externalStatus')" prop="externalStatus" min-width="120"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag :type="['info', 'primary', 'success', 'danger'][row.status]">{{ externalStatusLabel(row.status) }}</el-tag>
|
<el-tag :type="row.externalStatus === 'normal' ? 'success' : 'danger'">{{ externalStatusLabel(row.externalStatus) }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="t('expertLibrary.table.action')" width="100" fixed="right">
|
<el-table-column :label="t('expertLibrary.table.action')" width="100" fixed="right">
|
||||||
@@ -108,19 +108,15 @@ const handleView = (row: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const levelLabel = (val: string) => {
|
const levelLabel = (val: string) => {
|
||||||
if (val === 'national') return t('expertApply.level.national');
|
if (val === 'national') return '一级';
|
||||||
if (val === 'provincial') return t('expertApply.level.provincial');
|
if (val === 'provincial') return '二级';
|
||||||
if (val === 'city') return t('expertApply.level.city');
|
|
||||||
return val || '-';
|
return val || '-';
|
||||||
};
|
};
|
||||||
|
|
||||||
const externalStatusLabel = (val: string) => {
|
const externalStatusLabel = (val: string) => {
|
||||||
return {
|
if (val === 'normal') return t('expertApply.externalStatusOptions.normal');
|
||||||
'0': t('expertLibrary.status.pending'),
|
if (val === 'invalid') return t('expertApply.externalStatusOptions.invalid');
|
||||||
'1': t('expertLibrary.status.reviewing'),
|
return val || '-';
|
||||||
'2': t('expertLibrary.status.approved'),
|
|
||||||
'3': t('expertLibrary.status.rejected'),
|
|
||||||
}[val] || 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ export default {
|
|||||||
attachments: 'Attachments',
|
attachments: 'Attachments',
|
||||||
evidences: 'Supporting Materials',
|
evidences: 'Supporting Materials',
|
||||||
level: 'Level',
|
level: 'Level',
|
||||||
expertStatus: 'Expert Status',
|
externalStatus: 'Expert Status',
|
||||||
inputPlaceholder: 'Please enter',
|
inputPlaceholder: 'Please enter',
|
||||||
selectPlaceholder: 'Please select',
|
selectPlaceholder: 'Please select',
|
||||||
},
|
},
|
||||||
expertStatusOptions: {
|
externalStatusOptions: {
|
||||||
normal: 'Normal',
|
normal: 'Normal',
|
||||||
invalid: 'Invalid',
|
invalid: 'Invalid',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ export default {
|
|||||||
attachments: '附件',
|
attachments: '附件',
|
||||||
evidences: '佐证材料',
|
evidences: '佐证材料',
|
||||||
level: '级别',
|
level: '级别',
|
||||||
expertStatus: '专家状态',
|
externalStatus: '专家状态',
|
||||||
inputPlaceholder: '请输入',
|
inputPlaceholder: '请输入',
|
||||||
selectPlaceholder: '请选择',
|
selectPlaceholder: '请选择',
|
||||||
},
|
},
|
||||||
expertStatusOptions: {
|
externalStatusOptions: {
|
||||||
normal: '正常',
|
normal: '正常',
|
||||||
invalid: '作废',
|
invalid: '作废',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -124,7 +124,19 @@
|
|||||||
<span class="detail-title">{{ t('reserveLibrary.detail.title') }}</span>
|
<span class="detail-title">{{ t('reserveLibrary.detail.title') }}</span>
|
||||||
<el-button class="close-btn" link icon="Close" @click="detailDrawerVisible = false" />
|
<el-button class="close-btn" link icon="Close" @click="detailDrawerVisible = false" />
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-content">
|
<!-- Tab 锚点导航 -->
|
||||||
|
<div class="detail-tabs">
|
||||||
|
<div
|
||||||
|
v-for="tab in detailTabs"
|
||||||
|
:key="tab.id"
|
||||||
|
class="detail-tab-item"
|
||||||
|
:class="{ active: activeTab === tab.id }"
|
||||||
|
@click="scrollToSection(tab.id)"
|
||||||
|
>
|
||||||
|
{{ tab.label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="detail-content" ref="detailContentRef" @scroll="handleDetailScroll">
|
||||||
<ProjectBasicInfoView :model-value="detailFormData" :main-title="t('reserveLibrary.detail.formTitle')" />
|
<ProjectBasicInfoView :model-value="detailFormData" :main-title="t('reserveLibrary.detail.formTitle')" />
|
||||||
</div>
|
</div>
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
@@ -235,6 +247,59 @@ const detailFormData = reactive<ProjectBasicInfoFormData>(createEmptyDetail());
|
|||||||
const tableLoading = ref(false);
|
const tableLoading = ref(false);
|
||||||
const detailLoading = ref(false);
|
const detailLoading = ref(false);
|
||||||
|
|
||||||
|
// Tab 锚点导航相关
|
||||||
|
const detailContentRef = ref<HTMLElement | null>(null);
|
||||||
|
const activeTab = ref('basicInfo');
|
||||||
|
const detailTabs = [
|
||||||
|
{ id: 'basicInfo', label: t('reserveRegistration.basicInfo.title') || '项目基本信息' },
|
||||||
|
{ id: 'investmentEstimate', label: t('reserveRegistration.investmentEstimate.title') || '投资估算' },
|
||||||
|
{ id: 'partnerInfo', label: t('reserveRegistration.partnerInfo.title') || '合作方信息' },
|
||||||
|
{ id: 'decisionInfo', label: t('reserveRegistration.decisionInfo.title') || '决策信息' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const scrollToSection = (sectionId: string) => {
|
||||||
|
activeTab.value = sectionId;
|
||||||
|
const contentEl = detailContentRef.value;
|
||||||
|
if (!contentEl) return;
|
||||||
|
|
||||||
|
// 根据 sectionId 查找对应的标题元素
|
||||||
|
const sectionMap: Record<string, number> = {
|
||||||
|
'basicInfo': 0,
|
||||||
|
'investmentEstimate': 1,
|
||||||
|
'partnerInfo': 2,
|
||||||
|
'decisionInfo': 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const sectionTitles = contentEl.querySelectorAll('.form-section-title, .sub-section-title');
|
||||||
|
const targetIndex = sectionMap[sectionId];
|
||||||
|
|
||||||
|
if (sectionTitles[targetIndex]) {
|
||||||
|
sectionTitles[targetIndex].scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDetailScroll = () => {
|
||||||
|
const contentEl = detailContentRef.value;
|
||||||
|
if (!contentEl) return;
|
||||||
|
|
||||||
|
const sectionTitles = contentEl.querySelectorAll('.form-section-title, .sub-section-title');
|
||||||
|
const scrollTop = contentEl.scrollTop;
|
||||||
|
const offsetTop = 100; // 偏移量
|
||||||
|
|
||||||
|
let currentSection = 'basicInfo';
|
||||||
|
const sectionIds = ['basicInfo', 'investmentEstimate', 'partnerInfo', 'decisionInfo'];
|
||||||
|
|
||||||
|
sectionTitles.forEach((el, index) => {
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
const containerRect = contentEl.getBoundingClientRect();
|
||||||
|
if (rect.top - containerRect.top <= offsetTop) {
|
||||||
|
currentSection = sectionIds[index] || currentSection;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
activeTab.value = currentSection;
|
||||||
|
};
|
||||||
|
|
||||||
const resetDetailForm = () => {
|
const resetDetailForm = () => {
|
||||||
const empty = createEmptyDetail();
|
const empty = createEmptyDetail();
|
||||||
Object.assign(detailFormData, empty);
|
Object.assign(detailFormData, empty);
|
||||||
@@ -453,10 +518,39 @@ onMounted(() => {
|
|||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-tabs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0;
|
||||||
|
padding: 0 20px;
|
||||||
|
border-bottom: 1px solid var(--el-border-color);
|
||||||
|
background: var(--el-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-tab-item {
|
||||||
|
padding: 12px 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-tab-item:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-tab-item.active {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
border-bottom-color: var(--el-color-primary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
.detail-content {
|
.detail-content {
|
||||||
padding: 0 20px 20px;
|
padding: 0 20px 20px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: calc(100% - 52px);
|
height: calc(100% - 96px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-form-item--default {
|
.el-form-item--default {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="fixed top-0 right-0 z-10 flex items-center p-5 space-x-2">
|
<div class="fixed top-0 right-0 z-10 flex items-center p-5 space-x-2">
|
||||||
<!-- 语言切换 -->
|
<!-- 语言切换 -->
|
||||||
<el-dropdown v-if="isI18nEnabled" trigger="click" @command="onLanguageChange">
|
<!-- <el-dropdown v-if="isI18nEnabled" trigger="click" @command="onLanguageChange">
|
||||||
<div
|
<div
|
||||||
class="flex items-center justify-center transition-colors rounded-lg cursor-pointer w-9 h-9 bg-white/80 dark:bg-slate-800/80 hover:bg-gray-100 dark:hover:bg-slate-700 backdrop-blur-sm"
|
class="flex items-center justify-center transition-colors rounded-lg cursor-pointer w-9 h-9 bg-white/80 dark:bg-slate-800/80 hover:bg-gray-100 dark:hover:bg-slate-700 backdrop-blur-sm"
|
||||||
>
|
>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<el-dropdown-item command="en" :disabled="state.disabledI18n === 'en'">English</el-dropdown-item>
|
<el-dropdown-item command="en" :disabled="state.disabledI18n === 'en'">English</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown> -->
|
||||||
|
|
||||||
<!-- 主题切换 -->
|
<!-- 主题切换 -->
|
||||||
<el-tooltip v-if="isDarkModeEnabled" :content="getThemeConfig.isDark ? '切换亮色模式' : '切换暗色模式'" placement="bottom">
|
<el-tooltip v-if="isDarkModeEnabled" :content="getThemeConfig.isDark ? '切换亮色模式' : '切换暗色模式'" placement="bottom">
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ export default {
|
|||||||
startTime: 'Initiation Time',
|
startTime: 'Initiation Time',
|
||||||
receivedTime: 'Received Time',
|
receivedTime: 'Received Time',
|
||||||
processTime: 'Process Time',
|
processTime: 'Process Time',
|
||||||
|
currentNode: 'Current Node',
|
||||||
status: 'Approval Status',
|
status: 'Approval Status',
|
||||||
actions: 'Actions',
|
actions: 'Actions',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ export default {
|
|||||||
startTime: '发起时间',
|
startTime: '发起时间',
|
||||||
receivedTime: '接收时间',
|
receivedTime: '接收时间',
|
||||||
processTime: '处理时间',
|
processTime: '处理时间',
|
||||||
|
currentNode: '当前节点',
|
||||||
status: '审批状态',
|
status: '审批状态',
|
||||||
actions: '操作',
|
actions: '操作',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -55,6 +55,11 @@
|
|||||||
min-width="180" />
|
min-width="180" />
|
||||||
<el-table-column prop="updateTime" :label="t('workbenchPage.pending.table.processTime')"
|
<el-table-column prop="updateTime" :label="t('workbenchPage.pending.table.processTime')"
|
||||||
min-width="180" />
|
min-width="180" />
|
||||||
|
<el-table-column prop="taskName" :label="t('workbenchPage.pending.table.currentNode')" min-width="140">
|
||||||
|
<template #default="scope">
|
||||||
|
{{ scope.row.taskName || scope.row.nodeName || scope.row.currentNode || '--' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="status" :label="t('workbenchPage.pending.table.status')" min-width="140">
|
<el-table-column prop="status" :label="t('workbenchPage.pending.table.status')" min-width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.status == 1" type="primary">进行中</el-tag>
|
<el-tag v-if="scope.row.status == 1" type="primary">进行中</el-tag>
|
||||||
|
|||||||
Reference in New Issue
Block a user