|
|
@@ -0,0 +1,146 @@
|
|
|
+<!-- 报告模板编辑 -->
|
|
|
+<script setup lang="ts">
|
|
|
+import { onMounted, ref, type Ref } from "vue";
|
|
|
+import { useRoute } from "vue-router";
|
|
|
+import { CompLog } from "@/helpers/log.helper";
|
|
|
+import { ChapterManager } from "@/models/report.model";
|
|
|
+import * as reportTemplateService from "@/services/reportTemplate.service"
|
|
|
+import type { Chapter, ChapterType, ReportMetadataItem, ReportTemplateSave } from "@/types/report.types";
|
|
|
+import { PlusOutlined } from "@ant-design/icons-vue";
|
|
|
+import PageHeader from '@/components/PageHeader.vue';
|
|
|
+import DynamicMeta from '../report/components/dynamic-meta/DynamicMeta.vue';
|
|
|
+import ChapterTypeSelect from "../report/components/ChapterTypeSelect.vue";
|
|
|
+import LogoComponent from "../report/components/LogoComponent.vue";
|
|
|
+import ChapterEditor from "../report/components/ChapterEditor.vue";
|
|
|
+import { message } from "ant-design-vue";
|
|
|
+
|
|
|
+const logError = CompLog.logErr("ReportTemplateEditorView")
|
|
|
+
|
|
|
+const route = useRoute()
|
|
|
+
|
|
|
+const reportTemplate = ref<ReportTemplateSave | null>(null);
|
|
|
+
|
|
|
+// 报告元数据
|
|
|
+const metadata: Ref<ReportMetadataItem[]> = ref([]);
|
|
|
+// 章节类型选择器可见状态
|
|
|
+const chapterTypeSelectVisible = ref(false);
|
|
|
+// 章节管理对象
|
|
|
+const chapterManager = new ChapterManager();
|
|
|
+// 正在保存状态
|
|
|
+const saveLoading = ref(false);
|
|
|
+
|
|
|
+function fetchReportTemplate(id: number) {
|
|
|
+ reportTemplateService.get(id).then((data) => {
|
|
|
+ reportTemplate.value = data;
|
|
|
+ chapterManager.setChapters(reportTemplate.value.chapters)
|
|
|
+ }).catch(logError)
|
|
|
+}
|
|
|
+
|
|
|
+function onMetaChange(data: ReportMetadataItem[]) {
|
|
|
+ console.log('metadata', data)
|
|
|
+ metadata.value = data;
|
|
|
+ if (reportTemplate.value) {
|
|
|
+ reportTemplate.value.metadata = metadata.value;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function onChapterTypeSelected(type: ChapterType) {
|
|
|
+ chapterManager.addChapter(type);
|
|
|
+}
|
|
|
+
|
|
|
+function onChapterChange(index: number, data: Chapter) {
|
|
|
+ chapterManager.setChapter(index, data);
|
|
|
+}
|
|
|
+
|
|
|
+function onChapterMoveUp(index: number) {
|
|
|
+ chapterManager.moveUp(index)
|
|
|
+}
|
|
|
+
|
|
|
+function onChapterMoveDown(index: number) {
|
|
|
+ chapterManager.moveDown(index)
|
|
|
+}
|
|
|
+
|
|
|
+function onChapterRemove(index: number) {
|
|
|
+ chapterManager.remove(index)
|
|
|
+}
|
|
|
+
|
|
|
+function onSave() {
|
|
|
+ if (reportTemplate.value) {
|
|
|
+ saveLoading.value = true
|
|
|
+ reportTemplateService.save(reportTemplate.value).then(() => {
|
|
|
+ message.success("保存成功")
|
|
|
+ saveLoading.value = false
|
|
|
+ }).catch((err) => {
|
|
|
+ logError(err)
|
|
|
+ saveLoading.value = false
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ const id = parseInt(route.params.id as string)
|
|
|
+ if (id) {
|
|
|
+ fetchReportTemplate(id)
|
|
|
+ }
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <PageHeader title="报告模板编辑" />
|
|
|
+ <a-row :gutter="24" v-if="reportTemplate">
|
|
|
+ <a-col :span="12">
|
|
|
+ <div class="metadata-wrap">
|
|
|
+ <a-row type="flex" style="align-items: center">
|
|
|
+ <a-col style="width: 120px; text-align: right;">
|
|
|
+ 报告模板名称:
|
|
|
+ </a-col>
|
|
|
+ <a-col flex="1">
|
|
|
+ <a-input
|
|
|
+ v-model:value="reportTemplate.name"
|
|
|
+ />
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <DynamicMeta v-model:data="reportTemplate.metadata" @change="onMetaChange" />
|
|
|
+ </div>
|
|
|
+ </a-col>
|
|
|
+ <a-col :span="12">
|
|
|
+ <LogoComponent />
|
|
|
+ </a-col>
|
|
|
+ </a-row>
|
|
|
+ <a-divider />
|
|
|
+ <div class="chapter-wrap" v-if="reportTemplate">
|
|
|
+ <ChapterEditor
|
|
|
+ v-for="(item, index) in chapterManager.getChapters()"
|
|
|
+ :key="index"
|
|
|
+ :data="item"
|
|
|
+ :contentEditorVisible="false"
|
|
|
+ @change="onChapterChange(index, $event)"
|
|
|
+ @move-up="onChapterMoveUp(index)"
|
|
|
+ @move-down="onChapterMoveDown(index)"
|
|
|
+ @remove="onChapterRemove(index)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="add-chapter-wrap">
|
|
|
+ <a-button @click="() => chapterTypeSelectVisible = true">
|
|
|
+ <plus-outlined />
|
|
|
+ 添加章节
|
|
|
+ </a-button>
|
|
|
+ </div>
|
|
|
+ <div class="bottom-button-group">
|
|
|
+ <a-space>
|
|
|
+ <a-button type="primary" @click="onSave" :loading="saveLoading">保存</a-button>
|
|
|
+ </a-space>
|
|
|
+ </div>
|
|
|
+ <ChapterTypeSelect @ok="onChapterTypeSelected" v-model:visible="chapterTypeSelectVisible" />
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+
|
|
|
+.add-chapter-wrap {
|
|
|
+ margin-top: 3em;
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-button-group {
|
|
|
+ margin-top: 5em;
|
|
|
+}
|
|
|
+</style>
|