diff --git a/src/views/oroqen/culture-category/OroqenCultureCategory.api.ts b/src/views/oroqen/culture-category/OroqenCultureCategory.api.ts
new file mode 100644
index 0000000..ab461a1
--- /dev/null
+++ b/src/views/oroqen/culture-category/OroqenCultureCategory.api.ts
@@ -0,0 +1,76 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+ list = '/oroqen/cultureCategory/list',
+ save = '/oroqen/cultureCategory/add',
+ edit = '/oroqen/cultureCategory/edit',
+ deleteOne = '/oroqen/cultureCategory/delete',
+ deleteBatch = '/oroqen/cultureCategory/deleteBatch',
+ importExcel = '/oroqen/cultureCategory/importExcel',
+ exportXls = '/oroqen/cultureCategory/exportXls',
+ queryById = '/oroqen/cultureCategory/queryById',
+ tree = '/oroqen/cultureCategory/tree',
+}
+
+/**
+ * 导出api
+ */
+export const getExportUrl = Api.exportXls;
+
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+
+/**
+ * 列表接口
+ */
+export const list = (params) => defHttp.get({ url: Api.list, params });
+
+/**
+ * 树形列表接口
+ */
+export const queryTreeList = (params) => defHttp.get({ url: Api.tree, params });
+
+/**
+ * 获取分类树
+ */
+export const getCategoryTree = () => defHttp.get({ url: Api.tree });
+
+/**
+ * 删除单个
+ */
+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 });
+};
\ No newline at end of file
diff --git a/src/views/oroqen/culture-category/OroqenCultureCategory.data.ts b/src/views/oroqen/culture-category/OroqenCultureCategory.data.ts
new file mode 100644
index 0000000..48c26cd
--- /dev/null
+++ b/src/views/oroqen/culture-category/OroqenCultureCategory.data.ts
@@ -0,0 +1,151 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { rules } from '/@/utils/helper/validator';
+import { render } from '/@/utils/common/renderUtils';
+
+// 列表页面公共参数、方法
+export const columns: BasicColumn[] = [
+ {
+ title: '分类名称',
+ align: 'left',
+ dataIndex: 'categoryName',
+ width: 200,
+ },
+ {
+ title: '分类编码',
+ align: 'center',
+ dataIndex: 'categoryCode',
+ width: 150,
+ },
+ {
+ title: '排序',
+ align: 'center',
+ dataIndex: 'sortOrder',
+ width: 80,
+ },
+ {
+ title: '状态',
+ align: 'center',
+ dataIndex: 'status',
+ width: 100,
+ customRender: ({ text }) => {
+ const statusMap = {
+ '1': { text: '启用', color: 'green' },
+ '0': { text: '禁用', color: 'red' }
+ };
+ const status = statusMap[text] || { text: '未知', color: 'gray' };
+ return render.renderTag(status.text, status.color);
+ },
+ },
+ {
+ title: '描述',
+ align: 'center',
+ dataIndex: 'description',
+ width: 200,
+ ellipsis: true,
+ },
+ {
+ title: '创建时间',
+ align: 'center',
+ dataIndex: 'createTime',
+ width: 150,
+ },
+];
+
+// 查询数据
+export const searchFormSchema: FormSchema[] = [
+ {
+ label: '分类名称',
+ field: 'categoryName',
+ component: 'Input',
+ colProps: { span: 6 },
+ },
+ {
+ label: '分类编码',
+ field: 'categoryCode',
+ component: 'Input',
+ colProps: { span: 6 },
+ },
+ {
+ label: '状态',
+ field: 'status',
+ component: 'JDictSelectTag',
+ componentProps: {
+ dictCode: 'valid_status',
+ placeholder: '请选择状态',
+ },
+ colProps: { span: 6 },
+ },
+];
+
+// 表单数据
+export const formSchema: FormSchema[] = [
+ {
+ label: '',
+ field: 'id',
+ component: 'Input',
+ show: false,
+ },
+ {
+ label: '上级分类',
+ field: 'parentId',
+ component: 'JTreeSelect',
+ componentProps: {
+ dict: 'oroqen_culture_category,category_name,id',
+ pidField: 'parent_id',
+ pidValue: '',
+ hasChildField: 'has_child',
+ placeholder: '请选择上级分类',
+ },
+ },
+ {
+ label: '分类名称',
+ field: 'categoryName',
+ component: 'Input',
+ required: true,
+ dynamicRules: ({ model, schema }) => {
+ return [{ required: true, message: '请输入分类名称!' }];
+ },
+ },
+ {
+ label: '分类编码',
+ field: 'categoryCode',
+ component: 'Input',
+ required: true,
+ dynamicRules: ({ model, schema }) => {
+ return [
+ { required: true, message: '请输入分类编码!' },
+ { pattern: /^[a-zA-Z0-9_]+$/, message: '编码只能包含字母、数字和下划线!' }
+ ];
+ },
+ },
+ {
+ label: '排序',
+ field: 'sortOrder',
+ component: 'InputNumber',
+ defaultValue: 0,
+ componentProps: {
+ min: 0,
+ placeholder: '请输入排序值',
+ },
+ },
+ {
+ label: '状态',
+ field: 'status',
+ component: 'JDictSelectTag',
+ defaultValue: '1',
+ componentProps: {
+ dictCode: 'valid_status',
+ placeholder: '请选择状态',
+ },
+ },
+ {
+ label: '描述',
+ field: 'description',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 3,
+ placeholder: '请输入分类描述',
+ },
+ },
+];
\ No newline at end of file
diff --git a/src/views/oroqen/culture-category/OroqenCultureCategoryList.vue b/src/views/oroqen/culture-category/OroqenCultureCategoryList.vue
new file mode 100644
index 0000000..07aa1c8
--- /dev/null
+++ b/src/views/oroqen/culture-category/OroqenCultureCategoryList.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+ 新增
+ 导出
+ 导入
+
+
+
+
+
+
+ 删除
+
+
+
+ 批量操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getAreaTextByCode(text) }}
+
+
+ 无文件
+ 下载
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/culture-category/components/OroqenCultureCategoryForm.vue b/src/views/oroqen/culture-category/components/OroqenCultureCategoryForm.vue
new file mode 100644
index 0000000..7148cac
--- /dev/null
+++ b/src/views/oroqen/culture-category/components/OroqenCultureCategoryForm.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/culture-category/components/OroqenCultureCategoryModal.vue b/src/views/oroqen/culture-category/components/OroqenCultureCategoryModal.vue
new file mode 100644
index 0000000..9e43c99
--- /dev/null
+++ b/src/views/oroqen/culture-category/components/OroqenCultureCategoryModal.vue
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/culture-content/OroqenCultureContent.api.ts b/src/views/oroqen/culture-content/OroqenCultureContent.api.ts
new file mode 100644
index 0000000..a1f556a
--- /dev/null
+++ b/src/views/oroqen/culture-content/OroqenCultureContent.api.ts
@@ -0,0 +1,75 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+ list = '/oroqen/cultureContent/list',
+ save = '/oroqen/cultureContent/add',
+ edit = '/oroqen/cultureContent/edit',
+ deleteOne = '/oroqen/cultureContent/delete',
+ deleteBatch = '/oroqen/cultureContent/deleteBatch',
+ importExcel = '/oroqen/cultureContent/importExcel',
+ exportXls = '/oroqen/cultureContent/exportXls',
+ queryById = '/oroqen/cultureContent/queryById',
+ recommend = '/oroqen/cultureContent/recommend',
+ cancelRecommend = '/oroqen/cultureContent/cancelRecommend',
+}
+
+/**
+ * 导出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 });
+};
+
+/**
+ * 推荐/取消推荐
+ */
+export const toggleRecommend = (id: string, isRecommend: boolean) => {
+ const url = isRecommend ? Api.recommend : Api.cancelRecommend;
+ return defHttp.post({ url: `${url}/${id}` });
+};
\ No newline at end of file
diff --git a/src/views/oroqen/culture-content/OroqenCultureContent.data.ts b/src/views/oroqen/culture-content/OroqenCultureContent.data.ts
new file mode 100644
index 0000000..4fc9248
--- /dev/null
+++ b/src/views/oroqen/culture-content/OroqenCultureContent.data.ts
@@ -0,0 +1,294 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { rules } from '/@/utils/helper/validator';
+import { render } from '/@/utils/common/renderUtils';
+import { JVxeTypes, JVxeColumn } from '/@/components/jeecg/JVxeTable/types';
+import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
+
+// 列表页面公共参数、方法
+export const columns: BasicColumn[] = [
+ {
+ title: '标题',
+ align: 'center',
+ dataIndex: 'title',
+ width: 200,
+ },
+ {
+ title: '分类',
+ align: 'center',
+ dataIndex: 'categoryName',
+ width: 120,
+ },
+ {
+ title: '封面图片',
+ align: 'center',
+ dataIndex: 'coverImage',
+ width: 120,
+ customRender: ({ text }) => {
+ if (!text) return '';
+ const imgUrl = getFileAccessHttpUrl(text);
+ return render.renderImage(imgUrl, {
+ style: { width: '60px', height: '40px', objectFit: 'cover' },
+ preview: true,
+ fallback: '/src/assets/images/no-image.png'
+ });
+ },
+ },
+ {
+ title: '作者',
+ align: 'center',
+ dataIndex: 'author',
+ width: 100,
+ },
+ {
+ title: '发布状态',
+ align: 'center',
+ dataIndex: 'status',
+ width: 100,
+ customRender: ({ text }) => {
+ const statusMap = {
+ '0': { text: '草稿', color: 'orange' },
+ '1': { text: '已发布', color: 'green' },
+ '2': { text: '已下线', color: 'red' }
+ };
+ const status = statusMap[text] || { text: '未知', color: 'gray' };
+ return render.renderTag(status.text, status.color);
+ },
+ },
+ {
+ title: '是否推荐',
+ align: 'center',
+ dataIndex: 'isRecommended',
+ width: 100,
+ customRender: ({ text }) => {
+ return render.renderSwitch(text, [
+ { text: '是', value: '1' },
+ { text: '否', value: '0' }
+ ]);
+ },
+ },
+ {
+ title: '浏览量',
+ align: 'center',
+ dataIndex: 'viewCount',
+ width: 100,
+ },
+ {
+ title: '点赞数',
+ align: 'center',
+ dataIndex: 'likeCount',
+ width: 100,
+ },
+ {
+ title: '创建时间',
+ align: 'center',
+ dataIndex: 'createTime',
+ width: 150,
+ },
+];
+
+// 查询数据
+export const searchFormSchema: FormSchema[] = [
+ {
+ label: '标题',
+ field: 'title',
+ component: 'Input',
+ colProps: { span: 6 },
+ },
+ {
+ label: '分类',
+ field: 'categoryId',
+ component: 'JTreeSelect',
+ componentProps: {
+ dict: 'oroqen_culture_category,category_name,id',
+ pidField: 'parent_id',
+ pidValue: '0',
+ hasChildField: 'has_child',
+ placeholder: '请选择分类',
+ },
+ colProps: { span: 6 },
+ },
+ {
+ label: '发布状态',
+ field: 'status',
+ component: 'JDictSelectTag',
+ componentProps: {
+ dictCode: 'content_status',
+ placeholder: '请选择状态',
+ },
+ colProps: { span: 6 },
+ },
+ {
+ label: '是否推荐',
+ field: 'isRecommended',
+ component: 'JDictSelectTag',
+ componentProps: {
+ dictCode: 'yes_no',
+ placeholder: '请选择',
+ },
+ colProps: { span: 6 },
+ },
+];
+
+// 表单数据
+export const formSchema: FormSchema[] = [
+ {
+ label: '',
+ field: 'id',
+ component: 'Input',
+ show: false,
+ },
+ {
+ label: '标题',
+ field: 'title',
+ component: 'Input',
+ required: true,
+ dynamicRules: ({ model, schema }) => {
+ return [{ required: true, message: '请输入标题!' }];
+ },
+ },
+ {
+ label: '分类',
+ field: 'categoryId',
+ component: 'JTreeSelect',
+ required: true,
+ componentProps: {
+ dict: 'oroqen_culture_category,category_name,id',
+ pidField: 'parent_id',
+ pidValue: '0',
+ hasChildField: 'has_child',
+ placeholder: '请选择分类',
+ },
+ dynamicRules: ({ model, schema }) => {
+ return [{ required: true, message: '请选择分类!' }];
+ },
+ },
+ {
+ label: '封面图片',
+ field: 'coverImage',
+ component: 'JUpload',
+ componentProps: {
+ fileType: 'image',
+ maxSize: 5,
+ maxCount: 1,
+ bizPath: 'culture/cover',
+ customRequest: (options) => {
+ const { file, onSuccess, onError } = options;
+
+ // 验证文件类型
+ const isImage = file.type.startsWith('image/');
+ if (!isImage) {
+ onError(new Error('只能上传图片文件!'));
+ return;
+ }
+
+ // 验证文件大小
+ const isLt5M = file.size / 1024 / 1024 < 5;
+ if (!isLt5M) {
+ onError(new Error('图片大小不能超过5MB!'));
+ return;
+ }
+
+ // 创建本地预览URL
+ const blobUrl = URL.createObjectURL(file);
+
+ // 模拟上传成功响应
+ setTimeout(() => {
+ onSuccess({
+ status: 'done',
+ url: blobUrl,
+ message: blobUrl,
+ response: {
+ success: true,
+ message: '上传成功',
+ result: {
+ url: blobUrl
+ }
+ }
+ });
+ }, 100);
+ }
+ },
+ },
+ {
+ label: '作者',
+ field: 'author',
+ component: 'Input',
+ },
+ {
+ label: '摘要',
+ field: 'summary',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 3,
+ placeholder: '请输入内容摘要',
+ },
+ },
+ {
+ label: '内容',
+ field: 'content',
+ component: 'JEditor',
+ required: true,
+ componentProps: {
+ height: 400,
+ placeholder: '请输入内容',
+ },
+ dynamicRules: ({ model, schema }) => {
+ return [{ required: true, message: '请输入内容!' }];
+ },
+ },
+ {
+ label: '发布状态',
+ field: 'status',
+ component: 'JDictSelectTag',
+ defaultValue: '0',
+ componentProps: {
+ dictCode: 'content_status',
+ placeholder: '请选择状态',
+ },
+ },
+ {
+ label: '是否推荐',
+ field: 'isRecommended',
+ component: 'JSwitch',
+ defaultValue: '0',
+ componentProps: {
+ options: ['0', '1'],
+ },
+ },
+ {
+ label: '排序',
+ field: 'sortOrder',
+ component: 'InputNumber',
+ defaultValue: 0,
+ componentProps: {
+ min: 0,
+ placeholder: '请输入排序值',
+ },
+ },
+ {
+ label: '标签',
+ field: 'tags',
+ component: 'Input',
+ componentProps: {
+ placeholder: '多个标签用逗号分隔',
+ },
+ },
+ {
+ label: '关键词',
+ field: 'keywords',
+ component: 'Input',
+ componentProps: {
+ placeholder: '多个关键词用逗号分隔',
+ },
+ },
+ {
+ label: '备注',
+ field: 'remark',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 2,
+ placeholder: '请输入备注',
+ },
+ },
+];
\ No newline at end of file
diff --git a/src/views/oroqen/culture-content/OroqenCultureContentList.vue b/src/views/oroqen/culture-content/OroqenCultureContentList.vue
new file mode 100644
index 0000000..765326f
--- /dev/null
+++ b/src/views/oroqen/culture-content/OroqenCultureContentList.vue
@@ -0,0 +1,162 @@
+
+
+
+
+
+
+ 新增
+ 导出
+ 导入
+
+
+
+
+
+
+ 删除
+
+
+
+ 批量操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getAreaTextByCode(text) }}
+
+
+ 无文件
+ 下载
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/oroqen/culture-content/components/OroqenCultureContentForm.vue b/src/views/oroqen/culture-content/components/OroqenCultureContentForm.vue
new file mode 100644
index 0000000..0f5ba44
--- /dev/null
+++ b/src/views/oroqen/culture-content/components/OroqenCultureContentForm.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/culture-content/components/OroqenCultureContentModal.vue b/src/views/oroqen/culture-content/components/OroqenCultureContentModal.vue
new file mode 100644
index 0000000..afbbd0e
--- /dev/null
+++ b/src/views/oroqen/culture-content/components/OroqenCultureContentModal.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/inheritor/OroqenInheritor.api.ts b/src/views/oroqen/inheritor/OroqenInheritor.api.ts
new file mode 100644
index 0000000..472ae9f
--- /dev/null
+++ b/src/views/oroqen/inheritor/OroqenInheritor.api.ts
@@ -0,0 +1,72 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+ list = '/oroqen/heritageInheritor/list',
+ save = '/oroqen/heritageInheritor/add',
+ edit = '/oroqen/heritageInheritor/edit',
+ deleteOne = '/oroqen/heritageInheritor/delete',
+ deleteBatch = '/oroqen/heritageInheritor/deleteBatch',
+ importExcel = '/oroqen/heritageInheritor/importExcel',
+ exportXls = '/oroqen/heritageInheritor/exportXls',
+ queryById = '/oroqen/heritageInheritor/queryById',
+}
+
+/**
+ * 导出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) => {
+ const url = isUpdate ? Api.edit : Api.save;
+ return defHttp.post({ url: url, params }, { isTransformResponse: false });
+};
+
+/**
+ * 根据ID查询
+ */
+export const queryById = (params) => {
+ return defHttp.get({ url: Api.queryById, params });
+};
\ No newline at end of file
diff --git a/src/views/oroqen/inheritor/OroqenInheritor.data.ts b/src/views/oroqen/inheritor/OroqenInheritor.data.ts
new file mode 100644
index 0000000..857bb8a
--- /dev/null
+++ b/src/views/oroqen/inheritor/OroqenInheritor.data.ts
@@ -0,0 +1,395 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { h } from 'vue';
+import { Image, Tag } from 'ant-design-vue';
+import { render } from '/@/utils/common/renderUtils';
+import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
+
+//列表数据
+export const columns: BasicColumn[] = [
+ {
+ title: '头像',
+ align: 'center',
+ dataIndex: 'avatar',
+ width: 80,
+ customRender: ({ text, record }) => {
+ if (!text) return '-';
+ const imageUrl = getFileAccessHttpUrl(text);
+
+ return h(Image, {
+ src: imageUrl,
+ alt: record?.name || '传承人头像',
+ width: 50,
+ height: 50,
+ style: { objectFit: 'cover', borderRadius: '4px' },
+ preview: true,
+ fallback: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3Ik1RnG4W+FgYxN'
+ });
+ }
+ },
+ {
+ title: '姓名',
+ dataIndex: 'name',
+ width: 120,
+ align: 'left',
+ ellipsis: true,
+ fixed: 'left',
+ },
+ {
+ title: '性别',
+ dataIndex: 'gender',
+ width: 80,
+ align: 'center',
+ customRender: ({ text }) => {
+ const genderMap = {
+ 1: { text: '男', color: 'blue' },
+ 2: { text: '女', color: 'pink' },
+ };
+ const gender = genderMap[text] || { text: '未知', color: 'default' };
+ return render.renderTag(gender.text, gender.color);
+ },
+ },
+ {
+ title: '年龄',
+ dataIndex: 'age',
+ width: 80,
+ align: 'center',
+ },
+ {
+ title: '民族',
+ dataIndex: 'ethnicity',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '传承项目',
+ dataIndex: 'heritageProject',
+ width: 150,
+ align: 'left',
+ ellipsis: true,
+ },
+ {
+ title: '传承级别',
+ dataIndex: 'heritageLevel',
+ width: 120,
+ align: 'center',
+ customRender: ({ text }) => {
+ const levelMap = {
+ 'national': { text: '国家级', color: 'red' },
+ 'provincial': { text: '省级', color: 'orange' },
+ 'municipal': { text: '市级', color: 'blue' },
+ 'county': { text: '县级', color: 'green' },
+ };
+ const level = levelMap[text] || { text: text || '未知', color: 'default' };
+ return render.renderTag(level.text, level.color);
+ },
+ },
+ {
+ title: '认定年份',
+ dataIndex: 'recognitionYear',
+ width: 100,
+ align: 'center',
+ },
+ {
+ title: '联系电话',
+ dataIndex: 'phone',
+ width: 120,
+ align: 'center',
+ },
+ {
+ title: '状态',
+ dataIndex: 'status',
+ width: 100,
+ align: 'center',
+ customRender: ({ text }) => {
+ const statusMap = {
+ 1: { text: '活跃', color: 'green' },
+ 0: { text: '停用', color: 'red' },
+ };
+ const status = statusMap[text] || { text: '未知', color: 'default' };
+ return render.renderTag(status.text, status.color);
+ },
+ },
+ {
+ title: '创建时间',
+ dataIndex: 'createTime',
+ width: 150,
+ align: 'center',
+ sorter: true,
+ },
+];
+
+//查询数据
+export const searchFormSchema: FormSchema[] = [
+ {
+ label: '姓名',
+ field: 'name',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入传承人姓名',
+ },
+ colProps: { span: 6 },
+ },
+ {
+ label: '性别',
+ field: 'gender',
+ component: 'Select',
+ componentProps: {
+ placeholder: '请选择性别',
+ options: [
+ { label: '男', value: 1 },
+ { label: '女', value: 2 },
+ ],
+ },
+ colProps: { span: 6 },
+ },
+ {
+ label: '传承级别',
+ field: 'heritageLevel',
+ component: 'Select',
+ componentProps: {
+ placeholder: '请选择传承级别',
+ options: [
+ { label: '国家级', value: 'national' },
+ { label: '省级', value: 'provincial' },
+ { label: '市级', value: 'municipal' },
+ { label: '县级', value: 'county' },
+ ],
+ },
+ colProps: { span: 6 },
+ },
+ {
+ label: '状态',
+ field: 'status',
+ component: 'Select',
+ componentProps: {
+ placeholder: '请选择状态',
+ options: [
+ { label: '活跃', value: 1 },
+ { label: '停用', value: 0 },
+ ],
+ },
+ colProps: { span: 6 },
+ },
+];
+
+//表单数据
+export const formSchema: FormSchema[] = [
+ {
+ label: '',
+ field: 'id',
+ component: 'Input',
+ show: false,
+ },
+ {
+ label: '姓名',
+ field: 'name',
+ component: 'Input',
+ required: true,
+ componentProps: {
+ placeholder: '请输入传承人姓名',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '性别',
+ field: 'gender',
+ component: 'Select',
+ required: true,
+ componentProps: {
+ placeholder: '请选择性别',
+ options: [
+ { label: '男', value: 1 },
+ { label: '女', value: 2 },
+ ],
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '年龄',
+ field: 'age',
+ component: 'InputNumber',
+ componentProps: {
+ min: 1,
+ max: 120,
+ placeholder: '请输入年龄',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '民族',
+ field: 'ethnicity',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入民族',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '传承项目',
+ field: 'heritageProject',
+ component: 'Input',
+ required: true,
+ componentProps: {
+ placeholder: '请输入传承项目',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '传承级别',
+ field: 'heritageLevel',
+ component: 'Select',
+ required: true,
+ componentProps: {
+ placeholder: '请选择传承级别',
+ options: [
+ { label: '国家级', value: 'national' },
+ { label: '省级', value: 'provincial' },
+ { label: '市级', value: 'municipal' },
+ { label: '县级', value: 'county' },
+ ],
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '认定年份',
+ field: 'recognitionYear',
+ component: 'InputNumber',
+ componentProps: {
+ min: 1900,
+ max: new Date().getFullYear(),
+ placeholder: '请输入认定年份',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '联系电话',
+ field: 'phone',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入联系电话',
+ },
+ colProps: { span: 12 },
+ },
+ // {
+ // label: '身份证号',
+ // field: 'idCard',
+ // component: 'Input',
+ // componentProps: {
+ // placeholder: '请输入身份证号',
+ // },
+ // colProps: { span: 12 },
+ // },
+ {
+ label: '地址',
+ field: 'address',
+ component: 'Input',
+ componentProps: {
+ placeholder: '请输入地址',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '状态',
+ field: 'status',
+ component: 'Select',
+ componentProps: {
+ placeholder: '请选择状态',
+ options: [
+ { label: '活跃', value: 1 },
+ { label: '停用', value: 0 },
+ ],
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '排序',
+ field: 'sortOrder',
+ component: 'InputNumber',
+ componentProps: {
+ min: 0,
+ placeholder: '请输入排序值',
+ },
+ colProps: { span: 12 },
+ },
+ {
+ label: '传承技艺描述',
+ field: 'skillDescription',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 4,
+ placeholder: '请输入传承技艺描述',
+ },
+ colProps: { span: 24 },
+ },
+ {
+ label: '个人简介',
+ field: 'biography',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 4,
+ placeholder: '请输入个人简介',
+ },
+ colProps: { span: 24 },
+ },
+ {
+ label: '传承经历',
+ field: 'heritageExperience',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 4,
+ placeholder: '请输入传承经历',
+ },
+ colProps: { span: 24 },
+ },
+ {
+ label: '获奖情况',
+ field: 'awards',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 3,
+ placeholder: '请输入获奖情况',
+ },
+ colProps: { span: 24 },
+ },
+ {
+ label: '头像',
+ field: 'avatar',
+ component: 'JUpload',
+ componentProps: {
+ fileType: 'image',
+ maxCount: 1,
+ maxSize: 5,
+ bizPath: 'inheritor/portrait',
+ 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: 24 },
+ },
+];
\ No newline at end of file
diff --git a/src/views/oroqen/inheritor/OroqenInheritorList.vue b/src/views/oroqen/inheritor/OroqenInheritorList.vue
new file mode 100644
index 0000000..bef92d4
--- /dev/null
+++ b/src/views/oroqen/inheritor/OroqenInheritorList.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+ 新增
+ 导出
+ 导入
+
+
+
+
+
+ 删除
+
+
+
+ 批量操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/inheritor/components/OroqenInheritorForm.vue b/src/views/oroqen/inheritor/components/OroqenInheritorForm.vue
new file mode 100644
index 0000000..24f9b0f
--- /dev/null
+++ b/src/views/oroqen/inheritor/components/OroqenInheritorForm.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/inheritor/components/OroqenInheritorModal.vue b/src/views/oroqen/inheritor/components/OroqenInheritorModal.vue
new file mode 100644
index 0000000..22c836f
--- /dev/null
+++ b/src/views/oroqen/inheritor/components/OroqenInheritorModal.vue
@@ -0,0 +1,265 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/product-category/OroqenProductCategory.api.ts b/src/views/oroqen/product-category/OroqenProductCategory.api.ts
new file mode 100644
index 0000000..3a8bcf4
--- /dev/null
+++ b/src/views/oroqen/product-category/OroqenProductCategory.api.ts
@@ -0,0 +1,76 @@
+import { defHttp } from '/@/utils/http/axios';
+import { useMessage } from '/@/hooks/web/useMessage';
+
+const { createConfirm } = useMessage();
+
+enum Api {
+ list = '/oroqen/productCategory/list',
+ save = '/oroqen/productCategory/add',
+ edit = '/oroqen/productCategory/edit',
+ deleteOne = '/oroqen/productCategory/delete',
+ deleteBatch = '/oroqen/productCategory/deleteBatch',
+ importExcel = '/oroqen/productCategory/importExcel',
+ exportXls = '/oroqen/productCategory/exportXls',
+ queryById = '/oroqen/productCategory/queryById',
+ tree = '/oroqen/productCategory/tree',
+}
+
+/**
+ * 导出api
+ */
+export const getExportUrl = Api.exportXls;
+
+/**
+ * 导入api
+ */
+export const getImportUrl = Api.importExcel;
+
+/**
+ * 列表接口
+ */
+export const list = (params) => defHttp.get({ url: Api.list, params });
+
+/**
+ * 树形列表接口
+ */
+export const queryTreeList = (params) => defHttp.get({ url: Api.tree, params });
+
+/**
+ * 获取分类树
+ */
+export const getCategoryTree = () => defHttp.get({ url: Api.tree });
+
+/**
+ * 删除单个
+ */
+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 });
+};
\ No newline at end of file
diff --git a/src/views/oroqen/product-category/OroqenProductCategory.data.ts b/src/views/oroqen/product-category/OroqenProductCategory.data.ts
new file mode 100644
index 0000000..1065fe5
--- /dev/null
+++ b/src/views/oroqen/product-category/OroqenProductCategory.data.ts
@@ -0,0 +1,214 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { rules } from '/@/utils/helper/validator';
+import { render } from '/@/utils/common/renderUtils';
+import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
+
+// 列表页面公共参数、方法
+export const columns: BasicColumn[] = [
+ {
+ title: '分类名称',
+ align: 'left',
+ dataIndex: 'categoryName',
+ width: 200,
+ },
+ {
+ title: '分类编码',
+ align: 'center',
+ dataIndex: 'categoryCode',
+ width: 150,
+ },
+ {
+ title: '分类图标',
+ align: 'center',
+ dataIndex: 'icon',
+ width: 100,
+ customRender: ({ text }) => {
+ if (!text) return '';
+ const imgUrl = getFileAccessHttpUrl(text);
+ return render.renderImage(imgUrl, {
+ style: { width: '40px', height: '40px', objectFit: 'cover' },
+ preview: true,
+ fallback: '/src/assets/images/no-image.png'
+ });
+ },
+ },
+ {
+ title: '排序',
+ align: 'center',
+ dataIndex: 'sortOrder',
+ width: 80,
+ },
+ {
+ title: '状态',
+ align: 'center',
+ dataIndex: 'status',
+ width: 100,
+ customRender: ({ text }) => {
+ const statusMap = {
+ '1': { text: '启用', color: 'green' },
+ '0': { text: '禁用', color: 'red' }
+ };
+ const status = statusMap[text] || { text: '未知', color: 'gray' };
+ return render.renderTag(status.text, status.color);
+ },
+ },
+ {
+ title: '描述',
+ align: 'center',
+ dataIndex: 'description',
+ width: 200,
+ ellipsis: true,
+ },
+ {
+ title: '创建时间',
+ align: 'center',
+ dataIndex: 'createTime',
+ width: 150,
+ },
+];
+
+// 查询数据
+export const searchFormSchema: FormSchema[] = [
+ {
+ label: '分类名称',
+ field: 'categoryName',
+ component: 'Input',
+ colProps: { span: 6 },
+ },
+ {
+ label: '分类编码',
+ field: 'categoryCode',
+ component: 'Input',
+ colProps: { span: 6 },
+ },
+ {
+ label: '状态',
+ field: 'status',
+ component: 'JDictSelectTag',
+ componentProps: {
+ dictCode: 'valid_status',
+ placeholder: '请选择状态',
+ },
+ colProps: { span: 6 },
+ },
+];
+
+// 表单数据
+export const formSchema: FormSchema[] = [
+ {
+ label: '',
+ field: 'id',
+ component: 'Input',
+ show: false,
+ },
+ {
+ label: '上级分类',
+ field: 'parentId',
+ component: 'JTreeSelect',
+ componentProps: {
+ dict: 'oroqen_product_category,category_name,id',
+ pidField: 'parent_id',
+ pidValue: '',
+ hasChildField: 'has_child',
+ placeholder: '请选择上级分类',
+ },
+ },
+ {
+ label: '分类名称',
+ field: 'categoryName',
+ component: 'Input',
+ required: true,
+ dynamicRules: ({ model, schema }) => {
+ return [{ required: true, message: '请输入分类名称!' }];
+ },
+ },
+ {
+ label: '分类编码',
+ field: 'categoryCode',
+ component: 'Input',
+ required: true,
+ dynamicRules: ({ model, schema }) => {
+ return [
+ { required: true, message: '请输入分类编码!' },
+ { pattern: /^[a-zA-Z0-9_]+$/, message: '编码只能包含字母、数字和下划线!' }
+ ];
+ },
+ },
+ {
+ label: '分类图标',
+ field: 'icon',
+ component: 'JUpload',
+ componentProps: {
+ fileType: 'image',
+ maxSize: 2,
+ maxCount: 1,
+ bizPath: 'product/category/icon',
+ customRequest: (options) => {
+ const { file, onSuccess, onError } = options;
+
+ // 验证文件类型
+ const isImage = file.type.startsWith('image/');
+ if (!isImage) {
+ onError(new Error('只能上传图片文件!'));
+ return;
+ }
+
+ // 验证文件大小
+ const isLt2M = file.size / 1024 / 1024 < 2;
+ if (!isLt2M) {
+ onError(new Error('图片大小不能超过2MB!'));
+ return;
+ }
+
+ // 创建本地预览URL
+ const blobUrl = URL.createObjectURL(file);
+
+ // 模拟上传成功响应
+ setTimeout(() => {
+ onSuccess({
+ status: 'done',
+ url: blobUrl,
+ message: blobUrl,
+ response: {
+ success: true,
+ message: '上传成功',
+ result: {
+ url: blobUrl
+ }
+ }
+ });
+ }, 100);
+ }
+ },
+ },
+ {
+ label: '排序',
+ field: 'sortOrder',
+ component: 'InputNumber',
+ defaultValue: 0,
+ componentProps: {
+ min: 0,
+ placeholder: '请输入排序值',
+ },
+ },
+ {
+ label: '状态',
+ field: 'status',
+ component: 'JDictSelectTag',
+ defaultValue: '1',
+ componentProps: {
+ dictCode: 'valid_status',
+ placeholder: '请选择状态',
+ },
+ },
+ {
+ label: '描述',
+ field: 'description',
+ component: 'InputTextArea',
+ componentProps: {
+ rows: 3,
+ placeholder: '请输入分类描述',
+ },
+ },
+];
\ No newline at end of file
diff --git a/src/views/oroqen/product-category/OroqenProductCategoryList.vue b/src/views/oroqen/product-category/OroqenProductCategoryList.vue
new file mode 100644
index 0000000..061f955
--- /dev/null
+++ b/src/views/oroqen/product-category/OroqenProductCategoryList.vue
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+ 新增
+ 导出
+ 导入
+
+
+
+
+
+
+ 删除
+
+
+
+ 批量操作
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ getAreaTextByCode(text) }}
+
+
+ 无文件
+ 下载
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/product-category/components/OroqenProductCategoryForm.vue b/src/views/oroqen/product-category/components/OroqenProductCategoryForm.vue
new file mode 100644
index 0000000..6082036
--- /dev/null
+++ b/src/views/oroqen/product-category/components/OroqenProductCategoryForm.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/oroqen/product-category/components/OroqenProductCategoryModal.vue b/src/views/oroqen/product-category/components/OroqenProductCategoryModal.vue
new file mode 100644
index 0000000..c6aa82d
--- /dev/null
+++ b/src/views/oroqen/product-category/components/OroqenProductCategoryModal.vue
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
\ No newline at end of file