docs(api): 添加联调接口文档并实现功能服务管理
- 创建了完整的 API 联调文档,包含各服务地址、ID 约定和鉴权规则 - 实现了 FeatureServiceManager 用于管理服务激活和配置功能 - 添加了安全配置确保各服务间正确的身份验证机制 - 定义了统一的响应格式和错误码处理规范 - 集成了 IM、推送和更新服务的管理接口实现
这个提交包含在:
父节点
fb82e4b8b6
当前提交
5c93a14941
@ -30,7 +30,7 @@
|
|||||||
<el-card class="service-card">
|
<el-card class="service-card">
|
||||||
<div class="service-header">
|
<div class="service-header">
|
||||||
<span class="service-name">{{ serviceLabel('IM') }}</span>
|
<span class="service-name">{{ serviceLabel('IM') }}</span>
|
||||||
<el-switch :model-value="imEnabled" @change="(val: boolean) => onToggleImService(val)" />
|
<el-switch :model-value="imEnabled" @change="(val: boolean) => onToggleService('IM', val)" />
|
||||||
</div>
|
</div>
|
||||||
<template v-if="imService">
|
<template v-if="imService">
|
||||||
<div style="margin-top:10px;display:flex;gap:8px;flex-wrap:wrap">
|
<div style="margin-top:10px;display:flex;gap:8px;flex-wrap:wrap">
|
||||||
@ -45,7 +45,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div style="margin-top:10px">
|
<div style="margin-top:10px">
|
||||||
<el-button size="small" type="primary" plain @click="openActivationRequest('ANDROID', 'IM')">
|
<el-button size="small" type="primary" plain @click="openActivationRequest('IM')">
|
||||||
申请开通
|
申请开通
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@ -56,38 +56,33 @@
|
|||||||
|
|
||||||
<el-card>
|
<el-card>
|
||||||
<template #header>离线推送与版本管理</template>
|
<template #header>离线推送与版本管理</template>
|
||||||
<el-tabs v-model="activePlatform">
|
|
||||||
<el-tab-pane label="Android" name="ANDROID" />
|
|
||||||
<el-tab-pane label="iOS" name="IOS" />
|
|
||||||
<el-tab-pane label="鸿蒙" name="HARMONY" />
|
|
||||||
</el-tabs>
|
|
||||||
|
|
||||||
<div class="service-grid">
|
<div class="service-grid">
|
||||||
<el-card v-for="svcType in ['PUSH', 'UPDATE']" :key="svcType" class="service-card">
|
<el-card v-for="svcType in ['PUSH', 'UPDATE']" :key="svcType" class="service-card">
|
||||||
<div class="service-header">
|
<div class="service-header">
|
||||||
|
<div class="service-title-block">
|
||||||
<span class="service-name">{{ serviceLabel(svcType) }}</span>
|
<span class="service-name">{{ serviceLabel(svcType) }}</span>
|
||||||
|
<span class="service-help">{{ serviceHelp(svcType) }}</span>
|
||||||
|
</div>
|
||||||
<el-switch
|
<el-switch
|
||||||
:model-value="isEnabled(activePlatform, svcType)"
|
:model-value="isServiceEnabled(svcType)"
|
||||||
@change="(val: boolean) => onToggleService(activePlatform, svcType, val)"
|
@change="(val: boolean) => onToggleService(svcType, val)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="isEnabled(activePlatform, svcType)">
|
<div class="service-status-row">
|
||||||
<div style="margin-top:10px">
|
<el-tag :type="isServiceEnabled(svcType) ? 'success' : 'info'" size="small">
|
||||||
<el-button
|
{{ isServiceEnabled(svcType) ? '已开通' : '未开通' }}
|
||||||
v-if="svcType === 'UPDATE'"
|
</el-tag>
|
||||||
size="small"
|
<span class="service-status-text">
|
||||||
@click="$router.push(`/apps/${route.params.id}/update`)">
|
{{ svcType === 'UPDATE'
|
||||||
|
? 'Android / iOS / 鸿蒙版本在版本管理页内分别配置。'
|
||||||
|
: '推送服务开通后即可在终端接收设备级推送。' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="service-actions" v-if="svcType === 'UPDATE'">
|
||||||
|
<el-button size="small" type="primary" plain @click="$router.push(`/apps/${route.params.id}/update`)">
|
||||||
版本管理 →
|
版本管理 →
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div style="margin-top:10px">
|
|
||||||
<el-button size="small" type="primary" plain @click="openActivationRequest(activePlatform, svcType)">
|
|
||||||
申请开通
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
@ -123,7 +118,6 @@
|
|||||||
<el-dialog v-model="showActivationDialog" title="申请开通服务" width="420px">
|
<el-dialog v-model="showActivationDialog" title="申请开通服务" width="420px">
|
||||||
<el-form label-width="80px">
|
<el-form label-width="80px">
|
||||||
<el-form-item label="服务">{{ serviceLabel(activationForm.serviceType) }}</el-form-item>
|
<el-form-item label="服务">{{ serviceLabel(activationForm.serviceType) }}</el-form-item>
|
||||||
<el-form-item v-if="activationForm.serviceType !== 'IM'" label="平台">{{ activationForm.platform }}</el-form-item>
|
|
||||||
<el-form-item label="申请理由">
|
<el-form-item label="申请理由">
|
||||||
<el-input v-model="activationForm.reason" type="textarea" :rows="3" placeholder="请描述您的业务场景" />
|
<el-input v-model="activationForm.reason" type="textarea" :rows="3" placeholder="请描述您的业务场景" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -147,7 +141,6 @@ import client from '@/api/client'
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const app = ref<App | null>(null)
|
const app = ref<App | null>(null)
|
||||||
const services = ref<FeatureService[]>([])
|
const services = ref<FeatureService[]>([])
|
||||||
const activePlatform = ref<'ANDROID' | 'IOS' | 'HARMONY'>('ANDROID')
|
|
||||||
const imService = computed(() => services.value.find(s => s.serviceType === 'IM') ?? null)
|
const imService = computed(() => services.value.find(s => s.serviceType === 'IM') ?? null)
|
||||||
const imEnabled = computed(() => imService.value?.enabled ?? false)
|
const imEnabled = computed(() => imService.value?.enabled ?? false)
|
||||||
|
|
||||||
@ -164,22 +157,24 @@ const showActivationDialog = ref(false)
|
|||||||
const submittingActivation = ref(false)
|
const submittingActivation = ref(false)
|
||||||
const activationForm = ref({ platform: '', serviceType: '', reason: '' })
|
const activationForm = ref({ platform: '', serviceType: '', reason: '' })
|
||||||
|
|
||||||
function isEnabled(platform: string, svcType: string) {
|
function isServiceEnabled(svcType: string) {
|
||||||
return services.value.some(
|
return services.value.some(s => s.serviceType === svcType && s.enabled)
|
||||||
s => s.platform === platform && s.serviceType === svcType && s.enabled
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getService(platform: string, svcType: string) {
|
|
||||||
return services.value.find(s => s.platform === platform && s.serviceType === svcType) ?? null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function serviceLabel(type: string) {
|
function serviceLabel(type: string) {
|
||||||
return { IM: '即时通讯 (IM)', PUSH: '离线推送', UPDATE: '版本管理' }[type] ?? type
|
return { IM: '即时通讯 (IM)', PUSH: '离线推送', UPDATE: '版本管理' }[type] ?? type
|
||||||
}
|
}
|
||||||
|
|
||||||
function imServicePlatform() {
|
function serviceHelp(type: string) {
|
||||||
return imService.value?.platform ?? 'ANDROID'
|
return {
|
||||||
|
IM: 'IM 服务独立开通后,在管理页配置回调和消息能力。',
|
||||||
|
PUSH: '一次开通后,推送配置在服务管理页按平台维护。',
|
||||||
|
UPDATE: '一次开通后,版本管理页按平台维护版本和发布。',
|
||||||
|
}[type] ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function getServiceRepresentative(svcType: string) {
|
||||||
|
return services.value.find(s => s.serviceType === svcType) ?? null
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadData() {
|
async function loadData() {
|
||||||
@ -192,34 +187,22 @@ async function loadData() {
|
|||||||
revealedSecret.value = null
|
revealedSecret.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onToggleService(platform: string, svcType: string, enable: boolean) {
|
async function onToggleService(svcType: string, enable: boolean) {
|
||||||
if (enable) {
|
if (enable) {
|
||||||
openActivationRequest(platform, svcType)
|
openActivationRequest(svcType)
|
||||||
} else {
|
} else {
|
||||||
await ElMessageBox.confirm(`确认关闭 ${platform} 平台的 ${serviceLabel(svcType)} 服务?`, '关闭服务', {
|
await ElMessageBox.confirm(`确认关闭 ${serviceLabel(svcType)} 服务?`, '关闭服务', {
|
||||||
type: 'warning', confirmButtonText: '确认关闭', cancelButtonText: '取消',
|
type: 'warning', confirmButtonText: '确认关闭', cancelButtonText: '取消',
|
||||||
})
|
})
|
||||||
|
const platform = getServiceRepresentative(svcType)?.platform ?? 'ANDROID'
|
||||||
await appApi.toggleService(route.params.id as string, platform, svcType, false)
|
await appApi.toggleService(route.params.id as string, platform, svcType, false)
|
||||||
ElMessage.success('已关闭')
|
ElMessage.success('已关闭')
|
||||||
loadData()
|
loadData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onToggleImService(enable: boolean) {
|
function openActivationRequest(svcType: string) {
|
||||||
if (enable) {
|
activationForm.value = { platform: 'ANDROID', serviceType: svcType, reason: '' }
|
||||||
openActivationRequest(imServicePlatform(), 'IM')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await ElMessageBox.confirm('确认关闭 即时通讯 服务?', '关闭服务', {
|
|
||||||
type: 'warning', confirmButtonText: '确认关闭', cancelButtonText: '取消',
|
|
||||||
})
|
|
||||||
await appApi.toggleService(route.params.id as string, imServicePlatform(), 'IM', false)
|
|
||||||
ElMessage.success('已关闭')
|
|
||||||
loadData()
|
|
||||||
}
|
|
||||||
|
|
||||||
function openActivationRequest(platform: string, svcType: string) {
|
|
||||||
activationForm.value = { platform, serviceType: svcType, reason: '' }
|
|
||||||
showActivationDialog.value = true
|
showActivationDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,8 +278,13 @@ onMounted(loadData)
|
|||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.mono { font-family: monospace; font-size: 12px; }
|
.mono { font-family: monospace; font-size: 12px; }
|
||||||
.service-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-top: 16px; }
|
.service-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 16px; margin-top: 16px; }
|
||||||
.service-card { border: 1px solid #e8e8e8; }
|
.service-card { border: 1px solid #e8e8e8; }
|
||||||
.service-header { display: flex; justify-content: space-between; align-items: center; font-weight: 500; }
|
.service-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; font-weight: 500; }
|
||||||
.service-name { font-size: 15px; }
|
.service-name { font-size: 15px; }
|
||||||
|
.service-title-block { display: flex; flex-direction: column; gap: 4px; }
|
||||||
|
.service-help { font-size: 12px; color: #6b7280; line-height: 1.4; }
|
||||||
|
.service-status-row { display: flex; align-items: center; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
|
||||||
|
.service-status-text { font-size: 13px; color: #6b7280; line-height: 1.5; }
|
||||||
|
.service-actions { margin-top: 12px; display: flex; gap: 8px; flex-wrap: wrap; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户