feat(app): 添加多模板关于我们页面及相关路由和404页面
- 新增404页面,优化未找到页面体验,避免被搜索引擎索引 - 增加文件代理接口,隐藏真实文件服务器地址,支持文件请求代理 - 实现/article、/case、/product及/page动态路由兼容列表与详情展示 - 添加动态CMS页面兼容入口处理旧式路径,统一路由与SEO设置 - 新增模板1、模板7、模板2、模板3关于我们页面,实现多模板支持 - 模板增强支持CMS单页内容加载及SEO信息动态设置 - 配置环境变量及Git忽略文件规则辅助开发和构建环境管理
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type { AppProduct, TenantContext } from '~/types'
|
||||
|
||||
/**
|
||||
* 获取当前应用产品信息(AppProduct)
|
||||
*
|
||||
* SSR:优先从 event.context.tenant.appProduct 读取(中间件已查询)
|
||||
* 客户端:从 SSR 注入的 useState 读取;若为空则调用 /api/app/info 补查
|
||||
*/
|
||||
export function useApp() {
|
||||
const appInfo = useState<AppProduct | null>('app-info', () => null)
|
||||
const loading = useState<boolean>('app-loading', () => false)
|
||||
const error = useState<string | null>('app-error', () => null)
|
||||
|
||||
// SSR 时直接从中间件识别结果注入,避免额外请求
|
||||
if (import.meta.server && !appInfo.value) {
|
||||
const event = useRequestEvent()
|
||||
const ctx = event?.context?.tenant as TenantContext | undefined
|
||||
if (ctx?.appProduct) {
|
||||
appInfo.value = ctx.appProduct
|
||||
}
|
||||
}
|
||||
|
||||
/** 主动获取应用信息(客户端兜底 / 手动刷新) */
|
||||
async function fetchAppInfo() {
|
||||
if (appInfo.value) return appInfo.value
|
||||
loading.value = true
|
||||
error.value = null
|
||||
try {
|
||||
const res = await $fetch<AppProduct | null>('/api/app/info')
|
||||
appInfo.value = res
|
||||
return res
|
||||
} catch (e: any) {
|
||||
error.value = e?.message || '获取应用信息失败'
|
||||
return null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 应用名称 */
|
||||
const appName = computed(() => appInfo.value?.productName || '')
|
||||
/** 应用编码 */
|
||||
const appCode = computed(() => appInfo.value?.productCode || '')
|
||||
/** 绑定域名 */
|
||||
const appDomain = computed(() => appInfo.value?.domain || '')
|
||||
/** 应用 Logo */
|
||||
const appLogo = computed(() => appInfo.value?.logo || '')
|
||||
/** 应用图标(站点小图标,用于 Header/Footer Logo 回退) */
|
||||
const appIcon = computed(() => appInfo.value?.icon || '')
|
||||
/**
|
||||
* 关联模板目录名(template-XX):【code 优先,主键兜底】
|
||||
* templateCode 与前端模板目录一一对应;templateId 主键存在跳号错位风险,仅兜底。
|
||||
* 为空时返回 '' 由上层回退默认模板。
|
||||
*/
|
||||
const appTemplateId = computed(() =>
|
||||
resolveTemplateKey(appInfo.value?.templateCode, appInfo.value?.templateId)
|
||||
)
|
||||
/** 是否已过期 */
|
||||
const appExpired = computed(() => {
|
||||
const t = appInfo.value?.expirationTime
|
||||
if (!t) return false
|
||||
return new Date(t).getTime() < Date.now()
|
||||
})
|
||||
|
||||
return {
|
||||
appInfo,
|
||||
loading,
|
||||
error,
|
||||
fetchAppInfo,
|
||||
appName,
|
||||
appCode,
|
||||
appDomain,
|
||||
appLogo,
|
||||
appIcon,
|
||||
appTemplateId,
|
||||
appExpired
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user