还是那一句,vue有手就会,vue3的写法有点像当年写jquery的感觉
vue3 + elementPlus 实现简单的增删改查,多选框批量删除
请求拦截器
import axios from 'axios';
import { ElNotification, ElMessageBox, ElMessage, ElLoading } from 'element-plus';
import { saveAs } from 'file-saver';
import store from '@/store';
import { getToken } from '@/utils/token';
import errorCode from '@/utils/errorCode';
import { isBlobData } from '@/utils/common';
import { encodeURIParams } from '@/utils/strUtil';
import cache from '@/plugins/cache';
let downloadLoadingInstance;
// 是否显示重新登录
export const isReLogin = { show: false };
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时
timeout: 30000,
});
// request拦截器
service.interceptors.request.use(
(config) => {
// 是否需要设置 token
const isToken = (config.headers || {}).isToken === false;
// 是否需要防止数据重复提交
const isRepeatSubmit = (config.headers || {}).repeatSubmit === false;
if (getToken() && !isToken) {
config.headers.AuthToken = `Bearer ${getToken()}`; // 让每个请求携带自定义token 请根据实际情况自行修改
}
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = `${config.url}?${encodeURIParams(config.params)}`;
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
const requestObj = {
url: config.url,
data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
time: new Date().getTime(),
};
const sessionObj = cache.session.getJSON('sessionObj');
if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
cache.session.setJSON('sessionObj', requestObj);
} else {
const s_url = sessionObj.url; // 请求地址
const s_data = sessionObj.data; // 请求数据
const s_time = sessionObj.time; // 请求时间
const interval = 10; // 间隔时间(ms),小于此时间视为重复提交
if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
const message = 'The request is in processing, please do not repeat the same request.';
console.warn(`[${s_url}]: ${message}`);
return Promise.reject(new Error(message));
}
cache.session.setJSON('sessionObj', requestObj);
}
}
return config;
},
(error) => {
console.log(error);
Promise.reject(error);
},
);
// 响应拦截器
service.interceptors.response.use(
(res) => {
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data;
} else {
if (res.data.state === 'S') {
return Promise.resolve(res.data.payload);
} else {
//{"state":"F","errorCode":5001,"error":"User is not exists!"}
// 未设置状态码则默认成功状态
const code = res.data.errorCode;
// 获取错误信息
const msg = res.data.error;
if (code == 4004 || code == 4005 || code == 4006 || code == 4007) {
if (!isReLogin.show) {
isReLogin.show = true;
ElMessageBox.confirm('Login state has been expired, Please re-login!', 'System Info', {
confirmButtonText: 'Re-Login',
cancelButtonText: 'Cancel',
type: 'warning',
})
.then(() => {
isReLogin.show = false;
store.dispatch('LogOut').then(() => {
location.href = import.meta.env.BASE_URL;
});
})
.catch(() => {
isReLogin.show = false;
});
}
return Promise.reject('Please re-login!');
} else {
ElNotification.error({
title: msg,
});
return Promise.reject('error');
}
}
}
return Promise.resolve(res.data.payload);
},
(error) => {
console.log(`err${error}`);
let { message } = error;
ElMessage({
message,
type: 'error',
duration: 5 * 1000,
});
return Promise.reject(error);
},
);
// 通用下载方法
export function download(url, params, filename) {
downloadLoadingInstance = ElLoading.service({ text: '正在下载数据,请稍候', background: 'rgba(0, 0, 0, 0.7)' });
return service
.post(url, params, {
transformRequest: [(params) => encodeURIParams(params)],
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
responseType: 'blob',
})
.then(async (data) => {
const isLogin = await isBlobData(data);
if (isLogin) {
const blob = new Blob([data]);
saveAs(blob, filename);
} else {
const resText = await data.text();
const rspObj = JSON.parse(resText);
const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode.default;
ElMessage.error(errMsg);
}
downloadLoadingInstance.close();
})
.catch((r) => {
console.error(r);
ElMessage.error('下载文件出现错误,请联系管理员!');
downloadLoadingInstance.close();
});
}
export default service;
api
import request from '@/utils/request';
export function addAccountSettingsSubscribeType(data) {
return request({
url: '/dic/common/accountSettingsSubscribeType',
method: 'post',
data
});
}
export function removeAccountSettingsSubscribeType(data) {
return request({
url: `/dic/common/accountSettingsSubscribeType` ,
method: 'delete',
data
});
}
export function updateAccountSettingsSubscribeType(data) {
return request({
url: `/dic/common/accountSettingsSubscribeType/` + data.id,
method: 'put',
data,
});
}
export function getAccountSettingsSubscribeType(data) {
return request({
url: `/dic/common/accountSettingsSubscribeType/` + data,
method: 'get'
});
}
export function getAccountSettingsSubscribeTypeList(data) {
return request({
url: '/dic/common/accountSettingsSubscribeType/findPage' + data,
method: 'get',
data
});
}
功能管理
<template>
<div>
<div class="card-wrap" style="padding: 0 12px;">
<el-form :model="state.queryParams" ref="queryRef" :inline="true" class="form-search-wrap">
<el-form-item label="code">
<el-input v-model="state.queryParams.code" clearable style="width: 240px" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="getList()">Search</el-button>
<el-button icon="Refresh" @click="resetSearchForm">Reset</el-button>
</el-form-item>
</el-form>
</div>
<div class="card-wrap" style="padding-bottom: 100px;">
<div class="operation-wrap">
<el-button type="primary" @click="handleEdit(null, 1)">Add</el-button>
<el-button type="danger" @click="batchRemove" >Remove</el-button>
</div>
<el-table :data="state.tableData"
v-loading="state.loading"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column prop="code" label="Code"></el-table-column>
<el-table-column prop="value" label="Value"></el-table-column>
<el-table-column prop="i18n" label="I18n"></el-table-column>
<el-table-column label="Operation" align="center">
<template #default="scope">
<el-button type="primary" icon="Edit" @click="handleEdit(scope.row, 0)" circle />
<el-button type="danger" icon="Delete" @click="remove(scope.row.id, 0)" circle />
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="state.queryParams.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="state.queryParams.size"
layout="total, sizes, prev, pager, next, jumper"
:total="state.queryParams.total">
</el-pagination>
</div>
</div>
<el-dialog :title="state.type?'add':'update'" v-model="state.dialogVisible" width="30%" destroy-on-close @close='resetForm'>
<el-form ref="addForm" :rules="state.rules" :model="state.addFormField" label-width="100px">
<el-form-item label="code" prop="code">
<el-input v-model="state.addFormField.code" style="width: 380px;" ></el-input>
</el-form-item>
<el-form-item label="value" prop="value">
<el-input v-model="state.addFormField.value" style="width: 380px;" ></el-input>
</el-form-item>
<el-form-item label="i18n" prop="i18n">
<el-input v-model="state.addFormField.i18n" style="width: 380px;" ></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="state.dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="add">Confirm</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { reactive, ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import * as api from '@/api/dic/accountSettingsSubscribeType';
const addForm = ref();
const state = reactive({
multipleSelection: [],
dialogVisible: false,
num: 1,
loading: false,
type: "add",
tableData: [],
addFormField: {
id: "",
code: "",
value: "",
i18n: "",
},
queryParams: {
code: undefined,
page: 1,
size: 10,
total: 0,
},
rules: {
code: [
{ required: "true", message: "code is not empty", trigger: ["change"] },
],
value: [
{ required: "true", message: "value is not empty", trigger: ["change"] },
],
i18n: [
{ required: "true", message: "i18n is not empty", trigger: ["change"] },
],
},
});
function handleSelectionChange(val) {
state.multipleSelection = val
}
function commonRemove(idList) {
ElMessageBox.confirm('Are you sure to remove this data?')
.then(() => {
api
.removeAccountSettingsSubscribeType({idList: idList})
.then((res) => {
})
.finally(() => {
state.loading = false;
});
ElMessage.success("success");
setTimeout(() => {
getList();
}, 300);
})
getList();
}
function remove(id){
let idList = [];
idList.push(id)
commonRemove(idList);
}
function batchRemove() {
if(state.multipleSelection == undefined || state.multipleSelection.length <= 0){
ElMessage.warning("Please select checkbox");
return;
}
let idList = [];
state.multipleSelection.forEach((value, index) => {
idList.push(value.id)
});
commonRemove(idList);
}
function handleEdit(row, type){
if(row){
state.addFormField = JSON.parse(JSON.stringify(row));
}
if (type) {
state.type = true;
} else{
state.type = false;
}
state.dialogVisible = true;
}
function resetForm(){
state.addFormField = {
id: undefined,
code: undefined,
value: undefined,
i18n: undefined,
}
}
function resetSearchForm(){
state.queryParams.code = undefined;
}
function add(){
addForm.value.validate((valid) => {
if (valid) {
let id = state.addFormField.id;
if (id) {
api
.updateAccountSettingsSubscribeType(state.addFormField)
.then((res) => {
ElMessage.success("success");
})
.finally(() => {
state.loading = false;
});
}else{
api
.addAccountSettingsSubscribeType(state.addFormField)
.then((res) => {
ElMessage.success("success");
})
.finally(() => {
state.loading = false;
});
}
resetForm();
state.dialogVisible = false;
setTimeout(() => {
getList();
}, 200);
} else {
return false;
}
});
}
function getList(){
state.loading = true;
let data = {};
if(state.queryParams){
data = JSON.stringify(state.queryParams).replace(/:/g, '=').replace(/,/g, '&').replace(/{/g, '?').replace(/}/g, '').replace(/"/g, '');
}
api
.getAccountSettingsSubscribeTypeList(data)
.then((res) => {
state.tableData = res.items;
state.queryParams.page = res.page;
state.queryParams.size = res.size;
state.queryParams.total = res.total;
})
.finally(() => {
state.loading = false;
});
}
function handleSizeChange(val){
state.queryParams.size = val;
getList();
}
function handleCurrentChange(val){
state.queryParams.page = val;
getList();
}
getList();
</script>
<style scoped >
/deep/ .el-overlay-dialog{
top:25%
}
.pagination {
background: #fff;
padding: 20px 10px 0;
display: flex;
justify-content: flex-end;
box-sizing: border-box;
}
.card-wrap{
padding: 15px 20px 20px 20px;
border-radius: 4px;
border: 1px solid #e6ebf5;
background-color: #fff;
overflow: hidden;
color: #303133;
-webkit-transition: .3s;
transition: .3s;
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
margin: 10px;
}
.operation-wrap{
margin: 0 0 16px 0;
}
.form-search-wrap{
margin: 10px 0 0 12px;
}
</style>
今天水一篇,祝各位大佬 1024程序员节快乐~