feat(account-manage): 新增账号管理页面布局和功能

This commit is contained in:
rd
2025-09-19 15:20:17 +08:00
parent 7af09d77e1
commit d8f2173eef
5 changed files with 138 additions and 87 deletions

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
d="M6.70215 8.47705C7.20637 8.52829 7.59961 8.95443 7.59961 9.47217V13.7173L7.59473 13.8198C7.54671 14.2902 7.17257 14.6636 6.70215 14.7114L6.59961 14.7173H2.35449L2.25195 14.7114C1.78167 14.6635 1.40736 14.2901 1.35938 13.8198L1.35449 13.7173V9.47217C1.35449 8.95454 1.74788 8.52843 2.25195 8.47705L2.35449 8.47217H6.59961L6.70215 8.47705ZM13.7471 10.3101C14.2513 10.3613 14.6455 10.7875 14.6455 11.3052V13.7173L14.6396 13.8188C14.5919 14.2895 14.2177 14.6636 13.7471 14.7114L13.6455 14.7173H9.42676C8.87474 14.7171 8.42689 14.2693 8.42676 13.7173V11.3052C8.42676 10.753 8.87466 10.3054 9.42676 10.3052H13.6455L13.7471 10.3101ZM2.55469 13.5171H6.40039V9.67139H2.55469V13.5171ZM9.62695 13.5171H13.4453V11.5044H9.62695V13.5171ZM13.7471 1.2876C14.2512 1.33887 14.6455 1.76503 14.6455 2.28271V8.35791L14.6396 8.46045C14.5917 8.93092 14.2176 9.3052 13.7471 9.35303L13.6455 9.35791H9.42676L9.3252 9.35303C8.85463 9.30527 8.48054 8.93097 8.43262 8.46045L8.42676 8.35791V2.28271C8.4268 1.7306 8.87469 1.28293 9.42676 1.28271H13.6455L13.7471 1.2876ZM9.62695 8.15771H13.4453V2.48291H9.62695V8.15771ZM6.70215 1.2876C7.20635 1.33883 7.59957 1.765 7.59961 2.28271V6.52783L7.59473 6.63037C7.54691 7.10097 7.17274 7.47514 6.70215 7.52295L6.59961 7.52783H2.35449L2.25195 7.52295C1.78151 7.475 1.40718 7.10086 1.35938 6.63037L1.35449 6.52783V2.28271C1.35453 1.7651 1.74788 1.33895 2.25195 1.2876L2.35449 1.28271H6.59961L6.70215 1.2876ZM2.55469 6.32861H6.40039V2.48291H2.55469V6.32861Z"
fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path
d="M4.19526 1.86198C4.45561 1.60163 4.87762 1.60163 5.13797 1.86198C5.39832 2.12233 5.39832 2.54434 5.13797 2.80469L3.13797 4.80469C2.87762 5.06504 2.45561 5.06504 2.19526 4.80469L1.19526 3.80469C0.934913 3.54434 0.934913 3.12233 1.19526 2.86198C1.43934 2.6179 1.82534 2.60284 2.08719 2.81641L2.13797 2.86198L2.66662 3.39063L4.19526 1.86198Z"
fill="currentColor"/>
<path
d="M4.19526 6.52865C4.45561 6.2683 4.87762 6.2683 5.13797 6.52865C5.39832 6.789 5.39832 7.21101 5.13797 7.47135L3.13797 9.47135C2.87762 9.7317 2.45561 9.7317 2.19526 9.47135L1.19526 8.47135C0.934913 8.21101 0.934913 7.789 1.19526 7.52865C1.43934 7.28457 1.82534 7.26951 2.08719 7.48307L2.13797 7.52865L2.66662 8.05729L4.19526 6.52865Z"
fill="currentColor"/>
<path
d="M4.19526 11.1953C4.45561 10.935 4.87762 10.935 5.13797 11.1953C5.39832 11.4557 5.39832 11.8777 5.13797 12.138L3.13797 14.138C2.87762 14.3984 2.45561 14.3984 2.19526 14.138L1.19526 13.138C0.934913 12.8777 0.934913 12.4557 1.19526 12.1953C1.43934 11.9512 1.82534 11.9362 2.08719 12.1497L2.13797 12.1953L2.66662 12.724L4.19526 11.1953Z"
fill="currentColor"/>
<path
d="M14.3333 7.33333C14.7015 7.33333 14.9999 7.63181 14.9999 8C14.9999 8.36819 14.7015 8.66667 14.3333 8.66667H6.99995C6.63176 8.66667 6.33328 8.36819 6.33328 8C6.33328 7.63181 6.63176 7.33333 6.99995 7.33333H14.3333Z"
fill="currentColor"/>
<path
d="M14.3333 12C14.7015 12 14.9999 12.2985 14.9999 12.6667C14.9999 13.0349 14.7015 13.3333 14.3333 13.3333H6.99995C6.63176 13.3333 6.33328 13.0349 6.33328 12.6667C6.33328 12.2985 6.63176 12 6.99995 12H14.3333Z"
fill="currentColor"/>
<path
d="M14.3333 2.66667C14.7015 2.66667 14.9999 2.96514 14.9999 3.33333C14.9999 3.70152 14.7015 4 14.3333 4H6.99995C6.63176 4 6.33328 3.70152 6.33328 3.33333C6.33328 2.96514 6.63176 2.66667 6.99995 2.66667H14.3333Z"
fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -28,3 +28,16 @@ export const PLATFORM_LIST = [
value: 1, value: 1,
}, },
]; ];
export const SHOW_TYPES = [
{
label: '卡片',
value: 'card',
svgName: 'svg-card',
},
{
label: '列表',
value: 'list',
svgName: 'svg-list',
},
];

View File

@ -4,7 +4,7 @@
--> -->
<template> <template>
<div class="account-manage-wrap"> <div class="account-manage-wrap">
<div class="filter-wrap bg-#fff rounded-8px"> <div class="filter-wrap mb-16px bg-#fff rounded-8px">
<div class="top flex h-64px px-24px py-10px justify-between items-center"> <div class="top flex h-64px px-24px py-10px justify-between items-center">
<p class="text-18px font-400 lh-26px color-#211F24 title">账号管理</p> <p class="text-18px font-400 lh-26px color-#211F24 title">账号管理</p>
<div class="flex items-center"> <div class="flex items-center">
@ -31,65 +31,71 @@
<FilterBlock ref="filterBlockRef" v-model:query="query" @onSearch="handleSearch" @onReset="handleReset" /> <FilterBlock ref="filterBlockRef" v-model:query="query" @onSearch="handleSearch" @onReset="handleReset" />
</div> </div>
<!--存在异常账号-->
<div <div
v-if="dataSource.length > 0" v-if="hasAbNormalStatus"
class="tip-row flex justify-between items-center px-16px py-10px w-100% my-12px h-48px" class="tip-row flex justify-between items-center px-16px w-100% h-42px mb-16px abnormal"
:class="selectedItems.length > 0 ? 'selected' : isAbNormalStatus ? 'abnormal' : 'normal'"
> >
<div class="flex items-center"> <div class="flex items-center">
<div class="flex items-center"> <div class="flex items-center">
<template v-if="selectedItems.length > 0"> <img :src="icon5" class="mr-8px" height="16" width="16" />
<Checkbox <span class="label"> {{ tipLabel }} </span>
:checked="checkedAll"
:indeterminate="indeterminate"
class="mr-8px"
@change="(e) => handleChangeAll(e.target.checked)"
/>
<span class="label mr-24px">
已选
<span class="color-#6D4CFE">{{ selectedItems.length }}</span>
个账号
</span>
<span class="operation-btn" :class="{ disabled: isDisabledBatchSyncData }" @click="handleBatchSyncData"
>批量更新数据</span
>
<span class="operation-btn" @click="handleBatchTag">批量标签</span>
<span class="operation-btn" @click="handleBatchGroup">批量分组</span>
<span class="operation-btn red" @click="handleBatchDelete"> 批量删除 </span>
</template>
<template v-else>
<img :src="isAbNormalStatus ? icon5 : icon4" width="16" height="16" class="mr-8px" />
<span class="label"> {{ tipLabel }} </span>
</template>
</div> </div>
</div> </div>
<template v-if="selectedItems.length > 0"> <Button class="!h-24px !px-12px" danger size="small" type="primary" @click="handleOpenAbnormalAccount">
<img :src="icon6" width="16" height="16" class="cursor-pointer" @click="handleCloseTip" /> <template #default>查看异常账号</template>
</template> </Button>
<div v-else> </div>
<Space v-if="isAbNormalStatus" class="flex items-center">
<Button type="primary" danger size="small" @click="handleOpenAbnormalAccount"> <!--操作行-->
<template #default>查看异常账号</template> <div class="tip-row flex justify-between items-center px-16px py-10px w-100% h-44px mb-16px">
<div class="flex items-center">
<Checkbox
:checked="checkedAll"
:indeterminate="indeterminate"
class="mr-24px"
@change="(e) => handleChangeAll(e.target.checked)"
>
全选
</Checkbox>
<template v-if="selectedItems.length">
<Button :disabled="isDisabledBatchSyncData" class="!h-24px !px-12px" type="text" @click="handleBatchSyncData">
批量更新数据
</Button> </Button>
</Space> <Button class="!h-24px !px-12px" type="text" @click="handleBatchTag"> 批量标签</Button>
<Button class="!h-24px !px-12px" type="text" @click="handleBatchGroup"> 批量分组</Button>
<Button class="!h-24px !px-12px" danger type="text" @click="handleBatchDelete"> 批量删除</Button>
</template>
</div>
<div class="flex items-center">
<RadioGroup v-model:value="showType">
<RadioButton v-for="(item, index) in SHOW_TYPES" :key="index" :value="item.value">
<div class="flex items-center">
<SvgIcon :name="item.svgName" class="mr-4px" size="16" />
<span>{{ item.label }}</span>
</div>
</RadioButton>
</RadioGroup>
</div> </div>
</div> </div>
<div class="card-wrap"> <div class="card-wrap">
<AccountTable <template v-if="showType === 'card'">
v-if="dataSource.length > 0" <AccountTable
:syncMediaAccounts="syncMediaAccounts" v-if="dataSource.length > 0"
:isLoadingTaskStatus="isLoadingTaskStatus" :dataSource="dataSource"
:dataSource="dataSource" :isLoadingTaskStatus="isLoadingTaskStatus"
:selectedItems="selectedItems" :selectedItems="selectedItems"
@selectionChange="handleSelectionChange" :syncMediaAccounts="syncMediaAccounts"
@delete="handleDelete" @delete="handleDelete"
@openEdit="handleOpenEdit" @openEdit="handleOpenEdit"
@update="getData" @selectionChange="handleSelectionChange"
@updateSyncStatus="handleUpdateSyncStatus" @update="getData"
/> @updateSyncStatus="handleUpdateSyncStatus"
<NoData v-else /> />
<NoData v-else />
</template>
<div v-if="pageInfo.total > 0" class="pagination-row"> <div v-if="pageInfo.total > 0" class="pagination-row">
<Pagination <Pagination
@ -118,10 +124,10 @@
<script setup> <script setup>
import { ref, provide } from 'vue'; import { ref, provide } from 'vue';
import { Checkbox, Button, Space, Pagination, notification } from 'ant-design-vue'; import { Checkbox, Button, Pagination, notification, RadioButton, RadioGroup } from 'ant-design-vue';
import FilterBlock from './components/filter-block'; import FilterBlock from './components/filter-block';
import AccountTable from './components/account-table'; import AccountTable from './components/account-table/card.vue';
import GroupManageModal from './components/group-manage-modal'; import GroupManageModal from './components/group-manage-modal';
import TagsManageModal from './components/tags-manage-modal'; import TagsManageModal from './components/tags-manage-modal';
import AddAccountModal from './components/add-account-modal'; import AddAccountModal from './components/add-account-modal';
@ -129,7 +135,7 @@ import DeleteAccountModal from './components/account-table/delete-account';
import BatchTagModal from './components/batch-tag-modal'; import BatchTagModal from './components/batch-tag-modal';
import BatchGroupModal from './components/batch-group-modal'; import BatchGroupModal from './components/batch-group-modal';
import { INITIAL_QUERY, INITIAL_PAGE_INFO } from './constants'; import { INITIAL_QUERY, INITIAL_PAGE_INFO, SHOW_TYPES } from './constants';
import { showImportResultNotification } from '@/utils/arcoD'; import { showImportResultNotification } from '@/utils/arcoD';
import { getTaskStatus } from '@/api/all/common'; import { getTaskStatus } from '@/api/all/common';
import { EnumStatus } from '@/views/property-marketing/media-account/components/status-select/status-box.tsx'; import { EnumStatus } from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
@ -143,9 +149,9 @@ import {
import icon2 from '@/assets/img/media-account/icon-group.png'; import icon2 from '@/assets/img/media-account/icon-group.png';
import icon3 from '@/assets/img/media-account/icon-tag.png'; import icon3 from '@/assets/img/media-account/icon-tag.png';
import icon4 from '@/assets/img/media-account/icon-success.png'; // import icon4 from '@/assets/img/media-account/icon-success.png';
import icon5 from '@/assets/img/media-account/icon-warn.png'; import icon5 from '@/assets/img/media-account/icon-warn.png';
import icon6 from '@/assets/img/media-account/icon-close.png'; // import icon6 from '@/assets/img/media-account/icon-close.png';
let syncDataTimer = null; let syncDataTimer = null;
let queryTaskTimer = null; let queryTaskTimer = null;
@ -165,17 +171,20 @@ const selectedItems = ref([]);
const healthData = ref({}); const healthData = ref({});
const syncMediaAccounts = ref([]); const syncMediaAccounts = ref([]);
const isLoadingTaskStatus = ref(false); // 正在查询状态中 const isLoadingTaskStatus = ref(false); // 正在查询状态中
const showType = ref('card');
const isAbNormalStatus = computed(() => healthData.value?.abnormal_number > 0); const hasAbNormalStatus = computed(() => healthData.value?.abnormal_number > 0);
const isDisabledBatchSyncData = computed(() => selectedItems.value.some((item) => item.status !== EnumStatus.NORMAL)); const isDisabledBatchSyncData = computed(() => selectedItems.value.some((item) => item.status !== EnumStatus.NORMAL));
const checkedAll = computed(() => selectedItems.value.length === dataSource.value.length); const checkedAll = computed(
() => dataSource.value.length > 0 && selectedItems.value.length === dataSource.value.length,
);
const indeterminate = computed( const indeterminate = computed(
() => selectedItems.value.length > 0 && selectedItems.value.length < dataSource.value.length, () => selectedItems.value.length > 0 && selectedItems.value.length < dataSource.value.length,
); );
const tipLabel = computed(() => { const tipLabel = computed(() => {
if (!isAbNormalStatus.value) { if (!hasAbNormalStatus.value) {
return '太棒啦!所有账号都在正常运行。'; return '太棒啦!所有账号都在正常运行。';
} }
@ -279,9 +288,7 @@ const handleDelete = (item) => {
const { id, name } = item; const { id, name } = item;
deleteAccountRef.value?.open({ id, name: `"${name || '-'}"` }); deleteAccountRef.value?.open({ id, name: `"${name || '-'}"` });
}; };
const handleCloseTip = () => {
selectedItems.value = [];
};
// 先立即执行一次 // 先立即执行一次
const getAsyncStatus = async () => { const getAsyncStatus = async () => {
const { code, data } = await getMediaAccountSyncStatus(); const { code, data } = await getMediaAccountSyncStatus();

View File

@ -17,46 +17,52 @@
} }
.tip-row { .tip-row {
border-radius: 2px; border-radius: 2px;
background: #f0edff; background: #fff;
.label { .label {
font-family: $font-family-medium; font-family: $font-family-regular;
font-size: 14px; font-size: 14px;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
line-height: 22px; line-height: 22px;
} }
&.normal {
background: #ebf7f2;
.label {
color: #211f24;
}
}
&.abnormal { &.abnormal {
background: #ffe7e4; background: #FFE9E7;
.label { .label {
color: #211f24; color: #211f24;
} }
} }
.operation-btn {
padding: 0; :deep(.ant-checkbox) {
cursor: pointer; + span {
color: var(--Brand-Brand-6, #6d4cfe); font-family: $font-family-medium;
font-family: $font-family-regular;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 22px; /* 157.143% */
&:not(:last-child) {
margin-right: 16px;
}
&.red {
color: #f64b31;
}
&.disabled {
color: #c5b7ff;
cursor: not-allowed;
} }
} }
:deep(.ant-radio-group) {
.ant-radio-button-wrapper {
color: #737478;
&:first-child {
border-radius: 4px 0 0 4px;
}
&:last-child {
border-radius: 0 4px 4px 0;
}
&:hover {
color: #6D4CFE;
border-color: #6D4CFE;
}
&-checked {
border-color: #6D4CFE;
background: #F0EDFF;
color: #6D4CFE;
}
}
}
} }
.card-wrap { .card-wrap {
display: flex; display: flex;