refactor: 新媒体账号状态重构

This commit is contained in:
rd
2025-07-25 10:26:53 +08:00
parent 458b4c0d60
commit a50234543b
10 changed files with 109 additions and 105 deletions

View File

@ -77,11 +77,7 @@
{{ record.platform === 0 ? '抖音' : record.platform === 1 ? '小红书' : '-' }} {{ record.platform === 0 ? '抖音' : record.platform === 1 ? '小红书' : '-' }}
</template> </template>
<template v-else-if="column.dataIndex === 'status'" #cell="{ record }"> <template v-else-if="column.dataIndex === 'status'" #cell="{ record }">
<div class="status-tag" :class="`status-tag-${record.status}`"> <StatusBox :item="record" class="w-fit h-28px" />
<span class="cts status-tag-text">{{
STATUS_LIST.find((item) => item.value === record.status)?.label
}}</span>
</div>
</template> </template>
<template v-else-if="column.dataIndex === 'ai_evaluate'" #cell="{ record }"> <template v-else-if="column.dataIndex === 'ai_evaluate'" #cell="{ record }">
<div class="ai-evaluation-row flex"> <div class="ai-evaluation-row flex">
@ -167,7 +163,7 @@ import { ref, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { getCustomColumns } from '@/api/all/common'; import { getCustomColumns } from '@/api/all/common';
import { STATUS_LIST } from '@/views/property-marketing/media-account/components/status-select/constants'; import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
import { formatTableField, formatNumberShow, exactFormatTime } from '@/utils/tools'; import { formatTableField, formatNumberShow, exactFormatTime } from '@/utils/tools';
import { getDefaultColumns, getPropPrefix } from '@/views/property-marketing/media-account/account-dashboard/constants'; import { getDefaultColumns, getPropPrefix } from '@/views/property-marketing/media-account/account-dashboard/constants';
import CustomTableColumnModal from '../custom-column-modal'; import CustomTableColumnModal from '../custom-column-modal';

View File

@ -15,42 +15,11 @@
font-weight: 400; font-weight: 400;
line-height: 22px; line-height: 22px;
} }
.status-tag { :deep(.status-box) {
width: fit-content; .label {
display: flex; font-family: $font-family-medium;
height: 28px; font-size: 14px;
padding: 0px 8px; line-height: 22px;
align-items: center;
border-radius: 2px;
background: #f2f3f5;
.status-tag-text {
color: var(--BG-700, #737478);
}
&-1 {
background: #ebf7f2;
.status-tag-text {
color: #25c883;
}
}
&-2,
&-4,
&-5,
&-6,
&-7 {
background: #ffe7e4;
.status-tag-text {
color: #f64b31;
}
}
&-3 {
background: #fff7e5;
color: #ffae00;
.status-tag-text {
color: #ffae00;
}
} }
} }
.ai-evaluation-row { .ai-evaluation-row {

View File

@ -88,11 +88,13 @@
<div v-if="isSyncFailed(item)" class="mask"> <div v-if="isSyncFailed(item)" class="mask">
<div class="flex items-center mb-16px box"> <div class="flex items-center mb-16px box">
<img :src="icon3" width="16" height="16" class="mr-8px" /> <img :src="icon3" width="16" height="16" class="mr-8px" />
<span class="name !mb-0">更新数据失败</span> <span class="name !mb-0">{{ getErrorStatusText(item) }}</span>
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<a-button class="search-btn mr-8px" size="mini" @click="onDeleteSyncStatus(item)">取消</a-button> <a-button type="outline" class="mr-8px" size="mini" @click="handleCancel(item)">取消</a-button>
<a-button class="search-btn" size="mini" @click="syncData(item)">重新更新</a-button> <a-button type="outline" size="mini" @click="handleConfirm(item)" v-if="showConfirmBtn(item)">{{
getConfirmBtnText(item)
}}</a-button>
</div> </div>
</div> </div>
</a-spin> </a-spin>
@ -105,9 +107,13 @@
<script setup> <script setup>
import { defineProps, ref, computed, inject } from 'vue'; import { defineProps, ref, computed, inject } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { EnumErrorStatus } from '@/views/property-marketing/media-account/components/status-select/status-box';
import { deleteSyncStatus } from '@/api/all/propertyMarketing'; import { deleteSyncStatus } from '@/api/all/propertyMarketing';
import { exactFormatTime } from '@/utils/tools'; import { exactFormatTime } from '@/utils/tools';
import {
EnumErrorStatus,
errorStatusMap,
EnumStatus,
} from '@/views/property-marketing/media-account/components/status-select/status-box';
import PauseAccountPatchModal from './pause-account-patch'; 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';
@ -118,7 +124,6 @@ import FooterBtn from './footer-btn';
import icon1 from '@/assets/img/media-account/icon-dy.png'; import icon1 from '@/assets/img/media-account/icon-dy.png';
import icon2 from '@/assets/img/media-account/icon-xhs.png'; import icon2 from '@/assets/img/media-account/icon-xhs.png';
import icon3 from '@/assets/img/media-account/icon-warn.png'; import icon3 from '@/assets/img/media-account/icon-warn.png';
// import icon3 from '@/assets/img/media-account/icon-delete.png';
const props = defineProps({ const props = defineProps({
dataSource: { dataSource: {
@ -140,6 +145,7 @@ const props = defineProps({
}); });
const emits = defineEmits(['openEdit', 'update', 'selectionChange', 'delete', 'updateSyncStatus']); const emits = defineEmits(['openEdit', 'update', 'selectionChange', 'delete', 'updateSyncStatus']);
const syncData = inject('handleSyncData');
const router = useRouter(); const router = useRouter();
@ -161,12 +167,6 @@ const toggleSelect = (item) => {
} }
emits('selectionChange', newSelected); emits('selectionChange', newSelected);
}; };
const isSyncing = (item) => {
if (!props.syncMediaAccounts.length) return false;
const target = props.syncMediaAccounts.find((v) => v.id === item.id);
return target?.status === 0;
};
const openEdit = (item) => { const openEdit = (item) => {
emits('openEdit', item); emits('openEdit', item);
@ -194,21 +194,22 @@ const isUnauthorizedStatus = (error_status) => {
return [EnumErrorStatus.UNAUTHORIZED].includes(error_status); return [EnumErrorStatus.UNAUTHORIZED].includes(error_status);
}; };
const syncData = inject('handleSyncData');
const goDetail = (item) => { const goDetail = (item) => {
router.push(`/media-account/detail/${item.id}`); router.push(`/media-account/detail/${item.id}`);
}; };
const onDeleteSyncStatus = async (item) => {
await deleteSyncStatus(item.id);
emits('updateSyncStatus', item);
};
const formatTime = (time) => { const formatTime = (time) => {
return exactFormatTime(time, 'YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm:ss'); 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 isSyncing = (item) => {
if (!props.syncMediaAccounts.length) return false;
return getSyncMediaAccount(item)?.status === 0;
};
const getLastSyncedAt = (item) => { const getLastSyncedAt = (item) => {
const target = props.syncMediaAccounts.find((v) => v.id === item.id); const target = getSyncMediaAccount(item);
if (props.isLoadingTaskStatus && target) { if (props.isLoadingTaskStatus && target) {
if (target?.status !== 0) { if (target?.status !== 0) {
return formatTime(target.last_synced_at); return formatTime(target.last_synced_at);
@ -217,8 +218,42 @@ const getLastSyncedAt = (item) => {
return formatTime(item.last_synced_at); return formatTime(item.last_synced_at);
}; };
const isSyncFailed = (item) => { const isSyncFailed = (item) => {
const target = props.syncMediaAccounts.find((v) => v.id === item.id); return getSyncMediaAccount(item)?.status === 2;
return target?.status === 2; };
const getErrorStatusText = (item) => {
const error_status = getSyncMediaAccount(item)?.error_status;
return `异常(${errorStatusMap.get(error_status)?.text ?? ''}`;
};
const handleCancel = async (item) => {
const error_status = getSyncMediaAccount(item)?.error_status;
await deleteSyncStatus(item.id);
item.status = EnumStatus.ABNORMAL;
item.error_status = error_status;
emits('updateSyncStatus', item);
};
const showConfirmBtn = (item) => {
const error_status = getSyncMediaAccount(item)?.error_status;
return [EnumErrorStatus.MISSING, EnumErrorStatus.LOGIN].includes(error_status);
};
const handleConfirm = (item) => {
const error_status = getSyncMediaAccount(item)?.error_status;
if (error_status === EnumErrorStatus.MISSING) {
syncData(item);
}
if (error_status === EnumErrorStatus.LOGIN) {
handleReauthorize(item);
}
};
const getConfirmBtnText = (item) => {
const error_status = getSyncMediaAccount(item)?.error_status;
if (error_status === EnumErrorStatus.MISSING) {
return '重新更新';
}
if (error_status === EnumErrorStatus.LOGIN) {
return '重新授权';
}
}; };
</script> </script>

View File

@ -297,11 +297,11 @@ const getAsyncStatus = async () => {
} }
} }
}; };
const handleUpdateSyncStatus = (item) => { const handleUpdateSyncStatus = (item) => {
const target = syncMediaAccounts.value.find((v) => v.id === item.id); const target = syncMediaAccounts.value.find((v) => v.id === item.id);
// 点击取消,设置状态为成功
if (target) { if (target) {
target.status = 1; target.status = EnumStatus.NORMAL;
} }
}; };

View File

@ -2,7 +2,7 @@
* @Author: RenXiaoDong * @Author: RenXiaoDong
* @Date: 2025-07-04 11:18:11 * @Date: 2025-07-04 11:18:11
*/ */
export enum EnumStatus { export enum EnumAccountStatus {
UNAUTHORIZED = 0, // 未授权 UNAUTHORIZED = 0, // 未授权
NORMAL = 1, // 正常 NORMAL = 1, // 正常
PAUSE = 2, // 暂停同步 PAUSE = 2, // 暂停同步
@ -19,55 +19,55 @@ export const STATUS_LIST = [
{ {
text: '正常', text: '正常',
label: '正常', label: '正常',
value: EnumStatus.NORMAL, value: EnumAccountStatus.NORMAL,
}, },
{ {
text: '即将过期', text: '即将过期',
label: '即将过期', label: '即将过期',
value: EnumStatus.ABNORMAL_EXPIRED, value: EnumAccountStatus.ABNORMAL_EXPIRED,
}, },
{ {
text: '暂停同步', text: '暂停同步',
label: '暂停同步', label: '暂停同步',
value: EnumStatus.PAUSE, value: EnumAccountStatus.PAUSE,
}, },
{ {
text: '全部异常', text: '全部异常',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL, value: EnumAccountStatus.ABNORMAL,
}, },
{ {
text: '异常(未授权)', text: '异常(未授权)',
label: '异常', label: '异常',
value: EnumStatus.UNAUTHORIZED, value: EnumAccountStatus.UNAUTHORIZED,
tooltip: '未授权', tooltip: '未授权',
class: '!pl-24px', class: '!pl-24px',
}, },
{ {
text: '异常(数据缺失)', text: '异常(数据缺失)',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_MISSING, value: EnumAccountStatus.ABNORMAL_MISSING,
tooltip: '数据缺失', tooltip: '数据缺失',
class: '!pl-24px', class: '!pl-24px',
}, },
{ {
text: '异常(登录状态失效)', text: '异常(登录状态失效)',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_LOGIN, value: EnumAccountStatus.ABNORMAL_LOGIN,
tooltip: '登录状态失效', tooltip: '登录状态失效',
class: '!pl-24px', class: '!pl-24px',
}, },
{ {
text: '异常(请求频繁)', text: '异常(请求频繁)',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_REQUEST, value: EnumAccountStatus.ABNORMAL_REQUEST,
tooltip: '请求频繁等待24小时后重试', tooltip: '请求频繁等待24小时后重试',
class: '!pl-24px', class: '!pl-24px',
}, },
{ {
text: '异常(账号被封)', text: '异常(账号被封)',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_FREEZE, value: EnumAccountStatus.ABNORMAL_FREEZE,
tooltip: '账号被封', tooltip: '账号被封',
class: '!pl-24px', class: '!pl-24px',
}, },

View File

@ -1,6 +1,6 @@
import { defineComponent, computed } from 'vue'; import { defineComponent, computed } from 'vue';
import { Tooltip } from '@arco-design/web-vue'; import { Tooltip } from '@arco-design/web-vue';
// import { STATUS_LIST } from '@/views/property-marketing/media-account/components/status-select/constants';
import iconWarn1 from '@/assets/img/media-account/icon-warn-1.png'; import iconWarn1 from '@/assets/img/media-account/icon-warn-1.png';
import iconWarn2 from '@/assets/img/media-account/icon-warn-2.png'; import iconWarn2 from '@/assets/img/media-account/icon-warn-2.png';
import icon1 from '@/assets/img/media-account/icon-schedule.png'; import icon1 from '@/assets/img/media-account/icon-schedule.png';
@ -41,13 +41,13 @@ const pauseStyle = {
background: '#fff7e5', background: '#fff7e5',
}; };
const tooltipMap = new Map([ export const errorStatusMap = new Map([
[1, { tooltip: '未授权' }], [1, { tooltip: '未授权', text: '未授权' }],
[2, { tooltip: '登录状态失效' }], [2, { tooltip: '登录状态失效', text: '登录状态失效' }],
[3, { tooltip: '请求频繁等待24小时后重试', btnTooltip: '请求频繁等待24小时后重试' }], [3, { tooltip: '请求频繁等待24小时后重试', btnTooltip: '请求频繁等待24小时后重试', text: '请求过于频繁' }],
[4, { tooltip: '账号被冻结', btnTooltip: '账号被封,解封后才能操作' }], [4, { tooltip: '账号被冻结', btnTooltip: '账号被封,解封后才能操作', text: '账号被冻结' }],
[5, { tooltip: '数据缺失' }], [5, { tooltip: '数据缺失', text: '数据缺失' }],
[6, { tooltip: '未知错误' }], [6, { tooltip: '未知错误', text: '未知错误' }],
]); ]);
/** /**
@ -58,14 +58,18 @@ const tooltipMap = new Map([
* @returns * @returns
*/ */
export const getStatusInfo = (status: EnumStatus, error_status: EnumErrorStatus, to_be_expire_for_cookie: EnumExpireForCookie) => { export const getStatusInfo = (
status: EnumStatus,
error_status: EnumErrorStatus,
to_be_expire_for_cookie: EnumExpireForCookie,
) => {
const statusInfo = { color: '', background: '', label: '', tooltip: '', disabledBtnTooltip: '' }; const statusInfo = { color: '', background: '', label: '', tooltip: '', disabledBtnTooltip: '' };
if (status === EnumStatus.ABNORMAL) { if (status === EnumStatus.ABNORMAL) {
statusInfo.color = abnormalStyle.color; statusInfo.color = abnormalStyle.color;
statusInfo.background = abnormalStyle.background; statusInfo.background = abnormalStyle.background;
statusInfo.label = '异常'; statusInfo.label = '异常';
const target = tooltipMap.get(error_status); const target = errorStatusMap.get(error_status);
statusInfo.tooltip = target?.tooltip ?? ''; statusInfo.tooltip = target?.tooltip ?? '';
statusInfo.disabledBtnTooltip = target?.btnTooltip ?? ''; statusInfo.disabledBtnTooltip = target?.btnTooltip ?? '';
} }
@ -111,11 +115,11 @@ export default defineComponent({
const { background, color, label } = statusInfo.value; const { background, color, label } = statusInfo.value;
if (status === EnumStatus.NORMAL) { if (status === EnumStatus.NORMAL) {
return ( return (
<div class="flex items-center"> <div class="flex items-center status-box">
{to_be_expire_for_cookie === EnumExpireForCookie.EXPIRE && ( {to_be_expire_for_cookie === EnumExpireForCookie.EXPIRE && (
<div class="flex items-center rounded-2px px-8px mr-8px" style={{ background, color }}> <div class="flex items-center rounded-2px px-8px mr-8px" style={{ background, color }}>
<img src={icon1} width="12" height="12" class="mr-4px" /> <img src={icon1} width="12" height="12" class="mr-4px" />
<span class="text-12px lh-20px font-400">{label}</span> <span class="text-12px lh-20px font-400 label">{label}</span>
</div> </div>
)} )}
<div <div
@ -129,8 +133,8 @@ export default defineComponent({
} }
return ( return (
<div class="flex items-center rounded-2px px-8px" style={{ background, color }}> <div class="flex items-center rounded-2px px-8px status-box" style={{ background, color }}>
<span class="text-12px lh-20px font-400">{label}</span> <span class="text-12px lh-20px font-400 label">{label}</span>
{status === EnumStatus.PAUSE ? ( {status === EnumStatus.PAUSE ? (
<img src={iconWarn1} width="12" height="12" class="ml-4px" /> <img src={iconWarn1} width="12" height="12" class="ml-4px" />
) : ( ) : (

View File

@ -77,7 +77,7 @@
<script setup> <script setup>
import { defineProps, ref, computed } from 'vue'; import { defineProps, ref, computed } from 'vue';
import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants'; import { PLATFORM_LIST } from '@/views/property-marketing/put-account/common_constants';
import { EnumStatus } from '@/views/property-marketing/put-account/components/status-select/constants'; import { EnumPutAccountStatus } from '@/views/property-marketing/put-account/components/status-select/constants';
import { formatNumberShow, exactFormatTime } from '@/utils/tools'; import { formatNumberShow, exactFormatTime } from '@/utils/tools';
@ -135,7 +135,7 @@ const handlePause = (item) => {
}; };
const showPauseButton = (status) => { const showPauseButton = (status) => {
return status === EnumStatus.NORMAL; return status === EnumPutAccountStatus.NORMAL;
}; };
</script> </script>

View File

@ -13,7 +13,7 @@
<script setup> <script setup>
import { computed } from 'vue'; import { computed } from 'vue';
import { STATUS_LIST, EnumStatus } from '@/views/property-marketing/put-account/components/status-select/constants'; import { STATUS_LIST, EnumPutAccountStatus } from '@/views/property-marketing/put-account/components/status-select/constants';
import iconWarn1 from '@/assets/img/media-account/icon-warn-1.png'; import iconWarn1 from '@/assets/img/media-account/icon-warn-1.png';
import iconWarn2 from '@/assets/img/media-account/icon-warn-2.png'; import iconWarn2 from '@/assets/img/media-account/icon-warn-2.png';
@ -38,16 +38,16 @@ const tooltipText = computed(() => {
}); });
const showIcon = computed(() => { const showIcon = computed(() => {
return ![EnumStatus.NORMAL, EnumStatus.UNAUTHORIZED].includes(props.status); return ![EnumPutAccountStatus.NORMAL, EnumPutAccountStatus.UNAUTHORIZED].includes(props.status);
}); });
const iconSrc = computed(() => { const iconSrc = computed(() => {
return props.status === EnumStatus.PAUSE ? iconWarn1 : iconWarn2; return props.status === EnumPutAccountStatus.PAUSE ? iconWarn1 : iconWarn2;
}); });
// 判断是否为禁用重新授权的状态 // 判断是否为禁用重新授权的状态
const isDisabledReauthorize = (status) => { const isDisabledReauthorize = (status) => {
return [EnumStatus.ABNORMAL_LOGIN, EnumStatus.ABNORMAL_REQUEST, EnumStatus.ABNORMAL_FREEZE].includes(status); return [EnumPutAccountStatus.ABNORMAL_LOGIN, EnumPutAccountStatus.ABNORMAL_REQUEST, EnumPutAccountStatus.ABNORMAL_FREEZE].includes(status);
}; };
</script> </script>

View File

@ -2,7 +2,7 @@
* @Author: RenXiaoDong * @Author: RenXiaoDong
* @Date: 2025-07-04 11:18:11 * @Date: 2025-07-04 11:18:11
*/ */
export enum EnumStatus { export enum EnumPutAccountStatus {
UNAUTHORIZED = 0, UNAUTHORIZED = 0,
NORMAL = 1, NORMAL = 1,
ABNORMAL = 3, ABNORMAL = 3,
@ -17,44 +17,44 @@ export const STATUS_LIST = [
{ {
text: '正常', text: '正常',
label: '正常', label: '正常',
value: EnumStatus.NORMAL, value: EnumPutAccountStatus.NORMAL,
}, },
{ {
text: '暂停同步', text: '暂停同步',
label: '暂停同步', label: '暂停同步',
value: EnumStatus.PAUSE, value: EnumPutAccountStatus.PAUSE,
}, },
{ {
text: '未授权', text: '未授权',
label: '未授权', label: '未授权',
value: EnumStatus.UNAUTHORIZED, value: EnumPutAccountStatus.UNAUTHORIZED,
}, },
{ {
text: '异常', text: '异常',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL, value: EnumPutAccountStatus.ABNORMAL,
}, },
{ {
text: '数据缺失', text: '数据缺失',
label: '数据缺失', label: '数据缺失',
value: EnumStatus.ABNORMAL_MISSING, value: EnumPutAccountStatus.ABNORMAL_MISSING,
}, },
{ {
text: '异常-登录状态失效', text: '异常-登录状态失效',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_LOGIN, value: EnumPutAccountStatus.ABNORMAL_LOGIN,
tooltip: '登录状态失效,需重新扫码授权', tooltip: '登录状态失效,需重新扫码授权',
}, },
{ {
text: '异常-请求过于频繁', text: '异常-请求过于频繁',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_REQUEST, value: EnumPutAccountStatus.ABNORMAL_REQUEST,
tooltip: '请求过于频繁需等待24小时后重试', tooltip: '请求过于频繁需等待24小时后重试',
}, },
{ {
text: '异常-账号被冻结/封禁', text: '异常-账号被冻结/封禁',
label: '异常', label: '异常',
value: EnumStatus.ABNORMAL_FREEZE, value: EnumPutAccountStatus.ABNORMAL_FREEZE,
tooltip: '账号被冻结/封禁', tooltip: '账号被冻结/封禁',
}, },
]; ];

View File

@ -19,7 +19,7 @@
<script setup> <script setup>
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { STATUS_LIST } from '@/views/property-marketing/media-account/components/status-select/constants'; import { STATUS_LIST } from '@/views/property-marketing/put-account/components/status-select/constants';
const props = defineProps({ const props = defineProps({
modelValue: { modelValue: {