提交个人中心

qhw-dev-0927
tengxi 1 year ago
parent 3e7b757943
commit 91c3f4ba04

@ -0,0 +1,156 @@
<script lang="ts" setup>
import { Avatar, Dropdown, Menu, MenuDivider } from 'ant-design-vue'
import { UserOutlined } from '@ant-design/icons-vue'
import type { MenuInfo } from 'ant-design-vue/lib/menu/src/interface'
import { computed } from 'vue'
import { DOC_URL } from '@/settings/siteSetting'
import { useUserStore } from '@/store/modules/user'
import { useHeaderSetting } from '@/hooks/setting/useHeaderSetting'
import { useI18n } from '@/hooks/web/useI18n'
import { useDesign } from '@/hooks/web/useDesign'
import { useModal } from '@/components/Modal'
import headerImg from '@/assets/images/header.jpg'
import { propTypes } from '@/utils/propTypes'
import { openWindow } from '@/utils'
import { useGo } from '@/hooks/web/usePage'
import { createAsyncComponent } from '@/utils/factory/createAsyncComponent'
defineOptions({ name: 'UserDropdown' })
defineProps({
theme: propTypes.oneOf(['dark', 'light']),
})
const go = useGo()
type MenuEvent = 'profile' | 'logout' | 'doc' | 'lock'
const MenuItem = createAsyncComponent(() => import('./DropMenuItem.vue'))
const LockAction = createAsyncComponent(() => import('../lock/LockModal.vue'))
const { prefixCls } = useDesign('header-user-dropdown')
const { t } = useI18n()
const { getShowDoc, getUseLockPage } = useHeaderSetting()
const userStore = useUserStore()
const getUserInfo = computed(() => {
const { nickname = '', avatar } = userStore.getUserInfo.user || {}
return { nickname, avatar: avatar || headerImg }
})
const [register, { openModal }] = useModal()
function handleLock() {
openModal(true)
}
// login out
function handleLoginOut() {
userStore.confirmLoginOut()
}
// open doc
function openDoc() {
openWindow(DOC_URL)
}
function openProfile() {
go('/profile/index')
}
function handleMenuClick(e: MenuInfo) {
switch (e.key as MenuEvent) {
case 'profile':
openProfile()
break
case 'logout':
handleLoginOut()
break
case 'doc':
openDoc()
break
case 'lock':
handleLock()
break
}
}
</script>
<template>
<Dropdown placement="bottomLeft" :overlay-class-name="`${prefixCls}-dropdown-overlay`">
<span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex">
<Avatar size="small" :class="`${prefixCls}__avatar`" :src="getUserInfo.avatar">
<template #icon>
<UserOutlined />
</template>
</Avatar>
<span :class="`${prefixCls}__info hidden md:block`">
<span :class="`${prefixCls}__name`" class="truncate">
{{ getUserInfo.nickname }}
</span>
</span>
</span>
<template #overlay>
<Menu @click="handleMenuClick">
<MenuItem key="profile" :text="t('layout.header.accountCenter')" icon="ion:person-outline" />
<MenuItem
v-if="getShowDoc" key="doc" :text="t('layout.header.dropdownItemDoc')"
icon="ion:document-text-outline"
/>
<MenuDivider v-if="getShowDoc" />
<MenuItem
v-if="getUseLockPage" key="lock" :text="t('layout.header.tooltipLock')"
icon="ion:lock-closed-outline"
/>
<MenuItem key="logout" :text="t('layout.header.dropdownItemLoginOut')" icon="ion:power-outline" />
</Menu>
</template>
</Dropdown>
<LockAction @register="register" />
</template>
<style lang="less">
@prefix-cls: ~'@{namespace}-header-user-dropdown';
.@{prefix-cls} {
align-items: center;
height: @header-height;
padding: 0 0 0 10px;
padding-right: 10px;
overflow: hidden;
font-size: 12px;
cursor: pointer;
&__avatar {
margin-right: 5px;
border-radius: 50%;
}
&__name {
font-size: 14px;
}
&--dark {
&:hover {
background-color: @header-dark-bg-hover-color;
}
}
&--light {
&:hover {
background-color: @header-light-bg-hover-color;
}
.@{prefix-cls}__desc {
color: @header-light-desc-color;
}
}
&-dropdown-overlay {
.ant-dropdown-menu-item {
min-width: 160px;
}
}
}
</style>

@ -0,0 +1,78 @@
<script lang="ts" setup>
import NoticeModal from './NoticeModal.vue'
import { columns, searchFormSchema } from './notice.data'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useModal } from '@/components/Modal'
import { IconEnum } from '@/enums/appEnum'
import { BasicTable, TableAction, useTable } from '@/components/Table'
import { deleteNotice, getNoticePage } from '@/api/system/notice'
defineOptions({ name: 'SystemNotice' })
const { t } = useI18n()
const { createMessage } = useMessage()
const [registerModal, { openModal }] = useModal()
const [registerTable, { reload }] = useTable({
title: '公告列表',
api: getNoticePage,
columns,
formConfig: { labelWidth: 120, schemas: searchFormSchema },
useSearchForm: true,
showTableSetting: true,
showIndexColumn: false,
actionColumn: {
width: 140,
title: t('common.action'),
dataIndex: 'action',
fixed: 'right',
},
})
function handleCreate() {
openModal(true, { isUpdate: false })
}
function handleEdit(record: Recordable) {
openModal(true, { record, isUpdate: true })
}
async function handleDelete(record: Recordable) {
await deleteNotice(record.id)
createMessage.success(t('common.delSuccessText'))
reload()
}
</script>
<template>
<div>
<BasicTable @register="registerTable">
<template #toolbar>
<a-button v-auth="['system:notice:create']" type="primary" :pre-icon="IconEnum.ADD" @click="handleCreate">
{{ t('action.create') }}
</a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{ icon: IconEnum.EDIT, label: t('action.edit'), auth: 'system:notice:update', onClick: handleEdit.bind(null, record) },
{
icon: IconEnum.DELETE,
danger: true,
label: t('action.delete'),
auth: 'system:notice:delete',
popConfirm: {
title: t('common.delMessage'),
placement: 'left',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</template>
</template>
</BasicTable>
<NoticeModal @register="registerModal" @success="reload()" />
</div>
</template>

@ -0,0 +1,56 @@
<script lang="ts" setup>
import { columns, searchFormSchema } from './message.data'
import { IconEnum } from '@/enums/appEnum'
import { useI18n } from '@/hooks/web/useI18n'
import { BasicTable, TableAction, useTable } from '@/components/Table'
import { getNotifyMessagePage } from '@/api/system/notify/message'
import MessageInfoModal from '@/views/system/notify/components/MessageInfoModal.vue'
import { useModal } from '@/components/Modal'
defineOptions({ name: 'SystemMessage' })
const { t } = useI18n()
const [registerTable] = useTable({
title: '站内信记录列表',
api: getNotifyMessagePage,
columns,
formConfig: { labelWidth: 120, schemas: searchFormSchema },
useSearchForm: true,
showTableSetting: true,
showIndexColumn: false,
actionColumn: {
width: 100,
title: t('common.action'),
fixed: 'right',
key: 'action',
},
})
const [registerModal, { openModal }] = useModal()
function handleShowInfo(record: Recordable) {
openModal(true, record)
}
</script>
<template>
<div>
<BasicTable @register="registerTable">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
label: t('action.detail'),
icon: IconEnum.LOG,
onClick: handleShowInfo.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
<MessageInfoModal @register="registerModal" />
</div>
</template>

@ -0,0 +1,142 @@
<script lang="ts" setup>
import { reactive } from 'vue'
import UserModal from './UserModal.vue'
import UserRoleModal from './UserRoleModal.vue'
import ResetPwdModal from './ResetPwdModal.vue'
import DeptTree from './DeptTree.vue'
import { columns, searchFormSchema } from './user.data'
import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { useModal } from '@/components/Modal'
import { IconEnum } from '@/enums/appEnum'
import { BasicTable, TableAction, useTable } from '@/components/Table'
import type { UserExportReqVO } from '@/api/system/user'
import { deleteUser, exportUser, getUserPage } from '@/api/system/user'
defineOptions({ name: 'SystemUser' })
const { t } = useI18n()
const { createConfirm, createMessage } = useMessage()
const [registerModal, { openModal }] = useModal()
const [registerRoleModal, { openModal: openRoleModal }] = useModal()
const [registerPwdModal, { openModal: openPwdModal }] = useModal()
const searchInfo = reactive<Recordable>({})
const [registerTable, { getForm, reload }] = useTable({
title: '账号列表',
api: getUserPage,
columns,
formConfig: {
labelWidth: 120,
schemas: searchFormSchema,
autoSubmitOnEnter: true,
},
useSearchForm: true,
showTableSetting: true,
showIndexColumn: false,
actionColumn: {
width: 140,
title: t('common.action'),
dataIndex: 'action',
fixed: 'right',
},
})
/** 新增按钮操作 */
function handleCreate() {
openModal(true, { isUpdate: false })
}
/** 导出按钮操作 */
async function handleExport() {
createConfirm({
title: t('common.exportTitle'),
iconType: 'warning',
content: t('common.exportMessage'),
async onOk() {
await exportUser(getForm().getFieldsValue() as UserExportReqVO)
createMessage.success(t('common.exportSuccessText'))
},
})
}
/** 修改按钮操作 */
function handleEdit(record: Recordable) {
openModal(true, { record, isUpdate: true })
}
/** 分配用户角色操作 */
function handleRole(record: Recordable) {
openRoleModal(true, { record })
}
/** 重置密码按钮操作 */
function handleResetPwd(record: Recordable) {
openPwdModal(true, { record })
}
/** 删除按钮操作 */
async function handleDelete(record: Recordable) {
await deleteUser(record.id)
createMessage.success(t('common.delSuccessText'))
reload()
}
/** 点击部门操作 */
function handleSelect(deptId = '') {
searchInfo.deptId = deptId
reload()
}
</script>
<template>
<div class="flex">
<DeptTree class="w-1/4 xl:w-1/5" @select="handleSelect" />
<BasicTable class="w-3/4 xl:w-4/5" :search-info="searchInfo" @register="registerTable">
<template #toolbar>
<a-button v-auth="['system:user:create']" type="primary" :pre-icon="IconEnum.ADD" @click="handleCreate">
{{ t('action.create') }}
</a-button>
<a-button v-auth="['system:user:export']" :pre-icon="IconEnum.EXPORT" @click="handleExport">
{{ t('action.export') }}
</a-button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{ icon: IconEnum.EDIT, label: t('action.edit'), auth: 'system:user:update', onClick: handleEdit.bind(null, record) },
]"
:drop-down-actions="[
{
icon: IconEnum.EDIT,
label: '分配角色',
auth: 'system:permission:assign-user-role',
onClick: handleRole.bind(null, record),
},
{
icon: IconEnum.EDIT,
label: '重置密码',
auth: 'system:user:update-password',
onClick: handleResetPwd.bind(null, record),
},
{
icon: IconEnum.DELETE,
danger: true,
label: t('action.delete'),
auth: 'system:user:delete',
popConfirm: {
title: t('common.delMessage'),
placement: 'left',
confirm: handleDelete.bind(null, record),
},
},
]"
/>
</template>
</template>
</BasicTable>
<UserModal @register="registerModal" @success="reload()" />
<UserRoleModal @register="registerRoleModal" @success="reload()" />
<ResetPwdModal @register="registerPwdModal" @success="reload()" />
</div>
</template>
Loading…
Cancel
Save