Merge remote-tracking branch 'origin/main' into feature/v1.2灵机空间-内容上传审核_rxd
# Conflicts: # src/components/_base/navbar/components/navbar-menu/index.vue
This commit is contained in:
BIN
src/assets/img/media-account/icon-schedule.png
Normal file
BIN
src/assets/img/media-account/icon-schedule.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 701 B |
@ -9,7 +9,12 @@
|
|||||||
<icon-caret-down size="16" class="arco-icon-down !mr-0" />
|
<icon-caret-down size="16" class="arco-icon-down !mr-0" />
|
||||||
</a-button>
|
</a-button>
|
||||||
<template #content>
|
<template #content>
|
||||||
<a-doption v-for="(child, ind) in item.children" :key="ind" @click="handleDropdownClick(child)">
|
<a-doption
|
||||||
|
v-for="(child, ind) in item.children"
|
||||||
|
:key="ind"
|
||||||
|
@click="handleDropdownClick(child)"
|
||||||
|
:class="{ active: child.includeRouteNames.includes(route.name) }"
|
||||||
|
>
|
||||||
<span class="menu-item-text"> {{ child.name }}</span>
|
<span class="menu-item-text"> {{ child.name }}</span>
|
||||||
</a-doption>
|
</a-doption>
|
||||||
</template>
|
</template>
|
||||||
@ -26,12 +31,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import { useSidebarStore } from '@/stores/modules/side-bar';
|
import { useSidebarStore } from '@/stores/modules/side-bar';
|
||||||
// import router from '@/router';
|
// import router from '@/router';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
const sidebarStore = useSidebarStore();
|
const sidebarStore = useSidebarStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
const selectedKey = computed(() => {
|
const selectedKey = computed(() => {
|
||||||
return [String(sidebarStore.activeMenuId)];
|
return [String(sidebarStore.activeMenuId)];
|
||||||
@ -39,6 +46,7 @@ const selectedKey = computed(() => {
|
|||||||
const menuList = computed(() => {
|
const menuList = computed(() => {
|
||||||
return sidebarStore.menuList;
|
return sidebarStore.menuList;
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleDropdownClick = (item) => {
|
const handleDropdownClick = (item) => {
|
||||||
router.push({ name: item.routeName });
|
router.push({ name: item.routeName });
|
||||||
};
|
};
|
||||||
@ -61,11 +69,11 @@ const handleDropdownClick = (item) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 10px 24px;
|
padding: 10px 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.menu-item-text {
|
.menu-item-text {
|
||||||
color: var(--Text-2, #3c4043);
|
color: var(--Text-2, #3c4043);
|
||||||
font-family: 'PuHuiTi-Regular';
|
font-family: $font-family-regular;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@ -73,11 +81,13 @@ const handleDropdownClick = (item) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:not(.arco-dropdown-option-disabled):hover {
|
&:not(.arco-dropdown-option-disabled):hover {
|
||||||
background-color: transparent;
|
|
||||||
.arco-dropdown-option-content {
|
|
||||||
border-radius: 8px;
|
|
||||||
background: var(--BG-200, #f2f3f5);
|
background: var(--BG-200, #f2f3f5);
|
||||||
}
|
}
|
||||||
|
&.active {
|
||||||
|
background: var(--Brand-Brand-1, #f0edff) !important;
|
||||||
|
.menu-item-text {
|
||||||
|
color: var(--Brand-Brand-6, #6d4cfe) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@
|
|||||||
.label {
|
.label {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
color: #211f24;
|
color: #211f24;
|
||||||
font-family: 'PuHuiTi-Regular';
|
font-family: $font-family-regular;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|||||||
@ -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';
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -53,11 +53,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="cts">
|
<p class="cts">
|
||||||
<template v-if="field.type === 'status'">
|
<template v-if="field.type === 'status'">
|
||||||
<div class="status-tag" :class="`status-tag-${detailData.status}`">
|
<StatusBox :item="detailData" class="w-fit" />
|
||||||
<span class="cts status-tag-text">{{
|
|
||||||
STATUS_LIST.find((item) => item.value === detailData.status)?.label
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="field.dataIndex === 'tags'">
|
<template v-else-if="field.dataIndex === 'tags'">
|
||||||
<div v-if="detailData.tags?.length" class="flex items-center">
|
<div v-if="detailData.tags?.length" class="flex items-center">
|
||||||
@ -138,8 +134,8 @@ import { useRoute } from 'vue-router';
|
|||||||
|
|
||||||
import { formatTableField, formatNumberShow, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, formatNumberShow, exactFormatTime } from '@/utils/tools';
|
||||||
import { getAccountInfoFields } from '../../constants';
|
import { getAccountInfoFields } from '../../constants';
|
||||||
import { STATUS_LIST } from '@/views/property-marketing/media-account/components/status-select/constants';
|
|
||||||
import { getPropPrefix } from '@/views/property-marketing/media-account/account-dashboard/constants';
|
import { getPropPrefix } from '@/views/property-marketing/media-account/account-dashboard/constants';
|
||||||
|
import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
|
||||||
|
|
||||||
import { getAccountBoardDetail } from '@/api/all/propertyMarketing';
|
import { getAccountBoardDetail } from '@/api/all/propertyMarketing';
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,168 @@
|
|||||||
|
import {
|
||||||
|
EnumStatus,
|
||||||
|
EnumErrorStatus,
|
||||||
|
getStatusInfo,
|
||||||
|
} from '@/views/property-marketing/media-account/components/status-select/status-box';
|
||||||
|
import { Dropdown, Doption, Button, Tooltip } from '@arco-design/web-vue';
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'FooterBtn',
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['syncData', 'handleReauthorize', 'handlePause', 'openDelete', 'openEdit'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
const statusInfo = computed(() => {
|
||||||
|
const { status, error_status, to_be_expire_for_cookie } = props.item;
|
||||||
|
return getStatusInfo(status, error_status, to_be_expire_for_cookie) ?? {};
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderEditDoption = () => {
|
||||||
|
return (
|
||||||
|
<Doption class="color-#211F24" onClick={() => emit('openEdit', props.item)}>
|
||||||
|
编辑
|
||||||
|
</Doption>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderReauthorizeDoption = (text = '重新授权') => {
|
||||||
|
return (
|
||||||
|
<Doption class="color-#211F24" onClick={() => emit('handleReauthorize', props.item)}>
|
||||||
|
{text}
|
||||||
|
</Doption>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderPauseDoption = () => {
|
||||||
|
return (
|
||||||
|
<Doption class="color-#211F24" onClick={() => emit('handlePause', props.item)}>
|
||||||
|
暂停同步
|
||||||
|
</Doption>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderUpdateBtn = () => {
|
||||||
|
return (
|
||||||
|
<Button type="outline" size="mini" onClick={() => emit('syncData', props.item)}>
|
||||||
|
更新数据
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderDeleteDoption = () => {
|
||||||
|
return (
|
||||||
|
<Doption class="color-#F64B31" onClick={() => emit('openDelete', props.item)}>
|
||||||
|
删除
|
||||||
|
</Doption>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderNormal = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
trigger="hover"
|
||||||
|
v-slots={{
|
||||||
|
default: () => (
|
||||||
|
<Button type="outline" class="mr-8px" size="mini">
|
||||||
|
更多
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
content: () => (
|
||||||
|
<>
|
||||||
|
{renderEditDoption()}
|
||||||
|
{renderReauthorizeDoption()}
|
||||||
|
{renderPauseDoption()}
|
||||||
|
{renderDeleteDoption()}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
></Dropdown>
|
||||||
|
{renderUpdateBtn()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderPause = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
trigger="hover"
|
||||||
|
v-slots={{
|
||||||
|
default: () => (
|
||||||
|
<Button type="outline" class="mr-8px" size="mini">
|
||||||
|
更多
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
content: () => (
|
||||||
|
<>
|
||||||
|
{renderEditDoption()}
|
||||||
|
{renderDeleteDoption()}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
></Dropdown>
|
||||||
|
<Button type="outline" size="mini" onClick={() => emit('handleReauthorize', props.item)}>
|
||||||
|
开启同步
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
// 异常情况
|
||||||
|
const renderAbnormal = () => {
|
||||||
|
const { error_status } = props.item;
|
||||||
|
const isMissing = error_status === EnumErrorStatus.MISSING;
|
||||||
|
const isUnauthorized = error_status === EnumErrorStatus.UNAUTHORIZED;
|
||||||
|
|
||||||
|
const renderSyncBtn = () => {
|
||||||
|
if (isMissing) {
|
||||||
|
return renderUpdateBtn();
|
||||||
|
} else if ([EnumErrorStatus.REQUEST, EnumErrorStatus.FREEZE].includes(error_status)) {
|
||||||
|
return (
|
||||||
|
<Tooltip content={statusInfo.value.disabledBtnTooltip}>
|
||||||
|
<Button type="outline" size="mini" disabled>
|
||||||
|
重新授权
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Button type="outline" size="mini" onClick={() => emit('handleReauthorize', props.item)}>
|
||||||
|
{isUnauthorized ? '去授权' : '重新授权'}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
trigger="hover"
|
||||||
|
v-slots={{
|
||||||
|
default: () => (
|
||||||
|
<Button type="outline" class="mr-8px" size="mini">
|
||||||
|
更多
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
content: () => (
|
||||||
|
<>
|
||||||
|
{renderEditDoption()}
|
||||||
|
{isMissing && renderReauthorizeDoption()}
|
||||||
|
{renderPauseDoption()}
|
||||||
|
{renderDeleteDoption()}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
></Dropdown>
|
||||||
|
{renderSyncBtn()}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const renderContent = () => {
|
||||||
|
const { status } = props.item;
|
||||||
|
if (status === EnumStatus.NORMAL) {
|
||||||
|
return renderNormal();
|
||||||
|
} else if (status === EnumStatus.PAUSE) {
|
||||||
|
return renderPause();
|
||||||
|
} else {
|
||||||
|
return renderAbnormal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return () => renderContent();
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -24,7 +24,7 @@
|
|||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<div class="field-row">
|
<div class="field-row">
|
||||||
<span class="label">状态</span>
|
<span class="label">状态</span>
|
||||||
<StatusBox :status="item.status" />
|
<StatusBox :item="item" />
|
||||||
</div>
|
</div>
|
||||||
<div class="field-row">
|
<div class="field-row">
|
||||||
<span class="label">数据更新时间</span>
|
<span class="label">数据更新时间</span>
|
||||||
@ -99,34 +99,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="operate-row">
|
<div class="operate-row">
|
||||||
<a-dropdown trigger="hover">
|
<FooterBtn
|
||||||
<a-button class="w-52px mr-8px" type="outline" size="mini">
|
:item="item"
|
||||||
<template #default>更多</template>
|
@handleReauthorize="handleReauthorize"
|
||||||
</a-button>
|
@syncData="syncData"
|
||||||
<template #content>
|
@openEdit="openEdit"
|
||||||
<a-doption class="color-#211F24" @click="openEdit(item)">编辑</a-doption>
|
@openDelete="openDelete"
|
||||||
<a-doption v-if="item.status === EnumStatus.NORMAL" class="color-#211F24" @click="handleReauthorize(item)"
|
@handlePause="handlePause"
|
||||||
>重新授权</a-doption
|
/>
|
||||||
>
|
|
||||||
<a-doption v-if="showPauseButton(item.status)" class="color-#211F24" @click="handlePause(item)"
|
|
||||||
>暂停同步</a-doption
|
|
||||||
>
|
|
||||||
<a-doption class="color-#F64B31" @click="openDelete(item)">删除</a-doption>
|
|
||||||
</template>
|
|
||||||
<a-button type="outline" size="mini" @click="onBtnClick(item)">
|
|
||||||
<template #default>{{ getBtnText(item) }}</template>
|
|
||||||
</a-button>
|
|
||||||
</a-dropdown>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<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 type="outline" class="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 type="outline" class="" 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>
|
||||||
@ -139,19 +131,23 @@
|
|||||||
<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 { STATUS_LIST, EnumStatus } from '@/views/property-marketing/media-account/components/status-select/constants';
|
|
||||||
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 '../status-box';
|
import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
|
||||||
import ReauthorizeAccountModal from '../reauthorize-account-modal';
|
import ReauthorizeAccountModal from '../reauthorize-account-modal';
|
||||||
import AuthorizedAccountModal from '../authorized-account-modal';
|
import AuthorizedAccountModal from '../authorized-account-modal';
|
||||||
|
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: {
|
||||||
@ -173,6 +169,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();
|
||||||
|
|
||||||
@ -194,12 +191,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);
|
||||||
@ -210,8 +201,8 @@ const openDelete = (item) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleReauthorize = (item) => {
|
const handleReauthorize = (item) => {
|
||||||
const { id, platform, status } = item;
|
const { id, platform, error_status } = item;
|
||||||
const isUnauthorized = isUnauthorizedStatus(status);
|
const isUnauthorized = isUnauthorizedStatus(error_status);
|
||||||
if (isUnauthorized) {
|
if (isUnauthorized) {
|
||||||
authorizedAccountModalRef.value?.open(id, platform);
|
authorizedAccountModalRef.value?.open(id, platform);
|
||||||
} else {
|
} else {
|
||||||
@ -223,79 +214,26 @@ const handlePause = (item) => {
|
|||||||
pauseAccountPatchModalRef.value?.open(item);
|
pauseAccountPatchModalRef.value?.open(item);
|
||||||
};
|
};
|
||||||
|
|
||||||
const showPauseButton = (status) => {
|
const isUnauthorizedStatus = (error_status) => {
|
||||||
return ![EnumStatus.PAUSE, EnumStatus.UNAUTHORIZED].includes(status);
|
return [EnumErrorStatus.UNAUTHORIZED].includes(error_status);
|
||||||
};
|
|
||||||
const showSyncDataButton = (status) => {
|
|
||||||
return [EnumStatus.NORMAL, EnumStatus.ABNORMAL_MISSING].includes(status);
|
|
||||||
};
|
|
||||||
const isUnauthorizedStatus = (status) => {
|
|
||||||
return [EnumStatus.UNAUTHORIZED].includes(status);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 三种异常情况
|
|
||||||
const isAbnormalStatus = (status) => {
|
|
||||||
return [
|
|
||||||
EnumStatus.ABNORMAL,
|
|
||||||
EnumStatus.ABNORMAL_LOGIN,
|
|
||||||
EnumStatus.ABNORMAL_REQUEST,
|
|
||||||
EnumStatus.ABNORMAL_FREEZE,
|
|
||||||
].includes(status);
|
|
||||||
};
|
|
||||||
|
|
||||||
// const getTooltipText = (status) => {
|
|
||||||
// return STATUS_LIST.find((v) => v.value === status)?.tooltip ?? '-';
|
|
||||||
// };
|
|
||||||
|
|
||||||
const syncData = inject('handleSyncData');
|
|
||||||
|
|
||||||
const onBtnClick = (item) => {
|
|
||||||
if (showSyncDataButton(item.status)) {
|
|
||||||
syncData(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (isUnauthorizedStatus(item.status)) {
|
|
||||||
handleReauthorize(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([EnumStatus.PAUSE].includes(item.status) || isAbnormalStatus(item.status)) {
|
|
||||||
handleReauthorize(item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePause(item);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBtnText = (item) => {
|
|
||||||
if (showSyncDataButton(item.status)) {
|
|
||||||
return '更新数据';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isUnauthorizedStatus(item.status)) {
|
|
||||||
return '去授权';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([EnumStatus.PAUSE].includes(item.status) || isAbnormalStatus(item.status)) {
|
|
||||||
return '重新授权';
|
|
||||||
}
|
|
||||||
|
|
||||||
return '暂停同步';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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);
|
||||||
@ -304,8 +242,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>
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import {
|
|||||||
} from '@arco-design/web-vue';
|
} from '@arco-design/web-vue';
|
||||||
import AuthorizedAccountModal from '../authorized-account-modal';
|
import AuthorizedAccountModal from '../authorized-account-modal';
|
||||||
// import ImportPromptModal from '../import-prompt-modal';
|
// import ImportPromptModal from '../import-prompt-modal';
|
||||||
import StatusBox from '../status-box';
|
import StatusBox from '@/views/property-marketing/media-account/components/status-select/status-box.tsx';
|
||||||
import SyncDataModal from '../sync-data-modal';
|
import SyncDataModal from '../sync-data-modal';
|
||||||
import CommonSelect from '@/components/common-select';
|
import CommonSelect from '@/components/common-select';
|
||||||
|
|
||||||
@ -353,7 +353,7 @@ export default {
|
|||||||
<Input v-model={form.value.account_id} placeholder="请输入..." size="large" disabled />
|
<Input v-model={form.value.account_id} placeholder="请输入..." size="large" disabled />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
<FormItem label="状态" field="status">
|
<FormItem label="状态" field="status">
|
||||||
<StatusBox status={form.value.status} />
|
<StatusBox item={form.value} />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -1,97 +0,0 @@
|
|||||||
<!--
|
|
||||||
* @Author: RenXiaoDong
|
|
||||||
* @Date: 2025-06-25 15:31:15
|
|
||||||
-->
|
|
||||||
<template>
|
|
||||||
<div class="status-box" :class="`status-box-${status}`">
|
|
||||||
<span class="text">{{ statusText }}</span>
|
|
||||||
<a-tooltip v-if="showTooltip" :content="tooltipText">
|
|
||||||
<img v-if="showIcon" :src="iconSrc" width="12" height="12" class="ml-4px" />
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { computed } from 'vue';
|
|
||||||
import { STATUS_LIST, EnumStatus } from '@/views/property-marketing/media-account/components/status-select/constants';
|
|
||||||
|
|
||||||
import iconWarn1 from '@/assets/img/media-account/icon-warn-1.png';
|
|
||||||
import iconWarn2 from '@/assets/img/media-account/icon-warn-2.png';
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
status: {
|
|
||||||
type: Number,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const statusText = computed(() => {
|
|
||||||
return STATUS_LIST.find((v) => v.value === props.status)?.label ?? '-';
|
|
||||||
});
|
|
||||||
|
|
||||||
const showTooltip = computed(() => {
|
|
||||||
return isDisabledReauthorize(props.status);
|
|
||||||
});
|
|
||||||
|
|
||||||
const tooltipText = computed(() => {
|
|
||||||
return STATUS_LIST.find((v) => v.value === props.status)?.tooltip ?? '-';
|
|
||||||
});
|
|
||||||
|
|
||||||
const showIcon = computed(() => {
|
|
||||||
return ![EnumStatus.NORMAL, EnumStatus.UNAUTHORIZED].includes(props.status);
|
|
||||||
});
|
|
||||||
|
|
||||||
const iconSrc = computed(() => {
|
|
||||||
return props.status === EnumStatus.PAUSE ? iconWarn1 : iconWarn2;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 判断是否为禁用重新授权的状态
|
|
||||||
const isDisabledReauthorize = (status) => {
|
|
||||||
return [EnumStatus.ABNORMAL_LOGIN, EnumStatus.ABNORMAL_REQUEST, EnumStatus.ABNORMAL_FREEZE].includes(status);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.status-box {
|
|
||||||
display: flex;
|
|
||||||
padding: 0px 8px;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 2px;
|
|
||||||
background: #f2f3f5;
|
|
||||||
|
|
||||||
.text {
|
|
||||||
color: var(--BG-700, #737478);
|
|
||||||
font-family: $font-family-medium;
|
|
||||||
font-size: 12px;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 20px; /* 166.667% */
|
|
||||||
}
|
|
||||||
|
|
||||||
&-1 {
|
|
||||||
background: #ebf7f2;
|
|
||||||
.text {
|
|
||||||
color: #25c883;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-2,
|
|
||||||
&-4,
|
|
||||||
&-5,
|
|
||||||
&-6,
|
|
||||||
&-7 {
|
|
||||||
background: #ffe7e4;
|
|
||||||
.text {
|
|
||||||
color: #f64b31;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&-3 {
|
|
||||||
background: #fff7e5;
|
|
||||||
color: #ffae00;
|
|
||||||
.text {
|
|
||||||
color: #ffae00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -132,8 +132,8 @@ import BatchGroupModal from './components/batch-group-modal';
|
|||||||
|
|
||||||
import { INITIAL_QUERY, INITIAL_PAGE_INFO } from './constants';
|
import { INITIAL_QUERY, INITIAL_PAGE_INFO } from './constants';
|
||||||
import { showImportResultNotification } from '@/utils/arcoD';
|
import { showImportResultNotification } from '@/utils/arcoD';
|
||||||
import { EnumStatus } from '@/views/property-marketing/media-account/components/status-select/constants';
|
|
||||||
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 {
|
import {
|
||||||
getMediaAccounts,
|
getMediaAccounts,
|
||||||
getMediaAccountsHealth,
|
getMediaAccountsHealth,
|
||||||
@ -167,7 +167,7 @@ const healthData = ref({});
|
|||||||
const syncMediaAccounts = ref([]);
|
const syncMediaAccounts = ref([]);
|
||||||
const isLoadingTaskStatus = ref(false); // 正在查询状态中
|
const isLoadingTaskStatus = ref(false); // 正在查询状态中
|
||||||
|
|
||||||
const isAbNormalStatus = computed(() => healthData.value?.total_abnormal_number > 0);
|
const isAbNormalStatus = 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(() => selectedItems.value.length === dataSource.value.length);
|
||||||
@ -181,12 +181,11 @@ const tipLabel = computed(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
total_abnormal_number = 0,
|
abnormal_number = 0,
|
||||||
login_invalid_number = 0,
|
login_invalid_number = 0,
|
||||||
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;
|
||||||
|
|
||||||
// 定义异常类型映射
|
// 定义异常类型映射
|
||||||
@ -195,13 +194,13 @@ 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: '其他异常' },
|
// { count: abnormal_number, label: '其他异常' },
|
||||||
];
|
];
|
||||||
|
|
||||||
// 过滤出有异常的项并格式化
|
// 过滤出有异常的项并格式化
|
||||||
const abnormalLabels = abnormalTypes.filter(({ count }) => count > 0).map(({ count, label }) => `${count}个${label}`);
|
const abnormalLabels = abnormalTypes.filter(({ count }) => count > 0).map(({ count, label }) => `${count}个${label}`);
|
||||||
|
|
||||||
return `共有 ${total_abnormal_number} 个账号存在授权异常,其中:${abnormalLabels.join(',')}。`;
|
return `共有 ${abnormal_number} 个账号存在授权异常,其中:${abnormalLabels.join(',')}。`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const getData = () => {
|
const getData = () => {
|
||||||
@ -297,11 +296,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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -346,7 +345,7 @@ const onBatchSuccess = () => {
|
|||||||
getData();
|
getData();
|
||||||
};
|
};
|
||||||
const handleOpenAbnormalAccount = () => {
|
const handleOpenAbnormalAccount = () => {
|
||||||
query.value.status = 2;
|
query.value.status = 3;
|
||||||
reload();
|
reload();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,59 +2,82 @@
|
|||||||
* @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, // 正常
|
||||||
ABNORMAL = 3,
|
PAUSE = 2, // 暂停同步
|
||||||
PAUSE = 2,
|
ABNORMAL = 3, // 全部异常
|
||||||
ABNORMAL_LOGIN = 4,
|
ABNORMAL_LOGIN = 4, // 异常(登录状态失效)
|
||||||
ABNORMAL_REQUEST = 5,
|
ABNORMAL_REQUEST = 5, // 异常(请求频繁)
|
||||||
ABNORMAL_FREEZE = 6,
|
ABNORMAL_FREEZE = 6, // 异常(账号被封)
|
||||||
ABNORMAL_MISSING = 7,
|
ABNORMAL_MISSING = 7, // 异常(数据缺失)
|
||||||
|
ABNORMAL_EXPIRED = 8, // 即将过期
|
||||||
}
|
}
|
||||||
|
|
||||||
export const STATUS_LIST = [
|
export const STATUS_LIST = [
|
||||||
{
|
{
|
||||||
text: '正常',
|
text: '正常',
|
||||||
label: '正常',
|
label: '正常',
|
||||||
value: EnumStatus.NORMAL,
|
value: EnumAccountStatus.NORMAL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '即将过期',
|
||||||
|
label: '即将过期',
|
||||||
|
value: EnumAccountStatus.ABNORMAL_EXPIRED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '暂停同步',
|
text: '暂停同步',
|
||||||
label: '暂停同步',
|
label: '暂停同步',
|
||||||
value: EnumStatus.PAUSE,
|
value: EnumAccountStatus.PAUSE,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '未授权',
|
text: '全部异常',
|
||||||
label: '未授权',
|
|
||||||
value: EnumStatus.UNAUTHORIZED,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '异常',
|
|
||||||
label: '异常',
|
label: '异常',
|
||||||
value: EnumStatus.ABNORMAL,
|
value: EnumAccountStatus.ABNORMAL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '数据缺失',
|
text: '异常(未授权)',
|
||||||
label: '数据缺失',
|
|
||||||
value: EnumStatus.ABNORMAL_MISSING,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '异常-登录状态失效',
|
|
||||||
label: '异常',
|
label: '异常',
|
||||||
value: EnumStatus.ABNORMAL_LOGIN,
|
value: EnumAccountStatus.UNAUTHORIZED,
|
||||||
tooltip: '登录状态失效,需重新扫码授权',
|
tooltip: '未授权',
|
||||||
|
style: {
|
||||||
|
'padding-left': '24px',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '异常-请求过于频繁',
|
text: '异常(数据缺失)',
|
||||||
label: '异常',
|
label: '异常',
|
||||||
value: EnumStatus.ABNORMAL_REQUEST,
|
value: EnumAccountStatus.ABNORMAL_MISSING,
|
||||||
tooltip: '请求过于频繁,需等待24小时后重试',
|
tooltip: '数据缺失',
|
||||||
|
style: {
|
||||||
|
'padding-left': '24px',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '异常-账号被冻结/封禁',
|
text: '异常(登录状态失效)',
|
||||||
label: '异常',
|
label: '异常',
|
||||||
value: EnumStatus.ABNORMAL_FREEZE,
|
value: EnumAccountStatus.ABNORMAL_LOGIN,
|
||||||
tooltip: '账号被冻结/封禁',
|
tooltip: '登录状态失效',
|
||||||
|
style: {
|
||||||
|
'padding-left': '24px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '异常(请求频繁)',
|
||||||
|
label: '异常',
|
||||||
|
value: EnumAccountStatus.ABNORMAL_REQUEST,
|
||||||
|
tooltip: '请求频繁,等待24小时后重试',
|
||||||
|
style: {
|
||||||
|
'padding-left': '24px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '异常(账号被封)',
|
||||||
|
label: '异常',
|
||||||
|
value: EnumAccountStatus.ABNORMAL_FREEZE,
|
||||||
|
tooltip: '账号被封',
|
||||||
|
style: {
|
||||||
|
'padding-left': '24px',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@ -11,7 +11,13 @@
|
|||||||
allow-clear
|
allow-clear
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
>
|
>
|
||||||
<a-option v-for="(item, index) in STATUS_LIST" :key="index" :value="item.value" :label="item.text">
|
<a-option
|
||||||
|
v-for="(item, index) in STATUS_LIST"
|
||||||
|
:key="index"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.text"
|
||||||
|
:style="item.style"
|
||||||
|
>
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
</a-option>
|
</a-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
|
|||||||
@ -0,0 +1,147 @@
|
|||||||
|
import { defineComponent, computed } from 'vue';
|
||||||
|
import { Tooltip } from '@arco-design/web-vue';
|
||||||
|
|
||||||
|
import iconWarn1 from '@/assets/img/media-account/icon-warn-1.png';
|
||||||
|
import iconWarn2 from '@/assets/img/media-account/icon-warn-2.png';
|
||||||
|
import icon1 from '@/assets/img/media-account/icon-schedule.png';
|
||||||
|
|
||||||
|
export enum EnumErrorStatus {
|
||||||
|
NORMAL = 0, // 正常
|
||||||
|
UNAUTHORIZED = 1, // 未授权
|
||||||
|
LOGIN = 2, // 登录状态失效
|
||||||
|
REQUEST = 3, // 请求过于频繁
|
||||||
|
FREEZE = 4, // 账号被冻结/封禁
|
||||||
|
MISSING = 5, // 数据缺失
|
||||||
|
UNKNOWN = 6, // 未知异常
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum EnumStatus {
|
||||||
|
ABNORMAL = 0, // 异常
|
||||||
|
NORMAL = 1, // 正常
|
||||||
|
PAUSE = 2, // 暂停同步
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum EnumExpireForCookie {
|
||||||
|
NORMAL = 0, // 正常
|
||||||
|
EXPIRE = 1, // 即将过期
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalStyle = {
|
||||||
|
color: '#25c883',
|
||||||
|
background: '#ebf7f2',
|
||||||
|
};
|
||||||
|
|
||||||
|
const abnormalStyle = {
|
||||||
|
color: '#f64b31',
|
||||||
|
background: '#ffe7e4',
|
||||||
|
};
|
||||||
|
|
||||||
|
const pauseStyle = {
|
||||||
|
color: '#ffae00',
|
||||||
|
background: '#fff7e5',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const errorStatusMap = new Map([
|
||||||
|
[1, { tooltip: '未授权', text: '未授权' }],
|
||||||
|
[2, { tooltip: '登录状态失效', text: '登录状态失效' }],
|
||||||
|
[3, { tooltip: '请求频繁,等待24小时后重试', btnTooltip: '请求频繁,等待24小时后重试', text: '请求过于频繁' }],
|
||||||
|
[4, { tooltip: '账号被冻结', btnTooltip: '账号被封,解封后才能操作', text: '账号被冻结' }],
|
||||||
|
[5, { tooltip: '数据缺失', text: '数据缺失' }],
|
||||||
|
[6, { tooltip: '未知错误', text: '未知错误' }],
|
||||||
|
]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param status 状态 0-异常,1-正常,2-暂停同步
|
||||||
|
* @param error_status 异常状态 0-无异常,1-未授权,2-登录状态失效,3-请求过于频繁,4-账号被冻结/封禁,5-数据缺失,6-未知错误
|
||||||
|
* @param to_be_expire_for_cookie cookie是否即将过期 0-否,1-是
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const getStatusInfo = (
|
||||||
|
status: EnumStatus,
|
||||||
|
error_status: EnumErrorStatus,
|
||||||
|
to_be_expire_for_cookie: EnumExpireForCookie,
|
||||||
|
) => {
|
||||||
|
const statusInfo = { color: '', background: '', label: '', tooltip: '', disabledBtnTooltip: '' };
|
||||||
|
if (status === EnumStatus.ABNORMAL) {
|
||||||
|
statusInfo.color = abnormalStyle.color;
|
||||||
|
statusInfo.background = abnormalStyle.background;
|
||||||
|
statusInfo.label = '异常';
|
||||||
|
|
||||||
|
const target = errorStatusMap.get(error_status);
|
||||||
|
statusInfo.tooltip = target?.tooltip ?? '';
|
||||||
|
statusInfo.disabledBtnTooltip = target?.btnTooltip ?? '';
|
||||||
|
} else if (status === EnumStatus.NORMAL) {
|
||||||
|
if (to_be_expire_for_cookie === EnumExpireForCookie.NORMAL) {
|
||||||
|
statusInfo.color = normalStyle.color;
|
||||||
|
statusInfo.background = normalStyle.background;
|
||||||
|
statusInfo.label = '正常';
|
||||||
|
} else {
|
||||||
|
statusInfo.color = abnormalStyle.color;
|
||||||
|
statusInfo.background = abnormalStyle.background;
|
||||||
|
statusInfo.label = '即将过期';
|
||||||
|
}
|
||||||
|
} else if (status === EnumStatus.PAUSE) {
|
||||||
|
statusInfo.color = pauseStyle.color;
|
||||||
|
statusInfo.background = pauseStyle.background;
|
||||||
|
statusInfo.label = '暂停同步';
|
||||||
|
statusInfo.tooltip = '暂停同步';
|
||||||
|
}
|
||||||
|
|
||||||
|
return statusInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'StatusBox',
|
||||||
|
props: {
|
||||||
|
item: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const statusInfo = computed(() => {
|
||||||
|
const { status, error_status, to_be_expire_for_cookie } = props.item;
|
||||||
|
return getStatusInfo(status, error_status, to_be_expire_for_cookie) ?? {};
|
||||||
|
});
|
||||||
|
|
||||||
|
const renderContent = () => {
|
||||||
|
const { to_be_expire_for_cookie, status } = props.item;
|
||||||
|
const { background, color, label } = statusInfo.value;
|
||||||
|
if (status === EnumStatus.NORMAL) {
|
||||||
|
return (
|
||||||
|
<div class="flex items-center status-box">
|
||||||
|
{to_be_expire_for_cookie === EnumExpireForCookie.EXPIRE && (
|
||||||
|
<div class="flex items-center rounded-2px px-8px mr-8px" style={{ background, color }}>
|
||||||
|
<img src={icon1} width="12" height="12" class="mr-4px" />
|
||||||
|
<span class="text-12px lh-20px font-400 label">{label}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
class="flex items-center rounded-2px px-8px"
|
||||||
|
style={{ background: normalStyle.background, color: normalStyle.color }}
|
||||||
|
>
|
||||||
|
<span class="text-12px lh-20px font-400">正常</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="flex items-center rounded-2px px-8px status-box" style={{ background, color }}>
|
||||||
|
<span class="text-12px lh-20px font-400 label">{label}</span>
|
||||||
|
{status === EnumStatus.PAUSE ? (
|
||||||
|
<img src={iconWarn1} width="12" height="12" class="ml-4px" />
|
||||||
|
) : (
|
||||||
|
<Tooltip content={statusInfo.value.tooltip}>
|
||||||
|
<img src={iconWarn2} width="12" height="12" class="ml-4px" />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return () => renderContent();
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -135,7 +135,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } 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';
|
||||||
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
import { formatTableField, exactFormatTime } from '@/utils/tools';
|
||||||
import { TABLE_COLUMNS } from './constants';
|
import { TABLE_COLUMNS } from './constants';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|||||||
@ -133,7 +133,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } 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';
|
||||||
import { formatTableField } from '@/utils/tools';
|
import { formatTableField } from '@/utils/tools';
|
||||||
import { TABLE_COLUMNS } from './constants';
|
import { TABLE_COLUMNS } from './constants';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
|||||||
@ -102,7 +102,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps, ref, computed } from 'vue';
|
import { defineProps, ref, computed } from 'vue';
|
||||||
import { PLATFORM_LIST } from '@/utils/platform';
|
import { PLATFORM_LIST } from '@/utils/platform';
|
||||||
import { EnumStatus } from '@/views/property-marketing/media-account/components/status-select/constants';
|
import { EnumStatus } from '@/views/property-marketing/put-account/components/status-select/constants';
|
||||||
|
|
||||||
import { formatNumberShow, exactFormatTime } from '@/utils/tools';
|
import { formatNumberShow, exactFormatTime } from '@/utils/tools';
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ const handlePause = (item) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const showPauseButton = (status) => {
|
const showPauseButton = (status) => {
|
||||||
return status === EnumStatus.NORMAL;
|
return status === EnumPutAccountStatus.NORMAL;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -73,7 +73,7 @@
|
|||||||
import { defineEmits, defineProps } from 'vue';
|
import { defineEmits, defineProps } from 'vue';
|
||||||
import { getPlacementAccountOperators, getProjectList } from '@/api/all/propertyMarketing';
|
import { getPlacementAccountOperators, getProjectList } from '@/api/all/propertyMarketing';
|
||||||
import { PLATFORM_LIST } from '@/utils/platform';
|
import { PLATFORM_LIST } from '@/utils/platform';
|
||||||
import StatusSelect from '@/views/property-marketing/media-account/components/status-select';
|
import StatusSelect from '@/views/property-marketing/put-account/components/status-select';
|
||||||
import CommonSelect from '@/components/common-select';
|
import CommonSelect from '@/components/common-select';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
.label {
|
.label {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
color: #211f24;
|
color: #211f24;
|
||||||
font-family: 'PuHuiTi-Regular';
|
font-family: $font-family-regular;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { STATUS_LIST, EnumStatus } from '@/views/property-marketing/media-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>
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ const isDisabledReauthorize = (status) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-2,
|
&-3,
|
||||||
&-4,
|
&-4,
|
||||||
&-5,
|
&-5,
|
||||||
&-6 {
|
&-6 {
|
||||||
@ -85,7 +85,7 @@ const isDisabledReauthorize = (status) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-3 {
|
&-2{
|
||||||
background: #fff7e5;
|
background: #fff7e5;
|
||||||
color: #ffae00;
|
color: #ffae00;
|
||||||
.text {
|
.text {
|
||||||
|
|||||||
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* @Author: RenXiaoDong
|
||||||
|
* @Date: 2025-07-04 11:18:11
|
||||||
|
*/
|
||||||
|
export enum EnumPutAccountStatus {
|
||||||
|
UNAUTHORIZED = 0,
|
||||||
|
NORMAL = 1,
|
||||||
|
ABNORMAL = 3,
|
||||||
|
PAUSE = 2,
|
||||||
|
ABNORMAL_LOGIN = 4,
|
||||||
|
ABNORMAL_REQUEST = 5,
|
||||||
|
ABNORMAL_FREEZE = 6,
|
||||||
|
ABNORMAL_MISSING = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
export const STATUS_LIST = [
|
||||||
|
{
|
||||||
|
text: '正常',
|
||||||
|
label: '正常',
|
||||||
|
value: EnumPutAccountStatus.NORMAL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '暂停同步',
|
||||||
|
label: '暂停同步',
|
||||||
|
value: EnumPutAccountStatus.PAUSE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '未授权',
|
||||||
|
label: '未授权',
|
||||||
|
value: EnumPutAccountStatus.UNAUTHORIZED,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '异常',
|
||||||
|
label: '异常',
|
||||||
|
value: EnumPutAccountStatus.ABNORMAL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '数据缺失',
|
||||||
|
label: '数据缺失',
|
||||||
|
value: EnumPutAccountStatus.ABNORMAL_MISSING,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '异常-登录状态失效',
|
||||||
|
label: '异常',
|
||||||
|
value: EnumPutAccountStatus.ABNORMAL_LOGIN,
|
||||||
|
tooltip: '登录状态失效,需重新扫码授权',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '异常-请求过于频繁',
|
||||||
|
label: '异常',
|
||||||
|
value: EnumPutAccountStatus.ABNORMAL_REQUEST,
|
||||||
|
tooltip: '请求过于频繁,需等待24小时后重试',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '异常-账号被冻结/封禁',
|
||||||
|
label: '异常',
|
||||||
|
value: EnumPutAccountStatus.ABNORMAL_FREEZE,
|
||||||
|
tooltip: '账号被冻结/封禁',
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: RenXiaoDong
|
||||||
|
* @Date: 2025-06-25 14:02:40
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<a-select
|
||||||
|
v-model="selectedStatus"
|
||||||
|
:multiple="multiple"
|
||||||
|
size="medium"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
allow-clear
|
||||||
|
@change="handleChange"
|
||||||
|
>
|
||||||
|
<a-option v-for="(item, index) in STATUS_LIST" :key="index" :value="item.value" :label="item.text">
|
||||||
|
{{ item.text }}
|
||||||
|
</a-option>
|
||||||
|
</a-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
import { STATUS_LIST } from '@/views/property-marketing/put-account/components/status-select/constants';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: [Array, String, Number],
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '全部',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:modelValue', 'change']);
|
||||||
|
|
||||||
|
const selectedStatus = ref(props.multiple ? [] : '');
|
||||||
|
|
||||||
|
// 监听外部传入的值变化
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
(newVal) => {
|
||||||
|
selectedStatus.value = newVal;
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
// 监听内部值变化,向外部发送更新
|
||||||
|
watch(selectedStatus, (newVal) => {
|
||||||
|
emits('update:modelValue', newVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleChange = (value) => {
|
||||||
|
selectedStatus.value = value;
|
||||||
|
emits('change', value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user