feat(cloudtentacles): 合并前端多账号支持改动

This commit is contained in:
yml
2026-05-20 00:38:20 +08:00
10 changed files with 385 additions and 72 deletions
@@ -1,29 +1,37 @@
import { apiGet, apiPost } from '@/lib/http'
import { apiDelete, apiGet, apiPost } from '@/lib/http'
import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSkuListResult,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSourceConfig,
AdminCloudtentaclesSourceConfigResponse,
AdminCloudtentaclesSourceItem,
AdminCloudtentaclesSourcesConfig,
AdminCloudtentaclesValidateSessionResult,
} from '@/types/admin'
export function fetchAdminCloudtentaclesSourceConfig() {
return apiGet<{
filePath: string
sessionFilePath: string
source: AdminCloudtentaclesSourceConfig
session: AdminCloudtentaclesPersistedSession
}>('/api/v1/admin/platform-config/cloudtentacles-source')
return apiGet<AdminCloudtentaclesSourceConfigResponse>(
'/api/v1/admin/platform-config/cloudtentacles-source',
)
}
export function saveAdminCloudtentaclesSourceConfig(payload: AdminCloudtentaclesSourceConfig) {
return apiPost<{
filePath: string
sessionFilePath: string
source: AdminCloudtentaclesSourceConfig
session: AdminCloudtentaclesPersistedSession
}>('/api/v1/admin/platform-config/cloudtentacles-source', payload)
export function saveAdminCloudtentaclesSourceConfig(
payload:
| AdminCloudtentaclesSourcesConfig
| ({ sourceKey: string } & Partial<AdminCloudtentaclesSourceItem>),
) {
return apiPost<AdminCloudtentaclesSourceConfigResponse>(
'/api/v1/admin/platform-config/cloudtentacles-source',
payload,
)
}
export function deleteAdminCloudtentaclesSource(sourceKey: string) {
return apiDelete<{ success: boolean }>(
`/api/v1/admin/platform-config/cloudtentacles-source/${sourceKey}`,
)
}
export function sendAdminCloudtentaclesSmsCode(payload: {
@@ -32,6 +40,7 @@ export function sendAdminCloudtentaclesSmsCode(payload: {
phone?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<AdminCloudtentaclesSendSmsResult>(
'/api/v1/admin/platform-config/cloudtentacles/send-sms-code',
@@ -47,6 +56,7 @@ export function testAdminCloudtentaclesLogin(payload: {
code?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<AdminCloudtentaclesLoginTestResult>(
'/api/v1/admin/platform-config/cloudtentacles/test-login',
@@ -59,6 +69,7 @@ export function validateAdminCloudtentaclesSession(payload: {
token?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<AdminCloudtentaclesValidateSessionResult>(
'/api/v1/admin/platform-config/cloudtentacles/validate-session',
@@ -71,6 +82,7 @@ export function fetchAdminCloudtentaclesAsset(payload: {
token?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/asset',
@@ -83,6 +95,7 @@ export function fetchAdminCloudtentaclesCategories(payload: {
token?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/categories',
@@ -95,6 +108,7 @@ export function fetchAdminCloudtentaclesSkuList(payload: {
token?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<AdminCloudtentaclesSkuListResult>(
'/api/v1/admin/platform-config/cloudtentacles/sku/list',
@@ -109,6 +123,7 @@ export function buyAdminCloudtentaclesSku(payload: {
deviceType?: number
id?: number
count?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/sku/buy',
@@ -124,6 +139,7 @@ export function useAdminCloudtentaclesSku(payload: {
id?: number
virtualNumberId?: number
phone?: string
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/sku/use',
@@ -136,6 +152,7 @@ export function fetchAdminCloudtentaclesKnapsack(payload: {
token?: string
deviceId?: string
deviceType?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/knapsack',
@@ -149,6 +166,7 @@ export function fetchAdminCloudtentaclesVnList(payload: {
deviceId?: string
deviceType?: number
key?: string
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/list',
@@ -162,6 +180,7 @@ export function appointAdminCloudtentaclesVn(payload: {
deviceId?: string
deviceType?: number
key?: string
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/appoint',
@@ -176,6 +195,7 @@ export function generateAdminCloudtentaclesVnLoginCode(payload: {
deviceType?: number
key?: string
id?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/generate-login-code',
@@ -190,6 +210,7 @@ export function fetchAdminCloudtentaclesVnCode(payload: {
deviceType?: number
key?: string
phone?: string
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/fetch-code',
@@ -205,6 +226,7 @@ export function verifyAdminCloudtentaclesVnCode(payload: {
key?: string
id?: number
code?: string
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/verify-code',
@@ -219,6 +241,7 @@ export function fetchAdminCloudtentaclesBindUrl(payload: {
deviceType?: number
key?: string
id?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/bind-url',
@@ -233,6 +256,7 @@ export function backAdminCloudtentaclesVn(payload: {
deviceType?: number
key?: string
id?: number
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/vn/back',
@@ -248,6 +272,7 @@ export function runAdminCloudtentaclesFullFlow(payload: {
skuId?: number
skuCount?: number
vnKey?: string
sourceKey?: string
}) {
return apiPost<Record<string, unknown>>(
'/api/v1/admin/platform-config/cloudtentacles/debug/full-flow',
+6 -10
View File
@@ -2,12 +2,7 @@
export type { AdminPagination } from './common'
// Auth types
export type {
AdminRole,
AdminUserStatus,
AdminLoginResponse,
AdminSessionSummary,
} from './auth'
export type { AdminRole, AdminUserStatus, AdminLoginResponse, AdminSessionSummary } from './auth'
// Users types
export type { AdminUserListItem } from './users'
@@ -37,10 +32,7 @@ export type {
} from './tasks'
// Inventory types
export type {
AdminInventorySkuSuggestion,
AdminInventoryItemListItem,
} from './inventory'
export type { AdminInventorySkuSuggestion, AdminInventoryItemListItem } from './inventory'
// Manual redeem types
export type { AdminManualRedeemDetail } from './manual-redeem'
@@ -83,6 +75,10 @@ export type {
AdminKuaishouEticketShopInfoResult,
AdminKuaishouEticketDetailResult,
AdminKuaishouEticketConsumeResult,
AdminCloudtentaclesSourceItem,
AdminCloudtentaclesSourcesConfig,
AdminCloudtentaclesSourceConfigResponse,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceConfig,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSendSmsResult,
@@ -1,5 +1,6 @@
export interface AdminCloudtentaclesSourceConfig {
enabled: boolean
export interface AdminCloudtentaclesSourceItem {
key: string
label: string
baseUrl: string
username: string
password: string
@@ -8,6 +9,11 @@ export interface AdminCloudtentaclesSourceConfig {
deviceType: number
}
export interface AdminCloudtentaclesSourcesConfig {
enabled: boolean
sources: AdminCloudtentaclesSourceItem[]
}
export interface AdminCloudtentaclesPersistedSession {
token: string
tokenMasked: string
@@ -20,6 +26,18 @@ export interface AdminCloudtentaclesPersistedSession {
hasToken: boolean
}
export interface AdminCloudtentaclesSessionsMap {
[sourceKey: string]: AdminCloudtentaclesPersistedSession
}
export interface AdminCloudtentaclesSourceConfigResponse {
filePath: string
sessionFilePath: string
enabled: boolean
sources: AdminCloudtentaclesSourceItem[]
sessions: AdminCloudtentaclesSessionsMap
}
export interface AdminCloudtentaclesSendSmsResult {
baseUrl: string
username: string
@@ -77,3 +95,14 @@ export interface AdminCloudtentaclesSkuListResult {
items: AdminCloudtentaclesSkuItem[]
rawItems: Record<string, unknown>[]
}
/** @deprecated Use AdminCloudtentaclesSourceItem + AdminCloudtentaclesSourcesConfig instead */
export interface AdminCloudtentaclesSourceConfig {
enabled: boolean
baseUrl: string
username: string
password: string
phone: string
deviceId: string
deviceType: number
}
@@ -33,6 +33,10 @@ export type {
} from './kuaishou-eticket'
export type {
AdminCloudtentaclesSourceItem,
AdminCloudtentaclesSourcesConfig,
AdminCloudtentaclesSourceConfigResponse,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceConfig,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSendSmsResult,
@@ -132,7 +132,14 @@ const {
cloudtentaclesDebugResult,
cloudtentaclesPersistedSession,
cloudtentaclesStats,
sources: cloudtentaclesSources,
sessions: cloudtentaclesSessions,
selectedSourceKey: selectedCloudtentaclesSourceKey,
sourceOptions: cloudtentaclesSourceOptions,
hydrateCloudtentaclesConfig,
switchSource: switchCloudtentaclesSource,
addSource: addCloudtentaclesSource,
removeSource: removeCloudtentaclesSource,
handleCloudtentaclesSaveSource,
handleCloudtentaclesSendSmsCode,
handleCloudtentaclesTestLogin,
@@ -417,6 +424,13 @@ onMounted(loadConfigs)
:cloudtentacles-debug-result="cloudtentaclesDebugResult"
:cloudtentacles-persisted-session="cloudtentaclesPersistedSession"
:cloudtentacles-stats="cloudtentaclesStats"
:sources="cloudtentaclesSources"
:sessions="cloudtentaclesSessions"
:selected-source-key="selectedCloudtentaclesSourceKey"
:source-options="cloudtentaclesSourceOptions"
:switch-source="switchCloudtentaclesSource"
:add-source="addCloudtentaclesSource"
:remove-source="removeCloudtentaclesSource"
:handle-cloudtentacles-save-source="handleCloudtentaclesSaveSource"
:handle-cloudtentacles-send-sms-code="handleCloudtentaclesSendSmsCode"
:handle-cloudtentacles-test-login="handleCloudtentaclesTestLogin"
@@ -2,6 +2,7 @@
import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSourceItem,
AdminCloudtentaclesValidateSessionResult,
} from '@/types/admin'
import AdminResultCard from '@/components/admin/AdminResultCard.vue'
@@ -22,6 +23,11 @@ type CloudtentaclesForm = {
deviceType: number
}
type SourceOption = {
key: string
label: string
}
type Props = {
cloudtentaclesForm: CloudtentaclesForm
cloudtentaclesSaving: boolean
@@ -32,13 +38,19 @@ type Props = {
cloudtentaclesSmsResult: AdminCloudtentaclesSendSmsResult | null
cloudtentaclesLoginResult: AdminCloudtentaclesLoginTestResult | null
cloudtentaclesValidateResult: AdminCloudtentaclesValidateSessionResult | null
selectedSourceKey: string
sourceOptions: SourceOption[]
sources: AdminCloudtentaclesSourceItem[]
handleCloudtentaclesSaveSource: () => void | Promise<void>
handleCloudtentaclesSendSmsCode: () => void | Promise<void>
handleCloudtentaclesTestLogin: () => void | Promise<void>
handleCloudtentaclesValidateSession: () => void | Promise<void>
switchSource: (sourceKey: string) => void
addSource: () => void
removeSource: (sourceKey: string) => void
}
defineProps<Props>()
const props = defineProps<Props>()
</script>
<template>
@@ -73,6 +85,32 @@ defineProps<Props>()
</div>
</template>
<!-- 账号选择器 -->
<div class="source-selector">
<el-select
:model-value="selectedSourceKey"
placeholder="选择账号"
@change="switchSource"
class="source-select"
>
<el-option
v-for="opt in sourceOptions"
:key="opt.key"
:label="opt.label"
:value="opt.key"
/>
</el-select>
<el-button type="primary" plain size="small" @click="addSource">新增账号</el-button>
<el-button
v-if="selectedSourceKey !== 'default'"
type="danger"
plain
size="small"
@click="removeSource(selectedSourceKey)"
>删除账号</el-button
>
</div>
<el-form label-width="auto" label-position="top">
<el-form-item label="Base URL">
<el-input v-model="cloudtentaclesForm.baseUrl" placeholder="https://123.207.217.176" />
@@ -242,6 +280,17 @@ defineProps<Props>()
flex-wrap: wrap;
}
.source-selector {
display: flex;
align-items: center;
gap: var(--space-2);
margin-bottom: var(--space-4);
}
.source-select {
width: 180px;
}
.result-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
@@ -1,6 +1,8 @@
<script setup lang="ts">
import type {
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSessionItem,
AdminCloudtentaclesSessionsMap,
} from '@/types/admin'
import { formatAdminDateTime } from '@/utils/admin-time'
@@ -8,9 +10,12 @@ type Props = {
cloudtentaclesFilePath: string
cloudtentaclesSessionFilePath: string
cloudtentaclesPersistedSession: AdminCloudtentaclesPersistedSession | null
sources: AdminCloudtentaclesSourceItem[]
sessions: AdminCloudtentaclesSessionsMap
selectedSourceKey: string
}
defineProps<Props>()
const props = defineProps<Props>()
</script>
<template>
@@ -25,17 +30,31 @@ defineProps<Props>()
<el-descriptions-item label="会话文件">
<code>{{ cloudtentaclesSessionFilePath || '-' }}</code>
</el-descriptions-item>
<el-descriptions-item label="账号数量">
{{ sources.length }}
</el-descriptions-item>
<el-descriptions-item label="当前选中账号">
{{ selectedSourceKey }}
</el-descriptions-item>
<el-descriptions-item label="职责">
管理 cloudtentacles 外部履约平台的账号短信验证码登录与 token
探活该区域不处理订单来源同步
</el-descriptions-item>
<el-descriptions-item label="已保存 token">
<el-descriptions-item label="当前账号已保存 token">
{{
cloudtentaclesPersistedSession?.hasToken
? `${cloudtentaclesPersistedSession.tokenMasked} / ${formatAdminDateTime(cloudtentaclesPersistedSession.loggedInAt)}`
: '未保存'
}}
</el-descriptions-item>
<el-descriptions-item v-if="Object.keys(sessions).length > 0" label="各账号会话状态">
<div class="session-list">
<div v-for="(session, key) in sessions" :key="key" class="session-item">
<el-tag :type="session.hasToken ? 'success' : 'info'" size="small">{{ key }}</el-tag>
<span>{{ session.hasToken ? session.tokenMasked : '未登录' }}</span>
</div>
</div>
</el-descriptions-item>
</el-descriptions>
</el-card>
</template>
@@ -50,4 +69,16 @@ defineProps<Props>()
font-weight: 600;
color: var(--text-primary);
}
.session-list {
display: flex;
flex-direction: column;
gap: var(--space-1);
}
.session-item {
display: flex;
align-items: center;
gap: var(--space-2);
}
</style>
@@ -3,6 +3,8 @@ import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSessionItem,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesValidateSessionResult,
} from '@/types/admin'
import AdminCloudtentaclesInfoCard from './AdminCloudtentaclesInfoCard.vue'
@@ -25,10 +27,16 @@ type CloudtentaclesForm = {
deviceType: number
}
type SourceOption = {
key: string
label: string
}
type CloudtentaclesStats = {
hasCredential: boolean
smsSent: boolean
validated: boolean
sourceCount: number
}
type Props = {
@@ -47,6 +55,10 @@ type Props = {
cloudtentaclesDebugResult: string
cloudtentaclesPersistedSession: AdminCloudtentaclesPersistedSession | null
cloudtentaclesStats: CloudtentaclesStats
sources: AdminCloudtentaclesSourceItem[]
sessions: AdminCloudtentaclesSessionsMap
selectedSourceKey: string
sourceOptions: SourceOption[]
handleCloudtentaclesSaveSource: () => void | Promise<void>
handleCloudtentaclesSendSmsCode: () => void | Promise<void>
handleCloudtentaclesTestLogin: () => void | Promise<void>
@@ -65,6 +77,9 @@ type Props = {
handleCloudtentaclesFetchBindUrl: () => void | Promise<void>
handleCloudtentaclesBackVn: () => void | Promise<void>
handleCloudtentaclesRunFullFlow: () => void | Promise<void>
switchSource: (sourceKey: string) => void
addSource: () => void
removeSource: (sourceKey: string) => void
}
defineProps<Props>()
@@ -76,6 +91,9 @@ defineProps<Props>()
:cloudtentacles-file-path="cloudtentaclesFilePath"
:cloudtentacles-session-file-path="cloudtentaclesSessionFilePath"
:cloudtentacles-persisted-session="cloudtentaclesPersistedSession"
:sources="sources"
:sessions="sessions"
:selected-source-key="selectedSourceKey"
/>
<AdminCloudtentaclesConfigCard
@@ -88,10 +106,16 @@ defineProps<Props>()
:cloudtentacles-sms-result="cloudtentaclesSmsResult"
:cloudtentacles-login-result="cloudtentaclesLoginResult"
:cloudtentacles-validate-result="cloudtentaclesValidateResult"
:selected-source-key="selectedSourceKey"
:source-options="sourceOptions"
:sources="sources"
:handle-cloudtentacles-save-source="handleCloudtentaclesSaveSource"
:handle-cloudtentacles-send-sms-code="handleCloudtentaclesSendSmsCode"
:handle-cloudtentacles-test-login="handleCloudtentaclesTestLogin"
:handle-cloudtentacles-validate-session="handleCloudtentaclesValidateSession"
:switch-source="switchSource"
:add-source="addSource"
:remove-source="removeSource"
/>
<AdminCloudtentaclesDebugCard
@@ -2,6 +2,7 @@ import { computed, ref } from 'vue'
import { showError, showSuccess } from '@/lib/feedback'
import {
deleteAdminCloudtentaclesSource,
saveAdminCloudtentaclesSourceConfig,
sendAdminCloudtentaclesSmsCode,
testAdminCloudtentaclesLogin,
@@ -11,7 +12,10 @@ import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesSourceConfig,
AdminCloudtentaclesSourceItem,
AdminCloudtentaclesSessionsMap,
AdminCloudtentaclesSourceConfigResponse,
AdminCloudtentaclesSourcesConfig,
AdminCloudtentaclesValidateSessionResult,
} from '@/types/admin'
@@ -21,6 +25,11 @@ import { useCloudtentaclesDebugActions } from './useCloudtentaclesDebugActions'
export function useAdminCloudtentaclesPlatform() {
const cloudtentaclesFilePath = ref('')
const cloudtentaclesSessionFilePath = ref('')
const selectedSourceKey = ref('default')
const sources = ref<AdminCloudtentaclesSourceItem[]>([])
const sessions = ref<AdminCloudtentaclesSessionsMap>({})
const cloudtentaclesForm = ref<CloudtentaclesForm>({
baseUrl: 'https://123.207.217.176',
username: '',
@@ -45,66 +54,179 @@ export function useAdminCloudtentaclesPlatform() {
const cloudtentaclesValidateResult = ref<AdminCloudtentaclesValidateSessionResult | null>(null)
const cloudtentaclesPersistedSession = ref<AdminCloudtentaclesPersistedSession | null>(null)
const debugActions = useCloudtentaclesDebugActions(cloudtentaclesForm, cloudtentaclesResultError)
const debugActions = useCloudtentaclesDebugActions(
cloudtentaclesForm,
cloudtentaclesResultError,
selectedSourceKey,
)
const sourceOptions = computed(() =>
sources.value.map((s) => ({ key: s.key, label: s.label })),
)
const currentSource = computed(
() => sources.value.find((s) => s.key === selectedSourceKey.value) || sources.value[0],
)
const currentSession = computed(
() => sessions.value[selectedSourceKey.value] || null,
)
const cloudtentaclesStats = computed(() => ({
hasCredential: Boolean(
cloudtentaclesForm.value.username.trim() &&
cloudtentaclesForm.value.password.trim() &&
cloudtentaclesForm.value.phone.trim(),
cloudtentaclesForm.value.password.trim() &&
cloudtentaclesForm.value.phone.trim(),
),
smsSent: Boolean(cloudtentaclesSmsResult.value),
validated: Boolean(cloudtentaclesValidateResult.value || cloudtentaclesLoginResult.value),
sourceCount: sources.value.length,
}))
function hydrateCloudtentaclesConfig(data: {
filePath: string
sessionFilePath: string
session: AdminCloudtentaclesPersistedSession
source: {
baseUrl?: string
username?: string
password?: string
phone?: string
deviceId?: string
deviceType?: number
}
}) {
function hydrateCloudtentaclesConfig(data: AdminCloudtentaclesSourceConfigResponse) {
cloudtentaclesFilePath.value = data.filePath
cloudtentaclesSessionFilePath.value = data.sessionFilePath
cloudtentaclesPersistedSession.value = data.session
cloudtentaclesForm.value = {
baseUrl: data.source.baseUrl || 'https://123.207.217.176',
username: data.source.username || '',
password: data.source.password || '',
phone: data.source.phone || '',
code: '',
token: data.session?.token || '',
vnKey: '1',
vnId: 0,
skuId: 5,
skuCount: 1,
deviceId: data.source.deviceId || '-',
deviceType: data.source.deviceType || 0,
sources.value = data.sources || []
sessions.value = data.sessions || {}
// Ensure 'default' always exists
if (!sources.value.length) {
sources.value.push({
key: 'default',
label: '默认账号',
baseUrl: 'https://123.207.217.176',
username: '',
password: '',
phone: '',
deviceId: '-',
deviceType: 0,
})
}
// Default selectedSourceKey to 'default' or first source
if (!sources.value.find((s) => s.key === selectedSourceKey.value)) {
selectedSourceKey.value = sources.value[0].key
}
// Hydrate form from the currently selected source
hydrateFormFromSource(selectedSourceKey.value)
}
function hydrateFormFromSource(sourceKey: string) {
const source = sources.value.find((s) => s.key === sourceKey)
const session = sessions.value[sourceKey]
if (source) {
cloudtentaclesForm.value = {
baseUrl: source.baseUrl || 'https://123.207.217.176',
username: source.username || '',
password: source.password || '',
phone: source.phone || '',
code: '',
token: session?.token || '',
vnKey: '1',
vnId: 0,
skuId: 5,
skuCount: 1,
deviceId: source.deviceId || '-',
deviceType: source.deviceType || 0,
}
}
cloudtentaclesPersistedSession.value = session || null
}
function switchSource(sourceKey: string) {
selectedSourceKey.value = sourceKey
// Clear transient results when switching
cloudtentaclesSmsResult.value = null
cloudtentaclesLoginResult.value = null
cloudtentaclesValidateResult.value = null
cloudtentaclesResultError.value = ''
hydrateFormFromSource(sourceKey)
}
function addSource() {
const newKey = `account${sources.value.length + 1}`
const newSource: AdminCloudtentaclesSourceItem = {
key: newKey,
label: `备用账号 ${sources.value.length}`,
baseUrl: 'https://123.207.217.176',
username: '',
password: '',
phone: '',
deviceId: '-',
deviceType: 0,
}
sources.value.push(newSource)
selectedSourceKey.value = newKey
hydrateFormFromSource(newKey)
}
async function removeSource(sourceKey: string) {
if (sourceKey === 'default') {
showError('默认账号不可删除')
return
}
try {
cloudtentaclesSaving.value = true
await deleteAdminCloudtentaclesSource(sourceKey)
sources.value = sources.value.filter((s) => s.key !== sourceKey)
delete sessions.value[sourceKey]
if (selectedSourceKey.value === sourceKey) {
selectedSourceKey.value = 'default'
hydrateFormFromSource('default')
}
showSuccess('账号已删除')
} catch (error) {
showError(error instanceof Error ? error.message : '删除账号失败')
} finally {
cloudtentaclesSaving.value = false
}
}
function buildCloudtentaclesConfigPayload(): AdminCloudtentaclesSourceConfig {
function buildCloudtentaclesConfigPayload(): AdminCloudtentaclesSourcesConfig {
// Update current source from form
const current = sources.value.find((s) => s.key === selectedSourceKey.value)
if (current) {
current.baseUrl = cloudtentaclesForm.value.baseUrl.trim() || 'https://123.207.217.176'
current.username = cloudtentaclesForm.value.username.trim()
current.password = cloudtentaclesForm.value.password.trim()
current.phone = cloudtentaclesForm.value.phone.trim()
current.deviceId = cloudtentaclesForm.value.deviceId.trim() || '-'
current.deviceType = Number(cloudtentaclesForm.value.deviceType || 0)
}
return {
enabled: true,
sources: sources.value.map((s) => ({
key: s.key,
label: s.label,
baseUrl: s.baseUrl,
username: s.username,
password: s.password,
phone: s.phone,
deviceId: s.deviceId,
deviceType: s.deviceType,
})),
}
}
function buildCloudtentaclesLoginPayload() {
return {
...buildCloudtentaclesSourcePayload(),
code: cloudtentaclesForm.value.code.trim(),
sourceKey: selectedSourceKey.value,
}
}
function buildCloudtentaclesSourcePayload() {
return {
baseUrl: cloudtentaclesForm.value.baseUrl.trim() || 'https://123.207.217.176',
username: cloudtentaclesForm.value.username.trim(),
password: cloudtentaclesForm.value.password.trim(),
phone: cloudtentaclesForm.value.phone.trim(),
deviceId: cloudtentaclesForm.value.deviceId.trim() || '-',
deviceType: Number(cloudtentaclesForm.value.deviceType || 0),
}
}
function buildCloudtentaclesLoginPayload() {
return {
...buildCloudtentaclesConfigPayload(),
code: cloudtentaclesForm.value.code.trim(),
sourceKey: selectedSourceKey.value,
}
}
@@ -142,8 +264,11 @@ export function useAdminCloudtentaclesPlatform() {
const response = await saveAdminCloudtentaclesSourceConfig(buildCloudtentaclesConfigPayload())
cloudtentaclesFilePath.value = response.data.filePath
cloudtentaclesSessionFilePath.value = response.data.sessionFilePath
cloudtentaclesPersistedSession.value = response.data.session
cloudtentaclesForm.value.token = response.data.session?.token || ''
sources.value = response.data.sources
sessions.value = response.data.sessions
const session = sessions.value[selectedSourceKey.value]
cloudtentaclesPersistedSession.value = session || null
cloudtentaclesForm.value.token = session?.token || ''
showSuccess('cloudtentacles 履约平台配置已保存')
} catch (error) {
cloudtentaclesResultError.value =
@@ -163,7 +288,7 @@ export function useAdminCloudtentaclesPlatform() {
cloudtentaclesResultError.value = ''
try {
const response = await sendAdminCloudtentaclesSmsCode(buildCloudtentaclesConfigPayload())
const response = await sendAdminCloudtentaclesSmsCode(buildCloudtentaclesSourcePayload())
cloudtentaclesSmsResult.value = response.data
showSuccess('cloudtentacles 短信验证码已发送')
} catch (error) {
@@ -198,6 +323,8 @@ export function useAdminCloudtentaclesPlatform() {
deviceType: Number(cloudtentaclesForm.value.deviceType || 0),
hasToken: Boolean(response.data.token),
}
// Update sessions map
sessions.value[selectedSourceKey.value] = cloudtentaclesPersistedSession.value
showSuccess('cloudtentacles 登录测试成功')
} catch (error) {
cloudtentaclesResultError.value =
@@ -224,6 +351,7 @@ export function useAdminCloudtentaclesPlatform() {
token,
deviceId: cloudtentaclesForm.value.deviceId.trim() || '-',
deviceType: Number(cloudtentaclesForm.value.deviceType || 0),
sourceKey: selectedSourceKey.value,
})
cloudtentaclesValidateResult.value = response.data
cloudtentaclesPersistedSession.value = {
@@ -239,6 +367,8 @@ export function useAdminCloudtentaclesPlatform() {
deviceType: Number(cloudtentaclesForm.value.deviceType || 0),
hasToken: Boolean(token),
}
// Update sessions map
sessions.value[selectedSourceKey.value] = cloudtentaclesPersistedSession.value
showSuccess('cloudtentacles 会话校验成功')
} catch (error) {
cloudtentaclesResultError.value =
@@ -265,7 +395,16 @@ export function useAdminCloudtentaclesPlatform() {
cloudtentaclesDebugResult: debugActions.cloudtentaclesDebugResult,
cloudtentaclesPersistedSession,
cloudtentaclesStats,
sources,
sessions,
selectedSourceKey,
sourceOptions,
currentSource,
currentSession,
hydrateCloudtentaclesConfig,
switchSource,
addSource,
removeSource,
handleCloudtentaclesSaveSource,
handleCloudtentaclesSendSmsCode,
handleCloudtentaclesTestLogin,
@@ -35,6 +35,7 @@ export type CloudtentaclesForm = {
export function useCloudtentaclesDebugActions(
cloudtentaclesForm: { value: CloudtentaclesForm },
cloudtentaclesResultError: { value: string },
selectedSourceKey: { value: string },
) {
const cloudtentaclesDebugLoading = ref(false)
const cloudtentaclesDebugResult = ref('')
@@ -45,6 +46,7 @@ export function useCloudtentaclesDebugActions(
token: cloudtentaclesForm.value.token.trim(),
deviceId: cloudtentaclesForm.value.deviceId.trim() || '-',
deviceType: Number(cloudtentaclesForm.value.deviceType || 0),
sourceKey: selectedSourceKey.value,
}
}