1423 lines
44 KiB
Plaintext
1423 lines
44 KiB
Plaintext
<template>
|
|
<view class="user-detail-page">
|
|
<admin-layout>
|
|
<view class="container">
|
|
<view class="page-header">
|
|
<view class="back-button" @click="goBack">
|
|
<text class="iconfont"></text>
|
|
<text>返回</text>
|
|
</view>
|
|
<text class="page-title">用户名详情</text>
|
|
<view class="header-actions">
|
|
<button
|
|
class="primary-btn"
|
|
@click="showRoleModal = true"
|
|
v-if="canManageUserRoles"
|
|
>
|
|
添加角色
|
|
</button>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="loading-container" v-if="loading">
|
|
<text>加载中...</text>
|
|
</view>
|
|
|
|
<view v-else>
|
|
<view class="user-info-card">
|
|
<view class="card-header">
|
|
<text class="card-title">基本信息</text>
|
|
<text
|
|
class="edit-link"
|
|
@click="showEditModal = true"
|
|
v-if="canManageUserInfo"
|
|
>
|
|
编辑
|
|
</text>
|
|
</view>
|
|
|
|
<view class="card-body">
|
|
<view class="info-row">
|
|
<view class="info-label">濮撳悕:</view>
|
|
<view class="info-value">{{ user.username ?? '-' }}</view>
|
|
</view>
|
|
|
|
<view class="info-row">
|
|
<view class="info-label">用户名</view>
|
|
<view class="info-value">{{ user.username }}</view>
|
|
</view>
|
|
|
|
<view class="info-row">
|
|
<view class="info-label">邮:</view>
|
|
<view class="info-value">{{ user.email ?? '-' }}</view>
|
|
</view>
|
|
|
|
<view class="info-row">
|
|
<view class="info-label">手机:</view>
|
|
<view class="info-value">{{ user.phone ?? '-' }}</view>
|
|
</view>
|
|
|
|
<view class="info-row">
|
|
<view class="info-label">状态</view>
|
|
<view class="info-value">
|
|
<text :class="['status-badge', user.is_active ? 'active' : 'inactive']">
|
|
{{ user.is_active ? '已启用' : '已禁用' }}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="info-row">
|
|
<view class="info-label">注册时间:</view>
|
|
<view class="info-value">{{ formatDate(user.created_at) }}</view>
|
|
</view>
|
|
|
|
<view class="info-row">
|
|
<view class="info-label">最后登录</view>
|
|
<view class="info-value">{{ (user.last_login != null && user.last_login !== '') ? formatDate(user.last_login as string) : '从未登录' }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<view class="roles-card">
|
|
<view class="card-header">
|
|
<text class="card-title">角色与权限</text>
|
|
</view>
|
|
|
|
<view class="card-body" v-if="userRoles.length === 0">
|
|
<text class="empty-text">该用户未分配任何角色</text>
|
|
</view>
|
|
|
|
<view class="card-body" v-else>
|
|
<view
|
|
class="role-item"
|
|
v-for="(role, index) in userRoles"
|
|
:key="index"
|
|
>
|
|
<view class="role-info">
|
|
<text class="role-name">{{ role.role_name }}</text>
|
|
<text class="role-scope" v-if="role.scope_name">
|
|
({{ role.scope_name }})
|
|
</text>
|
|
<text class="role-level">Level {{ role.level }}</text>
|
|
</view>
|
|
<view class="role-actions">
|
|
<text
|
|
class="delete-btn"
|
|
@click="confirmDeleteRole(role)"
|
|
v-if="canManageUserRoles"
|
|
>
|
|
绉婚櫎
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="modal" v-if="showEditModal">
|
|
<view class="modal-content">
|
|
<view class="modal-header">
|
|
<text class="modal-title">缂栬緫用户名淇℃伅</text>
|
|
<text class="close-btn" @click="showEditModal = false">脳</text>
|
|
</view>
|
|
|
|
<view class="modal-body">
|
|
<view class="form-group">
|
|
<text class="form-label">姓名:</text>
|
|
<input type="text" v-model="editForm.name" placeholder="请输入用户姓名" />
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">邮箱:</text>
|
|
<input type="text" v-model="editForm.email" placeholder="请输入邮箱地址" />
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">手嬫満:</text>
|
|
<input type="text" v-model="editForm.phone" placeholder="请输入手机号 />
|
|
</view>
|
|
|
|
<view class="form-group">
|
|
<text class="form-label">状态讹拷?</text>
|
|
<view class="status-toggle">
|
|
<text
|
|
class="toggle-option"
|
|
:class="{ active: editForm.is_active }"
|
|
@click="editForm.is_active = true"
|
|
>
|
|
后敤
|
|
</text>
|
|
<text
|
|
class="toggle-option"
|
|
:class="{ active: !editForm.is_active }"
|
|
@click="editForm.is_active = false"
|
|
>
|
|
绂佺敤
|
|
</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="modal-footer">
|
|
<button class="cancel-btn" @click="showEditModal = false">鍙栨秷</button>
|
|
<button class="submit-btn" @click="saveUserInfo">淇濆瓨</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 添加角色妯℃€佹 -->
|
|
<view class="modal" v-if="showRoleModal">
|
|
<view class="modal-content">
|
|
<view class="modal-header">
|
|
<text class="modal-title">添加角色</text>
|
|
<text class="close-btn" @click="showRoleModal = false">脳</text>
|
|
</view>
|
|
|
|
<view class="modal-body">
|
|
<view class="form-group">
|
|
<text class="form-label">角掕壊:</text>
|
|
<view class="picker-field" @click="showRolePicker = true">
|
|
<text>{{ selectedRoleIndex >= 0 ? roleOptions[selectedRoleIndex].name : '请烽€夋嫨角掕壊' }}</text>
|
|
<text class="picker-arrow">></text>
|
|
</view>
|
|
<view v-if="showRolePicker" class="picker-modal">
|
|
<picker-view
|
|
class="picker-view"
|
|
:value="[tempRoleIndex]"
|
|
:indicator-style="'height: 50px;'"
|
|
@change="onRolePickerViewChange"
|
|
>
|
|
<picker-view-column style="width:750rpx;">
|
|
<view v-for="(r, idx) in roleOptions" :key="r.id" class="picker-item">{{ r.name }}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
<view class="picker-actions">
|
|
<button @click="showRolePicker = false">鍙栨秷</button>
|
|
<button @click="confirmRolePicker" class="picker-actions-button">纭畾</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group" v-if="showScopeSelection">
|
|
<text class="form-label">作用域类型</text>
|
|
<view class="scope-toggle">
|
|
<text
|
|
class="toggle-option"
|
|
:class="{ active: roleForm.scope_type === 'region' }"
|
|
@click="changeScopeType('region')"
|
|
>
|
|
地板尯
|
|
</text>
|
|
<text
|
|
class="toggle-option"
|
|
:class="{ active: roleForm.scope_type === 'school' }"
|
|
@click="changeScopeType('school')"
|
|
>
|
|
瀛︽牎
|
|
</text>
|
|
<text
|
|
class="toggle-option"
|
|
:class="{ active: roleForm.scope_type === 'grade' }"
|
|
@click="changeScopeType('grade')"
|
|
>
|
|
骞寸骇
|
|
</text>
|
|
<text
|
|
class="toggle-option"
|
|
:class="{ active: roleForm.scope_type === 'class' }"
|
|
@click="changeScopeType('class')"
|
|
>
|
|
鐝骇
|
|
</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group" v-if="['region', 'school', 'grade', 'class'].includes(roleForm.scope_type ?? '')">
|
|
<text class="form-label">閫夋嫨地板尯:</text>
|
|
<view class="picker-field" @click="showRegionPicker = true">
|
|
<text>{{ selectedRegionIndex >= 0 ? regionOptions[selectedRegionIndex].name : '请烽€夋嫨地板尯' }}</text>
|
|
<text class="picker-arrow">></text>
|
|
</view>
|
|
<view v-if="showRegionPicker" class="picker-modal">
|
|
<picker-view
|
|
class="picker-view"
|
|
:value="[tempRegionIndex]"
|
|
:indicator-style="'height: 50px;'"
|
|
@change="onRegionPickerViewChange"
|
|
>
|
|
<picker-view-column style="width:750rpx;">
|
|
<view v-for="(r, idx) in regionOptions" :key="r.id" class="picker-item">{{ r.name }}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
<view class="picker-actions">
|
|
<button @click="showRegionPicker = false">鍙栨秷</button>
|
|
<button @click="confirmRegionPicker" class="picker-actions-button">纭畾</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group" v-if="['school', 'grade', 'class'].includes(roleForm.scope_type ?? '') && selectedRegionIndex >= 0">
|
|
<text class="form-label">閫夋嫨瀛︽牎:</text>
|
|
<view class="picker-field" @click="showSchoolPicker = true">
|
|
<text>{{ selectedSchoolIndex >= 0 ? schoolOptions[selectedSchoolIndex].name : '请烽€夋嫨瀛︽牎' }}</text>
|
|
<text class="picker-arrow">></text>
|
|
</view>
|
|
<view v-if="showSchoolPicker" class="picker-modal">
|
|
<picker-view
|
|
class="picker-view"
|
|
:value="[tempSchoolIndex]"
|
|
:indicator-style="'height: 50px;'"
|
|
@change="onSchoolPickerViewChange"
|
|
>
|
|
<picker-view-column style="width:750rpx;">
|
|
<view v-for="(s, idx) in schoolOptions" :key="s.id" class="picker-item">{{ s.name }}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
<view class="picker-actions">
|
|
<button @click="showSchoolPicker = false">鍙栨秷</button>
|
|
<button @click="confirmSchoolPicker" class="picker-actions-button">纭畾</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group" v-if="['grade', 'class'].includes(roleForm.scope_type ?? '') && selectedSchoolIndex >= 0">
|
|
<text class="form-label">閫夋嫨骞寸骇:</text>
|
|
<view class="picker-field" @click="showGradePicker = true">
|
|
<text>{{ selectedGradeIndex >= 0 ? gradeOptions[selectedGradeIndex].name : '请烽€夋嫨骞寸骇' }}</text>
|
|
<text class="picker-arrow">></text>
|
|
</view>
|
|
<view v-if="showGradePicker" class="picker-modal">
|
|
<picker-view
|
|
class="picker-view"
|
|
:value="[tempGradeIndex]"
|
|
:indicator-style="'height: 50px;'"
|
|
@change="onGradePickerViewChange"
|
|
>
|
|
<picker-view-column style="width:750rpx;">
|
|
<view v-for="(g, idx) in gradeOptions" :key="g.id" class="picker-item">{{ g.name }}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
<view class="picker-actions">
|
|
<button @click="showGradePicker = false">鍙栨秷</button>
|
|
<button @click="confirmGradePicker" class="picker-actions-button">纭畾</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="form-group" v-if="roleForm.scope_type === 'class' && selectedGradeIndex >= 0">
|
|
<text class="form-label">閫夋嫨鐝骇:</text>
|
|
<view class="picker-field" @click="showClassPicker = true">
|
|
<text>{{ selectedClassIndex >= 0 ? classOptions[selectedClassIndex].name : '请烽€夋嫨鐝骇' }}</text>
|
|
<text class="picker-arrow">></text>
|
|
</view>
|
|
<view v-if="showClassPicker" class="picker-modal">
|
|
<picker-view
|
|
class="picker-view"
|
|
:value="[tempClassIndex]"
|
|
:indicator-style="'height: 50px;'"
|
|
@change="onClassPickerViewChange"
|
|
>
|
|
<picker-view-column style="width:750rpx;">
|
|
<view v-for="(c, idx) in classOptions" :key="c.id" class="picker-item">{{ c.name }}</view>
|
|
</picker-view-column>
|
|
</picker-view>
|
|
<view class="picker-actions">
|
|
<button @click="showClassPicker = false">鍙栨秷</button>
|
|
<button @click="confirmClassPicker" class="picker-actions-button">纭畾</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="modal-footer">
|
|
<button class="cancel-btn" @click="showRoleModal = false">鍙栨秷</button>
|
|
<button class="submit-btn" @click="addRole" :disabled="canAddRole === false">娣诲姞</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 删除角色确认 -->
|
|
<view class="modal" v-if="showDeleteModal">
|
|
<view class="modal-content">
|
|
<view class="modal-header">
|
|
<text class="modal-title">纭绉婚櫎角掕壊</text>
|
|
<text class="close-btn" @click="showDeleteModal = false">脳</text>
|
|
</view>
|
|
|
|
<view class="modal-body">
|
|
<text>纭畾瑕佺Щ闄よ用户名鐨勪互涓嬭色插悧></text>
|
|
<text class="role-confirm-text">
|
|
{{ deleteRole?.role_name }}{{ (deleteRole?.scope_name != null && deleteRole?.scope_name !== '') ? ' (' + deleteRole?.scope_name + ')' : '' }}
|
|
</text>
|
|
</view>
|
|
|
|
<view class="modal-footer">
|
|
<button class="cancel-btn" @click="showDeleteModal = false">鍙栨秷</button>
|
|
<button class="confirm-btn" @click="deleteUserRole">纭</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</admin-layout>
|
|
</view>
|
|
</template>
|
|
|
|
<script lang="uts">
|
|
import { ref, computed, onMounted } from 'vue'
|
|
import AdminLayout from '../layout.uvue'
|
|
import supa from '@/components/supadb/aksupainstance.uts'
|
|
import { hasPermission, getUserPermissions } from '@/utils/permissionService.uts'
|
|
import { state as userStore } from '@/utils/store.uts'
|
|
import { UserDetail, UserRole, EditForm, RoleForm, RoleOption, RegionOption, SchoolOption, GradeOption, ClassOption } from '../admintypes.uts'
|
|
|
|
export default {
|
|
name: 'UserDetail',
|
|
components: {
|
|
AdminLayout
|
|
},
|
|
setup() {
|
|
const db = supa
|
|
|
|
// 鑾峰彇用户名ID
|
|
const userId = ref('')
|
|
// let query: any = undefined
|
|
// try {
|
|
// query = (uni.getEnterOptionsSync() as any)?.query
|
|
// } catch (e) {
|
|
// query = undefined
|
|
// }
|
|
// if (query != null && typeof query.id === 'string') {
|
|
// userId.value = query.id
|
|
// }
|
|
|
|
// 鍩虹状态讹拷?
|
|
const loading = ref(true)
|
|
const user = ref<UserDetail>({
|
|
id: '',
|
|
username: '',
|
|
is_active: false,
|
|
created_at: ''
|
|
})
|
|
|
|
const userRoles = ref<UserRole[]>([])
|
|
const showRolePicker = ref(false)
|
|
const tempRoleIndex = ref(-1)
|
|
const showRegionPicker = ref(false)
|
|
const tempRegionIndex = ref(-1)
|
|
const showSchoolPicker = ref(false)
|
|
const tempSchoolIndex = ref(-1)
|
|
const showGradePicker = ref(false)
|
|
const tempGradeIndex = ref(-1)
|
|
const showClassPicker = ref(false)
|
|
const tempClassIndex = ref(-1)
|
|
// 缂栬緫用户名淇℃伅状态讹拷?
|
|
const showEditModal = ref(false)
|
|
const editForm = ref<EditForm>({
|
|
name: '',
|
|
email: '',
|
|
phone: '',
|
|
is_active: true
|
|
})
|
|
|
|
// 添加角色状态讹拷?
|
|
const showRoleModal = ref(false)
|
|
const roleOptions = ref<RoleOption[]>([])
|
|
const selectedRoleIndex = ref(-1)
|
|
const roleForm = ref<RoleForm>({
|
|
name: '',
|
|
level: 0,
|
|
description: '',
|
|
is_system: false,
|
|
scope_type: null,
|
|
scope_id: null
|
|
})
|
|
|
|
// 作用域状态
|
|
const regionOptions = ref<RegionOption[]>([])
|
|
const selectedRegionIndex = ref(-1)
|
|
const schoolOptions = ref<SchoolOption[]>([])
|
|
const selectedSchoolIndex = ref(-1)
|
|
const gradeOptions = ref<GradeOption[]>([])
|
|
const selectedGradeIndex = ref(-1)
|
|
const classOptions = ref<ClassOption[]>([])
|
|
const selectedClassIndex = ref(-1)
|
|
|
|
// 创犻櫎角掕壊状态讹拷?
|
|
const showDeleteModal = ref(false)
|
|
const deleteRole = ref<UserRole | null>(null)
|
|
|
|
// 鏉冮檺状态讹拷?
|
|
const canManageUserInfo = ref(false)
|
|
const canManageUserRoles = ref(false)
|
|
|
|
|
|
// 计算属性烇拷?
|
|
const showScopeSelection = computed(() => {
|
|
const role = selectedRoleIndex.value >= 0 ? roleOptions.value[selectedRoleIndex.value] : null
|
|
return role != null && role?.requires_scope === true
|
|
})
|
|
|
|
const canAddRole = computed(() => {
|
|
if (selectedRoleIndex.value < 0) return false
|
|
const role = roleOptions.value[selectedRoleIndex.value]
|
|
if (role == null) return false
|
|
if (role?.requires_scope !== true) return true
|
|
if (roleForm.value.scope_type == null || roleForm.value.scope_type === '') return false
|
|
if (roleForm.value.scope_type === 'region') {
|
|
return selectedRegionIndex.value >= 0
|
|
}
|
|
if (roleForm.value.scope_type === 'school') {
|
|
return selectedRegionIndex.value >= 0 && selectedSchoolIndex.value >= 0
|
|
}
|
|
if (roleForm.value.scope_type === 'grade') {
|
|
return selectedRegionIndex.value >= 0 && selectedSchoolIndex.value >= 0 && selectedGradeIndex.value >= 0
|
|
}
|
|
if (roleForm.value.scope_type === 'class') {
|
|
return selectedRegionIndex.value >= 0 && selectedSchoolIndex.value >= 0 &&
|
|
selectedGradeIndex.value >= 0 && selectedClassIndex.value >= 0
|
|
}
|
|
return false
|
|
})
|
|
|
|
// 格式化日期
|
|
const formatDate = (dateStr: string): string => {
|
|
if (dateStr == null || dateStr === '') return '-'
|
|
try {
|
|
const date = new Date(dateStr)
|
|
return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
|
|
} catch (error) {
|
|
return dateStr
|
|
}
|
|
}
|
|
|
|
// 鑾峰彇用户名淇℃伅
|
|
const fetchUserInfo = async () => {
|
|
loading.value = true
|
|
console.log('fetchUserInfo')
|
|
try {
|
|
const result = await db.from('ak_users')
|
|
.select('*', {})
|
|
.eq('id', userId.value)
|
|
.execute()
|
|
console.log(result)
|
|
const { data , error } = result;
|
|
if (error != null) {
|
|
console.error('鑾峰彇用户名淇℃伅澶辫触:', error)
|
|
uni.showToast({
|
|
title: '鑾峰彇用户名淇℃伅澶辫触',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
if (data != null) {
|
|
let adata: UTSJSONObject | null = null
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
adata = data[0] as UTSJSONObject
|
|
} else if (data != null && typeof data === 'object' && typeof data !== 'string') {
|
|
adata = data as UTSJSONObject
|
|
}
|
|
if (adata != null) {
|
|
user.value = {
|
|
id: adata.getString("id") ?? '',
|
|
username: adata.getString("username") ?? '',
|
|
is_active: adata.getBoolean("is_active")??false,
|
|
created_at: adata.getString("created_at") ?? '',
|
|
name: adata.getString("name") ?? '',
|
|
email: adata.getString("email") ?? '',
|
|
phone: adata.getString("phone") ?? '',
|
|
last_login: adata.getString("last_login") ?? ''
|
|
} as UserDetail
|
|
console.log(user.value)
|
|
// 设置编辑表单的初始值嬶拷?
|
|
editForm.value = {
|
|
name: user.value.name ?? '',
|
|
email: user.value.email ?? '',
|
|
phone: user.value.phone ?? '',
|
|
is_active: user.value.is_active ?? true
|
|
} as EditForm
|
|
console.log(editForm.value)
|
|
} else {
|
|
uni.showToast({
|
|
title: '手句笉创拌用户名',
|
|
icon: 'none'
|
|
})
|
|
uni.navigateBack()
|
|
}
|
|
} else {
|
|
uni.showToast({
|
|
title: '手句笉创拌用户名',
|
|
icon: 'none'
|
|
})
|
|
uni.navigateBack()
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇用户名淇℃伅寮傚父:', error)
|
|
uni.showToast({
|
|
title: '鑾峰彇用户名淇℃伅澶辫触',
|
|
icon: 'none'
|
|
})
|
|
uni.navigateBack()
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
console.log('ak detail 11')
|
|
|
|
// 鑾峰彇用户名角掕壊
|
|
const fetchUserRoles = async () => {
|
|
try {
|
|
const result = await db.from('ak_user_roles')
|
|
.select(`
|
|
id,
|
|
user_id,
|
|
role_id,
|
|
scope_type,
|
|
scope_id,
|
|
role:ak_roles(name, level)
|
|
`, {})
|
|
.eq('user_id', userId.value)
|
|
.order('scope_type', { ascending: true })
|
|
.execute();
|
|
console.log(result)
|
|
const { data, error } = result;
|
|
if (error!=null) {
|
|
console.error('鑾峰彇用户名角掕壊澶辫触:', error)
|
|
return
|
|
}
|
|
if (data as Array<UTSJSONObject> != null) {
|
|
const arr: UserRole[] = []
|
|
for (let i = 0; i < data.length; i++) {
|
|
const item = data[i] as UTSJSONObject
|
|
arr.push({
|
|
id: item.getString("id") ?? '',
|
|
user_id: item.getString("user_id") ?? '',
|
|
role_id: item.getString("role_id") ?? '',
|
|
role_name: (() => {
|
|
const roleObj = item.get("role")
|
|
return roleObj != null ? (roleObj as UTSJSONObject).getString("name") ?? '' : ''
|
|
})(),
|
|
level: (() => {
|
|
const roleObj = item.get("role")
|
|
return roleObj != null ? (roleObj as UTSJSONObject).getNumber("level") ?? 0 : 0
|
|
})(),
|
|
scope_type: item.getString("scope_type") ?? '',
|
|
scope_id: item.getString("scope_id") ?? '',
|
|
scope_name: item.getString("name")
|
|
})
|
|
}
|
|
userRoles.value = arr
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇用户名角掕壊寮傚父:', error)
|
|
}
|
|
}
|
|
|
|
// 鑾峰彇角掕壊创楄〃
|
|
const fetchRoles = async () => {
|
|
try {
|
|
const result = await db.from('ak_roles')
|
|
.select('*', {})
|
|
.order('level', { ascending: false })
|
|
.execute()
|
|
const { data, error } = result;
|
|
console.log(data,error)
|
|
if (error != null) {
|
|
console.error('鑾峰彇角掕壊创楄〃澶辫触:', error)
|
|
return
|
|
}
|
|
if (data as Array<UTSJSONObject> != null) {
|
|
const arr: RoleOption[] = []
|
|
for (let i = 0; i < data.length; i++) {
|
|
const role = data[i] as UTSJSONObject
|
|
arr.push({
|
|
id: role.getString("id") ?? '',
|
|
name: role.getString("name") ?? '',
|
|
level: role.getNumber("level") ?? 0,
|
|
requires_scope: role.getBoolean("requires_scope") ?? false
|
|
})
|
|
}
|
|
roleOptions.value = arr
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇角掕壊创楄〃寮傚父:', error)
|
|
}
|
|
}
|
|
|
|
// 鑾峰彇地板尯创楄〃
|
|
const fetchRegions = async () => {
|
|
try {
|
|
const result = await db.from('ak_regions')
|
|
.select('*', {})
|
|
.order('level', { ascending: true })
|
|
.order('name', { ascending: true })
|
|
.execute();
|
|
const { data, error } = result;
|
|
console.log(data, error)
|
|
if (error != null) {
|
|
console.error('鑾峰彇地板尯创楄〃澶辫触:', error)
|
|
return
|
|
}
|
|
if (data as Array<UTSJSONObject> != null) {
|
|
const arr: RegionOption[] = []
|
|
for (let i = 0; i < data.length; i++) {
|
|
const region = data[i] as UTSJSONObject
|
|
arr.push({
|
|
id: region.getString("id") ?? '',
|
|
name: region.getString("name") ?? ''
|
|
})
|
|
}
|
|
regionOptions.value = arr
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇地板尯创楄〃寮傚父:', error)
|
|
}
|
|
}
|
|
|
|
// 鑾峰彇瀛︽牎创楄〃
|
|
const fetchSchools = async (regionId: string) => {
|
|
try {
|
|
const result = await db.from('ak_schools')
|
|
.select('*', {})
|
|
.eq('region_id', regionId)
|
|
.order('name', { ascending: true })
|
|
.execute()
|
|
const { data, error } = result;
|
|
if (error != null) {
|
|
console.error('鑾峰彇瀛︽牎创楄〃澶辫触:', error)
|
|
return
|
|
}
|
|
if (data as Array<UTSJSONObject> != null) {
|
|
const arr: SchoolOption[] = []
|
|
for (let i = 0; i < data.length; i++) {
|
|
const school = data[i] as UTSJSONObject
|
|
arr.push({
|
|
id: school.getString("id") ?? '',
|
|
name: school.getString("name") ?? '',
|
|
region_id: school.getString("region_id") ?? ''
|
|
})
|
|
}
|
|
schoolOptions.value = arr
|
|
selectedSchoolIndex.value = -1
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇瀛︽牎创楄〃寮傚父:', error)
|
|
}
|
|
}
|
|
|
|
// 鑾峰彇骞寸骇创楄〃
|
|
const fetchGrades = async (schoolId: string) => {
|
|
try {
|
|
const result = await db.from('ak_grades')
|
|
.select('*', {})
|
|
.eq('school_id', schoolId)
|
|
.order('order_num', { ascending: true })
|
|
.execute()
|
|
const { data, error } = result;
|
|
if (error != null) {
|
|
console.error('鑾峰彇骞寸骇创楄〃澶辫触:', error)
|
|
return
|
|
}
|
|
if (data as Array<UTSJSONObject> != null) {
|
|
const arr: GradeOption[] = []
|
|
for (let i = 0; i < data.length; i++) {
|
|
const grade = data[i] as UTSJSONObject
|
|
arr.push({
|
|
id: grade.getString("id") ?? '',
|
|
name: grade.getString("name") ?? '',
|
|
school_id: grade.getString("school_id") ?? ''
|
|
})
|
|
}
|
|
gradeOptions.value = arr
|
|
selectedGradeIndex.value = -1
|
|
// 閲嶇疆鐝骇閫夋嫨
|
|
classOptions.value = []
|
|
selectedClassIndex.value = -1
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇骞寸骇创楄〃寮傚父:', error)
|
|
}
|
|
}
|
|
|
|
// 鑾峰彇鐝骇创楄〃
|
|
const fetchClasses = async (gradeId: string) => {
|
|
try {
|
|
const result = await db.from('ak_classes')
|
|
.select('*', {})
|
|
.eq('grade_id', gradeId)
|
|
.order('name', { ascending: true })
|
|
.execute()
|
|
const { data, error } = result;
|
|
if (error != null) {
|
|
console.error('鑾峰彇鐝骇创楄〃澶辫触:', error)
|
|
return
|
|
}
|
|
if (data as Array<UTSJSONObject> != null) {
|
|
const arr: ClassOption[] = []
|
|
for (let i = 0; i < data.length; i++) {
|
|
const cls = data[i] as UTSJSONObject
|
|
arr.push({
|
|
id: cls.getString("id") ?? '',
|
|
name: cls.getString("name") ?? '',
|
|
grade_id: cls.getString("grade_id") ?? ''
|
|
})
|
|
}
|
|
classOptions.value = arr
|
|
selectedClassIndex.value = -1
|
|
}
|
|
} catch (error) {
|
|
console.error('鑾峰彇鐝骇创楄〃寮傚父:', error)
|
|
}
|
|
}
|
|
|
|
// 检查权限
|
|
const checkPermissions = async () => {
|
|
try {
|
|
const uid = userId.value;
|
|
canManageUserInfo.value = await hasPermission({ userId: uid, permissionCode: 'admin.users.manage' })
|
|
canManageUserRoles.value = await hasPermission({ userId: uid, permissionCode: 'admin.roles.assign' })
|
|
} catch (error) {
|
|
console.error('权限检查异常', error)
|
|
}
|
|
}
|
|
|
|
// 返回上一页
|
|
const goBack = () => {
|
|
uni.navigateBack()
|
|
}
|
|
|
|
// 淇濆瓨用户名淇℃伅
|
|
const saveUserInfo = async () => {
|
|
try {
|
|
const result = await db.from('ak_users')
|
|
.update({
|
|
name: editForm.value.name,
|
|
email: editForm.value.email,
|
|
phone: editForm.value.phone,
|
|
is_active: editForm.value.is_active
|
|
})
|
|
.eq('id', userId.value)
|
|
.execute()
|
|
const { error } = result;
|
|
if (error != null) {
|
|
console.error('修存柊用户名淇℃伅澶辫触:', error)
|
|
uni.showToast({
|
|
title: '淇濆瓨澶辫触',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
uni.showToast({
|
|
title: '淇濆瓨密愬姛',
|
|
icon: 'success'
|
|
})
|
|
// 修存柊最湴用户名淇℃伅
|
|
user.value.name = editForm.value.name
|
|
user.value.email = editForm.value.email
|
|
user.value.phone = editForm.value.phone
|
|
user.value.is_active = editForm.value.is_active
|
|
showEditModal.value = false
|
|
} catch (error) {
|
|
console.error('修存柊用户名淇℃伅寮傚父:', error)
|
|
uni.showToast({
|
|
title: '淇濆瓨澶辫触',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
}
|
|
|
|
// 角掕壊閫夋嫨
|
|
const onRolePickerViewChange = (e: UniPickerViewChangeEvent) => {
|
|
let index = -1
|
|
if (e != null && e.detail != null) {
|
|
|
|
index = e.detail.value[0]
|
|
|
|
}
|
|
selectedRoleIndex.value = index
|
|
const role = roleOptions.value[index]
|
|
roleForm.value.role_id = role.id
|
|
roleForm.value.role_name = role.name
|
|
roleForm.value.level = role.level
|
|
if (!role.requires_scope) {
|
|
roleForm.value.scope_type = null
|
|
roleForm.value.scope_id = null
|
|
} else if (roleForm.value.scope_type == null || roleForm.value.scope_type === '') {
|
|
roleForm.value.scope_type = 'region'
|
|
}
|
|
}
|
|
|
|
// 淇敼作用域类型
|
|
const changeScopeType = (type: string) => {
|
|
roleForm.value.scope_type = type
|
|
roleForm.value.scope_id = null
|
|
selectedRegionIndex.value = -1
|
|
selectedSchoolIndex.value = -1
|
|
selectedGradeIndex.value = -1
|
|
selectedClassIndex.value = -1
|
|
// 閲嶇疆鐩稿叧閫夐」
|
|
schoolOptions.value = []
|
|
gradeOptions.value = []
|
|
classOptions.value = []
|
|
}
|
|
|
|
// 地板尯閫夋嫨
|
|
const onRegionPickerViewChange = (e: UniPickerViewChangeEvent) => {
|
|
let index = -1
|
|
if (e != null && e.detail != null) {
|
|
index = e.detail.value[0]
|
|
|
|
}
|
|
selectedRegionIndex.value = index
|
|
const region = regionOptions.value[index]
|
|
if (roleForm.value.scope_type === 'region') {
|
|
roleForm.value.scope_id = region.id
|
|
} else if (["school", "grade", "class"].includes(roleForm.value.scope_type ?? '')) {
|
|
fetchSchools(region.id)
|
|
}
|
|
}
|
|
|
|
// 瀛︽牎閫夋嫨
|
|
const onSchoolPickerViewChange = (e: UniPickerViewChangeEvent) => {
|
|
let index = -1
|
|
if (e != null && e.detail != null) {
|
|
index = e.detail.value[0]
|
|
}
|
|
selectedSchoolIndex.value = index
|
|
const school = schoolOptions.value[index]
|
|
if (roleForm.value.scope_type === 'school') {
|
|
roleForm.value.scope_id = school.id
|
|
} else if (["grade", "class"].includes(roleForm.value.scope_type ?? '')) {
|
|
fetchGrades(school.id)
|
|
}
|
|
}
|
|
|
|
// 骞寸骇閫夋嫨
|
|
const onGradePickerViewChange = (e: UniPickerViewChangeEvent) => {
|
|
let index = -1
|
|
if (e != null && e.detail != null) {
|
|
index = e.detail.value[0]
|
|
}
|
|
selectedGradeIndex.value = index
|
|
const grade = gradeOptions.value[index]
|
|
if (roleForm.value.scope_type === 'grade') {
|
|
roleForm.value.scope_id = grade.id
|
|
} else if (roleForm.value.scope_type === 'class') {
|
|
fetchClasses(grade.id)
|
|
}
|
|
}
|
|
|
|
// 鐝骇閫夋嫨
|
|
const onClassPickerViewChange = (e: UniPickerViewChangeEvent) => {
|
|
let index = -1
|
|
if (e != null && e.detail != null) {
|
|
index = e.detail.value[0]
|
|
}
|
|
selectedClassIndex.value = index
|
|
const cls = classOptions.value[index]
|
|
roleForm.value.scope_id = cls.id
|
|
}
|
|
|
|
// 添加角色
|
|
const addRole = async () => {
|
|
if (!canAddRole.value) return
|
|
try {
|
|
// 妫€鏌ユ槸后﹀凡最夌浉后岀殑角掕壊创嗛厤
|
|
const existingRole = userRoles.value.find(r =>
|
|
r.role_id === roleForm.value.role_id &&
|
|
r.scope_type === roleForm.value.scope_type &&
|
|
r.scope_id === roleForm.value.scope_id
|
|
)
|
|
if (existingRole != null) {
|
|
uni.showToast({
|
|
title: '请ヨ色插凡创嗛厤缁欐用户名',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
const result = await db.from('ak_user_roles')
|
|
.insert({
|
|
user_id: userId.value,
|
|
role_id: roleForm.value.role_id,
|
|
scope_type: roleForm.value.scope_type ,
|
|
scope_id: roleForm.value.scope_id
|
|
})
|
|
.execute()
|
|
const { error } = result;
|
|
if (error != null) {
|
|
console.error('添加角色澶辫触:', error)
|
|
uni.showToast({
|
|
title: '添加角色澶辫触',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
uni.showToast({
|
|
title: '添加角色密愬姛',
|
|
icon: 'success'
|
|
})
|
|
fetchUserRoles()
|
|
showRoleModal.value = false
|
|
selectedRoleIndex.value = -1
|
|
selectedRegionIndex.value = -1
|
|
selectedSchoolIndex.value = -1
|
|
selectedGradeIndex.value = -1
|
|
selectedClassIndex.value = -1
|
|
roleForm.value = {
|
|
role_id: '',
|
|
role_name: '',
|
|
name: '',
|
|
level: 0,
|
|
description: '',
|
|
is_system: false,
|
|
scope_type: null,
|
|
scope_id: null
|
|
} as RoleForm
|
|
} catch (error) {
|
|
console.error('添加角色寮傚父:', error)
|
|
uni.showToast({
|
|
title: '添加角色澶辫触',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
}
|
|
|
|
// 纭创犻櫎角掕壊
|
|
const confirmDeleteRole = (role: UserRole) => {
|
|
deleteRole.value = role
|
|
showDeleteModal.value = true
|
|
}
|
|
|
|
// 创犻櫎用户名角掕壊
|
|
const deleteUserRole = async () => {
|
|
const role = deleteRole.value
|
|
if (role == null) return
|
|
try {
|
|
const result = await db.from('ak_user_roles')
|
|
.delete()
|
|
.eq('id', role.id)
|
|
.execute()
|
|
const { error } = result;
|
|
if (error != null) {
|
|
console.error('创犻櫎角掕壊澶辫触:', error)
|
|
uni.showToast({
|
|
title: '绉婚櫎角掕壊澶辫触',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
uni.showToast({
|
|
title: '角色已删除,
|
|
icon: 'success'
|
|
})
|
|
fetchUserRoles()
|
|
} catch (error) {
|
|
console.error('创犻櫎角掕壊寮傚父:', error)
|
|
uni.showToast({
|
|
title: '绉婚櫎角掕壊澶辫触',
|
|
icon: 'none'
|
|
})
|
|
} finally {
|
|
showDeleteModal.value = false
|
|
deleteRole.value = null
|
|
}
|
|
}
|
|
const confirmRolePicker = () => {
|
|
selectedRoleIndex.value = tempRoleIndex.value
|
|
showRolePicker.value = false
|
|
// 鍙€夛細角﹀彂 onRolePickerViewChange 閫昏緫
|
|
// onRolePickerViewChange({ detail: { value: [tempRoleIndex.value] } } as UniPickerViewChangeEvent)
|
|
}
|
|
const confirmRegionPicker = () => {
|
|
selectedRegionIndex.value = tempRegionIndex.value
|
|
showRegionPicker.value = false
|
|
// onRegionPickerViewChange({ detail: { value: [tempRegionIndex.value] } } as UniPickerViewChangeEvent)
|
|
}
|
|
const confirmSchoolPicker = () => {
|
|
selectedSchoolIndex.value = tempSchoolIndex.value
|
|
showSchoolPicker.value = false
|
|
// onSchoolPickerViewChange({ detail: { value: [tempSchoolIndex.value] } } as UniPickerViewChangeEvent)
|
|
}
|
|
const confirmGradePicker = () => {
|
|
selectedGradeIndex.value = tempGradeIndex.value
|
|
showGradePicker.value = false
|
|
// onGradePickerViewChange({ detail: { value: [tempGradeIndex.value] } } as UniPickerViewChangeEvent)
|
|
}
|
|
const confirmClassPicker = () => {
|
|
selectedClassIndex.value = tempClassIndex.value
|
|
showClassPicker.value = false
|
|
// onClassPickerViewChange({ detail: { value: [tempClassIndex.value] } } as any)
|
|
}
|
|
// 椤甸潰鍔犺浇
|
|
onLoad((op:UTSJSONObject) => {
|
|
console.log(op)
|
|
userId.value = op?.getString("id") ?? ""
|
|
if (userId.value==null) {
|
|
uni.showToast({
|
|
title: '用户名ID涓嶈兘涓虹┖',
|
|
icon: 'none'
|
|
})
|
|
|
|
}
|
|
|
|
fetchUserInfo()
|
|
fetchUserRoles()
|
|
fetchRoles()
|
|
fetchRegions()
|
|
checkPermissions()
|
|
})
|
|
console.log('ak detail 33')
|
|
return {
|
|
loading,
|
|
user,
|
|
userRoles,
|
|
showEditModal,
|
|
editForm,
|
|
showRoleModal,
|
|
roleOptions,
|
|
selectedRoleIndex,
|
|
roleForm,
|
|
showScopeSelection,
|
|
regionOptions,
|
|
selectedRegionIndex,
|
|
schoolOptions,
|
|
selectedSchoolIndex,
|
|
gradeOptions,
|
|
selectedGradeIndex,
|
|
classOptions,
|
|
selectedClassIndex,
|
|
canAddRole,
|
|
showDeleteModal,
|
|
deleteRole,
|
|
canManageUserInfo,
|
|
canManageUserRoles,
|
|
|
|
// 鏂规硶
|
|
formatDate,
|
|
goBack,
|
|
saveUserInfo,
|
|
changeScopeType,
|
|
// 宸插簾寮冪殑 handleRegionChange/handleSchoolChange/handleGradeChange/handleClassChange 涓嶅啀瀵煎嚭
|
|
addRole,
|
|
confirmDeleteRole,
|
|
deleteUserRole,
|
|
// picker-view寮圭獥状态佸拰绱㈠紩
|
|
showRolePicker,
|
|
tempRoleIndex,
|
|
showRegionPicker,
|
|
tempRegionIndex,
|
|
showSchoolPicker,
|
|
tempSchoolIndex,
|
|
showGradePicker,
|
|
tempGradeIndex,
|
|
showClassPicker,
|
|
tempClassIndex,
|
|
// picker-view浜嬩欢
|
|
onRolePickerViewChange,
|
|
confirmRolePicker,
|
|
onRegionPickerViewChange,
|
|
confirmRegionPicker,
|
|
onSchoolPickerViewChange,
|
|
confirmSchoolPicker,
|
|
onGradePickerViewChange,
|
|
confirmGradePicker,
|
|
onClassPickerViewChange,
|
|
confirmClassPicker,
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
.user-detail-page {
|
|
flex: 1;
|
|
}
|
|
|
|
.container {
|
|
padding: 20px;
|
|
}
|
|
|
|
.page-header {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.back-button {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 5px 10px;
|
|
margin-right: 10px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.page-title {
|
|
flex: 1;
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.header-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.primary-btn {
|
|
height: 36px;
|
|
padding: 0 15px;
|
|
background-color: #1890ff;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.loading-container {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 200px;
|
|
}
|
|
|
|
.user-info-card, .roles-card {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
margin-bottom: 20px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.card-header {
|
|
padding: 15px 20px;
|
|
border-bottom: 1px solid #ebeef5;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.edit-link {
|
|
color: #1890ff;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.card-body {
|
|
padding: 15px 20px;
|
|
}
|
|
|
|
.info-row {
|
|
display: flex;
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.info-label {
|
|
width: 100px;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.info-value {
|
|
flex: 1;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-block;
|
|
padding: 2px 8px;
|
|
border-radius: 10px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.status-badge.active {
|
|
background-color: #f0f9eb;
|
|
color: #67c23a;
|
|
}
|
|
|
|
.status-badge.inactive {
|
|
background-color: #fef0f0;
|
|
color: #f56c6c;
|
|
}
|
|
|
|
.empty-text {
|
|
color: #909399;
|
|
text-align: center;
|
|
padding: 20px 0;
|
|
}
|
|
|
|
.role-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 12px 0;
|
|
border-bottom: 1px solid #ebeef5;
|
|
}
|
|
|
|
.role-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.role-info {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.role-name {
|
|
font-weight: normal;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.role-scope {
|
|
color: #606266;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
.role-level {
|
|
background-color: #f5f7fa;
|
|
color: #909399;
|
|
padding: 2px 6px;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.role-actions {
|
|
display: flex;
|
|
padding: 10px;
|
|
}
|
|
|
|
.delete-btn {
|
|
color: #f56c6c;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* 妯℃€佹鏍峰紡 */
|
|
.modal {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 1000;
|
|
}
|
|
|
|
.modal-content {
|
|
background-color: white;
|
|
width: 400px;
|
|
border-radius: 4px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
.modal-header {
|
|
padding: 15px;
|
|
border-bottom: 1px solid #ebeef5;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.modal-title {
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.close-btn {
|
|
font-size: 20px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.modal-body {
|
|
padding: 15px;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.form-label {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.modal-body input {
|
|
width: 100%;
|
|
height: 36px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
padding: 0 10px;
|
|
}
|
|
|
|
.picker-text {
|
|
display: inline-block;
|
|
width: 100%;
|
|
height: 36px;
|
|
line-height: 36px;
|
|
padding: 0 10px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.status-toggle, .scope-toggle {
|
|
display: flex;
|
|
}
|
|
|
|
.toggle-option {
|
|
flex: 1;
|
|
height: 36px;
|
|
line-height: 36px;
|
|
text-align: center;
|
|
border: 1px solid #dcdfe6;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.toggle-option:first-child {
|
|
border-radius: 4px 0 0 4px;
|
|
}
|
|
|
|
.toggle-option:last-child {
|
|
border-radius: 0 4px 4px 0;
|
|
}
|
|
|
|
.toggle-option.active {
|
|
background-color: #1890ff;
|
|
color: white;
|
|
border-color: #1890ff;
|
|
}
|
|
|
|
.role-confirm-text {
|
|
display: block;
|
|
font-weight: normal;
|
|
margin-top: 10px;
|
|
padding: 10px;
|
|
background-color: #f5f7fa;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.modal-footer {
|
|
padding: 10px 15px;
|
|
border-top: 1px solid #ebeef5;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.cancel-btn, .confirm-btn, .submit-btn {
|
|
padding: 8px 15px;
|
|
border-radius: 4px;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.cancel-btn {
|
|
border: 1px solid #dcdfe6;
|
|
background-color: white;
|
|
}
|
|
|
|
.confirm-btn, .submit-btn {
|
|
background-color: #1890ff;
|
|
color: white;
|
|
border: none;
|
|
}
|
|
</style> |