diff --git a/public/assets/img/today-new-student.png b/public/assets/img/today-new-student.png new file mode 100644 index 0000000000000000000000000000000000000000..1cc337a856e631dc0ed4faac4dd5baf345fd371d Binary files /dev/null and b/public/assets/img/today-new-student.png differ diff --git a/public/assets/img/year-month-target.png b/public/assets/img/year-month-target.png new file mode 100644 index 0000000000000000000000000000000000000000..edae361039779c9f00900977f619bacf3d76d9f0 Binary files /dev/null and b/public/assets/img/year-month-target.png differ diff --git a/public/assets/img/year-total.png b/public/assets/img/year-total.png new file mode 100644 index 0000000000000000000000000000000000000000..2d6e44cb0890da2f9e092360677280846cac5881 Binary files /dev/null and b/public/assets/img/year-total.png differ diff --git a/src/index.ts b/src/index.ts index ed6feadb85c1b1c7820be1bef9af70585ed76e1a..2d951ae27d9b861c7d151585c13569c477254e2c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,13 @@ import { App } from 'vue'; import { IBizDigitalFlop } from './digital-flop/index'; import { IBizScreenDashboard } from './screen-dashboard/index'; +import { IBizScreenPanelAttribute } from './screen-panel-attribute/index'; // 注入组件 export default { install(_app: App): void { _app.use(IBizDigitalFlop); _app.use(IBizScreenDashboard); + _app.use(IBizScreenPanelAttribute); }, }; diff --git a/src/screen-panel-attribute/global.ts b/src/screen-panel-attribute/global.ts new file mode 100644 index 0000000000000000000000000000000000000000..85e28ca32a7d8b00668214c43e1f4b506a870cc1 --- /dev/null +++ b/src/screen-panel-attribute/global.ts @@ -0,0 +1,8 @@ +// 文件路径: [插件项目的根目录]/src/global.ts + +// eslint-disable-next-line import/no-extraneous-dependencies +import { PluginStaticResource } from '@ibiz-template/runtime'; + +const resource = new PluginStaticResource(import.meta.url); + +export { resource }; diff --git a/src/screen-panel-attribute/index.ts b/src/screen-panel-attribute/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..4550a4dd6a0fdc24560a1ecee3faa47052170737 --- /dev/null +++ b/src/screen-panel-attribute/index.ts @@ -0,0 +1,17 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { withInstall } from '@ibiz-template/vue3-util'; +import { App } from 'vue'; +import { registerPanelItemProvider } from '@ibiz-template/runtime'; +import { ScreenPanelAttribute } from './screen-panel-attribute'; +import { ScreenPanelAttributeControllerProvider } from './screen-panel-attribute.provider'; + +export const IBizScreenPanelAttribute = withInstall( + ScreenPanelAttribute, + function (v: App) { + v.component(ScreenPanelAttribute.name, ScreenPanelAttribute); + registerPanelItemProvider( + 'EDITOR_CUSTOMSTYLE_SCREEN_PANEL_ATTRIBUTE', + () => new ScreenPanelAttributeControllerProvider(), + ); + }, +); diff --git a/src/screen-panel-attribute/screen-panel-attribute.controller.ts b/src/screen-panel-attribute/screen-panel-attribute.controller.ts new file mode 100644 index 0000000000000000000000000000000000000000..75894df00247dbb8e3f03e6f08f12b5be7a23eb4 --- /dev/null +++ b/src/screen-panel-attribute/screen-panel-attribute.controller.ts @@ -0,0 +1,67 @@ +import { IPanelRawItem } from '@ibiz/model-core'; + +// eslint-disable-next-line import/no-extraneous-dependencies +import { PanelItemController } from '@ibiz-template/runtime'; + +/** + * @description 大屏面板属性 + * @export + * @class DigitalFlopController + * @extends {EditorController} + */ +export class ScreenPanelAttributeController extends PanelItemController { + /** + * 展示模式 + * + * @author fangZhiHao + * @date 2024-08-07 15:08:14 + * @type {string} + */ + showModel: string = 'model1'; + + /** + * 单位 + * + * @author fangZhiHao + * @date 2024-08-07 14:08:14 + * @type {string} + */ + public unit: string = '个'; + + /** + * 标题位置 + * + * @author fangZhiHao + * @date 2024-08-07 14:08:38 + * @type {string} + */ + public labelPosition: string = 'bottom'; + + /** + * 初始化 + */ + protected async onInit(): Promise { + console.log('this.model', this.model); + if (this.model.rawItem) { + const { rawItemParams } = this.model.rawItem; + if (rawItemParams) { + const unitParams = rawItemParams.find(item => item.key === 'UNIT'); + if (unitParams && unitParams.value) { + this.unit = unitParams.value; + } + const labelPositionParams = rawItemParams.find( + item => item.key === 'LABELPOSITION', + ); + if (labelPositionParams && labelPositionParams.value) { + this.labelPosition = labelPositionParams.value; + } + const showModelParams = rawItemParams.find( + item => item.key === 'SHOWMODEL', + ); + if (showModelParams && showModelParams.value) { + this.showModel = showModelParams.value; + } + } + } + } +} diff --git a/src/screen-panel-attribute/screen-panel-attribute.provider.ts b/src/screen-panel-attribute/screen-panel-attribute.provider.ts new file mode 100644 index 0000000000000000000000000000000000000000..eae6076361ffc186185868e68be7824d38d18daf --- /dev/null +++ b/src/screen-panel-attribute/screen-panel-attribute.provider.ts @@ -0,0 +1,30 @@ +import { IPanelItem } from '@ibiz/model-core'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { + PanelController, + IPanelItemProvider, + PanelItemController, +} from '@ibiz-template/runtime'; +import { ScreenPanelAttributeController } from './screen-panel-attribute.controller'; + +/** + * @description 大屏面板属性 + * @export + * @class DigitalFlopControllerProvider + * @implements {IEditorProvider} + */ +export class ScreenPanelAttributeControllerProvider + implements IPanelItemProvider +{ + component: string = 'ScreenPanelAttribute'; + + async createController( + panelItem: IPanelItem, + panel: PanelController, + parent: PanelItemController | undefined, + ): Promise { + const c = new ScreenPanelAttributeController(panelItem, panel, parent); + await c.init(); + return c; + } +} diff --git a/src/screen-panel-attribute/screen-panel-attribute.scss b/src/screen-panel-attribute/screen-panel-attribute.scss new file mode 100644 index 0000000000000000000000000000000000000000..983255a8eec196c2f595b5501d1684755c582fc3 --- /dev/null +++ b/src/screen-panel-attribute/screen-panel-attribute.scss @@ -0,0 +1,308 @@ +$screen-panel-attribute: ( + 'min-height': 124px, + 'margin-top': 16px, + 'textvalue-top': 15%, + 'textvalue-left': 52%, + 'textvalue-transform': translateX(-50%), + 'textvalue-height': 100%, + 'textvalue-left-top': 0%, + 'textvalue-left-margin-top': 46%, + 'textvalue-right-top': 0%, + 'textvalue-right-margin-top': 46%, + 'textvalue-top-top': 0%, + 'hours-font-size': 36px, + 'hours-font-weight': bold, + 'hours-color': transparent, + 'hours-background-image': linear-gradient(white, #77c0f9), + 'hours-transform': skewX(-10deg), + 'unit-padding-top': 10px, + 'unit-font-size': 11px, + 'unit-font-weight': bold, + 'unit-color': transparent, + 'unit-background-image': linear-gradient(white, #77c0f9), + 'unit-transform': skewX(-10deg), + 'label-font-size': 14px, + 'label-color': #77c0f9, + 'backimg-margin':0 auto, + 'backimg-height':103px, + 'backimg-width':173px, + 'backimg-background-image':url('../../public/assets/img/year-month-target.png'), +); + +@include b(screen-panel-attribute) { + @include set-component-css-var( + 'screen-panel-attribute', + $screen-panel-attribute + ); + + @include e(backimg) { + width: 173px; + height: 103px; + margin: 0 auto; + background-image: url('../../public/assets/img/year-month-target.png'); + } + + position: relative; + min-height: getCssVar('screen-panel-attribute', 'min-height'); + margin-top: getCssVar('screen-panel-attribute', 'margin-top'); + overflow: hidden; + text-align: center; + + @include e(textvalue) { + position: absolute; + top: getCssVar('screen-panel-attribute', 'textvalue-top'); + left: getCssVar('screen-panel-attribute', 'textvalue-left'); + display: flex; + flex-direction: column; + width: max-content; + height: getCssVar('screen-panel-attribute', 'textvalue-height'); + transform: getCssVar('screen-panel-attribute', 'textvalue-transform'); + + &.left { + top: getCssVar('screen-panel-attribute', 'textvalue-left-top'); + flex-direction: row-reverse; + .#{bem('screen-panel-attribute','label')} { + margin-top: getCssVar( + 'screen-panel-attribute', + 'textvalue-left-margin-top' + ); + } + } + + &.right { + top: getCssVar('screen-panel-attribute', 'textvalue-right-top'); + flex-direction: row; + .#{bem('screen-panel-attribute','label')} { + margin-top: getCssVar( + 'screen-panel-attribute', + 'textvalue-right-margin-top' + ); + } + } + + &.top { + top: getCssVar('screen-panel-attribute', 'textvalue-top-top'); + flex-direction: column-reverse; + } + } + + @include e(value) { + display: flex; + align-items: center; + justify-content: center; + vertical-align: bottom; + } + @include e(hours) { + font-size: getCssVar('screen-panel-attribute', 'hours-font-size'); + font-weight: getCssVar('screen-panel-attribute', 'hours-font-weight'); + color: getCssVar('screen-panel-attribute', 'hours-color'); + background-image: getCssVar( + 'screen-panel-attribute', + 'hours-background-image' + ); + background-clip: text; + transform: getCssVar('screen-panel-attribute', 'hours-transform'); + } + + @include e(unit) { + padding-top: getCssVar('screen-panel-attribute', 'unit-padding-top'); + font-size: getCssVar('screen-panel-attribute', 'unit-font-size'); + font-weight: getCssVar('screen-panel-attribute', 'unit-font-weight'); + color: getCssVar('screen-panel-attribute', 'unit-color'); + background-image: getCssVar( + 'screen-panel-attribute', + 'unit-background-image' + ); + background-clip: text; + transform: getCssVar('screen-panel-attribute', 'unit-transform'); + } + + @include e(label) { + font-size: getCssVar('screen-panel-attribute', 'label-font-size'); + color: getCssVar('screen-panel-attribute', 'label-color'); + } +} + +$screen-panel-attribute-model3: ( + 'padding-top': 40px, + 'margin-bottom': -20px, + 'value-height': 53px, + 'value-background-image': url('../../public/assets/img/year-total.png'), + 'total-padding-top': 2px, + 'total-font-size': 28px, + 'total-color': #fefefe, + 'total-text-shadow': 1px 0 4px rgb(39 116 245 / 50%) -1px 0 4px rgb( + 39 116 245 / 50% + ) 0 -1px 4px rgb(39 116 245 / 50%) 0 1px 4px rgb(39 116 245 / 50%), + 'total-letter-spacing': 5px, + 'total-webkit-text-stroke': 0.5px #3474c6, + 'label-margin-top': 5px, + 'label-font-size': 16px, + 'label-font-weight': 700, + 'label-color': #fff, + 'text-margin': 0 2px, +); + +@include b(screen-panel-attribute-model3) { + @include set-component-css-var( + 'screen-panel-attribute-model3', + $screen-panel-attribute-model3 + ); + + padding-top: getCssVar('screen-panel-attribute-model3', 'padding-top'); + margin-bottom: getCssVar('screen-panel-attribute-model3', 'margin-bottom'); + + @include e(value) { + height: getCssVar('screen-panel-attribute-model3', 'value-height'); + text-align: center; + background-image: getCssVar( + 'screen-panel-attribute-model3', + 'value-background-image' + ); + background-repeat: no-repeat; + background-position: center; + } + + @include e(total) { + padding-top: getCssVar( + 'screen-panel-attribute-model3', + 'total-padding-top' + ); + font-size: getCssVar('screen-panel-attribute-model3', 'total-font-size'); + color: getCssVar('screen-panel-attribute-model3', 'total-font-size'); + text-shadow: getCssVar( + 'screen-panel-attribute-model3', + 'total-text-shadow' + ); + letter-spacing: getCssVar( + 'screen-panel-attribute-model3', + 'total-letter-spacing' + ); + -webkit-text-stroke: getCssVar( + 'screen-panel-attribute-model3', + 'total-webkit-text-stroke' + ); + } + + @include e(label) { + display: block; + margin-top: getCssVar('screen-panel-attribute-model3', 'label-margin-top'); + font-size: getCssVar('screen-panel-attribute-model3', 'label-font-size'); + font-weight: getCssVar( + 'screen-panel-attribute-model3', + 'label-font-weight' + ); + color: getCssVar('screen-panel-attribute-model3', 'label-color'); + text-align: center; + } + @include e(text) { + margin: 0 2px; + } +} + +$screen-panel-attribute-model2: ( + 'min-width': 366px, + 'height': 90px, + 'textvalue-top': 0, + 'textvalue-left': 50%, + 'textvalue-width': 288px, + 'textvalue-height': 100%, + 'textvalue-background-image': + url('../../public/assets/img/today-new-student.png'), + 'textvalue-transform': translateX(-50%), + 'label-padding-top': 10px, + 'label-font-size': 18px, + 'label-font-weight': normal, + 'label-color': #409df1, + 'label-letter-spacing': 4px, + 'label-webkit-text-stroke': 0.3px, + 'value-padding-top': 6px, + 'value-font-size': 36px, + 'value-font-weight': bold, + 'value-color': transparent, + 'value-background': linear-gradient(to bottom, white, #3cbef1), + 'value-transform': skewX(-10deg), + 'unit-font-size': 18px, + 'unit-font-weight': 600, +); + +@include b(screen-panel-attribute-model2) { + @include set-component-css-var( + 'screen-panel-attribute-model2', + $screen-panel-attribute-model2 + ); + + position: relative; + min-width: getCssVar('screen-panel-attribute-model2', 'min-width'); + height: getCssVar('screen-panel-attribute-model2', 'height'); + overflow: hidden; + text-align: center; + + @include e(textvalue) { + position: absolute; + top: getCssVar('screen-panel-attribute-model2', 'textvalue-top'); + left: getCssVar('screen-panel-attribute-model2', 'textvalue-left'); + display: flex; + flex-direction: column; + width: getCssVar('screen-panel-attribute-model2', 'textvalue-width'); + height: getCssVar('screen-panel-attribute-model2', 'textvalue-height'); + background-image: getCssVar( + 'screen-panel-attribute-model2', + 'textvalue-background-image' + ); + transform: getCssVar( + 'screen-panel-attribute-model2', + 'textvalue-transform' + ); + } + @include e(label) { + display: flex; + flex: 0; + justify-content: center; + padding-top: getCssVar( + 'screen-panel-attribute-model2', + 'label-padding-top' + ); + font-size: getCssVar('screen-panel-attribute-model2', 'label-font-size'); + font-weight: getCssVar( + 'screen-panel-attribute-model2', + 'label-font-weight' + ); + color: getCssVar('screen-panel-attribute-model2', 'label-color'); + letter-spacing: getCssVar( + 'screen-panel-attribute-model2', + 'label-letter-spacing' + ); + -webkit-text-stroke: getCssVar( + 'screen-panel-attribute-model2', + 'label-webkit-text-stroke' + ); + } + + @include e(value) { + display: flex; + flex: 1; + align-items: baseline; + justify-content: center; + padding-top: getCssVar( + 'screen-panel-attribute-model2', + 'value-padding-top' + ); + font-size: getCssVar('screen-panel-attribute-model2', 'value-font-size'); + font-weight: getCssVar( + 'screen-panel-attribute-model2', + 'value-font-weight' + ); + color: getCssVar('screen-panel-attribute-model2', 'value-color'); + background: getCssVar('screen-panel-attribute-model2', 'value-background'); + background-clip: text; + transform: getCssVar('screen-panel-attribute-model2', 'value-transform'); + } + + @include e(unit) { + display: inline-flex; + align-items: end; + font-size: getCssVar('screen-panel-attribute-model2', 'unit-font-size'); + font-weight: getCssVar('screen-panel-attribute-model2', 'unit-font-weight'); + } +} diff --git a/src/screen-panel-attribute/screen-panel-attribute.tsx b/src/screen-panel-attribute/screen-panel-attribute.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c037d3eff44646974a61e601deebf422d1143746 --- /dev/null +++ b/src/screen-panel-attribute/screen-panel-attribute.tsx @@ -0,0 +1,102 @@ +import { defineComponent, PropType, computed } from 'vue'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { useNamespace } from '@ibiz-template/vue3-util'; +import { IPanelRawItem } from '@ibiz/model-core'; +import { ScreenPanelAttributeController } from './screen-panel-attribute.controller'; +import './screen-panel-attribute.scss'; + +export const ScreenPanelAttribute = defineComponent({ + name: 'ScreenPanelAttribute', + props: { + modelData: { + type: Object as PropType, + required: true, + }, + controller: { + type: ScreenPanelAttributeController, + required: true, + }, + }, + setup(props) { + const ns = useNamespace('screen-panel-attribute'); + + const c = props.controller; + console.log('c', c, props); + + const label = computed(() => { + if (c.model.caption) { + return c.model.caption; + } + return ''; + }); + + const renderModel1 = () => { + return ( +
+
+
+
+
{0}
+
{c.unit}
+
+
{label.value}
+
+
+ ); + }; + + const renderModel2 = () => { + return ( +
+
+
{label.value}
+
+ {0} +
{c.unit}
+
+
+
+ ); + }; + + const renderModel3 = () => { + return ( +
+
+
{0}
+
+
+ + {label.value} + +
+
+ ); + }; + + const renderModel = () => { + if (c.showModel === 'model1') { + return renderModel1(); + } + if (c.showModel === 'model2') { + return renderModel2(); + } + if (c.showModel === 'model3') { + return renderModel3(); + } + }; + + return { + ns, + c, + label, + renderModel1, + renderModel2, + renderModel3, + renderModel, + }; + }, + render() { + return this.renderModel(); + }, +});