feat(customer): 新增ICC客户信息同步功能 - OAuth2密码模式鉴权拉取org_base客户、按icc_code幂等upsert写入并记录icc_sync_log,注册每10分钟定时任务;客户档案管理页新增手动'同步客户'按钮(POST /api/customers/sync/icc),同步后自动刷新列表与统计;customer表新增icc_code字段及唯一索引,同步db_seed与设计文档
This commit is contained in:
1 parent
be91d04431
commit
9d3bb13ecf
24 files changed
+1159
-5
No files matched your search
@@ -19,6 +19,10 @@
|
||||
<p class="desc">统一维护客户的基础资料、联系信息与业务阶段,支持快速检索与档案管理。</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<a-button :loading="syncing" @click="handleSync">
|
||||
<template #icon><SyncOutlined /></template>
|
||||
同步客户
|
||||
</a-button>
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
新增客户
|
||||
@@ -323,13 +327,14 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import {
|
||||
SearchOutlined,
|
||||
ReloadOutlined,
|
||||
PlusOutlined,
|
||||
DeleteOutlined,
|
||||
EditOutlined,
|
||||
SyncOutlined,
|
||||
TeamOutlined,
|
||||
AimOutlined,
|
||||
FileProtectOutlined,
|
||||
@@ -352,6 +357,7 @@ const permissionStore = usePermissionStore();
|
||||
|
||||
// ==================== 数据 ====================
|
||||
const loading = ref(false);
|
||||
const syncing = ref(false);
|
||||
const dataSource = ref<CustomerInfo[]>([]);
|
||||
const total = ref(0);
|
||||
const editNo = ref<string>('');
|
||||
@@ -568,6 +574,38 @@ function getSalesmanName(id?: number) {
|
||||
return found?.label ?? '-';
|
||||
}
|
||||
|
||||
// ==================== ICC 手动同步 ====================
|
||||
function handleSync() {
|
||||
Modal.confirm({
|
||||
title: '同步客户',
|
||||
content: '将从 ICC 平台拉取客户信息,并按 ICC 客户编号幂等新增/更新本地客户档案,是否继续?',
|
||||
okText: '开始同步',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
syncing.value = true;
|
||||
try {
|
||||
const res: any = await customerApi.syncIccCustomers();
|
||||
if (res.code === 200) {
|
||||
const d = res.data || {};
|
||||
const pulled = d.pulled ?? 0;
|
||||
const inserted = d.inserted ?? 0;
|
||||
const updated = d.updated ?? 0;
|
||||
const skipped = d.skipped ?? 0;
|
||||
message.success(`同步完成:拉取 ${pulled} 条,新增 ${inserted} 条,更新 ${updated} 条,跳过 ${skipped} 条`);
|
||||
fetchList();
|
||||
fetchStats();
|
||||
} else {
|
||||
message.error(res.message || '同步失败');
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('同步失败,请稍后重试');
|
||||
} finally {
|
||||
syncing.value = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== 搜索重置 ====================
|
||||
function handleSearch() {
|
||||
searchForm.page = 1;
|
||||
|
||||
Reference in new issue
Block a user