feat(account-manage): 添加表格视图并优化现有组件样式和逻辑

This commit is contained in:
rd
2025-09-19 17:31:07 +08:00
parent 7846e02447
commit a4ce67cd18
5 changed files with 401 additions and 123 deletions

View File

@ -3,7 +3,8 @@
* @Date: 2025-06-25 15:31:15 * @Date: 2025-06-25 15:31:15
--> -->
<template> <template>
<div class="card-container"> <NoData v-if="!dataSource.length" />
<div v-else class="card-container">
<Spin <Spin
v-for="(item, index) in dataSource" v-for="(item, index) in dataSource"
:key="index" :key="index"
@ -14,7 +15,12 @@
<template #icon> <template #icon>
<icon-sync size="24" /> <icon-sync size="24" />
</template> </template>
<Checkbox :checked="isSelected(item)" :value="item.id" @change="toggleSelect(item)" class="relative top--2px"></Checkbox> <Checkbox
:checked="isSelected(item)"
:value="item.id"
class="relative top--2px"
@change="toggleSelect(item)"
></Checkbox>
<div class="ml-8px flex-1"> <div class="ml-8px flex-1">
<Tooltip title="点击查看账号详情"> <Tooltip title="点击查看账号详情">
<p class="name cursor-pointer hover:!color-#6d4cfe" @click="goDetail(item)">{{ item.name || '-' }}</p> <p class="name cursor-pointer hover:!color-#6d4cfe" @click="goDetail(item)">{{ item.name || '-' }}</p>
@ -47,30 +53,30 @@
<span class="label">运营人员</span> <span class="label">运营人员</span>
<span class="cts">{{ item.operator?.name || '-' }}</span> <span class="cts">{{ item.operator?.name || '-' }}</span>
</div> </div>
<div class="field-row"> <!-- <div class="field-row">-->
<span class="label">所属项目</span> <!-- <span class="label">所属项目</span>-->
<span v-if="!item.projects.length" class="cts">-</span> <!-- <span v-if="!item.projects.length" class="cts">-</span>-->
<div v-else class="flex items-center"> <!-- <div v-else class="flex items-center">-->
<Tooltip <!-- <Tooltip-->
v-if="item.projects.length > 2" <!-- v-if="item.projects.length > 2"-->
placement="bottom" <!-- placement="bottom"-->
:title=" <!-- :title="-->
item.projects <!-- item.projects-->
.slice(2) <!-- .slice(2)-->
.map((v) => v.name) <!-- .map((v) => v.name)-->
.join(',') <!-- .join(',')-->
" <!-- "-->
> <!-- >-->
<div class="tag-box"> <!-- <div class="tag-box">-->
<span class="text">{{ `+${item.projects.length - 2}` }}</span> <!-- <span class="text">{{ `+${item.projects.length - 2}` }}</span>-->
</div> <!-- </div>-->
</Tooltip> <!-- </Tooltip>-->
<div v-for="(project, index) in item.projects.slice(0, 2)" :key="index" class="tag-box"> <!-- <div v-for="(project, index) in item.projects.slice(0, 2)" :key="index" class="tag-box">-->
<span class="text">{{ project.name }}</span> <!-- <span class="text">{{ project.name }}</span>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
<div class="field-row"> <div class="field-row">
<span class="label">分组</span> <span class="label">分组</span>
<span class="cts">{{ item.group?.name || '-' }}</span> <span class="cts">{{ item.group?.name || '-' }}</span>
@ -123,14 +129,11 @@
</div> </div>
</div> </div>
</Spin> </Spin>
<PauseAccountPatchModal ref="pauseAccountPatchModalRef" @success="emits('update')" />
<ReauthorizeAccountModal ref="reauthorizeAccountModalRef" @update="emits('update')" />
<AuthorizedAccountModal ref="authorizedAccountModalRef" @update="emits('update')" />
</div> </div>
</template> </template>
<script setup> <script setup>
import { defineProps, ref, computed, inject } from 'vue'; import { defineProps, inject } from 'vue';
import { Checkbox, Button, Tooltip, Spin } from 'ant-design-vue'; import { Checkbox, Button, Tooltip, Spin } from 'ant-design-vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { deleteSyncStatus } from '@/api/all/propertyMarketing'; import { deleteSyncStatus } from '@/api/all/propertyMarketing';
@ -141,10 +144,7 @@ import {
EnumStatus, EnumStatus,
} from '@/views/property-marketing/media-account/components/status-select/status-box'; } from '@/views/property-marketing/media-account/components/status-select/status-box';
import PauseAccountPatchModal from './pause-account-patch';
import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx'; import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
import ReauthorizeAccountModal from '../reauthorize-account-modal';
import AuthorizedAccountModal from '../authorized-account-modal';
import FooterBtn from './footer-btn'; import FooterBtn from './footer-btn';
import icon1 from '@/assets/img/platform/icon-dy.png'; import icon1 from '@/assets/img/platform/icon-dy.png';
@ -160,7 +160,7 @@ const props = defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
}, },
selectedItems: { selectedRows: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
@ -170,28 +170,26 @@ const props = defineProps({
}, },
}); });
const emits = defineEmits(['openEdit', 'update', 'selectionChange', 'delete', 'updateSyncStatus']); const emits = defineEmits([
'openEdit',
'update',
'delete',
'updateSyncStatus',
'pause',
'reauthorize',
'select',
'selectAll',
]);
const syncData = inject('handleSyncData'); const syncData = inject('handleSyncData');
const router = useRouter(); const router = useRouter();
const pauseAccountPatchModalRef = ref(null);
const reauthorizeAccountModalRef = ref(null);
const authorizedAccountModalRef = ref(null);
// 判断当前 item 是否被选中
const isSelected = (item) => { const isSelected = (item) => {
return props.selectedItems.some((i) => i.id === item.id); return props.selectedRows.some((i) => i.id === item.id);
}; };
const toggleSelect = (item) => { const toggleSelect = (item) => {
let newSelected; emits('select', item, !isSelected(item));
if (isSelected(item)) {
newSelected = props.selectedItems.filter((i) => i.id !== item.id);
} else {
newSelected = [...props.selectedItems, item];
}
emits('selectionChange', newSelected);
}; };
const openEdit = (item) => { const openEdit = (item) => {
@ -203,21 +201,11 @@ const openDelete = (item) => {
}; };
const handleReauthorize = (item) => { const handleReauthorize = (item) => {
const { id, platform, error_status } = item; emits('reauthorize', item);
const isUnauthorized = isUnauthorizedStatus(error_status);
if (isUnauthorized) {
authorizedAccountModalRef.value?.open(id, platform);
} else {
reauthorizeAccountModalRef.value?.open(id, platform);
}
}; };
const handlePause = (item) => { const handlePause = (item) => {
pauseAccountPatchModalRef.value?.open(item); emits('pause', item);
};
const isUnauthorizedStatus = (error_status) => {
return [EnumErrorStatus.UNAUTHORIZED].includes(error_status);
}; };
const goDetail = (item) => { const goDetail = (item) => {
@ -269,6 +257,7 @@ const handleConfirm = (item) => {
syncData(item); syncData(item);
} }
if (error_status === EnumErrorStatus.LOGIN) { if (error_status === EnumErrorStatus.LOGIN) {
emits('');
handleReauthorize(item); handleReauthorize(item);
} }
}; };

View File

@ -3,9 +3,8 @@ import {
EnumErrorStatus, EnumErrorStatus,
getStatusInfo, getStatusInfo,
} from '@/views/property-marketing/media-account/components/status-select/status-box'; } from '@/views/property-marketing/media-account/components/status-select/status-box';
import { Dropdown, Menu } from 'ant-design-vue'; import { Dropdown, Menu, Tooltip, Button } from 'ant-design-vue';
const { Item: MenuItem } = Menu; const { Item: MenuItem } = Menu;
import { Tooltip, Button } from 'ant-design-vue';
export default defineComponent({ export default defineComponent({
name: 'FooterBtn', name: 'FooterBtn',
props: { props: {
@ -44,7 +43,7 @@ export default defineComponent({
}; };
const renderUpdateBtn = () => { const renderUpdateBtn = () => {
return ( return (
<Button type="primary" ghost size="small" onClick={() => emit('syncData', props.item)}> <Button type="primary" class="!h-24px !px-12px" ghost size="small" onClick={() => emit('syncData', props.item)}>
</Button> </Button>
); );
@ -63,7 +62,7 @@ export default defineComponent({
trigger="hover" trigger="hover"
v-slots={{ v-slots={{
default: () => ( default: () => (
<Button type="primary" ghost class="mr-8px" size="small"> <Button type="primary" ghost class="!h-24px !px-12px mr-8px" size="small">
</Button> </Button>
), ),
@ -88,7 +87,7 @@ export default defineComponent({
trigger="hover" trigger="hover"
v-slots={{ v-slots={{
default: () => ( default: () => (
<Button type="primary" ghost class="mr-8px" size="small"> <Button type="primary" ghost class="mr-8px !h-24px !px-12px" size="small">
</Button> </Button>
), ),
@ -100,7 +99,13 @@ export default defineComponent({
), ),
}} }}
></Dropdown> ></Dropdown>
<Button type="primary" ghost size="small" onClick={() => emit('handleReauthorize', props.item)}> <Button
type="primary"
ghost
size="small"
class="!h-24px !px-12px"
onClick={() => emit('handleReauthorize', props.item)}
>
</Button> </Button>
</> </>
@ -118,14 +123,20 @@ export default defineComponent({
} else if ([EnumErrorStatus.REQUEST, EnumErrorStatus.FREEZE].includes(error_status)) { } else if ([EnumErrorStatus.REQUEST, EnumErrorStatus.FREEZE].includes(error_status)) {
return ( return (
<Tooltip title={statusInfo.value.disabledBtnTooltip}> <Tooltip title={statusInfo.value.disabledBtnTooltip}>
<Button type="primary" ghost size="small" disabled> <Button type="primary" ghost size="small" disabled class="!h-24px !px-12px">
</Button> </Button>
</Tooltip> </Tooltip>
); );
} else { } else {
return ( return (
<Button type="primary" ghost size="small" onClick={() => emit('handleReauthorize', props.item)}> <Button
type="primary"
ghost
class="!h-24px !px-12px"
size="small"
onClick={() => emit('handleReauthorize', props.item)}
>
{isUnauthorized ? '去授权' : '重新授权'} {isUnauthorized ? '去授权' : '重新授权'}
</Button> </Button>
); );
@ -137,7 +148,7 @@ export default defineComponent({
trigger="hover" trigger="hover"
v-slots={{ v-slots={{
default: () => ( default: () => (
<Button type="primary" ghost class="mr-8px" size="small"> <Button type="primary" ghost size="small" class="mr-8px !h-24px !px-12px">
</Button> </Button>
), ),

View File

@ -0,0 +1,185 @@
<template>
<Table
ref="tableRef"
:dataSource="dataSource"
:pagination="false"
:rowSelection="rowSelection"
:scroll="{ x: '100%' }"
:showSorterTooltip="false"
bordered
class="flex-1 manuscript-table w-100%"
rowKey="id"
>
<template #emptyText>
<NoData text="暂无文件" />
</template>
<Column
v-for="column in tableColumns"
:key="column.dataIndex"
:align="column.align"
:dataIndex="column.dataIndex"
:ellipsis="true"
:fixed="column.fixed"
:minWidth="column.minWidth"
:sorter="column.sortable"
:width="column.width"
>
<template #title>
<span class="cts mr-4px">{{ column.title }}</span>
<Tooltip v-if="column.tooltip" :title="column.tooltip" placement="top">
<icon-question-circle class="tooltip-icon color-#737478" size="16" />
</Tooltip>
</template>
<template v-if="column.dataIndex === 'name'" #customRender="{ record }">
<TextOverTips
:context="record.name || '-'"
:line="1"
class="name cursor-pointer hover:!color-#6d4cfe"
@click="goDetail(record)"
/>
</template>
<template v-else-if="column.dataIndex === 'tags'" #customRender="{ record }">
<div v-if="record.tags.length > 0" class="flex flex-wrap gap-4px">
<Tag v-for="tag in record.tags" :key="tag.id" class="mr-0 rounded-4px bg-#F2F3F5 px-8px">
<Tooltip v-if="tag.name.length > 5" :title="tag.name">
<span class="cts !color-#55585F !lh-24px !text-14px"> {{ `${tag.name.slice(0, 5)}...` }} </span>
</Tooltip>
<span v-else class="cts !color-#55585F !lh-24px !text-14px"> {{ tag.name }} </span>
</Tag>
</div>
<template v-else> -</template>
</template>
<template v-else-if="column.dataIndex === 'status'" #customRender="{ record }">
<StatusBox :item="record" />
</template>
<template v-else-if="column.dataIndex === 'platform'" #customRender="{ record }">
<img :src="record.platform === 0 ? icon2 : icon3" height="16" width="16" />
</template>
<template v-else-if="column.dataIndex === 'last_synced_at'" #customRender="{ record }">
<span class="cts num">{{ getLastSyncedAt(record) }}</span>
</template>
<template v-else-if="column.dataIndex === 'last_authorized_at'" #customRender="{ record }">
<span class="cts num">{{ formatTime(record.last_authorized_at) }}</span>
</template>
<template v-else-if="column.dataIndex === 'operation'" #customRender="{ record }">
<div class="flex items-center">
<FooterBtn
:item="record"
@handlePause="handlePause"
@handleReauthorize="handleReauthorize"
@openDelete="openDelete"
@openEdit="openEdit"
@syncData="syncData"
/>
</div>
</template>
<template v-else #customRender="{ record }">
{{ formatTableField(column, record, true) }}
</template>
</Column>
</Table>
</template>
<script setup>
import { ref, computed, inject } from 'vue';
import { Tooltip, Table, Tag } from 'ant-design-vue';
import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
const { Column } = Table;
import { formatTableField, exactFormatTime } from '@/utils/tools';
import TextOverTips from '@/components/text-over-tips';
import FooterBtn from './footer-btn';
// import icon1 from '@/assets/img/media-account/icon-delete.png';
import icon2 from '@/assets/img/platform/icon-dy.png';
import icon3 from '@/assets/img/platform/icon-xhs.png';
const emits = defineEmits([
'openEdit',
'update',
'selectionChange',
'delete',
'updateSyncStatus',
'pause',
'reauthorize',
'select',
'selectAll',
]);
const syncData = inject('handleSyncData');
const router = useRouter();
const props = defineProps({
dataSource: {
type: Array,
default: () => [],
},
tableColumns: {
type: Array,
default: () => [],
},
selectedRowKeys: {
type: Array,
default: () => [],
},
syncMediaAccounts: {
type: Array,
default: () => [],
},
isLoadingTaskStatus: {
type: Boolean,
default: () => false,
},
});
const tableRef = ref(null);
const goDetail = (item) => {
router.push(`/media-account/detail/${item.id}`);
};
const handlePause = (item) => {
emits('pause', item);
};
const handleReauthorize = (item) => {
emits('reauthorize', item);
};
const openEdit = (item) => {
emits('openEdit', item);
};
const openDelete = (item) => {
emits('delete', item);
};
const formatTime = (time) => {
return exactFormatTime(time, 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss');
};
const getSyncMediaAccount = (item) => {
return props.syncMediaAccounts.find((v) => v.id === item.id);
};
const getLastSyncedAt = (item) => {
const target = getSyncMediaAccount(item);
if (props.isLoadingTaskStatus && target) {
if (target?.status !== 0) {
return formatTime(target.last_synced_at);
}
}
return formatTime(item.last_synced_at);
};
const rowSelection = {
selectedRowKeys: computed(() => props.selectedRowKeys),
onSelect: (record, selected) => {
emits('select', record, selected);
},
onSelectAll: (selected) => {
emits('selectAll', selected);
},
};
</script>
<style lang="scss" scoped>
@import './style.scss';
</style>

View File

@ -41,3 +41,63 @@ export const SHOW_TYPES = [
svgName: 'svg-list', svgName: 'svg-list',
}, },
]; ];
export const TABLE_COLUMNS = [
{
title: '账号名称',
dataIndex: 'name',
width: 200,
fixed: 'left',
},
{
title: '状态',
dataIndex: 'status',
width: 100,
},
{
title: '数据更新时间',
dataIndex: 'last_synced_at',
width: 140,
},
{
title: '最后授权时间',
dataIndex: 'last_authorized_at',
width: 140,
},
{
title: '平台',
dataIndex: 'platform',
width: 80,
},
{
title: '账号ID',
dataIndex: 'account_id',
width: 140,
},
{
title: '手机号码',
dataIndex: 'mobile',
width: 140,
},
{
title: '运营人员',
dataIndex: 'operator.name',
width: 140,
},
{
title: '分组',
dataIndex: 'group.name',
width: 140,
},
{
title: '标签',
dataIndex: 'tags',
width: 180,
},
{
title: '操作',
dataIndex: 'operation',
width: 180,
fixed: 'right',
},
];

View File

@ -55,12 +55,12 @@
:checked="checkedAll" :checked="checkedAll"
:indeterminate="indeterminate" :indeterminate="indeterminate"
class="mr-24px" class="mr-24px"
@change="(e) => handleChangeAll(e.target.checked)" @change="(e) => handleSelectAll(e.target.checked)"
> >
全选 全选
</Checkbox> </Checkbox>
<template v-if="selectedItems.length"> <template v-if="selectedRows.length">
<Button :disabled="isDisabledBatchSyncData" class="!h-24px !px-12px" type="text" @click="handleBatchSyncData"> <Button :disabled="isDisabledBatchSyncData" class="!h-24px !px-12px" type="text" @click="handleBatchSyncData">
批量更新数据 批量更新数据
</Button> </Button>
@ -81,21 +81,24 @@
</div> </div>
</div> </div>
<div class="card-wrap"> <div class="card-wrap">
<template v-if="showType === 'card'"> <component
<AccountTable :is="showType === 'card' ? Card : Table"
v-if="dataSource.length > 0"
:dataSource="dataSource" :dataSource="dataSource"
:isLoadingTaskStatus="isLoadingTaskStatus" :isLoadingTaskStatus="isLoadingTaskStatus"
:selectedItems="selectedItems" :selectedItems="selectedItems"
:selectedRowKeys="selectedRowKeys"
:selectedRows="selectedRows"
:syncMediaAccounts="syncMediaAccounts" :syncMediaAccounts="syncMediaAccounts"
:tableColumns="TABLE_COLUMNS"
@delete="handleDelete" @delete="handleDelete"
@openEdit="handleOpenEdit" @openEdit="handleOpenEdit"
@selectionChange="handleSelectionChange" @pause="handlePause"
@reauthorize="handleReauthorize"
@select="handleSelect"
@selectAll="handleSelectAll"
@update="getData" @update="getData"
@updateSyncStatus="handleUpdateSyncStatus" @updateSyncStatus="handleUpdateSyncStatus"
/> />
<NoData v-else />
</template>
<div v-if="pageInfo.total > 0" class="pagination-row"> <div v-if="pageInfo.total > 0" class="pagination-row">
<Pagination <Pagination
@ -105,7 +108,7 @@
showSizeChanger showSizeChanger
showQuickJumper showQuickJumper
:current="pageInfo.page" :current="pageInfo.page"
:pageSize="pageInfo.pageSize" :pageSize="pageInfo.page_size"
:pageSizeOptions="['8', '16', '20', '32', '64']" :pageSizeOptions="['8', '16', '20', '32', '64']"
@change="onPageChange" @change="onPageChange"
/> />
@ -119,6 +122,10 @@
<DeleteAccountModal ref="deleteAccountRef" @update="getData" @batchUpdate="onBatchSuccess" /> <DeleteAccountModal ref="deleteAccountRef" @update="getData" @batchUpdate="onBatchSuccess" />
<BatchTagModal ref="batchTagModalRef" @update="onBatchSuccess" /> <BatchTagModal ref="batchTagModalRef" @update="onBatchSuccess" />
<BatchGroupModal ref="batchGroupModalRef" @update="onBatchSuccess" /> <BatchGroupModal ref="batchGroupModalRef" @update="onBatchSuccess" />
<PauseAccountPatchModal ref="pauseAccountPatchModalRef" @success="getData" />
<ReauthorizeAccountModal ref="reauthorizeAccountModalRef" @update="getData" />
<AuthorizedAccountModal ref="authorizedAccountModalRef" @update="getData" />
</div> </div>
</template> </template>
@ -127,7 +134,12 @@ import { ref, provide } from 'vue';
import { Checkbox, Button, Pagination, notification, RadioButton, RadioGroup } 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/card.vue'; import Card from './components/account-table/card.vue';
import Table from './components/account-table/table.vue';
import PauseAccountPatchModal from './components/account-table/pause-account-patch.vue';
import AuthorizedAccountModal from './components/authorized-account-modal';
import ReauthorizeAccountModal from './components/reauthorize-account-modal';
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';
@ -135,10 +147,14 @@ 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, SHOW_TYPES } from './constants'; import { INITIAL_QUERY, SHOW_TYPES, TABLE_COLUMNS } from './constants';
import { showImportResultNotification } from '@/utils/notification'; import { showImportResultNotification } from '@/utils/notification';
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 { useTableSelectionWithPagination } from '@/hooks/useTableSelectionWithPagination';
import {
EnumErrorStatus,
EnumStatus,
} from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
import { import {
getMediaAccounts, getMediaAccounts,
getMediaAccountsHealth, getMediaAccountsHealth,
@ -156,6 +172,21 @@ import icon5 from '@/assets/img/media-account/icon-warn.png';
let syncDataTimer = null; let syncDataTimer = null;
let queryTaskTimer = null; let queryTaskTimer = null;
const {
selectedRowKeys,
selectedRows,
dataSource,
pageInfo,
DEFAULT_PAGE_INFO,
onPageChange,
handleSelect,
handleSelectAll,
} = useTableSelectionWithPagination({
onPageChange: () => {
getData();
},
});
const groupManageModalRef = ref(null); const groupManageModalRef = ref(null);
const tagsManageModalRef = ref(null); const tagsManageModalRef = ref(null);
const addAccountModalRef = ref(null); const addAccountModalRef = ref(null);
@ -163,10 +194,12 @@ const deleteAccountRef = ref(null);
const batchTagModalRef = ref(null); const batchTagModalRef = ref(null);
const batchGroupModalRef = ref(null); const batchGroupModalRef = ref(null);
const filterBlockRef = ref(null); const filterBlockRef = ref(null);
const pauseAccountPatchModalRef = ref(null);
const reauthorizeAccountModalRef = ref(null);
const authorizedAccountModalRef = ref(null);
const pageInfo = ref(cloneDeep(INITIAL_PAGE_INFO));
const query = ref(cloneDeep(INITIAL_QUERY)); const query = ref(cloneDeep(INITIAL_QUERY));
const dataSource = ref([]); // const dataSource = ref([]);
const selectedItems = ref([]); const selectedItems = ref([]);
const healthData = ref({}); const healthData = ref({});
const syncMediaAccounts = ref([]); const syncMediaAccounts = ref([]);
@ -174,13 +207,11 @@ const isLoadingTaskStatus = ref(false); // 正在查询状态中
const showType = ref('card'); const showType = ref('card');
const hasAbNormalStatus = 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(() => selectedRows.value.some((item) => item.status !== EnumStatus.NORMAL));
const checkedAll = computed( const checkedAll = computed(() => dataSource.value.length > 0 && selectedRows.value.length === dataSource.value.length);
() => 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, () => selectedRows.value.length > 0 && selectedRows.value.length < dataSource.value.length,
); );
const tipLabel = computed(() => { const tipLabel = computed(() => {
@ -223,10 +254,10 @@ const getHealthData = async () => {
} }
}; };
const getAccountData = async () => { const getAccountData = async () => {
const { page, pageSize } = pageInfo.value; const { page, page_size } = pageInfo.value;
const { code, data } = await getMediaAccounts({ const { code, data } = await getMediaAccounts({
page, page,
page_size: pageSize, page_size,
...query.value, ...query.value,
}); });
if (code === 200) { if (code === 200) {
@ -242,23 +273,13 @@ const handleSearch = () => {
reload(); reload();
}; };
const handleReset = () => { const handleReset = () => {
pageInfo.value = cloneDeep(INITIAL_PAGE_INFO); pageInfo.value = cloneDeep(DEFAULT_PAGE_INFO);
selectedItems.value = []; selectedRows.value = [];
selectedRowKeys.value = [];
query.value = cloneDeep(INITIAL_QUERY); query.value = cloneDeep(INITIAL_QUERY);
reload(); reload();
}; };
const onPageChange = (current, pageSize) => {
pageInfo.value.page = current;
pageInfo.value.pageSize = pageSize;
getData();
};
const onPageSizeChange = (pageSize) => {
pageInfo.value.pageSize = pageSize;
reload();
};
const handleOpenGroupModal = () => { const handleOpenGroupModal = () => {
groupManageModalRef.value?.open(); groupManageModalRef.value?.open();
}; };
@ -273,15 +294,9 @@ const handleOpenEdit = (item) => {
addAccountModalRef.value?.open(item.id); addAccountModalRef.value?.open(item.id);
}; };
const handleSelectionChange = (val) => {
selectedItems.value = val;
};
const handleChangeAll = (checked) => {
selectedItems.value = checked ? cloneDeep(dataSource.value) : [];
};
const handleBatchDelete = () => { const handleBatchDelete = () => {
const ids = selectedItems.value.map((item) => item.id); const ids = selectedRows.value.map((item) => item.id);
const names = selectedItems.value.map((item) => `"${item.name || '-'}"`).join(''); const names = selectedRows.value.map((item) => `"${item.name || '-'}"`).join('');
deleteAccountRef.value?.open({ id: ids, name: names }); deleteAccountRef.value?.open({ id: ids, name: names });
}; };
const handleDelete = (item) => { const handleDelete = (item) => {
@ -330,14 +345,14 @@ const handleSyncData = async (item) => {
}; };
const handleBatchTag = () => { const handleBatchTag = () => {
batchTagModalRef.value?.open(selectedItems.value); batchTagModalRef.value?.open(selectedRows.value);
}; };
const handleBatchSyncData = async () => { const handleBatchSyncData = async () => {
if (isDisabledBatchSyncData.value) { if (isDisabledBatchSyncData.value) {
return; return;
} }
const ids = selectedItems.value.map((item) => item.id); const ids = selectedRows.value.map((item) => item.id);
const { code } = await postBatchSyncMediaAccountData({ ids }); const { code } = await postBatchSyncMediaAccountData({ ids });
if (code === 200) { if (code === 200) {
if (!isLoadingTaskStatus.value) { if (!isLoadingTaskStatus.value) {
@ -346,10 +361,11 @@ const handleBatchSyncData = async () => {
} }
}; };
const handleBatchGroup = () => { const handleBatchGroup = () => {
batchGroupModalRef.value?.open(selectedItems.value); batchGroupModalRef.value?.open(selectedRows.value);
}; };
const onBatchSuccess = () => { const onBatchSuccess = () => {
selectedItems.value = []; selectedRowKeys.value = [];
selectedRows.value = [];
getData(); getData();
}; };
const handleOpenAbnormalAccount = () => { const handleOpenAbnormalAccount = () => {
@ -357,6 +373,23 @@ const handleOpenAbnormalAccount = () => {
reload(); reload();
}; };
const isUnauthorizedStatus = (error_status) => {
return [EnumErrorStatus.UNAUTHORIZED].includes(error_status);
};
const handlePause = (item) => {
pauseAccountPatchModalRef.value?.open(item);
};
const handleReauthorize = (item) => {
const { id, platform, error_status } = item;
const isUnauthorized = isUnauthorizedStatus(error_status);
if (isUnauthorized) {
authorizedAccountModalRef.value?.open(id, platform);
} else {
reauthorizeAccountModalRef.value?.open(id, platform);
}
};
// 查询导入账号任务状态 // 查询导入账号任务状态
const getSyncTaskStatus = async (id, notificationId) => { const getSyncTaskStatus = async (id, notificationId) => {
const { code, data } = await getTaskStatus(id); const { code, data } = await getTaskStatus(id);