Files
lingji-work-fe/src/views/components/management/account/index.vue
2025-07-16 17:40:45 +08:00

300 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="bg-#fff rounded-8px border-1px border-#D7D7D9 border-solid w-100% py-0 px-20px mt-24px pb-24px">
<div class="title-row">
<span class="title">账号管理</span>
<a-button type="outline" class="add-account-button" @click="handleAddAccount">添加子账号</a-button>
</div>
<a-table
:columns="columns"
:data="dataSource"
:pagination="pagination"
class="mt-8px h-540px"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
>
<template #empty>
<NoData />
</template>
<template #mobile="{ record }">
<div class="flex item-center pt-13px pb-13px">
<span class="mr-4px">{{ record.mobile }}</span>
<a-tag v-if="record.type === 0" class="primary-account">主账号</a-tag>
<a-tag v-else class="sub-account">子账号</a-tag>
</div>
</template>
<template #action="{ record }">
<a-button
v-if="record.type !== 0"
class="delete-button"
size="mini"
type="outline"
status="danger"
@click="openDeleteModal(record)"
>
删除
</a-button>
</template>
</a-table>
<Modal v-model:visible="addAccountVisible" width="480px" title="添加子账号" :okText="okText" @ok="handleOk">
<div v-if="canAddAccount" class="add-account-container">
<h2 class="add-account-title">生成企业专属链接成员通过访问即可注册并加入企业账号</h2>
<p class="add-account-subtitle">子账号可独立登录权限继承主账号配置</p>
<div class="add-account-body">
<p>用该链接加入企业吧</p>
<p>{{ inviteUrl }}</p>
</div>
</div>
<div v-else class="add-account-container">
<h2 class="cannot-add-account-title flex item-center">
<img src="@/assets/warning.svg" alt="" />
当前可用子账号数为0
</h2>
<p class="cannot-add-account-subtitle">如需添加更多子账号您可联系销售人员进行购买和权限扩展</p>
</div>
</Modal>
<CustomerServiceModal v-model:visible="customerServiceVisible" />
<DeleteModal v-model:visible="deleteVisible" :title="deleteTitle" @ok="handleDelete">
<p class="delete-modal-content">删除后该账号将无法登录您的企业</p>
</DeleteModal>
</div>
</template>
<script setup lang="ts">
import Container from '@/components/container.vue';
import { ref, onMounted, reactive, computed } from 'vue';
import { fetchSubAccountPage, removeEnterpriseAccount, getEnterpriseInviteCode } from '@/api/all';
import Modal from '@/components/modal.vue';
import DeleteModal from '@/components/delete-modal.vue';
import CustomerServiceModal from '@/components/customer-service-modal.vue';
import { useClipboard } from '@vueuse/core';
import { useEnterpriseStore } from '@/stores/modules/enterprise';
const store = useEnterpriseStore();
const columns = [
{
title: '手机号',
slotName: 'mobile',
},
{
title: '操作',
slotName: 'action',
},
];
const dataSource = ref([]);
const pagination = reactive({
total: 0,
showPageSize: true,
showTotal: true,
defaultCurrent: 1,
defaultPageSize: 10,
});
const params = reactive({
page_size: 10,
page: 1,
});
const inviteUrl = ref('');
const addAccountVisible = ref(false);
const deleteVisible = ref(false);
const deleteTitle = ref('');
const enterpriseInfo = store.enterpriseInfo;
const okText = computed(() => {
if (!canAddAccount.value) {
return '联系客服';
}
return '复制邀请链接';
});
const customerServiceVisible = ref(false);
const canAddAccount = computed(() => {
if (!enterpriseInfo) return false;
return enterpriseInfo.sub_account_quota > enterpriseInfo.used_sub_account_count;
});
const currentSelectAccount = ref();
const { copy, copied, isSupported } = useClipboard({ source: inviteUrl });
function handlePageChange(current: number) {
params.page = current;
getSubAccount();
}
function handlePageSizeChange(pageSize: number) {
params.page_size = pageSize;
getSubAccount();
}
async function getSubAccount() {
const res = await fetchSubAccountPage(params);
const { data, code } = res;
if (code === 200) {
pagination.total = data.total;
dataSource.value = data?.data ?? [];
}
}
async function handleAddAccount() {
if (canAddAccount.value) {
const res = await getEnterpriseInviteCode();
const port = window.location.port === '' ? '' : ':' + window.location.port;
const domain = window.location.protocol + '//' + window.location.hostname + port;
inviteUrl.value = domain + '?invite_code=' + res.data?.invite_code;
}
addAccountVisible.value = true;
}
function handleOk() {
if (!canAddAccount.value) {
customerServiceVisible.value = true;
return;
}
if (!isSupported) {
AMessage.error('您的浏览器不支持复制,请手动复制!');
}
copy(inviteUrl.value);
if (!copied) {
AMessage.error('复制失败,请手动复制!');
}
AMessage.success('复制成功!');
}
function openDeleteModal(record: { id: number; mobile: string }) {
currentSelectAccount.value = record;
deleteTitle.value = `确认删除“${record.mobile}”子账号吗?`;
deleteVisible.value = true;
}
async function handleDelete() {
await removeEnterpriseAccount(currentSelectAccount.value.id);
AMessage.success('移除成功!');
}
onMounted(() => {
getSubAccount();
});
</script>
<style scoped lang="scss">
.primary-account {
border-radius: 2px;
padding-right: 8px;
padding-left: 8px;
background: var(--Brand-Brand-1, rgba(240, 237, 255, 1));
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
line-height: 20px;
color: var(--Brand-Brand-6, rgba(109, 76, 254, 1));
}
.sub-account {
border-radius: 2px;
padding-right: 8px;
padding-left: 8px;
background: var(--Functional-Warning-1, rgba(255, 245, 222, 1));
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
color: var(--Functional-Warning-6, rgba(255, 174, 0, 1));
}
.delete-button {
border-radius: 4px;
padding: 2px 12px;
border: 1px solid var(--Functional-Danger-6, rgba(246, 75, 49, 1));
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
line-height: 20px;
color: var(--Functional-Danger-6, rgba(246, 75, 49, 1));
}
.add-account-button {
border-radius: 4px;
padding: 5px 16px;
border: 1px solid var(--Brand-Brand-6, rgba(109, 76, 254, 1));
font-family: $font-family-medium;
font-weight: 400;
font-size: 14px;
color: var(--Brand-Brand-6, rgba(109, 76, 254, 1));
}
.add-account-container {
margin-top: 13px;
margin-bottom: 12px;
.add-account-title {
margin: 0;
font-family: $font-family-medium;
font-weight: 400;
font-size: 14px;
color: var(--Text-1, rgba(33, 31, 36, 1));
}
.add-account-subtitle {
margin: 4px 0 0 0;
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
color: var(--Text-2, rgba(60, 64, 67, 1));
}
.add-account-body {
margin-top: 16px;
width: 432px;
height: 84px;
border-radius: 4px;
padding: 12px 16px;
background: var(--BG-200, rgba(242, 243, 245, 1));
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
color: var(--Text-2, rgba(60, 64, 67, 1));
p {
padding: 0;
margin: 0;
}
}
.cannot-add-account-title {
margin: 0;
font-family: $font-family-medium;
font-weight: 400;
font-size: 14px;
color: var(--Text-1, rgba(33, 31, 36, 1));
img {
width: 20px;
height: 20px;
margin-right: 12px;
}
}
.cannot-add-account-subtitle {
margin: 16px 0 0 0;
padding-left: 32px;
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
color: var(--Text-2, rgba(60, 64, 67, 1));
}
}
.delete-modal-content {
margin-left: 34px;
margin-top: 16px;
font-family: $font-family-medium;
font-weight: 400;
font-size: 12px;
color: var(--Text-2, rgba(60, 64, 67, 1));
}
.title-row {
display: flex;
height: 64px;
padding: 10px 0 2px 0;
align-items: center;
justify-content: space-between;
.title {
color: var(--Text-1, #211f24);
font-family: $font-family-medium;
font-size: 18px;
font-style: normal;
font-weight: 400;
line-height: 24px; /* 150% */
}
}
</style>