fetch(modify):修改账号列表中的分配角色弹窗
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m33s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m33s
This commit is contained in:
@@ -422,7 +422,7 @@
|
||||
"agent": "代理商管理",
|
||||
"customerAccount": "客户账号",
|
||||
"enterpriseCustomer": "企业客户",
|
||||
"enterpriseCustomerAccounts": "企业客户账号列表",
|
||||
"enterpriseCustomerAccounts": "客户账号列表",
|
||||
"enterpriseCards": "企业卡管理",
|
||||
"customerCommission": "客户账号佣金"
|
||||
},
|
||||
|
||||
@@ -82,27 +82,107 @@
|
||||
</ElDialog>
|
||||
|
||||
<!-- 分配角色对话框 -->
|
||||
<ElDialog v-model="roleDialogVisible" title="分配角色" width="500px">
|
||||
<ElCheckboxGroup v-model="selectedRoles">
|
||||
<div v-for="role in allRoles" :key="role.id" style="margin-bottom: 12px">
|
||||
<ElCheckbox :value="role.id">
|
||||
{{ role.role_name }}
|
||||
<ElTag
|
||||
:type="role.role_type === 1 ? 'primary' : 'success'"
|
||||
size="small"
|
||||
style="margin-left: 8px"
|
||||
>
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</ElCheckbox>
|
||||
<ElDialog v-model="roleDialogVisible" width="900px">
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span class="dialog-title">分配角色</span>
|
||||
<div class="account-info">
|
||||
<span class="account-name">{{ currentAccountName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</ElCheckboxGroup>
|
||||
</template>
|
||||
<div class="role-transfer-container">
|
||||
<!-- 左侧:可分配角色列表 -->
|
||||
<div class="transfer-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-title">可分配角色</span>
|
||||
<ElInput
|
||||
v-model="leftRoleFilter"
|
||||
placeholder="搜索角色"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ElCheckboxGroup v-model="rolesToAdd" class="role-list">
|
||||
<div
|
||||
v-for="role in filteredAvailableRoles"
|
||||
:key="role.ID"
|
||||
class="role-item"
|
||||
>
|
||||
<ElCheckbox :label="role.ID" :disabled="selectedRoles.includes(role.ID)">
|
||||
<span class="role-info">
|
||||
<span>{{ role.role_name }}</span>
|
||||
<ElTag
|
||||
:type="role.role_type === 1 ? 'primary' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
</ElCheckbox>
|
||||
</div>
|
||||
</ElCheckboxGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间:操作按钮 -->
|
||||
<div class="transfer-buttons">
|
||||
<ElButton
|
||||
type="primary"
|
||||
:icon="'ArrowRight'"
|
||||
@click="addRoles"
|
||||
:disabled="rolesToAdd.length === 0"
|
||||
>
|
||||
添加
|
||||
</ElButton>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:已分配角色列表 -->
|
||||
<div class="transfer-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-title">已分配角色</span>
|
||||
<ElInput
|
||||
v-model="rightRoleFilter"
|
||||
placeholder="搜索角色"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="role-list">
|
||||
<div
|
||||
v-for="role in filteredAssignedRoles"
|
||||
:key="role.ID"
|
||||
class="role-item assigned-role-item"
|
||||
>
|
||||
<span class="role-info">
|
||||
<span>{{ role.role_name }}</span>
|
||||
<ElTag
|
||||
:type="role.role_type === 1 ? 'primary' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
<ElButton
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="removeSingleRole(role.ID)"
|
||||
>
|
||||
移除
|
||||
</ElButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="roleDialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleAssignRoles" :loading="roleSubmitLoading"
|
||||
>提交</ElButton
|
||||
>
|
||||
<ElButton @click="roleDialogVisible = false">关闭</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
@@ -122,7 +202,7 @@
|
||||
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
|
||||
import { AccountService } from '@/api/modules/account'
|
||||
import { RoleService } from '@/api/modules/role'
|
||||
import { ShopService } from '@/api/modules'
|
||||
import { ShopService, EnterpriseService } from '@/api/modules'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import type { PlatformRole } from '@/types/api'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
@@ -139,8 +219,12 @@
|
||||
const loading = ref(false)
|
||||
const roleSubmitLoading = ref(false)
|
||||
const currentAccountId = ref<number>(0)
|
||||
const currentAccountName = ref<string>('')
|
||||
const selectedRoles = ref<number[]>([])
|
||||
const allRoles = ref<PlatformRole[]>([])
|
||||
const rolesToAdd = ref<number[]>([])
|
||||
const leftRoleFilter = ref('')
|
||||
const rightRoleFilter = ref('')
|
||||
|
||||
// 定义表单搜索初始值
|
||||
const initialSearchState = {
|
||||
@@ -239,6 +323,22 @@
|
||||
placeholder: '请输入店铺名称搜索'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '关联企业',
|
||||
prop: 'enterprise_id',
|
||||
type: 'select',
|
||||
options: enterpriseList.value.map((enterprise) => ({
|
||||
label: enterprise.enterprise_name,
|
||||
value: enterprise.id
|
||||
})),
|
||||
config: {
|
||||
clearable: true,
|
||||
filterable: true,
|
||||
remote: true,
|
||||
remoteMethod: handleEnterpriseSearch,
|
||||
placeholder: '请输入企业名称搜索'
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
@@ -436,6 +536,7 @@
|
||||
getAccountList()
|
||||
loadAllRoles()
|
||||
loadShopList()
|
||||
loadEnterpriseList()
|
||||
})
|
||||
|
||||
// 加载所有角色列表
|
||||
@@ -450,10 +551,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 计算属性:过滤后的可分配角色
|
||||
const filteredAvailableRoles = computed(() => {
|
||||
if (!leftRoleFilter.value) return allRoles.value
|
||||
const keyword = leftRoleFilter.value.toLowerCase()
|
||||
return allRoles.value.filter((role) => role.role_name.toLowerCase().includes(keyword))
|
||||
})
|
||||
|
||||
// 计算属性:过滤后的已分配角色
|
||||
const filteredAssignedRoles = computed(() => {
|
||||
const assignedRolesList = allRoles.value.filter((role) => selectedRoles.value.includes(role.ID))
|
||||
if (!rightRoleFilter.value) return assignedRolesList
|
||||
const keyword = rightRoleFilter.value.toLowerCase()
|
||||
return assignedRolesList.filter((role) => role.role_name.toLowerCase().includes(keyword))
|
||||
})
|
||||
|
||||
// 显示分配角色对话框
|
||||
const showRoleDialog = async (row: any) => {
|
||||
currentAccountId.value = row.id
|
||||
currentAccountName.value = row.username
|
||||
selectedRoles.value = []
|
||||
rolesToAdd.value = []
|
||||
leftRoleFilter.value = ''
|
||||
rightRoleFilter.value = ''
|
||||
|
||||
try {
|
||||
// 每次打开对话框时重新加载最新的角色列表
|
||||
@@ -464,7 +584,8 @@
|
||||
if (res.code === 0) {
|
||||
// 提取角色ID数组
|
||||
const roles = res.data || []
|
||||
selectedRoles.value = roles.map((role: any) => role.id)
|
||||
// 兼容 ID 和 id 两种字段名
|
||||
selectedRoles.value = roles.map((role: any) => role.ID || role.id)
|
||||
// 数据加载完成后再打开对话框
|
||||
roleDialogVisible.value = true
|
||||
}
|
||||
@@ -473,19 +594,41 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 提交分配角色
|
||||
const handleAssignRoles = async () => {
|
||||
roleSubmitLoading.value = true
|
||||
// 批量添加角色
|
||||
const addRoles = async () => {
|
||||
if (rolesToAdd.value.length === 0) return
|
||||
|
||||
try {
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, selectedRoles.value)
|
||||
ElMessage.success('分配角色成功')
|
||||
roleDialogVisible.value = false
|
||||
// 将选中的角色添加到已分配列表
|
||||
const newRoles = [...new Set([...selectedRoles.value, ...rolesToAdd.value])]
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, newRoles)
|
||||
|
||||
selectedRoles.value = newRoles
|
||||
rolesToAdd.value = []
|
||||
|
||||
ElMessage.success('角色添加成功')
|
||||
// 刷新列表以更新角色显示
|
||||
await getAccountList()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
roleSubmitLoading.value = false
|
||||
console.error('添加角色失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 移除单个角色
|
||||
const removeSingleRole = async (roleId: number) => {
|
||||
try {
|
||||
// 从已分配列表中移除该角色
|
||||
const newRoles = selectedRoles.value.filter((id) => id !== roleId)
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, newRoles)
|
||||
|
||||
selectedRoles.value = newRoles
|
||||
|
||||
ElMessage.success('角色移除成功')
|
||||
// 刷新列表以更新角色显示
|
||||
await getAccountList()
|
||||
} catch (error) {
|
||||
console.error('移除角色失败:', error)
|
||||
ElMessage.error('角色移除失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,10 +763,156 @@
|
||||
const handleShopSearch = (query: string) => {
|
||||
loadShopList(query)
|
||||
}
|
||||
|
||||
// 加载企业列表
|
||||
const loadEnterpriseList = async (keyword: string = '') => {
|
||||
try {
|
||||
const res = await EnterpriseService.getEnterprises({
|
||||
page: 1,
|
||||
page_size: 20, // 默认加载20条
|
||||
status: 1, // 只加载启用的企业
|
||||
enterprise_name: keyword || undefined // 根据企业名称搜索
|
||||
})
|
||||
if (res.code === 0) {
|
||||
enterpriseList.value = res.data.items || []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取企业列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 企业搜索处理
|
||||
const handleEnterpriseSearch = (query: string) => {
|
||||
loadEnterpriseList(query)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.account-page {
|
||||
// 账号管理页面样式
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.dialog-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.account-name {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.role-transfer-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
gap: 20px;
|
||||
padding: 20px 0;
|
||||
min-height: 500px;
|
||||
|
||||
.transfer-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
max-width: 380px;
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: var(--el-fill-color-light);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
|
||||
.panel-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
|
||||
.role-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.role-item {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color-light);
|
||||
border-color: var(--el-border-color);
|
||||
}
|
||||
|
||||
.role-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.el-checkbox) {
|
||||
width: 100%;
|
||||
|
||||
.el-checkbox__label {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.assigned-role-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.role-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 10px;
|
||||
|
||||
.el-button {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
v-model:filter="searchForm"
|
||||
:items="searchFormItems"
|
||||
:show-expand="false"
|
||||
:label-width="90"
|
||||
label-width="90"
|
||||
@reset="handleReset"
|
||||
@search="handleSearch"
|
||||
></ArtSearchBar>
|
||||
@@ -210,7 +210,7 @@
|
||||
import { h } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { EnterpriseService, ShopService } from '@/api/modules'
|
||||
import { ElMessage, ElMessageBox, ElTag, ElSwitch } from 'element-plus'
|
||||
import { ElMessage, ElSwitch } from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { EnterpriseItem, ShopResponse } from '@/types/api'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
@@ -220,8 +220,6 @@
|
||||
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
|
||||
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { BgColorEnum } from '@/enums/appEnum'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
|
||||
defineOptions({ name: 'EnterpriseCustomer' })
|
||||
|
||||
@@ -807,9 +805,3 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.enterprise-customer-page {
|
||||
// 可以在这里添加企业客户页面特定样式
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -114,18 +114,107 @@
|
||||
</ElDialog>
|
||||
|
||||
<!-- 分配角色对话框 -->
|
||||
<ElDialog v-model="roleDialogVisible" title="分配角色" width="500px">
|
||||
<ElCheckboxGroup v-model="selectedRoles">
|
||||
<div v-for="role in allRoles" :key="role.ID" style="margin-bottom: 12px">
|
||||
<ElCheckbox :label="role.ID">{{ role.role_name }}</ElCheckbox>
|
||||
<ElDialog v-model="roleDialogVisible" width="900px">
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<span class="dialog-title">分配角色</span>
|
||||
<div class="account-info">
|
||||
<span class="account-name">{{ currentAccountName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</ElCheckboxGroup>
|
||||
</template>
|
||||
<div class="role-transfer-container">
|
||||
<!-- 左侧:可分配角色列表 -->
|
||||
<div class="transfer-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-title">可分配角色</span>
|
||||
<ElInput
|
||||
v-model="leftRoleFilter"
|
||||
placeholder="搜索角色"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ElCheckboxGroup v-model="rolesToAdd" class="role-list">
|
||||
<div
|
||||
v-for="role in filteredAvailableRoles"
|
||||
:key="role.ID"
|
||||
class="role-item"
|
||||
>
|
||||
<ElCheckbox :label="role.ID" :disabled="selectedRoles.includes(role.ID)">
|
||||
<span class="role-info">
|
||||
<span>{{ role.role_name }}</span>
|
||||
<ElTag
|
||||
:type="role.role_type === 1 ? 'primary' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
</ElCheckbox>
|
||||
</div>
|
||||
</ElCheckboxGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间:操作按钮 -->
|
||||
<div class="transfer-buttons">
|
||||
<ElButton
|
||||
type="primary"
|
||||
:icon="'ArrowRight'"
|
||||
@click="addRoles"
|
||||
:disabled="rolesToAdd.length === 0"
|
||||
>
|
||||
添加
|
||||
</ElButton>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:已分配角色列表 -->
|
||||
<div class="transfer-panel">
|
||||
<div class="panel-header">
|
||||
<span class="panel-title">已分配角色</span>
|
||||
<ElInput
|
||||
v-model="rightRoleFilter"
|
||||
placeholder="搜索角色"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 180px"
|
||||
/>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="role-list">
|
||||
<div
|
||||
v-for="role in filteredAssignedRoles"
|
||||
:key="role.ID"
|
||||
class="role-item assigned-role-item"
|
||||
>
|
||||
<span class="role-info">
|
||||
<span>{{ role.role_name }}</span>
|
||||
<ElTag
|
||||
:type="role.role_type === 1 ? 'primary' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ role.role_type === 1 ? '平台角色' : '客户角色' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
<ElButton
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="removeSingleRole(role.ID)"
|
||||
>
|
||||
移除
|
||||
</ElButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="roleDialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleAssignRoles" :loading="roleSubmitLoading"
|
||||
>提交</ElButton
|
||||
>
|
||||
<ElButton @click="roleDialogVisible = false">关闭</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
@@ -185,8 +274,12 @@
|
||||
const roleSubmitLoading = ref(false)
|
||||
const passwordSubmitLoading = ref(false)
|
||||
const currentAccountId = ref<number>(0)
|
||||
const currentAccountName = ref<string>('')
|
||||
const selectedRoles = ref<number[]>([])
|
||||
const allRoles = ref<PlatformRole[]>([])
|
||||
const rolesToAdd = ref<number[]>([])
|
||||
const leftRoleFilter = ref('')
|
||||
const rightRoleFilter = ref('')
|
||||
|
||||
// 定义表单搜索初始值
|
||||
const initialSearchState = {
|
||||
@@ -528,10 +621,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 计算属性:过滤后的可分配角色
|
||||
const filteredAvailableRoles = computed(() => {
|
||||
if (!leftRoleFilter.value) return allRoles.value
|
||||
const keyword = leftRoleFilter.value.toLowerCase()
|
||||
return allRoles.value.filter((role) => role.role_name.toLowerCase().includes(keyword))
|
||||
})
|
||||
|
||||
// 计算属性:过滤后的已分配角色
|
||||
const filteredAssignedRoles = computed(() => {
|
||||
const assignedRolesList = allRoles.value.filter((role) => selectedRoles.value.includes(role.ID))
|
||||
if (!rightRoleFilter.value) return assignedRolesList
|
||||
const keyword = rightRoleFilter.value.toLowerCase()
|
||||
return assignedRolesList.filter((role) => role.role_name.toLowerCase().includes(keyword))
|
||||
})
|
||||
|
||||
// 显示分配角色对话框
|
||||
const showRoleDialog = async (row: PlatformAccount) => {
|
||||
currentAccountId.value = row.id
|
||||
currentAccountName.value = row.username
|
||||
selectedRoles.value = []
|
||||
rolesToAdd.value = []
|
||||
leftRoleFilter.value = ''
|
||||
rightRoleFilter.value = ''
|
||||
|
||||
try {
|
||||
// 每次打开对话框时重新加载最新的角色列表
|
||||
@@ -542,7 +654,8 @@
|
||||
if (res.code === 0) {
|
||||
// 提取角色ID数组
|
||||
const roles = res.data || []
|
||||
selectedRoles.value = roles.map((role: any) => role.id)
|
||||
// 兼容 ID 和 id 两种字段名
|
||||
selectedRoles.value = roles.map((role: any) => role.ID || role.id)
|
||||
// 数据加载完成后再打开对话框
|
||||
roleDialogVisible.value = true
|
||||
}
|
||||
@@ -551,19 +664,42 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 提交分配角色
|
||||
const handleAssignRoles = async () => {
|
||||
roleSubmitLoading.value = true
|
||||
// 批量添加角色
|
||||
const addRoles = async () => {
|
||||
if (rolesToAdd.value.length === 0) return
|
||||
|
||||
try {
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, selectedRoles.value)
|
||||
ElMessage.success('分配角色成功')
|
||||
roleDialogVisible.value = false
|
||||
// 将选中的角色添加到已分配列表
|
||||
const newRoles = [...new Set([...selectedRoles.value, ...rolesToAdd.value])]
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, newRoles)
|
||||
|
||||
selectedRoles.value = newRoles
|
||||
rolesToAdd.value = []
|
||||
|
||||
ElMessage.success('角色添加成功')
|
||||
// 刷新列表以更新角色显示
|
||||
await getAccountList()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
roleSubmitLoading.value = false
|
||||
console.error('添加角色失败:', error)
|
||||
ElMessage.error('角色添加失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 移除单个角色
|
||||
const removeSingleRole = async (roleId: number) => {
|
||||
try {
|
||||
// 从已分配列表中移除该角色
|
||||
const newRoles = selectedRoles.value.filter((id) => id !== roleId)
|
||||
await AccountService.assignRolesToAccount(currentAccountId.value, newRoles)
|
||||
|
||||
selectedRoles.value = newRoles
|
||||
|
||||
ElMessage.success('角色移除成功')
|
||||
// 刷新列表以更新角色显示
|
||||
await getAccountList()
|
||||
} catch (error) {
|
||||
console.error('移除角色失败:', error)
|
||||
ElMessage.error('角色移除失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -768,4 +904,128 @@
|
||||
.platform-account-page {
|
||||
// 平台账号管理页面样式
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.dialog-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.account-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
.account-name {
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.role-transfer-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
gap: 20px;
|
||||
padding: 20px 0;
|
||||
min-height: 500px;
|
||||
|
||||
.transfer-panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
max-width: 380px;
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: var(--el-fill-color-light);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
|
||||
.panel-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--el-text-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
|
||||
.role-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.role-item {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--el-border-color-lighter);
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color-light);
|
||||
border-color: var(--el-border-color);
|
||||
}
|
||||
|
||||
.role-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.el-checkbox) {
|
||||
width: 100%;
|
||||
|
||||
.el-checkbox__label {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.assigned-role-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.role-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.transfer-buttons {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 10px;
|
||||
|
||||
.el-button {
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
:currentPage="pagination.page"
|
||||
:pageSize="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:marginTop="10"
|
||||
:marginTop="10"v
|
||||
height="60vh"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
@@ -43,7 +43,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, computed } from 'vue'
|
||||
import { h, computed, ref, reactive, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElTag, ElIcon, ElButton, ElCard } from 'element-plus'
|
||||
import { ArrowLeft } from '@element-plus/icons-vue'
|
||||
|
||||
Reference in New Issue
Block a user