fix:1,优化投注记录
parent
609cc7b1b8
commit
3416e62a1b
|
|
@ -8,6 +8,22 @@ export function listRole(query) {
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 获取角色选择框列表
|
||||||
|
export function optionselect(query) {
|
||||||
|
return request({
|
||||||
|
url: '/system/role/optionselect',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取菜单角色
|
||||||
|
export function getMenu(roleId) {
|
||||||
|
return request({
|
||||||
|
url: '/system/role/getMenu/' + roleId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 查询角色详细
|
// 查询角色详细
|
||||||
export function getRole(roleId) {
|
export function getRole(roleId) {
|
||||||
|
|
@ -97,7 +113,15 @@ export function authUserCancelAll(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/cancelAll',
|
url: '/system/role/authUser/cancelAll',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 批量清除关联账号
|
||||||
|
export function authRolecancelAll(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/role/authRole/cancelAll',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +130,7 @@ export function authUserSelectAll(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/role/authUser/selectAll',
|
url: '/system/role/authUser/selectAll',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
params: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,36 @@ export function delUser(userId) {
|
||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//删除账户/批量删除
|
||||||
|
export function deleteUserSystem(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/delete',
|
||||||
|
method: 'delete',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//冻结账户
|
||||||
|
export function changeStatus(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/changeStatus',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//清空角色
|
||||||
|
export function resetRole(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/resetRole',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 用户密码重置
|
// 用户密码重置
|
||||||
export function resetUserPwd(userId, password,codeGoogle) {
|
export function resetUserPwd(userId,inputGoogleCode) {
|
||||||
const data = {
|
const data = {
|
||||||
userId,
|
userId,
|
||||||
password,
|
inputGoogleCode
|
||||||
codeGoogle
|
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/resetPwd',
|
url: '/system/user/resetPwd',
|
||||||
|
|
@ -58,6 +81,20 @@ export function resetUserPwd(userId, password,codeGoogle) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户重置谷歌验证码
|
||||||
|
export function resetGoogle(userId,inputGoogleCode) {
|
||||||
|
const data = {
|
||||||
|
userId,
|
||||||
|
inputGoogleCode
|
||||||
|
}
|
||||||
|
return request({
|
||||||
|
url: '/system/user/resetGoogle',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 用户状态修改
|
// 用户状态修改
|
||||||
export function changeUserStatus(userId, status) {
|
export function changeUserStatus(userId, status) {
|
||||||
const data = {
|
const data = {
|
||||||
|
|
@ -89,10 +126,11 @@ export function updateUserProfile(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户密码重置
|
// 用户密码重置
|
||||||
export function updateUserPwd(oldPassword, newPassword) {
|
export function updateUserPwd(oldPassword, newPassword,codeGoogle) {
|
||||||
const data = {
|
const data = {
|
||||||
oldPassword,
|
oldPassword,
|
||||||
newPassword
|
newPassword,
|
||||||
|
codeGoogle
|
||||||
}
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile/updatePwd',
|
url: '/system/user/profile/updatePwd',
|
||||||
|
|
@ -101,6 +139,15 @@ export function updateUserPwd(oldPassword, newPassword) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改密码
|
||||||
|
export function updateUserPassword(data) {
|
||||||
|
return request({
|
||||||
|
url: '/system/user/profile/change/password',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 用户头像上传
|
// 用户头像上传
|
||||||
export function uploadAvatar(data) {
|
export function uploadAvatar(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
@ -136,11 +183,10 @@ export function deptTreeSelect() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修改密码
|
// 用户名称检查
|
||||||
export function updateUserPassword(data) {
|
export function getSystemUserCheck(userName) {
|
||||||
return request({
|
return request({
|
||||||
url: '/resetPwd',
|
url: '/system/user/check/' + userName,
|
||||||
method: 'post',
|
method: 'get'
|
||||||
data: data
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
<template>
|
||||||
|
<!-- 表格批量操作组件 -->
|
||||||
|
<div class="table-op">
|
||||||
|
<el-checkbox v-model="isAllSelection" @change="allSelectionChange" style="transform: translateY(3px);">{{
|
||||||
|
t('全选当前页')
|
||||||
|
}}</el-checkbox>
|
||||||
|
<el-select v-model="batchOpType" :disabled="selectionData.length === 0" :placeholder="t('批量操作')"
|
||||||
|
style="width: 150px; margin-left: 20px;" @change="opTypeChange">
|
||||||
|
<el-option v-for="item in opTypeOptions" :label="t(item.label)" :value="item.value" :disabled="item.disabled" />
|
||||||
|
</el-select>
|
||||||
|
<span class="selection-tips" v-if="selectionData.length > 0">{{ t('已选择')
|
||||||
|
}}<b>{{ selectionData.length }}</b>{{ t('条数据') }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
selectionData: { // 选中的表格数据
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
},
|
||||||
|
opTypeOptions: { // 批量操作选项
|
||||||
|
type: Array,
|
||||||
|
default: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const isAllSelection = defineModel('isAllSelection', { type: Boolean, default: false }); // 是否全选
|
||||||
|
const batchOpType = defineModel('batchOpType', { type: String, default: '' }); // 选中的批量操作类型
|
||||||
|
const emit = defineEmits(['allSelectionChange', 'opTypeChange']);
|
||||||
|
|
||||||
|
// 全选当前页
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
emit('allSelectionChange');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择批量操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
emit('opTypeChange');
|
||||||
|
}
|
||||||
|
const reset = () => {
|
||||||
|
batchOpType.value = null;
|
||||||
|
emit('selectionDataNu');
|
||||||
|
}
|
||||||
|
defineExpose({
|
||||||
|
reset
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.table-op {
|
||||||
|
position: absolute;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 10px;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
.selection-tips {
|
||||||
|
font-size: 14px;
|
||||||
|
padding-left: 10px;
|
||||||
|
color: #666666;
|
||||||
|
|
||||||
|
b {
|
||||||
|
color: #F56C6C;
|
||||||
|
padding: 0 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -27,17 +27,19 @@
|
||||||
/>
|
/>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</el-scrollbar> -->
|
</el-scrollbar> -->
|
||||||
<div class="avatar-container">
|
<div class="avatar-container" style="margin-right: 10px;" >
|
||||||
<el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click">
|
<el-dropdown @command="handleCommand" style="" class="right-menu-item hover-effect" trigger="click">
|
||||||
<div class="avatar-wrapper">
|
<div class="avatar-wrapper" style="display: flex;align-items: center;justify-content: center;color: #fff;font-size: 14px;">
|
||||||
<img :src="userStore.avatar" class="user-avatar" />
|
<!-- <img :src="userStore.avatar" class="user-avatar" />
|
||||||
<el-icon><caret-bottom /></el-icon>
|
<el-icon><caret-bottom /></el-icon> -->
|
||||||
|
{{ nickName }}
|
||||||
</div>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<router-link to="/user/profile">
|
<!-- <router-link to="/user/profile">
|
||||||
<el-dropdown-item>个人中心</el-dropdown-item>
|
<el-dropdown-item>个人中心</el-dropdown-item>
|
||||||
</router-link>
|
</router-link> -->
|
||||||
|
<el-dropdown-item @click="handleClick">{{ t("账户设置") }}</el-dropdown-item>
|
||||||
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
|
<el-dropdown-item command="setLayout" v-if="settingsStore.showSettings">
|
||||||
<span>布局设置</span>
|
<span>布局设置</span>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
|
|
@ -48,6 +50,61 @@
|
||||||
</template>
|
</template>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-dialog :title="t('账号设置')" align-center v-model="dialogVisible" width="700" append-to-body>
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<el-form ref="userRef" :model="formData" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item label="后台账号" prop="roleName">
|
||||||
|
{{ formData.userName }}
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="后台昵称" prop="nickName">
|
||||||
|
<el-input v-model="formData.nickName"
|
||||||
|
:placeholder="t('仅支持中英文和数字,为1-20个字符')" maxlength="20" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="登录密码">
|
||||||
|
<el-row style="width: 100%;">
|
||||||
|
<el-col :span="12">
|
||||||
|
{{ t('已设置') }}
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12" style="display: flex;justify-content: right;">
|
||||||
|
<el-button type="primary" @click="updatePassword">修改密码</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
|
<el-button @click="closeDialog">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<!-- 修改密码 -->
|
||||||
|
<el-dialog :title="t('修改密码')" align-center v-model="passwordDialogVisible" width="630" append-to-body>
|
||||||
|
<el-scrollbar max-height="600px">
|
||||||
|
<el-form ref="passwordRef" :model="passwordFormData" :rules="rulesPassword" label-width="100px">
|
||||||
|
<el-form-item label="旧密码" prop="oldPassword">
|
||||||
|
<el-input v-model="passwordFormData.oldPassword" placeholder="请输入旧密码" type="password" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="新密码" prop="newPassword">
|
||||||
|
<el-input v-model="passwordFormData.newPassword" placeholder="请输入新密码" type="password" show-password />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="确认密码" prop="confirmPassword">
|
||||||
|
<el-input v-model="passwordFormData.confirmPassword" placeholder="请确认新密码" type="password" show-password/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="谷歌验证码" prop="codeGoogle">
|
||||||
|
<el-input v-model="passwordFormData.codeGoogle" maxlength="6" placeholder="请输入谷歌验证码"/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
|
<el-button @click="closePasswordDialog">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submitPasswordForm">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -60,19 +117,49 @@ import useAppStore from '@/store/modules/app'
|
||||||
import useSettingsStore from '@/store/modules/settings'
|
import useSettingsStore from '@/store/modules/settings'
|
||||||
import usePermissionStore from '@/store/modules/permission'
|
import usePermissionStore from '@/store/modules/permission'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
|
import { updateUserProfile,getUserProfile,updateUserPwd } from "@/api/system/user";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
const permissionStore = usePermissionStore()
|
const permissionStore = usePermissionStore()
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
const sidebarRouters = computed(() => permissionStore.sidebarRouters);
|
const sidebarRouters = computed(() => permissionStore.sidebarRouters);
|
||||||
const showLogo = computed(() => settingsStore.sidebarLogo);
|
const showLogo = computed(() => settingsStore.sidebarLogo);
|
||||||
const sideTheme = computed(() => settingsStore.sideTheme);
|
const sideTheme = computed(() => settingsStore.sideTheme);
|
||||||
const theme = computed(() => settingsStore.theme);
|
const theme = computed(() => settingsStore.theme);
|
||||||
const windowWidth = ref(window.innerWidth)
|
const windowWidth = ref(window.innerWidth)
|
||||||
|
const nickName = ref(getLocalStorage('userInfo')?.nickName);
|
||||||
|
|
||||||
|
const dialogVisible = ref(false);
|
||||||
|
const rules = ref({
|
||||||
|
});
|
||||||
|
const formData = ref({
|
||||||
|
});
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
const passwordDialogVisible = ref(false);
|
||||||
|
const passwordFormData = ref({
|
||||||
|
oldPassword: undefined,
|
||||||
|
newPassword: undefined,
|
||||||
|
confirmPassword: undefined,
|
||||||
|
codeGoogle: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
const equalToPassword = (rule, value, callback) => {
|
||||||
|
if (passwordFormData.value.newPassword !== value) {
|
||||||
|
callback(new Error("两次输入的密码不一致"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const rulesPassword = ref({
|
||||||
|
oldPassword: [{ required: true, message: "旧密码不能为空", trigger: "change" }],
|
||||||
|
newPassword: [{ required: true, message: "新密码不能为空", trigger: "change" }, { min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "change" }, { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "change" }],
|
||||||
|
confirmPassword: [{ required: true, message: "确认密码不能为空", trigger: "change" }, { required: true, validator: equalToPassword, trigger: "change" }],
|
||||||
|
codeGoogle: [{ required: true, message: "谷歌验证码不能为空", trigger: "change" }]
|
||||||
|
});
|
||||||
|
|
||||||
function updateWidth() {
|
function updateWidth() {
|
||||||
windowWidth.value = window.innerWidth
|
windowWidth.value = window.innerWidth
|
||||||
|
|
@ -125,6 +212,51 @@ function logout() {
|
||||||
})
|
})
|
||||||
}).catch(() => { });
|
}).catch(() => { });
|
||||||
}
|
}
|
||||||
|
const handleClick = () => {
|
||||||
|
getUserProfile().then(response => {
|
||||||
|
formData.value = response.data;
|
||||||
|
dialogVisible.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
oldForm.value = JSON.stringify(formData.value);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const closeDialog = () => {
|
||||||
|
dialogVisible.value = false;
|
||||||
|
}
|
||||||
|
//修改密码
|
||||||
|
const updatePassword = () => {
|
||||||
|
passwordDialogVisible.value = true;
|
||||||
|
}
|
||||||
|
const submitForm = () => {
|
||||||
|
proxy.$refs.userRef.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
if (JSON.stringify(formData.value) != oldForm.value) {
|
||||||
|
updateUserProfile(formData.value).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
|
nickName.value = formData.value.nickName;
|
||||||
|
dialogVisible.value = false;
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
dialogVisible.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const closePasswordDialog = () => {
|
||||||
|
passwordDialogVisible.value = false;
|
||||||
|
}
|
||||||
|
const submitPasswordForm = () => {
|
||||||
|
proxy.$refs.passwordRef.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
updateUserPwd(passwordFormData.value.oldPassword, passwordFormData.value.newPassword,passwordFormData.value.codeGoogle).then(response => {
|
||||||
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
|
passwordDialogVisible.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,8 @@
|
||||||
</el-input-number>
|
</el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||||||
<el-input v-model="form.googleCode" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
<el-input v-model="form.googleCode" :maxlength="6" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <div class="label-scoreRatio">
|
<!-- <div class="label-scoreRatio">
|
||||||
<span>{{ t('平台比例') }}</span>
|
<span>{{ t('平台比例') }}</span>
|
||||||
|
|
@ -162,7 +163,7 @@
|
||||||
</el-input-number>
|
</el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||||||
<el-input v-model="form.googleCode" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
<el-input v-model="form.googleCode" :maxlength="6" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item :label="t('商户模式')" prop="tenantType">
|
<!-- <el-form-item :label="t('商户模式')" prop="tenantType">
|
||||||
<el-radio-group v-model="form.tenantType" :disabled="openView">
|
<el-radio-group v-model="form.tenantType" :disabled="openView">
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@
|
||||||
{{ t(' (万法定货币=1万通用额度)') }}
|
{{ t(' (万法定货币=1万通用额度)') }}
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||||||
<el-input v-model="form.googleCode" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
<el-input v-model="form.googleCode" :maxlength="6" style="width: 260px;" :placeholder="t('请输入谷歌验证码')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="label-scoreRatio">
|
<div class="label-scoreRatio">
|
||||||
<span>{{ t('平台比例') }}</span>
|
<span>{{ t('平台比例') }}</span>
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,12 @@
|
||||||
<el-table-column :label="t('结算时间')" align="center" min-width="160" prop="settlementTime" :show-overflow-tooltip="true">
|
<el-table-column :label="t('结算时间')" align="center" min-width="160" prop="settlementTime" :show-overflow-tooltip="true">
|
||||||
<template #default="scope">{{ parseTime(scope.row.settlementTime) }}</template>
|
<template #default="scope">{{ parseTime(scope.row.settlementTime) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('创建时间')" align="center" min-width="160" prop="ffcreateAt" :show-overflow-tooltip="true">
|
||||||
|
<template #default="scope">{{ parseTime(scope.row.ffCreateAt) }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column :label="t('更新时间')" align="center" min-width="160" prop="ffupdateAt" :show-overflow-tooltip="true">
|
||||||
|
<template #default="scope">{{ parseTime(scope.row.ffUpdateAt) }}</template>
|
||||||
|
</el-table-column>
|
||||||
<!-- <el-table-column :label="t('操作')" align="center" width="200" class-name="small-padding fixed-width">
|
<!-- <el-table-column :label="t('操作')" align="center" width="200" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('详情') }}</el-button>
|
<el-button link type="primary" @click="handleView(scope.row)" v-hasPermi="['agent:tenant:view']">{{ t('详情') }}</el-button>
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
<el-input v-model="userInfos.walletAddress" disabled auto-complete="off" placeholder="请输入钱包地址" />
|
<el-input v-model="userInfos.walletAddress" disabled auto-complete="off" placeholder="请输入钱包地址" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||||||
<el-input v-model="form.googleCode" :placeholder="t('请输入谷歌验证码')" />
|
<el-input v-model="form.googleCode" :maxlength="6" :placeholder="t('请输入谷歌验证码')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
<el-dialog v-model="goodDialogVisible" style="margin-top: 45vh !important;" :title="t('温馨提示')" width="418" :before-close="handleClose">
|
<el-dialog v-model="goodDialogVisible" style="margin-top: 45vh !important;" :title="t('温馨提示')" width="418" :before-close="handleClose">
|
||||||
<div style="width: 90%;margin-bottom: 20px;">{{ t('请用手机打开客服端Google身份验证器,输入验证码') }}</div>
|
<div style="width: 90%;margin-bottom: 20px;">{{ t('请用手机打开客服端Google身份验证器,输入验证码') }}</div>
|
||||||
<div class="">
|
<div class="">
|
||||||
<el-input v-model="gooleCode" style="width: 90%" :placeholder="t('验证码只能为数字')" />
|
<el-input v-model="gooleCode" :maxlength="6" style="width: 90%" :placeholder="t('验证码只能为数字')" />
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
</div>
|
</div>
|
||||||
<el-form ref="authenticatorRef" :model="authenticatorForm" :rules="authenticatorRules">
|
<el-form ref="authenticatorRef" :model="authenticatorForm" :rules="authenticatorRules">
|
||||||
<el-form-item label="谷歌验证码" prop="authenticatorCode">
|
<el-form-item label="谷歌验证码" prop="authenticatorCode">
|
||||||
<el-input v-model="authenticatorForm.authenticatorCode" :digit="2" style="width: 100%;height: 36px;" :placeholder="t('验证码只能为数字')" />
|
<el-input v-model="authenticatorForm.authenticatorCode" :maxlength="6" :digit="2" style="width: 100%;height: 36px;" :placeholder="t('验证码只能为数字')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div class="" style="margin-top: 20px;margin-bottom: 20px;">
|
<div class="" style="margin-top: 20px;margin-bottom: 20px;">
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
{{ t('如需扣余额,则输入负数,例如:-10.50') }}
|
{{ t('如需扣余额,则输入负数,例如:-10.50') }}
|
||||||
</div>
|
</div>
|
||||||
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||||||
<el-input v-model="formAdjustment.googleCode" :placeholder="t('请输入谷歌验证码')" />
|
<el-input v-model="formAdjustment.googleCode" :maxlength="6" :placeholder="t('请输入谷歌验证码')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('备注')" prop="remark">
|
<el-form-item :label="t('备注')" prop="remark">
|
||||||
<el-input type="textarea" rows="4" v-model="formAdjustment.remark" :placeholder="t('请输入备注')" />
|
<el-input type="textarea" rows="4" v-model="formAdjustment.remark" :placeholder="t('请输入备注')" />
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
<el-form-item :label="t('谷歌验证码')" prop="googleCode">
|
||||||
<el-input v-model="formAdjustment.googleCode" :placeholder="t('请输入谷歌验证码')" />
|
<el-input v-model="formAdjustment.googleCode" :maxlength="6" :placeholder="t('请输入谷歌验证码')" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('备注')" prop="remark">
|
<el-form-item :label="t('备注')" prop="remark">
|
||||||
<el-input type="textarea" rows="4" v-model="formAdjustment.remark" :placeholder="t('请输入备注')" />
|
<el-input type="textarea" rows="4" v-model="formAdjustment.remark" :placeholder="t('请输入备注')" />
|
||||||
|
|
|
||||||
|
|
@ -296,7 +296,12 @@ currencySelectArr.value = res.map(item => {
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
function getList() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
superTenantList(queryParams.value).then(response => {
|
let queryParams={
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
tenantKey: "",
|
||||||
|
}
|
||||||
|
superTenantList(queryParams).then(response => {
|
||||||
agentList.value = response.rows;
|
agentList.value = response.rows;
|
||||||
total.value = response.total;
|
total.value = response.total;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<table-search-card :leftSpan="20" :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
<table-search-card :leftSpan="20" :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||||||
<template #left>
|
<template #left>
|
||||||
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
|
<table-search-date v-model:dateRange="dateRange" v-model:operateTimeType="operateTimeType"></table-search-date>
|
||||||
<el-form-item :label="t('商户账号')" prop="tenantKey">
|
<!-- <el-form-item :label="t('商户账号')" prop="tenantKey">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="queryParams.tenantKey"
|
v-model="queryParams.tenantKey"
|
||||||
:placeholder="t('请输入商户账号')"
|
:placeholder="t('请输入商户账号')"
|
||||||
|
|
@ -11,6 +11,40 @@
|
||||||
style="width: 200px"
|
style="width: 200px"
|
||||||
@keyup.enter="handleQuery"
|
@keyup.enter="handleQuery"
|
||||||
/>
|
/>
|
||||||
|
</el-form-item> -->
|
||||||
|
<el-form-item :label="t('商户账号')" prop="tenantKey">
|
||||||
|
<el-select
|
||||||
|
v-model="queryParams.tenantKey"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
reserve-keyword
|
||||||
|
placeholder="请输入租户Key搜索"
|
||||||
|
:remote-method="loadOptions"
|
||||||
|
:loading="loadingSelect"
|
||||||
|
style="width: 240px"
|
||||||
|
>
|
||||||
|
<!-- 正常列表 -->
|
||||||
|
<el-option
|
||||||
|
v-for="item in agentListSelect"
|
||||||
|
:key="item.tenantKey"
|
||||||
|
:label="item.tenantKey"
|
||||||
|
:value="item.tenantKey"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 加载更多按钮 -->
|
||||||
|
<el-option
|
||||||
|
v-if="hasMore && agentListSelect.length > 0"
|
||||||
|
disabled
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="color:#409EFF;cursor:pointer;width:100%;"
|
||||||
|
@click.stop="loadMore"
|
||||||
|
>
|
||||||
|
{{ loadingMore ? "加载中..." : "加载更多" }}
|
||||||
|
</div>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('玩家账号')" prop="memberAccount">
|
<el-form-item :label="t('玩家账号')" prop="memberAccount">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -43,9 +77,9 @@
|
||||||
<CustomSelect v-if="showLoding3" v-model="queryParams.platformCode" :options="quotaplatformCodeArr" filterable placeholder="请选择平台" style="width: 200px" />
|
<CustomSelect v-if="showLoding3" v-model="queryParams.platformCode" :options="quotaplatformCodeArr" filterable placeholder="请选择平台" style="width: 200px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="t('操作类型')" prop="operationType">
|
<el-form-item :label="t('操作类型')" prop="operationType">
|
||||||
<el-select v-if="operationTypeOption.length > 0" v-model="queryParams.operationType" clearable style="width:220px;" :placeholder="t('请选择')">
|
<el-select v-model="queryParams.operationType" clearable style="width:220px;" :placeholder="t('请选择')">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="dict in operationTypeOption"
|
v-for="dict in operationTypes"
|
||||||
:key="dict.value"
|
:key="dict.value"
|
||||||
:label="dict.label"
|
:label="dict.label"
|
||||||
:value="dict.value"
|
:value="dict.value"
|
||||||
|
|
@ -236,7 +270,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="Agent">
|
<script setup name="Agent">
|
||||||
import { superTenantQuotaflow,superCommonPlatSelect,superTenantQuotaAudit,getSuperCommonOperationType } from "@/api/super/tenant";
|
import { superTenantQuotaflow,superCommonPlatSelect,superTenantQuotaAudit,getSuperCommonOperationType,superTenantList } from "@/api/super/tenant";
|
||||||
import Crontab from '@/components/Crontab'
|
import Crontab from '@/components/Crontab'
|
||||||
import { getLocalStorage } from "@/utils/auth";
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
import CopyIcon from '@/components/CopyIcon'
|
import CopyIcon from '@/components/CopyIcon'
|
||||||
|
|
@ -297,6 +331,18 @@ const dd = String(today.getDate()).padStart(2, '0');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//操作类型
|
||||||
|
const operationTypes = ref([
|
||||||
|
{ label: proxy.t('商户转入转出'), value: 1 },
|
||||||
|
{ label: proxy.t('日用额度结算'), value: 2 },
|
||||||
|
{ label: proxy.t('信誉额度充值'), value: 3 },
|
||||||
|
{ label: proxy.t('后台人工操作'), value: 4 },
|
||||||
|
{ label: proxy.t('商户订单充值'), value: 5 },
|
||||||
|
{ label: proxy.t('转入恢复'), value: 6 },
|
||||||
|
{ label: proxy.t('转出恢复'), value: 7 },
|
||||||
|
|
||||||
|
|
||||||
|
]);
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
const quotaTypeArr = ref([
|
const quotaTypeArr = ref([
|
||||||
{ label: proxy.t('可用额度'), value: "BALANCE" },
|
{ label: proxy.t('可用额度'), value: "BALANCE" },
|
||||||
|
|
@ -461,9 +507,52 @@ const handleAudit = (row) => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const agentListSelect = ref([])
|
||||||
|
|
||||||
|
|
||||||
|
const loadingSelect = ref(false)
|
||||||
|
|
||||||
|
const loadingMore = ref(false)
|
||||||
|
|
||||||
|
const hasMore = ref(true)
|
||||||
|
|
||||||
|
const queryParamSelect = ref({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
tenantKey: ""
|
||||||
|
})
|
||||||
|
|
||||||
|
// 加载第一页(搜索)
|
||||||
|
const loadOptions = async (query) => {
|
||||||
|
queryParamSelect.value.pageNum = 1
|
||||||
|
queryParamSelect.value.tenantKey = query
|
||||||
|
loadingSelect.value = true
|
||||||
|
try {
|
||||||
|
const res = await superTenantList(queryParamSelect.value)
|
||||||
|
agentListSelect.value = res.rows || []
|
||||||
|
hasMore.value = agentListSelect.value.length < (res.total || 0)
|
||||||
|
} finally {
|
||||||
|
loadingSelect.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多(分页)
|
||||||
|
const loadMore = async () => {
|
||||||
|
if (!hasMore.value) return
|
||||||
|
queryParamSelect.value.pageNum++
|
||||||
|
loadingMore.value = true
|
||||||
|
try {
|
||||||
|
const res = await superTenantList(queryParamSelect.value)
|
||||||
|
agentListSelect.value = [...agentListSelect.value, ...(res.rows || [])]
|
||||||
|
hasMore.value = agentListSelect.value.length < (res.total || 0)
|
||||||
|
} finally {
|
||||||
|
loadingMore.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
//初始化
|
//初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
|
loadOptions('');
|
||||||
getsuperCommonCurrencySelect();
|
getsuperCommonCurrencySelect();
|
||||||
getSuperCommonOperationTypes();
|
getSuperCommonOperationTypes();
|
||||||
getsuperCommonPlatformTypeSelect();
|
getsuperCommonPlatformTypeSelect();
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,7 @@
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await passwordForm.value.validate();
|
await passwordForm.value.validate();
|
||||||
let objForm = {
|
let objForm = {
|
||||||
password:form.value.newPassword
|
newPassword:form.value.newPassword
|
||||||
}
|
}
|
||||||
// 这里添加实际的API调用
|
// 这里添加实际的API调用
|
||||||
updateUserPassword(objForm).then(response => {
|
updateUserPassword(objForm).then(response => {
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<el-table-column label="权限字符" align="center" prop="roleKey" />
|
<el-table-column label="权限字符" align="center" prop="roleKey" />
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ onActivated(() => {
|
||||||
|
|
||||||
// 路由跳转过来
|
// 路由跳转过来
|
||||||
if (Object.keys(routeParams).length) {
|
if (Object.keys(routeParams).length) {
|
||||||
activeName.value = routeParams.activeName || 'auditManage';
|
activeName.value = routeParams.activeName || 'userList';
|
||||||
memberAccount.value = routeParams.memberAccount || '';
|
memberAccount.value = routeParams.memberAccount || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<svg-icon icon-class="date" />创建日期
|
<svg-icon icon-class="date" />创建日期
|
||||||
<div class="pull-right">{{ state.user.createTime }}</div>
|
<div class="pull-right">{{ formatTime(state.user.createTime) }}</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="user-info-head" @click="editCropper()">
|
<div class="user-info-head" @click="editCropper()">
|
||||||
<img :src="options.img" title="点击上传头像" class="img-circle img-lg" />
|
<img :src="options.img" title="点击上传头像" class="img-circle img-lg" />
|
||||||
<el-dialog :title="title" align-center v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
|
<el-dialog :title="title" v-model="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
<el-col :xs="24" :md="12" :style="{ height: '350px' }">
|
||||||
<vue-cropper
|
<vue-cropper
|
||||||
|
|
@ -63,17 +63,19 @@ import "vue-cropper/dist/index.css";
|
||||||
import { VueCropper } from "vue-cropper";
|
import { VueCropper } from "vue-cropper";
|
||||||
import { uploadAvatar } from "@/api/system/user";
|
import { uploadAvatar } from "@/api/system/user";
|
||||||
import useUserStore from "@/store/modules/user";
|
import useUserStore from "@/store/modules/user";
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
|
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
const fileHost = getLocalStorage('fileUrl') || ''; // 文件host
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const title = ref("修改头像");
|
const title = ref("修改头像");
|
||||||
|
|
||||||
//图片裁剪数据
|
//图片裁剪数据
|
||||||
const options = reactive({
|
const options = reactive({
|
||||||
img: userStore.avatar, // 裁剪图片的地址
|
img: fileHost + userStore.avatar, // 裁剪图片的地址
|
||||||
autoCrop: true, // 是否默认生成截图框
|
autoCrop: true, // 是否默认生成截图框
|
||||||
autoCropWidth: 200, // 默认生成截图框宽度
|
autoCropWidth: 200, // 默认生成截图框宽度
|
||||||
autoCropHeight: 200, // 默认生成截图框高度
|
autoCropHeight: 200, // 默认生成截图框高度
|
||||||
|
|
@ -133,7 +135,7 @@ function uploadImg() {
|
||||||
formData.append("avatarfile", data, options.filename);
|
formData.append("avatarfile", data, options.filename);
|
||||||
uploadAvatar(formData).then(response => {
|
uploadAvatar(formData).then(response => {
|
||||||
open.value = false;
|
open.value = false;
|
||||||
options.img = import.meta.env.VITE_APP_BASE_API + response.imgUrl;
|
options.img = response.imgUrl;
|
||||||
userStore.avatar = options.img;
|
userStore.avatar = options.img;
|
||||||
proxy.$modal.msgSuccess("修改成功");
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
|
|
@ -148,7 +150,7 @@ function realTime(data) {
|
||||||
|
|
||||||
/** 关闭窗口 */
|
/** 关闭窗口 */
|
||||||
function closeDialog() {
|
function closeDialog() {
|
||||||
options.img = userStore.avatar;
|
options.img = fileHost + userStore.avatar;
|
||||||
options.visible = false;
|
options.visible = false;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,221 +0,0 @@
|
||||||
# 权限树状表格组件使用说明
|
|
||||||
|
|
||||||
## 概述
|
|
||||||
|
|
||||||
这个权限树状表格组件实现了类似表格的树形权限管理界面,左侧显示树形菜单结构,右侧显示对应的权限复选框,完全符合您截图中的设计需求。
|
|
||||||
|
|
||||||
## 文件结构
|
|
||||||
|
|
||||||
```
|
|
||||||
src/views/system/user/role/
|
|
||||||
├── render.vue # 核心权限树状表格组件
|
|
||||||
├── permission-dialog.vue # 权限选择对话框组件
|
|
||||||
├── permission-example.vue # 完整使用示例
|
|
||||||
└── README.md # 使用说明
|
|
||||||
```
|
|
||||||
|
|
||||||
## 核心功能
|
|
||||||
|
|
||||||
### 1. 树状表格展示
|
|
||||||
- 表格样式的树形结构展示
|
|
||||||
- 支持多级树形结构
|
|
||||||
- 可展开/收起节点
|
|
||||||
- 支持节点复选框选择(含半选状态)
|
|
||||||
|
|
||||||
### 2. 权限复选框管理
|
|
||||||
- 每个节点可以配置独立的权限项
|
|
||||||
- 权限项以复选框形式展示在右侧
|
|
||||||
- 支持权限项的选中状态管理
|
|
||||||
- 支持热门权限标记
|
|
||||||
|
|
||||||
### 3. 表格式布局
|
|
||||||
- 左侧:菜单名称列(支持树形缩进)
|
|
||||||
- 右侧:权限操作列(权限复选框)
|
|
||||||
- 表格头部标题
|
|
||||||
- 行分隔线和悬停效果
|
|
||||||
|
|
||||||
## 数据结构
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const treeData = [
|
|
||||||
{
|
|
||||||
id: 1, // 节点唯一标识
|
|
||||||
label: '开站管理', // 节点显示名称
|
|
||||||
children: [ // 子节点(可选)
|
|
||||||
{
|
|
||||||
id: 11,
|
|
||||||
label: '待审核',
|
|
||||||
perms: [] // 权限列表(可选)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 12,
|
|
||||||
label: '待付款',
|
|
||||||
perms: [ // 权限项配置
|
|
||||||
{
|
|
||||||
key: 'pay',
|
|
||||||
label: '付款',
|
|
||||||
checked: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 15,
|
|
||||||
label: '已上线',
|
|
||||||
perms: [
|
|
||||||
{
|
|
||||||
key: 'add_brand',
|
|
||||||
label: '新增子品牌',
|
|
||||||
checked: false,
|
|
||||||
isHot: true // 热门权限标记
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'edit',
|
|
||||||
label: '修改',
|
|
||||||
checked: false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
## 使用方法
|
|
||||||
|
|
||||||
### 1. 基础使用
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
|
|
||||||
const treeTableRef = ref()
|
|
||||||
|
|
||||||
// 获取选中的数据
|
|
||||||
const getSelectedData = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
return treeTableRef.value.getCheckedData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 对话框形式使用
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<template>
|
|
||||||
<PermissionDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
:role-id="currentRoleId"
|
|
||||||
@confirm="handlePermissionConfirm"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import PermissionDialog from './permission-dialog.vue'
|
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const currentRoleId = ref(1)
|
|
||||||
|
|
||||||
const handlePermissionConfirm = (data) => {
|
|
||||||
console.log('选中的权限:', data)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
|
|
||||||
## 样式说明
|
|
||||||
|
|
||||||
### 1. 表格式布局
|
|
||||||
- 使用 CSS Grid 布局实现表格效果
|
|
||||||
- 左列:菜单名称(固定宽度 300px)
|
|
||||||
- 右列:权限操作(自适应宽度)
|
|
||||||
- 表格头部和内容分离
|
|
||||||
|
|
||||||
### 2. 主要样式类名
|
|
||||||
- `.permission-tree-table`: 组件容器
|
|
||||||
- `.table-header`: 表格头部
|
|
||||||
- `.table-content`: 表格内容区域
|
|
||||||
- `.table-row`: 每行的容器
|
|
||||||
- `.row-left`: 左侧菜单名称区域
|
|
||||||
- `.row-right`: 右侧权限操作区域
|
|
||||||
- `.expand-icon`: 展开/收起图标
|
|
||||||
- `.hot-tag`: 热门权限标记
|
|
||||||
|
|
||||||
### 3. 核心样式
|
|
||||||
```css
|
|
||||||
.permission-tree-table {
|
|
||||||
border: 1px solid #ebeef5;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-header {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 300px 1fr;
|
|
||||||
background: #f5f7fa;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 300px 1fr;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-row:hover {
|
|
||||||
background-color: #f5f7fa;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## API 说明
|
|
||||||
|
|
||||||
### Props
|
|
||||||
- `modelValue`: 对话框显示状态(仅对话框组件)
|
|
||||||
- `roleId`: 角色ID(可选)
|
|
||||||
|
|
||||||
### Events
|
|
||||||
- `confirm`: 确认选择权限时触发,返回选中的权限数据
|
|
||||||
|
|
||||||
### Methods
|
|
||||||
- `getCheckedData()`: 获取当前选中的数据
|
|
||||||
- 返回格式:
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
checkedNodes: [ // 选中的节点
|
|
||||||
{ id: 1, label: '开站管理' }
|
|
||||||
],
|
|
||||||
checkedPermissions: { // 选中的权限
|
|
||||||
"12": [
|
|
||||||
{ key: 'pay', label: '付款' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 扩展功能
|
|
||||||
|
|
||||||
### 1. 权限标记
|
|
||||||
可以为特定权限添加标记(如"热门"标记):
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
const isHot = perm === '新增子品牌'
|
|
||||||
// 在渲染时添加标记
|
|
||||||
h('span', { class: 'hot-tag' }, '热')
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 权限分组
|
|
||||||
可以通过树形结构对权限进行分组管理。
|
|
||||||
|
|
||||||
### 3. 权限搜索
|
|
||||||
可以添加搜索功能来快速定位特定权限。
|
|
||||||
|
|
||||||
## 注意事项
|
|
||||||
|
|
||||||
1. 确保每个节点的 `id` 唯一
|
|
||||||
2. `perms` 数组为空时不会显示权限复选框
|
|
||||||
3. 权限状态通过 `permissionState` 响应式对象管理
|
|
||||||
4. 使用 `:deep()` 选择器来修改 Element Plus 组件的默认样式
|
|
||||||
|
|
@ -70,7 +70,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User">
|
<script setup name="AuthUser">
|
||||||
import selectUser from "./selectUser";
|
import selectUser from "./selectUser";
|
||||||
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
|
import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role";
|
||||||
|
|
||||||
|
|
@ -108,7 +108,7 @@ const userIds = ref([]);
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 20,
|
||||||
roleId: route.params.roleId,
|
roleId: route.params.roleId,
|
||||||
userName: undefined,
|
userName: undefined,
|
||||||
phonenumber: undefined,
|
phonenumber: undefined,
|
||||||
|
|
|
||||||
|
|
@ -1,188 +1,163 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="68px">
|
|
||||||
<el-form-item label="角色名称" prop="roleName">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.roleName"
|
|
||||||
placeholder="请输入角色名称"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="权限字符" prop="roleKey">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.roleKey"
|
|
||||||
placeholder="请输入权限字符"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
@keyup.enter="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="status">
|
|
||||||
<el-select
|
|
||||||
v-model="queryParams.status"
|
|
||||||
placeholder="角色状态"
|
|
||||||
clearable
|
|
||||||
style="width: 240px"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="dict in sys_normal_disable"
|
|
||||||
:key="dict.value"
|
|
||||||
:label="dict.label"
|
|
||||||
:value="dict.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="创建时间" style="width: 308px">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
icon="Plus"
|
|
||||||
@click="handleAdd"
|
|
||||||
v-hasPermi="['system:role:add']"
|
|
||||||
>新增</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="success"
|
|
||||||
plain
|
|
||||||
icon="Edit"
|
|
||||||
:disabled="single"
|
|
||||||
@click="handleUpdate"
|
|
||||||
v-hasPermi="['system:role:edit']"
|
|
||||||
>修改</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
plain
|
|
||||||
icon="Delete"
|
|
||||||
:disabled="multiple"
|
|
||||||
@click="handleDelete"
|
|
||||||
v-hasPermi="['system:role:remove']"
|
|
||||||
>删除</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="warning"
|
|
||||||
plain
|
|
||||||
icon="Download"
|
|
||||||
@click="handleExport"
|
|
||||||
v-hasPermi="['system:role:export']"
|
|
||||||
>导出</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
|
<table-search-card :model="queryParams" @getList="getList" @handleQuery="handleQuery" @resetQuery="resetQuery">
|
||||||
|
<template #left>
|
||||||
|
<select-input-form ref="selectInputFormRef" :queryParamsList="queryParamsList" :queryParams="queryParams"
|
||||||
|
@handleQuery="handleQuery">
|
||||||
|
</select-input-form>
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
|
||||||
|
</template>
|
||||||
|
</table-search-card>
|
||||||
|
<el-alert :title="t('提示: 删除权限:后台账号数为0时,才能删除权限')" style="margin-bottom: 10px;" :closable="false" type="warning"
|
||||||
|
show-icon />
|
||||||
<!-- 表格数据 -->
|
<!-- 表格数据 -->
|
||||||
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
|
<el-table v-loading="loading" :data="roleList" ref="tableRef" class="c-table-main" @select="tableSelect"
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
@select-all="tableSelect" stripe border>
|
||||||
<el-table-column label="角色编号" prop="roleId" width="120" />
|
<el-table-column type="selection" width="55" :selectable="rowSelectable" align="center" />
|
||||||
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
|
<el-table-column label="权限名称" prop="roleName" min-width="150" align="center" >
|
||||||
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
|
<template #default="{ row }">
|
||||||
<el-table-column label="显示顺序" prop="roleSort" width="100" />
|
<span>{{ row.roleName }} <span v-if="row.defaultStatus == 0">(默认)</span></span>
|
||||||
<el-table-column label="状态" align="center" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch
|
|
||||||
v-model="scope.row.status"
|
|
||||||
active-value="0"
|
|
||||||
inactive-value="1"
|
|
||||||
@change="handleStatusChange(scope.row)"
|
|
||||||
></el-switch>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime">
|
<!-- <el-table-column label="权限类型" prop="roleName" min-width="110" align="center" /> -->
|
||||||
<template #default="scope">
|
<el-table-column label="权限适用范围" prop="roleScope" min-width="150" align="center">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<template #default="{ row }">
|
||||||
|
{{ row.roleScope || '--' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="用户列表" prop="roleSort" min-width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div v-if="row.sysUsers.length > 0">
|
||||||
|
<span v-for="(item, index) in row.sysUsers.slice(0, 5)" :key="item.userId" @click="handleUserListClick(row)" style="color: rgb(64, 158, 255);cursor: pointer;">
|
||||||
|
{{ item.userName }}
|
||||||
|
<span v-if="index < Math.min(5, row.sysUsers.length) - 1">,</span>
|
||||||
|
</span>
|
||||||
|
<span v-if="row.sysUsers.length > 5"> ...</span>
|
||||||
|
</div>
|
||||||
|
<div v-else>--</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="权限数" prop="menuCount" align="center" min-width="80">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.menuCount || '--' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="备注" prop="remark" min-width="130">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.remark || '--' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" min-width="200" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tooltip content="修改" placement="top" v-if="scope.row.roleId !== 1">
|
<el-button link type="primary" @click="handleDetail(scope.row)" v-hasPermi="['system:role:edit']">{{ t('详情')
|
||||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
}}</el-button>
|
||||||
</el-tooltip>
|
<el-button link type="primary" v-if="scope.row.defaultStatus == 1" @click="handleUpdate(scope.row)"
|
||||||
<el-tooltip content="删除" placement="top" v-if="scope.row.roleId !== 1">
|
v-hasPermi="['system:role:edit']">{{ t('修改') }}</el-button>
|
||||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']"></el-button>
|
<el-button link type="primary" @click="handleManage(scope.row)" v-hasPermi="['system:role:edit']">{{ t('管理')
|
||||||
</el-tooltip>
|
}}</el-button>
|
||||||
<el-tooltip content="数据权限" placement="top" v-if="scope.row.roleId !== 1">
|
<el-button link type="primary" v-if="scope.row.defaultStatus == 1" @click="handleDelete(scope.row)"
|
||||||
<el-button link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
v-hasPermi="['system:role:remove']">{{ t('删除') }}</el-button>
|
||||||
</el-tooltip>
|
|
||||||
<el-tooltip content="分配用户" placement="top" v-if="scope.row.roleId !== 1">
|
|
||||||
<el-button link type="primary" icon="User" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
|
||||||
</el-tooltip>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize"
|
||||||
<pagination
|
@pagination="getList" />
|
||||||
v-show="total > 0"
|
<!-- 批量操作 -->
|
||||||
:total="total"
|
<table-batch-operate v-if="total > 0" v-model:batchOpType="batchOpType"
|
||||||
v-model:page="queryParams.pageNum"
|
v-model:isAllSelection="isAllSelection" @allSelectionChange="allSelectionChange" @opTypeChange="opTypeChange"
|
||||||
v-model:limit="queryParams.pageSize"
|
:selectionData="selectionData" :opTypeOptions="opTypeOptions"></table-batch-operate>
|
||||||
@pagination="getList"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 添加或修改角色配置对话框 -->
|
<!-- 添加或修改角色配置对话框 -->
|
||||||
<el-dialog :title="title" align-center v-model="open" width="860px" append-to-body>
|
<el-dialog :title="title" align-center v-model="open" width="860px" append-to-body>
|
||||||
<el-scrollbar max-height="600px">
|
<el-scrollbar max-height="800px">
|
||||||
<el-form ref="roleRef" :model="form" :rules="rules" label-width="100px">
|
<el-form ref="roleRef" :model="form" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="角色名称" prop="roleName">
|
<el-form-item label="角色名称" prop="roleName">
|
||||||
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
|
<el-input v-model="form.roleName" :disabled="modifyStatus == 'detail' || modifyStatus == 'Manage'"
|
||||||
|
placeholder="请输入角色名称" maxlength="20" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="roleKey">
|
<el-form-item label="权限范围">
|
||||||
<template #label>
|
<el-select disabled v-model="form.dataScope" style="width: 350px;" @change="dataScopeSelectChange">
|
||||||
<span>
|
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label"
|
||||||
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
|
:value="item.value"></el-option>
|
||||||
<el-icon><question-filled /></el-icon>
|
</el-select>
|
||||||
</el-tooltip>
|
|
||||||
权限字符
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色顺序" prop="roleSort">
|
<el-form-item v-if="modifyStatus == 'add'" label="复制权限">
|
||||||
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
|
<el-select v-model="form.copyRoleId" style="width: 350px;" clearable @change="changeMenu">
|
||||||
|
<el-option v-for="item in roleOptions" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="角色等级" prop="roleLevel">
|
<el-form-item label="备注">
|
||||||
<NumberInput v-model="form.roleLevel" :placeholder="t('数字越高级别越高')" style="width: 200px;"></NumberInput>
|
<el-input v-model="form.remark" :disabled="modifyStatus == 'detail' || modifyStatus == 'Manage'"
|
||||||
|
type="textarea" placeholder="请输入内容"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态">
|
<el-form-item v-if="modifyStatus == 'Manage'" label="添加账号">
|
||||||
<el-radio-group v-model="form.status">
|
<el-row style="width: 100%;">
|
||||||
<el-radio
|
<el-col :span="16">
|
||||||
v-for="dict in sys_normal_disable"
|
<div style="width: 100%;">
|
||||||
:key="dict.value"
|
<checkbox-select v-if="showLoding" collapse-tags collapse-tags-tooltip style="width: 100%;" v-model="accountLinking"
|
||||||
:value="dict.value"
|
:options="accountOptions" :placeholder="t('请选择账号进行权限关联')"></checkbox-select>
|
||||||
>{{ dict.label }}</el-radio>
|
</div>
|
||||||
</el-radio-group>
|
</el-col>
|
||||||
|
<el-col :span="8" style="display: flex;justify-content: right;">
|
||||||
|
<div style="margin-left: 10px;">
|
||||||
|
<el-button type="primary" @click="handleAddAccount">{{ t('添加账户') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row v-if="sysUsersArr.length > 0" style="width: 100%;margin-top: 20px;">
|
||||||
|
<el-col :span="20">
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<el-input v-model="userNameText" style="width: 100%" :placeholder="t('输入关键字进行用户列表过滤,支持空格隔开的多关键字匹配')" @input="handleFilter" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4" style="display: flex;justify-content: right;">
|
||||||
|
<div style="margin-left: 10px;">
|
||||||
|
<el-button type="primary" @click="handleRemoveAccount">{{ t('移出账户') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="accounts-about-scroll-container" v-if="sysUsersArr.length > 0">
|
||||||
|
<el-tag v-for="(item,index) in form.sysUsers" :key="item.userId" closable type="info" style="margin-right: 10px;" @close="handleClose(item)">
|
||||||
|
{{ item.userName }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="菜单权限">
|
|
||||||
<!-- <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox> -->
|
<div style="display: flex;">
|
||||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
<div style="font-size: 14px;font-weight: 600;">{{ t('权限设置') }}</div>
|
||||||
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
<div style="margin-left: 10px;">{{ t('权限数') }}:{{ countTree }}</div>
|
||||||
|
<div @click="handleCheckedTreeExpand($event, 'menu')"
|
||||||
|
style="cursor: pointer;color: rgb(64, 158, 255);margin-left: 10px;">
|
||||||
|
<span v-if="!defaultExpandAll">{{ t('全部展开') }}</span>
|
||||||
|
<span v-if="defaultExpandAll">{{ t('全部收起') }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 100%;margin-top: 10px;">
|
||||||
|
<el-input v-model="filterText" style="width: 100%" :placeholder="t('输入关键字进行权限过滤,支持空格隔开的多关键字匹配')" />
|
||||||
|
</div>
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
<el-checkbox v-model="menuNodeAll" :disabled="modifyStatus == 'Manage' || modifyStatus == 'detail'"
|
||||||
|
@change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
||||||
|
<el-checkbox v-model="form.menuCheckStrictly" :disabled="modifyStatus == 'Manage' || modifyStatus == 'detail'"
|
||||||
|
@change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
||||||
<div class="table">
|
<div class="table">
|
||||||
<div class="menu-list">
|
<div class="menu-list">
|
||||||
<el-tree ref="menuRef" :data="menuOptions" default-expand-all :expand-on-click-node='false' check-on-click-node show-checkbox node-key="id"
|
<el-tree ref="menuRef" :data="menuOptions" v-if="defaultExpandShow" :default-expand-all="defaultExpandAll"
|
||||||
:check-strictly="!form.menuCheckStrictly" :props="{ label: 'label', children: 'children' }"></el-tree>
|
:expand-on-click-node='false' check-on-click-node show-checkbox node-key="id"
|
||||||
|
:check-strictly="!form.menuCheckStrictly"
|
||||||
|
:props="{ label: 'label', children: 'children', disabled: (data, node) => modifyStatus == 'Manage' || modifyStatus == 'detail', }"
|
||||||
|
:filter-node-method="filterNode"></el-tree>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <el-form-item label="菜单权限">
|
||||||
|
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
||||||
|
|
||||||
<!-- <el-tree
|
|
||||||
|
<el-tree
|
||||||
class="tree-border"
|
class="tree-border"
|
||||||
:data="menuOptions"
|
:data="menuOptions"
|
||||||
show-checkbox
|
show-checkbox
|
||||||
|
|
@ -192,21 +167,47 @@
|
||||||
empty-text="加载中,请稍候"
|
empty-text="加载中,请稍候"
|
||||||
:render-content="renderContent"
|
:render-content="renderContent"
|
||||||
:props="{ label: 'label', children: 'children' }"
|
:props="{ label: 'label', children: 'children' }"
|
||||||
></el-tree> -->
|
></el-tree>
|
||||||
|
</el-form-item> -->
|
||||||
|
</el-form>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
|
<el-button v-if="modifyStatus == 'detail' || modifyStatus == 'Manage'" @click="cancel">关 闭</el-button>
|
||||||
|
<el-button v-if="modifyStatus == 'add' || modifyStatus == 'edit'" type="primary" @click="submitForm">确
|
||||||
|
定</el-button>
|
||||||
|
<el-button v-if="modifyStatus == 'add' || modifyStatus == 'edit'" @click="cancel">取 消</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog :title="t('用户列表')" align-center v-model="openUserList" width="1050px" append-to-body>
|
||||||
|
<el-scrollbar max-height="800px">
|
||||||
|
<el-form ref="roleRef" label-width="100px">
|
||||||
|
<el-form-item label="权限名称">
|
||||||
|
{{ formUserList.roleName }}<span v-if="formUserList.defaultStatus == 0">(默认)</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备注">
|
<el-form-item label="用户列表">
|
||||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
<el-row v-if="sysUsersArr.length > 0" style="width: 100%;margin-top: 20px;">
|
||||||
|
<el-col :span="24">
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<el-input v-model="userListText" style="width: 100%" :placeholder="t('输入关键字进行用户列表过滤,支持空格隔开的多关键字匹配')" @input="handleUserListFilter" />
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="accounts-about-scroll-container" v-if="sysUsersArr.length > 0">
|
||||||
|
<el-tag v-for="(item,index) in formUserList.sysUsers" :key="item.userId" type="info" style="margin-right: 10px;" >
|
||||||
|
{{ item.userName }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button @click="cancelUserList">关 闭</el-button>
|
||||||
<el-button @click="cancel">取 消</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 分配角色数据权限对话框 -->
|
<!-- 分配角色数据权限对话框 -->
|
||||||
<el-dialog :title="title" align-center v-model="openDataScope" width="500px" append-to-body>
|
<el-dialog :title="title" align-center v-model="openDataScope" width="500px" append-to-body>
|
||||||
<el-form :model="form" label-width="80px">
|
<el-form :model="form" label-width="80px">
|
||||||
|
|
@ -217,30 +218,19 @@
|
||||||
<el-input v-model="form.roleKey" :disabled="true" />
|
<el-input v-model="form.roleKey" :disabled="true" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="权限范围">
|
<el-form-item label="权限范围">
|
||||||
<el-select v-model="form.dataScope" @change="dataScopeSelectChange">
|
<el-select @change="dataScopeSelectChange">
|
||||||
<el-option
|
<el-option v-for="item in dataScopeOptions" :key="item.value" :label="item.label"
|
||||||
v-for="item in dataScopeOptions"
|
:value="item.value"></el-option>
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="数据权限" v-show="form.dataScope == 2">
|
<el-form-item label="数据权限" v-show="form.dataScope == 2">
|
||||||
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
|
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
|
||||||
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
|
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">全选/全不选</el-checkbox>
|
||||||
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
|
<el-checkbox v-model="form.deptCheckStrictly"
|
||||||
<el-tree
|
@change="handleCheckedTreeConnect($event, 'dept')">父子联动</el-checkbox>
|
||||||
class="tree-border"
|
<el-tree class="tree-border" :data="deptOptions" show-checkbox default-expand-all ref="deptRef" node-key="id"
|
||||||
:data="deptOptions"
|
:check-strictly="!form.deptCheckStrictly" empty-text="加载中,请稍候"
|
||||||
show-checkbox
|
:props="{ label: 'label', children: 'children' }"></el-tree>
|
||||||
default-expand-all
|
|
||||||
ref="deptRef"
|
|
||||||
node-key="id"
|
|
||||||
:check-strictly="!form.deptCheckStrictly"
|
|
||||||
empty-text="加载中,请稍候"
|
|
||||||
:props="{ label: 'label', children: 'children' }"
|
|
||||||
></el-tree>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -253,14 +243,18 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User">
|
<script setup name="User">
|
||||||
import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from "@/api/system/role";
|
import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect, optionselect, getMenu, unallocatedUserList,authUserSelectAll,authUserCancelAll,authUserCancel,authRolecancelAll } from "@/api/system/role";
|
||||||
import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu";
|
import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu";
|
||||||
import NumberInput from "@/components/NumberInput";
|
import NumberInput from "@/components/NumberInput";
|
||||||
import Render from "./render.vue";
|
import TableBatchOperate from '@/components/TableBatchOperate'; // 批量操作
|
||||||
|
import CheckboxSelect from "@/components/CheckboxSelect"; // 下拉框多/全选
|
||||||
|
import { formatTime } from '@/utils/ruoyi';
|
||||||
|
import SelectInputForm from '@/components/SelectInputForm';
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||||
|
import { getLocalStorage } from "@/utils/auth";
|
||||||
const roleList = ref([]);
|
const roleList = ref([]);
|
||||||
const open = ref(false);
|
const open = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
|
|
@ -280,6 +274,23 @@ const deptOptions = ref([]);
|
||||||
const openDataScope = ref(false);
|
const openDataScope = ref(false);
|
||||||
const menuRef = ref(null);
|
const menuRef = ref(null);
|
||||||
const deptRef = ref(null);
|
const deptRef = ref(null);
|
||||||
|
const filterText = ref('');
|
||||||
|
const modifyStatus = ref('add');
|
||||||
|
const accountLinking = ref([]);
|
||||||
|
const accountOptions = ref([]);
|
||||||
|
const sysUsersArr = ref([]);
|
||||||
|
const formUserList = ref({});
|
||||||
|
const oldForm = shallowRef({ });
|
||||||
|
const queryParamsList = ref([{
|
||||||
|
label: proxy.t('角色名称'),
|
||||||
|
value: 'roleName',
|
||||||
|
}, {
|
||||||
|
label: proxy.t('后台账户'),
|
||||||
|
value: 'account',
|
||||||
|
}, {
|
||||||
|
label: proxy.t('后台呢称'),
|
||||||
|
value: 'nickName',
|
||||||
|
}])
|
||||||
|
|
||||||
/** 数据范围选项*/
|
/** 数据范围选项*/
|
||||||
const dataScopeOptions = ref([
|
const dataScopeOptions = ref([
|
||||||
|
|
@ -293,7 +304,8 @@ const data = reactive({
|
||||||
form: {},
|
form: {},
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 20,
|
||||||
|
searchType: 'roleName',
|
||||||
roleName: undefined,
|
roleName: undefined,
|
||||||
roleKey: undefined,
|
roleKey: undefined,
|
||||||
status: undefined
|
status: undefined
|
||||||
|
|
@ -307,7 +319,67 @@ const data = reactive({
|
||||||
});
|
});
|
||||||
|
|
||||||
const { queryParams, form, rules } = toRefs(data);
|
const { queryParams, form, rules } = toRefs(data);
|
||||||
|
// 批量操作
|
||||||
|
const tableRef = ref(),
|
||||||
|
isAllSelection = ref(false), // 是否全选
|
||||||
|
selectionData = ref([]), // 选中的表格数据
|
||||||
|
batchOpType = ref(''); // 选中的批量操作类型
|
||||||
|
// 批量操作选项
|
||||||
|
const opTypeOptions = ref([
|
||||||
|
{ label: proxy.t('批量清除关联账户'), value: 'update' },
|
||||||
|
{ label: proxy.t('批量删除'), value: 'ignore' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 勾选表格
|
||||||
|
const tableSelect = (val) => {
|
||||||
|
selectionData.value = val;
|
||||||
|
// 是否全选中
|
||||||
|
if (val.length == roleList.value.length) {
|
||||||
|
isAllSelection.value = true;
|
||||||
|
} else {
|
||||||
|
isAllSelection.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 全选表格
|
||||||
|
const allSelectionChange = () => {
|
||||||
|
tableRef.value.toggleAllSelection();
|
||||||
|
}
|
||||||
|
// 选择批量数据操作类型
|
||||||
|
const opTypeChange = () => {
|
||||||
|
if (batchOpType.value === 'ignore') {
|
||||||
|
const params = selectionData.value.map(i => i.roleId); // 选中的id集合
|
||||||
|
proxy.$modal.confirm(proxy.t('确认批量删除已选的' + params.length + '条记录吗?')).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
delRole(params).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
handleQuery();
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}else if (batchOpType.value === 'update') {
|
||||||
|
const params = selectionData.value.map(i => i.roleId); // 选中的id集合
|
||||||
|
proxy.$modal.confirm(proxy.t(`确认清除这些权限的关联账号(共${params.length}个)?`)).then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
authRolecancelAll({roleIds: params}).then(res => {
|
||||||
|
loading.value = false;
|
||||||
|
batchOpType.value = '';
|
||||||
|
proxy.$modal.msgSuccess(proxy.t('操作成功!'));
|
||||||
|
handleQuery();
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}).catch(() => {
|
||||||
|
batchOpType.value = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
/** 查询角色列表 */
|
/** 查询角色列表 */
|
||||||
function getList() {
|
function getList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
@ -318,6 +390,31 @@ function getList() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听输入框,调用 el-tree 的 filter
|
||||||
|
watch(filterText, (val) => {
|
||||||
|
menuRef.value && menuRef.value.filter(val);
|
||||||
|
});
|
||||||
|
const rowSelectable = (row, index) => {
|
||||||
|
return row.defaultStatus == 0 ? false:true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const openUserList = ref(false);
|
||||||
|
//打开用户列表
|
||||||
|
const handleUserListClick = (row) => {
|
||||||
|
openUserList.value = true;
|
||||||
|
sysUsersArr.value = row.sysUsers;
|
||||||
|
formUserList.value = row;
|
||||||
|
};
|
||||||
|
const cancelUserList = () => {
|
||||||
|
openUserList.value = false;
|
||||||
|
}
|
||||||
|
// 节点过滤方法
|
||||||
|
const filterNode = (value, data) => {
|
||||||
|
if (!value) return true;
|
||||||
|
// 支持多关键字,用空格分隔
|
||||||
|
const keywords = value.split(" ");
|
||||||
|
return keywords.every((kw) => data.label.includes(kw));
|
||||||
|
};
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
function handleQuery() {
|
function handleQuery() {
|
||||||
queryParams.value.pageNum = 1;
|
queryParams.value.pageNum = 1;
|
||||||
|
|
@ -339,7 +436,7 @@ function handleDelete(row) {
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
getList();
|
getList();
|
||||||
proxy.$modal.msgSuccess("删除成功");
|
proxy.$modal.msgSuccess("删除成功");
|
||||||
}).catch(() => {});
|
}).catch(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 导出按钮操作 */
|
/** 导出按钮操作 */
|
||||||
|
|
@ -387,14 +484,115 @@ function handleCommand(command, row) {
|
||||||
function handleAuthUser(row) {
|
function handleAuthUser(row) {
|
||||||
router.push("/system/role-auth/user/" + row.roleId);
|
router.push("/system/role-auth/user/" + row.roleId);
|
||||||
}
|
}
|
||||||
|
const countTree = ref(0);
|
||||||
/** 查询菜单树结构 */
|
/** 查询菜单树结构 */
|
||||||
function getMenuTreeselect() {
|
function getMenuTreeselect() {
|
||||||
menuTreeselect().then(response => {
|
menuTreeselect().then(response => {
|
||||||
|
countTree.value = response.count;
|
||||||
menuOptions.value = response.data;
|
menuOptions.value = response.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const showLoding = ref(true);
|
||||||
|
/** 获取用户列表 */
|
||||||
|
const getunallocatedUserList = (roleId) => {
|
||||||
|
unallocatedUserList({roleId: roleId }).then(response => {
|
||||||
|
accountOptions.value = response.data.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
label: item.userName,
|
||||||
|
value: item.userId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
showLoding.value = false;
|
||||||
|
nextTick(() => {
|
||||||
|
showLoding.value = true;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//添加关联账户
|
||||||
|
const handleAddAccount = () => {
|
||||||
|
if (accountLinking.value.length == 0){
|
||||||
|
proxy.$modal.msgError(proxy.t('请选择要关联的账户'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
proxy.$modal.confirm('请确认此操作,是否继续?').then(function () {
|
||||||
|
let obj = {
|
||||||
|
roleId:form.value.roleId,
|
||||||
|
userIds:accountLinking.value
|
||||||
|
}
|
||||||
|
return authUserSelectAll(obj);
|
||||||
|
}).then(() => {
|
||||||
|
getRole(form.value.roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
});
|
||||||
|
accountLinking.value = [];
|
||||||
|
getunallocatedUserList(form.value.roleId);
|
||||||
|
handleQuery();
|
||||||
|
proxy.$modal.msgSuccess("关联成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
const userNameText = ref('');
|
||||||
|
//片段2
|
||||||
|
const handleFilter = () => {
|
||||||
|
if (!userNameText.value.trim()) return form.value.sysUsers = sysUsersArr.value
|
||||||
|
|
||||||
|
const keywords = userNameText.value.trim().split(/\s+/) // 支持空格分隔多个关键词
|
||||||
|
form.value.sysUsers = sysUsersArr.value.filter(user =>
|
||||||
|
keywords.every(k => user.userName.includes(k))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const userListText = ref('');
|
||||||
|
//
|
||||||
|
const handleUserListFilter = () => {
|
||||||
|
if (!userListText.value.trim()) return formUserList.value.sysUsers = sysUsersArr.value
|
||||||
|
const keywords = userListText.value.trim().split(/\s+/) // 支持空格分隔多个关键词
|
||||||
|
formUserList.value.sysUsers = sysUsersArr.value.filter(user =>
|
||||||
|
keywords.every(k => user.userName.includes(k))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
//移出关联账户
|
||||||
|
const handleRemoveAccount = () => {
|
||||||
|
if (form.value.sysUsers.length == 0){
|
||||||
|
proxy.$modal.msgError("请选择要移出的账户");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
proxy.$modal.confirm('请确认此操作,是否继续?').then(function () {
|
||||||
|
let userIds = form.value.sysUsers.map(item => item.userId);
|
||||||
|
let obj = {
|
||||||
|
roleId:form.value.roleId,
|
||||||
|
userIds:userIds
|
||||||
|
}
|
||||||
|
return authUserCancelAll(obj);
|
||||||
|
}).then(() => {
|
||||||
|
getRole(form.value.roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
});
|
||||||
|
handleQuery();
|
||||||
|
getunallocatedUserList(form.value.roleId);
|
||||||
|
proxy.$modal.msgSuccess("移出成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
//单个移出关联账户
|
||||||
|
const handleClose = (row) => {
|
||||||
|
proxy.$modal.confirm('请确认此操作,是否继续?').then(function () {
|
||||||
|
let userIds = form.value.sysUsers.map(item => item.userId);
|
||||||
|
let obj = {
|
||||||
|
roleId:form.value.roleId,
|
||||||
|
userId:row.userId
|
||||||
|
}
|
||||||
|
return authUserCancel(obj);
|
||||||
|
}).then(() => {
|
||||||
|
getRole(form.value.roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
});
|
||||||
|
handleQuery();
|
||||||
|
getunallocatedUserList(form.value.roleId);
|
||||||
|
proxy.$modal.msgSuccess("移出成功");
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
/** 所有部门节点数据 */
|
/** 所有部门节点数据 */
|
||||||
function getDeptAllCheckedKeys() {
|
function getDeptAllCheckedKeys() {
|
||||||
// 目前被选中的部门节点
|
// 目前被选中的部门节点
|
||||||
|
|
@ -428,15 +626,94 @@ function reset() {
|
||||||
};
|
};
|
||||||
proxy.resetForm("roleRef");
|
proxy.resetForm("roleRef");
|
||||||
}
|
}
|
||||||
|
const roleOptions = ref([]);
|
||||||
/** 添加角色 */
|
/** 添加角色 */
|
||||||
function handleAdd() {
|
function handleAdd() {
|
||||||
reset();
|
reset();
|
||||||
getMenuTreeselect();
|
getMenuTreeselect();
|
||||||
open.value = true;
|
open.value = true;
|
||||||
title.value = "添加角色";
|
title.value = "新增角色";
|
||||||
|
modifyStatus.value = 'add';
|
||||||
|
form.value.dataScope = getLocalStorage('userInfo')?.nickName;
|
||||||
|
optionselect({}).then(response => {
|
||||||
|
roleOptions.value = response.data.map(item => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
label: item.roleName,
|
||||||
|
value: item.roleId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
const handleDetail = (row) => {
|
||||||
|
reset();
|
||||||
|
const roleId = row.roleId || ids.value;
|
||||||
|
const roleMenu = getRoleMenuTreeselect(roleId);
|
||||||
|
getRole(roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
form.value.roleSort = Number(form.value.roleSort);
|
||||||
|
open.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
roleMenu.then((res) => {
|
||||||
|
let checkedKeys = res.checkedKeys;
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
nextTick(() => {
|
||||||
|
menuRef.value.setChecked(v, true, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
form.value.dataScope = response.data.roleScope;
|
||||||
|
modifyStatus.value = 'detail';
|
||||||
|
title.value = "角色详情";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 角色管理
|
||||||
|
const handleManage = (row) => {
|
||||||
|
reset();
|
||||||
|
const roleId = row.roleId || ids.value;
|
||||||
|
const roleMenu = getRoleMenuTreeselect(roleId);
|
||||||
|
getunallocatedUserList(roleId);
|
||||||
|
getRole(roleId).then(response => {
|
||||||
|
form.value = response.data;
|
||||||
|
sysUsersArr.value = response.data.sysUsers;
|
||||||
|
form.value.roleSort = Number(form.value.roleSort);
|
||||||
|
open.value = true;
|
||||||
|
nextTick(() => {
|
||||||
|
roleMenu.then((res) => {
|
||||||
|
let checkedKeys = res.checkedKeys;
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
nextTick(() => {
|
||||||
|
menuRef.value.setChecked(v, true, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
form.value.dataScope = response.data.roleScope;
|
||||||
|
modifyStatus.value = 'Manage';
|
||||||
|
title.value = "角色管理";
|
||||||
|
form.value.roleId = row.roleId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//复制权限
|
||||||
|
const changeMenu = (roleId) => {
|
||||||
|
if (roleId) {
|
||||||
|
getMenu(roleId).then(response => {
|
||||||
|
let checkedKeys = response.data;
|
||||||
|
checkedKeys.forEach((v) => {
|
||||||
|
nextTick(() => {
|
||||||
|
menuRef.value.setChecked(v, true, false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
menuRef.value.setCheckedKeys([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/** 修改角色 */
|
/** 修改角色 */
|
||||||
function handleUpdate(row) {
|
function handleUpdate(row) {
|
||||||
reset();
|
reset();
|
||||||
|
|
@ -456,6 +733,13 @@ function handleUpdate(row) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
|
oldForm.value = JSON.stringify(form.value);
|
||||||
|
}, 600);
|
||||||
|
form.value.dataScope = response.data.roleScope;
|
||||||
|
modifyStatus.value = 'edit';
|
||||||
title.value = "修改角色";
|
title.value = "修改角色";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -475,14 +759,25 @@ function getDeptTree(roleId) {
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const defaultExpandAll = ref(false);
|
||||||
|
const defaultExpandShow = ref(true);
|
||||||
/** 树权限(展开/折叠)*/
|
/** 树权限(展开/折叠)*/
|
||||||
function handleCheckedTreeExpand(value, type) {
|
function handleCheckedTreeExpand(value, type) {
|
||||||
if (type == "menu") {
|
if (type == "menu") {
|
||||||
let treeList = menuOptions.value;
|
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
// let treeList = menuOptions.value;
|
||||||
menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
// for (let i = 0; i < treeList.length; i++) {
|
||||||
|
// menuRef.value.store.nodesMap[treeList[i].id].expanded = value;
|
||||||
|
// }
|
||||||
|
if (!defaultExpandAll.value) {
|
||||||
|
defaultExpandAll.value = true;
|
||||||
|
} else {
|
||||||
|
defaultExpandAll.value = false;
|
||||||
}
|
}
|
||||||
|
defaultExpandShow.value = false;
|
||||||
|
nextTick(() => {
|
||||||
|
defaultExpandShow.value = true;
|
||||||
|
});
|
||||||
} else if (type == "dept") {
|
} else if (type == "dept") {
|
||||||
let treeList = deptOptions.value;
|
let treeList = deptOptions.value;
|
||||||
for (let i = 0; i < treeList.length; i++) {
|
for (let i = 0; i < treeList.length; i++) {
|
||||||
|
|
@ -525,14 +820,32 @@ function submitForm() {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (form.value.roleId != undefined) {
|
if (form.value.roleId != undefined) {
|
||||||
form.value.menuIds = getMenuAllCheckedKeys();
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
updateRole(form.value).then(response => {
|
|
||||||
|
if (JSON.stringify(form.value) != oldForm.value) {
|
||||||
|
let params = {
|
||||||
|
menuIds: form.value.menuIds,
|
||||||
|
roleName: form.value.roleName,
|
||||||
|
remark: form.value.remark,
|
||||||
|
roleSort: form.value.roleSort,
|
||||||
|
roleId: form.value.roleId,
|
||||||
|
};
|
||||||
|
updateRole(params).then(response => {
|
||||||
proxy.$modal.msgSuccess("修改成功");
|
proxy.$modal.msgSuccess("修改成功");
|
||||||
open.value = false;
|
open.value = false;
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
}else{
|
||||||
|
open.value = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
form.value.menuIds = getMenuAllCheckedKeys();
|
form.value.menuIds = getMenuAllCheckedKeys();
|
||||||
addRole(form.value).then(response => {
|
let params = {
|
||||||
|
menuIds: form.value.menuIds,
|
||||||
|
roleName: form.value.roleName,
|
||||||
|
remark: form.value.remark,
|
||||||
|
roleSort: form.value.roleSort,
|
||||||
|
};
|
||||||
|
addRole(params).then(response => {
|
||||||
proxy.$modal.msgSuccess("新增成功");
|
proxy.$modal.msgSuccess("新增成功");
|
||||||
open.value = false;
|
open.value = false;
|
||||||
getList();
|
getList();
|
||||||
|
|
@ -592,8 +905,10 @@ function cancelDataScope() {
|
||||||
openDataScope.value = false;
|
openDataScope.value = false;
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
//初始化
|
||||||
getList();
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.custom-node-row {
|
.custom-node-row {
|
||||||
|
|
@ -622,6 +937,7 @@ getList();
|
||||||
width: 240px;
|
width: 240px;
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table {
|
.table {
|
||||||
// padding: 20px;
|
// padding: 20px;
|
||||||
// min-height: 88vh;
|
// min-height: 88vh;
|
||||||
|
|
@ -629,39 +945,51 @@ getList();
|
||||||
width: 100%;
|
width: 100%;
|
||||||
// margin: 20px;
|
// margin: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-list {
|
.menu-list {
|
||||||
::v-deep .el-tree {
|
::v-deep .el-tree {
|
||||||
border-top: 1px solid #ebeef5;
|
border-top: 1px solid #ebeef5;
|
||||||
border-left: 1px solid #ebeef5;
|
border-left: 1px solid #ebeef5;
|
||||||
border-right: 1px solid #ebeef5;
|
border-right: 1px solid #ebeef5;
|
||||||
|
|
||||||
.el-tree-node__expand-icon {
|
.el-tree-node__expand-icon {
|
||||||
// display: none !important;
|
// display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node {
|
.el-tree-node {
|
||||||
|
|
||||||
&.is-expanded,
|
&.is-expanded,
|
||||||
&.is-current,
|
&.is-current,
|
||||||
&.is-focusable {
|
&.is-focusable {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node__content {
|
.el-tree-node__content {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> .el-tree-node {
|
|
||||||
|
>.el-tree-node {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid #ebeef5;
|
border-bottom: 1px solid #ebeef5;
|
||||||
position: relative;
|
position: relative;
|
||||||
> .el-tree-node__content {
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
>.el-tree-node__content {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-left: 20px !important;
|
padding-left: 20px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node__children {
|
.el-tree-node__children {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
content: ' ';
|
content: ' ';
|
||||||
display: block;
|
display: block;
|
||||||
|
|
@ -672,6 +1000,7 @@ getList();
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tree-node {
|
.el-tree-node {
|
||||||
// width: 350px;
|
// width: 350px;
|
||||||
padding: 10px 0px;
|
padding: 10px 0px;
|
||||||
|
|
@ -683,4 +1012,16 @@ getList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.accounts-about-scroll-container {
|
||||||
|
align-items: flex-start;
|
||||||
|
content-visibility: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin-top: 10px;
|
||||||
|
max-height: 100px;
|
||||||
|
overflow: auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
align-center
|
|
||||||
title="新增权限"
|
|
||||||
width="800px"
|
|
||||||
:before-close="handleClose"
|
|
||||||
>
|
|
||||||
<div class="permission-dialog">
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button @click="handleCancel">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed } from 'vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
modelValue: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
roleId: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: null
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'confirm'])
|
|
||||||
|
|
||||||
const treeTableRef = ref()
|
|
||||||
|
|
||||||
const dialogVisible = computed({
|
|
||||||
get: () => props.modelValue,
|
|
||||||
set: (val) => emit('update:modelValue', val)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取选中的权限数据
|
|
||||||
const getSelectedPermissions = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
return treeTableRef.value.getCheckedData()
|
|
||||||
}
|
|
||||||
return { checkedNodes: [], checkedPermissions: {} }
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCancel = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleConfirm = () => {
|
|
||||||
const selectedData = getSelectedPermissions()
|
|
||||||
emit('confirm', selectedData)
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.permission-dialog {
|
|
||||||
max-height: 500px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-footer {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,195 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="permission-example">
|
|
||||||
<div class="header">
|
|
||||||
<h2>权限树使用示例</h2>
|
|
||||||
<el-button type="primary" @click="showPermissionDialog">
|
|
||||||
新增权限
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 权限对话框 -->
|
|
||||||
<PermissionDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
:role-id="currentRoleId"
|
|
||||||
@confirm="handlePermissionConfirm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 直接展示权限树状表格 -->
|
|
||||||
<div class="tree-container">
|
|
||||||
<h3>权限树状表格展示:</h3>
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
|
|
||||||
<div class="action-buttons">
|
|
||||||
<el-button @click="getSelectedData">获取选中数据</el-button>
|
|
||||||
<el-button type="primary" @click="savePermissions">保存权限</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 已选权限展示 -->
|
|
||||||
<div v-if="selectedData" class="selected-permissions">
|
|
||||||
<h3>已选择的权限:</h3>
|
|
||||||
|
|
||||||
<div class="permission-summary">
|
|
||||||
<div class="section">
|
|
||||||
<h4>选中的节点:</h4>
|
|
||||||
<div class="node-list">
|
|
||||||
<el-tag
|
|
||||||
v-for="node in selectedData.checkedNodes"
|
|
||||||
:key="node.id"
|
|
||||||
size="small"
|
|
||||||
class="node-tag"
|
|
||||||
>
|
|
||||||
{{ node.label }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section">
|
|
||||||
<h4>选中的权限:</h4>
|
|
||||||
<div v-for="(perms, nodeId) in selectedData.checkedPermissions" :key="nodeId" class="node-permissions">
|
|
||||||
<strong>节点 {{ nodeId }}:</strong>
|
|
||||||
<el-tag
|
|
||||||
v-for="perm in perms"
|
|
||||||
:key="perm.key"
|
|
||||||
size="small"
|
|
||||||
type="success"
|
|
||||||
class="perm-tag"
|
|
||||||
>
|
|
||||||
{{ perm.label }}
|
|
||||||
</el-tag>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PermissionDialog from './permission-dialog.vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const currentRoleId = ref(1)
|
|
||||||
const selectedData = ref(null)
|
|
||||||
const treeTableRef = ref()
|
|
||||||
|
|
||||||
const showPermissionDialog = () => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePermissionConfirm = (data) => {
|
|
||||||
console.log('确认选择的权限:', data)
|
|
||||||
selectedData.value = data
|
|
||||||
|
|
||||||
// 这里可以调用API保存权限
|
|
||||||
// await saveRolePermissions(currentRoleId.value, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSelectedData = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
const data = treeTableRef.value.getCheckedData()
|
|
||||||
selectedData.value = data
|
|
||||||
console.log('当前选中的数据:', data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const savePermissions = async () => {
|
|
||||||
const data = getSelectedData()
|
|
||||||
if (data) {
|
|
||||||
try {
|
|
||||||
// 这里调用保存权限的API
|
|
||||||
// await saveRolePermissions(currentRoleId.value, data)
|
|
||||||
console.log('保存权限成功:', data)
|
|
||||||
// 显示成功消息
|
|
||||||
// ElMessage.success('权限保存成功')
|
|
||||||
} catch (error) {
|
|
||||||
console.error('保存权限失败:', error)
|
|
||||||
// ElMessage.error('权限保存失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.permission-example {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tree-container {
|
|
||||||
margin-bottom: 30px;
|
|
||||||
padding: 20px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons {
|
|
||||||
margin-top: 20px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.action-buttons .el-button {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selected-permissions {
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.permission-summary {
|
|
||||||
margin-top: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section h4 {
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
color: #303133;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-permissions {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
padding: 10px;
|
|
||||||
background: white;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-permissions strong {
|
|
||||||
display: block;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
color: #303133;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-tag,
|
|
||||||
.perm-tag {
|
|
||||||
margin-right: 8px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.node-tag {
|
|
||||||
background-color: #409eff;
|
|
||||||
border-color: #409eff;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,588 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="table">
|
|
||||||
<!-- default-expand-all 默认展开全部数据 -->
|
|
||||||
<!-- expand-on-click-node 只有点击箭头才会收缩节点 -->
|
|
||||||
<!-- check-on-click-node 点击文本选中 -->
|
|
||||||
<!-- show-checkbox 复选框 -->
|
|
||||||
<div class="menu-list">
|
|
||||||
<el-tree ref="tree" :data="list" default-expand-all :expand-on-click-node='false' check-on-click-node show-checkbox node-key="menuId" :props="defaultProps"></el-tree>
|
|
||||||
</div>
|
|
||||||
<el-button @click="getCheckedKeys">通过 key 获取</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
list: [
|
|
||||||
{
|
|
||||||
"menuId": 1,
|
|
||||||
"menuName": "首页(首页)",
|
|
||||||
"menuCode": "首页",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 0,
|
|
||||||
"path": "/page",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shouye",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 2,
|
|
||||||
"menuName": "首页(首页)",
|
|
||||||
"menuCode": "首页",
|
|
||||||
"parentId": 1,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "/welcome",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 3,
|
|
||||||
"menuName": "随访数据查询(随访数据查询)",
|
|
||||||
"menuCode": "随访数据查询",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "/followUpDataQuery",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shengwuxuejiance",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 4,
|
|
||||||
"menuName": "随访数据查询(随访数据查询)",
|
|
||||||
"menuCode": "随访数据查询",
|
|
||||||
"parentId": 3,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 5,
|
|
||||||
"menuName": "随访详情(随访详情)",
|
|
||||||
"menuCode": "随访详情",
|
|
||||||
"parentId": 3,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "detail",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 21,
|
|
||||||
"menuName": "此单名称(11)",
|
|
||||||
"menuCode": "11",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "请问请问饿```",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "321",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
// "children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 6,
|
|
||||||
"menuName": "调查数据查询(调查数据查询)",
|
|
||||||
"menuCode": "调查数据查询",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "/surveyDataQuery",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shaichaxinxichaxun",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 7,
|
|
||||||
"menuName": "调查数据查询(调查数据查询)",
|
|
||||||
"menuCode": "调查数据查询",
|
|
||||||
"parentId": 6,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 8,
|
|
||||||
"menuName": "新建问卷(新建问卷)",
|
|
||||||
"menuCode": "新建问卷",
|
|
||||||
"parentId": 6,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "evaluationreport",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 9,
|
|
||||||
"menuName": "随访详情(随访详情)",
|
|
||||||
"menuCode": "随访详情",
|
|
||||||
"parentId": 6,
|
|
||||||
"orderNum": 3,
|
|
||||||
"path": "evaluationlook",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 10,
|
|
||||||
"menuName": "任务配置(任务配置)",
|
|
||||||
"menuCode": "任务配置",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 3,
|
|
||||||
"path": "/taskSet",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-renwuguanli",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 11,
|
|
||||||
"menuName": "任务配置(任务配置)",
|
|
||||||
"menuCode": "任务配置",
|
|
||||||
"parentId": 10,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 12,
|
|
||||||
"menuName": "数据统计(数据统计)",
|
|
||||||
"menuCode": "数据统计",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 4,
|
|
||||||
"path": "/dataStatistics",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-shujutongji",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 13,
|
|
||||||
"menuName": "数据统计(数据统计)",
|
|
||||||
"menuCode": "数据统计",
|
|
||||||
"parentId": 12,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 14,
|
|
||||||
"menuName": "数据导出(数据导出)",
|
|
||||||
"menuCode": "数据导出",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 5,
|
|
||||||
"path": "/dataExport",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-suifangrenwuguanli",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 15,
|
|
||||||
"menuName": "数据导出(数据导出)",
|
|
||||||
"menuCode": "数据导出",
|
|
||||||
"parentId": 14,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "index",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 16,
|
|
||||||
"menuName": "系统管理(系统管理)",
|
|
||||||
"menuCode": "系统管理",
|
|
||||||
"parentId": 0,
|
|
||||||
"orderNum": 6,
|
|
||||||
"path": "/systemManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 0,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "iconfont icon-xitongguanli",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 1,
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"menuId": 17,
|
|
||||||
"menuName": "用户管理(用户管理)",
|
|
||||||
"menuCode": "用户管理",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 1,
|
|
||||||
"path": "usersManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 18,
|
|
||||||
"menuName": "角色管理(角色管理)",
|
|
||||||
"menuCode": "角色管理",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 2,
|
|
||||||
"path": "roleManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 19,
|
|
||||||
"menuName": "权限配置(权限配置)",
|
|
||||||
"menuCode": "权限配置",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 3,
|
|
||||||
"path": "permissionSetting",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"menuId": 20,
|
|
||||||
"menuName": "菜单管理(菜单管理)",
|
|
||||||
"menuCode": "菜单管理",
|
|
||||||
"parentId": 16,
|
|
||||||
"orderNum": 4,
|
|
||||||
"path": "menuManage",
|
|
||||||
"component": null,
|
|
||||||
"query": null,
|
|
||||||
"isFrame": 0,
|
|
||||||
"isCache": 0,
|
|
||||||
"menuType": 1,
|
|
||||||
"visible": 1,
|
|
||||||
"perms": null,
|
|
||||||
"icon": "",
|
|
||||||
"status": 1,
|
|
||||||
"remark": null,
|
|
||||||
"roleId": null,
|
|
||||||
"selected": true,
|
|
||||||
"level": 2,
|
|
||||||
"children": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
defaultProps: {
|
|
||||||
children: 'children', // 子级
|
|
||||||
label: 'menuName' // 名称
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
// 回显菜单
|
|
||||||
this.setCheckedKeys()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 提交数据
|
|
||||||
getCheckedKeys () {
|
|
||||||
// 获取子级的key
|
|
||||||
const childMenu = this.$refs.tree.getCheckedKeys()
|
|
||||||
// 获取父级的key
|
|
||||||
const partMenu = this.$refs.tree.getHalfCheckedKeys()
|
|
||||||
// 合并数据
|
|
||||||
const menu = partMenu.concat(childMenu)
|
|
||||||
console.log(menu)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 回显菜单
|
|
||||||
setCheckedKeys () {
|
|
||||||
// 一般是调接口,拿到菜单数据和回显的菜单数组
|
|
||||||
|
|
||||||
// 如果default-expand-all没有展开列表时,可以使用下面代码,设置展开所有行,
|
|
||||||
// const nodesMap = this.$refs.tree.store.nodesMap
|
|
||||||
// const keys = Object.keys(nodesMap)
|
|
||||||
// keys.forEach(key => {
|
|
||||||
// nodesMap[key].expanded = true
|
|
||||||
// })
|
|
||||||
|
|
||||||
// 设置回显的菜单
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.tree.setCheckedKeys([3])
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.table {
|
|
||||||
padding: 20px;
|
|
||||||
min-height: 88vh;
|
|
||||||
background: #fff;
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
.menu-list {
|
|
||||||
::v-deep .el-tree {
|
|
||||||
border-top: 1px solid #ebeef5;
|
|
||||||
border-left: 1px solid #ebeef5;
|
|
||||||
border-right: 1px solid #ebeef5;
|
|
||||||
.el-tree-node__expand-icon {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
.el-tree-node {
|
|
||||||
&.is-expanded,
|
|
||||||
&.is-current,
|
|
||||||
&.is-focusable {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
.el-tree-node__content {
|
|
||||||
background-color: transparent !important;
|
|
||||||
&:hover {
|
|
||||||
background-color: transparent !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
> .el-tree-node {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
position: relative;
|
|
||||||
> .el-tree-node__content {
|
|
||||||
width: 300px;
|
|
||||||
height: 100%;
|
|
||||||
padding-left: 20px !important;
|
|
||||||
}
|
|
||||||
.el-tree-node__children {
|
|
||||||
position: relative;
|
|
||||||
&::after {
|
|
||||||
content: ' ';
|
|
||||||
display: block;
|
|
||||||
width: 1px;
|
|
||||||
height: 100%;
|
|
||||||
border-left: 1px solid #ebeef5;
|
|
||||||
position: absolute;
|
|
||||||
left: 0px;
|
|
||||||
top: 0px;
|
|
||||||
}
|
|
||||||
.el-tree-node {
|
|
||||||
width: 350px;
|
|
||||||
padding: 10px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 授权用户 -->
|
<!-- 授权用户 -->
|
||||||
<el-dialog title="选择用户" align-center v-model="visible" width="800px" top="5vh" append-to-body>
|
<el-dialog title="选择用户" v-model="visible" width="800px" top="5vh" append-to-body>
|
||||||
<el-form :model="queryParams" ref="queryRef" :inline="true">
|
<el-form :model="queryParams" ref="queryRef" :inline="true">
|
||||||
<el-form-item label="用户名称" prop="userName">
|
<el-form-item label="用户名称" prop="userName">
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
<span>{{ formatTime(scope.row.createTime) }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup name="User">
|
<script setup name="SelectUser">
|
||||||
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role";
|
import { authUserSelectAll, unallocatedUserList } from "@/api/system/role";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -79,7 +79,7 @@ const userIds = ref([]);
|
||||||
|
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 20,
|
||||||
roleId: undefined,
|
roleId: undefined,
|
||||||
userName: undefined,
|
userName: undefined,
|
||||||
phonenumber: undefined
|
phonenumber: undefined
|
||||||
|
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="test-page">
|
|
||||||
<el-card>
|
|
||||||
<template #header>
|
|
||||||
<div class="card-header">
|
|
||||||
<span>权限树状表格测试页面</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 权限树状表格 -->
|
|
||||||
<PermissionTreeTable ref="treeTableRef" />
|
|
||||||
|
|
||||||
<!-- 操作按钮 -->
|
|
||||||
<div class="actions">
|
|
||||||
<el-button @click="getSelectedData">获取选中数据</el-button>
|
|
||||||
<el-button type="primary" @click="showDialog">打开对话框</el-button>
|
|
||||||
<el-button type="success" @click="setDefaultData">设置默认选中</el-button>
|
|
||||||
<el-button type="warning" @click="clearAll">清空所有</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 结果展示 -->
|
|
||||||
<div v-if="selectedData" class="result">
|
|
||||||
<h3>选中结果:</h3>
|
|
||||||
<el-alert
|
|
||||||
title="数据获取成功"
|
|
||||||
type="success"
|
|
||||||
:closable="false"
|
|
||||||
show-icon
|
|
||||||
/>
|
|
||||||
<pre>{{ JSON.stringify(selectedData, null, 2) }}</pre>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 对话框测试 -->
|
|
||||||
<PermissionDialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
@confirm="handleDialogConfirm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PermissionTreeTable from './render.vue'
|
|
||||||
import PermissionDialog from './permission-dialog.vue'
|
|
||||||
|
|
||||||
const treeTableRef = ref()
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const selectedData = ref(null)
|
|
||||||
|
|
||||||
// 获取选中数据
|
|
||||||
const getSelectedData = () => {
|
|
||||||
if (treeTableRef.value) {
|
|
||||||
const data = treeTableRef.value.getCheckedData()
|
|
||||||
selectedData.value = data
|
|
||||||
console.log('选中的数据:', data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示对话框
|
|
||||||
const showDialog = () => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理对话框确认
|
|
||||||
const handleDialogConfirm = (data) => {
|
|
||||||
selectedData.value = data
|
|
||||||
console.log('对话框确认的数据:', data)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置默认选中数据(示例)
|
|
||||||
const setDefaultData = () => {
|
|
||||||
// 这里可以实现设置默认选中状态的逻辑
|
|
||||||
console.log('设置默认选中数据')
|
|
||||||
// 由于当前实现是内部状态管理,这里只是示例
|
|
||||||
// 实际使用时可能需要通过props传入初始状态
|
|
||||||
}
|
|
||||||
|
|
||||||
// 清空所有选中
|
|
||||||
const clearAll = () => {
|
|
||||||
// 这里可以实现清空所有选中状态的逻辑
|
|
||||||
console.log('清空所有选中')
|
|
||||||
selectedData.value = null
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.test-page {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
margin: 20px 0;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions .el-button {
|
|
||||||
margin: 0 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result {
|
|
||||||
margin-top: 20px;
|
|
||||||
padding: 20px;
|
|
||||||
background: #f9f9f9;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result h3 {
|
|
||||||
margin-top: 0;
|
|
||||||
color: #303133;
|
|
||||||
}
|
|
||||||
|
|
||||||
.result pre {
|
|
||||||
background: #fff;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #e4e7ed;
|
|
||||||
overflow-x: auto;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-alert {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
<template>
|
||||||
|
<!-- 账户详情 -->
|
||||||
|
<el-dialog :title="t('账户详情')" align-center v-model="showDialog" width="700px" append-to-body
|
||||||
|
class="el-dialog">
|
||||||
|
<el-scrollbar max-height="700px">
|
||||||
|
<el-descriptions :column="1" border class="c-descriptions">
|
||||||
|
<el-descriptions-item :label="t('所属部门')" label-width="150">
|
||||||
|
{{ modifyDate.dept?.deptName||'--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('后台账号')" label-width="150" >
|
||||||
|
{{ modifyDate.userName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('后台昵称')" label-width="150">
|
||||||
|
{{ modifyDate.nickName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('权限名称')" label-width="150">
|
||||||
|
{{ modifyDate.roleName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('创建人')" label-width="150">
|
||||||
|
{{ modifyDate.updateBy||modifyDate.createBy }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('创建时间')" label-width="150">
|
||||||
|
{{ formatTime(modifyDate.createTime) }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登录方式')" label-width="150">
|
||||||
|
{{ t('密码登录') }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登录时间')" label-width="150">
|
||||||
|
{{ formatTime(modifyDate.loginDate) || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登出时间')" label-width="150">
|
||||||
|
{{ formatTime(modifyDate.exitDate) || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :label="t('最后登入IP')" label-width="150">
|
||||||
|
{{ modifyDate.loginIp || '--' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
|
||||||
|
|
||||||
|
</el-descriptions>
|
||||||
|
</el-scrollbar>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="closeDialog">{{ t('取 消') }}</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
|
import { formatTime } from '@/utils/ruoyi';
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const emits = defineEmits(['submit', 'update:show']) // 自定义事件
|
||||||
|
const props = defineProps({ // 父组件向子组件传值
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
modifyDate: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const showDialog = computed({// 对话框显示隐藏
|
||||||
|
get() {
|
||||||
|
return props.show
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emits('update:show', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const formAll = reactive({ // 表单验证数据
|
||||||
|
id: '',
|
||||||
|
rewardAmount:'',
|
||||||
|
auditRate:'',
|
||||||
|
remark:'',
|
||||||
|
password:''
|
||||||
|
})
|
||||||
|
|
||||||
|
//数据更新区域
|
||||||
|
nextTick(() => {
|
||||||
|
formAll.id = props.modifyDate.id;
|
||||||
|
})
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
});
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scope lang="scss">
|
||||||
|
.icon-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.disable-click {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 150px;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 150px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
<template>
|
||||||
|
<!-- Google验证码 -->
|
||||||
|
<el-dialog v-model="showDialog" align-center width="500px" append-to-body
|
||||||
|
class="el-dialog">
|
||||||
|
<template #title>
|
||||||
|
<div class="title" style="width: 100%;text-align: center;">Google验证码</div>
|
||||||
|
</template>
|
||||||
|
<el-form :model="formGoogle" :rules="rulesGoogle" ref="googleRef" label-width="130px">
|
||||||
|
<el-form-item label="Google验证码" prop="googleCode">
|
||||||
|
<el-input v-model="formGoogle.googleCode" placeholder="请输入您的Google验证码" maxlength="6" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer" style="display: flex;justify-content: center;">
|
||||||
|
<el-button @click="showDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitGoogle">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { nextTick, ref } from "vue";
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
const emits = defineEmits(['submit', 'update:show']) // 自定义事件
|
||||||
|
const props = defineProps({ // 父组件向子组件传值
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
modifyDate: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const showDialog = computed({// 对话框显示隐藏
|
||||||
|
get() {
|
||||||
|
return props.show
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
emits('update:show', value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const rulesGoogle = reactive({
|
||||||
|
googleCode: [{ required: true, message: "请输入谷歌验证码", trigger: "change" }]
|
||||||
|
});
|
||||||
|
const formGoogle = reactive({
|
||||||
|
googleCode: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
//数据更新区域
|
||||||
|
nextTick(() => {
|
||||||
|
|
||||||
|
})
|
||||||
|
const submitGoogle = () => {
|
||||||
|
proxy.$refs["googleRef"].validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
emits('submit', formGoogle.googleCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 初始化
|
||||||
|
onMounted(() => {
|
||||||
|
});
|
||||||
|
// 关闭弹窗
|
||||||
|
const closeDialog = () => {
|
||||||
|
showDialog.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<style scope lang="scss">
|
||||||
|
.icon-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.disable-click {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.clt-item {
|
||||||
|
.label-box {
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 150px;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
word-break: break-all;
|
||||||
|
line-height: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-form-item__error) {
|
||||||
|
padding-left: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
width: calc(100% - 150px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
<span>批量数量:</span>
|
||||||
|
<b>{{ batchCount }}</b>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form :model="form">
|
||||||
|
<el-form-item label="操作类型">
|
||||||
|
<el-select v-model="form.actionType" placeholder="请选择操作类型" style="width: 300px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in options"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { reactive } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
batchCount: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
actionType: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
// 这里可以暴露给外部取值
|
||||||
|
defineExpose({ form });
|
||||||
|
</script>
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue