vue&element项目实战 之element使用&用户&字典模块实现
6.用户模块
用户模块api
import request from '@/utils/request'
export function login(data) {
return request({
url: '/sys-user/login',
method: 'post',
data
})
}export function getInfo(token) {
return request({
url: '/sys-user/queryUserInfo',
method: 'get',
params: { token }
})
}
// 退出登录
export const logout = () => request({ url: '/sys-user/logout', method: 'post' })// 获取用户列表
export const queryList = (param) => request({ url: '/sys-user/queryList', params: param, method: 'post' })// 修改或更新用户
export const updateOrSave = (param) => request({ url: '/sys-user/updateOrSave', params: param, method: 'post' })// 修改或更新用户
export const deleteUser = (id) => request({ url: `/sys-user/delete?id=${id}`, method: 'post' })
用户模块代码
<template>
<div>
<span>
更新时间:
<el-date-picker
v-model="time"
type="daterange"
range-separator="至"
start-placeholder="开始"
end-placeholder="结束"
size="default"
/>
</span>
<span v-for="(item, index) in infoArray" :key="index">
{{ item.label }}:
<el-select v-model="queryParam[item.value]" class="m-2" placeholder="请选择">
<el-option v-for="item in infolist[item.value]" :key="item.value" :label="item.text" :value="item.value" />
</el-select>
</span>
<el-button type="primary" @click="queryList()">查询</el-button>
<el-button type="primary" @click="showDialog()">新增</el-button>
<el-table :data="tableData" border style="width: 100%">
<template v-for="(item, index) in columnList">
<el-table-column :key="index" :prop="item.field" :label="item.title" :width="item.width">
<template slot-scope="scope">
<span> {{ scope.row[item.field] | qxSelffilter(item.value) }}</span>
</template>
</el-table-column>
</template> <el-table-column label="操作">
<template slot-scope="{row,$index}">
<el-button type="primary" @click="updateShowDialog(row)">
修改
</el-button>
<el-button type="danger" @click="deleteUser(row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 20px; text-align: center"
:current-page="queryParam.currentPage"
:page-size="queryParam.pageSize"
:page-sizes="[3, 5, 10, 20]"
:total="total"
:pager-count="5"
layout=" prev, pager, next , total,sizes"
@size-change="handleSizeChange"
@current-change="goPage"
/>
<!-- 弹框
:visible.sync:控制对话框显示与隐藏用的
Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可
-->
<el-dialog :visible.sync="dialogFormVisible" :title="dialogName">
<el-form ref="ruleForm" :model="form" :rules="rules">
<el-form-item label="账号" prop="userName">
<el-input v-model="form.userName" autocomplete="off" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="form.password" autocomplete="off" />
</el-form-item>
<!-- 下拉选项
item: { label: "用户状态", value: "status", enumType: "status" },
obj: {"enumType":"status","value":"0","text":"启用"}
-->
<span v-for="(item, index) in infoArray" :key="index">
<el-form-item :label="item.label" :prop="item.value">
<el-select v-model="form[item.value]" class="m-2" placeholder="请选择">
<el-option
v-for="obj in infolist[item.value]"
:key="obj.value"
:label="obj.text"
:value="item.String ? obj.value : Number(obj.value)"
/>
</el-select>
</el-form-item>
</span>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import { EnumUtility } from '@/utils/EnumUtility'
import * as DateUtil from '@/utils/DateUtil'
export default {
name: 'UserInfo',
data() {
const _startTime = DateUtil.ToString(
DateUtil.AddDays(new Date(), -7),
'yyyy-MM-dd'
)
const _endTime = DateUtil.ToString(new Date(), 'yyyy-MM-dd')
// 自定义校验规则
var validateUserName = (rule, value, callback) => {
// 自定义校验规则
if (value.length < 6 || value.length > 10) {
callback(new Error('登录账号6-10位'))
} else {
callback()
}
}
return {
// 时间选择器
time: [_startTime, _endTime],
// 下拉选择属性
infoArray: [
/*
* label:下拉选项的标题,如:用户状态
* value: 选择值列表 与 传到 服务端的字段: 如:status=30
* enumType:从字典=>枚举 中的下拉选项映射值 , 枚举值赋值是在创建vue对象后,即方法中实现的
*/
{ label: '用户状态', value: 'status', enumType: 'status' },
{ label: '用户类型', value: 'type', enumType: 'user_type' }
],
// 下拉选项值
/* 枚举中完成赋值的status,type*/
infolist: {},
// 列表查询参数
queryParam: {
currentPage: 1,
pageSize: 10,
startTime: _startTime,
endTime: DateUtil.ToString(
DateUtil.AddDays(_endTime, +1),
'yyyy-MM-dd'
)
},
// 列表数据
tableData: [],
total: 0,
// 列字段
columnList: [
{ title: '编号', field: 'id' },
{ title: '账号', field: 'userName' },
{ title: '类型', field: 'type', value: { enum: 'user_type' }},
{ title: '状态', field: 'status', value: { enum: 'status' }},
{ title: '备注', field: 'remark' },
{
title: '更新时间',
field: 'updateTime',
value: { date: 'MM-dd hh:mm:ss' }
},
{
title: '创建时间',
field: 'createTime',
value: { date: 'MM-dd hh:mm:ss' }
}
],
dialogFormVisible: false, // 是否显示弹框
dialogName: '', // 弹框标题 如:新增用户 或 修改 用户
form: { // 新增 或 修改表单数据
},
rules: {
// 品牌名称的验证规则
// require:必须要校验字段(前面五角星有关系) message 提示信息 trigger:用户行为设置(事件的设置:blur、change)
// tmName 对应表单上的prop的名称必须一致 <el-form-item label="品牌名称" :label-width="formLabelWidth" prop="tmName">
userName: [
{ required: true, message: '必须输入登录账号', trigger: 'blur' },
// { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' },
// 自定义校验规则
{ validator: validateUserName, trigger: 'change' }
],
password: [{ required: true, message: '请输入密码' }],
status: [{ required: true, message: '请选择状态' }],
type: [{ required: true, message: '请选择类型' }]
}
}
},
watch: {
time(val) {
if (!val) {
// 参数为空时清空数据
this.queryParam.startTime = ''
this.queryParam.endTime = ''
}
if (val && val.length > 0) {
this.queryParam.startTime = DateUtil.ToString(val[0], 'yyyy-MM-dd')
this.queryParam.endTime = DateUtil.ToString(
DateUtil.AddDays(val[1], +1),
'yyyy-MM-dd'
)
}
}
},
mounted() {
// this.queryList()
},
created() {
// 给枚举赋值
const enumUtility = new EnumUtility()
this.infoArray.forEach((element) => {
if (element.enumType) {
// 枚举数据结构 [{"enumType":"status","value":"0","text":"启用"},{"enumType":"status","value":"1","text":"禁用"}]
console.log('element.enumType=', element.enumType)
console.log('enumUtility.Get(element.enumType)', enumUtility.Get(element.enumType))
this.infolist[element.value] = enumUtility.Get(element.enumType)
}
})
},
methods: {
async queryList() {
const result = await this.$api.user.queryList(this.queryParam)
if (result.code == '100') {
this.tableData = result.data.list
this.total = result.data.total
}
},
goPage(currentPage) {
this.queryParam.currentPage = currentPage
this.queryList()
},
handleSizeChange(pageSize) {
this.queryParam.pageSize = pageSize
this.queryParam.currentPage = 1
this.queryList()
},
showDialog() {
// console.log('显示弹框')
this.dialogName = '添加用户'
this.form = {}
this.dialogFormVisible = true
},
updateShowDialog(row) {
this.dialogName = '修改用户'
this.form = { ...row }
// 显示对话框
this.dialogFormVisible = true
},
submitForm() {
// 当全部验证字段通过,再去书写业务逻辑
this.$refs.ruleForm.validate(async(success) => {
if (success) {
const result = await this.$api.user.updateOrSave(this.form)
if (result.code == '100') {
// 关闭窗口
this.dialogFormVisible = false
// 查询数据
this.queryList()
}
} else {
console.log('检查提交参数')
return false
}
})
},
deleteUser(row) {
// 弹框
this.$confirm(`你确定删除:${row.userName}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async() => {
// 当用户点击确定按钮的时候会出发
// 向服务器发请求
const result = await this.$api.user.deleteUser(row.id)
// 如果删除成功
if (result.code == '100') {
this.$message({
type: 'success',
message: '删除成功!'
})
// 再次获取品牌列表数据
this.queryList()
}
})
.catch(() => {
// 当用户点击取消按钮的时候会触发
this.$message({
type: 'info',
message: '已取消删除'
})
})
}
}
}
</script> <style lang="scss"></style>
管道过滤器配置
// 全局过滤器要放在Vue实例化代码前面,不然会报错
// eslint-disable-next-line no-unused-vars
import qxfilter from '@/utils/filter/filter'
引入时间格式依赖
"moment": "^2.29.1"
页面显示
7.字典模块
编辑弹框
<template>
<el-dialog
:title="ruleForm.dialogName"
:visible.sync="showEdit"
:close-on-click-modal="false"
width="550px"
center
@close="close"
>
<el-form
ref="ruleForm"
:model="ruleForm"
:rules="rules"
label-width="100px"
class="flex flex_center"
>
<el-form-item
v-for="item in ruleList"
:key="item.title"
:label="item.title"
:prop="item.field"
>
<el-input
v-if="!item.option"
v-model="ruleForm[item.field]"
:type="item.type"
clearable
:disabled="item.field == 'enumType' && ruleForm.id"
placeholder="请输入"
/>
<el-select
v-else
v-model="ruleForm[item.field]"
filterable
placeholder="请选择"
>
<el-option
v-for="(it, Index) in infolist[item.option]"
:key="Index"
:label="it.text"
:value="Number(it.value)"
/>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button type="danger" @click="close()">取消</el-button>
</span>
</el-dialog>
</template> <script>
export default {
props: {
showEdit: Boolean,
infolist: Object,
ruleForm: Object
},
data() {
return {
ruleList: [
{ title: '字典类型', field: 'enumType' },
{ title: '字典值', field: 'value' },
{ title: '显示名称', field: 'text' },
{ title: '排序编号', field: 'shortNo', type: 'number' },
{ title: '状态', field: 'status', option: 'status' }
],
rules: {}
}
},
computed: {},
watch: {
ruleForm(val) {
// 监听变化的值,及时校验输入看数据
if (!this.ruleForm.id && this.$refs['ruleForm']) {
this.resetForm('ruleForm')
}
}
},
created() {
this.ruleList.forEach((element) => {
this.rules[element.field] = [
{ required: true, message: `${element.title}不能为空` }
]
})
},
mounted() {},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
// valid 表示输入框的校验结果,校验通过返回true
if (valid) {
this.saveOrUpdateDic()
} else {
return false
}
})
},
async saveOrUpdateDic() {
const result = await this.$api.dic.saveOrUpdateDic(this.ruleForm)
if (result.code === '100') {
// 成功消息提示
this.$message.success('添加成功')
// 关闭窗口
this.close('insert')
} else {
if (result.message) this.$message.error(result.message)
}
},
resetForm(formName) {
this.$refs[formName].resetFields()
},
// 关闭弹框
close(val) {
const data = { name: 'showEdit', isRefresh: val }
// 子组件向父组件通信
this.$emit('close', data)
this.resetForm('ruleForm')
}
}
}
</script>
<style scoped>
</style>
列表页面
<template>
<div>
<span v-for="(item, index) in infoArray" :key="index">
{{ item.label }}:
<el-select
v-model="queryParam[item.value]"
class="m-2"
placeholder="请选择"
>
<el-option
v-for="item in infolist[item.value]"
:key="item.value"
:label="item.text"
:value="item.value"
/>
</el-select>
</span>
<span v-for="item in infoInput" :key="item.value" class="info">
<el-input
v-model="queryParam[item.value]"
:placeholder="item.placeholder"
>
<i slot="prefix" class="el-input__icon el-icon-search" />
</el-input>
</span>
<el-button type="primary" @click="queryList()">查询</el-button>
<el-button type="primary" @click="showDialog()">新增</el-button>
<el-table :data="tableData" border style="width: 100%">
<template v-for="(item, index) in columnList">
<el-table-column
:key="index"
:prop="item.field"
:label="item.title"
:width="item.width"
>
<template slot-scope="scope">
<span> {{ scope.row[item.field] | qxSelffilter(item.value) }}</span>
</template>
</el-table-column>
</template> <el-table-column label="操作">
<template slot-scope="{ row, $index }">
<el-button type="primary" @click="updateShowDialog(row)">
修改
</el-button>
<el-button type="danger" @click="deleteUser(row)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
<edit-model
:show-edit="dialogFormVisible"
:infolist="infolist"
:rule-form="itemEdit"
@close="CloseShow"
/>
</div>
</template>
<script>
import EditModel from './model/EditModel.vue'
export default {
name: 'DicInfo',
components: { EditModel },
data() {
return {
// 下拉选择属性
infoArray: [
/*
* label:下拉选项的标题,如:用户状态
* value: 选择值列表 与 传到 服务端的字段: 如:status=30
* enumType:从字典=>枚举 中的下拉选项映射值 , 枚举值赋值是在创建vue对象后,即方法中实现的
*/
{ label: '字典状态', value: 'status', enumType: 'status' }
],
infoInput: [
/* infoInput:输入框数据 */
{ placeholder: '输入:字典类型', value: 'enumType' },
{ placeholder: '输入:显示名称', value: 'text' }
],
// 下拉选项值
/* 枚举中完成赋值的status,type*/
infolist: {
status: [
{ enumType: 'status', value: '0', text: '启用' },
{ enumType: 'status', value: '1', text: '禁用' }
]
},
// 列表查询参数
queryParam: {},
// 列表数据
tableData: [],
// 列字段
columnList: [
{ title: '编号', field: 'id' },
{ title: '字典类型', field: 'enumType' },
{ title: '字典值', field: 'value' },
{ title: '显示名称', field: 'text' },
{ title: '排序编号', field: 'shortNo' },
{ title: '状态', field: 'status', value: { enum: 'status' }},
{
title: '更新时间',
field: 'updateTime',
value: { date: 'MM-dd hh:mm:ss' }
},
{
title: '创建时间',
field: 'createTime',
value: { date: 'MM-dd hh:mm:ss' }
}
],
dialogFormVisible: false, // 是否显示弹框
itemEdit: {
dialogName: '修改字典' // 弹框标题 如:新增用户 或 修改 用户
}, // 编辑或修改的字段,如name, idd等
rules: {
// 品牌名称的验证规则
// require:必须要校验字段(前面五角星有关系) message 提示信息 trigger:用户行为设置(事件的设置:blur、change)
// tmName 对应表单上的prop的名称必须一致 <el-form-item label="品牌名称" :label-width="formLabelWidth" prop="tmName">
userName: [
{ required: true, message: '必须输入登录账号', trigger: 'blur' }
],
password: [{ required: true, message: '请输入密码' }],
status: [{ required: true, message: '请选择状态' }],
type: [{ required: true, message: '请选择类型' }]
}
}
},
watch: {},
mounted() {
// this.queryList()
},
created() {
// 给枚举赋值 { label: "字典状态", value: "status", enumType: "status" },
// let enumUtility = new EnumUtility();
// this.infoArray.forEach((element) => {
// if (element.enumType) {
// 枚举数据结构 [{"enumType":"status","value":"0","text":"启用"},{"enumType":"status","value":"1","text":"禁用"}]
// this.infolist[element.value] = enumUtility.Get(element.enumType);
// }
// });
},
methods: {
async queryList() {
const result = await this.$api.dic.getDicList(this.queryParam)
if (result.code == '100') {
this.tableData = result.data
}
},
goPage() {
this.queryList()
},
showDialog() {
// console.log('显示弹框')
this.dialogFormVisible = true
this.itemEdit = {
enumType: '',
value: '',
text: '',
status: '',
shortNo: '',
dialogName: '添加字典'
}
},
updateShowDialog(row) {
this.itemEdit = { ...row }
this.itemEdit['dialogName'] = '修改字典'
// 显示对话框
this.dialogFormVisible = true
},
submitForm() {
// 当全部验证字段通过,再去书写业务逻辑
this.$refs.ruleForm.validate(async(success) => {
if (success) {
const result = await this.$api.user.updateOrSave(this.form)
// eslint-disable-next-line eqeqeq
if (result.code == '100') {
// 关闭窗口
this.dialogFormVisible = false
// 查询数据
this.queryList()
}
} else {
console.log('检查提交参数')
return false
}
})
},
deleteUser(row) {
// 弹框
this.$confirm(`你确定删除字典:${row.enumType}?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async() => {
// 当用户点击确定按钮的时候会出发
// 向服务器发请求
const result = await this.$api.dic.deleteDic(row.id)
// 如果删除成功
if (result.code == '100') {
this.$message({
type: 'success',
message: '删除成功!'
})
// 再次获取品牌列表数据
this.queryList()
}
})
.catch(() => {
// 当用户点击取消按钮的时候会触发
this.$message({
type: 'info',
message: '已取消删除'
})
})
},
CloseShow(data) {
// console.log(data);
// 关闭对话
this.dialogFormVisible = false
if (data.isRefresh == 'update') {
this.queryList() // 更新的情况
}
if (data.isRefresh == 'insert') {
this.queryList() // 新增的情况
}
}
}
}
</script> <style lang="scss">
</style>
页面显示
8.打包部署
打包:
将dist文件压缩上传到nginx配置的路径下
如果,nginx不熟悉,可以学习我们之前专门讲解的nginx课程
这里给出nginx在Windows下的常用命令,实际开发中nginx都是部署在linux上的,但是我们自己学习一般是在windows上操作,本质上是一样的
1.启动
start nginx
2.停止
taskkill /f /t /im nginx.exe
# 卡券后台管理系统
upstream couponAdminApi{
server 127.0.0.1:6001;
#server 127.1.2.51:6001; # 负载均衡配置
}
server {
listen 6002;
server_name localhost;
location / {
root F:\vue\kecheng\webhome\quanyi; #vue打包后的项目地址
index index.html index.htm;
}
location /prod-api/ {
# return 500;
proxy_set_header Host pro.ldp.com;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Real_IP $remote_addr;
proxy_pass http://couponAdminApi/;
}
}
部署好后,重启nginx,访问
http://localhost:6002/
完美!
vue&element项目实战 之element使用&用户&字典模块实现的更多相关文章
- 新书上线:《Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统》,欢迎大家买回去垫椅子垫桌脚
新书上线 大家好,笔者的新书<Spring Boot+Spring Cloud+Vue+Element项目实战:手把手教你开发权限管理系统>已上线,此书内容充实.材质优良,乃家中必备垫桌脚 ...
- 循序渐进VUE+Element 前端应用开发(15)--- 用户管理模块的处理
在前面随笔介绍了ABP+Vue前后端的整合处理,包括介绍了ABP的后端设计,以及前端对ABP接口API的ES6的封装,通过JS的继承类处理,极大减少了重复臃肿的代码,可以简化对后端API接口的封装,而 ...
- Vue公司项目实战步骤
一.无权限,无验证的Vue项目 1.打好HTML+CSS+JS基础,及<Vue 2.0 实战> 2.编写用mock设计的案例: 3.将以上案例的后台用C#改写: 二.带安全验证的Vue项目 ...
- 如何在Vue的项目里对element的表单验证进行封装
介绍需求 熟悉并优化公司项目的第五天,领导说能不能把表单验证封装一下,我打开代码一看 由于是后台管理系统,无数个需要验证的输入框,由于截图长度受限,只能展示部分,类似于这种页面还有无数个!代码重复率非 ...
- vue+webpack项目实战
概述 -- 项目中会用到的插件 vue-router vue-resource 打包工具 webpack 依赖环境 node.js start 安装vue开发的模板 # 全局安装 vue-cli $ ...
- vue全家桶(Vue+Vue-router+Vuex+axios)(Vue+webpack项目实战系列之二)
Vue有多优秀搭配全家桶做项目有多好之类的咱就不谈了,直奔主题. 一.Vue 系列一已经用vue-cli搭建了Vue项目,此处就不赘述了. 二.Vue-router Vue的路由,先献上文档(http ...
- Ant Design Vue Pro 项目实战-项目初始化(一)
写在前面 时间真快,转眼又是新的一年.随着前后端技术的不断更新迭代,尤其是前端,在目前前后端分离开发模式这样的一个大环境下,交互性.兼容性等传统的开发模式已经显得有些吃力.之前一直用的是react,随 ...
- vue组件(Vue+webpack项目实战系列之三)
组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.特别对于大型应用开发来说,尽量组件化,并且先造好轮子库,不要重复去写组件,这会显著提升项目 ...
- 第10章-Vue.js 项目实战
一.本节内容 掌握项目环境中路由的配置方法 ***** 熟练掌握编写单文件组件的编写 *** 能够使用swiper.js进行轮播图组件的封装 能够使用axios进行数据请求 二.webpack项目的目 ...
- react 项目实战(七)用户编辑与删除
添加操作列 编辑与删除功能都是针对已存在的某一个用户执行的操作,所以在用户列表中需要再加一个“操作”列来展现[编辑]与[删除]这两个按钮. 修改/src/pages/UserList.js文件,添加方 ...
随机推荐
- SDL3 入门(1):Hello, SDL3!
在本系列中我们使用 Windows Terminal + Powershell 组合作为我们在 Windows 系统下的终端工具,Windows 11 自带该环境.你也可以使用任意自己喜欢的终端环境代 ...
- html 适配iphone X 底部导航
html 适配iphone X 底部导航 适配手机底部有横线的手机,以免被横线遮挡 padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iO ...
- K8s高可用集群二进制部署-V1.20
一.前置知识点 1.1 生产环境部署K8s集群的两种方式 kubeadm Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集 ...
- mysql多表删除指定记录
在Mysql4.0之后,mysql开始支持跨表delete. Mysql可以在一个sql语句中同时删除多表记录,也可以根据多个表之间的关系来删除某一个表中的记录. 假定我们有两张表:Product表和 ...
- 实验9.单臂路由实现Vlan互通实验
# 单臂路由实现Vlan互通实验 本实验用于测试单臂路由方式实现Vlan路由. 实验组 实验过程 SW int g0/0/1 port link-type access port default vl ...
- 基于 .net core 8.0 的 swagger 文档优化分享-根据命名空间分组显示
前言 公司项目是是微服务项目,网关是手撸的一个.net core webapi 项目,使用 refit 封装了 20+ 服务 SDK,在网关中进行统一调用和聚合等处理,以及给前端提供 swagger ...
- Mysql通过frm和ibd恢复数据库
昨天的考试过程中,有个考点的服务器蓝屏重启后发现Mysql启动不了(5.6.45 x32版本,使用innoDB),重装后无法加载原数据库记录,通过查询资料,通过frm和idb文件成功恢复了数据库记录. ...
- js-内置函数-手稿
- idea 提交代码到GitHub
配置账户 配置Git安装目录 一般默认识别,其他参数不变 配置GitHub账户 提交到GitHub 1.VCS->import into version control -> share ...
- 使用requests库实现http请求
1.发送请求 import requests url = 'http://www.tipdm.com/tipdm/index.html' rqq = requests.get(url) In [ ]: ...