khhao 自动同步
This commit is contained in:
@@ -17,6 +17,7 @@ import type {
|
||||
AdminAgisoShopConfigItem,
|
||||
AdminKhhaoLoginTestResult,
|
||||
AdminKhhaoOrderQueryResult,
|
||||
AdminKhhaoSyncState,
|
||||
AdminKhhaoOrderSyncResult,
|
||||
} from '@/types/admin'
|
||||
import { hasAdminRole } from '@/utils/admin-auth'
|
||||
@@ -47,6 +48,7 @@ const activePlatform = ref<PlatformTab>('agiso')
|
||||
|
||||
const agisoFilePath = ref('')
|
||||
const khhaoFilePath = ref('')
|
||||
const khhaoStateFilePath = ref('')
|
||||
const defaults = ref<EditableDefaults>(createEmptyDefaults())
|
||||
const shops = ref<EditableShop[]>([])
|
||||
const observedShops = ref<AdminAgisoObservedShopItem[]>([])
|
||||
@@ -59,6 +61,10 @@ const khhaoForm = ref({
|
||||
page: 1,
|
||||
limit: 10,
|
||||
maxCaptchaAttempts: 3,
|
||||
autoSyncEnabled: false,
|
||||
autoSyncIntervalMinutes: 3,
|
||||
autoSyncPages: 2,
|
||||
autoSyncPageSize: 20,
|
||||
})
|
||||
const khhaoTesting = ref(false)
|
||||
const khhaoQuerying = ref(false)
|
||||
@@ -67,6 +73,7 @@ const khhaoResultError = ref('')
|
||||
const khhaoLoginResult = ref<AdminKhhaoLoginTestResult | null>(null)
|
||||
const khhaoQueryResult = ref<AdminKhhaoOrderQueryResult | null>(null)
|
||||
const khhaoSyncResult = ref<AdminKhhaoOrderSyncResult | null>(null)
|
||||
const khhaoAutoSyncState = ref<AdminKhhaoSyncState | null>(null)
|
||||
|
||||
const agisoStats = computed(() => ({
|
||||
configuredShopCount: shops.value.length,
|
||||
@@ -77,8 +84,8 @@ const agisoStats = computed(() => ({
|
||||
const khhaoStats = computed(() => ({
|
||||
hasCredential: Boolean(khhaoForm.value.username.trim() && khhaoForm.value.password.trim()),
|
||||
queryCount: khhaoQueryResult.value?.itemCount || 0,
|
||||
syncedCount: khhaoSyncResult.value?.syncedCount || 0,
|
||||
ignoredCount: khhaoSyncResult.value?.ignoredCount || 0,
|
||||
syncedCount: khhaoAutoSyncState.value?.syncedCount || khhaoSyncResult.value?.syncedCount || 0,
|
||||
ignoredCount: khhaoAutoSyncState.value?.ignoredCount || khhaoSyncResult.value?.ignoredCount || 0,
|
||||
}))
|
||||
|
||||
function createEmptyDefaults(): EditableDefaults {
|
||||
@@ -141,6 +148,8 @@ async function loadConfigs() {
|
||||
expandedShopIds.value = []
|
||||
|
||||
khhaoFilePath.value = khhaoResponse.data.filePath
|
||||
khhaoStateFilePath.value = khhaoResponse.data.stateFilePath
|
||||
khhaoAutoSyncState.value = khhaoResponse.data.syncState
|
||||
khhaoForm.value = {
|
||||
baseUrl: khhaoResponse.data.source.baseUrl || 'https://admin.khhao.com',
|
||||
username: khhaoResponse.data.source.username || '',
|
||||
@@ -148,6 +157,10 @@ async function loadConfigs() {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
maxCaptchaAttempts: khhaoResponse.data.source.maxCaptchaAttempts || 3,
|
||||
autoSyncEnabled: khhaoResponse.data.source.autoSync?.enabled === true,
|
||||
autoSyncIntervalMinutes: khhaoResponse.data.source.autoSync?.intervalMinutes || 3,
|
||||
autoSyncPages: khhaoResponse.data.source.autoSync?.pages || 2,
|
||||
autoSyncPageSize: khhaoResponse.data.source.autoSync?.pageSize || 20,
|
||||
}
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof Error ? error.message : '读取平台配置失败'
|
||||
@@ -294,8 +307,16 @@ async function handleKhhaoSaveSource() {
|
||||
username: khhaoForm.value.username.trim(),
|
||||
password: khhaoForm.value.password.trim(),
|
||||
maxCaptchaAttempts: Number(khhaoForm.value.maxCaptchaAttempts || 3),
|
||||
autoSync: {
|
||||
enabled: Boolean(khhaoForm.value.autoSyncEnabled),
|
||||
intervalMinutes: Number(khhaoForm.value.autoSyncIntervalMinutes || 3),
|
||||
pages: Number(khhaoForm.value.autoSyncPages || 2),
|
||||
pageSize: Number(khhaoForm.value.autoSyncPageSize || 20),
|
||||
},
|
||||
})
|
||||
khhaoFilePath.value = response.data.filePath
|
||||
khhaoStateFilePath.value = response.data.stateFilePath
|
||||
khhaoAutoSyncState.value = response.data.syncState
|
||||
showSuccess('khhao 来源配置已保存')
|
||||
} catch (error) {
|
||||
khhaoResultError.value = error instanceof Error ? error.message : 'khhao 来源配置保存失败'
|
||||
@@ -610,6 +631,10 @@ onMounted(loadConfigs)
|
||||
<span class="meta-label">配置文件</span>
|
||||
<code>{{ khhaoFilePath || '-' }}</code>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">状态文件</span>
|
||||
<code>{{ khhaoStateFilePath || '-' }}</code>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">职责</span>
|
||||
<span>管理 khhao 的来源地址、登录账号、密码与验证码重试次数,并执行测试登录、查询订单与手动同步。</span>
|
||||
@@ -660,6 +685,29 @@ onMounted(loadConfigs)
|
||||
<span>验证码重试次数</span>
|
||||
<input v-model.number="khhaoForm.maxCaptchaAttempts" class="text-input" type="number" min="1" max="5" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>自动同步开关</span>
|
||||
<label class="checkbox-line checkbox-box">
|
||||
<input v-model="khhaoForm.autoSyncEnabled" type="checkbox" />
|
||||
<span>启用自动同步</span>
|
||||
</label>
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>同步间隔(分钟)</span>
|
||||
<input v-model.number="khhaoForm.autoSyncIntervalMinutes" class="text-input" type="number" min="1" max="60" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>同步页数</span>
|
||||
<input v-model.number="khhaoForm.autoSyncPages" class="text-input" type="number" min="1" max="5" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>每页条数</span>
|
||||
<input v-model.number="khhaoForm.autoSyncPageSize" class="text-input" type="number" min="1" max="50" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<p v-if="khhaoResultError" class="error-copy">{{ khhaoResultError }}</p>
|
||||
@@ -689,6 +737,33 @@ onMounted(loadConfigs)
|
||||
<p v-else>完成履约配置后可在这里手动同步。</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<div v-if="khhaoAutoSyncState" class="meta-card compact-meta">
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">自动同步状态</span>
|
||||
<span>{{ khhaoAutoSyncState.lastRunStatus || 'idle' }}</span>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">同步基线</span>
|
||||
<span>{{ formatAdminDateTime(khhaoAutoSyncState.syncFromCreatedAt) }}</span>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">最近开始</span>
|
||||
<span>{{ formatAdminDateTime(khhaoAutoSyncState.lastRunStartedAt) }}</span>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">最近完成</span>
|
||||
<span>{{ formatAdminDateTime(khhaoAutoSyncState.lastRunFinishedAt) }}</span>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">最近结果</span>
|
||||
<span>拉取 {{ khhaoAutoSyncState.fetchedCount }} 条,成功 {{ khhaoAutoSyncState.syncedCount }} 条,忽略 {{ khhaoAutoSyncState.ignoredCount }} 条</span>
|
||||
</div>
|
||||
<div v-if="khhaoAutoSyncState.lastErrorMessage" class="meta-line">
|
||||
<span class="meta-label">最近错误</span>
|
||||
<span class="error-copy">{{ khhaoAutoSyncState.lastErrorMessage }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section v-if="khhaoQueryResult" class="table-card">
|
||||
@@ -1036,6 +1111,14 @@ onMounted(loadConfigs)
|
||||
color: #475467;
|
||||
}
|
||||
|
||||
.checkbox-box {
|
||||
min-height: 42px;
|
||||
padding: 0 14px;
|
||||
border-radius: 14px;
|
||||
border: 1px solid rgba(86, 108, 138, 0.18);
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
}
|
||||
|
||||
.result-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
@@ -1068,6 +1151,10 @@ onMounted(loadConfigs)
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.compact-meta {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
Reference in New Issue
Block a user