256 lines
7.1 KiB
JavaScript
256 lines
7.1 KiB
JavaScript
import {computed, reactive, ref} from 'vue'
|
|
|
|
import lang from '../../../i18n/i18n';
|
|
|
|
import {http} from "@/utils/axios";
|
|
|
|
import {ElNotification} from "element-plus";
|
|
|
|
import {Plus} from "@element-plus/icons-vue";
|
|
|
|
import {useGlobalStatusStore} from "@/stores/useGlobalStatusStore";
|
|
import {confirmRecentAuthentication, isRecentAuthenticationCancelled, requestWithRecentAuthentication} from '@/utils/recentAuthentication'
|
|
import {roleMeta, assignableRoles, canManageUser} from '@/utils/userRoles.mjs'
|
|
|
|
export function recoveryCodeMeta(configured) {
|
|
return configured
|
|
? { label: '已开启', type: 'success' }
|
|
: { label: '未开启', type: 'info' }
|
|
}
|
|
|
|
export function externalEmailMeta(enabled, configured) {
|
|
if (!enabled) {
|
|
return { label: '已关闭', type: 'warning' }
|
|
}
|
|
return configured
|
|
? { label: '已绑定', type: 'success' }
|
|
: { label: '未绑定', type: 'info' }
|
|
}
|
|
|
|
export function accountStatusMeta(disabled) {
|
|
return disabled === 1
|
|
? { label: '已禁用', type: 'danger' }
|
|
: { label: '正常', type: 'success' }
|
|
}
|
|
|
|
export function isSameUser(selectedUser, currentUser) {
|
|
const selectedID = Number(selectedUser?.ID || 0)
|
|
const currentID = Number(currentUser?.id || 0)
|
|
if (selectedID > 0 && currentID > 0) {
|
|
return selectedID === currentID
|
|
}
|
|
return Boolean(selectedUser?.Account && currentUser?.account)
|
|
&& selectedUser.Account === currentUser.account
|
|
}
|
|
|
|
export function canManageRecoveryCode(user) {
|
|
return Boolean(user?.ID) && user.Role !== 'super_admin'
|
|
}
|
|
|
|
export function usePage() {
|
|
const globalStatus = useGlobalStatusStore()
|
|
|
|
const userList = reactive([])
|
|
|
|
const currentPage = ref(1)
|
|
|
|
const totalPage = ref(1)
|
|
|
|
const userInfoDialog = ref(false)
|
|
|
|
const editModel = ref("edit")
|
|
|
|
const selectedUser = ref(null)
|
|
|
|
const recoveryCodeDialogVisible = ref(false)
|
|
|
|
const externalEmailDialogVisible = ref(false)
|
|
|
|
const securityDialogOpening = ref('')
|
|
|
|
const submitting = ref(false)
|
|
|
|
const availableRoles = computed(() => assignableRoles(globalStatus.role))
|
|
|
|
const canCreateUser = computed(() => globalStatus.hasCapability('user.create'))
|
|
|
|
const canEditSelectedUser = computed(() => editModel.value === 'create'
|
|
? canCreateUser.value && availableRoles.value.length > 0
|
|
: canManageUser(globalStatus.role, selectedUser.value?.Role))
|
|
|
|
const canSelectRole = computed(() => canEditSelectedUser.value
|
|
&& (editModel.value === 'create' || globalStatus.hasCapability('role.manage')))
|
|
|
|
const editingCurrentUser = computed(() => isSameUser(selectedUser.value, globalStatus.userInfos))
|
|
|
|
const recoveryCodeWebManaged = computed(() => canManageRecoveryCode(selectedUser.value))
|
|
|
|
const editUserInfo = reactive({
|
|
"account": "",
|
|
"name": "",
|
|
"password": "",
|
|
"disabled": false,
|
|
"role": "user"
|
|
})
|
|
|
|
const roleChanged = computed(() => editModel.value === 'edit'
|
|
&& editUserInfo.role !== selectedUser.value?.Role)
|
|
|
|
const title = ref(lang.editUser)
|
|
|
|
const reflushList = function () {
|
|
http.post('/api/v1/user/list', {"current_page": currentPage.value, "page_size": 6}).then(res => {
|
|
userList.length = 0
|
|
totalPage.value = res.data.total_page
|
|
if (res.data["list"]) {
|
|
userList.push(...res.data["list"])
|
|
if (selectedUser.value?.ID) {
|
|
selectedUser.value = userList.find(item => item.ID === selectedUser.value.ID) || selectedUser.value
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
const handleEdit = function (idx, row) {
|
|
selectedUser.value = row
|
|
editUserInfo.account = row.Account
|
|
editUserInfo.name = row.Name
|
|
editUserInfo.disabled = row.Disabled === 1
|
|
editUserInfo.password = ""
|
|
editUserInfo.role = row.Role
|
|
editModel.value = "edit"
|
|
title.value = lang.editUser
|
|
userInfoDialog.value = true
|
|
}
|
|
|
|
const createUser = function () {
|
|
if (!canCreateUser.value) return
|
|
selectedUser.value = null
|
|
editUserInfo.account = ""
|
|
editUserInfo.name = ""
|
|
editUserInfo.disabled = false
|
|
editUserInfo.password = ""
|
|
editUserInfo.role = "user"
|
|
editModel.value = "create"
|
|
title.value = lang.newUser
|
|
userInfoDialog.value = true
|
|
}
|
|
|
|
const confirmSecurityDialogAccess = async function (dialogName) {
|
|
if (securityDialogOpening.value) return false
|
|
securityDialogOpening.value = dialogName
|
|
try {
|
|
await confirmRecentAuthentication()
|
|
return true
|
|
} catch (error) {
|
|
if (!isRecentAuthenticationCancelled(error)) {
|
|
ElNotification({
|
|
title: lang.fail,
|
|
message: error?.message || '身份确认失败',
|
|
type: 'error',
|
|
})
|
|
}
|
|
return false
|
|
} finally {
|
|
securityDialogOpening.value = ''
|
|
}
|
|
}
|
|
|
|
const openRecoveryCodeDialog = async function () {
|
|
if (!recoveryCodeWebManaged.value) return
|
|
if (!await confirmSecurityDialogAccess('recovery-code')) return
|
|
recoveryCodeDialogVisible.value = true
|
|
}
|
|
|
|
const openExternalEmailDialog = async function () {
|
|
if (!selectedUser.value?.ID) return
|
|
if (!await confirmSecurityDialogAccess('external-email')) return
|
|
externalEmailDialogVisible.value = true
|
|
}
|
|
|
|
const handleSecurityChanged = function () {
|
|
reflushList()
|
|
}
|
|
|
|
const submit = async function () {
|
|
if (submitting.value || !canEditSelectedUser.value) return
|
|
submitting.value = true
|
|
try {
|
|
const creating = editModel.value === 'create'
|
|
const newData = {
|
|
"account": editUserInfo.account,
|
|
"username": editUserInfo.name,
|
|
"disabled": editUserInfo.disabled ? 1 : 0
|
|
}
|
|
if (creating || roleChanged.value) newData.role = editUserInfo.role
|
|
if (creating || editUserInfo.password !== '') newData.password = editUserInfo.password
|
|
const res = await requestWithRecentAuthentication(() => creating
|
|
? http.post('/api/v1/user/create', newData)
|
|
: http.post('/api/v1/user/edit', newData))
|
|
if (!res || res.errorNo !== 0) {
|
|
throw new Error(res?.errorMsg || '保存用户失败')
|
|
}
|
|
ElNotification({ title: lang.succ, message: '用户信息已保存', type: 'success' })
|
|
editUserInfo.password = ''
|
|
reflushList()
|
|
userInfoDialog.value = false
|
|
} catch (error) {
|
|
if (!isRecentAuthenticationCancelled(error)) {
|
|
ElNotification({
|
|
title: lang.fail,
|
|
message: error?.message || '保存用户失败,请稍后重试',
|
|
type: 'error'
|
|
})
|
|
}
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
|
|
reflushList()
|
|
|
|
return {
|
|
reactive,
|
|
ref,
|
|
lang,
|
|
http,
|
|
ElNotification,
|
|
Plus,
|
|
userList,
|
|
currentPage,
|
|
totalPage,
|
|
userInfoDialog,
|
|
editModel,
|
|
editUserInfo,
|
|
availableRoles,
|
|
canCreateUser,
|
|
canEditSelectedUser,
|
|
canSelectRole,
|
|
roleChanged,
|
|
submitting,
|
|
selectedUser,
|
|
editingCurrentUser,
|
|
recoveryCodeWebManaged,
|
|
recoveryCodeDialogVisible,
|
|
externalEmailDialogVisible,
|
|
securityDialogOpening,
|
|
openRecoveryCodeDialog,
|
|
openExternalEmailDialog,
|
|
handleSecurityChanged,
|
|
title,
|
|
reflushList,
|
|
handleEdit,
|
|
createUser,
|
|
submit,
|
|
roleMeta,
|
|
recoveryCodeMeta,
|
|
externalEmailMeta,
|
|
accountStatusMeta
|
|
}
|
|
}
|
|
|
|
export {
|
|
Plus,
|
|
roleMeta
|
|
}
|