feat: 同步数据loading

This commit is contained in:
rd
2025-07-14 17:30:59 +08:00
parent ac7a8abfe3
commit aa176fd2b4
6 changed files with 42 additions and 10 deletions

View File

@ -122,7 +122,8 @@ import icon4 from '@/assets/img/media-account/icon-success.png';
const route = useRoute(); const route = useRoute();
const id = route.params.id; const id = route.params.id;
const dateType = route.query.type; const dateType = route.query.type ?? 'week';
const detailData = ref({}); const detailData = ref({});
const showMore = ref(false); const showMore = ref(false);

View File

@ -21,7 +21,7 @@ import { useRouter } from 'vue-router';
const router = useRouter(); const router = useRouter();
const handleBack = () => { const handleBack = () => {
router.push('/media-account/dashboard'); router.go(-1);
}; };
</script> </script>

View File

@ -4,17 +4,24 @@
--> -->
<template> <template>
<div class="card-container"> <div class="card-container">
<div <!-- <a-spin class="w-100% h-100%"> -->
<a-spin
v-for="(item, index) in dataSource" v-for="(item, index) in dataSource"
:key="index" :key="index"
:loading="isSyncing(item)"
tip="更新数据中..."
class="card-item" class="card-item"
:class="{ :class="{
checked: isSelected(item), checked: isSelected(item),
}" }"
> >
<template #icon>
<icon-sync size="24" />
</template>
<a-checkbox :model-value="isSelected(item)" :value="item.id" @change="toggleSelect(item)"></a-checkbox> <a-checkbox :model-value="isSelected(item)" :value="item.id" @change="toggleSelect(item)"></a-checkbox>
<div class="ml-8px flex-1"> <div class="ml-8px flex-1">
<p class="name">{{ item.name || '-' }}</p> <p class="name cursor-pointer" @click="goDetail(item)">{{ item.name || '-' }}</p>
<div class="field-row"> <div class="field-row">
<span class="label">状态</span> <span class="label">状态</span>
<StatusBox :status="item.status" /> <StatusBox :status="item.status" />
@ -108,7 +115,8 @@
</a-button> --> </a-button> -->
</div> </div>
</div> </div>
</div> </a-spin>
<!-- </div> -->
<PauseAccountPatchModal ref="pauseAccountPatchModalRef" @success="emits('update')" /> <PauseAccountPatchModal ref="pauseAccountPatchModalRef" @success="emits('update')" />
<ReauthorizeAccountModal ref="reauthorizeAccountModalRef" @update="emits('update')" /> <ReauthorizeAccountModal ref="reauthorizeAccountModalRef" @update="emits('update')" />
<AuthorizedAccountModal ref="authorizedAccountModalRef" @update="emits('update')" /> <AuthorizedAccountModal ref="authorizedAccountModalRef" @update="emits('update')" />
@ -117,6 +125,7 @@
<script setup> <script setup>
import { defineProps, ref, computed, inject } from 'vue'; import { defineProps, ref, computed, inject } from 'vue';
import { useRouter } from 'vue-router';
import { STATUS_LIST, EnumStatus } from '@/views/property-marketing/media-account/components/status-select/constants'; import { STATUS_LIST, EnumStatus } from '@/views/property-marketing/media-account/components/status-select/constants';
import PauseAccountPatchModal from './pause-account-patch'; import PauseAccountPatchModal from './pause-account-patch';
@ -133,6 +142,10 @@ const props = defineProps({
type: Array, type: Array,
default: () => [], default: () => [],
}, },
syncMediaAccounts: {
type: Array,
default: () => [],
},
selectedItems: { selectedItems: {
type: Array, type: Array,
default: () => [], default: () => [],
@ -141,6 +154,8 @@ const props = defineProps({
const emits = defineEmits(['openEdit', 'update', 'selectionChange', 'delete']); const emits = defineEmits(['openEdit', 'update', 'selectionChange', 'delete']);
const router = useRouter();
const pauseAccountPatchModalRef = ref(null); const pauseAccountPatchModalRef = ref(null);
const reauthorizeAccountModalRef = ref(null); const reauthorizeAccountModalRef = ref(null);
const authorizedAccountModalRef = ref(null); const authorizedAccountModalRef = ref(null);
@ -159,6 +174,12 @@ const toggleSelect = (item) => {
} }
emits('selectionChange', newSelected); emits('selectionChange', newSelected);
}; };
const isSyncing = (item) => {
if (!props.selectedItems.length) return false;
const target = props.selectedItems.find((v) => v.id === item.id);
return target.status === 0;
};
const openEdit = (item) => { const openEdit = (item) => {
emits('openEdit', item); emits('openEdit', item);
@ -169,7 +190,6 @@ const openDelete = (item) => {
}; };
const handleReauthorize = (item) => { const handleReauthorize = (item) => {
console.log({ item });
const { id, platform, status } = item; const { id, platform, status } = item;
const isUnauthorized = isUnauthorizedStatus(status); const isUnauthorized = isUnauthorizedStatus(status);
if (isUnauthorized) { if (isUnauthorized) {
@ -207,11 +227,11 @@ const getTooltipText = (status) => {
return STATUS_LIST.find((v) => v.value === status)?.tooltip ?? '-'; return STATUS_LIST.find((v) => v.value === status)?.tooltip ?? '-';
}; };
const handleSyncData = inject('handleSyncData'); const syncData = inject('handleSyncData');
const onBtnClick = (item) => { const onBtnClick = (item) => {
if (showSyncDataButton(item.status)) { if (showSyncDataButton(item.status)) {
handleSyncData && handleSyncData(item); syncData(item);
return; return;
} }
if (isUnauthorizedStatus(item.status)) { if (isUnauthorizedStatus(item.status)) {
@ -242,6 +262,10 @@ const getBtnText = (item) => {
return '暂停同步'; return '暂停同步';
}; };
const goDetail = (item) => {
router.push(`/media-account/detail/${item.id}`);
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -31,7 +31,7 @@ import { defineExpose } from 'vue';
import icon1 from '@/assets/img/media-account/icon-warn-1.png'; import icon1 from '@/assets/img/media-account/icon-warn-1.png';
const handleSyncData = inject('handleSyncData'); const syncData = inject('handleSyncData');
const id = ref(''); const id = ref('');
@ -45,7 +45,7 @@ const close = () => {
visible.value = false; visible.value = false;
}; };
const handleOk = () => { const handleOk = () => {
handleSyncData({ id: id.value }); syncData({ id: id.value });
close(); close();
}; };
defineExpose({ defineExpose({

View File

@ -79,6 +79,7 @@
<div class="card-wrap"> <div class="card-wrap">
<AccountTable <AccountTable
v-if="dataSource.length > 0" v-if="dataSource.length > 0"
:syncMediaAccounts="syncMediaAccounts"
:dataSource="dataSource" :dataSource="dataSource"
:selectedItems="selectedItems" :selectedItems="selectedItems"
@selectionChange="handleSelectionChange" @selectionChange="handleSelectionChange"
@ -159,6 +160,7 @@ 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 startSyncData = ref(false); const startSyncData = ref(false);
const isAbNormalStatus = computed(() => healthData.value?.total_abnormal_number > 0); const isAbNormalStatus = computed(() => healthData.value?.total_abnormal_number > 0);
@ -180,6 +182,7 @@ const tipLabel = computed(() => {
too_many_requests_number = 0, too_many_requests_number = 0,
account_frozen_number = 0, account_frozen_number = 0,
miss_data_number = 0, miss_data_number = 0,
abnormal_number = 0,
} = healthData.value; } = healthData.value;
// 定义异常类型映射 // 定义异常类型映射
@ -188,6 +191,7 @@ const tipLabel = computed(() => {
{ count: too_many_requests_number, label: '请求频繁' }, { count: too_many_requests_number, label: '请求频繁' },
{ count: account_frozen_number, label: '账号被封' }, { count: account_frozen_number, label: '账号被封' },
{ count: miss_data_number, label: '数据缺失' }, { count: miss_data_number, label: '数据缺失' },
{ count: abnormal_number, label: '其他异常' },
]; ];
// 过滤出有异常的项并格式化 // 过滤出有异常的项并格式化
@ -281,6 +285,7 @@ const startSyncDataPolling = () => {
syncDataTimer = setInterval(async () => { syncDataTimer = setInterval(async () => {
const { code, data } = await getMediaAccountSyncStatus(); const { code, data } = await getMediaAccountSyncStatus();
if (code === 200) { if (code === 200) {
syncMediaAccounts.value = data;
// 所有任务都结束了,才停止轮询,刷新页面 // 所有任务都结束了,才停止轮询,刷新页面
const isEnd = data.every((item) => item.status !== 0); const isEnd = data.every((item) => item.status !== 0);
if (isEnd) { if (isEnd) {

View File

@ -141,6 +141,7 @@ const tipLabel = computed(() => {
too_many_requests_number = 0, too_many_requests_number = 0,
account_frozen_number = 0, account_frozen_number = 0,
miss_data_number = 0, miss_data_number = 0,
abnormal_number = 0,
} = healthData.value; } = healthData.value;
// 定义异常类型映射 // 定义异常类型映射
@ -149,6 +150,7 @@ const tipLabel = computed(() => {
{ count: too_many_requests_number, label: '请求频繁' }, { count: too_many_requests_number, label: '请求频繁' },
{ count: account_frozen_number, label: '账号被封' }, { count: account_frozen_number, label: '账号被封' },
{ count: miss_data_number, label: '数据缺失' }, { count: miss_data_number, label: '数据缺失' },
{ count: abnormal_number, label: '其他异常' },
]; ];
// 过滤出有异常的项并格式化 // 过滤出有异常的项并格式化