若依vue3.0表格的增删改查文件封装
一、因若依生成的文件没进行封装,维护起来比较麻烦。所以自己简单的进行封装了一下
gitee代码(文件)地址:https://gitee.com/liu_yu_ting09/ruo_yi.git
二、封装的方法(下面绿色按钮进行全局封装一个JeecgListMixin.js文件)
三、文件目录
四、具体文件内容
1、JeecgListMixin.js(按照自己的目录进行创建,我的文件目录在src/mixins/JeecgListMixin.js)
JeecgListMixin.js文件代码如下:
import { ref } from "vue";
export const useCommonMixin = (additionalParams) => {///公共参数const { list, queryParams, registerModal,deleteOne,proxy,id,queryRef } = additionalParams; //传递过来的公共参数const loading = ref(false);//是否加载中const selectionRows = ref([]); //选中的数组,用于多选const selectedRowKeys = ref([]);//选中的key数组const dataSource = ref([]);//数据源const total = ref(0);//总条数function loadData(index){//加载数据loading.value = true;list(queryParams.value).then((res) => {loading.value = false;dataSource.value = res.rows;total.value = res.total;if(index ==1)proxy.$modal.msgSuccess("查询成功!");if(index ==2)proxy.$modal.msgSuccess("重置成功!");});}/** 新增按钮操作 */function handleAdd() {registerModal.value.add();}/** 修改按钮操作 */function handleUpdate(row) {registerModal.value.edit(row);}/** 搜索按钮操作 */function handleQuery(index) {queryParams.value.pageNum = 1;if(index ==1) return loadData(2);loadData(1);}// /** 一项删除按钮操作 */function handleDeleteOne(id) {proxy.$modal.confirm('是否确认删除这一项吗?').then(function () {return deleteOne(id);}).then(() => {loadData();proxy.$modal.msgSuccess("删除成功");}).catch(() => {});}// 选中事件触发function handleSelectionChange(selection) {selectionRows.value = selection;selectedRowKeys.value = selection.map((item) => item[id]);;}function handleDeleteBatch(index) {if (selectedRowKeys.value.length == 0) return proxy.$modal.msgWarning("请选择需要删除的数据");;let ids = selectedRowKeysif(index ==1) ids = selectedRowKeys.value.join(','); //批量删除转化字符串转化proxy.$modal.confirm(`是否确认批量删除 ${selectedRowKeys.value.length} 条数据?`).then(function () {return deleteOne(ids.value);}).then(() => {loadData();proxy.$modal.msgSuccess("删除成功");}).catch(() => {});}function searchReset(){ //搜索重置proxy.resetForm(queryRef);handleQuery(1);}function handleExport(url,queryParams,name) { //导出 --参数 url 请求地址 queryParams 参数名 name 文件名称proxy.download(url,queryParams,name);}return {loading,dataSource,total,loadData,handleAdd,handleUpdate,selectionRows,selectedRowKeys,handleQuery,handleDeleteOne,handleSelectionChange,handleDeleteBatch,searchReset,handleExport};
};
2、主页面文件(index文件下图:)
index代码:
<template><div class="app-container"><el-row :gutter="20"><!--部门数据--><el-col :span="4" :xs="24"><div class="head-container"><el-inputv-model="deptName"placeholder="请输入部门名称"clearableprefix-icon="Search"style="margin-bottom: 20px"/></div><div class="head-container"><el-tree:data="deptOptions":props="{ label: 'label', children: 'children' }":expand-on-click-node="false":filter-node-method="filterNode"ref="deptTreeRef"node-key="id"highlight-currentdefault-expand-all@node-click="handleNodeClick"/></div></el-col><!--用户数据--><el-col :span="20" :xs="24"><el-form:model="queryParams"ref="queryRef":inline="true"v-show="showSearch"label-width="68px"><el-form-item label="用户名称" prop="userName"><el-inputv-model="queryParams.userName"placeholder="请输入用户名称"clearablestyle="width: 240px"@keyup.enter="handleQuery"/></el-form-item><el-form-item label="手机号码" prop="phonenumber"><el-inputv-model="queryParams.phonenumber"placeholder="请输入手机号码"clearablestyle="width: 240px"@keyup.enter="handleQuery"/></el-form-item><el-form-item label="状态" prop="status"><el-selectv-model="queryParams.status"placeholder="用户状态"clearablestyle="width: 240px"><el-optionv-for="dict in sys_normal_disable":key="dict.value":label="dict.label":value="dict.value"/></el-select></el-form-item><el-form-item><el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button><el-button icon="Refresh" @click="resetQuery">重置</el-button></el-form-item></el-form><el-row :gutter="10" class="mb8"><el-col :span="1.5"><el-buttontype="primary"plainicon="Plus"@click="handleAdd"v-hasPermi="['system:user:add']">新增</el-button></el-col><el-col :span="1.5"><el-buttontype="danger"plainicon="Delete":disabled="selectedRowKeys.length ==0"@click="handleDeleteBatch()"v-hasPermi="['system:user:remove']">批量删除</el-button></el-col><el-col :span="1.5"><el-buttontype="info"plainicon="Upload"@click="handleImport"v-hasPermi="['system:user:import']">导入</el-button></el-col><el-col :span="1.5"><el-buttontype="warning"plainicon="Download"@click="handleExport('system/user/export', queryParams,`user_${new Date().getTime()}.xlsx`)"v-hasPermi="['system:user:export']">导出</el-button></el-col><right-toolbarv-model:showSearch="showSearch"@queryTable="loadData":columns="columns"></right-toolbar></el-row><el-tablev-loading="loading":data="dataSource"@selection-change="handleSelectionChange"><el-table-column type="selection" width="50" align="center" /><el-table-columnlabel="用户编号"align="center"key="userId"prop="userId"v-if="columns[0].visible"/><el-table-columnlabel="用户名称"align="center"key="userName"prop="userName"v-if="columns[1].visible":show-overflow-tooltip="true"/><el-table-columnlabel="用户昵称"align="center"key="nickName"prop="nickName"v-if="columns[2].visible":show-overflow-tooltip="true"/><el-table-columnlabel="部门"align="center"key="deptName"prop="dept.deptName"v-if="columns[3].visible":show-overflow-tooltip="true"/><el-table-columnlabel="手机号码"align="center"key="phonenumber"prop="phonenumber"v-if="columns[4].visible"width="120"/><el-table-columnlabel="状态"align="center"key="status"v-if="columns[5].visible"><template #default="scope"><el-switchv-model="scope.row.status"active-value="0"inactive-value="1"@change="handleStatusChange(scope.row)"></el-switch></template></el-table-column><el-table-columnlabel="创建时间"align="center"prop="createTime"v-if="columns[6].visible"width="160"><template #default="scope"><span>{{ parseTime(scope.row.createTime) }}</span></template></el-table-column><el-table-columnlabel="操作"align="center"width="150"class-name="small-padding fixed-width"><template #default="scope"><el-tooltipcontent="修改"placement="top"v-if="scope.row.userId !== 1"><el-buttonlinktype="primary"icon="Edit"@click="handleUpdate(scope.row)"v-hasPermi="['system:user:edit']"></el-button></el-tooltip><el-tooltipcontent="删除"placement="top"v-if="scope.row.userId !== 1"><el-buttonlinktype="primary"icon="Delete"@click="handleDeleteOne(scope.row.userId)"v-hasPermi="['system:user:remove']"></el-button></el-tooltip><el-tooltipcontent="重置密码"placement="top"v-if="scope.row.userId !== 1"><el-buttonlinktype="primary"icon="Key"@click="handleResetPwd(scope.row)"v-hasPermi="['system:user:resetPwd']"></el-button></el-tooltip><el-tooltipcontent="分配角色"placement="top"v-if="scope.row.userId !== 1"><el-buttonlinktype="primary"icon="CircleCheck"@click="handleAuthRole(scope.row)"v-hasPermi="['system:user:edit']"></el-button></el-tooltip></template></el-table-column></el-table><paginationv-show="total > 0":total="total"v-model:page="queryParams.pageNum"v-model:limit="queryParams.pageSize"@pagination="loadData"/></el-col></el-row><!-- 添加或修改用户配置对话框 --><!-- 用户导入对话框 --><el-dialog:title="upload.title"v-model="upload.open"width="400px"append-to-body><el-uploadref="uploadRef":limit="1"accept=".xlsx, .xls":headers="upload.headers":action="upload.url + '?updateSupport=' + upload.updateSupport":disabled="upload.isUploading":on-progress="handleFileUploadProgress":on-success="handleFileSuccess":auto-upload="false"drag><el-icon class="el-icon--upload"><upload-filled /></el-icon><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><template #tip><div class="el-upload__tip text-center"><div class="el-upload__tip"><el-checkboxv-model="upload.updateSupport"/>是否更新已经存在的用户数据</div><span>仅允许导入xls、xlsx格式文件。</span><el-linktype="primary":underline="false"style="font-size: 12px; vertical-align: baseline"@click="importTemplate">下载模板</el-link></div></template></el-upload><template #footer><div class="dialog-footer"><el-button type="primary" @click="submitFileForm">确 定</el-button><el-button @click="upload.open = false">取 消</el-button></div></template></el-dialog><userModal ref="registerModal" @success="loadData" /><!-- 用户注册编辑对话框 --></div>
</template>
<script setup name="User">
import { getToken } from "@/utils/auth";
import {changeUserStatus,listUser,resetUserPwd,delUser,deptTreeSelect,
} from "./api/userApi";
const router = useRouter();
const { proxy } = getCurrentInstance();
const { sys_normal_disable, sys_user_sex } = proxy.useDict("sys_normal_disable","sys_user_sex"
);
import { useCommonMixin } from "@/mixins/JeecgListMixin.js"; //公共方法
import userModal from "./components/userModal.vue"; //公共方法
const registerModal = ref();
const showSearch = ref(true);
const deptName = ref("");
const deptOptions = ref(undefined);
/*** 用户导入参数 */
const upload = reactive({// 是否显示弹出层(用户导入)open: false,// 弹出层标题(用户导入)title: "",// 是否禁用上传isUploading: false,// 是否更新已经存在的用户数据updateSupport: 0,// 设置上传的请求头部headers: { Authorization: "Bearer " + getToken() },// 上传的地址url: import.meta.env.VITE_APP_BASE_API + "/system/user/importData",
});
// 列显隐信息
const columns = ref([{ key: 0, label: `用户编号`, visible: true },{ key: 1, label: `用户名称`, visible: true },{ key: 2, label: `用户昵称`, visible: true },{ key: 3, label: `部门`, visible: true },{ key: 4, label: `手机号码`, visible: true },{ key: 5, label: `状态`, visible: true },{ key: 6, label: `创建时间`, visible: true },
]);const data = reactive({queryParams: {pageNum: 1,pageSize: 10,userName: undefined,phonenumber: undefined,status: undefined,deptId: undefined,},
});
const { queryParams } = toRefs(data);
// 根据需要传入额外参数(传递给JeecgListMixin页面的文件)
const additionalParams = {list: listUser,//查询用户列表queryParams: queryParams,//查询参数registerModal:registerModal,//用户注册编辑对话框deleteOne:delUser,//删除用户接口proxy:proxy,//公共方法id: "userId",//主键idqueryRef:'queryRef',//查询框ref
}
const { loading, dataSource, total, loadData, handleAdd,handleUpdate,handleQuery,handleDeleteOne,handleDeleteBatch,handleSelectionChange,searchReset,handleExport,selectionRows,selectedRowKeys} =useCommonMixin(additionalParams);
/** 通过条件过滤节点 */
const filterNode = (value, data) => {if (!value) return true;return data.label.indexOf(value) !== -1;
};
/** 根据名称筛选部门树 */
watch(deptName, (val) => {proxy.$refs["deptTreeRef"].filter(val);
});
/** 查询部门下拉树结构 */
function getDeptTree() {deptTreeSelect().then((response) => {deptOptions.value = response.data;});
}
/** 节点单击事件 */
function handleNodeClick(data) {queryParams.value.deptId = data.id;handleQuery();
}
/** 重置按钮操作 */
function resetQuery() {queryParams.value.deptId = undefined;proxy.$refs.deptTreeRef.setCurrentKey(null);searchReset();
}
/** 用户状态修改 */
function handleStatusChange(row) {let text = row.status === "0" ? "启用" : "停用";proxy.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function () {return changeUserStatus(row.userId, row.status);}).then(() => {proxy.$modal.msgSuccess(text + "成功");}).catch(function () {row.status = row.status === "0" ? "1" : "0";});
}
/** 更多操作 */
// function handleCommand(command, row) {
// switch (command) {
// case "handleResetPwd":
// handleResetPwd(row);
// break;
// case "handleAuthRole":
// handleAuthRole(row);
// break;
// default:
// break;
// }
// }/** 跳转角色分配 */
function handleAuthRole(row) {const userId = row.userId;router.push("/system/user-auth/role/" + userId);
}/** 重置密码按钮操作 */
function handleResetPwd(row) {proxy.$prompt('请输入"' + row.userName + '"的新密码', "提示", {confirmButtonText: "确定",cancelButtonText: "取消",closeOnClickModal: false,inputPattern: /^.{5,20}$/,inputErrorMessage: "用户密码长度必须介于 5 和 20 之间",inputValidator: (value) => {if (/<|>|"|'|\||\\/.test(value)) {return "不能包含非法字符:< > \" ' \\\ |";}},}).then(({ value }) => {resetUserPwd(row.userId, value).then((response) => {proxy.$modal.msgSuccess("修改成功,新密码是:" + value);});}).catch(() => {});
}
/** 导入按钮操作 */
function handleImport() {upload.title = "用户导入";upload.open = true;
}
/** 下载模板操作 */
function importTemplate() {proxy.download("system/user/importTemplate",{},`user_template_${new Date().getTime()}.xlsx`);
}
/**文件上传中处理 */
const handleFileUploadProgress = (event, file, fileList) => {upload.isUploading = true;
};/** 文件上传成功处理 */
const handleFileSuccess = (response, file, fileList) => {upload.open = false;upload.isUploading = false;proxy.$refs["uploadRef"].handleRemove(file);proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +response.msg +"</div>","导入结果",{ dangerouslyUseHTMLString: true });loadData();
};
/** 提交上传文件 */
function submitFileForm() {proxy.$refs["uploadRef"].submit();
}
getDeptTree();
loadData();
</script>
3、api(接口文件)
具体代码:
import request from '@/utils/request'
import { parseStrEmpty } from "@/utils/ruoyi";// 查询用户列表
export function listUser(query) {return request({url: '/system/user/list',method: 'get',params: query})
}// 查询用户详细
export function getUser(userId) {return request({url: '/system/user/' + parseStrEmpty(userId),method: 'get'})
}// 新增用户
export function addUser(data) {return request({url: '/system/user',method: 'post',data: data})
}// 修改用户
export function updateUser(data) {return request({url: '/system/user',method: 'put',data: data})
}
export function saveOrUpdate(data,isUpdate) { // 新增-编辑const method = isUpdate ? 'put' : 'post';return request({url: '/system/user',method: method,data: data})
}
// 删除用户
export function delUser(userId) {return request({url: '/system/user/' + userId,method: 'delete'})
}// 用户密码重置
export function resetUserPwd(userId, password) {const data = {userId,password}return request({url: '/system/user/resetPwd',method: 'put',data: data})
}// 用户状态修改
export function changeUserStatus(userId, status) {const data = {userId,status}return request({url: '/system/user/changeStatus',method: 'put',data: data})
}// 查询用户个人信息
export function getUserProfile() {return request({url: '/system/user/profile',method: 'get'})
}// 修改用户个人信息
export function updateUserProfile(data) {return request({url: '/system/user/profile',method: 'put',data: data})
}// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {const data = {oldPassword,newPassword}return request({url: '/system/user/profile/updatePwd',method: 'put',params: data})
}// 用户头像上传
export function uploadAvatar(data) {return request({url: '/system/user/profile/avatar',method: 'post',headers: { 'Content-Type': 'application/x-www-form-urlencoded' },data: data})
}// 查询授权角色
export function getAuthRole(userId) {return request({url: '/system/user/authRole/' + userId,method: 'get'})
}// 保存授权角色
export function updateAuthRole(data) {return request({url: '/system/user/authRole',method: 'put',params: data})
}// 查询部门下拉树结构
export function deptTreeSelect() {return request({url: '/system/user/deptTree',method: 'get'})
}
4、新增编辑弹窗文件
具体代码
1、userModal.vue文件
<template><el-dialog v-model="visible" :title="title" :width="width"><div v-if="visible"><userForm ref="registerForm" @ok="submitCallback" @onLose="onLose" /></div><template #footer> <!-- 按钮 --><div class="dialog-footer"><el-button type="primary" @click="handleOk" :disabled="disabled">确 定</el-button><el-button @click="handleCancel">取 消</el-button></div></template></el-dialog>
</template>
<script setup >
import { ref, nextTick } from "vue";
import userForm from "./userForm.vue";
const title = ref("");
const width = ref('800');
const visible = ref(false);
const disabled = ref(false);
const registerForm = ref();
const emit = defineEmits(["register", "success"]);
/*** 新增*/
function add() {title.value = "新增";visible.value = true;nextTick(() => {registerForm.value.add();});
}
/*** 编辑**/
function edit(record) {title.value = "编辑";visible.value = true;nextTick(() => {registerForm.value.edit(record);});}
/*** 确定按钮点击事件*/
function handleOk() {disabled.value = true;registerForm.value.submitForm();
}
function onLose() {disabled.value = false;
}
/*** form保存回调事件*/
function submitCallback() {handleCancel();onLose();emit("success");
}
/*** 取消按钮回调事件*/
function handleCancel() {visible.value = false;
}
defineExpose({add,edit,
});
</script>
2、userForm.vue文件
<template><el-form :model="formData" :rules="rules" :disabled="disabled" ref="formRef" label-width="80px"><el-row><el-col :span="12"><el-form-item label="用户昵称" prop="nickName"><el-inputv-model="formData.nickName"placeholder="请输入用户昵称"maxlength="30"/></el-form-item></el-col><el-col :span="12"><el-form-item label="归属部门" prop="deptId"><el-tree-selectv-model="formData.deptId":data="deptOptions":props="{ value: 'id', label: 'label', children: 'children' }"value-key="id"placeholder="请选择归属部门"check-strictly/></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="手机号码" prop="phonenumber"><el-inputv-model="formData.phonenumber"placeholder="请输入手机号码"maxlength="11"/></el-form-item></el-col><el-col :span="12"><el-form-item label="邮箱" prop="email"><el-inputv-model="formData.email"placeholder="请输入邮箱"maxlength="50"/></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-itemv-if="formData.userId == undefined"label="用户名称"prop="userName"><el-inputv-model="formData.userName"placeholder="请输入用户名称"maxlength="30"/></el-form-item></el-col><el-col :span="12"><el-form-itemv-if="formData.userId == undefined"label="用户密码"prop="password"><el-inputv-model="formData.password"placeholder="请输入用户密码"type="password"maxlength="20"show-password/></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="用户性别"><el-select v-model="formData.sex" placeholder="请选择"><el-optionv-for="dict in sys_user_sex":key="dict.value":label="dict.label":value="dict.value"></el-option></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="状态"><el-radio-group v-model="formData.status"><el-radiov-for="dict in sys_normal_disable":key="dict.value":value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item></el-col></el-row><el-row><el-col :span="12"><el-form-item label="岗位"><el-select v-model="formData.postIds" multiple placeholder="请选择"><el-optionv-for="item in postOptions":key="item.postId":label="item.postName":value="item.postId":disabled="item.status == 1"></el-option></el-select></el-form-item></el-col><el-col :span="12"><el-form-item label="角色"><el-select v-model="formData.roleIds" multiple placeholder="请选择"><el-optionv-for="item in roleOptions":key="item.roleId":label="item.roleName":value="item.roleId":disabled="item.status == 1"></el-option></el-select></el-form-item></el-col></el-row><el-row><el-col :span="24"><el-form-item label="备注"><el-inputv-model="formData.remark"type="textarea"placeholder="请输入内容"></el-input></el-form-item></el-col></el-row></el-form>
</template>
<script setup>
import { ref, reactive, nextTick } from "vue";
const { proxy } = getCurrentInstance();
import {saveOrUpdate,deptTreeSelect,getUser
} from "../api/userApi";
const { sys_normal_disable, sys_user_sex } = proxy.useDict("sys_normal_disable","sys_user_sex"
);
const emit = defineEmits(["register", "ok"]);
const formRef = ref();
const deptOptions = ref(undefined);
const postOptions = ref([]);
const disabled = ref(false);
const roleOptions = ref([]);
const formData = reactive({userId: undefined,deptId: undefined,userName: undefined,nickName: undefined,password: undefined,phonenumber: undefined,email: undefined,sex: undefined,status: "0",remark: undefined,postIds: [],roleIds: [],
});
//表单验证
const rules = {userName: [{ required: true, message: "用户名称不能为空", trigger: "blur" },{min: 2,max: 20,message: "用户名称长度必须介于 2 和 20 之间",trigger: "blur",},],nickName: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],password: [{ required: true, message: "用户密码不能为空", trigger: "blur" },{min: 5,max: 20,message: "用户密码长度必须介于 5 和 20 之间",trigger: "blur",},{pattern: /^[^<>"'|\\]+$/,message: "不能包含非法字符:< > \" ' \\\ |",trigger: "blur",},],email: [{type: "email",message: "请输入正确的邮箱地址",trigger: ["blur", "change"],},],phonenumber: [{pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,message: "请输入正确的手机号码",trigger: "blur",},],
};/*** 新增*/
function add() {edit({});
}
/*** 编辑*/
function edit(record) {nextTick(() => {//赋值表单数据Object.assign(formData, record);});console.log(formData);proxy.resetForm("formRef");
}
/*** 提交数据*/
async function submitForm() {disabled.value = true;proxy.$refs["formRef"].validate((valid) => {if (valid) {let model = { ...formData };const isUpdate = formData.createTime;saveOrUpdate(model,isUpdate).then((res) => {disabled.value = false;if (res.code ==200) {proxy.$modal.msgSuccess(res.msg);emit("ok");} else {emit("onLose");proxy.$modal.msgError(res.msg);}});}else{disabled.value = false;emit("onLose");} });
}
/** 查询部门下拉树结构 */
function getDeptTree() {deptTreeSelect().then((response) => { //部门下拉树deptOptions.value = response.data;});getUser().then(response => { //岗位角色postOptions.value = response.posts;roleOptions.value = response.roles;});
} getDeptTree();
defineExpose({add,edit,submitForm,
});
</script>
文档:使用
useCommonMixin
进行用户管理概述
useCommonMixin
是一个 Vue 组合式 API,用于简化用户管理界面的操作,包括数据加载、用户添加、修改、删除和导出功能。该混合器接受一组公共参数,提供了一些基本的方法和状态管理。参数
useCommonMixin
接受以下参数:
list
: 查询用户列表的方法。queryParams
: 查询参数的响应式对象。registerModal
: 用户注册/编辑对话框的引用。deleteOne
: 删除用户的 API 接口。proxy
: 公共方法的引用。id
: 主键 ID 字段名。queryRef
: 查询框的引用。返回值
该混合器返回一个对象,包含以下属性和方法:
状态管理
loading
: 布尔值,表示数据是否在加载中。dataSource
: 用户数据源,响应式数组。total
: 用户总数,响应式数值。selectionRows
: 当前选中的用户数组。selectedRowKeys
: 当前选中的用户 ID 数组。方法
loadData(index)
: 加载用户数据,并根据index
显示成功消息。handleAdd()
: 打开用户添加对话框。handleUpdate(row)
: 打开用户编辑对话框,传入待编辑的行数据。handleQuery(index)
: 执行查询操作,重置页码并调用loadData
。handleDeleteOne(id)
: 确认并删除单个用户。handleSelectionChange(selection)
: 更新选中的用户数组和 ID。handleDeleteBatch(index)
: 确认并删除选中的多个用户。searchReset()
: 重置搜索表单并重新加载数据。handleExport(url, queryParams, name)
: 导出用户数据。使用示例
在 Vue 组件中引入并使用该混合器:
javascriptCopy Code
import { useCommonMixin } from './jeecglistMixin'; const additionalParams = { list: listUser, queryParams: queryParams, registerModal: registerModal, deleteOne: delUser, proxy: proxy, id: 'userId', queryRef: 'queryRef', }; const { loading, dataSource, total, loadData, handleAdd, handleUpdate, handleQuery, handleDeleteOne, handleDeleteBatch, handleSelectionChange, searchReset, handleExport, selectionRows, selectedRowKeys, } = useCommonMixin(additionalParams);
注意事项
确保传入的
queryParams
和registerModal
是响应式对象,且list
和deleteOne
是可用的 API 方法。总结
useCommonMixin
提供了一套完整的用户管理功能,帮助开发者轻松实现常见的 CRUD 操作。通过合理传递参数,可以快速构建出高效、用户友好的管理界面。
相关文章:

若依vue3.0表格的增删改查文件封装
一、因若依生成的文件没进行封装,维护起来比较麻烦。所以自己简单的进行封装了一下 gitee代码(文件)地址:https://gitee.com/liu_yu_ting09/ruo_yi.git 二、封装的方法(下面绿色按钮进行全局封装一个JeecgListMixin.js…...
【已解决】如何使用JAVA 语言实现二分查找-二分搜索折半查找【算法】手把手学会二分查找【数据结构与算法】
文章目录 前言任务描述编程要求 输出样例:未查找到11元素! 二、代码实现总结理解不了考试的时候直接背下来就好了。 前言 [TOC]二分搜索 任务描述 折半查找(二分搜索) 设a[low..high]是当前的查找区间,首先确定该区间的中点位置…...
ERROR 1524 (HY000): Plugin ‘mysql_native_password‘ is not loaded
你遇到的错误是由于 MySQL 版本不再默认支持 mysql_native_password 认证插件导致的。从 MySQL 8.0 开始,默认的认证插件是 caching_sha2_password,而不是 mysql_native_password。 解释: 错误 ERROR 1524 (HY000): Plugin mysql_native_pa…...

.NET 6.0 WebAPI 使用JWT生成Token的验证授权
1.引入相关程序包JwtBearer注意版本: 2.配置文件appsettings.json写相关配置参数(也可不写,写在程序里面,数据库读取也是一样的) , //JWT加密"JWTToken": {"SecretKey": "jsaduwqe6asdjewejdue7dfmsdfu0sdfmwmsd8wfsd6",…...

M9410A VXT PXI 矢量收发信机,300/600/1200MHz带宽
M9410A PXI 矢量收发信机 -300/600/1200MHz带宽- M9410A VXT PXI 矢量收发信机,300/600/1200MHz带宽支持 5G 的 PXI 矢量收发信机(VXT)是一个 2 插槽模块,具有 1.2 GHz 的瞬时带宽 主要特点 Keysight M9410A VXT PXIe 矢量收发…...
用工厂模式演示springboot三种注入方式 | @Autowired
背景:看了个demo工厂模式,示例代码的工厂类是new出来的,但是实际项目中都是用springboot框架、bean都是会给容器管理的,所以在思考这个工厂类要交给springboot托管要怎么改。以下是总结笔记 依赖注入 1.工厂类用new实现2.工厂类用…...
es查询语法
查询关键词的含义: match: 用于进行全文搜索,分析查询文本并与倒排索引中的词项进行匹配。 term: 精确匹配,适用于非分析字段,如 keyword 类型。用于查找字段值完全相等的文档。 bool: 组合多个查询条件。可以使用 must…...

LabVIEW提高开发效率技巧----合理使用数据流与内存管理
理使用数据流和内存管理是LabVIEW开发中提高性能和稳定性的关键,特别是在处理大数据或高频率信号时,优化可以避免内存消耗过大、程序卡顿甚至崩溃。 1. 使用 Shift Register 进行内存管理 Shift Register(移位寄存器) 是 LabVIE…...
如何在 ECharts 中设置轴标签
在 ECharts 中,轴标签(Axis Label)是指 X 轴或 Y 轴上的刻度标签,用于显示轴上的数据值或分类名称。你可以通过配置 xAxis(X 轴)或 yAxis(Y 轴)的 axisLabel 属性来设置轴标签的样式…...

怎么用gitee做一个图片仓库,在md文档中用这个图片网络地址,然后显示图片
痛因:我为什么要这样做,呃,我一开始图片都是存本地地址的,放在和这个md文档同级的assets文件夹下面,这样子确实当时很方便,复制粘贴什么也不用管,但是想把这个文档分享给别的人的时候࿰…...

Thinkphp(TP)
1.远程命令执行 /index.php?sindex/think\app/invokefunction&functioncall_user_func_array&vars[0]system&vars[1][]whoami 2.远程代码执行 /index.php?sindex/think\app/invokefunction&functioncall_user_func_array&vars[0]phpinfo&vars[1][]…...
【艾思科蓝】前端框架巅峰对决:React、Vue与Angular的全面解析与实战指南
【JPCS独立出版】第三届能源与动力工程国际学术会议(EPE 2024)_艾思科蓝_学术一站式服务平台 更多学术会议请看:https://ais.cn/u/nuyAF3 引言 在快速发展的前端技术领域,选择合适的框架或库对于项目的成功至关重要。React、Vu…...
IT行业的未来:技术变革与创新的持续推动
IT行业的未来:技术变革与创新的持续推动 随着数字化进程的不断加速,信息技术(IT)行业正迈入一个快速变革的时代。新兴技术如人工智能(AI)、5G、物联网(IoT)和区块链,正在…...
Python PDF转图片自定义输出
PDF转图片自定义输出 一、引入必要库 1 2import fitz import os也可以检查一下版本就是了:print(fitz.__doc__) 上一篇文章已经介绍过要使用的库,和写代码要用到的思路了。我们直接开始: 二、找到文件 首先是我们要获取用户的输入&#x…...
Git 常用操作命令说明
Git 常用操作命令 1. 初始化和克隆仓库 1.1 初始化仓库 git init在当前目录初始化一个新的 Git 仓库。 1.2 克隆仓库 git clone <repository-url>从远程仓库克隆项目到本地。 示例: git clone https://github.com/user/repo.git2. 查看状态和日志 2.1…...

自学前端的正确姿势是...
师傅带进门,修行在个人。 在前端自学成才的道路上,有些人走的很快,有些人却举步维艰。 为什么会这样子呢?因为他们没有掌握自学前端的正确姿势。 在介绍应该要怎样自学前端之前,首先来看下,自学前端容易…...

C/C++语言基础--C++构造函数、析构函数、深拷贝与浅拷贝等等相关知识讲解
本专栏目的 更新C/C的基础语法,包括C的一些新特性 前言 周末休息了,没有更新,请大家见谅哈;构造函数、析构函数可以说便随着C每一个程序,故学构造函数、析构函数是必要的;C语言后面也会继续更新知识点&am…...
json格式互相转换
您提供的字符串已经是一个JSON格式的字符串,但是JSON标准要求键名必须用双引号括起来,而不是单引号。因此,您需要将字符串中的单引号替换为双引号。以下是转换后的JSON字符串: {"图片描述": "高速公路上发生了严重…...
Linux下共享内存详解
共享内存是Linux中一种高效的进程间通信(IPC)方式,它允许多个进程共享同一段内存,从而实现数据的快速传递。共享内存通常比其他IPC机制(如管道或消息队列)更快,因为数据直接存储在内存中&#x…...

MySQL篇(管理工具)
目录 一、系统数据库 二、常用工具 1. mysql 2. mysqladmin 3. mysqlbinlog 4. mysqlshow 5. mysqldump 6. mysqlimport/source 6.1 mysqlimport 6.2 source 一、系统数据库 MySQL数据库安装完成后,自带了一下四个数据库,具体作用如下…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...