vue3-后台开发模板
·
效果图


api.js
import axios from "axios";
//创建一个axios实例
let api = axios.create({
baseURL: "/api",
timeout: 3000
});
export default api;
vue开发模板
<template>
<!-- 搜索条件 -->
<div class="search">
<el-form :model="searchForm" inline ref="searchRef">
<el-form-item label="编号:" prop="id">
<el-input v-model="searchForm.id" placeholder="请输入编号" />
</el-form-item>
<el-form-item label="名称:" prop="name">
<el-input v-model="searchForm.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="时间:" prop="time">
<el-date-picker v-model="searchForm.time" value-format="YYYY-MM-DD" type="daterange" unlink-panels
range-separator="到" start-placeholder="开始时间" end-placeholder="截至时间" />
</el-form-item>
<el-form-item label="分类:" prop="sort">
<el-select name="sort" id="sort" style="width: 140px" v-model="searchForm.sort" placeholder="请选择分类">
<el-option label="不限" value="" />
<el-option v-for="item in sortList" :key="item.id" :label="item.name" :value="item.id"
:disabled="item.disabled" />
</el-select>
</el-form-item>
</el-form>
</div>
<!-- 操作区域 -->
<div class="action" style="display: flex; align-items: center; justify-content: space-between;">
<div>
<el-button type="primary" :icon="Search" solid @click="search()">查询</el-button>
<el-button type="success" :icon="CirclePlus" @click="add" solid>添加</el-button>
<el-button type="warning" :icon="Edit" @click="edit" solid>编辑</el-button>
<el-button type="danger" :icon="Delete" @click="remove" solid>删除</el-button>
<el-button type="info" :icon="Refresh" @click="reset" solid>重置</el-button>
</div>
<el-radio-group v-model="viewType" size="small">
<el-radio-button label="formView">
<div class="radio-content">
<el-icon>
<Grid />
</el-icon>
<span>卡片视图</span>
</div>
</el-radio-button>
<el-radio-button label="tblView">
<div class="radio-content">
<el-icon>
<Plus />
</el-icon>
<span>表格视图</span>
</div>
</el-radio-button>
</el-radio-group>
</div>
<!-- 显示区域 -->
<div class="grid" v-show="viewType === 'formView'">
<el-table :data="tblDate" border @row-click="tblRowClick" ref="tblRef" :row-class-name="tblRowClassName">
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="头像" fixed width="100">
<template #default="scope">
<div :style="'background-image: url(' + (baseUrl + scope.row.avatar) + ')'"></div>
</template>
</el-table-column>
<el-table-column label="编号" prop="id" />
<el-table-column label="操作" width="160" align="center" fixed="right">
<template #default="scope">
<el-button type="primary" size="small" @click.stop="editRow(scope.row)">编辑</el-button>
<el-button type="danger" size="small" @click.stop="removeRow(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="card" v-show="viewType === 'tblView'">
<div class="card-container">
<el-card shadow="hover" class="data-card" v-for="item in tblDate" :key="item.id">
<template #header>
<div class="card-header">
<div class="card-title-section">
<el-checkbox v-model="item.name"></el-checkbox>
<span class="card-title">{{ item.name }}</span>
</div>
<div class="card-actions">
<el-button @click="editRow(item)" type="text">编辑</el-button>
<span class="divider">|</span>
<el-button @click="removeRow(item)" type="text" class="card-remove">删除</el-button>
</div>
</div>
</template>
<el-form :model="item" label-position="left" label-width="50px">
<el-form-item label="编号:">
<el-input v-model="item.id" readonly />
</el-form-item>
<el-form-item label="名称:">
<el-input v-model="item.name" readonly />
</el-form-item>
<el-form-item label="分类">
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<el-tag v-for="(sort, index) in item.sort" :key="index">
{{ sort }}
</el-tag>
</div>
</el-form-item>
</el-form>
</el-card>
</div>
</div>
<!-- 分页区域 -->
<div class="pagination">
<el-pagination v-model:current-page="pi.currentPage" v-model:page-size="pi.pageSize" ref="piDRef"
layout="total, prev, pager, next" :total="pi.total" @change="search" />
</div>
<!-- 对话框 -->
<div class="dialog">
<el-dialog v-model="dlgVisible" :title="dlgName" width="30%" align-center draggable @close="resetDlg">
<el-form ref="dlgTblRef" :model="dlgTblForm" label-width="80px" :rules>
<el-row>
<el-col :span="16">
<el-form-item label="编号" prop="id">
<el-input v-model="dlgTblForm.id" placeholder="请输入编号"></el-input>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="dlgTblForm.name" placeholder="请输入名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-upload class="avatar" action="/avatar" :on-success="uploadSuccess" :show-file-list="false"
:headers="headers">
<div class="img" v-if="dlgTblForm.avatar" :style="'background-image: url(' + (dlgTblForm.avatar) + ')'">
</div>
<el-icon v-else class="icon">
<Plus />
</el-icon>
</el-upload>
</el-col>
</el-row>
<el-form-item label="描述" prop="description">
<el-input type="textarea" v-model="dlgTblForm.description" :rows="4" placeholder="请输入描述" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dlgVisible = false">取消</el-button>
<el-button type="primary" @click="doSubmit()">确定</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { onMounted, ref, reactive, toRaw } from 'vue';
import { Search, CirclePlus, Edit, Delete, Refresh, Plus, Grid } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus';
import api from '@/util/api'
onMounted(() => {
//初始化操作
// search()
// searchSort()
})
//===============================================视图===============================
let viewType = ref('formView')
function tblRowClassName({ row, rowIndex }) {
switch (row.status) {
case 0:
return 'danger-row';
case 1:
return 'warning-row';
case 2:
return 'success-row';
default:
return '';
}
}
//===============================================查询相关===============================
//搜索条件
let searchForm = ref({
id: null,
time: null,
sort: null,
})
//单选框数据
let sortList = ref([])
//表格数据
let tblDate = ref()
tblDate.value = [
{ id: 1, name: 'n1', sort: ['s1', 's2', 's3'], status: 1 },
{ id: 2, name: 'n2', sort: ['s1', 's2', 's3'], status: 0 },
{ id: 3, name: 'n3', sort: ['s1', 's2', 's3'], status: 1 },
{ id: 4, name: 'n4', sort: ['s1', 's2', 's3'], status: 2 },
]
//分页信息
let pi = ref({
currentPage: 1,
pageSize: 5,
total: 10,
})
//条件查询
async function search(currentPage = 1, pageSize = 10) {
let searchBean = toRaw(searchForm)
if (searchBean.time) {
searchBean.beginTime = searchBean.time[0]
searchBean.endTime = searchBean.time[0]
delete searchBean.time
}
let resp = await api({
url: "/list",
method: "get",
params: {
currentPage,
pageSize,
...searchForm
}
})
if (resp.success) {
tblDate.value = resp.data
pi.total.value = resp.data.total
} else {
ElMessage.error(resp.msg)
}
}
//种类查询
async function searchSort() {
let resp = await api({
url: "/sortList",
method: "get",
params: {
}
})
if (resp.success) {
sortList.value = resp.data.records
pi.currentPage = resp.data.current
pi.pageSize = resp.data.size
pi.total = resp.data.total
} else {
ElMessage.error(resp.msg)
}
}
//重置查询条件
function reset() {
searchForm.value.resetFields();
}
//===================================================选中================================
//行响应对象
let tblRef = ref()
//行选中/取消
function tblRowClick(row) {
tblRef.value.toggleRowSelection(row)
}
//===================================================删除=================================
//操作区删除
function remove() {
let rows = tblRef.value.getSelectionRows();
if (rows.length === 0) {
ElMessage.warning("请选中数据后进行操作!");
} else {
ElMessageBox.confirm("是否删除当前选中的数据", "警告", {
cancelButtonText: "取消",
confirmButtonText: "确定",
type: "warning"
}).then(() => {
let ids = rows.map(it => it.id);
removeByIds(ids);
}).catch(() => {
ElMessage.success("取消删除");
})
}
}
//行信息删除
function removeRow(row) {
ElMessageBox.confirm("是否删除当前选中的数据", "警告", {
cancelButtonText: "取消",
confirmButtonText: "确定",
type: "warning"
}).then(() => {
let ids = toRaw(row).id
removeByIds([ids]);
}).catch(() => {
ElMessage.success("取消删除");
})
}
//实际删除
async function removeByIds(ids) {
let resp = await api({
url: "/delete",
method: "delete",
data: ids,
})
if (resp.success) {
console.log(resp)
ElMessage.success(resp.msg)
} else {
ElMessage.error(resp.msg || ("删除数据失败,请重新尝试"));
}
search(pi.currentPage, pi.pageSize);
}
//====================================================添加/编辑==========================
//对话框是否显示
let dlgVisible = ref(false)
//对话框标题
let dlgName = ref('对话框标题')
//对话框表单
let dlgTblForm = ref({
id: null,
name: null,
avatar: null,
description: null,
})
//显示添加对话框
function add() {
dlgName.value = "添加数据"
dlgVisible.value = true;
}
//显示编辑对话框 + 数据回显
function edit() {
dlgName.value = "编辑数据"
let editRow = tblRef.value.getSelectionRows();
if (editRow.length === 0) {
ElMessage.warning("请选中您要修改的行");
} else if (editRow.length !== 1) {
ElMessage.warning("您仅能选中一条数据");
} else {
dlgVisible.value = true;
nextTick(() => {
dlgTblForm.value = cloneDeep(toRaw(editRow[0]));
})
}
}
function editRow(row) {
dlgName.value = "编辑数据";
dlgVisible.value = true;
nextTick(() => {
depTblForm.value = cloneDeep(toRaw(row));
})
}
//点击提交
function doSubmit() {
if (dlgName.value === "添加数据") {
submitAdd()
} else if (dlgName.value === "编辑数据") {
submitEdit()
}
}
//添加数据
async function submitAdd() {
let formInfo = toRaw(dlgTblForm.value)
let resp = await api({
url: "/add",
method: "post",
data: {
...formInfo
}
})
if (resp.success) {
dlgVisible.value = false
ElMessage.success(resp.msg)
dlgTblForm.value.resetFields();
search(pi.currentPage, pi.pageSize)
} else {
ElMessage.error(resp.msg)
}
}
//添加数据
async function submitEdit() {
let formInfo = toRaw(dlgTblForm.value)
let resp = await api({
url: "/edit",
method: "post",
data: {
...formInfo
}
})
if (resp.success) {
dlgVisible.value = false
ElMessage.success(resp.msg)
dlgTblForm.value.resetFields();
search(pi.currentPage, pi.pageSize)
} else {
ElMessage.error(resp.msg)
}
}
//===================================================图片上传===============================
import baseUrl from "@/util/constant.js"
import { getJwt } from "@/api/jwt.js";
//设置返回头信息
const headers = {
"Authorization": getJwt()
}
function uploadSuccess(resp) {
let url = baseUrl + resp.data;
dlgTblForm.value.avatar = url;
}
</script>
<style>
.el-table .warning-row {
background-color: #fff9e6;
}
.el-table .danger-row {
background-color: #ffeeea;
}
.el-table .success-row {
background-color: #f0f9ff;
}
</style>
<style scoped>
/* ==================================视图=========================== */
.radio-content {
display: flex;
align-items: center;
gap: 4px;
}
/* =================================卡片============================== */
.card-container {
display: flex;
flex-wrap: wrap;
gap: 2%;
}
.data-card {
flex: 0 1 calc(32.9% - 1%);
margin-bottom: 20px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-title-section {
display: flex;
align-items: center;
gap: 10px;
}
.card-remove {
color: #F56C6C;
}
.divider {
color: #dcdfe6;
margin: 0 8px;
}
/* ===================================图片============================== */
.avatar {
width: 80px;
height: 80px;
border: 1px dashed #ccc;
border-radius: 4px;
margin-left: 8px;
display: flex;
}
.avatar .icon {
font-size: 28px;
justify-content: center;
align-items: center;
}
.avatar .img {
width: 80px;
height: 80px;
background-repeat: no-repeat;
background-size: contain;
background-position: center center;
}
</style>更多推荐


所有评论(0)