mirror of
https://gitee.com/gz-yami/mall4v.git
synced 2026-03-22 08:07:17 +08:00
增加 系统管理模块
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "2.1.0",
|
"@element-plus/icons-vue": "2.1.0",
|
||||||
|
"@smallwei/avue": "^3.2.22",
|
||||||
"@tinymce/tinymce-vue": "^5.1.0",
|
"@tinymce/tinymce-vue": "^5.1.0",
|
||||||
"axios": "1.3.4",
|
"axios": "1.3.4",
|
||||||
"big.js": "6.2.1",
|
"big.js": "6.2.1",
|
||||||
|
|||||||
70
src/crud/admin/form.js
Normal file
70
src/crud/admin/form.js
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '表单名称',
|
||||||
|
prop: 'formName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '按钮文本',
|
||||||
|
prop: 'buttonName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '提交次数',
|
||||||
|
prop: 'submitNum',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '不做限制',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '每个IP限填一次',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: '开启验证',
|
||||||
|
prop: 'needValidation',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '不需要',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '需要',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: '提交权限',
|
||||||
|
prop: 'submitPerm',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '所有人',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '仅会员可提交',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
47
src/crud/admin/indexImg.js
Normal file
47
src/crud/admin/indexImg.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '轮播图片',
|
||||||
|
prop: 'imgUrl',
|
||||||
|
type: 'upload',
|
||||||
|
slot: true,
|
||||||
|
listType: 'picture-img'
|
||||||
|
}, {
|
||||||
|
label: '顺序',
|
||||||
|
prop: 'seq'
|
||||||
|
}, {
|
||||||
|
width: 150,
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
search: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '禁用',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '正常',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
52
src/crud/admin/message.js
Normal file
52
src/crud/admin/message.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
selection: true,
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTime'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '姓名',
|
||||||
|
prop: 'userName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '邮箱',
|
||||||
|
prop: 'email'
|
||||||
|
}, {
|
||||||
|
label: '联系方式',
|
||||||
|
prop: 'contact'
|
||||||
|
}, {
|
||||||
|
label: '审核',
|
||||||
|
prop: 'status',
|
||||||
|
search: true,
|
||||||
|
slot: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '未审核',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '审核通过',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
77
src/crud/prod/prodComm.js
Normal file
77
src/crud/prod/prodComm.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
align: 'center',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '商品名',
|
||||||
|
prop: 'prodName',
|
||||||
|
search: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '用户昵称',
|
||||||
|
prop: 'nickName',
|
||||||
|
slot: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '记录时间',
|
||||||
|
prop: 'recTime',
|
||||||
|
width: '200'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '回复时间',
|
||||||
|
slot: true,
|
||||||
|
prop: 'replyTime',
|
||||||
|
width: '200',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '无',
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '评价得分',
|
||||||
|
prop: 'score'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '是否匿名',
|
||||||
|
prop: 'isAnonymous',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '否',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '是',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'status',
|
||||||
|
label: '审核状态',
|
||||||
|
search: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '待审核',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '审核通过',
|
||||||
|
value: 1
|
||||||
|
}, {
|
||||||
|
label: '审核未通过',
|
||||||
|
value: -1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
59
src/crud/prod/prodList.js
Normal file
59
src/crud/prod/prodList.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '产品名字',
|
||||||
|
prop: 'prodName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '商品原价',
|
||||||
|
prop: 'oriPrice'
|
||||||
|
}, {
|
||||||
|
label: '商品现价',
|
||||||
|
prop: 'price'
|
||||||
|
}, {
|
||||||
|
label: '商品库存',
|
||||||
|
prop: 'totalStocks'
|
||||||
|
}, {
|
||||||
|
label: '产品图片',
|
||||||
|
prop: 'pic',
|
||||||
|
type: 'upload',
|
||||||
|
width: 150,
|
||||||
|
listType: 'picture-img'
|
||||||
|
|
||||||
|
}, {
|
||||||
|
width: 150,
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
search: true,
|
||||||
|
slot: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '未上架',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '上架',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
46
src/crud/prod/prodTag.js
Normal file
46
src/crud/prod/prodTag.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
align: 'center',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '标签名称',
|
||||||
|
prop: 'title',
|
||||||
|
search: true,
|
||||||
|
slot: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
type: 'select',
|
||||||
|
slot: true,
|
||||||
|
search: true,
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '禁用',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '正常',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '默认类型',
|
||||||
|
prop: 'isDfault',
|
||||||
|
slot: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '排序',
|
||||||
|
prop: 'seq'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
30
src/crud/prod/spec.js
Normal file
30
src/crud/prod/spec.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '属性名称',
|
||||||
|
prop: 'propName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '属性值',
|
||||||
|
prop: 'prodPropValues',
|
||||||
|
slot: true
|
||||||
|
}]
|
||||||
|
}
|
||||||
52
src/crud/shop/hotSearch.js
Normal file
52
src/crud/shop/hotSearch.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: false,
|
||||||
|
selection: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
align: 'center',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '热搜标题',
|
||||||
|
prop: 'title',
|
||||||
|
search: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '热搜内容',
|
||||||
|
prop: 'content',
|
||||||
|
search: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '录入时间',
|
||||||
|
prop: 'recDate',
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '顺序',
|
||||||
|
prop: 'seq',
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '启用状态',
|
||||||
|
prop: 'status',
|
||||||
|
type: 'select',
|
||||||
|
slot: true,
|
||||||
|
search: true,
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '未启用',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '启用',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
52
src/crud/shop/notice.js
Normal file
52
src/crud/shop/notice.js
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
align: 'center',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '公告内容',
|
||||||
|
prop: 'title',
|
||||||
|
search: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
search: true,
|
||||||
|
slot: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '撤销',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '公布',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '是否置顶',
|
||||||
|
prop: 'isTop',
|
||||||
|
search: true,
|
||||||
|
slot: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '否',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '是',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
43
src/crud/shop/pickAddr.js
Normal file
43
src/crud/shop/pickAddr.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: false,
|
||||||
|
selection: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '自提点名称',
|
||||||
|
prop: 'addrName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '手机号',
|
||||||
|
prop: 'mobile'
|
||||||
|
}, {
|
||||||
|
label: '省份',
|
||||||
|
prop: 'province'
|
||||||
|
}, {
|
||||||
|
label: '城市',
|
||||||
|
prop: 'city'
|
||||||
|
}, {
|
||||||
|
label: '区/县',
|
||||||
|
prop: 'area'
|
||||||
|
}, {
|
||||||
|
label: '地址',
|
||||||
|
prop: 'addr'
|
||||||
|
}]
|
||||||
|
}
|
||||||
27
src/crud/shop/transport.js
Normal file
27
src/crud/shop/transport.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: false,
|
||||||
|
selection: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '模板名称',
|
||||||
|
prop: 'transName',
|
||||||
|
search: true
|
||||||
|
}]
|
||||||
|
}
|
||||||
30
src/crud/sys/area.js
Normal file
30
src/crud/sys/area.js
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
align: 'center',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'areaId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'areaName'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'parentId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '',
|
||||||
|
prop: 'level'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
33
src/crud/sys/config.js
Normal file
33
src/crud/sys/config.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '参数名',
|
||||||
|
prop: 'paramKey',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '参数值',
|
||||||
|
prop: 'paramValue'
|
||||||
|
}, {
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark'
|
||||||
|
}]
|
||||||
|
}
|
||||||
47
src/crud/sys/log.js
Normal file
47
src/crud/sys/log.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
menu: false, // 移除操作栏
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '用户名',
|
||||||
|
prop: 'username',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '用户操作',
|
||||||
|
prop: 'operation',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '请求方法',
|
||||||
|
prop: 'method'
|
||||||
|
}, {
|
||||||
|
label: '请求参数',
|
||||||
|
prop: 'params'
|
||||||
|
}, {
|
||||||
|
label: '执行时长(毫秒)',
|
||||||
|
prop: 'time'
|
||||||
|
}, {
|
||||||
|
label: 'IP地址',
|
||||||
|
prop: 'ip'
|
||||||
|
}, {
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createDate'
|
||||||
|
}]
|
||||||
|
}
|
||||||
33
src/crud/sys/role.js
Normal file
33
src/crud/sys/role.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '角色名称',
|
||||||
|
prop: 'roleName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '备注',
|
||||||
|
prop: 'remark'
|
||||||
|
}, {
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTime'
|
||||||
|
}]
|
||||||
|
}
|
||||||
50
src/crud/sys/user.js
Normal file
50
src/crud/sys/user.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '用户名',
|
||||||
|
prop: 'username',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '邮箱',
|
||||||
|
prop: 'email'
|
||||||
|
}, {
|
||||||
|
label: '手机号',
|
||||||
|
prop: 'mobile'
|
||||||
|
}, {
|
||||||
|
label: '创建时间',
|
||||||
|
prop: 'createTime'
|
||||||
|
}, {
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '禁用',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '正常',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}]
|
||||||
|
}
|
||||||
80
src/crud/user/addr.js
Normal file
80
src/crud/user/addr.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
index: true,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
align: 'center',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
column: [
|
||||||
|
{
|
||||||
|
label: '收货人名称',
|
||||||
|
prop: 'receiver'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '省',
|
||||||
|
prop: 'province'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '城市',
|
||||||
|
prop: 'city'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '区',
|
||||||
|
prop: 'area'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '地址',
|
||||||
|
prop: 'addr'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '邮编',
|
||||||
|
prop: 'postCode'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '手机',
|
||||||
|
prop: 'mobile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
search: true,
|
||||||
|
type: 'select',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '无效',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '正常',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '默认地址',
|
||||||
|
prop: 'commonAddr',
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '否',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '是',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '建立时间',
|
||||||
|
prop: 'createTime'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '更新时间',
|
||||||
|
prop: 'updateTime'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
53
src/crud/user/user.js
Normal file
53
src/crud/user/user.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
export const tableOption = {
|
||||||
|
searchMenuSpan: 6,
|
||||||
|
columnBtn: false,
|
||||||
|
border: true,
|
||||||
|
// selection: true,
|
||||||
|
index: false,
|
||||||
|
indexLabel: '序号',
|
||||||
|
stripe: true,
|
||||||
|
menuAlign: 'center',
|
||||||
|
menuWidth: 350,
|
||||||
|
align: 'center',
|
||||||
|
refreshBtn: true,
|
||||||
|
searchSize: 'mini',
|
||||||
|
addBtn: false,
|
||||||
|
editBtn: false,
|
||||||
|
delBtn: false,
|
||||||
|
viewBtn: false,
|
||||||
|
props: {
|
||||||
|
label: 'label',
|
||||||
|
value: 'value'
|
||||||
|
},
|
||||||
|
column: [{
|
||||||
|
label: '用户昵称',
|
||||||
|
prop: 'nickName',
|
||||||
|
search: true
|
||||||
|
}, {
|
||||||
|
label: '用户头像',
|
||||||
|
prop: 'pic',
|
||||||
|
type: 'upload',
|
||||||
|
imgWidth: 150,
|
||||||
|
listType: 'picture-img',
|
||||||
|
slot: true
|
||||||
|
}, {
|
||||||
|
label: '状态',
|
||||||
|
prop: 'status',
|
||||||
|
search: true,
|
||||||
|
type: 'select',
|
||||||
|
slot: true,
|
||||||
|
dicData: [
|
||||||
|
{
|
||||||
|
label: '禁用',
|
||||||
|
value: 0
|
||||||
|
}, {
|
||||||
|
label: '正常',
|
||||||
|
value: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: '注册时间',
|
||||||
|
prop: 'userRegtime',
|
||||||
|
imgWidth: 150
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -6,6 +6,10 @@ import moment from 'moment'
|
|||||||
import 'element-plus/dist/index.css'
|
import 'element-plus/dist/index.css'
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
import locale from 'element-plus/lib/locale/lang/zh-cn'
|
||||||
|
import Avue from '@smallwei/avue'
|
||||||
|
import '@smallwei/avue/lib/index.css'
|
||||||
|
|
||||||
// 全局样式
|
// 全局样式
|
||||||
import '@/styles/index.scss'
|
import '@/styles/index.scss'
|
||||||
// svg
|
// svg
|
||||||
@@ -34,8 +38,10 @@ app.use(pinia)
|
|||||||
|
|
||||||
app.component('SvgIcon', svgIcon)
|
app.component('SvgIcon', svgIcon)
|
||||||
|
|
||||||
|
// Avue
|
||||||
|
app.use(Avue)
|
||||||
// element-plus
|
// element-plus
|
||||||
app.use(ElementPlus)
|
app.use(ElementPlus, { locale })
|
||||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
app.component(key, component)
|
app.component(key, component)
|
||||||
}
|
}
|
||||||
|
|||||||
147
src/views/modules/sys/area/add-or-update.vue
Normal file
147
src/views/modules/sys/area/add-or-update.vue
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
:title="!dataForm.areaId ? '新增' : '修改'"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="dataForm"
|
||||||
|
:rules="dataRule"
|
||||||
|
label-width="100px"
|
||||||
|
@keyup.enter="onSubmit()"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="地区名称"
|
||||||
|
prop="areaName"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.areaName"
|
||||||
|
placeholder="请输入地区名称"
|
||||||
|
maxlength="50"
|
||||||
|
show-word-limit
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="上级地区"
|
||||||
|
prop="parentId"
|
||||||
|
>
|
||||||
|
<el-cascader
|
||||||
|
v-model="selectedOptions"
|
||||||
|
expand-trigger="hover"
|
||||||
|
:options="areaList"
|
||||||
|
:props="categoryTreeProps"
|
||||||
|
change-on-select
|
||||||
|
filterable
|
||||||
|
@change="handleChange"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button
|
||||||
|
@click="visible = false"
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="onSubmit()"
|
||||||
|
>
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { treeDataTranslate } from '@/utils'
|
||||||
|
import { Debounce } from '@/utils/debounce'
|
||||||
|
const emit = defineEmits(['refreshDataList'])
|
||||||
|
const dataRule = reactive({
|
||||||
|
areaName: [
|
||||||
|
{ required: true, message: '区域名称不能为空', trigger: 'blur' },
|
||||||
|
{ pattern: /\s\S+|S+\s|\S/, message: '请输入正确的区域名称', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const areaList = ref([])
|
||||||
|
const dataForm = ref({
|
||||||
|
areaId: '',
|
||||||
|
areaName: null,
|
||||||
|
parentId: null,
|
||||||
|
level: null
|
||||||
|
})
|
||||||
|
const categoryTreeProps = reactive({
|
||||||
|
value: 'areaId',
|
||||||
|
label: 'areaName'
|
||||||
|
})
|
||||||
|
const selectedOptions = ref([])
|
||||||
|
const dataFormRef = ref(null)
|
||||||
|
const init = (areaId) => {
|
||||||
|
dataForm.value.areaId = areaId || 0
|
||||||
|
visible.value = true
|
||||||
|
selectedOptions.value = []
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
if (dataForm.value.areaId) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/admin/area/info/' + dataForm.value.areaId),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
}).then(({ data }) => {
|
||||||
|
dataForm.value = data
|
||||||
|
selectedOptions.value.push(dataForm.value.parentId)
|
||||||
|
categoryTreeProps.areaId = dataForm.value.areaId
|
||||||
|
categoryTreeProps.areaName = dataForm.value.areaName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/admin/area/list'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
}).then(({ data }) => {
|
||||||
|
areaList.value = treeDataTranslate(data, 'areaId', 'parentId')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defineExpose({ init })
|
||||||
|
|
||||||
|
const page = {
|
||||||
|
total: 0, // 总页数
|
||||||
|
currentPage: 1, // 当前页数
|
||||||
|
pageSize: 20 // 每页显示多少条
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 表单提交
|
||||||
|
*/
|
||||||
|
const onSubmit = Debounce(() => {
|
||||||
|
dataFormRef.value?.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/admin/area'),
|
||||||
|
method: dataForm.value.areaId ? 'put' : 'post',
|
||||||
|
data: http.adornData(dataForm.value)
|
||||||
|
}).then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('refreshDataList', page)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleChange = (val) => {
|
||||||
|
dataForm.value.parentId = val[val.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
162
src/views/modules/sys/area/index.vue
Normal file
162
src/views/modules/sys/area/index.vue
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mod-sys-area">
|
||||||
|
<el-input
|
||||||
|
v-model="areaName"
|
||||||
|
class="area-search-input"
|
||||||
|
placeholder="地区关键词"
|
||||||
|
/>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
class="area-add-btn"
|
||||||
|
@click="onAddOrUpdate()"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-tree
|
||||||
|
ref="tree2Ref"
|
||||||
|
:data="areaTreeData"
|
||||||
|
node-key="areaId"
|
||||||
|
:filter-node-method="filterNode"
|
||||||
|
:props="props"
|
||||||
|
:expand-on-click-node="false"
|
||||||
|
>
|
||||||
|
<template #default="{ node, data }">
|
||||||
|
<span>{{ node.label }}</span>
|
||||||
|
<span>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click="() => update(node, data)"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
|
||||||
|
@click="() => remove(node, data)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-tree>
|
||||||
|
|
||||||
|
<add-or-update
|
||||||
|
v-if="addOrUpdateVisible"
|
||||||
|
ref="addOrUpdateRef"
|
||||||
|
@refresh-data-list="getDataList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import AddOrUpdate from './add-or-update.vue'
|
||||||
|
import { treeDataTranslate } from '@/utils'
|
||||||
|
|
||||||
|
const areaName = ref('')
|
||||||
|
const props = {
|
||||||
|
id: 'areaId',
|
||||||
|
label: 'areaName',
|
||||||
|
children: 'children'
|
||||||
|
}
|
||||||
|
|
||||||
|
const tree2Ref = ref(null)
|
||||||
|
watch(
|
||||||
|
() => areaName,
|
||||||
|
(val) => {
|
||||||
|
tree2Ref.value?.filter(val)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDataList(page)
|
||||||
|
})
|
||||||
|
|
||||||
|
const page = reactive({
|
||||||
|
total: 0, // 总页数
|
||||||
|
currentPage: 1, // 当前页数
|
||||||
|
pageSize: 10 // 每页显示多少条
|
||||||
|
})
|
||||||
|
const areaTreeData = ref(null)
|
||||||
|
const getDataList = (pageParam, params) => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/admin/area/list'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams(Object.assign({
|
||||||
|
current: pageParam == null ? page.currentPage : pageParam.currentPage,
|
||||||
|
size: pageParam == null ? page.pageSize : pageParam.pageSize
|
||||||
|
}, params))
|
||||||
|
}).then(({ data }) => {
|
||||||
|
areaTreeData.value = treeDataTranslate(data, 'areaId', 'parentId')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const addOrUpdateRef = ref(null)
|
||||||
|
const addOrUpdateVisible = ref(false)
|
||||||
|
/**
|
||||||
|
* 新增 / 修改
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
const onAddOrUpdate = (id) => {
|
||||||
|
addOrUpdateVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
addOrUpdateRef.value?.init(id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
* @param areaId
|
||||||
|
*/
|
||||||
|
const onDelete = (areaId) => {
|
||||||
|
ElMessageBox.confirm('确定进行删除操作?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/admin/area/' + areaId),
|
||||||
|
method: 'delete',
|
||||||
|
data: http.adornData({})
|
||||||
|
}).then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
getDataList(page)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const update = (node, data) => {
|
||||||
|
onAddOrUpdate(data.areaId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const remove = (node, data) => {
|
||||||
|
onDelete(data.areaId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterNode = (value, data) => {
|
||||||
|
if (!value) return true
|
||||||
|
return data.areaName.indexOf(value) !== -1
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.mod-sys-area {
|
||||||
|
.area-search-input {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
.area-add-btn {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
124
src/views/modules/sys/config/add-or-update.vue
Normal file
124
src/views/modules/sys/config/add-or-update.vue
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
:title="!dataForm.id ? '新增' : '修改'"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="dataForm"
|
||||||
|
:rules="dataRule"
|
||||||
|
label-width="80px"
|
||||||
|
@keyup.enter="onSubmit()"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="参数名"
|
||||||
|
prop="paramKey"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.paramKey"
|
||||||
|
placeholder="参数名"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="参数值"
|
||||||
|
prop="paramValue"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.paramValue"
|
||||||
|
placeholder="参数值"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="备注"
|
||||||
|
prop="remark"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.remark"
|
||||||
|
placeholder="备注"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="onSubmit()"
|
||||||
|
>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { Debounce } from '@/utils/debounce'
|
||||||
|
const emit = defineEmits(['refreshDataList'])
|
||||||
|
const visible = ref(false)
|
||||||
|
const dataForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
paramKey: '',
|
||||||
|
paramValue: '',
|
||||||
|
remark: ''
|
||||||
|
})
|
||||||
|
const dataRule = {
|
||||||
|
paramKey: [
|
||||||
|
{ required: true, message: '参数名不能为空', trigger: 'blur' },
|
||||||
|
{ pattern: /\s\S+|S+\s|\S/, message: '请输入正确的参数名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
paramValue: [
|
||||||
|
{ required: true, message: '参数值不能为空', trigger: 'blur' },
|
||||||
|
{ pattern: /\s\S+|S+\s|\S/, message: '请输入正确的参数值', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const dataFormRef = ref(null)
|
||||||
|
const init = (id) => {
|
||||||
|
dataForm.id = id || 0
|
||||||
|
visible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
if (dataForm.id) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl(`/sys/config/info/${dataForm.id}`),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
}).then(({ data }) => {
|
||||||
|
dataForm.paramKey = data.paramKey
|
||||||
|
dataForm.paramValue = data.paramValue
|
||||||
|
dataForm.remark = data.remark
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defineExpose({ init })
|
||||||
|
/**
|
||||||
|
* 表单提交
|
||||||
|
*/
|
||||||
|
const onSubmit = Debounce(() => {
|
||||||
|
dataFormRef.value?.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/config'),
|
||||||
|
method: dataForm.id ? 'put' : 'post',
|
||||||
|
data: http.adornData({
|
||||||
|
id: dataForm.id || undefined,
|
||||||
|
paramKey: dataForm.paramKey,
|
||||||
|
paramValue: dataForm.paramValue,
|
||||||
|
remark: dataForm.remark
|
||||||
|
})
|
||||||
|
}).then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('refreshDataList')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
144
src/views/modules/sys/config/index.vue
Normal file
144
src/views/modules/sys/config/index.vue
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mod-config">
|
||||||
|
<avue-crud
|
||||||
|
ref="crudRef"
|
||||||
|
:page="page"
|
||||||
|
:data="dataList"
|
||||||
|
:option="tableOption"
|
||||||
|
@search-change="onSearch"
|
||||||
|
@selection-change="selectionChange"
|
||||||
|
@on-load="getDataList"
|
||||||
|
>
|
||||||
|
<template #menu-left>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click.stop="onAddOrUpdate()"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
:disabled="dataListSelections.length <= 0"
|
||||||
|
@click="onDelete()"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<template #menu="scope">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click.stop="onAddOrUpdate(scope.row.id)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click.stop="onDelete(scope.row.id)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</avue-crud>
|
||||||
|
|
||||||
|
<!-- 弹窗, 新增 / 修改 -->
|
||||||
|
<add-or-update
|
||||||
|
v-if="addOrUpdateVisible"
|
||||||
|
ref="addOrUpdateRef"
|
||||||
|
@refresh-data-list="getDataList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { tableOption } from '@/crud/sys/config.js'
|
||||||
|
const dataList = ref([])
|
||||||
|
const page = reactive({
|
||||||
|
total: 0, // 总页数
|
||||||
|
currentPage: 1, // 当前页数
|
||||||
|
pageSize: 10 // 每页显示多少条
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* 获取数据列表
|
||||||
|
*/
|
||||||
|
const getDataList = (pageParam, params, done) => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/config/page'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
current: pageParam == null ? page.currentPage : pageParam.currentPage,
|
||||||
|
size: pageParam == null ? page.pageSize : pageParam.pageSize
|
||||||
|
},
|
||||||
|
params
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
dataList.value = data.records
|
||||||
|
page.total = data.total
|
||||||
|
if (done) done()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 条件查询
|
||||||
|
*/
|
||||||
|
const onSearch = (params, done) => {
|
||||||
|
getDataList(page, params, done)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataListSelections = ref([])
|
||||||
|
/**
|
||||||
|
* 多选变化
|
||||||
|
*/
|
||||||
|
const selectionChange = (val) => {
|
||||||
|
dataListSelections.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
const addOrUpdateVisible = ref(false)
|
||||||
|
const addOrUpdate = ref(null)
|
||||||
|
/**
|
||||||
|
* 新增 / 修改
|
||||||
|
*/
|
||||||
|
const onAddOrUpdate = (id) => {
|
||||||
|
addOrUpdateVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
addOrUpdate.value?.init(id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
const onDelete = (id) => {
|
||||||
|
const ids = id ? [id] : dataListSelections.value?.map(item => {
|
||||||
|
return item.id
|
||||||
|
})
|
||||||
|
ElMessageBox.confirm(`确定对[id=${ids.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/config'),
|
||||||
|
method: 'delete',
|
||||||
|
data: http.adornData(ids, false)
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
57
src/views/modules/sys/log/index.vue
Normal file
57
src/views/modules/sys/log/index.vue
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mod-log">
|
||||||
|
<avue-crud
|
||||||
|
ref="crudRef"
|
||||||
|
:page="page"
|
||||||
|
:data="dataList"
|
||||||
|
:option="tableOption"
|
||||||
|
@search-change="onSearch"
|
||||||
|
@on-load="getDataList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { tableOption } from '@/crud/sys/log.js'
|
||||||
|
const dataList = ref([])
|
||||||
|
const page = reactive({
|
||||||
|
total: 0, // 总页数
|
||||||
|
currentPage: 1, // 当前页数
|
||||||
|
pageSize: 10 // 每页显示多少条
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getDataList()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据列表
|
||||||
|
*/
|
||||||
|
const getDataList = (pageParam, params, done) => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/log/page'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
current: pageParam == null ? page.currentPage : pageParam.currentPage,
|
||||||
|
size: pageParam == null ? page.pageSize : pageParam.pageSize
|
||||||
|
},
|
||||||
|
params
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
dataList.value = data.records
|
||||||
|
page.total = data.total
|
||||||
|
if (done) done()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 条件查询
|
||||||
|
*/
|
||||||
|
const onSearch = (params, done) => {
|
||||||
|
getDataList(page, params, done)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
@@ -197,7 +197,9 @@ onMounted(() => {
|
|||||||
onLoadIcons()
|
onLoadIcons()
|
||||||
})
|
})
|
||||||
const iconList = []
|
const iconList = []
|
||||||
// 加载图标
|
/**
|
||||||
|
* 加载图标
|
||||||
|
*/
|
||||||
const onLoadIcons = () => {
|
const onLoadIcons = () => {
|
||||||
const icons = import.meta.glob('@/icons/svg/*.svg')
|
const icons = import.meta.glob('@/icons/svg/*.svg')
|
||||||
for (const icon in icons) {
|
for (const icon in icons) {
|
||||||
@@ -251,11 +253,16 @@ defineExpose({ init })
|
|||||||
const handleSelectMenuChange = (val) => {
|
const handleSelectMenuChange = (val) => {
|
||||||
dataForm.parentId = val[val.length - 1]
|
dataForm.parentId = val[val.length - 1]
|
||||||
}
|
}
|
||||||
// 图标选中
|
/**
|
||||||
|
* 图标选中
|
||||||
|
* @param iconName
|
||||||
|
*/
|
||||||
const iconActiveHandle = (iconName) => {
|
const iconActiveHandle = (iconName) => {
|
||||||
dataForm.icon = iconName
|
dataForm.icon = iconName
|
||||||
}
|
}
|
||||||
// 表单提交
|
/**
|
||||||
|
* 表单提交
|
||||||
|
*/
|
||||||
const onSubmit = Debounce(() => {
|
const onSubmit = Debounce(() => {
|
||||||
dataFormRef.value?.validate((valid) => {
|
dataFormRef.value?.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
|||||||
151
src/views/modules/sys/role/add-or-update.vue
Normal file
151
src/views/modules/sys/role/add-or-update.vue
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
:title="!dataForm.id ? '新增' : '修改'"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="dataForm"
|
||||||
|
:rules="dataRule"
|
||||||
|
label-width="80px"
|
||||||
|
@keyup.enter="onSubmit()"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="角色名称"
|
||||||
|
prop="roleName"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.roleName"
|
||||||
|
placeholder="角色名称"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="备注"
|
||||||
|
prop="remark"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.remark"
|
||||||
|
placeholder="备注"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="授权">
|
||||||
|
<el-tree
|
||||||
|
ref="menuListTreeRef"
|
||||||
|
:data="menuList"
|
||||||
|
:props="menuListTreeProps"
|
||||||
|
node-key="menuId"
|
||||||
|
show-checkbox
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="onSubmit()"
|
||||||
|
>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { treeDataTranslate } from '@/utils'
|
||||||
|
import { Debounce } from '@/utils/debounce'
|
||||||
|
|
||||||
|
const emit = defineEmits(['refreshDataList'])
|
||||||
|
const tempKey = -666666 // 临时key) 用于解决tree半选中状态项不能传给后台接口问题. # 待优化
|
||||||
|
const visible = ref(false)
|
||||||
|
const menuList = ref([])
|
||||||
|
const menuListTreeProps = {
|
||||||
|
label: 'name',
|
||||||
|
children: 'children'
|
||||||
|
}
|
||||||
|
const dataForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
roleName: '',
|
||||||
|
remark: ''
|
||||||
|
})
|
||||||
|
const dataRule = reactive({
|
||||||
|
roleName: [
|
||||||
|
{ required: true, message: '角色名称不能为空', trigger: 'blur' },
|
||||||
|
{ pattern: /\s\S+|S+\s|\S/, message: '请输入正确的角色名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
remark: [
|
||||||
|
{ required: false, pattern: /\s\S+|S+\s|\S/, message: '输入格式有误', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
const dataFormRef = ref(null)
|
||||||
|
const menuListTreeRef = ref(null)
|
||||||
|
const init = (id) => {
|
||||||
|
dataForm.id = id || 0
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/menu/table'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
menuList.value = treeDataTranslate(data, 'menuId', 'parentId')
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
visible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
menuListTreeRef.value?.setCheckedKeys([])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
if (dataForm.id) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl(`/sys/role/info/${dataForm.id}`),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
dataForm.roleName = data.roleName
|
||||||
|
dataForm.remark = data.remark
|
||||||
|
const idx = data.menuIdList.indexOf(tempKey)
|
||||||
|
if (idx !== -1) {
|
||||||
|
data.menuIdList.splice(idx, data.menuIdList.length - idx)
|
||||||
|
}
|
||||||
|
menuListTreeRef.value?.setCheckedKeys(data.menuIdList)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defineExpose({ init })
|
||||||
|
/**
|
||||||
|
* 表单提交
|
||||||
|
*/
|
||||||
|
const onSubmit = Debounce(() => {
|
||||||
|
dataFormRef.value?.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/role'),
|
||||||
|
method: dataForm.id ? 'put' : 'post',
|
||||||
|
data: http.adornData({
|
||||||
|
roleId: dataForm.id || undefined,
|
||||||
|
roleName: dataForm.roleName,
|
||||||
|
remark: dataForm.remark,
|
||||||
|
menuIdList: [].concat(menuListTreeRef.value?.getCheckedKeys(), [tempKey], menuListTreeRef.value?.getHalfCheckedKeys())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('refreshDataList')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
153
src/views/modules/sys/role/index.vue
Normal file
153
src/views/modules/sys/role/index.vue
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mod-role">
|
||||||
|
<avue-crud
|
||||||
|
ref="crudRef"
|
||||||
|
:page="page"
|
||||||
|
:data="dataList"
|
||||||
|
:option="tableOption"
|
||||||
|
@search-change="onSearch"
|
||||||
|
@selection-change="selectionChange"
|
||||||
|
@on-load="getDataList"
|
||||||
|
>
|
||||||
|
<template #menu-left>
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:role:save')"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click.stop="onAddOrUpdate()"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:role:delete')"
|
||||||
|
type="danger"
|
||||||
|
:disabled="dataListSelections.length <= 0"
|
||||||
|
@click="onDelete()"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #menu="scope">
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:role:update')"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click.stop="onAddOrUpdate(scope.row.roleId)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:role:delete')"
|
||||||
|
type="danger"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click.stop="onDelete(scope.row.roleId)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</avue-crud>
|
||||||
|
|
||||||
|
<!-- 弹窗, 新增 / 修改 -->
|
||||||
|
<add-or-update
|
||||||
|
v-if="addOrUpdateVisible"
|
||||||
|
ref="addOrUpdateRef"
|
||||||
|
@refresh-data-list="getDataList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { isAuth } from '@/utils'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { tableOption } from '@/crud/sys/role.js'
|
||||||
|
import AddOrUpdate from './add-or-update.vue'
|
||||||
|
const dataList = ref([])
|
||||||
|
const dataListSelections = ref([])
|
||||||
|
const page = reactive({
|
||||||
|
total: 0, // 总页数
|
||||||
|
currentPage: 1, // 当前页数
|
||||||
|
pageSize: 10 // 每页显示多少条
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据列表
|
||||||
|
*/
|
||||||
|
const getDataList = (pageParam, params, done) => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/role/page'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
current: pageParam == null ? page.currentPage : pageParam.currentPage,
|
||||||
|
size: pageParam == null ? page.pageSize : pageParam.pageSize
|
||||||
|
},
|
||||||
|
params
|
||||||
|
)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
dataList.value = data.records
|
||||||
|
page.total = data.total
|
||||||
|
if (done) {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 条件查询
|
||||||
|
*/
|
||||||
|
const onSearch = (params, done) => {
|
||||||
|
getDataList(page, params, done)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 多选变化
|
||||||
|
*/
|
||||||
|
const selectionChange = (val) => {
|
||||||
|
dataListSelections.value = val
|
||||||
|
}
|
||||||
|
const addOrUpdateVisible = ref(false)
|
||||||
|
const addOrUpdateRef = ref(null)
|
||||||
|
/**
|
||||||
|
* 新增 / 修改
|
||||||
|
*/
|
||||||
|
const onAddOrUpdate = (id) => {
|
||||||
|
addOrUpdateVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
addOrUpdateRef.value?.init(id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
const onDelete = (id) => {
|
||||||
|
const ids = id ? [id] : dataListSelections.value?.map(item => {
|
||||||
|
return item.roleId
|
||||||
|
})
|
||||||
|
ElMessageBox.confirm(`确定进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/role'),
|
||||||
|
method: 'delete',
|
||||||
|
data: http.adornData(ids, false)
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
245
src/views/modules/sys/user/add-or-update.vue
Normal file
245
src/views/modules/sys/user/add-or-update.vue
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="visible"
|
||||||
|
:title="!dataForm.id ? '新增' : '修改'"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="dataFormRef"
|
||||||
|
:model="dataForm"
|
||||||
|
:rules="dataRule"
|
||||||
|
label-width="80px"
|
||||||
|
@keyup.enter="onSubmit()"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="用户名"
|
||||||
|
prop="userName"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.userName"
|
||||||
|
placeholder="登录帐号"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="密码"
|
||||||
|
prop="password"
|
||||||
|
:class="{ 'is-required': !dataForm.id }"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.password"
|
||||||
|
type="password"
|
||||||
|
placeholder="密码"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="确认密码"
|
||||||
|
prop="comfirmPassword"
|
||||||
|
:class="{ 'is-required': !dataForm.id }"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.comfirmPassword"
|
||||||
|
type="password"
|
||||||
|
placeholder="确认密码"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="邮箱"
|
||||||
|
prop="email"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.email"
|
||||||
|
placeholder="邮箱"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="手机号"
|
||||||
|
prop="mobile"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="dataForm.mobile"
|
||||||
|
maxlength="11"
|
||||||
|
placeholder="手机号"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="角色"
|
||||||
|
prop="roleIdList"
|
||||||
|
>
|
||||||
|
<el-checkbox-group v-model="dataForm.roleIdList">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="role in roleList"
|
||||||
|
:key="role.roleId"
|
||||||
|
:label="role.roleId"
|
||||||
|
>
|
||||||
|
{{ role.roleName }}
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="状态"
|
||||||
|
prop="status"
|
||||||
|
>
|
||||||
|
<el-radio-group v-model="dataForm.status">
|
||||||
|
<el-radio :label="0">
|
||||||
|
禁用
|
||||||
|
</el-radio>
|
||||||
|
<el-radio :label="1">
|
||||||
|
正常
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="onSubmit()"
|
||||||
|
>确定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import { isEmail, isMobile } from '@/utils/validate'
|
||||||
|
import { Debounce } from '@/utils/debounce'
|
||||||
|
import { encrypt } from '@/utils/crypto'
|
||||||
|
const emit = defineEmits(['refreshDataList'])
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const dataForm = reactive({
|
||||||
|
id: 0,
|
||||||
|
userName: '',
|
||||||
|
password: '',
|
||||||
|
comfirmPassword: '',
|
||||||
|
email: '',
|
||||||
|
mobile: '',
|
||||||
|
roleIdList: [],
|
||||||
|
status: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const validatePassword = (rule, value, callback) => {
|
||||||
|
if (!dataForm.id && !/\S/.test(value)) {
|
||||||
|
callback(new Error('密码不能为空'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const validateComfirmPassword = (rule, value, callback) => {
|
||||||
|
if (!dataForm.id && !/\S/.test(value)) {
|
||||||
|
dataForm.password = ''
|
||||||
|
callback(new Error('确认密码不能为空'))
|
||||||
|
} else if (dataForm.password !== value) {
|
||||||
|
callback(new Error('确认密码与密码输入不一致'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const validateEmail = (rule, value, callback) => {
|
||||||
|
if (!isEmail(value)) {
|
||||||
|
callback(new Error('邮箱格式错误'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const validateMobile = (rule, value, callback) => {
|
||||||
|
if (!isMobile(value)) {
|
||||||
|
callback(new Error('手机号格式错误'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const dataRule = {
|
||||||
|
userName: [
|
||||||
|
{ required: true, message: '用户名不能为空', trigger: 'blur' },
|
||||||
|
{ pattern: /\s\S+|S+\s|\S/, message: '请输入正确的用户名', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
password: [
|
||||||
|
{ validator: validatePassword, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
comfirmPassword: [
|
||||||
|
{ validator: validateComfirmPassword, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
email: [
|
||||||
|
{ required: true, message: '邮箱不能为空', trigger: 'blur' },
|
||||||
|
{ validator: validateEmail, trigger: 'blur' }
|
||||||
|
],
|
||||||
|
mobile: [
|
||||||
|
{ required: true, message: '手机号不能为空', trigger: 'blur' },
|
||||||
|
{ validator: validateMobile, trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const roleList = ref([])
|
||||||
|
const dataFormRef = ref(null)
|
||||||
|
const init = (id) => {
|
||||||
|
dataForm.id = id || 0
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/role/list'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
}).then(({ data }) => {
|
||||||
|
roleList.value = data
|
||||||
|
}).then(() => {
|
||||||
|
visible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
dataFormRef.value?.resetFields()
|
||||||
|
})
|
||||||
|
}).then(() => {
|
||||||
|
if (dataForm.id) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl(`/sys/user/info/${dataForm.id}`),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams()
|
||||||
|
}).then(({ data }) => {
|
||||||
|
dataForm.userName = data.username
|
||||||
|
dataForm.email = data.email
|
||||||
|
dataForm.mobile = data.mobile
|
||||||
|
dataForm.roleIdList = data.roleIdList
|
||||||
|
dataForm.status = data.status
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defineExpose({ init })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表单提交
|
||||||
|
*/
|
||||||
|
const onSubmit = Debounce(() => {
|
||||||
|
dataFormRef.value?.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/user'),
|
||||||
|
method: dataForm.id ? 'put' : 'post',
|
||||||
|
data: http.adornData({
|
||||||
|
userId: dataForm.id || undefined,
|
||||||
|
username: dataForm.userName,
|
||||||
|
password: encrypt(dataForm.password),
|
||||||
|
email: dataForm.email,
|
||||||
|
mobile: dataForm.mobile,
|
||||||
|
status: dataForm.status,
|
||||||
|
roleIdList: dataForm.roleIdList
|
||||||
|
})
|
||||||
|
}).then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
visible.value = false
|
||||||
|
emit('refreshDataList')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
155
src/views/modules/sys/user/index.vue
Normal file
155
src/views/modules/sys/user/index.vue
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<template>
|
||||||
|
<div class="mod-user">
|
||||||
|
<avue-crud
|
||||||
|
ref="crudRef"
|
||||||
|
:page="page"
|
||||||
|
:data="dataList"
|
||||||
|
:option="tableOption"
|
||||||
|
@search-change="onSearch"
|
||||||
|
@selection-change="selectionChange"
|
||||||
|
@on-load="getDataList"
|
||||||
|
>
|
||||||
|
<template #menu-left>
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:user:save')"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click.stop="onAddOrUpdate()"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:user:delete')"
|
||||||
|
type="danger"
|
||||||
|
|
||||||
|
:disabled="dataListSelections.length <= 0"
|
||||||
|
@click="onDelete()"
|
||||||
|
>
|
||||||
|
批量删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
<template
|
||||||
|
#menu="scope"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:user:update')"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-edit"
|
||||||
|
@click.stop="onAddOrUpdate(scope.row.userId)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
v-if="isAuth('sys:user:delete')"
|
||||||
|
type="danger"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
@click.stop="onDelete(scope.row.userId)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</avue-crud>
|
||||||
|
|
||||||
|
<!-- 弹窗, 新增 / 修改 -->
|
||||||
|
<add-or-update
|
||||||
|
v-if="addOrUpdateVisible"
|
||||||
|
ref="addOrUpdateRef"
|
||||||
|
@refresh-data-list="getDataList"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { isAuth } from '@/utils'
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
|
import { tableOption } from '@/crud/sys/user.js'
|
||||||
|
import AddOrUpdate from './add-or-update.vue'
|
||||||
|
|
||||||
|
const dataList = ref([])
|
||||||
|
const dataListLoading = ref(false)
|
||||||
|
const dataListSelections = ref([])
|
||||||
|
const addOrUpdateVisible = ref(false)
|
||||||
|
const page = reactive({
|
||||||
|
total: 0, // 总页数
|
||||||
|
currentPage: 1, // 当前页数
|
||||||
|
pageSize: 10 // 每页显示多少条
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取数据列表
|
||||||
|
*/
|
||||||
|
const getDataList = (pageParam, params, done) => {
|
||||||
|
dataListLoading.value = true
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/user/page'),
|
||||||
|
method: 'get',
|
||||||
|
params: http.adornParams(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
current: pageParam == null ? page.currentPage : pageParam.currentPage,
|
||||||
|
size: pageParam == null ? page.pageSize : pageParam.pageSize
|
||||||
|
},
|
||||||
|
params
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}).then(({ data }) => {
|
||||||
|
dataList.value = data.records
|
||||||
|
page.total = data.total
|
||||||
|
dataListLoading.value = false
|
||||||
|
if (done) done()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 条件查询
|
||||||
|
*/
|
||||||
|
const onSearch = (params, done) => {
|
||||||
|
getDataList(page, params, done)
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 多选变化
|
||||||
|
*/
|
||||||
|
const selectionChange = (val) => {
|
||||||
|
dataListSelections.value = val
|
||||||
|
}
|
||||||
|
|
||||||
|
const addOrUpdateRef = ref(null)
|
||||||
|
/**
|
||||||
|
* 新增 / 修改
|
||||||
|
*/
|
||||||
|
const onAddOrUpdate = (id) => {
|
||||||
|
addOrUpdateVisible.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
addOrUpdateRef.value?.init(id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
const onDelete = (id) => {
|
||||||
|
const userIds = id ? [id] : dataListSelections.value?.map(item => {
|
||||||
|
return item.userId
|
||||||
|
})
|
||||||
|
ElMessageBox.confirm(`确定对[id=${userIds.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
http({
|
||||||
|
url: http.adornUrl('/sys/user'),
|
||||||
|
method: 'delete',
|
||||||
|
data: http.adornData(userIds, false)
|
||||||
|
}).then(() => {
|
||||||
|
ElMessage({
|
||||||
|
message: '操作成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user