From 5607aab900c3af70c7fb547a9aa774ed11dc36bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=94=BF=E6=9D=83?= <1978141412@qq.com> Date: Fri, 1 Nov 2024 19:57:39 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E8=A1=A8=E5=8D=95=E5=88=86?= =?UTF-8?q?=E9=A1=B5=E3=80=81=E9=9D=A2=E6=9D=BF=E5=88=86=E9=A1=B5=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0activeTab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../form-tab-panel/form-tab-panel.tsx | 27 +++++++++++- .../panel-tab-panel.controller.ts | 42 +++++++++++++++++++ .../panel-tab-panel.provider.ts | 5 ++- .../panel-tab-panel/panel-tab-panel.state.ts | 21 ++++++++++ .../panel-tab-panel/panel-tab-panel.tsx | 18 ++++++-- 5 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 src/panel-component/panel-tab-panel/panel-tab-panel.controller.ts create mode 100644 src/panel-component/panel-tab-panel/panel-tab-panel.state.ts diff --git a/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx b/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx index 89b80479c8..460177e243 100644 --- a/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx +++ b/src/control/form/form-detail/form-tab-panel/form-tab-panel.tsx @@ -2,7 +2,10 @@ import { defineComponent, PropType, VNode } from 'vue'; import { useController, useNamespace } from '@ibiz-template/vue3-util'; import './form-tab-panel.scss'; import { IDEFormTabPanel } from '@ibiz/model-core'; -import { FormTabPanelController } from '@ibiz-template/runtime'; +import { + FormTabPageController, + FormTabPanelController, +} from '@ibiz-template/runtime'; export const FormTabPanel = defineComponent({ name: 'IBizFormTabPanel', @@ -20,8 +23,27 @@ export const FormTabPanel = defineComponent({ const ns = useNamespace('form-tab-panel'); useController(props.controller); + const onTabClick = (args: { + name: string; + title: string; + event: MouseEvent; + disabled: boolean; + }) => { + const { name, event } = args; + props.controller.onTabChange(name); + + // 触发对应FormTabPage的点击事件 + const pageC = props.controller.form.details[ + name + ] as FormTabPageController; + if (pageC) { + pageC.onClick(event); + } + }; + return { ns, + onTabClick, }; }, render() { @@ -33,7 +55,8 @@ export const FormTabPanel = defineComponent({ this.ns.m(this.modelData.codeName), ...this.controller.containerClass, ]} - model-value={this.modelData.deformTabPages?.[0].id} + model-value={this.controller.state.activeTab} + onClickTab={this.onTabClick} > {defaultSlots.map(slot => { const props = slot.props as IData; diff --git a/src/panel-component/panel-tab-panel/panel-tab-panel.controller.ts b/src/panel-component/panel-tab-panel/panel-tab-panel.controller.ts new file mode 100644 index 0000000000..f0b489d159 --- /dev/null +++ b/src/panel-component/panel-tab-panel/panel-tab-panel.controller.ts @@ -0,0 +1,42 @@ +import { PanelItemController } from '@ibiz-template/runtime'; +import { IPanelTabPanel } from '@ibiz/model-core'; +import { PanelTabPanelState } from './panel-tab-panel.state'; + +export class PanelTabPanelController extends PanelItemController { + declare state: PanelTabPanelState; + + /** + * 新建状态 + * + * @author tony001 + * @date 2024-05-12 14:05:16 + * @protected + * @return {*} {PanelTabPanelState} + */ + protected createState(): PanelTabPanelState { + return new PanelTabPanelState(this.parent?.state); + } + + /** + * 初始化 + * + * @author tony001 + * @date 2024-05-12 14:05:51 + * @return {*} {Promise} + */ + async onInit(): Promise { + await super.onInit(); + this.state.activeTab = this.model.panelTabPages?.[0].id || ''; + } + + /** + * 分页点击切换处理 + * + * @author tony001 + * @date 2024-05-12 14:05:11 + * @param {string} tabId + */ + onTabChange(tabId: string): void { + this.state.activeTab = tabId; + } +} diff --git a/src/panel-component/panel-tab-panel/panel-tab-panel.provider.ts b/src/panel-component/panel-tab-panel/panel-tab-panel.provider.ts index 0936663d6b..c193bb5c1d 100644 --- a/src/panel-component/panel-tab-panel/panel-tab-panel.provider.ts +++ b/src/panel-component/panel-tab-panel/panel-tab-panel.provider.ts @@ -4,6 +4,7 @@ import { PanelItemController, } from '@ibiz-template/runtime'; import { IPanelItem } from '@ibiz/model-core'; +import { PanelTabPanelController } from './panel-tab-panel.controller'; /** * 面板分页面板适配器 @@ -19,8 +20,8 @@ export class PanelTabPanelProvider implements IPanelItemProvider { panelItem: IPanelItem, panel: PanelController, parent: PanelItemController | undefined, - ): Promise { - const c = new PanelItemController(panelItem, panel, parent); + ): Promise { + const c = new PanelTabPanelController(panelItem, panel, parent); await c.init(); return c; } diff --git a/src/panel-component/panel-tab-panel/panel-tab-panel.state.ts b/src/panel-component/panel-tab-panel/panel-tab-panel.state.ts new file mode 100644 index 0000000000..f96a6d7328 --- /dev/null +++ b/src/panel-component/panel-tab-panel/panel-tab-panel.state.ts @@ -0,0 +1,21 @@ +import { PanelItemState } from '@ibiz-template/runtime'; + +/** + * 分页面板状态 + * + * @author tony001 + * @date 2024-05-12 14:05:01 + * @export + * @class PanelTabPanelState + * @extends {PanelItemState} + */ +export class PanelTabPanelState extends PanelItemState { + /** + * 当前激活分页 + * + * @author tony001 + * @date 2024-05-12 14:05:36 + * @type {string} + */ + activeTab: string = ''; +} diff --git a/src/panel-component/panel-tab-panel/panel-tab-panel.tsx b/src/panel-component/panel-tab-panel/panel-tab-panel.tsx index b0feed487f..46d389e46f 100644 --- a/src/panel-component/panel-tab-panel/panel-tab-panel.tsx +++ b/src/panel-component/panel-tab-panel/panel-tab-panel.tsx @@ -1,7 +1,7 @@ import { useNamespace } from '@ibiz-template/vue3-util'; import { IPanelTabPanel } from '@ibiz/model-core'; import { computed, defineComponent, PropType, VNode } from 'vue'; -import { PanelItemController } from '@ibiz-template/runtime'; +import { PanelTabPanelController } from './panel-tab-panel.controller'; import './panel-tab-panel.scss'; export const PanelTabPanel = defineComponent({ @@ -12,7 +12,7 @@ export const PanelTabPanel = defineComponent({ required: true, }, controller: { - type: PanelItemController, + type: PanelTabPanelController, required: true, }, }, @@ -27,9 +27,20 @@ export const PanelTabPanel = defineComponent({ return result; }); + const onTabClick = (args: { + name: string; + title: string; + event: MouseEvent; + disabled: boolean; + }) => { + const { name } = args; + props.controller.onTabChange(name); + }; + return { ns, classArr, + onTabClick, }; }, render() { @@ -47,7 +58,8 @@ export const PanelTabPanel = defineComponent({ ...this.controller.containerClass, ]} lazy-render - model-value={this.modelData.panelTabPages?.[0].id} + model-value={this.controller.state.activeTab} + onClickTab={this.onTabClick} > {defaultSlots!.map(slot => { const props = slot.props as IData; -- Gitee From b40b5b444cb17b2baab3f6c811ac4252d9626dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=94=BF=E6=9D=83?= <1978141412@qq.com> Date: Fri, 1 Nov 2024 19:58:23 +0800 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E5=85=A8?= =?UTF-8?q?=E5=B1=8F=E6=A0=B7=E5=BC=8F=E4=B8=BAclass=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fullscreen-header/fullscreen-header.scss | 25 +++++++-- src/mob-app/App.scss | 7 ++- src/util/fullscreen/fullscreen-util.ts | 52 +++++++++++-------- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/common/fullscreen-header/fullscreen-header.scss b/src/common/fullscreen-header/fullscreen-header.scss index aee3fdae11..dc42aa6167 100644 --- a/src/common/fullscreen-header/fullscreen-header.scss +++ b/src/common/fullscreen-header/fullscreen-header.scss @@ -1,17 +1,36 @@ +$fullscreen-header: ( + height: rem(44px), + font-size: getCssVar(font-size, header, 5), + font-weight: getCssVar(font-weight, bold), +); + @include b('fullscreen-header'){ - height: getCssVar(spacing,extra,loose); + @include set-component-css-var('fullscreen-header', $fullscreen-header); + height: getCssVar(fullscreen-header, height); display: flex; justify-content: center; align-items: center; overflow: hidden; position: relative; + font-size: getCssVar(fullscreen-header, font-size); + font-weight: getCssVar(fullscreen-header, font-weight); @include e('close'){ position: absolute; right: getCssVar(spacing,extra,tight); - font-size: getCssVar(font-size,header-3); + font-size: getCssVar(font-size,header-1); height: 100%; display: flex; align-items: center; } - +} + + +@include b(full-screen) { + position: fixed; + top: 0; + left: 0; + height: 100vh; + width: 100vw; + // 移动端安全距离 + padding: var(--safe-area-inset-top) var(--safe-area-inset-right) var(--safe-area-inset-bottom) var(--safe-area-inset-left); } \ No newline at end of file diff --git a/src/mob-app/App.scss b/src/mob-app/App.scss index 4b8d52cb9c..b22e8273ae 100644 --- a/src/mob-app/App.scss +++ b/src/mob-app/App.scss @@ -1,7 +1,12 @@ #app { + --safe-area-inset-top: env(safe-area-inset-top); + --safe-area-inset-right: env(safe-area-inset-right); + --safe-area-inset-bottom: env(safe-area-inset-bottom); + --safe-area-inset-left: env(safe-area-inset-left); + width: 100vw; height: 100vh; background: getCssVar(color, bg, 0); // 移动端安全距离 - padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); + padding: var(--safe-area-inset-top) var(--safe-area-inset-right) var(--safe-area-inset-bottom) var(--safe-area-inset-left); } \ No newline at end of file diff --git a/src/util/fullscreen/fullscreen-util.ts b/src/util/fullscreen/fullscreen-util.ts index ebee995685..bb7ab715b0 100644 --- a/src/util/fullscreen/fullscreen-util.ts +++ b/src/util/fullscreen/fullscreen-util.ts @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { createApp } from 'vue'; +import { useNamespace } from '@ibiz-template/vue3-util'; import { IBizFullscreenHeader } from '../../common/fullscreen-header/fullscreen-header'; /** @@ -17,6 +18,13 @@ export class FullscreenUtil { */ constructor() {} + /** + * @description 全屏dom + * @type {(HTMLElement | null)} + * @memberof FullscreenUtil + */ + fullscreenElement: HTMLElement | null = null; + /** *是否全屏状态 * @@ -24,7 +32,7 @@ export class FullscreenUtil { * @memberof FullscreenUtil */ get isFullScreen() { - return !!document.fullscreenElement; + return !!this.fullscreenElement; } /** @@ -32,7 +40,7 @@ export class FullscreenUtil { * @author fzh * @date 2024-07-15 19:39:40 */ - public FullscreenClass: string = 'full-screen-class'; + public FullscreenClass: string = 'full-screen'; /** * 指定元素全屏 @@ -43,23 +51,21 @@ export class FullscreenUtil { if (data?.class) { this.FullscreenClass = data.class; } - if (!document.fullscreenElement && div) { + if (!this.isFullScreen && div) { + const ns = useNamespace(this.FullscreenClass); if (this.FullscreenClass) { - div.classList.add(this.FullscreenClass); + div.classList.add(ns.b()); } - // 通过传递参数决定是否绘制标题和关闭按钮 - if (data?.showClose || data?.srftitle) { - const content = document.createElement('div'); - content.id = 'fullscreen'; - const app = createApp(IBizFullscreenHeader, { - title: data?.srftitle, - }); - app.mount(content); - // 直接操作传进来的元素 - div.insertBefore(content, div.children[0]); - } - div.requestFullscreen(); + const content = document.createElement('div'); + content.classList.add(ns.e('header')); + const app = createApp(IBizFullscreenHeader, { + title: data?.srftitle, + }); + app.mount(content); + // 直接操作传进来的元素 + div.insertBefore(content, div.children[0]); + this.fullscreenElement = div; } } @@ -70,11 +76,15 @@ export class FullscreenUtil { */ public closeElementFullscreen(): void { // 退出前移除全屏元素的全屏样式 - document.fullscreenElement?.classList.remove(this.FullscreenClass); - const close = document.fullscreenElement?.querySelector('#fullscreen'); - if (close) { - close.remove(); + if (!this.fullscreenElement) { + return; + } + const ns = useNamespace(this.FullscreenClass); + this.fullscreenElement.classList.remove(ns.b()); + const header = this.fullscreenElement.querySelector(`.${ns.e('header')}`); + if (header) { + header.remove(); } - document.exitFullscreen(); + this.fullscreenElement = null; } } -- Gitee From 837c0e6c83259b6fe627b2b4935e9895ae8dce33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=94=BF=E6=9D=83?= <1978141412@qq.com> Date: Fri, 1 Nov 2024 19:59:07 +0800 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0ios=E6=90=AD?= =?UTF-8?q?=E8=BD=BD=E5=B9=B3=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ibiz-vue3.ts | 3 ++ src/mob-app/App.tsx | 2 ++ src/platform/index.ts | 1 + src/platform/ios-platform-provider.ts | 45 +++++++++++++++++++++++++++ 4 files changed, 51 insertions(+) create mode 100644 src/platform/ios-platform-provider.ts diff --git a/src/ibiz-vue3.ts b/src/ibiz-vue3.ts index 59b1b1f35c..e0434e5d06 100644 --- a/src/ibiz-vue3.ts +++ b/src/ibiz-vue3.ts @@ -36,6 +36,7 @@ import IBizPanelComponents from './panel-component'; import { VueBrowserPlatformProvider, DingTalkPlatformProvider, + IosPlatformProvider, } from './platform'; import { IBizPortalView } from './view/portal-view'; import { IBizViewEngine } from './view-engine'; @@ -48,6 +49,7 @@ export default { // vue 浏览器搭载平台 const browserPlatformProvider = new VueBrowserPlatformProvider(); const dingTalkPlatformProvider = new DingTalkPlatformProvider(); + const iosPlatformProvider = new IosPlatformProvider(); registerPlatformProvider( PlatformType.BROWSER, () => browserPlatformProvider, @@ -56,6 +58,7 @@ export default { PlatformType.DINGTALK, () => dingTalkPlatformProvider, ); + registerPlatformProvider(PlatformType.IOS, () => iosPlatformProvider); v.use(IBizCommonComponents); v.use(IBizViewEngine); diff --git a/src/mob-app/App.tsx b/src/mob-app/App.tsx index 4da0d8a0a7..bde985e130 100644 --- a/src/mob-app/App.tsx +++ b/src/mob-app/App.tsx @@ -12,6 +12,7 @@ export default defineComponent({ transitionName.value = type === 'push' ? 'forward' : 'back'; }; + ibiz.platform.init(); // 适配devtool const listenDevtool = async (e: KeyboardEvent): Promise => { if ((e.ctrlKey || e.metaKey) && e.code === 'F12') { @@ -33,6 +34,7 @@ export default defineComponent({ onUnmounted(() => { off('onBeforeStackChange', onViewStackChange); + ibiz.platform.onDestroyed(); }); const viewModals = new Map(); diff --git a/src/platform/index.ts b/src/platform/index.ts index cea95bb884..ab3701ae38 100644 --- a/src/platform/index.ts +++ b/src/platform/index.ts @@ -1,2 +1,3 @@ export { VueBrowserPlatformProvider } from './vue-browser-platform-provider'; export { DingTalkPlatformProvider } from './ding-talk-platform-provider'; +export { IosPlatformProvider } from './ios-platform-provider'; diff --git a/src/platform/ios-platform-provider.ts b/src/platform/ios-platform-provider.ts new file mode 100644 index 0000000000..7c54159b39 --- /dev/null +++ b/src/platform/ios-platform-provider.ts @@ -0,0 +1,45 @@ +import { listenJSEvent, NOOP } from '@ibiz-template/core'; +import { PlatformProviderBase } from '@ibiz-template/runtime'; + +/** + * @description ios搭载平台 + * @export + * @class IosPlatformProvider + * @extends {PlatformProviderBase} + */ +export class IosPlatformProvider extends PlatformProviderBase { + protected clean = NOOP; + + /** + * @description初始化 + * @return {*} {Promise} + * @memberof IosPlatformProvider + */ + async init(): Promise { + this.clean = listenJSEvent(window, 'load', () => { + const windowHeight = window.innerHeight; + const documentHeight = document.documentElement.scrollHeight; + if (documentHeight > windowHeight) { + // 存在安全距离 + const safeAreaBottom = documentHeight - windowHeight; + const root: HTMLElement | null = document.querySelector('#app'); + if (root) { + root.style.setProperty( + '--safe-area-inset-bottom', + `${safeAreaBottom}px`, + ); + } + } + }); + } + + /** + * @description 应用销毁 + * @memberof IosPlatformProvider + */ + onDestroyed(): void { + if (this.clean !== NOOP) { + this.clean(); + } + } +} -- Gitee From 24b93512d05969e7eb96ed0bb727bfb01270c175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=94=BF=E6=9D=83?= <1978141412@qq.com> Date: Fri, 1 Nov 2024 19:59:42 +0800 Subject: [PATCH 4/5] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8048f88ab..ccffa85649 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,9 @@ - 气泡工具栏样式调整 - markdown编辑器图片样式调整 - 通知消息样式调整,防止ios点击两次跳转 +- 表单分页、面板分页添加activeTab +- 调整全屏样式为class控制 +- 添加ios搭载平台 ### Fixed -- Gitee From 613ce2ef1ea1bd6af32fdee737e7fc2c6d9a338c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=94=BF=E6=9D=83?= <1978141412@qq.com> Date: Fri, 1 Nov 2024 20:06:22 +0800 Subject: [PATCH 5/5] =?UTF-8?q?feat:=20=E8=B0=83=E6=95=B4=E6=90=AD?= =?UTF-8?q?=E8=BD=BD=E5=B9=B3=E5=8F=B0=E9=94=80=E6=AF=81=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/platform/ios-platform-provider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/ios-platform-provider.ts b/src/platform/ios-platform-provider.ts index 7c54159b39..34ce8152b0 100644 --- a/src/platform/ios-platform-provider.ts +++ b/src/platform/ios-platform-provider.ts @@ -37,7 +37,7 @@ export class IosPlatformProvider extends PlatformProviderBase { * @description 应用销毁 * @memberof IosPlatformProvider */ - onDestroyed(): void { + async destroyed(): Promise { if (this.clean !== NOOP) { this.clean(); } -- Gitee