基于naive ui重构设置-团队页面及弹窗
This commit is contained in:
parent
8b617d833b
commit
345d3db483
@ -1,88 +1,162 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog
|
<n-modal
|
||||||
:options="{
|
v-model:show="showDialog"
|
||||||
title: $t('Add New Member'),
|
preset="card"
|
||||||
actions: [
|
:title="$t('Add New Member')"
|
||||||
{
|
:style="modalStyle"
|
||||||
label: $t('Invite Member'),
|
:mask-closable="true"
|
||||||
variant: 'solid',
|
:close-on-esc="true"
|
||||||
onClick: inviteMember,
|
class="invite-member-modal"
|
||||||
},
|
|
||||||
],
|
|
||||||
}"
|
|
||||||
v-model="show"
|
|
||||||
>
|
>
|
||||||
<template #body-content>
|
<template #header>
|
||||||
<div class="space-y-4">
|
<span class="text-lg font-semibold">{{ $t('Add New Member') }}</span>
|
||||||
<FormControl :label="$t('Username')" v-model="username" />
|
</template>
|
||||||
<div
|
<n-space vertical :size="20">
|
||||||
v-if="$resources.roles.data?.length > 0"
|
<n-form-item :label="$t('Username')" :required="true">
|
||||||
class="flex items-center space-x-2"
|
<n-input
|
||||||
>
|
v-model:value="username"
|
||||||
<FormControl
|
placeholder=""
|
||||||
class="w-full"
|
:size="inputSize"
|
||||||
type="autocomplete"
|
class="w-full"
|
||||||
:label="$t('Select Role')"
|
/>
|
||||||
:options="roleOptions"
|
</n-form-item>
|
||||||
v-model="selectedRole"
|
<div v-if="$resources.roles.data?.length > 0" class="space-y-4">
|
||||||
/>
|
<div class="flex items-end gap-2">
|
||||||
<Button
|
<n-form-item :label="$t('Select Role')" class="flex-1">
|
||||||
:label="$t('Add')"
|
<n-select
|
||||||
icon-left="plus"
|
v-model:value="selectedRole"
|
||||||
|
:options="roleOptions"
|
||||||
|
:placeholder="$t('Select a role')"
|
||||||
|
:size="inputSize"
|
||||||
|
class="w-full"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-button
|
||||||
|
type="primary"
|
||||||
:disabled="!selectedRole"
|
:disabled="!selectedRole"
|
||||||
@click="addRole"
|
@click="addRole"
|
||||||
class="mt-5"
|
:size="buttonSize"
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="selectedRoles.length > 0"
|
|
||||||
class="divide-y rounded border border-gray-300 px-1.5"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex w-full items-center space-x-2 py-1.5"
|
|
||||||
v-for="role in selectedRoles"
|
|
||||||
>
|
>
|
||||||
<div class="flex w-full items-center justify-between px-3 py-2">
|
<template #icon>
|
||||||
<div class="text-base text-gray-800">{{ role.label }}</div>
|
<n-icon><PlusIcon /></n-icon>
|
||||||
</div>
|
</template>
|
||||||
<Button
|
{{ $t('Add') }}
|
||||||
class="ml-auto"
|
</n-button>
|
||||||
variant="ghost"
|
</div>
|
||||||
icon="x"
|
<div v-if="selectedRoles.length > 0" class="space-y-2">
|
||||||
|
<div
|
||||||
|
v-for="role in selectedRoles"
|
||||||
|
:key="role.value"
|
||||||
|
class="flex items-center justify-between p-3 rounded border border-gray-200 bg-gray-50"
|
||||||
|
>
|
||||||
|
<div class="text-base text-gray-800">{{ role.label }}</div>
|
||||||
|
<n-button
|
||||||
|
tertiary
|
||||||
|
circle
|
||||||
|
size="small"
|
||||||
@click="removeRole(role.value)"
|
@click="removeRole(role.value)"
|
||||||
/>
|
>
|
||||||
|
<template #icon>
|
||||||
|
<n-icon><XIcon /></n-icon>
|
||||||
|
</template>
|
||||||
|
</n-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<n-alert
|
||||||
|
v-if="$team.inviteTeamMember.error"
|
||||||
|
type="error"
|
||||||
|
:title="getErrorMessage($team.inviteTeamMember.error)"
|
||||||
|
/>
|
||||||
|
</n-space>
|
||||||
|
<template #action>
|
||||||
|
<n-space :vertical="isMobile" :size="isMobile ? 12 : 16" class="w-full">
|
||||||
|
<n-button @click="hide" :block="isMobile" :size="buttonSize">
|
||||||
|
{{ $t('Cancel') }}
|
||||||
|
</n-button>
|
||||||
|
<n-button
|
||||||
|
type="primary"
|
||||||
|
:loading="$team.inviteTeamMember.loading"
|
||||||
|
@click="inviteMember"
|
||||||
|
:block="isMobile"
|
||||||
|
:size="buttonSize"
|
||||||
|
>
|
||||||
|
{{ $t('Invite Member') }}
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</n-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {
|
||||||
|
NModal,
|
||||||
|
NFormItem,
|
||||||
|
NInput,
|
||||||
|
NSpace,
|
||||||
|
NAlert,
|
||||||
|
NButton,
|
||||||
|
NSelect,
|
||||||
|
NIcon,
|
||||||
|
} from 'naive-ui';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
|
import PlusIcon from '~icons/lucide/plus';
|
||||||
|
import XIcon from '~icons/lucide/x';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
NModal,
|
||||||
|
NFormItem,
|
||||||
|
NInput,
|
||||||
|
NSpace,
|
||||||
|
NAlert,
|
||||||
|
NButton,
|
||||||
|
NSelect,
|
||||||
|
NIcon,
|
||||||
|
PlusIcon,
|
||||||
|
XIcon,
|
||||||
|
},
|
||||||
|
emits: ['success', 'update:modelValue'],
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
username: '',
|
username: '',
|
||||||
show: true,
|
|
||||||
selectedRoles: [],
|
selectedRoles: [],
|
||||||
selectedRole: null,
|
selectedRole: null,
|
||||||
|
windowWidth: window.innerWidth,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
resources: {
|
computed: {
|
||||||
roles() {
|
showDialog: {
|
||||||
|
get() {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit('update:modelValue', value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isMobile() {
|
||||||
|
return this.windowWidth <= 768;
|
||||||
|
},
|
||||||
|
modalStyle() {
|
||||||
return {
|
return {
|
||||||
type: 'list',
|
width: this.isMobile ? '95vw' : '700px',
|
||||||
pagetype: 'Jcloud Role',
|
maxWidth: this.isMobile ? '95vw' : '90vw',
|
||||||
fields: ['name', 'title'],
|
|
||||||
initialData: [],
|
|
||||||
auto: true,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
inputSize() {
|
||||||
computed: {
|
return this.isMobile ? 'medium' : 'large';
|
||||||
|
},
|
||||||
|
buttonSize() {
|
||||||
|
return this.isMobile ? 'medium' : 'medium';
|
||||||
|
},
|
||||||
roleOptions() {
|
roleOptions() {
|
||||||
|
if (!this.$resources.roles.data) return [];
|
||||||
return this.$resources.roles.data
|
return this.$resources.roles.data
|
||||||
.filter((role) => {
|
.filter((role) => {
|
||||||
return !this.selectedRoles.some(
|
return !this.selectedRoles.some(
|
||||||
@ -95,11 +169,36 @@ export default {
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.handleResize();
|
||||||
|
window.addEventListener('resize', this.handleResize);
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
window.removeEventListener('resize', this.handleResize);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handleResize() {
|
||||||
|
this.windowWidth = window.innerWidth;
|
||||||
|
},
|
||||||
|
getErrorMessage(error) {
|
||||||
|
if (!error) return '';
|
||||||
|
if (typeof error === 'string') return error;
|
||||||
|
if (error.message) return error.message;
|
||||||
|
if (error.messages && Array.isArray(error.messages)) {
|
||||||
|
return error.messages.join('\n');
|
||||||
|
}
|
||||||
|
return String(error);
|
||||||
|
},
|
||||||
addRole() {
|
addRole() {
|
||||||
if (this.selectedRole) {
|
if (this.selectedRole) {
|
||||||
this.selectedRoles.push(this.selectedRole);
|
const role = this.$resources.roles.data.find(r => r.name === this.selectedRole);
|
||||||
this.selectedRole = null;
|
if (role) {
|
||||||
|
this.selectedRoles.push({
|
||||||
|
label: role.title,
|
||||||
|
value: role.name,
|
||||||
|
});
|
||||||
|
this.selectedRole = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeRole(roleToRemove) {
|
removeRole(roleToRemove) {
|
||||||
@ -115,19 +214,87 @@ export default {
|
|||||||
if (this.$team.inviteTeamMember.loading) return;
|
if (this.$team.inviteTeamMember.loading) return;
|
||||||
|
|
||||||
toast.success(this.$t('Member added to team'), { duration: 2000 });
|
toast.success(this.$t('Member added to team'), { duration: 2000 });
|
||||||
this.show = false;
|
|
||||||
this.$team.inviteTeamMember.submit({
|
this.$team.inviteTeamMember.submit({
|
||||||
username: this.username,
|
username: this.username,
|
||||||
roles: this.selectedRoles.map((role) => role.value),
|
roles: this.selectedRoles.map((role) => role.value),
|
||||||
});
|
});
|
||||||
this.username = '';
|
this.hide();
|
||||||
this.selectedRoles = [];
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.$team?.getTeamMembers) {
|
if (this.$team?.getTeamMembers) {
|
||||||
this.$team.getTeamMembers.submit();
|
this.$team.getTeamMembers.submit();
|
||||||
}
|
}
|
||||||
|
this.$emit('success');
|
||||||
}, 500);
|
}, 500);
|
||||||
},
|
},
|
||||||
|
hide() {
|
||||||
|
this.showDialog = false;
|
||||||
|
this.username = '';
|
||||||
|
this.selectedRoles = [];
|
||||||
|
this.selectedRole = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
resources: {
|
||||||
|
roles() {
|
||||||
|
return {
|
||||||
|
type: 'list',
|
||||||
|
pagetype: 'Jcloud Role',
|
||||||
|
fields: ['name', 'title'],
|
||||||
|
initialData: [],
|
||||||
|
auto: true,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
:deep(.invite-member-modal .n-card) {
|
||||||
|
width: 700px;
|
||||||
|
max-width: 90vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-card-body) {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-form-item) {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-input),
|
||||||
|
:deep(.invite-member-modal .n-select) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-card__action) {
|
||||||
|
padding: 16px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
:deep(.invite-member-modal .n-card) {
|
||||||
|
width: 95vw !important;
|
||||||
|
max-width: 95vw !important;
|
||||||
|
margin: 20px auto;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-card-body) {
|
||||||
|
padding: 20px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-card__header) {
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-card__action) {
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.invite-member-modal .n-button) {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,22 +1,129 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-5">
|
<div class="team-settings-container">
|
||||||
<ObjectList :options="teamMembersListOptions"> </ObjectList>
|
<n-card :title="$t('Team Members')" class="settings-card">
|
||||||
|
<ObjectList :options="teamMembersListOptions" />
|
||||||
|
</n-card>
|
||||||
|
|
||||||
|
<!-- 团队设置弹窗 -->
|
||||||
|
<n-modal
|
||||||
|
v-model:show="showTeamSettingsDialog"
|
||||||
|
preset="card"
|
||||||
|
:title="$t('Settings')"
|
||||||
|
:style="modalStyle"
|
||||||
|
:mask-closable="true"
|
||||||
|
:close-on-esc="true"
|
||||||
|
class="team-settings-modal"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<span class="text-lg font-semibold">{{ $t('Settings') }}</span>
|
||||||
|
</template>
|
||||||
|
<n-space vertical :size="20">
|
||||||
|
<n-form-item>
|
||||||
|
<div class="flex items-center justify-between w-full">
|
||||||
|
<div class="flex-1">
|
||||||
|
<div class="text-base font-medium text-gray-900 mb-1">
|
||||||
|
{{ $t('Enforce Two-Factor Authentication') }}
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-gray-600">
|
||||||
|
{{ $t('Require all team members to enable two-factor authentication') }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<n-switch
|
||||||
|
:value="enforce2FA"
|
||||||
|
@update:value="handleEnforce2FAChange"
|
||||||
|
size="medium"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</n-form-item>
|
||||||
|
</n-space>
|
||||||
|
</n-modal>
|
||||||
|
|
||||||
|
<!-- 邀请成员弹窗 -->
|
||||||
|
<InviteTeamMemberDialog
|
||||||
|
v-if="showInviteMemberDialog"
|
||||||
|
v-model="showInviteMemberDialog"
|
||||||
|
@success="handleInviteSuccess"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 移除成员确认弹窗 -->
|
||||||
|
<n-modal
|
||||||
|
v-model:show="showRemoveMemberDialog"
|
||||||
|
preset="dialog"
|
||||||
|
:title="$t('Remove Member')"
|
||||||
|
:positive-text="$t('Remove')"
|
||||||
|
:positive-button-props="{ type: 'error' }"
|
||||||
|
:loading="team.removeTeamMember.loading"
|
||||||
|
:mask-closable="true"
|
||||||
|
:close-on-esc="true"
|
||||||
|
@positive-click="handleRemoveMember"
|
||||||
|
>
|
||||||
|
<div class="py-4">
|
||||||
|
<p class="text-base">
|
||||||
|
{{ $t('Are you sure you want to remove') }} <strong>{{ selectedMember?.full_name || '' }}</strong> {{ $t('from the team?') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</n-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineAsyncComponent, h, ref, getCurrentInstance } from 'vue';
|
import {
|
||||||
|
NCard,
|
||||||
|
NModal,
|
||||||
|
NSpace,
|
||||||
|
NFormItem,
|
||||||
|
NSwitch,
|
||||||
|
NButton,
|
||||||
|
} from 'naive-ui';
|
||||||
|
import { defineAsyncComponent, h, ref, getCurrentInstance, computed, onMounted } from 'vue';
|
||||||
import { toast } from 'vue-sonner';
|
import { toast } from 'vue-sonner';
|
||||||
import { getTeam } from '../../data/team';
|
import { getTeam } from '../../data/team';
|
||||||
import { confirmDialog, renderDialog } from '../../utils/components';
|
import { icon } from '../../utils/components';
|
||||||
import ObjectList from '../ObjectList.vue';
|
import ObjectList from '../ObjectList.vue';
|
||||||
import UserWithAvatarCell from '../UserWithAvatarCell.vue';
|
import UserWithAvatarCell from '../UserWithAvatarCell.vue';
|
||||||
|
import InviteTeamMemberDialog from './InviteTeamMemberDialog.vue';
|
||||||
|
|
||||||
const instance = getCurrentInstance();
|
const instance = getCurrentInstance();
|
||||||
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
const $t = instance?.appContext.config.globalProperties.$t || ((key) => key);
|
||||||
|
|
||||||
const team = getTeam();
|
const team = getTeam();
|
||||||
team.getTeamMembers.submit();
|
const windowWidth = ref(window.innerWidth);
|
||||||
|
const showTeamSettingsDialog = ref(false);
|
||||||
|
const showInviteMemberDialog = ref(false);
|
||||||
|
const showRemoveMemberDialog = ref(false);
|
||||||
|
const selectedMember = ref(null);
|
||||||
|
|
||||||
|
const isMobile = computed(() => windowWidth.value <= 768);
|
||||||
|
const modalStyle = computed(() => ({
|
||||||
|
width: isMobile.value ? '95vw' : '700px',
|
||||||
|
maxWidth: isMobile.value ? '95vw' : '90vw',
|
||||||
|
}));
|
||||||
|
const buttonSize = computed(() => (isMobile.value ? 'medium' : 'medium'));
|
||||||
|
|
||||||
|
const enforce2FA = computed(() => {
|
||||||
|
return Boolean(team.pg?.enforce_2fa);
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleEnforce2FAChange(value) {
|
||||||
|
team.setValue.submit({ enforce_2fa: value });
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleInviteSuccess() {
|
||||||
|
showInviteMemberDialog.value = false;
|
||||||
|
team.getTeamMembers.submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRemoveMember() {
|
||||||
|
if (!selectedMember.value) return;
|
||||||
|
team.removeTeamMember.submit({ member: selectedMember.value.name });
|
||||||
|
toast.success($t('Member removed'), { duration: 2000 });
|
||||||
|
setTimeout(() => {
|
||||||
|
team.getTeamMembers.submit();
|
||||||
|
showRemoveMemberDialog.value = false;
|
||||||
|
selectedMember.value = null;
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
const teamMembersListOptions = ref({
|
const teamMembersListOptions = ref({
|
||||||
onRowClick: () => {},
|
onRowClick: () => {},
|
||||||
rowHeight: 50,
|
rowHeight: 50,
|
||||||
@ -36,7 +143,6 @@ const teamMembersListOptions = ref({
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
rowActions({ row }) {
|
rowActions({ row }) {
|
||||||
let team = getTeam();
|
|
||||||
if (row.name === team.pg.user || row.name === team.pg.user_info?.name)
|
if (row.name === team.pg.user || row.name === team.pg.user_info?.name)
|
||||||
return [];
|
return [];
|
||||||
return [
|
return [
|
||||||
@ -44,47 +150,105 @@ const teamMembersListOptions = ref({
|
|||||||
label: $t('Remove Member'),
|
label: $t('Remove Member'),
|
||||||
condition: () => row.name !== team.pg.user,
|
condition: () => row.name !== team.pg.user,
|
||||||
onClick() {
|
onClick() {
|
||||||
if (team.removeTeamMember.loading) return;
|
selectedMember.value = row;
|
||||||
confirmDialog({
|
showRemoveMemberDialog.value = true;
|
||||||
title: $t('Remove Member'),
|
|
||||||
message: $t('Are you sure you want to remove <b>{name}</b> from the team?', { name: row.full_name }),
|
|
||||||
onSuccess({ hide }) {
|
|
||||||
toast.success($t('Member removed'), { duration: 2000 });
|
|
||||||
hide();
|
|
||||||
team.removeTeamMember.submit({ member: row.name });
|
|
||||||
setTimeout(() => {
|
|
||||||
team.getTeamMembers.submit();
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
actions() {
|
secondaryAction() {
|
||||||
return [
|
return {
|
||||||
{
|
label: $t('Settings'),
|
||||||
label: $t('Settings'),
|
icon: 'settings',
|
||||||
iconLeft: 'settings',
|
onClick: () => {
|
||||||
onClick() {
|
showTeamSettingsDialog.value = true;
|
||||||
const TeamSettingsDialog = defineAsyncComponent(() =>
|
|
||||||
import('./TeamSettingsDialog.vue')
|
|
||||||
);
|
|
||||||
renderDialog(h(TeamSettingsDialog));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('Add Member'),
|
|
||||||
variant: 'solid',
|
|
||||||
iconLeft: 'plus',
|
|
||||||
onClick() {
|
|
||||||
const InviteTeamMemberDialog = defineAsyncComponent(() =>
|
|
||||||
import('./InviteTeamMemberDialog.vue')
|
|
||||||
);
|
|
||||||
renderDialog(h(InviteTeamMemberDialog));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
];
|
};
|
||||||
|
},
|
||||||
|
primaryAction() {
|
||||||
|
return {
|
||||||
|
label: $t('Add Member'),
|
||||||
|
slots: { prefix: icon('plus') },
|
||||||
|
onClick: () => {
|
||||||
|
showInviteMemberDialog.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
function handleResize() {
|
||||||
|
windowWidth.value = window.innerWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
handleResize();
|
||||||
|
window.addEventListener('resize', handleResize);
|
||||||
|
team.getTeamMembers.submit();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.team-settings-container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-card {
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
|
||||||
|
transition: box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-card:hover {
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card) {
|
||||||
|
width: 700px;
|
||||||
|
max-width: 90vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card-body) {
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card__action) {
|
||||||
|
padding: 16px 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.team-settings-container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-card {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card) {
|
||||||
|
width: 95vw !important;
|
||||||
|
max-width: 95vw !important;
|
||||||
|
margin: 20px auto;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card-body) {
|
||||||
|
padding: 20px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card__header) {
|
||||||
|
padding: 16px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-card__action) {
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.team-settings-modal .n-button) {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 16px;
|
||||||
|
height: 44px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -4,27 +4,30 @@
|
|||||||
$account.user.name === $account.team.user ||
|
$account.user.name === $account.team.user ||
|
||||||
$account.user.user_type === 'System User'
|
$account.user.user_type === 'System User'
|
||||||
"
|
"
|
||||||
class="space-y-5"
|
class="team-settings-view"
|
||||||
>
|
>
|
||||||
<AccountMembers />
|
<TeamSettings />
|
||||||
<AccountGroups />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import AccountGroups from './AccountGroups.vue';
|
import TeamSettings from '../../components/settings/TeamSettings.vue';
|
||||||
import AccountMembers from './AccountMembers.vue';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AccountSettings',
|
name: 'TeamSettingsView',
|
||||||
pageMeta() {
|
pageMeta() {
|
||||||
return {
|
return {
|
||||||
title: 'Settings - Team'
|
title: 'Settings - Team'
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
AccountMembers,
|
TeamSettings
|
||||||
AccountGroups
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.team-settings-view {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -843,6 +843,8 @@ Username is required,用户名为必填项,
|
|||||||
Member added to team,已添加成员到团队,
|
Member added to team,已添加成员到团队,
|
||||||
Remove Member,移除成员,
|
Remove Member,移除成员,
|
||||||
Are you sure you want to remove <b>{name}</b> from the team?,确定要将 <b>{name}</b> 从团队中移除吗?,
|
Are you sure you want to remove <b>{name}</b> from the team?,确定要将 <b>{name}</b> 从团队中移除吗?,
|
||||||
|
Are you sure you want to remove,确定要将,
|
||||||
|
from the team?,从团队中移除吗?,
|
||||||
Member removed,成员已被删除,
|
Member removed,成员已被删除,
|
||||||
Add Member,添加成员,
|
Add Member,添加成员,
|
||||||
Enforce Two-Factor Authentication,强制启用双因素认证,
|
Enforce Two-Factor Authentication,强制启用双因素认证,
|
||||||
|
|||||||
|
Can't render this file because it has a wrong number of fields in line 400.
|
Loading…
x
Reference in New Issue
Block a user