hortimagic 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,70 @@
1
+ import { LitElement, css, html } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
4
+
5
+
6
+ const iconMap = new Map([
7
+ ['magic-wand', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m12.64 1.87l-.84 2.48a.41.41 0 0 0 0 .37l1.57 2.1a.4.4 0 0 1-.33.64h-2.62a.43.43 0 0 0-.33.17l-1.46 2.1a.4.4 0 0 1-.71-.11l-.78-2.5a.38.38 0 0 0-.26-.26l-2.5-.78a.4.4 0 0 1-.11-.71l2.14-1.51a.43.43 0 0 0 .17-.33V.91a.4.4 0 0 1 .6-.33l2.1 1.57a.41.41 0 0 0 .37.05l2.48-.84a.4.4 0 0 1 .51.51m-5.6 5.09L.5 13.5" stroke-width="1"/></svg>'],
8
+ ['close', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M6.4 19L5 17.6l5.6-5.6L5 6.4L6.4 5l5.6 5.6L17.6 5L19 6.4L13.4 12l5.6 5.6l-1.4 1.4l-5.6-5.6z"/></svg>'],
9
+ ['open', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M4 21q-.425 0-.712-.288T3 20v-6q0-.425.288-.712T4 13t.713.288T5 14v3.6L17.6 5H14q-.425 0-.712-.288T13 4t.288-.712T14 3h6q.425 0 .713.288T21 4v6q0 .425-.288.713T20 11t-.712-.288T19 10V6.4L6.4 19H10q.425 0 .713.288T11 20t-.288.713T10 21z"/></svg>'],
10
+ ['arrow-up', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M16.21 16H7.79a1.76 1.76 0 0 1-1.59-1a2.1 2.1 0 0 1 .26-2.21l4.21-5.1a1.76 1.76 0 0 1 2.66 0l4.21 5.1A2.1 2.1 0 0 1 17.8 15a1.76 1.76 0 0 1-1.59 1"/></svg>'],
11
+ ['arrow-down', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M12 17a1.72 1.72 0 0 1-1.33-.64l-4.21-5.1a2.1 2.1 0 0 1-.26-2.21A1.76 1.76 0 0 1 7.79 8h8.42a1.76 1.76 0 0 1 1.59 1.05a2.1 2.1 0 0 1-.26 2.21l-4.21 5.1A1.72 1.72 0 0 1 12 17"/></svg>'],
12
+ ['template', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><defs><mask id="SVGZZ153dkC"><path fill="#4d4d4d" stroke="#fff" stroke-linejoin="round" stroke-width="4" d="M23 4H4v22h19zm21 30H4v9h40zm0-30H31v8h13zm0 14H31v8h13z"/></mask></defs><path fill="currentColor" d="M0 0h48v48H0z" mask="url(#SVGZZ153dkC)"/></svg>'],
13
+ ['js', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="currentColor" d="M10.77 7.3h.002c1.045.393 2.479.93 2.479 2.45a2.5 2.5 0 0 1-.224 1.02a2.5 2.5 0 0 1-1.515 1.364a2.5 2.5 0 0 1-1.035.115a2 2 0 0 1-.214.012a2.5 2.5 0 0 1-1.673-.65a2.52 2.52 0 0 1-.838-1.859c0-.202.078-.39.22-.532a.77.77 0 0 1 1.06 0a.74.74 0 0 1 .221.53c0 .952 1.041 1 1.25 1s1.25-.048 1.25-1c0-.413-.447-.648-1.514-1.048h-.003C9.19 8.307 7.753 7.77 7.753 6.25q.005-.537.224-1.02a2.5 2.5 0 0 1 .614-.842a2.5 2.5 0 0 1 .9-.52a3.5 3.5 0 0 1 2.023 0a2.52 2.52 0 0 1 1.738 2.381c0 .201-.078.39-.22.531a.77.77 0 0 1-1.061 0a.74.74 0 0 1-.22-.53c0-.952-1.041-1-1.25-1s-1.25.048-1.25 1c0 .413.447.648 1.514 1.048zM5.751 4.5c0-.2.078-.388.22-.53a.77.77 0 0 1 1.06 0c.142.141.22.33.22.53v5a2.75 2.75 0 0 1-4.695 1.945A2.73 2.73 0 0 1 1.75 9.5V9c0-.2.078-.388.22-.53a.77.77 0 0 1 1.061 0c.142.141.22.33.22.53v.5c0 .33.134.652.366.884c.465.465 1.303.465 1.768 0c.232-.233.366-.555.366-.884z"/></svg>'],
14
+ ['filter', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M3 4c2.01 2.59 7 9 7 9v7h4v-7s4.98-6.41 7-9z"/></svg>'],
15
+ ['filter-off', '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="currentColor" d="M3.004 1.59L3 1.586L1.586 3l4.928 4.928L10 12.818V21h4v-5.585l7 7l1.41-1.41L3 1.595zm12.266 9.446L21 3H7.234z"/></svg>'],
16
+
17
+ ]);
18
+
19
+ // 提供静态方法用于外部注册图标
20
+ export function registerIcon(name: string, svgContent: string) {
21
+ iconMap.set(name, svgContent);
22
+ }
23
+
24
+ // 获取svg代码
25
+ export function getIcon(name: string) {
26
+ // 修复:从 iconMap 中获取对应图标,如果没有则返回默认图标
27
+ return iconMap.get(name) || '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="m12.64 1.87l-.84 2.48a.41.41 0 0 0 0 .37l1.57 2.1a.4.4 0 0 1-.33.64h-2.62a.43.43 0 0 0-.33.17l-1.46 2.1a.4.4 0 0 1-.71-.11l-.78-2.5a.38.38 0 0 0-.26-.26l-2.5-.78a.4.4 0 0 1-.11-.71l2.14-1.51a.43.43 0 0 0 .17-.33V.91a.4.4 0 0 1 .6-.33l2.1 1.57a.41.41 0 0 0 .37.05l2.48-.84a.4.4 0 0 1 .51.51m-5.6 5.09L.5 13.5" stroke-width="1"/></svg>';
28
+ }
29
+
30
+ @customElement('hm-icon')
31
+ export class HmIcon extends LitElement {
32
+ @property({ type: String })
33
+ icon = 'magic-wand';
34
+
35
+ @property({ type: String })
36
+ size = '16px';
37
+
38
+ /** 触发点击事件 */
39
+ handelClick() {
40
+ this.dispatchEvent(new CustomEvent('hm-icon-click'));
41
+ }
42
+ static styles = css`
43
+ :host {
44
+ display: inline-block;
45
+ }
46
+ .icon {
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+
54
+ .icon svg {
55
+ width: 100%;
56
+ height: 100%;
57
+ }
58
+ `;
59
+
60
+ render() {
61
+ return html`
62
+ <div class="icon"
63
+ style="width:${this.size}; height:${this.size};"
64
+ @click="${this.handelClick}"
65
+ >
66
+ ${unsafeSVG(getIcon(this.icon))}
67
+ </div>
68
+ `;
69
+ }
70
+ }
@@ -0,0 +1,116 @@
1
+ import { LitElement, css, html } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+
4
+ /**
5
+ * @example <caption>基本使用</caption>
6
+ * <hm-input label="用户名" placeholder="请输入用户名"></hm-input>
7
+ *
8
+ * @example <caption>带图标的输入框</caption>
9
+ * <hm-input label="密码" icon="password" placeholder="请输入密码"></hm-input>
10
+ *
11
+ * @example <caption>禁用状态</caption>
12
+ * <hm-input label="禁用输入框" value="已禁用" enable="false"></hm-input>
13
+ *
14
+ * @example <caption>只读状态</caption>
15
+ * <hm-input label="只读输入框" value="只读内容" readonly="true"></hm-input>
16
+ */
17
+ @customElement('hm-input')
18
+ export class HmInput extends LitElement {
19
+ @property({ type: String })
20
+ type = 'text';
21
+ /** 按钮图标 */
22
+ @property({ type: String })
23
+ icon = '';
24
+ /** 输入框标签 */
25
+ @property({ type: String })
26
+ label = '输入框';
27
+
28
+ /** 占位符文本 */
29
+ @property({ type: String })
30
+ placeholder = '';
31
+
32
+ /** 是否启用 */
33
+ @property({ type: Boolean })
34
+ enable = true;
35
+
36
+ @property({ type: Boolean })
37
+ readonly = false;
38
+
39
+ @property()
40
+ value = '';
41
+
42
+ static styles = css`
43
+ :host {
44
+ display: block;
45
+ }
46
+ .input-container {
47
+ display: flex;
48
+ align-items: center;
49
+ }
50
+ .label {
51
+ margin-right: 8px;
52
+ }
53
+ input {
54
+ flex: 1;
55
+ padding: 8px 12px;
56
+ border: 1px solid #d9d9d9;
57
+ border-radius: 4px;
58
+ font-size: 14px;
59
+ outline: none;
60
+ transition: all 0.2s ease;
61
+ }
62
+ input:disabled {
63
+ background-color: #f5f5f5;
64
+ color: #999;
65
+ border-color: #ddd;
66
+ cursor: not-allowed;
67
+ }
68
+ input[readonly] {
69
+ background-color: #f5f5f5;
70
+ cursor: default;
71
+ }
72
+ .icon {
73
+ margin-right: 8px;
74
+ width: 16px;
75
+ height: 16px;
76
+ }
77
+ `;
78
+
79
+ // 添加键盘事件处理方法,阻止事件冒泡
80
+ private _handleKeyDown(e: KeyboardEvent) {
81
+ e.stopPropagation();
82
+ }
83
+
84
+ // 添加输入事件处理方法,触发自定义事件
85
+ private _handleInput(e: Event) {
86
+ const target = e.target as HTMLInputElement;
87
+ this.value = target.value;
88
+ this.dispatchEvent(new CustomEvent('hm-input-change', {
89
+ detail: { value: this.value },
90
+ bubbles: true,
91
+ composed: true
92
+ }));
93
+ }
94
+
95
+ render() {
96
+ return html`
97
+ <div class="input-container">
98
+ <span class="label">${this.label}</span>
99
+ ${this.icon ? html`<hm-icon icon="${this.icon}" class="icon"></hm-icon>` : ''}
100
+ <input
101
+ type="${this.type}"
102
+ value="${this.value}"
103
+ ?disabled="${!this.enable}"
104
+ ?readonly="${this.readonly}"
105
+ placeholder="${this.placeholder}"
106
+ style="padding-left: ${this.icon ? '24px' : '8px'};"
107
+ @keydown="${this._handleKeyDown}"
108
+ @input="${this._handleInput}"
109
+ />
110
+ <slot name="right">
111
+ </slot>
112
+ </div>
113
+ `;
114
+ }
115
+
116
+ }
@@ -0,0 +1,94 @@
1
+ import { LitElement, css, html } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+
4
+ @customElement('hm-menu')
5
+ export class HmMenu extends LitElement {
6
+ @property({ type: String })
7
+ icon = 'magic-wand';
8
+ @property({ type: String })
9
+ content = 'HortiMagic';
10
+ @property({ type: Boolean })
11
+ flag = false;
12
+ @property({ type: Boolean })
13
+ isMenuItem = false;
14
+
15
+
16
+
17
+ static styles = css`
18
+ :host {
19
+ color: rgb(33,33,33);
20
+ height: 56px;
21
+ }
22
+ .menu:hover {
23
+ color: rgba(255, 255, 0, 1);
24
+ }
25
+ .menu {
26
+ height: 56px;
27
+ align-items: center;
28
+ }
29
+ .icon {
30
+ display: flex;
31
+ justify-content: center;
32
+ align-items: center;
33
+ height: 56px;
34
+ width: 56px;
35
+ }
36
+ .left {
37
+ margin-right: 16px;
38
+ color: rgb(117,117,117);
39
+ }
40
+ .right {
41
+ position: absolute;
42
+ right: 2px;
43
+ display: flex;
44
+ justify-content: center;
45
+ align-items: center;
46
+ }
47
+ .content {
48
+ font-size: 16px;
49
+ font-weight:bold;
50
+ margin-right:auto;
51
+ }
52
+ .is-menu-item {
53
+ background:rgb(240,240,240);
54
+ }
55
+ .not-menu-item {
56
+ background:rgb(255,255,255);
57
+ }
58
+ `;
59
+
60
+ /** 触发点击事件 */
61
+ handleClick() {
62
+ if (!this.isMenuItem)
63
+ this.flag = !this.flag;
64
+ this.dispatchEvent(new CustomEvent('hm-menu-click'));
65
+ }
66
+
67
+ render() {
68
+ return html`
69
+ <div
70
+ class="menu ${this.isMenuItem ? 'is-menu-item' : 'not-menu-item'}"
71
+ style="display:${this.isMenuItem && !this.flag ? 'none' : 'flex'}"
72
+ @click="${this.handleClick}"
73
+ >
74
+ <hm-icon class="left icon" icon="${this.icon}" size="24px"></hm-icon>
75
+ <div class="content">
76
+ <slot name="content"> ${this.content} </slot>
77
+ </div>
78
+ <div class="right">
79
+ <slot name="right">
80
+ ${this.isMenuItem ? '' : html`<hm-icon
81
+ class="icon right"
82
+ icon="${this.flag ? 'arrow-up' : 'arrow-down'}"
83
+ ></hm-icon
84
+ >`}
85
+ </slot>
86
+ </div>
87
+ </div>
88
+
89
+
90
+
91
+
92
+ `;
93
+ }
94
+ }
@@ -0,0 +1,358 @@
1
+ import { LitElement, css, html } from 'lit';
2
+ import { customElement, property, queryAsync } from 'lit/decorators.js';
3
+
4
+ /** 创建的窗口列表 */
5
+ export let movePanelItemList: HmMovePanel[] = [];
6
+ /** 窗口基础的层级,每新建一个加一,从99999开始加 */
7
+ export let movePanelItemMaxZindex: number = 99999;
8
+
9
+ /** 移动面板组件 */
10
+ @customElement('hm-move-panel')
11
+ export class HmMovePanel extends LitElement {
12
+ /** 主内容区宽 */
13
+ @property({ type: Number })
14
+ width = 320;
15
+ /** 主内容区高 */
16
+ @property({ type: Number })
17
+ height = 490;
18
+ @property({ type: String, attribute: 'header-background-color' })
19
+ headerBackgroundColor = 'rgba(66,134,182,0.9)';
20
+ @property({ type: String, attribute: 'header-color' })
21
+ headerColor = 'rgb(255,255,255)';
22
+ @property({ type: String, attribute: 'body-background-color' })
23
+ bodyBackgroundColor = 'rgba(255,255,255,0.7)';
24
+ @property({ type: String, attribute: 'body-color' })
25
+ bodyColor = 'rgba(23, 23, 23, 0.9)';
26
+ @property({ type: String, attribute: 'footer-background-color' })
27
+ footerBackgroundColor = 'rgba(255,255,255,0.7)';
28
+ @property({ type: String, attribute: 'button-background-color' })
29
+ buttonBackgroundColor = 'rgba(255,255,255,0.9)';
30
+ @property({ type: String, attribute: 'button-color' })
31
+ buttonColor = 'rgba(66,134,182,0.9)';
32
+ /** 标题 */
33
+ @property({ type: String }) titleContent = '面板';
34
+ @property({ type: String, attribute: 'left-button-text' })
35
+ leftButtonText = '按钮1';
36
+ @property({ type: String, attribute: 'right-button-text' })
37
+ rightButtonText = '按钮2';
38
+ /** 显示状态,不建议直接修改,请使用show()和hide()方法,否则无法触发对应事件 */
39
+ @property({ type: Boolean, attribute: 'is-display' })
40
+ isDisplay = false;
41
+ @property({ type: Number })
42
+ zIndex = movePanelItemMaxZindex;
43
+ /** 左上角图标 */
44
+ @property({ type: String })
45
+ icon = 'magic-wand'
46
+ /* 定位左边 */
47
+ @property({ type: Number })
48
+ left = (window.innerWidth - this.width) / 2;
49
+ /* 定位顶部 */
50
+ @property({ type: Number })
51
+ top = (window.innerHeight - (this.height + 80)) / 2;
52
+
53
+ handleLeftClick() {
54
+ this.hideMovePanel();
55
+ }
56
+ handleRightClick() {
57
+ this.hideMovePanel();
58
+ }
59
+ /**
60
+ * 组件内部的body元素
61
+ */
62
+ @queryAsync('.body')
63
+ body!: Promise<HTMLDivElement>;
64
+
65
+ static styles = css`
66
+ .panel {
67
+ position: absolute;
68
+ display: block;
69
+ }
70
+
71
+ .header {
72
+ display: flex;
73
+ align-items: center;
74
+ justify-content: space-between;
75
+ height: 40px;
76
+ }
77
+ .header-left {
78
+ display: flex;
79
+ align-items: center;
80
+ }
81
+
82
+ .header-icon {
83
+ display: flex;
84
+ align-items: center;
85
+ margin-left: 24px;
86
+ margin-right: 24px;
87
+ }
88
+ .left-icon {
89
+ display: flex;
90
+ align-items: center;
91
+ }
92
+ .header-title {
93
+ margin-right: auto;
94
+ font-size: 16px !important;
95
+ opacity: 0.7;
96
+ font-weight: bold;
97
+ height: 100%;
98
+ line-height: 40px;
99
+ }
100
+
101
+
102
+ .header-close {
103
+ cursor: pointer;
104
+ display: flex;
105
+ align-items: center;
106
+ justify-content: center;
107
+ width: 40px;
108
+ higth: 40px;
109
+ }
110
+
111
+ .body {
112
+ display: block;
113
+ position: absolute;
114
+ top: 40px;
115
+ overflow: auto;
116
+ scrollbar-width: none; /* Firefox */
117
+ }
118
+ .body::-webkit-scrollbar {
119
+ display: none; /* Chrome/Safari/Webkit */
120
+ }
121
+
122
+ .footer {
123
+ display: flex;
124
+ position: absolute;
125
+ height: 40px;
126
+ bottom: 0px;
127
+ width: 100%; /* 添加宽度占满父容器 */
128
+ box-sizing: border-box; /* 确保padding不会增加元素总宽度 */
129
+ }
130
+
131
+ .footer-button {
132
+ flex: 1;
133
+ border: none;
134
+ border-radius: 4px;
135
+ cursor: pointer;
136
+ transition: all 0.2s;
137
+ }
138
+
139
+ .footer-button:active {
140
+ transform: scale(0.98);
141
+ }
142
+ `;
143
+
144
+ constructor() {
145
+ super();
146
+ // 添加到窗口列表
147
+ movePanelItemList.push(this);
148
+ // 设置初始层级
149
+ this.zIndex = ++movePanelItemMaxZindex;
150
+ }
151
+ /** 关闭移动窗口 */
152
+ hideMovePanel() {
153
+ this.isDisplay = false;
154
+ console.debug('关闭事件');
155
+ this.dispatchEvent(new CustomEvent('close', {
156
+ detail: { isDisplay: this.isDisplay, message: '关闭事件' },
157
+ bubbles: true,
158
+ composed: true
159
+ }));
160
+ }
161
+ /** 显示移动窗口 */
162
+ showMovePanel() {
163
+ this.isDisplay = true;
164
+ console.debug('显示事件');
165
+ this.dispatchEvent(new CustomEvent('show', {
166
+ detail: { isDisplay: this.isDisplay },
167
+ bubbles: true,
168
+ composed: true
169
+ }));
170
+ }
171
+ /** 显示状态翻转 */
172
+ toogleDisplay() {
173
+ if (this.isDisplay) {
174
+ this.hideMovePanel();
175
+ } else {
176
+ this.showMovePanel();
177
+ }
178
+ }
179
+ // 添加拖动功能
180
+ dragging = false
181
+ mouseDragging(e: MouseEvent) {
182
+ // console.debug('标题按下');
183
+ // 窗口原本位置
184
+ let templeft = this.left;
185
+ // 窗口原本位置
186
+ let temptop = this.top;
187
+
188
+ // 窗口左上角的偏移量
189
+ let offsetX = e.clientX - templeft;
190
+ let offsetY = e.clientY - temptop;
191
+
192
+ // console.debug('鼠标位置', e.clientX, e.clientY);
193
+ // console.debug('窗口位置', templeft, temptop);
194
+ (this.dragging == false) && (this.dragging = true);
195
+ document.onmousemove = (e) => {
196
+ if (this.dragging) {
197
+ this.left = e.clientX - offsetX;
198
+ this.top = e.clientY - offsetY;
199
+ }
200
+ }
201
+ document.onmouseup = () => {
202
+ // console.debug('标题抬起');
203
+ this.dragging && (this.dragging = false);
204
+ document.onmousemove = null
205
+ }
206
+ }
207
+ // 适配移动端
208
+ touchDragging(e: TouchEvent) {
209
+ // console.debug('触摸标题按下');
210
+ // 窗口原本位置
211
+ let templeft = this.left;
212
+ // 窗口原本位置
213
+ let temptop = this.top;
214
+
215
+ // 窗口左上角的偏移量
216
+ let offsetX = e.touches[0].clientX - templeft;
217
+ let offsetY = e.touches[0].clientY - temptop;
218
+
219
+ // console.debug('触摸鼠标位置', e.touches[0].clientX, e.touches[0].clientY);
220
+ // console.debug('触摸窗口位置', templeft, temptop);
221
+ (this.dragging == false) && (this.dragging = true);
222
+ document.ontouchmove = (e) => {
223
+ if (this.dragging) {
224
+ this.left = e.touches[0].clientX - offsetX;
225
+ this.top = e.touches[0].clientY - offsetY;
226
+ }
227
+ }
228
+ document.ontouchend = () => {
229
+ // console.debug('标题抬起');
230
+ this.dragging && (this.dragging = false);
231
+ document.onmousemove = null
232
+ }
233
+ }
234
+ // 置顶窗口
235
+ putTop() {
236
+ // console.debug('置顶窗口');
237
+ let res = false;
238
+ if (movePanelItemList.includes(this)) {
239
+ // 先把比它大的都减小一层
240
+ for (let i = 0; i < movePanelItemList.length; i++) {
241
+ if (movePanelItemList[i].zIndex > this.zIndex)
242
+ movePanelItemList[i].zIndex = movePanelItemList[i].zIndex - 1;
243
+ }
244
+ // 再把自己设置成最高的
245
+ this.zIndex = movePanelItemMaxZindex;
246
+ res = true;
247
+ // console.debug('置顶窗口成功');
248
+ } else {
249
+ // console.warn('置顶失败,窗口不在列表中');
250
+ res = false;
251
+ }
252
+ return res;
253
+ }
254
+
255
+ /**
256
+ * 切换元素的置顶状态和显示状态
257
+ *
258
+ * 当元素的zIndex不等于最大移动面板层级时,将元素置于顶层并显示移动面板;
259
+ * 当元素的zIndex等于最大移动面板层级时,切换元素的显示状态
260
+ */
261
+ putTopToggel() {
262
+ // 如果当前层级不是最顶层,则置顶并显示移动面板
263
+ if (this.zIndex != movePanelItemMaxZindex) {
264
+ this.putTop();
265
+ this.showMovePanel();
266
+ } else {
267
+ // 如果已经是顶层,则切换显示状态
268
+ this.toogleDisplay();
269
+ }
270
+ }
271
+ render() {
272
+ return html`
273
+ <div
274
+ class="panel"
275
+ style="
276
+ width: ${this.width}px;
277
+ height: ${this.height + 80}px;
278
+ left: ${this.left}px;
279
+ top: ${this.top}px;
280
+ display: ${this.isDisplay ? 'block' : 'none'};
281
+ z-index: ${this.zIndex};
282
+ "
283
+ @mousedown="${this.putTop}"
284
+ @touchstart="${this.putTop}"
285
+ >
286
+ <div
287
+ class="header"
288
+ style="background-color: ${this.headerBackgroundColor}; color: ${this.headerColor};"
289
+ @mousedown="${this.mouseDragging}"
290
+ @touchstart="${this.touchDragging}"
291
+ >
292
+ <div class="header-left">
293
+ <div class="header-icon">
294
+ <slot name="left-icon" class="left-icon">
295
+ <hm-icon icon="${this.icon}" size="24px"></hm-icon>
296
+ </slot>
297
+ </div>
298
+ <div class="header-title">${this.titleContent}</div>
299
+ </div>
300
+ <div class="header-close" @click="${this._handleClose}">
301
+ <slot name="right-icon" class="right-icon">
302
+ <hm-icon icon="close" size="18px"></hm-icon>
303
+ </slot>
304
+ </div>
305
+ </div>
306
+ <div
307
+ class="body"
308
+ style="background-color: ${this.bodyBackgroundColor}; color: ${this.bodyColor}; height:${this.height}px;width:${this.width}px;"
309
+ >
310
+ <slot></slot>
311
+ </div>
312
+ <div class="footer" style="background-color: ${this.footerBackgroundColor};width:${this.width}px;">
313
+ <hm-button
314
+ class="footer-button footer-button-left"
315
+ icon="magic-wand"
316
+ width="100%"
317
+ backgroundColor="${this.buttonBackgroundColor}"
318
+ color="${this.buttonColor}"
319
+ @click="${this._handleLeftButtonClick}"
320
+ >
321
+ ${this.leftButtonText}
322
+ </hm-button>
323
+ <hm-button
324
+ class="footer-button footer-button-right"
325
+ icon="magic-wand"
326
+ width="100%"
327
+ backgroundColor="${this.buttonColor}"
328
+ color="${this.buttonBackgroundColor}"
329
+ @click="${this._handleRightButtonClick}"
330
+ >
331
+ ${this.rightButtonText}
332
+ </hm-button>
333
+ </div>
334
+ </div>
335
+
336
+ `;
337
+ }
338
+
339
+ _handleClose() {
340
+ this.hideMovePanel();
341
+ }
342
+
343
+ _handleLeftButtonClick() {
344
+ this.dispatchEvent(new CustomEvent('left-button-click', {
345
+ detail: { message: '左侧按钮被点击' },
346
+ bubbles: true,
347
+ composed: true
348
+ }));
349
+ }
350
+
351
+ _handleRightButtonClick() {
352
+ this.dispatchEvent(new CustomEvent('right-button-click', {
353
+ detail: { message: '右侧按钮被点击' },
354
+ bubbles: true,
355
+ composed: true
356
+ }));
357
+ }
358
+ }