拆分平台配置页履约调试区块

This commit is contained in:
yml
2026-05-04 11:19:17 +08:00
parent 254a03129a
commit 8f6a72fa46
3 changed files with 294 additions and 188 deletions
@@ -0,0 +1,256 @@
<script setup lang="ts">
import type {
AdminCloudtentaclesLoginTestResult,
AdminCloudtentaclesPersistedSession,
AdminCloudtentaclesSendSmsResult,
AdminCloudtentaclesValidateSessionResult,
} from '@/types/admin'
import { formatAdminDateTime } from '@/utils/admin-time'
type CloudtentaclesForm = {
baseUrl: string
username: string
password: string
phone: string
code: string
token: string
vnKey: string
vnId: number
skuId: number
skuCount: number
deviceId: string
deviceType: number
}
type CloudtentaclesStats = {
hasCredential: boolean
smsSent: boolean
validated: boolean
}
type Props = {
cloudtentaclesFilePath: string
cloudtentaclesSessionFilePath: string
cloudtentaclesForm: CloudtentaclesForm
cloudtentaclesSaving: boolean
cloudtentaclesSendingSms: boolean
cloudtentaclesTesting: boolean
cloudtentaclesValidating: boolean
cloudtentaclesResultError: string
cloudtentaclesSmsResult: AdminCloudtentaclesSendSmsResult | null
cloudtentaclesLoginResult: AdminCloudtentaclesLoginTestResult | null
cloudtentaclesValidateResult: AdminCloudtentaclesValidateSessionResult | null
cloudtentaclesDebugLoading: boolean
cloudtentaclesDebugResult: string
cloudtentaclesPersistedSession: AdminCloudtentaclesPersistedSession | null
cloudtentaclesStats: CloudtentaclesStats
handleCloudtentaclesSaveSource: () => void | Promise<void>
handleCloudtentaclesSendSmsCode: () => void | Promise<void>
handleCloudtentaclesTestLogin: () => void | Promise<void>
handleCloudtentaclesValidateSession: () => void | Promise<void>
handleCloudtentaclesFetchAsset: () => void | Promise<void>
handleCloudtentaclesFetchCategories: () => void | Promise<void>
handleCloudtentaclesFetchSkuList: () => void | Promise<void>
handleCloudtentaclesBuySku: () => void | Promise<void>
handleCloudtentaclesUseSku: () => void | Promise<void>
handleCloudtentaclesFetchKnapsack: () => void | Promise<void>
handleCloudtentaclesFetchVnList: () => void | Promise<void>
handleCloudtentaclesAppointVn: () => void | Promise<void>
handleCloudtentaclesGenerateVnLoginCode: () => void | Promise<void>
handleCloudtentaclesFetchVnCode: () => void | Promise<void>
handleCloudtentaclesVerifyVnCode: () => void | Promise<void>
handleCloudtentaclesFetchBindUrl: () => void | Promise<void>
handleCloudtentaclesBackVn: () => void | Promise<void>
handleCloudtentaclesRunFullFlow: () => void | Promise<void>
}
defineProps<Props>()
</script>
<template>
<section class="meta-card">
<div class="meta-line">
<span class="meta-label">配置文件</span>
<code>{{ cloudtentaclesFilePath || '-' }}</code>
</div>
<div class="meta-line">
<span class="meta-label">会话文件</span>
<code>{{ cloudtentaclesSessionFilePath || '-' }}</code>
</div>
<div class="meta-line">
<span class="meta-label">职责</span>
<span>管理 cloudtentacles 外部履约平台的账号短信验证码登录与 token 探活该区域不处理订单来源同步</span>
</div>
<div class="meta-line">
<span class="meta-label">已保存 token</span>
<span>
{{ cloudtentaclesPersistedSession?.hasToken ? `${cloudtentaclesPersistedSession.tokenMasked} / ${formatAdminDateTime(cloudtentaclesPersistedSession.loggedInAt)}` : '未保存' }}
</span>
</div>
</section>
<section class="table-card">
<div class="section-title-row">
<div>
<h3>cloudtentacles 履约平台配置</h3>
<p>先保存账号密码手机号和设备头再发送短信验证码最后执行登录测试或手动校验 token</p>
</div>
<div class="section-actions">
<el-button :loading="cloudtentaclesSaving" round @click="handleCloudtentaclesSaveSource">保存履约配置</el-button>
<el-button :loading="cloudtentaclesSendingSms" round @click="handleCloudtentaclesSendSmsCode">发送短信验证码</el-button>
<el-button :loading="cloudtentaclesTesting" round type="primary" @click="handleCloudtentaclesTestLogin">测试登录</el-button>
<el-button :loading="cloudtentaclesValidating" round @click="handleCloudtentaclesValidateSession">校验 token</el-button>
</div>
</div>
<div class="form-grid">
<label class="field-block field-wide">
<span>Base URL</span>
<input v-model="cloudtentaclesForm.baseUrl" class="text-input" placeholder="https://123.207.217.176" />
</label>
<label class="field-block">
<span>账号</span>
<input v-model="cloudtentaclesForm.username" class="text-input" placeholder="cloudtentacles 登录账号" />
</label>
<label class="field-block">
<span>密码</span>
<input v-model="cloudtentaclesForm.password" class="text-input" type="password" placeholder="cloudtentacles 登录密码" />
</label>
<label class="field-block">
<span>手机号</span>
<input v-model="cloudtentaclesForm.phone" class="text-input" placeholder="接收短信验证码的手机号" />
</label>
<label class="field-block">
<span>短信验证码</span>
<input v-model="cloudtentaclesForm.code" class="text-input" placeholder="收到验证码后填写" />
</label>
<label class="field-block">
<span>VN Key</span>
<input v-model="cloudtentaclesForm.vnKey" class="text-input" placeholder="例如 1" />
</label>
<label class="field-block">
<span>VN ID</span>
<input v-model.number="cloudtentaclesForm.vnId" class="text-input" type="number" min="0" />
</label>
<label class="field-block">
<span>SKU ID</span>
<input v-model.number="cloudtentaclesForm.skuId" class="text-input" type="number" min="0" />
</label>
<label class="field-block">
<span>购买数量</span>
<input v-model.number="cloudtentaclesForm.skuCount" class="text-input" type="number" min="1" />
</label>
<label class="field-block">
<span>deviceId</span>
<input v-model="cloudtentaclesForm.deviceId" class="text-input" placeholder="-" />
</label>
<label class="field-block">
<span>deviceType</span>
<input v-model.number="cloudtentaclesForm.deviceType" class="text-input" type="number" />
</label>
<label class="field-block field-wide">
<span>token可手动粘贴</span>
<input v-model="cloudtentaclesForm.token" class="text-input" placeholder="登录成功后可自动回填,也可手动粘贴" />
</label>
</div>
<p v-if="cloudtentaclesResultError" class="error-copy">{{ cloudtentaclesResultError }}</p>
<div class="result-grid">
<article class="result-card">
<span class="result-label">短信发送</span>
<strong>{{ cloudtentaclesSmsResult ? '成功' : '未执行' }}</strong>
<p v-if="cloudtentaclesSmsResult">
{{ cloudtentaclesSmsResult.phoneMasked }}{{ formatAdminDateTime(cloudtentaclesSmsResult.sentAt) }}
</p>
<p v-else>先发送短信验证码确认手机号可用</p>
</article>
<article class="result-card">
<span class="result-label">登录结果</span>
<strong>{{ cloudtentaclesLoginResult ? '成功' : '未执行' }}</strong>
<p v-if="cloudtentaclesLoginResult">
{{ cloudtentaclesLoginResult.phoneMasked }}{{ formatAdminDateTime(cloudtentaclesLoginResult.loggedInAt) }}
</p>
<p v-else>填写短信验证码后可执行测试登录</p>
</article>
<article class="result-card">
<span class="result-label">会话校验</span>
<strong>{{ cloudtentaclesValidateResult ? '成功' : '未执行' }}</strong>
<p v-if="cloudtentaclesValidateResult">
权限 {{ cloudtentaclesValidateResult.session.permissionCount }} 余额 {{ cloudtentaclesValidateResult.asset }}
</p>
<p v-else>登录成功后可继续校验 token 会话</p>
</article>
</div>
</section>
<section class="table-card">
<div class="section-title-row">
<div>
<h3>cloudtentacles 开发调试工具</h3>
<p>仅开发模式展示用于调试分类SKU购买发货虚拟号兑换链接和结束退还链路</p>
</div>
<div class="section-actions">
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchAsset">余额</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchCategories">分类</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchSkuList">SKU</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesBuySku">购买</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round type="primary" @click="handleCloudtentaclesUseSku">发货</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchKnapsack">背包</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchVnList">虚拟号列表</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesAppointVn">申请虚拟号</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesGenerateVnLoginCode">生成登录码</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchVnCode">获取验证码</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesVerifyVnCode">校验验证码</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round @click="handleCloudtentaclesFetchBindUrl">兑换链接</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round type="warning" @click="handleCloudtentaclesBackVn">退还号码</el-button>
<el-button :loading="cloudtentaclesDebugLoading" round type="success" @click="handleCloudtentaclesRunFullFlow">完整流程</el-button>
</div>
</div>
<pre v-if="cloudtentaclesDebugResult" class="debug-result">{{ cloudtentaclesDebugResult }}</pre>
<div v-else class="empty-inline">执行一次调试动作后这里会显示原始返回数据</div>
</section>
<section v-if="cloudtentaclesLoginResult || cloudtentaclesValidateResult" class="table-card">
<div class="section-title-row">
<div>
<h3>cloudtentacles 调试结果</h3>
<p>用于确认当前账号会话权限和用户信息后续发货执行器会复用这里的登录能力</p>
</div>
</div>
<div class="result-grid">
<article class="result-card">
<span class="result-label">当前 token</span>
<strong>{{ cloudtentaclesValidateResult?.session.tokenMasked || cloudtentaclesLoginResult?.session.tokenMasked || '-' }}</strong>
<p>原始 token 已写入上方输入框可继续用于校验或后续调试</p>
</article>
<article class="result-card">
<span class="result-label">权限</span>
<strong>{{ cloudtentaclesValidateResult?.session.permissionCount || cloudtentaclesLoginResult?.session.permissionCount || 0 }} </strong>
<p>{{ (cloudtentaclesValidateResult?.session.permissions || cloudtentaclesLoginResult?.session.permissions || []).join('、') || '暂无' }}</p>
</article>
<article class="result-card">
<span class="result-label">余额</span>
<strong>{{ cloudtentaclesValidateResult?.asset || cloudtentaclesLoginResult?.asset || 0 }}</strong>
<p>可用于确认当前履约账号状态</p>
</article>
</div>
</section>
</template>