src/views/data/ind/item/AtomIndDefineForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/data/ind/item/DerIndDefineForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/data/ind/item/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/data/ind/item/selectItemType.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/views/data/ind/item/AtomIndDefineForm.vue
对比新文件 @@ -0,0 +1,263 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle" width="55%"> <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="指标编码" prop="itemNo"> <el-input v-model="formData.itemNo" disabled/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="指标名称" prop="itemName"> <el-input v-model="formData.itemName" placeholder="请输入指标名称"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="指标分类" prop="itemCategory"> <el-select v-model="formData.itemCategory" clearable placeholder="请选择指标分类"> <el-option v-for="item in dataCategoryList" :key="item.id" :label="item.label" :value="item.id + ''" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="时间粒度" prop="timeGranularity"> <el-select v-model="formData.timeGranularity" placeholder="请选择"> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.TIME_GRANULARITY)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="8"> <el-form-item label="指标精度" prop="precision"> <el-input v-model="formData.precision"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="转换系数" prop="coefficient"> <el-input v-model="formData.coefficient"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="数量单位" prop="unit"> <el-input v-model="formData.unit"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="备注" prop="remark"> <el-input v-model="formData.remark" type="textarea" maxlength="100"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="数据集" prop="atomItem.dataSet"> <el-select v-model="formData.atomItem.dataSet" clearable placeholder="请选择数据集" @change="handleDataSetChange($event)"> <el-option v-for="item in dataSetList" :key="item.id" :label="item.name" :value="item.id + ''" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="使用字段" prop="atomItem.usingField"> <el-select v-model="formData.atomItem.usingField" clearable placeholder="请选择字段"> <el-option v-for="item in dataSetFieldList" :key="item.id" :label="item.fieldCode" :value="item.id + ''" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="统计方式" prop="statFunc"> <el-select v-model="formData.atomItem.statFunc" placeholder="请选择"> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.STAT_FUNC)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> <script lang="ts" setup> import {DICT_TYPE, getStrDictOptions} from '@/utils/dict' import * as ItemApi from '@/api/data/ind/item/item' import * as DataSetApi from '@/api/data/ind/data/data.set' import * as DataSetFieldApi from '@/api/data/ind/data/data.field' import * as CategoryApi from '@/api/data/ind/category/index' defineOptions({name: 'IndDataSetForm'}) const {t} = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 let formData = ref({ id: undefined, itemNo: '', itemName: '', itemType: '', itemCategory: '', coefficient: '', precision: '', businessType: '', timeRange: '', timeGranularity: '', remark: '', atomItem:{ dataSource:'', dataSet: '', usingField: '', statFunc: '' } }) const validateAsNumber = (rule, value, callback) => { const regex = /^(\-|\+)?\d+(\.\d+)?$/; if (!regex.test(value)) { callback(new Error('请输入数字!')); } } const formRules = reactive({ itemName: [{required: true, message: '指标名称不能为空', trigger: 'blur'}], itemCategory: [{required: true, message: '指标分类不能为空', trigger: 'blur'}], precision: [{validator: validateAsNumber, trigger: 'blur' }], coefficient: [{validator: validateAsNumber, trigger: 'blur' }], "atomItem.dataSet": [{required: true, message: '数据集不能为空', trigger: 'blur'}], "atomItem.usingField":[{required: true, message: '使用字段不能为空', trigger: 'blur'}] }) const formRef = ref() // 表单 Ref const dataSetList = ref([] as DataSetApi.DataSetVO[]) const dataSetFieldList = ref([] as DataSetFieldApi.DataSetFieldVO[]) const dataCategoryList = ref([]) /** 打开弹窗 */ const open = async (type: string, id?: string) => { dialogVisible.value = true dialogTitle.value = '原子指标' formType.value = type resetForm() // 加载数据源列表 dataSetList.value = await DataSetApi.getDataSetList() dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() // 修改时,设置数据 if (id) { formLoading.value = true try { formData.value = await ItemApi.getItem(id) if(formData.value.atomItem.dataSet !== null){ const queryParams = reactive({ dataSetId: formData.value.atomItem.dataSet, }) dataSetFieldList.value = (await DataSetFieldApi.getDataSetFieldPage(queryParams)).list } } finally { formLoading.value = false } } } defineExpose({open}) // 提供 open 方法,用于打开弹窗 /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { // 校验表单 if (!formRef) return const valid = await formRef.value.validate() if (!valid) return // 提交请求 formLoading.value = true try { formData.value.itemType = 'ATOM' for (let index in dataSetList.value){ if(formData.value.atomItem.dataSet === dataSetList.value[index].id){ formData.value.atomItem.dataSource = dataSetList.value[index].dataSource } } const data = formData.value as ItemApi.ItemVO if (formType.value === 'create') { await ItemApi.createItem(data) message.success(t('common.createSuccess')) } else { await ItemApi.updateItem(data) message.success(t('common.updateSuccess')) } dialogVisible.value = false // 发送操作成功的事件 emit('success') } finally { formLoading.value = false } } /** 重置表单 */ const resetForm = () => { formData.value = { id: '', itemNo: '', itemName: '', itemType: '', itemCategory: '', coefficient: '', precision: '', businessType: '', timeRange: '', timeGranularity: '', remark: '', atomItem:{ dataSource:'', dataSet: '', usingField: '', statFunc: '' } } dataSetFieldList.value = [] formRef.value?.resetFields() } async function handleDataSetChange(event) { if (event !== null && event !== undefined) { const queryParams = reactive({ dataSetId: event, }) dataSetFieldList.value = (await DataSetFieldApi.getDataSetFieldPage(queryParams)).list } } </script> src/views/data/ind/item/DerIndDefineForm.vue
对比新文件 @@ -0,0 +1,329 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle" width="55%"> <el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="原子指标" prop="atomItem.id"> <el-select v-model="selected" clearable placeholder="请选择原子指标" @change="handleChange($event)"> <el-option v-for="item in atomItemList" :key="item.id" :label="item.itemNo" :value="item.id" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="原子指标名称" prop="atomItem.itemName"> <el-input v-model="formData.atomItem.itemName" disabled/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="指标编码" prop="itemNo"> <el-input v-model="formData.itemNo" disabled/> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="指标名称" prop="itemName"> <el-input v-model="formData.itemName"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="指标分类" prop="itemCategory"> <el-select v-model="formData.itemCategory" clearable placeholder="请选择指标分类"> <el-option v-for="item in dataCategoryList" :key="item.id" :label="item.label" :value="item.id + ''" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="时间粒度" prop="timeGranularity"> <el-select v-model="formData.timeGranularity" placeholder="请选择"> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.TIME_GRANULARITY)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="8"> <el-form-item label="指标精度" prop="precision"> <el-input v-model="formData.precision"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="转换系数" prop="coefficient"> <el-input v-model="formData.coefficient"/> </el-form-item> </el-col> <el-col :span="6"> <el-form-item label="数量单位" prop="unit"> <el-input v-model="formData.unit"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="20"> <el-form-item label="备注" prop="remark"> <el-input v-model="formData.remark" type="textarea" maxlength="100"/> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="时间标识" prop="timeLabel"> <el-select v-model="formData.derItem.timeLabel" clearable placeholder="请选择时间标识"> <el-option v-for="item in dataSetFieldList" :key="item.id" :label="item.fieldCode" :value="item.id + ''" /> </el-select> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="时间限定" prop="timeLimit"> <el-select v-model="formData.timeLimit" placeholder="请选择" @change="handleTimeLimitChange($event)"> <el-option v-for="dict in getStrDictOptions(DICT_TYPE.TIME_LIMIT)" :key="dict.value" :label="dict.label" :value="dict.value" /> </el-select> </el-form-item> </el-col> </el-row> <el-row v-if="showTimeChange"> <el-col :span="12"> <el-form-item label="开始时间" prop="timeStart"> <el-date-picker v-model="formData.derItem.timeStart" type="datetime" placeholder="请选择开始时间" /> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="结束时间" prop="timeEnd"> <el-date-picker v-model="formData.derItem.timeEnd" type="datetime" placeholder="请选择结束时间" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="分析维度" prop="dimension"> <el-select v-model="formData.derItem.dimension" clearable placeholder="请选择分析维度" multiple> <el-option v-for="item in dataSetFieldList" :key="item.id" :label="item.fieldCode" :value="item.id + ''" /> </el-select> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <el-button :="formLoading" type="primary" @click="submitForm">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> </template> </Dialog> </template> <script lang="ts" setup> import {DICT_TYPE, getStrDictOptions} from '@/utils/dict' import * as DataSetApi from '@/api/data/ind/data/data.set' import * as ItemApi from '@/api/data/ind/item/item' import {CommonStatusEnum} from '@/utils/constants' import * as DataSourceConfigApi from "@/api/infra/dataSourceConfig"; import {PageParam} from "@/api/data/ind/item/item"; import * as CategoryApi from "@/api/data/ind/category"; import * as DataSetFieldApi from "@/api/data/ind/data/data.field"; defineOptions({name: 'IndDataSetForm'}) const {t} = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 let formData = ref({ id: undefined, itemNo: '', itemName: '', itemType: '', itemCategory: '', coefficient: '', precision: '', businessType: '', timeRange: '', timeGranularity: '', atomItem: { id: '', itemNo: '', itemName: '', }, derItem: { atomItemId: '', timeLabel: '', timeLimit: '', timeStart: '', timeEnd: '', dimension: '' } }) const queryParams = ref({ itemType: 'ATOM' }) const validateAsNumber = (rule, value, callback) => { const regex = /^(\-|\+)?\d+(\.\d+)?$/; if (!regex.test(value)) { callback(new Error('请输入数字!')); } } const formRules = reactive({ itemName: [{required: true, message: '指标名称不能为空', trigger: 'blur'}], itemCategory: [{required: true, message: '指标类型不能为空', trigger: 'blur'}], precision: [{validator: validateAsNumber, trigger: 'blur' }], coefficient: [{validator: validateAsNumber, trigger: 'blur' }], "atomItem.id": [{required: true, message: '原子指标不能为空', trigger: 'blur'}] }) const formRef = ref() // 表单 Ref const dataSourceList = ref([] as DataSourceConfigApi.DataSourceConfigVO[]) const atomItemList = ref([] as ItemApi.ItemVO[]) const selected = ref(null) const showTimeChange = ref(false) const dataCategoryList = ref([] as CategoryApi.IndItemCategoryVO[]) const dataSetFieldList = ref([] as DataSetFieldApi.DataSetFieldVO[]) /** 打开弹窗 */ const open = async (type: string, id?: string) => { dialogVisible.value = true dialogTitle.value = '派生指标' formType.value = type resetForm() // 加载数据源列表 dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() atomItemList.value = await ItemApi.getItemList(queryParams) selected.value = null // 修改时,设置数据 if (id) { formLoading.value = true try { formData.value = await ItemApi.getItem(id) } finally { formLoading.value = false } } } defineExpose({open}) // 提供 open 方法,用于打开弹窗 /** 提交表单 */ const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 const submitForm = async () => { // 校验表单 if (!formRef) return const valid = await formRef.value.validate() if (!valid) return // 提交请求 formLoading.value = true try { formData.value.itemType = 'DER' formData.value.derItem.atomItemId = formData.value.atomItem.id if(formData.value.derItem.dimension.length > 0){ let dimension = '' for (let index in formData.value.derItem.dimension){ dimension = dimension + formData.value.derItem.dimension[index] + ',' } formData.value.derItem.dimension = dimension.substring(0, dimension.length - 1) } const data = formData.value as ItemApi.ItemVO if (formType.value === 'create') { await ItemApi.createItem(data) message.success(t('common.createSuccess')) } else { await ItemApi.updateItem(data) message.success(t('common.updateSuccess')) } dialogVisible.value = false // 发送操作成功的事件 emit('success') } finally { formLoading.value = false } } /** 重置表单 */ const resetForm = () => { formData.value = { id: undefined, itemNo: '', itemName: '', itemType: '', itemCategory: '', coefficient: '', precision: '', businessType: '', timeRange: '', timeGranularity: '', remark: '', atomItem: { id: '', itemNo: '', itemName: '', }, derItem: { atomItemId: '', timeLabel: '', timeLimit: '', timeStart: '', timeEnd: '', dimension: '' } } } async function handleChange(event) { if (event !== null && event !== undefined) { const itemData = await ItemApi.getItem(event) formData.value.atomItem.itemName = itemData.itemName formData.value.atomItem.id = itemData.atomItem.id const queryParams = reactive({ dataSetId: itemData.atomItem.dataSet, }) dataSetFieldList.value = (await DataSetFieldApi.getDataSetFieldPage(queryParams)).list } } function handleTimeLimitChange(event) { showTimeChange.value = event === 'CUSTOM'; } </script> src/views/data/ind/item/index.vue
对比新文件 @@ -0,0 +1,195 @@ <template> <!-- 搜索工作栏 --> <ContentWrap> <el-form ref="queryFormRef" :inline="true" :model="queryParams" class="-mb-15px" label-width="68px"> <el-form-item label="指标编码" prop="name"> <el-input v-model="queryParams.itemNo" class="!w-240px" clearable placeholder="请输入指标编码" @keyup.enter="handleQuery"/> </el-form-item> <el-form-item label="指标名称" prop="name"> <el-input v-model="queryParams.itemName" class="!w-240px" clearable placeholder="请输入指标名称" @keyup.enter="handleQuery"/> </el-form-item> <el-form-item> <el-button @click="handleQuery"> <Icon class="mr-5px" icon="ep:search"/> 搜索 </el-button> <el-button @click="resetQuery"> <Icon class="mr-5px" icon="ep:refresh"/> 重置 </el-button> <el-button v-hasPermi="['data:ind-item:create']" plain type="primary" @click="openForm('create')" > <Icon class="mr-5px" icon="ep:plus"/> 新增 </el-button> </el-form-item> </el-form> </ContentWrap> <!-- 列表 --> <ContentWrap> <el-table v-loading="loading" :data="list"> <el-table-column prop="itemNo" label="指标编码" header-align="center" align="center" min-width="80"/> <el-table-column prop="itemName" label="指标名称" header-align="center" align="center" min-width="120"/> <el-table-column prop="itemCategoryName" label="指标分类" header-align="center" align="center" min-width="100"/> <el-table-column prop="itemType" label="指标类型" header-align="center" align="center" min-width="60"> <template #default="scope"> <dict-tag :type="DICT_TYPE.ITEM_TYPE" :value="scope.row.itemType" /> </template> </el-table-column> <el-table-column prop="coefficient" label="系数" header-align="center" align="center" min-width="60"/> <el-table-column prop="precision" label="指标精度" header-align="center" align="center" min-width="60"/> <el-table-column prop="timeGranularity" label="时间粒度" header-align="center" align="center" min-width="40"> <template #default="scope"> <dict-tag :type="DICT_TYPE.TIME_GRANULARITY" :value="scope.row.timeGranularity" /> </template> </el-table-column> <el-table-column :formatter="dateFormatter" align="center" label="创建时间" prop="createTime" width="180"/> <el-table-column align="center" label="操作"> <template #default="scope"> <el-button v-hasPermi="['data:ind-item:update']" link type="primary" @click="openForm('update', scope.row)"> 修改 </el-button> <el-button v-hasPermi="['data:ind-item:delete']" link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <Pagination v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNo" :total="total" @pagination="getList" /> </ContentWrap> <!-- 表单弹窗:添加/修改 --> <AtomIndDefineForm ref="atomFormRef" @success="getList" /> <DerIndDefineForm ref="derFormRef" @success="getList" /> <CalIndDefineForm ref="calFormRef" @success="getList" /> <SelectItemType ref="itemTypeSel"/> </template> <script lang="ts" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' import * as DataSetApi from '@/api/data/ind/data/data.set' import AtomIndDefineForm from './AtomIndDefineForm.vue' import DerIndDefineForm from './DerIndDefineForm.vue' import CalIndDefineForm from './CalIndDefineForm.vue' import SelectItemType from './selectItemType.vue' import download from '@/utils/download' import * as ItemApi from '@/api/data/ind/item/item' import * as CategoryApi from "@/api/data/ind/category"; defineOptions({ name: 'IndDataSet' }) const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 const dataCategoryList = ref([] as CategoryApi.IndItemCategoryVO[]) const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref([]) // 字典表格数据 const queryParams = reactive({ pageNo: 1, pageSize: 10, itemNo: '', itemName: '', itemType: '', itemCategory: '' }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 /** 查询字典类型列表 */ const getList = async () => { loading.value = true try { const data = await ItemApi.getItemPage(queryParams) list.value = data.list total.value = data.total dataCategoryList.value = await CategoryApi.getCategoryListAllSimple() } finally { loading.value = false } } /** 搜索按钮操作 */ const handleQuery = () => { queryParams.pageNo = 1 getList() } /** 重置按钮操作 */ const resetQuery = () => { queryFormRef.value.resetFields() handleQuery() } /** 添加/修改操作 */ const atomFormRef = ref() const derFormRef = ref() const calFormRef = ref() const itemTypeSel = ref() const openForm = (type: string, row) => { if(row !== null && row !==undefined){ if(row.itemType === 'ATOM'){ if (row.id){ atomFormRef.value.open(type,row.id) } }else if(row.itemType === 'CAL'){ if (row.id){ calFormRef.value.open(type,row.id) } }else if(row.itemType === 'DER'){ if (row.id){ derFormRef.value.open(type,row.id) } } }else { itemTypeSel.value.open(type) } } /** 删除按钮操作 */ const handleDelete = async (id: number) => { try { // 删除的二次确认 await message.delConfirm() // 发起删除 await ItemApi.deleteItem(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() } catch {} } /** 初始化 **/ onMounted(() => { getList() }) </script> src/views/data/ind/item/selectItemType.vue
对比新文件 @@ -0,0 +1,96 @@ <template> <Dialog v-model="dialogVisible" :title="dialogTitle" width="47%"> <div class="card" @click="openForm('ATOM')"> <img src="../img/ATOM.png" alt="Card Image" class="card-img"/> <div class="card-body"> <p class="card-title-text">{{ "原子指标" }}</p> <p class="card-text">{{ "从0开始创建一个新指标" }}</p> </div> </div> <div class="card" @click="openForm('DER')"> <img src="../img/DER.png" alt="Card Image" class="card-img"/> <div class="card-body"> <p class="card-title-text">{{ "派生指标" }}</p> <p class="card-text">{{ "基于单个原子指标通过条件过滤派生出的新指标" }}</p> </div> </div> <div class="card" @click="openForm('CAL')"> <img src="../img/CAL.png" alt="Card Image" class="card-img"/> <div class="card-body"> <p class="card-title-text">{{ "复合指标" }}</p> <p class="card-text">{{ "基于一组原子指标通过条件过滤派生出的新指标" }}</p> </div> </div> </Dialog> <AtomIndDefineForm ref="atomFormRef" @success="getList" /> <DerIndDefineForm ref="derFormRef" @success="getList" /> <CalIndDefineForm ref="calFormRef" @success="getList" /> </template> <script lang="ts" setup> import * as DataSetApi from '@/api/data/ind/data/data.set' import AtomIndDefineForm from './AtomIndDefineForm.vue' import DerIndDefineForm from './DerIndDefineForm.vue' import CalIndDefineForm from './CalIndDefineForm.vue' defineOptions({ name: 'IndDataSetForm' }) const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 const dialogVisible = ref(false) // 弹窗的是否展示 const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 /** 打开弹窗 */ const open = async (type: string) => { dialogVisible.value = true dialogTitle.value = t('action.' + type) formType.value = type } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 const atomFormRef = ref() const derFormRef = ref() const calFormRef = ref() const openForm = (category: string) => { if(category === 'ATOM'){ atomFormRef.value.open("create",null) }else if(category === 'DER'){ derFormRef.value.open("create",null) }else if(category === 'CAL'){ calFormRef.value.open("create",null) } } </script> <style scoped> .card { width: 25vh; margin: 10px 16px; display: inline-block; vertical-align: top; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); height: 30vh; cursor: pointer; } .card-img { width: 100%; height: 150px; object-fit: cover; } .card-body { padding: 10px; text-align: center; } .card-title-text{ font-size: larger; } .card-text { font-size: smaller; margin: 0; } </style>