Vben 管理者の自己学習記録 - モックを使用してデータをシミュレートし、API ジョイント デバッグ インターフェイスをシミュレートします (継続的に更新されます...)

Vben Admin - モックを使用してデータをシミュレートし、API ジョイント デバッグ インターフェイスをシミュレートします

データモックと共同デバッグ関連の概念と使用法

演習 - 前の表に基づいて、モックを使用してデータをシミュレートし、元の無効なデータを置き換え、API の新規追加、表示、変更、削除を行い、シンプルで完全な追加、削除、変更、確認ページを実装するためのロジックを追加します。

/mock フォルダーの下に table フォルダーを追加し、その中に tableMock.ts を追加します。

ここに画像の説明を挿入します

/mock/table/tableMock.ts

import {
    
     time } from 'console';
import {
    
     MockMethod } from 'vite-plugin-mock';
import {
    
     resultSuccess, resultError, requestParams, getRequestToken } from '../_util';

const tableListData = {
    
    
  pager: {
    
    
    list: [
      {
    
    
        contno: '610964224475996443',
        name: '张三',
        sex: '0',
        dt: '20200701',
        age: '22',
        tel: '13789890909',
        address: '北京市北京小区',
      },
      {
    
    
        contno: '610964224475996442',
        name: '李四',
        sex: '1',
        dt: '20230507',
        age: '27',
        tel: '15477778888',
        address: '大连市大连小区',
      },
      {
    
    
        contno: '610964224475996445',
        name: '王五',
        sex: '0',
        dt: '20221001',
        age: '26',
        tel: '15477778888',
        address: '大连市大连小区',
      },
      {
    
    
        contno: '610964224475996446',
        name: '小明',
        sex: '0',
        dt: '20220701',
        age: '25',
        tel: '15477778888',
        address: '大连市大连小区',
      },
      {
    
    
        contno: '610964224475996447',
        name: '小红',
        sex: '1',
        dt: '20180808',
        age: '28',
        tel: '15477778888',
        address: '大连市大连小区',
      },
    ],
  },
};

export default [
  {
    
    
    url: '/basic-api/table/getListData',
    timeout: 200,
    method: 'get',
    response: () => {
    
    
      return resultSuccess(tableListData);
    },
  },
  {
    
    
    url: '/basic-api/table/addListData',
    timeout: 1000,
    method: 'post',
    response: (request: requestParams) => {
    
    
      tableListData.pager.list.push(request.body);
      return resultSuccess({
    
    });
    },
  },
  {
    
    
    url: '/basic-api/table/editListData',
    timeout: 1000,
    method: 'post',
    response: (request: requestParams) => {
    
    
      let list: any[] = [];
      for (let item of tableListData.pager.list) {
    
    
        console.log('item', item);

        if (request.body.contno === item.contno) {
    
    
          list.push(request.body);
        } else {
    
    
          list.push(item);
        }
      }
      tableListData.pager.list = list;
      return resultSuccess({
    
    });
    },
  },
  {
    
    
    url: '/basic-api/table/delListData',
    timeout: 1000,
    method: 'post',
    response: (request: requestParams) => {
    
    
      let list: any[] = [];
      for (let item of tableListData.pager.list) {
    
    
        console.log('item', item);

        if (request.body.contno === item.contno) {
    
    
        } else {
    
    
          list.push(item);
        }
      }
      tableListData.pager.list = list;
      return resultSuccess({
    
    });
    },
  },
] as MockMethod[];
関連する API を /src/api/table に追加します

ここに画像の説明を挿入します
/src/api/table/tableApi.ts

import {
    
     defHttp } from '/@/utils/http/axios';

enum Api {
    
    
  LIST_DATA = '/table/getListData',
  ADD_DATA = '/table/addListData',
  EDIT_DATA = '/table/editListData',
  DEL_DATA = '/table/delListData',
}

/**
 * @description: Get sample list value
 */

// export const printSignIssue = (params) =>
//   defHttp.post({
    
    
//     url: Api.PRINT_AMT,
//     params,
//   });
// table列表
export const getListDataApi = (params) =>
  defHttp.get({
    
    
    url: Api.LIST_DATA,
    params,
  });

// 新增
export const addListDataApi = (params) =>
  defHttp.post({
    
    
    url: Api.ADD_DATA,
    params,
  });

// 编辑
export const editListDataApi = (params) =>
  defHttp.post({
    
    
    url: Api.EDIT_DATA,
    params,
  });

// 删除
export const delListDataApi = (params) =>
  defHttp.post({
    
    
    url: Api.DEL_DATA,
    params,
  });
知らせ:

ページでモックと API を使用する前に、まず /src/settings/componentSetting.ts で応答後の処理構成を変更する必要があります。これまでにこれを設定したことがなかったので、テーブル コンポーネントの useTable インターフェイスは、componentSetting でブロックされました。 ts
ここに画像の説明を挿入します

export default {
    
    
  // basic-table setting
  table: {
    
    
    // Form interface request general configuration
    // support xxx.xxx.xxx
    fetchSetting: {
    
    
      // The field name of the current page passed to the background
      pageField: 'page',
      // The number field name of each page displayed in the background
      sizeField: 'pageSize',
      // Field name of the form data returned by the interface
      // listField: 'items',
      
      // 这里要和 mock 和 api 返回的数据字段匹配
      listField: 'pager.list',
      
      // Total number of tables returned by the interface field name
      totalField: 'total',
    },
    // Number of pages that can be selected
    pageSizeOptions: ['10', '50', '80', '100'],
    // Default display quantity on one page
    defaultPageSize: 10,
    // Default Size
    defaultSize: 'middle',
    // Custom general sort function
    defaultSortFn: (sortInfo: SorterResult) => {
    
    
      const {
    
     field, order } = sortInfo;
      if (field && order) {
    
    
        return {
    
    
          // The sort field passed to the backend you
          field,
          // Sorting method passed to the background asc/desc
          order,
        };
      } else {
    
    
        return {
    
    };
      }
    },
    // Custom general filter function
    defaultFilterFn: (data: Partial<Recordable<string[]>>) => {
    
    
      return data;
    },
  },
  // scrollbar setting
  scrollbar: {
    
    
    // Whether to use native scroll bar
    // After opening, the menu, modal, drawer will change the pop-up scroll bar to native
    native: false,
  },
};
前のテーブル演習で API を追加して使用します。注: 新しい追加、編集、表示はすべて、Drawer コンポーネントを使用してポップアップするように変更されました。AEVDrawerPage.vue を追加しました。これは、前回の引き出しの練習。

ここに画像の説明を挿入します
過去の関連記録:

データ.ts

import {
    
     FormProps, FormSchema } from '/@/components/Form';
import {
    
     BasicColumn } from '/@/components/Table';
import {
    
     formatToDate } from '/@/utils/dateUtil';
import {
    
     Switch } from 'ant-design-vue';
import {
    
     ref, h, computed } from 'vue';

type sexOptionType = [{
    
     label: string; value: string }, {
    
     label: string; value: string }];

const sexOption: sexOptionType = [
  {
    
     value: '0', label: '男' },
  {
    
     value: '1', label: '女' },
];

// 配置表格SearchForm字段
export const formConfig: Partial<FormProps> = {
    
    
  labelWidth: 120,
  actionColOptions: {
    
    
    span: 25,
  },
  //自动展开行
  autoAdvancedLine: 1,
  showAdvancedButton: true,

  baseColProps: {
    
    
    span: 8,
  },
  schemas: [
    {
    
    
      field: 'contno',
      label: '承兑协议号',
      component: 'Input',
      defaultValue: '',
      componentProps: ({
    
     formModel }) => {
    
    
        return {
    
    
          style: {
    
     width: '100%', textAlign: 'left' },
          onInput: (e) => {
    
    
            formModel.contno = formModel.contno.replace(/[^\w-\/]/gi, '');
          },
        };
      },
    },
    {
    
    
      field: 'name',
      label: '姓名',
      component: 'Input',
    },
    {
    
    
      field: 'sex',
      label: '性别',
      component: 'Select',
      componentProps: {
    
    
        options: sexOption,
      },
    },
    {
    
    
      field: 'dt',
      label: '出生日期',
      component: 'DatePicker',
      componentProps: {
    
    
        style: {
    
    
          width: '100%',
        },
        valueFormat: 'YYYYMMDD',
      },
    },
    {
    
    
      field: 'age',
      label: '年龄',
      component: 'InputNumber',
      componentProps: {
    
    
        style: {
    
    
          width: '100%',
        },
      },
    },
  ],
};

// 配置表格表头字段
export const columns: BasicColumn[] = [
  {
    
    
    title: '承兑协议号',
    dataIndex: 'contno',
    // ifShow:false
    width: 200,
  },
  {
    
    
    title: '姓名',
    width: 200,
    dataIndex: 'name',
    // helpMessage:'aaa',
    // edit:true
  },
  {
    
    
    title: '性别',
    width: 200,
    dataIndex: 'sex',
    customRender: function (text) {
    
    
      console.log('text', text);
      return text.text === '0' ? '男' : '女';
    },
    // customRender:({record}) => {
    
    
    //   console.log(record)
    //   return h(Switch,{checked:record.sex == '0'},)
    // }
  },
  {
    
    
    title: '出生日期',
    width: 200,
    dataIndex: 'dt',
    customRender: function (text) {
    
    
      return formatToDate(text.text);
    },
  },
  {
    
    
    title: '年龄',
    width: 200,
    dataIndex: 'age',
  },
  {
    
    
    title: '电话',
    width: 200,
    dataIndex: 'tel',
  },
  {
    
    
    title: '住址',
    width: 200,
    dataIndex: 'address',
  },
];

export const schemasView: FormSchema[] = [
  {
    
    
    field: 'divider-bill',
    component: 'Divider',
    label: '信息',
    colProps: {
    
    
      span: 24,
    },
  },
  {
    
    
    field: 'contno',
    component: 'Input',
    label: '承兑协议号',
    required: true,
    defaultValue: '',
    componentProps: ({
    
     formModel }) => {
    
    
      return {
    
    
        style: {
    
     width: '100%', textAlign: 'left' },
        oninput: (e) => {
    
    
          // formModel.contno = formModel.contno.replace(/[^\w\/]/ig, '');
        },
      };
    },
    dynamicRules: () => {
    
    
      return [
        {
    
    
          required: true,
          validator: (_, value) => {
    
    
            if (!value) {
    
    
              return Promise.reject('请输入承兑协议号');
            }
          },
        },
      ];
    },
  },
  {
    
    
    field: 'name',
    component: 'Input',
    label: '姓名',
    required: true,
  },
  {
    
    
    field: 'sex',
    component: 'Select',
    label: '性别',
    required: true,
    componentProps: {
    
    
      options: sexOption,
    },
  },
  {
    
    
    field: 'dt',
    component: 'DatePicker',
    label: '出生日期',
    required: true,
    componentProps: {
    
    
      style: {
    
     width: '100%' },
      valueFormat: 'YYYYMMDD',
    },
  },
  {
    
    
    field: 'age',
    component: 'InputNumber',
    label: '年龄',
    required: true,
    componentProps: {
    
    
      style: {
    
     width: '100%' },
      step: 1,
      min: 0,
      max: 150,
    },
  },
  {
    
    
    label: '电话',
    field: 'tel',
    component: 'Input',
    required: true,
    dynamicRules: ({
    
     values }) => {
    
    
      if (values.tel !== undefined) {
    
    
        if (values.tel.indexOf('-') > 0) {
    
    
          return [
            {
    
    
              required: true,
              trigger: 'change',
              message: '请输入正确的号码',
              pattern: /(^\d{4}-\d{7}$)|(^\d{3}-\d{8}$)/,
            },
          ];
        } else {
    
    
          return [
            {
    
    
              required: true,
              trigger: 'change',
              message: '请输入正确的号码',
              pattern: /^1[3|4|5|7|8][0-9]{9}$/,
            },
          ];
        }
      } else {
    
    
        return [{
    
     required: true, message: '请输入电话' }];
      }
    },
  },
  {
    
    
    field: 'address',
    component: 'InputTextArea',
    label: '住址',
    required: true,
  },
];

// 姓名
// 性别
// 出生日期
// 年龄
// 电话    tel
// 住址    address

// 表单数据
export function initData() {
    
    
  return [
    {
    
    
      name: '张三',
      sex: '男',
      dt: '20200701',
      age: '22',
      tel: '13789890909',
      address: '北京市北京小区',
    },
    {
    
    
      name: '李四',
      sex: '女',
      dt: '20230507',
      age: '27',
      tel: '15477778888',
      address: '大连市大连小区',
    },
    {
    
    
      name: '王五',
      sex: '男',
      dt: '20221001',
      age: '26',
      tel: '15477778888',
      address: '大连市大连小区',
    },
    {
    
    
      name: '小明',
      sex: '男',
      dt: '20220701',
      age: '25',
      tel: '15477778888',
      address: '大连市大连小区',
    },
    {
    
    
      name: '小红',
      sex: '女',
      dt: '20180808',
      age: '28',
      tel: '15477778888',
      address: '大连市大连小区',
    },
  ];
}

BasicTable.vue

<template>
  <div
    :style="{
      overflow: 'hidden',
      position: 'relative',
      height: '100%',
    }"
  >
    <!-- 注册table -->
    <BasicTable @register="registerTable">
      <template #action="{ record }">
        <TableAction
          :actions="[
            {
              tooltip: '查看',
              icon: 'clarity:info-standard-line',
              onClick: handleOpen.bind(null, { type: 'view', data: record }),
            },
            {
              tooltip: '编辑',
              icon: 'clarity:note-edit-line',
              onClick: handleOpen.bind(null, { type: 'edit', data: record }),
            },
            {
              tooltip: '删除',
              color: 'error',
              icon: 'ant-design:delete-outlined',
              popConfirm: {
                title: '是否确定删除?',
                confirm: handleDel.bind(null, record),
              },
            },
          ]"
        />
      </template>
      <template #toolbar>
        <a-button type="primary" @click="handleOpen({ type: 'add', data: {} })">{
   
   {
          '新增'
        }}</a-button>

        <a-button color="warning" @click="exitExcel()">{
   
   { '导出 Excel' }}</a-button>
      </template>
    </BasicTable>

    <AEVDrawerPage @reload="handleReload" @register="registerDrawer" />
    <!-- <ViewDrawer @reload="handleReload" @register="registerDrawer" /> -->
    <!-- <EditModal @reload="handleReload" @register="registerModal" /> -->
  </div>
</template>

<script lang="ts">
  import {
      
       defineComponent } from 'vue';
  // import { router } from '/@/router';
  import {
      
       formConfig, columns, initData } from './data';
  import {
      
       BasicTable, useTable, TableAction } from '/@/components/Table';
  import {
      
       useDrawer } from '/@/components/Drawer';
  // import { useModal } from '/@/components/Modal';
  import {
      
       useMessage } from '/@/hooks/web/useMessage';
  // import { aoaToSheetXlsx } from '/@/components/Excel';
  import {
      
       getListDataApi, delListDataApi } from '../../../api/table/tableApi';
  // import ViewDrawer from './ViewDrawer.vue';
  // import EditModal from './EditModal.vue';
  import AEVDrawerPage from './AEVDrawerPage.vue';
  export default defineComponent({
      
      
    name: 'tableTest',
    components: {
      
      
      BasicTable,
      TableAction,
      AEVDrawerPage,
      // ViewDrawer,
      // EditModal
    },
    setup() {
      
      
      // const data = initData();

      const {
      
       createMessage } = useMessage();
      // 设置table
      const [registerTable, {
      
       reload, clearSelectedRowKeys }] = useTable(
        {
      
      
          title: '查询结果',
          // 调用接口,之前的写死数据就不用了
          api: getListDataApi,
          // dataSource: data,
          columns: columns,
          bordered: true,
          useSearchForm: true, //开启搜索区域
          formConfig: formConfig,
          // striped:false,
          // showSummary:true,
          // loading:true,
          afterFetch: (data) => {
      
      
            console.log('data', data);
            clearSelectedRowKeys();
          },
          actionColumn: {
      
      
            width: 120,
            title: '操作',
            dataIndex: 'action',
            slots: {
      
       customRender: 'action' },
          },
          rowSelection: {
      
       type: 'radio' },
          pagination: {
      
       pageSize: 10 },
          showTableSetting: true,
          tableSetting: {
      
       fullScreen: true },
          showIndexColumn: true,
          indexColumnProps: {
      
       fixed: 'left' },
        },
      );

      // 注册Drawer
      const [registerDrawer, {
      
       openDrawer: openAEVDrawerPage, setDrawerProps }] = useDrawer();

      // 配置Modal
      // const [registerModal, { openModal }] = useModal();

      async function handleOpen({
       
        type, data }) {
      
      
        await openAEVDrawerPage(true, {
      
       type, data });
        if (type === 'add') {
      
      
          setDrawerProps({
      
       title: '新增' });
        } else if (type === 'edit') {
      
      
          setDrawerProps({
      
       title: '修改' });
        } else {
      
      
          setDrawerProps({
      
       title: '查看' });
        }
      }

      // async function exitExcel() {
      
      
      //   let tableData:[][] = getDataSource();
      //   let columns = getColumns()
      //   let titleArr = columns.map(item => {
      
      
      //     return item.title
      //   })
      //   console.log('tableData', tableData,columns,titleArr);

      //   // debugger;
      //   aoaToSheetXlsx({
      
      
      //     data: tableData,
      //     header: titleArr,
      //     filename: '导出excel.xlsx',
      //   });
      // }

      // 新增按钮
      // function handleAdd() {
      
      
      //   router.push({
      
      
      //     path: '/testRoute/addPage',
      //   });
      // }

      // 查看按钮
      // function handleView({ data }) {
      
      
      //   openDrawer(true, data);
      // }

      // 编辑按钮
      // function handleEdit({ data }) {
      
      
      //   openModal(true, data);
      // }

      // 删除按钮
      async function handleDel(record: Recordable) {
      
      
        console.log('删除数据', record);
        await delListDataApi(record).then(() => {
      
      
          createMessage.success('删除成功');
          reload();
        });
      }

      function handleReload() {
      
      
        reload();
      }
      return {
      
      
        registerTable,
        reload,

        handleOpen,
        // 新增路由跳转
        // handleAdd,

        // 查看抽屉
        registerDrawer,
        // handleView,
        handleReload,

        // 编辑弹窗
        // registerModal,
        // handleEdit,

        // 删除
        handleDel,

        // exitExcel,
      };
    },
  });
</script>

<style scoped></style>

AEVDrawerPage.vue (メインの呼び出しインターフェイスに加えて、私が自分で練習したタブやその他の関連コードもあります。それらは無視してかまいません...)

<template>
  <div
    :style="{
      overflow: 'hidden',
    }"
  >
    <BasicDrawer
      v-bind="$attrs"
      @register="registerDrawer"
      @visibleChange="handleVisibleChange"
      :isDetail="true"
      title="查看"
      placement="bottom"
      height="100%"
      :destroyOnClose="true"
    >
      <a-tabs>
        <a-tab-pane key="1" tab="表单页面">
          <div>
            <BasicForm @register="registerForm"></BasicForm>
          </div>
          <Divider />
          <PageFooter v-if="showPageFooter">
            <template #right>
              <a-button @click="handleCancel"> 取消</a-button>
              <a-button class="!ml-4" type="primary" @click="handleSubmit" :loading="isLoading">
                保存</a-button
              >
            </template>
          </PageFooter>
        </a-tab-pane>
        <a-tab-pane key="2" tab="明细页面">
          <!-- <BasicTable @register="registerTable">
            <template #action="{}">
              <TableAction
                :actions="[
                  {
                    tooltip: '查看',
                    icon: 'clarity:info-standard-line',
                    
                  },
                  {
                    tooltip: '编辑',
                    icon: 'clarity:note-edit-line',
                    
                  },
                  {
                    tooltip: '删除',
                    color: 'error',
                    icon: 'ant-design:delete-outlined',

                  },
                ]"
              />
            </template>
            <template #toolbar>
              <a-button type="primary">{
    
    {
                '新增'
              }}</a-button>

              <a-button color="warning" >{
    
    { '导出 Excel' }}</a-button>
            </template>
          </BasicTable> -->
        </a-tab-pane>
        <a-tab-pane key="3" tab="其他页面"></a-tab-pane>
      </a-tabs>
    </BasicDrawer>
  </div>
</template>

<script lang="ts">
  import {
      
       defineComponent, Ref, ref } from 'vue';
  import {
      
       Button, Divider, Tabs } from 'ant-design-vue';
  import {
      
       BasicTable, useTable, TableAction } from '/@/components/Table';
  import {
      
       BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  import {
      
       BasicForm, useForm } from '/@/components/Form';
  import {
      
       PageFooter } from '/@/components/Page';
  import {
      
       useMessage } from '/@/hooks/web/useMessage';
  import {
      
       schemasView } from './data';
  import {
      
      
    // getListDataApi,
    addListDataApi,
    editListDataApi,
  } from '/@/api/table/tableApi';
  // import { formConfig, columns, initData } from './data';

  export default defineComponent({
      
      
    name: 'AEVDrawerPage',
    components: {
      
      
      BasicDrawer,
      BasicForm,
      Divider,
      PageFooter,
      [Tabs.name]: Tabs,
      [Tabs.TabPane.name]: Tabs.TabPane,
      [Button.name]: Button,
      BasicTable,
      TableAction,
    },
    setup(_, {
       
        emit }) {
      
      
      const {
      
       createMessage } = useMessage();
      const currentType: Ref = ref('add');
      const showPageFooter: Ref = ref(true);
      const isLoading = ref(false);
      // const [registerTable, {  }] = useTable(
      //   {
      
      
      //     title: '查询结果',
      //     api: getListDataApi,
      //     // dataSource: data,
      //     columns: columns,
      //     bordered: true,
      //     // useSearchForm: true, //开启搜索区域
      //     // formConfig: formConfig,
      //     // striped:false,
      //     // showSummary:true,
      //     // loading:true,
      //     actionColumn: {
      
      
      //       width: 120,
      //       title: '操作',
      //       dataIndex: 'action',
      //       slots: { customRender: 'action' },
      //     },
      //     rowSelection: { type: 'radio' },
      //     pagination: { pageSize: 10 },
      //     showTableSetting: true,
      //     tableSetting: { fullScreen: true },
      //     showIndexColumn: true,
      //     indexColumnProps: { fixed: 'left' },
      //   },
      // );
      // 配置Drawer
      const [registerDrawer, {
      
       closeDrawer }] = useDrawerInner(async ({
       
        type, data }) => {
      
      
        console.log('打印从table传递的数据:', type, data);
        currentType.value = type;
        console.log('currentType', currentType);
        setFieldsValue(data);
        if (type == 'view') {
      
      
          showPageFooter.value = false;
          setProps({
      
       disabled: true });
        } else {
      
      
          showPageFooter.value = true;
        }
      });

      // 配置Form
      const [registerForm, {
      
       validate, getFieldsValue, setFieldsValue, setProps }] = useForm({
      
      
        labelWidth: 150,
        baseColProps: {
      
      
          offset: 1,
          span: 10,
        },
        schemas: schemasView,
        showActionButtonGroup: false,
      });

      function handleVisibleChange(visible: boolean) {
      
      
        if (!visible) {
      
      
          emit('reload');
        }
      }

      async function handleSubmit() {
      
      
        console.log('handleSubmit', currentType);
        // await validate();
        const paramsData = await getFieldsValue();
        console.log('paramsData', paramsData);
        isLoading.value = true;

        if (currentType.value === 'add') {
      
      
          await addListDataApi({
      
       ...paramsData }).then((res) => {
      
      
            isLoading.value = false;
            createMessage.success('保存成功');
            closeDrawer();
          });
        } else {
      
      
          await editListDataApi({
      
       ...paramsData }).then((res) => {
      
      
            isLoading.value = false;
            createMessage.success('保存成功');
            closeDrawer();
          });
        }
      }

      // 取消按钮
      function handleCancel() {
      
      
        console.log('handleCancel', currentType);
        emit('back');
        closeDrawer();
      }
      return {
      
      
        currentType,
        showPageFooter,
        isLoading,
        registerDrawer,
        closeDrawer,

        registerForm,
        validate,
        getFieldsValue,
        setFieldsValue,
        setProps,

        handleVisibleChange,
        handleSubmit,
        handleCancel,

        // registerTable,
      };
    },
  });
</script>

<style scoped></style>

ページ効果

vben-admin はモックを使用してインターフェイス ロジックと共同デバッグを追加、削除、変更します

おすすめ

転載: blog.csdn.net/qq_36842789/article/details/130661170