jianghu-ui 1.0.1

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.
Files changed (112) hide show
  1. package/README.md +376 -0
  2. package/dist/jianghu-ui.css +2318 -0
  3. package/dist/jianghu-ui.js +2 -0
  4. package/dist/jianghu-ui.js.LICENSE.txt +1 -0
  5. package/package.json +56 -0
  6. package/src/Design.stories.mdx +195 -0
  7. package/src/Introduction.stories.mdx +148 -0
  8. package/src/components/JhAddressSelect/JhAddressSelect.md +250 -0
  9. package/src/components/JhAddressSelect/JhAddressSelect.stories.js +282 -0
  10. package/src/components/JhAddressSelect/JhAddressSelect.vue +261 -0
  11. package/src/components/JhCard/JhCard.md +246 -0
  12. package/src/components/JhCard/JhCard.stories.js +688 -0
  13. package/src/components/JhCard/JhCard.vue +604 -0
  14. package/src/components/JhCheckCard/JhCheckCard.md +245 -0
  15. package/src/components/JhCheckCard/JhCheckCard.stories.js +750 -0
  16. package/src/components/JhCheckCard/JhCheckCard.vue +476 -0
  17. package/src/components/JhConfirmDialog/JhConfirmDialog.md +70 -0
  18. package/src/components/JhConfirmDialog/JhConfirmDialog.stories.js +550 -0
  19. package/src/components/JhConfirmDialog/JhConfirmDialog.vue +181 -0
  20. package/src/components/JhDateRangePicker/JhDateRangePicker.md +56 -0
  21. package/src/components/JhDateRangePicker/JhDateRangePicker.stories.js +320 -0
  22. package/src/components/JhDateRangePicker/JhDateRangePicker.vue +307 -0
  23. package/src/components/JhDescriptions/JhDescriptions.md +724 -0
  24. package/src/components/JhDescriptions/JhDescriptions.stories.js +858 -0
  25. package/src/components/JhDescriptions/JhDescriptions.vue +933 -0
  26. package/src/components/JhDraggable/JhDraggable.md +66 -0
  27. package/src/components/JhDraggable/JhDraggable.stories.js +161 -0
  28. package/src/components/JhDraggable/JhDraggable.vue +254 -0
  29. package/src/components/JhDrawer/JhDrawer.md +68 -0
  30. package/src/components/JhDrawer/JhDrawer.stories.js +478 -0
  31. package/src/components/JhDrawer/JhDrawer.vue +281 -0
  32. package/src/components/JhDrawerForm/JhDrawerForm.md +69 -0
  33. package/src/components/JhDrawerForm/JhDrawerForm.stories.js +492 -0
  34. package/src/components/JhDrawerForm/JhDrawerForm.vue +297 -0
  35. package/src/components/JhEditableTable/JhEditableTable.md +507 -0
  36. package/src/components/JhEditableTable/JhEditableTable.stories.js +615 -0
  37. package/src/components/JhEditableTable/JhEditableTable.vue +685 -0
  38. package/src/components/JhFileInput/JhFileInput.md +56 -0
  39. package/src/components/JhFileInput/JhFileInput.stories.js +103 -0
  40. package/src/components/JhFileInput/JhFileInput.vue +253 -0
  41. package/src/components/JhForm/JhForm.md +676 -0
  42. package/src/components/JhForm/JhForm.stories.js +1375 -0
  43. package/src/components/JhForm/JhForm.vue +657 -0
  44. package/src/components/JhFormField/JhFormField.stories.js +217 -0
  45. package/src/components/JhFormField/JhFormField.vue +439 -0
  46. package/src/components/JhFormFields/JhFormFields.md +647 -0
  47. package/src/components/JhFormFields/JhFormFields.stories.js +922 -0
  48. package/src/components/JhFormFields/JhFormFields.vue +998 -0
  49. package/src/components/JhFormList/JhFormList.md +303 -0
  50. package/src/components/JhFormList/JhFormList.stories.js +661 -0
  51. package/src/components/JhFormList/JhFormList.vue +1127 -0
  52. package/src/components/JhJsonEditor/JhJsonEditor.md +54 -0
  53. package/src/components/JhJsonEditor/JhJsonEditor.stories.js +157 -0
  54. package/src/components/JhJsonEditor/JhJsonEditor.vue +178 -0
  55. package/src/components/JhLayout/JhLayout.md +580 -0
  56. package/src/components/JhLayout/JhLayout.stories.js +414 -0
  57. package/src/components/JhLayout/JhLayout.vue +387 -0
  58. package/src/components/JhList/JhList.md +441 -0
  59. package/src/components/JhList/JhList.stories.js +524 -0
  60. package/src/components/JhList/JhList.vue +571 -0
  61. package/src/components/JhMarkdownEditor/JhMarkdownEditor.md +56 -0
  62. package/src/components/JhMarkdownEditor/JhMarkdownEditor.stories.js +191 -0
  63. package/src/components/JhMarkdownEditor/JhMarkdownEditor.vue +188 -0
  64. package/src/components/JhMask/JhMask.md +62 -0
  65. package/src/components/JhMask/JhMask.stories.js +270 -0
  66. package/src/components/JhMask/JhMask.vue +123 -0
  67. package/src/components/JhMenu/JhMenu.md +85 -0
  68. package/src/components/JhMenu/JhMenu.stories.js +384 -0
  69. package/src/components/JhMenu/JhMenu.vue +545 -0
  70. package/src/components/JhModal/JhModal.md +68 -0
  71. package/src/components/JhModal/JhModal.stories.js +562 -0
  72. package/src/components/JhModal/JhModal.vue +235 -0
  73. package/src/components/JhModalForm/JhModalForm.md +69 -0
  74. package/src/components/JhModalForm/JhModalForm.stories.js +592 -0
  75. package/src/components/JhModalForm/JhModalForm.vue +298 -0
  76. package/src/components/JhPageContainer/JhPageContainer.md +409 -0
  77. package/src/components/JhPageContainer/JhPageContainer.stories.js +209 -0
  78. package/src/components/JhPageContainer/JhPageContainer.vue +72 -0
  79. package/src/components/JhQueryFilter/JhQueryFilter.md +77 -0
  80. package/src/components/JhQueryFilter/JhQueryFilter.stories.js +684 -0
  81. package/src/components/JhQueryFilter/JhQueryFilter.vue +429 -0
  82. package/src/components/JhScene/JhScene.md +64 -0
  83. package/src/components/JhScene/JhScene.stories.js +317 -0
  84. package/src/components/JhScene/JhScene.vue +376 -0
  85. package/src/components/JhStatisticCard/JhStatisticCard.md +363 -0
  86. package/src/components/JhStatisticCard/JhStatisticCard.stories.js +847 -0
  87. package/src/components/JhStatisticCard/JhStatisticCard.vue +459 -0
  88. package/src/components/JhStepsForm/JhStepsForm.md +666 -0
  89. package/src/components/JhStepsForm/JhStepsForm.stories.js +1224 -0
  90. package/src/components/JhStepsForm/JhStepsForm.vue +749 -0
  91. package/src/components/JhTable/JhTable.md +730 -0
  92. package/src/components/JhTable/JhTable.stories.js +1444 -0
  93. package/src/components/JhTable/JhTable.vue +2298 -0
  94. package/src/components/JhTableAttachment/JhTableAttachment.md +70 -0
  95. package/src/components/JhTableAttachment/JhTableAttachment.stories.js +198 -0
  96. package/src/components/JhTableAttachment/JhTableAttachment.vue +264 -0
  97. package/src/components/JhToast/JhToast.md +67 -0
  98. package/src/components/JhToast/JhToast.stories.js +386 -0
  99. package/src/components/JhToast/JhToast.vue +239 -0
  100. package/src/components/JhTreeSelect/JhTreeSelect.md +82 -0
  101. package/src/components/JhTreeSelect/JhTreeSelect.stories.js +391 -0
  102. package/src/components/JhTreeSelect/JhTreeSelect.vue +727 -0
  103. package/src/components/JhWaterMark/JhWaterMark.md +190 -0
  104. package/src/components/JhWaterMark/JhWaterMark.stories.js +675 -0
  105. package/src/components/JhWaterMark/JhWaterMark.vue +351 -0
  106. package/src/components/README.md +52 -0
  107. package/src/index.js +135 -0
  108. package/src/style/globalCSSJHV4.css +348 -0
  109. package/src/style/globalCSSVuetifyV4.css +637 -0
  110. package/src/style/storybook.css +4 -0
  111. package/src/tailwind.css +3 -0
  112. package/src/utils/vuetify.js +31 -0
@@ -0,0 +1,66 @@
1
+ # JhDraggable - 拖拽搭建容器
2
+
3
+ JhDraggable 是基于 `vuedraggable` 的拖拽容器,提供组件库到设计区域的拖拽、排序能力,适合作为低代码页面的基础框架。
4
+
5
+ ## 功能特性
6
+
7
+ - 🧱 **双面板设计**:左侧组件库、右侧设计区,支持克隆式拖入
8
+ - 🧠 **受控数据**:组件库/设计区都以数组驱动,可直接持久化配置
9
+ - 🎨 **拖拽状态样式**:`dragClass`、`ghostClass`、`chosenClass` 可自定义
10
+ - 🧲 **空状态引导**:未放入组件时提供占位提示,提高可用性
11
+ - 🔌 **事件透传**:暴露 `start/end/input/change`,方便监听拖拽或保存
12
+
13
+ ## 基础用法
14
+
15
+ ```vue
16
+ <template>
17
+ <jh-draggable
18
+ :components="materialList"
19
+ v-model="pageBlocks"
20
+ component-library-title="组件库"
21
+ @change="save"
22
+ >
23
+ <template #item="{ item }">
24
+ <div class="custom-block">{{ item.title }}</div>
25
+ </template>
26
+ </jh-draggable>
27
+ </template>
28
+ ```
29
+
30
+ ## API
31
+
32
+ ### Props
33
+
34
+ | 参数 | 说明 | 类型 | 默认值 |
35
+ | --- | --- | --- | --- |
36
+ | components | 组件库数据源 | Array | [] |
37
+ | value | v-model,设计区元素数组 | Array | [] |
38
+ | showComponentLibrary | 是否显示左侧组件库 | boolean | true |
39
+ | componentLibraryTitle | 左侧标题 | string | `组件` |
40
+ | groupName | vuedraggable 分组名 | string | `draggable-group` |
41
+ | animation | 拖拽动画时长(ms) | number | 300 |
42
+ | dragClass | 拖拽中附加的 class | string | `jh-drag-class` |
43
+ | ghostClass | 占位元素 class | string | `jh-ghost-class` |
44
+ | chosenClass | 选中元素 class | string | `jh-chosen-class` |
45
+ | emptyPlaceholder | 空状态提示文案 | string | `从左侧拖入或点选组件进行内容设计` |
46
+
47
+ ### Events
48
+
49
+ | 事件名 | 说明 | 回调参数 |
50
+ | --- | --- | --- |
51
+ | input | 设计区内容变更 | (blocks: any[]) |
52
+ | change | 设计区排序/新增后的内容 | (blocks: any[]) |
53
+ | start | 拖拽开始 | - |
54
+ | end | 拖拽结束 | - |
55
+
56
+ ### Slots
57
+
58
+ | 名称 | 说明 |
59
+ | --- | --- |
60
+ | item | 自定义设计区内每个元素的展示,参数 `{ item }` |
61
+
62
+ ## 使用建议
63
+
64
+ - 组件默认会为设计区元素补齐唯一 id,建议根据业务字段(如 `component`)渲染
65
+ - 如需拖拽嵌套或跨页面共享,可通过 `groupName` 配置相同分组名
66
+ - 若 `vuedraggable` 未被全局注册,需要在父级组件手动注册/引入
@@ -0,0 +1,161 @@
1
+ import JhDraggable from './JhDraggable.vue';
2
+
3
+ export default {
4
+ title: '基础组件/JhDraggable - 拖拽排序',
5
+ component: JhDraggable,
6
+ tags: ['autodocs'],
7
+ argTypes: {
8
+ components: {
9
+ control: 'object',
10
+ description: '组件库列表',
11
+ },
12
+ value: {
13
+ control: 'object',
14
+ description: '设计区域的元素列表',
15
+ },
16
+ showComponentLibrary: {
17
+ control: 'boolean',
18
+ description: '是否显示左侧组件库',
19
+ },
20
+ componentLibraryTitle: {
21
+ control: 'text',
22
+ description: '组件库标题',
23
+ },
24
+ groupName: {
25
+ control: 'text',
26
+ description: '拖拽分组名称',
27
+ },
28
+ animation: {
29
+ control: 'number',
30
+ description: '动画时长(毫秒)',
31
+ },
32
+ emptyPlaceholder: {
33
+ control: 'text',
34
+ description: '空状态占位文本',
35
+ },
36
+ },
37
+ parameters: {
38
+ docs: {
39
+ description: {
40
+ component: `
41
+
42
+ 基于 Vue.Draggable 的拖拽排序组件。
43
+
44
+ ## 使用前提
45
+
46
+ 需要在项目中安装并引入 vuedraggable:
47
+
48
+ \`\`\`bash
49
+ npm install vuedraggable
50
+ \`\`\`
51
+
52
+ 或在 HTML 中引入 CDN:
53
+
54
+ \`\`\`html
55
+ <script src="https://cdn.jsdelivr.net/npm/sortable@1.15.0/Sortable.min.js"></script>
56
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>
57
+ \`\`\`
58
+
59
+ ## 功能特性
60
+
61
+ - 支持从组件库拖拽到设计区
62
+ - 支持设计区内拖拽排序
63
+ - 自动处理 ID 冲突
64
+ - 支持自定义样式
65
+ - 支持空状态提示
66
+ `,
67
+ },
68
+ },
69
+ },
70
+ };
71
+
72
+ const formComponents = [
73
+ { id: 1, name: '输入框', type: 'input' },
74
+ { id: 2, name: '单选框', type: 'radio' },
75
+ { id: 3, name: '多选框', type: 'checkbox' },
76
+ { id: 4, name: '下拉选择', type: 'select' },
77
+ { id: 5, name: '日期选择', type: 'date' },
78
+ { id: 6, name: '文本域', type: 'textarea' },
79
+ ];
80
+
81
+ export const 基础示例 = {
82
+ args: {
83
+ components: formComponents,
84
+ value: [],
85
+ showComponentLibrary: true,
86
+ componentLibraryTitle: '组件',
87
+ groupName: 'form-builder',
88
+ animation: 300,
89
+ emptyPlaceholder: '从左侧拖入或点选组件进行内容设计',
90
+ },
91
+ };
92
+
93
+ export const 预设元素 = {
94
+ args: {
95
+ components: formComponents,
96
+ value: [
97
+ { id: 101, name: '用户名输入框', type: 'input' },
98
+ { id: 102, name: '性别单选框', type: 'radio' },
99
+ { id: 103, name: '兴趣多选框', type: 'checkbox' },
100
+ ],
101
+ showComponentLibrary: true,
102
+ componentLibraryTitle: '表单组件',
103
+ groupName: 'form-builder',
104
+ animation: 300,
105
+ emptyPlaceholder: '从左侧拖入组件',
106
+ },
107
+ };
108
+
109
+ export const 无组件库 = {
110
+ args: {
111
+ components: [],
112
+ value: [
113
+ { id: 1, name: '任务 1', status: 'todo' },
114
+ { id: 2, name: '任务 2', status: 'in-progress' },
115
+ { id: 3, name: '任务 3', status: 'done' },
116
+ { id: 4, name: '任务 4', status: 'todo' },
117
+ ],
118
+ showComponentLibrary: false,
119
+ componentLibraryTitle: '',
120
+ groupName: 'task-list',
121
+ animation: 200,
122
+ emptyPlaceholder: '暂无任务',
123
+ },
124
+ };
125
+
126
+ export const 自定义动画 = {
127
+ args: {
128
+ components: [
129
+ { id: 1, name: '标题', type: 'heading' },
130
+ { id: 2, name: '段落', type: 'paragraph' },
131
+ { id: 3, name: '图片', type: 'image' },
132
+ { id: 4, name: '视频', type: 'video' },
133
+ { id: 5, name: '按钮', type: 'button' },
134
+ ],
135
+ value: [],
136
+ showComponentLibrary: true,
137
+ componentLibraryTitle: '页面元素',
138
+ groupName: 'page-builder',
139
+ animation: 500,
140
+ emptyPlaceholder: '拖拽元素到这里构建页面',
141
+ },
142
+ };
143
+
144
+ export const 卡片组件 = {
145
+ args: {
146
+ components: [
147
+ { id: 1, name: '📊 数据卡片', type: 'data-card' },
148
+ { id: 2, name: '📈 图表卡片', type: 'chart-card' },
149
+ { id: 3, name: '📋 列表卡片', type: 'list-card' },
150
+ { id: 4, name: '📝 表单卡片', type: 'form-card' },
151
+ ],
152
+ value: [
153
+ { id: 100, name: '📊 销售数据', type: 'data-card' },
154
+ ],
155
+ showComponentLibrary: true,
156
+ componentLibraryTitle: '卡片组件',
157
+ groupName: 'dashboard-builder',
158
+ animation: 300,
159
+ emptyPlaceholder: '拖拽卡片组件到这里',
160
+ },
161
+ };
@@ -0,0 +1,254 @@
1
+ <template>
2
+ <v-app>
3
+ <v-container fluid>
4
+ <v-row class="draggable-container">
5
+ <!-- 左侧组件库 -->
6
+ <v-col v-if="showComponentLibrary" cols="12" md="3">
7
+ <div class="title">{{ componentLibraryTitle }}</div>
8
+ <draggable
9
+ v-if="isDraggableLoaded"
10
+ v-model="componentsInternal"
11
+ :group="{ name: groupName, pull: 'clone', put: false }"
12
+ :animation="animation"
13
+ :drag-class="dragClass"
14
+ :ghost-class="ghostClass"
15
+ :chosen-class="chosenClass"
16
+ @start="handleStart"
17
+ @end="handleEnd"
18
+ >
19
+ <transition-group>
20
+ <div
21
+ class="draggable-item"
22
+ v-for="item in componentsInternal"
23
+ :key="item.id"
24
+ >
25
+ {{ item.name }}
26
+ </div>
27
+ </transition-group>
28
+ </draggable>
29
+ </v-col>
30
+
31
+ <!-- 右侧设计区域 -->
32
+ <v-col :cols="showComponentLibrary ? 12 : 12" :md="showComponentLibrary ? 9 : 12">
33
+ <draggable
34
+ v-if="isDraggableLoaded"
35
+ v-model="designAreaInternal"
36
+ :group="groupName"
37
+ :animation="animation"
38
+ :drag-class="dragClass"
39
+ :ghost-class="ghostClass"
40
+ :chosen-class="chosenClass"
41
+ @start="handleStart"
42
+ @end="handleEnd"
43
+ >
44
+ <transition-group>
45
+ <div
46
+ class="draggable-item"
47
+ v-for="item in designAreaInternal"
48
+ :key="item.id"
49
+ >
50
+ <slot name="item" :item="item">
51
+ {{ item.name }}
52
+ </slot>
53
+ </div>
54
+ </transition-group>
55
+ </draggable>
56
+
57
+ <!-- 空状态提示 -->
58
+ <v-row v-show="!designAreaInternal.length" class="ma-0 pa-0" style="width: 100%;">
59
+ <v-card height="100" class="ma-12" width="100%" color="#f5f8fa" style="border: 1px dashed #333333">
60
+ <draggable
61
+ v-if="isDraggableLoaded"
62
+ v-model="designAreaInternal"
63
+ :group="groupName"
64
+ :animation="animation"
65
+ :drag-class="dragClass"
66
+ :ghost-class="ghostClass"
67
+ class="d-flex align-center justify-center"
68
+ style="height: 100%;"
69
+ >
70
+ <v-card-text class="text-center title draggable-placeholder">
71
+ {{ emptyPlaceholder }}
72
+ </v-card-text>
73
+ </draggable>
74
+ </v-card>
75
+ </v-row>
76
+ </v-col>
77
+ </v-row>
78
+ </v-container>
79
+ </v-app>
80
+ </template>
81
+
82
+ <script>
83
+ export default {
84
+ name: 'JhDraggable',
85
+ props: {
86
+ // 组件库列表
87
+ components: {
88
+ type: Array,
89
+ default: () => []
90
+ },
91
+ // 设计区域列表
92
+ value: {
93
+ type: Array,
94
+ default: () => []
95
+ },
96
+ // 是否显示组件库
97
+ showComponentLibrary: {
98
+ type: Boolean,
99
+ default: true
100
+ },
101
+ // 组件库标题
102
+ componentLibraryTitle: {
103
+ type: String,
104
+ default: '组件'
105
+ },
106
+ // 分组名称
107
+ groupName: {
108
+ type: String,
109
+ default: 'draggable-group'
110
+ },
111
+ // 动画时长
112
+ animation: {
113
+ type: Number,
114
+ default: 300
115
+ },
116
+ // 拖拽中的样式类
117
+ dragClass: {
118
+ type: String,
119
+ default: 'jh-drag-class'
120
+ },
121
+ // 占位样式类
122
+ ghostClass: {
123
+ type: String,
124
+ default: 'jh-ghost-class'
125
+ },
126
+ // 选中样式类
127
+ chosenClass: {
128
+ type: String,
129
+ default: 'jh-chosen-class'
130
+ },
131
+ // 空状态占位文本
132
+ emptyPlaceholder: {
133
+ type: String,
134
+ default: '从左侧拖入或点选组件进行内容设计'
135
+ }
136
+ },
137
+ data() {
138
+ return {
139
+ drag: false,
140
+ componentsInternal: [],
141
+ designAreaInternal: [],
142
+ isDraggableLoaded: false
143
+ };
144
+ },
145
+ watch: {
146
+ components: {
147
+ handler(val) {
148
+ this.componentsInternal = [...val];
149
+ },
150
+ immediate: true,
151
+ deep: true
152
+ },
153
+ value: {
154
+ handler(val) {
155
+ this.designAreaInternal = [...val];
156
+ },
157
+ immediate: true,
158
+ deep: true
159
+ },
160
+ designAreaInternal: {
161
+ handler(val) {
162
+ this.$emit('input', val);
163
+ this.$emit('change', val);
164
+ },
165
+ deep: true
166
+ }
167
+ },
168
+ mounted() {
169
+ // 检查 vuedraggable 是否已加载
170
+ this.checkDraggableLibrary();
171
+ },
172
+ methods: {
173
+ checkDraggableLibrary() {
174
+ // 检查是否有 draggable 组件可用
175
+ if (this.$options.components.draggable || window.vuedraggable) {
176
+ this.isDraggableLoaded = true;
177
+ } else {
178
+ console.warn('Vue Draggable library is not loaded. Please include vuedraggable library.');
179
+ // 提供一个降级方案,使用原生的 v-for
180
+ this.isDraggableLoaded = false;
181
+ }
182
+ },
183
+ handleStart() {
184
+ this.drag = true;
185
+ this.$emit('start');
186
+ },
187
+ handleEnd() {
188
+ this.drag = false;
189
+ this.ensureUniqueIds();
190
+ this.$emit('end');
191
+ },
192
+ // 确保每个项目有唯一的 id
193
+ ensureUniqueIds() {
194
+ const allIds = [
195
+ ...this.componentsInternal.map(item => item.id),
196
+ ...this.designAreaInternal.map(item => item.id)
197
+ ];
198
+ let maxId = Math.max(...allIds);
199
+
200
+ this.designAreaInternal.forEach(item => {
201
+ if (this.componentsInternal.some(comp => comp.id === item.id)) {
202
+ item.id = ++maxId;
203
+ }
204
+ });
205
+ }
206
+ }
207
+ };
208
+ </script>
209
+
210
+ <style scoped>
211
+ .draggable-container {
212
+ margin: 10px;
213
+ }
214
+
215
+ .title {
216
+ padding: 6px 12px;
217
+ font-weight: 500;
218
+ color: #333;
219
+ }
220
+
221
+ .draggable-item {
222
+ padding: 6px 12px;
223
+ margin: 0px 10px 6px 10px;
224
+ border: solid 1px #eee;
225
+ background-color: #f1f1f1;
226
+ cursor: move;
227
+ transition: background-color 0.2s;
228
+ }
229
+
230
+ .draggable-item:hover {
231
+ background-color: #fdfdfd;
232
+ }
233
+
234
+ :deep(.jh-ghost-class) {
235
+ background-color: #e3f2fd !important;
236
+ opacity: 0.8 !important;
237
+ }
238
+
239
+ :deep(.jh-chosen-class) {
240
+ background-color: #bbdefb !important;
241
+ opacity: 1 !important;
242
+ }
243
+
244
+ :deep(.jh-drag-class) {
245
+ background-color: #90caf9 !important;
246
+ opacity: 0.9 !important;
247
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
248
+ }
249
+
250
+ .draggable-placeholder {
251
+ color: #999;
252
+ user-select: none;
253
+ }
254
+ </style>
@@ -0,0 +1,68 @@
1
+ # JhDrawer - 抽屉面板组件
2
+
3
+ JhDrawer 提供左右或底部滑出的信息面板,包含统一的头部、操作按钮和默认内容区域,适合在列表页展示详情、表单或设置。
4
+
5
+ ## 功能特性
6
+
7
+ - 📐 **多方向弹出**:通过 `position` 快速切换左/右/底部抽屉
8
+ - 🎯 **受控显示**:`v-model` 控制开关,自动派发 open/close 事件
9
+ - 🧩 **插槽扩展**:`actions` 插槽可自定义按钮组,默认提供确定/取消
10
+ - 📏 **自定义尺寸**:支持百分比或像素宽度,满足不同布局
11
+ - 🔔 **快捷操作**:内置浮动关闭按钮,移动端也可轻松关闭
12
+
13
+ ## 基础用法
14
+
15
+ ```vue
16
+ <template>
17
+ <jh-drawer
18
+ v-model="visible"
19
+ title="高级筛选"
20
+ width="480px"
21
+ @confirm="submit"
22
+ @cancel="close"
23
+ >
24
+ <filter-form />
25
+ </jh-drawer>
26
+ </template>
27
+ ```
28
+
29
+ ## API
30
+
31
+ ### Props
32
+
33
+ | 参数 | 说明 | 类型 | 默认值 |
34
+ | --- | --- | --- | --- |
35
+ | value | v-model,抽屉显隐 | boolean | false |
36
+ | title | 标题文本 | string | `抽屉` |
37
+ | position | 抽屉位置 `left/right/bottom` | string | `right` |
38
+ | width | 抽屉宽度,支持百分比或像素 | string / number | `90%` |
39
+ | height | 底部抽屉高度,支持百分比、像素或 `vh` | string / number | `60vh` |
40
+ | showConfirmButton | 是否显示确认按钮 | boolean | true |
41
+ | showCancelButton | 是否显示取消按钮 | boolean | true |
42
+ | showCloseButton | 是否显示浮动关闭按钮 | boolean | true |
43
+ | confirmText | 确认按钮文本 | string | `确认` |
44
+ | cancelText | 取消按钮文本 | string | `取消` |
45
+
46
+ ### Events
47
+
48
+ | 事件名 | 说明 | 回调参数 |
49
+ | --- | --- | --- |
50
+ | input | `v-model` 绑定事件 | (visible: boolean) |
51
+ | open | 抽屉打开时触发 | - |
52
+ | close | 抽屉关闭后触发 | - |
53
+ | confirm | 点击确认按钮触发 | - |
54
+ | cancel | 点击取消按钮或浮动关闭触发 | - |
55
+
56
+ ### Slots
57
+
58
+ | 名称 | 说明 |
59
+ | --- | --- |
60
+ | default | 主体内容区域 |
61
+ | actions | 头部按钮区域,覆盖默认确认/取消按钮 |
62
+
63
+ ## 使用建议
64
+
65
+ - 当抽屉内容需要滚动时,可自行在插槽内部包裹滚动容器
66
+ - 通过监听 `confirm/cancel` 事件,在外部控制提交或关闭逻辑
67
+ - 底部抽屉默认隐藏浮动关闭按钮,可在内容区自行提供操作区
68
+ - 配合 `JhDrawerForm` 可以快速构建配置中心、复杂筛选面板