feat: 优化账号管理操作部分交互

This commit is contained in:
rd
2025-07-04 15:49:42 +08:00
parent 6e590dbb04
commit c49e12d988
10 changed files with 96 additions and 29 deletions

View File

@ -32,7 +32,7 @@ import { ref } from 'vue';
import { deleteMediaAccount, batchDeleteMediaAccounts } from '@/api/all/propertyMarketing'; import { deleteMediaAccount, batchDeleteMediaAccounts } from '@/api/all/propertyMarketing';
import icon1 from '@/assets/img/media-account/icon-warn-1.png'; import icon1 from '@/assets/img/media-account/icon-warn-1.png';
const emits = defineEmits(['success', 'close']); const emits = defineEmits(['update', 'close']);
const visible = ref(false); const visible = ref(false);
const accountId = ref(null); const accountId = ref(null);
@ -56,11 +56,12 @@ const open = (record) => {
}; };
async function onDelete() { async function onDelete() {
const _fn = isBatch ? batchDeleteMediaAccounts : deleteMediaAccount; const _fn = isBatch.value ? batchDeleteMediaAccounts : deleteMediaAccount;
const { code } = await _fn(accountId.value); const _params = isBatch.value ? { ids: accountId.value } : { id: accountId.value };
const { code } = await _fn(_params);
if (code === 200) { if (code === 200) {
AMessage.success('删除成功'); AMessage.success('删除成功');
emits('success'); emits('update');
onClose(); onClose();
} }
} }

View File

@ -58,13 +58,29 @@
</div> </div>
</a-tooltip> </a-tooltip>
<div v-for="(tag, index) in item.tags.slice(0, 2).reverse()" :key="index" class="tag-box"> <div v-for="(tag, index) in item.tags.slice(0, 2)" :key="index" class="tag-box">
<span class="text">{{ tag.name }}</span> <span class="text">{{ tag.name }}</span>
</div> </div>
</div> </div>
</div> </div>
<div class="operate-row"> <div class="operate-row">
<img :src="icon3" width="16" height="16" class="mr-8px cursor-pointer" @click="openDelete(item)" /> <a-dropdown trigger="hover">
<a-button class="w-52px search-btn mr-8px" size="mini">
<template #default>更多</template>
</a-button>
<template #content>
<a-doption class="color-#211F24" @click="openEdit(item)">编辑</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 class="search-btn" size="mini" @click="onBtnClick(item)">
<template #default>{{ getBtnText(item) }}</template>
</a-button>
</a-dropdown>
<!-- <img :src="icon3" width="16" height="16" class="mr-8px cursor-pointer" @click="openDelete(item)" />
<a-button <a-button
v-if="showPauseButton(item.status)" v-if="showPauseButton(item.status)"
class="w-64px search-btn mr-8px" class="w-64px search-btn mr-8px"
@ -73,7 +89,7 @@
> >
<template #default>暂停同步</template> <template #default>暂停同步</template>
</a-button> </a-button>
<a-tooltip v-if="isDisabledReauthorize(item.status)" :content="getTooltipText(item.status)"> <a-tooltip v-if="isAbnormalStatus(item.status)" :content="getTooltipText(item.status)">
<a-button class="w-64px search-btn mr-8px" size="mini" @click="handleReauthorize(item)"> <a-button class="w-64px search-btn mr-8px" size="mini" @click="handleReauthorize(item)">
<template #default>重新授权</template> <template #default>重新授权</template>
</a-button> </a-button>
@ -86,7 +102,7 @@
<a-button class="w-40px search-btn" size="mini" @click="openEdit(item)"> <a-button class="w-40px search-btn" size="mini" @click="openEdit(item)">
<template #default>编辑</template> <template #default>编辑</template>
</a-button> </a-button> -->
</div> </div>
</div> </div>
</div> </div>
@ -107,7 +123,7 @@ import AuthorizedAccountModal from '../authorized-account-modal';
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-delete.png'; // import icon3 from '@/assets/img/media-account/icon-delete.png';
const props = defineProps({ const props = defineProps({
dataSource: { dataSource: {
@ -170,13 +186,44 @@ const isUnauthorizedStatus = (status) => {
}; };
// 三种异常情况 // 三种异常情况
const isDisabledReauthorize = (status) => { const isAbnormalStatus = (status) => {
return [EnumStatus.ABNORMAL_LOGIN, EnumStatus.ABNORMAL_REQUEST, EnumStatus.ABNORMAL_FREEZE].includes(status); return [
EnumStatus.ABNORMAL,
EnumStatus.ABNORMAL_LOGIN,
EnumStatus.ABNORMAL_REQUEST,
EnumStatus.ABNORMAL_FREEZE,
].includes(status);
}; };
const getTooltipText = (status) => { const getTooltipText = (status) => {
return STATUS_LIST.find((v) => v.value === status)?.tooltip ?? '-'; return STATUS_LIST.find((v) => v.value === status)?.tooltip ?? '-';
}; };
const onBtnClick = (item) => {
if (isUnauthorizedStatus(item.status)) {
handleReauthorize(item);
return;
}
if ([EnumStatus.PAUSE, EnumStatus.NORMAL].includes(item.status) || isAbnormalStatus(item.status)) {
handleReauthorize(item);
return;
}
handlePause(item);
};
const getBtnText = (item) => {
if (isUnauthorizedStatus(item.status)) {
return '去授权';
}
if ([EnumStatus.PAUSE, EnumStatus.NORMAL].includes(item.status) || isAbnormalStatus(item.status)) {
return '重新授权';
}
return '暂停同步';
};
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -34,7 +34,7 @@
<div class="img-box"> <div class="img-box">
<template v-if="qrCodeLoading"> <template v-if="qrCodeLoading">
<div class="relative w-160px h-160px"> <div class="relative w-160px h-160px">
<img :src="icon1" width="160" height="160" /> <a-image :src="icon1" width="160" height="160" />
<div class="absolute top-0 left-0 z-2 w-full h-full flex flex-col items-center justify-center"> <div class="absolute top-0 left-0 z-2 w-full h-full flex flex-col items-center justify-center">
<icon-loading size="24" class="color-#6D4CFE mb-13px" /> <icon-loading size="24" class="color-#6D4CFE mb-13px" />
<span class="s2 !color-#6D4CFE">二维码生成中...</span> <span class="s2 !color-#6D4CFE">二维码生成中...</span>
@ -44,7 +44,7 @@
></div> ></div>
</div> </div>
</template> </template>
<img v-else :src="qrCodeUrl" width="160" height="160" /> <a-image v-else :src="qrCodeUrl" width="160" height="160" />
<div v-if="isOverdue" class="mask cursor-pointer" @click="getAuthorizedQrCode"> <div v-if="isOverdue" class="mask cursor-pointer" @click="getAuthorizedQrCode">
<icon-refresh size="24" class="mb-13px" /> <icon-refresh size="24" class="mb-13px" />
@ -84,6 +84,8 @@ const isSuccess = ref(false);
const failReason = ref(''); const failReason = ref('');
const progress = ref(0); const progress = ref(0);
const id = ref(''); const id = ref('');
const qrCodeError = ref(false);
const qrCodeUrl = ref(''); const qrCodeUrl = ref('');
const qrCodeLoading = ref(false); const qrCodeLoading = ref(false);
@ -110,6 +112,7 @@ const resetTaskFields = () => {
progress.value = 0; progress.value = 0;
qrCodeUrl.value = ''; qrCodeUrl.value = '';
qrCodeLoading.value = false; qrCodeLoading.value = false;
qrCodeError.value = false;
}; };
const close = () => { const close = () => {
resetTaskFields(); resetTaskFields();
@ -133,7 +136,11 @@ const getAuthorizedQrCode = async () => {
overdueTimer = setTimeout(() => { overdueTimer = setTimeout(() => {
isOverdue.value = true; isOverdue.value = true;
}, OVERDUE_TIME); }, OVERDUE_TIME);
} else {
qrCodeError.value = true;
} }
} catch (error) {
qrCodeError.value = true;
} finally { } finally {
qrCodeLoading.value = false; qrCodeLoading.value = false;
} }

View File

@ -97,14 +97,14 @@ const isEdit = ref(false);
const addGroupRef = ref(null); const addGroupRef = ref(null);
const deleteGroupRef = ref(null); const deleteGroupRef = ref(null);
const currentGroup = ref(null); // const currentGroup = ref(null);
const list = ref([]); const list = ref([]);
const loading = ref(false); const loading = ref(false);
const query = ref({ const query = ref({
name: '', name: '',
sort_column: '', sort_column: undefined,
sort_order: '', sort_order: undefined,
}); });
const pageInfo = ref({ const pageInfo = ref({
page: 1, page: 1,
@ -138,8 +138,8 @@ function open() {
const close = () => { const close = () => {
query.value.name = ''; query.value.name = '';
query.value.sort_column = ''; query.value.sort_column = undefined;
query.value.sort_order = ''; query.value.sort_order = undefined;
pageInfo.value.page = 1; pageInfo.value.page = 1;
pageInfo.value.pageSize = 20; pageInfo.value.pageSize = 20;
pageInfo.value.total = 0; pageInfo.value.total = 0;

View File

@ -34,7 +34,7 @@
<div class="img-box"> <div class="img-box">
<template v-if="qrCodeLoading"> <template v-if="qrCodeLoading">
<div class="relative w-160px h-160px"> <div class="relative w-160px h-160px">
<img :src="icon1" width="160" height="160" /> <a-image :src="icon1" width="160" height="160" />
<div class="absolute top-0 left-0 z-2 w-full h-full flex flex-col items-center justify-center"> <div class="absolute top-0 left-0 z-2 w-full h-full flex flex-col items-center justify-center">
<icon-loading size="24" class="color-#6D4CFE mb-13px" /> <icon-loading size="24" class="color-#6D4CFE mb-13px" />
<span class="s2 !color-#6D4CFE">二维码生成中...</span> <span class="s2 !color-#6D4CFE">二维码生成中...</span>
@ -44,7 +44,7 @@
></div> ></div>
</div> </div>
</template> </template>
<img v-else :src="qrCodeUrl" width="160" height="160" /> <a-image v-else :src="qrCodeUrl" width="160" height="160" />
<div v-if="isOverdue" class="mask cursor-pointer" @click="getAuthorizedQrCode"> <div v-if="isOverdue" class="mask cursor-pointer" @click="getAuthorizedQrCode">
<icon-refresh size="24" class="mb-13px" /> <icon-refresh size="24" class="mb-13px" />
@ -121,6 +121,8 @@ const isSuccess = ref(false);
const failReason = ref(''); const failReason = ref('');
const progress = ref(0); const progress = ref(0);
const id = ref(''); const id = ref('');
const qrCodeError = ref(false);
const qrCodeUrl = ref(''); const qrCodeUrl = ref('');
const qrCodeLoading = ref(false); const qrCodeLoading = ref(false);
@ -160,6 +162,7 @@ const resetTaskFields = () => {
qrCodeUrl.value = ''; qrCodeUrl.value = '';
qrCodeLoading.value = false; qrCodeLoading.value = false;
isNicknameChanged.value = false; isNicknameChanged.value = false;
qrCodeError.value = false;
actionType.value = 1; actionType.value = 1;
taskStep.value = TASK_STEP.default; taskStep.value = TASK_STEP.default;
}; };
@ -211,7 +214,11 @@ const getAuthorizedQrCode = async () => {
overdueTimer = setTimeout(() => { overdueTimer = setTimeout(() => {
isOverdue.value = true; isOverdue.value = true;
}, OVERDUE_TIME); }, OVERDUE_TIME);
} else {
qrCodeError.value = true;
} }
} catch (error) {
qrCodeError.value = true;
} finally { } finally {
qrCodeLoading.value = false; qrCodeLoading.value = false;
} }

View File

@ -81,6 +81,7 @@
@selectionChange="handleSelectionChange" @selectionChange="handleSelectionChange"
@delete="handleDelete" @delete="handleDelete"
@openEdit="handleOpenEdit" @openEdit="handleOpenEdit"
@update="getData"
/> />
<NoData v-else /> <NoData v-else />

View File

@ -98,8 +98,8 @@ const list = ref([]);
const loading = ref(false); const loading = ref(false);
const query = ref({ const query = ref({
name: '', name: '',
sort_column: '', sort_column: undefined,
sort_order: '', sort_order: undefined,
}); });
const pageInfo = ref({ const pageInfo = ref({
page: 1, page: 1,
@ -139,8 +139,8 @@ const close = () => {
pageInfo.value.page = 1; pageInfo.value.page = 1;
pageInfo.value.pageSize = 20; pageInfo.value.pageSize = 20;
pageInfo.value.total = 0; pageInfo.value.total = 0;
query.value.sort_column = ''; query.value.sort_column = undefined;
query.value.sort_order = ''; query.value.sort_order = undefined;
list.value = []; list.value = [];
visible.value = false; visible.value = false;
}; };

View File

@ -57,7 +57,7 @@ const open = (record) => {
async function onDelete() { async function onDelete() {
const _fn = isBatch.value ? batchDeletePlacementAccounts : deletePlacementAccount; const _fn = isBatch.value ? batchDeletePlacementAccounts : deletePlacementAccount;
const _params = isBatch.value ? { ids: accountId.value } : accountId.value; const _params = isBatch.value ? { ids: accountId.value } : { id: accountId.value };
const { code } = await _fn(_params); const { code } = await _fn(_params);
if (code === 200) { if (code === 200) {
AMessage.success('删除成功'); AMessage.success('删除成功');

View File

@ -85,10 +85,13 @@ const lastSyncedAt = ref(null);
const syncType = ref('sync'); // sync no_sync const syncType = ref('sync'); // sync no_sync
const showSyncTip = ref(false); const showSyncTip = ref(false);
const form = ref({ const INITIAL_FORM = {
account: '', account: '',
password: '', password: '',
}); };
const form = ref(cloneDeep(INITIAL_FORM));
let progressTimer = null; let progressTimer = null;
let statusPollingTimer = null; let statusPollingTimer = null;
@ -118,6 +121,7 @@ const close = () => {
formRef.value?.resetFields(); formRef.value?.resetFields();
formRef.value?.clearValidate(); formRef.value?.clearValidate();
form.value = cloneDeep(INITIAL_FORM);
isLoading.value = false; isLoading.value = false;
isCompleted.value = false; isCompleted.value = false;
isSuccess.value = false; isSuccess.value = false;

View File

@ -230,12 +230,12 @@ const handleChangeAll = (val) => {
}; };
const handleBatchDelete = () => { const handleBatchDelete = () => {
const ids = selectedItems.value.map((item) => item.id); const ids = selectedItems.value.map((item) => item.id);
const names = selectedItems.value.map((item) => `"${item.name}"`).join(','); const names = selectedItems.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) => {
const { id, name } = item; const { id, name } = item;
deleteAccountRef.value?.open({ id, name: `"${name}"` }); deleteAccountRef.value?.open({ id, name: `"${name || '-'}"` });
}; };
const handleCloseTip = () => { const handleCloseTip = () => {
selectedItems.value = []; selectedItems.value = [];