diff --git a/pages/champion/champion.vue b/pages/champion/champion.vue
index 1c2fd0e..ebb7bfa 100644
--- a/pages/champion/champion.vue
+++ b/pages/champion/champion.vue
@@ -117,14 +117,6 @@
confirm-type="search"
@confirm="onMaterialSearch"
/>
-
+ :key="item.id || index">
-
-
- 知识分类:{{ item.category }}
- 应用行业:{{ item.industry }}
- 创建人:{{ item.creator }}
-
-
-
-
- 状态:{{ item.status }}
+
-
- {{ item.updateTime ? `更新时间:${formatDateTime(item.updateTime)}` : `创建时间:${formatDateTime(item.createTime)}` }}
+
+ 所属行业: {{ item.industry }}
+
+
+
+
+ 详情: {{ getContentPreview(item.content) }}
+
+
+ 备注: {{ item.remark }}
+
+
+
+
+
@@ -213,6 +216,8 @@
placeholder="请输入知识分类"
placeholder-style="color: #9ca3af"
maxlength="100"
+ :disabled="true"
+ readonly
/>
@@ -228,15 +233,13 @@
文件上传
-
-
- {{ file.name || '文件' + (index + 1) }}
-
-
-
+
+ {{ materialForm.file.name || '文件' }}
+
+
-
+
@@ -254,6 +257,85 @@
+
+
+
+
+
+
+
@@ -264,6 +346,16 @@
// #endif
import { getApiUrl } from "@/common/config.js";
+ // 获取租户ID
+ function getTenantId() {
+ try {
+ return uni.getStorageSync('backend-tenant-id') || '';
+ } catch (e) {
+ console.error('获取 tenantId 失败:', e);
+ return '';
+ }
+ }
+
export default {
// #ifdef APP
components: {
@@ -283,7 +375,7 @@
},
materialQuery: {
title: '',
- category: '',
+ category: '基础知识库',
industry: '',
creator: '',
status: ''
@@ -295,7 +387,22 @@
category: '',
industry: '',
files: []
- }
+ },
+ // 编辑素材弹出框
+ showEditMaterialPopup: false,
+ editMaterialForm: {
+ id: '',
+ title: '',
+ category: '',
+ industry: '',
+ content: '',
+ remark: ''
+ },
+ // 上下文菜单
+ contextMenuVisible: false,
+ contextMenuIndex: -1,
+ contextMenuTop: 0,
+ contextMenuLeft: 0
}
},
onLoad() {
@@ -338,10 +445,10 @@
try {
const queryParams = {
current: this.materialPage.current,
- size: this.materialPage.size
+ size: this.materialPage.size,
+ category: '基础知识库' // 默认添加知识分类参数
};
const trimmedTitle = this.materialQuery?.title?.trim();
- const trimmedCategory = this.materialQuery?.category?.trim();
const trimmedIndustry = this.materialQuery?.industry?.trim();
const trimmedCreator = this.materialQuery?.creator?.trim();
const trimmedStatus = this.materialQuery?.status?.trim();
@@ -349,9 +456,6 @@
if (trimmedTitle) {
queryParams.title = trimmedTitle;
}
- if (trimmedCategory) {
- queryParams.category = trimmedCategory;
- }
if (trimmedIndustry) {
queryParams.industry = trimmedIndustry;
}
@@ -366,9 +470,18 @@
.map(key => `${key}=${encodeURIComponent(queryParams[key])}`)
.join('&');
const url = `${getApiUrl('/api/knowledgeBase/list')}?${queryString}`;
+
+ // 获取租户ID
+ const tenantId = getTenantId();
+ const headers = {};
+ if (tenantId) {
+ headers['X-Tenant-Id'] = tenantId;
+ }
+
const res = await uni.request({
url,
method: 'POST',
+ header: headers,
timeout: 10000
});
@@ -419,20 +532,210 @@
// 查看素材详情
console.log('查看素材详情', item);
},
+ getContentPreview(content) {
+ if (!content) return '';
+ return content.length > 10 ? content.substring(0, 10) : content;
+ },
+ showContextMenu(item, index, event) {
+ // 阻止事件冒泡
+ if (event && event.stopPropagation) {
+ event.stopPropagation();
+ }
+ // 获取系统信息以计算位置
+ const systemInfo = uni.getSystemInfoSync();
+ // 获取点击位置 - 优先使用触摸事件坐标
+ let top = 100;
+ let left = systemInfo.windowWidth - 180;
+
+ if (event) {
+ if (event.touches && event.touches.length > 0) {
+ // 触摸事件
+ top = event.touches[0].clientY;
+ left = event.touches[0].clientX - 80;
+ } else if (event.detail && typeof event.detail.x === 'number') {
+ // tap事件坐标(单位:px,需要转换)
+ top = event.detail.y;
+ left = event.detail.x - 80;
+ } else if (event.clientY !== undefined) {
+ // 鼠标事件
+ top = event.clientY;
+ left = event.clientX - 80;
+ }
+ }
+
+ // 确保菜单不超出屏幕
+ if (left + 160 > systemInfo.windowWidth) {
+ left = systemInfo.windowWidth - 180;
+ }
+ if (left < 0) {
+ left = 10;
+ }
+
+ this.contextMenuTop = top;
+ this.contextMenuLeft = left;
+ // 显示菜单
+ this.contextMenuIndex = index;
+ this.contextMenuVisible = true;
+ },
+ closeContextMenu() {
+ this.contextMenuVisible = false;
+ this.contextMenuIndex = -1;
+ },
+ handleEditMaterial(item) {
+ this.closeContextMenu();
+ // 填充编辑表单
+ this.editMaterialForm = {
+ id: item.id,
+ title: item.title || '',
+ category: item.category || '',
+ industry: item.industry || '',
+ content: item.content || '',
+ remark: item.remark || ''
+ };
+ this.showEditMaterialPopup = true;
+ },
+ closeEditMaterialPopup() {
+ this.showEditMaterialPopup = false;
+ this.editMaterialForm = {
+ id: '',
+ title: '',
+ category: '',
+ industry: '',
+ content: '',
+ remark: ''
+ };
+ },
+ async submitEditMaterial() {
+ // 表单验证
+ if (!this.editMaterialForm.title || !this.editMaterialForm.title.trim()) {
+ uni.showToast({
+ title: "请输入知识标题",
+ icon: "none"
+ });
+ return;
+ }
+
+ try {
+ uni.showLoading({
+ title: "保存中..."
+ });
+
+ // 获取租户ID
+ const tenantId = getTenantId();
+ const headers = {
+ "Content-Type": "application/json"
+ };
+ if (tenantId) {
+ headers['X-Tenant-Id'] = tenantId;
+ // 同时在数据中也添加租户ID(如果后端需要)
+ if (!this.editMaterialForm.tenantId) {
+ this.editMaterialForm.tenantId = tenantId;
+ }
+ }
+
+ const res = await uni.request({
+ url: getApiUrl('/api/knowledgeBase/update'),
+ method: 'PUT',
+ data: this.editMaterialForm,
+ header: headers,
+ timeout: 15000
+ });
+
+ uni.hideLoading();
+
+ if (res.statusCode === 200 && res.data && (res.data.success || res.data.code === 200)) {
+ uni.showToast({
+ title: res.data?.message || "保存成功",
+ icon: "success"
+ });
+ // 关闭弹出框并刷新列表
+ this.closeEditMaterialPopup();
+ this.materialPage.current = 1;
+ this.fetchMaterialList({ force: true });
+ } else {
+ uni.showToast({
+ title: res.data?.message || "保存失败",
+ icon: "none"
+ });
+ }
+ } catch (error) {
+ uni.hideLoading();
+ console.error("保存素材失败:", error);
+ uni.showToast({
+ title: error?.message || "保存失败,请重试",
+ icon: "none"
+ });
+ }
+ },
+ handleDeleteMaterial(item) {
+ this.closeContextMenu();
+ uni.showModal({
+ title: '提示',
+ content: '确认删除该素材吗?',
+ success: async (res) => {
+ if (res.confirm) {
+ try {
+ uni.showLoading({
+ title: "删除中..."
+ });
+
+ // 获取租户ID
+ const tenantId = getTenantId();
+ const headers = {};
+ if (tenantId) {
+ headers['X-Tenant-Id'] = tenantId;
+ }
+
+ const deleteRes = await uni.request({
+ url: getApiUrl(`/api/knowledgeBase/delete/${item.id}`),
+ method: 'DELETE',
+ header: headers,
+ timeout: 15000
+ });
+
+ uni.hideLoading();
+
+ if (deleteRes.statusCode === 200 && deleteRes.data && (deleteRes.data.success || deleteRes.data.code === 200)) {
+ uni.showToast({
+ title: deleteRes.data?.message || "删除成功",
+ icon: "success"
+ });
+ // 刷新列表
+ this.materialPage.current = 1;
+ this.fetchMaterialList({ force: true });
+ } else {
+ uni.showToast({
+ title: deleteRes.data?.message || "删除失败",
+ icon: "none"
+ });
+ }
+ } catch (error) {
+ uni.hideLoading();
+ console.error("删除素材失败:", error);
+ uni.showToast({
+ title: error?.message || "删除失败,请重试",
+ icon: "none"
+ });
+ }
+ }
+ }
+ });
+ },
// 添加素材相关方法
showAddMaterial() {
this.showMaterialPopup = true;
this.materialForm = {
title: '',
- category: '',
- industry: '',
- files: []
+ category: '基础知识库', // 固定值,不可修改
+ industry: '汽车销售', // 默认值
+ file: null
};
},
closeMaterialPopup() {
this.showMaterialPopup = false;
},
chooseFile() {
+ // 限制只能上传一个文件
// #ifdef H5
// H5平台使用chooseFile
uni.chooseFile({
@@ -441,11 +744,12 @@
const tempFiles = res.tempFiles || [];
if (tempFiles.length > 0) {
const file = tempFiles[0];
- this.materialForm.files.push({
+ // 替换文件,而不是添加
+ this.materialForm.file = {
name: file.name || '文件',
path: file.path || file.url,
size: file.size
- });
+ };
}
},
fail: (err) => {
@@ -465,11 +769,12 @@
const tempFiles = res.tempFiles || [];
if (tempFiles.length > 0) {
const file = tempFiles[0];
- this.materialForm.files.push({
+ // 替换文件,而不是添加
+ this.materialForm.file = {
name: file.name || '图片',
path: file.path,
size: file.size
- });
+ };
}
},
fail: (err) => {
@@ -482,8 +787,9 @@
});
// #endif
},
- removeFile(index) {
- this.materialForm.files.splice(index, 1);
+ removeFile() {
+ // 清空文件
+ this.materialForm.file = null;
},
async submitMaterial() {
// 表单验证
@@ -500,67 +806,88 @@
title: "提交中..."
});
- // 先上传文件(如果有)
- let fileUrls = [];
- if (this.materialForm.files && this.materialForm.files.length > 0) {
- for (let file of this.materialForm.files) {
- try {
- // 上传文件到后端
- const uploadRes = await uni.uploadFile({
- url: getApiUrl('/api/knowledgeBase/upload'),
- filePath: file.path,
- name: 'file',
- formData: {
- 'name': file.name || 'file'
- }
- });
-
- if (uploadRes.statusCode === 200) {
- let result;
- try {
- result = typeof uploadRes.data === 'string' ? JSON.parse(uploadRes.data) : uploadRes.data;
- } catch (e) {
- result = uploadRes.data;
- }
-
- if (result && (result.success || result.code === 200)) {
- const url = result.data?.url || result.data || result.url;
- if (url) {
- fileUrls.push(url);
- }
- }
- }
- } catch (uploadError) {
- console.error('文件上传失败:', uploadError);
- // 继续处理其他文件,不中断整个流程
- }
+ // 获取租户ID
+ const tenantId = getTenantId();
+
+ let res;
+
+ // 如果有文件,使用 uni.uploadFile 同时上传文件和其他表单数据
+ if (this.materialForm.file) {
+ // 使用 uni.uploadFile 将文件和其他字段一起提交
+ const formData = {
+ // 其他表单字段
+ 'title': this.materialForm.title.trim(),
+ 'category': this.materialForm.category?.trim() || '',
+ 'industry': this.materialForm.industry?.trim() || '',
+ 'content': '-',
+ 'fileName': this.materialForm.file.name || 'file' // 文件名
+ };
+
+ // 添加租户ID到formData
+ if (tenantId) {
+ formData['tenantId'] = tenantId;
}
- }
-
- // 构建提交数据
- const payload = {
- title: this.materialForm.title.trim(),
- category: this.materialForm.category?.trim() || '',
- industry: this.materialForm.industry?.trim() || '',
- fileUrls: fileUrls.length > 0 ? fileUrls : undefined
- };
-
- // 提交到后端
- const res = await uni.request({
- url: getApiUrl('/api/knowledgeBase/add'),
- method: 'POST',
- data: payload,
- header: {
+
+ res = await uni.uploadFile({
+ url: getApiUrl('/api/knowledgeBase/add'),
+ filePath: this.materialForm.file.path,
+ name: 'file', // 文件字段名
+ formData: formData,
+ header: tenantId ? {
+ 'X-Tenant-Id': tenantId
+ } : {},
+ timeout: 15000
+ });
+ } else {
+ // 如果没有文件,使用 uni.request 提交表单数据
+ const payload = {
+ title: this.materialForm.title.trim(),
+ category: this.materialForm.category?.trim() || '',
+ industry: this.materialForm.industry?.trim() || '',
+ content: "-"
+ };
+
+ // 添加租户ID到payload
+ if (tenantId) {
+ payload.tenantId = tenantId;
+ }
+
+ const headers = {
"Content-Type": "application/json"
- },
- timeout: 15000
- });
+ };
+
+ // 添加租户ID到header
+ if (tenantId) {
+ headers['X-Tenant-Id'] = tenantId;
+ }
+
+ res = await uni.request({
+ url: getApiUrl('/api/knowledgeBase/add'),
+ method: 'POST',
+ data: payload,
+ header: headers,
+ timeout: 15000
+ });
+ }
uni.hideLoading();
- if (res.statusCode === 200 && res.data && (res.data.success || res.data.code === 200)) {
+ // 处理响应(uni.uploadFile 返回的 data 可能是字符串,需要解析)
+ let result;
+ if (this.materialForm.file) {
+ // uni.uploadFile 返回的数据需要解析
+ try {
+ result = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
+ } catch (e) {
+ result = res.data;
+ }
+ } else {
+ result = res.data;
+ }
+
+ if (res.statusCode === 200 && result && (result.success || result.code === 200)) {
uni.showToast({
- title: res.data?.message || "提交成功",
+ title: result?.message || "提交成功",
icon: "success"
});
// 关闭弹出框并刷新列表
@@ -569,7 +896,7 @@
this.fetchMaterialList({ force: true });
} else {
uni.showToast({
- title: res.data?.message || "提交失败",
+ title: result?.message || "提交失败",
icon: "none"
});
}
@@ -577,7 +904,7 @@
uni.hideLoading();
console.error("提交素材失败:", error);
uni.showToast({
- title: "提交失败,请重试",
+ title: error?.message || "提交失败,请重试",
icon: "none"
});
}
@@ -713,7 +1040,7 @@
font-size: 26rpx;
color: #666;
margin-right: 16rpx;
- width: 100%;
+ white-space: nowrap;
}
.toolbar-input {
@@ -771,6 +1098,53 @@
box-sizing: border-box;
padding: 0;
margin: 0;
+ position: relative;
+ }
+
+ .card-menu-trigger {
+ width: 48rpx;
+ height: 48rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ flex-shrink: 0;
+ }
+
+ .context-menu {
+ position: fixed;
+ background-color: #FFFFFF;
+ border-radius: 8rpx;
+ box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
+ z-index: 1001;
+ min-width: 160rpx;
+ padding: 8rpx 0;
+ max-width: 200rpx;
+ }
+
+ .context-menu-item {
+ padding: 24rpx 32rpx;
+ font-size: 28rpx;
+ color: #333;
+ text-align: left;
+ }
+
+ .context-menu-item:active {
+ background-color: #f5f5f5;
+ }
+
+ .context-menu-item--danger {
+ color: #FF3B30;
+ }
+
+ .context-menu-mask {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 1000;
+ background-color: transparent;
}
.staff-info {
@@ -982,6 +1356,26 @@
box-sizing: border-box;
}
+ /* 只读输入框样式 */
+ .form-item__input[disabled],
+ .form-item__input[readonly] {
+ background-color: #f3f4f6;
+ color: #6b7280;
+ cursor: not-allowed;
+ }
+
+ .form-item__textarea {
+ flex: 1;
+ min-width: 0;
+ min-height: 200rpx;
+ background-color: #f9fafb;
+ border-radius: 12rpx;
+ padding: 24rpx;
+ font-size: 32rpx;
+ color: #333;
+ box-sizing: border-box;
+ }
+
.file-upload-area {
width: 100%;
display: flex;
@@ -989,10 +1383,6 @@
gap: 12rpx;
}
- .file-list {
- margin-bottom: 0;
- }
-
.file-item {
display: flex;
align-items: center;