考核心得

表格

普通表格

<template>
  <!---------- 查询表单form begin ----------->
  <a-form class="smart-query-form">
        <a-row class="smart-query-form-row">
            <a-form-item label="关键字" class="smart-query-form-item">
                <a-input style="width: 200px" v-model:value="queryForm.queryKey" placeholder="请输入订单号关键字" />
            </a-form-item>
            <a-form-item class="smart-query-form-item">
                <a-button type="primary" @click="onSearch">
                    <template #icon>
                        <SearchOutlined />
                    </template>
                    查询
                </a-button>
                <a-button @click="resetQuery" class="smart-margin-left10">
                    <template #icon>
                        <ReloadOutlined />
                    </template>
                    重置
                </a-button>
            </a-form-item>
        </a-row>
    </a-form>
    <!---------- 查询表单form end ----------->
    <a-card size="small" :bordered="false" :hoverable="true">
        <!---------- 表格操作行 begin ----------->
        <a-row class="smart-table-btn-block">
            <div class="smart-table-operate-block">
                <a-button @click="showForm" type="primary" size="small" form-id="showForm">
                    <template #icon>
                        <PlusOutlined />
                    </template>
                    新建
                </a-button>
                <a-button @click="confirmBatchDelete" type="primary" danger size="small" :disabled="selectedRowKeyList.length == 0">
                    <template #icon>
                        <DeleteOutlined />
                    </template>
                    批量删除
                </a-button>
            </div>
            <div class="smart-table-setting-block">
                <TableOperator v-model="columns" :tableId="null" :refresh="queryData" />
            </div>
        </a-row>
        <!---------- 表格操作行 end ----------->
  <!---------- 表格 begin ----------->
  <a-table
        size="small"
        :dataSource="tableData"
        :columns="columns"
        rowKey="id"
        bordered
        :loading="tableLoading"
        :pagination="false"
        :row-selection="{ selectedRowKeys: selectedRowKeyList, onChange: onSelectChange }"
    >
      <template #bodyCell="{ text, record, column }">
        <template v-if="column.dataIndex === 'action'">
          <div class="smart-table-operate">
            <a-button @click="showForm(record)" type="link">编辑</a-button>
            <a-button @click="onDelete(record)" danger type="link">删除</a-button>
          </div>
        </template>
      </template>
    </a-table>
    <!---------- 表格 end ----------->
    <div class="smart-query-table-page">
            <a-pagination
                showSizeChanger
                showQuickJumper
                show-less-items
                :pageSizeOptions="PAGE_SIZE_OPTIONS"
                :defaultPageSize="queryForm.pageSize"
                v-model:current="queryForm.pageNum"
                v-model:pageSize="queryForm.pageSize"
                :total="total"
                @change="queryData"
                @showSizeChange="queryData"
                :show-total="(total) => `共${total}条`"
            />
        </div>
        <UnitForm  ref="formRef" @reloadList="queryData"/>
    </a-card>
</template>
<script setup>
import {reactive, ref, onMounted} from 'vue';
import {message, Modal} from 'ant-design-vue';
import {SmartLoading} from '/@/components/framework/smart-loading';
import {unitApi} from '/@/api/business/mes/base/unit-api.js';
import {PAGE_SIZE_OPTIONS} from '/@/constants/common-const';
import {smartSentry} from '/@/lib/smart-sentry';
import TableOperator from '/@/components/support/table-operator/index.vue';
import UnitForm from './unit-form.vue';
import DictSelect from "/@/components/support/dict-select/index.vue";
import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';
// ---------------------------- 表格列 ----------------------------
  const columns = ref([
  {
    title: '单位名称',
    dataIndex: 'name',
    ellipsis: true,
  },
  {
    title: '单位编码',
    dataIndex: 'unitCode',
    ellipsis: true,
  },
  {
    title: '创建时间',
    dataIndex: 'createTime',
    ellipsis: true,
  },
  {
    title: '创建人',
    dataIndex: 'createBy',
    ellipsis: true,
  },
  {
    title: '更新时间',
    dataIndex: 'updateTime',
    ellipsis: true,
  },
  {
    title: '更新人',
    dataIndex: 'updateBy',
    ellipsis: true,
  },
  {
    title: '备注',
    dataIndex: 'remark',
    ellipsis: true,
  },
  {
    title: '操作',
    dataIndex: 'action',
    fixed: 'right',
    width: 90,
  },
]);
// ---------------------------- 查询数据表单和方法 ----------------------------

const queryFormState = {
        queryKey: undefined, //订单编号关键字
        pageNum: 1,
        pageSize: 10,
    };
    // 查询表单form
    const queryForm = reactive({ ...queryFormState });
    // 表格加载loading
    const tableLoading = ref(false);
    // 表格数据
    const tableData = ref([]);
    // 总数
    const total = ref(0);

// 重置查询条件
function resetQuery() {
        let pageSize = queryForm.pageSize;
        Object.assign(queryForm, queryFormState);
        queryForm.pageSize = pageSize;
        queryData();
    }
    // 搜索
function onSearch(){
  queryForm.pageNum = 1;
  queryData();
}
    // 查询数据
async function queryData() {
    tableLoading.value = true;
    try {
      let queryResult = await unitApi.queryPage(queryForm);
      tableData.value = queryResult.data.list;
      total.value = queryResult.data.total;
    } catch (e) {
         smartSentry.captureError(e);
    }finally {
      tableLoading.value = false;
     }

}
onMounted(queryData);

// ---------------------------- 添加/修改 ----------------------------
const formRef = ref();

function showForm(data) {
    formRef.value.show(data);
}

// ---------------------------- 单个删除 ----------------------------
//确认删除
function onDelete(data){
    Modal.confirm({
        title: '提示',
        content: '确定要删除选项吗?',
        okText: '删除',
        okType: 'danger',
        onOk() {
            requestDelete(data);
        },
        cancelText: '取消',
        onCancel() {},
    });
}

//请求删除
async function requestDelete(data){
    SmartLoading.show();
    try {
        let deleteForm = {
            goodsIdList: selectedRowKeyList.value,
        };
        await unitApi.delete(data.id);
        message.success('删除成功');
        queryData();
    } catch (e) {
        smartSentry.captureError(e);
    } finally {
        SmartLoading.hide();
    }
}

// ---------------------------- 批量删除 ----------------------------

// 选择表格行
const selectedRowKeyList = ref([]);

function onSelectChange(selectedRowKeys) {
    selectedRowKeyList.value = selectedRowKeys;
}

// 批量删除
function confirmBatchDelete() {
    Modal.confirm({
        title: '提示',
        content: '确定要批量删除这些数据吗?',
        okText: '删除',
        okType: 'danger',
        onOk() {
            requestBatchDelete();
        },
        cancelText: '取消',
        onCancel() {},
    });
}

//请求批量删除
async function requestBatchDelete() {
    try {
        SmartLoading.show();
        await unitApi.batchDelete(selectedRowKeyList.value);
        message.success('删除成功');
        queryData();
    } catch (e) {
        smartSentry.captureError(e);
    } finally {
        SmartLoading.hide();
    }
}
</script>

对应响应新建编辑表单

<template>
  <a-modal
      :title="form.id ? '编辑' : '添加'"
      :width="800"
      :open="visibleFlag"
      @cancel="onClose"
      :maskClosable="false"
      :destroyOnClose="true"
  >
  <a-form ref="formRef" :model="form" :rules="rules" :label-col="{ span: 5 }" >
    <a-form-item label="单位名称" name="name">
      <a-input style="width: 100%" v-model:value="form.name" placeholder="单位名称" />
    </a-form-item>
    <a-form-item label="单位编码" name="unitCode">
      <a-input style="width: 100%" v-model:value="form.unitCode" placeholder="单位编码" />
    </a-form-item>
    <a-form-item label="备注" name="remark">
      <a-input style="width: 100%" v-model:value="form.remark" placeholder="备注" />
    </a-form-item>
  </a-form>
    <template #footer>
      <a-space>
        <a-button @click="onClose">取消</a-button>
        <a-button type="primary" @click="onSubmit">保存</a-button>
      </a-space>
    </template>
  </a-modal>
</template>
<script setup>
import { reactive, ref, nextTick, defineEmits, defineExpose } from 'vue';
import _ from 'lodash';
import { message } from 'ant-design-vue';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { unitApi } from '/@/api/business/mes/base/unit-api.js';
import { smartSentry } from '/@/lib/smart-sentry';

// ------------------------ 事件 ------------------------
const emits = defineEmits(['reloadList']);

// ------------------------ 显示与隐藏 ------------------------
const visibleFlag = ref(false);

function show(rowData) {
  Object.assign(form, formDefault);
  if (rowData && !_.isEmpty(rowData)) {
    Object.assign(form, rowData);
  }
  visibleFlag.value = true;
  nextTick(() => {
    formRef.value.clearValidate();
  });
}

function onClose() {
  Object.assign(form, formDefault);
  visibleFlag.value = false;
}

// ------------------------ 表单 ------------------------
const formRef = ref();

const formDefault = {
  name: undefined, // 单位名称
  unitCode: undefined, // 单位编码
  remark: undefined, // 备注
};

let form = reactive({ ...formDefault });

const rules = {
  name: [{ required: true, message: '单位名称 必填' }],
};

// 点击确定,验证表单
async function onSubmit() {
  try {
    await formRef.value.validateFields();
    
    // 检查 unitCode 是否为空
    if (!form.unitCode) {
      form.unitCode = await getUnitNo();
    }
    
    save();
  } catch (err) {
    message.error('参数验证错误,请仔细填写表单数据!');
  }
}

// 新建、编辑API
async function save() {
  SmartLoading.show();
  try {
    if (form.id) {
      await unitApi.update(form);
    } else {
      await unitApi.add(form);
    }
    message.success('操作成功');
    emits('reloadList');
    onClose();
  } catch (err) {
    smartSentry.captureError(err);
  } finally {
    SmartLoading.hide();
  }
}

// 暴露方法
defineExpose({
  show,
});

// 获取单位编号
async function getUnitNo() {
  try {
    const response = await unitApi.getUnitNo();
    return response.data; // 假设返回的单位编号在 response.data 中
  } catch (err) {
    smartSentry.captureError(err);
    message.error('获取单位编号失败');
    throw err;
  }
}
</script>

选中组件

<template v-else-if="column.dataIndex === 'standard'">
    <a-tag v-if="record.isSelected" color="blue">选中</a-tag>
</template>
const columns = ref([
  {
    title: '是否选中',
    dataIndex: 'standard',
    fixed: 'right',
    width: 90,
  },
]);
// 查询数据
async function queryData() {
  tableLoading.value = true;
  try {
    // 如果有选中的模板名称,尝试选中对应的记录
    if (selectedTemplateId.value) {
      const selectedRecord = tableData.value.find(item => item.templateName === selectedTemplateId.value);
      if (selectedRecord) {
        selectedRecord.isSelected = true;
        previousSelectedRecord.value = selectedRecord;
      }
    }
  } catch (e) {
    smartSentry.captureError(e);
  } finally {
    tableLoading.value = false;
  }
}
// 点击事件
function handleRowClick(record, showMessage = true) {
  // 清除所有行的选中状态
  tableData.value.forEach(item => (item.isSelected = false));
  // 设置当前行的选中状态为 true
  record.isSelected = true;
  // 将选中的模板ID存储在响应式变量中
  selectedTemplateId.value = record.templateName;
  // 保存到 localStorage
  localStorage.setItem('selectedTemplateName', record.templateName);
  // 更新选中的尺码ID
  selectedSizes.value[record.templateName] = null; // 初始化为null
  // 保存上一次选中的记录
  previousSelectedRecord.value = record;
  // 重新加载数据
  queryData().then(() => {
    // 在新数据加载完成后,恢复之前的选中状态(如果有)
    if (previousSelectedRecord.value) {
      const newSelectedRecord = tableData.value.find(item => item.id === previousSelectedRecord.value.id);
      if (newSelectedRecord) {
        newSelectedRecord.isSelected = true;
      }
    }
  });
  // 根据传入的参数决定是否显示消息
  if (showMessage) {
    message.success('点击成功'); 
  }
}

树形表格

<template>
  <a-card size="small" :bordered="false" :hoverable="true">
    <a-row class="smart-table-btn-block">
            <div class="smart-table-operate-block">
                <a-button size="small" type="primary" @click="showForm({ type: 'add', parentId:0})">
                    <template #icon>
                        <PlusOutlined />
                    </template>
                    新建分类
                </a-button>
            </div>
            <div class="smart-table-setting-block">
                <TableOperator v-model="columns" :tableId="null" :refresh="queryData" />
            </div>
        </a-row>
    <a-table
      :columns="columns"
      :data-source="tableData"
      bordered
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.dataIndex === 'action'">
          <div class="smart-table-operate">
            <a-button type="primary" @click="showForm({ type: 'add', parentId: record.key })">增加子分类</a-button>
            <a-button type="link" @click="showForm({ type: 'edit', data: record })">编辑</a-button>
            <a-button danger type="link" @click="onDelete(record)">删除</a-button>
          </div>
        </template>
      </template>
    </a-table>
    <SeasonForm ref="formRef" @reloadList="queryData"/>
  </a-card>
</template>
<script setup>
import { reactive, ref, onMounted } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { smartSentry } from '/@/lib/smart-sentry';
import { SmartLoading } from '/@/components/framework/smart-loading';
import { seasonApi } from '/@/api/business/mes/base/season-api';
import SeasonForm from './season-form.vue'; 

// 定义表格列
const columns = ref([
  {
    title: '季度名称',
    dataIndex: 'seasonName',
    key: 'seasonName'
  },
  {
    title: '操作',
    dataIndex: 'action',
    fixed: 'right',
    width: '500px', // 设置操作列的宽度为500px
    customHeaderCell: () => ({
      style: {
        textAlign: 'center',
      },
    }),
  },
]);
const queryFormState = {
  queryKey: undefined,
  parentId: undefined,
};
const queryForm = reactive({ ...queryFormState });
// 定义数据源
const tableData = ref([]);

// 定义数据格式化函数
function formatData(data) {
  return data.map(item => {
    return {
      key: item.id,
      parentId:item.parentId||0,
      seasonName: item.seasonName,
      children: item.children ? formatData(item.children) : []
    };
  });
}

async function queryData() {
  try {
    const result = await seasonApi.queryPage({ queryForm });    
    if (result.data) { 
      tableData.value = formatData(result.data);
     // 对 tableData 进行倒序排列
     tableData.value.sort((a, b) => b.seasonName.localeCompare(a.seasonName));
    }
  } catch (error) {
    console.error('请求数据失败:', error);
  }
}
const formRef = ref();
// 显示表单
function showForm(data) {
  if (data.type === 'add') {
    // 增加子分类模式
    formRef.value.show({
      id: null, // 确保 id 为 null 或 undefined
      parentId: data.parentId ? data.parentId : 0, // 如果有父节点,则传递父节点的 id
      type: 'add', // 传递 type 为 'add'
    });
  } else if (data.type === 'edit') {
    // 编辑模式
    formRef.value.show({
      ...data.data,
      id: data.data.key,
      type: 'edit' // 传递 type 为 'edit'
    });
  }
}

// 删除记录
function onDelete(data) {
  Modal.confirm({
    title: '提示',
    content: '确定要删除选项吗?',
    okText: '删除',
    okType: 'danger',
    onOk() {
      requestDelete(data);
    },
    cancelText: '取消',
    onCancel() {},
  });
}
// 请求删除
async function requestDelete(data) {
  SmartLoading.show();
  try {
    await seasonApi.delete(data.key);
    message.success('删除成功');
    queryData();
  } catch (e) {
    smartSentry.captureError(e);
  } finally {
    SmartLoading.hide();
  }
}
onMounted(queryData);
</script>

对应响应新建编辑表单

<template>
  <a-modal
      :title="form.type === 'add' ? '添加' : '编辑'"
      :width="800"
      :open="visibleFlag"
      @cancel="onClose"
      :maskClosable="false"
      :destroyOnClose="true"
  >
    <a-form ref="formRef" :model="form" :rules="rules" :label-col="{ span: 5 }" >
        <a-form-item label="季度名称"  name="seasonName">
          <a-input style="width: 100%" v-model:value="form.seasonName" placeholder="季度名称" />
        </a-form-item>
        <a-form-item label="父级id"  name="parentId">
          <a-input-number style="width: 100%" v-model:value="form.parentId" placeholder="父级id" />
        </a-form-item>
    </a-form>

    <template #footer>
      <a-space>
        <a-button @click="onClose">取消</a-button>
        <a-button type="primary" @click="onSubmit">保存</a-button>
      </a-space>
    </template>
  </a-modal>
</template>
<script setup>
  import { reactive, ref, nextTick } from 'vue';
  import _ from 'lodash';
  import { message } from 'ant-design-vue';
  import { SmartLoading } from '/@/components/framework/smart-loading';
  import { seasonApi } from '/@/api/business/mes/base/season-api';
  import { smartSentry } from '/@/lib/smart-sentry';

  // ------------------------ 事件 ------------------------
  const emits = defineEmits(['reloadList']);

  // ------------------------ 显示与隐藏 ------------------------
  // 是否显示
  const visibleFlag = ref(false);

  function show(rowData) {
    Object.assign(form, formDefault);
    if (rowData && !_.isEmpty(rowData)) {
      Object.assign(form, rowData);
    }
    visibleFlag.value = true;
    nextTick(() => {
      formRef.value.clearValidate();
    });
  }

  function onClose() {
    Object.assign(form, formDefault);
    visibleFlag.value = false;
  }

  // ------------------------ 表单 ------------------------

  // 组件ref
  const formRef = ref();

  const formDefault = {
    id: undefined, // 确保 id 为 undefined
    seasonName: undefined, //季度名称
    parentId: undefined, //父级Id
  };

  let form = reactive({ ...formDefault });

  const rules = {
    seasonName: [{ required: true, message: '季度名称 必填' }],
  };

  // 点击确定,验证表单
  async function onSubmit() {
    try {
      await formRef.value.validateFields();
      save();
    } catch (err) {
      message.error('参数验证错误,请仔细填写表单数据!');
    }
  }

  // 新建、编辑API
  async function save() {
    SmartLoading.show();
    try {
      console.log(form);
      
      if (form.id) {
        await seasonApi.update(form);
      } else {
        await seasonApi.add(form);
      }
      message.success('操作成功');
      emits('reloadList');
      onClose();
    } catch (err) {
      smartSentry.captureError(err);
    } finally {
      SmartLoading.hide();
    }
  }

  defineExpose({
    show,
  });
</script>


考核心得
http://localhost:8090//archives/kao-he-xin-de
作者
林依琪
发布于
2025年03月03日
许可协议