feat: 添加角色导入导出;修改组件信息
This commit is contained in:
parent
962f1e1ab5
commit
a461e0d1dd
25
package.json
25
package.json
|
@ -1,9 +1,32 @@
|
|||
{
|
||||
"name": "bunny-admin-web",
|
||||
"name": "bunny-auth-admin",
|
||||
"version": "3.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"bunny-auth-admin",
|
||||
"element-plus",
|
||||
"tailwindcss",
|
||||
"typescript",
|
||||
"pinia",
|
||||
"vue3",
|
||||
"vite",
|
||||
"esm"
|
||||
],
|
||||
"homepage": "https://github.com/BunnyMaster",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/BunnyMaster/bunny-admin-web.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/BunnyMaster/bunny-admin-web/issues"
|
||||
},
|
||||
"author": {
|
||||
"name": "BunnyMaster",
|
||||
"email": "1319900154@qq.com",
|
||||
"url": "https://github.com/BunnyMaster"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "NODE_OPTIONS=--max-old-space-size=1024 vite",
|
||||
"serve": "pnpm vite",
|
||||
|
|
|
@ -132,7 +132,7 @@ class PureHttp {
|
|||
|
||||
// 检查配置的响应类型是否为二进制类型('blob' 或 'arraybuffer'), 如果是,直接返回响应对象
|
||||
if ($config.responseType === 'blob' || $config.responseType === 'arraybuffer') {
|
||||
return data;
|
||||
return response;
|
||||
}
|
||||
|
||||
// 登录过期,和异常处理
|
||||
|
|
|
@ -55,8 +55,8 @@ export const fetchLogout = (data?: object) => {
|
|||
};
|
||||
|
||||
/** 获取用户信息,根据当前token获取 */
|
||||
export const fetchGetUserinfo = () => {
|
||||
return http.request<BaseResult<any>>('get', 'user/noManage/getUserinfo');
|
||||
export const fetchUserinfo = () => {
|
||||
return http.request<BaseResult<any>>('get', 'user/noManage/userinfo');
|
||||
};
|
||||
|
||||
/** 用户信息---获取用户信息列表 */
|
||||
|
|
|
@ -9,8 +9,8 @@ export const fetchGetRoleList = (data: any) => {
|
|||
};
|
||||
|
||||
/** 角色---获取所有角色 */
|
||||
export const fetchGetAllRoles = () => {
|
||||
return http.request<BaseResult<any>>('get', `role/noManage/getAllRoles`);
|
||||
export const fetchAllRoles = () => {
|
||||
return http.request<BaseResult<any>>('get', `role/noManage/allRoles`);
|
||||
};
|
||||
|
||||
/** 角色---根据用户id获取所有角色 */
|
||||
|
@ -18,6 +18,21 @@ export const fetchGetRoleListByUserId = (data) => {
|
|||
return http.request<BaseResult<any>>('get', `userRole/getRoleListByUserId`, { params: data });
|
||||
};
|
||||
|
||||
/** 角色---使用Excel导出导出角色列表 */
|
||||
export const fetchExportByExcel = () => {
|
||||
return http.request<BaseResult<any>>('get', `role/exportByExcel`, { responseType: 'blob' });
|
||||
};
|
||||
|
||||
/* 角色---使用Excel更新角色列表 */
|
||||
export const fetchUpdateRoleByFile = (data: any) => {
|
||||
return http.request<BaseResult<any>>(
|
||||
'put',
|
||||
`/role/update/roleByFile`,
|
||||
{ data },
|
||||
{ headers: { 'Content-Type': 'multipart/form-data' } }
|
||||
);
|
||||
};
|
||||
|
||||
/** 角色---添加角色 */
|
||||
export const fetchAddRole = (data: any) => {
|
||||
return http.request<BaseResult<object>>('post', 'role/addRole', { data });
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,174 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { fetchMenuIconList } from '@/api/v1/menu/menuIcon';
|
||||
import { FormProps } from './types';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
|
||||
const props = withDefaults(defineProps<FormProps>(), {
|
||||
formInline: () => ({
|
||||
icon: '',
|
||||
}),
|
||||
});
|
||||
|
||||
const innerForm = reactive({
|
||||
datalist: [],
|
||||
currentPage: 1,
|
||||
pageSize: 30,
|
||||
total: 100,
|
||||
loading: false,
|
||||
});
|
||||
const form = ref(props.formInline);
|
||||
|
||||
/** 搜索和初始化 */
|
||||
const onSearch = async () => {
|
||||
innerForm.loading = true;
|
||||
const { currentPage, pageSize } = innerForm;
|
||||
|
||||
// 获取数据
|
||||
const baseResult = await fetchMenuIconList({ currentPage, pageSize });
|
||||
if (baseResult.code !== 200) return;
|
||||
const data = baseResult.data;
|
||||
|
||||
// 赋值内容
|
||||
innerForm.datalist = data.list;
|
||||
innerForm.currentPage = data.pageNo;
|
||||
innerForm.pageSize = data.pageSize;
|
||||
innerForm.total = data.total;
|
||||
innerForm.loading = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* * 修改图标
|
||||
* @param value
|
||||
*/
|
||||
const onChangeIcon = (value: any) => {
|
||||
form.value.icon = value.iconCode;
|
||||
};
|
||||
|
||||
/** 清除图标 */
|
||||
const onClear = () => (form.value.icon = '');
|
||||
|
||||
/** 修改当前页 */
|
||||
const onCurrentChange = async (value: number) => {
|
||||
innerForm.currentPage = value;
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
onSearch();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="selector">
|
||||
<el-popover :popper-options="{ placement: 'auto' }" :width="350" popper-class="pure-popper" trigger="click">
|
||||
<template #reference>
|
||||
<div class="w-[60px] h-[32px] cursor-pointer flex justify-center items-center">
|
||||
<el-text v-if="!form.icon" type="primary">{{ $t('select_icon') }}</el-text>
|
||||
<IconifyIconOnline v-else :icon="form.icon" style="font-size: 32px" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<ul class="flex flex-wrap px-2 ml-2 h-[210px]">
|
||||
<li
|
||||
v-for="(item, key) in innerForm.datalist"
|
||||
:key="key"
|
||||
:class="`icon-item p-2 cursor-pointer mr-2 mt-1 flex justify-center items-center border border-[#e5e7eb] ${item.iconCode === form.icon ? 'current' : ''}`"
|
||||
:title="item.iconName"
|
||||
@click="onChangeIcon(item)"
|
||||
>
|
||||
<IconifyIconOnline :icon="item.iconCode" height="20px" width="20px" />
|
||||
</li>
|
||||
</ul>
|
||||
<el-empty v-show="innerForm.datalist.length === 0" :image-size="60" description="图标不存在" />
|
||||
|
||||
<div class="w-full h-9 flex items-center overflow-auto border-t border-[#e5e7eb]">
|
||||
<el-pagination
|
||||
:current-page="innerForm.currentPage"
|
||||
:page-size="innerForm.pageSize"
|
||||
:pager-count="5"
|
||||
:total="innerForm.total"
|
||||
background
|
||||
class="flex-auto ml-2"
|
||||
hide-on-single-page
|
||||
layout="pager"
|
||||
size="small"
|
||||
@current-change="onCurrentChange"
|
||||
/>
|
||||
<el-button bg class="justify-end mr-2 ml-2" size="small" text type="danger" @click="onClear">清空</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
<el-link
|
||||
:title="$t('systemMenuIcon.officialWebsite')"
|
||||
:underline="false"
|
||||
href="https://icon-sets.iconify.design/"
|
||||
target="_blank"
|
||||
type="primary"
|
||||
>
|
||||
{{ $t('systemMenuIcon.officialWebsite') }}
|
||||
</el-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.current {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
transition: all 0.4s;
|
||||
transform: scaleX(1.05);
|
||||
}
|
||||
|
||||
.icon-item {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
transition: all 0.4s;
|
||||
transform: scaleX(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav-next) {
|
||||
font-size: 15px;
|
||||
line-height: 32px;
|
||||
box-shadow: -5px 0 5px -6px #ccc;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav-prev) {
|
||||
font-size: 15px;
|
||||
line-height: 32px;
|
||||
box-shadow: 5px 0 5px -6px #ccc;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__item) {
|
||||
height: 30px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__header),
|
||||
:deep(.el-tabs__nav-wrap) {
|
||||
position: static;
|
||||
margin: 0;
|
||||
box-shadow: 0 2px 5px rgb(0 0 0 / 6%);
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav-wrap::after) {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav-wrap) {
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__content) {
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
|
@ -1,127 +1,184 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { fetchMenuIconList } from '@/api/v1/menu/menuIcon';
|
||||
import { FormProps } from './types';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { IconJson } from '@/components/ReIcon/data';
|
||||
import { cloneDeep, isAllEmpty } from '@pureadmin/utils';
|
||||
import { computed, CSSProperties, ref, watch } from 'vue';
|
||||
import Search from '@iconify-icons/ri/search-eye-line';
|
||||
|
||||
const props = withDefaults(defineProps<FormProps>(), {
|
||||
formInline: () => ({
|
||||
icon: '',
|
||||
}),
|
||||
type ParameterCSSProperties = (item?: string) => CSSProperties | undefined;
|
||||
|
||||
defineOptions({
|
||||
name: 'IconSelect',
|
||||
});
|
||||
|
||||
const innerForm = reactive({
|
||||
datalist: [],
|
||||
currentPage: 1,
|
||||
pageSize: 30,
|
||||
total: 100,
|
||||
loading: false,
|
||||
const inputValue = defineModel({ type: String });
|
||||
|
||||
const iconList = ref(IconJson);
|
||||
const icon = ref();
|
||||
const currentActiveType = ref('ep:');
|
||||
// 深拷贝图标数据,前端做搜索
|
||||
const copyIconList = cloneDeep(iconList.value);
|
||||
const totalPage = ref(0);
|
||||
// 每页显示35个图标
|
||||
const pageSize = ref(35);
|
||||
const currentPage = ref(1);
|
||||
|
||||
// 搜索条件
|
||||
const filterValue = ref('');
|
||||
|
||||
const tabsList = [
|
||||
{
|
||||
label: 'Element Plus',
|
||||
name: 'ep:',
|
||||
},
|
||||
{
|
||||
label: 'Remix Icon',
|
||||
name: 'ri:',
|
||||
},
|
||||
{
|
||||
label: 'Font Awesome 5 Solid',
|
||||
name: 'fa-solid:',
|
||||
},
|
||||
];
|
||||
|
||||
const pageList = computed(
|
||||
() =>
|
||||
currentActiveType.value !== 'web' &&
|
||||
copyIconList[currentActiveType.value]
|
||||
.filter((i) => i.includes(filterValue.value))
|
||||
.slice((currentPage.value - 1) * pageSize.value, currentPage.value * pageSize.value)
|
||||
);
|
||||
|
||||
const iconItemStyle = computed((): ParameterCSSProperties => {
|
||||
return (item) => {
|
||||
if (inputValue.value === currentActiveType.value + item) {
|
||||
return {
|
||||
borderColor: 'var(--el-color-primary)',
|
||||
color: 'var(--el-color-primary)',
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
const form = ref(props.formInline);
|
||||
|
||||
/** 搜索和初始化 */
|
||||
const onSearch = async () => {
|
||||
innerForm.loading = true;
|
||||
const { currentPage, pageSize } = innerForm;
|
||||
function setVal() {
|
||||
currentActiveType.value = inputValue.value.substring(0, inputValue.value.indexOf(':') + 1);
|
||||
icon.value = inputValue.value.substring(inputValue.value.indexOf(':') + 1);
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
const baseResult = await fetchMenuIconList({ currentPage, pageSize });
|
||||
if (baseResult.code !== 200) return;
|
||||
const data = baseResult.data;
|
||||
function onBeforeEnter() {
|
||||
if (isAllEmpty(icon.value)) return;
|
||||
setVal();
|
||||
// 寻找当前图标在第几页
|
||||
const curIconIndex = copyIconList[currentActiveType.value].findIndex((i) => i === icon.value);
|
||||
currentPage.value = Math.ceil((curIconIndex + 1) / pageSize.value);
|
||||
}
|
||||
|
||||
// 赋值内容
|
||||
innerForm.datalist = data.list;
|
||||
innerForm.currentPage = data.pageNo;
|
||||
innerForm.pageSize = data.pageSize;
|
||||
innerForm.total = data.total;
|
||||
innerForm.loading = false;
|
||||
};
|
||||
function onAfterLeave() {
|
||||
filterValue.value = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* * 修改图标
|
||||
* @param value
|
||||
*/
|
||||
const onChangeIcon = (value: any) => {
|
||||
form.value.icon = value.iconCode;
|
||||
};
|
||||
function handleClick({ props }) {
|
||||
currentPage.value = 1;
|
||||
currentActiveType.value = props.name;
|
||||
}
|
||||
|
||||
/** 清除图标 */
|
||||
const onClear = () => (form.value.icon = '');
|
||||
function onChangeIcon(item) {
|
||||
icon.value = item;
|
||||
inputValue.value = currentActiveType.value + item;
|
||||
}
|
||||
|
||||
/** 修改当前页 */
|
||||
const onCurrentChange = async (value: number) => {
|
||||
innerForm.currentPage = value;
|
||||
await onSearch();
|
||||
};
|
||||
function onCurrentChange(page) {
|
||||
currentPage.value = page;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
onSearch();
|
||||
});
|
||||
function onClear() {
|
||||
icon.value = '';
|
||||
inputValue.value = '';
|
||||
}
|
||||
|
||||
watch(
|
||||
() => pageList.value,
|
||||
() =>
|
||||
currentActiveType.value !== 'web' &&
|
||||
(totalPage.value = copyIconList[currentActiveType.value].filter((i) => i.includes(filterValue.value)).length),
|
||||
{ immediate: true }
|
||||
);
|
||||
watch(
|
||||
() => inputValue.value,
|
||||
(val) => val && setVal(),
|
||||
{ immediate: true }
|
||||
);
|
||||
watch(
|
||||
() => filterValue.value,
|
||||
() => (currentPage.value = 1)
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="selector">
|
||||
<el-popover :popper-options="{ placement: 'auto' }" :width="350" popper-class="pure-popper" trigger="click">
|
||||
<template #reference>
|
||||
<div class="w-[60px] h-[32px] cursor-pointer flex justify-center items-center">
|
||||
<el-text v-if="!form.icon" type="primary">{{ $t('select_icon') }}</el-text>
|
||||
<IconifyIconOnline v-else :icon="form.icon" style="font-size: 32px" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<ul class="flex flex-wrap px-2 ml-2 h-[210px]">
|
||||
<li
|
||||
v-for="(item, key) in innerForm.datalist"
|
||||
:key="key"
|
||||
:class="`icon-item p-2 cursor-pointer mr-2 mt-1 flex justify-center items-center border border-[#e5e7eb] ${item.iconCode === form.icon ? 'current' : ''}`"
|
||||
:title="item.iconName"
|
||||
@click="onChangeIcon(item)"
|
||||
<el-input v-model="inputValue" disabled>
|
||||
<template #append>
|
||||
<el-popover
|
||||
:popper-options="{
|
||||
placement: 'auto',
|
||||
}"
|
||||
:width="350"
|
||||
popper-class="pure-popper"
|
||||
trigger="click"
|
||||
@before-enter="onBeforeEnter"
|
||||
@after-leave="onAfterLeave"
|
||||
>
|
||||
<IconifyIconOnline :icon="item.iconCode" height="20px" width="20px" />
|
||||
</li>
|
||||
</ul>
|
||||
<el-empty v-show="innerForm.datalist.length === 0" :image-size="60" description="图标不存在" />
|
||||
<template #reference>
|
||||
<div class="w-[40px] h-[32px] cursor-pointer flex justify-center items-center">
|
||||
<IconifyIconOffline v-if="!icon" :icon="Search" />
|
||||
<IconifyIconOnline v-else :icon="inputValue" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="w-full h-9 flex items-center overflow-auto border-t border-[#e5e7eb]">
|
||||
<el-pagination
|
||||
:current-page="innerForm.currentPage"
|
||||
:page-size="innerForm.pageSize"
|
||||
:pager-count="5"
|
||||
:total="innerForm.total"
|
||||
background
|
||||
class="flex-auto ml-2"
|
||||
hide-on-single-page
|
||||
layout="pager"
|
||||
size="small"
|
||||
@current-change="onCurrentChange"
|
||||
/>
|
||||
<el-button bg class="justify-end mr-2 ml-2" size="small" text type="danger" @click="onClear">清空</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
<el-link
|
||||
:title="$t('systemMenuIcon.officialWebsite')"
|
||||
:underline="false"
|
||||
href="https://icon-sets.iconify.design/"
|
||||
target="_blank"
|
||||
type="primary"
|
||||
>
|
||||
{{ $t('systemMenuIcon.officialWebsite') }}
|
||||
</el-link>
|
||||
<el-input v-model="filterValue" class="px-2 pt-2" clearable placeholder="搜索图标" />
|
||||
|
||||
<el-tabs v-model="currentActiveType" @tab-click="handleClick">
|
||||
<el-tab-pane v-for="(pane, index) in tabsList" :key="index" :label="pane.label" :name="pane.name">
|
||||
<el-scrollbar height="220px">
|
||||
<ul class="flex flex-wrap px-2 ml-2">
|
||||
<li
|
||||
v-for="(item, key) in pageList"
|
||||
:key="key"
|
||||
:style="iconItemStyle(item)"
|
||||
:title="item"
|
||||
class="icon-item p-2 cursor-pointer mr-2 mt-1 flex justify-center items-center border border-[#e5e7eb]"
|
||||
@click="onChangeIcon(item)"
|
||||
>
|
||||
<IconifyIconOnline :icon="currentActiveType + item" height="20px" width="20px" />
|
||||
</li>
|
||||
</ul>
|
||||
<el-empty v-show="pageList.length === 0" :description="`${filterValue} 图标不存在`" :image-size="60" />
|
||||
</el-scrollbar>
|
||||
<div class="w-full h-9 flex items-center overflow-auto border-t border-[#e5e7eb]">
|
||||
<el-pagination
|
||||
:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
:pager-count="5"
|
||||
:total="totalPage"
|
||||
background
|
||||
class="flex-auto ml-2"
|
||||
layout="pager"
|
||||
size="small"
|
||||
@current-change="onCurrentChange"
|
||||
/>
|
||||
<el-button bg class="justify-end mr-2 ml-2" size="small" text type="danger" @click="onClear">
|
||||
清空
|
||||
</el-button>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.current {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
transition: all 0.4s;
|
||||
transform: scaleX(1.05);
|
||||
}
|
||||
|
||||
.icon-item {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { defineStore } from 'pinia';
|
||||
import {
|
||||
fetchAddRole,
|
||||
fetchAllRoles,
|
||||
fetchAssignPowersToRole,
|
||||
fetchDeleteRole,
|
||||
fetchGetAllRoles,
|
||||
fetchGetRoleList,
|
||||
fetchUpdateRole,
|
||||
fetchUpdateRoleByFile,
|
||||
} from '@/api/v1/system/role';
|
||||
import { pageSizes } from '@/enums/baseConstant';
|
||||
import { storeMessage } from '@/utils/message';
|
||||
|
@ -58,8 +59,8 @@ export const useRoleStore = defineStore('roleStore', {
|
|||
},
|
||||
|
||||
/** 获取所有角色 */
|
||||
async getAllRoles() {
|
||||
const result = await fetchGetAllRoles();
|
||||
async allRoles() {
|
||||
const result = await fetchAllRoles();
|
||||
if (result.code !== 200) return;
|
||||
|
||||
this.allRoleList = result.data.map((role) => ({ key: role.id, label: role.description }));
|
||||
|
@ -71,6 +72,12 @@ export const useRoleStore = defineStore('roleStore', {
|
|||
return storeMessage(result);
|
||||
},
|
||||
|
||||
/* 使用Excel更新角色列表 */
|
||||
async updateRoleByFile(data: any) {
|
||||
const result = await fetchUpdateRoleByFile(data);
|
||||
return storeMessage(result);
|
||||
},
|
||||
|
||||
/** 为角色分配权限 */
|
||||
async assignPowersToRole(data: any) {
|
||||
const result = await fetchAssignPowersToRole(data);
|
||||
|
|
|
@ -2,10 +2,10 @@ import { defineStore } from 'pinia';
|
|||
import { resetRouter, router, routerArrays, storageLocal, store, type userType } from '../utils';
|
||||
import {
|
||||
fetchAssignRolesToUsers,
|
||||
fetchGetUserinfo,
|
||||
fetchLogin,
|
||||
fetchLogout,
|
||||
fetchPostEmailCode,
|
||||
fetchUserinfo,
|
||||
refreshTokenApi,
|
||||
} from '@/api/v1/system/adminUser';
|
||||
import { useMultiTagsStoreHook } from '../multiTags';
|
||||
|
@ -86,7 +86,7 @@ export const useUserStore = defineStore({
|
|||
|
||||
/** 获取用户信息 */
|
||||
async getUserinfo() {
|
||||
const result = await fetchGetUserinfo();
|
||||
const result = await fetchUserinfo();
|
||||
if (result.code === 200) {
|
||||
const data = result.data;
|
||||
setToken(data);
|
||||
|
|
|
@ -62,6 +62,7 @@ export async function download(blob: any, filename: string) {
|
|||
const result = await blobToJson(blob);
|
||||
if (result) return;
|
||||
|
||||
blob = blob.data;
|
||||
// 创建一个临时的 URL,用于下载文件
|
||||
const a = document.createElement('a');
|
||||
const url = window.URL.createObjectURL(new Blob([blob]));
|
||||
|
@ -117,8 +118,7 @@ export const downloadBlob = async (response: any, fileName: string) => {
|
|||
const contentDisposition = response.headers['content-disposition'];
|
||||
// let fileName = 'download.zip';
|
||||
if (contentDisposition) {
|
||||
const fileNameMatch = contentDisposition.match(/filename="?(.+)"/);
|
||||
|
||||
const fileNameMatch = contentDisposition.match(/filename=?(.+)/);
|
||||
if (fileNameMatch && fileNameMatch[1]) {
|
||||
fileName = fileNameMatch[1];
|
||||
}
|
||||
|
@ -144,7 +144,8 @@ export const downloadBlob = async (response: any, fileName: string) => {
|
|||
*/
|
||||
async function blobToJson(blob: any): Promise<any> {
|
||||
try {
|
||||
const text = await blob.text();
|
||||
const text = await blob.data.text();
|
||||
|
||||
const json = JSON.parse(text);
|
||||
if (json.code !== 200) {
|
||||
message(json.message, { type: 'error' });
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
|
||||
import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
||||
import PureTableBar from '@/components/TableBar/src/bar';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
import { useEmailTemplateStore } from '@/store/configuration/emailTemplate';
|
||||
import {
|
||||
auth,
|
||||
columns,
|
||||
|
@ -11,19 +17,15 @@ import {
|
|||
selectRows,
|
||||
viewTemplate,
|
||||
} from '@/views/configuration/email-template/utils';
|
||||
import PureTableBar from '@/components/TableBar/src/bar';
|
||||
import AddFill from '@iconify-icons/ri/add-circle-line';
|
||||
import PureTable from '@pureadmin/table';
|
||||
import Delete from '@iconify-icons/ep/delete';
|
||||
import EditPen from '@iconify-icons/ep/edit-pen';
|
||||
import Refresh from '@iconify-icons/ep/refresh';
|
||||
import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { useEmailTemplateStore } from '@/store/configuration/emailTemplate';
|
||||
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
import View from '@iconify-icons/ep/view';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
import AddFill from '@iconify-icons/ri/add-circle-line';
|
||||
import PureTable from '@pureadmin/table';
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
defineOptions({ name: 'EmailTemplate' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
|
|
|
@ -35,7 +35,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -28,6 +28,8 @@ import { hasAuth } from '@/router/utils';
|
|||
import { enabledOrNotStatus } from '@/enums/baseConstant';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'EmailUsersConfiguration' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const emailUsersStore = useEmailUsersStore();
|
||||
|
|
|
@ -23,7 +23,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -24,6 +24,7 @@ import MenuIconSelectIconName from '@/views/configuration/menu-icon/components/m
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'MenuIconConfiguration' });
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const menuIconStore = useMenuIconStore();
|
||||
|
|
|
@ -13,7 +13,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', width: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -8,6 +8,8 @@ import { userI18nTypeStore } from '@/store/i18n/i18nType';
|
|||
import { usePublicHooks } from '@/views/hooks';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
defineOptions({ name: 'WebConfiguration' });
|
||||
|
||||
const ruleFormRef = ref<FormInstance>();
|
||||
const i18nTypeStore = userI18nTypeStore();
|
||||
// 用户是否停用样式
|
||||
|
|
|
@ -76,6 +76,6 @@ defineExpose({ formRef });
|
|||
</el-form-item>
|
||||
|
||||
<!-- 更新提示 -->
|
||||
<el-text type="danger">{{ $t('update_i18n_tip') }}</el-text>
|
||||
<el-text type="danger">{{ $t('update_tip') }}</el-text>
|
||||
</el-form>
|
||||
</template>
|
||||
|
|
|
@ -27,6 +27,8 @@ import Download from '@iconify-icons/ep/download';
|
|||
import Upload from '@iconify-icons/ri/upload-line';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'I18n' });
|
||||
|
||||
const tableRef = ref();
|
||||
const pageFormRef = ref();
|
||||
const i18nStore = userI18nStore();
|
||||
|
@ -134,7 +136,7 @@ onMounted(() => {
|
|||
|
||||
<!-- 下载多语言配置 -->
|
||||
<el-dropdown v-if="hasAuth(auth.update)" class="mr-1" type="primary">
|
||||
<el-button :icon="useRenderIcon(Upload)" plain type="primary">{{ $t('file_update') }}</el-button>
|
||||
<el-button :icon="useRenderIcon(Upload)" plain type="primary">{{ $t('file_import') }}</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item @click="updateI18nSetting('json')">{{ $t('use_json_update') }}</el-dropdown-item>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// 多语言表格列字段
|
||||
import { reactive } from 'vue';
|
||||
import type { FormRules } from 'element-plus';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import type { FormRules } from 'element-plus';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
export const columns: TableColumnList = [
|
||||
{ type: 'selection', align: 'left' },
|
||||
|
@ -13,7 +13,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', width: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加多语言表单规则
|
||||
|
|
|
@ -14,6 +14,8 @@ import { selectUserinfo } from '@/components/Table/Userinfo/columns';
|
|||
import { $t } from '@/plugins/i18n';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
|
||||
defineOptions({ name: 'I18nType' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const i18nTypeStore = userI18nTypeStore();
|
||||
|
|
|
@ -12,7 +12,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime' },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', width: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -6,6 +6,8 @@ import { formState, settingLR } from '@/views/message-manger/message-editing/uti
|
|||
import MarkdownEditor from '@/views/message-manger/message-editing/components/markdown-editor.vue';
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
defineOptions({ name: 'MessageEditer' });
|
||||
|
||||
/** 退出提醒 */
|
||||
const exitAlter = () => {
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
|
|
|
@ -24,6 +24,8 @@ import { Message } from '@element-plus/icons-vue';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'MessageReceived' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const messageReceivedStore = useMessageReceivedStore();
|
||||
|
|
|
@ -25,6 +25,8 @@ import { useMessageTypeStore } from '@/store/message/messageType';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'MessageSender' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const messageTypeStore = useMessageTypeStore();
|
||||
|
|
|
@ -39,7 +39,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -26,6 +26,8 @@ import { usePublicHooks } from '@/views/hooks';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'MessageType' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const messageTypeStore = useMessageTypeStore();
|
||||
|
|
|
@ -18,7 +18,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, width: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', width: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import { onMounted, ref } from 'vue';
|
||||
import { fetchSystemCaches } from '@/api/v1/actuator';
|
||||
|
||||
defineOptions({ name: 'SystemCaches' });
|
||||
|
||||
const caches = ref([]);
|
||||
const onSearch = async () => {
|
||||
let result = await fetchSystemCaches();
|
||||
|
@ -16,7 +18,7 @@ onMounted(() => {
|
|||
|
||||
<template>
|
||||
<el-descriptions :column="2" border direction="vertical" title="系统已缓存内容">
|
||||
<el-descriptions-item v-for="cache in caches" :key="cache.key" :label="cache.key" style="overflow: auto">
|
||||
<el-descriptions-item v-for="cache in caches" :key="cache.key" :label="cache.key">
|
||||
{{ cache.value }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
|
|
@ -25,6 +25,8 @@ import 'vue-json-pretty/lib/styles.css';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'SchedulerExecuteLog' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const quartzExecuteLogStore = useQuartzExecuteLogStore();
|
||||
|
|
|
@ -23,7 +23,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
// 添加规则
|
||||
export const rules = reactive({});
|
||||
|
|
|
@ -4,6 +4,8 @@ import { info, loading, svg } from '@/views/monitor/server/utils';
|
|||
import SystemServer from '@/views/monitor/server/components/system-server.vue';
|
||||
import SystemCpu from '@/views/monitor/server/components/system-cpu.vue';
|
||||
import SystemJvmCpu from '@/views/monitor/server/components/system-jvm-cpu.vue';
|
||||
|
||||
defineOptions({ name: 'MonitorServer' });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -22,6 +22,8 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'UserLoginLog' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const userLoginLogStore = useUserLoginLogStore();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { reactive } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
// 表格列
|
||||
export const columns: TableColumnList = [
|
||||
|
@ -23,7 +23,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -24,6 +24,8 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'SchedulerGroup' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const schedulersGroupStore = useSchedulersGroupStore();
|
||||
|
|
|
@ -13,7 +13,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, width: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', width: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', width: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', width: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -24,6 +24,8 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'SchedulerTask' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const schedulersStore = useSchedulersStore();
|
||||
|
|
|
@ -18,7 +18,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('schedulers_triggerState'), prop: 'triggerState' },
|
||||
// corn表达式
|
||||
{ label: $t('schedulers_cronExpression'), prop: 'cronExpression' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -26,7 +26,7 @@ const getRoleListByUserId = async () => {
|
|||
};
|
||||
|
||||
onMounted(() => {
|
||||
roleStore.getAllRoles();
|
||||
roleStore.allRoles();
|
||||
getRoleListByUserId();
|
||||
});
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ import { usePublicHooks } from '@/views/hooks';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'AdminUserManger' });
|
||||
|
||||
const adminUserStore = useAdminUserStore();
|
||||
const deptStore = useDeptStore();
|
||||
// 用户是否停用样式
|
||||
|
|
|
@ -25,6 +25,7 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'DeptManger' });
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const deptStore = useDeptStore();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { reactive } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { reactive } from 'vue';
|
||||
|
||||
// 表格列
|
||||
export const columns: TableColumnList = [
|
||||
|
@ -15,7 +15,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -27,6 +27,8 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'FileManger' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const filesStore = useFilesStore();
|
||||
|
|
|
@ -17,7 +17,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
// 添加规则
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import ReAnimateSelector from '@/components/ReAnimateSelector/src/index.vue';
|
||||
import ReCol from '@/components/ReCol';
|
||||
import IconSelect from '@/components/ReIcon/src/Select.vue';
|
||||
import Segmented from '@/components/ReSegmented';
|
||||
import {
|
||||
fixedTagOptions,
|
||||
|
@ -17,6 +16,7 @@ import { FormProps, formRules } from '@/views/system/menu/utils';
|
|||
import { onMounted, ref } from 'vue';
|
||||
import { userMenuStore } from '@/store/system/menu';
|
||||
import { useRoleStore } from '@/store/system/role';
|
||||
import NetWorkIcon from '@/components/ReIcon/src/NetWorkIcon.vue';
|
||||
|
||||
const props = withDefaults(defineProps<FormProps>(), {
|
||||
formInline: () => ({
|
||||
|
@ -66,7 +66,7 @@ const getRoleListByRouterId = async () => {
|
|||
|
||||
onMounted(() => {
|
||||
// 获取所有的角色列表
|
||||
roleStore.getAllRoles();
|
||||
roleStore.allRoles();
|
||||
|
||||
// 根据当前路由id,查找这个路由下所有的角色信息
|
||||
getRoleListByRouterId();
|
||||
|
@ -150,7 +150,8 @@ defineExpose({ menuFormRef: formRef });
|
|||
<!-- 菜单图标 -->
|
||||
<re-col :sm="24" :value="12" :xs="24">
|
||||
<el-form-item label="菜单图标" prop="icon">
|
||||
<IconSelect :form-inline="form" class="w-full" />
|
||||
<!--<IconSelect v-show="true" :form-inline="form" class="w-full" />-->
|
||||
<NetWorkIcon :form-inline="form" class="w-full" />
|
||||
</el-form-item>
|
||||
</re-col>
|
||||
|
||||
|
|
|
@ -26,24 +26,20 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'MenuManger' });
|
||||
|
||||
const menuStore = userMenuStore();
|
||||
const routerStore = userMenuStore();
|
||||
const formRef = ref();
|
||||
|
||||
/**
|
||||
* 表单重置
|
||||
* @param formEl
|
||||
*/
|
||||
/* 表单重置 */
|
||||
const resetForm = async (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* * 选择多行
|
||||
* @param rows
|
||||
*/
|
||||
/* 选择多行 */
|
||||
const onSelectionChange = (rows: Array<any>) => {
|
||||
selectIds.value = rows.map((row: any) => row.id);
|
||||
};
|
||||
|
|
|
@ -104,7 +104,7 @@ export const columns: TableColumnList = [
|
|||
{ label: $t('table.createTime'), prop: 'createTime', sortable: true, minWidth: 160 },
|
||||
{ label: $t('table.createUser'), prop: 'createUser', slot: 'createUser', minWidth: 130 },
|
||||
{ label: $t('table.updateUser'), prop: 'updateUser', slot: 'updateUser', minWidth: 130 },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 160, slot: 'operation' },
|
||||
{ label: $t('table.operation'), fixed: 'right', minWidth: 210, slot: 'operation' },
|
||||
];
|
||||
|
||||
/** 自定义表单规则校验 */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
import { FormProps, powerCascadeProps, rules } from '@/views/system/power/utils';
|
||||
import { FormProps, powerCascadeProps, rules } from '@/views/system/permission/utils';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { handleTree } from '@pureadmin/utils';
|
||||
import { usePowerStore } from '@/store/system/power';
|
|
@ -10,7 +10,7 @@ import {
|
|||
onUpdate,
|
||||
onUpdateBatchParent,
|
||||
powerIds,
|
||||
} from '@/views/system/power/utils';
|
||||
} from '@/views/system/permission/utils';
|
||||
import PureTableBar from '@/components/TableBar/src/bar';
|
||||
import AddFill from '@iconify-icons/ri/add-circle-line';
|
||||
import PureTable from '@pureadmin/table';
|
||||
|
@ -26,6 +26,8 @@ import { FormInstance } from 'element-plus';
|
|||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
|
||||
defineOptions({ name: 'PermissionManger' });
|
||||
|
||||
const tableRef = ref();
|
||||
const formRef = ref();
|
||||
const powerStore = usePowerStore();
|
|
@ -1,12 +1,12 @@
|
|||
import { addDialog } from '@/components/ReDialog/index';
|
||||
import PowerDialog from '@/views/system/power/components/power-dialog.vue';
|
||||
import PowerDialog from '@/views/system/permission/components/power-dialog.vue';
|
||||
import { usePowerStore } from '@/store/system/power';
|
||||
import { h, reactive, ref } from 'vue';
|
||||
import { message, messageBox } from '@/utils/message';
|
||||
import type { FormItemProps } from '@/views/system/power/utils/types';
|
||||
import type { FormItemProps } from '@/views/system/permission/utils/types';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { handleTree } from '@pureadmin/utils';
|
||||
import { powerCascadeProps } from '@/views/system/power/utils/columns';
|
||||
import { powerCascadeProps } from '@/views/system/permission/utils/columns';
|
||||
import { ElCascader, ElForm, ElFormItem } from 'element-plus';
|
||||
import DeleteBatchDialog from '@/components/Table/DeleteBatchDialog.vue';
|
||||
|
|
@ -13,7 +13,7 @@ import Check from '@iconify-icons/ep/check';
|
|||
import { computed, nextTick, onMounted, ref, watch } from 'vue';
|
||||
import { delay, getKeyList, handleTree, subBefore, useResizeObserver } from '@pureadmin/utils';
|
||||
import { usePowerStore } from '@/store/system/power';
|
||||
import { powerCascadeProps } from '@/views/system/power/utils';
|
||||
import { powerCascadeProps } from '@/views/system/permission/utils';
|
||||
import { useRoleStore } from '@/store/system/role';
|
||||
|
||||
const powerStore = usePowerStore();
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
<script lang="ts" setup>
|
||||
import { FormInstance, type FormRules, genFileId, type UploadProps, type UploadRawFile } from 'element-plus';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { reactive, ref } from 'vue';
|
||||
|
||||
import { UploadFilled } from '@element-plus/icons-vue';
|
||||
|
||||
interface Props {
|
||||
form: {
|
||||
file: any;
|
||||
};
|
||||
}
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
file: [{ required: true, message: `${$t('select')}${$t('files')}`, trigger: 'blur' }],
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
form: () => ({
|
||||
file: undefined,
|
||||
}),
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
const form = ref(props.form);
|
||||
const uploadRef = ref();
|
||||
|
||||
const handleExceed: UploadProps['onExceed'] = (files) => {
|
||||
uploadRef.value!.clearFiles();
|
||||
const file = files[0] as UploadRawFile;
|
||||
file.uid = genFileId();
|
||||
uploadRef.value!.handleStart(file);
|
||||
};
|
||||
|
||||
defineExpose({ formRef });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-form ref="formRef" :model="form" :rules="rules" isDefault-icon>
|
||||
<el-form-item :label="$t('files')" prop="file">
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
v-model:file-list="form.file"
|
||||
:autoUpload="false"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
class="w-full mt-2"
|
||||
drag
|
||||
>
|
||||
<el-icon class="el-icon--upload">
|
||||
<UploadFilled />
|
||||
</el-icon>
|
||||
<div class="el-upload__text">
|
||||
<em>{{ `${$t('drop_file_here')} / ${$t('click_to_upload')}` }}</em>
|
||||
</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 更新提示 -->
|
||||
<el-text type="danger">{{ $t('update_tip') }}</el-text>
|
||||
</el-form>
|
||||
</template>
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue';
|
||||
import { h, onMounted } from 'vue';
|
||||
import {
|
||||
auth,
|
||||
columns,
|
||||
|
@ -30,44 +30,76 @@ import Menu from '@iconify-icons/ep/menu';
|
|||
import AssignPowersToRole from '@/views/system/role/components/assign-powers-to-role.vue';
|
||||
import { hasAuth } from '@/router/utils';
|
||||
import ReAuth from '@/components/ReAuth/src/auth';
|
||||
import { fetchExportByExcel } from '@/api/v1/system/role';
|
||||
import { downloadBlob } from '@/utils/sso';
|
||||
import Download from '@iconify-icons/ep/download';
|
||||
import Upload from '@iconify-icons/ri/upload-line';
|
||||
import { addDialog } from '@/components/ReDialog/index';
|
||||
import FileUpdateRoleDialog from '@/views/system/role/components/file-update-role-dialog.vue';
|
||||
import { FormInstance } from 'element-plus';
|
||||
|
||||
defineOptions({ name: 'RoleManger' });
|
||||
|
||||
const roleStore = useRoleStore();
|
||||
|
||||
/**
|
||||
* * 当前页改变时
|
||||
*/
|
||||
/* 当前页改变时 */
|
||||
const onCurrentPageChange = async (value: number) => {
|
||||
roleStore.pagination.currentPage = value;
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
/**
|
||||
* * 当分页发生变化
|
||||
* @param value
|
||||
*/
|
||||
/* 当分页发生变化 */
|
||||
const onPageSizeChange = async (value: number) => {
|
||||
roleStore.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) => {
|
||||
/* 重置表单 */
|
||||
const resetForm = async (formEl: FormInstance) => {
|
||||
if (!formEl) return;
|
||||
formEl.resetFields();
|
||||
await onSearch();
|
||||
};
|
||||
|
||||
/* 使用Excel导出导出角色列表 */
|
||||
const downloadRoleExcel = async () => {
|
||||
const result = await fetchExportByExcel();
|
||||
|
||||
downloadBlob(result, 'role.zip');
|
||||
};
|
||||
|
||||
/* 使用文件更新角色 */
|
||||
const onUpdateByFile = (row: any) => {
|
||||
addDialog({
|
||||
title: `${$t('modify')}${$t('role')}`,
|
||||
width: '30%',
|
||||
props: { form: { file: undefined } },
|
||||
draggable: true,
|
||||
fullscreenIcon: true,
|
||||
closeOnClickModal: false,
|
||||
contentRenderer: () => h(FileUpdateRoleDialog, { ref: formRef }),
|
||||
beforeSure: (done, { options }) => {
|
||||
const form = options.props.form;
|
||||
formRef.value.formRef.validate(async (valid: any) => {
|
||||
if (!valid) return;
|
||||
// 更新文件 data
|
||||
const data = { file: form.file[0].raw };
|
||||
|
||||
// 更新角色信息
|
||||
const result = await roleStore.updateRoleByFile(data);
|
||||
if (!result) return;
|
||||
done();
|
||||
await onSearch();
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
onSearch();
|
||||
});
|
||||
|
@ -122,6 +154,27 @@ onMounted(() => {
|
|||
@refresh="onSearch"
|
||||
>
|
||||
<template #buttons>
|
||||
<!-- 下载Excel配置 -->
|
||||
<el-button
|
||||
v-if="hasAuth(auth.downloadRole)"
|
||||
:icon="useRenderIcon(Download)"
|
||||
plain
|
||||
type="primary"
|
||||
@click="downloadRoleExcel"
|
||||
>
|
||||
{{ $t('download_configuration') }}
|
||||
</el-button>
|
||||
<!-- 文件更新 -->
|
||||
<el-button
|
||||
v-if="hasAuth(auth.update)"
|
||||
:icon="useRenderIcon(Upload)"
|
||||
plain
|
||||
type="primary"
|
||||
@click="onUpdateByFile"
|
||||
>
|
||||
{{ $t('file_import') }}
|
||||
</el-button>
|
||||
|
||||
<el-button v-if="hasAuth(auth.add)" :icon="useRenderIcon(AddFill)" plain type="primary" @click="onAdd">
|
||||
{{ $t('addNew') }}
|
||||
</el-button>
|
||||
|
|
|
@ -9,4 +9,6 @@ export const auth = {
|
|||
deleted: ['role::deleteRole'],
|
||||
// 为角色分配权限
|
||||
assignPowersToRole: ['rolePower::assignPowersToRole'],
|
||||
// 下载角色配置
|
||||
downloadRole: ['role::downloadRole'],
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { computed, reactive } from 'vue';
|
||||
import { $t } from '@/plugins/i18n';
|
||||
import { computed, reactive } from 'vue';
|
||||
|
||||
// 表格列
|
||||
export const columns: TableColumnList = [
|
||||
|
|
|
@ -58,10 +58,7 @@ export function onAdd() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* * 更新角色
|
||||
* @param row
|
||||
*/
|
||||
/* 更新角色 */
|
||||
export function onUpdate(row: any) {
|
||||
addDialog({
|
||||
title: `${$t('modify')}${$t('role')}`,
|
||||
|
|
Loading…
Reference in New Issue