Commit a92c4ba3 by Neo Turing

feat: update Lac module components

parent dcb685b2
...@@ -92,7 +92,7 @@ async function fetchTestDetails() { ...@@ -92,7 +92,7 @@ async function fetchTestDetails() {
try { try {
loading.value = true; loading.value = true;
const response = await axios.post('/Restful/Kivii.Standards.Entities.Detection/Query.json', { const response = await axios.post('/Restful/Kivii.Standards.Entities.Detection/Query.json', {
StandardKvid: props.standardKvid StandardKvid: props.standardKvid
}); });
...@@ -101,14 +101,14 @@ async function fetchTestDetails() { ...@@ -101,14 +101,14 @@ async function fetchTestDetails() {
// 处理树形结构数据 // 处理树形结构数据
const treeData = processTreeData(response.data.Results); const treeData = processTreeData(response.data.Results);
planDetails.value = treeData; planDetails.value = treeData;
message.success(`已加载${response.data.Results.length}个测试项目`); message.success(`已加载${response.data.Results.length}个测试项目`);
} else { } else {
message.error('获取测试数据失败'); message.error('获取测试数据失败');
} }
} catch (error) { } catch (error) {
message.error('获取测试详情失败'); message.error('获取测试详情失败');
console.error(error); // console.error(error);
} finally { } finally {
loading.value = false; loading.value = false;
} }
...@@ -155,7 +155,7 @@ function processTreeData(data: any[]) { ...@@ -155,7 +155,7 @@ function processTreeData(data: any[]) {
} }
} }
}; };
cleanEmptyChildren(result); cleanEmptyChildren(result);
return result; return result;
} }
...@@ -206,14 +206,14 @@ function confirm() { ...@@ -206,14 +206,14 @@ function confirm() {
// 提取完整树形结构中被选中的节点和它们的子节点 // 提取完整树形结构中被选中的节点和它们的子节点
const cloneTreeData = JSON.parse(JSON.stringify(planDetails.value)); const cloneTreeData = JSON.parse(JSON.stringify(planDetails.value));
// 过滤并标记选中的树节点 // 过滤并标记选中的树节点
const filterSelectedNodes = (nodes: any[]) => { const filterSelectedNodes = (nodes: any[]) => {
const result: any[] = []; const result: any[] = [];
for (const node of nodes) { for (const node of nodes) {
const isSelected = checkedRowKeys.value.includes(node.key); const isSelected = checkedRowKeys.value.includes(node.key);
// 如果当前节点被选中或者有被选中的子节点,则保留 // 如果当前节点被选中或者有被选中的子节点,则保留
if (isSelected) { if (isSelected) {
// 创建一个节点副本,只保留需要的属性 // 创建一个节点副本,只保留需要的属性
...@@ -224,7 +224,7 @@ function confirm() { ...@@ -224,7 +224,7 @@ function confirm() {
standardValue: node.standardValue, standardValue: node.standardValue,
allowableRange: node.allowableRange allowableRange: node.allowableRange
}; };
// 如果有子节点,递归处理 // 如果有子节点,递归处理
if (node.children && node.children.length > 0) { if (node.children && node.children.length > 0) {
const selectedChildren = filterSelectedNodes(node.children); const selectedChildren = filterSelectedNodes(node.children);
...@@ -232,7 +232,7 @@ function confirm() { ...@@ -232,7 +232,7 @@ function confirm() {
newNode.children = selectedChildren; newNode.children = selectedChildren;
} }
} }
result.push(newNode); result.push(newNode);
} else if (node.children && node.children.length > 0) { } else if (node.children && node.children.length > 0) {
// 如果当前节点未被选中,但可能有被选中的子节点 // 如果当前节点未被选中,但可能有被选中的子节点
...@@ -251,12 +251,12 @@ function confirm() { ...@@ -251,12 +251,12 @@ function confirm() {
} }
} }
} }
return result; return result;
}; };
const selectedTreeData = filterSelectedNodes(cloneTreeData); const selectedTreeData = filterSelectedNodes(cloneTreeData);
// 计算选中的项目总数 // 计算选中的项目总数
const countSelectedItems = (nodes: any[]): number => { const countSelectedItems = (nodes: any[]): number => {
let count = 0; let count = 0;
...@@ -268,9 +268,9 @@ function confirm() { ...@@ -268,9 +268,9 @@ function confirm() {
} }
return count; return count;
}; };
const selectedCount = countSelectedItems(selectedTreeData); const selectedCount = countSelectedItems(selectedTreeData);
// 将处理后的树形结构传递给父组件 // 将处理后的树形结构传递给父组件
emit('confirm', selectedTreeData); emit('confirm', selectedTreeData);
message.success(`已选择${selectedCount}个测试项目`); message.success(`已选择${selectedCount}个测试项目`);
......
...@@ -76,11 +76,11 @@ const createDateComputed = (getter: () => string | null, setter: (val: string | ...@@ -76,11 +76,11 @@ const createDateComputed = (getter: () => string | null, setter: (val: string |
const formattedDate = dateVal.toISOString(); const formattedDate = dateVal.toISOString();
setter(formattedDate); setter(formattedDate);
} else { } else {
console.warn('无效的日期值:', val); // console.warn('无效的日期值:', val);
setter(null); setter(null);
} }
} catch (err) { } catch (err) {
console.error('日期处理错误:', err); // console.error('日期处理错误:', err);
setter(null); setter(null);
} }
} }
...@@ -127,15 +127,15 @@ const hasDataChanged = (): { changed: boolean; changedFields: Partial<ItemProps> ...@@ -127,15 +127,15 @@ const hasDataChanged = (): { changed: boolean; changedFields: Partial<ItemProps>
const fetchDetail = async (kvid: string) => { const fetchDetail = async (kvid: string) => {
if (!kvid) return; if (!kvid) return;
console.log(`准备获取详情数据,Kvid: ${kvid},当前loadedKvid: ${detailedData.Kvid}`); // console.log(`准备获取详情数据,Kvid: ${kvid},当前loadedKvid: ${detailedData.Kvid}`);
if (kvid === detailedData.Kvid && Object.keys(detailedData).length > 0) { if (kvid === detailedData.Kvid && Object.keys(detailedData).length > 0) {
console.log('跳过重复请求,使用已缓存的数据'); // console.log('跳过重复请求,使用已缓存的数据');
return; return;
} }
loading.value = true; loading.value = true;
try { try {
console.log('开始获取详情数据,Kvid:', kvid); // console.log('开始获取详情数据,Kvid:', kvid);
// 调用接口获取详情数据 // 调用接口获取详情数据
const response = await axios.get(`/Restful/Kivii.Lims.Entities.Report/Read.json?Kvid=${kvid}`); const response = await axios.get(`/Restful/Kivii.Lims.Entities.Report/Read.json?Kvid=${kvid}`);
...@@ -144,14 +144,14 @@ const fetchDetail = async (kvid: string) => { ...@@ -144,14 +144,14 @@ const fetchDetail = async (kvid: string) => {
Object.assign(detailedData, response.data.Result || {}); Object.assign(detailedData, response.data.Result || {});
// 同时更新原始数据副本 // 同时更新原始数据副本
originalData.value = JSON.parse(JSON.stringify(response.data.Result || {})); originalData.value = JSON.parse(JSON.stringify(response.data.Result || {}));
console.log('获取到详情数据:', response.data.Result); // console.log('获取到详情数据:', response.data.Result);
message.success('详情数据加载成功'); message.success('详情数据加载成功');
} else { } else {
message.error('获取详情数据失败'); message.error('获取详情数据失败');
} }
} catch (error) { } catch (error) {
console.error('获取详情数据失败:', error); // console.error('获取详情数据失败:', error);
message.error('获取详情数据失败,请稍后重试'); message.error('获取详情数据失败,请稍后重试');
} finally { } finally {
loading.value = false; loading.value = false;
...@@ -181,15 +181,14 @@ watch( ...@@ -181,15 +181,14 @@ watch(
// 组件加载时初始化 // 组件加载时初始化
onMounted(() => { onMounted(() => {
console.log('applicationInformation组件已挂载'); // console.log('applicationInformation组件已挂载');
// 确保detailedData对象已正确初始化 // 确保detailedData对象已正确初始化
if (Object.keys(detailedData).length === 0) { if (Object.keys(detailedData).length === 0) {
Object.assign(detailedData, {}); Object.assign(detailedData, {});
} }
// 如果已有选择的实验室名称,确保它被设置 // 如果已有选择的实验室名称,确保它被设置
if (detailedData.SampleName) { if (detailedData.SampleName) {
console.log('已有实验室名称:', detailedData.SampleName); // console.log('已有实验室名称:', detailedData.SampleName);
} }
}); });
...@@ -197,7 +196,7 @@ onMounted(() => { ...@@ -197,7 +196,7 @@ onMounted(() => {
const createEntity = async () => { const createEntity = async () => {
// 验证:Kvid不存在时才创建 // 验证:Kvid不存在时才创建
if (detailedData.Kvid) { if (detailedData.Kvid) {
console.log('实体已存在,无需创建'); // console.log('实体已存在,无需创建');
return { success: true, data: detailedData }; return { success: true, data: detailedData };
} }
...@@ -248,7 +247,7 @@ const createEntity = async () => { ...@@ -248,7 +247,7 @@ const createEntity = async () => {
const requestData = { Item }; const requestData = { Item };
console.log('创建实体请求数据:', requestData); // console.log('创建实体请求数据:', requestData);
// 调用创建接口 // 调用创建接口
const response = await axios.post('/Restful/Kivii.Lims.Entities.Report/Create.json', requestData); const response = await axios.post('/Restful/Kivii.Lims.Entities.Report/Create.json', requestData);
...@@ -259,18 +258,18 @@ const createEntity = async () => { ...@@ -259,18 +258,18 @@ const createEntity = async () => {
Object.assign(detailedData, response.data.Results[0]); Object.assign(detailedData, response.data.Results[0]);
} }
console.log('实体创建成功:', response.data); // console.log('实体创建成功:', response.data);
message.success('实体创建成功'); message.success('实体创建成功');
return { success: true, data: response.data }; return { success: true, data: response.data };
} }
// 处理错误情况 // 处理错误情况
console.error('创建失败:', response.data); // console.error('创建失败:', response.data);
message.error(response.data?.Message || '创建失败,请重试'); message.error(response.data?.Message || '创建失败,请重试');
return { success: false, error: response.data?.Message || '创建失败' }; return { success: false, error: response.data?.Message || '创建失败' };
} catch (error) { } catch (error) {
console.error('创建实体失败:', error); // console.error('创建实体失败:', error);
message.error('系统错误,请稍后重试'); message.error('系统错误,请稍后重试');
return { success: false, error: '系统错误' }; return { success: false, error: '系统错误' };
} finally { } finally {
...@@ -282,7 +281,7 @@ const createEntity = async () => { ...@@ -282,7 +281,7 @@ const createEntity = async () => {
const updateEntity = async (changedFields: Partial<ItemProps> = {}) => { const updateEntity = async (changedFields: Partial<ItemProps> = {}) => {
// 验证:Kvid存在时才更新 // 验证:Kvid存在时才更新
if (!detailedData.Kvid) { if (!detailedData.Kvid) {
console.log('实体不存在,无法更新'); // console.log('实体不存在,无法更新');
message.error('实体不存在,请先创建'); message.error('实体不存在,请先创建');
return { success: false, error: '实体不存在' }; return { success: false, error: '实体不存在' };
} }
...@@ -298,7 +297,7 @@ const updateEntity = async (changedFields: Partial<ItemProps> = {}) => { ...@@ -298,7 +297,7 @@ const updateEntity = async (changedFields: Partial<ItemProps> = {}) => {
} }
}; };
console.log('更新实体请求数据:', requestData); // console.log('更新实体请求数据:', requestData);
// 调用更新接口 // 调用更新接口
const response = await axios.post('/Restful/Kivii.Lims.Entities.Report/Update.json', requestData); const response = await axios.post('/Restful/Kivii.Lims.Entities.Report/Update.json', requestData);
...@@ -310,18 +309,18 @@ const updateEntity = async (changedFields: Partial<ItemProps> = {}) => { ...@@ -310,18 +309,18 @@ const updateEntity = async (changedFields: Partial<ItemProps> = {}) => {
Object.assign(detailedData, response.data.Results[0]); Object.assign(detailedData, response.data.Results[0]);
} }
console.log('实体更新成功:', response.data); // console.log('实体更新成功:', response.data);
message.success('实体更新成功'); message.success('实体更新成功');
return { success: true, data: response.data }; return { success: true, data: response.data };
} }
// 处理错误情况 // 处理错误情况
console.error('更新失败:', response.data); // console.error('更新失败:', response.data);
message.error(response.data?.Message || '更新失败,请重试'); message.error(response.data?.Message || '更新失败,请重试');
return { success: false, error: response.data?.Message || '更新失败' }; return { success: false, error: response.data?.Message || '更新失败' };
} catch (error) { } catch (error) {
console.error('更新实体失败:', error); // console.error('更新实体失败:', error);
message.error('系统错误,请稍后重试'); message.error('系统错误,请稍后重试');
return { success: false, error: '系统错误' }; return { success: false, error: '系统错误' };
} finally { } finally {
...@@ -331,10 +330,10 @@ const updateEntity = async (changedFields: Partial<ItemProps> = {}) => { ...@@ -331,10 +330,10 @@ const updateEntity = async (changedFields: Partial<ItemProps> = {}) => {
// 智能验证和保存方法(统一入口) // 智能验证和保存方法(统一入口)
const validateAndSave = async () => { const validateAndSave = async () => {
console.log('开始验证和保存数据...'); // console.log('开始验证和保存数据...');
// 1. 验证必填字段 // 1. 验证必填字段
console.log('验证实验室名称:', detailedData.SampleName); // console.log('验证实验室名称:', detailedData.SampleName);
if (!detailedData.SampleName) { if (!detailedData.SampleName) {
message.error('请输入实验室名称'); message.error('请输入实验室名称');
return false; return false;
...@@ -345,7 +344,7 @@ const validateAndSave = async () => { ...@@ -345,7 +344,7 @@ const validateAndSave = async () => {
if (!hasKvid) { if (!hasKvid) {
// 没有Kvid,需要创建 // 没有Kvid,需要创建
console.log('检测到无Kvid,执行创建操作'); // console.log('检测到无Kvid,执行创建操作');
const result = await createEntity(); const result = await createEntity();
if (result.success) { if (result.success) {
// 创建成功后更新原始数据副本 // 创建成功后更新原始数据副本
...@@ -358,12 +357,12 @@ const validateAndSave = async () => { ...@@ -358,12 +357,12 @@ const validateAndSave = async () => {
if (!changed) { if (!changed) {
// 没有变化,直接返回成功 // 没有变化,直接返回成功
console.log('数据没有变化,无需更新'); // console.log('数据没有变化,无需更新');
message.success('数据已是最新,无需保存'); message.success('数据已是最新,无需保存');
return true; return true;
} else { } else {
// 有变化,需要更新 // 有变化,需要更新
console.log('检测到数据变化,执行更新操作,变更字段:', changedFields); // console.log('检测到数据变化,执行更新操作,变更字段:', changedFields);
const result = await updateEntity(changedFields); const result = await updateEntity(changedFields);
if (result.success) { if (result.success) {
// 更新成功后更新原始数据副本 // 更新成功后更新原始数据副本
......
...@@ -75,7 +75,7 @@ async function fetchTestPlanOptions() { ...@@ -75,7 +75,7 @@ async function fetchTestPlanOptions() {
// 调用标准实体查询接口 // 调用标准实体查询接口
const response = await axios.post('/Restful/Kivii.Standards.Entities.Standard/Query.json?Type=比对测试'); const response = await axios.post('/Restful/Kivii.Standards.Entities.Standard/Query.json?Type=比对测试');
console.log('测试方案响应数据:', response.data); // console.log('测试方案响应数据:', response.data);
// 添加数据存在性检查 // 添加数据存在性检查
if (response.data && response.data.Results) { if (response.data && response.data.Results) {
...@@ -85,12 +85,12 @@ async function fetchTestPlanOptions() { ...@@ -85,12 +85,12 @@ async function fetchTestPlanOptions() {
value: item.Kvid value: item.Kvid
})); }));
} else { } else {
console.error('无效的数据格式:', response.data); // console.error('无效的数据格式:', response.data);
message.error('数据格式不正确'); message.error('数据格式不正确');
} }
} catch (error) { } catch (error) {
message.error('获取测试方案失败'); message.error('获取测试方案失败');
console.error('获取测试方案失败:', error); // console.error('获取测试方案失败:', error);
} finally { } finally {
loading.value = false; loading.value = false;
} }
......
...@@ -271,7 +271,7 @@ async function fetchAuditItems() { ...@@ -271,7 +271,7 @@ async function fetchAuditItems() {
message.success('审核项目加载成功'); message.success('审核项目加载成功');
} catch (error) { } catch (error) {
message.error('获取审核项目失败'); message.error('获取审核项目失败');
console.error('获取审核项目失败:', error); // console.error('获取审核项目失败:', error);
} finally { } finally {
loading.value = false; loading.value = false;
} }
......
...@@ -232,7 +232,7 @@ async function fetchAuditSchemes() { ...@@ -232,7 +232,7 @@ async function fetchAuditSchemes() {
message.success('审核方案加载成功'); message.success('审核方案加载成功');
} catch (error) { } catch (error) {
message.error('获取审核方案失败'); message.error('获取审核方案失败');
console.error('获取审核方案失败:', error); // console.error('获取审核方案失败:', error);
} finally { } finally {
schemesLoading.value = false; schemesLoading.value = false;
} }
...@@ -288,7 +288,7 @@ async function fetchAuditTeam() { ...@@ -288,7 +288,7 @@ async function fetchAuditTeam() {
message.success('审核团队加载成功'); message.success('审核团队加载成功');
} catch (error) { } catch (error) {
message.error('获取审核团队失败'); message.error('获取审核团队失败');
console.error('获取审核团队失败:', error); // console.error('获取审核团队失败:', error);
} finally { } finally {
teamLoading.value = false; teamLoading.value = false;
} }
......
<script setup lang="ts"> <script setup lang="ts">
import { computed, defineEmits, defineProps, h, onMounted, ref, resolveComponent, watch } from 'vue'; import { computed, defineEmits, defineProps, h,reactive, onMounted,withDefaults, ref, resolveComponent, watch } from 'vue';
import FileListView from './fileListView.vue'; // '/codes/fileListView.vue'; import FileListView from './fileListView.vue'; // '/codes/fileListView.vue';
...@@ -40,64 +40,101 @@ interface FileItem { ...@@ -40,64 +40,101 @@ interface FileItem {
[key: string]: any; // 添加索引签名,以支持可能出现的其他字段 [key: string]: any; // 添加索引签名,以支持可能出现的其他字段
} }
// eslint-disable-next-line @typescript-eslint/no-unused-vars // 定义Item对象的接口
const props = defineProps({ interface ItemProps {
fileList: { Kvid?: string;
type: Array as () => FileItem[], [key: string]: any;
required: true }
},
kvid: {
type: String,
default: ''
}
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const emit = defineEmits(['update:file-list', 'update:reviewResult', 'update:reviewComment']);
// 定义props
const props = withDefaults(
defineProps<{
item?: ItemProps;
active?: boolean; // 新增:是否激活状态,用于按需加载
}>(),
{
item: () => ({}),
active: false
}
);
// 状态变量 // 状态变量
const titleOptions = ref<SelectOption[]>([]); const titleOptions = ref<any[]>([]);
const selectedStandardKvid = ref<string>(''); const selectedStandard = reactive<any>({}); // 存储选中的完整对象
const fileData = ref<FileItem[]>([]); const fileData = ref<FileItem[]>([]); // 改回ref,避免过度响应式
const loading = ref<boolean>(false); const loading = ref<boolean>(false);
// 记录当前已加载的reportKvid,避免重复请求 // 存储API返回的详细数据
const loadedReportKvid = ref(''); const detailedData = reactive<ItemProps>({});
// 控制fileListView模态框显示 // 控制fileListView模态框显示
const showFileListView = ref<boolean>(false); const showFileListView = ref<boolean>(false);
// 根据选择的标题筛选数据 // 使用ref来避免计算属性的循环更新问题
const filteredData = computed(() => { const selectedStandardKvid = ref<string>('');
if (!selectedStandardKvid.value) {
return fileData.value; // 计算是否有数据存在,用于控制NSelect状态
} const hasExistingData = computed(() => {
return fileData.value.filter(file => file.StandardKvid === selectedStandardKvid.value); return fileData.value.length > 0;
}); });
// 根据选择的标题筛选数据 - 优化性能
const filteredData = computed(() => {
return fileData.value;
});
// 辅助函数:将API的StatusType映射为显示状态
const mapStatusType = (statusType: string) => {
const statusMap: { [key: string]: string } = {
Unsupported: '草稿',
BeforeTest: '待上传',
Asigning: '已上传',
Testing: '审核中',
BeforeReview: '待复核',
TestFinished: '不通过',
TestCollected: '已通过'
};
return statusMap[statusType] || '草稿';
};
// 辅助函数:根据状态获取颜色
const getStatusColor = (status: string) => {
const statusColorMap: { [key: string]: string } = {
BeforeTest: '#f56a00', // 橙色 - 待处理
Asigning: '#1890ff', // 蓝色 - 进行中
Testing: '#722ed1', // 紫色 - 重要评审
BeforeReview: '#eb2f96', // 粉红色 - 测试阶段
TestFinished: '#13c2c2', // 青色 - 即将完成
TestCollected: '#52c41a' // 绿色 - 已完成
};
return statusColorMap[status] || '#666';
};
// 获取文件类型数据 // 获取文件类型数据
async function fetchTitleOptions() { async function fetchTitleOptions() {
console.log('🔄 FileReview: 开始加载文件类型数据');
try { try {
loading.value = true; loading.value = true;
// 调用标准实体查询接口 // 调用标准实体查询接口
const response = await axios.post('/Restful/Kivii.Standards.Entities.Standard/Query.json?Type=文件审核'); const response = await axios.post('/Restful/Kivii.Standards.Entities.Standard/Query.json?Type=文件审核');
console.log('完整响应数据:', response.data); // console.log('完整响应数据:', response.data);
// 添加数据存在性检查 // 添加数据存在性检查
if (response.data && response.data.Results) { if (response.data && response.data.Results) {
// 直接使用Results数组
titleOptions.value = response.data.Results.map((item: any) => ({ // 将API返回的数据转换为NSelect需要的格式
titleOptions.value = response.data.Results.map((item: any, index: number) => ({
label: item.Title, label: item.Title,
value: item.Kvid value: item.Kvid,
// 可以选择以下任一方式存储完整对象信息:
// 方式1:直接将完整对象作为额外属性
fullObject: item
})); }));
} else { } else {
console.error('无效的数据格式:', response.data); // console.error('无效的数据格式:', response.data);
message.error('数据格式不正确'); message.error('数据格式不正确');
} }
} catch (error) { } catch (error) {
message.error('获取文件类型失败'); message.error('获取文件类型失败');
console.error('获取文件类型失败:', error); // console.error('获取文件类型失败:', error);
} finally { } finally {
loading.value = false; loading.value = false;
} }
...@@ -107,32 +144,46 @@ async function fetchTitleOptions() { ...@@ -107,32 +144,46 @@ async function fetchTitleOptions() {
async function fetchFileDetails() { async function fetchFileDetails() {
if (!selectedStandardKvid.value) return; if (!selectedStandardKvid.value) return;
// 如果数据已存在,直接返回(UI已有提示)
if(fileData.value.length > 0) {
return;
}
try { try {
loading.value = true; loading.value = true;
const queryParams: any = { const queryParams: any = {
StandardKvid: selectedStandardKvid.value StandardKvid: selectedStandardKvid.value,
}; OrderBy:'SortId'
};
// 如果有报告Kvid,添加到查询参数中
if (props.kvid) {
queryParams.ReportKvid = props.kvid;
}
const response = await axios.post('/Restful/Kivii.Standards.Entities.Detection/Query.json', queryParams); const response = await axios.post('/Restful/Kivii.Standards.Entities.DetectionEx/DetectionWithPriceQuery.json', queryParams);
if (response.data && response.data.Results) { if (response.data && response.data.Results) {
// 直接使用API返回的数据 const data :any={
fileData.value = response.data.Results; Detections:response.data.Results,
ReportKvid:detailedData.Kvid
}
const resp=await axios.post('/Restful/Kivii.Lims.Entities.ReportItem/Detection.json', data);
if(resp.data&&resp.data.Results){
fileData.value = resp.data.Results.map((item: any) => ({
// 直接使用API字段名
...item,
// 向父组件更新文件列表 // 保留转换后的自定义字段
emit('update:file-list', fileData.value); Status: mapStatusType(item.StatusType),
StatusColor: getStatusColor(item.StatusType)
}));
}else{
message.error('创建文件审核数据失败');
}
} else { } else {
message.error('获取文件数据失败'); message.error('获取文件数据失败');
} }
} catch (error) { } catch (error) {
message.error('获取文件详情失败'); message.error('获取文件详情失败');
console.error(error); // console.error(error);
} finally { } finally {
loading.value = false; loading.value = false;
} }
...@@ -142,40 +193,41 @@ async function fetchFileDetails() { ...@@ -142,40 +193,41 @@ async function fetchFileDetails() {
async function fetchDataByReportKvid(reportKvid: string) { async function fetchDataByReportKvid(reportKvid: string) {
if (!reportKvid) return; if (!reportKvid) return;
console.log(`准备获取文件审核数据,ReportKvid: ${reportKvid},当前loadedReportKvid: ${loadedReportKvid.value}`); if (reportKvid === detailedData.Kvid && fileData.value.length > 0) {
if (reportKvid === loadedReportKvid.value && fileData.value.length > 0) { console.log('🔄 FileReview: 跳过重复请求,使用已缓存的数据');
console.log('跳过重复请求,使用已缓存的数据');
return; return;
} }
console.log('🔄 FileReview: 开始获取文件审核数据,ReportKvid:', reportKvid);
try { try {
loading.value = true; loading.value = true;
const response = await axios.post('/Restful/Kivii.Standards.Entities.Detection/Query.json', { const response = await axios.post('/Restful/Kivii.Lims.Entities.ReportItem/QueryEx.json', {
ReportKvid: reportKvid ReportKvid: reportKvid,
OrderBy:'SortId,SortIdEx,Kvid',
WorkGroupName:'文件审核'
}); });
if (response.data && response.data.Results) { if (response.data && response.data.Results&&response.data.Results.length>0) {
// 直接使用API返回的数据 // 直接使用API返回的数据
fileData.value = response.data.Results; // fileData.value = response.data.Results;
// fileData.value.forEach((item: any) => {
// 如果有StandardKvid,自动选中对应的标题 // item.StatusType = mapStatusType(item.StatusType);
if (fileData.value.length > 0 && fileData.value[0].StandardKvid) { // });
selectedStandardKvid.value = fileData.value[0].StandardKvid; fileData.value = response.data.Results.map((item: any) => ({
} // 直接使用API字段名
...item,
// 向父组件更新文件列表
emit('update:file-list', fileData.value); // 保留转换后的自定义字段
Status: mapStatusType(item.StatusType),
// 更新已加载的reportKvid StatusColor: getStatusColor(item.StatusType)
loadedReportKvid.value = reportKvid; }));
message.success('文件审核数据加载成功'); message.success('文件审核数据加载成功');
} else { } else {
message.info('暂无文件审核数据'); message.info('暂无文件审核数据');
} }
} catch (error) { } catch (error) {
console.error('获取文件审核数据失败:', error); // console.error('获取文件审核数据失败:', error);
message.error('获取文件审核数据失败,请稍后重试'); message.error('获取文件审核数据失败,请稍后重试');
} finally { } finally {
loading.value = false; loading.value = false;
...@@ -184,33 +236,69 @@ async function fetchDataByReportKvid(reportKvid: string) { ...@@ -184,33 +236,69 @@ async function fetchDataByReportKvid(reportKvid: string) {
// 处理标题选择变化 // 处理标题选择变化
function handleTitleChange(value: string) { function handleTitleChange(value: string) {
selectedStandardKvid.value = value; selectedStandardKvid.value = value; // 同步选中值
// 获取选中项的完整对象信息
const selectedOption = titleOptions.value.find(option => option.value === value);
if (selectedOption) {
// 清空现有属性
Object.keys(selectedStandard).forEach(key => {
delete selectedStandard[key];
});
// 添加新属性
Object.keys(selectedOption.fullObject).forEach(key => {
selectedStandard[key] = selectedOption.fullObject[key];
});
}
fetchFileDetails(); fetchFileDetails();
} }
// 监听kvid的变化,如果有值则获取详情数据 // 监听props.item变化,同步到detailedData
watch( watch(
() => props.kvid, () => props.item,
newKvid => { newItem => {
if (newKvid && newKvid !== loadedReportKvid.value) { if (newItem && newItem.Kvid && newItem.Kvid !== detailedData.Kvid) {
fetchDataByReportKvid(newKvid); fetchDataByReportKvid(newItem.Kvid);
} }
// 保持detailedData为props.item的响应式副本
Object.assign(detailedData, newItem || {});
}, },
{ immediate: true } { immediate: true, deep: true }
); );
// 页面加载时获取文件类型
// 页面加载时按需获取数据
onMounted(() => { onMounted(() => {
fetchTitleOptions(); // 只有在激活状态下才加载数据
if (props.active) {
fetchTitleOptions();
// 如果有kvid,获取数据 // 如果有kvid,获取数据
if (props.kvid && props.kvid !== loadedReportKvid.value) { if (props.item && props.item.Kvid && props.item.Kvid !== detailedData.Kvid) {
fetchDataByReportKvid(props.kvid); fetchDataByReportKvid(props.item.Kvid);
}
} }
}); });
// 监听active属性变化,实现按需加载
watch(
() => props.active,
(newActive) => {
if (newActive && titleOptions.value.length === 0) {
// 第一次激活且数据未加载时,加载数据
fetchTitleOptions();
if (props.item && props.item.Kvid && props.item.Kvid !== detailedData.Kvid) {
fetchDataByReportKvid(props.item.Kvid);
}
}
},
{ immediate: true }
);
// 表格列定义 // 表格列定义
const columns = ref<DataTableColumn<FileItem>[]>([ const columns = ref<any[]>([
{ {
title: '文件名称', title: '文件名称',
key: 'Title', key: 'Title',
...@@ -223,27 +311,31 @@ const columns = ref<DataTableColumn<FileItem>[]>([ ...@@ -223,27 +311,31 @@ const columns = ref<DataTableColumn<FileItem>[]>([
}, },
{ {
title: '文件状态', title: '文件状态',
key: 'StatusType', key: 'Status',
width: '15%', width: '15%',
align: 'center', align: 'center',
render(row: FileItem) { render(row: any) {
const statusMap: Record<string, { type: string; label: string }> = { const statusColor = row.StatusColor || '#666';
Disable: { type: 'warning', label: '待上传' },
approved: { type: 'success', label: '已通过' }
};
const status = row.StatusType || '';
const { type, label } = statusMap[status] || { type: 'default', label: status || '未知' };
return h( return h(
resolveComponent('n-tag'), resolveComponent('n-tag'),
{ {
type, style: {
backgroundColor: statusColor,
color: '#fff',
border: 'none',
fontWeight: '500',
borderRadius: '6px',
padding: '4px 8px',
fontSize: '12px',
boxShadow: `0 2px 4px ${statusColor}30`
},
size: 'small' size: 'small'
}, },
{ default: () => label } { default: () => row.Status || '未知' }
); );
} }
}, },
{ {
title: '操作', title: '操作',
key: 'actions', key: 'actions',
width: 200, width: 200,
...@@ -254,16 +346,41 @@ const columns = ref<DataTableColumn<FileItem>[]>([ ...@@ -254,16 +346,41 @@ const columns = ref<DataTableColumn<FileItem>[]>([
resolveComponent('n-button'), resolveComponent('n-button'),
{ {
size: 'small', size: 'small',
style: {
backgroundColor: '#1890ff',
color: '#fff',
border: 'none',
borderRadius: '4px',
padding: '4px 12px',
fontSize: '12px',
fontWeight: '500'
},
onClick: () => viewFile(row) onClick: () => viewFile(row)
}, },
{ default: () => '查看' } { default: () => '附件' }
), ),
h( h(
resolveComponent('n-button'), resolveComponent('n-button'),
{ {
size: 'small', size: 'small',
type: 'error', style: {
onClick: () => deleteFileRecord(row) backgroundColor: '#ff4d4f',
color: '#fff',
border: 'none',
borderRadius: '4px',
padding: '4px 12px',
fontSize: '12px',
fontWeight: '500'
},
onClick: () => {
dialog.warning({
title: '确认删除',
content: `确定要删除文件"${row.Title}"吗?此操作不可撤销。`,
positiveText: '确定删除',
negativeText: '取消',
onPositiveClick: () => deleteFileRecord(row)
});
}
}, },
{ default: () => '删除' } { default: () => '删除' }
) )
...@@ -275,18 +392,90 @@ const columns = ref<DataTableColumn<FileItem>[]>([ ...@@ -275,18 +392,90 @@ const columns = ref<DataTableColumn<FileItem>[]>([
// 查看文件 // 查看文件
function viewFile(row: FileItem) { function viewFile(row: FileItem) {
// 可以根据需要将文件信息传递给fileListView组件 // 可以根据需要将文件信息传递给fileListView组件
console.log(`查看文件: ${row.Title}`); // console.log(`查看文件: ${row.Title}`);
showFileListView.value = true; showFileListView.value = true;
} }
// 封装删除实体的方法
async function deleteEntities(kvids: string[]) {
if (!kvids || kvids.length === 0) {
message.error('请选择要删除的项目');
return false;
}
try {
loading.value = true;
const response = await axios.post('/Restful/Kivii.Lims.Entities.ReportItem/Delete.json', {
Kvids: kvids
});
if (response.data && response.data.Results && response.data.Results.length>0) {
message.success(`成功删除 ${kvids.length} 个文件`);
return true;
} else {
message.error(response.data?.Message || '删除失败');
return false;
}
} catch (error) {
console.error('删除文件失败:', error);
message.error('删除文件失败,请稍后重试');
return false;
} finally {
loading.value = false;
}
}
// 删除文件记录 // 删除文件记录
function deleteFileRecord(row: FileItem) { async function deleteFileRecord(row: FileItem) {
// 实际应该调用删除API if (!row.Kvid) {
message.success(`文件"${row.Title}"删除成功`); message.error('无效的文件ID');
// 从列表中移除 return;
fileData.value = fileData.value.filter(item => item.Kvid !== row.Kvid); }
// 向父组件更新文件列表
emit('update:file-list', fileData.value); // 调用删除接口
const success = await deleteEntities([row.Kvid]);
if (success) {
// 从列表中移除
fileData.value = fileData.value.filter(item => item.Kvid !== row.Kvid);
}
}
// 清空所有文件数据
function clearAllFileData() {
dialog.warning({
title: '确认删除',
content: '确定要删除所有文件审核数据吗?此操作不可撤销。',
positiveText: '确定删除',
negativeText: '取消',
onPositiveClick: async () => {
if (fileData.value.length === 0) {
message.info('没有数据需要删除');
return;
}
// 收集所有Kvid
const kvids = fileData.value.map(item => item.Kvid).filter(kvid => kvid);
if (kvids.length === 0) {
message.error('没有有效的数据ID');
return;
}
// 调用删除接口
const success = await deleteEntities(kvids);
if (success) {
fileData.value = [];
selectedStandardKvid.value = '';
// 清空selectedStandard对象
Object.keys(selectedStandard).forEach(key => {
delete selectedStandard[key];
});
}
}
});
} }
</script> </script>
...@@ -302,16 +491,50 @@ function deleteFileRecord(row: FileItem) { ...@@ -302,16 +491,50 @@ function deleteFileRecord(row: FileItem) {
<span>审核文件提交</span> <span>审核文件提交</span>
</div> </div>
<NFormItem label="选择文件类型"> <NFormItem label="选择文件类型">
<NSelect <div class="file-type-selector">
v-model:value="selectedStandardKvid" <div class="selector-row">
:options="titleOptions" <NSelect
placeholder="选择文件类型" v-model:value="selectedStandardKvid"
@update:value="handleTitleChange" :options="titleOptions"
></NSelect> :placeholder="hasExistingData ? '已有数据,请先删除' : '选择文件类型'"
:disabled="hasExistingData"
label-field="label"
value-field="value"
@update:value="handleTitleChange"
class="selector-input"
></NSelect>
<!-- 有数据时显示删除按钮 -->
<NButton
v-if="hasExistingData"
type="error"
size="small"
@click="clearAllFileData"
class="clear-button"
>
<template #icon>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16">
<path fill="currentColor" d="M9,3V4H4V6H5V19A2,2 0 0,0 7,21H17A2,2 0 0,0 19,19V6H20V4H15V3H9M7,6H17V19H7V6M9,8V17H11V8H9M13,8V17H15V8H13Z" />
</svg>
</template>
清空数据
</NButton>
</div>
<!-- 简洁的状态提示 -->
<div v-if="hasExistingData" class="status-tip">
<NIcon size="14" color="#f0a020">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="currentColor" d="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z" />
</svg>
</NIcon>
<span>已有 {{ fileData.length }} 条文件审核数据</span>
</div>
</div>
</NFormItem> </NFormItem>
<NDataTable <NDataTable
:columns="columns" :columns="columns"
:data="filteredData" :data="filteredData"
:bordered="false" :bordered="false"
...@@ -353,4 +576,54 @@ function deleteFileRecord(row: FileItem) { ...@@ -353,4 +576,54 @@ function deleteFileRecord(row: FileItem) {
.mt-4 { .mt-4 {
margin-top: 16px; margin-top: 16px;
} }
.file-type-selector {
width: 100%;
}
.selector-row {
display: flex;
align-items: center;
gap: 12px;
width: 100%;
}
.selector-input {
flex: 1;
}
.clear-button {
flex-shrink: 0;
border-radius: 6px;
height: 34px;
padding: 0 12px;
display: flex;
align-items: center;
gap: 6px;
}
.status-tip {
display: flex;
align-items: center;
gap: 6px;
margin-top: 6px;
font-size: 12px;
color: #f0a020;
padding: 4px 0;
}
.status-tip span {
line-height: 1;
}
/* 禁用状态下的选择器样式 */
:deep(.n-base-selection--disabled) {
background-color: #fef2f2;
border-color: #fecaca;
}
:deep(.n-base-selection--disabled .n-base-selection-placeholder) {
color: #dc2626 !important;
font-weight: 500;
}
</style> </style>
...@@ -3,8 +3,9 @@ import { computed, onMounted, reactive, ref, watch, withDefaults } from 'vue'; ...@@ -3,8 +3,9 @@ import { computed, onMounted, reactive, ref, watch, withDefaults } from 'vue';
import ApplicationInformation from './applicationInformation.vue'; // '/codes/applicationInformation.vue'; import ApplicationInformation from './applicationInformation.vue'; // '/codes/applicationInformation.vue';
import FileReview from './fileReview.vue'; // '/codes/fileReview.vue'; import FileReview from './fileReview.vue'; // '/codes/fileReview.vue';
import ComparisonTest from './comparisonTest.vue'; // '/codes/comparisonTest.vue'; import ComparisonTest from './comparisonTest.vue'; // '/codes/comparisonTest.vue';
import FieldReviewPlanning from './fieldReviewPlanning.vue'; // '/codes/fieldReviewPlanning.vue'; // import FieldReviewPlanning from './fieldReviewPlanning.vue'; // '/codes/fieldReviewPlanning.vue';
import FieldReviewExecution from './fieldReviewExecution.vue'; // '/codes/fieldReviewExecution.vue'; // import FieldReviewExecution from './fieldReviewExecution.vue'; // '/codes/fieldReviewExecution.vue';
import { number } from 'echarts';
// 定义Item对象的接口 // 定义Item对象的接口
interface ItemProps { interface ItemProps {
...@@ -27,7 +28,7 @@ const emit = defineEmits(['close-and-refresh']); ...@@ -27,7 +28,7 @@ const emit = defineEmits(['close-and-refresh']);
// 返回列表并刷新数据 // 返回列表并刷新数据
const handleClose = () => { const handleClose = () => {
console.log('返回列表并刷新数据'); // console.log('返回列表并刷新数据');
// 发送关闭并刷新数据的信号 // 发送关闭并刷新数据的信号
emit('close-and-refresh'); emit('close-and-refresh');
}; };
...@@ -57,6 +58,9 @@ const cssVars = computed(() => ({ ...@@ -57,6 +58,9 @@ const cssVars = computed(() => ({
// 当前步骤 // 当前步骤
const currentStep = ref(0); const currentStep = ref(0);
// 记录已访问过的步骤(用于优化数据加载)
const visitedSteps = ref(new Set([0])); // 默认第一步已访问
// 加载状态 // 加载状态
const loading = ref(false); const loading = ref(false);
...@@ -73,16 +77,28 @@ watch( ...@@ -73,16 +77,28 @@ watch(
{ immediate: true, deep: true } { immediate: true, deep: true }
); );
// 定义FileItem接口,与FileReview组件保持一致
interface FileItem {
id?: number;
Kvid: string;
StandardKvid: string;
Title?: string;
Code?: string;
Unit?: string;
QualifiedValue?: string;
Description?: string;
StatusType?: string;
ReportKvid?: string;
// 兼容原有字段
name?: string;
type?: string;
status?: string;
size?: string;
[key: string]: any;
}
// 文件列表 // 文件列表
const fileList = ref< const fileList = ref<FileItem[]>([]);
Array<{
id: number;
name: string;
type: string;
status: string;
size?: string;
}>
>([]);
// 测试项目 // 测试项目
const testItems = ref([ const testItems = ref([
...@@ -117,13 +133,14 @@ const availabilityData = reactive({ ...@@ -117,13 +133,14 @@ const availabilityData = reactive({
// 下一步 // 下一步
function nextStep() { function nextStep() {
if (currentStep.value < 4) { if (currentStep.value < 2) { // 修改为2,因为只有3个步骤
// 如果当前是第一步(申请信息填写),则调用子组件的创建接口 // 如果当前是第一步(申请信息填写),则调用子组件的创建接口
if (currentStep.value === 0) { if (currentStep.value === 0) {
// // 如果已经存在Kvid(从props的Item或formModel中),则直接进入下一步 // // 如果已经存在Kvid(从props的Item或formModel中),则直接进入下一步
// if ((props.item && props.item.Kvid) || formModel.Kvid) { // if ((props.item && props.item.Kvid) || formModel.Kvid) {
// console.log('已存在Kvid,直接进入下一步'); // console.log('已存在Kvid,直接进入下一步');
// currentStep.value += 1; // currentStep.value += 1;
// visitedSteps.value.add(currentStep.value);
// return; // return;
// } // }
...@@ -134,9 +151,9 @@ function nextStep() { ...@@ -134,9 +151,9 @@ function nextStep() {
if (success) { if (success) {
// 保存成功后进入下一步,并获取返回的Kvid // 保存成功后进入下一步,并获取返回的Kvid
Object.assign(formModel, appInfoRef.value.detailedData); Object.assign(formModel, appInfoRef.value.detailedData);
// formModel = { ...appInfoRef.value.detailedData };
// formModel.Kvid = appInfoRef.value.detailedData.Kvid || '';
currentStep.value += 1; currentStep.value += 1;
// 记录新访问的步骤
visitedSteps.value.add(currentStep.value);
} }
}); });
} else { } else {
...@@ -145,6 +162,8 @@ function nextStep() { ...@@ -145,6 +162,8 @@ function nextStep() {
} else { } else {
// 不是第一步,直接进入下一步 // 不是第一步,直接进入下一步
currentStep.value += 1; currentStep.value += 1;
// 记录新访问的步骤
visitedSteps.value.add(currentStep.value);
} }
} }
} }
...@@ -153,6 +172,7 @@ function nextStep() { ...@@ -153,6 +172,7 @@ function nextStep() {
function prevStep() { function prevStep() {
if (currentStep.value > 0) { if (currentStep.value > 0) {
currentStep.value -= 1; currentStep.value -= 1;
// 上一步时不需要添加到visitedSteps,因为已经访问过了
} }
} }
...@@ -165,11 +185,11 @@ function saveApplication(submit = true) { ...@@ -165,11 +185,11 @@ function saveApplication(submit = true) {
} }
message.success('申请提交成功'); message.success('申请提交成功');
console.log('Submit application:', { /* console.log('Submit application:', {
form: formModel, form: formModel,
files: fileList.value, files: fileList.value,
tests: testItems.value.filter(item => item.selected) tests: testItems.value.filter(item => item.selected)
}); }); */
}); });
} }
</script> </script>
...@@ -192,22 +212,97 @@ function saveApplication(submit = true) { ...@@ -192,22 +212,97 @@ function saveApplication(submit = true) {
<NCard style="margin-bottom: 10px"> <NCard style="margin-bottom: 10px">
<div class="page-header"> <div class="page-header">
<NSteps :current="currentStep" class="mt-8"> <div style="width: 100%; display: flex; align-items: center;">
<NStep title="申请信息填写" :status="currentStep === 0 ? 'process' : 'finish'"></NStep> <!-- 第一步 -->
<NStep <div style="flex: 1; text-align: center; position: relative;">
title="审核文件提交" <div style="display: flex; align-items: center; justify-content: center; margin-bottom: 12px;">
:status="currentStep === 1 ? 'process' : currentStep > 1 ? 'finish' : 'wait'" <div :style="{
></NStep> width: '32px',
<NStep height: '32px',
title="比对测试选择" borderRadius: '50%',
:status="currentStep === 2 ? 'process' : currentStep > 2 ? 'finish' : 'wait'" display: 'flex',
></NStep> alignItems: 'center',
<NStep justifyContent: 'center',
title="现场审核规划" fontSize: '14px',
:status="currentStep === 3 ? 'process' : currentStep > 3 ? 'finish' : 'wait'" fontWeight: 'bold',
></NStep> backgroundColor: currentStep >= 0 ? '#2080f0' : '#f0f0f0',
<NStep title="现场审核执行" :status="currentStep === 4 ? 'process' : 'wait'"></NStep> color: currentStep >= 0 ? 'white' : '#999',
</NSteps> border: currentStep === 0 ? '2px solid #2080f0' : 'none'
}">
{{ currentStep > 0 ? '✓' : '1' }}
</div>
</div>
<div :style="{
fontSize: '14px',
color: currentStep === 0 ? '#2080f0' : '#333',
fontWeight: currentStep === 0 ? 'bold' : 'normal'
}">
申请信息填写
</div>
</div>
<!-- 连接线1 -->
<div style="flex: 0 0 80px; height: 2px; background: #e0e0e0; margin: 0 20px; margin-bottom: 30px;"></div>
<!-- 第二步 -->
<div style="flex: 1; text-align: center; position: relative;">
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 12px;">
<div :style="{
width: '32px',
height: '32px',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '14px',
fontWeight: 'bold',
backgroundColor: currentStep >= 1 ? '#2080f0' : '#f0f0f0',
color: currentStep >= 1 ? 'white' : '#999',
border: currentStep === 1 ? '2px solid #2080f0' : 'none'
}">
{{ currentStep > 1 ? '✓' : '2' }}
</div>
</div>
<div :style="{
fontSize: '14px',
color: currentStep === 1 ? '#2080f0' : '#333',
fontWeight: currentStep === 1 ? 'bold' : 'normal'
}">
审核文件提交
</div>
</div>
<!-- 连接线2 -->
<div style="flex: 0 0 80px; height: 2px; background: #e0e0e0; margin: 0 20px; margin-bottom: 30px;"></div>
<!-- 第三步 -->
<div style="flex: 1; text-align: center; position: relative;">
<div style="display: flex; align-items: center; justify-content: center; margin-bottom: 12px;">
<div :style="{
width: '32px',
height: '32px',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '14px',
fontWeight: 'bold',
backgroundColor: currentStep >= 2 ? '#2080f0' : '#f0f0f0',
color: currentStep >= 2 ? 'white' : '#999',
border: currentStep === 2 ? '2px solid #2080f0' : 'none'
}">
{{ currentStep > 2 ? '✓' : '3' }}
</div>
</div>
<div :style="{
fontSize: '14px',
color: currentStep === 2 ? '#2080f0' : '#333',
fontWeight: currentStep === 2 ? 'bold' : 'normal'
}">
比对测试选择
</div>
</div>
</div>
</div> </div>
</NCard> </NCard>
...@@ -220,39 +315,45 @@ function saveApplication(submit = true) { ...@@ -220,39 +315,45 @@ function saveApplication(submit = true) {
require-mark-placement="right-hanging" require-mark-placement="right-hanging"
size="medium" size="medium"
> >
<!-- 步骤1: 申请信息填写 --> <!-- 步骤1: 申请信息填写 -->
<ApplicationInformation v-if="currentStep === 0" ref="appInfoRef" :item="formModel"></ApplicationInformation> <ApplicationInformation
v-if="visitedSteps.has(0) && currentStep === 0"
ref="appInfoRef"
:item="formModel"
:active="currentStep === 0"
></ApplicationInformation>
<!-- 步骤2: 审核文件提交 --> <!-- 步骤2: 审核文件提交 -->
<FileReview <FileReview
v-if="currentStep === 1" v-if="visitedSteps.has(1) && currentStep === 1"
:file-list="fileList" :item="formModel"
:Kvid="formModel.Kvid" :active="currentStep === 1"
@update:file-list="newList => (fileList = newList)" @update:file-list="newList => (fileList = newList)"
></FileReview> ></FileReview>
<!-- 步骤3: 比对测试选择 --> <!-- 步骤3: 比对测试选择 -->
<ComparisonTest <ComparisonTest
v-if="currentStep === 2" v-if="visitedSteps.has(2) && currentStep === 2"
:test-items="testItems" :test-items="testItems"
:save-as-draft="false" :save-as-draft="false"
:active="currentStep === 2"
@update:test-items="newItems => (testItems = newItems)" @update:test-items="newItems => (testItems = newItems)"
></ComparisonTest> ></ComparisonTest>
<!--
步骤4: 现场审核规划
<FieldReviewPlanning v-show="currentStep === 3"></FieldReviewPlanning>
<!-- 步骤4: 现场审核规划 --> 步骤5: 现场审核执行
<FieldReviewPlanning v-if="currentStep === 3"></FieldReviewPlanning> <FieldReviewExecution v-show="currentStep === 4"></FieldReviewExecution> -->
<!-- 步骤5: 现场审核执行 -->
<FieldReviewExecution v-if="currentStep === 4"></FieldReviewExecution>
</NForm> </NForm>
<NDivider></NDivider> <NDivider></NDivider>
<div> <div>
<NSpace justify="center"> <NSpace justify="center">
<NButton v-if="currentStep > 0" round @click="prevStep">上一步</NButton> <NButton v-if="currentStep > 0" round @click="prevStep">上一步</NButton>
<NButton v-if="currentStep < 4" type="primary" round @click="nextStep">下一步</NButton> <NButton v-if="currentStep < 2" type="primary" round @click="nextStep">下一步</NButton>
<NPopconfirm v-if="currentStep === 4" @positive-click="saveApplication(true)"> <NPopconfirm v-if="currentStep == 2" @positive-click="saveApplication(true)">
<template #trigger> <template #trigger>
<NButton type="primary" round> <NButton type="primary" round>
<template #icon> <template #icon>
...@@ -273,21 +374,21 @@ function saveApplication(submit = true) { ...@@ -273,21 +374,21 @@ function saveApplication(submit = true) {
<style scoped> <style scoped>
.apply-page-container { .apply-page-container {
padding: 24px; /* padding: 14px; */
min-height: 100vh; /* min-height: 100vh; */
width: 100%; width: 100%;
} }
/* 响应式容器 */ /* 响应式容器 */
@media (max-width: 768px) { @media (max-width: 768px) {
.apply-page-container { .apply-page-container {
padding: 16px; padding: 5px;
} }
} }
@media (max-width: 480px) { @media (max-width: 480px) {
.apply-page-container { .apply-page-container {
padding: 12px; padding: 5px;
} }
} }
...@@ -304,20 +405,7 @@ function saveApplication(submit = true) { ...@@ -304,20 +405,7 @@ function saveApplication(submit = true) {
overflow: hidden; overflow: hidden;
} }
/* 强制设置当前步骤样式 */ /* 自定义步骤条样式已移至内联样式 */
:deep(.n-step--process .n-step-indicator) {
background-color: #2080f0 !important;
color: white !important;
}
:deep(.n-step--process .n-step-header__title) {
color: #2080f0 !important;
font-weight: bold !important;
}
:deep(.n-step--process .n-step-header__description) {
color: #2080f0 !important;
}
.section-title { .section-title {
display: flex; display: flex;
...@@ -417,37 +505,15 @@ function saveApplication(submit = true) { ...@@ -417,37 +505,15 @@ function saveApplication(submit = true) {
color: #9ca3af; color: #9ca3af;
} }
/* 隐藏最后一个步骤的横线 */
:deep(.n-steps .n-step:last-child .n-step-splitor) {
display: none;
}
/* 调整步骤组件布局,去除右侧空白 */
:deep(.n-steps) {
width: 100%;
margin: 0 auto;
}
/* 确保步骤之间的连接线自适应显示 */
:deep(.n-step-splitor) {
display: block !important;
width: auto !important;
flex: 1 !important;
}
/* 只隐藏最后一个步骤的连接线 */
:deep(.n-steps .n-step:last-child .n-step-splitor) {
display: none !important;
}
/* 步骤在小屏幕上的响应式处理 */ /* 步骤在小屏幕上的响应式处理 */
@media (max-width: 768px) { @media (max-width: 768px) {
:deep(.n-steps) { .page-header > div {
max-width: 100%; flex-direction: column;
gap: 20px;
} }
:deep(.n-step-header__title) { .page-header > div > div[style*="flex: 0 0 80px"] {
font-size: 14px !important; display: none;
} }
} }
...@@ -455,7 +521,7 @@ function saveApplication(submit = true) { ...@@ -455,7 +521,7 @@ function saveApplication(submit = true) {
.header { .header {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 20px; /* margin-bottom: 20px; */
gap: 16px; gap: 16px;
} }
......
...@@ -104,12 +104,12 @@ const getProgressByStatus = (status: string) => { ...@@ -104,12 +104,12 @@ const getProgressByStatus = (status: string) => {
const getActionsByStatus = (status: string) => { const getActionsByStatus = (status: string) => {
const actionsMap: { [key: string]: string[] } = { const actionsMap: { [key: string]: string[] } = {
草稿: ['查看详情', '提交申请', '删除'], 草稿: ['查看详情', '提交申请', '删除'],
待审核: ['查看详情', '开始审核'], 待审核: ['查看详情'],
文件审核: ['查看详情', '文件评审'], 文件审核: ['查看详情'],
现场评审: ['查看详情', '现场评审'], 现场评审: ['查看详情'],
比对测试: ['查看详情', '测试管理'], 比对测试: ['查看详情'],
认证签发: ['查看详情', '签发证书'], 认证签发: ['查看详情'],
认证完成: ['查看详情', '下载证书'] 认证完成: ['查看详情']
}; };
return actionsMap[status] || ['查看详情']; return actionsMap[status] || ['查看详情'];
}; };
...@@ -164,7 +164,7 @@ const fetchData = async () => { ...@@ -164,7 +164,7 @@ const fetchData = async () => {
const data = response.data; const data = response.data;
if (!data) { if (!data) {
console.error('获取数据失败: 无响应数据'); // console.error('获取数据失败: 无响应数据');
message.error('获取数据失败,请稍后重试'); message.error('获取数据失败,请稍后重试');
return; return;
} }
...@@ -192,7 +192,7 @@ const fetchData = async () => { ...@@ -192,7 +192,7 @@ const fetchData = async () => {
message.error('获取数据失败:响应格式错误'); message.error('获取数据失败:响应格式错误');
} }
} catch (error: any) { } catch (error: any) {
console.error('获取数据失败:', error); // console.error('获取数据失败:', error);
message.error('获取数据失败,请稍后重试'); message.error('获取数据失败,请稍后重试');
} finally { } finally {
loading.value = false; loading.value = false;
...@@ -281,7 +281,7 @@ onMounted(() => { ...@@ -281,7 +281,7 @@ onMounted(() => {
// 处理关闭并刷新数据 // 处理关闭并刷新数据
const handleCloseAndRefresh = () => { const handleCloseAndRefresh = () => {
console.log('关闭mainSupplier组件并刷新数据'); // console.log('关闭mainSupplier组件并刷新数据');
showMainSupplier.value = false; showMainSupplier.value = false;
currentItem.value = {}; // 清空当前Item currentItem.value = {}; // 清空当前Item
fetchData(); fetchData();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment