Skip to content

vue3+naive ui+jsx的简单增删改查页面示例

摘要

  • vue3
  • naive ui
  • jsx
  • flex布局 table数据flex:1占满剩余空间
vue

<template>
  <div class="table-page fx-column">
    <div class="fx ju-sb al-ct">
      <div class="fx al-ct fx-gp10">
        <n-input @keyup.enter="getList" v-model:value="paginationParams.keyword" clearable></n-input>
        <n-button type="primary" @click="handleClickSearch">搜索</n-button>
        <n-button @click="handleClickReset">重置</n-button>
      </div>
      <div class="fx al-ct fx-gp10">
        <n-button type="primary" @click="handleClickInsert">新增</n-button>
      </div>
    </div>

    <div ref="tableScrollbar" style="flex: 1">
      <n-scrollbar>
        <n-data-table :max-height="tableMaxHeight" :columns="columns" :data="dataList"/>
      </n-scrollbar>
    </div>
    <div class="fx ju-fe">
      <n-pagination v-model:page="paginationParams.pageNum"
                    :display-order="['quick-jumper', 'pages', 'size-picker']"
                    show-quick-jumper
                    show-size-picker
                    :page-count="Math.ceil(paginationParams.total / paginationParams.pageSize)"
                    :page-size="paginationParams.pageSize"
                    :page-sizes="[10, 20, 50]"
                    :show-size-picker="true"
                    :show-quick-jumper="true"
                    @update:page="paginationParams.handleUpdatePageNum"
                    @update:page-size="paginationParams.handleUpdatePageSize"
      />
    </div>

  </div>
</template>
<script setup lang="jsx">
  import {ref, onMounted, useTemplateRef} from "vue";
  import {useModal, useLoadingBar} from 'naive-ui'
  import request from "@/src/common/utils/request.js";
  import {Pencil, TrashBin} from '@vicons/ionicons5'
  import FuncModalConfirm from "../../../components/func-comp/func-modal-confirm/index.jsx";

  const loadingBar = useLoadingBar();
  const modal = useModal();
  const tableScrollbarRef = useTemplateRef('tableScrollbar');
  const tableMaxHeight = ref(100);
  onMounted(() => {
    getList()
    tableMaxHeight.value = tableScrollbarRef.value.clientHeight - 100
  })
  const paginationParams = ref({
    total: 0,
    pageNum: 1,
    pageSize: 10,
    keyword: undefined,
    handleUpdatePageSize(pageSize) {
      reset()
      paginationParams.value.pageSize = pageSize
      getList()
    },
    handleUpdatePageNum(pageNum) {
      paginationParams.value.pageNum = pageNum
      getList()
    }
  })


  function getList() {
    request.loadingRequest({
      loadingBar,
      method: 'post',
      url: '/config/list',
      data: {
        pageSize: paginationParams.value.pageSize,
        pageNum: paginationParams.value.pageNum,
        keyword: paginationParams.value.keyword
      }
    }).then(res => {
      dataList.value = res.data.rows
      paginationParams.value.total = res.data.total
    })

  }

  function handleClickSearch() {
    getList()
  }

  function reset() {
    paginationParams.value.pageSize = 10
    paginationParams.value.pageNum = 1
    paginationParams.value.keyword = undefined;
    paginationParams.value.total = 0;
  }

  function handleClickReset() {
    reset()
    getList()
  }

  const rules = {
    config_key: [
      {required: true, message: '请输入配置key', trigger: ['change']},
    ],
    config_value: [
      {required: true, message: '请输入配置value', trigger: ['change']},
    ],
    config_remark: [
      {required: true, message: '请输入配置备注', trigger: ['change']},
    ]
  }

  function handleClickInsert() {
    const formRef = ref(null)
    const form = ref({
      config_key: '',
      config_value: '',
      config_remark: '',
    })

    const confirm = async () => {
      try {
        await formRef.value.validate().catch((e) => {
          throw e
        })
        await request.loadingRequest({
          loadingBar,
          url: '/config/add',
          method: 'post',
          data: form.value
        })
        $message.success('新增成功');
        getList()
        instance.destroy()
      } catch (e) {
        console.log('e', e)
      }

    }
    const cancel = () => {
      instance.destroy()
    }
    const instance = renderForm({
      modal,
      form,
      formRef,
      rules,
      confirm,
      cancel
    })
  }

  const dataList = ref([]);

  function renderForm(options) {
    const {form, rules, formRef, confirm, cancel, modal, title = '新增'} = options;
    return modal.create({
      title,
      preset: 'card',
      style: {
        width: '500px',
        padding: '1rem'
      },
      content: () => {
        return <n-form ref={formRef} model={form.value} rules={rules} label-placement="left" label-width={"100px"}>
          <n-form-item path="config_key" label="KEY">
            <n-input placeholder="请输入KEY" v-model={[form.value.config_key, 'value']}></n-input>
          </n-form-item>
          <n-form-item path="config_value" label="VALUE">
            <n-input placeholder="请输入VALUE" v-model={[form.value.config_value, 'value']}></n-input>
          </n-form-item>
          <n-form-item path="config_remark" label="REMARK">
            <n-input placeholder="请输入备注" v-model={[form.value.config_remark, 'value']}></n-input>
          </n-form-item>
          <div class="fx al-ct ju-ct fx-gp10">
            <n-button type="primary" onClick={confirm}>确认</n-button>
            <n-button onClick={cancel}>取消</n-button>
          </div>
        </n-form>
      }
    })
  }

  function handleClickUpdate(row) {
    const formRef = ref(null)
    const form = ref({
      id: row.id,
      config_key: row.config_key,
      config_value: row.config_value,
      config_remark: row.config_remark,
    })

    const confirm = async () => {
      try {
        await formRef.value.validate().catch((e) => {
          throw e
        })
        await request.loadingRequest({
          loadingBar,
          url: '/config/update',
          method: 'post',
          data: form.value
        })
        $message.success('修改成功');
        getList()
        instance.destroy()
      } catch (e) {
        console.log('e', e)
      }

    }
    const cancel = () => {
      instance.destroy()
    }
    const instance = renderForm({
      title: '修改',
      modal,
      form,
      formRef,
      rules,
      confirm,
      cancel
    })
  }

  async function handleClickDelete(row) {
    await FuncModalConfirm({modal})
    await request.loadingRequest({
      loadingBar,
      url: '/config/delete',
      method: 'post',
      data: {id: row.id}
    })
    $message.success('删除成功');
    getList()
  }

  const columns = ref([
    {title: 'KEY', key: 'config_key'},
    {title: 'VALUE', key: 'config_value'},
    {title: '备注', key: 'config_remark'},
    {title: '创建时间', key: 'create_time'},
    {title: '修改时间', key: 'update_time'},
    {
      title: '操作', width: 120, align: 'center', fixed: "right",
      render: (row) => {
        return <div class="fx al-ct fx-gp10 ju-ct">
          <Pencil onClick={() => handleClickUpdate(row)} style="width: 1.2rem;cursor: pointer"/>
          <TrashBin onClick={() => handleClickDelete(row)} style="width: 1.2rem;cursor: pointer"/>
        </div>
      }
    },
  ])
</script>
<style scoped lang="scss">

</style>
/src/technology/dateblog/2025/05/20250519-vue3-naive-ui%E5%8A%A0jsx%E7%9A%84%E7%AE%80%E5%8D%95%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5%E9%A1%B5%E9%9D%A2%E7%A4%BA%E4%BE%8B.html