|
|
@@ -0,0 +1,77 @@
|
|
|
+<!-- 报告元数据,封面上的动态字段 -->
|
|
|
+<script setup lang="ts">
|
|
|
+import { defineAsyncComponent, ref, markRaw, type Ref } from "vue";
|
|
|
+import { PlusOutlined } from '@ant-design/icons-vue';
|
|
|
+import type ReportMetaTextInput from './ReportMetaTextInput.vue';
|
|
|
+
|
|
|
+type ComponentType = typeof ReportMetaTextInput;
|
|
|
+
|
|
|
+const components: Ref<ComponentType[]> = ref([]);
|
|
|
+const props: Ref<any[]> = ref([]);
|
|
|
+
|
|
|
+const emits = defineEmits<{
|
|
|
+ (e: "change", data: any[]): void;
|
|
|
+}>();
|
|
|
+
|
|
|
+function addTextComponent() {
|
|
|
+ const comp = markRaw(defineAsyncComponent(() => import('./ReportMetaTextInput.vue') ));
|
|
|
+ components.value.push(comp);
|
|
|
+ props.value.push({
|
|
|
+ name: '',
|
|
|
+ value: ''
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function addDateComponent() {
|
|
|
+ const comp = markRaw(defineAsyncComponent(() => import('./ReportMetaDateInput.vue') ));
|
|
|
+ components.value.push(comp);
|
|
|
+ props.value.push({
|
|
|
+ name: '',
|
|
|
+ value: ''
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleMenuClick(e: {key: string}) {
|
|
|
+ if (e.key == 'text') {
|
|
|
+ addTextComponent();
|
|
|
+ } else if (e.key === 'date') {
|
|
|
+ addDateComponent();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function onMetaCompChange() {
|
|
|
+ emits("change", props.value);
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="dynamic-meta-wrap">
|
|
|
+ <component
|
|
|
+ :is="comp"
|
|
|
+ v-for="(comp, index) in components"
|
|
|
+ :key="index"
|
|
|
+ v-model:data="props[index]"
|
|
|
+ @update:data="onMetaCompChange"
|
|
|
+ />
|
|
|
+ <a-dropdown>
|
|
|
+ <template #overlay>
|
|
|
+ <a-menu @click="handleMenuClick">
|
|
|
+ <a-menu-item key="text">文本</a-menu-item>
|
|
|
+ <a-menu-item key="date">日期</a-menu-item>
|
|
|
+ </a-menu>
|
|
|
+ </template>
|
|
|
+ <a-button>
|
|
|
+ 添加新项
|
|
|
+ <plus-outlined />
|
|
|
+ </a-button>
|
|
|
+ </a-dropdown>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.dynamic-meta-wrap {
|
|
|
+ > * {
|
|
|
+ margin-top: 0.5em;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|