feat(ads/compliance): add account select filter and optimize csv export

1. 新增获取广告账户列表的API接口
2. 将搜索表单的账户ID输入框改为下拉选择器
3. 优化CSV导出的表头和日期格式处理,避免Excel解析问题
This commit is contained in:
2026-05-15 14:48:33 +08:00
parent 1991f74b7e
commit f1cfa21118
2 changed files with 70 additions and 26 deletions

View File

@@ -169,3 +169,17 @@ export function exportRejectedMaterials(data: ExportParams = {}, requestOptions?
requestOptions,
});
}
export interface AccountItem {
accountId: number;
corporationName: string;
}
export function getAccountList(requestOptions?: RequestOptions) {
return request({
url: '/cid/material/verify/controller/list-accounts',
method: 'post',
data: {},
requestOptions,
});
}

View File

@@ -19,14 +19,15 @@
<el-option label="校验不通过" value="REJECTED"></el-option>
</el-select>
</el-form-item>
<el-form-item label="账户ID">
<el-input
v-model="imageFilters.accountId"
placeholder="账户ID"
style="width: 150px"
clearable
@keyup.enter="searchImage"
></el-input>
<el-form-item label="账户">
<el-select v-model="imageFilters.accountId" placeholder="请选择账户" style="width: 220px" clearable>
<el-option
v-for="account in accountList"
:key="account.accountId"
:label="`${account.accountId} - ${account.corporationName}`"
:value="String(account.accountId)"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchImage">搜索</el-button>
@@ -106,14 +107,15 @@
<el-option label="校验不通过" value="REJECTED"></el-option>
</el-select>
</el-form-item>
<el-form-item label="账户ID">
<el-input
v-model="videoFilters.accountId"
placeholder="账户ID"
style="width: 150px"
clearable
@keyup.enter="searchVideo"
></el-input>
<el-form-item label="账户">
<el-select v-model="videoFilters.accountId" placeholder="请选择账户" style="width: 220px" clearable>
<el-option
v-for="account in accountList"
:key="account.accountId"
:label="`${account.accountId} - ${account.corporationName}`"
:value="String(account.accountId)"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchVideo">搜索</el-button>
@@ -228,6 +230,7 @@ import {
getVideoList,
getVerifyLogList,
exportRejectedMaterials,
getAccountList,
// manualVerifyImage,
// manualVerifyVideo,
// pollImageResults as pollImageResultsApi,
@@ -241,6 +244,9 @@ const activeTab = ref('image');
// const pollLoading = ref(false);
// const batchLoading = ref(false);
// 账户列表
const accountList = ref<any[]>([]);
// 图片统计
const imageStats = reactive({ pending: 0, verified: 0, rejected: 0 });
// 视频统计
@@ -476,25 +482,35 @@ const exportVideoUrls = () => {
};
const downloadJsonAsCsv = (filename: string, items: any[]) => {
const headers = ['ID', '素材ID', '账户ID', '公司名称', '预览URL', '描述', '错误信息', '素材类型', '图片用途', '创建时间'];
const headers = ['序号', '账户(名称)', '预览URL', '描述', '失败原因', '检测时间'];
const rows = [headers];
items.forEach((item) => {
items.forEach((item, index) => {
// 将日期转换为 Excel 可识别的格式,添加等号前缀强制作为文本处理
const formattedDate = item.createdAt ? `="${item.createdAt}"` : '-';
rows.push([
item.id,
item.materialId,
item.accountId,
item.corporationName || '-',
index + 1,
`${item.accountId} - ${item.corporationName || ''}`,
(item.previewUrl || '').trim(),
item.description || '-',
item.errorMsg || '-',
item.materialType || '-',
item.imageUsage || '-',
item.createdAt || '-',
formattedDate,
]);
});
const csv = rows.map((r) => r.map((v) => `"${String(v).replace(/"/g, '""')}"`).join(',')).join('\n');
const csv = rows
.map((r) =>
r
.map((v) => {
// 如果值以 "=" 开头,需要特殊处理避免被 Excel 当作公式
if (String(v).startsWith('=')) {
return v;
}
return `"${String(v).replace(/"/g, '""')}"`;
})
.join(',')
)
.join('\n');
const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
@@ -671,8 +687,22 @@ const getLogTypeText = (type: string) => {
return map[type] || type || '信息';
};
// 加载账户列表
const loadAccountList = () => {
getAccountList()
.then((res: any) => {
if (res.data && res.data.list) {
accountList.value = res.data.list;
}
})
.catch(() => {
ElMessage.error('获取账户列表失败');
});
};
// 组件挂载时加载数据
onMounted(() => {
loadAccountList();
loadStats();
loadImageList();
});