传承人卡片优化

This commit is contained in:
Qi 2025-08-10 20:42:19 +08:00
parent 1fe792a910
commit 07420c01af
4 changed files with 257 additions and 26 deletions

View File

@ -0,0 +1,127 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
enum Api {
list = '/oroqen/heritageProject/list',
save = '/oroqen/heritageProject/add',
edit = '/oroqen/heritageProject/edit',
deleteOne = '/oroqen/heritageProject/delete',
deleteBatch = '/oroqen/heritageProject/deleteBatch',
importExcel = '/oroqen/heritageProject/importExcel',
exportXls = '/oroqen/heritageProject/exportXls',
queryById = '/oroqen/heritageProject/queryById',
recommended = '/oroqen/heritageProject/recommended',
byLevel = '/oroqen/heritageProject/byLevel',
byCategory = '/oroqen/heritageProject/byCategory',
}
/**
* api
*/
export const getExportUrl = Api.exportXls;
/**
* api
*/
export const getImportUrl = Api.importExcel;
/**
*
*/
export const list = (params) => defHttp.get({ url: Api.list, params });
/**
*
*/
export const deleteOne = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
};
/**
*
*/
export const batchDelete = (params, handleSuccess) => {
createConfirm({
iconType: 'warning',
title: '确认删除',
content: '是否删除选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
}
});
};
/**
*
*/
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params });
};
/**
* ID查询
*/
export const queryById = (id) => {
return defHttp.get({ url: Api.queryById, params: { id } });
};
/**
*
*/
export const getHeritageProjectOptions = () => {
return defHttp.get({
url: Api.list,
params: {
pageNo: 1,
pageSize: 1000,
status: 1 // 只获取启用状态的项目
}
}).then(res => {
console.log('非遗项目API响应:', res);
// 修正数据结构判断,直接使用 res.records
if (res && res.records && Array.isArray(res.records)) {
const options = res.records.map(item => ({
label: item.projectName, // 使用 projectName 字段
value: item.projectName, // 使用项目名称作为值
key: item.id
}));
console.log('非遗项目选项数据:', options);
return options;
}
console.log('非遗项目数据为空或格式错误');
return [];
}).catch(error => {
console.error('获取非遗项目数据失败:', error);
return [];
});
};
/**
*
*/
export const getRecommendedProjects = () => {
return defHttp.get({ url: Api.recommended });
};
/**
*
*/
export const getProjectsByLevel = (level) => {
return defHttp.get({ url: Api.byLevel, params: { level } });
};
/**
*
*/
export const getProjectsByCategory = (category) => {
return defHttp.get({ url: Api.byCategory, params: { category } });
};

View File

@ -340,6 +340,18 @@ export const formSchema: FormSchema[] = [
showCount: true, showCount: true,
}, },
}, },
{
label: '制作流程',
field: 'craftProcess',
component: 'InputTextArea',
componentProps: {
placeholder: '请输入制作流程多个步骤用逗号分隔或输入JSON数组格式',
rows: 4,
maxlength: 2000,
showCount: true,
},
helpMessage: '可以输入逗号分隔的步骤步骤1,步骤2,步骤3或JSON数组格式["步骤1","步骤2","步骤3"]',
},
{ {
label: '传承价值', label: '传承价值',
field: 'value', field: 'value',
@ -573,20 +585,21 @@ export const superQuerySchema = {
fullDescription: {title: '详细描述',order: 7,view: 'textarea', type: 'string',}, fullDescription: {title: '详细描述',order: 7,view: 'textarea', type: 'string',},
history: {title: '历史渊源',order: 8,view: 'textarea', type: 'string',}, history: {title: '历史渊源',order: 8,view: 'textarea', type: 'string',},
features: {title: '技艺特点',order: 9,view: 'textarea', type: 'string',}, features: {title: '技艺特点',order: 9,view: 'textarea', type: 'string',},
value: {title: '传承价值',order: 10,view: 'textarea', type: 'string',}, craftProcess: {title: '制作流程',order: 10,view: 'textarea', type: 'string',},
coverImage: {title: '封面图片',order: 11,view: 'text', type: 'string',}, value: {title: '传承价值',order: 11,view: 'textarea', type: 'string',},
images: {title: '图片集',order: 12,view: 'textarea', type: 'string',}, coverImage: {title: '封面图片',order: 12,view: 'text', type: 'string',},
videoUrl: {title: '视频链接',order: 13,view: 'text', type: 'string',}, images: {title: '图片集',order: 13,view: 'textarea', type: 'string',},
audioUrl: {title: '音频链接',order: 14,view: 'text', type: 'string',}, videoUrl: {title: '视频链接',order: 14,view: 'text', type: 'string',},
tags: {title: '标签',order: 15,view: 'text', type: 'string',}, audioUrl: {title: '音频链接',order: 15,view: 'text', type: 'string',},
inheritorIds: {title: '关联传承人ID',order: 16,view: 'textarea', type: 'string',}, tags: {title: '标签',order: 16,view: 'text', type: 'string',},
protectionUnit: {title: '保护单位',order: 17,view: 'text', type: 'string',}, inheritorIds: {title: '关联传承人ID',order: 17,view: 'textarea', type: 'string',},
protectionMeasures: {title: '保护措施',order: 18,view: 'text', type: 'string',}, protectionUnit: {title: '保护单位',order: 18,view: 'text', type: 'string',},
currentStatus: {title: '保护现状',order: 19,view: 'text', type: 'string',}, protectionMeasures: {title: '保护措施',order: 19,view: 'text', type: 'string',},
isRecommended: {title: '是否推荐',order: 20,view: 'number', type: 'number',}, currentStatus: {title: '保护现状',order: 20,view: 'text', type: 'string',},
viewCount: {title: '浏览次数',order: 21,view: 'number', type: 'number',}, isRecommended: {title: '是否推荐',order: 21,view: 'number', type: 'number',},
likeCount: {title: '点赞次数',order: 22,view: 'number', type: 'number',}, viewCount: {title: '浏览次数',order: 22,view: 'number', type: 'number',},
status: {title: '状态',order: 23,view: 'number', type: 'number',}, likeCount: {title: '点赞次数',order: 23,view: 'number', type: 'number',},
status: {title: '状态',order: 24,view: 'number', type: 'number',},
}; };
/** /**

View File

@ -4,6 +4,7 @@ import { h } from 'vue';
import { Image, Tag } from 'ant-design-vue'; import { Image, Tag } from 'ant-design-vue';
import { render } from '/@/utils/common/renderUtils'; import { render } from '/@/utils/common/renderUtils';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'; import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { getHeritageProjectOptions } from '/@/api/oroqen/OroqenHeritageProject';
//列表数据 //列表数据
export const columns: BasicColumn[] = [ export const columns: BasicColumn[] = [
@ -63,10 +64,19 @@ export const columns: BasicColumn[] = [
}, },
{ {
title: '传承项目', title: '传承项目',
dataIndex: 'heritageProject', dataIndex: 'heritageSkills',
width: 150, width: 150,
align: 'left', align: 'left',
ellipsis: true, ellipsis: true,
customRender: ({ text }) => {
if (!text) return '-';
// 如果是数组格式的项目ID需要转换为项目名称显示
// 这里暂时直接显示后续可以通过API获取项目名称
if (Array.isArray(text)) {
return text.join(', ');
}
return text;
},
}, },
{ {
title: '传承级别', title: '传承级别',
@ -227,11 +237,40 @@ export const formSchema: FormSchema[] = [
}, },
{ {
label: '传承项目', label: '传承项目',
field: 'heritageProject', field: 'heritageSkills',
component: 'Input', component: 'ApiSelect',
required: true,
componentProps: { componentProps: {
placeholder: '请输入传承项目', api: getHeritageProjectOptions,
params: {},
resultField: '',
labelField: 'label',
valueField: 'value',
placeholder: '请选择传承项目',
mode: 'multiple',
showSearch: true,
filterOption: (input: string, option: any) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
},
},
// 数据转换:数据库存储为逗号分隔的字符串,前端显示为数组
dynamicRules: ({ model, schema }) => {
return [];
},
// 表单值转换
valueFormat: (value) => {
// 从数据库读取时:字符串转数组
if (typeof value === 'string' && value) {
return value.split(',').filter(v => v.trim());
}
return value || [];
},
// 提交时转换
valueTransform: (value) => {
// 提交到数据库时:数组转字符串
if (Array.isArray(value)) {
return value.join(',');
}
return value || '';
}, },
colProps: { span: 12 }, colProps: { span: 12 },
}, },
@ -390,6 +429,46 @@ export const formSchema: FormSchema[] = [
}, 100); }, 100);
}, },
}, },
colProps: { span: 24 }, colProps: { span: 12 },
},
{
label: '作品图片',
field: 'workImages',
component: 'JUpload',
componentProps: {
fileType: 'image',
maxCount: 10,
maxSize: 5,
bizPath: 'inheritor/works',
customRequest: (options) => {
// 验证文件类型和大小
const { file } = options;
const isImage = file.type.startsWith('image/');
if (!isImage) {
console.error('只能上传图片文件!');
return;
}
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) {
console.error('图片大小不能超过5MB!');
return;
}
// 创建本地预览URL
const localUrl = URL.createObjectURL(file);
// 直接设置文件的url为本地预览URL
file.url = localUrl;
// 模拟上传成功响应返回blob URL作为message
setTimeout(() => {
options.onSuccess({
success: true,
message: localUrl, // 返回blob URL
}, file);
}, 100);
},
},
colProps: { span: 12 },
}, },
]; ];

View File

@ -37,10 +37,14 @@
isDetail.value = data?.mode === 'detail'; isDetail.value = data?.mode === 'detail';
if (unref(isUpdate)) { if (unref(isUpdate)) {
//
const record = { ...data.record };
if (record.heritageSkills && typeof record.heritageSkills === 'string') {
record.heritageSkills = record.heritageSkills.split(',').filter(v => v.trim());
}
// //
await setFieldsValue({ await setFieldsValue(record);
...data.record,
});
} }
// //
setProps({ disabled: unref(isDetail) }); setProps({ disabled: unref(isDetail) });
@ -56,6 +60,11 @@
let values = await validate(); let values = await validate();
console.log('表单验证通过,提交数据:', values); console.log('表单验证通过,提交数据:', values);
//
if (values.heritageSkills && Array.isArray(values.heritageSkills)) {
values.heritageSkills = values.heritageSkills.join(',');
}
// //
changeDateValue(values); changeDateValue(values);
setModalProps({ confirmLoading: true }); setModalProps({ confirmLoading: true });
@ -108,8 +117,8 @@
console.log('开始处理文件上传,表单数据:', formData); console.log('开始处理文件上传,表单数据:', formData);
try { try {
// //
const fileFields = ['avatar']; const fileFields = ['avatar', 'workImages'];
for (const field of fileFields) { for (const field of fileFields) {
// blob URL // blob URL
@ -176,8 +185,11 @@
throw new Error('无法获取文件对象'); throw new Error('无法获取文件对象');
} }
// - // -
let bizPath = 'inheritor/avatar'; let bizPath = 'inheritor/avatar';
if (fieldName === 'workImages') {
bizPath = 'inheritor/works';
}
// //
const uploadParams = { const uploadParams = {