feat(个人中心): 个人中心部分接口
This commit is contained in:
parent
742d10690d
commit
c1e82b45d8
|
@ -123,6 +123,7 @@
|
|||
try {
|
||||
Message.loading(t('personal.switchOrgLoading'));
|
||||
await switchUserOrg(id, userStore.id || '');
|
||||
switchOrgVisible.value = false;
|
||||
Message.clear();
|
||||
Message.success(t('personal.switchOrgSuccess'));
|
||||
personalMenusVisible.value = false;
|
||||
|
@ -145,6 +146,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
const isActiveSwitchOrg = ref(false);
|
||||
const personalMenus = [
|
||||
{
|
||||
label: t('personal.info'),
|
||||
|
@ -155,10 +157,16 @@
|
|||
},
|
||||
{
|
||||
label: t('personal.switchOrg'),
|
||||
icon: <MsIcon type="icon-icon_switch_outlined1" class="text-[var(--color-text-4)]" />,
|
||||
icon: () => (
|
||||
<MsIcon
|
||||
type="icon-icon_switch_outlined1"
|
||||
class={isActiveSwitchOrg.value ? 'text-[rgb(var(--primary-5))]' : 'text-[var(--color-text-4)]'}
|
||||
/>
|
||||
),
|
||||
isTrigger: true,
|
||||
event: () => {
|
||||
switchOrgVisible.value = true;
|
||||
isActiveSwitchOrg.value = true;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -171,6 +179,14 @@
|
|||
},
|
||||
];
|
||||
|
||||
watch(
|
||||
() => personalMenusVisible.value,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
isActiveSwitchOrg.value = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
const personalInfoMenu = () => {
|
||||
return (
|
||||
<a-trigger
|
||||
|
@ -189,24 +205,36 @@
|
|||
}
|
||||
if (e.isTrigger) {
|
||||
return (
|
||||
<a-dropdown
|
||||
<a-trigger
|
||||
v-model:popup-visible={switchOrgVisible.value}
|
||||
trigger="click"
|
||||
unmount-on-close={false}
|
||||
popup-offset={14}
|
||||
position="right"
|
||||
class={['arco-trigger-menu switch-org-dropdown', switchOrgVisible.value ? 'block' : 'hidden']}
|
||||
v-slots={{
|
||||
content: () => (
|
||||
<>
|
||||
<div class="arco-trigger-menu-inner">
|
||||
<a-input-search
|
||||
v-model:model-value={orgKeyword.value}
|
||||
placeholder={t('personal.searchOrgPlaceholder')}
|
||||
/>
|
||||
<a-divider class="ms-dropdown-divider" />
|
||||
<a-divider margin="4px" />
|
||||
<div class="switch-org-dropdown-list">
|
||||
{orgList.value.map((item) => (
|
||||
<a-doption
|
||||
<div
|
||||
key={item.id}
|
||||
value={item.id}
|
||||
class={item.id === appStore.currentOrgId ? 'active-org' : ''}
|
||||
class={[
|
||||
'arco-trigger-menu-item !w-[calc(100%-12px)]',
|
||||
item.id === appStore.currentOrgId ? 'active-org' : '',
|
||||
]}
|
||||
onClick={() => {
|
||||
switchOrg(item.id);
|
||||
}}
|
||||
>
|
||||
{item.name}
|
||||
<a-tooltip content={item.name}>
|
||||
<div class="one-line-text max-w-[220px]">{item.name}</div>
|
||||
</a-tooltip>
|
||||
{item.id === appStore.currentOrgId ? (
|
||||
<MsTag
|
||||
type="primary"
|
||||
|
@ -217,27 +245,27 @@
|
|||
{t('personal.currentOrg')}
|
||||
</MsTag>
|
||||
) : null}
|
||||
</a-doption>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
onSelect={(orgId: string) => {
|
||||
switchOrg(orgId);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="arco-trigger-menu-item"
|
||||
class={
|
||||
isActiveSwitchOrg.value ? 'active-org arco-trigger-menu-item' : 'arco-trigger-menu-item'
|
||||
}
|
||||
onClick={() => {
|
||||
if (typeof e.event === 'function') {
|
||||
e.event();
|
||||
}
|
||||
}}
|
||||
>
|
||||
{e.icon}
|
||||
{e.icon()}
|
||||
{e.label}
|
||||
</div>
|
||||
</a-dropdown>
|
||||
</a-trigger>
|
||||
);
|
||||
}
|
||||
return (
|
||||
|
@ -434,6 +462,20 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.switch-org-dropdown {
|
||||
@apply absolute max-h-none;
|
||||
|
||||
width: 300px;
|
||||
.arco-trigger-popup-wrapper {
|
||||
@apply max-h-full;
|
||||
.switch-org-dropdown-list {
|
||||
@apply overflow-y-auto;
|
||||
.ms-scroll-bar();
|
||||
|
||||
max-height: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.active-org {
|
||||
color: rgb(var(--primary-5));
|
||||
background-color: rgb(var(--primary-1));
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary" class="mr-[14px]" :loading="updateLoading" @click="updateBaseInfo">
|
||||
<a-button type="primary" class="mr-[14px]" :loading="updateLoading" @click="editBaseInfo">
|
||||
{{ t('common.update') }}
|
||||
</a-button>
|
||||
<a-button type="secondary" :disabled="updateLoading" @click="cancelEdit">{{ t('common.cancel') }}</a-button>
|
||||
|
@ -89,11 +89,11 @@
|
|||
class="check-icon"
|
||||
/>
|
||||
</div>
|
||||
<div v-for="(avatar, index) of avatarList" :key="avatar" class="avatar" @click="changeAvatar(index)">
|
||||
<div v-for="(avatar, index) of avatarList" :key="avatar" class="avatar" @click="changeAvatar(avatar)">
|
||||
<MsAvatar :avatar="avatar" class="mb-[4px]" />
|
||||
<div class="text-[12px] text-[var(--color-text-1)]">{{ t('ms.personal.avatar', { index: index }) }}</div>
|
||||
<MsIcon
|
||||
v-if="activeAvatar === index"
|
||||
v-if="activeAvatar === avatar"
|
||||
type="icon-icon_succeed_filled"
|
||||
:style="{ color: 'rgb(var(--success-6))' }"
|
||||
class="check-icon"
|
||||
|
@ -126,6 +126,7 @@
|
|||
import MsTag from '@/components/pure/ms-tag/ms-tag.vue';
|
||||
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
||||
|
||||
import { getBaseInfo, updateBaseInfo } from '@/api/modules/user';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useUserStore from '@/store/modules/user/index';
|
||||
import { validateEmail, validatePhone } from '@/utils/validate';
|
||||
|
@ -136,6 +137,7 @@
|
|||
|
||||
const { t } = useI18n();
|
||||
|
||||
const loading = ref(false);
|
||||
const isEdit = ref(false);
|
||||
const descriptions = ref<Description[]>([
|
||||
{
|
||||
|
@ -162,6 +164,19 @@
|
|||
phone: userStore.phone,
|
||||
});
|
||||
const baseInfoFormRef = ref<FormInstance>();
|
||||
const orgList = ref([]);
|
||||
|
||||
onBeforeMount(async () => {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await getBaseInfo(userStore.id || '');
|
||||
console.log(res);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
});
|
||||
|
||||
const updateLoading = ref(false);
|
||||
|
||||
function cancelEdit() {
|
||||
|
@ -194,12 +209,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
function updateBaseInfo() {
|
||||
function editBaseInfo() {
|
||||
baseInfoFormRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
updateLoading.value = true;
|
||||
await updateBaseInfo({
|
||||
id: userStore.id || '',
|
||||
username: baseInfoForm.value.name || '',
|
||||
email: baseInfoForm.value.email || '',
|
||||
phone: baseInfoForm.value.phone || '',
|
||||
avatar: userStore.avatar || '',
|
||||
});
|
||||
Message.success(t('common.updateSuccess'));
|
||||
await userStore.isLogin();
|
||||
isEdit.value = false;
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
@ -212,25 +235,8 @@
|
|||
}
|
||||
|
||||
const avatarModalVisible = ref(false);
|
||||
|
||||
async function handleChangeAvatarConfirm(done: (closed: boolean) => void) {
|
||||
try {
|
||||
// if (replaceVersion.value !== '') {
|
||||
// await useLatestVersion(replaceVersion.value);
|
||||
// }
|
||||
// await toggleVersionStatus(activeRecord.value.id);
|
||||
Message.success(t('common.updateSuccess'));
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
done(false);
|
||||
} finally {
|
||||
done(true);
|
||||
}
|
||||
}
|
||||
|
||||
const activeAvatarType = ref<'builtIn' | 'word'>('builtIn');
|
||||
const activeAvatar = ref<string | number>('default');
|
||||
const activeAvatar = ref('default');
|
||||
const avatarList = ref<string[]>([]);
|
||||
let i = 1;
|
||||
while (i <= 46) {
|
||||
|
@ -238,9 +244,29 @@
|
|||
i++;
|
||||
}
|
||||
|
||||
function changeAvatar(avatar: string | number) {
|
||||
function changeAvatar(avatar: string) {
|
||||
activeAvatar.value = avatar;
|
||||
}
|
||||
|
||||
async function handleChangeAvatarConfirm(done: (closed: boolean) => void) {
|
||||
try {
|
||||
await updateBaseInfo({
|
||||
id: userStore.id || '',
|
||||
username: baseInfoForm.value.name || '',
|
||||
email: baseInfoForm.value.email || '',
|
||||
phone: baseInfoForm.value.phone || '',
|
||||
avatar: activeAvatar.value,
|
||||
});
|
||||
Message.success(t('common.updateSuccess'));
|
||||
await userStore.isLogin();
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
done(false);
|
||||
} finally {
|
||||
done(true);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -37,9 +37,15 @@
|
|||
import MsPasswordInput from '@/components/pure/ms-password-input/index.vue';
|
||||
import MsFormItemSub from '@/components/business/ms-form-item-sub/index.vue';
|
||||
|
||||
import { updatePsw } from '@/api/modules/user';
|
||||
import { useI18n } from '@/hooks/useI18n';
|
||||
import useUser from '@/hooks/useUser';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { encrypted } from '@/utils';
|
||||
import { validatePasswordLength, validateWordPassword } from '@/utils/validate';
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { logout } = useUser();
|
||||
const { t } = useI18n();
|
||||
|
||||
const form = ref({
|
||||
|
@ -80,12 +86,26 @@
|
|||
],
|
||||
};
|
||||
|
||||
const counting = ref(3);
|
||||
|
||||
function changePsw() {
|
||||
formRef.value?.validate(async (errors) => {
|
||||
if (!errors) {
|
||||
try {
|
||||
loading.value = true;
|
||||
Message.success(t('common.updateSuccess'));
|
||||
await updatePsw({
|
||||
id: userStore.id || '',
|
||||
newPassword: encrypted(form.value.newPsw) || '',
|
||||
oldPassword: encrypted(form.value.password) || '',
|
||||
});
|
||||
Message.success({
|
||||
content: t('ms.personal.updatePswSuccess', { count: counting.value }),
|
||||
duration: 4000,
|
||||
});
|
||||
setInterval(() => counting.value--, 1000);
|
||||
setTimeout(() => {
|
||||
logout();
|
||||
}, 3000);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
|
|
|
@ -112,6 +112,25 @@ export interface UserRoleRelation {
|
|||
createUser: string;
|
||||
}
|
||||
// 个人信息
|
||||
export interface PersonalOrganization {
|
||||
id: string;
|
||||
num: number;
|
||||
organizationId: string;
|
||||
name: string;
|
||||
description: string;
|
||||
createTime: number;
|
||||
updateTime: number;
|
||||
updateUser: string;
|
||||
createUser: string;
|
||||
deleteTime: number;
|
||||
deleted: boolean;
|
||||
deleteUser: string;
|
||||
enable: boolean;
|
||||
moduleSetting: string;
|
||||
}
|
||||
export interface OrganizationProjectMap {
|
||||
[key: string]: PersonalOrganization[];
|
||||
}
|
||||
export interface PersonalInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -128,15 +147,9 @@ export interface PersonalInfo {
|
|||
createUser: string;
|
||||
updateUser: string;
|
||||
deleted: boolean;
|
||||
userRoles: UserRole[];
|
||||
userRoleRelations: UserRoleRelation[];
|
||||
userRolePermissions: UserRolePermission[];
|
||||
platformInfo: string;
|
||||
seleniumServer: string;
|
||||
apiServer: string;
|
||||
avatar: string;
|
||||
organizationProjectMap: OrganizationProjectMap;
|
||||
}
|
||||
|
||||
export interface UpdateBaseInfo {
|
||||
id: string;
|
||||
username: string;
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
<a-button type="primary" @click="handleAddClick">{{ t('project.fileManagement.addFile') }}</a-button>
|
||||
<div class="header-right">
|
||||
<a-select v-model="tableFileType" class="w-[240px]" :loading="fileTypeLoading" @change="searchList">
|
||||
<template #prefix>
|
||||
{{ t('project.fileManagement.type') }}
|
||||
</template>
|
||||
<a-option key="" value="">{{ t('common.all') }}</a-option>
|
||||
<a-option v-for="item of tableFileTypeOptions" :key="item" :value="item">
|
||||
{{ item }}
|
||||
|
|
Loading…
Reference in New Issue