Compare commits
6 Commits
main_beta
...
09a300e98a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
09a300e98a | ||
|
|
7a496e6407 | ||
| e69cffbdb6 | |||
|
|
bcac3326a3 | ||
| f9393dfca8 | |||
| 67fe2e22fc |
@@ -17,21 +17,6 @@ export interface UpdateStatusReqVO {
|
|||||||
status: number
|
status: number
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取登陆用户的应用
|
|
||||||
export const getMyPage = async (params: PageParam) => {
|
|
||||||
return await request.get({ url: '/system/oauth2-client/myPage', params })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取角色下的应用id
|
|
||||||
export const getRoleAppIds = async (roleId: number) => {
|
|
||||||
return await request.get({ url: '/system/permission/list-role-clients?roleId=' + roleId })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增角色
|
|
||||||
export const saveApp = async (data: any) => {
|
|
||||||
return await request.post({ url: '/system/permission/assign-role-client', data })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询角色列表
|
// 查询角色列表
|
||||||
export const getRolePage = async (params: PageParam) => {
|
export const getRolePage = async (params: PageParam) => {
|
||||||
return await request.get({ url: '/system/role/page', params })
|
return await request.get({ url: '/system/role/page', params })
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
></InputTimeRange>
|
></InputTimeRange>
|
||||||
</template>
|
</template>
|
||||||
<template #header v-if="Object.keys(dimensionFields)?.length">
|
<template #header v-if="Object.keys(dimensionFields)?.length">
|
||||||
<div style="display:flex;margin-left:40px">
|
<div style="display:flex;margin-left:40px">
|
||||||
<el-checkbox-group @change="searchDimension" v-model="tableSearch['Group by']"
|
<el-checkbox-group @change="searchDimension" v-model="tableSearch['Group by']"
|
||||||
placeholder="请选择内容">
|
placeholder="请选择内容">
|
||||||
<template v-for="(item,key) in dimensionFields">
|
<template v-for="(item,key) in dimensionFields">
|
||||||
@@ -128,6 +128,7 @@ const tableInfo = ref<any>({})
|
|||||||
const timerObj = ref<any>({})
|
const timerObj = ref<any>({})
|
||||||
const numberRange = ref<string[]>([])
|
const numberRange = ref<string[]>([])
|
||||||
const dateRange=ref<string[]>([])
|
const dateRange=ref<string[]>([])
|
||||||
|
const hideColumns=ref<string[]>([])
|
||||||
const dateTimeRange=ref<string[]>([])
|
const dateTimeRange=ref<string[]>([])
|
||||||
const timeRange=ref<string[]>([])
|
const timeRange=ref<string[]>([])
|
||||||
const amountFieds=ref<any>({})
|
const amountFieds=ref<any>({})
|
||||||
@@ -136,6 +137,7 @@ const crudRef = ref()
|
|||||||
const dimensionFields=ref<any>({})
|
const dimensionFields=ref<any>({})
|
||||||
const exportLoading = ref(false)
|
const exportLoading = ref(false)
|
||||||
const fieldList = ref<any[]>([]) // 添加fieldList引用
|
const fieldList = ref<any[]>([]) // 添加fieldList引用
|
||||||
|
const hideFeilds= ref<any>({})
|
||||||
const permissions =
|
const permissions =
|
||||||
wsCache.get(CACHE_KEY.USER).lideeYunjipermissions?.[route.meta.menuDataId as string] || false
|
wsCache.get(CACHE_KEY.USER).lideeYunjipermissions?.[route.meta.menuDataId as string] || false
|
||||||
const selectIds = computed(() => {
|
const selectIds = computed(() => {
|
||||||
@@ -177,6 +179,7 @@ const initTable = async () => {
|
|||||||
const isPage = reportVo.dataConfig?.includes('page')
|
const isPage = reportVo.dataConfig?.includes('page')
|
||||||
const isPermi = reportVo.dataConfig?.includes('authTrue')
|
const isPermi = reportVo.dataConfig?.includes('authTrue')
|
||||||
const isHideExport = reportVo.tableConfig?.includes('hideExport')
|
const isHideExport = reportVo.tableConfig?.includes('hideExport')
|
||||||
|
hideColumns.value=[]
|
||||||
tableInfo.value = { ...reportVo, isPage, isHeight, isPermi, isHideExport }
|
tableInfo.value = { ...reportVo, isPage, isHeight, isPermi, isHideExport }
|
||||||
tableOption.value = {
|
tableOption.value = {
|
||||||
selection: !isHideExport,
|
selection: !isHideExport,
|
||||||
@@ -258,8 +261,12 @@ const initTable = async () => {
|
|||||||
}
|
}
|
||||||
if(item.isDimension=='Y'){
|
if(item.isDimension=='Y'){
|
||||||
dimensionFields.value[config.prop]=config
|
dimensionFields.value[config.prop]=config
|
||||||
|
hideFeilds.value[config.prop]=item.isHideDimension
|
||||||
|
}
|
||||||
|
if(item.isHideCol == 'Y') {
|
||||||
|
config.hide = true
|
||||||
|
hideColumns.value.push( config.prop )
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.queryMode == 'RANGE') config.searchRange = true
|
if (item.queryMode == 'RANGE') config.searchRange = true
|
||||||
if (['Integer', 'BigInt', 'BigDecimal'].includes(item.fieldType)) config.type = 'number'
|
if (['Integer', 'BigInt', 'BigDecimal'].includes(item.fieldType)) config.type = 'number'
|
||||||
else if (item.fieldType == 'Date') {
|
else if (item.fieldType == 'Date') {
|
||||||
@@ -301,6 +308,7 @@ const initTable = async () => {
|
|||||||
initTableLayout()
|
initTableLayout()
|
||||||
}
|
}
|
||||||
const searchDimension=()=>{
|
const searchDimension=()=>{
|
||||||
|
|
||||||
searchChange()
|
searchChange()
|
||||||
}
|
}
|
||||||
const initTableLayout = () => {
|
const initTableLayout = () => {
|
||||||
@@ -467,6 +475,15 @@ const clearSearch = () => {
|
|||||||
const searchChange = (params?, done?) => {
|
const searchChange = (params?, done?) => {
|
||||||
if (tablePage.value) tablePage.value['currentPage'] = 1
|
if (tablePage.value) tablePage.value['currentPage'] = 1
|
||||||
getTableData().finally(() => {
|
getTableData().finally(() => {
|
||||||
|
let field=tableSearch.value['Group by']
|
||||||
|
let hides=[]
|
||||||
|
if(field.length){
|
||||||
|
hides=Object.keys(hideFeilds.value).length?hideFeilds.value[field].split(','):[]
|
||||||
|
}
|
||||||
|
Object.keys(tableOption.value.column).forEach(key=>{
|
||||||
|
let item=tableOption.value.column[key]
|
||||||
|
item.hide=hides.includes(item.prop)||hideColumns.value.includes(item.prop)
|
||||||
|
})
|
||||||
if (done) done()
|
if (done) done()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export default {
|
|||||||
noPermission: `抱歉,您无权访问此页面。`,
|
noPermission: `抱歉,您无权访问此页面。`,
|
||||||
pageError: '抱歉,您访问的页面不存在。',
|
pageError: '抱歉,您访问的页面不存在。',
|
||||||
networkError: '抱歉,服务器报告错误。',
|
networkError: '抱歉,服务器报告错误。',
|
||||||
returnToHome: '返回首页'
|
returnToHome: '返回工作台'
|
||||||
},
|
},
|
||||||
permission: {
|
permission: {
|
||||||
hasPermission: `请设置操作权限标签值`,
|
hasPermission: `请设置操作权限标签值`,
|
||||||
@@ -157,7 +157,7 @@ export default {
|
|||||||
router: {
|
router: {
|
||||||
login: '登录',
|
login: '登录',
|
||||||
socialLogin: '社交登录',
|
socialLogin: '社交登录',
|
||||||
home: '首页',
|
home: '工作台',
|
||||||
analysis: '分析页',
|
analysis: '分析页',
|
||||||
workplace: '工作台'
|
workplace: '工作台'
|
||||||
},
|
},
|
||||||
@@ -275,7 +275,7 @@ export default {
|
|||||||
},
|
},
|
||||||
exception: {
|
exception: {
|
||||||
backLogin: '返回登录',
|
backLogin: '返回登录',
|
||||||
backHome: '返回首页',
|
backHome: '返回工作台',
|
||||||
subTitle403: '抱歉,您无权访问此页面。',
|
subTitle403: '抱歉,您无权访问此页面。',
|
||||||
subTitle404: '抱歉,您访问的页面不存在。',
|
subTitle404: '抱歉,您访问的页面不存在。',
|
||||||
subTitle500: '抱歉,服务器报告错误。',
|
subTitle500: '抱歉,服务器报告错误。',
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ v-for="(category, categoryName) in filteredCategories"
|
|||||||
|
|
||||||
<div class="apps-grid">
|
<div class="apps-grid">
|
||||||
<div
|
<div
|
||||||
v-for="app in category.apps"
|
v-for="app in category.apps"
|
||||||
:key="app.id"
|
:key="app.id"
|
||||||
class="app-card"
|
class="app-card"
|
||||||
@click="handleAppClick(app)">
|
@click="handleAppClick(app)">
|
||||||
@@ -77,7 +77,7 @@ v-for="(category, categoryName) in filteredCategories"
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as RoleApi from '@/api/system/role'
|
import * as ClientApi from '@/api/system/oauth2/client'
|
||||||
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
|
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
|
||||||
export default {
|
export default {
|
||||||
name: 'AppManager',
|
name: 'AppManager',
|
||||||
@@ -138,7 +138,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
async fetchApps() {
|
async fetchApps() {
|
||||||
try {
|
try {
|
||||||
const data = await RoleApi.getMyPage({ pageNo: 1, pageSize: 1000 })
|
const data = await ClientApi.getOAuth2ClientPage({ pageNo: 1, pageSize: 1000 })
|
||||||
const list = data?.list || []
|
const list = data?.list || []
|
||||||
this.appsData = list.map(item => ({
|
this.appsData = list.map(item => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
|||||||
@@ -183,6 +183,43 @@ export const useRenderVxeColumn = (useType = 'table') => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
LowSelectMultiple: {
|
||||||
|
default: (renderOpts, { row, column }, isStop = false) => {
|
||||||
|
const { dicData } = renderOpts
|
||||||
|
const value = row[column.field]
|
||||||
|
const valStr=dicData.filter(item=>value.includes(item.value)).map(item=>item.label).join(',')
|
||||||
|
return <span>{valStr}</span>
|
||||||
|
},
|
||||||
|
edit: (renderOpts, { row, rowIndex, column }) => {
|
||||||
|
const { multiple, filterable, allowCreate, typeKey ,dicData} = renderOpts
|
||||||
|
interface DictItem {
|
||||||
|
label: string;
|
||||||
|
value: string | number;
|
||||||
|
[key: string]: any; // 兼容其他可能的字段
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<el-select
|
||||||
|
popper-class="vxe-table--ignore-clear"
|
||||||
|
v-model={row[column.field]}
|
||||||
|
placeholder={'请选择 ' + column.title}
|
||||||
|
multiple={multiple}
|
||||||
|
filterable={filterable}
|
||||||
|
collapseTags={true}
|
||||||
|
collapseTagsTooltip={true}
|
||||||
|
allowCreate={allowCreate}
|
||||||
|
clearable={true}
|
||||||
|
>
|
||||||
|
{dicData.map((item: DictItem, index: number) => (
|
||||||
|
<el-option
|
||||||
|
key={index} // 建议用 item.value 作为 key,更稳定
|
||||||
|
label={item.label}
|
||||||
|
value={item.value}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</el-select>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
LowSummaryBottomSql: {
|
LowSummaryBottomSql: {
|
||||||
default: (renderOpts, { row, column }, isStop = false) => {
|
default: (renderOpts, { row, column }, isStop = false) => {
|
||||||
const { dicObj } = renderOpts
|
const { dicObj } = renderOpts
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ const parentFieldMap = ref(new Map())
|
|||||||
const fieldList = computed(() => {
|
const fieldList = computed(() => {
|
||||||
let dicData: Array<{ label: string; value: string; type: string }> = []
|
let dicData: Array<{ label: string; value: string; type: string }> = []
|
||||||
infoData.value.basics.forEach((item) => {
|
infoData.value.basics.forEach((item) => {
|
||||||
|
|
||||||
if (item.fieldCode && item.isDb == 'Y')
|
if (item.fieldCode && item.isDb == 'Y')
|
||||||
dicData.push({
|
dicData.push({
|
||||||
label: `${item.fieldCode}${item.fieldName ? '(' + item.fieldName + ')' : ''}`,
|
label: `${item.fieldCode}${item.fieldName ? '(' + item.fieldName + ')' : ''}`,
|
||||||
@@ -257,7 +258,9 @@ const initEditInfoData = () => {
|
|||||||
if (fieldItem.hasChildren === 'Y') {
|
if (fieldItem.hasChildren === 'Y') {
|
||||||
fieldItem.hasChildren = 'Y'
|
fieldItem.hasChildren = 'Y'
|
||||||
}
|
}
|
||||||
|
if (!!fieldItem.isHideDimension&&Object.prototype.toString.call(fieldItem.isHideDimension) == '[object String]') {
|
||||||
|
fieldItem.isHideDimension=fieldItem.isHideDimension.split(',')
|
||||||
|
}
|
||||||
fieldList.push(fieldItem)
|
fieldList.push(fieldItem)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -282,7 +285,9 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tableInfoOption.infoColumn.fieldColumn.isHideDimension.editRender.dicData = infoData.value.basics.map(({fieldCode,fieldName})=>{
|
||||||
|
return {label:fieldName,value:fieldCode}
|
||||||
|
})
|
||||||
// 设置父字段下拉选项
|
// 设置父字段下拉选项
|
||||||
const updateParentFieldOptions = () => {
|
const updateParentFieldOptions = () => {
|
||||||
// 获取所有parentFieldCode为空的字段作为可选父字段
|
// 获取所有parentFieldCode为空的字段作为可选父字段
|
||||||
|
|||||||
@@ -157,9 +157,11 @@ const infoColumn = {
|
|||||||
queryMode: { title: '查询模式', width: 130, editRender: { name: 'LowSelect', verifyEdit: true, dicData: dicObj.queryMode, dicObj: getDicObj('queryMode') } },
|
queryMode: { title: '查询模式', width: 130, editRender: { name: 'LowSelect', verifyEdit: true, dicData: dicObj.queryMode, dicObj: getDicObj('queryMode') } },
|
||||||
dictCode: { title: '字典Code', width: 180, editRender: { name: 'LowSelect', verifyEdit: true, filterable: true, noStop: true, dicData: [] } },
|
dictCode: { title: '字典Code', width: 180, editRender: { name: 'LowSelect', verifyEdit: true, filterable: true, noStop: true, dicData: [] } },
|
||||||
isExport: { title: '是否可导出', width: 90, align: "center", editRender: { name: 'LowCheckbox' } },
|
isExport: { title: '是否可导出', width: 90, align: "center", editRender: { name: 'LowCheckbox' } },
|
||||||
|
isHideCol: { title: '隐藏列', width: 90, align: "center", editRender: { name: 'LowCheckbox' } },
|
||||||
isAmount: { title: '是否合计', width: 75, align: "center", editRender: { name: 'LowCheckboxSum' } },
|
isAmount: { title: '是否合计', width: 75, align: "center", editRender: { name: 'LowCheckboxSum' } },
|
||||||
isDimension: { title: '是否维度', width: 75, align: "center", editRender: { name: 'LowCheckbox' } },
|
isDimension: { title: '是否维度', width: 75, align: "center", editRender: { name: 'LowCheckbox' } },
|
||||||
|
|
||||||
|
isHideDimension: { title: '维度隐藏列', width: 180, editRender: { name: 'LowSelectMultiple', verifyEdit: true, filterable: true, multiple:true,dicData: [] } },
|
||||||
isShowSort: { title: '是否排序', width: 75, align: "center", editRender: { name: 'LowCheckbox' } },
|
isShowSort: { title: '是否排序', width: 75, align: "center", editRender: { name: 'LowCheckbox' } },
|
||||||
hasChildren: { title: '子字段', width: 90, align: "center", editRender: { name: 'LowButton', disabled: (row) => row.isSubField === true, buttonText: '添加子字段', buttonType: 'primary', buttonSize: 'small' } },
|
hasChildren: { title: '子字段', width: 90, align: "center", editRender: { name: 'LowButton', disabled: (row) => row.isSubField === true, buttonText: '添加子字段', buttonType: 'primary', buttonSize: 'small' } },
|
||||||
},
|
},
|
||||||
@@ -187,7 +189,7 @@ for (const key in infoColumn) {
|
|||||||
//默认值
|
//默认值
|
||||||
const infoDefaultData = {
|
const infoDefaultData = {
|
||||||
basics: {
|
basics: {
|
||||||
fieldCode: '', fieldName: '', parentFieldName: '', labelI18n: '', fieldType: 'String', queryIsDb: 'N', queryIsWeb: 'N', queryMode: 'LIKE', dictCode: '', isExport: 'Y', isShowSort: 'N', isAmount: '', isDimension: '', hasChildren: 'N', isSubField: false, parentFieldId: '', parentFieldCode: '',
|
fieldCode: '', fieldName: '', parentFieldName: '', labelI18n: '', fieldType: 'String', queryIsDb: 'N', queryIsWeb: 'N', queryMode: 'LIKE', dictCode: '',isHideCol:'N', isExport: 'Y', isShowSort: 'N', isAmount: '', isDimension: '',isHideDimension:'', hasChildren: 'N', isSubField: false, parentFieldId: '', parentFieldCode: '',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ const tableFormVerify = (type) => {
|
|||||||
const index = Number(i)
|
const index = Number(i)
|
||||||
const item = filedData[index]
|
const item = filedData[index]
|
||||||
item.sortNum = index + 1
|
item.sortNum = index + 1
|
||||||
|
item.isHideDimension?item.isHideDimension=item.isHideDimension.join(','):''
|
||||||
let messageText = ''
|
let messageText = ''
|
||||||
let tabKey = 'mysql'
|
let tabKey = 'mysql'
|
||||||
// 子字段不能再包含子字段
|
// 子字段不能再包含子字段
|
||||||
|
|||||||
@@ -1,233 +0,0 @@
|
|||||||
<template>
|
|
||||||
<DesignPopup v-model="dialogVisible" title="应用权限" :is-footer="true" width="40%">
|
|
||||||
<div class="p-20px">
|
|
||||||
<el-form ref="formRef" v-loading="formLoading" :model="formData" label-width="80px">
|
|
||||||
<el-form-item label="角色名称">
|
|
||||||
<el-tag>{{ formData.name }}</el-tag>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="角色标识">
|
|
||||||
<el-tag>{{ formData.code }}</el-tag>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="应用权限">
|
|
||||||
<el-card class="w-full h-400px !overflow-y-scroll" shadow="never">
|
|
||||||
<template #header>
|
|
||||||
全选/全不选:
|
|
||||||
<el-switch
|
|
||||||
v-model="treeNodeAll"
|
|
||||||
active-text="是"
|
|
||||||
inactive-text="否"
|
|
||||||
inline-prompt
|
|
||||||
@change="handleCheckedTreeNodeAll"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<!-- 修复:移除未使用的node变量,优化无子集Tree展示 -->
|
|
||||||
<el-tree
|
|
||||||
ref="treeRef"
|
|
||||||
:data="appOptions"
|
|
||||||
:props="{ label: 'name', children: 'children' }"
|
|
||||||
empty-text="暂无应用数据"
|
|
||||||
node-key="id"
|
|
||||||
show-checkbox
|
|
||||||
check-strictly
|
|
||||||
v-loading="tableLoading"
|
|
||||||
class="app-tree-list"
|
|
||||||
:indent="0"
|
|
||||||
>
|
|
||||||
<!-- 修复:只解构使用到的data,删除未使用的node -->
|
|
||||||
<template #default="{ data }">
|
|
||||||
<div class="app-tree-node">
|
|
||||||
<span class="node-name">{{ data.name }}</span>
|
|
||||||
<span class="node-clientId">客户端ID:{{ data.clientId }}</span>
|
|
||||||
<span class="node-status">
|
|
||||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="data.status" />
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-tree>
|
|
||||||
</el-card>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
|
||||||
</template>
|
|
||||||
</DesignPopup>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { DICT_TYPE } from '@/utils/dict'
|
|
||||||
import * as RoleApi from '@/api/system/role'
|
|
||||||
|
|
||||||
defineOptions({ name: 'SystemRoleAssignAppForm' })
|
|
||||||
|
|
||||||
const { t } = useI18n()
|
|
||||||
const message = useMessage()
|
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const formLoading = ref(false)
|
|
||||||
const tableLoading = ref(false)
|
|
||||||
const formData = ref({
|
|
||||||
id: 0,
|
|
||||||
name: '',
|
|
||||||
code: '',
|
|
||||||
clientIds: [] as number[]
|
|
||||||
})
|
|
||||||
const formRef = ref()
|
|
||||||
const treeRef = ref()
|
|
||||||
const appOptions = ref<any[]>([])
|
|
||||||
const treeNodeAll = ref(false)
|
|
||||||
|
|
||||||
// 优化Tree配置:明确指定无children,纯列表展示
|
|
||||||
const treeProps = {
|
|
||||||
label: 'name',
|
|
||||||
children: () => [] // 强制返回空数组,彻底避免树形层级
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 打开弹窗 */
|
|
||||||
const open = async (row: RoleApi.RoleVO) => {
|
|
||||||
dialogVisible.value = true
|
|
||||||
formLoading.value = true
|
|
||||||
resetForm()
|
|
||||||
// 设置角色信息
|
|
||||||
formData.value.id = row.id
|
|
||||||
formData.value.name = row.name
|
|
||||||
formData.value.code = row.code
|
|
||||||
try {
|
|
||||||
// 加载应用列表(pageSize=99,模拟不分页)
|
|
||||||
await getAppList()
|
|
||||||
// 获取当前角色已有的应用ID
|
|
||||||
const roleAppIds = await RoleApi.getRoleAppIds(row.id)
|
|
||||||
formData.value.clientIds = roleAppIds
|
|
||||||
// 设置Tree选中状态
|
|
||||||
await nextTick()
|
|
||||||
treeRef.value?.setCheckedNodes([])
|
|
||||||
formData.value.clientIds.forEach(id => {
|
|
||||||
treeRef.value?.setChecked(id, true, false)
|
|
||||||
})
|
|
||||||
} finally {
|
|
||||||
formLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defineExpose({ open })
|
|
||||||
|
|
||||||
/** 获取应用列表(固定pageSize=99,不分页) */
|
|
||||||
const getAppList = async () => {
|
|
||||||
tableLoading.value = true
|
|
||||||
try {
|
|
||||||
const data = await RoleApi.getMyPage({
|
|
||||||
pageNo: 1,
|
|
||||||
pageSize: 99 // 设为99,覆盖大部分场景的数量,模拟不分页
|
|
||||||
})
|
|
||||||
// 优化:确保返回数据绝对没有children字段,避免树形展示
|
|
||||||
appOptions.value = data.list.map(item => {
|
|
||||||
const { children, ...rest } = item // 移除可能存在的children字段
|
|
||||||
return { ...rest, children: [] } // 强制设置空children
|
|
||||||
})
|
|
||||||
} finally {
|
|
||||||
tableLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 全选/全不选(适配Tree组件) */
|
|
||||||
const handleCheckedTreeNodeAll = () => {
|
|
||||||
if (treeNodeAll.value) {
|
|
||||||
// 全选:选中所有节点
|
|
||||||
treeRef.value?.setCheckedNodes(appOptions.value)
|
|
||||||
formData.value.clientIds = appOptions.value.map(item => item.id)
|
|
||||||
} else {
|
|
||||||
// 全不选:清空选中
|
|
||||||
treeRef.value?.setCheckedNodes([])
|
|
||||||
formData.value.clientIds = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 提交表单 */
|
|
||||||
const emit = defineEmits(['success'])
|
|
||||||
const submitForm = async () => {
|
|
||||||
if (!formRef) return
|
|
||||||
const valid = await formRef.value.validate()
|
|
||||||
if (!valid) return
|
|
||||||
formLoading.value = true
|
|
||||||
try {
|
|
||||||
// 获取Tree选中的节点ID
|
|
||||||
formData.value.clientIds = treeRef.value?.getCheckedKeys(false) as number[]
|
|
||||||
const data = {
|
|
||||||
roleId: formData.value.id,
|
|
||||||
clientIds: formData.value.clientIds
|
|
||||||
}
|
|
||||||
await RoleApi.saveApp(data)
|
|
||||||
message.success(t('common.updateSuccess'))
|
|
||||||
dialogVisible.value = false
|
|
||||||
emit('success')
|
|
||||||
} finally {
|
|
||||||
formLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置表单 */
|
|
||||||
const resetForm = () => {
|
|
||||||
treeNodeAll.value = false
|
|
||||||
formData.value = {
|
|
||||||
id: 0,
|
|
||||||
name: '',
|
|
||||||
code: '',
|
|
||||||
clientIds: []
|
|
||||||
}
|
|
||||||
appOptions.value = []
|
|
||||||
treeRef.value?.setCheckedNodes([])
|
|
||||||
formRef.value?.resetFields()
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
// 自定义Tree节点样式,模拟表格列布局
|
|
||||||
.app-tree-list {
|
|
||||||
::v-deep(.el-tree-node) {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
border-bottom: 1px solid #f5f7fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep(.el-tree-node__content) {
|
|
||||||
padding: 0 10px;
|
|
||||||
height: 40px !important;
|
|
||||||
// 移除树形节点的默认图标
|
|
||||||
.el-tree-node__expand-icon {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep(.el-tree-node__children) {
|
|
||||||
padding-left: 0 !important; // 彻底去掉子节点缩进
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 节点内容布局
|
|
||||||
.app-tree-node {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
.node-name {
|
|
||||||
flex: 0 0 120px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.node-clientId {
|
|
||||||
flex: 0 0 150px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
.node-status {
|
|
||||||
flex: 0 0 80px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 卡片样式优化
|
|
||||||
::v-deep(.el-card__header) {
|
|
||||||
padding: 10px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep(.el-card__body) {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -58,15 +58,6 @@
|
|||||||
<span>菜单权限</span>
|
<span>菜单权限</span>
|
||||||
</div>
|
</div>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item
|
|
||||||
:command="{ type: 'app', row }"
|
|
||||||
v-if="checkPermi(['system:permission:assign-role-app'])"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<Icon icon="ep:menu" />
|
|
||||||
<span>应用权限</span>
|
|
||||||
</div>
|
|
||||||
</el-dropdown-item>
|
|
||||||
<el-dropdown-item
|
<el-dropdown-item
|
||||||
:command="{ type: 'data', row }"
|
:command="{ type: 'data', row }"
|
||||||
v-if="checkPermi(['system:permission:assign-role-data-scope'])"
|
v-if="checkPermi(['system:permission:assign-role-data-scope'])"
|
||||||
@@ -95,8 +86,6 @@
|
|||||||
<RoleAssignMenuForm ref="assignMenuFormRef" @success="getTableData" />
|
<RoleAssignMenuForm ref="assignMenuFormRef" @success="getTableData" />
|
||||||
<!-- 表单弹窗:数据权限 -->
|
<!-- 表单弹窗:数据权限 -->
|
||||||
<RoleDataPermissionForm ref="dataPermissionFormRef" @success="getTableData" />
|
<RoleDataPermissionForm ref="dataPermissionFormRef" @success="getTableData" />
|
||||||
<!-- 表单弹窗:应用权限 -->
|
|
||||||
<RoleAssignAppForm ref="assignAppFormRef" @success="getTableData" />
|
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
@@ -107,7 +96,6 @@ import * as RoleApi from '@/api/system/role'
|
|||||||
import { CommonStatusEnum } from '@/utils/constants'
|
import { CommonStatusEnum } from '@/utils/constants'
|
||||||
import RoleAssignMenuForm from './RoleAssignMenuForm.vue'
|
import RoleAssignMenuForm from './RoleAssignMenuForm.vue'
|
||||||
import RoleDataPermissionForm from './RoleDataPermissionForm.vue'
|
import RoleDataPermissionForm from './RoleDataPermissionForm.vue'
|
||||||
import RoleAssignAppForm from './RoleAssignAppForm.vue'
|
|
||||||
|
|
||||||
defineOptions({ name: 'SystemRole' })
|
defineOptions({ name: 'SystemRole' })
|
||||||
|
|
||||||
@@ -198,7 +186,7 @@ const tablePage = ref({
|
|||||||
total: 0
|
total: 0
|
||||||
})
|
})
|
||||||
const permission = getCurrPermi(['system:role'])
|
const permission = getCurrPermi(['system:role'])
|
||||||
const assignAppFormRef = ref()
|
|
||||||
const crudRef = ref()
|
const crudRef = ref()
|
||||||
|
|
||||||
useCrudHeight(crudRef)
|
useCrudHeight(crudRef)
|
||||||
@@ -209,11 +197,6 @@ const menuHandle = ({ row, type }) => {
|
|||||||
if (type == 'menu') openAssignMenuForm(row)
|
if (type == 'menu') openAssignMenuForm(row)
|
||||||
else if (type == 'data') openDataPermissionForm(row)
|
else if (type == 'data') openDataPermissionForm(row)
|
||||||
else if (type == 'del') rowDel(row)
|
else if (type == 'del') rowDel(row)
|
||||||
else if (type == 'app') openAssignAppForm(row)
|
|
||||||
}
|
|
||||||
|
|
||||||
const openAssignAppForm = (row) => {
|
|
||||||
assignAppFormRef.value.open(row)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
|
|||||||
Reference in New Issue
Block a user