Files
tiantian-system/app/utils/appEntry.ts
2026-04-08 17:10:58 +08:00

150 lines
3.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { AppProduct } from '@/api/app/appProduct/model'
import { APP_TYPE } from '@/api/app/appProduct/model'
/** 入口动作类型 */
export type EntryType =
| 'visit-site' // 访问网站
| 'scan-qr' // 扫码体验(小程序)
| 'download' // 下载安装
| 'admin' // 管理后台
/** 单个入口配置 */
export interface AppEntry {
type: EntryType
label: string
/** Ant Design 图标组件名 */
icon: string
url?: string
available: boolean
isPrimary: boolean
}
/** 扫码提示文案映射 */
const SCAN_TIPS: Record<number, string> = {
[APP_TYPE.WECHAT_MP]: '打开微信扫一扫体验',
[APP_TYPE.DOUYIN_MP]: '打开抖音扫一扫体验',
[APP_TYPE.BAIDU_MP]: '打开百度APP扫一扫体验',
[APP_TYPE.ALIPAY_MP]: '打开支付宝扫一扫体验',
}
/** 小程序 appType 集合 */
const MINI_PROGRAM_TYPES = new Set([
APP_TYPE.WECHAT_MP,
APP_TYPE.DOUYIN_MP,
APP_TYPE.BAIDU_MP,
APP_TYPE.ALIPAY_MP,
])
/** 移动端/桌面端 appType 集合 */
const INSTALLABLE_TYPES = new Set([
APP_TYPE.ANDROID,
APP_TYPE.IOS,
APP_TYPE.MACOS,
APP_TYPE.WINDOWS,
])
/**
* 解析 Web 应用的前台 URL
* 优先使用显式配置的 homeUrl否则用 domain + prefix 拼接
*/
export function resolveWebHomeUrl(app: AppProduct): string | null {
if (app.homeUrl) return app.homeUrl
if (app.domain) {
const prefix = app.prefix ? `/${app.prefix.replace(/^\//, '')}` : ''
return `https://${app.domain}${prefix}`
}
return null
}
/**
* 获取应用的所有可用入口(按优先级排列)
*/
export function getAppEntries(app: AppProduct): AppEntry[] {
const entries: AppEntry[] = []
const type = app.appType
// 1. 访问网站(仅 Web 应用)
if (type === APP_TYPE.WEBSITE) {
const url = resolveWebHomeUrl(app)
entries.push({
type: 'visit-site',
label: '访问网站',
icon: 'GlobalOutlined',
url: url || undefined,
available: !!url,
isPrimary: true,
})
}
// 2. 扫码体验(小程序类型)
if (type && MINI_PROGRAM_TYPES.has(type)) {
entries.push({
type: 'scan-qr',
label: '扫码体验',
icon: 'QrcodeOutlined',
url: app.qrcode,
available: !!app.qrcode,
isPrimary: true,
})
}
// 3. 下载安装(移动端 / 桌面端)
if (type && INSTALLABLE_TYPES.has(type)) {
entries.push({
type: 'download',
label: '下载安装',
icon: 'DownloadOutlined',
url: app.downloadUrl,
available: !!app.downloadUrl,
isPrimary: true,
})
}
// 4. 管理后台(所有类型通用)
entries.push({
type: 'admin',
label: '管理后台',
icon: 'SettingOutlined',
url: app.adminUrl,
available: !!app.adminUrl,
// 插件的后台即主入口
isPrimary: type === APP_TYPE.PLUGIN,
})
return entries
}
/**
* 获取主入口
*/
export function getPrimaryEntry(app: AppProduct): AppEntry | null {
return getAppEntries(app).find(e => e.isPrimary && e.available) || null
}
/**
* 获取扫码提示文案
*/
export function getScanTip(appType: number): string {
return SCAN_TIPS[appType] || '扫一扫体验'
}
/**
* 执行入口动作(返回是否由调用方自行处理,如扫码弹窗)
*/
export function executeEntry(entry: AppEntry): boolean {
if (!entry.available) return false
switch (entry.type) {
case 'visit-site':
case 'download':
case 'admin':
window.open(entry.url, '_blank', 'noreferrer')
return false
case 'scan-qr':
// 需要调用方弹出二维码弹窗
return true
default:
return false
}
}