Browse Source

feature 1001687

1. 动态字段选项中支持起止日期选项
2. 动态字段必须要有名称或者值
Kevin Jiang 2 years ago
parent
commit
017baf2afc

+ 1 - 1
src/types/report.types.ts

@@ -122,7 +122,7 @@ export interface ReportCreateRequest {
 export interface ReportMetadataItem {
   name: string;
   value: string;
-  type: 'text' | 'date';
+  type: 'text' | 'date' | 'dateRange';
 }
 
 export interface Chapter {

+ 8 - 0
src/views/report/ReportEditorView.vue

@@ -150,6 +150,14 @@ function onSave() {
       keywordsEl.value?.focus();
       return;
     }
+    if (report.value.metadata) {
+      for (const item of report.value.metadata) {
+        if (item.name == '' || item.value == '') {
+          message.warning("有动态字段的名称或值为空,请填写!")
+          return;
+        }
+      }
+    }
     saveLoading.value = true;
     reportService.save(report.value).then(() => {
       saveLoading.value = false;

+ 15 - 4
src/views/report/components/dynamic-meta/DynamicMeta.vue

@@ -1,7 +1,7 @@
 <!-- 报告元数据,封面上的动态字段 -->
 <script setup lang="ts">
 import { defineAsyncComponent, ref, markRaw, type Ref, type PropType, onMounted } from "vue";
-import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
+import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons-vue';
 import draggable from 'vuedraggable'
 
 import type ReportMetaTextInput from './ReportMetaTextInput.vue';
@@ -29,7 +29,6 @@ const emits = defineEmits<{
 }>();
 
 function addTextComponent(index: number, prop: ReportMetadataItem = { name: '', value: '', type: 'text' }) {
-  // prop = prop || { name: '', value: '', type: 'text' }
   dynamicComponents.value.push({
     id: index,
     component: markRaw(defineAsyncComponent(() => import('./ReportMetaTextInput.vue') )),
@@ -38,7 +37,6 @@ function addTextComponent(index: number, prop: ReportMetadataItem = { name: '',
 }
 
 function addDateComponent(index: number, prop: ReportMetadataItem = { name: '', value: '', type: 'date' }) {
-  // prop = prop || { name: '', value: '', type: 'date' }
   dynamicComponents.value.push({
     id: index,
     component: markRaw(defineAsyncComponent(() => import('./ReportMetaDateInput.vue') )),
@@ -46,12 +44,22 @@ function addDateComponent(index: number, prop: ReportMetadataItem = { name: '',
   });
 }
 
+function addDateRangeComponent(index: number, prop: ReportMetadataItem = { name: '', value: '', type: 'dateRange' }) {
+  dynamicComponents.value.push({
+    id: index,
+    component: markRaw(defineAsyncComponent(() => import('./ReportMetaDateRangeInput.vue') )),
+    prop
+  });
+}
+
 function handleMenuClick(e: {key: string}) {
   const index = dynamicComponents.value.length+1;
   if (e.key == 'text') {
     addTextComponent(index);
   } else if (e.key === 'date') {
     addDateComponent(index);
+  } else if (e.key === 'dateRange') {
+    addDateRangeComponent(index);
   }
 }
 
@@ -80,6 +88,8 @@ onMounted(() => {
         addTextComponent(index, metadataItem);
       } else if (metadataItem.type == 'date') {
         addDateComponent(index, metadataItem);
+      } else if (metadataItem.type == 'dateRange') {
+        addDateRangeComponent(index, metadataItem);
       }
     })
   }
@@ -100,7 +110,7 @@ onMounted(() => {
           </a-col>
           <a-col>
             <a-button type="text" @click="deleteComponent(index)">
-              <template #icon><delete-outlined /></template>
+              <template #icon><minus-circle-outlined /></template>
             </a-button>
           </a-col>
         </a-row>
@@ -111,6 +121,7 @@ onMounted(() => {
         <a-menu @click="handleMenuClick">
           <a-menu-item key="text">文本项</a-menu-item>
           <a-menu-item key="date">日期项</a-menu-item>
+          <a-menu-item key="dateRange">日期范围项</a-menu-item>
         </a-menu>
       </template>
       <a-button>

+ 0 - 5
src/views/report/components/dynamic-meta/ReportMetaDateInput.vue

@@ -6,11 +6,6 @@ import type { Dayjs } from 'dayjs';
 import dayjs from "dayjs";
 import type { ReportMetadataItem } from "@/types/report.types";
 
-// export interface Prop {
-//   name: string;
-//   value: string;
-// }
-
 const props = defineProps({
   data: {
     type: Object as PropType<ReportMetadataItem>,

+ 71 - 0
src/views/report/components/dynamic-meta/ReportMetaDateRangeInput.vue

@@ -0,0 +1,71 @@
+<!-- 报告元数据日期输入类型组件 -->
+
+<script setup lang="ts">
+import { onMounted, ref, type PropType } from "vue";
+import type { Dayjs } from 'dayjs';
+import dayjs from "dayjs";
+import type { ReportMetadataItem } from "@/types/report.types";
+
+const props = defineProps({
+  data: {
+    type: Object as PropType<ReportMetadataItem>,
+    required: true,
+  }
+});
+
+type RangeValue = [Dayjs, Dayjs];
+
+const value = ref<RangeValue>();
+
+onMounted(() => {
+  const [from, to] = props.data.value.split(' ');
+  const dateFrom = dayjs(from);
+  const dateTo = dayjs(to);
+  if (dateFrom.isValid() && dateTo.isValid()) {
+    value.value = [dateFrom, dateTo]
+  }
+});
+
+const emits = defineEmits<{
+  (e: "update:data", data: ReportMetadataItem): void;
+}>();
+
+function onNameChange(e: InputEvent) {
+  change((e.target as HTMLInputElement).value, props.data.value);
+}
+
+function onValueChange(_: Dayjs | string, dateString: [string, string]) {
+  change(props.data.name, dateString.join(' '));
+}
+
+function change(name: string, value: string) {
+  emits("update:data", { name, value, type: props.data.type });
+}
+</script>
+
+<template>
+  <a-row type="flex" style="align-items: center">
+    <a-col class="name-wrap">
+      <a-space>
+        <a-input :value="data.name" @change="onNameChange" placeholder="字段名称" class="name" />
+        <span>:</span>
+      </a-space>
+    </a-col>
+    <a-col flex="1">
+      <a-range-picker v-model:value="value" @change="onValueChange" class="value" />
+    </a-col>
+  </a-row>
+</template>
+
+<style scoped lang="scss">
+.name-wrap {
+  width: 120px;
+
+  .name {
+    width: 100%
+  }
+}
+.value {
+  width: 100%;
+}
+</style>