From eb7d70d6faa08fc0be8a933e09a5806d24719e8d Mon Sep 17 00:00:00 2001 From: EditorWang Date: Sun, 10 Oct 2021 18:54:01 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix(panel):=E4=BF=AE=E5=A4=8D=E4=BA=86bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/panel/index.ts | 7 ++ devui/panel/src/body/panel-body.tsx | 52 +++++++++++ devui/panel/src/foot/panel-foot.tsx | 14 +++ devui/panel/src/header/panel-header.tsx | 54 ++++++++++++ devui/panel/src/panel.scss | 12 +++ devui/panel/src/panel.tsx | 111 +++++------------------- devui/panel/src/panel.type.ts | 36 ++++++++ devui/panel/src/store/store.ts | 15 ++++ docs/components/panel/index.md | 7 +- 9 files changed, 215 insertions(+), 93 deletions(-) create mode 100644 devui/panel/src/body/panel-body.tsx create mode 100644 devui/panel/src/foot/panel-foot.tsx create mode 100644 devui/panel/src/header/panel-header.tsx create mode 100644 devui/panel/src/panel.type.ts create mode 100644 devui/panel/src/store/store.ts diff --git a/devui/panel/index.ts b/devui/panel/index.ts index fee0e61c..2fb985dd 100644 --- a/devui/panel/index.ts +++ b/devui/panel/index.ts @@ -1,8 +1,14 @@ import type { App } from 'vue' import Panel from './src/panel' +import PanelHeader from './src/header/panel-header'; +import PanelBody from './src/body/panel-body'; +import PanelFooter from './src/foot/panel-foot'; Panel.install = function(app: App) { app.component(Panel.name, Panel) + app.component(PanelHeader.name, PanelHeader); + app.component(PanelBody.name, PanelBody); + app.component(PanelFooter.name, PanelFooter); } export { Panel } @@ -14,3 +20,4 @@ export default { app.use(Panel as any) } } + diff --git a/devui/panel/src/body/panel-body.tsx b/devui/panel/src/body/panel-body.tsx new file mode 100644 index 00000000..d13c29f1 --- /dev/null +++ b/devui/panel/src/body/panel-body.tsx @@ -0,0 +1,52 @@ +import { defineComponent,ref,onMounted,Transition,inject } from 'vue'; +import { PanelProps } from '../panel.type'; +import Store from '../store/store'; + +export default defineComponent({ + name: 'DPanelBody', + props:PanelProps, + setup(props,ctx){ + const animationName = inject('showAnimation') ? 'devui-panel' : null; + const hasLeftPadding = !inject('hasLeftPadding') ? 'noLeftPadding' : null; + const keys = Object.keys(Store.state()); + const key = keys.pop(); + const isCollapsed = Store.state(); + const bodyEl = ref(); + onMounted(() => { + if(bodyEl.value) { + const dom = bodyEl.value; + if(isCollapsed[key]) + dom.style.height = `${dom.offsetHeight}px`; + } + }) + + const enter = (element: Element ) => { + const el = (element as HTMLElement); + el.style.height = ''; + const height = el.offsetHeight; + el.style.height = '0px'; + // 需要执行一次才会生效 + el.offsetHeight; + el.style.height = `${height}px`; + } + const leave = (element: Element) => { + const el = (element as HTMLElement); + el.style.height = '0px'; + } + + return () => { + return ( +
+ + {isCollapsed[key] === undefined || isCollapsed[key] ? +
+
+ {ctx.slots.default?.()} +
+
: null } +
+
+ ) + } + }, +}) \ No newline at end of file diff --git a/devui/panel/src/foot/panel-foot.tsx b/devui/panel/src/foot/panel-foot.tsx new file mode 100644 index 00000000..65d7a3ad --- /dev/null +++ b/devui/panel/src/foot/panel-foot.tsx @@ -0,0 +1,14 @@ +import {ref,defineComponent} from 'vue'; + +export default defineComponent({ + name: 'DPanelFooter', + setup(props,ctx){ + return () => { + const footerContent = (ctx.slots.default ? + : null); + return footerContent + } + } +}) \ No newline at end of file diff --git a/devui/panel/src/header/panel-header.tsx b/devui/panel/src/header/panel-header.tsx new file mode 100644 index 00000000..4a4f77f7 --- /dev/null +++ b/devui/panel/src/header/panel-header.tsx @@ -0,0 +1,54 @@ +import { defineComponent,ref,inject } from 'vue'; +import {PanelProps} from '../panel.type'; +import Store from '../store/store'; + +export default defineComponent({ + name: 'DPanelHeader', + props: PanelProps, + setup(props,ctx){ + const beforeToggle = inject('beforeToggle'); + const keys = Object.keys(Store.state()); + const key = keys.pop(); + const isCollapsed = ref(Store.state()[key]); + + const canToggle = (): Promise => { + let changeResult = Promise.resolve(true); + if(beforeToggle) { + const result = beforeToggle(isCollapsed); + if(typeof result !== undefined) { + if(result instanceof Promise) { + changeResult = result; + } else { + changeResult = Promise.resolve(result); + } + } + } + return changeResult; + } + + const toggleBody = (): void => { + canToggle().then((val) => { + if (!val){ + return; + } + if (isCollapsed.value !== undefined) { + Store.setData(`${key}`, !isCollapsed.value); + isCollapsed.value = !isCollapsed.value; + props.toggle?.(isCollapsed.value); + } + }) + + }; + return () => { + let header = null; + if (ctx.slots.default){ + header = ( +
+ {ctx.slots.default?.()} +
+ ) + } + return header + } + }, +}) \ No newline at end of file diff --git a/devui/panel/src/panel.scss b/devui/panel/src/panel.scss index 38be0fd2..ded182c5 100644 --- a/devui/panel/src/panel.scss +++ b/devui/panel/src/panel.scss @@ -13,6 +13,18 @@ } } + .noLeftPadding { + &.devui-panel-body-collapse { + &::before { + display: none; + } + + .d-panel-body { + border-left: none !important; + } + } + } + .devui-panel-body { display: flex; position: relative; diff --git a/devui/panel/src/panel.tsx b/devui/panel/src/panel.tsx index 12ccc03d..079a1de0 100644 --- a/devui/panel/src/panel.tsx +++ b/devui/panel/src/panel.tsx @@ -1,65 +1,19 @@ -import { defineComponent, ref, Transition, onMounted } from 'vue'; -import './panel.scss' - -export type PanelType = 'default' | 'primary' | 'success' | 'danger' | 'warning' | 'info'; +import { defineComponent, ref, Transition, onMounted, provide } from 'vue'; +import './panel.scss'; +import { PanelProps } from './panel.type'; +import Store from './store/store'; export default defineComponent({ name: 'DPanel', - props: { - type: { - type: String as () => PanelType, - default: 'default' - }, - cssClass: { - type: String, - default: '' - }, - isCollapsed: { - type: Boolean, - default: undefined - }, - beforeToggle: { - type: Function as unknown as () => (value: boolean) => boolean | Promise, - default: null - }, - toggle: { - type: Function as unknown as ()=> ((value: boolean) => void), - default: null - } - }, + props: PanelProps, setup(props, ctx) { - + provide('beforeToggle', props.beforeToggle); + provide('showAnimation', props.showAnimation); + provide('hasLeftPadding', props.hasLeftPadding); const isCollapsed = ref(props.isCollapsed); const bodyEl = ref(); - const canToggle = (): Promise => { - let changeResult = Promise.resolve(true); - if(props.beforeToggle) { - const result = props.beforeToggle(props.isCollapsed); - if(typeof result !== undefined) { - if(result instanceof Promise) { - changeResult = result; - } else { - changeResult = Promise.resolve(result); - } - } - } - return changeResult; - } - - const toggleBody = (): void => { - canToggle().then((val) => { - if (!val){ - return; - } - if (isCollapsed.value !== undefined) { - isCollapsed.value = !isCollapsed.value; - props.toggle?.(isCollapsed.value); - } - }) - } - onMounted(() => { if(bodyEl.value) { const dom = bodyEl.value; @@ -67,47 +21,26 @@ export default defineComponent({ dom.style.height = `${dom.offsetHeight}px`; } }) + const timeStamp = new Date().getTime().toString(); + Store.setData(`isCollapsed[${timeStamp}]`, isCollapsed.value); - const enter = (element: Element ) => { - const el = (element as HTMLElement); - el.style.height = ''; - const height = el.offsetHeight; - el.style.height = '0px'; - // 需要执行一次才会生效 - el.offsetHeight; - el.style.height = `${height}px`; - } - const leave = (element: Element) => { - const el = (element as HTMLElement); - el.style.height = '0px'; + + return () => { + return ( +
+ {ctx.slots.default()} +
+ ) } - + }, + render(){ + const {props,$slots} = this; return () => { - - const headerContent = (ctx.slots.header ? -
- { ctx.slots.header?.() } -
: null); - - const footerContent = (ctx.slots.footer ? - : null); - return (
- {headerContent} - - {isCollapsed.value === undefined || isCollapsed.value ? -
-
- { ctx.slots.body?.() } -
-
: null } -
- {footerContent} + {$slots.default()}
) } } -}) +}) \ No newline at end of file diff --git a/devui/panel/src/panel.type.ts b/devui/panel/src/panel.type.ts new file mode 100644 index 00000000..58a80760 --- /dev/null +++ b/devui/panel/src/panel.type.ts @@ -0,0 +1,36 @@ +import {ExtractPropTypes} from 'vue'; + +export type PanelType = 'default' | 'primary' | 'success' | 'danger' | 'warning' | 'info'; + +export const PanelProps = { + type: { + type: String as () => PanelType, + default: 'default' + }, + cssClass: { + type: String, + default: '' + }, + isCollapsed: { + type: Boolean, + default: undefined + }, + beforeToggle: { + type: Function as unknown as () => (value: boolean) => boolean | Promise, + default: null + }, + toggle: { + type: Function as unknown as ()=> ((value: boolean) => void), + default: null + }, + showAnimation: { + type: Boolean, + default: true, + }, + hasLeftPadding:{ + type: Boolean, + default: true, + } +} + +export type PanelPropsType = ExtractPropTypes; \ No newline at end of file diff --git a/devui/panel/src/store/store.ts b/devui/panel/src/store/store.ts new file mode 100644 index 00000000..9e989228 --- /dev/null +++ b/devui/panel/src/store/store.ts @@ -0,0 +1,15 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +import {ref,reactive} from 'vue'; + +export const option = reactive({}) + +class Store { + public static state() { + return option; + } + public static setData(key,value){ + option[key] = ref(value); + } +} + +export default Store \ No newline at end of file diff --git a/docs/components/panel/index.md b/docs/components/panel/index.md index 10c3ae76..942bb571 100644 --- a/docs/components/panel/index.md +++ b/docs/components/panel/index.md @@ -9,15 +9,15 @@ ### 基本用法
- + Panel with foldable - + This is body

- + Panel has no left padding @@ -32,7 +32,6 @@
- ```html
-- Gitee From 39fb60c8519759d6d71b69f6985a4739deb91266 Mon Sep 17 00:00:00 2001 From: EditorWang Date: Sun, 10 Oct 2021 20:01:04 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(panel):=E4=BF=AE=E6=94=B9=E4=BA=86?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=90=8D=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/panel/index.ts | 2 +- devui/panel/src/body/panel-body.tsx | 3 ++- .../src/foot/{panel-foot.tsx => panel-footer.tsx} | 0 devui/panel/src/panel.scss | 2 +- docs/components/panel/index.md | 10 ++++++++++ 5 files changed, 14 insertions(+), 3 deletions(-) rename devui/panel/src/foot/{panel-foot.tsx => panel-footer.tsx} (100%) diff --git a/devui/panel/index.ts b/devui/panel/index.ts index 2fb985dd..a2e8ecc5 100644 --- a/devui/panel/index.ts +++ b/devui/panel/index.ts @@ -2,7 +2,7 @@ import type { App } from 'vue' import Panel from './src/panel' import PanelHeader from './src/header/panel-header'; import PanelBody from './src/body/panel-body'; -import PanelFooter from './src/foot/panel-foot'; +import PanelFooter from './src/foot/panel-footer'; Panel.install = function(app: App) { app.component(Panel.name, Panel) diff --git a/devui/panel/src/body/panel-body.tsx b/devui/panel/src/body/panel-body.tsx index d13c29f1..4fc2a2a6 100644 --- a/devui/panel/src/body/panel-body.tsx +++ b/devui/panel/src/body/panel-body.tsx @@ -7,7 +7,8 @@ export default defineComponent({ props:PanelProps, setup(props,ctx){ const animationName = inject('showAnimation') ? 'devui-panel' : null; - const hasLeftPadding = !inject('hasLeftPadding') ? 'noLeftPadding' : null; + const hasLeftPadding = !inject('hasLeftPadding') ? 'no-left-padding' : null; + const keys = Object.keys(Store.state()); const key = keys.pop(); const isCollapsed = Store.state(); diff --git a/devui/panel/src/foot/panel-foot.tsx b/devui/panel/src/foot/panel-footer.tsx similarity index 100% rename from devui/panel/src/foot/panel-foot.tsx rename to devui/panel/src/foot/panel-footer.tsx diff --git a/devui/panel/src/panel.scss b/devui/panel/src/panel.scss index ded182c5..7a5d9a91 100644 --- a/devui/panel/src/panel.scss +++ b/devui/panel/src/panel.scss @@ -13,7 +13,7 @@ } } - .noLeftPadding { + .no-left-padding { &.devui-panel-body-collapse { &::before { display: none; diff --git a/docs/components/panel/index.md b/docs/components/panel/index.md index 942bb571..6a4cf0bb 100644 --- a/docs/components/panel/index.md +++ b/docs/components/panel/index.md @@ -71,3 +71,13 @@ export default defineComponent({ } }) + + +|参数| 类型| 默认| 说明| +|:-:|:-:|:-:|:-:| +|type| PanelType| 'default'| 可选,面板的类型| +|cssClass| string| --| 可选,自定义 class 名| +|isCollapsed| boolean| false| 可选,是否展开| +|hasLeftPadding| boolean| true| 可选,是否显示左侧填充| +|showAnimation| boolean| true| 可选,是否展示动画| +|beforeToggle| Function\|Promise\|Observable| --| 可选,面板折叠状态改变前的回调函数,返回 boolean 类型,返回 false 可以阻止面板改变折叠状态 根据条件阻止折叠| \ No newline at end of file -- Gitee From af2c0c07c1aad8409ffa6e4a4f8f5ec3eeb110f5 Mon Sep 17 00:00:00 2001 From: EditorWang Date: Sun, 10 Oct 2021 20:06:30 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(panel):=E4=BF=AE=E6=94=B9=E4=BA=86?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=90=8D=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/panel/src/body/panel-body.tsx | 4 ++-- devui/panel/src/panel.scss | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/devui/panel/src/body/panel-body.tsx b/devui/panel/src/body/panel-body.tsx index 4fc2a2a6..43454382 100644 --- a/devui/panel/src/body/panel-body.tsx +++ b/devui/panel/src/body/panel-body.tsx @@ -8,7 +8,7 @@ export default defineComponent({ setup(props,ctx){ const animationName = inject('showAnimation') ? 'devui-panel' : null; const hasLeftPadding = !inject('hasLeftPadding') ? 'no-left-padding' : null; - + const keys = Object.keys(Store.state()); const key = keys.pop(); const isCollapsed = Store.state(); @@ -41,7 +41,7 @@ export default defineComponent({ {isCollapsed[key] === undefined || isCollapsed[key] ?
-
+
{ctx.slots.default?.()}
: null } diff --git a/devui/panel/src/panel.scss b/devui/panel/src/panel.scss index 7a5d9a91..2cb1bb83 100644 --- a/devui/panel/src/panel.scss +++ b/devui/panel/src/panel.scss @@ -19,7 +19,7 @@ display: none; } - .d-panel-body { + .devui-panel-content { border-left: none !important; } } @@ -30,7 +30,7 @@ position: relative; border-top: 1px solid $devui-dividing-line; - .d-panel-body { + .devui-panel-content { line-height: 1.5; padding: 15px; background: $devui-base-bg; @@ -44,7 +44,7 @@ height: 100%; } - .d-panel-body { + .devui-panel-content { border-left: 2px solid $devui-dividing-line; } } @@ -74,7 +74,7 @@ } .devui-panel-body-collapse { - .d-panel-body { + .devui-panel-content { border-color: $devui-primary-line; } } @@ -87,7 +87,7 @@ } .devui-panel-body-collapse { - .d-panel-body { + .devui-panel-content { border-color: $devui-info-line; } } @@ -100,7 +100,7 @@ } .devui-panel-body-collapse { - .d-panel-body { + .devui-panel-content { border-color: $devui-success-line; } } @@ -113,7 +113,7 @@ } .devui-panel-body-collapse { - .d-panel-body { + .devui-panel-content { border-color: $devui-warning-line; } } @@ -126,7 +126,7 @@ } .devui-panel-body-collapse { - .d-panel-body { + .devui-panel-content { border-color: $devui-danger-line; } } -- Gitee From 919685d6b21c739ea453dff845c356e12f275f42 Mon Sep 17 00:00:00 2001 From: EditorWang Date: Mon, 11 Oct 2021 20:29:05 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/panel/src/body/panel-body.tsx | 6 +-- devui/panel/src/header/panel-header.tsx | 2 +- docs/components/panel/index.md | 49 +++---------------------- 3 files changed, 10 insertions(+), 47 deletions(-) diff --git a/devui/panel/src/body/panel-body.tsx b/devui/panel/src/body/panel-body.tsx index 43454382..84a64108 100644 --- a/devui/panel/src/body/panel-body.tsx +++ b/devui/panel/src/body/panel-body.tsx @@ -6,8 +6,8 @@ export default defineComponent({ name: 'DPanelBody', props:PanelProps, setup(props,ctx){ - const animationName = inject('showAnimation') ? 'devui-panel' : null; - const hasLeftPadding = !inject('hasLeftPadding') ? 'no-left-padding' : null; + const animationName = inject('showAnimation') ? 'devui-panel' : ''; + const hasLeftPadding = !inject('hasLeftPadding') ? 'no-left-padding' : ''; const keys = Object.keys(Store.state()); const key = keys.pop(); @@ -40,7 +40,7 @@ export default defineComponent({
{isCollapsed[key] === undefined || isCollapsed[key] ? -
+
{ctx.slots.default?.()}
diff --git a/devui/panel/src/header/panel-header.tsx b/devui/panel/src/header/panel-header.tsx index 4a4f77f7..93f70162 100644 --- a/devui/panel/src/header/panel-header.tsx +++ b/devui/panel/src/header/panel-header.tsx @@ -43,7 +43,7 @@ export default defineComponent({ let header = null; if (ctx.slots.default){ header = ( -
+
{ctx.slots.default?.()}
) diff --git a/docs/components/panel/index.md b/docs/components/panel/index.md index 6a4cf0bb..e25db707 100644 --- a/docs/components/panel/index.md +++ b/docs/components/panel/index.md @@ -7,12 +7,13 @@ 当页面内容需要进行分组显示时使用,一般包含头部、内容区域、底部三个部分。 ### 基本用法 +:::demo -
- +```vue + ``` - - +::: |参数| 类型| 默认| 说明| -- Gitee