陪练页面开发
This commit is contained in:
@@ -70,15 +70,237 @@
|
||||
|
||||
<!-- 陪练内容 -->
|
||||
<scroll-view
|
||||
class="tab-content"
|
||||
class="tab-content practice-content"
|
||||
scroll-y
|
||||
v-if="activeTab === 'practice'">
|
||||
<view class="champion-card">
|
||||
<text class="champion-title">陪练</text>
|
||||
<text class="champion-desc">这里是陪练相关的内容展示区域</text>
|
||||
v-if="activeTab === 'practice'"
|
||||
@scrolltolower="onPracticeReachBottom">
|
||||
<view class="service-status-toolbar">
|
||||
<text class="toolbar-total">共{{ practiceTotal }}条</text>
|
||||
<input
|
||||
class="toolbar-input"
|
||||
v-model="practiceQuery.title"
|
||||
placeholder="知识标题"
|
||||
placeholder-style="color: #b0b0b0"
|
||||
confirm-type="search"
|
||||
@confirm="onPracticeSearch"
|
||||
/>
|
||||
<input
|
||||
class="toolbar-input"
|
||||
v-model="practiceQuery.industry"
|
||||
placeholder="应用行业"
|
||||
placeholder-style="color: #b0b0b0"
|
||||
confirm-type="search"
|
||||
@confirm="onPracticeSearch"
|
||||
/>
|
||||
<view class="toolbar-actions">
|
||||
<view class="toolbar-btn toolbar-btn--refresh" @click="onPracticeRefresh">
|
||||
<uni-icons type="refresh" size="18" color="#2A68FF"></uni-icons>
|
||||
<text>刷新</text>
|
||||
</view>
|
||||
<view class="toolbar-btn toolbar-btn--add" @click="showAddPractice">
|
||||
<uni-icons type="plus" size="18" color="#2A68FF"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="service-card practice-card-item"
|
||||
v-for="(item, index) in practiceList"
|
||||
:key="item.id || index">
|
||||
<view class="card-header">
|
||||
<view class="staff-info">
|
||||
<view class="staff-avatar">
|
||||
<text class="avatar-text">{{ (item.title || '知').charAt(0) }}</text>
|
||||
</view>
|
||||
<text class="staff-name">{{ item.title || '未命名知识' }}</text>
|
||||
</view>
|
||||
<view class="card-menu-trigger" @tap.stop="showPracticeContextMenu(item, index, $event)">
|
||||
<uni-icons type="more-filled" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="customer-info">
|
||||
<text class="customer-name" v-if="item.industry">所属行业: {{ item.industry }}</text>
|
||||
</view>
|
||||
|
||||
<view class="customer-tags">
|
||||
<view class="tag-item tag-blue" v-if="item.content">
|
||||
<text>详情: {{ getContentPreview(item.content) }}</text>
|
||||
</view>
|
||||
<view class="tag-item tag-orange" v-if="item.remark">
|
||||
<text>备注: {{ item.remark }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 上下文菜单 -->
|
||||
<view
|
||||
class="context-menu"
|
||||
v-if="practiceContextMenuVisible && practiceContextMenuIndex === index"
|
||||
:style="{ top: practiceContextMenuTop + 'px', left: practiceContextMenuLeft + 'px' }"
|
||||
@tap.stop>
|
||||
<view class="context-menu-item" @tap.stop="handleEditPractice(item)">
|
||||
<text>编辑</text>
|
||||
</view>
|
||||
<view class="context-menu-item context-menu-item--danger" @tap.stop="handleDeletePractice(item)">
|
||||
<text>删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="service-status-empty" v-if="!practiceLoading && !practiceList.length">
|
||||
<text>暂无陪练</text>
|
||||
</view>
|
||||
<view class="service-status-loading-more" v-if="practiceLoading && practiceList.length">
|
||||
<text>正在加载更多...</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 添加陪练弹出框 -->
|
||||
<view class="material-popup-mask" v-if="showPracticePopup" @click="closePracticePopup">
|
||||
</view>
|
||||
<view class="material-popup" v-if="showPracticePopup" @click.stop>
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">添加陪练</text>
|
||||
<view class="popup-close" @click="closePracticePopup">
|
||||
<uni-icons type="close" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="popup-content" scroll-y>
|
||||
<view class="form-card">
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">知识标题</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="practiceForm.title"
|
||||
placeholder="请输入知识标题"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="512"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">知识分类</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="practiceForm.category"
|
||||
placeholder="请输入知识分类"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="100"
|
||||
:disabled="true"
|
||||
readonly
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">应用行业</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="practiceForm.industry"
|
||||
placeholder="请输入应用行业"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="100"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">文件上传</text>
|
||||
<view class="file-upload-area">
|
||||
<view class="file-item" v-if="practiceForm.file">
|
||||
<text class="file-name">{{ practiceForm.file.name || '文件' }}</text>
|
||||
<view class="file-delete" @click="removePracticeFile">
|
||||
<uni-icons type="close" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="file-upload-btn" v-if="!practiceForm.file" @click="choosePracticeFile">
|
||||
<uni-icons type="plus" size="24" color="#2A68FF"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-actions">
|
||||
<view class="popup-btn popup-btn--cancel" @click="closePracticePopup">
|
||||
<uni-icons class="popup-btn__icon" type="close" size="20" color="#2A68FF"></uni-icons>
|
||||
<text class="popup-btn__text">取消</text>
|
||||
</view>
|
||||
<view class="popup-btn popup-btn--submit" @click="submitPractice">
|
||||
<uni-icons class="popup-btn__icon" type="checkmarkempty" size="20" color="#2A68FF"></uni-icons>
|
||||
<text class="popup-btn__text">提交</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 编辑陪练弹出框 -->
|
||||
<view class="material-popup-mask" v-if="showEditPracticePopup" @click="closeEditPracticePopup">
|
||||
</view>
|
||||
<view class="material-popup" v-if="showEditPracticePopup" @click.stop>
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">编辑陪练</text>
|
||||
<view class="popup-close" @click="closeEditPracticePopup">
|
||||
<uni-icons type="close" size="20" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<scroll-view class="popup-content" scroll-y>
|
||||
<view class="form-card">
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">知识标题</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="editPracticeForm.title"
|
||||
placeholder="请输入知识标题"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="512"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">知识分类</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="editPracticeForm.category"
|
||||
placeholder="请输入知识分类"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="100"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">应用行业</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="editPracticeForm.industry"
|
||||
placeholder="请输入应用行业"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="100"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">详情</text>
|
||||
<textarea
|
||||
class="form-item__textarea"
|
||||
v-model="editPracticeForm.content"
|
||||
placeholder="请输入详情内容"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="2000"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="form-item__label">备注</text>
|
||||
<input
|
||||
class="form-item__input"
|
||||
v-model="editPracticeForm.remark"
|
||||
placeholder="请输入备注"
|
||||
placeholder-style="color: #9ca3af"
|
||||
maxlength="500"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-actions">
|
||||
<view class="popup-btn popup-btn--cancel" @click="closeEditPracticePopup">
|
||||
<uni-icons class="popup-btn__icon" type="close" size="20" color="#2A68FF"></uni-icons>
|
||||
<text class="popup-btn__text">取消</text>
|
||||
</view>
|
||||
<view class="popup-btn popup-btn--submit" @click="submitEditPractice">
|
||||
<uni-icons class="popup-btn__icon" type="checkmarkempty" size="20" color="#2A68FF"></uni-icons>
|
||||
<text class="popup-btn__text">保存</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 实战内容 -->
|
||||
<scroll-view
|
||||
class="tab-content"
|
||||
@@ -380,6 +602,20 @@
|
||||
creator: '',
|
||||
status: ''
|
||||
},
|
||||
// 陪练相关数据
|
||||
practiceList: [],
|
||||
practiceLoading: false,
|
||||
practiceTotal: 0,
|
||||
practicePage: {
|
||||
current: 1,
|
||||
size: 10
|
||||
},
|
||||
practiceQuery: {
|
||||
title: '',
|
||||
industry: '',
|
||||
creator: '',
|
||||
status: ''
|
||||
},
|
||||
// 添加素材弹出框
|
||||
showMaterialPopup: false,
|
||||
materialForm: {
|
||||
@@ -402,7 +638,30 @@
|
||||
contextMenuVisible: false,
|
||||
contextMenuIndex: -1,
|
||||
contextMenuTop: 0,
|
||||
contextMenuLeft: 0
|
||||
contextMenuLeft: 0,
|
||||
// 添加陪练弹出框
|
||||
showPracticePopup: false,
|
||||
practiceForm: {
|
||||
title: '',
|
||||
category: '',
|
||||
industry: '',
|
||||
files: []
|
||||
},
|
||||
// 编辑陪练弹出框
|
||||
showEditPracticePopup: false,
|
||||
editPracticeForm: {
|
||||
id: '',
|
||||
title: '',
|
||||
category: '',
|
||||
industry: '',
|
||||
content: '',
|
||||
remark: ''
|
||||
},
|
||||
// 陪练上下文菜单
|
||||
practiceContextMenuVisible: false,
|
||||
practiceContextMenuIndex: -1,
|
||||
practiceContextMenuTop: 0,
|
||||
practiceContextMenuLeft: 0
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
@@ -416,6 +675,9 @@
|
||||
if (tab === 'material') {
|
||||
// 当进入素材页面时,请求接口填充数据
|
||||
this.fetchMaterialList();
|
||||
} else if (tab === 'practice') {
|
||||
// 当进入陪练页面时,请求接口填充数据
|
||||
this.fetchPracticeList();
|
||||
}
|
||||
},
|
||||
// 素材相关方法
|
||||
@@ -908,6 +1170,473 @@
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
},
|
||||
// 陪练相关方法
|
||||
onPracticeSearch() {
|
||||
if (this.activeTab !== 'practice') {
|
||||
this.activeTab = 'practice';
|
||||
}
|
||||
this.practicePage.current = 1;
|
||||
this.fetchPracticeList({ force: true });
|
||||
},
|
||||
onPracticeRefresh() {
|
||||
this.practicePage.current = 1;
|
||||
this.fetchPracticeList({ force: true });
|
||||
},
|
||||
onPracticeReachBottom() {
|
||||
// 已在加载中或全部加载完成则不再触发
|
||||
if (this.practiceLoading) return;
|
||||
if (this.practiceList.length >= this.practiceTotal) return;
|
||||
this.practicePage.current += 1;
|
||||
this.fetchPracticeList();
|
||||
},
|
||||
async fetchPracticeList({ force = false } = {}) {
|
||||
if (this.practiceLoading && !force) {
|
||||
return;
|
||||
}
|
||||
this.practiceLoading = true;
|
||||
try {
|
||||
const queryParams = {
|
||||
current: this.practicePage.current,
|
||||
size: this.practicePage.size,
|
||||
category: 'AI陪练虚拟人' // 默认添加知识分类参数
|
||||
};
|
||||
const trimmedTitle = this.practiceQuery?.title?.trim();
|
||||
const trimmedIndustry = this.practiceQuery?.industry?.trim();
|
||||
const trimmedCreator = this.practiceQuery?.creator?.trim();
|
||||
const trimmedStatus = this.practiceQuery?.status?.trim();
|
||||
|
||||
if (trimmedTitle) {
|
||||
queryParams.title = trimmedTitle;
|
||||
}
|
||||
if (trimmedIndustry) {
|
||||
queryParams.industry = trimmedIndustry;
|
||||
}
|
||||
if (trimmedCreator) {
|
||||
queryParams.creator = trimmedCreator;
|
||||
}
|
||||
if (trimmedStatus) {
|
||||
queryParams.status = trimmedStatus;
|
||||
}
|
||||
|
||||
const queryString = Object.keys(queryParams)
|
||||
.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
|
||||
});
|
||||
|
||||
if (res.statusCode === 200 && res.data && res.data.success) {
|
||||
const records = Array.isArray(res.data.data) ? res.data.data : [];
|
||||
// 第一页或强制刷新时重置列表,否则追加
|
||||
if (this.practicePage.current === 1 || force) {
|
||||
this.practiceList = records;
|
||||
} else {
|
||||
this.practiceList = this.practiceList.concat(records);
|
||||
}
|
||||
this.practiceTotal = Number(res.data.total) || 0;
|
||||
} else {
|
||||
this.practiceList = [];
|
||||
this.practiceTotal = 0;
|
||||
uni.showToast({
|
||||
title: res.data?.message || '获取陪练列表失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取陪练列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取陪练列表失败,请稍后重试',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
this.practiceLoading = false;
|
||||
}
|
||||
},
|
||||
showPracticeContextMenu(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.practiceContextMenuTop = top;
|
||||
this.practiceContextMenuLeft = left;
|
||||
// 显示菜单
|
||||
this.practiceContextMenuIndex = index;
|
||||
this.practiceContextMenuVisible = true;
|
||||
},
|
||||
closePracticeContextMenu() {
|
||||
this.practiceContextMenuVisible = false;
|
||||
this.practiceContextMenuIndex = -1;
|
||||
},
|
||||
handleEditPractice(item) {
|
||||
this.closePracticeContextMenu();
|
||||
// 填充编辑表单
|
||||
this.editPracticeForm = {
|
||||
id: item.id,
|
||||
title: item.title || '',
|
||||
category: item.category || '',
|
||||
industry: item.industry || '',
|
||||
content: item.content || '',
|
||||
remark: item.remark || ''
|
||||
};
|
||||
this.showEditPracticePopup = true;
|
||||
},
|
||||
closeEditPracticePopup() {
|
||||
this.showEditPracticePopup = false;
|
||||
this.editPracticeForm = {
|
||||
id: '',
|
||||
title: '',
|
||||
category: '',
|
||||
industry: '',
|
||||
content: '',
|
||||
remark: ''
|
||||
};
|
||||
},
|
||||
async submitEditPractice() {
|
||||
// 表单验证
|
||||
if (!this.editPracticeForm.title || !this.editPracticeForm.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.editPracticeForm.tenantId) {
|
||||
this.editPracticeForm.tenantId = tenantId;
|
||||
}
|
||||
}
|
||||
|
||||
const res = await uni.request({
|
||||
url: getApiUrl('/api/knowledgeBase/update'),
|
||||
method: 'PUT',
|
||||
data: this.editPracticeForm,
|
||||
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.closeEditPracticePopup();
|
||||
this.practicePage.current = 1;
|
||||
this.fetchPracticeList({ 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"
|
||||
});
|
||||
}
|
||||
},
|
||||
handleDeletePractice(item) {
|
||||
this.closePracticeContextMenu();
|
||||
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.practicePage.current = 1;
|
||||
this.fetchPracticeList({ 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"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 添加陪练相关方法
|
||||
showAddPractice() {
|
||||
this.showPracticePopup = true;
|
||||
this.practiceForm = {
|
||||
title: '',
|
||||
category: 'AI陪练虚拟人', // 固定值,不可修改
|
||||
industry: '汽车销售', // 默认值
|
||||
file: null
|
||||
};
|
||||
},
|
||||
closePracticePopup() {
|
||||
this.showPracticePopup = false;
|
||||
},
|
||||
choosePracticeFile() {
|
||||
// 限制只能上传一个文件
|
||||
// #ifdef H5
|
||||
// H5平台使用chooseFile
|
||||
uni.chooseFile({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
const tempFiles = res.tempFiles || [];
|
||||
if (tempFiles.length > 0) {
|
||||
const file = tempFiles[0];
|
||||
// 替换文件,而不是添加
|
||||
this.practiceForm.file = {
|
||||
name: file.name || '文件',
|
||||
path: file.path || file.url,
|
||||
size: file.size
|
||||
};
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择文件失败:', err);
|
||||
uni.showToast({
|
||||
title: '选择文件失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
// 非H5平台使用chooseImage(可以选择图片文件)
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
const tempFiles = res.tempFiles || [];
|
||||
if (tempFiles.length > 0) {
|
||||
const file = tempFiles[0];
|
||||
// 替换文件,而不是添加
|
||||
this.practiceForm.file = {
|
||||
name: file.name || '图片',
|
||||
path: file.path,
|
||||
size: file.size
|
||||
};
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择文件失败:', err);
|
||||
uni.showToast({
|
||||
title: '选择文件失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
removePracticeFile() {
|
||||
// 清空文件
|
||||
this.practiceForm.file = null;
|
||||
},
|
||||
async submitPractice() {
|
||||
// 表单验证
|
||||
if (!this.practiceForm.title || !this.practiceForm.title.trim()) {
|
||||
uni.showToast({
|
||||
title: "请输入知识标题",
|
||||
icon: "none"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
uni.showLoading({
|
||||
title: "提交中..."
|
||||
});
|
||||
|
||||
// 获取租户ID
|
||||
const tenantId = getTenantId();
|
||||
|
||||
let res;
|
||||
|
||||
// 如果有文件,使用 uni.uploadFile 同时上传文件和其他表单数据
|
||||
if (this.practiceForm.file) {
|
||||
// 使用 uni.uploadFile 将文件和其他字段一起提交
|
||||
const formData = {
|
||||
// 其他表单字段
|
||||
'title': this.practiceForm.title.trim(),
|
||||
'category': this.practiceForm.category?.trim() || '',
|
||||
'industry': this.practiceForm.industry?.trim() || '',
|
||||
'content': '-',
|
||||
'fileName': this.practiceForm.file.name || 'file' // 文件名
|
||||
};
|
||||
|
||||
// 添加租户ID到formData
|
||||
if (tenantId) {
|
||||
formData['tenantId'] = tenantId;
|
||||
}
|
||||
|
||||
res = await uni.uploadFile({
|
||||
url: getApiUrl('/api/knowledgeBase/add'),
|
||||
filePath: this.practiceForm.file.path,
|
||||
name: 'file', // 文件字段名
|
||||
formData: formData,
|
||||
header: tenantId ? {
|
||||
'X-Tenant-Id': tenantId
|
||||
} : {},
|
||||
timeout: 15000
|
||||
});
|
||||
} else {
|
||||
// 如果没有文件,使用 uni.request 提交表单数据
|
||||
const payload = {
|
||||
title: this.practiceForm.title.trim(),
|
||||
category: this.practiceForm.category?.trim() || '',
|
||||
industry: this.practiceForm.industry?.trim() || '',
|
||||
content: "-"
|
||||
};
|
||||
|
||||
// 添加租户ID到payload
|
||||
if (tenantId) {
|
||||
payload.tenantId = tenantId;
|
||||
}
|
||||
|
||||
const headers = {
|
||||
"Content-Type": "application/json"
|
||||
};
|
||||
|
||||
// 添加租户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();
|
||||
|
||||
// 处理响应(uni.uploadFile 返回的 data 可能是字符串,需要解析)
|
||||
let result;
|
||||
if (this.practiceForm.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: result?.message || "提交成功",
|
||||
icon: "success"
|
||||
});
|
||||
// 关闭弹出框并刷新列表
|
||||
this.closePracticePopup();
|
||||
this.practicePage.current = 1;
|
||||
this.fetchPracticeList({ force: true });
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result?.message || "提交失败",
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
uni.hideLoading();
|
||||
console.error("提交陪练失败:", error);
|
||||
uni.showToast({
|
||||
title: error?.message || "提交失败,请重试",
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user