optimize: ♻️ 添加权限验证以及修改表格bug
This commit is contained in:
parent
3d5c2eaa12
commit
397dbcfdff
|
@ -8,7 +8,7 @@ export const fetchGetDeptList = (data: any) => {
|
||||||
|
|
||||||
/** 部门管理---获取所有部门管理列表 */
|
/** 部门管理---获取所有部门管理列表 */
|
||||||
export const fetchGetAllDeptList = () => {
|
export const fetchGetAllDeptList = () => {
|
||||||
return http.request<BaseResult<object>>('get', 'dept/getAllDeptList');
|
return http.request<BaseResult<object>>('get', 'dept/noManage/getAllDeptList');
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 部门管理---添加部门管理 */
|
/** 部门管理---添加部门管理 */
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import vxeTableBar from './src/bar';
|
||||||
|
import { withInstall } from '@pureadmin/utils';
|
||||||
|
|
||||||
|
/** 配合 `vxe-table` 实现快速便捷的表格操作 */
|
||||||
|
export const VxeTableBar = withInstall(vxeTableBar);
|
|
@ -0,0 +1,266 @@
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
import { transformI18n } from '@/plugins/i18n';
|
||||||
|
import { useEpThemeStoreHook } from '@/store/modules/epTheme';
|
||||||
|
import { cloneDeep, delay, getKeyList } from '@pureadmin/utils';
|
||||||
|
import { computed, defineComponent, getCurrentInstance, nextTick, type PropType, ref, unref } from 'vue';
|
||||||
|
import Fullscreen from '@iconify-icons/ri/fullscreen-fill';
|
||||||
|
import ExitFullscreen from '@iconify-icons/ri/fullscreen-exit-fill';
|
||||||
|
import DragIcon from '@/assets/table-bar/drag.svg?component';
|
||||||
|
import ExpandIcon from '@/assets/table-bar/expand.svg?component';
|
||||||
|
import RefreshIcon from '@/assets/table-bar/refresh.svg?component';
|
||||||
|
import SettingIcon from '@/assets/table-bar/settings.svg?component';
|
||||||
|
import CollapseIcon from '@/assets/table-bar/collapse.svg?component';
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
/** 头部最左边的标题 */
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '列表',
|
||||||
|
},
|
||||||
|
vxeTableRef: {
|
||||||
|
type: Object as PropType<any>,
|
||||||
|
},
|
||||||
|
/** 需要展示的列 */
|
||||||
|
columns: {
|
||||||
|
type: Array as PropType<any>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
/** 是否为树列表 */
|
||||||
|
tree: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isExpandAll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
tableKey: {
|
||||||
|
type: [String, Number] as PropType<string | number>,
|
||||||
|
default: '0',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'VxeTableBar',
|
||||||
|
props,
|
||||||
|
emits: ['refresh', 'fullscreen'],
|
||||||
|
setup(props, { emit, slots, attrs }) {
|
||||||
|
const size = ref('small');
|
||||||
|
const loading = ref(false);
|
||||||
|
const checkAll = ref(true);
|
||||||
|
const isFullscreen = ref(false);
|
||||||
|
const isIndeterminate = ref(false);
|
||||||
|
const instance = getCurrentInstance()!;
|
||||||
|
const isExpandAll = ref(props.isExpandAll);
|
||||||
|
let checkColumnList = getKeyList(cloneDeep(props?.columns), 'title');
|
||||||
|
const checkedColumns = ref(getKeyList(cloneDeep(props?.columns), 'title'));
|
||||||
|
const dynamicColumns = ref(cloneDeep(props?.columns));
|
||||||
|
|
||||||
|
const getDropdownItemStyle = computed(() => {
|
||||||
|
return s => {
|
||||||
|
return {
|
||||||
|
background: s === size.value ? useEpThemeStoreHook().epThemeColor : '',
|
||||||
|
color: s === size.value ? '#fff' : 'var(--el-text-color-primary)',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const iconClass = computed(() => {
|
||||||
|
return ['text-black', 'dark:text-white', 'duration-100', 'hover:!text-primary', 'cursor-pointer', 'outline-none'];
|
||||||
|
});
|
||||||
|
|
||||||
|
const topClass = computed(() => {
|
||||||
|
return ['flex', 'justify-between', 'pt-[3px]', 'px-[11px]', 'border-b-[1px]', 'border-solid', 'border-[#dcdfe6]', 'dark:border-[#303030]'];
|
||||||
|
});
|
||||||
|
|
||||||
|
function onReFresh() {
|
||||||
|
loading.value = true;
|
||||||
|
emit('refresh');
|
||||||
|
delay(500).then(() => (loading.value = false));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExpand() {
|
||||||
|
isExpandAll.value = !isExpandAll.value;
|
||||||
|
isExpandAll.value ? props.vxeTableRef.setAllTreeExpand(true) : props.vxeTableRef.clearTreeExpand();
|
||||||
|
props.vxeTableRef.refreshColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFullscreen() {
|
||||||
|
isFullscreen.value = !isFullscreen.value;
|
||||||
|
emit('fullscreen', isFullscreen.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadColumn() {
|
||||||
|
const curCheckedColumns = cloneDeep(dynamicColumns.value).filter(item => checkedColumns.value.includes(item.title));
|
||||||
|
props.vxeTableRef.reloadColumn(curCheckedColumns);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCheckAllChange(val: boolean) {
|
||||||
|
checkedColumns.value = val ? checkColumnList : [];
|
||||||
|
isIndeterminate.value = false;
|
||||||
|
reloadColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCheckedColumnsChange(value: string[]) {
|
||||||
|
checkedColumns.value = value;
|
||||||
|
const checkedCount = value.length;
|
||||||
|
checkAll.value = checkedCount === checkColumnList.length;
|
||||||
|
isIndeterminate.value = checkedCount > 0 && checkedCount < checkColumnList.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function onReset() {
|
||||||
|
checkAll.value = true;
|
||||||
|
isIndeterminate.value = false;
|
||||||
|
dynamicColumns.value = cloneDeep(props?.columns);
|
||||||
|
checkColumnList = [];
|
||||||
|
checkColumnList = getKeyList(cloneDeep(props?.columns), 'title');
|
||||||
|
checkedColumns.value = getKeyList(cloneDeep(props?.columns), 'title');
|
||||||
|
props.vxeTableRef.refreshColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeSize(curSize: string) {
|
||||||
|
size.value = curSize;
|
||||||
|
props.vxeTableRef.refreshColumn();
|
||||||
|
}
|
||||||
|
|
||||||
|
const dropdown = {
|
||||||
|
dropdown: () => (
|
||||||
|
<el-dropdown-menu class='translation'>
|
||||||
|
<el-dropdown-item style={getDropdownItemStyle.value('medium')} onClick={() => changeSize('medium')}>
|
||||||
|
宽松
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item style={getDropdownItemStyle.value('small')} onClick={() => changeSize('small')}>
|
||||||
|
默认
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item style={getDropdownItemStyle.value('mini')} onClick={() => changeSize('mini')}>
|
||||||
|
紧凑
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 列展示拖拽排序 */
|
||||||
|
const rowDrop = (event: { preventDefault: () => void }) => {
|
||||||
|
event.preventDefault();
|
||||||
|
nextTick(() => {
|
||||||
|
const wrapper: HTMLElement = (instance?.proxy?.$refs[`VxeGroupRef${unref(props.tableKey)}`] as any).$el.firstElementChild;
|
||||||
|
Sortable.create(wrapper, {
|
||||||
|
animation: 300,
|
||||||
|
handle: '.drag-btn',
|
||||||
|
onEnd: ({ newIndex, oldIndex, item }) => {
|
||||||
|
const targetThElem = item;
|
||||||
|
const wrapperElem = targetThElem.parentNode as HTMLElement;
|
||||||
|
const oldColumn = dynamicColumns.value[oldIndex];
|
||||||
|
const newColumn = dynamicColumns.value[newIndex];
|
||||||
|
if (oldColumn?.fixed || newColumn?.fixed) {
|
||||||
|
// 当前列存在fixed属性 则不可拖拽
|
||||||
|
const oldThElem = wrapperElem.children[oldIndex] as HTMLElement;
|
||||||
|
if (newIndex > oldIndex) {
|
||||||
|
wrapperElem.insertBefore(targetThElem, oldThElem);
|
||||||
|
} else {
|
||||||
|
wrapperElem.insertBefore(targetThElem, oldThElem ? oldThElem.nextElementSibling : oldThElem);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const currentRow = dynamicColumns.value.splice(oldIndex, 1)[0];
|
||||||
|
dynamicColumns.value.splice(newIndex, 0, currentRow);
|
||||||
|
reloadColumn();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const isFixedColumn = (title: string) => {
|
||||||
|
return dynamicColumns.value.filter(item => transformI18n(item.title) === transformI18n(title))[0].fixed;
|
||||||
|
};
|
||||||
|
|
||||||
|
const rendTippyProps = (content: string) => {
|
||||||
|
// https://vue-tippy.netlify.app/props
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
offset: [0, 18],
|
||||||
|
duration: [300, 0],
|
||||||
|
followCursor: true,
|
||||||
|
hideOnClick: 'toggle',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const reference = {
|
||||||
|
reference: () => <SettingIcon class={['w-[16px]', iconClass.value]} v-tippy={rendTippyProps('列设置')} />,
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<>
|
||||||
|
<div {...attrs} class={['w-[99/100]', 'px-2', 'pb-2', 'bg-bg_color', isFullscreen.value ? ['!w-full', '!h-full', 'z-[2002]', 'fixed', 'inset-0'] : 'mt-2']}>
|
||||||
|
<div class='flex justify-between w-full h-[60px] p-4'>
|
||||||
|
{slots?.title ? slots.title() : <p class='font-bold truncate'>{props.title}</p>}
|
||||||
|
<div class='flex items-center justify-around'>
|
||||||
|
{slots?.buttons ? <div class='flex mr-4'>{slots.buttons()}</div> : null}
|
||||||
|
{props.tree ? (
|
||||||
|
<>
|
||||||
|
<ExpandIcon
|
||||||
|
class={['w-[16px]', iconClass.value]}
|
||||||
|
style={{
|
||||||
|
transform: isExpandAll.value ? 'none' : 'rotate(-90deg)',
|
||||||
|
}}
|
||||||
|
v-tippy={rendTippyProps(isExpandAll.value ? '折叠' : '展开')}
|
||||||
|
onClick={() => onExpand()}
|
||||||
|
/>
|
||||||
|
<el-divider direction='vertical' />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
<RefreshIcon class={['w-[16px]', iconClass.value, loading.value ? 'animate-spin' : '']} v-tippy={rendTippyProps('刷新')} onClick={() => onReFresh()} />
|
||||||
|
<el-divider direction='vertical' />
|
||||||
|
<el-dropdown v-slots={dropdown} trigger='click' v-tippy={rendTippyProps('密度')}>
|
||||||
|
<CollapseIcon class={['w-[16px]', iconClass.value]} />
|
||||||
|
</el-dropdown>
|
||||||
|
<el-divider direction='vertical' />
|
||||||
|
|
||||||
|
<el-popover v-slots={reference} placement='bottom-start' popper-style={{ padding: 0 }} width='200' trigger='click'>
|
||||||
|
<div class={[topClass.value]}>
|
||||||
|
<el-checkbox class='!-mr-1' label='列展示' v-model={checkAll.value} indeterminate={isIndeterminate.value} onChange={value => handleCheckAllChange(value)} />
|
||||||
|
<el-button type='primary' link onClick={() => onReset()}>
|
||||||
|
重置
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='pt-[6px] pl-[11px]'>
|
||||||
|
<el-scrollbar max-height='36vh'>
|
||||||
|
<el-checkbox-group ref={`VxeGroupRef${unref(props.tableKey)}`} modelValue={checkedColumns.value} onChange={value => handleCheckedColumnsChange(value)}>
|
||||||
|
<el-space direction='vertical' alignment='flex-start' size={0}>
|
||||||
|
{checkColumnList.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<div class='flex items-center'>
|
||||||
|
<DragIcon class={['drag-btn w-[16px] mr-2', isFixedColumn(item) ? '!cursor-no-drop' : '!cursor-grab']} onMouseenter={(event: { preventDefault: () => void }) => rowDrop(event)} />
|
||||||
|
<el-checkbox key={index} label={item} value={item} onChange={reloadColumn}>
|
||||||
|
<span title={transformI18n(item)} class='inline-block w-[120px] truncate hover:text-text_color_primary'>
|
||||||
|
{transformI18n(item)}
|
||||||
|
</span>
|
||||||
|
</el-checkbox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</el-space>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-scrollbar>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
<el-divider direction='vertical' />
|
||||||
|
|
||||||
|
<iconifyIconOffline
|
||||||
|
class={['w-[16px]', iconClass.value]}
|
||||||
|
icon={isFullscreen.value ? ExitFullscreen : Fullscreen}
|
||||||
|
v-tippy={isFullscreen.value ? '退出全屏' : '全屏'}
|
||||||
|
onClick={() => onFullscreen()}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{slots.default({
|
||||||
|
size: size.value,
|
||||||
|
dynamicColumns: dynamicColumns.value,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
|
@ -110,7 +110,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCheckColumnListChange(val: boolean, label: string) {
|
function handleCheckColumnListChange(val: boolean, label: string) {
|
||||||
dynamicColumns.value.filter(item => $t(item.label) === $t(label))[0].hide = !val;
|
dynamicColumns.value.filter(item => item.label === label)[0].hide = !val;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReset() {
|
function onReset() {
|
||||||
|
@ -169,7 +169,7 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
const isFixedColumn = (label: string) => {
|
const isFixedColumn = (label: string) => {
|
||||||
return !!dynamicColumns.value.filter(item => item.label === label)[0].fixed;
|
return dynamicColumns.value.filter(item => item.label === label)[0].fixed;
|
||||||
};
|
};
|
||||||
|
|
||||||
const rendTippyProps = (content: string) => ({
|
const rendTippyProps = (content: string) => ({
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// 多组件库的国际化和本地项目国际化兼容
|
// 多组件库的国际化和本地项目国际化兼容
|
||||||
import { createI18n } from 'vue-i18n';
|
import { createI18n } from 'vue-i18n';
|
||||||
import type { App } from 'vue';
|
import type { App, WritableComputedRef } from 'vue';
|
||||||
|
import { isObject } from '@pureadmin/utils';
|
||||||
|
|
||||||
// ? 从本地存储中获取数据
|
// ? 从本地存储中获取数据
|
||||||
const languageData = localStorage.getItem('i18nStore');
|
const languageData = localStorage.getItem('i18nStore');
|
||||||
|
@ -17,7 +18,7 @@ export const i18n = createI18n({
|
||||||
messages: languageData ? JSON.parse(languageData).i18n : {},
|
messages: languageData ? JSON.parse(languageData).i18n : {},
|
||||||
});
|
});
|
||||||
|
|
||||||
/*const siphonI18n = (function () {
|
const siphonI18n = (function () {
|
||||||
// 仅初始化一次国际化配置
|
// 仅初始化一次国际化配置
|
||||||
let cache = Object.fromEntries(
|
let cache = Object.fromEntries(
|
||||||
Object.entries(import.meta.glob('../../locales/!*.y(a)?ml', { eager: true })).map(([key, value]: any) => {
|
Object.entries(import.meta.glob('../../locales/!*.y(a)?ml', { eager: true })).map(([key, value]: any) => {
|
||||||
|
@ -30,7 +31,7 @@ export const i18n = createI18n({
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/!** 获取对象中所有嵌套对象的key键,并将它们用点号分割组成字符串 *!/
|
/** 获取对象中所有嵌套对象的key键,并将它们用点号分割组成字符串 */
|
||||||
function getObjectKeys(obj) {
|
function getObjectKeys(obj) {
|
||||||
const stack = [];
|
const stack = [];
|
||||||
const keys: Set<string> = new Set();
|
const keys: Set<string> = new Set();
|
||||||
|
@ -54,7 +55,7 @@ function getObjectKeys(obj) {
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
/!** 将展开的key缓存 *!/
|
/** 将展开的key缓存 */
|
||||||
const keysCache: Map<string, Set<string>> = new Map();
|
const keysCache: Map<string, Set<string>> = new Map();
|
||||||
const flatI18n = (prefix = 'zh') => {
|
const flatI18n = (prefix = 'zh') => {
|
||||||
let cache = keysCache.get(prefix);
|
let cache = keysCache.get(prefix);
|
||||||
|
@ -65,11 +66,11 @@ const flatI18n = (prefix = 'zh') => {
|
||||||
return cache;
|
return cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/!**
|
/**
|
||||||
* 国际化转换工具函数(自动读取根目录locales文件夹下文件进行国际化匹配)
|
* 国际化转换工具函数(自动读取根目录locales文件夹下文件进行国际化匹配)
|
||||||
* @param message message
|
* @param message message
|
||||||
* @returns 转化后的message
|
* @returns 转化后的message
|
||||||
*!/
|
*/
|
||||||
export function transformI18n(message: any = '') {
|
export function transformI18n(message: any = '') {
|
||||||
if (!message) {
|
if (!message) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -91,7 +92,7 @@ export function transformI18n(message: any = '') {
|
||||||
} else {
|
} else {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
export const $t: any = (i18n.global as any).t as any;
|
export const $t: any = (i18n.global as any).t as any;
|
||||||
|
|
||||||
|
|
|
@ -312,6 +312,10 @@ function hasAuth(value: string | Array<string>): boolean {
|
||||||
/** 从当前路由的`meta`字段里获取按钮级别的所有自定义`code`值 */
|
/** 从当前路由的`meta`字段里获取按钮级别的所有自定义`code`值 */
|
||||||
const metaAuths = getAuths();
|
const metaAuths = getAuths();
|
||||||
if (!metaAuths) return false;
|
if (!metaAuths) return false;
|
||||||
|
// 管理员权限
|
||||||
|
if (metaAuths.includes('*::*::*') || metaAuths.includes('*::*') || metaAuths.includes('*')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return isString(value) ? metaAuths.includes(value) : isIncludeAllChildren(value, metaAuths);
|
return isString(value) ? metaAuths.includes(value) : isIncludeAllChildren(value, metaAuths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@ import Airplane from '@/assets/svg/airplane.svg';
|
||||||
import { useDeptStore } from '@/store/system/dept';
|
import { useDeptStore } from '@/store/system/dept';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
import { usePublicHooks } from '@/views/hooks';
|
import { usePublicHooks } from '@/views/hooks';
|
||||||
|
import { auth } from '@/views/system/adminUser/utils/auth';
|
||||||
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
const adminUserStore = useAdminUserStore();
|
const adminUserStore = useAdminUserStore();
|
||||||
const deptStore = useDeptStore();
|
const deptStore = useDeptStore();
|
||||||
|
@ -88,6 +90,7 @@ onMounted(() => {
|
||||||
<div :class="['flex', 'justify-between', deviceDetection() && 'flex-wrap']">
|
<div :class="['flex', 'justify-between', deviceDetection() && 'flex-wrap']">
|
||||||
<tree ref="treeRef" :class="['mr-2', deviceDetection() ? 'w-full' : 'min-w-[200px]']" :treeData="deptList" :treeLoading="deptStore.loading" @tree-select="onTreeSelect" />
|
<tree ref="treeRef" :class="['mr-2', deviceDetection() ? 'w-full' : 'min-w-[200px]']" :treeData="deptList" :treeLoading="deptStore.loading" @tree-select="onTreeSelect" />
|
||||||
<div :class="[deviceDetection() ? ['w-full', 'mt-2'] : 'w-[calc(100%-200px)]']">
|
<div :class="[deviceDetection() ? ['w-full', 'mt-2'] : 'w-[calc(100%-200px)]']">
|
||||||
|
<Auth :value="auth.search">
|
||||||
<el-form ref="formRef" :inline="true" :model="adminUserStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="formRef" :inline="true" :model="adminUserStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<!-- 查询用户名 -->
|
<!-- 查询用户名 -->
|
||||||
<el-form-item :label="$t('adminUser_username')" prop="username">
|
<el-form-item :label="$t('adminUser_username')" prop="username">
|
||||||
|
@ -133,13 +136,16 @@ onMounted(() => {
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<PureTableBar :columns="columns" :title="$t('userinfo')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
<PureTableBar :columns="columns" :title="$t('userinfo')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd"> {{ $t('addNew') }}</el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd">
|
||||||
|
{{ $t('addNew') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量删除按钮 -->
|
<!-- 批量删除按钮 -->
|
||||||
<el-button :disabled="!(deleteIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
<el-button v-if="hasAuth(auth.deleted)" :disabled="!(deleteIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
||||||
{{ $t('deleteBatches') }}
|
{{ $t('deleteBatches') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -212,10 +218,10 @@ onMounted(() => {
|
||||||
|
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<!-- 修改 -->
|
<!-- 修改 -->
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
<el-button v-if="hasAuth(auth.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
|
|
||||||
<!-- 删除 -->
|
<!-- 删除 -->
|
||||||
<el-popconfirm :title="`${$t('delete')} ${row.username}?`" @confirm="onDelete(row)">
|
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')} ${row.username}?`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
{{ $t('delete') }}
|
{{ $t('delete') }}
|
||||||
|
@ -228,16 +234,20 @@ onMounted(() => {
|
||||||
<el-button :icon="useRenderIcon(More)" :size="size" class="ml-3 mt-[2px]" link type="primary" />
|
<el-button :icon="useRenderIcon(More)" :size="size" class="ml-3 mt-[2px]" link type="primary" />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item>
|
<!-- 上传头像 -->
|
||||||
|
<el-dropdown-item v-if="hasAuth(auth.uploadAvatarByAdmin)">
|
||||||
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Upload)" :size="size" link type="primary" @click="onUploadAvatar(row)"> {{ $t('upload_avatar') }} </el-button>
|
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Upload)" :size="size" link type="primary" @click="onUploadAvatar(row)"> {{ $t('upload_avatar') }} </el-button>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item>
|
<!-- 重置密码 -->
|
||||||
|
<el-dropdown-item v-if="hasAuth(auth.updateUserPasswordByAdmin)">
|
||||||
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Password)" :size="size" link type="primary" @click="onResetPassword(row)"> {{ $t('reset_passwords') }} </el-button>
|
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Password)" :size="size" link type="primary" @click="onResetPassword(row)"> {{ $t('reset_passwords') }} </el-button>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item>
|
<!-- 分配角色 -->
|
||||||
|
<el-dropdown-item v-if="hasAuth(auth.updateUserPasswordByAdmin)">
|
||||||
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Role)" :size="size" link type="primary" @click="onAssignRolesToUser(row)"> {{ $t('assign_roles') }} </el-button>
|
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Role)" :size="size" link type="primary" @click="onAssignRolesToUser(row)"> {{ $t('assign_roles') }} </el-button>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item>
|
<!-- 强制下线 -->
|
||||||
|
<el-dropdown-item v-if="hasAuth(auth.forcedOffline)">
|
||||||
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Airplane)" :size="size" link type="primary" @click="onForcedOffline(row)"> {{ $t('forced_offline') }} </el-button>
|
<el-button :class="tableSelectButtonClass" :icon="useRenderIcon(Airplane)" :size="size" link type="primary" @click="onForcedOffline(row)"> {{ $t('forced_offline') }} </el-button>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
export const auth = {
|
||||||
|
// 分页查询
|
||||||
|
search: ['user::getAdminUserList'],
|
||||||
|
// 添加操作
|
||||||
|
add: ['user::addAdminUser'],
|
||||||
|
// 更新操作
|
||||||
|
update: ['user::updateAdminUser'],
|
||||||
|
// 删除操作
|
||||||
|
deleted: ['user::deleteAdminUser'],
|
||||||
|
// 管理员上传为用户修改头像
|
||||||
|
uploadAvatarByAdmin: ['user::uploadAvatarByAdmin'],
|
||||||
|
// 强制用户下线
|
||||||
|
forcedOffline: ['user::forcedOffline'],
|
||||||
|
// 修改用户状态:是否禁用
|
||||||
|
updateUserStatusByAdmin: ['user::updateUserStatusByAdmin'],
|
||||||
|
// 管理员修改密码
|
||||||
|
updateUserPasswordByAdmin: ['user::updateUserPasswordByAdmin'],
|
||||||
|
};
|
|
@ -9,7 +9,7 @@ export const isAddUserinfo = ref(false);
|
||||||
// 表格列
|
// 表格列
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ type: 'selection', align: 'left' },
|
{ type: 'selection', align: 'left' },
|
||||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
{ type: 'index', index: (index: number) => index + 1, label: $t('index'), width: 60 },
|
||||||
// 用户名
|
// 用户名
|
||||||
{ label: $t('adminUser_username'), prop: 'username', width: 260 },
|
{ label: $t('adminUser_username'), prop: 'username', width: 260 },
|
||||||
// 状态
|
// 状态
|
||||||
|
|
|
@ -256,7 +256,7 @@ export const onUploadAvatar = (row: any) => {
|
||||||
*/
|
*/
|
||||||
export const onResetPassword = (row: any) => {
|
export const onResetPassword = (row: any) => {
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `重置 ${row.username} 用户的密码`,
|
title: `${$t('buttons.reset')} ${row.username} ${$t('userPassword')}`,
|
||||||
width: '30%',
|
width: '30%',
|
||||||
draggable: true,
|
draggable: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
|
@ -287,7 +287,7 @@ export const onResetPassword = (row: any) => {
|
||||||
*/
|
*/
|
||||||
export const onAssignRolesToUser = (row: any) => {
|
export const onAssignRolesToUser = (row: any) => {
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `为 ${row.username} 分配角色`,
|
title: `${$t('for')} ${row.username} ${$t('assign_roles')}`,
|
||||||
width: '45%',
|
width: '45%',
|
||||||
draggable: true,
|
draggable: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
|
|
|
@ -14,41 +14,32 @@ import { useDeptStore } from '@/store/system/dept';
|
||||||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
import { handleTree } from '@/utils/tree';
|
import { handleTree } from '@/utils/tree';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
|
import { auth } from '@/views/system/dept/utils/auth';
|
||||||
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const deptStore = useDeptStore();
|
const deptStore = useDeptStore();
|
||||||
const datalist = computed(() => handleTree(deptStore.datalist));
|
const datalist = computed(() => handleTree(deptStore.datalist));
|
||||||
|
|
||||||
/**
|
/** 当前页改变时 */
|
||||||
* * 当前页改变时
|
|
||||||
*/
|
|
||||||
const onCurrentPageChange = async (value: number) => {
|
const onCurrentPageChange = async (value: number) => {
|
||||||
deptStore.pagination.currentPage = value;
|
deptStore.pagination.currentPage = value;
|
||||||
await onSearch();
|
await onSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/** 当分页发生变化 */
|
||||||
* * 当分页发生变化
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
const onPageSizeChange = async (value: number) => {
|
const onPageSizeChange = async (value: number) => {
|
||||||
deptStore.pagination.pageSize = value;
|
deptStore.pagination.pageSize = value;
|
||||||
await onSearch();
|
await onSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/** 选择多行 */
|
||||||
* * 选择多行
|
|
||||||
* @param rows
|
|
||||||
*/
|
|
||||||
const onSelectionChange = (rows: Array<any>) => {
|
const onSelectionChange = (rows: Array<any>) => {
|
||||||
deleteIds.value = rows.map((row: any) => row.id);
|
deleteIds.value = rows.map((row: any) => row.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/** 重置表单 */
|
||||||
* 重置表单
|
|
||||||
* @param formEl
|
|
||||||
*/
|
|
||||||
const resetForm = async (formEl: FormInstance | undefined) => {
|
const resetForm = async (formEl: FormInstance | undefined) => {
|
||||||
if (!formEl) return;
|
if (!formEl) return;
|
||||||
formEl.resetFields();
|
formEl.resetFields();
|
||||||
|
@ -62,6 +53,7 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
<Auth :value="auth.search">
|
||||||
<el-form ref="formRef" :inline="true" :model="deptStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="formRef" :inline="true" :model="deptStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<el-form-item :label="$t('dept_deptName')" prop="deptName">
|
<el-form-item :label="$t('dept_deptName')" prop="deptName">
|
||||||
<el-input v-model="deptStore.form.deptName" :placeholder="`${$t('input')}${$t('dept_deptName')}`" class="!w-[180px]" clearable />
|
<el-input v-model="deptStore.form.deptName" :placeholder="`${$t('input')}${$t('dept_deptName')}`" class="!w-[180px]" clearable />
|
||||||
|
@ -74,13 +66,16 @@ onMounted(() => {
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<PureTableBar :columns="columns" :isExpandAll="true" :tableRef="tableRef?.getTableRef()" :title="$t('dept')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
<PureTableBar :columns="columns" :isExpandAll="true" :tableRef="tableRef?.getTableRef()" :title="$t('dept')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd()"> {{ $t('addNew') }}</el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd()">
|
||||||
|
{{ $t('addNew') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量删除按钮 -->
|
<!-- 批量删除按钮 -->
|
||||||
<el-button :disabled="!(deleteIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
<el-button v-if="hasAuth(auth.deleted)" :disabled="!(deleteIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
||||||
{{ $t('deleteBatches') }}
|
{{ $t('deleteBatches') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -120,9 +115,9 @@ onMounted(() => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
<el-button v-if="hasAuth(auth.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary" @click="onAdd(row.id)"> {{ $t('addNew') }} </el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary" @click="onAdd(row.id)"> {{ $t('addNew') }} </el-button>
|
||||||
<el-popconfirm :title="`${$t('delete')} ${row.deptName}?`" @confirm="onDelete(row)">
|
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')} ${row.deptName}?`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
{{ $t('delete') }}
|
{{ $t('delete') }}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const auth = {
|
||||||
|
// 分页查询
|
||||||
|
search: ['dept::getDeptList'],
|
||||||
|
// 添加操作
|
||||||
|
add: ['dept::addDept'],
|
||||||
|
// 更新操作
|
||||||
|
update: ['dept::updateDept'],
|
||||||
|
// 删除操作
|
||||||
|
deleted: ['dept::deleteDept'],
|
||||||
|
};
|
|
@ -4,7 +4,7 @@ import { $t } from '@/plugins/i18n';
|
||||||
// 表格列
|
// 表格列
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ type: 'selection', align: 'left' },
|
{ type: 'selection', align: 'left' },
|
||||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
{ type: 'index', index: (index: number) => index + 1, label: $t('index'), width: 60 },
|
||||||
// 部门名称
|
// 部门名称
|
||||||
{ label: $t('dept_deptName'), prop: 'deptName', width: 160 },
|
{ label: $t('dept_deptName'), prop: 'deptName', width: 160 },
|
||||||
// 管理者
|
// 管理者
|
||||||
|
|
|
@ -14,6 +14,8 @@ import { $t } from '@/plugins/i18n';
|
||||||
import { useFilesStore } from '@/store/monitor/files';
|
import { useFilesStore } from '@/store/monitor/files';
|
||||||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
|
import { auth } from '@/views/system/files/utils/auth';
|
||||||
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
@ -50,6 +52,7 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
<Auth :value="auth.search">
|
||||||
<el-form ref="formRef" :inline="true" :model="filesStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="formRef" :inline="true" :model="filesStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<el-form-item :label="$t('files_filename')" prop="filename">
|
<el-form-item :label="$t('files_filename')" prop="filename">
|
||||||
<el-input v-model="filesStore.form.filename" :placeholder="`${$t('input')}${$t('files_filename')}`" class="!w-[180px]" clearable />
|
<el-input v-model="filesStore.form.filename" :placeholder="`${$t('input')}${$t('files_filename')}`" class="!w-[180px]" clearable />
|
||||||
|
@ -68,18 +71,21 @@ onMounted(() => {
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<PureTableBar :columns="columns" :title="$t('system_file')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
<PureTableBar :columns="columns" :title="$t('system_file')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd"> {{ $t('addNew') }}</el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd">
|
||||||
|
{{ $t('addNew') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量下载 -->
|
<!-- 批量下载 -->
|
||||||
<el-button :disabled="!(selectRows.length > 0)" :icon="useRenderIcon(Download)" type="success" @click="onDownloadBatch">
|
<el-button v-if="hasAuth(auth.downloadFilesByFileId)" :disabled="!(selectRows.length > 0)" :icon="useRenderIcon(Download)" type="success" @click="onDownloadBatch">
|
||||||
{{ $t('download_batch') }}
|
{{ $t('download_batch') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量删除按钮 -->
|
<!-- 批量删除按钮 -->
|
||||||
<el-button :disabled="!(selectRows.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
<el-button v-if="hasAuth(auth.deleted)" :disabled="!(selectRows.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
||||||
{{ $t('deleteBatches') }}
|
{{ $t('deleteBatches') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -118,9 +124,11 @@ onMounted(() => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
<el-button v-if="hasAuth(auth.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onDownload(row)"> {{ $t('download') }} </el-button>
|
<el-button v-if="hasAuth(auth.downloadFilesByFileId)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onDownload(row)">
|
||||||
<el-popconfirm :title="`${$t('delete')} ${row.filename}?`" @confirm="onDelete(row)">
|
{{ $t('download') }}
|
||||||
|
</el-button>
|
||||||
|
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')} ${row.filename}?`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
{{ $t('delete') }}
|
{{ $t('delete') }}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
export const auth = {
|
||||||
|
// 更新操作
|
||||||
|
update: ['files::updateFiles'],
|
||||||
|
// 添加操作
|
||||||
|
add: ['files::addFiles'],
|
||||||
|
// 分页查询
|
||||||
|
search: ['files::getFilesList'],
|
||||||
|
// 删除操作
|
||||||
|
deleted: ['files::deleteFiles'],
|
||||||
|
// 上传
|
||||||
|
upload: ['files::upload'],
|
||||||
|
// 下载文件
|
||||||
|
downloadFilesByFileId: ['files::downloadFilesByFileId'],
|
||||||
|
};
|
|
@ -4,7 +4,7 @@ import { $t } from '@/plugins/i18n';
|
||||||
// 表格列
|
// 表格列
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ type: 'selection', align: 'left' },
|
{ type: 'selection', align: 'left' },
|
||||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
{ type: 'index', index: (index: number) => index + 1, label: $t('index'), width: 60 },
|
||||||
// 文件的名称
|
// 文件的名称
|
||||||
{ label: $t('files_filename'), prop: 'filename', width: 400 },
|
{ label: $t('files_filename'), prop: 'filename', width: 400 },
|
||||||
// 文件在服务器上的存储路径
|
// 文件在服务器上的存储路径
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { h, ref } from 'vue';
|
||||||
import { message, messageBox } from '@/utils/message';
|
import { message, messageBox } from '@/utils/message';
|
||||||
import type { FormItemProps } from '@/views/system/files/utils/types';
|
import type { FormItemProps } from '@/views/system/files/utils/types';
|
||||||
import { $t } from '@/plugins/i18n';
|
import { $t } from '@/plugins/i18n';
|
||||||
import { downloadFilesByFileId, downloadFilesByFilepath } from '@/api/v1/files';
|
import { downloadFilesByFileId } from '@/api/v1/files';
|
||||||
import { download } from '@/utils/sso';
|
import { download } from '@/utils/sso';
|
||||||
import type { UploadFiles } from 'element-plus';
|
import type { UploadFiles } from 'element-plus';
|
||||||
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
||||||
|
@ -154,7 +154,7 @@ export const onDeleteBatch = async () => {
|
||||||
* @param row
|
* @param row
|
||||||
*/
|
*/
|
||||||
export const onDownload = async (row: any) => {
|
export const onDownload = async (row: any) => {
|
||||||
const blob = await downloadFilesByFilepath({ filepath: row.filepath });
|
const blob = await downloadFilesByFileId({ id: row.id });
|
||||||
|
|
||||||
download(blob, row.filename);
|
download(blob, row.filename);
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,8 @@ import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
||||||
import Upload from '@iconify-icons/ri/upload-line';
|
import Upload from '@iconify-icons/ri/upload-line';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
import { usePublicHooks } from '@/views/hooks';
|
import { usePublicHooks } from '@/views/hooks';
|
||||||
|
import { auth } from '@/views/system/menu/utils/auth';
|
||||||
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const routerStore = userMenuStore();
|
const routerStore = userMenuStore();
|
||||||
|
@ -59,25 +61,34 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
<Auth :value="auth.search">
|
||||||
<el-form ref="formRef" :inline="true" :model="routerStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="formRef" :inline="true" :model="routerStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<el-form-item label="菜单名称" prop="title">
|
<el-form-item label="菜单名称" prop="title">
|
||||||
<el-input v-model="routerStore.form.title" class="!w-[180px]" clearable placeholder="输入菜单名称" />
|
<el-input v-model="routerStore.form.title" :placeholder="$t('input')" class="!w-[180px]" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="routerStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
<el-button :icon="useRenderIcon('ri:search-line')" :loading="routerStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<PureTableBar :columns="columns" :isExpandAll="false" :tableRef="tableRef?.getTableRef()" title="菜单管理" @fullscreen="tableRef?.setAdaptive()" @refresh="onSearch">
|
<PureTableBar :columns="columns" :isExpandAll="false" :tableRef="tableRef?.getTableRef()" title="菜单管理" @fullscreen="tableRef?.setAdaptive()" @refresh="onSearch">
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<!-- 添加菜单 -->
|
<!-- 添加菜单 -->
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd()"> {{ $t('addNew') }}</el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd()">
|
||||||
|
{{ $t('addNew') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量分配角色 -->
|
<!-- 批量为菜单添加角色 -->
|
||||||
<el-button :disabled="!(selectIds.length > 0)" :icon="useRenderIcon('iwwa:assign')" type="warning" @click="assignBatchRolesToRouter()"> {{ $t('assignBatchRolesToRouter') }} </el-button>
|
<el-button v-if="hasAuth(auth.assignAddBatchRolesToRouter)" :disabled="!(selectIds.length > 0)" :icon="useRenderIcon('iwwa:assign')" type="warning" @click="assignBatchRolesToRouter()">
|
||||||
|
{{ $t('assignBatchRolesToRouter') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 清除选中所以角色 -->
|
<!-- 清除选中所以角色 -->
|
||||||
<el-button :disabled="!(selectIds.length > 0)" :icon="useRenderIcon('ic:baseline-clear')" type="danger" @click="clearAllRolesSelect()"> {{ $t('clearAllRolesSelect') }} </el-button>
|
<el-button v-if="hasAuth(auth.clearAllRolesSelect)" :disabled="!(selectIds.length > 0)" :icon="useRenderIcon('ic:baseline-clear')" type="danger" @click="clearAllRolesSelect()">
|
||||||
|
{{ $t('clearAllRolesSelect') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot="{ size, dynamicColumns }">
|
<template v-slot="{ size, dynamicColumns }">
|
||||||
|
@ -130,13 +141,15 @@ onMounted(() => {
|
||||||
|
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<!-- 修改 -->
|
<!-- 修改 -->
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
<el-button v-if="hasAuth(auth.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
|
|
||||||
<!-- 新增 -->
|
<!-- 新增 -->
|
||||||
|
<Auth :value="auth.add">
|
||||||
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary" @click="onAdd(row.id)"> {{ $t('addNew') }} </el-button>
|
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary" @click="onAdd(row.id)"> {{ $t('addNew') }} </el-button>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<!-- 删除操作 -->
|
<!-- 删除操作 -->
|
||||||
<el-popconfirm :title="`${$t('delete')} ${$t(row.title)}?`" @confirm="onDelete(row)">
|
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')} ${$t(row.title)}?`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
{{ $t('delete') }}
|
{{ $t('delete') }}
|
||||||
|
@ -145,9 +158,11 @@ onMounted(() => {
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
|
|
||||||
<!-- 分配角色 -->
|
<!-- 分配角色 -->
|
||||||
|
<Auth :value="auth.assignRolesToRouter">
|
||||||
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(Upload)" :size="size" class="reset-margin" link type="primary" @click="assignRolesToRouter(row)">
|
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(Upload)" :size="size" class="reset-margin" link type="primary" @click="assignRolesToRouter(row)">
|
||||||
{{ $t('assign_roles') }}
|
{{ $t('assign_roles') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
</Auth>
|
||||||
</template>
|
</template>
|
||||||
</pure-table>
|
</pure-table>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import IconSelect from '@/components/SelectIcon/Select.vue';
|
||||||
import Segmented from '@/components/Segmented';
|
import Segmented from '@/components/Segmented';
|
||||||
import { menuTypeOptions } from '@/enums';
|
import { menuTypeOptions } from '@/enums';
|
||||||
import { FormProps } from '@/views/system/menu/utils/types';
|
import { FormProps } from '@/views/system/menu/utils/types';
|
||||||
|
import { $t } from '@/plugins/i18n';
|
||||||
|
|
||||||
const props = withDefaults(defineProps<FormProps>(), {
|
const props = withDefaults(defineProps<FormProps>(), {
|
||||||
formInline: () => ({}),
|
formInline: () => ({}),
|
||||||
|
@ -20,13 +21,13 @@ defineExpose({ menuFormRef: ruleFormRef });
|
||||||
<el-form ref="ruleFormRef" :model="newFormInline" :rules="formRules" label-width="82px">
|
<el-form ref="ruleFormRef" :model="newFormInline" :rules="formRules" label-width="82px">
|
||||||
<el-row :gutter="30">
|
<el-row :gutter="30">
|
||||||
<re-col>
|
<re-col>
|
||||||
<el-form-item label="菜单类型">
|
<el-form-item :label="$t('menuType')">
|
||||||
<Segmented v-model="newFormInline.menuType" :options="menuTypeOptions" />
|
<Segmented v-model="newFormInline.menuType" :options="menuTypeOptions" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
|
|
||||||
<re-col>
|
<re-col>
|
||||||
<el-form-item label="上级菜单">
|
<el-form-item :label="$t('previousMenu')">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
v-model="newFormInline.parentId"
|
v-model="newFormInline.parentId"
|
||||||
:options="newFormInline.higherMenuOptions"
|
:options="newFormInline.higherMenuOptions"
|
||||||
|
@ -45,29 +46,29 @@ defineExpose({ menuFormRef: ruleFormRef });
|
||||||
</re-col>
|
</re-col>
|
||||||
|
|
||||||
<re-col :sm="24" :value="12" :xs="24">
|
<re-col :sm="24" :value="12" :xs="24">
|
||||||
<el-form-item label="菜单名称" prop="title">
|
<el-form-item :label="$t('menuName')" prop="title">
|
||||||
<el-input v-model="newFormInline.title" clearable placeholder="请输入菜单名称" />
|
<el-input v-model="newFormInline.title" clearable placeholder="请输入菜单名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
<re-col :sm="24" :value="12" :xs="24">
|
<re-col :sm="24" :value="12" :xs="24">
|
||||||
<el-form-item label="路由名称" prop="name">
|
<el-form-item :label="$t('routerName')" prop="name">
|
||||||
<el-input v-model="newFormInline.name" clearable placeholder="请输入路由名称" />
|
<el-input v-model="newFormInline.name" clearable placeholder="请输入路由名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
|
|
||||||
<re-col :sm="24" :value="12" :xs="24">
|
<re-col :sm="24" :value="12" :xs="24">
|
||||||
<el-form-item label="路由路径" prop="path">
|
<el-form-item :label="$t('routerPath')" prop="path">
|
||||||
<el-input v-model="newFormInline.path" clearable placeholder="请输入路由路径" />
|
<el-input v-model="newFormInline.path" clearable placeholder="请输入路由路径" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
<re-col v-show="newFormInline.menuType === 0" :sm="24" :value="12" :xs="24">
|
<re-col v-show="newFormInline.menuType === 0" :sm="24" :value="12" :xs="24">
|
||||||
<el-form-item label="组件路径">
|
<el-form-item :label="$t('componentPath')">
|
||||||
<el-input v-model="newFormInline.component" clearable placeholder="请输入组件路径" />
|
<el-input v-model="newFormInline.component" clearable placeholder="请输入组件路径" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
|
|
||||||
<re-col :sm="24" :value="12" :xs="24">
|
<re-col :sm="24" :value="12" :xs="24">
|
||||||
<el-form-item v-model="newFormInline.rank" label="菜单排序" prop="rank">
|
<el-form-item v-model="newFormInline.rank" :label="$t('sort')" prop="rank">
|
||||||
<el-input-number v-model="newFormInline.rank" :max="9999" :min="1" class="!w-full" controls-position="right" />
|
<el-input-number v-model="newFormInline.rank" :max="9999" :min="1" class="!w-full" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
|
@ -86,7 +87,9 @@ defineExpose({ menuFormRef: ruleFormRef });
|
||||||
|
|
||||||
<re-col :sm="24" :value="12" :xs="24">
|
<re-col :sm="24" :value="12" :xs="24">
|
||||||
<el-form-item label="是否显示">
|
<el-form-item label="是否显示">
|
||||||
<el-switch v-model="newFormInline.visible" active-text="开启" inactive-text="隐藏" inline-prompt style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" />
|
<el-switch v-model="newFormInline.visible" :inactive-text="$t('visible')" active-text="开启" inline-prompt style="
|
||||||
|
|
||||||
|
--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</re-col>
|
</re-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
export const auth = {
|
||||||
|
// 更新操作
|
||||||
|
update: ['router::updateMenu'],
|
||||||
|
// 修改菜单排序
|
||||||
|
updateMenuByIdWithRank: ['router::updateMenuByIdWithRank'],
|
||||||
|
// 添加操作
|
||||||
|
add: ['router::addMenu'],
|
||||||
|
// 分页查询
|
||||||
|
search: ['router::getMenusList'],
|
||||||
|
// 删除操作
|
||||||
|
deleted: ['router::deletedMenuByIds'],
|
||||||
|
// 为菜单分配角色
|
||||||
|
assignRolesToRouter: ['routerRole::assignRolesToRouter'],
|
||||||
|
// 批量为菜单添加角色
|
||||||
|
assignAddBatchRolesToRouter: ['routerRole::assignAddBatchRolesToRouter'],
|
||||||
|
// 根据菜单id获取所有角色
|
||||||
|
getRoleListByRouterId: ['routerRole::getRoleListByRouterId'],
|
||||||
|
// 清除选中菜单所有角色
|
||||||
|
clearAllRolesSelect: ['routerRole::clearAllRolesSelect'],
|
||||||
|
};
|
|
@ -13,11 +13,11 @@ import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
const getMenuType = (type: number, text: boolean = false): any => {
|
const getMenuType = (type: number, text: boolean = false): any => {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case 0:
|
||||||
return text ? '菜单' : 'primary';
|
return text ? $t('menu') : 'primary';
|
||||||
case 1:
|
case 1:
|
||||||
return text ? 'iframe' : 'warning';
|
return text ? 'iframe' : 'warning';
|
||||||
case 2:
|
case 2:
|
||||||
return text ? '外链' : 'danger';
|
return text ? $t('externalLink') : 'danger';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ export const formatHigherMenuOptions = (treeList: any) => {
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ type: 'selection', align: 'left' },
|
{ type: 'selection', align: 'left' },
|
||||||
{
|
{
|
||||||
label: '菜单名称',
|
label: $t('menuName'),
|
||||||
prop: 'title',
|
prop: 'title',
|
||||||
align: 'left',
|
align: 'left',
|
||||||
cellRenderer: ({ row }) => (
|
cellRenderer: ({ row }) => (
|
||||||
|
@ -51,7 +51,7 @@ export const columns: TableColumnList = [
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '菜单类型',
|
label: $t('menuType'),
|
||||||
prop: 'menuType',
|
prop: 'menuType',
|
||||||
width: 100,
|
width: 100,
|
||||||
cellRenderer: ({ row, props }) => (
|
cellRenderer: ({ row, props }) => (
|
||||||
|
@ -60,14 +60,14 @@ export const columns: TableColumnList = [
|
||||||
</ElTag>
|
</ElTag>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{ label: '路由路径', prop: 'path' },
|
{ label: $t('routerPath'), prop: 'path' },
|
||||||
{
|
{
|
||||||
label: '组件路径',
|
label: $t('componentPath'),
|
||||||
prop: 'component',
|
prop: 'component',
|
||||||
formatter: ({ path, component }) => (isAllEmpty(component) ? path : component),
|
formatter: ({ path, component }) => (isAllEmpty(component) ? path : component),
|
||||||
},
|
},
|
||||||
{ label: '排序', prop: 'rank', width: 80, slot: 'rank' },
|
{ label: $t('sort'), prop: 'rank', width: 80, slot: 'rank' },
|
||||||
{ label: '隐藏', prop: 'visible', slot: 'visible', width: 100 },
|
{ label: $t('visible'), prop: 'visible', slot: 'visible', width: 100 },
|
||||||
{ label: $t('table.updateTime'), prop: 'updateTime', sortable: true },
|
{ label: $t('table.updateTime'), prop: 'updateTime', sortable: true },
|
||||||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true },
|
{ label: $t('table.createTime'), prop: 'createTime', sortable: true },
|
||||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||||
|
@ -77,8 +77,7 @@ export const columns: TableColumnList = [
|
||||||
|
|
||||||
/** 自定义表单规则校验 */
|
/** 自定义表单规则校验 */
|
||||||
export const formRules = reactive<FormRules>({
|
export const formRules = reactive<FormRules>({
|
||||||
title: [{ required: true, message: '菜单名称为必填项', trigger: 'blur' }],
|
title: [{ required: true, message: $t('menuNameTip'), trigger: 'blur' }],
|
||||||
name: [{ required: true, message: '路由名称为必填项', trigger: 'blur' }],
|
name: [{ required: true, message: $t('routerNameTip'), trigger: 'blur' }],
|
||||||
path: [{ required: true, message: '路由路径为必填项且为"/"开头', trigger: ['blur', 'change'], pattern: /^\/.*/ }],
|
path: [{ required: true, message: $t('routerPathTip'), trigger: ['blur', 'change'], pattern: /^\/.*/ }],
|
||||||
auths: [{ required: true, message: '权限标识为必填项', trigger: 'blur' }],
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const onSearch = async () => {
|
||||||
/** 添加菜单 */
|
/** 添加菜单 */
|
||||||
export function onAdd(parentId: any = 0) {
|
export function onAdd(parentId: any = 0) {
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `新增菜单`,
|
title: $t('addNew') + $t('menu'),
|
||||||
props: {
|
props: {
|
||||||
formInline: {
|
formInline: {
|
||||||
menuType: 0,
|
menuType: 0,
|
||||||
|
@ -75,7 +75,7 @@ export function onAdd(parentId: any = 0) {
|
||||||
*/
|
*/
|
||||||
export const onUpdate = (row?: FormItemProps) => {
|
export const onUpdate = (row?: FormItemProps) => {
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `更新菜单`,
|
title: $t('update') + $t('menu'),
|
||||||
props: {
|
props: {
|
||||||
formInline: {
|
formInline: {
|
||||||
menuType: row?.menuType,
|
menuType: row?.menuType,
|
||||||
|
@ -209,7 +209,7 @@ export const onChangeMenuRank = async (row: any) => {
|
||||||
*/
|
*/
|
||||||
export const assignRolesToRouter = (row: any) => {
|
export const assignRolesToRouter = (row: any) => {
|
||||||
addDialog({
|
addDialog({
|
||||||
title: `为 【${$t(row.title)}】 分配角色`,
|
title: `${$t('for')} 【${$t(row.title)}】 ${$t('assign_roles')}`,
|
||||||
width: '45%',
|
width: '45%',
|
||||||
draggable: true,
|
draggable: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
|
|
|
@ -14,6 +14,8 @@ import { usePowerStore } from '@/store/system/power';
|
||||||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
import { handleTree } from '@pureadmin/utils';
|
import { handleTree } from '@pureadmin/utils';
|
||||||
import { FormInstance } from 'element-plus';
|
import { FormInstance } from 'element-plus';
|
||||||
|
import { auth } from '@/views/system/power/utils/auth';
|
||||||
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
|
@ -62,6 +64,7 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
<Auth :value="auth.search">
|
||||||
<el-form ref="formRef" :inline="true" :model="powerStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="formRef" :inline="true" :model="powerStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<el-form-item :label="$t('power_powerCode')" prop="powerCode">
|
<el-form-item :label="$t('power_powerCode')" prop="powerCode">
|
||||||
<el-input v-model="powerStore.form.powerCode" :placeholder="`${$t('input')}${$t('power_powerCode')}`" class="!w-[180px]" clearable />
|
<el-input v-model="powerStore.form.powerCode" :placeholder="`${$t('input')}${$t('power_powerCode')}`" class="!w-[180px]" clearable />
|
||||||
|
@ -77,19 +80,22 @@ onMounted(() => {
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<PureTableBar :columns="columns" :isExpandAll="true" :tableRef="tableRef?.getTableRef()" :title="$t('power')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
<PureTableBar :columns="columns" :isExpandAll="true" :tableRef="tableRef?.getTableRef()" :title="$t('power')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<!-- 添加权限按钮 -->
|
<!-- 添加权限按钮 -->
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd()"> {{ $t('addNew') }}</el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd()">
|
||||||
|
{{ $t('addNew') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量更新父级id -->
|
<!-- 批量更新父级id -->
|
||||||
<el-button :disabled="!(powerIds.length > 0)" :icon="useRenderIcon(EditPen)" type="primary" @click="onUpdateBatchParent">
|
<el-button v-if="hasAuth(auth.updateBatchByPowerWithParentId)" :disabled="!(powerIds.length > 0)" :icon="useRenderIcon(EditPen)" type="primary" @click="onUpdateBatchParent">
|
||||||
{{ $t('update_batches_parent') }}
|
{{ $t('update_batches_parent') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量删除按钮 -->
|
<!-- 批量删除按钮 -->
|
||||||
<el-button :disabled="!(powerIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
<el-button v-if="hasAuth(auth.deleted)" :disabled="!(powerIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
||||||
{{ $t('deleteBatches') }}
|
{{ $t('deleteBatches') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -127,12 +133,14 @@ onMounted(() => {
|
||||||
{{ row.updateUsername }}
|
{{ row.updateUsername }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<!-- 修改 -->
|
<!-- 修改 -->
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
<el-button v-if="hasAuth(auth.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary" @click="onAdd(row.id)"> {{ $t('addNew') }} </el-button>
|
<!-- 添加 -->
|
||||||
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" :size="size" class="reset-margin" link type="primary" @click="onAdd(row.id)"> {{ $t('addNew') }} </el-button>
|
||||||
<!-- 删除 -->
|
<!-- 删除 -->
|
||||||
<el-popconfirm :title="`${$t('delete')}${row.powerName}?`" @confirm="onDelete(row)">
|
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')}${row.powerName}?`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
{{ $t('delete') }}
|
{{ $t('delete') }}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
export const auth = {
|
||||||
|
// 分页查询
|
||||||
|
search: ['power::getPowerList'],
|
||||||
|
// 获取所有权限
|
||||||
|
getAllPowers: ['power::getAllPowers'],
|
||||||
|
// 添加操作
|
||||||
|
add: ['power::addPower'],
|
||||||
|
// 更新操作
|
||||||
|
update: ['power::updatePower'],
|
||||||
|
// 批量修改权限父级
|
||||||
|
updateBatchByPowerWithParentId: ['power::updateBatchByPowerWithParentId'],
|
||||||
|
// 删除操作
|
||||||
|
deleted: ['power::deletePower'],
|
||||||
|
};
|
|
@ -5,7 +5,7 @@ import type { FormRules } from 'element-plus';
|
||||||
// 表格列
|
// 表格列
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ type: 'selection', align: 'left' },
|
{ type: 'selection', align: 'left' },
|
||||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
{ type: 'index', index: (index: number) => index + 1, label: $t('index'), width: 60 },
|
||||||
// 权限编码
|
// 权限编码
|
||||||
{ label: $t('power_powerCode'), prop: 'powerCode' },
|
{ label: $t('power_powerCode'), prop: 'powerCode' },
|
||||||
// 权限名称
|
// 权限名称
|
||||||
|
|
|
@ -15,6 +15,8 @@ import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||||
import { deviceDetection } from '@pureadmin/utils';
|
import { deviceDetection } from '@pureadmin/utils';
|
||||||
import Menu from '@iconify-icons/ep/menu';
|
import Menu from '@iconify-icons/ep/menu';
|
||||||
import AssignPowersToRole from '@/views/system/role/assign-powers-to-role.vue';
|
import AssignPowersToRole from '@/views/system/role/assign-powers-to-role.vue';
|
||||||
|
import { auth } from '@/views/system/role/utils/auth';
|
||||||
|
import { hasAuth } from '@/router/utils';
|
||||||
|
|
||||||
const roleStore = useRoleStore();
|
const roleStore = useRoleStore();
|
||||||
|
|
||||||
|
@ -60,6 +62,7 @@ onMounted(() => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
|
<Auth :value="auth.search">
|
||||||
<el-form ref="formRef" :inline="true" :model="roleStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
<el-form ref="formRef" :inline="true" :model="roleStore.form" class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto">
|
||||||
<el-form-item :label="$t('role_roleCode')" prop="roleCode">
|
<el-form-item :label="$t('role_roleCode')" prop="roleCode">
|
||||||
<el-input v-model="roleStore.form.roleCode" :placeholder="`${$t('input')}${$t('role_roleCode')}`" class="!w-[180px]" clearable />
|
<el-input v-model="roleStore.form.roleCode" :placeholder="`${$t('input')}${$t('role_roleCode')}`" class="!w-[180px]" clearable />
|
||||||
|
@ -72,6 +75,7 @@ onMounted(() => {
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
</Auth>
|
||||||
|
|
||||||
<div ref="contentRef" :class="['flex', deviceDetection() ? 'flex-wrap' : '']">
|
<div ref="contentRef" :class="['flex', deviceDetection() ? 'flex-wrap' : '']">
|
||||||
<PureTableBar
|
<PureTableBar
|
||||||
|
@ -83,10 +87,12 @@ onMounted(() => {
|
||||||
@refresh="onSearch"
|
@refresh="onSearch"
|
||||||
>
|
>
|
||||||
<template #buttons>
|
<template #buttons>
|
||||||
<el-button :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd"> {{ $t('addNew') }}</el-button>
|
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" type="primary" @click="onAdd">
|
||||||
|
{{ $t('addNew') }}
|
||||||
|
</el-button>
|
||||||
|
|
||||||
<!-- 批量删除按钮 -->
|
<!-- 批量删除按钮 -->
|
||||||
<el-button v-show="deleteIds.length > 0" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
<el-button v-if="hasAuth(auth.deleted)" :disabled="!(deleteIds.length > 0)" :icon="useRenderIcon(Delete)" type="danger" @click="onDeleteBatch">
|
||||||
{{ $t('delete_batches') }}
|
{{ $t('delete_batches') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -125,10 +131,10 @@ onMounted(() => {
|
||||||
</template>
|
</template>
|
||||||
<template #operation="{ row }">
|
<template #operation="{ row }">
|
||||||
<!-- 修改 -->
|
<!-- 修改 -->
|
||||||
<el-button :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
<el-button v-if="hasAuth(auth.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </el-button>
|
||||||
|
|
||||||
<!-- 删除 -->
|
<!-- 删除 -->
|
||||||
<el-popconfirm :title="`${$t('delete')}${row.roleCode}?`" @confirm="onDelete(row)">
|
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')}${row.roleCode}?`" @confirm="onDelete(row)">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||||
{{ $t('delete') }}
|
{{ $t('delete') }}
|
||||||
|
@ -136,7 +142,9 @@ onMounted(() => {
|
||||||
</template>
|
</template>
|
||||||
</el-popconfirm>
|
</el-popconfirm>
|
||||||
|
|
||||||
<el-button :icon="useRenderIcon(Menu)" :size="size" class="reset-margin" link type="primary" @click="onMenuPowerClick(row)"> {{ $t('power_setting') }} </el-button>
|
<el-button v-if="hasAuth(auth.assignPowersToRole)" :icon="useRenderIcon(Menu)" :size="size" class="reset-margin" link type="primary" @click="onMenuPowerClick(row)">
|
||||||
|
{{ $t('power_setting') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</pure-table>
|
</pure-table>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
export const auth = {
|
||||||
|
// 分页查询
|
||||||
|
search: ['role::getRoleList'],
|
||||||
|
// 添加操作
|
||||||
|
add: ['role::addRole'],
|
||||||
|
// 更新操作
|
||||||
|
update: ['role::updateRole'],
|
||||||
|
// 删除操作
|
||||||
|
deleted: ['role::deleteRole'],
|
||||||
|
// 为角色分配权限
|
||||||
|
assignPowersToRole: ['rolePower::assignPowersToRole'],
|
||||||
|
};
|
|
@ -4,7 +4,7 @@ import { $t } from '@/plugins/i18n';
|
||||||
// 表格列
|
// 表格列
|
||||||
export const columns: TableColumnList = [
|
export const columns: TableColumnList = [
|
||||||
{ type: 'selection', align: 'left' },
|
{ type: 'selection', align: 'left' },
|
||||||
{ type: 'index', index: (index: number) => index + 1, label: '序号', width: 60 },
|
{ type: 'index', index: (index: number) => index + 1, label: $t('index'), width: 60 },
|
||||||
// 角色代码
|
// 角色代码
|
||||||
{ label: $t('role_roleCode'), prop: 'roleCode' },
|
{ label: $t('role_roleCode'), prop: 'roleCode' },
|
||||||
// 描述
|
// 描述
|
||||||
|
|
Loading…
Reference in New Issue