mirror of
https://github.com/kuaifan/dootask.git
synced 2026-07-27 00:17:51 +00:00
feat(mobile): 主程序前端 nativeApp 桥接契约改造 + /share 接收页 + 子模块切到 Expo 工程
新移动端从 EEUI(weex) 切到 Expo(react-native),UA 标识从 'eeui' 改为 'DooTaskApp', 桥接底层从全局 requireModuleJs 切到 window.__nativeBridge.call(method,args) Promise RPC。 约 52 个文件批量改名(256 处引用): - 平台识别:$A.isEEUIApp/Vue.prototype.$isEEUIApp → isMobileApp / $isMobileApp app.js 顶部 UA 正则 /eeui/i → /DooTaskApp/i app.js requireModuleJs 等待逻辑替换为 window.__nativeBridge 就绪判定 - 桥接 API:$A.eeuiAppXXX → $A.nativeAppXXX - functions/eeui.js 删除,重写为 functions/native-app.js 底层走 window.__nativeBridge.call;nativeAppSendMessage 把旧 sendMessage 的 各 action 拆解为独立 method 调用(updateTheme/windowSize/setBadge/vibrate/ callTel/picturePreview/videoPreview/startMeeting/updateMeetingInfo 等) - types/dootask-globals.d.ts:方法签名同步改名 - store/actions.js:清理 saveUserInfoBase 内旧的 userChatList/userUploadUrl sendMessage(二期由 /share 接收页直接调接口替代) 二期 /share 接收页(跨 App 分享): - pages/share.vue(新增):原生 Share Extension / Android Intent 通过 dootask://share?token=... 拉起 App 后跳本页; 调 nativeAppGetSharedPayload 取分享元数据; 复用 api/users/share/list 渲染会话列表; 用户选会话 → POST api/dialog/msg/sendfiles 上传 + sendtext 发文本/URL; 完成后 nativeAppClearSharedPayload 清理 + 跳目标会话 - routes.js 注册 /share 路由 - language/original-web.txt 加 share.vue 用到的文案 构建链路(electron/build.js): - appbuild app 子命令:前端产物从复制到 resources/mobile/src/public + EEUI docker 构建 改为同步到 resources/mobile/assets/web(由 plugins/withWebAssets 注入原生 bundle) - android-upload apk 路径:从 platforms/android/eeuiApp/... 改为 android/app/build/outputs/apk/release(Expo prebuild 标准布局) 子模块 resources/mobile 指针更新到新 Expo 工程提交(feat/mobile-expo-rewrite 分支)。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9151939ba5
commit
f479047fc9
55
electron/build.js
vendored
55
electron/build.js
vendored
@ -401,48 +401,15 @@ async function startBuild(data) {
|
||||
fs.writeFileSync(indexFile, indexString, 'utf8');
|
||||
//
|
||||
if (data.id === 'app') {
|
||||
const eeuiDir = path.resolve(__dirname, "../resources/mobile");
|
||||
const publicDir = path.resolve(__dirname, "../resources/mobile/src/public");
|
||||
const containerName = `dootask-eeui-${Date.now()}-${process.pid}`;
|
||||
fse.removeSync(publicDir)
|
||||
fse.copySync(electronDir, publicDir)
|
||||
if (argv[3] === "publish") {
|
||||
// Android config
|
||||
const gradleFile = path.resolve(eeuiDir, "platforms/android/eeuiApp/local.properties")
|
||||
let gradleResult = fs.existsSync(gradleFile) ? fs.readFileSync(gradleFile, 'utf8') : "";
|
||||
gradleResult = gradleResult.replace(/(versionCode|versionName)\s*=\s*(.+?)(\n|$)/g, '')
|
||||
gradleResult += `versionCode = ${config.codeVerson}\nversionName = ${config.version}\n`
|
||||
fs.writeFileSync(gradleFile, gradleResult, 'utf8')
|
||||
// iOS config
|
||||
const xcconfigFile = path.resolve(eeuiDir, "platforms/ios/eeuiApp/Config/Version.xcconfig")
|
||||
let xcconfigResult = fs.existsSync(xcconfigFile) ? fs.readFileSync(xcconfigFile, 'utf8') : "";
|
||||
xcconfigResult = xcconfigResult.replace(/(VERSION_CODE|VERSION_NAME)\s*=\s*(.+?)(\n|$)/g, '')
|
||||
xcconfigResult += `VERSION_CODE = ${config.codeVerson}\nVERSION_NAME = ${config.version}\n`
|
||||
fs.writeFileSync(xcconfigFile, xcconfigResult, 'utf8')
|
||||
}
|
||||
if (['build', 'publish'].includes(argv[3])) {
|
||||
child_process.execSync(
|
||||
`docker run -d --name ${containerName} -v ${shellQuote(eeuiDir)}:/work -w /work kuaifan/eeui-cli:0.0.1 sleep infinity`,
|
||||
{stdio: "ignore", cwd: "resources/mobile"}
|
||||
);
|
||||
try {
|
||||
if (!fs.existsSync(path.resolve(eeuiDir, "node_modules"))) {
|
||||
child_process.execSync(`docker exec ${containerName} npm install`, {stdio: "inherit", cwd: "resources/mobile"});
|
||||
}
|
||||
child_process.execSync(`docker exec ${containerName} node /work/scripts/patch-eeui-build.js`, {stdio: "inherit", cwd: "resources/mobile"});
|
||||
child_process.execSync(`docker exec ${containerName} eeui build --simple`, {stdio: "inherit", cwd: "resources/mobile"});
|
||||
} finally {
|
||||
child_process.execSync(`docker rm -f ${containerName}`, {stdio: "ignore", cwd: "resources/mobile"});
|
||||
}
|
||||
} else {
|
||||
[
|
||||
path.resolve(publicDir, "../../platforms/ios/eeuiApp/bundlejs/eeui/public"),
|
||||
path.resolve(publicDir, "../../platforms/android/eeuiApp/app/src/main/assets/eeui/public"),
|
||||
].some(dir => {
|
||||
fse.removeSync(dir)
|
||||
fse.copySync(electronDir, dir)
|
||||
})
|
||||
}
|
||||
// 新 Expo 移动端:将前端构建产物作为离线包同步到 resources/mobile/assets/web,
|
||||
// 由 config plugin(withWebAssets) 在 prebuild 时注入原生 bundle,运行时本地静态服务 serve。
|
||||
const mobileDir = path.resolve(__dirname, "../resources/mobile");
|
||||
const webDir = path.resolve(mobileDir, "assets/web");
|
||||
fse.removeSync(webDir)
|
||||
fse.copySync(electronDir, webDir)
|
||||
console.log(`移动端离线包已同步: ${webDir}`);
|
||||
// 版本号由 resources/mobile/app.config.ts 从根 package.json 动态读取,无需改原生工程;
|
||||
// App 原生打包在 resources/mobile 下执行 expo prebuild + eas build(见 WS7)。
|
||||
return;
|
||||
}
|
||||
const output = `dist/${data.id.replace(/\./g, '-')}/${platform}`
|
||||
@ -560,7 +527,9 @@ if (["dev"].includes(argv[2])) {
|
||||
process.exit(1)
|
||||
}
|
||||
const client = r2.createR2Client()
|
||||
const releaseDir = path.resolve(__dirname, "../resources/mobile/platforms/android/eeuiApp/app/build/outputs/apk/release");
|
||||
// 新 Expo 移动端:apk 由 EAS Build 输出(或本地 expo prebuild + gradle assembleRelease)。
|
||||
// EAS 流水线产物路径示例:android/app/build/outputs/apk/release 或 EAS 远端构建直接上传。
|
||||
const releaseDir = path.resolve(__dirname, "../resources/mobile/android/app/build/outputs/apk/release");
|
||||
if (!fs.existsSync(releaseDir)) {
|
||||
console.error("发布文件未找到")
|
||||
process.exit(1)
|
||||
|
||||
@ -2469,3 +2469,10 @@ AI任务分析
|
||||
操作引导启动失败
|
||||
最多只能添加(*)个
|
||||
该标签已存在
|
||||
发送给
|
||||
搜索会话
|
||||
暂无会话
|
||||
缺少分享凭据
|
||||
分享内容不存在或已过期
|
||||
加载会话列表失败
|
||||
正在发送
|
||||
|
||||
@ -217,11 +217,11 @@ export default {
|
||||
handler() {
|
||||
this.$store.dispatch("websocketConnection");
|
||||
//
|
||||
if (this.$isEEUIApp) {
|
||||
if (this.$isMobileApp) {
|
||||
this.umengAliasTimer && clearTimeout(this.umengAliasTimer)
|
||||
if (this.userId > 0) {
|
||||
// 给 APP 发送初始化消息
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'initApp',
|
||||
apiUrl: $A.apiUrl(''),
|
||||
userid: this.userId,
|
||||
@ -231,7 +231,7 @@ export default {
|
||||
});
|
||||
|
||||
// 更新设备信息
|
||||
$A.eeuiAppGetDeviceInfo().then(async info => {
|
||||
$A.nativeAppGetDeviceInfo().then(async info => {
|
||||
let deviceName = info.deviceName || info.modelName
|
||||
if (info.systemName === 'Android') {
|
||||
if ($A.strExists(info.modelName, info.brand)) {
|
||||
@ -254,14 +254,14 @@ export default {
|
||||
// 设置友盟别名
|
||||
this.umengAliasTimer = setTimeout(_ => {
|
||||
this.umengAliasTimer = null;
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'setUmengAlias',
|
||||
url: $A.apiUrl('users/umeng/alias')
|
||||
});
|
||||
}, 6000)
|
||||
} else {
|
||||
// 删除友盟别名
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'delUmengAlias',
|
||||
url: $A.apiUrl('users/umeng/alias')
|
||||
});
|
||||
@ -385,7 +385,7 @@ export default {
|
||||
},
|
||||
|
||||
onRouterViewMounted() {
|
||||
document.documentElement.setAttribute("data-platform", $A.isElectron ? "desktop" : $A.isEEUIApp ? "app" : "web")
|
||||
document.documentElement.setAttribute("data-platform", $A.isElectron ? "desktop" : $A.isMobileApp ? "app" : "web")
|
||||
},
|
||||
|
||||
/**
|
||||
@ -649,12 +649,12 @@ export default {
|
||||
},
|
||||
|
||||
eeuiEvents() {
|
||||
if (!this.$isEEUIApp) {
|
||||
if (!this.$isMobileApp) {
|
||||
return;
|
||||
}
|
||||
// 隐藏快照
|
||||
setTimeout(() => {
|
||||
this.appActivated && $A.eeuiAppHideWebviewSnapshot()
|
||||
this.appActivated && $A.nativeAppHideWebviewSnapshot()
|
||||
}, 500)
|
||||
// APP进入前台
|
||||
window.__onAppActive = async () => {
|
||||
@ -667,12 +667,12 @@ export default {
|
||||
|
||||
this.autoTheme()
|
||||
$A.updateTimezone()
|
||||
$A.eeuiAppHideWebviewSnapshot()
|
||||
$A.nativeAppHideWebviewSnapshot()
|
||||
this.$store.dispatch("safeAreaInsets")
|
||||
const nowYmd = $A.daytz().format('YYYY-MM-DD')
|
||||
if (this.lastCheckUpgradeYmd != nowYmd) {
|
||||
this.lastCheckUpgradeYmd = nowYmd
|
||||
$A.eeuiAppCheckUpdate();
|
||||
$A.nativeAppCheckUpdate();
|
||||
}
|
||||
}
|
||||
// APP进入后台
|
||||
@ -683,12 +683,12 @@ export default {
|
||||
// 如果APP处于激活状态,则不显示快照
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppGetWebviewSnapshot(ok => {
|
||||
$A.nativeAppGetWebviewSnapshot(ok => {
|
||||
if (!ok || this.appActivated) {
|
||||
// 如果获取快照失败,或者APP处于激活状态,则不显示快照
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppShowWebviewSnapshot()
|
||||
$A.nativeAppShowWebviewSnapshot()
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
@ -714,7 +714,7 @@ export default {
|
||||
return;
|
||||
} else if (urlType === 1) {
|
||||
// 使用默认浏览器打开
|
||||
$A.eeuiAppOpenWeb(url);
|
||||
$A.nativeAppOpenWeb(url);
|
||||
return;
|
||||
}
|
||||
// App 内置浏览器打开
|
||||
@ -741,7 +741,7 @@ export default {
|
||||
tourist_id: event.uuid,
|
||||
}
|
||||
}).then(({data}) => {
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'updateMeetingInfo',
|
||||
infos: {
|
||||
uuid: event.uuid,
|
||||
@ -790,7 +790,7 @@ export default {
|
||||
}
|
||||
this.$store.state.keyboardShow = event.keyboardType === 'show';
|
||||
this.$store.state.keyboardHeight = event.keyboardHeight;
|
||||
$A.eeuiAppShakeToEditEnabled(this.$store.state.keyboardShow)
|
||||
$A.nativeAppShakeToEditEnabled(this.$store.state.keyboardShow)
|
||||
}
|
||||
// 通知权限
|
||||
window.__onNotificationPermissionStatus = (ret) => {
|
||||
@ -801,22 +801,22 @@ export default {
|
||||
this.goForward({ path: (path || '').indexOf('/') !==0 ? "/" + path : path });
|
||||
}
|
||||
// 发送网页尺寸
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'windowSize',
|
||||
width: this.windowWidth,
|
||||
height: this.windowHeight,
|
||||
});
|
||||
// 取消长按振动
|
||||
$A.eeuiAppSetHapticBackEnabled(false)
|
||||
$A.nativeAppSetHapticBackEnabled(false)
|
||||
// 设置语言
|
||||
$A.eeuiAppSetCachesString("languageWebBack", this.$L("后退"))
|
||||
$A.eeuiAppSetCachesString("languageWebForward", this.$L("前进"))
|
||||
$A.eeuiAppSetCachesString("languageWebBrowser", this.$L("浏览器打开"))
|
||||
$A.eeuiAppSetCachesString("languageWebRefresh", this.$L("刷新"))
|
||||
$A.eeuiAppSetCachesString("updateDefaultTitle", this.$L("发现新版本"))
|
||||
$A.eeuiAppSetCachesString("updateDefaultContent", this.$L("暂无更新介绍!"))
|
||||
$A.eeuiAppSetCachesString("updateDefaultCancelText", this.$L("以后再说"))
|
||||
$A.eeuiAppSetCachesString("updateDefaultUpdateText", this.$L("立即更新"))
|
||||
$A.nativeAppSetCachesString("languageWebBack", this.$L("后退"))
|
||||
$A.nativeAppSetCachesString("languageWebForward", this.$L("前进"))
|
||||
$A.nativeAppSetCachesString("languageWebBrowser", this.$L("浏览器打开"))
|
||||
$A.nativeAppSetCachesString("languageWebRefresh", this.$L("刷新"))
|
||||
$A.nativeAppSetCachesString("updateDefaultTitle", this.$L("发现新版本"))
|
||||
$A.nativeAppSetCachesString("updateDefaultContent", this.$L("暂无更新介绍!"))
|
||||
$A.nativeAppSetCachesString("updateDefaultCancelText", this.$L("以后再说"))
|
||||
$A.nativeAppSetCachesString("updateDefaultUpdateText", this.$L("立即更新"))
|
||||
},
|
||||
|
||||
otherEvents() {
|
||||
|
||||
28
resources/assets/js/app.js
vendored
28
resources/assets/js/app.js
vendored
@ -1,6 +1,7 @@
|
||||
const isElectron = !!(window && window.process && window.process.type && window.electron);
|
||||
const isEEUIApp = window && window.navigator && /eeui/i.test(window.navigator.userAgent);
|
||||
const isSoftware = isElectron || isEEUIApp;
|
||||
// 新移动端在 UA 追加 DooTaskApp/<codeVersion>(resources/mobile/src/webview/WebViewShell.tsx)
|
||||
const isMobileApp = window && window.navigator && /DooTaskApp/i.test(window.navigator.userAgent);
|
||||
const isSoftware = isElectron || isMobileApp;
|
||||
|
||||
document.getElementById("app")?.setAttribute("data-preload", "false");
|
||||
|
||||
@ -8,7 +9,7 @@ import {languageName, switchLanguage as $L} from "./language";
|
||||
import {isLocalHost} from "./components/Replace/utils";
|
||||
|
||||
import './functions/common'
|
||||
import './functions/eeui'
|
||||
import './functions/native-app'
|
||||
import './functions/web'
|
||||
|
||||
import Vue from 'vue'
|
||||
@ -188,8 +189,8 @@ Vue.prototype.copyText = function (obj) {
|
||||
error: "复制失败"
|
||||
}
|
||||
}
|
||||
if ($A.isEEUIApp) {
|
||||
$A.eeuiAppCopyText(obj.text)
|
||||
if ($A.isMobileApp) {
|
||||
$A.nativeAppCopyText(obj.text)
|
||||
obj.success && $A.messageSuccess(obj.success)
|
||||
return
|
||||
}
|
||||
@ -207,7 +208,7 @@ $A.Electron = null;
|
||||
$A.Platform = "web";
|
||||
$A.isMainElectron = false;
|
||||
$A.isSubElectron = false;
|
||||
$A.isEEUIApp = isEEUIApp;
|
||||
$A.isMobileApp = isMobileApp;
|
||||
$A.isElectron = isElectron;
|
||||
$A.isSoftware = isSoftware;
|
||||
$A.openLog = false;
|
||||
@ -216,7 +217,7 @@ if (isElectron) {
|
||||
$A.Platform = /macintosh|mac os x/i.test(navigator.userAgent) ? "mac" : "win";
|
||||
$A.isMainElectron = /\s+MainTaskWindow\//.test(window.navigator.userAgent);
|
||||
$A.isSubElectron = /\s+SubTaskWindow\//.test(window.navigator.userAgent);
|
||||
} else if (isEEUIApp) {
|
||||
} else if (isMobileApp) {
|
||||
$A.Platform = /(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent) ? "ios" : "android";
|
||||
}
|
||||
|
||||
@ -287,7 +288,7 @@ Vue.prototype.$Electron = $A.Electron;
|
||||
Vue.prototype.$Platform = $A.Platform;
|
||||
Vue.prototype.$isMainElectron = $A.isMainElectron;
|
||||
Vue.prototype.$isSubElectron = $A.isSubElectron;
|
||||
Vue.prototype.$isEEUIApp = $A.isEEUIApp;
|
||||
Vue.prototype.$isMobileApp = $A.isMobileApp;
|
||||
Vue.prototype.$isSoftware = $A.isSoftware;
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
@ -324,15 +325,16 @@ const $init = async () => {
|
||||
const $preload = async () => {
|
||||
document.getElementById("app")?.setAttribute("data-preload", "true")
|
||||
|
||||
if ($A.isEEUIApp) {
|
||||
if ($A.isMobileApp) {
|
||||
// 等待新 RN 桥接传输层(window.__nativeBridge)就绪,注入时机为 webview 加载内容前
|
||||
const requireTime = new Date().getTime();
|
||||
while (typeof requireModuleJs !== "function") {
|
||||
while (!window.__nativeBridge) {
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
if (new Date().getTime() - requireTime > 15 * 1000) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (typeof requireModuleJs !== "function") {
|
||||
if (!window.__nativeBridge) {
|
||||
const errorTip = $A.L("加载失败,请重启软件")
|
||||
const errorView = document.querySelector(".app-view-loading")
|
||||
if (errorView) {
|
||||
@ -342,8 +344,8 @@ const $preload = async () => {
|
||||
}
|
||||
return
|
||||
}
|
||||
const pageInfo = $A.eeuiAppGetPageInfo() || {};
|
||||
store.state.isFirstPage = pageInfo.pageName === 'firstPage'
|
||||
// 新移动端单 WebView 套壳,永远是首屏;isFirstPage 恒 true(旧 EEUI 是多 page 容器才需要判定)
|
||||
store.state.isFirstPage = true
|
||||
await store.dispatch("safeAreaInsets")
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
:placement="placement"
|
||||
:effect="tooltipTheme"
|
||||
:delay="delay"
|
||||
:disabled="$isEEUIApp || windowTouch || !showTooltip || disabled"
|
||||
:disabled="$isMobileApp || windowTouch || !showTooltip || disabled"
|
||||
:max-width="tooltipMaxWidth"
|
||||
transfer>
|
||||
<span ref="content" @mouseenter="handleTooltipIn" class="common-auto-tip" @click="onClick">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<ETooltip v-if="visible" :disabled="$isEEUIApp || windowTouch || content == ''" :content="content">
|
||||
<ETooltip v-if="visible" :disabled="$isMobileApp || windowTouch || content == ''" :content="content">
|
||||
<svg v-if="type === 'svg'" viewBox="25 25 50 50" class="common-loading">
|
||||
<circle cx="50" cy="50" r="20" fill="none" stroke-width="5" stroke-miterlimit="10" class="common-path"></circle>
|
||||
</svg>
|
||||
|
||||
@ -257,7 +257,7 @@ export default {
|
||||
systemInfo: window.systemInfo,
|
||||
windowType: this.windowType,
|
||||
|
||||
isEEUIApp: $A.isEEUIApp,
|
||||
isMobileApp: $A.isMobileApp,
|
||||
isElectron: $A.isElectron,
|
||||
isMainElectron: $A.isMainElectron,
|
||||
isSubElectron: $A.isSubElectron,
|
||||
@ -515,7 +515,7 @@ export default {
|
||||
width: mergedConfig.width,
|
||||
height: mergedConfig.height,
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
await this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: ' ',
|
||||
@ -541,7 +541,7 @@ export default {
|
||||
path: config.url,
|
||||
title: config.title || ' ',
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
await this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: ' ',
|
||||
|
||||
@ -175,14 +175,14 @@ export default {
|
||||
},
|
||||
|
||||
appAndroidEvents() {
|
||||
if (this.$isEEUIApp && $A.isAndroid()) {
|
||||
$A.eeuiAppSetPageBackPressed({
|
||||
if (this.$isMobileApp && $A.isAndroid()) {
|
||||
$A.nativeAppSetPageBackPressed({
|
||||
pageName: 'firstPage',
|
||||
}, _ => {
|
||||
if (this.canBack()) {
|
||||
this.onBack();
|
||||
} else {
|
||||
$A.eeuiAppGoDesktop()
|
||||
$A.nativeAppGoDesktop()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ export default {
|
||||
if (this.duration > 0) {
|
||||
this.timer = setTimeout(this.close, this.duration)
|
||||
}
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'setVibrate',
|
||||
});
|
||||
},
|
||||
|
||||
@ -198,7 +198,7 @@ export default {
|
||||
if (this.windowActive) {
|
||||
return
|
||||
}
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'setBdageNotify',
|
||||
bdage: this.unreadAndOverdue,
|
||||
});
|
||||
|
||||
@ -32,7 +32,7 @@ export default {
|
||||
},
|
||||
previewImageList(l) {
|
||||
if (l.length > 0) {
|
||||
if ($A.isEEUIApp || $A.isElectron) {
|
||||
if ($A.isMobileApp || $A.isElectron) {
|
||||
let position = Math.min(Math.max(this.$store.state.previewImageIndex, 0), this.$store.state.previewImageList.length - 1)
|
||||
let paths = l.map(item => {
|
||||
if ($A.isJson(item)) {
|
||||
@ -74,9 +74,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
videoPreview(path) {
|
||||
if ($A.isEEUIApp) {
|
||||
$A.eeuiAppSendMessage({
|
||||
language: $A.eeuiAppConvertLanguage(),
|
||||
if ($A.isMobileApp) {
|
||||
$A.nativeAppSendMessage({
|
||||
language: $A.nativeAppConvertLanguage(),
|
||||
action: 'videoPreview',
|
||||
path
|
||||
});
|
||||
@ -89,9 +89,9 @@ export default {
|
||||
}
|
||||
},
|
||||
imagePreview(index, paths) {
|
||||
if ($A.isEEUIApp) {
|
||||
$A.eeuiAppSendMessage({
|
||||
language: $A.eeuiAppConvertLanguage(),
|
||||
if ($A.isMobileApp) {
|
||||
$A.nativeAppSendMessage({
|
||||
language: $A.nativeAppConvertLanguage(),
|
||||
action: 'picturePreview',
|
||||
position: index,
|
||||
paths
|
||||
|
||||
@ -18,7 +18,7 @@ const convertLocalResourcePath = (() => {
|
||||
if (initialized) return
|
||||
|
||||
// 设置应用前缀URL
|
||||
if ($A.isEEUIApp || $A.isElectron) {
|
||||
if ($A.isMobileApp || $A.isElectron) {
|
||||
appPreUrl = window.location.origin + "/"
|
||||
}
|
||||
|
||||
|
||||
@ -94,14 +94,14 @@ export default {
|
||||
},
|
||||
|
||||
showDown() {
|
||||
if (this.$Electron || this.$isEEUIApp || this.windowTouch) {
|
||||
if (this.$Electron || this.$isMobileApp || this.windowTouch) {
|
||||
return false
|
||||
}
|
||||
return this.routeName === 'login'
|
||||
},
|
||||
|
||||
showPrivacy() {
|
||||
return $A.isDooServer() && this.$isEEUIApp && ['login'].includes(this.routeName)
|
||||
return $A.isDooServer() && this.$isMobileApp && ['login'].includes(this.routeName)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<Loading v-if="loadIng > 0"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.nativeAppKeyboardHide">
|
||||
<Input type="search" ref="searchKey" v-model="searchKey" :placeholder="$L('请输入关键字')"/>
|
||||
</Form>
|
||||
<div v-if="aiSearchAvailable" class="search-ai" @click="toggleAiSearch">
|
||||
@ -142,7 +142,7 @@ export default {
|
||||
},
|
||||
|
||||
showModal(v) {
|
||||
$A.eeuiAppSetScrollDisabled(v)
|
||||
$A.nativeAppSetScrollDisabled(v)
|
||||
}
|
||||
},
|
||||
|
||||
@ -262,7 +262,7 @@ export default {
|
||||
},
|
||||
|
||||
onTouchstart() {
|
||||
$A.eeuiAppKeyboardHide();
|
||||
$A.nativeAppKeyboardHide();
|
||||
},
|
||||
|
||||
onTag(type, e) {
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
v-if="item.hidden !== true"
|
||||
placement="top"
|
||||
:key="key"
|
||||
:disabled="$isEEUIApp || windowTouch || !item.title"
|
||||
:disabled="$isMobileApp || windowTouch || !item.title"
|
||||
:content="item.title"
|
||||
:enterable="false"
|
||||
:open-delay="600">
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<ETooltip
|
||||
:open-delay="openDelay"
|
||||
:disabled="$isEEUIApp || windowTouch || tooltipDisabled || isBot"
|
||||
:disabled="$isMobileApp || windowTouch || tooltipDisabled || isBot"
|
||||
:placement="tooltipPlacement">
|
||||
<div v-if="user" slot="content" class="common-avatar-transfer">
|
||||
<slot/>
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
<Loading v-if="loadIng > 0"/>
|
||||
<Icon v-else type="ios-search"/>
|
||||
</div>
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.nativeAppKeyboardHide">
|
||||
<Input
|
||||
type="search"
|
||||
v-model="searchKey"
|
||||
@ -377,7 +377,7 @@ export default {
|
||||
}
|
||||
this.$emit("on-show-change", v)
|
||||
//
|
||||
$A.eeuiAppSetScrollDisabled(v && this.windowPortrait)
|
||||
$A.nativeAppSetScrollDisabled(v && this.windowPortrait)
|
||||
},
|
||||
|
||||
searchKey() {
|
||||
|
||||
4
resources/assets/js/functions/common.js
vendored
4
resources/assets/js/functions/common.js
vendored
@ -782,7 +782,7 @@ const timezone = require("dayjs/plugin/timezone");
|
||||
* @returns {string}
|
||||
*/
|
||||
reloadUrl() {
|
||||
if ($A.isEEUIApp && $A.isAndroid()) {
|
||||
if ($A.isMobileApp && $A.isAndroid()) {
|
||||
let url = window.location.href;
|
||||
let key = '_='
|
||||
let reg = new RegExp(key + '\\d+');
|
||||
@ -805,7 +805,7 @@ const timezone = require("dayjs/plugin/timezone");
|
||||
}
|
||||
}
|
||||
}
|
||||
$A.eeuiAppSetUrl(url);
|
||||
$A.nativeAppSetUrl(url);
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
381
resources/assets/js/functions/eeui.js
vendored
381
resources/assets/js/functions/eeui.js
vendored
@ -1,381 +0,0 @@
|
||||
/**
|
||||
* EEUI App 专用
|
||||
*/
|
||||
import {languageName} from "../language";
|
||||
|
||||
(function (window) {
|
||||
const $ = window.$A;
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* **************************** EEUI App extra *****************************
|
||||
* =============================================================================
|
||||
*/
|
||||
$.extend({
|
||||
// 获取eeui模块
|
||||
eeuiModule(name = 'eeui') {
|
||||
if (typeof requireModuleJs === "function") {
|
||||
return requireModuleJs(name);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
// 获取eeui模块(Promise)
|
||||
eeuiModulePromise(name = 'eeui') {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
const eeui = $A.eeuiModule(name);
|
||||
if (!eeui) {
|
||||
return reject({msg: "module not found"});
|
||||
}
|
||||
resolve(eeui);
|
||||
} catch (e) {
|
||||
reject({msg: e.message});
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取eeui版本号
|
||||
eeuiAppVersion() {
|
||||
return $A.eeuiModule()?.getVersion();
|
||||
},
|
||||
|
||||
// 获取本地软件版本号
|
||||
eeuiAppLocalVersion() {
|
||||
return $A.eeuiModule()?.getLocalVersion();
|
||||
},
|
||||
|
||||
// Alert
|
||||
eeuiAppAlert(object, callback) {
|
||||
if (typeof callback !== "function") callback = _ => {};
|
||||
$A.eeuiModule()?.alert(object, callback);
|
||||
},
|
||||
|
||||
// Toast
|
||||
eeuiAppToast(object) {
|
||||
$A.eeuiModule()?.toast(object);
|
||||
},
|
||||
|
||||
// 相对地址基于当前地址补全
|
||||
eeuiAppRewriteUrl(val) {
|
||||
return $A.eeuiModule()?.rewriteUrl(val);
|
||||
},
|
||||
|
||||
// 获取页面信息
|
||||
eeuiAppGetPageInfo(pageName) {
|
||||
return $A.eeuiModule()?.getPageInfo(pageName || "");
|
||||
},
|
||||
|
||||
// 打开app新页面
|
||||
eeuiAppOpenPage(object, callback) {
|
||||
if (typeof callback !== "function") {
|
||||
callback = _ => {};
|
||||
}
|
||||
if (typeof object.callback === "function") {
|
||||
callback = object.callback;
|
||||
delete object.callback
|
||||
}
|
||||
$A.eeuiModule()?.openPage(Object.assign({
|
||||
softInputMode: "resize",
|
||||
}, object), callback);
|
||||
},
|
||||
|
||||
// 使用系统浏览器打开网页
|
||||
eeuiAppOpenWeb(url) {
|
||||
$A.eeuiModule()?.openWeb(url)
|
||||
},
|
||||
|
||||
// 拦截返回按键事件(仅支持android、iOS无效)
|
||||
eeuiAppSetPageBackPressed(object, callback) {
|
||||
if (typeof callback !== "function") callback = _ => {};
|
||||
$A.eeuiModule()?.setPageBackPressed(object, callback);
|
||||
},
|
||||
|
||||
// 返回手机桌面
|
||||
eeuiAppGoDesktop() {
|
||||
$A.eeuiModule()?.goDesktop();
|
||||
},
|
||||
|
||||
// 打开屏幕常亮
|
||||
eeuiAppKeepScreenOn() {
|
||||
$A.eeuiModule()?.keepScreenOn();
|
||||
},
|
||||
|
||||
// 关闭屏幕常亮
|
||||
eeuiAppKeepScreenOff() {
|
||||
$A.eeuiModule()?.keepScreenOff();
|
||||
},
|
||||
|
||||
// 隐藏软键盘
|
||||
eeuiAppKeyboardHide() {
|
||||
$A.eeuiModule()?.keyboardHide();
|
||||
},
|
||||
|
||||
// 给app发送消息
|
||||
eeuiAppSendMessage(object) {
|
||||
$A.eeuiModule("webview")?.sendMessage(object);
|
||||
},
|
||||
|
||||
// 设置浏览器地址
|
||||
eeuiAppSetUrl(url) {
|
||||
$A.eeuiModule("webview")?.setUrl(url);
|
||||
},
|
||||
|
||||
// 生成webview快照
|
||||
eeuiAppGetWebviewSnapshot(callback) {
|
||||
$A.eeuiModule("webview")?.createSnapshot(callback);
|
||||
},
|
||||
|
||||
// 显示webview快照
|
||||
eeuiAppShowWebviewSnapshot() {
|
||||
$A.eeuiModule("webview")?.showSnapshot();
|
||||
},
|
||||
|
||||
// 隐藏webview快照
|
||||
eeuiAppHideWebviewSnapshot() {
|
||||
$A.eeuiModule("webview")?.hideSnapshot();
|
||||
},
|
||||
|
||||
// 扫码
|
||||
eeuiAppScan(callback) {
|
||||
$A.eeuiModule()?.openScaner({}, (res) => {
|
||||
switch (res.status) {
|
||||
case "success":
|
||||
callback(res.text);
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 检查更新
|
||||
eeuiAppCheckUpdate() {
|
||||
$A.eeuiModule()?.checkUpdate();
|
||||
},
|
||||
|
||||
// 获取主题名称 light|dark
|
||||
eeuiAppGetThemeName() {
|
||||
return $A.eeuiModule()?.getThemeName();
|
||||
},
|
||||
|
||||
// 判断软键盘是否可见
|
||||
eeuiAppKeyboardStatus() {
|
||||
return $A.eeuiModule()?.keyboardStatus();
|
||||
},
|
||||
|
||||
// 设置全局变量
|
||||
eeuiAppSetVariate(key, value) {
|
||||
$A.eeuiModule()?.setVariate(key, value);
|
||||
},
|
||||
|
||||
// 获取全局变量
|
||||
eeuiAppGetVariate(key, defaultVal = "") {
|
||||
return $A.eeuiModule()?.getVariate(key, defaultVal);
|
||||
},
|
||||
|
||||
// 设置缓存数据
|
||||
eeuiAppSetCachesString(key, value, expired = 0) {
|
||||
$A.eeuiModule()?.setCachesString(key, value, expired);
|
||||
},
|
||||
|
||||
// 获取缓存数据
|
||||
eeuiAppGetCachesString(key, defaultVal = "") {
|
||||
return $A.eeuiModule()?.getCachesString(key, defaultVal);
|
||||
},
|
||||
|
||||
// 是否长按内容震动(仅支持android、iOS无效)
|
||||
eeuiAppSetHapticBackEnabled(val) {
|
||||
$A.eeuiModule("webview").setHapticBackEnabled(val);
|
||||
},
|
||||
|
||||
// 禁止长按选择(仅支持android、iOS无效)
|
||||
eeuiAppSetDisabledUserLongClickSelect(val) {
|
||||
const webview = $A.eeuiModule("webview");
|
||||
$A.__disabledUserLongClickSelectTimer && clearTimeout($A.__disabledUserLongClickSelectTimer);
|
||||
if (!/^\d+$/.test(val)) {
|
||||
webview.setDisabledUserLongClickSelect(val);
|
||||
return;
|
||||
}
|
||||
webview.setDisabledUserLongClickSelect(true);
|
||||
$A.__disabledUserLongClickSelectTimer = setTimeout(() => {
|
||||
$A.__disabledUserLongClickSelectTimer = null;
|
||||
webview.setDisabledUserLongClickSelect(false);
|
||||
}, val);
|
||||
},
|
||||
__disabledUserLongClickSelectTimer: null,
|
||||
|
||||
// 复制文本
|
||||
eeuiAppCopyText(text) {
|
||||
$A.eeuiModule()?.copyText(text)
|
||||
},
|
||||
|
||||
// 设置是否禁止滚动
|
||||
eeuiAppSetScrollDisabled(disabled) {
|
||||
if (disabled) {
|
||||
$A.__setScrollDisabledNum++
|
||||
} else {
|
||||
$A.__setScrollDisabledNum--
|
||||
}
|
||||
$A.eeuiModule("webview")?.setScrollEnabled($A.__setScrollDisabledNum <= 0);
|
||||
},
|
||||
__setScrollDisabledNum: 0,
|
||||
|
||||
// 设置应用程序级别的摇动撤销(仅支持iOS、android无效)
|
||||
eeuiAppShakeToEditEnabled(enabled) {
|
||||
if (enabled) {
|
||||
$A.eeuiModule()?.shakeToEditOn();
|
||||
} else {
|
||||
$A.eeuiModule()?.shakeToEditOff();
|
||||
}
|
||||
},
|
||||
|
||||
// 获取最新一张照片
|
||||
eeuiAppGetLatestPhoto(expiration = 60, timeout = 10) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const eeui = await $A.eeuiModule();
|
||||
|
||||
const timer = timeout > 0 ? setTimeout(() => {
|
||||
reject({msg: "timeout"});
|
||||
}, timeout * 1000) : null;
|
||||
|
||||
eeui.getLatestPhoto(result => {
|
||||
timer && clearTimeout(timer);
|
||||
if (
|
||||
result.status !== 'success' ||
|
||||
result.thumbnail.width < 10 || !result.thumbnail.base64 ||
|
||||
result.original.width < 10 || !result.original.path
|
||||
) {
|
||||
return reject({msg: result.error || "no photo"});
|
||||
}
|
||||
if (expiration > 0 && (result.created + expiration) < $A.dayjs().unix()) {
|
||||
return reject({msg: "photo expired"});
|
||||
}
|
||||
if ($A.__latestPhotoCreated && $A.__latestPhotoCreated === result.created) {
|
||||
return reject({msg: "photo expired"});
|
||||
}
|
||||
$A.__latestPhotoCreated = result.created;
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
},
|
||||
__latestPhotoCreated: null,
|
||||
|
||||
// 上传照片(通过 eeuiAppGetLatestPhoto 获取到的path,params 参数:{url,data,headers,path,fieldName})
|
||||
eeuiAppUploadPhoto(params, timeout = 30) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const eeui = await $A.eeuiModulePromise();
|
||||
|
||||
const timer = timeout > 0 ? setTimeout(() => {
|
||||
reject({msg: "timeout"});
|
||||
}, timeout * 1000) : null;
|
||||
|
||||
if (!$A.isJson(params)) {
|
||||
return reject({msg: "params error"});
|
||||
}
|
||||
|
||||
let onReady = null;
|
||||
if (typeof params.onReady !== "undefined") {
|
||||
onReady = params.onReady;
|
||||
delete params.onReady;
|
||||
}
|
||||
|
||||
eeui.uploadPhoto(params, result => {
|
||||
if (result.status === 'ready') {
|
||||
typeof onReady === "function" && onReady(result.id)
|
||||
return
|
||||
}
|
||||
|
||||
timer && clearTimeout(timer);
|
||||
if (result.status !== 'success') {
|
||||
return reject({msg: result.error || "upload failed"});
|
||||
}
|
||||
if (result.data.ret !== 1) {
|
||||
return reject({msg: result.data.msg || "upload failed"});
|
||||
}
|
||||
resolve(result.data.data);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 取消上传照片
|
||||
eeuiAppCancelUploadPhoto(id) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const eeui = await $A.eeuiModulePromise();
|
||||
eeui.cancelUploadPhoto(id, result => {
|
||||
if (result.status !== 'success') {
|
||||
return reject({msg: result.error || "cancel failed"});
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取导航栏和状态栏高度
|
||||
eeuiAppGetSafeAreaInsets() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const eeui = await $A.eeuiModulePromise();
|
||||
eeui.getSafeAreaInsets(result => {
|
||||
if (result.status !== 'success') {
|
||||
return reject({msg: result.error || "get failed"});
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取当前语言
|
||||
eeuiAppConvertLanguage() {
|
||||
const specialMappings = {
|
||||
"zh": "zh-Hans",
|
||||
"zh-CHT": "zh-Hant"
|
||||
};
|
||||
return specialMappings[languageName] || languageName;
|
||||
},
|
||||
|
||||
// 获取设备信息
|
||||
eeuiAppGetDeviceInfo() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const eeui = await $A.eeuiModulePromise();
|
||||
eeui.getDeviceInfo(result => {
|
||||
if (result.status !== 'success') {
|
||||
return reject({msg: result.error || "get failed"});
|
||||
}
|
||||
resolve(result);
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 判断是否窗口化
|
||||
eeuiAppIsWindowed() {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
const eeui = await $A.eeuiModulePromise();
|
||||
resolve(eeui.isFullscreen() === false || eeui.isFullscreen() === 0);
|
||||
} catch (e) {
|
||||
resolve(false);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
window.$A = $;
|
||||
})(window);
|
||||
194
resources/assets/js/functions/native-app.js
vendored
Executable file
194
resources/assets/js/functions/native-app.js
vendored
Executable file
@ -0,0 +1,194 @@
|
||||
/**
|
||||
* Native App 桥接(替代旧 functions/eeui.js)
|
||||
*
|
||||
* 底层从 weex 的 requireModuleJs 切换为新 RN 桥接 window.__nativeBridge(src/bridge/injected.ts 注入)。
|
||||
* 方法名规则:$A.nativeAppXxx(args) → __nativeBridge.call('xxx', args),其中 xxx 为首字母小写。
|
||||
*
|
||||
* 契约见 resources/mobile/src/bridge/CONTRACT.md。
|
||||
*/
|
||||
import {languageName} from "../language";
|
||||
|
||||
(function (window) {
|
||||
const $ = window.$A;
|
||||
|
||||
/** 通用调用入口:返回 Promise;桥接未就绪则 resolve undefined(避免抛错炸主流程) */
|
||||
function call(method, args) {
|
||||
const bridge = window.__nativeBridge;
|
||||
if (!bridge || typeof bridge.call !== "function") {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
return bridge.call(method, args === undefined ? null : args);
|
||||
}
|
||||
|
||||
/** 同步调用包装:调用方需要立刻拿到值的场景(仅适用于在 native 端有缓存的 method)。
|
||||
* 注意:所有桥接调用本质是异步;同步方法目前用兜底默认值返回。 */
|
||||
function syncDefault(_method, defaultValue) { return defaultValue; }
|
||||
|
||||
$.extend({
|
||||
// === 设备/系统 ===
|
||||
nativeAppVersion() { return syncDefault('getAppVersion', undefined); },
|
||||
nativeAppVersionAsync() { return call('getAppVersion'); },
|
||||
nativeAppLocalVersion() { return syncDefault('getAppLocalVersion', 0); },
|
||||
nativeAppLocalVersionAsync() { return call('getAppLocalVersion'); },
|
||||
nativeAppGetPageInfo() { return {}; },
|
||||
nativeAppGetThemeName() { return syncDefault('getThemeName', undefined); },
|
||||
nativeAppKeyboardStatus() { return syncDefault('keyboardStatus', undefined); },
|
||||
nativeAppRewriteUrl(val) { return val; },
|
||||
|
||||
// === UI 容器控制 ===
|
||||
nativeAppAlert(object, callback) {
|
||||
if (typeof callback !== "function") callback = _ => {};
|
||||
call('alert', object).then(callback).catch(callback);
|
||||
},
|
||||
nativeAppToast(object) { call('toast', typeof object === 'string' ? { message: object } : object); },
|
||||
nativeAppKeyboardHide() { call('keyboardHide'); },
|
||||
nativeAppKeepScreenOn() { call('keepScreenOn'); },
|
||||
nativeAppKeepScreenOff() { call('keepScreenOff'); },
|
||||
nativeAppSetPageBackPressed(object, callback) {
|
||||
if (typeof callback !== "function") callback = _ => {};
|
||||
// 旧契约:原生回调由 setPageBackPressed 触发;新契约用全局事件 __onBackPressed
|
||||
window.__onBackPressed = callback;
|
||||
call('setPageBackPressed', object);
|
||||
},
|
||||
nativeAppGoDesktop() { call('goDesktop'); },
|
||||
nativeAppSetHapticBackEnabled(val) { call('setHapticBackEnabled', !!val); },
|
||||
nativeAppSetDisabledUserLongClickSelect(val) {
|
||||
$.__disabledUserLongClickSelectTimer && clearTimeout($.__disabledUserLongClickSelectTimer);
|
||||
if (!/^\d+$/.test(val)) {
|
||||
call('setScrollDisabled', !!val);
|
||||
return;
|
||||
}
|
||||
call('setScrollDisabled', true);
|
||||
$.__disabledUserLongClickSelectTimer = setTimeout(() => {
|
||||
$.__disabledUserLongClickSelectTimer = null;
|
||||
call('setScrollDisabled', false);
|
||||
}, parseInt(val));
|
||||
},
|
||||
__disabledUserLongClickSelectTimer: null,
|
||||
nativeAppSetScrollDisabled(disabled) {
|
||||
if (disabled) {
|
||||
$.__setScrollDisabledNum++
|
||||
} else {
|
||||
$.__setScrollDisabledNum--
|
||||
}
|
||||
call('setScrollDisabled', $.__setScrollDisabledNum > 0);
|
||||
},
|
||||
__setScrollDisabledNum: 0,
|
||||
nativeAppShakeToEditEnabled(_enabled) { /* iOS 摇动撤销在 RN 由系统默认支持,no-op */ },
|
||||
|
||||
// === 存储 ===
|
||||
nativeAppSetVariate(key, value) { call('setVariate', { key, value }); },
|
||||
nativeAppGetVariate(_key, defaultVal = "") {
|
||||
// 异步返回;同步签名兼容兜底(不推荐使用)
|
||||
return defaultVal;
|
||||
},
|
||||
nativeAppGetVariateAsync(key, defaultVal = "") {
|
||||
return call('getVariate', { key, defaultVal });
|
||||
},
|
||||
nativeAppSetCachesString(key, value, expired = 0) { call('setCache', { key, value, expired }); },
|
||||
nativeAppGetCachesString(_key, defaultVal = "") { return defaultVal; },
|
||||
nativeAppGetCachesStringAsync(key, defaultVal = "") {
|
||||
return call('getCache', { key, defaultVal });
|
||||
},
|
||||
|
||||
// === 媒体 ===
|
||||
nativeAppScan(callback) {
|
||||
call('scan').then((text) => { typeof callback === 'function' && callback(text); });
|
||||
},
|
||||
nativeAppCopyText(text) { call('copyText', text); },
|
||||
nativeAppGetLatestPhoto(expiration = 60, _timeout = 10) {
|
||||
return call('getLatestPhoto', { expiration }).then((res) => {
|
||||
// 旧契约外形:{thumbnail:{base64,width,height}, original:{path,width,height}}
|
||||
// 新最小实现只返回 {path,width,height,created},包装为兼容形态。
|
||||
if (!res || !res.path) return Promise.reject({ msg: 'no photo' });
|
||||
return {
|
||||
thumbnail: { base64: '', width: res.width, height: res.height },
|
||||
original: { path: res.path, width: res.width, height: res.height },
|
||||
created: res.created,
|
||||
};
|
||||
});
|
||||
},
|
||||
nativeAppUploadPhoto(params, _timeout = 30) {
|
||||
const onReady = params && params.onReady;
|
||||
if (typeof onReady === 'function') delete params.onReady;
|
||||
return call('uploadPhoto', params).then((data) => {
|
||||
if (typeof onReady === 'function') onReady();
|
||||
return data;
|
||||
});
|
||||
},
|
||||
nativeAppCancelUploadPhoto(id) { return call('cancelUploadPhoto', { id }); },
|
||||
|
||||
// === 交互/外链 ===
|
||||
nativeAppOpenPage(object, callback) {
|
||||
if (typeof callback !== "function") callback = _ => {};
|
||||
if (typeof object.callback === "function") {
|
||||
callback = object.callback;
|
||||
delete object.callback
|
||||
}
|
||||
call('openPage', object).then(callback).catch(callback);
|
||||
},
|
||||
nativeAppOpenWeb(url) { call('openWeb', url); },
|
||||
nativeAppSetUrl(url) { call('setUrl', url); },
|
||||
nativeAppGetWebviewSnapshot(callback) { typeof callback === 'function' && callback({status: 'noop'}); },
|
||||
nativeAppShowWebviewSnapshot() { /* 新移动端不再用 weex 快照机制 */ },
|
||||
nativeAppHideWebviewSnapshot() { /* 同上 */ },
|
||||
nativeAppCheckUpdate() { call('checkUpdate'); },
|
||||
|
||||
// === 信息(异步)===
|
||||
nativeAppGetDeviceInfo() {
|
||||
return call('getDeviceInfo').then((info) => {
|
||||
if (!info) return Promise.reject({ msg: 'no device info' });
|
||||
return info;
|
||||
});
|
||||
},
|
||||
nativeAppGetSafeAreaInsets() {
|
||||
return call('getSafeAreaInsets').then((insets) => {
|
||||
if (!insets) return Promise.reject({ msg: 'no safe area' });
|
||||
return { status: 'success', top: insets.top, bottom: insets.bottom, data: insets };
|
||||
});
|
||||
},
|
||||
nativeAppIsWindowed() { return call('isWindowed').then((v) => !!v); },
|
||||
|
||||
// === 平台无关:纯前端语言映射(不走桥接) ===
|
||||
nativeAppConvertLanguage() {
|
||||
const specialMappings = {"zh": "zh-Hans", "zh-CHT": "zh-Hant"};
|
||||
return specialMappings[languageName] || languageName;
|
||||
},
|
||||
|
||||
// === sendMessage:拆解为独立 method ===
|
||||
// 旧 $A.nativeAppSendMessage({action:'xxx', ...}) 全部路由到对应桥接 method。
|
||||
nativeAppSendMessage(object) {
|
||||
if (!object || typeof object !== 'object') return;
|
||||
const action = object.action;
|
||||
const rest = Object.assign({}, object); delete rest.action;
|
||||
switch (action) {
|
||||
case 'updateTheme': return call('updateTheme', rest);
|
||||
case 'windowSize': return call('windowSize', rest);
|
||||
case 'setBadgeNum':
|
||||
case 'setBdageNotify': return call('setBadge', { count: parseInt(rest.bdage) || 0 });
|
||||
case 'setVibrate': return call('vibrate', { time: parseInt(rest.time) || 0 });
|
||||
case 'callTel': return call('callTel', { tel: rest.tel });
|
||||
case 'picturePreview': return call('picturePreview', rest);
|
||||
case 'videoPreview': return call('videoPreview', rest);
|
||||
case 'clearAllNotify': return call('clearAllNotify');
|
||||
case 'gotoSetting': return call('gotoNotificationSetting');
|
||||
case 'getNotificationPermission': return call('getNotificationPermission');
|
||||
case 'startMeeting': return call('startMeeting', rest);
|
||||
case 'updateMeetingInfo': return call('updateMeetingInfo', rest);
|
||||
// 推送注册:新链路 — 不再走 sendMessage,外层逻辑改用 registerPush;
|
||||
// 旧 action 静默忽略以兼容尚未迁移的调用点
|
||||
case 'initApp':
|
||||
case 'setUmengAlias':
|
||||
case 'delUmengAlias':
|
||||
return;
|
||||
default:
|
||||
// 未识别 action:调试时打日志,避免静默失败
|
||||
if (window.systemInfo && window.systemInfo.debug === 'yes') {
|
||||
console.warn('[nativeApp] unhandled sendMessage action:', action, rest);
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
window.$A = $;
|
||||
})(window);
|
||||
18
resources/assets/js/functions/web.js
vendored
18
resources/assets/js/functions/web.js
vendored
@ -881,7 +881,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
config.onCancel();
|
||||
}
|
||||
};
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
$A.Modal.confirm({
|
||||
render: (h) => {
|
||||
return h('div', [
|
||||
@ -958,7 +958,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
})
|
||||
}
|
||||
}
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
$A.Modal.confirm($A.modalConfig(config));
|
||||
},
|
||||
|
||||
@ -970,7 +970,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
setTimeout(() => { $A.modalSuccess(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
$A.Modal.success($A.modalConfig(config));
|
||||
},
|
||||
|
||||
@ -982,7 +982,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
setTimeout(() => { $A.modalInfo(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
$A.Modal.info($A.modalConfig(config));
|
||||
},
|
||||
|
||||
@ -997,7 +997,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
setTimeout(() => { $A.modalWarning(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
$A.Modal.warning($A.modalConfig(config));
|
||||
},
|
||||
|
||||
@ -1012,7 +1012,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
setTimeout(() => { $A.modalError(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
$A.Modal.error($A.modalConfig(config));
|
||||
},
|
||||
|
||||
@ -1020,7 +1020,7 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
if (msg === false) {
|
||||
return;
|
||||
}
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
alert($A.L(msg));
|
||||
},
|
||||
|
||||
@ -1273,8 +1273,8 @@ import {convertLocalResourcePath} from "../components/Replace/utils";
|
||||
|
||||
autoDarkMode() {
|
||||
let darkScheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
if ($A.isEEUIApp) {
|
||||
darkScheme = $A.eeuiAppGetThemeName() === "dark"
|
||||
if ($A.isMobileApp) {
|
||||
darkScheme = $A.nativeAppGetThemeName() === "dark"
|
||||
}
|
||||
if (darkScheme) {
|
||||
this.enableDarkMode()
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<div class="login-box">
|
||||
<div class="login-mode-switch">
|
||||
<div class="login-mode-switch-box">
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch" :content="$L(loginMode=='qrcode' ? '帐号登录' : '扫码登录')" placement="left">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch" :content="$L(loginMode=='qrcode' ? '帐号登录' : '扫码登录')" placement="left">
|
||||
<span class="login-mode-switch-icon no-dark-content" @click="switchLoginMode">
|
||||
<svg v-if="loginMode=='qrcode'" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-icon="PcOutlined"><path d="M23 16a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h18a2 2 0 0 1 2 2v12ZM21 4H3v9h18V4ZM3 15v1h18v-1H3Zm3 6a1 1 0 0 1 1-1h10a1 1 0 1 1 0 2H7a1 1 0 0 1-1-1Z" fill="currentColor"></path></svg>
|
||||
<svg v-else viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" data-icon="QrOutlined"><path d="M6.5 7.5a1 1 0 0 1 1-1h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1Z" fill="currentColor"></path><path d="M4.5 2.5c-1.1 0-2 .9-2 2v7c0 1.1.9 2 2 2h7c1.1 0 2-.9 2-2v-7c0-1.1-.9-2-2-2h-7Zm0 2h7v7h-7v-7ZM11 16a1 1 0 1 1 2 0 1 1 0 0 1-2 0Zm0 3.5a1 1 0 1 1 2 0v1a1 1 0 1 1-2 0v-1Zm4-7.5a1 1 0 1 1 2 0 1 1 0 0 1-2 0Zm3.5 0a1 1 0 0 1 1-1h1a1 1 0 1 1 0 2h-1a1 1 0 0 1-1-1ZM15 17c0-1.1.9-2 2-2h2.5c1.1 0 2 .9 2 2v2.5c0 1.1-.9 2-2 2H17c-1.1 0-2-.9-2-2V17Zm4.5 0H17v2.5h2.5V17Zm-15-2c-1.1 0-2 .9-2 2v2.5c0 1.1.9 2 2 2H7c1.1 0 2-.9 2-2V17c0-1.1-.9-2-2-2H4.5Zm0 2H7v2.5H4.5V17ZM15 4.5c0-1.1.9-2 2-2h2.5c1.1 0 2 .9 2 2V7c0 1.1-.9 2-2 2H17c-1.1 0-2-.9-2-2V4.5Zm4.5 0H17V7h2.5V4.5Z" fill="currentColor"></path></svg>
|
||||
@ -205,7 +205,7 @@ export default {
|
||||
},
|
||||
|
||||
async mounted() {
|
||||
this.privacyShow = !!this.$isEEUIApp && (await $A.IDBString("cachePrivacyShow")) !== "no";
|
||||
this.privacyShow = !!this.$isMobileApp && (await $A.IDBString("cachePrivacyShow")) !== "no";
|
||||
this.email = await $A.IDBString("cacheLoginEmail") || ''
|
||||
//
|
||||
if (this.$isSoftware) {
|
||||
@ -497,7 +497,7 @@ export default {
|
||||
this.chackServerUrl().catch(_ => {});
|
||||
$A.IDBSet("cachePrivacyShow", "no")
|
||||
} else {
|
||||
$A.eeuiAppGoDesktop()
|
||||
$A.nativeAppGoDesktop()
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@
|
||||
<Draggable
|
||||
:list="projectDraggableList"
|
||||
:animation="150"
|
||||
:disabled="$isEEUIApp || windowTouch || !!projectKeyValue || ownerProjectTabsVisible"
|
||||
:disabled="$isMobileApp || windowTouch || !!projectKeyValue || ownerProjectTabsVisible"
|
||||
tag="ul"
|
||||
item-key="id"
|
||||
draggable="li:not(.pinned)"
|
||||
@ -258,7 +258,7 @@
|
||||
<Loading v-if="projectKeyLoading > 0"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.nativeAppKeyboardHide">
|
||||
<Input type="search" v-model="projectKeyValue" :placeholder="$L(`共${projectTotal || cacheProjects.length}个项目,搜索...`)" clearable/>
|
||||
</Form>
|
||||
</div>
|
||||
@ -769,7 +769,7 @@ export default {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
showDownloadClient() {
|
||||
return !this.$Electron && !this.$isEEUIApp && !!this.clientDownloadUrl
|
||||
return !this.$Electron && !this.$isMobileApp && !!this.clientDownloadUrl
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1562,7 +1562,7 @@ export default {
|
||||
if (silence) {
|
||||
return; // 静默消息不通知
|
||||
}
|
||||
if (!this.natificationReady && !this.$isEEUIApp) {
|
||||
if (!this.natificationReady && !this.$isMobileApp) {
|
||||
return; // 通知未准备好不通知
|
||||
}
|
||||
if (this.windowActive && data.dialog_id === $A.last(this.dialogIns)?.dialog_id) {
|
||||
@ -1593,7 +1593,7 @@ export default {
|
||||
const notificationFuncB = (title, body, userimg) => {
|
||||
if (this.__notificationId === id) {
|
||||
this.__notificationId = null
|
||||
if (this.$isEEUIApp) {
|
||||
if (this.$isMobileApp) {
|
||||
emitter.emit('openMobileNotification', {
|
||||
userid: userid,
|
||||
title,
|
||||
|
||||
@ -552,7 +552,7 @@ export default {
|
||||
{value: "vote", label: "群投票", sort: 100},
|
||||
{value: "addProject", label: "创建项目", sort: 110},
|
||||
{value: "addTask", label: "添加任务", sort: 120},
|
||||
{value: "scan", label: "扫一扫", sort: 130, show: $A.isEEUIApp},
|
||||
{value: "scan", label: "扫一扫", sort: 130, show: $A.isMobileApp},
|
||||
|
||||
// 管理员应用
|
||||
{type: 'admin', value: "ldap", label: "LDAP", sort: 160, show: this.userIsAdmin},
|
||||
@ -1085,7 +1085,7 @@ export default {
|
||||
this.appPushShow = true;
|
||||
break;
|
||||
case 'scan':
|
||||
$A.eeuiAppScan(this.scanResult);
|
||||
$A.nativeAppScan(this.scanResult);
|
||||
break;
|
||||
case 'word-chain':
|
||||
case 'vote':
|
||||
|
||||
@ -79,24 +79,24 @@
|
||||
:visibleArrow="false"
|
||||
placement="top"
|
||||
popperClass="chat-input-emoji-popover">
|
||||
<ETooltip slot="reference" ref="emojiTip" :disabled="$isEEUIApp || windowTouch || showEmoji" placement="top" :enterable="false" :content="$L('表情')">
|
||||
<ETooltip slot="reference" ref="emojiTip" :disabled="$isMobileApp || windowTouch || showEmoji" placement="top" :enterable="false" :content="$L('表情')">
|
||||
<i class="taskfont"></i>
|
||||
</ETooltip>
|
||||
<ChatEmoji v-if="showEmoji" @on-select="onSelectEmoji" :searchKey="emojiQuickKey"/>
|
||||
</EPopover>
|
||||
<ETooltip v-else ref="emojiTip" :disabled="$isEEUIApp || windowTouch || showEmoji" placement="top" :enterable="false" :content="$L('表情')">
|
||||
<ETooltip v-else ref="emojiTip" :disabled="$isMobileApp || windowTouch || showEmoji" placement="top" :enterable="false" :content="$L('表情')">
|
||||
<i class="taskfont" @click="showEmoji=!showEmoji"></i>
|
||||
</ETooltip>
|
||||
</li>
|
||||
|
||||
<!-- @ # -->
|
||||
<li>
|
||||
<ETooltip placement="top" :disabled="$isEEUIApp || windowTouch" :enterable="false" :content="$L('选择成员')">
|
||||
<ETooltip placement="top" :disabled="$isMobileApp || windowTouch" :enterable="false" :content="$L('选择成员')">
|
||||
<i class="taskfont" @click="onToolbar('user')"></i>
|
||||
</ETooltip>
|
||||
</li>
|
||||
<li>
|
||||
<ETooltip placement="top" :disabled="$isEEUIApp || windowTouch" :enterable="false" :content="$L('选择任务')">
|
||||
<ETooltip placement="top" :disabled="$isMobileApp || windowTouch" :enterable="false" :content="$L('选择任务')">
|
||||
<i class="taskfont" @click="onToolbar('task')"></i>
|
||||
</ETooltip>
|
||||
</li>
|
||||
@ -109,7 +109,7 @@
|
||||
:visibleArrow="false"
|
||||
placement="top"
|
||||
popperClass="chat-input-more-popover">
|
||||
<ETooltip slot="reference" ref="moreTip" :disabled="$isEEUIApp || windowTouch || showMore" placement="top" :enterable="false" :content="$L('展开')">
|
||||
<ETooltip slot="reference" ref="moreTip" :disabled="$isMobileApp || windowTouch || showMore" placement="top" :enterable="false" :content="$L('展开')">
|
||||
<i class="taskfont"></i>
|
||||
</ETooltip>
|
||||
<template v-if="!isAiBot">
|
||||
@ -177,7 +177,7 @@
|
||||
trigger="manual"
|
||||
placement="top"
|
||||
popperClass="chat-input-more-popover">
|
||||
<ETooltip slot="reference" ref="sendTip" placement="top" :disabled="$isEEUIApp || windowTouch || showMenu" :enterable="false" :content="$L(sendContent)">
|
||||
<ETooltip slot="reference" ref="sendTip" placement="top" :disabled="$isMobileApp || windowTouch || showMenu" :enterable="false" :content="$L(sendContent)">
|
||||
<div v-if="loading">
|
||||
<div class="chat-load">
|
||||
<Loading/>
|
||||
@ -562,7 +562,7 @@ export default {
|
||||
}
|
||||
}, 1000)
|
||||
//
|
||||
if (this.$isEEUIApp) {
|
||||
if (this.$isMobileApp) {
|
||||
window.__onPermissionRequest = (type, result) => {
|
||||
if (type === 'recordAudio' && result === false) {
|
||||
// Android 录音权限被拒绝了
|
||||
@ -609,7 +609,7 @@ export default {
|
||||
...mapGetters(['getDialogDraft', 'getDialogQuote']),
|
||||
|
||||
isEnterSend({cacheKeyboard}) {
|
||||
if (this.$isEEUIApp) {
|
||||
if (this.$isMobileApp) {
|
||||
return cacheKeyboard.send_button_app === 'enter';
|
||||
} else {
|
||||
return cacheKeyboard.send_button_desktop === 'enter';
|
||||
@ -624,7 +624,7 @@ export default {
|
||||
},
|
||||
|
||||
canCall() {
|
||||
return this.dialogData.type === 'user' && !this.dialogData.bot && this.$isEEUIApp
|
||||
return this.dialogData.type === 'user' && !this.dialogData.bot && this.$isMobileApp
|
||||
},
|
||||
|
||||
canAnon() {
|
||||
@ -838,7 +838,7 @@ export default {
|
||||
if (this.isAiBot) {
|
||||
return
|
||||
}
|
||||
$A.eeuiAppGetLatestPhoto().then(({thumbnail, original}) => {
|
||||
$A.nativeAppGetLatestPhoto().then(({thumbnail, original}) => {
|
||||
const size = Math.min(120, Math.max(100, this.$refs.moreFull.clientWidth));
|
||||
this.maybePhotoStyle = {
|
||||
width: size + 'px',
|
||||
@ -1038,7 +1038,7 @@ export default {
|
||||
},
|
||||
selectionPlugin: {
|
||||
onTextSelected: (selectedText) => {
|
||||
if (this.$isEEUIApp || this.windowTouch) {
|
||||
if (this.$isMobileApp || this.windowTouch) {
|
||||
return
|
||||
}
|
||||
this.selectedText = !!selectedText.trim()
|
||||
@ -1170,7 +1170,7 @@ export default {
|
||||
|
||||
// Set enterkeyhint
|
||||
this.$nextTick(_ => {
|
||||
if (this.$isEEUIApp && this.cacheKeyboard.send_button_app === 'enter') {
|
||||
if (this.$isMobileApp && this.cacheKeyboard.send_button_app === 'enter') {
|
||||
this.quill.root.setAttribute('enterkeyhint', 'send')
|
||||
}
|
||||
})
|
||||
|
||||
@ -94,7 +94,7 @@ export default {
|
||||
|
||||
show(v) {
|
||||
this.$store.state.dialogModalShow = v;
|
||||
$A.eeuiAppSetScrollDisabled(v && this.windowPortrait)
|
||||
$A.nativeAppSetScrollDisabled(v && this.windowPortrait)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -142,7 +142,7 @@
|
||||
<Loading v-if="searchLoad > 0"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.nativeAppKeyboardHide">
|
||||
<Input type="search" ref="searchInput" v-model="searchKey" :placeholder="$L('搜索消息')" @on-keyup="onSearchKeyup" clearable/>
|
||||
<div v-if="searchLoad === 0 && searchResult.length > 0" class="search-total">{{searchLocation}}/{{searchResult.length}}</div>
|
||||
</Form>
|
||||
@ -1892,7 +1892,7 @@ export default {
|
||||
}
|
||||
this.tempMsgs.push(tempMsg)
|
||||
//
|
||||
$A.eeuiAppUploadPhoto({
|
||||
$A.nativeAppUploadPhoto({
|
||||
url: $A.apiUrl('dialog/msg/sendfile'),
|
||||
data: {
|
||||
dialog_id: tempMsg.dialog_id,
|
||||
@ -2432,7 +2432,7 @@ export default {
|
||||
onTouchStart() {
|
||||
// Android 阻止长按反馈导致失去焦点页面抖动
|
||||
if (this.keyboardShow) {
|
||||
$A.eeuiAppSetDisabledUserLongClickSelect(500);
|
||||
$A.nativeAppSetDisabledUserLongClickSelect(500);
|
||||
}
|
||||
},
|
||||
|
||||
@ -2600,7 +2600,7 @@ export default {
|
||||
spinner: 600,
|
||||
}).then(({data}) => {
|
||||
if (data.tel) {
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'callTel',
|
||||
tel: data.tel
|
||||
});
|
||||
@ -3547,7 +3547,7 @@ export default {
|
||||
const {file_uid, file_method} = this.operateItem
|
||||
if (file_method === "photo") {
|
||||
try {
|
||||
await $A.eeuiAppCancelUploadPhoto(file_uid)
|
||||
await $A.nativeAppCancelUploadPhoto(file_uid)
|
||||
} catch (e) {
|
||||
// 取消失败
|
||||
}
|
||||
@ -3932,7 +3932,7 @@ export default {
|
||||
title,
|
||||
titleFixed: true,
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: title,
|
||||
@ -4567,7 +4567,7 @@ export default {
|
||||
|
||||
autoScrollInto() {
|
||||
return this.location === "modal"
|
||||
&& this.$isEEUIApp
|
||||
&& this.$isMobileApp
|
||||
&& this.windowPortrait
|
||||
&& this.$refs.input?.isFocus
|
||||
},
|
||||
|
||||
@ -55,14 +55,14 @@
|
||||
</Dropdown>
|
||||
<template v-if="!file.only_view">
|
||||
<div class="header-icons">
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch" :content="$L('文件链接')">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch" :content="$L('文件链接')">
|
||||
<div class="header-icon" @click="handleClick('link')"><i class="taskfont"></i></div>
|
||||
</ETooltip>
|
||||
<EPopover v-model="historyShow" trigger="click">
|
||||
<div class="file-content-history">
|
||||
<FileHistory :value="historyShow" :file="file" @on-restore="onRestoreHistory"/>
|
||||
</div>
|
||||
<ETooltip slot="reference" ref="historyTip" :disabled="$isEEUIApp || windowTouch || historyShow" :content="$L('历史版本')">
|
||||
<ETooltip slot="reference" ref="historyTip" :disabled="$isMobileApp || windowTouch || historyShow" :content="$L('历史版本')">
|
||||
<div class="header-icon"><i class="taskfont"></i></div>
|
||||
</ETooltip>
|
||||
</EPopover>
|
||||
|
||||
@ -187,7 +187,7 @@ export default {
|
||||
title,
|
||||
titleFixed: true,
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: title,
|
||||
|
||||
@ -298,7 +298,7 @@ export default {
|
||||
async onOpen(isDirect = false) {
|
||||
// 判断是否在会议中
|
||||
let isMeeting = false;
|
||||
if ($A.isEEUIApp) {
|
||||
if ($A.isMobileApp) {
|
||||
isMeeting = this.appMeetingShow;
|
||||
} else if ($A.Electron) {
|
||||
const meetingWindow = await $A.Electron.sendAsync("getChildWindow", 'meeting-window')
|
||||
@ -349,7 +349,7 @@ export default {
|
||||
delete data.name;
|
||||
delete data.msgs;
|
||||
// App 直接使用新窗口打开会议
|
||||
if ($A.isEEUIApp) {
|
||||
if ($A.isMobileApp) {
|
||||
loader(true);
|
||||
this.loadNum = 0
|
||||
this.loadTimer && clearInterval(this.loadTimer)
|
||||
@ -360,7 +360,7 @@ export default {
|
||||
clearInterval(this.loadTimer)
|
||||
loader(false)
|
||||
}, 1000)
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'startMeeting',
|
||||
meetingParams: {
|
||||
name: this.addData.name,
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div :id="id" class="player">
|
||||
<div class="player-bg" :style="playerStyle"></div>
|
||||
</div>
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch || !username">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch || !username">
|
||||
<div slot="content">
|
||||
{{username}}
|
||||
</div>
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<Loading v-if="loadProjects > 0"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.nativeAppKeyboardHide">
|
||||
<Input type="search" v-model="projectKeyValue" :placeholder="$L(loadProjects > 0 ? '更新中...' : '搜索')" clearable/>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
@ -224,7 +224,7 @@ export default {
|
||||
path: path,
|
||||
title: this.$L(title),
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
e.preventDefault()
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
</li>
|
||||
<template v-if="!(windowWidth <= 980 || projectData.cacheParameter.chat) && projectUser.length > 0" v-for="item in projectUser">
|
||||
<li v-if="item.userid === -1" class="more">
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch" :content="$L('共' + (projectData.project_user.length) + '个成员')">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch" :content="$L('共' + (projectData.project_user.length) + '个成员')">
|
||||
<Icon type="ios-more"/>
|
||||
</ETooltip>
|
||||
</li>
|
||||
@ -33,7 +33,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
<li v-if="!projectData.department_readonly" class="project-icon" @click="addTaskOpen(0)">
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch" :content="$L('添加任务')">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch" :content="$L('添加任务')">
|
||||
<Icon class="menu-icon" type="md-add" />
|
||||
</ETooltip>
|
||||
</li>
|
||||
@ -121,7 +121,7 @@
|
||||
<Draggable
|
||||
:list="columnList"
|
||||
:animation="150"
|
||||
:disabled="sortDisabled || isDepartmentReadonly || $isEEUIApp || windowTouch"
|
||||
:disabled="sortDisabled || isDepartmentReadonly || $isMobileApp || windowTouch"
|
||||
class="column-list"
|
||||
tag="ul"
|
||||
draggable=".column-item"
|
||||
@ -193,7 +193,7 @@
|
||||
<Draggable
|
||||
:list="column.tasks"
|
||||
:animation="150"
|
||||
:disabled="sortDisabled || isDepartmentReadonly || $isEEUIApp || windowTouch"
|
||||
:disabled="sortDisabled || isDepartmentReadonly || $isMobileApp || windowTouch"
|
||||
class="task-list"
|
||||
draggable=".task-draggable"
|
||||
filter=".complete"
|
||||
@ -240,7 +240,7 @@
|
||||
<ETooltip
|
||||
v-if="item.end_at"
|
||||
:class="['task-time', item.today ? 'today' : '', item.overdue ? 'overdue' : '']"
|
||||
:disabled="$isEEUIApp || windowTouch"
|
||||
:disabled="$isMobileApp || windowTouch"
|
||||
:open-delay="600"
|
||||
:content="item.end_at">
|
||||
<div v-if="!item.complete_at"><i class="taskfont"></i>{{ expiresFormat(item.end_at) }}</div>
|
||||
|
||||
@ -103,7 +103,7 @@
|
||||
<Draggable
|
||||
:list="data.project_flow_item"
|
||||
:animation="150"
|
||||
:disabled="$isEEUIApp || windowTouch"
|
||||
:disabled="$isMobileApp || windowTouch"
|
||||
class="taskflow-config-table-list-wrapper"
|
||||
tag="div"
|
||||
draggable=".column-border"
|
||||
|
||||
@ -13,13 +13,13 @@
|
||||
<Radio label="daily" :disabled="id > 0 && reportData.type =='weekly'">{{ $L("日报") }}</Radio>
|
||||
</RadioGroup>
|
||||
<ButtonGroup v-if="id === 0" class="report-buttongroup">
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch" :content="prevCycleText" placement="bottom">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch" :content="prevCycleText" placement="bottom">
|
||||
<Button type="primary" @click="prevCycle">
|
||||
<Icon type="ios-arrow-back" />
|
||||
</Button>
|
||||
</ETooltip>
|
||||
<div class="report-buttongroup-vertical"></div>
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch || reportData.offset >= 0" :content="nextCycleText" placement="bottom">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch || reportData.offset >= 0" :content="nextCycleText" placement="bottom">
|
||||
<Button type="primary" @click="nextCycle" :disabled="reportData.offset >= 0">
|
||||
<Icon type="ios-arrow-forward" />
|
||||
</Button>
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
<Button @click="advanced=!advanced">{{$L('高级选项')}}</Button>
|
||||
<ul class="advanced-priority">
|
||||
<li v-for="(item, key) in taskPriority" :key="key">
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch" :content="taskPriorityContent(item)">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch" :content="taskPriorityContent(item)">
|
||||
<i
|
||||
class="taskfont"
|
||||
:style="{color:item.color}"
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<div v-if="parentId == 0" class="priority">
|
||||
<ul>
|
||||
<li v-for="(item, key) in taskPriority" :key="key">
|
||||
<ETooltip v-if="active" :disabled="$isEEUIApp || windowTouch" :content="taskPriorityContent(item)">
|
||||
<ETooltip v-if="active" :disabled="$isMobileApp || windowTouch" :content="taskPriorityContent(item)">
|
||||
<i
|
||||
class="taskfont"
|
||||
:style="{color:item.color}"
|
||||
@ -57,7 +57,7 @@
|
||||
<div class="priority">
|
||||
<ul>
|
||||
<li v-for="(item, key) in taskPriority" :key="key">
|
||||
<ETooltip v-if="active" :disabled="$isEEUIApp || windowTouch" :content="taskPriorityContent(item)">
|
||||
<ETooltip v-if="active" :disabled="$isMobileApp || windowTouch" :content="taskPriorityContent(item)">
|
||||
<i
|
||||
class="taskfont"
|
||||
:style="{color:item.color}"
|
||||
|
||||
@ -175,7 +175,7 @@ export default {
|
||||
title: title,
|
||||
titleFixed: true,
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: title,
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
<p v-if="taskDetail.id"><span>{{taskDetail.id}}</span></p>
|
||||
</div>
|
||||
<div class="function">
|
||||
<ETooltip v-if="$Electron" :disabled="$isEEUIApp || windowTouch" :content="$L('独立窗口显示')">
|
||||
<ETooltip v-if="$Electron" :disabled="$isMobileApp || windowTouch" :content="$L('独立窗口显示')">
|
||||
<i class="taskfont open" @click="openNewWin"></i>
|
||||
</ETooltip>
|
||||
<div v-if="!isDepartmentReadonly" class="menu">
|
||||
@ -289,7 +289,7 @@
|
||||
</div>
|
||||
<ul class="item-content loop">
|
||||
<li>
|
||||
<ETooltip :disabled="$isEEUIApp || windowTouch || !taskDetail.loop_at" :content="`${$L('下个周期')}: ${taskDetail.loop_at}`" placement="right">
|
||||
<ETooltip :disabled="$isMobileApp || windowTouch || !taskDetail.loop_at" :content="`${$L('下个周期')}: ${taskDetail.loop_at}`" placement="right">
|
||||
<span ref="loopText" @click="!isDepartmentReadonly && onLoop($event)">{{$L(loopLabel(taskDetail.loop))}}</span>
|
||||
</ETooltip>
|
||||
</li>
|
||||
@ -1046,7 +1046,7 @@ export default {
|
||||
this.ready = true;
|
||||
this.loadRelatedTasks();
|
||||
} else {
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
this.timeOpen = false;
|
||||
this.timeForce = false;
|
||||
this.loopForce = false;
|
||||
@ -1926,7 +1926,7 @@ export default {
|
||||
this.$store.dispatch('openDialog', dialogId).catch(({msg}) => {
|
||||
$A.modalError(msg);
|
||||
})
|
||||
$A.eeuiAppKeyboardHide();
|
||||
$A.nativeAppKeyboardHide();
|
||||
}
|
||||
},
|
||||
|
||||
@ -2085,7 +2085,7 @@ export default {
|
||||
title: `${file.name} (${$A.bytesToSize(file.size)})`,
|
||||
titleFixed: true,
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: `${file.name} (${$A.bytesToSize(file.size)})`,
|
||||
@ -2361,7 +2361,7 @@ export default {
|
||||
},
|
||||
|
||||
autoScrollInto() {
|
||||
return this.$isEEUIApp
|
||||
return this.$isMobileApp
|
||||
&& this.windowPortrait
|
||||
&& this.$refs.chatInput?.isFocus
|
||||
},
|
||||
|
||||
@ -41,7 +41,7 @@ export default {
|
||||
|
||||
watch: {
|
||||
show(v) {
|
||||
$A.eeuiAppSetScrollDisabled(v && this.windowPortrait)
|
||||
$A.nativeAppSetScrollDisabled(v && this.windowPortrait)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -94,7 +94,7 @@
|
||||
<ETooltip
|
||||
v-if="!item.complete_at && item.end_at"
|
||||
:class="['task-time', item.today ? 'today' : '', item.overdue ? 'overdue' : '']"
|
||||
:disabled="$isEEUIApp || windowTouch"
|
||||
:disabled="$isMobileApp || windowTouch"
|
||||
:open-delay="600"
|
||||
:content="item.end_at">
|
||||
<div @click="openTask(item)">{{expiresFormat(item.end_at)}}</div>
|
||||
|
||||
@ -451,8 +451,8 @@ export default {
|
||||
$A.modalConfirm({
|
||||
content: `是否拨打电话给 ${this.userData.nickname}?`,
|
||||
onOk: () => {
|
||||
if ($A.isEEUIApp()) {
|
||||
$A.eeuiAppSendMessage({
|
||||
if ($A.isMobileApp()) {
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'callTel',
|
||||
tel: this.userData.tel
|
||||
});
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
<i class="taskfont"></i>
|
||||
<em>{{item.sub_complete}}/{{item.sub_num}}</em>
|
||||
</div>
|
||||
<ETooltip v-if="item.end_at" :disabled="$isEEUIApp || windowTouch" :content="item.end_at" placement="right">
|
||||
<ETooltip v-if="item.end_at" :disabled="$isMobileApp || windowTouch" :content="item.end_at" placement="right">
|
||||
<div :class="['item-icon', item.today ? 'today' : '', item.overdue ? 'overdue' : '']">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{expiresFormat(item.end_at)}}</em>
|
||||
|
||||
@ -1010,7 +1010,7 @@ export default {
|
||||
fileShow(val) {
|
||||
if (!val) {
|
||||
this.browseFile(0)
|
||||
$A.eeuiAppKeyboardHide()
|
||||
$A.nativeAppKeyboardHide()
|
||||
}
|
||||
},
|
||||
|
||||
@ -1508,7 +1508,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
// 客户端打开独立窗口
|
||||
if (this.$Electron || this.$isEEUIApp) {
|
||||
if (this.$Electron || this.$isMobileApp) {
|
||||
this.openFileSingle(item);
|
||||
return;
|
||||
}
|
||||
@ -1526,7 +1526,7 @@ export default {
|
||||
title: $A.getFileName(item),
|
||||
titleFixed: true,
|
||||
});
|
||||
} else if (this.$isEEUIApp) {
|
||||
} else if (this.$isMobileApp) {
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: $A.getFileName(item),
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<Loading v-if="searchLoading"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.eeuiAppKeyboardHide">
|
||||
<Form class="search-form" action="javascript:void(0)" @submit.native.prevent="$A.nativeAppKeyboardHide">
|
||||
<Input
|
||||
v-if="tabActive==='dialog'"
|
||||
type="search"
|
||||
@ -60,7 +60,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="$isEEUIApp && !appNotificationPermission" class="messenger-notify-permission" @click="onOpenAppSetting">
|
||||
<div v-if="$isMobileApp && !appNotificationPermission" class="messenger-notify-permission" @click="onOpenAppSetting">
|
||||
{{$L('未开启通知权限')}}<i class="taskfont"></i>
|
||||
</div>
|
||||
<Scrollbar
|
||||
@ -356,8 +356,8 @@ export default {
|
||||
//
|
||||
this.$nextTick(_ => this.activeNum++)
|
||||
//
|
||||
if ($A.isEEUIApp) {
|
||||
$A.eeuiAppSendMessage({action: 'getNotificationPermission'});
|
||||
if ($A.isMobileApp) {
|
||||
$A.nativeAppSendMessage({action: 'getNotificationPermission'});
|
||||
}
|
||||
},
|
||||
|
||||
@ -1243,7 +1243,7 @@ export default {
|
||||
},
|
||||
|
||||
onOpenAppSetting() {
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'gotoSetting',
|
||||
});
|
||||
},
|
||||
|
||||
@ -140,7 +140,7 @@ export default {
|
||||
* 唤醒APP
|
||||
*/
|
||||
wakeApp() {
|
||||
if (!$A.Electron && !$A.isEEUIApp && navigator.userAgent.indexOf("MicroMessenger") === -1) {
|
||||
if (!$A.Electron && !$A.isMobileApp && navigator.userAgent.indexOf("MicroMessenger") === -1) {
|
||||
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
|
||||
try {
|
||||
if (/Android/i.test(navigator.userAgent)) {
|
||||
|
||||
@ -113,7 +113,7 @@
|
||||
<Radio label="close">{{$L('关闭')}}</Radio>
|
||||
</RadioGroup>
|
||||
<div class="form-tip">{{$L('任务完成后自动归档。')}}</div>
|
||||
<ETooltip v-if="formDatum.auto_archived=='open'" placement="right" :disabled="$isEEUIApp || windowTouch">
|
||||
<ETooltip v-if="formDatum.auto_archived=='open'" placement="right" :disabled="$isMobileApp || windowTouch">
|
||||
<div class="setting-auto-day">
|
||||
<Input v-model="formDatum.archived_day" type="number">
|
||||
<span slot="append">{{$L('天')}}</span>
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<transition :name="$isEEUIApp ? 'mobile-dialog' : 'none'">
|
||||
<transition :name="$isMobileApp ? 'mobile-dialog' : 'none'">
|
||||
<div v-if="showContent" class="setting-content">
|
||||
<MobileNavTitle :title="settingTitleName"/>
|
||||
<div class="setting-content-title">{{titleNameRoute}}</div>
|
||||
@ -62,8 +62,8 @@ export default {
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.$isEEUIApp) {
|
||||
this.clientVersion = `${window.systemInfo.version} (${$A.eeuiAppLocalVersion()})`
|
||||
if (this.$isMobileApp) {
|
||||
this.clientVersion = `${window.systemInfo.version} (${$A.nativeAppLocalVersion()})`
|
||||
}
|
||||
},
|
||||
|
||||
@ -87,11 +87,11 @@ export default {
|
||||
{path: 'theme', name: '主题设置'},
|
||||
]
|
||||
|
||||
if (this.$Electron || this.$isEEUIApp) {
|
||||
if (this.$Electron || this.$isMobileApp) {
|
||||
menu.push({path: 'keyboard', name: '键盘设置'})
|
||||
}
|
||||
|
||||
if ($A.isDooServer() && this.$isEEUIApp) {
|
||||
if ($A.isDooServer() && this.$isMobileApp) {
|
||||
menu.push(...[
|
||||
{path: 'privacy', name: '隐私政策', divided: true},
|
||||
{path: 'delete', name: '删除帐号'},
|
||||
@ -198,7 +198,7 @@ export default {
|
||||
|
||||
openPrivacy() {
|
||||
const url = $A.apiUrl('privacy')
|
||||
if (this.$isEEUIApp) {
|
||||
if (this.$isMobileApp) {
|
||||
this.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: ' ',
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
</div>
|
||||
</FormItem>
|
||||
</template>
|
||||
<FormItem v-if="$isEEUIApp" :label="$L('发送按钮')">
|
||||
<FormItem v-if="$isMobileApp" :label="$L('发送按钮')">
|
||||
<RadioGroup v-model="formData.send_button_app">
|
||||
<Radio label="button">{{$L('开启')}}</Radio>
|
||||
<Radio label="enter">{{$L('关闭')}}</Radio>
|
||||
|
||||
334
resources/assets/js/pages/share.vue
Normal file
334
resources/assets/js/pages/share.vue
Normal file
@ -0,0 +1,334 @@
|
||||
<template>
|
||||
<div class="page-share">
|
||||
<div class="share-header">
|
||||
<div class="share-cancel" @click="onCancel">{{ $L('取消') }}</div>
|
||||
<div class="share-title">{{ $L('发送给') }}</div>
|
||||
<div class="share-action" @click="onSend" :class="{ disabled: !canSend }">
|
||||
{{ sendingState || $L('发送') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="loading" class="share-loading">
|
||||
<Loading :content="$L('加载中')"/>
|
||||
</div>
|
||||
|
||||
<div v-else-if="errorMessage" class="share-error">
|
||||
<p>{{ errorMessage }}</p>
|
||||
<Button @click="onCancel">{{ $L('返回') }}</Button>
|
||||
</div>
|
||||
|
||||
<template v-else>
|
||||
<div class="share-preview">
|
||||
<div v-if="payload.text" class="share-preview-text">{{ payload.text }}</div>
|
||||
<div v-if="payload.url" class="share-preview-url">{{ payload.url }}</div>
|
||||
<div v-if="payload.items && payload.items.length" class="share-preview-items">
|
||||
<div
|
||||
v-for="(item, idx) in payload.items"
|
||||
:key="idx"
|
||||
class="share-preview-item"
|
||||
>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div class="meta">{{ formatSize(item.size) }} · {{ item.mime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="share-search">
|
||||
<Input
|
||||
v-model="keyword"
|
||||
:placeholder="$L('搜索会话')"
|
||||
clearable
|
||||
@on-change="loadList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="share-list">
|
||||
<div
|
||||
v-for="item in list"
|
||||
:key="item.name + '_' + (item.extend && item.extend.dialog_ids)"
|
||||
class="share-list-item"
|
||||
:class="{ selected: isSelected(item) }"
|
||||
@click="toggleSelect(item)"
|
||||
>
|
||||
<img class="icon" :src="item.icon" alt=""/>
|
||||
<div class="name">{{ item.name }}</div>
|
||||
<div v-if="isSelected(item)" class="check">✓</div>
|
||||
</div>
|
||||
<div v-if="!list.length" class="share-list-empty">{{ $L('暂无会话') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Loading from "../components/Loading.vue";
|
||||
|
||||
/**
|
||||
* 跨 App 分享接收页(二期 WS11)
|
||||
*
|
||||
* 流程:原生 (iOS Share Extension / Android Intent) 写共享 payload 到本地
|
||||
* → deep link `dootask://share?token=<x>` → __handleLink → 跳本页
|
||||
* → 调 $A.nativeAppGetSharedPayload(token) 拿元数据
|
||||
* → 拉 api/users/share/list 渲染会话/用户列表(type='text' 接口仅返回会话,简洁)
|
||||
* → 用户选会话 → POST api/dialog/msg/sendfiles 上传
|
||||
* → 调 $A.nativeAppClearSharedPayload(token) 清理 + 跳目标会话
|
||||
*/
|
||||
export default {
|
||||
name: "share",
|
||||
components: { Loading },
|
||||
data() {
|
||||
return {
|
||||
token: "",
|
||||
payload: { items: [], text: undefined, url: undefined },
|
||||
list: [],
|
||||
keyword: "",
|
||||
selectedIds: [],
|
||||
loading: true,
|
||||
errorMessage: "",
|
||||
sendingState: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
canSend() {
|
||||
if (!this.selectedIds.length) return false;
|
||||
const hasAttachment =
|
||||
(this.payload.items && this.payload.items.length > 0) ||
|
||||
this.payload.text ||
|
||||
this.payload.url;
|
||||
return !!hasAttachment && !this.sendingState;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.token = String(this.$route.query.token || "");
|
||||
if (!this.token) {
|
||||
this.errorMessage = this.$L("缺少分享凭据");
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
this.loadPayload();
|
||||
},
|
||||
methods: {
|
||||
async loadPayload() {
|
||||
try {
|
||||
const result = await this.callBridge("getSharedPayload", { token: this.token });
|
||||
if (!result) {
|
||||
this.errorMessage = this.$L("分享内容不存在或已过期");
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
this.payload = result;
|
||||
await this.loadList();
|
||||
} catch (e) {
|
||||
this.errorMessage = (e && e.message) || this.$L("加载失败");
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async loadList() {
|
||||
// type='text' 仅返回会话列表(无文件夹),用于普通会话分享场景;
|
||||
// 若用户希望分享到"文件"模块需用 type='file',二期暂不暴露切换。
|
||||
const params = { url: "users/share/list", data: { type: "text", key: this.keyword } };
|
||||
try {
|
||||
const { data } = await this.$store.dispatch("call", params);
|
||||
const lists = Array.isArray(data) ? data : (data && data.lists) || [];
|
||||
this.list = lists.filter(it => it.type === "item");
|
||||
} catch (e) {
|
||||
this.errorMessage = (e && e.msg) || this.$L("加载会话列表失败");
|
||||
}
|
||||
},
|
||||
isSelected(item) {
|
||||
const id = item.extend && item.extend.dialog_ids;
|
||||
return !!id && this.selectedIds.indexOf(id) !== -1;
|
||||
},
|
||||
toggleSelect(item) {
|
||||
const id = item.extend && item.extend.dialog_ids;
|
||||
if (!id) return;
|
||||
const idx = this.selectedIds.indexOf(id);
|
||||
if (idx === -1) this.selectedIds.push(id);
|
||||
else this.selectedIds.splice(idx, 1);
|
||||
},
|
||||
formatSize(bytes) {
|
||||
if (!bytes && bytes !== 0) return "";
|
||||
if (bytes < 1024) return bytes + " B";
|
||||
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
|
||||
return (bytes / (1024 * 1024)).toFixed(1) + " MB";
|
||||
},
|
||||
callBridge(method, args) {
|
||||
if (window.__nativeBridge && typeof window.__nativeBridge.call === "function") {
|
||||
return window.__nativeBridge.call(method, args);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
async onSend() {
|
||||
if (!this.canSend) return;
|
||||
const dialogIds = this.selectedIds.join(",");
|
||||
|
||||
try {
|
||||
if (this.payload.items && this.payload.items.length) {
|
||||
this.sendingState = this.$L("正在发送");
|
||||
for (const item of this.payload.items) {
|
||||
await this.uploadOne(dialogIds, item);
|
||||
}
|
||||
}
|
||||
// 文本/URL:拼成普通消息发到每个会话
|
||||
const extraText = [this.payload.text, this.payload.url].filter(Boolean).join("\n");
|
||||
if (extraText) {
|
||||
await this.$store.dispatch("call", {
|
||||
url: "dialog/msg/sendtext",
|
||||
method: "post",
|
||||
data: { dialog_ids: dialogIds, text: extraText, text_type: "text" },
|
||||
});
|
||||
}
|
||||
|
||||
// 清理共享文件
|
||||
await this.callBridge("clearSharedPayload", { token: this.token });
|
||||
|
||||
// 跳到第一个目标会话
|
||||
this.$store.state.dialogId = this.selectedIds[0];
|
||||
this.$router.replace({ name: "manage-messenger" });
|
||||
} catch (e) {
|
||||
$A.modalError({ content: (e && e.msg) || this.$L("发送失败") });
|
||||
this.sendingState = "";
|
||||
}
|
||||
},
|
||||
async uploadOne(dialogIds, item) {
|
||||
// file:// uri → Blob → multipart upload
|
||||
const res = await fetch(item.uri);
|
||||
const blob = await res.blob();
|
||||
const form = new FormData();
|
||||
form.append("dialog_ids", dialogIds);
|
||||
form.append("files", blob, item.name || "shared");
|
||||
await this.$store.dispatch("call", {
|
||||
url: "dialog/msg/sendfiles",
|
||||
method: "post",
|
||||
data: form,
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
},
|
||||
async onCancel() {
|
||||
if (this.token) {
|
||||
try { await this.callBridge("clearSharedPayload", { token: this.token }); } catch (e) { /* ignore */ }
|
||||
}
|
||||
this.$router.replace({ name: "index" });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-share {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--ee-bg-color, #f7f8fa);
|
||||
|
||||
.share-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
|
||||
.share-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.share-cancel,
|
||||
.share-action {
|
||||
font-size: 14px;
|
||||
color: #1890ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.share-action.disabled {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.share-loading,
|
||||
.share-error {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.share-preview {
|
||||
background: #fff;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
|
||||
.share-preview-text,
|
||||
.share-preview-url {
|
||||
padding: 8px 0;
|
||||
font-size: 14px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.share-preview-url { color: #1890ff; }
|
||||
|
||||
.share-preview-items {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
.share-preview-item {
|
||||
padding: 6px 8px;
|
||||
background: #f0f2f5;
|
||||
border-radius: 4px;
|
||||
.name { font-size: 13px; }
|
||||
.meta { font-size: 11px; color: #8c8c8c; margin-top: 2px; }
|
||||
}
|
||||
}
|
||||
|
||||
.share-search {
|
||||
padding: 8px 12px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #eaecef;
|
||||
}
|
||||
|
||||
.share-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
background: #fff;
|
||||
|
||||
.share-list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid #f0f2f5;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected { background: #e6f7ff; }
|
||||
|
||||
.icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 18px;
|
||||
margin-right: 12px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.name {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
.check {
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
.share-list-empty {
|
||||
padding: 32px;
|
||||
text-align: center;
|
||||
color: #8c8c8c;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -3,7 +3,7 @@
|
||||
<PageTitle :title="pageName"/>
|
||||
<Loading v-if="loadIng > 0"/>
|
||||
<template v-else-if="fileInfo">
|
||||
<FilePreview v-if="isPreview" :code="code" :file="fileInfo" :historyId="historyId" :headerShow="!$isEEUIApp"/>
|
||||
<FilePreview v-if="isPreview" :code="code" :file="fileInfo" :historyId="historyId" :headerShow="!$isMobileApp"/>
|
||||
<FileContent v-else v-model="fileShow" :file="fileInfo"/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@ -35,7 +35,7 @@ export default {
|
||||
return {
|
||||
loadIng: 0,
|
||||
info: null,
|
||||
showHeader: !$A.isEEUIApp,
|
||||
showHeader: !$A.isMobileApp,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
5
resources/assets/js/routes.js
vendored
5
resources/assets/js/routes.js
vendored
@ -14,6 +14,11 @@ export default [
|
||||
path: '/meeting/:meetingId?/:sharekey?',
|
||||
component: () => import('./pages/meeting.vue'),
|
||||
},
|
||||
{
|
||||
name: 'share',
|
||||
path: '/share',
|
||||
component: () => import('./pages/share.vue'),
|
||||
},
|
||||
{
|
||||
name: 'manage',
|
||||
path: '/manage',
|
||||
|
||||
44
resources/assets/js/store/actions.js
vendored
44
resources/assets/js/store/actions.js
vendored
@ -35,7 +35,7 @@ export default {
|
||||
labelWidth: windowWidth > 576 ? 'auto' : '',
|
||||
}
|
||||
|
||||
$A.eeuiAppSendMessage({
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'windowSize',
|
||||
width: windowWidth,
|
||||
height: windowHeight,
|
||||
@ -48,10 +48,11 @@ export default {
|
||||
|
||||
window.addEventListener('message', ({data}) => {
|
||||
data = $A.jsonParse(data);
|
||||
if (data.action === 'eeuiAppSendMessage') {
|
||||
// 兼容:前端内部 iframe/postMessage 转 nativeAppSendMessage 的中转桥
|
||||
if (data.action === 'nativeAppSendMessage' || data.action === 'eeuiAppSendMessage') {
|
||||
const items = $A.isArray(data.data) ? data.data : [data.data];
|
||||
items.forEach(item => {
|
||||
$A.eeuiAppSendMessage(item);
|
||||
$A.nativeAppSendMessage(item);
|
||||
})
|
||||
}
|
||||
})
|
||||
@ -177,7 +178,7 @@ export default {
|
||||
if (!state.isFirstPage) {
|
||||
return resolve(null)
|
||||
}
|
||||
$A.eeuiAppGetSafeAreaInsets().then(async data => {
|
||||
$A.nativeAppGetSafeAreaInsets().then(async data => {
|
||||
data.top = data.top || state.safeAreaSize?.data?.top || 0
|
||||
data.bottom = data.bottom || state.safeAreaSize?.data?.bottom || 0
|
||||
const proportion = data.height / window.outerHeight
|
||||
@ -483,8 +484,8 @@ export default {
|
||||
action: 'createDownload',
|
||||
url
|
||||
});
|
||||
} else if ($A.isEEUIApp) {
|
||||
$A.eeuiAppOpenWeb(url);
|
||||
} else if ($A.isMobileApp) {
|
||||
$A.nativeAppOpenWeb(url);
|
||||
} else {
|
||||
window.open(url)
|
||||
}
|
||||
@ -557,7 +558,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
if (!$A.dark.utils.supportMode()) {
|
||||
if ($A.isEEUIApp) {
|
||||
if ($A.isMobileApp) {
|
||||
$A.modalWarning("仅Android设置支持主题功能");
|
||||
} else {
|
||||
$A.modalWarning("仅客户端或Chrome浏览器支持主题功能");
|
||||
@ -600,8 +601,8 @@ export default {
|
||||
state.themeName = $A.dark.isDarkEnabled() ? 'dark' : 'light'
|
||||
window.localStorage.setItem("__system:themeConf__", state.themeConf)
|
||||
//
|
||||
if ($A.isEEUIApp) {
|
||||
$A.eeuiAppSendMessage({
|
||||
if ($A.isMobileApp) {
|
||||
$A.nativeAppSendMessage({
|
||||
action: 'updateTheme',
|
||||
themeName: state.themeName,
|
||||
themeDefault: {
|
||||
@ -771,23 +772,14 @@ export default {
|
||||
state.userId = userInfo.userid;
|
||||
state.userToken = userInfo.token;
|
||||
state.userIsAdmin = $A.inArray('admin', userInfo.identity);
|
||||
if ($A.isSubElectron || ($A.isEEUIApp && !state.isFirstPage)) {
|
||||
if ($A.isSubElectron || ($A.isMobileApp && !state.isFirstPage)) {
|
||||
// 子窗口(Electron)、不是第一个页面(App) 不保存
|
||||
} else {
|
||||
await $A.IDBSet("userInfo", state.userInfo);
|
||||
}
|
||||
//
|
||||
$A.eeuiAppSendMessage({
|
||||
action: 'userChatList',
|
||||
language: $A.eeuiAppConvertLanguage(),
|
||||
url: $A.mainUrl('api/users/share/list') + `?token=${state.userToken}`
|
||||
});
|
||||
$A.eeuiAppSendMessage({
|
||||
action:"userUploadUrl",
|
||||
dirUrl: $A.mainUrl('api/file/content/upload') + `?token=${state.userToken}`,
|
||||
chatUrl: $A.mainUrl('api/dialog/msg/sendfiles') + `?token=${state.userToken}`,
|
||||
});
|
||||
//
|
||||
// 旧 EEUI 用 userChatList/userUploadUrl 把 share/list 和 sendfiles 接口
|
||||
// 通过 App Group 同步给 iOS Share Extension 内嵌 UI;新移动端 /share 路由
|
||||
// 由 WebView 内主前端直接调用接口,无需提前同步。
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
@ -1322,7 +1314,7 @@ export default {
|
||||
selectclose: "true",
|
||||
channel,
|
||||
}
|
||||
$A.eeuiAppSetVariate(`location::${channel}`, "");
|
||||
$A.nativeAppSetVariate(`location::${channel}`, "");
|
||||
const url = $A.urlAddParams(window.location.origin + '/tools/map/index.html', Object.assign(params, objects || {}))
|
||||
dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
@ -1335,9 +1327,9 @@ export default {
|
||||
},
|
||||
callback: ({status}) => {
|
||||
if (status === 'pause') {
|
||||
const data = $A.jsonParse($A.eeuiAppGetVariate(`location::${channel}`));
|
||||
const data = $A.jsonParse($A.nativeAppGetVariate(`location::${channel}`));
|
||||
if (data.point) {
|
||||
$A.eeuiAppSetVariate(`location::${channel}`, "");
|
||||
$A.nativeAppSetVariate(`location::${channel}`, "");
|
||||
if (data.distance > objects.radius) {
|
||||
$A.modalError(`你选择的位置「${data.title}」不在签到范围内`)
|
||||
return
|
||||
@ -1367,7 +1359,7 @@ export default {
|
||||
objects.params.showProgress = !isLocalHost(objects.params.url)
|
||||
}
|
||||
|
||||
$A.eeuiAppOpenPage(objects)
|
||||
$A.nativeAppOpenPage(objects)
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
2
resources/assets/js/utils/file.js
vendored
2
resources/assets/js/utils/file.js
vendored
@ -75,7 +75,7 @@ export function openFileInClient(vm, item, options = {}) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (vm.$isEEUIApp) {
|
||||
if (vm.$isMobileApp) {
|
||||
vm.$store.dispatch('openAppChildPage', {
|
||||
pageType: 'app',
|
||||
pageTitle: finalTitle,
|
||||
|
||||
4
resources/assets/js/utils/index.js
vendored
4
resources/assets/js/utils/index.js
vendored
@ -54,11 +54,11 @@ function __callData(key, requestData, state) {
|
||||
} else {
|
||||
deleted_id = []
|
||||
}
|
||||
if ($A.isEEUIApp) {
|
||||
if ($A.isMobileApp) {
|
||||
hasUpdate = state.isFirstPage
|
||||
}
|
||||
if (hasUpdate) {
|
||||
if ($A.isSubElectron || ($A.isEEUIApp && !state.isFirstPage)) {
|
||||
if ($A.isSubElectron || ($A.isMobileApp && !state.isFirstPage)) {
|
||||
// 子窗口(Electron)、不是第一个页面(App) 不保存
|
||||
} else {
|
||||
await $A.IDBSet("callAt", state.callAt)
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 97ac53c3a932041bb8d3fde41a5c6822fb2d95a0
|
||||
Subproject commit 41d9889b79a7aaab644e1f99c5b16b16ce286881
|
||||
78
types/dootask-globals.d.ts
vendored
78
types/dootask-globals.d.ts
vendored
@ -154,7 +154,7 @@ interface DooTaskGlobal {
|
||||
/** 是否 Electron 子窗口 */
|
||||
isSubElectron: boolean;
|
||||
/** 是否 EEUI App 环境 */
|
||||
isEEUIApp: boolean;
|
||||
isMobileApp: boolean;
|
||||
/** 是否 Electron 环境 */
|
||||
isElectron: boolean;
|
||||
/** 是否客户端软件环境(Electron 或 EEUI) */
|
||||
@ -574,81 +574,81 @@ interface DooTaskGlobal {
|
||||
/** 获取eeui模块(Promise) */
|
||||
eeuiModulePromise(name?: string): Promise<any>;
|
||||
/** 获取eeui版本号 */
|
||||
eeuiAppVersion(): string | undefined;
|
||||
nativeAppVersion(): string | undefined;
|
||||
/** 获取本地软件版本号 */
|
||||
eeuiAppLocalVersion(): string | undefined;
|
||||
nativeAppLocalVersion(): string | undefined;
|
||||
/** Alert 弹窗 */
|
||||
eeuiAppAlert(object: any, callback?: (result: any) => void): void;
|
||||
nativeAppAlert(object: any, callback?: (result: any) => void): void;
|
||||
/** Toast 提示 */
|
||||
eeuiAppToast(object: any): void;
|
||||
nativeAppToast(object: any): void;
|
||||
/** 相对地址基于当前地址补全 */
|
||||
eeuiAppRewriteUrl(val: string): string | undefined;
|
||||
nativeAppRewriteUrl(val: string): string | undefined;
|
||||
/** 获取页面信息 */
|
||||
eeuiAppGetPageInfo(pageName?: string): any;
|
||||
nativeAppGetPageInfo(pageName?: string): any;
|
||||
/** 打开app新页面 */
|
||||
eeuiAppOpenPage(object: Record<string, any>, callback?: (result: any) => void): void;
|
||||
nativeAppOpenPage(object: Record<string, any>, callback?: (result: any) => void): void;
|
||||
/** 使用系统浏览器打开网页 */
|
||||
eeuiAppOpenWeb(url: string): void;
|
||||
nativeAppOpenWeb(url: string): void;
|
||||
/** 拦截返回按键事件(仅支持android、iOS无效) */
|
||||
eeuiAppSetPageBackPressed(object: any, callback?: (result: any) => void): void;
|
||||
nativeAppSetPageBackPressed(object: any, callback?: (result: any) => void): void;
|
||||
/** 返回手机桌面 */
|
||||
eeuiAppGoDesktop(): void;
|
||||
nativeAppGoDesktop(): void;
|
||||
/** 打开屏幕常亮 */
|
||||
eeuiAppKeepScreenOn(): void;
|
||||
nativeAppKeepScreenOn(): void;
|
||||
/** 关闭屏幕常亮 */
|
||||
eeuiAppKeepScreenOff(): void;
|
||||
nativeAppKeepScreenOff(): void;
|
||||
/** 隐藏软键盘 */
|
||||
eeuiAppKeyboardHide(): void;
|
||||
nativeAppKeyboardHide(): void;
|
||||
/** 给app发送消息 */
|
||||
eeuiAppSendMessage(object: any): void;
|
||||
nativeAppSendMessage(object: any): void;
|
||||
/** 设置浏览器地址 */
|
||||
eeuiAppSetUrl(url: string): void;
|
||||
nativeAppSetUrl(url: string): void;
|
||||
/** 生成webview快照 */
|
||||
eeuiAppGetWebviewSnapshot(callback: (result: any) => void): void;
|
||||
nativeAppGetWebviewSnapshot(callback: (result: any) => void): void;
|
||||
/** 显示webview快照 */
|
||||
eeuiAppShowWebviewSnapshot(): void;
|
||||
nativeAppShowWebviewSnapshot(): void;
|
||||
/** 隐藏webview快照 */
|
||||
eeuiAppHideWebviewSnapshot(): void;
|
||||
nativeAppHideWebviewSnapshot(): void;
|
||||
/** 扫码(成功时回调扫码文本) */
|
||||
eeuiAppScan(callback: (text: string) => void): void;
|
||||
nativeAppScan(callback: (text: string) => void): void;
|
||||
/** 检查更新 */
|
||||
eeuiAppCheckUpdate(): void;
|
||||
nativeAppCheckUpdate(): void;
|
||||
/** 获取主题名称 light|dark */
|
||||
eeuiAppGetThemeName(): string | undefined;
|
||||
nativeAppGetThemeName(): string | undefined;
|
||||
/** 判断软键盘是否可见 */
|
||||
eeuiAppKeyboardStatus(): boolean | undefined;
|
||||
nativeAppKeyboardStatus(): boolean | undefined;
|
||||
/** 设置全局变量 */
|
||||
eeuiAppSetVariate(key: string, value: any): void;
|
||||
nativeAppSetVariate(key: string, value: any): void;
|
||||
/** 获取全局变量 */
|
||||
eeuiAppGetVariate(key: string, defaultVal?: any): any;
|
||||
nativeAppGetVariate(key: string, defaultVal?: any): any;
|
||||
/** 设置缓存数据 */
|
||||
eeuiAppSetCachesString(key: string, value: string, expired?: number): void;
|
||||
nativeAppSetCachesString(key: string, value: string, expired?: number): void;
|
||||
/** 获取缓存数据 */
|
||||
eeuiAppGetCachesString(key: string, defaultVal?: string): string | undefined;
|
||||
nativeAppGetCachesString(key: string, defaultVal?: string): string | undefined;
|
||||
/** 是否长按内容震动(仅支持android、iOS无效) */
|
||||
eeuiAppSetHapticBackEnabled(val: boolean): void;
|
||||
nativeAppSetHapticBackEnabled(val: boolean): void;
|
||||
/** 禁止长按选择(仅支持android、iOS无效;传毫秒数则临时禁止) */
|
||||
eeuiAppSetDisabledUserLongClickSelect(val: boolean | number | string): void;
|
||||
nativeAppSetDisabledUserLongClickSelect(val: boolean | number | string): void;
|
||||
/** 复制文本 */
|
||||
eeuiAppCopyText(text: string): void;
|
||||
nativeAppCopyText(text: string): void;
|
||||
/** 设置是否禁止滚动 */
|
||||
eeuiAppSetScrollDisabled(disabled: boolean): void;
|
||||
nativeAppSetScrollDisabled(disabled: boolean): void;
|
||||
/** 设置应用程序级别的摇动撤销(仅支持iOS、android无效) */
|
||||
eeuiAppShakeToEditEnabled(enabled: boolean): void;
|
||||
nativeAppShakeToEditEnabled(enabled: boolean): void;
|
||||
/** 获取最新一张照片 */
|
||||
eeuiAppGetLatestPhoto(expiration?: number, timeout?: number): Promise<any>;
|
||||
nativeAppGetLatestPhoto(expiration?: number, timeout?: number): Promise<any>;
|
||||
/** 上传照片(params 参数:{url,data,headers,path,fieldName,onReady?}) */
|
||||
eeuiAppUploadPhoto(params: Record<string, any>, timeout?: number): Promise<any>;
|
||||
nativeAppUploadPhoto(params: Record<string, any>, timeout?: number): Promise<any>;
|
||||
/** 取消上传照片 */
|
||||
eeuiAppCancelUploadPhoto(id: any): Promise<any>;
|
||||
nativeAppCancelUploadPhoto(id: any): Promise<any>;
|
||||
/** 获取导航栏和状态栏高度 */
|
||||
eeuiAppGetSafeAreaInsets(): Promise<any>;
|
||||
nativeAppGetSafeAreaInsets(): Promise<any>;
|
||||
/** 获取当前语言(zh -> zh-Hans 等映射) */
|
||||
eeuiAppConvertLanguage(): string;
|
||||
nativeAppConvertLanguage(): string;
|
||||
/** 获取设备信息 */
|
||||
eeuiAppGetDeviceInfo(): Promise<any>;
|
||||
nativeAppGetDeviceInfo(): Promise<any>;
|
||||
/** 判断是否窗口化 */
|
||||
eeuiAppIsWindowed(): Promise<boolean>;
|
||||
nativeAppIsWindowed(): Promise<boolean>;
|
||||
}
|
||||
|
||||
/** DooTask 全局工具对象(jQuery 实例 + $.extend 扩展方法) */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user