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 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 accountId = ref(null);
@ -56,11 +56,12 @@ const open = (record) => {
};
async function onDelete() {
const _fn = isBatch ? batchDeleteMediaAccounts : deleteMediaAccount;
const { code } = await _fn(accountId.value);
const _fn = isBatch.value ? batchDeleteMediaAccounts : deleteMediaAccount;
const _params = isBatch.value ? { ids: accountId.value } : { id: accountId.value };
const { code } = await _fn(_params);
if (code === 200) {
AMessage.success('删除成功');
emits('success');
emits('update');
onClose();
}
}

View File

@ -58,13 +58,29 @@
</div>
</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>
</div>
</div>
</div>
<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
v-if="showPauseButton(item.status)"
class="w-64px search-btn mr-8px"
@ -73,7 +89,7 @@
>
<template #default>暂停同步</template>
</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)">
<template #default>重新授权</template>
</a-button>
@ -86,7 +102,7 @@
<a-button class="w-40px search-btn" size="mini" @click="openEdit(item)">
<template #default>编辑</template>
</a-button>
</a-button> -->
</div>
</div>
</div>
@ -107,7 +123,7 @@ import AuthorizedAccountModal from '../authorized-account-modal';
import icon1 from '@/assets/img/media-account/icon-dy.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({
dataSource: {
@ -170,13 +186,44 @@ const isUnauthorizedStatus = (status) => {
};
// 三种异常情况
const isDisabledReauthorize = (status) => {
return [EnumStatus.ABNORMAL_LOGIN, EnumStatus.ABNORMAL_REQUEST, EnumStatus.ABNORMAL_FREEZE].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 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>
<style scoped lang="scss">

View File

@ -34,7 +34,7 @@
<div class="img-box">
<template v-if="qrCodeLoading">
<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">
<icon-loading size="24" class="color-#6D4CFE mb-13px" />
<span class="s2 !color-#6D4CFE">二维码生成中...</span>
@ -44,7 +44,7 @@
></div>
</div>
</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">
<icon-refresh size="24" class="mb-13px" />
@ -84,6 +84,8 @@ const isSuccess = ref(false);
const failReason = ref('');
const progress = ref(0);
const id = ref('');
const qrCodeError = ref(false);
const qrCodeUrl = ref('');
const qrCodeLoading = ref(false);
@ -110,6 +112,7 @@ const resetTaskFields = () => {
progress.value = 0;
qrCodeUrl.value = '';
qrCodeLoading.value = false;
qrCodeError.value = false;
};
const close = () => {
resetTaskFields();
@ -133,7 +136,11 @@ const getAuthorizedQrCode = async () => {
overdueTimer = setTimeout(() => {
isOverdue.value = true;
}, OVERDUE_TIME);
} else {
qrCodeError.value = true;
}
} catch (error) {
qrCodeError.value = true;
} finally {
qrCodeLoading.value = false;
}

View File

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

View File

@ -34,7 +34,7 @@
<div class="img-box">
<template v-if="qrCodeLoading">
<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">
<icon-loading size="24" class="color-#6D4CFE mb-13px" />
<span class="s2 !color-#6D4CFE">二维码生成中...</span>
@ -44,7 +44,7 @@
></div>
</div>
</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">
<icon-refresh size="24" class="mb-13px" />
@ -121,6 +121,8 @@ const isSuccess = ref(false);
const failReason = ref('');
const progress = ref(0);
const id = ref('');
const qrCodeError = ref(false);
const qrCodeUrl = ref('');
const qrCodeLoading = ref(false);
@ -160,6 +162,7 @@ const resetTaskFields = () => {
qrCodeUrl.value = '';
qrCodeLoading.value = false;
isNicknameChanged.value = false;
qrCodeError.value = false;
actionType.value = 1;
taskStep.value = TASK_STEP.default;
};
@ -211,7 +214,11 @@ const getAuthorizedQrCode = async () => {
overdueTimer = setTimeout(() => {
isOverdue.value = true;
}, OVERDUE_TIME);
} else {
qrCodeError.value = true;
}
} catch (error) {
qrCodeError.value = true;
} finally {
qrCodeLoading.value = false;
}

View File

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

View File

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

View File

@ -57,7 +57,7 @@ const open = (record) => {
async function onDelete() {
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);
if (code === 200) {
AMessage.success('删除成功');

View File

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

View File

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