Introducing new features. 增加app客户管理,角色管理等

This commit is contained in:
aeizzz 2023-02-10 16:34:43 +08:00
parent b4aabe36d6
commit c8306ca5fd
17 changed files with 1037 additions and 9 deletions

64
src/api/app/approle.ts Normal file
View File

@ -0,0 +1,64 @@
import request from "/@/utils/request";
export function fetchList(query: any) {
return request({
url: '/admin/approle/page',
method: 'get',
params: query
})
}
export function list() {
return request({
url: '/admin/approle/list',
method: 'get'
})
}
export function addObj(obj: any) {
return request({
url: '/admin/approle',
method: 'post',
data: obj
})
}
export function getObj(id: string) {
return request({
url: '/admin/approle/' + id,
method: 'get'
})
}
export function delObj(id: string) {
return request({
url: '/admin/approle/' + id,
method: 'delete'
})
}
export function putObj(obj: any) {
return request({
url: '/admin/approle',
method: 'put',
data: obj
})
}
export function fetchRoleTree(roleId: string) {
return request({
url: '/admin/appmenu/tree/' + roleId,
method: 'get'
})
}
export function permissionUpd(roleId: string, menuIds: string) {
return request({
url: '/admin/approle/menu',
method: 'put',
data: {
roleId: roleId,
menuIds: menuIds
}
})
}

View File

@ -0,0 +1,39 @@
import request from "/@/utils/request";
export function fetchList(query: any) {
return request({
url: '/admin/approlemenu/page',
method: 'get',
params: query
})
}
export function addObj(obj: any) {
return request({
url: '/admin/approlemenu',
method: 'post',
data: obj
})
}
export function getObj(id:string) {
return request({
url: '/admin/approlemenu/' + id,
method: 'get'
})
}
export function delObj(id:string) {
return request({
url: '/admin/approlemenu/' + id,
method: 'delete'
})
}
export function putObj(obj: string) {
return request({
url: '/admin/approlemenu',
method: 'put',
data: obj
})
}

39
src/api/app/appuser.ts Normal file
View File

@ -0,0 +1,39 @@
import request from "/@/utils/request"
export function fetchList(query: any) {
return request({
url: '/admin/appuser/page',
method: 'get',
params: query
})
}
export function addObj(obj: any) {
return request({
url: '/admin/appuser',
method: 'post',
data: obj
})
}
export function getObj(id: string) {
return request({
url: '/admin/appuser/' + id,
method: 'get'
})
}
export function delObj(id: string) {
return request({
url: '/admin/appuser/' + id,
method: 'delete'
})
}
export function putObj(obj: any) {
return request({
url: '/admin/appuser',
method: 'put',
data: obj
})
}

View File

@ -0,0 +1,39 @@
import request from "/@/utils/request"
export function fetchList(query: any) {
return request({
url: '/admin/appuserrole/page',
method: 'get',
params: query
})
}
export function addObj(obj: any) {
return request({
url: '/admin/appuserrole',
method: 'post',
data: obj
})
}
export function getObj(id: string) {
return request({
url: '/admin/appuserrole/' + id,
method: 'get'
})
}
export function delObj(id: string) {
return request({
url: '/admin/appuserrole/' + id,
method: 'delete'
})
}
export function putObj(obj: any) {
return request({
url: '/admin/appuserrole',
method: 'put',
data: obj
})
}

View File

@ -39,7 +39,7 @@
</el-form-item>
</el-col>
<el-col :span="12" class="mb20" v-if="state.ruleForm.menuType !== '1'">
<el-form-item :label="$t('sysmenu.keepAlive')" prop="keepAlive">
<el-form-item :label="$t('sysmenu.visible')" prop="visible">
<el-radio-group v-model="state.ruleForm.visible">
<el-radio-button label="1">显示</el-radio-button>
<el-radio-button label="0">隐藏</el-radio-button>

View File

@ -5,7 +5,7 @@ export default {
sortOrder: 'sortOrder',
path: 'path',
menuType: 'menuType',
keepAlive: 'keepAlive',
visible: 'visible',
permission: 'permission',
inputNameTip: 'input name',
parentId: 'parent menu'

View File

@ -5,7 +5,7 @@ export default {
sortOrder: '排序',
path: '路由路径',
menuType: '菜单类型',
keepAlive: '缓冲',
visible: '显示状态',
permission: '权限标识',
inputNameTip: '请输入菜单名称',
parentId: '上级菜单'

View File

@ -19,15 +19,14 @@
<el-table-column prop="path" :label="$t('appmenu.path')" show-overflow-tooltip></el-table-column>
<el-table-column :label="$t('appmenu.menuType')" show-overflow-tooltip>
<template #default="scope">
<el-tag v-if="scope.row.menuType === '0'" type="success">左菜单</el-tag>
<el-tag v-if="scope.row.menuType === '2'" type="success">顶菜单</el-tag>
<el-tag v-if="scope.row.menuType === '1'" type="info">按钮</el-tag>
<el-tag v-if="scope.row.menuType === '0'" type="success">页面</el-tag>
<el-tag v-if="scope.row.menuType === '2'" type="success">按钮</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('appmenu.keepAlive')" show-overflow-tooltip>
<el-table-column :label="$t('appmenu.visible')" show-overflow-tooltip>
<template #default="scope">
<el-tag v-if="scope.row.keepAlive === '0'" type="info">关闭</el-tag>
<el-tag v-if="scope.row.keepAlive === '1'" type="success">开启</el-tag>
<el-tag v-if="scope.row.visible === '0'" type="info">关闭</el-tag>
<el-tag v-if="scope.row.visible === '1'" type="success">开启</el-tag>
</template>
</el-table-column>
<el-table-column prop="permission" :label="$t('appmenu.permission')"

View File

@ -0,0 +1,156 @@
<template>
<el-dialog :title="form.roleId ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" label-width="90px">
<el-row :gutter="35">
<el-col :span="12" class="mb20">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="角色标识" prop="roleCode">
<el-input v-model="form.roleCode" placeholder="请输入角色标识" clearable></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
<el-form-item label="角色描述" prop="roleDesc">
<el-input v-model="form.roleDesc" type="textarea" placeholder="请输入角色描述" maxlength="150"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false" >{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" >{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="systemRoleDialog">import { rule } from '/@/utils/validate';
// /
const emit = defineEmits(['refresh']);
import { useMessage } from "/@/hooks/message";
import { getObj, addObj, putObj } from '/@/api/app/approle'
import { useI18n } from "vue-i18n"
const { t } = useI18n();
//
const dataFormRef = ref();
const deptTreeRef = ref()
const visible = ref(false)
//
const form = reactive({
roleId: '',
roleName: '',
roleCode: '',
roleDesc: '',
dsType: 0,
dsScope: ''
});
//
const dataForm = reactive({
deptData: [],
checkedDsScope: [],
deptProps: {
children: 'children',
label: 'name',
value: 'id'
}
});
//
const dataRules = ref(
{
roleName: [
{ required: true, message: '角色名称不能为空', trigger: 'blur' },
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
],
roleCode: [
{ required: true, message: '角色标识不能为空', trigger: 'blur' },
{ min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' },
{ validator: rule.validatorKey, trigger: 'blur' }
],
roleDesc: [{ max: 128, message: '长度在 128 个字符内', trigger: 'blur' }],
dsType: [{ required: true, message: "请选择数据权限类型", trigger: "blur" }]
}
)
//
const openDialog = (id: string) => {
visible.value = true
form.roleId = ''
//
if (dataFormRef.value) {
dataFormRef.value.resetFields()
}
//
if (id) {
form.roleId = id
getRoleData(id)
}
};
//
const onSubmit = () => {
if (form.dsType === 1) {
form.dsScope = deptTreeRef.value.getCheckedKeys().join(',')
} else {
form.dsScope = ''
}
dataFormRef.value.validate((valid: boolean) => {
if (!valid) {
return false
}
//
if (form.roleId) {
putObj(form).then(() => {
useMessage().success(t('common.editSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
})
} else {
addObj(form).then(() => {
useMessage().success(t('common.addSuccessText'))
visible.value = false //
emit('refresh')
}).catch((err: any) => {
useMessage().error(err.msg)
})
}
})
};
//
const getRoleData = (id: string) => {
//
getObj(id).then((res: any) => {
Object.assign(form, res.data)
if (res.data.dsScope) {
dataForm.checkedDsScope = (res.data.dsScope).split(',')
} else {
dataForm.checkedDsScope = []
}
})
};
//
defineExpose({
openDialog,
});
</script>

View File

@ -0,0 +1,8 @@
export default {
approle: {
index: 'index',
roleName: 'roleName',
inputRoleNameTip: 'input roleName',
permissionTip: 'grant',
}
}

View File

@ -0,0 +1,8 @@
export default {
approle: {
index: '序号',
roleName: '角色名',
inputRoleNameTip: '请输入角色名称',
permissionTip: '授权',
}
}

View File

@ -0,0 +1,148 @@
<template>
<div class="layout-padding">
<el-card shadow="hover" class="layout-padding-auto">
<el-row shadow="hover" v-show="showSearch" class="mb8">
<el-form :model="state.queryForm" ref="queryRef" :inline="true">
<el-form-item :label="$t('approle.roleName')" prop="roleName">
<el-input :placeholder="$t('approle.inputRoleNameTip')" v-model="state.queryForm.roleName"
style="max-width: 180px" />
</el-form-item>
<el-form-item class="ml2">
<el-button icon="search" type="primary" @click="getDataList">
{{ $t('common.queryBtn') }}
</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-button icon="folder-add" type="primary" class="ml10" @click="roleDialogRef.openDialog()" v-auth="'app_approle_add'">
{{ $t('common.addBtn') }}
</el-button>
<el-button icon="upload-filled" type="primary" class="ml10" @click="excelUploadRef.show()" v-auth="'app_approle_export'">
{{ $t('common.importBtn') }}
</el-button>
<el-button icon="Download" type="primary" class="ml10" @click="exportExcel">
{{ $t('common.exportBtn') }}
</el-button>
<el-button :disabled="multiple" icon="Delete" type="primary" class="ml10" v-auth="'app_approle_del'"
@click="handleDelete(undefined)">
{{ $t('common.delBtn') }}
</el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column type="index" label="序号" width="80" />
<el-table-column prop="roleName" label="角色名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="roleCode" label="角色标识" show-overflow-tooltip></el-table-column>
<el-table-column prop="roleDesc" label="角色描述" show-overflow-tooltip></el-table-column>
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
<el-table-column :label="$t('common.action')" width="150">
<template #default="scope">
<el-button text type="primary" v-auth="'app_approle_edit'"
@click="roleDialogRef.openDialog(scope.row.roleId)">{{ $t('common.editBtn') }}</el-button>
<el-button text type="primary" v-auth="'app_approle_del'" @click="handleDelete(scope.row)">{{
$t('common.delBtn')
}}</el-button>
<el-button text type="primary" @click="permessionRef.openDialog(scope.row)" v-auth="'app_approle_perm'">{{
$t('approle.permissionTip')
}}</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
</el-card>
<!-- 角色编辑新增 -->
<role-dialog ref="roleDialogRef" @refresh="getDataList()" />
<!-- 导入角色 -->
<upload-excel ref="excelUploadRef" :title="$t('sysuser.importUserTip')" url="/admin/role/import"
temp-url="/admin/sys-file/local/file/role.xlsx" @refreshDataList="getDataList" />
<!-- 授权 -->
<permession ref="permessionRef" />
</div>
</template>
<script setup lang="ts" name="systemRole">
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObj } from "/@/api/app/approle";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useI18n } from "vue-i18n";
//
const RoleDialog = defineAsyncComponent(() => import('./form.vue'));
const Permession = defineAsyncComponent(() => import('./permession.vue'))
const { t } = useI18n()
//
const roleDialogRef = ref()
const permessionRef = ref()
const excelUploadRef = ref()
const queryRef = ref()
const showSearch = ref(true)
// rows
const selectObjs = ref([])
//
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
roleName: ''
},
pageList: fetchList // H
});
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
downBlobFile
} = useTable(state)
//
const resetQuery = () => {
queryRef.value.resetFields()
getDataList()
}
//
const handleSelectionChange = (val: any) => {
selectObjs.value = val
multiple.value = !val.length
}
// excel
const exportExcel = () => {
downBlobFile('/admin/approle/export', state.queryForm, 'approle.xlsx')
}
//
const handleDelete = (row: any) => {
if (!row) {
selectObjs.value.forEach((val: any) => {
handleDelete(val)
});
return
}
useMessageBox().confirm(`${t('common.delConfirmText')}${row.roleName}?`)
.then(() => {
delObj(row.roleId).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'));
}).catch((err: any) => {
useMessage().error(err.msg)
})
})
};
</script>

View File

@ -0,0 +1,112 @@
<template>
<div class="system-role-dialog-container">
<el-dialog :title="state.dialog.title" v-model="state.dialog.isShowDialog" :close-on-click-modal="false" draggable>
<el-tree
ref="menuTree"
:data="state.treeData"
:default-checked-keys="state.checkedKeys"
:check-strictly="false"
:props="state.defaultProps"
class="filter-tree"
node-key="id"
highlight-current
show-checkbox
default-expand-all/>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel" size="default"> </el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ state.dialog.submitTxt }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="role-permession">
import {fetchRoleTree, permissionUpd} from '/@/api/app/approle'
import {pageList} from '/@/api/app/appmenu'
import {useMessage} from "/@/hooks/message";
import {Ref} from "vue";
import {useI18n} from "vue-i18n";
const {t} = useI18n();
const menuTree = ref()
const state = reactive({
checkedKeys: [] as any[],
treeData: [] as any[],
defaultProps: {
label: 'name',
value: 'id'
},
roleId: '',
dialog: {
isShowDialog: false,
title: '分配权限',
submitTxt: '更新',
},
});
const checkedKeys: Ref<any[]> = ref([])
//
const openDialog = (row: any) => {
state.checkedKeys = []
state.treeData = []
checkedKeys.value = []
state.roleId = row.roleId
fetchRoleTree(row.roleId).then(res => {
checkedKeys.value = res.data
return pageList()
}).then(r => {
state.treeData = r.data
state.checkedKeys = resolveAllEunuchNodeId(state.treeData, checkedKeys.value, [])
})
state.dialog.isShowDialog = true;
};
//
const closeDialog = () => {
state.dialog.isShowDialog = false;
};
//
const onCancel = () => {
closeDialog();
};
const onSubmit = () => {
const menuIds = menuTree.value.getCheckedKeys().join(',').concat(',').concat(menuTree.value.getHalfCheckedKeys().join(','))
permissionUpd(state.roleId, menuIds).then(() => {
state.dialog.isShowDialog = false;
useMessage().success(t('common.editSuccessText'))
})
}
const resolveAllEunuchNodeId = (json: any[], idArr: any[], temp: any[]) => {
for (let i = 0; i < json.length; i++) {
const item = json[i]
//
item.name = t(item.name)
// ;jsonid
if (item.children && item.children.length !== 0) {
resolveAllEunuchNodeId(item.children, idArr, temp)
} else {
temp.push(idArr.filter(id => id === item.id))
}
}
return temp
}
//
defineExpose({
openDialog,
});
</script>
<style scoped>
</style>

View File

@ -0,0 +1,209 @@
<template>
<div class="system-user-dialog-container">
<el-dialog :title="dataForm.userId ? $t('common.editBtn') : $t('common.addBtn')" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="dataForm" :rules="dataRules" size="default" label-width="90px">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.username')" prop="username">
<el-input v-model="dataForm.username" placeholder="请输入用户名" :disabled="dataForm.userId !== ''"></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.password')" prop="password">
<el-input v-model="dataForm.password" type="password" placeholder="请输入密码" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.name')" prop="name">
<el-input v-model="dataForm.name" placeholder="请输入姓名" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.phone')" prop="phone">
<el-input v-model="dataForm.phone" placeholder="请输入手机号" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.role')" prop="role">
<el-select v-model="dataForm.role" placeholder="请选择角色" clearable class="w100" multiple>
<el-option v-for="item in roleData" :key="item.roleId" :label="item.roleName" :value="item.roleId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.email')" prop="email">
<el-input v-model="dataForm.email" placeholder="请输入邮箱" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.nickname')" prop="nickname">
<el-input v-model="dataForm.nickname" placeholder="请输入昵称" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item :label="$t('appuser.lockFlag')" prop="lockFlag">
<el-radio-group v-model="dataForm.lockFlag">
<el-radio :label="item.value" v-for="(item, index) in lock_flag" border :key="index">{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false" size="default">{{ $t('common.cancelButtonText') }}</el-button>
<el-button type="primary" @click="onSubmit" size="default">{{ $t('common.confirmButtonText') }}</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="systemUserDialog">
import { getObj, addObj, putObj } from '/@/api/app/appuser'
import { list as roleList } from '/@/api/app/approle'
import { useDict } from "/@/hooks/dict";
import { useI18n } from "vue-i18n";
import { useMessage } from '/@/hooks/message';
const { t } = useI18n()
// emit
const emit = defineEmits(['refresh']);
// @ts-ignore
const { lock_flag } = useDict('lock_flag')
//
const dataFormRef = ref();
const visible = ref(false)
const roleData = ref<any[]>([])
const dataForm = reactive({
userId: '',
username: '',
password: '' as String | undefined,
salt: '',
wxOpenid: '',
qqOpenid: '',
lockFlag: '0',
phone: '' as String | undefined,
deptId: '',
roleList: [],
postList: [],
nickname: '',
name: '',
email: '',
post: [] as String[],
role: [] as String[],
});
const dataRules = ref(
{
username: [{ required: true, message: "用户名不能为空", trigger: "blur" }, {
min: 5,
max: 20,
message: "用户名称长度必须介于 5 和 20 之间",
trigger: "blur"
}],
password: [{ required: true, message: "密码不能为空", trigger: "blur" }, {
min: 6,
max: 20,
message: "用户密码长度必须介于 6 和 20 之间",
trigger: "blur"
}],
name: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
role: [{ required: true, message: "角色不能为空", trigger: "blur" }],
phone: [{ required: true, message: "手机号不能为空", trigger: "blur" }, {
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur"
}],
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }]
}
)
//
const openDialog = (id: string) => {
visible.value = true
dataForm.userId = ''
//
if (dataFormRef.value) {
dataFormRef.value.resetFields()
}
//
if (id) {
dataForm.userId = id
getUserData(id)
}
getRoleData()
};
//
const onSubmit = () => {
dataFormRef.value.validate((valid: boolean) => {
if (!valid) {
return false
}
//
if (dataForm.userId) {
if (dataForm.phone && dataForm.phone.indexOf("*") >= 0) {
dataForm.phone = undefined
}
if (dataForm.password && dataForm.password.indexOf("******") >= 0) {
dataForm.password = undefined
}
putObj(dataForm).then(() => {
useMessage().success(t('common.editSuccessText'))
visible.value = false; //
emit('refresh');
}).catch(err => {
useMessage().error(err.msg)
})
} else { //
if (dataForm.phone && dataForm.phone.indexOf("*") > 0) {
dataForm.phone = undefined
}
addObj(dataForm).then(() => {
useMessage().success(t('common.addSuccessText'))
visible.value = false //
emit('refresh')
}).catch(err => {
useMessage().error(err.msg)
})
}
})
};
//
const getUserData = (id: string) => {
//
getObj(id).then(res => {
Object.assign(dataForm, res.data)
dataForm.password = '******'
if (res.data.roleList) {
dataForm.role = []
res.data.roleList.map((item: any) => {
dataForm.role.push(item.roleId)
})
}
})
};
//
const getRoleData = () => {
roleList().then(res => {
roleData.value = res.data
})
}
//
defineExpose({
openDialog,
});
</script>

View File

@ -0,0 +1,20 @@
export default {
appuser: {
index: 'index',
username: 'username',
name: 'name',
phone: 'phone',
post: 'post',
role: 'role',
lockFlag: 'lockFlag',
createTime: 'createTime',
password: 'password',
dept: 'dept',
email: 'email',
nickname: 'nickname',
inputUsernameTip: 'input username',
inputPhoneTip: 'input phone',
inputNameTip: 'input name',
importUserTip: 'user import'
}
}

View File

@ -0,0 +1,21 @@
export default {
appuser: {
index: '序号',
username: '用户名',
name: '姓名',
phone: '手机号',
post: '岗位',
role: '角色',
lockFlag: '状态',
createTime: '创建时间',
password: '密码',
dept: '部门',
email: '邮箱',
nickname: '昵称',
inputUsernameTip: '请输入用户名',
inputPhoneTip: '请输入手机号',
inputNameTip: '请输入姓名',
importUserTip: '用户导入'
},
}

View File

@ -0,0 +1,166 @@
<template>
<div class="layout-padding">
<el-card shadow="hover" class="layout-padding-auto">
<el-row v-show="showSearch" class="mb8">
<el-form :model="state.queryForm" ref="queryRef" :inline="true">
<el-form-item :label="$t('appuser.username')" prop="username">
<el-input v-model="state.queryForm.username" :placeholder="$t('appuser.inputUsernameTip')" clearable
style="width: 240px" @keyup.enter="getDataList" />
</el-form-item>
<el-form-item :label="$t('appuser.phone')" prop="phone">
<el-input v-model="state.queryForm.phone" :placeholder="$t('appuser.inputPhoneTip')" clearable
style="width: 240px" @keyup.enter="getDataList" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="getDataList">{{ $t('common.queryBtn') }}</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ $t('common.resetBtn') }}</el-button>
</el-form-item>
</el-form>
</el-row>
<el-row>
<div class="mb8" style="width: 100%">
<el-button icon="folder-add" type="primary" class="ml10" @click="userDialogRef.openDialog()"
v-auth="'sys_user_add'">
{{ $t('common.addBtn') }}
</el-button>
<el-button icon="upload-filled" type="primary" class="ml10" @click="excelUploadRef.show()"
v-auth="'sys_user_add'">
{{ $t('common.importBtn') }}
</el-button>
<el-button icon="Download" type="primary" class="ml10" @click="exportExcel" v-auth="'sys_user_export'">
{{ $t('common.exportBtn') }}
</el-button>
<el-button :disabled="multiple" icon="Delete" type="primary" class="ml10" v-auth="'sys_user_del'"
@click="handleDelete(undefined)">
{{ $t('common.delBtn') }}
</el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" style="float: right;margin-right: 20px"
@queryTable="getDataList"></right-toolbar>
</div>
</el-row>
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column type="index" :label="$t('appuser.index')" width="80" />
<el-table-column prop="username" :label="$t('appuser.username')" show-overflow-tooltip></el-table-column>
<el-table-column prop="name" :label="$t('appuser.name')" show-overflow-tooltip></el-table-column>
<el-table-column prop="phone" :label="$t('appuser.phone')" show-overflow-tooltip></el-table-column>
<el-table-column :label="$t('appuser.role')" show-overflow-tooltip>
<template #default="scope">
<el-tag v-for="(item, index) in scope.row.roleList" type="success" :key="index">{{ item.roleName }}
</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('appuser.lockFlag')" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="lock_flag" :value="scope.row.lockFlag"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('appuser.createTime')"
show-overflow-tooltip></el-table-column>
<el-table-column :label="$t('common.action')" width="100">
<template #default="scope">
<el-button text type="primary" @click="userDialogRef.openDialog(scope.row.userId)"
v-auth="'sys_user_edit'"> {{
$t('common.editBtn')
}}
</el-button>
<el-button text type="primary" @click="handleDelete(scope.row)" v-auth="'sys_user_del'">
{{ $t('common.delBtn') }}
</el-button>
</template>
</el-table-column>
</el-table>
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination">
</pagination>
</el-card>
<user-form ref="userDialogRef" @refresh="getDataList()" />
<upload-excel ref="excelUploadRef" :title="$t('appuser.importUserTip')" url="/admin/user/import"
temp-url="/admin/sys-file/local/file/user.xlsx" @refreshDataList="getDataList" />
</div>
</template>
<script setup lang="ts" name="systemUser">
import { fetchList, delObj } from '/@/api/app/appuser'
import { BasicTableProps, useTable } from '/@/hooks/table'
import { useDict } from '/@/hooks/dict'
import { useMessage, useMessageBox } from '/@/hooks/message'
import { useI18n } from 'vue-i18n'
//
const UserForm = defineAsyncComponent(() => import('./form.vue'));
const { lock_flag } = useDict('lock_flag')
const { t } = useI18n()
//
const userDialogRef = ref();
const excelUploadRef = ref();
const queryRef = ref();
const showSearch = ref(true)
// rows
const selectObjs = ref([]);
//
const multiple = ref(true);
// API
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
username: '',
phone: ''
},
pageList: fetchList
});
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
downBlobFile
} = useTable(state)
//
const resetQuery = () => {
queryRef.value.resetFields()
getDataList()
}
//
const handleSelectionChange = (val: any) => {
selectObjs.value = val
multiple.value = !val.length
}
// excel
const exportExcel = () => {
downBlobFile('/admin/appuser/export', state.queryForm, 'users.xlsx')
}
//
const handleDelete = (row: any) => {
if (!row) {
selectObjs.value.forEach(val => {
handleDelete(val)
});
return
}
useMessageBox().confirm(`${t('common.delConfirmText')}${row.username} ?`).then(() => {
//
delObj(row.userId).then(() => {
getDataList();
useMessage().success(t('common.delSuccessText'))
}).catch(err => {
useMessage().error(err.msg)
})
})
};
</script>