Commit 8cbb38c2 by Neo Turing

feat: 更新LAC文件列表视图和文件审核组件

parent 4ff0ebd7
......@@ -101,7 +101,11 @@
</n-descriptions-item>
</n-descriptions>
<div class="modal-footer">
<n-button type="primary" @click="downloadSingleFile(currentFile!)">
<n-button
type="primary"
@click="currentFile && downloadSingleFile(currentFile)"
:disabled="!currentFile"
>
下载文件
</n-button>
<n-button @click="showPreviewModal = false">
......@@ -115,7 +119,7 @@
<script setup lang="ts">
import { h, ref, computed, resolveComponent, watch, withDefaults, onBeforeUnmount } from 'vue';
import type { DataTableColumns } from 'naive-ui';
// import type { DataTableColumns } from 'naive-ui';
interface FileItem {
Kvid: string;
......@@ -650,8 +654,19 @@ function formatFileSize(size: number): string {
// 关闭并传递文件数据
function closeWithFileData() {
emit('update-files', fileData.value);
emit('close');
emit('close', fileData.value); // 在关闭时传递当前的文件数据
}
// 获取当前文件列表的方法
function getCurrentFileList() {
return fileData.value;
}
// 暴露方法给父组件使用
defineExpose({
getCurrentFileList,
fileData
});
</script>
<style scoped>
......
<script setup lang="ts">
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/Vue3/Lab/FileListView.vue'; //'./fileListView.vue';
// 主体框架内置的第三方方法通过window对象暴露、供外部组件使用
const axios = (window as any).$axios;
......@@ -12,18 +12,6 @@ const message = (window as any).$message;
const dialog = (window as any).$dialog;
// 通过计算属性确定当前的主体色
const isDarkMode = computed(() => themeStore?.darkMode || false);
// 根据主题计算文字颜色
const textColor = computed(() => (isDarkMode.value ? 'rgba(255, 255, 255, 0.85)' : 'rgba(0, 0, 0, 0.85)'));
const legendTextColor = computed(() => (isDarkMode.value ? 'rgba(255, 255, 255, 0.65)' : 'rgba(0, 0, 0, 0.65)'));
const borderColor = computed(() => (isDarkMode.value ? '#303030' : '#ffffff'));
// CSS变量
const cssVars = computed(() => ({
'--text-color': textColor.value,
'--bg-color': isDarkMode.value ? '#1f1f1f' : '#f5f5f5',
'--panel-bg': isDarkMode.value ? '#262626' : '#ffffff',
'--card-bg': isDarkMode.value ? '#303030' : '#ffffff',
'--border-color': isDarkMode.value ? '#434343' : '#e8e8e8'
}));
// 修改FileItem接口,但保留原有字段
interface FileItem {
......@@ -37,7 +25,7 @@ interface FileItem {
Description?: string;
StatusType?: string;
ReportKvid?: string;
[key: string]: any; // 添加索引签名,以支持可能出现的其他字段
[key: string]: any;
}
// 定义Item对象的接口
......@@ -50,7 +38,7 @@ interface ItemProps {
const props = withDefaults(
defineProps<{
item?: ItemProps;
active?: boolean; // 新增:是否激活状态,用于按需加载
active?: boolean;
}>(),
{
item: () => ({}),
......@@ -59,30 +47,82 @@ const props = withDefaults(
);
// 状态变量
const titleOptions = ref<any[]>([]);
const selectedStandard = reactive<any>({}); // 存储选中的完整对象
const fileData = ref<FileItem[]>([]); // 改回ref,避免过度响应式
/**
* 🔸 选中的标准对象(可能未充分使用)
* @description 存储选中文件类型的完整对象信息
* @usage ⚠️ 在handleTitleChange中填充,但后续业务逻辑中使用频率较低
*/
const selectedStandard = reactive<any>({});
/**
* 文件审核数据列表
* @description 存储当前显示的所有文件审核记录
*/
const fileData = ref<FileItem[]>([]);
/**
* 加载状态标识
* @description 控制各种异步操作的加载状态显示
*/
const loading = ref<boolean>(false);
// 存储API返回的详细数据
/**
* 存储从props传入的详细数据
* @description 保存父组件传递的item数据的响应式副本
*/
const detailedData = reactive<ItemProps>({});
// 控制fileListView模态框显示
/**
* 控制FileListView模态框显示状态
* @description 控制文件管理模态框的开关
*/
const showFileListView = ref<boolean>(false);
// 存储当前选中的文件行数据
/**
* 当前选中的文件行数据
* @description 存储用户点击查看的文件行完整数据
*/
const currentFileRow = ref<FileItem | null>(null);
// 使用ref来避免计算属性的循环更新问题
/**
* FileListView组件引用
* @description 用于调用子组件的方法和访问子组件数据
*/
const fileListViewRef = ref<any>(null);
/**
* 🔸 选中的标准Kvid(可能未充分使用)
* @description 存储当前选择的文件类型ID
* @usage ⚠️ 主要在handleTitleChange和fetchFileDetails中使用
*/
const selectedStandardKvid = ref<string>('');
// 计算是否有数据存在,用于控制NSelect状态
/**
* 计算是否存在文件数据
* @description 用于控制文件类型选择器的禁用状态和清空按钮的显示
* @returns {boolean} 是否有现有的文件审核数据
* @usage 控制NSelect的disabled状态和清空按钮的显示条件
*/
const hasExistingData = computed(() => {
return fileData.value.length > 0;
});
// 根据选择的标题筛选数据 - 优化性能
/**
* 🔸 过滤后的数据(当前无过滤逻辑)
* @description 原计划用于数据过滤,当前直接返回所有数据
* @returns {FileItem[]} 文件数据数组
* @usage ⚠️ 绑定到NDataTable的:data属性,但无实际过滤功能
*/
const filteredData = computed(() => {
return fileData.value;
});
// 辅助函数:将API的StatusType映射为显示状态
/**
* 状态类型映射函数
* @description 将API返回的StatusType字符串映射为中文显示状态
* @param {string} statusType - API返回的状态类型字符串
* @returns {string} 对应的中文状态显示名称
* @usage 在数据处理和状态显示时使用
*/
const mapStatusType = (statusType: string) => {
const statusMap: { [key: string]: string } = {
Unsupported: '草稿',
......@@ -96,21 +136,33 @@ const mapStatusType = (statusType: string) => {
return statusMap[statusType] || '草稿';
};
// 辅助函数:根据状态获取颜色
/**
* 状态颜色获取函数
* @description 根据状态类型返回对应的UI显示颜色
* @param {string} status - 状态类型字符串
* @returns {string} 对应状态的十六进制颜色值
* @usage 在表格和标签组件中设置状态颜色
*/
const getStatusColor = (status: string) => {
const statusColorMap: { [key: string]: string } = {
BeforeTest: '#f56a00', // 橙色 - 待处理
Asigning: '#1890ff', // 蓝色 - 进行中
Testing: '#722ed1', // 紫色 - 重要评审
BeforeReview: '#eb2f96', // 粉红色 - 测试阶段
TestFinished: '#13c2c2', // 青色 - 即将完成
TestCollected: '#52c41a' // 绿色 - 已完成
BeforeTest: '#f56a00',
Asigning: '#1890ff',
Testing: '#722ed1',
BeforeReview: '#eb2f96',
TestFinished: '#13c2c2',
TestCollected: '#52c41a'
};
return statusColorMap[status] || '#666';
};
// 状态映射函数(为模态框标题使用)
const getStatusInfo = (status: number) => {
/**
* 状态信息获取函数
* @description 根据数字状态码返回包含标签、颜色和类型的状态信息对象
* @param {any} status - 数字状态码
* @returns {object} 包含label、color、type的状态信息对象
* @usage 主要用于模态框标题和状态标签显示
*/
const getStatusInfo = (status: any) => {
const statusMap = {
0: { label: '草稿', color: '#909399', type: 'default' },
100: { label: '待上传', color: '#E6A23C', type: 'warning' },
......@@ -118,7 +170,14 @@ const getStatusInfo = (status: number) => {
200: { label: '审核中', color: '#F56C6C', type: 'error' },
250: { label: '待复核', color: '#722ED1', type: 'warning' },
300: { label: '不通过', color: '#FF7A45', type: 'error' },
2147483647: { label: '已通过', color: '#67C23A', type: 'success' }
2147483647: { label: '已通过', color: '#67C23A', type: 'success' },
Unsupported: { label: '草稿', color: '#909399', type: 'default' },
BeforeTest: { label: '待上传', color: '#E6A23C', type: 'warning' },
Asigning: { label: '已上传', color: '#409EFF', type: 'info' },
Testing: { label: '审核中', color: '#F56C6C', type: 'error' },
BeforeReview: { label: '待复核', color: '#722ED1', type: 'warning' },
TestFinished: { label: '不通过', color: '#FF7A45', type: 'error' },
TestCollected: { label: '已通过', color: '#67C23A', type: 'success' }
};
return statusMap[status as keyof typeof statusMap] || {
......@@ -128,49 +187,52 @@ const getStatusInfo = (status: number) => {
};
};
// 计算当前行的只读状态
/**
* 🔸 计算当前行的只读状态(可能未使用)
* @description 判断当前选中行是否为只读状态(状态值大于150)
* @returns {boolean} 是否为只读状态
* @usage ⚠️ 在模板中可能被引用,但实际业务逻辑中可能不需要
*/
const isCurrentRowReadonly = computed(() => {
return currentFileRow.value && currentFileRow.value.Status > 150;
});
// 获取文件类型数据
/**
* 获取文件类型选项数据
* @description 从标准实体接口查询文件审核类型数据,用于下拉选择器
* @returns {Promise<void>} 无返回值,结果存储在titleOptions.value中
* @usage 在组件初始化和激活时调用,用于填充文件类型下拉选择器
*/
async function fetchTitleOptions() {
console.log('🔄 FileReview: 开始加载文件类型数据');
try {
loading.value = true;
// 调用标准实体查询接口
const response = await axios.post('/Restful/Kivii.Standards.Entities.Standard/Query.json?Type=文件审核');
// console.log('完整响应数据:', response.data);
// 添加数据存在性检查
if (response.data && response.data.Results) {
// 将API返回的数据转换为NSelect需要的格式
titleOptions.value = response.data.Results.map((item: any, index: number) => ({
label: item.Title,
value: item.Kvid,
// 可以选择以下任一方式存储完整对象信息:
// 方式1:直接将完整对象作为额外属性
fullObject: item
}));
} else {
// console.error('无效的数据格式:', response.data);
message.error('数据格式不正确');
}
} catch (error) {
message.error('获取文件类型失败');
// console.error('获取文件类型失败:', error);
} finally {
loading.value = false;
}
}
// 获取文件详情数据
/**
* 🔸 获取文件详情数据(可能未使用)
* @description 基于选中的标准Kvid创建文件审核数据记录
* @returns {Promise<void>} 无返回值,结果存储在fileData.value中
* @usage ⚠️ 当前代码中通过handleTitleChange调用,但实际业务流程可能不使用此方法
*/
async function fetchFileDetails() {
if (!selectedStandardKvid.value) return;
// 如果数据已存在,直接返回(UI已有提示)
if(fileData.value.length > 0) {
return;
}
......@@ -178,10 +240,10 @@ async function fetchFileDetails() {
try {
loading.value = true;
const queryParams: any = {
StandardKvid: selectedStandardKvid.value,
OrderBy:'SortId'
};
const queryParams: any = {
StandardKvid: selectedStandardKvid.value,
OrderBy:'SortId'
};
const response = await axios.post('/Restful/Kivii.Standards.Entities.DetectionEx/DetectionWithPriceQuery.json', queryParams);
......@@ -191,60 +253,54 @@ async function fetchFileDetails() {
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,
// 保留转换后的自定义字段
Status: mapStatusType(item.StatusType),
StatusColor: getStatusColor(item.StatusType)
}));
}else{
message.error('创建文件审核数据失败');
}
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) => ({
...item,
Status: mapStatusType(item.StatusType),
StatusColor: getStatusColor(item.StatusType)
}));
}else{
message.error('创建文件审核数据失败');
}
} else {
message.error('获取文件数据失败');
}
} catch (error) {
message.error('获取文件详情失败');
// console.error(error);
} finally {
loading.value = false;
}
}
// 使用报告Kvid获取数据
/**
* 根据报告Kvid获取文件审核数据
* @description 使用报告ID查询已存在的文件审核数据记录
* @param {string} reportKvid - 报告的唯一标识符
* @returns {Promise<void>} 无返回值,结果存储在fileData.value中
* @usage 在组件初始化和props变化时调用,获取现有的文件审核数据
*/
async function fetchDataByReportKvid(reportKvid: string) {
if (!reportKvid) return;
if (reportKvid === detailedData.Kvid && fileData.value.length > 0) {
console.log('🔄 FileReview: 跳过重复请求,使用已缓存的数据');
return;
}
console.log('🔄 FileReview: 开始获取文件审核数据,ReportKvid:', reportKvid);
try {
loading.value = true;
const response = await axios.post('/Restful/Kivii.Lims.Entities.ReportItem/QueryEx.json', {
ReportKvid: reportKvid,
OrderBy:'SortId,SortIdEx,Kvid',
WorkGroupName:'文件审核'
const response = await axios.get('/Restful/Kivii.Lims.Entities.ReportItem/QueryEx.json', {
params: {
ReportKvid: reportKvid,
OrderBy:'SortId,SortIdEx,Kvid',
WorkGroupName:'文件审核'
}
});
if (response.data && response.data.Results&&response.data.Results.length>0) {
// 直接使用API返回的数据
// fileData.value = response.data.Results;
// fileData.value.forEach((item: any) => {
// item.StatusType = mapStatusType(item.StatusType);
// });
fileData.value = response.data.Results.map((item: any) => ({
// 直接使用API字段名
...item,
// 保留转换后的自定义字段
Status: mapStatusType(item.StatusType),
StatusColor: getStatusColor(item.StatusType)
}));
......@@ -253,25 +309,27 @@ async function fetchDataByReportKvid(reportKvid: string) {
message.info('暂无文件审核数据');
}
} catch (error) {
// console.error('获取文件审核数据失败:', error);
message.error('获取文件审核数据失败,请稍后重试');
} finally {
loading.value = false;
}
}
// 处理标题选择变化
/**
* 🔸 处理文件类型选择变化(可能未使用)
* @description 当用户选择不同的文件类型时触发,同步选中值并获取详情
* @param {string} value - 选中的文件类型Kvid
* @returns {void} 无返回值
* @usage ⚠️ 绑定到NSelect的@update:value事件,但实际业务可能不需要此功能
*/
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];
});
......@@ -294,25 +352,20 @@ watch(
);
// 页面加载时按需获取数据
onMounted(() => {
// 只有在激活状态下才加载数据
if (props.active) {
fetchTitleOptions();
// 如果有kvid,获取数据
if (props.item && props.item.Kvid && props.item.Kvid !== detailedData.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) {
......@@ -323,25 +376,17 @@ watch(
{ immediate: true }
);
// 存储最新的文件列表数据
/**
* 🔸 最新文件列表数据(备用存储)
* @description 备用存储FileListView的实时文件数据,主要通过关闭事件获取数据
* @usage ⚠️ 作为数据同步的备用方案,当前主要逻辑已转移到handleModalClose
*/
const latestFileListData = ref<any[]>([]);
// 监听FileListView模态框的显示状态
watch(
() => showFileListView.value,
(newValue, oldValue) => {
// 当模态框从显示变为隐藏时
if (oldValue === true && newValue === false) {
console.log('FileListView模态框已关闭,最新文件数据:', latestFileListData.value);
// 这里可以添加您需要的其他处理逻辑
// 例如:调用API保存数据、更新其他组件状态等
handleFileListClosed(latestFileListData.value);
}
}
);
// 表格列定义
/**
* 表格列配置定义
* @description 定义NDataTable的列结构、渲染方式和操作按钮
*/
const columns = ref<any[]>([
{
title: '序号',
......@@ -442,20 +487,26 @@ const columns = ref<any[]>([
}
]);
// 查看文件
/**
* 查看文件详情
* @description 打开文件列表模态框,显示指定行的文件详情和管理界面
* @param {FileItem} row - 选中的文件行数据
* @returns {void} 无返回值
* @usage 绑定到表格操作列的"附件"按钮点击事件
*/
function viewFile(row: FileItem) {
// 将整个row数据存储到currentFileRow中
currentFileRow.value = row;
console.log('传递给FileListView的数据:', row);
// 清空之前的文件列表数据
latestFileListData.value = [];
// 显示模态框
showFileListView.value = true;
}
// 封装删除实体的方法
/**
* 批量删除实体数据
* @description 通用的删除方法,支持批量删除多个文件审核记录
* @param {string[]} kvids - 要删除的记录ID数组
* @returns {Promise<boolean>} 删除操作是否成功
* @usage 被deleteFileRecord和clearAllFileData方法调用
*/
async function deleteEntities(kvids: string[]) {
if (!kvids || kvids.length === 0) {
message.error('请选择要删除的项目');
......@@ -477,7 +528,6 @@ async function deleteEntities(kvids: string[]) {
return false;
}
} catch (error) {
console.error('删除文件失败:', error);
message.error('删除文件失败,请稍后重试');
return false;
} finally {
......@@ -485,23 +535,32 @@ async function deleteEntities(kvids: string[]) {
}
}
// 删除文件记录
/**
* 删除单个文件记录
* @description 删除表格中指定的单个文件审核记录
* @param {FileItem} row - 要删除的文件行数据
* @returns {Promise<void>} 无返回值
* @usage 绑定到表格操作列的"删除"按钮确认回调
*/
async function deleteFileRecord(row: FileItem) {
if (!row.Kvid) {
message.error('无效的文件ID');
return;
}
// 调用删除接口
const success = await deleteEntities([row.Kvid]);
if (success) {
// 从列表中移除
fileData.value = fileData.value.filter(item => item.Kvid !== row.Kvid);
}
}
// 清空所有文件数据
/**
* 清空所有文件数据
* @description 删除当前列表中的所有文件审核记录,并重置相关状态
* @returns {void} 无返回值
* @usage 绑定到"清空数据"按钮的点击事件
*/
function clearAllFileData() {
dialog.warning({
title: '确认删除',
......@@ -514,7 +573,6 @@ function clearAllFileData() {
return;
}
// 收集所有Kvid
const kvids = fileData.value.map(item => item.Kvid).filter(kvid => kvid);
if (kvids.length === 0) {
......@@ -522,13 +580,11 @@ function clearAllFileData() {
return;
}
// 调用删除接口
const success = await deleteEntities(kvids);
if (success) {
fileData.value = [];
selectedStandardKvid.value = '';
// 清空selectedStandard对象
Object.keys(selectedStandard).forEach(key => {
delete selectedStandard[key];
});
......@@ -537,44 +593,83 @@ function clearAllFileData() {
});
}
// 处理模态框关闭
/**
* 防重复调用标志
* @description 防止模态框关闭事件重复触发数据处理逻辑
*/
const isProcessingClose = ref(false);
/**
* 处理模态框关闭事件
* @description 模态框关闭后获取FileListView中的文件数据并进行状态更新处理
* @returns {void} 无返回值
* @usage 绑定到NModal的@after-leave事件,防重复调用机制
*/
function handleModalClose() {
currentFileRow.value = null;
}
if (isProcessingClose.value) {
return;
}
// 处理FileListView实时文件列表更新(实时同步数据)
function handleFileListUpdate(files: any[]) {
console.log('FileReview: 接收到文件列表实时更新', files);
try {
isProcessingClose.value = true;
if (fileListViewRef.value && currentFileRow.value) {
const currentFiles = fileListViewRef.value.getCurrentFileList?.() || [];
handleFileListClosed(currentFiles);
}
currentFileRow.value = null;
} finally {
setTimeout(() => {
isProcessingClose.value = false;
}, 100);
}
}
// 存储最新的文件列表数据,用于界面关闭时处理
latestFileListData.value = [...files]; // 深拷贝确保数据独立性
/**
* 🔸 处理FileListView组件关闭事件(功能简化)
* @description 简单关闭模态框,实际数据处理由handleModalClose负责
* @param {any[]} files - 可选的文件数据参数(当前未使用)
* @returns {void} 无返回值
* @usage ⚠️ 绑定到FileListView的@close事件,但主要逻辑已转移到handleModalClose
*/
function handleFileListViewClose(files?: any[]) {
showFileListView.value = false;
}
console.log(`📁 实时数据同步: ${files.length} 个文件`);
/**
* 🔸 处理FileListView实时文件更新(备用方法)
* @description 实时同步FileListView中的文件数据变化(主要通过关闭事件获取数据)
* @param {any[]} files - 更新的文件数据数组
* @returns {void} 无返回值
* @usage ⚠️ 绑定到FileListView的@update-files事件,作为备用数据同步方式
*/
function handleFileListUpdate(files: any[]) {
latestFileListData.value = [...files];
}
// 处理FileListView界面关闭后的数据处理
/**
* 处理FileListView关闭后的数据处理
* @description 根据FileListView中的文件数量自动更新文件审核记录的状态
* @param {any[]} files - 从FileListView获取的文件数据数组
* @returns {Promise<void>} 无返回值
* @usage 被handleModalClose调用,根据文件数量自动设置状态(0个文件=待上传,>0个文件=已上传)
*/
async function handleFileListClosed(files: any[]) {
console.log('🔒 FileListView界面已关闭,开始处理文件数据集合');
// 检查当前行状态,如果超过150则直接返回
if (!currentFileRow.value || currentFileRow.value.Status > 150) {
console.log('⚠️ 当前状态不允许更新,Status:', currentFileRow.value?.Status);
return;
}
const fileCount = files.length;
try {
// 根据文件数量确定状态值
const newStatus = fileCount <= 0 ? 100 : 150;
if(currentFileRow.value.Status===newStatus){
// message.info('文件状态未发生变化,无需更新');
const statusInfo=getStatusInfo(newStatus);
if(currentFileRow.value.Status===statusInfo.label){
return;
}
console.log(`📋 准备更新状态: 文件数量=${fileCount}, 新状态=${newStatus}`);
// 调用更新接口
const response = await axios.post('/Restful/Kivii.Lims.Entities.ReportItem/Update.json', {
const response = await axios.post('/Restful/Kivii.Lims.Entities.ReportItem/UpdateEx2.json', {
Item: {
Kvid: currentFileRow.value.Kvid,
Status: newStatus
......@@ -582,39 +677,21 @@ async function handleFileListClosed(files: any[]) {
});
if (response.data && response.data.Results && response.data.Results.length > 0) {
// 更新成功,同步本地状态
currentFileRow.value.Status = newStatus;
// 同时更新状态显示文本和颜色
const statusText = newStatus === 100 ? '待上传' : '已上传';
const statusColor = newStatus === 100 ? '#E6A23C' : '#409EFF';
currentFileRow.value.Status = statusText;
currentFileRow.value.StatusColor = statusColor;
// 在fileData数组中找到对应项并更新
const itemIndex = fileData.value.findIndex(item => item.Kvid === currentFileRow.value?.Kvid);
const itemIndex = fileData.value.findIndex(item => item.Kvid === response.data.Results[0].Kvid);
if (itemIndex !== -1) {
fileData.value[itemIndex].Status = statusText;
fileData.value[itemIndex].StatusColor = statusColor;
fileData.value[itemIndex].Status = mapStatusType(response.data.Results[0].StatusType);
fileData.value[itemIndex].StatusColor = getStatusColor(response.data.Results[0].StatusType);
}
message.success(`状态更新成功:${statusText} (${fileCount}个文件)`);
console.log('✅ 状态更新成功:', {
记录ID: currentFileRow.value.Kvid,
文件数量: fileCount,
新状态: newStatus,
状态描述: statusText
});
} else {
message.error('状态更新失败:' + (response.data?.Message || '未知错误'));
console.error('❌ 状态更新失败:', response.data);
}
} catch (error) {
message.error('状态更新失败,请稍后重试');
console.error('❌ 状态更新异常:', error);
}
}
</script>
......@@ -695,11 +772,14 @@ async function handleFileListClosed(files: any[]) {
<n-space align="center" :size="12">
<span class="modal-title-compact">文件详情 - {{ currentFileRow?.Title || '文件列表' }}</span>
<n-tag
:type="getStatusInfo(currentFileRow?.Status || 0).type as any"
:color="{ color: getStatusInfo(currentFileRow?.Status || 0).color }"
size="small"
:style="{
backgroundColor: getStatusInfo(currentFileRow?.Status).color,
color: 'white',
border: 'none'
}"
>
{{ getStatusInfo(currentFileRow?.Status || 0).label }}
{{ getStatusInfo(currentFileRow?.Status).label }}
</n-tag>
<span v-if="isCurrentRowReadonly" class="readonly-hint-modal">
(当前状态不允许上传/删除操作)
......@@ -710,8 +790,9 @@ async function handleFileListClosed(files: any[]) {
<FileListView
v-if="currentFileRow"
ref="fileListViewRef"
:owner-item="currentFileRow"
@close="showFileListView = false"
@close="handleFileListViewClose"
@update-files="handleFileListUpdate"
></FileListView>
</NModal>
......
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