2025-08-02 11:15:22 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<view class="add-resource-page">
|
|
|
|
|
|
<!-- 表单内容 -->
|
|
|
|
|
|
<scroll-view scroll-y class="form-scroll-view">
|
|
|
|
|
|
<view class="form-container">
|
|
|
|
|
|
<!-- 资源目录 -->
|
|
|
|
|
|
<view class="info-card">
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">资源目录 <text class="required">*</text></text>
|
2025-08-09 11:36:56 +08:00
|
|
|
|
<view class="picker-row" @click="showResourceTypeTree">
|
|
|
|
|
|
<text :class="{ placeholder: !formData.resourType }">
|
|
|
|
|
|
{{ getResourceTypeText() || '请选择资源目录' }}
|
|
|
|
|
|
</text>
|
|
|
|
|
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
|
|
|
|
|
</view>
|
2025-08-02 11:15:22 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 课题名称 -->
|
|
|
|
|
|
<view class="info-card">
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">课题名称 <text class="required">*</text></text>
|
|
|
|
|
|
<uni-easyinput
|
|
|
|
|
|
v-model="formData.resourName"
|
|
|
|
|
|
placeholder="请输入课题名称"
|
|
|
|
|
|
:inputBorder="false"
|
|
|
|
|
|
class="content-input"
|
|
|
|
|
|
></uni-easyinput>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 课时 -->
|
|
|
|
|
|
<view class="info-card">
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">课时 <text class="required">*</text></text>
|
|
|
|
|
|
<uni-easyinput
|
|
|
|
|
|
v-model="formData.hour"
|
|
|
|
|
|
placeholder="请输入课时"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
:inputBorder="false"
|
|
|
|
|
|
class="content-input"
|
|
|
|
|
|
></uni-easyinput>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 资源类别 -->
|
|
|
|
|
|
<view class="info-card">
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">资源类别 <text class="required">*</text></text>
|
|
|
|
|
|
<picker
|
|
|
|
|
|
mode="selector"
|
|
|
|
|
|
:range="categoryOptions"
|
|
|
|
|
|
range-key="label"
|
|
|
|
|
|
@change="handleCategoryChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<view class="picker-row">
|
|
|
|
|
|
<text :class="{ placeholder: !formData.category }">
|
|
|
|
|
|
{{ getCategoryText() || '请选择资源类别' }}
|
|
|
|
|
|
</text>
|
|
|
|
|
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</picker>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 资源描述 -->
|
|
|
|
|
|
<view class="info-card">
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">资源描述</text>
|
|
|
|
|
|
<uni-easyinput
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
autoHeight
|
|
|
|
|
|
v-model="formData.content"
|
|
|
|
|
|
placeholder="请输入资源描述"
|
|
|
|
|
|
:inputBorder="false"
|
|
|
|
|
|
class="content-input"
|
|
|
|
|
|
></uni-easyinput>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 上传资源 -->
|
|
|
|
|
|
<view class="info-card">
|
|
|
|
|
|
<view class="form-item">
|
|
|
|
|
|
<text class="form-label">上传资源 <text class="required">*</text></text>
|
|
|
|
|
|
<view class="attachment-list">
|
|
|
|
|
|
<view
|
|
|
|
|
|
v-for="(att, index) in formData.attachments"
|
|
|
|
|
|
:key="index"
|
|
|
|
|
|
class="attachment-item"
|
|
|
|
|
|
>
|
|
|
|
|
|
<uni-icons
|
|
|
|
|
|
:type="getAttachmentIcon(att.type)"
|
|
|
|
|
|
size="20"
|
|
|
|
|
|
color="#666"
|
|
|
|
|
|
class="attachment-icon"
|
|
|
|
|
|
></uni-icons>
|
|
|
|
|
|
<text class="attachment-name" @click="previewAttachment(att)">{{
|
|
|
|
|
|
att.name
|
|
|
|
|
|
}}</text>
|
|
|
|
|
|
<uni-icons
|
|
|
|
|
|
type="closeempty"
|
|
|
|
|
|
size="18"
|
|
|
|
|
|
color="#999"
|
|
|
|
|
|
class="remove-icon"
|
|
|
|
|
|
@click="removeAttachment(index)"
|
|
|
|
|
|
></uni-icons>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
<view class="add-attachment-placeholder" @click="addAttachment">
|
|
|
|
|
|
<view class="add-icon"
|
|
|
|
|
|
><uni-icons type="plusempty" size="20" color="#ccc"></uni-icons
|
|
|
|
|
|
></view>
|
|
|
|
|
|
<text class="placeholder-text">添加图文/视频/文件</text>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</view>
|
|
|
|
|
|
</scroll-view>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 底部提交按钮 -->
|
|
|
|
|
|
<view class="bottom-actions">
|
|
|
|
|
|
<button class="action-btn confirm-btn" @click="handleSubmitForm" :disabled="isSubmitting">
|
|
|
|
|
|
{{ isSubmitting ? '提交中...' : '提交' }}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</view>
|
2025-08-09 11:36:56 +08:00
|
|
|
|
|
|
|
|
|
|
<!-- 资源目录选择树 -->
|
|
|
|
|
|
<BasicTree
|
|
|
|
|
|
ref="treeRef"
|
|
|
|
|
|
:range="treeData"
|
|
|
|
|
|
idKey="key"
|
|
|
|
|
|
rangeKey="title"
|
|
|
|
|
|
title="选择资源目录"
|
|
|
|
|
|
:multiple="false"
|
|
|
|
|
|
:selectParent="false"
|
|
|
|
|
|
@confirm="onTreeConfirm"
|
|
|
|
|
|
@cancel="onTreeCancel"
|
|
|
|
|
|
/>
|
2025-08-02 11:15:22 +08:00
|
|
|
|
</view>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2025-10-29 10:30:04 +08:00
|
|
|
|
import { zymxSaveApi } from "@/api/base/server";
|
|
|
|
|
|
import { zymlFindTreeApi } from "@/api/base/server";
|
2025-08-02 11:15:22 +08:00
|
|
|
|
import { attachmentUpload } from "@/api/system/upload";
|
|
|
|
|
|
import { imagUrl } from "@/utils";
|
|
|
|
|
|
import { useDicStore } from "@/store/modules/dic";
|
2025-08-09 11:36:56 +08:00
|
|
|
|
import BasicTree from "@/components/BasicTree/Tree.vue";
|
2025-08-02 11:15:22 +08:00
|
|
|
|
|
|
|
|
|
|
const { findByPid } = useDicStore();
|
|
|
|
|
|
|
|
|
|
|
|
interface Attachment {
|
|
|
|
|
|
name: string;
|
|
|
|
|
|
type: string;
|
|
|
|
|
|
url: string;
|
|
|
|
|
|
size?: number;
|
|
|
|
|
|
path?: string;
|
|
|
|
|
|
id?: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 表单数据
|
|
|
|
|
|
const formData = reactive({
|
|
|
|
|
|
resourName: '',
|
|
|
|
|
|
resourType: '',
|
|
|
|
|
|
category: '',
|
|
|
|
|
|
content: '',
|
|
|
|
|
|
fileId: '',
|
|
|
|
|
|
filePath: '',
|
|
|
|
|
|
resSuf: '',
|
|
|
|
|
|
hour: '',
|
|
|
|
|
|
id: '',
|
|
|
|
|
|
fileName: '',
|
|
|
|
|
|
attachments: [] as Attachment[] // 新增附件列表
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 树形数据
|
|
|
|
|
|
const treeData = ref([]);
|
|
|
|
|
|
|
2025-08-09 11:36:56 +08:00
|
|
|
|
// 树组件引用
|
|
|
|
|
|
const treeRef = ref();
|
|
|
|
|
|
|
2025-08-02 11:15:22 +08:00
|
|
|
|
// 提交状态
|
|
|
|
|
|
const isSubmitting = ref(false);
|
|
|
|
|
|
|
|
|
|
|
|
// 资源类别选项 - 从字典表获取
|
|
|
|
|
|
const categoryOptions = ref([]);
|
|
|
|
|
|
|
|
|
|
|
|
// 加载资源类别数据
|
|
|
|
|
|
const loadCategoryOptions = async () => {
|
|
|
|
|
|
try {
|
2025-08-09 11:36:56 +08:00
|
|
|
|
// 使用正确的字典ID
|
2025-08-02 11:15:22 +08:00
|
|
|
|
const result = await findByPid({ pid: 1391443399 });
|
2025-08-09 11:36:56 +08:00
|
|
|
|
|
|
|
|
|
|
// 检查返回的数据结构
|
|
|
|
|
|
if (result && result.resultCode === 1 && result.result && Array.isArray(result.result) && result.result.length > 0) {
|
|
|
|
|
|
categoryOptions.value = result.result.map(item => ({
|
2025-08-02 11:15:22 +08:00
|
|
|
|
value: item.dictionaryCode,
|
|
|
|
|
|
label: item.dictionaryValue
|
|
|
|
|
|
}));
|
2025-08-09 11:36:56 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 如果没有数据,使用默认选项
|
|
|
|
|
|
categoryOptions.value = [
|
|
|
|
|
|
{ value: '1', label: '课件' },
|
|
|
|
|
|
{ value: '2', label: '教案' },
|
|
|
|
|
|
{ value: '3', label: '学案' },
|
|
|
|
|
|
{ value: '4', label: '作业' },
|
|
|
|
|
|
{ value: '5', label: '试卷' },
|
|
|
|
|
|
{ value: '6', label: '教材' },
|
|
|
|
|
|
{ value: '7', label: '示范课' },
|
|
|
|
|
|
{ value: '8', label: '音视频合集' },
|
|
|
|
|
|
];
|
2025-08-02 11:15:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
// 如果加载失败,使用默认选项
|
|
|
|
|
|
categoryOptions.value = [
|
|
|
|
|
|
{ value: '1', label: '课件' },
|
|
|
|
|
|
{ value: '2', label: '教案' },
|
|
|
|
|
|
{ value: '3', label: '学案' },
|
|
|
|
|
|
{ value: '4', label: '作业' },
|
|
|
|
|
|
{ value: '5', label: '试卷' },
|
|
|
|
|
|
{ value: '6', label: '教材' },
|
|
|
|
|
|
{ value: '7', label: '示范课' },
|
|
|
|
|
|
{ value: '8', label: '音视频合集' },
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-09 11:36:56 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 显示资源目录选择树
|
|
|
|
|
|
const showResourceTypeTree = () => {
|
|
|
|
|
|
if (treeRef.value) {
|
|
|
|
|
|
treeRef.value._show();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 树形选择确认
|
|
|
|
|
|
const onTreeConfirm = (selectedItems: any[]) => {
|
|
|
|
|
|
if (selectedItems.length > 0) {
|
|
|
|
|
|
const selectedItem = selectedItems[0]; // 单选模式
|
|
|
|
|
|
formData.resourType = selectedItem.key;
|
|
|
|
|
|
}
|
2025-08-02 11:15:22 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-09 11:36:56 +08:00
|
|
|
|
// 树形选择取消
|
|
|
|
|
|
const onTreeCancel = () => {
|
|
|
|
|
|
// 取消选择资源目录
|
2025-08-02 11:15:22 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 资源类别选择
|
|
|
|
|
|
const handleCategoryChange = (e: any) => {
|
|
|
|
|
|
const index = e.detail.value;
|
|
|
|
|
|
const selectedItem = categoryOptions.value[index];
|
|
|
|
|
|
formData.category = selectedItem.value;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 添加附件
|
|
|
|
|
|
const addAttachment = () => {
|
|
|
|
|
|
uni.chooseFile({
|
|
|
|
|
|
count: 5,
|
|
|
|
|
|
type: 'all',
|
|
|
|
|
|
success: async (res) => {
|
|
|
|
|
|
const tempFiles = res.tempFiles;
|
|
|
|
|
|
if (Array.isArray(tempFiles) && tempFiles.length > 0) {
|
|
|
|
|
|
uni.showLoading({ title: '上传中...' });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
for (const file of tempFiles) {
|
|
|
|
|
|
const fileInfo = file as any;
|
|
|
|
|
|
let fileType = 'file';
|
|
|
|
|
|
const fileName = fileInfo.name || '';
|
|
|
|
|
|
const fileExtension = fileName.split('.').pop()?.toLowerCase();
|
|
|
|
|
|
|
|
|
|
|
|
// 根据文件扩展名判断类型
|
|
|
|
|
|
if (['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'].includes(fileExtension || '')) {
|
|
|
|
|
|
fileType = 'image';
|
|
|
|
|
|
} else if (['mp4', 'mov', 'avi', 'wmv', 'flv'].includes(fileExtension || '')) {
|
|
|
|
|
|
fileType = 'video';
|
|
|
|
|
|
} else if (['mp3', 'wav', 'aac', 'ogg'].includes(fileExtension || '')) {
|
|
|
|
|
|
fileType = 'audio';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据MIME类型判断
|
|
|
|
|
|
if (fileInfo.type && typeof fileInfo.type === 'string' &&
|
|
|
|
|
|
(fileInfo.type.startsWith('image/') || fileInfo.type.startsWith('video/') || fileInfo.type.startsWith('audio/'))) {
|
|
|
|
|
|
fileType = fileInfo.type.split('/')[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 先添加到附件列表
|
|
|
|
|
|
formData.attachments.push({
|
|
|
|
|
|
name: fileName,
|
|
|
|
|
|
type: fileType,
|
|
|
|
|
|
url: '',
|
|
|
|
|
|
size: fileInfo.size,
|
|
|
|
|
|
path: fileInfo.path,
|
|
|
|
|
|
id: Date.now()
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 上传文件
|
|
|
|
|
|
await uploadFile(fileInfo);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({ title: '附件上传完成', icon: 'success' });
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('附件上传失败:', error);
|
|
|
|
|
|
uni.showToast({ title: '附件上传失败', icon: 'error' });
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
fail: (err) => {
|
|
|
|
|
|
console.error('选择附件失败:', err);
|
|
|
|
|
|
if (err.errMsg && !err.errMsg.includes('cancel')) {
|
|
|
|
|
|
uni.showToast({ title: '选择附件失败', icon: 'none' });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 移除附件
|
|
|
|
|
|
const removeAttachment = (index: number) => {
|
|
|
|
|
|
formData.attachments.splice(index, 1);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 预览附件
|
|
|
|
|
|
const previewAttachment = (attachment: Attachment) => {
|
|
|
|
|
|
// 如果是图片类型,可以预览
|
|
|
|
|
|
if (attachment.type === 'image') {
|
|
|
|
|
|
const fullUrl = imagUrl(attachment.url);
|
|
|
|
|
|
uni.previewImage({
|
|
|
|
|
|
urls: [fullUrl],
|
|
|
|
|
|
current: fullUrl,
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({
|
|
|
|
|
|
title: `预览 ${attachment.name} 功能待实现`,
|
|
|
|
|
|
icon: 'none',
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取附件图标
|
|
|
|
|
|
const getAttachmentIcon = (type: string): string => {
|
|
|
|
|
|
if (type === 'image') return 'image';
|
|
|
|
|
|
if (type === 'video') return 'videocam';
|
|
|
|
|
|
if (type === 'audio') return 'mic';
|
|
|
|
|
|
return 'paperclip';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 上传文件
|
|
|
|
|
|
const uploadFile = async (file: any) => {
|
|
|
|
|
|
uni.showLoading({ title: '上传中...' });
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 使用 attachmentUpload 接口
|
|
|
|
|
|
const uploadResult: any = await attachmentUpload(file.path as any);
|
|
|
|
|
|
|
|
|
|
|
|
if (uploadResult.resultCode === 1 && uploadResult.result && uploadResult.result.length > 0) {
|
|
|
|
|
|
// 保存原始的 filePath(用于提交到服务器)
|
|
|
|
|
|
const originalPath = uploadResult.result[0].filePath;
|
|
|
|
|
|
const fileId = uploadResult.result[0].id;
|
|
|
|
|
|
const fileType = uploadResult.result[0].fileType;
|
|
|
|
|
|
|
|
|
|
|
|
// 更新最后一个附件的信息
|
|
|
|
|
|
const lastAttachment = formData.attachments[formData.attachments.length - 1];
|
|
|
|
|
|
if (lastAttachment) {
|
|
|
|
|
|
lastAttachment.url = originalPath;
|
|
|
|
|
|
lastAttachment.id = fileId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 同时更新原有的文件信息(保持兼容性)
|
|
|
|
|
|
formData.fileId = fileId;
|
|
|
|
|
|
formData.filePath = originalPath;
|
|
|
|
|
|
formData.resSuf = fileType;
|
|
|
|
|
|
formData.fileName = file.name;
|
|
|
|
|
|
|
|
|
|
|
|
uni.showToast({ title: '上传成功', icon: 'success' });
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error('上传失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('上传失败:', error);
|
|
|
|
|
|
uni.showToast({ title: '上传失败', icon: 'none' });
|
|
|
|
|
|
// 移除上传失败的附件
|
|
|
|
|
|
formData.attachments.pop();
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
uni.hideLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 提交表单
|
|
|
|
|
|
const handleSubmitForm = async () => {
|
|
|
|
|
|
// 表单验证
|
|
|
|
|
|
if (!formData.resourName.trim()) {
|
|
|
|
|
|
uni.showToast({ title: '请输入课题名称', icon: 'none' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!formData.resourType) {
|
|
|
|
|
|
uni.showToast({ title: '请选择资源目录', icon: 'none' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!formData.hour.trim()) {
|
|
|
|
|
|
uni.showToast({ title: '请输入课时', icon: 'none' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!formData.category) {
|
|
|
|
|
|
uni.showToast({ title: '请选择资源类别', icon: 'none' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (formData.attachments.length === 0) {
|
|
|
|
|
|
uni.showToast({ title: '请上传资源文件', icon: 'none' });
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (isSubmitting.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
isSubmitting.value = true;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
const params = {
|
|
|
|
|
|
resourName: formData.resourName,
|
|
|
|
|
|
resourType: formData.resourType,
|
|
|
|
|
|
category: formData.category,
|
|
|
|
|
|
remark: formData.content,
|
|
|
|
|
|
resourId: formData.fileId, // 保留原有的文件ID
|
|
|
|
|
|
resourUrl: formData.filePath, // 保留原有的文件路径
|
|
|
|
|
|
resSuf: formData.resSuf, // 保留原有的文件后缀
|
|
|
|
|
|
hour: formData.hour,
|
|
|
|
|
|
id: formData.id
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-08-09 11:36:56 +08:00
|
|
|
|
|
2025-08-02 11:15:22 +08:00
|
|
|
|
|
2025-10-29 10:30:04 +08:00
|
|
|
|
const result = await zymxSaveApi(params);
|
2025-08-02 11:15:22 +08:00
|
|
|
|
|
|
|
|
|
|
if (result.resultCode === 1) {
|
|
|
|
|
|
uni.showToast({ title: '操作成功', icon: 'success' });
|
|
|
|
|
|
// 返回上一页并刷新列表
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
uni.navigateBack();
|
|
|
|
|
|
// 通过事件总线通知列表页面刷新
|
|
|
|
|
|
uni.$emit('refreshResourceList');
|
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uni.showToast({ title: '操作失败', icon: 'none' });
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('提交失败:', error);
|
|
|
|
|
|
uni.showToast({ title: '操作失败,请重试', icon: 'none' });
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
isSubmitting.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 重置表单数据
|
|
|
|
|
|
const resetFormData = () => {
|
|
|
|
|
|
formData.resourName = '';
|
|
|
|
|
|
formData.resourType = '';
|
|
|
|
|
|
formData.category = '';
|
|
|
|
|
|
formData.content = '';
|
|
|
|
|
|
formData.fileId = '';
|
|
|
|
|
|
formData.filePath = '';
|
|
|
|
|
|
formData.resSuf = '';
|
|
|
|
|
|
formData.hour = '';
|
|
|
|
|
|
formData.id = '';
|
|
|
|
|
|
formData.fileName = '';
|
|
|
|
|
|
formData.attachments = []; // 重置附件列表
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 加载树形数据
|
|
|
|
|
|
const loadTreeData = async () => {
|
|
|
|
|
|
try {
|
2025-10-29 10:30:04 +08:00
|
|
|
|
const res = await zymlFindTreeApi();
|
2025-08-09 11:36:56 +08:00
|
|
|
|
// 处理返回的数据结构,确保与BasicTree组件兼容
|
|
|
|
|
|
if (res && Array.isArray(res)) {
|
|
|
|
|
|
treeData.value = res.map(item => ({
|
|
|
|
|
|
key: item.key || item.id,
|
|
|
|
|
|
title: item.title || item.name,
|
|
|
|
|
|
children: item.children ? item.children.map(child => ({
|
|
|
|
|
|
key: child.key || child.id,
|
|
|
|
|
|
title: child.title || child.name,
|
|
|
|
|
|
children: child.children || []
|
|
|
|
|
|
})) : []
|
|
|
|
|
|
}));
|
|
|
|
|
|
} else {
|
|
|
|
|
|
treeData.value = res.result || [];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-02 11:15:22 +08:00
|
|
|
|
} catch (error) {
|
2025-08-09 11:36:56 +08:00
|
|
|
|
|
|
|
|
|
|
// 如果加载失败,使用空数组
|
|
|
|
|
|
treeData.value = [];
|
2025-08-02 11:15:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取资源目录文本
|
|
|
|
|
|
const getResourceTypeText = () => {
|
2025-08-09 11:36:56 +08:00
|
|
|
|
// 递归查找选中的项目
|
|
|
|
|
|
const findSelectedItem = (items: any[], targetKey: string): any => {
|
|
|
|
|
|
for (const item of items) {
|
|
|
|
|
|
if (item.key === targetKey) {
|
|
|
|
|
|
return item;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
|
const found = findSelectedItem(item.children, targetKey);
|
|
|
|
|
|
if (found) return found;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const selectedItem = findSelectedItem(treeData.value, formData.resourType);
|
2025-08-02 11:15:22 +08:00
|
|
|
|
return selectedItem ? selectedItem.title : '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取资源类别文本
|
|
|
|
|
|
const getCategoryText = () => {
|
|
|
|
|
|
const selectedItem = categoryOptions.value.find(item => item.value === formData.category);
|
|
|
|
|
|
return selectedItem ? selectedItem.label : '';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
loadTreeData();
|
|
|
|
|
|
loadCategoryOptions(); // 加载资源类别选项
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.add-resource-page {
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
background-color: #f4f5f7;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.form-scroll-view {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-container {
|
|
|
|
|
|
padding: 30rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-card {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
border-radius: 12rpx;
|
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-item {
|
|
|
|
|
|
margin-bottom: 15rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.form-label {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
margin-bottom: 10rpx;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.required {
|
|
|
|
|
|
color: #ff3b30;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-input {
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.uni-easyinput__content) {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.uni-easyinput__content-input) {
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
:deep(.uni-easyinput__placeholder-class) {
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.picker-row {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 20rpx 0;
|
|
|
|
|
|
border-bottom: 1rpx solid #f0f0f0;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.placeholder {
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.attachment-list {
|
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.attachment-item {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
border: 1px solid #e9ecef;
|
|
|
|
|
|
|
|
|
|
|
|
.attachment-icon {
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.attachment-name {
|
|
|
|
|
|
flex-grow: 1;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #495057;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.remove-icon {
|
|
|
|
|
|
flex-shrink: 0;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
opacity: 0.7;
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
color: #dc3545 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.add-attachment-placeholder {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
border: 1px dashed #d5d8de;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
background-color: #f8f8f8;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
transition: background-color 0.2s;
|
|
|
|
|
|
|
|
|
|
|
|
.add-icon {
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
border: 1px solid #d5d8de;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-right: 12px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
|
|
|
|
|
|
.uni-icons {
|
|
|
|
|
|
color: #999 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.placeholder-text {
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:active {
|
|
|
|
|
|
background-color: #eee;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.bottom-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
|
padding: 30rpx;
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
border-top: 1rpx solid #f0f0f0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.confirm-btn {
|
2025-08-09 11:36:56 +08:00
|
|
|
|
width: 100%;
|
2025-08-02 11:15:22 +08:00
|
|
|
|
padding: 20rpx;
|
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
background: linear-gradient(135deg, #007aff 0%, #0056cc 100%);
|
|
|
|
|
|
color: white;
|
|
|
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0, 122, 255, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.confirm-btn:disabled {
|
|
|
|
|
|
opacity: 0.6;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|