Initial commit: X-Server Mobile enterprise tool system
- Frontend: React 18 + TypeScript + Vite + Ant Design Mobile - Backend: PHP 8.5 + Webman 2.x + MySQL + Redis - i18n support: Chinese, English, Russian, Spanish, French - Approval workflow engine - Docker development environment - Feishu integration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* 飞书 SDK 封装
|
||||
*/
|
||||
export const FeishuSDK = {
|
||||
/**
|
||||
* 判断是否在飞书环境
|
||||
*/
|
||||
isFeishuEnv(): boolean {
|
||||
return !!(window as any).h5panel || !!(window as any).tt
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取免登授权码
|
||||
*/
|
||||
async getAuthCode(): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.isFeishuEnv()) {
|
||||
reject(new Error('Not in Feishu environment'))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const tt = (window as any).tt || (window as any).h5panel
|
||||
tt.ready(() => {
|
||||
tt.requestAuthCode({
|
||||
success: (res: { authCode: string }) => {
|
||||
resolve(res.authCode)
|
||||
},
|
||||
fail: (err: Error) => {
|
||||
reject(err)
|
||||
},
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取当前租户信息(用于后端识别公司)
|
||||
*/
|
||||
getTenantContext(): { tenantKey?: string } {
|
||||
if (!this.isFeishuEnv()) {
|
||||
return {}
|
||||
}
|
||||
|
||||
try {
|
||||
const tt = (window as any).tt || (window as any).h5panel
|
||||
// 飞书容器中的租户信息
|
||||
return {
|
||||
tenantKey: tt?.tenantKey || '',
|
||||
}
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 初始化飞书 JSAPI
|
||||
*/
|
||||
async init(): Promise<void> {
|
||||
if (!this.isFeishuEnv()) {
|
||||
console.log('Not in Feishu environment, skip initialization')
|
||||
return
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const tt = (window as any).tt || (window as any).h5panel
|
||||
tt.ready(() => {
|
||||
console.log('Feishu JSAPI initialized')
|
||||
resolve()
|
||||
})
|
||||
tt.error((err: Error) => {
|
||||
console.error('Feishu JSAPI error:', err)
|
||||
reject(err)
|
||||
})
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
// 声明飞书全局类型
|
||||
declare global {
|
||||
interface Window {
|
||||
tt?: any
|
||||
h5panel?: any
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 动态设置根字体大小,实现移动端适配
|
||||
*/
|
||||
export function setRem(): void {
|
||||
// 设计稿宽度
|
||||
const designWidth = 375 // iPhone 6/7/8 的宽度
|
||||
// 基础字体大小
|
||||
const baseFontSize = 16
|
||||
|
||||
// 获取当前设备宽度
|
||||
const deviceWidth = document.documentElement.clientWidth || window.innerWidth
|
||||
|
||||
// 计算缩放比例
|
||||
const scale = deviceWidth / designWidth
|
||||
|
||||
// 设置根字体大小(最大不超过 20px,最小不小于 12px)
|
||||
const fontSize = Math.min(Math.max(scale * baseFontSize, 12), 20)
|
||||
|
||||
document.documentElement.style.fontSize = fontSize + 'px'
|
||||
|
||||
console.log(`设备宽度: ${deviceWidth}px, 根字体: ${fontSize}px`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 rem 适配
|
||||
*/
|
||||
export function initRem(): void {
|
||||
setRem()
|
||||
|
||||
// 监听窗口大小变化
|
||||
window.addEventListener('resize', setRem)
|
||||
|
||||
// 监听设备方向变化
|
||||
window.addEventListener('orientationchange', setRem)
|
||||
}
|
||||
Reference in New Issue
Block a user