基于AVue的二次封装:快速构建后台管理系统的CRUD方案

news2025/2/23 2:35:12

基于AVue的二次封装:快速构建后台管理系统的CRUD方案

在开发后台管理系统时,表格是常见的组件之一。然而,使用原生的Element Plus实现CRUD(增删改查)功能往往需要编写大量重复代码,过程繁琐。即使借助类似AVue这样的数据驱动视图框架,虽然能简化开发,但配置和使用上仍不够简洁。因此,我对AVue进行了二次封装,打造了一个更高效的CRUD组件——f-crud,以提升开发效率。

本文将详细介绍封装思路、实现代码以及使用方法,并附上效果图和建议。


一、封装目标

  1. 简化配置:通过统一的接口和配置项,减少开发者重复编写CRUD逻辑的负担。
  2. 功能完整:支持表格展示、搜索、分页、增删改查等核心功能。
  3. 灵活扩展:支持插槽自定义列渲染,适配不同业务场景。
  4. 快速上手:只需简单配置即可实现完整的CRUD功能。

二、实现方案

1. 使用层代码 (f-crud 使用示例)

以下是基于f-crud组件的使用示例,直接实现一个日志管理页面:

<template>
  <div class="app-log-page flex pt-[10px]">
    <f-crud
      ref="fcrud"
      :option="option"
      :operate="operate"
      :formProps="formProps"
      v-model="form"
      class="p-[12px] w-full"
    >
      <!-- 自定义列渲染:显示应用Logo -->
      <template #appLogoUrl="{ row }">
        <img v-if="row.appLogoUrl" :src="row.appLogoUrl" alt="" width="60px" height="60px">
      </template>
      <!-- 可选插槽:自定义操作按钮 -->
      <template #menuLeft="{ row }"></template>
      <template #menu="{ row }"></template>
      <template #search-menu="{ row }"></template>
    </f-crud>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted } from "vue";

// 搜索表单数据
const form = ref({ status: "", userName: "", includedSub: true });

// CRUD 接口配置
const operate = ref({
  getList: "/getItalentSyncLogList",
  postUrl: "/admin/data/area",
  putUrl: "/admin/data/area",
  delUrl: "/admin/data/area/",
});

const fcrud = ref(null);

// 分页等基础属性
const formProps = ref({ pageSize: 10 });

// 表格及表单配置
const option = () => ({
  border: true,
  searchSpan: 4,
  searchLabelWidth: 1,
  searchIcon: true,
  searchGutter: 20,
  searchMenuSpan: 7,
  searchIndex: 5,
  indexWidth: 60,
  emptyBtnText: "重置",
  columnBtn: false,
  index: true,
  align: "center",
  column: [
    { label: "北森修改人", prop: "operatorName" },
    { label: "动作", prop: "actionTypeName" },
    { label: "类型", prop: "typeName" },
    { label: "同步前组织名称", prop: "name" },
    { label: "同步前信息", prop: "beforeUpdate", showOverflowTooltip: true, overHidden: true, width: 250 },
    { label: "同步后信息", prop: "afterUpdate", showOverflowTooltip: true, overHidden: true, width: 250 },
    { label: "创建时间", prop: "createTime", width: 200, align: "center" },
    // 搜索字段(隐藏在表格中)
    { prop: "beforeUpdate", search: true, hide: true, placeholder: "修改前信息搜索", width: 250 },
    { prop: "afterUpdate", search: true, hide: true, placeholder: "修改后信息搜索" },
    {
      prop: "actionType",
      placeholder: "操作类型",
      search: true,
      hide: true,
      type: "select",
      dicData: [
        { label: "新增", value: "1" },
        { label: "修改", value: "2" },
        { label: "禁用", value: "3" },
      ],
    },
  ],
});

// 初始化加载数据
onMounted(() => {
  fcrud.value.getList();
});
</script>

<style lang="scss" scoped></style>

效果图

效果图

通过以上代码,只需配置option(表格和表单结构)、operate(接口地址)和formProps(分页参数),即可实现完整的增删改查功能。


2. 封装层代码 (f-crud.vue)

f-crud组件基于AVue的avue-crud,对其进行封装,统一处理数据请求、分页、表单等逻辑:

<template>
  <div>
    <avue-crud
      v-loading="data.listLoading"
      @search-reset="resetList"
      element-loading-text="Loading..."
      element-loading-spinner="svg"
      ref="crud"
      v-model:page="data.page"
      v-model:search="data.tForm"
      v-model="data.tForm"
      @row-update="rowEdit"
      @row-save="rowSave"
      @search-change="handleFilter"
      @size-change="sizeChange"
      @current-change="currentChange"
      @row-del="rowDelete"
      @refreshChange="handleRefreshChange"
      :data="data.list"
      :option="option()"
      :beforeOpen="beforeOpen"
      @selection-change="selectionChange"
    >
      <template #menu="{ row }">
        <slot name="menu" :row="row"></slot>
      </template>
      <template #menu-left="{ row }">
        <slot name="menuLeft" :row="row"></slot>
      </template>
      <template #search-menu="{ row }">
        <slot name="search-menu" :row="row"></slot>
      </template>
      <template #appLogoUrl="{ row }">
        <slot name="appLogoUrl" :row="row"></slot>
      </template>
    </avue-crud>
  </div>
</template>

<script setup lang="ts">
import { reactive, watch, ref, onMounted } from "vue";
import { useTable } from "@/utils/use-table";

interface Props<T = any> {
  operate: T;
  modelValue: T;
  formProps?: T;
  option: T;
}

const props = withDefaults(defineProps<Props>(), {
  operate: { getList: "", postUrl: "", putUrl: "", delUrl: "" },
  modelValue: {},
  formProps: {},
  option: () => {},
});

const crud = ref<any>(null);
const data = reactive({
  page: {
    total: 0,
    currentPage: 1,
    pageSize: props.formProps.pageSize || 20,
    isAsc: false,
  },
  listLoading: true,
  getList: props.operate.getList,
  postUrl: props.operate.postUrl,
  putUrl: props.operate.putUrl,
  delUrl: props.operate.delUrl,
  props: props.formProps,
  query: {},
  list: [],
  tForm: {},
});

const emit = defineEmits(["update:modelValue", "selectionChange"]);

const beforeOpen = (done: Function) => {
  crud.value.dicInit();
  done();
};

watch(() => data.tForm, (value) => emit("update:modelValue", value));

onMounted(() => {
  data.tForm = props.modelValue;
});

const selectionChange = (list) => emit("selectionChange", list);

const resetList = () => getList();

const { getList, rowSave, rowEdit, rowDelete, handleFilter, handleRefreshChange, currentChange, sizeChange } =
  useTable(data);

defineExpose({ getList, rowSave, rowEdit, rowDelete, handleFilter, handleRefreshChange, currentChange, sizeChange, data, crud });
</script>

3. 逻辑层代码 (use-table.ts)

use-table是一个独立的工具函数,封装了CRUD的核心逻辑,包括数据获取、分页处理和表单操作:

import { ElMessageBox, ElNotification } from "element-plus";
import Api from "@/api/common";

export function useTable(data: any) {
  const getList = (params: any = {}) => {
    params = Object.assign(params, data.tForm, data.props || {});
    data.listLoading = true;
    return Api.getList(
      { ...params, pageNum: data.page.currentPage, pageSize: data.page.pageSize },
      data
    ).then((response: any) => {
      data.list = response.data.resultData?.list || response.data.resultData;
      data.page.total = response.data.resultData?.total;
      data.listLoading = false;
    });
  };

  const handleFilter = (param: any, done: Function) => {
    data.page.currentPage = 1;
    getList(param);
    done && done();
  };

  const handleRefreshChange = (current?: number) => {
    if (current) data.page.currentPage = current;
    getList();
  };

  const sizeChange = (pageSize: number) => {
    data.page.pageSize = pageSize;
    handleRefreshChange();
  };

  const currentChange = (current: number) => {
    data.page.currentPage = current;
    handleRefreshChange();
  };

  const rowSave = async (form: any, done: Function, loading: Function) => {
    if (data.props) Object.assign(form, data.props);
    await Api.post(form, data).then(() => {
      ElNotification({ message: "操作成功", type: "success" });
      done();
      loading();
      handleRefreshChange();
    }).catch(loading);
  };

  const rowEdit = async (form: any, index: number, done: Function, loading: Function) => {
    if (data.props) Object.assign(form, data.props);
    await Api.put(form, data).then(() => {
      ElNotification({ message: "操作成功", type: "success" });
      done && done();
      loading && loading();
      handleRefreshChange();
    }).catch(loading);
  };

  const rowDelete = (form: any) => {
    ElMessageBox.confirm("此操作将永久删除该数据,是否继续?", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }).then(async () => {
      await Api.del(form.id, data);
      ElNotification({ message: "操作成功", type: "success" });
      handleRefreshChange();
    });
  };

  return { getList, rowSave, rowEdit, rowDelete, handleFilter, handleRefreshChange, currentChange, sizeChange };
}

4. 请求层代码 (common.ts)

封装Axios请求,提供统一的接口调用方法:

import request from "@/plugins/axios";

const common = {
  getList: (params: {}, { getList = "", id = "" }) =>
    request({ url: getList + id, method: "get", params }),
  post: (data: {}, { postUrl = "", postMethod = "post" }) =>
    request({ url: postUrl, method: postMethod, data }),
  del: (id: string, { delUrl = "", delMethod = "delete" }, params = {}) =>
    request({ url: delUrl + id, method: delMethod, params }),
  put: (data: {}, { putUrl = "", putMethod = "put" }) =>
    request({ url: putUrl, method: putMethod, data }),
};

export default common;

三、使用方法

  1. 引入组件:将f-crud.vue注册到项目中。
  2. 配置参数
    • option:定义表格列、搜索字段和样式。
    • operate:提供CRUD接口地址。
    • formProps:设置分页等额外参数。
  3. 绑定数据:通过v-model绑定搜索表单数据。
  4. 自定义扩展:通过插槽自定义列渲染或按钮。

四、优点与建议

优点

  • 高效开发:只需少量配置即可实现完整CRUD功能。
  • 代码复用:逻辑抽离到use-table,便于维护和复用。
  • 灵活性:支持插槽和AVue原生属性,满足复杂需求。

建议

如果对样式要求不高,可以考虑使用百度的AMIS低代码框架。AMIS提供更强大的CRUD功能和更高的开发效率,尤其适合快速原型开发。

  • AVue官网:https://avuejs.com/
  • AMIS官网:https://aisuda.bce.baidu.com/amis/zh-CN/docs/index

希望这个封装方案能帮助你更高效地构建后台管理系统!如果有其他需求,可以随时交流优化方案。


这篇文章基于xai进行重新编辑

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2303714.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第6章:基于LangChain如何开发Agents,附带客户支持智能体示例

本文主要介绍了 LangChain4j 中的 Agent&#xff08;代理&#xff09; 概念&#xff0c;以及如何使用 LangChain4j 构建代理系统&#xff0c;重点提供了一个客户支持系统的智能体样例 代理&#xff08;Agents&#xff09;| LangChain4j 注意&#xff1a; 请注意&#xff0c;“A…

传统的自动化行业的触摸屏和上位机,PLC是否会被取代?

传统的自动化行业的触摸屏和上位机是否会被取代&#xff1f; 在工业自动化领域&#xff0c;触摸屏和上位机长期扮演着核心角色&#xff0c;尤其在污水处理、化工生产等场景中&#xff0c;它们通过实时数据采集、逻辑控制、报警联动等功能&#xff0c;保障了生产设备的稳定运行…

智能合约的部署

https://blog.csdn.net/qq_40261606/article/details/123249473 编译 点击图中的 “Compile 1_Storage.sol” 存和取一个数的合约&#xff0c;remix自带 pragma solidity >0.8.2 <0.9.0; /*** title Storage* dev Store & retrieve value in a variable* custom:d…

word$deepseep

1、进入官网地址。 DeepSeek 2、进入DeepSeek的API文档 3、点击DeepSeek开放平台左侧的“API Keys”, 再点击“创建API Key” 4、在弹出的对话框中&#xff0c;输入自己的API Key名称&#xff0c;点击创建。 sk-0385cad5e19346a0a4ac8b7f0d7be428 5、打开Word文档。 6、Word找…

Mac系统下使用Docker快速部署MaxKB:打造本地知识库问答系统

随着大语言模型的广泛应用&#xff0c;知识库问答系统逐渐成为提升工作效率和个人学习的有力工具。MaxKB是一款基于LLM&#xff08;Large Language Model&#xff09;大语言模型的知识库问答系统&#xff0c;支持多模型对接、文档上传和自动爬取等功能。本文将详细介绍如何在Ma…

如何为自己的 PDF 文件添加密码?在线加密 PDF 文件其实更简单

随着信息泄露和数据安全问题的日益突出&#xff0c;保护敏感信息变得尤为重要。加密 PDF 文件是一种有效的手段&#xff0c;可以确保只有授权用户才能访问或修改文档内容。本文将详细介绍如何使用 CleverPDF 在线工具为你的 PDF 文件添加密码保护&#xff0c;确保其安全性。 为…

华为昇腾910b服务器部署DeepSeek翻车现场

最近到祸一台HUAWEI Kunpeng 920 5250&#xff0c;先看看配置。之前是部署的讯飞大模型&#xff0c;发现资源利用率太低了。把5台减少到3台&#xff0c;就出了他 硬件配置信息 基本硬件信息 按照惯例先来看看配置。一共3块盘&#xff0c;500G的系统盘&#xff0c; 2块3T固态…

hive—常用的函数整理

1、size(split(...))函数用于计算分割后字符串数组的长度 实例1&#xff09;&#xff1a;由客户编号列表计算客户编号个数 --数据准备 with tmp_test01 as ( select tag074445270 tag_id,202501busi_mon , 012399931003,012399931000 index_val union all select tag07444527…

Unity Mirror 多房间匹配

文章目录 一 、一些唠叨二 、案例位置三、多房间匹配代码解析四、关于MatchInterestManagement五、总结 一 、一些唠叨 最近使用Mirror开发了一款多人同时在线的肉鸽塔防游戏,其目的是巩固一下Mirror这个插件的熟练度,另一方面是想和身边的朋友一起玩一下自己开发的游戏. 但是…

基于flask+vue框架的的医院预约挂号系统i1616(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。

系统程序文件列表 项目功能:用户,医生,科室信息,就诊信息,医院概况,挂号信息,诊断信息,取消挂号 开题报告内容 基于FlaskVue框架的医院预约挂号系统开题报告 一、研究背景与意义 随着医疗技术的不断进步和人们健康意识的日益增强&#xff0c;医院就诊量逐年增加。传统的现场…

Rust编程语言入门教程(五)猜数游戏:生成、比较神秘数字并进行多次猜测

Rust 系列 &#x1f380;Rust编程语言入门教程&#xff08;一&#xff09;安装Rust&#x1f6aa; &#x1f380;Rust编程语言入门教程&#xff08;二&#xff09;hello_world&#x1f6aa; &#x1f380;Rust编程语言入门教程&#xff08;三&#xff09; Hello Cargo&#x1f…

【代码审计】-Tenda AC 18 v15.03.05.05 /goform接口文档漏洞挖掘

路由器&#xff1a;Tenda AC 18 v15.03.05.05 固件下载地址&#xff1a;https://www.tenda.com.cn/material?keywordac18 1./goform/SetSpeedWan 接口文档&#xff1a; formSetSpeedWan函数中speed_di参数缓冲区溢出漏洞&#xff1a; 使用 binwalk -eM 解包固件&#xff0c…

2025年02月21日Github流行趋势

项目名称&#xff1a;source-sdk-2013 项目地址url&#xff1a;https://github.com/ValveSoftware/source-sdk-2013项目语言&#xff1a;C历史star数&#xff1a;7343今日star数&#xff1a;929项目维护者&#xff1a;JoeLudwig, jorgenpt, narendraumate, sortie, alanedwarde…

git 克隆及拉取github项目到本地微信开发者工具,微信开发者工具通过git commit、git push上传代码到github仓库

git 克隆及拉取github项目到本地微信开发者工具&#xff0c;微信开发者工具通过git commit、git push上传代码到github仓库 git 克隆及拉取github项目到本地 先在自己的用户文件夹新建一个项目文件夹&#xff0c;取名为项目名 例如这样 C:\Users\HP\yzj-再打开一个终端页面&…

【算法基础】--前缀和

前缀和 一、一维前缀和示例模板[寻找数组的中心下标 ](https://leetcode.cn/problems/tvdfij/description/)除自身以外的数组乘积和可被k整除的子数组 一、一维前缀和 前缀和就是快速求出数组某一个连续区间内所有元素的和。 示例模板 已知一个数组arr&#xff0c;求前缀和 …

统一的多摄像头3D感知框架!PETRv2论文精读

论文地址&#xff1a;PETRv2: A Unified Framework for 3D Perception from Multi-Camera Images 源代码&#xff1a;PETR 摘要 在本文中&#xff0c;我们提出了PETRv2&#xff0c;用于从多视角图像中进行3D感知的统一框架。基于PETR [24]&#xff0c;PETRv2探索了时间建模的…

【Linux】Linux 文件系统—— 探讨软链接(symbolic link)

ℹ️大家好&#xff0c;我是练小杰&#xff0c;周五又到了&#xff0c;明天应该就是牛马的休息日了吧&#xff01;&#xff01;&#x1f606; 前天我们详细介绍了 硬链接的特点&#xff0c;现在继续探讨 软链接的特点&#xff0c;并且后续将添加更多相关知识噢&#xff0c;谢谢…

Linux-CentOS 7安装

Centos 7镜像&#xff1a;https://pan.baidu.com/s/1fkQHYT64RMFRGLZy1xnSWw 提取码: q2w2 VMware Workstation&#xff1a;https://pan.baidu.com/s/1JnRcDBIIOWGf6FnGY_0LgA 提取码: w2e2 1、打开vmware workstation 2、选择主界面的"创建新的虚拟机"或者点击左上…

AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践

清华大学出品《DeepSeek&#xff1a;从入门到精通》分享 在忙碌的职场中&#xff0c;制作一份高质量的PPT往往需要投入大量时间和精力&#xff0c;尤其是在临近截止日期时。今天&#xff0c;我们将探索如何借助 AI 工具 —— DeepSeek 和 Kimi —— 让 PPT 制作变得既快捷又高…

【opencv】图像基本操作

一.计算机眼中的图像 1.1 图像读取 cv2.IMREAD_COLOR&#xff1a;彩色图像 cv2.IMREAD_GRAYSCCALE&#xff1a;灰色图像 ①导包 import cv2 # opencv读取的格式是BGR import matplotlib.pyplot as plt import numpy as np %matplotlib inline ②读取图像 img cv2.imread(…