|
|
@@ -5,7 +5,44 @@
|
|
|
: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
|
|
|
+ v-if="!isViewMode"
|
|
|
+ label="上传文件"
|
|
|
+ :maxCount="1"
|
|
|
+ :fileList="uploadFileList"
|
|
|
+ @uploadSuccess="handleUploadSuccess"
|
|
|
+ />
|
|
|
+ <div v-else-if="ruleFormData.fileUrl" class="file-display">
|
|
|
+ <a :href="ruleFormData.fileUrl" target="_blank" class="file-link">{{ getFileName(ruleFormData.fileUrl) }}</a>
|
|
|
+ </div>
|
|
|
+ <span v-else class="no-file">暂无文件</span>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <div v-if="!isViewMode" class="editor-container">
|
|
|
+ <Editor
|
|
|
+ v-model="ruleFormData.content"
|
|
|
+ :defaultConfig="editorConfig"
|
|
|
+ style="height: 400px"
|
|
|
+ @onCreated="handleEditorCreated"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div v-else class="content-display" v-html="ruleFormData.content || '暂无内容'"></div>
|
|
|
+ </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>
|
|
|
@@ -16,30 +53,46 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { computed, onMounted, ref } from 'vue';
|
|
|
+ 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 } from '@wangeditor/editor-for-vue';
|
|
|
+ import '@wangeditor/editor/dist/css/style.css';
|
|
|
import { useFormConfigHook } from '@/hooks/useFormConfigHook';
|
|
|
- import { INVENTORY_FORM_CONFIG, INVENTORY_FORM_DATA, INVENTORY_FORM_RULES } from '../configs/form';
|
|
|
- import { queryInventoryDetail, saveInventory, updateInventory } from '@/api/inventory';
|
|
|
+ import {
|
|
|
+ INDUSTRY_STANDARD_FORM_CONFIG,
|
|
|
+ INDUSTRY_STANDARD_FORM_DATA,
|
|
|
+ INDUSTRY_STANDARD_FORM_RULES,
|
|
|
+ } from '../configs/form';
|
|
|
+ import {
|
|
|
+ queryIndustryStandardById,
|
|
|
+ saveIndustryStandard,
|
|
|
+ updateIndustryStandard,
|
|
|
+ type ProductionSafetyFile,
|
|
|
+ } from '@/api/production-safety-system';
|
|
|
+ import type { FileItem } from '@/components/UploadFiles/types';
|
|
|
|
|
|
const router = useRouter();
|
|
|
const route = useRoute();
|
|
|
|
|
|
- const operate = computed(() => (route.query.operate as string) || 'inventory-create');
|
|
|
+ const operate = computed(() => (route.query.operate as string) || 'industry-standard-create');
|
|
|
const currentId = computed(() => Number(route.query.id));
|
|
|
|
|
|
- const isCreateMode = computed(() => operate.value === 'inventory-create');
|
|
|
- const isEditMode = computed(() => operate.value === 'inventory-edit');
|
|
|
- const isViewMode = computed(() => operate.value === 'inventory-view');
|
|
|
+ const isCreateMode = computed(() => operate.value === 'industry-standard-create');
|
|
|
+ const isEditMode = computed(() => operate.value === 'industry-standard-edit');
|
|
|
+ const isViewMode = computed(() => operate.value === 'industry-standard-view');
|
|
|
|
|
|
- const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } =
|
|
|
- useFormConfigHook(INVENTORY_FORM_CONFIG, INVENTORY_FORM_DATA, INVENTORY_FORM_RULES);
|
|
|
+ const { ruleFormData, formRules, ruleFormConfig, cloneRuleFormData, beforeRouteLeave } = useFormConfigHook(
|
|
|
+ INDUSTRY_STANDARD_FORM_CONFIG,
|
|
|
+ INDUSTRY_STANDARD_FORM_DATA,
|
|
|
+ INDUSTRY_STANDARD_FORM_RULES,
|
|
|
+ );
|
|
|
|
|
|
// 查看模式下,所有字段设为只读
|
|
|
const viewFormConfig = ref(
|
|
|
- INVENTORY_FORM_CONFIG.map((item) => ({
|
|
|
+ INDUSTRY_STANDARD_FORM_CONFIG.map((item) => ({
|
|
|
...item,
|
|
|
componentProps: {
|
|
|
...item.componentProps,
|
|
|
@@ -57,6 +110,35 @@
|
|
|
|
|
|
const basicFormRef = ref<InstanceType<typeof BasicForm>>();
|
|
|
|
|
|
+ // 富文本编辑器
|
|
|
+ const editorRef = shallowRef();
|
|
|
+ const editorConfig = {
|
|
|
+ placeholder: '请输入文档内容',
|
|
|
+ MENU_CONF: {},
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleEditorCreated = (editor: any) => {
|
|
|
+ editorRef.value = editor;
|
|
|
+ };
|
|
|
+
|
|
|
+ // 文件上传
|
|
|
+ const uploadFileList = ref<FileItem[]>([]);
|
|
|
+
|
|
|
+ const handleUploadSuccess = (files: FileItem[]) => {
|
|
|
+ uploadFileList.value = files;
|
|
|
+ if (files.length > 0 && files[0].file) {
|
|
|
+ // 这里需要实际上传文件到服务器,获取 fileUrl
|
|
|
+ // 暂时使用文件对象,实际应该调用上传接口
|
|
|
+ ruleFormData.fileUrl = files[0].file.name; // 临时处理,需要替换为实际上传后的URL
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const getFileName = (url: string) => {
|
|
|
+ if (!url) return '';
|
|
|
+ const parts = url.split('/');
|
|
|
+ return parts[parts.length - 1];
|
|
|
+ };
|
|
|
+
|
|
|
const handleValidate = async () => {
|
|
|
if (!basicFormRef.value) return;
|
|
|
const res = await basicFormRef.value.validateForm();
|
|
|
@@ -66,17 +148,34 @@
|
|
|
const getDetail = async () => {
|
|
|
if (!currentId.value) return;
|
|
|
try {
|
|
|
- const res = await queryInventoryDetail(currentId.value);
|
|
|
+ const res = await queryIndustryStandardById(currentId.value);
|
|
|
if (res) {
|
|
|
// 映射接口字段到表单字段
|
|
|
- ruleFormData.itemName = res.stuffName; // 物品名称
|
|
|
- ruleFormData.warehouseDate = res.inStoreTime ? res.inStoreTime.split('T')[0] : ''; // 入库日期(YYYY-MM-DD)
|
|
|
- ruleFormData.itemQuantity = res.stuffQty; // 物品数量
|
|
|
- ruleFormData.remarks = res.remark || ''; // 备注
|
|
|
+ ruleFormData.fileName = res.fileName || '';
|
|
|
+ ruleFormData.classifyName = res.classifyName || '';
|
|
|
+ ruleFormData.fileCode = res.fileCode || '';
|
|
|
+ ruleFormData.fileVersion = res.fileVersion || '';
|
|
|
+ ruleFormData.fileFormat = res.fileFormat || '';
|
|
|
+ ruleFormData.releaseDate = res.releaseDate || '';
|
|
|
+ ruleFormData.fileUrl = res.fileUrl || '';
|
|
|
+ ruleFormData.content = res.content || '';
|
|
|
+ ruleFormData.status = res.status ?? 1;
|
|
|
+
|
|
|
+ // 如果有文件URL,转换为FileItem格式
|
|
|
+ if (res.fileUrl) {
|
|
|
+ uploadFileList.value = [
|
|
|
+ {
|
|
|
+ fileId: Date.now(),
|
|
|
+ fileName: getFileName(res.fileUrl),
|
|
|
+ fileType: res.fileFormat?.toLowerCase() === 'pdf' ? 'pdf' : 'word',
|
|
|
+ fileSize: '0KB',
|
|
|
+ },
|
|
|
+ ];
|
|
|
+ }
|
|
|
}
|
|
|
cloneRuleFormData();
|
|
|
} catch (e) {
|
|
|
- console.error('获取物品库存详情失败:', e);
|
|
|
+ console.error('获取行业标准详情失败:', e);
|
|
|
ElMessage.error('获取详情失败');
|
|
|
}
|
|
|
};
|
|
|
@@ -85,20 +184,23 @@
|
|
|
const res = await handleValidate();
|
|
|
if (!res) return;
|
|
|
try {
|
|
|
- const basePayload = {
|
|
|
- stuffName: ruleFormData.itemName,
|
|
|
- inStoreTime: ruleFormData.warehouseDate
|
|
|
- ? new Date(ruleFormData.warehouseDate).toISOString()
|
|
|
- : '',
|
|
|
- stuffQty: ruleFormData.itemQuantity,
|
|
|
- remark: ruleFormData.remarks || '',
|
|
|
+ const basePayload: ProductionSafetyFile = {
|
|
|
+ fileName: ruleFormData.fileName,
|
|
|
+ classifyName: ruleFormData.classifyName,
|
|
|
+ fileCode: ruleFormData.fileCode,
|
|
|
+ fileVersion: ruleFormData.fileVersion,
|
|
|
+ fileFormat: ruleFormData.fileFormat,
|
|
|
+ releaseDate: ruleFormData.releaseDate,
|
|
|
+ fileUrl: ruleFormData.fileUrl || undefined,
|
|
|
+ content: ruleFormData.content || undefined,
|
|
|
+ status: ruleFormData.status ?? 1,
|
|
|
};
|
|
|
|
|
|
if (isCreateMode.value) {
|
|
|
- await saveInventory(basePayload);
|
|
|
+ await saveIndustryStandard(basePayload);
|
|
|
ElMessage.success('创建成功');
|
|
|
} else if (isEditMode.value && currentId.value) {
|
|
|
- await updateInventory({
|
|
|
+ await updateIndustryStandard({
|
|
|
id: currentId.value,
|
|
|
...basePayload,
|
|
|
});
|
|
|
@@ -107,7 +209,7 @@
|
|
|
|
|
|
router.back();
|
|
|
} catch (e) {
|
|
|
- console.error('保存物品库存失败:', e);
|
|
|
+ console.error('保存行业标准失败:', e);
|
|
|
ElMessage.error('保存失败,请重试');
|
|
|
}
|
|
|
};
|
|
|
@@ -119,9 +221,42 @@
|
|
|
getDetail();
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ onBeforeUnmount(() => {
|
|
|
+ const editor = editorRef.value;
|
|
|
+ if (editor == null) return;
|
|
|
+ editor.destroy();
|
|
|
+ });
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@use '@/styles/page-details-layout.scss' as *;
|
|
|
-</style>
|
|
|
|
|
|
+ .editor-container {
|
|
|
+ width: 100%;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .content-display {
|
|
|
+ min-height: 200px;
|
|
|
+ padding: 12px;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ }
|
|
|
+
|
|
|
+ .file-display {
|
|
|
+ .file-link {
|
|
|
+ color: #409eff;
|
|
|
+ text-decoration: none;
|
|
|
+ &:hover {
|
|
|
+ text-decoration: underline;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .no-file {
|
|
|
+ color: rgba(0, 0, 0, 0.65);
|
|
|
+ }
|
|
|
+</style>
|