修复一些的过时测试 优化readme

This commit is contained in:
yml
2026-05-21 13:16:07 +08:00
parent 5474d77799
commit 25671078d6
38 changed files with 331 additions and 210 deletions
@@ -1,19 +1,19 @@
import { computed, ref, type Ref, type ComputedRef } from 'vue'
import { computed, ref, type ComputedRef } from 'vue'
import { POLL_INTERVAL_MS, POLL_FAILURE_LIMIT } from './sessionConstants'
export interface UseSessionPollingOptions<T> {
export interface UseSessionPollingOptions {
/** Whether there is an active session used as a guard inside the poll loop. */
hasSession: ComputedRef<boolean>
/** Called on each poll tick (typically refreshSessionSummary). */
onPollTick: () => Promise<void>
onPollTick: () => Promise<unknown>
/** Optional: determines whether polling should continue. Defaults to checking hasSession. */
shouldKeepPolling?: ComputedRef<boolean>
/** Context-specific warning message prefix when polling fails repeatedly. */
pollWarningPrefix: string
}
export function useSessionPolling(options: UseSessionPollingOptions<unknown>) {
export function useSessionPolling(options: UseSessionPollingOptions) {
const { hasSession, onPollTick, pollWarningPrefix } = options
const pollWarningMessage = ref('')
@@ -5,6 +5,8 @@ import type { TencentLoginType } from '@/types/tencent/session'
import { DEFAULT_LOGIN_TYPE } from './sessionConstants'
type ReadableRef<T> = Pick<Ref<T>, 'value'>
// ---------------------------------------------------------------------------
// syncLoginTypeFromDetail
// ---------------------------------------------------------------------------
@@ -102,7 +104,7 @@ export interface UseSessionPresentationOptions {
}
export function useSessionRoleFacts(options: UseSessionPresentationOptions) {
const { activityInfo, statusLabel, roleFactDefaults } = options
const { activityInfo, roleFactDefaults } = options
const roleFacts = computed<FactItem[]>(() => [
{
@@ -168,17 +170,17 @@ export function useSessionResultFacts(options: UseSessionResultFactsOptions) {
// ---------------------------------------------------------------------------
export function buildRedeemBlockedReason(options: {
detail: ComputedRef<unknown | null>
hasSession: ComputedRef<boolean>
loginTypeLabel: ComputedRef<string>
redeemLoading: ComputedRef<boolean>
roleReady: ComputedRef<boolean>
roleConfirmed: ComputedRef<boolean>
sessionNotice: ComputedRef<string>
detail: ReadableRef<unknown | null>
hasSession: ReadableRef<boolean>
loginTypeLabel: ReadableRef<string>
redeemLoading: ReadableRef<boolean>
roleReady: ReadableRef<boolean>
roleConfirmed: ReadableRef<boolean>
sessionNotice: ReadableRef<string>
context: 'claim' | 'admin'
/** Claim-specific fields */
tokenStatus?: ComputedRef<string>
requiresSupportReview?: ComputedRef<boolean>
tokenStatus?: ReadableRef<string>
requiresSupportReview?: ReadableRef<boolean>
}): string {
const {
detail,
@@ -1,4 +1,4 @@
import { computed, ref, watch, type Ref, type ComputedRef } from 'vue'
import { computed, ref, watch, type ComputedRef } from 'vue'
/**
* Shared QR code display logic: renders the base64 QR image, tracks its
@@ -122,7 +122,7 @@ export function useAdminManualRedeemPage() {
() => `请让客户使用${loginTypeLabel.value}扫码,并在手机上确认登录`,
)
const { roleFacts } = useSessionRoleFacts({
useSessionRoleFacts({
activityInfo,
statusLabel,
roleFactDefaults: { nickname: '等待客户登录' },
@@ -230,10 +230,6 @@ export function useAdminManualRedeemPage() {
})
// ── Helpers ────────────────────────────────────────────────────────
function applyLoginTypeFromDetail(nextDetail: AdminManualRedeemDetail) {
loginType.value = syncLoginTypeFromDetail(nextDetail, loginType.value)
}
function restartPollingIfNeeded(nextDetail = detail.value) {
resetPolling()
@@ -88,7 +88,7 @@ export function useClaimPage(token: string) {
() => `请使用${loginTypeLabel.value}扫描二维码,并在手机上确认登录`,
)
const { roleFacts } = useSessionRoleFacts({
useSessionRoleFacts({
activityInfo,
statusLabel,
roleFactDefaults: { nickname: '等待扫码登录' },
@@ -1,8 +1,6 @@
import { apiDelete, apiGet, apiPost } from '@/lib/http'
import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSkuListResult,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSourceConfigResponse,
+1
View File
@@ -81,6 +81,7 @@ export type {
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceConfig,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSessionItem,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSessionSummary,
AdminCloudtentaclesLoginTestResult,
@@ -26,6 +26,8 @@ export interface AdminCloudtentaclesPersistedSession {
hasToken: boolean
}
export type AdminCloudtentaclesSessionItem = AdminCloudtentaclesPersistedSession
export interface AdminCloudtentaclesSessionsMap {
[sourceKey: string]: AdminCloudtentaclesPersistedSession
}
@@ -39,6 +39,7 @@ export type {
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceConfig,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSessionItem,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSessionSummary,
AdminCloudtentaclesLoginTestResult,
@@ -1,4 +1,4 @@
import type { AdminFulfillmentBindingConfigItem, AdminObservedProductItem } from '@/types/admin'
import type { AdminObservedProductItem } from '@/types/admin'
export type EditableBinding = {
id: string
@@ -3,7 +3,6 @@ import { reactive, ref } from 'vue'
import { lookupAdminFulfillmentBindingOrder } from '@/services/admin'
import type { AdminFulfillmentLookupItem, AdminFulfillmentLookupResult } from '@/types/admin'
import type { ImportableProductCandidate } from './types'
import type { useFulfillmentBindings } from './useFulfillmentBindings'
export function useFulfillmentBindingsLookup(
@@ -1,7 +1,7 @@
<script setup lang="ts">
import type { AdminNinetyoneOrderItem } from '@/types/admin'
const props = defineProps<{
defineProps<{
ninetyoneLookupLoading: boolean
ninetyoneLookupErrorMessage: string
ninetyoneLookupResults: AdminNinetyoneOrderItem[]
@@ -68,9 +68,12 @@ const emit = defineEmits<{
</div>
<div class="section-action-group">
<el-button round @click="emit('expandAll')">全部展开</el-button>
<el-checkbox :model-value="enabled" @update:model-value="emit('update:enabled', $event)"
>启用整条配置</el-checkbox
<el-checkbox
:model-value="enabled"
@update:model-value="emit('update:enabled', Boolean($event))"
>
启用整条配置
</el-checkbox>
<el-button round @click="emit('collapseReady')">收起已完成</el-button>
<el-button round :loading="cloudSkuCatalogLoading" @click="emit('refreshCloudSku')"
>刷新 cloud SKU</el-button
@@ -528,6 +528,7 @@ export function useKuaishouCloudConfig() {
// consume shops
getKuaishouConsumeShopOptions,
findKuaishouConsumeShop,
getDefaultKuaishouConsumeShop,
formatKuaishouConsumeShopOption,
handleKuaishouConsumeShopSelected,
// collapse
@@ -1,6 +1,6 @@
import { computed, nextTick, reactive, ref } from 'vue'
import { computed, reactive, ref } from 'vue'
import { showError, showSuccess } from '@/lib/feedback'
import { showSuccess } from '@/lib/feedback'
import { fetchAdminNinetyoneOrders } from '@/services/admin'
import type { AdminNinetyoneOrderItem } from '@/types/admin'
@@ -39,9 +39,7 @@ export function useKuaishouCloudNinetyone(
function createItemFromNinetyoneOrder(item: AdminNinetyoneOrderItem): EditableItem {
const productNo = String(item.productNo || '').trim()
const productName = String(item.productName || productNo).trim()
const defaultShop = config.getDefaultKuaishouConsumeShop ? config.findKuaishouConsumeShop() : null
const shopOpts = config.getKuaishouConsumeShopOptions()
const shop = defaultShop || (shopOpts.length > 0 ? shopOpts[0] : null)
const shop = config.getDefaultKuaishouConsumeShop()
return {
localId: crypto.randomUUID(),
id: '',
@@ -32,7 +32,6 @@ const {
singleDisplayValue,
bulkText,
skuSuggestionsLoading,
inventorySkuSuggestions,
entrySkuSuggestions,
// actions
loadInventoryItems,
@@ -49,8 +48,6 @@ const {
getSkuNamingHint,
formatInventoryStatus,
getGroupSuggestion,
// utils
hasAdminRole,
formatAdminDateTime,
} = useAdminInventory()
</script>
@@ -6,15 +6,12 @@ import {
fetchAdminInventoryItems,
fetchAdminInventorySkuSuggestions,
importAdminInventoryItems,
invalidateAdminInventoryItem,
releaseAdminInventoryItem,
} from '@/services/admin'
import type {
AdminInventoryItemListItem,
AdminInventorySkuSuggestion,
AdminPagination,
} from '@/types/admin'
import { hasAdminRole } from '@/utils/admin-auth'
import { formatAdminDateTime } from '@/utils/admin-time'
import {
adminInventoryCredentialTypeOptions,
@@ -425,7 +422,6 @@ export function useAdminInventory() {
formatInventoryStatus,
getGroupSuggestion,
// utils
hasAdminRole,
formatAdminDateTime,
adminInventoryCredentialTypeOptions,
adminInventoryStatusOptions,
@@ -184,6 +184,7 @@ const taskDetailLink = computed(() =>
:review-card-title="reviewCardTitle"
:review-ready="reviewReady"
:result-ready="resultReady"
:screenshot-empty-title="screenshotEmptyTitle"
:screenshot-empty-message="screenshotEmptyMessage"
:screenshot-url="screenshotUrl"
:screenshot-loading="screenshotLoading"
@@ -3,6 +3,7 @@ type Props = {
reviewCardTitle: string
reviewReady: boolean
resultReady: boolean
screenshotEmptyTitle: string
screenshotEmptyMessage: string
screenshotUrl: string
screenshotLoading: boolean
@@ -1,7 +1,7 @@
<script setup lang="ts">
type TaskDetail = {
taskNo?: string
taskId?: string
taskId?: string | number
status?: string
}
@@ -50,7 +50,7 @@ type Props = {
removeSource: (sourceKey: string) => void
}
const props = defineProps<Props>()
defineProps<Props>()
</script>
<template>
@@ -1,8 +1,8 @@
<script setup lang="ts">
import type {
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSessionItem,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceItem,
} from '@/types/admin'
import { formatAdminDateTime } from '@/utils/admin-time'
@@ -15,7 +15,7 @@ type Props = {
selectedSourceKey: string
}
const props = defineProps<Props>()
defineProps<Props>()
</script>
<template>
@@ -3,8 +3,8 @@ import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSessionItem,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceItem,
AdminCloudtentaclesValidateSessionResult,
} from '@/types/admin'
import AdminCloudtentaclesInfoCard from './AdminCloudtentaclesInfoCard.vue'
@@ -1,5 +1,5 @@
<script setup lang="ts">
import type { EditableKuaishouEticketShop } from '../composables/types'
import type { EditableKuaishouEticketShop } from '../../composables/types'
import type {
AdminKuaishouEticketConsumeResult,
AdminKuaishouEticketDetailResult,
@@ -195,7 +195,7 @@ function mapEditableShop(item: AdminAgisoShopConfigItem): EditableShop {
id: crypto.randomUUID(),
shopId: item.shopId,
shopName: item.shopName,
accessToken: item.accessToken,
accessToken: item.AccessToken,
enabled: item.enabled !== false,
messageTemplate: item.messageTemplate,
autoDeliveryMessageTemplate: item.autoDeliveryMessageTemplate,
@@ -1,4 +1,4 @@
import { ref, computed, type Ref } from 'vue'
import { ref, computed } from 'vue'
import { showError, showSuccess } from '@/lib/feedback'
import {
consumeAdminKuaishouEticket,
@@ -66,13 +66,10 @@ export function useAdminKuaishouEticketPlatform() {
function hydrateKuaishouEticketConfig(data: {
filePath: string
source: {
baseUrl?: string
shops: AdminKuaishouEticketShopInfoResult['shop'][]
}
source: AdminKuaishouEticketSourceConfig
}) {
kuaishouEticketFilePath.value = data.filePath
shopManager.setShopsFromConfig(data.source.shops as any)
shopManager.setShopsFromConfig(data.source.shops)
kuaishouEticketForm.value = {
baseUrl: data.source.baseUrl || 'https://s.kwaixiaodian.com',
selectedShopId: '',
@@ -106,7 +103,7 @@ export function useAdminKuaishouEticketPlatform() {
}
function addKuaishouEticketShop() {
const { newSelectedId } = shopManager.addKuaishouEticketShop(kuaishouEticketForm.value.selectedShopId)
const { newSelectedId } = shopManager.addKuaishouEticketShop()
setKuaishouEticketDebugShop(newSelectedId)
}
@@ -1,12 +1,12 @@
import { ref } from 'vue'
import type { EditableKuaishouEticketShop } from '../types'
import type { EditableKuaishouEticketShop } from './types'
import type { AdminKuaishouEticketShopConfigItem } from '@/types/admin'
export function useKuaishouEticketShopManager() {
const kuaishouEticketShops = ref<EditableKuaishouEticketShop[]>([])
const expandedKuaishouEticketShopIds = ref<string[]>([])
function addKuaishouEticketShop(selectedShopId: string) {
function addKuaishouEticketShop() {
const shop = createEmptyKuaishouEticketShop()
kuaishouEticketShops.value.unshift(shop)
return { shop, newSelectedId: shop.id }
@@ -12,7 +12,7 @@ import {
regenerateAdminTaskClaimLink,
retryAdminTask,
} from "@/services/admin";
import type { AdminTaskActionResponse, AdminTaskListItem } from "@/types/admin";
import type { AdminTaskListItem } from "@/types/admin";
import { hasAdminRole } from "@/utils/admin-auth";
import {
formatBindingRoleSummary,
@@ -379,7 +379,7 @@ function resetFilters() {
action: async () => {
const response = await retryAdminTask(row.taskId);
if (response.data.claimUrl)
lastClaimUrl.value = response.data.claimUrl;
lastClaimUrl = response.data.claimUrl;
},
successMessage: '任务已重试',
confirmText: `确认重试任务 ${row.taskNo} 吗?`,
@@ -8,7 +8,7 @@ interface Props {
canCloseTasks: boolean
}
const props = defineProps<Props>()
defineProps<Props>()
const emit = defineEmits<{
retry: []
@@ -1,18 +1,11 @@
import { computed, onBeforeUnmount, ref } from 'vue'
import { useRoute } from 'vue-router'
import { showError, showSuccess } from '@/lib/feedback'
import { showConfirm, showError, showSuccess } from '@/lib/feedback'
import {
closeAdminTask,
completeAdminTaskManualDispatch,
fetchAdminTaskScreenshot,
fetchAdminTaskDetail,
markAdminTaskManualReview,
redeemAdminTaskAssisted,
regenerateAdminTaskClaimLink,
releaseAdminTaskInventoryBinding,
retryAdminTask,
confirmAdminTaskAssistedRole,
} from '@/services/admin'
import type { AdminTaskActionResponse, AdminTaskDetail } from '@/types/admin'
import { hasAdminRole } from '@/utils/admin-auth'
@@ -52,7 +45,11 @@ export function useAdminTaskDetail() {
const claimLinkInvalid = computed(() => {
const tokenStatus = String(detail.value?.claimToken?.status || '').trim()
return Boolean(detail.value?.claimToken?.claimUrl) && tokenStatus && tokenStatus !== 'active'
return Boolean(
detail.value?.claimToken?.claimUrl &&
tokenStatus &&
tokenStatus !== 'active',
)
})
const screenshotSectionTitle = computed(() => {
@@ -6,7 +6,7 @@ import {
refreshAdminTaskKuaishouCloudRoleInfo,
returnNumberAdminTaskKuaishouCloudFulfillment,
} from '@/services/admin'
import type { AdminTaskDetail } from '@/types/admin'
import type { AdminTaskActionResponse, AdminTaskDetail } from '@/types/admin'
import { formatKuaishouRoleInfoLabel } from '@/utils/admin-display'
import { formatAdminDateTime } from '@/utils/admin-time'
@@ -15,7 +15,7 @@ import type { ChecklistItem, RoleInfoEntry, SummaryCard } from './types'
export function useAdminTaskKuaishouCloud(
detail: Ref<AdminTaskDetail | null>,
runAction: (
action: () => Promise<{ data: any }>,
action: () => Promise<{ data: AdminTaskActionResponse }>,
successMessage: string,
confirmText: string,
) => Promise<void>,
@@ -61,7 +61,7 @@ const claim = useKuaishouCloudClaim(() => props.token)
:refreshing-role="claim.refreshingRole.value"
:confirming-role="claim.confirmingRole.value"
:flow="claim.flow.value"
:format-date-time="claim.formatDateTime"
:format-date-time="claim.formatAdminDateTime"
@open-bind-url="claim.openBindUrl($event)"
@refresh-role="claim.refreshRole()"
@confirm-role="claim.confirmRole()"
@@ -85,7 +85,7 @@ const claim = useKuaishouCloudClaim(() => props.token)
:order-item="claim.orderItem.value"
:role-name="claim.roleName.value"
:role-id="claim.roleId.value"
:format-date-time="claim.formatDateTime"
:format-date-time="claim.formatAdminDateTime"
/>
</template>