增加平台持久化
This commit is contained in:
@@ -4,6 +4,8 @@ import { computed, nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import { showSuccess } from '@/lib/feedback'
|
||||
import {
|
||||
fetchAdminFulfillmentBindingConfigs,
|
||||
fetchAdminKhhaoSourceConfig,
|
||||
queryAdminKhhaoOrders,
|
||||
lookupAdminFulfillmentBindingOrder,
|
||||
saveAdminFulfillmentBindingConfigs,
|
||||
} from '@/services/admin'
|
||||
@@ -11,6 +13,7 @@ import type {
|
||||
AdminFulfillmentBindingConfigItem,
|
||||
AdminFulfillmentLookupItem,
|
||||
AdminFulfillmentLookupResult,
|
||||
AdminKhhaoOrderPreview,
|
||||
AdminObservedProductItem,
|
||||
} from '@/types/admin'
|
||||
import { hasAdminRole } from '@/utils/admin-auth'
|
||||
@@ -82,6 +85,18 @@ const lookupForm = reactive({
|
||||
shopId: '',
|
||||
platformOrderId: '',
|
||||
})
|
||||
const khhaoLookupLoading = ref(false)
|
||||
const khhaoLookupErrorMessage = ref('')
|
||||
const khhaoLookupResults = ref<AdminKhhaoOrderPreview[]>([])
|
||||
const importedKhhaoOrderIds = ref<string[]>([])
|
||||
const khhaoLookupForm = reactive({
|
||||
baseUrl: 'https://admin.khhao.com',
|
||||
username: '',
|
||||
password: '',
|
||||
page: 1,
|
||||
limit: 10,
|
||||
maxCaptchaAttempts: 3,
|
||||
})
|
||||
|
||||
const ruleMetrics = computed(() => {
|
||||
const completedCount = bindings.value.filter(isEditableBindingComplete).length
|
||||
@@ -205,12 +220,19 @@ async function loadConfigs() {
|
||||
errorMessage.value = ''
|
||||
|
||||
try {
|
||||
const response = await fetchAdminFulfillmentBindingConfigs()
|
||||
const [response, khhaoSourceResponse] = await Promise.all([
|
||||
fetchAdminFulfillmentBindingConfigs(),
|
||||
fetchAdminKhhaoSourceConfig(),
|
||||
])
|
||||
filePath.value = response.data.filePath
|
||||
const nextBindings = response.data.bindings.map(mapEditableBinding)
|
||||
bindings.value = nextBindings
|
||||
collapsedBindingIds.value = buildCollapsedIds(nextBindings)
|
||||
observedProducts.value = response.data.observedProducts
|
||||
khhaoLookupForm.baseUrl = khhaoSourceResponse.data.source.baseUrl || 'https://admin.khhao.com'
|
||||
khhaoLookupForm.username = khhaoSourceResponse.data.source.username || ''
|
||||
khhaoLookupForm.password = khhaoSourceResponse.data.source.password || ''
|
||||
khhaoLookupForm.maxCaptchaAttempts = khhaoSourceResponse.data.source.maxCaptchaAttempts || 3
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof Error ? error.message : '读取履约配置失败'
|
||||
} finally {
|
||||
@@ -269,6 +291,25 @@ function isLookupProductImported(lineId: string) {
|
||||
return importedLookupLineIds.value.includes(lineId)
|
||||
}
|
||||
|
||||
function importKhhaoProduct(item: AdminKhhaoOrderPreview) {
|
||||
importObservedProduct({
|
||||
provider: item.provider || 'khhao',
|
||||
platform: item.platform || 'unknown',
|
||||
shopId: item.shopId,
|
||||
externalSkuCode: item.skuCode,
|
||||
externalItemId: item.itemId,
|
||||
externalSkuName: item.itemTitle,
|
||||
})
|
||||
|
||||
if (!importedKhhaoOrderIds.value.includes(item.platformOrderId)) {
|
||||
importedKhhaoOrderIds.value = [...importedKhhaoOrderIds.value, item.platformOrderId]
|
||||
}
|
||||
}
|
||||
|
||||
function isKhhaoProductImported(platformOrderId: string) {
|
||||
return importedKhhaoOrderIds.value.includes(platformOrderId)
|
||||
}
|
||||
|
||||
function normalizeBindingForSave(item: EditableBinding): SaveBindingPayload {
|
||||
return {
|
||||
provider: item.provider.trim() || 'agiso',
|
||||
@@ -459,6 +500,34 @@ async function lookupOrderProducts() {
|
||||
}
|
||||
}
|
||||
|
||||
async function lookupKhhaoProducts() {
|
||||
if (!khhaoLookupForm.username.trim() || !khhaoLookupForm.password.trim()) {
|
||||
khhaoLookupErrorMessage.value = '请先填写 khhao 账号和密码'
|
||||
return
|
||||
}
|
||||
|
||||
khhaoLookupLoading.value = true
|
||||
khhaoLookupErrorMessage.value = ''
|
||||
|
||||
try {
|
||||
const response = await queryAdminKhhaoOrders({
|
||||
baseUrl: khhaoLookupForm.baseUrl.trim() || 'https://admin.khhao.com',
|
||||
username: khhaoLookupForm.username.trim(),
|
||||
password: khhaoLookupForm.password.trim(),
|
||||
page: Number(khhaoLookupForm.page || 1),
|
||||
limit: Number(khhaoLookupForm.limit || 10),
|
||||
maxCaptchaAttempts: Number(khhaoLookupForm.maxCaptchaAttempts || 3),
|
||||
})
|
||||
khhaoLookupResults.value = response.data.items
|
||||
importedKhhaoOrderIds.value = []
|
||||
} catch (error) {
|
||||
khhaoLookupResults.value = []
|
||||
khhaoLookupErrorMessage.value = error instanceof Error ? error.message : 'khhao 订单查询失败'
|
||||
} finally {
|
||||
khhaoLookupLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadConfigs)
|
||||
</script>
|
||||
|
||||
@@ -681,6 +750,112 @@ onMounted(loadConfigs)
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="table-card table-card--dense">
|
||||
<div class="section-title-row section-title-row--tight">
|
||||
<div>
|
||||
<h3>khhao 订单取样导入</h3>
|
||||
<p>先用 khhao 账号查订单样本,再直接把商品导入成规则草稿,适合首批建规则。</p>
|
||||
</div>
|
||||
<span class="section-note-chip">khhao / kuaishou</span>
|
||||
</div>
|
||||
|
||||
<div class="khhao-toolbar">
|
||||
<label class="field-block field-wide">
|
||||
<span>Base URL</span>
|
||||
<input v-model="khhaoLookupForm.baseUrl" class="text-input" placeholder="https://admin.khhao.com" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>账号</span>
|
||||
<input v-model="khhaoLookupForm.username" class="text-input" placeholder="khhao 登录账号" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>密码</span>
|
||||
<input v-model="khhaoLookupForm.password" class="text-input" type="password" placeholder="khhao 登录密码" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>页码</span>
|
||||
<input v-model.number="khhaoLookupForm.page" class="text-input" type="number" min="1" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>每页条数</span>
|
||||
<input v-model.number="khhaoLookupForm.limit" class="text-input" type="number" min="1" max="50" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>验证码重试</span>
|
||||
<input v-model.number="khhaoLookupForm.maxCaptchaAttempts" class="text-input" type="number" min="1" max="5" />
|
||||
</label>
|
||||
|
||||
<div class="field-block field-block--action">
|
||||
<span>操作</span>
|
||||
<el-button :loading="khhaoLookupLoading" round type="primary" @click="lookupKhhaoProducts">查询 khhao 订单</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="toolbar-hint">这里直接读取 khhao 订单列表,不写库,只用于导入规则草稿。</p>
|
||||
<p v-if="khhaoLookupErrorMessage" class="error-copy lookup-error">{{ khhaoLookupErrorMessage }}</p>
|
||||
<div v-else-if="khhaoLookupLoading" class="empty-inline">正在查询 khhao 订单…</div>
|
||||
|
||||
<table v-else class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>订单</th>
|
||||
<th>店铺</th>
|
||||
<th>商品</th>
|
||||
<th>金额 / 状态</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in khhaoLookupResults" :key="`${item.platformOrderId}:${item.skuCode}:${item.itemId}`">
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ item.platformOrderId }}</strong>
|
||||
<span class="cell-subtle">{{ item.platformLabel || item.platform || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ item.shopName || item.shopId || '-' }}</strong>
|
||||
<span class="cell-subtle">ID: {{ item.shopId || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ item.itemTitle || '-' }}</strong>
|
||||
<span class="cell-subtle">SKU: {{ item.skuCode || '-' }}</span>
|
||||
<span class="cell-subtle">ItemId: {{ item.itemId || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ (item.totalAmountFen / 100).toFixed(2) }}</strong>
|
||||
<span class="cell-subtle">{{ item.statusLabel || item.status || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<el-button
|
||||
v-if="!isKhhaoProductImported(item.platformOrderId)"
|
||||
link
|
||||
type="primary"
|
||||
@click="importKhhaoProduct(item)"
|
||||
>
|
||||
导入到规则
|
||||
</el-button>
|
||||
<span v-else class="cell-subtle">已导入草稿</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="khhaoLookupResults.length === 0">
|
||||
<td colspan="5" class="empty-inline">还没有 khhao 查询结果。</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section class="table-card table-card--dense">
|
||||
<div class="section-title-row section-title-row--tight">
|
||||
<div>
|
||||
@@ -1027,6 +1202,7 @@ onMounted(loadConfigs)
|
||||
}
|
||||
|
||||
.lookup-toolbar,
|
||||
.khhao-toolbar,
|
||||
.lookup-summary {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
@@ -1037,6 +1213,11 @@ onMounted(loadConfigs)
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.khhao-toolbar {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.field-block--action :deep(.el-button) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ const navItems = computed(() => {
|
||||
|
||||
if (isAdmin.value) {
|
||||
baseItems.splice(1, 0, { to: '/admin/users', label: '用户' })
|
||||
baseItems.push({ to: '/admin/platform-shops', label: 'Agiso店铺' })
|
||||
baseItems.push({ to: '/admin/platform-shops', label: '平台配置' })
|
||||
baseItems.push({ to: '/admin/platform-fulfillment', label: '履约配置' })
|
||||
baseItems.push({ to: '/admin/audit-logs', label: '审计' })
|
||||
}
|
||||
|
||||
@@ -2,11 +2,22 @@
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
import { showError, showSuccess } from '@/lib/feedback'
|
||||
import { fetchAdminAgisoShopConfigs, saveAdminAgisoShopConfigs } from '@/services/admin'
|
||||
import {
|
||||
fetchAdminAgisoShopConfigs,
|
||||
fetchAdminKhhaoSourceConfig,
|
||||
queryAdminKhhaoOrders,
|
||||
saveAdminAgisoShopConfigs,
|
||||
saveAdminKhhaoSourceConfig,
|
||||
syncAdminKhhaoOrders,
|
||||
testAdminKhhaoLogin,
|
||||
} from '@/services/admin'
|
||||
import type {
|
||||
AdminAgisoMessagingDefaults,
|
||||
AdminAgisoObservedShopItem,
|
||||
AdminAgisoShopConfigItem,
|
||||
AdminKhhaoLoginTestResult,
|
||||
AdminKhhaoOrderQueryResult,
|
||||
AdminKhhaoOrderSyncResult,
|
||||
} from '@/types/admin'
|
||||
import { hasAdminRole } from '@/utils/admin-auth'
|
||||
import { formatAdminDateTime } from '@/utils/admin-time'
|
||||
@@ -28,12 +39,29 @@ type EditableShop = {
|
||||
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const khhaoSaving = ref(false)
|
||||
const errorMessage = ref('')
|
||||
const filePath = ref('')
|
||||
const khhaoFilePath = ref('')
|
||||
const defaults = ref<EditableDefaults>(createEmptyDefaults())
|
||||
const shops = ref<EditableShop[]>([])
|
||||
const observedShops = ref<AdminAgisoObservedShopItem[]>([])
|
||||
const expandedShopIds = ref<string[]>([])
|
||||
const khhaoForm = ref({
|
||||
baseUrl: 'https://admin.khhao.com',
|
||||
username: '',
|
||||
password: '',
|
||||
page: 1,
|
||||
limit: 10,
|
||||
maxCaptchaAttempts: 3,
|
||||
})
|
||||
const khhaoTesting = ref(false)
|
||||
const khhaoQuerying = ref(false)
|
||||
const khhaoSyncing = ref(false)
|
||||
const khhaoResultError = ref('')
|
||||
const khhaoLoginResult = ref<AdminKhhaoLoginTestResult | null>(null)
|
||||
const khhaoQueryResult = ref<AdminKhhaoOrderQueryResult | null>(null)
|
||||
const khhaoSyncResult = ref<AdminKhhaoOrderSyncResult | null>(null)
|
||||
|
||||
function createEmptyDefaults(): EditableDefaults {
|
||||
return {
|
||||
@@ -83,11 +111,23 @@ async function loadConfigs() {
|
||||
errorMessage.value = ''
|
||||
|
||||
try {
|
||||
const response = await fetchAdminAgisoShopConfigs()
|
||||
filePath.value = response.data.filePath
|
||||
defaults.value = mapEditableDefaults(response.data.defaults)
|
||||
shops.value = response.data.shops.map(mapEditableShop)
|
||||
observedShops.value = response.data.observedShops
|
||||
const [agisoResponse, khhaoResponse] = await Promise.all([
|
||||
fetchAdminAgisoShopConfigs(),
|
||||
fetchAdminKhhaoSourceConfig(),
|
||||
])
|
||||
filePath.value = agisoResponse.data.filePath
|
||||
defaults.value = mapEditableDefaults(agisoResponse.data.defaults)
|
||||
shops.value = agisoResponse.data.shops.map(mapEditableShop)
|
||||
observedShops.value = agisoResponse.data.observedShops
|
||||
khhaoFilePath.value = khhaoResponse.data.filePath
|
||||
khhaoForm.value = {
|
||||
baseUrl: khhaoResponse.data.source.baseUrl || 'https://admin.khhao.com',
|
||||
username: khhaoResponse.data.source.username || '',
|
||||
password: khhaoResponse.data.source.password || '',
|
||||
page: 1,
|
||||
limit: 10,
|
||||
maxCaptchaAttempts: khhaoResponse.data.source.maxCaptchaAttempts || 3,
|
||||
}
|
||||
expandedShopIds.value = []
|
||||
} catch (error) {
|
||||
errorMessage.value = error instanceof Error ? error.message : '读取店铺配置失败'
|
||||
@@ -207,6 +247,111 @@ async function saveConfigs() {
|
||||
}
|
||||
}
|
||||
|
||||
function buildKhhaoPayload() {
|
||||
return {
|
||||
baseUrl: khhaoForm.value.baseUrl.trim() || 'https://admin.khhao.com',
|
||||
username: khhaoForm.value.username.trim(),
|
||||
password: khhaoForm.value.password.trim(),
|
||||
page: Number(khhaoForm.value.page || 1),
|
||||
limit: Number(khhaoForm.value.limit || 10),
|
||||
maxCaptchaAttempts: Number(khhaoForm.value.maxCaptchaAttempts || 3),
|
||||
}
|
||||
}
|
||||
|
||||
function ensureKhhaoCredentials() {
|
||||
if (!khhaoForm.value.username.trim() || !khhaoForm.value.password.trim()) {
|
||||
khhaoResultError.value = '请先填写 khhao 账号和密码'
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function handleKhhaoTestLogin() {
|
||||
if (!ensureKhhaoCredentials()) {
|
||||
return
|
||||
}
|
||||
|
||||
khhaoTesting.value = true
|
||||
khhaoResultError.value = ''
|
||||
|
||||
try {
|
||||
const response = await testAdminKhhaoLogin({
|
||||
...buildKhhaoPayload(),
|
||||
includeImageBase64: false,
|
||||
})
|
||||
khhaoLoginResult.value = response.data
|
||||
showSuccess('khhao 登录测试成功')
|
||||
} catch (error) {
|
||||
khhaoResultError.value = error instanceof Error ? error.message : 'khhao 登录测试失败'
|
||||
showError(khhaoResultError.value)
|
||||
} finally {
|
||||
khhaoTesting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleKhhaoSaveSource() {
|
||||
khhaoSaving.value = true
|
||||
khhaoResultError.value = ''
|
||||
|
||||
try {
|
||||
const response = await saveAdminKhhaoSourceConfig({
|
||||
enabled: true,
|
||||
baseUrl: khhaoForm.value.baseUrl.trim() || 'https://admin.khhao.com',
|
||||
username: khhaoForm.value.username.trim(),
|
||||
password: khhaoForm.value.password.trim(),
|
||||
maxCaptchaAttempts: Number(khhaoForm.value.maxCaptchaAttempts || 3),
|
||||
})
|
||||
khhaoFilePath.value = response.data.filePath
|
||||
showSuccess('khhao 来源配置已保存')
|
||||
} catch (error) {
|
||||
khhaoResultError.value = error instanceof Error ? error.message : 'khhao 来源配置保存失败'
|
||||
showError(khhaoResultError.value)
|
||||
} finally {
|
||||
khhaoSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleKhhaoQueryOrders() {
|
||||
if (!ensureKhhaoCredentials()) {
|
||||
return
|
||||
}
|
||||
|
||||
khhaoQuerying.value = true
|
||||
khhaoResultError.value = ''
|
||||
|
||||
try {
|
||||
const response = await queryAdminKhhaoOrders(buildKhhaoPayload())
|
||||
khhaoQueryResult.value = response.data
|
||||
showSuccess(`khhao 订单查询成功,共返回 ${response.data.itemCount} 条`)
|
||||
} catch (error) {
|
||||
khhaoResultError.value = error instanceof Error ? error.message : 'khhao 订单查询失败'
|
||||
showError(khhaoResultError.value)
|
||||
} finally {
|
||||
khhaoQuerying.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleKhhaoSyncOrders() {
|
||||
if (!ensureKhhaoCredentials()) {
|
||||
return
|
||||
}
|
||||
|
||||
khhaoSyncing.value = true
|
||||
khhaoResultError.value = ''
|
||||
|
||||
try {
|
||||
const response = await syncAdminKhhaoOrders(buildKhhaoPayload())
|
||||
khhaoSyncResult.value = response.data
|
||||
showSuccess(`khhao 同步完成:拉取 ${response.data.fetchedCount} 条,成功 ${response.data.syncedCount} 条`)
|
||||
} catch (error) {
|
||||
khhaoResultError.value = error instanceof Error ? error.message : 'khhao 订单同步失败'
|
||||
showError(khhaoResultError.value)
|
||||
} finally {
|
||||
khhaoSyncing.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadConfigs)
|
||||
</script>
|
||||
|
||||
@@ -270,6 +415,153 @@ onMounted(loadConfigs)
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="table-card">
|
||||
<div class="section-title-row">
|
||||
<div>
|
||||
<h3>khhao 数据来源接入</h3>
|
||||
<p>这里用于保存 khhao 来源凭据,并测试登录、查询订单和手动同步。后续履约规则可去“履约配置”页从查询结果里直接导入。</p>
|
||||
</div>
|
||||
<div class="section-actions">
|
||||
<el-button :loading="khhaoSaving" round @click="handleKhhaoSaveSource">保存来源配置</el-button>
|
||||
<el-button :loading="khhaoTesting" round @click="handleKhhaoTestLogin">测试登录</el-button>
|
||||
<el-button :loading="khhaoQuerying" round @click="handleKhhaoQueryOrders">查询订单</el-button>
|
||||
<el-button :loading="khhaoSyncing" round type="primary" @click="handleKhhaoSyncOrders">同步订单</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="meta-card">
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">配置文件</span>
|
||||
<code>{{ khhaoFilePath || '-' }}</code>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">说明</span>
|
||||
<span>khhao 的 Base URL、账号、密码和验证码重试次数会单独保存在该文件中,不与 Agiso 店铺配置混用。</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="shop-grid">
|
||||
<label class="field-block field-wide">
|
||||
<span>Base URL</span>
|
||||
<input v-model="khhaoForm.baseUrl" class="text-input" placeholder="https://admin.khhao.com" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>账号</span>
|
||||
<input v-model="khhaoForm.username" class="text-input" placeholder="khhao 登录账号" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>密码</span>
|
||||
<input v-model="khhaoForm.password" class="text-input" type="password" placeholder="khhao 登录密码" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>页码</span>
|
||||
<input v-model.number="khhaoForm.page" class="text-input" type="number" min="1" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>每页条数</span>
|
||||
<input v-model.number="khhaoForm.limit" class="text-input" type="number" min="1" max="50" />
|
||||
</label>
|
||||
|
||||
<label class="field-block">
|
||||
<span>验证码重试次数</span>
|
||||
<input v-model.number="khhaoForm.maxCaptchaAttempts" class="text-input" type="number" min="1" max="5" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<p v-if="khhaoResultError" class="error-copy">{{ khhaoResultError }}</p>
|
||||
|
||||
<div v-if="khhaoLoginResult" class="meta-card">
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">登录测试</span>
|
||||
<span>账号 {{ khhaoLoginResult.username }},第 {{ khhaoLoginResult.attempt }} 次成功,Cookie {{ khhaoLoginResult.session.cookieCount }} 个,验证码识别:{{ khhaoLoginResult.captcha.recognizedText || '-' }}</span>
|
||||
</div>
|
||||
<div class="meta-line">
|
||||
<span class="meta-label">时间</span>
|
||||
<span>{{ formatAdminDateTime(khhaoLoginResult.loggedInAt) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="khhaoQueryResult">
|
||||
<div class="section-title-row compact-top">
|
||||
<div>
|
||||
<h3>khhao 查询结果</h3>
|
||||
<p>当前页 {{ khhaoQueryResult.page }},本页 {{ khhaoQueryResult.itemCount }} 条,总数 {{ khhaoQueryResult.total }}。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>订单</th>
|
||||
<th>店铺</th>
|
||||
<th>商品</th>
|
||||
<th>金额</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in khhaoQueryResult.items" :key="`${item.platformOrderId}:${item.skuCode}:${item.itemId}`">
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ item.platformOrderId }}</strong>
|
||||
<span class="cell-subtle">{{ item.platformLabel || item.platform || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ item.shopName || item.shopId || '-' }}</strong>
|
||||
<span class="cell-subtle">ID: {{ item.shopId || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="cell-stack">
|
||||
<strong>{{ item.itemTitle || '-' }}</strong>
|
||||
<span class="cell-subtle">SKU: {{ item.skuCode || '-' }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ (item.totalAmountFen / 100).toFixed(2) }}</td>
|
||||
<td>{{ item.statusLabel || item.status || '-' }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<template v-if="khhaoSyncResult">
|
||||
<div class="section-title-row compact-top">
|
||||
<div>
|
||||
<h3>khhao 同步结果</h3>
|
||||
<p>拉取 {{ khhaoSyncResult.fetchedCount }} 条,成功 {{ khhaoSyncResult.syncedCount }} 条,忽略 {{ khhaoSyncResult.ignoredCount }} 条。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>订单</th>
|
||||
<th>店铺</th>
|
||||
<th>商品</th>
|
||||
<th>结果</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="item in khhaoSyncResult.results" :key="`${item.platformOrderId}:${item.skuCode}`">
|
||||
<td>{{ item.platformOrderId }}</td>
|
||||
<td>{{ item.shopId || '-' }}</td>
|
||||
<td>{{ item.itemTitle || item.skuCode || '-' }}</td>
|
||||
<td>
|
||||
<span v-if="item.ignored">已忽略:{{ item.ignoreReason || '-' }}</span>
|
||||
<span v-else>已入库,订单 {{ item.orderId || '-' }},任务 {{ item.taskCount }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
</section>
|
||||
|
||||
<section class="table-card">
|
||||
<div class="section-title-row">
|
||||
<div>
|
||||
@@ -437,6 +729,10 @@ onMounted(loadConfigs)
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.compact-top {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.meta-card,
|
||||
.table-card,
|
||||
.empty-block,
|
||||
|
||||
Reference in New Issue
Block a user