Jay
2024-09-24 c627685b89bc8aedf71e8d02411bc66d8f5bb6e3
指标定义
已添加4个文件
883 ■■■■■ 文件已修改
src/views/data/ind/item/AtomIndDefineForm.vue 263 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/ind/item/DerIndDefineForm.vue 329 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/ind/item/index.vue 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/ind/item/selectItemType.vue 96 ●●●●● 补丁 | 查看 | 原始文档 | 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>