|
@@ -1,349 +1,449 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <main class="safety-platform-container__main">
|
|
|
|
|
- <BasicForm ref="basicFormRef" :formData="ruleFormData" :formRules="isViewMode ? undefined : formRules"
|
|
|
|
|
- :formConfig="computedFormConfig">
|
|
|
|
|
- <template #fileFormat>
|
|
|
|
|
- <el-radio-group v-model="ruleFormData.fileFormat" :disabled="isViewMode">
|
|
|
|
|
- <el-radio value="PDF">PDF</el-radio>
|
|
|
|
|
- <el-radio value="WORD">WORD</el-radio>
|
|
|
|
|
- </el-radio-group>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #fileUrl>
|
|
|
|
|
- <UploadFiles label="上传文件" :maxCount="1" :file-list="ruleFormData.fileUrlList" :disabled="isViewMode"
|
|
|
|
|
- :allow-all-file-types="true" @uploadSuccess="handleUploadSuccess" />
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #content>
|
|
|
|
|
- <div class="editor-container">
|
|
|
|
|
- <Toolbar style="border-bottom: 1px solid #dcdfe6" :editor="editorRef" />
|
|
|
|
|
- <Editor style="height: 400px; overflow-y: auto" v-model="ruleFormData.content" mode="default"
|
|
|
|
|
- :defaultConfig="editorConfig" @on-created="handleEditorCreated"
|
|
|
|
|
- @on-change="handleEditorChange" />
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #imageFileUrl>
|
|
|
|
|
- <el-upload class="image-uploader" action="/api/admin/minio/uploadFile"
|
|
|
|
|
- :file-list="ruleFormData.imageFileUrl" :disabled="isViewMode" :limit="5"
|
|
|
|
|
- :on-success="handleImageUploadSuccess" :on-remove="handleImageRemove" list-type="picture-card">
|
|
|
|
|
- <el-icon>
|
|
|
|
|
- <Plus />
|
|
|
|
|
- </el-icon>
|
|
|
|
|
- <template #tip>
|
|
|
|
|
- <div class="el-upload__tip">
|
|
|
|
|
- 支持格式:.rar .zip .doc .docx .pdf ,单个文件不能超过20MB
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- </el-upload>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #status>
|
|
|
|
|
- <el-radio-group v-model="ruleFormData.status" :disabled="isViewMode">
|
|
|
|
|
- <el-radio :value="1">启用</el-radio>
|
|
|
|
|
- <el-radio :value="0">禁用</el-radio>
|
|
|
|
|
- </el-radio-group>
|
|
|
|
|
- </template>
|
|
|
|
|
- </BasicForm>
|
|
|
|
|
- </main>
|
|
|
|
|
- <footer class="safety-platform-container__footer">
|
|
|
|
|
- <el-button @click="router.back()">返回</el-button>
|
|
|
|
|
- <el-button v-if="!isViewMode" type="primary" @click="handleSubmit">
|
|
|
|
|
- {{ isCreateMode ? '提交' : '保存' }}
|
|
|
|
|
- </el-button>
|
|
|
|
|
- </footer>
|
|
|
|
|
|
|
+ <main class="safety-platform-container__main">
|
|
|
|
|
+ <BasicForm
|
|
|
|
|
+ ref="basicFormRef"
|
|
|
|
|
+ :formData="ruleFormData"
|
|
|
|
|
+ :formRules="isViewMode ? undefined : formRules"
|
|
|
|
|
+ :formConfig="computedFormConfig"
|
|
|
|
|
+ >
|
|
|
|
|
+ <template #fileFormat>
|
|
|
|
|
+ <el-radio-group v-model="ruleFormData.fileFormat" :disabled="isViewMode">
|
|
|
|
|
+ <el-radio value="PDF">PDF</el-radio>
|
|
|
|
|
+ <el-radio value="WORD">WORD</el-radio>
|
|
|
|
|
+ </el-radio-group>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #fileUrl>
|
|
|
|
|
+ <!-- <UploadFiles label="上传文件" :maxCount="1" :file-list="ruleFormData.fileUrlList" :disabled="isViewMode"
|
|
|
|
|
+ :allow-all-file-types="true" @uploadSuccess="handleUploadSuccess" /> -->
|
|
|
|
|
+
|
|
|
|
|
+ <UploadFiles
|
|
|
|
|
+ v-if="!isViewMode"
|
|
|
|
|
+ label="上传文件"
|
|
|
|
|
+ :maxCount="1"
|
|
|
|
|
+ :file-list="ruleFormData.attachmentUrl"
|
|
|
|
|
+ :disabled="isViewMode"
|
|
|
|
|
+ :allow-all-file-types="true"
|
|
|
|
|
+ @uploadSuccess="(list: FileItem[]) => handleUploadSuccess(list)"
|
|
|
|
|
+ />
|
|
|
|
|
+ <div class="file-list" v-else>
|
|
|
|
|
+ <div class="file-item" v-for="file in ruleFormData.attachmentUrl" :key="file.fileId">
|
|
|
|
|
+ <span class="file-item--name">{{ file.fileName }}</span>
|
|
|
|
|
+ <div class="file-item--footer">
|
|
|
|
|
+ <el-button link type="primary" @click="previewOnline(file.fileUrl, file.fileType)">预览</el-button>
|
|
|
|
|
+ <!-- <el-button link type="primary" @click.stop="downloadFile(file.fileUrl, file.fileName)"
|
|
|
|
|
+ >下载</el-button
|
|
|
|
|
+ > -->
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #content>
|
|
|
|
|
+ <div class="editor-container">
|
|
|
|
|
+ <Toolbar style="border-bottom: 1px solid #dcdfe6" :editor="editorRef" />
|
|
|
|
|
+ <Editor
|
|
|
|
|
+ style="height: 400px; overflow-y: auto"
|
|
|
|
|
+ v-model="ruleFormData.content"
|
|
|
|
|
+ mode="default"
|
|
|
|
|
+ :defaultConfig="editorConfig"
|
|
|
|
|
+ @on-created="handleEditorCreated"
|
|
|
|
|
+ @on-change="handleEditorChange"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #imageFileUrl>
|
|
|
|
|
+ <el-upload
|
|
|
|
|
+ :key="approvalUploadKey"
|
|
|
|
|
+ ref="approvalUploadRef"
|
|
|
|
|
+ v-model:file-list="approvalImageFileList"
|
|
|
|
|
+ :auto-upload="false"
|
|
|
|
|
+ list-type="picture-card"
|
|
|
|
|
+ :limit="1"
|
|
|
|
|
+ :disabled="isViewMode"
|
|
|
|
|
+ :on-change="handleApprovalImageChange"
|
|
|
|
|
+ :on-exceed="handleApprovalImageExceed"
|
|
|
|
|
+ :on-preview="handleApprovalPictureCardPreview"
|
|
|
|
|
+ :on-remove="handleApprovalImageRemove"
|
|
|
|
|
+ >
|
|
|
|
|
+ <el-icon><Plus /></el-icon>
|
|
|
|
|
+ <template #file="{ file }">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
|
|
|
|
|
+ <span class="el-upload-list__item-actions" v-if="!isViewMode">
|
|
|
|
|
+ <span class="el-upload-list__item-preview" @click="handleApprovalPictureCardPreview(file)">
|
|
|
|
|
+ <el-icon><ZoomIn /></el-icon>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span class="el-upload-list__item-delete" @click.stop="handleApprovalDeleteClick()">
|
|
|
|
|
+ <el-icon><Delete /></el-icon>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-upload>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ <template #status>
|
|
|
|
|
+ <el-radio-group v-model="ruleFormData.status" :disabled="isViewMode">
|
|
|
|
|
+ <el-radio :value="1">启用</el-radio>
|
|
|
|
|
+ <el-radio :value="0">禁用</el-radio>
|
|
|
|
|
+ </el-radio-group>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </BasicForm>
|
|
|
|
|
+ <PreviewOnline ref="previewOnlineRef" />
|
|
|
|
|
+ </main>
|
|
|
|
|
+ <el-dialog v-model="dialogVisible" width="30%">
|
|
|
|
|
+ <div class="dialog-content">
|
|
|
|
|
+ <img :src="dialogImageUrl" alt="Preview Image" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ <footer class="safety-platform-container__footer">
|
|
|
|
|
+ <el-button @click="router.back()">返回</el-button>
|
|
|
|
|
+ <el-button v-if="!isViewMode" type="primary" @click="handleSubmit">
|
|
|
|
|
+ {{ isCreateMode ? '提交' : '保存' }}
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </footer>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { computed, onMounted, ref, shallowRef, onBeforeUnmount } from 'vue';
|
|
|
|
|
-import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
-import { ElMessage } from 'element-plus';
|
|
|
|
|
-import BasicForm from '@/components/BasicForm.vue';
|
|
|
|
|
-import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
|
|
|
|
|
-import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
|
|
|
|
-import '@wangeditor/editor/dist/css/style.css';
|
|
|
|
|
-import { useFormConfigHook } from '@/hooks/useFormConfigHook';
|
|
|
|
|
-import { ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES } from '../configs/form';
|
|
|
|
|
-import {
|
|
|
|
|
|
|
+ import { computed, onMounted, ref, shallowRef, onBeforeUnmount } from 'vue';
|
|
|
|
|
+ import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
+ import { ElMessage } from 'element-plus';
|
|
|
|
|
+ import BasicForm from '@/components/BasicForm.vue';
|
|
|
|
|
+ import UploadFiles from '@/components/UploadFiles/UploadFiles.vue';
|
|
|
|
|
+ import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
|
|
|
|
+ import '@wangeditor/editor/dist/css/style.css';
|
|
|
|
|
+ import { useFormConfigHook } from '@/hooks/useFormConfigHook';
|
|
|
|
|
+ import { ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES } from '../configs/form';
|
|
|
|
|
+ import {
|
|
|
queryAcademyFileById,
|
|
queryAcademyFileById,
|
|
|
saveAcademyFile,
|
|
saveAcademyFile,
|
|
|
updateAcademyFile,
|
|
updateAcademyFile,
|
|
|
type safetyCultureFile,
|
|
type safetyCultureFile,
|
|
|
-} from '@/api/safety-culture';
|
|
|
|
|
-import type { FileItem } from '@/components/UploadFiles/types';
|
|
|
|
|
-import { formatAttachmentList } from '@/components/UploadFiles/utils';
|
|
|
|
|
-import { Plus, Delete } from '@element-plus/icons-vue';
|
|
|
|
|
-
|
|
|
|
|
-const router = useRouter();
|
|
|
|
|
-const route = useRoute();
|
|
|
|
|
-
|
|
|
|
|
-const operate = computed(() => (route.query.operate as string) || 'safety-culture-material-create');
|
|
|
|
|
-const currentId = computed(() => Number(route.query.id));
|
|
|
|
|
-
|
|
|
|
|
-const isCreateMode = computed(() => operate.value === 'safety-culture-material-create');
|
|
|
|
|
-const isEditMode = computed(() => operate.value === 'safety-culture-material-edit');
|
|
|
|
|
-const isViewMode = computed(() => operate.value === 'safety-culture-material-view');
|
|
|
|
|
-
|
|
|
|
|
-const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } =
|
|
|
|
|
- useFormConfigHook(ACADEMY_FILE_FORM_CONFIG, ACADEMY_FILE_FORM_DATA, ACADEMY_FILE_FORM_RULES);
|
|
|
|
|
-
|
|
|
|
|
-// 查看模式下,所有字段设为只读
|
|
|
|
|
-const viewFormConfig = ref(
|
|
|
|
|
|
|
+ } from '@/api/safety-culture';
|
|
|
|
|
+ import { uploadFileApi, UPLOAD_BIZ_TYPE } from '@/api/minio';
|
|
|
|
|
+ import type { FileItem } from '@/components/UploadFiles/types';
|
|
|
|
|
+ import { formatAttachmentList } from '@/components/UploadFiles/utils';
|
|
|
|
|
+ import { Plus, Delete, ZoomIn } from '@element-plus/icons-vue';
|
|
|
|
|
+ import { genFileId, type UploadProps, type UploadUserFile, type UploadRawFile, type UploadInstance } from 'element-plus';
|
|
|
|
|
+ import PreviewOnline from '@/views/disaster/components/PreviewOnline.vue';
|
|
|
|
|
+
|
|
|
|
|
+ const router = useRouter();
|
|
|
|
|
+ const route = useRoute();
|
|
|
|
|
+
|
|
|
|
|
+ const operate = computed(() => (route.query.operate as string) || 'safety-culture-material-create');
|
|
|
|
|
+ const currentId = computed(() => Number(route.query.id));
|
|
|
|
|
+
|
|
|
|
|
+ const isCreateMode = computed(() => operate.value === 'safety-culture-material-create');
|
|
|
|
|
+ const isEditMode = computed(() => operate.value === 'safety-culture-material-edit');
|
|
|
|
|
+ const isViewMode = computed(() => operate.value === 'safety-culture-material-view');
|
|
|
|
|
+ const previewOnlineRef = ref<InstanceType<typeof PreviewOnline>>();
|
|
|
|
|
+ const approvalUploadRef = ref<UploadInstance>();
|
|
|
|
|
+ const approvalImageFileList = ref<UploadUserFile[]>([]);
|
|
|
|
|
+ const approvalUploadKey = ref(0);
|
|
|
|
|
+ const dialogImageUrl = ref('');
|
|
|
|
|
+ const dialogVisible = ref(false);
|
|
|
|
|
+
|
|
|
|
|
+ const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } = useFormConfigHook(
|
|
|
|
|
+ ACADEMY_FILE_FORM_CONFIG,
|
|
|
|
|
+ ACADEMY_FILE_FORM_DATA,
|
|
|
|
|
+ ACADEMY_FILE_FORM_RULES,
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // 查看模式下,所有字段设为只读
|
|
|
|
|
+ const viewFormConfig = ref(
|
|
|
ACADEMY_FILE_FORM_CONFIG.map((item) => ({
|
|
ACADEMY_FILE_FORM_CONFIG.map((item) => ({
|
|
|
- ...item,
|
|
|
|
|
- componentProps: {
|
|
|
|
|
- ...item.componentProps,
|
|
|
|
|
- disabled: true,
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ componentProps: {
|
|
|
|
|
+ ...item.componentProps,
|
|
|
|
|
+ disabled: true,
|
|
|
|
|
+ },
|
|
|
})),
|
|
})),
|
|
|
-);
|
|
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
-const computedFormConfig = computed(() => {
|
|
|
|
|
|
|
+ const computedFormConfig = computed(() => {
|
|
|
if (isViewMode.value) {
|
|
if (isViewMode.value) {
|
|
|
- return viewFormConfig.value;
|
|
|
|
|
|
|
+ return viewFormConfig.value;
|
|
|
}
|
|
}
|
|
|
return ruleFormConfig.value;
|
|
return ruleFormConfig.value;
|
|
|
-});
|
|
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
-const basicFormRef = ref<InstanceType<typeof BasicForm>>();
|
|
|
|
|
|
|
+ const basicFormRef = ref<InstanceType<typeof BasicForm>>();
|
|
|
|
|
|
|
|
-// 富文本编辑器
|
|
|
|
|
-const editorRef = shallowRef();
|
|
|
|
|
-const editorConfig = computed(() => ({
|
|
|
|
|
|
|
+ // 富文本编辑器
|
|
|
|
|
+ const editorRef = shallowRef();
|
|
|
|
|
+ const editorConfig = computed(() => ({
|
|
|
placeholder: '请输入文档内容',
|
|
placeholder: '请输入文档内容',
|
|
|
MENU_CONF: {},
|
|
MENU_CONF: {},
|
|
|
-}));
|
|
|
|
|
|
|
+ }));
|
|
|
|
|
|
|
|
-const handleEditorCreated = (editor: any) => {
|
|
|
|
|
|
|
+ const handleEditorCreated = (editor: any) => {
|
|
|
editorRef.value = editor;
|
|
editorRef.value = editor;
|
|
|
-};
|
|
|
|
|
|
|
+ if (isViewMode.value) {
|
|
|
|
|
+ editor.disable();
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
-const handleEditorChange = () => {
|
|
|
|
|
|
|
+ const handleEditorChange = () => {
|
|
|
// 编辑器内容变化时的处理
|
|
// 编辑器内容变化时的处理
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 文件上传
|
|
|
|
|
-const handleUploadSuccess = (files: FileItem[]) => {
|
|
|
|
|
- ruleFormData.fileUrlList = files;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 将逗号分隔的URL字符串转换为FileItem数组
|
|
|
|
|
-const convertFileUrlToFileItems = (fileUrl: string): FileItem[] => {
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 文件上传
|
|
|
|
|
+ const handleUploadSuccess = (files: FileItem[]) => {
|
|
|
|
|
+ ruleFormData.attachmentUrl = files;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleApprovalPictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
|
|
|
|
|
+ dialogImageUrl.value = uploadFile.url || '';
|
|
|
|
|
+ dialogVisible.value = true;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const resetApprovalImageUpload = () => {
|
|
|
|
|
+ approvalUploadRef.value?.clearFiles();
|
|
|
|
|
+ ruleFormData.imageUrls = [];
|
|
|
|
|
+ approvalImageFileList.value = [];
|
|
|
|
|
+ approvalUploadKey.value += 1;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleApprovalDeleteClick = () => {
|
|
|
|
|
+ resetApprovalImageUpload();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleApprovalImageRemove: UploadProps['onRemove'] = () => {
|
|
|
|
|
+ resetApprovalImageUpload();
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleApprovalImageChange = (uploadFile: UploadUserFile) => {
|
|
|
|
|
+ if (!uploadFile.raw) return;
|
|
|
|
|
+
|
|
|
|
|
+ uploadFileApi({
|
|
|
|
|
+ file: uploadFile.raw,
|
|
|
|
|
+ bizType: UPLOAD_BIZ_TYPE['DICTIONARY'],
|
|
|
|
|
+ fileName: uploadFile.raw.name,
|
|
|
|
|
+ })
|
|
|
|
|
+ .then((res) => {
|
|
|
|
|
+ ruleFormData.imageUrls = [res.url];
|
|
|
|
|
+ approvalImageFileList.value = [
|
|
|
|
|
+ {
|
|
|
|
|
+ name: uploadFile.name || res.url.split('/').pop() || 'image',
|
|
|
|
|
+ url: res.url,
|
|
|
|
|
+ },
|
|
|
|
|
+ ];
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(() => {
|
|
|
|
|
+ ElMessage.error('图片上传失败,请重试');
|
|
|
|
|
+ });
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const handleApprovalImageExceed: UploadProps['onExceed'] = (files) => {
|
|
|
|
|
+ const uploadInstance = approvalUploadRef.value;
|
|
|
|
|
+ if (!uploadInstance) return;
|
|
|
|
|
+
|
|
|
|
|
+ uploadInstance.clearFiles();
|
|
|
|
|
+ const file = files[0] as UploadRawFile;
|
|
|
|
|
+ file.uid = genFileId();
|
|
|
|
|
+ uploadInstance.handleStart(file);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 将逗号分隔的URL字符串转换为FileItem数组
|
|
|
|
|
+ const convertFileUrlToFileItems = (fileUrl: string): FileItem[] => {
|
|
|
if (!fileUrl || !fileUrl.trim()) {
|
|
if (!fileUrl || !fileUrl.trim()) {
|
|
|
- return [];
|
|
|
|
|
|
|
+ return [];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 按逗号分割URL
|
|
// 按逗号分割URL
|
|
|
- const urls = fileUrl.split(',').map(url => url.trim()).filter(url => url);
|
|
|
|
|
|
|
+ const urls = fileUrl
|
|
|
|
|
+ .split(',')
|
|
|
|
|
+ .map((url) => url.trim())
|
|
|
|
|
+ .filter((url) => url);
|
|
|
|
|
|
|
|
return urls.map((url, index) => {
|
|
return urls.map((url, index) => {
|
|
|
- // 从URL中提取文件名
|
|
|
|
|
- const urlParts = url.split('/');
|
|
|
|
|
- const fileName = urlParts[urlParts.length - 1] || `附件${index + 1}`;
|
|
|
|
|
-
|
|
|
|
|
- // 根据文件扩展名判断文件类型
|
|
|
|
|
- const extension = fileName.split('.').pop()?.toLowerCase() || '';
|
|
|
|
|
- let fileType = 'pdf';
|
|
|
|
|
- if (extension === 'doc' || extension === 'docx') {
|
|
|
|
|
- fileType = 'word';
|
|
|
|
|
- } else if (extension === 'xls' || extension === 'xlsx') {
|
|
|
|
|
- fileType = 'excel';
|
|
|
|
|
- } else if (extension === 'ppt' || extension === 'pptx') {
|
|
|
|
|
- fileType = 'ppt';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return {
|
|
|
|
|
- fileId: Date.now() + index,
|
|
|
|
|
- fileName,
|
|
|
|
|
- fileType,
|
|
|
|
|
- fileSize: '0',
|
|
|
|
|
- fileUrl: url,
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ // 从URL中提取文件名
|
|
|
|
|
+ const urlParts = url.split('/');
|
|
|
|
|
+ const fileName = urlParts[urlParts.length - 1] || `附件${index + 1}`;
|
|
|
|
|
+
|
|
|
|
|
+ // 根据文件扩展名判断文件类型
|
|
|
|
|
+ const extension = fileName.split('.').pop()?.toLowerCase() || '';
|
|
|
|
|
+ let fileType = 'pdf';
|
|
|
|
|
+ if (extension === 'doc' || extension === 'docx') {
|
|
|
|
|
+ fileType = 'word';
|
|
|
|
|
+ } else if (extension === 'xls' || extension === 'xlsx') {
|
|
|
|
|
+ fileType = 'excel';
|
|
|
|
|
+ } else if (extension === 'ppt' || extension === 'pptx') {
|
|
|
|
|
+ fileType = 'ppt';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ fileId: Date.now() + index,
|
|
|
|
|
+ fileName,
|
|
|
|
|
+ fileType,
|
|
|
|
|
+ fileSize: '0',
|
|
|
|
|
+ fileUrl: url,
|
|
|
|
|
+ };
|
|
|
});
|
|
});
|
|
|
-};
|
|
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
-const handleValidate = async () => {
|
|
|
|
|
|
|
+ const handleValidate = async () => {
|
|
|
if (!basicFormRef.value) return;
|
|
if (!basicFormRef.value) return;
|
|
|
const res = await basicFormRef.value.validateForm();
|
|
const res = await basicFormRef.value.validateForm();
|
|
|
return res;
|
|
return res;
|
|
|
-};
|
|
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
-const getDetail = async () => {
|
|
|
|
|
|
|
+ const getDetail = async () => {
|
|
|
if (!currentId.value) return;
|
|
if (!currentId.value) return;
|
|
|
try {
|
|
try {
|
|
|
- const res = await queryAcademyFileById(currentId.value);
|
|
|
|
|
- if (res) {
|
|
|
|
|
- // 映射接口字段到表单字段
|
|
|
|
|
- ruleFormData.fileName = res.fileName || '';
|
|
|
|
|
- ruleFormData.categoryName = res.categoryName || '';
|
|
|
|
|
- ruleFormData.fileCode = res.fileCode || '';
|
|
|
|
|
- ruleFormData.fileVersion = res.fileVersion || '';
|
|
|
|
|
- ruleFormData.fileFormat = res.fileFormat === 1 ? 'PDF' : 'WORD';
|
|
|
|
|
- ruleFormData.publishDate = res.publishDate || '';
|
|
|
|
|
- ruleFormData.fileUrl = res.fileUrl || '';
|
|
|
|
|
- ruleFormData.content = res.content || '';
|
|
|
|
|
- ruleFormData.status = res.status ?? 1;
|
|
|
|
|
-
|
|
|
|
|
- // 如果有文件URL,转换为FileItem格式
|
|
|
|
|
- ruleFormData.fileUrlList = convertFileUrlToFileItems(res.fileUrl || '');
|
|
|
|
|
- }
|
|
|
|
|
- cloneRuleFormData();
|
|
|
|
|
|
|
+ const res = await queryAcademyFileById(currentId.value);
|
|
|
|
|
+ if (res) {
|
|
|
|
|
+ // 映射接口字段到表单字段
|
|
|
|
|
+ ruleFormData.fileName = res.fileName || '';
|
|
|
|
|
+ ruleFormData.categoryName = res.categoryName || '';
|
|
|
|
|
+ ruleFormData.fileCode = res.fileCode || '';
|
|
|
|
|
+ ruleFormData.fileVersion = res.fileVersion || '';
|
|
|
|
|
+ ruleFormData.fileFormat = res.fileFormat === 1 ? 'PDF' : 'WORD';
|
|
|
|
|
+ ruleFormData.publishDate = res.publishDate || '';
|
|
|
|
|
+ ruleFormData.content = res.content || '';
|
|
|
|
|
+ ruleFormData.status = res.status ?? 1;
|
|
|
|
|
+ ruleFormData.imageUrls = JSON.parse(res.imageUrls || '[]');
|
|
|
|
|
+ approvalImageFileList.value = (ruleFormData.imageUrls || []).map((url, index) => ({
|
|
|
|
|
+ name: `图片${index + 1}`,
|
|
|
|
|
+ url,
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有文件URL,转换为FileItem格式
|
|
|
|
|
+ ruleFormData.attachmentUrl = JSON.parse(res.attachmentUrl || res.fileUrl || '');
|
|
|
|
|
+ }
|
|
|
|
|
+ cloneRuleFormData();
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
- console.error('获取院级文件详情失败:', e);
|
|
|
|
|
- ElMessage.error('获取详情失败');
|
|
|
|
|
|
|
+ console.error('获取院级文件详情失败:', e);
|
|
|
|
|
+ ElMessage.error('获取详情失败');
|
|
|
}
|
|
}
|
|
|
-};
|
|
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
-const handleSubmit = async () => {
|
|
|
|
|
|
|
+ const handleSubmit = async () => {
|
|
|
const res = await handleValidate();
|
|
const res = await handleValidate();
|
|
|
if (!res) return;
|
|
if (!res) return;
|
|
|
|
|
|
|
|
// 验证文件上传(必填)
|
|
// 验证文件上传(必填)
|
|
|
- if (!ruleFormData.fileUrlList || ruleFormData.fileUrlList.length === 0) {
|
|
|
|
|
- ElMessage.warning('请上传文件');
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ if (!ruleFormData.attachmentUrl || ruleFormData.attachmentUrl.length === 0) {
|
|
|
|
|
+ ElMessage.warning('请上传文件');
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
try {
|
|
try {
|
|
|
- // 处理文件上传:先上传文件获取 URL,然后提取 fileUrl
|
|
|
|
|
- let fileUrl = '';
|
|
|
|
|
- if (ruleFormData.fileUrlList && ruleFormData.fileUrlList.length > 0) {
|
|
|
|
|
- // 分离已有URL的文件和新上传的文件
|
|
|
|
|
- const existingFiles: string[] = [];
|
|
|
|
|
- const newFiles: FileItem[] = [];
|
|
|
|
|
-
|
|
|
|
|
- ruleFormData.fileUrlList.forEach((file: FileItem) => {
|
|
|
|
|
- // 如果文件已经有 fileUrl 且没有 file 对象,说明是已有文件
|
|
|
|
|
- if (file.fileUrl && !file.file) {
|
|
|
|
|
- existingFiles.push(file.fileUrl);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 否则是需要上传的新文件
|
|
|
|
|
- newFiles.push(file);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- // 上传新文件
|
|
|
|
|
- let uploadedUrls: string[] = [];
|
|
|
|
|
- if (newFiles.length > 0) {
|
|
|
|
|
- const uploadedFiles = await formatAttachmentList(newFiles);
|
|
|
|
|
- uploadedUrls = uploadedFiles
|
|
|
|
|
- .map((file: any) => file.fileUrl || file.url || '')
|
|
|
|
|
- .filter((url: string) => url);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 合并已有URL和新上传的URL,取第一个作为fileUrl
|
|
|
|
|
- const allUrls = [...existingFiles, ...uploadedUrls].filter((url: string) => url);
|
|
|
|
|
- fileUrl = allUrls.length > 0 ? allUrls[0] : '';
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const basePayload: safetyCultureFile = {
|
|
|
|
|
- fileName: ruleFormData.fileName,
|
|
|
|
|
- classifyName: ruleFormData.classifyName,
|
|
|
|
|
- categoryName: ruleFormData.categoryName,
|
|
|
|
|
- fileCode: ruleFormData.fileCode,
|
|
|
|
|
- fileVersion: ruleFormData.fileVersion,
|
|
|
|
|
- fileFormat: ruleFormData.fileFormat === 'PDF' ? 1 : 2,
|
|
|
|
|
- publishDate: ruleFormData.publishDate,
|
|
|
|
|
- attachmentUrl: fileUrl || '',
|
|
|
|
|
- content: ruleFormData.content || undefined,
|
|
|
|
|
- status: ruleFormData.status ?? 1,
|
|
|
|
|
- releaseDate: ruleFormData.publishDate,
|
|
|
|
|
- description: '',
|
|
|
|
|
- caseName: '',
|
|
|
|
|
- imageUrls: ruleFormData.imageFileUrl.map(item => item.fileUrl || item.url || '').join(',') || '',
|
|
|
|
|
- };
|
|
|
|
|
- if (isCreateMode.value) {
|
|
|
|
|
- await saveAcademyFile(basePayload);
|
|
|
|
|
- ElMessage.success('创建成功');
|
|
|
|
|
- } else if (isEditMode.value && currentId.value) {
|
|
|
|
|
- await updateAcademyFile({
|
|
|
|
|
- id: currentId.value,
|
|
|
|
|
- ...basePayload,
|
|
|
|
|
- });
|
|
|
|
|
- ElMessage.success('保存成功');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- router.back();
|
|
|
|
|
|
|
+ const uploadedFileList = await formatAttachmentList(ruleFormData.attachmentUrl);
|
|
|
|
|
+
|
|
|
|
|
+ const basePayload: any = {
|
|
|
|
|
+ fileName: ruleFormData.fileName,
|
|
|
|
|
+ classifyName: ruleFormData.classifyName,
|
|
|
|
|
+ categoryName: ruleFormData.categoryName,
|
|
|
|
|
+ fileCode: ruleFormData.fileCode,
|
|
|
|
|
+ fileVersion: ruleFormData.fileVersion,
|
|
|
|
|
+ fileFormat: ruleFormData.fileFormat === 'PDF' ? 1 : 2,
|
|
|
|
|
+ publishDate: ruleFormData.publishDate,
|
|
|
|
|
+ attachmentUrl: JSON.stringify(uploadedFileList),
|
|
|
|
|
+ content: ruleFormData.content || undefined,
|
|
|
|
|
+ status: ruleFormData.status ?? 1,
|
|
|
|
|
+ releaseDate: ruleFormData.publishDate,
|
|
|
|
|
+ description: '',
|
|
|
|
|
+ caseName: '',
|
|
|
|
|
+ imageUrls: JSON.stringify(ruleFormData.imageUrls),
|
|
|
|
|
+ };
|
|
|
|
|
+ if (isCreateMode.value) {
|
|
|
|
|
+ await saveAcademyFile(basePayload);
|
|
|
|
|
+ ElMessage.success('创建成功');
|
|
|
|
|
+ } else if (isEditMode.value && currentId.value) {
|
|
|
|
|
+ await updateAcademyFile({
|
|
|
|
|
+ id: currentId.value,
|
|
|
|
|
+ ...basePayload,
|
|
|
|
|
+ });
|
|
|
|
|
+ ElMessage.success('保存成功');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ router.back();
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
- console.error('保存院级文件失败:', e);
|
|
|
|
|
- ElMessage.error('保存失败,请重试');
|
|
|
|
|
|
|
+ console.error('保存院级文件失败:', e);
|
|
|
|
|
+ ElMessage.error('保存失败,请重试');
|
|
|
}
|
|
}
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const handleImageUploadSuccess = (response: any, file: any, fileList: any[]) => {
|
|
|
|
|
- const imageUrl = response.data?.url || file.url;
|
|
|
|
|
- ruleFormData.imageFileUrl = fileList.map(item => ({
|
|
|
|
|
- fileId: Date.now() + Math.random(),
|
|
|
|
|
- fileName: item.name,
|
|
|
|
|
- fileType: 'image',
|
|
|
|
|
- fileSize: (item.size / 1024).toFixed(2) + 'KB',
|
|
|
|
|
- fileUrl: imageUrl || item.url
|
|
|
|
|
- }));
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const handleImageRemove = (file: any, fileList: any[]) => {
|
|
|
|
|
- ruleFormData.imageFileUrl = fileList.map(item => ({
|
|
|
|
|
- fileId: item.fileId || Date.now() + Math.random(),
|
|
|
|
|
- fileName: item.name || item.fileName,
|
|
|
|
|
- fileType: 'image',
|
|
|
|
|
- fileSize: item.size ? (item.size / 1024).toFixed(2) + 'KB' : item.fileSize,
|
|
|
|
|
- fileUrl: item.url || item.fileUrl
|
|
|
|
|
- }));
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-onMounted(() => {
|
|
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ const previewOnline = (url: string | undefined, type) => {
|
|
|
|
|
+ if (url) {
|
|
|
|
|
+ previewOnlineRef.value?.open(url, type);
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ onMounted(() => {
|
|
|
cloneRuleFormData();
|
|
cloneRuleFormData();
|
|
|
// beforeRouteLeave();
|
|
// beforeRouteLeave();
|
|
|
if (isEditMode.value || isViewMode.value) {
|
|
if (isEditMode.value || isViewMode.value) {
|
|
|
- getDetail();
|
|
|
|
|
|
|
+ getDetail();
|
|
|
}
|
|
}
|
|
|
-});
|
|
|
|
|
|
|
+ });
|
|
|
|
|
|
|
|
-onBeforeUnmount(() => {
|
|
|
|
|
|
|
+ onBeforeUnmount(() => {
|
|
|
const editor = editorRef.value;
|
|
const editor = editorRef.value;
|
|
|
if (editor == null) return;
|
|
if (editor == null) return;
|
|
|
editor.destroy();
|
|
editor.destroy();
|
|
|
-});
|
|
|
|
|
|
|
+ });
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
<style scoped lang="scss">
|
|
|
-@use '@/styles/page-details-layout.scss' as *;
|
|
|
|
|
|
|
+ @use '@/styles/page-details-layout.scss' as *;
|
|
|
|
|
|
|
|
-.editor-container {
|
|
|
|
|
|
|
+ .editor-container {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
border: 1px solid #dcdfe6;
|
|
border: 1px solid #dcdfe6;
|
|
|
border-radius: 4px;
|
|
border-radius: 4px;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
-}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-.content-display {
|
|
|
|
|
|
|
+ .content-display {
|
|
|
min-height: 200px;
|
|
min-height: 200px;
|
|
|
padding: 12px;
|
|
padding: 12px;
|
|
|
border: 1px solid #dcdfe6;
|
|
border: 1px solid #dcdfe6;
|
|
|
border-radius: 4px;
|
|
border-radius: 4px;
|
|
|
background-color: #f5f7fa;
|
|
background-color: #f5f7fa;
|
|
|
-}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-.file-display {
|
|
|
|
|
|
|
+ .file-display {
|
|
|
.file-link {
|
|
.file-link {
|
|
|
- color: #409eff;
|
|
|
|
|
- text-decoration: none;
|
|
|
|
|
|
|
+ color: #409eff;
|
|
|
|
|
+ text-decoration: none;
|
|
|
|
|
|
|
|
- &:hover {
|
|
|
|
|
- text-decoration: underline;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ text-decoration: underline;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-.no-file {
|
|
|
|
|
|
|
+ .no-file {
|
|
|
color: rgba(0, 0, 0, 0.65);
|
|
color: rgba(0, 0, 0, 0.65);
|
|
|
-}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
-.image-uploader {
|
|
|
|
|
|
|
+ .image-uploader {
|
|
|
:deep(.el-upload--picture-card) {
|
|
:deep(.el-upload--picture-card) {
|
|
|
- width: 80px !important;
|
|
|
|
|
- height: 80px !important;
|
|
|
|
|
- line-height: 80px;
|
|
|
|
|
|
|
+ width: 80px !important;
|
|
|
|
|
+ height: 80px !important;
|
|
|
|
|
+ line-height: 80px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
:deep(.el-upload-list--picture-card .el-upload-list__item) {
|
|
:deep(.el-upload-list--picture-card .el-upload-list__item) {
|
|
|
- width: 80px !important;
|
|
|
|
|
- height: 80px !important;
|
|
|
|
|
|
|
+ width: 80px !important;
|
|
|
|
|
+ height: 80px !important;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .dialog-content {
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
}
|
|
}
|
|
|
-}
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+</style>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss">
|
|
|
|
|
+ .w-e-full-screen-container {
|
|
|
|
|
+ inset: 0 !important;
|
|
|
|
|
+ z-index: 3000 !important;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .w-e-full-screen-container .w-e-text-container {
|
|
|
|
|
+ height: calc(100vh - 42px) !important;
|
|
|
|
|
+ }
|
|
|
</style>
|
|
</style>
|