optimize: ♻️ 添加权限验证以及修改表格bug
This commit is contained in:
parent
3d5c2eaa12
commit
397dbcfdff
|
@ -8,7 +8,7 @@ export const fetchGetDeptList = (data: any) => {
|
|||
|
||||
/** 部门管理---获取所有部门管理列表 */
|
||||
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) {
|
||||
dynamicColumns.value.filter(item => $t(item.label) === $t(label))[0].hide = !val;
|
||||
dynamicColumns.value.filter(item => item.label === label)[0].hide = !val;
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
|
@ -169,7 +169,7 @@ export default defineComponent({
|
|||
};
|
||||
|
||||
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) => ({
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// 多组件库的国际化和本地项目国际化兼容
|
||||
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');
|
||||
|
@ -17,7 +18,7 @@ export const i18n = createI18n({
|
|||
messages: languageData ? JSON.parse(languageData).i18n : {},
|
||||
});
|
||||
|
||||
/*const siphonI18n = (function () {
|
||||
const siphonI18n = (function () {
|
||||
// 仅初始化一次国际化配置
|
||||
let cache = Object.fromEntries(
|
||||
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) {
|
||||
const stack = [];
|
||||
const keys: Set<string> = new Set();
|
||||
|
@ -54,7 +55,7 @@ function getObjectKeys(obj) {
|
|||
return keys;
|
||||
}
|
||||
|
||||
/!** 将展开的key缓存 *!/
|
||||
/** 将展开的key缓存 */
|
||||
const keysCache: Map<string, Set<string>> = new Map();
|
||||
const flatI18n = (prefix = 'zh') => {
|
||||
let cache = keysCache.get(prefix);
|
||||
|
@ -65,11 +66,11 @@ const flatI18n = (prefix = 'zh') => {
|
|||
return cache;
|
||||
};
|
||||
|
||||
/!**
|
||||
/**
|
||||
* 国际化转换工具函数(自动读取根目录locales文件夹下文件进行国际化匹配)
|
||||
* @param message message
|
||||
* @returns 转化后的message
|
||||
*!/
|
||||
*/
|
||||
export function transformI18n(message: any = '') {
|
||||
if (!message) {
|
||||
return '';
|
||||
|
@ -91,7 +92,7 @@ export function transformI18n(message: any = '') {
|
|||
} else {
|
||||
return message;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
export const $t: any = (i18n.global as any).t as any;
|
||||
|
||||
|
|
|
@ -312,6 +312,10 @@ function hasAuth(value: string | Array<string>): boolean {
|
|||
/** 从当前路由的`meta`字段里获取按钮级别的所有自定义`code`值 */
|
||||
const metaAuths = getAuths();
|
||||
if (!metaAuths) return false;
|
||||
// 管理员权限
|
||||
if (metaAuths.includes('*::*::*') || metaAuths.includes('*::*') || metaAuths.includes('*')) {
|
||||
return true;
|
||||
}
|
||||
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 { FormInstance } from 'element-plus';
|
||||
import { usePublicHooks } from '@/views/hooks';
|
||||
import { auth } from '@/views/system/adminUser/utils/auth';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
const adminUserStore = useAdminUserStore();
|
||||
const deptStore = useDeptStore();
|
||||
|
@ -88,58 +90,62 @@ onMounted(() => {
|
|||
<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" />
|
||||
<div :class="[deviceDetection() ? ['w-full', 'mt-2'] : 'w-[calc(100%-200px)]']">
|
||||
<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-input v-model="adminUserStore.form.username" :placeholder="`${$t('input')}${$t('adminUser_username')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<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-item :label="$t('adminUser_username')" prop="username">
|
||||
<el-input v-model="adminUserStore.form.username" :placeholder="`${$t('input')}${$t('adminUser_username')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 查询昵称 -->
|
||||
<el-form-item :label="$t('adminUser_nickname')" prop="nickname">
|
||||
<el-input v-model="adminUserStore.form.nickname" :placeholder="`${$t('input')}${$t('adminUser_nickname')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<!-- 查询昵称 -->
|
||||
<el-form-item :label="$t('adminUser_nickname')" prop="nickname">
|
||||
<el-input v-model="adminUserStore.form.nickname" :placeholder="`${$t('input')}${$t('adminUser_nickname')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 查询邮箱 -->
|
||||
<el-form-item :label="$t('adminUser_email')" prop="email">
|
||||
<el-input v-model="adminUserStore.form.email" :placeholder="`${$t('input')}${$t('adminUser_email')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<!-- 查询邮箱 -->
|
||||
<el-form-item :label="$t('adminUser_email')" prop="email">
|
||||
<el-input v-model="adminUserStore.form.email" :placeholder="`${$t('input')}${$t('adminUser_email')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 查询手机号 -->
|
||||
<el-form-item :label="$t('adminUser_phone')" prop="phone">
|
||||
<el-input v-model="adminUserStore.form.phone" :placeholder="`${$t('input')}${$t('adminUser_phone')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<!-- 查询手机号 -->
|
||||
<el-form-item :label="$t('adminUser_phone')" prop="phone">
|
||||
<el-input v-model="adminUserStore.form.phone" :placeholder="`${$t('input')}${$t('adminUser_phone')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 查询性别 -->
|
||||
<el-form-item :label="$t('adminUser_sex')" prop="sex">
|
||||
<el-select v-model="adminUserStore.form.sex" :placeholder="`${$t('input')}${$t('adminUser_sex')}`" class="!w-[180px]" clearable filterable>
|
||||
<el-option v-for="(item, index) in sexConstant" :key="index" :label="item.label" :navigationBar="false" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 查询性别 -->
|
||||
<el-form-item :label="$t('adminUser_sex')" prop="sex">
|
||||
<el-select v-model="adminUserStore.form.sex" :placeholder="`${$t('input')}${$t('adminUser_sex')}`" class="!w-[180px]" clearable filterable>
|
||||
<el-option v-for="(item, index) in sexConstant" :key="index" :label="item.label" :navigationBar="false" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 查询简介 -->
|
||||
<el-form-item :label="$t('adminUser_summary')" prop="summary">
|
||||
<el-input v-model="adminUserStore.form.summary" :placeholder="`${$t('input')}${$t('adminUser_summary')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<!-- 查询简介 -->
|
||||
<el-form-item :label="$t('adminUser_summary')" prop="summary">
|
||||
<el-input v-model="adminUserStore.form.summary" :placeholder="`${$t('input')}${$t('adminUser_summary')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 查询状态 -->
|
||||
<el-form-item :label="$t('adminUser_status')" prop="status">
|
||||
<el-select v-model="adminUserStore.form.status" :placeholder="`${$t('input')}${$t('adminUser_status')}`" class="!w-[180px]" clearable filterable>
|
||||
<el-option v-for="(item, index) in userStatus" :key="index" :label="item.label" :navigationBar="false" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 查询状态 -->
|
||||
<el-form-item :label="$t('adminUser_status')" prop="status">
|
||||
<el-select v-model="adminUserStore.form.status" :placeholder="`${$t('input')}${$t('adminUser_status')}`" class="!w-[180px]" clearable filterable>
|
||||
<el-option v-for="(item, index) in userStatus" :key="index" :label="item.label" :navigationBar="false" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="adminUserStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="adminUserStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Auth>
|
||||
|
||||
<PureTableBar :columns="columns" :title="$t('userinfo')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||
<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') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -212,10 +218,10 @@ onMounted(() => {
|
|||
|
||||
<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>
|
||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||
{{ $t('delete') }}
|
||||
|
@ -228,16 +234,20 @@ onMounted(() => {
|
|||
<el-button :icon="useRenderIcon(More)" :size="size" class="ml-3 mt-[2px]" link type="primary" />
|
||||
<template #dropdown>
|
||||
<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-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-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-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-dropdown-item>
|
||||
</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 = [
|
||||
{ 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 },
|
||||
// 状态
|
||||
|
|
|
@ -256,7 +256,7 @@ export const onUploadAvatar = (row: any) => {
|
|||
*/
|
||||
export const onResetPassword = (row: any) => {
|
||||
addDialog({
|
||||
title: `重置 ${row.username} 用户的密码`,
|
||||
title: `${$t('buttons.reset')} ${row.username} ${$t('userPassword')}`,
|
||||
width: '30%',
|
||||
draggable: true,
|
||||
closeOnClickModal: false,
|
||||
|
@ -287,7 +287,7 @@ export const onResetPassword = (row: any) => {
|
|||
*/
|
||||
export const onAssignRolesToUser = (row: any) => {
|
||||
addDialog({
|
||||
title: `为 ${row.username} 分配角色`,
|
||||
title: `${$t('for')} ${row.username} ${$t('assign_roles')}`,
|
||||
width: '45%',
|
||||
draggable: true,
|
||||
closeOnClickModal: false,
|
||||
|
|
|
@ -14,41 +14,32 @@ import { useDeptStore } from '@/store/system/dept';
|
|||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||
import { handleTree } from '@/utils/tree';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { auth } from '@/views/system/dept/utils/auth';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const deptStore = useDeptStore();
|
||||
const datalist = computed(() => handleTree(deptStore.datalist));
|
||||
|
||||
/**
|
||||
* * 当前页改变时
|
||||
*/
|
||||
/** 当前页改变时 */
|
||||
const onCurrentPageChange = async (value: number) => {
|
||||
deptStore.pagination.currentPage = value;
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* * 当分页发生变化
|
||||
* @param value
|
||||
*/
|
||||
/** 当分页发生变化 */
|
||||
const onPageSizeChange = async (value: number) => {
|
||||
deptStore.pagination.pageSize = value;
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* * 选择多行
|
||||
* @param rows
|
||||
*/
|
||||
/** 选择多行 */
|
||||
const onSelectionChange = (rows: Array<any>) => {
|
||||
deleteIds.value = rows.map((row: any) => row.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置表单
|
||||
* @param formEl
|
||||
*/
|
||||
/** 重置表单 */
|
||||
const resetForm = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
|
@ -62,25 +53,29 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="main">
|
||||
<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-input v-model="deptStore.form.deptName" :placeholder="`${$t('input')}${$t('dept_deptName')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dept_summary')" prop="summary">
|
||||
<el-input v-model="deptStore.form.summary" :placeholder="`${$t('input')}${$t('dept_summary')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="deptStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<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-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-form-item>
|
||||
<el-form-item :label="$t('dept_summary')" prop="summary">
|
||||
<el-input v-model="deptStore.form.summary" :placeholder="`${$t('input')}${$t('dept_summary')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="deptStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Auth>
|
||||
|
||||
<PureTableBar :columns="columns" :isExpandAll="true" :tableRef="tableRef?.getTableRef()" :title="$t('dept')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||
<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') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -120,9 +115,9 @@ onMounted(() => {
|
|||
</template>
|
||||
|
||||
<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 :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-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 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 v-if="hasAuth(auth.deleted)" :title="`${$t('delete')} ${row.deptName}?`" @confirm="onDelete(row)">
|
||||
<template #reference>
|
||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||
{{ $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 = [
|
||||
{ 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 },
|
||||
// 管理者
|
||||
|
|
|
@ -14,6 +14,8 @@ import { $t } from '@/plugins/i18n';
|
|||
import { useFilesStore } from '@/store/monitor/files';
|
||||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { auth } from '@/views/system/files/utils/auth';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
|
@ -50,36 +52,40 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="main">
|
||||
<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-input v-model="filesStore.form.filename" :placeholder="`${$t('input')}${$t('files_filename')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('files_filepath')" prop="filepath">
|
||||
<el-input v-model="filesStore.form.filepath" :placeholder="`${$t('input')}${$t('files_filepath')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('files_fileType')" prop="fileType">
|
||||
<el-input v-model="filesStore.form.fileType" :placeholder="`${$t('input')}${$t('files_fileType')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('files_downloadCount')" prop="downloadCount">
|
||||
<el-input v-model="filesStore.form.downloadCount" :placeholder="`${$t('input')}${$t('files_downloadCount')}`" class="!w-[180px]" clearable min="0" type="number" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="filesStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<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-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-form-item>
|
||||
<el-form-item :label="$t('files_filepath')" prop="filepath">
|
||||
<el-input v-model="filesStore.form.filepath" :placeholder="`${$t('input')}${$t('files_filepath')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('files_fileType')" prop="fileType">
|
||||
<el-input v-model="filesStore.form.fileType" :placeholder="`${$t('input')}${$t('files_fileType')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('files_downloadCount')" prop="downloadCount">
|
||||
<el-input v-model="filesStore.form.downloadCount" :placeholder="`${$t('input')}${$t('files_downloadCount')}`" class="!w-[180px]" clearable min="0" type="number" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="filesStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Auth>
|
||||
|
||||
<PureTableBar :columns="columns" :title="$t('system_file')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||
<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') }}
|
||||
</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') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -118,9 +124,11 @@ onMounted(() => {
|
|||
</template>
|
||||
|
||||
<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 :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onDownload(row)"> {{ $t('download') }} </el-button>
|
||||
<el-popconfirm :title="`${$t('delete')} ${row.filename}?`" @confirm="onDelete(row)">
|
||||
<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 v-if="hasAuth(auth.downloadFilesByFileId)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onDownload(row)">
|
||||
{{ $t('download') }}
|
||||
</el-button>
|
||||
<el-popconfirm v-if="hasAuth(auth.deleted)" :title="`${$t('delete')} ${row.filename}?`" @confirm="onDelete(row)">
|
||||
<template #reference>
|
||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||
{{ $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 = [
|
||||
{ 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 },
|
||||
// 文件在服务器上的存储路径
|
||||
|
|
|
@ -5,7 +5,7 @@ import { h, ref } from 'vue';
|
|||
import { message, messageBox } from '@/utils/message';
|
||||
import type { FormItemProps } from '@/views/system/files/utils/types';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { downloadFilesByFileId, downloadFilesByFilepath } from '@/api/v1/files';
|
||||
import { downloadFilesByFileId } from '@/api/v1/files';
|
||||
import { download } from '@/utils/sso';
|
||||
import type { UploadFiles } from 'element-plus';
|
||||
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
||||
|
@ -154,7 +154,7 @@ export const onDeleteBatch = async () => {
|
|||
* @param row
|
||||
*/
|
||||
export const onDownload = async (row: any) => {
|
||||
const blob = await downloadFilesByFilepath({ filepath: row.filepath });
|
||||
const blob = await downloadFilesByFileId({ id: row.id });
|
||||
|
||||
download(blob, row.filename);
|
||||
};
|
||||
|
|
|
@ -28,6 +28,8 @@ import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
|||
import Upload from '@iconify-icons/ri/upload-line';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { usePublicHooks } from '@/views/hooks';
|
||||
import { auth } from '@/views/system/menu/utils/auth';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
const formRef = ref();
|
||||
const routerStore = userMenuStore();
|
||||
|
@ -59,25 +61,34 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="main">
|
||||
<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-input v-model="routerStore.form.title" class="!w-[180px]" clearable placeholder="输入菜单名称" />
|
||||
</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(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<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-item label="菜单名称" prop="title">
|
||||
<el-input v-model="routerStore.form.title" :placeholder="$t('input')" class="!w-[180px]" clearable />
|
||||
</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(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Auth>
|
||||
|
||||
<PureTableBar :columns="columns" :isExpandAll="false" :tableRef="tableRef?.getTableRef()" title="菜单管理" @fullscreen="tableRef?.setAdaptive()" @refresh="onSearch">
|
||||
<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 v-slot="{ size, dynamicColumns }">
|
||||
|
@ -130,13 +141,15 @@ onMounted(() => {
|
|||
|
||||
<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 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 :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>
|
||||
</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>
|
||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||
{{ $t('delete') }}
|
||||
|
@ -145,9 +158,11 @@ onMounted(() => {
|
|||
</el-popconfirm>
|
||||
|
||||
<!-- 分配角色 -->
|
||||
<el-button v-show="row.menuType !== 3" :icon="useRenderIcon(Upload)" :size="size" class="reset-margin" link type="primary" @click="assignRolesToRouter(row)">
|
||||
{{ $t('assign_roles') }}
|
||||
</el-button>
|
||||
<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)">
|
||||
{{ $t('assign_roles') }}
|
||||
</el-button>
|
||||
</Auth>
|
||||
</template>
|
||||
</pure-table>
|
||||
</template>
|
||||
|
|
|
@ -6,6 +6,7 @@ import IconSelect from '@/components/SelectIcon/Select.vue';
|
|||
import Segmented from '@/components/Segmented';
|
||||
import { menuTypeOptions } from '@/enums';
|
||||
import { FormProps } from '@/views/system/menu/utils/types';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
|
||||
const props = withDefaults(defineProps<FormProps>(), {
|
||||
formInline: () => ({}),
|
||||
|
@ -20,13 +21,13 @@ defineExpose({ menuFormRef: ruleFormRef });
|
|||
<el-form ref="ruleFormRef" :model="newFormInline" :rules="formRules" label-width="82px">
|
||||
<el-row :gutter="30">
|
||||
<re-col>
|
||||
<el-form-item label="菜单类型">
|
||||
<el-form-item :label="$t('menuType')">
|
||||
<Segmented v-model="newFormInline.menuType" :options="menuTypeOptions" />
|
||||
</el-form-item>
|
||||
</re-col>
|
||||
|
||||
<re-col>
|
||||
<el-form-item label="上级菜单">
|
||||
<el-form-item :label="$t('previousMenu')">
|
||||
<el-cascader
|
||||
v-model="newFormInline.parentId"
|
||||
:options="newFormInline.higherMenuOptions"
|
||||
|
@ -45,29 +46,29 @@ defineExpose({ menuFormRef: ruleFormRef });
|
|||
</re-col>
|
||||
|
||||
<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-form-item>
|
||||
</re-col>
|
||||
<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-form-item>
|
||||
</re-col>
|
||||
|
||||
<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-form-item>
|
||||
</re-col>
|
||||
<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-form-item>
|
||||
</re-col>
|
||||
|
||||
<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-form-item>
|
||||
</re-col>
|
||||
|
@ -86,7 +87,9 @@ defineExpose({ menuFormRef: ruleFormRef });
|
|||
|
||||
<re-col :sm="24" :value="12" :xs="24">
|
||||
<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>
|
||||
</re-col>
|
||||
</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 => {
|
||||
switch (type) {
|
||||
case 0:
|
||||
return text ? '菜单' : 'primary';
|
||||
return text ? $t('menu') : 'primary';
|
||||
case 1:
|
||||
return text ? 'iframe' : 'warning';
|
||||
case 2:
|
||||
return text ? '外链' : 'danger';
|
||||
return text ? $t('externalLink') : 'danger';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,7 @@ export const formatHigherMenuOptions = (treeList: any) => {
|
|||
export const columns: TableColumnList = [
|
||||
{ type: 'selection', align: 'left' },
|
||||
{
|
||||
label: '菜单名称',
|
||||
label: $t('menuName'),
|
||||
prop: 'title',
|
||||
align: 'left',
|
||||
cellRenderer: ({ row }) => (
|
||||
|
@ -51,7 +51,7 @@ export const columns: TableColumnList = [
|
|||
),
|
||||
},
|
||||
{
|
||||
label: '菜单类型',
|
||||
label: $t('menuType'),
|
||||
prop: 'menuType',
|
||||
width: 100,
|
||||
cellRenderer: ({ row, props }) => (
|
||||
|
@ -60,14 +60,14 @@ export const columns: TableColumnList = [
|
|||
</ElTag>
|
||||
),
|
||||
},
|
||||
{ label: '路由路径', prop: 'path' },
|
||||
{ label: $t('routerPath'), prop: 'path' },
|
||||
{
|
||||
label: '组件路径',
|
||||
label: $t('componentPath'),
|
||||
prop: 'component',
|
||||
formatter: ({ path, component }) => (isAllEmpty(component) ? path : component),
|
||||
},
|
||||
{ label: '排序', prop: 'rank', width: 80, slot: 'rank' },
|
||||
{ label: '隐藏', prop: 'visible', slot: 'visible', width: 100 },
|
||||
{ label: $t('sort'), prop: 'rank', width: 80, slot: 'rank' },
|
||||
{ label: $t('visible'), prop: 'visible', slot: 'visible', width: 100 },
|
||||
{ label: $t('table.updateTime'), prop: 'updateTime', sortable: true },
|
||||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||
|
@ -77,8 +77,7 @@ export const columns: TableColumnList = [
|
|||
|
||||
/** 自定义表单规则校验 */
|
||||
export const formRules = reactive<FormRules>({
|
||||
title: [{ required: true, message: '菜单名称为必填项', trigger: 'blur' }],
|
||||
name: [{ required: true, message: '路由名称为必填项', trigger: 'blur' }],
|
||||
path: [{ required: true, message: '路由路径为必填项且为"/"开头', trigger: ['blur', 'change'], pattern: /^\/.*/ }],
|
||||
auths: [{ required: true, message: '权限标识为必填项', trigger: 'blur' }],
|
||||
title: [{ required: true, message: $t('menuNameTip'), trigger: 'blur' }],
|
||||
name: [{ required: true, message: $t('routerNameTip'), trigger: 'blur' }],
|
||||
path: [{ required: true, message: $t('routerPathTip'), trigger: ['blur', 'change'], pattern: /^\/.*/ }],
|
||||
});
|
||||
|
|
|
@ -30,7 +30,7 @@ export const onSearch = async () => {
|
|||
/** 添加菜单 */
|
||||
export function onAdd(parentId: any = 0) {
|
||||
addDialog({
|
||||
title: `新增菜单`,
|
||||
title: $t('addNew') + $t('menu'),
|
||||
props: {
|
||||
formInline: {
|
||||
menuType: 0,
|
||||
|
@ -75,7 +75,7 @@ export function onAdd(parentId: any = 0) {
|
|||
*/
|
||||
export const onUpdate = (row?: FormItemProps) => {
|
||||
addDialog({
|
||||
title: `更新菜单`,
|
||||
title: $t('update') + $t('menu'),
|
||||
props: {
|
||||
formInline: {
|
||||
menuType: row?.menuType,
|
||||
|
@ -209,7 +209,7 @@ export const onChangeMenuRank = async (row: any) => {
|
|||
*/
|
||||
export const assignRolesToRouter = (row: any) => {
|
||||
addDialog({
|
||||
title: `为 【${$t(row.title)}】 分配角色`,
|
||||
title: `${$t('for')} 【${$t(row.title)}】 ${$t('assign_roles')}`,
|
||||
width: '45%',
|
||||
draggable: true,
|
||||
closeOnClickModal: false,
|
||||
|
|
|
@ -14,6 +14,8 @@ import { usePowerStore } from '@/store/system/power';
|
|||
import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
||||
import { handleTree } from '@pureadmin/utils';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { auth } from '@/views/system/power/utils/auth';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
|
@ -62,34 +64,38 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="main">
|
||||
<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-input v-model="powerStore.form.powerCode" :placeholder="`${$t('input')}${$t('power_powerCode')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('power_powerName')" prop="powerName">
|
||||
<el-input v-model="powerStore.form.powerName" :placeholder="`${$t('input')}${$t('power_powerName')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('power_requestUrl')" prop="requestUrl">
|
||||
<el-input v-model="powerStore.form.requestUrl" :placeholder="`${$t('input')}${$t('power_requestUrl')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="powerStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<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-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-form-item>
|
||||
<el-form-item :label="$t('power_powerName')" prop="powerName">
|
||||
<el-input v-model="powerStore.form.powerName" :placeholder="`${$t('input')}${$t('power_powerName')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('power_requestUrl')" prop="requestUrl">
|
||||
<el-input v-model="powerStore.form.requestUrl" :placeholder="`${$t('input')}${$t('power_requestUrl')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="powerStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Auth>
|
||||
|
||||
<PureTableBar :columns="columns" :isExpandAll="true" :tableRef="tableRef?.getTableRef()" :title="$t('power')" @fullscreen="tableRef.setAdaptive()" @refresh="onSearch">
|
||||
<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 -->
|
||||
<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') }}
|
||||
</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') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -127,12 +133,14 @@ onMounted(() => {
|
|||
{{ row.updateUsername }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
<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 :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.update)" :icon="useRenderIcon(EditPen)" :size="size" class="reset-margin" link type="primary" @click="onUpdate(row)"> {{ $t('modify') }} </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>
|
||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||
{{ $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 = [
|
||||
{ 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' },
|
||||
// 权限名称
|
||||
|
|
|
@ -15,6 +15,8 @@ import { useRenderIcon } from '@/components/CommonIcon/src/hooks';
|
|||
import { deviceDetection } from '@pureadmin/utils';
|
||||
import Menu from '@iconify-icons/ep/menu';
|
||||
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();
|
||||
|
||||
|
@ -60,18 +62,20 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<div class="main">
|
||||
<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-input v-model="roleStore.form.roleCode" :placeholder="`${$t('input')}${$t('role_roleCode')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('role_description')" prop="description">
|
||||
<el-input v-model="roleStore.form.description" :placeholder="`${$t('input')}${$t('role_description')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="roleStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<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-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-form-item>
|
||||
<el-form-item :label="$t('role_description')" prop="description">
|
||||
<el-input v-model="roleStore.form.description" :placeholder="`${$t('input')}${$t('role_description')}`" class="!w-[180px]" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button :icon="useRenderIcon('ri:search-line')" :loading="roleStore.loading" type="primary" @click="onSearch"> {{ $t('search') }} </el-button>
|
||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)"> {{ $t('buttons.reset') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</Auth>
|
||||
|
||||
<div ref="contentRef" :class="['flex', deviceDetection() ? 'flex-wrap' : '']">
|
||||
<PureTableBar
|
||||
|
@ -83,10 +87,12 @@ onMounted(() => {
|
|||
@refresh="onSearch"
|
||||
>
|
||||
<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') }}
|
||||
</el-button>
|
||||
</template>
|
||||
|
@ -125,10 +131,10 @@ onMounted(() => {
|
|||
</template>
|
||||
<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>
|
||||
<el-button :icon="useRenderIcon(Delete)" :size="size" class="reset-margin" link type="primary">
|
||||
{{ $t('delete') }}
|
||||
|
@ -136,7 +142,9 @@ onMounted(() => {
|
|||
</template>
|
||||
</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>
|
||||
</pure-table>
|
||||
</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 = [
|
||||
{ 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' },
|
||||
// 描述
|
||||
|
|
Loading…
Reference in New Issue