@neatui/nuxt 0.1.0 → 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 (85) hide show
  1. package/BUILD.md +128 -0
  2. package/IMPORT_GUIDE.md +142 -0
  3. package/README.md +98 -1
  4. package/SSR_COMPATIBILITY.md +201 -0
  5. package/USAGE.md +291 -0
  6. package/nuxt.config.example.ts +37 -0
  7. package/package.json +34 -11
  8. package/src/components/basic/IDraggable.vue +87 -65
  9. package/src/components/basic/IFollowView.vue +32 -23
  10. package/src/components/basic/IRouterView.vue +38 -23
  11. package/src/components/basic/IScrollView.vue +11 -7
  12. package/src/components/basic/Icon.vue +17 -17
  13. package/src/components/basic/LayerView/Layer.vue +33 -106
  14. package/src/components/basic/follow.ts +133 -0
  15. package/src/components/display/Calendar.vue +14 -14
  16. package/src/components/display/CalendarReg.vue +14 -14
  17. package/src/components/display/Image.vue +8 -8
  18. package/src/components/display/PhotoEditor.vue +36 -36
  19. package/src/components/display/PhotoViewer.vue +8 -8
  20. package/src/components/display/Tree.vue +6 -6
  21. package/src/components/display/TreeView.vue +4 -4
  22. package/src/components/display/index.ts +2 -2
  23. package/src/components/form/Cascader.vue +19 -19
  24. package/src/components/form/Checkbox.vue +64 -0
  25. package/src/components/form/DatePicker.vue +6 -7
  26. package/src/components/form/DateRangePicker@v3.vue +4 -4
  27. package/src/components/form/DateRangeView@v3.vue +18 -19
  28. package/src/components/form/DateView.vue +14 -14
  29. package/src/components/form/DateView@v2.vue +14 -14
  30. package/src/components/form/DateView@v3.vue +331 -318
  31. package/src/components/form/ImgUpload.vue +7 -7
  32. package/src/components/form/Input@v3.vue +11 -11
  33. package/src/components/form/MoreSelect@v3.vue +87 -17
  34. package/src/components/form/MoreSelectList.vue +8 -8
  35. package/src/components/form/MoreSelectPanel@v3.vue +3 -3
  36. package/src/components/form/MoreSelectPicker.vue +7 -7
  37. package/src/components/form/MoreSelectTags.vue +8 -8
  38. package/src/components/form/PageMoreSelect.vue +14 -14
  39. package/src/components/form/PageSelect.vue +16 -16
  40. package/src/components/form/SearchMoreSelect.vue +12 -12
  41. package/src/components/form/SearchSelect@v3.vue +3 -3
  42. package/src/components/form/Select@v3.vue +229 -23
  43. package/src/components/form/SelectList.vue +8 -8
  44. package/src/components/form/SelectPicker.vue +6 -6
  45. package/src/components/form/SelectTags.vue +7 -7
  46. package/src/components/form/SelectTree/SelectTree@v1.vue +5 -5
  47. package/src/components/form/Switch.vue +38 -103
  48. package/src/components/form/TextArea.vue +18 -18
  49. package/src/components/form/Textarea@v2.vue +275 -0
  50. package/src/components/form/TimeView.vue +14 -14
  51. package/src/components/form/Upload.vue +806 -297
  52. package/src/components/form/date.ts +321 -0
  53. package/src/components/form/index.ts +7 -5
  54. package/src/components/form/number.ts +3 -0
  55. package/src/components/form/type.ts +224 -0
  56. package/src/components/icon/OrderIcon.vue +113 -0
  57. package/src/components/loader/FormLoader/FormLoader@v2.vue +193 -195
  58. package/src/components/loader/FormLoader/FormLoader@v3.vue.backup +372 -291
  59. package/src/components/loader/FormLoader/FormRender@v3.vue.backup +4 -0
  60. package/src/components/loader/FormLoader/NodeLoader.vue +85 -0
  61. package/src/components/loader/FormLoader@v1/FormLoader.vue +1 -1
  62. package/src/components/loader/FormLoader@v1/FormRender.vue +49 -24
  63. package/src/components/loader/LayerLoader/LayerLoader.vue +318 -0
  64. package/src/components/loader/LayerLoader/index.ts +2 -0
  65. package/src/components/loader/LayerLoader/style.scss +77 -0
  66. package/src/components/loader/LimitLoader/LimitLoader@v3.vue +39 -28
  67. package/src/components/loader/MoveLoader/MoveLoader.vue +628 -0
  68. package/src/components/loader/MoveLoader/index.ts +2 -0
  69. package/src/components/loader/MoveLoader/style.scss +77 -0
  70. package/src/components/loader/TableLoader/TableLoader.vue +227 -195
  71. package/src/components/loader/TableLoader/TableRender.vue +141 -0
  72. package/src/components/loader/TableLoader/index.ts +47 -0
  73. package/src/components/loader/index.ts +3 -2
  74. package/src/components/tools/Pagination@a.vue +17 -18
  75. package/src/components/tools/Pagination@b.vue +16 -16
  76. package/src/index.ts +2 -1
  77. package/src/module.ts +169 -0
  78. package/src/runtime/types.d.ts +36 -0
  79. package/src/store/{myui.ts → frame.ts} +4 -4
  80. package/src/utils/theme.ts +14 -0
  81. package/tsconfig.json +1 -1
  82. package/src/components/loader/FormLoader/index.ts +0 -2
  83. package/src/components/loader/LimitLoader/LimitLoader.vue.backup +0 -131
  84. package/src/components/loader/LimitLoader/LimitLoader@v2.vue.backup +0 -174
  85. package/src/components/loader/TableLoader/TableColView.vue +0 -115
package/USAGE.md ADDED
@@ -0,0 +1,291 @@
1
+ # @neatui/nuxt 使用指南
2
+
3
+ ## 📦 安装
4
+
5
+ ```bash
6
+ npm install @neatui/nuxt
7
+ ```
8
+
9
+ ## ⚙️ 配置
10
+
11
+ 在 `nuxt.config.ts` 中添加模块:
12
+
13
+ ```ts
14
+ export default defineNuxtConfig({
15
+ modules: [
16
+ '@neatui/nuxt'
17
+ ],
18
+ neatui: {
19
+ prefix: 'Neat', // 组件前缀
20
+ theme: 'default' // 主题
21
+ }
22
+ })
23
+ ```
24
+
25
+ ## 🎯 基础使用
26
+
27
+ ### 方式1: 自动导入 (推荐)
28
+
29
+ 配置模块后,组件会自动注册,直接在模板中使用:
30
+
31
+ #### 表单组件
32
+
33
+ ```vue
34
+ <template>
35
+ <div>
36
+ <!-- 输入框 -->
37
+ <NeatInput
38
+ v-model="form.name"
39
+ placeholder="请输入姓名"
40
+ :rules="[{ required: true, message: '姓名必填' }]"
41
+ />
42
+
43
+ <!-- 选择器 -->
44
+ <NeatSelect
45
+ v-model="form.city"
46
+ :options="cityOptions"
47
+ placeholder="选择城市"
48
+ />
49
+
50
+ <!-- 日期选择 -->
51
+ <NeatDatePicker
52
+ v-model="form.date"
53
+ placeholder="选择日期"
54
+ />
55
+
56
+ <!-- 上传组件 -->
57
+ <NeatUpload
58
+ v-model="form.files"
59
+ :limit="3"
60
+ accept="image/*"
61
+ />
62
+
63
+ <!-- 按钮 -->
64
+ <NeatButton @click="submit" type="primary">
65
+ 提交
66
+ </NeatButton>
67
+ </div>
68
+ </template>
69
+
70
+ <script setup>
71
+ const form = reactive({
72
+ name: '',
73
+ city: '',
74
+ date: '',
75
+ files: []
76
+ })
77
+
78
+ const cityOptions = [
79
+ { label: '北京', value: 'beijing' },
80
+ { label: '上海', value: 'shanghai' },
81
+ { label: '广州', value: 'guangzhou' }
82
+ ]
83
+
84
+ const submit = () => {
85
+ console.log('提交数据:', form)
86
+ }
87
+ </script>
88
+ ```
89
+
90
+ ### 展示组件
91
+
92
+ ```vue
93
+ <template>
94
+ <div>
95
+ <!-- 表格组件 -->
96
+ <NeatTableLoader
97
+ :data="tableData"
98
+ :columns="columns"
99
+ :loading="loading"
100
+ />
101
+
102
+ <!-- 分页组件 -->
103
+ <NeatPageSelect
104
+ v-model="currentPage"
105
+ :total="total"
106
+ :page-size="pageSize"
107
+ />
108
+ </div>
109
+ </template>
110
+
111
+ <script setup>
112
+ const tableData = ref([])
113
+ const loading = ref(false)
114
+ const currentPage = ref(1)
115
+ const total = ref(0)
116
+ const pageSize = ref(10)
117
+
118
+ const columns = [
119
+ { key: 'name', title: '姓名' },
120
+ { key: 'age', title: '年龄' },
121
+ { key: 'city', title: '城市' }
122
+ ]
123
+ </script>
124
+ ```
125
+
126
+ ### 表单构建器
127
+
128
+ ```vue
129
+ <template>
130
+ <div>
131
+ <!-- 动态表单 -->
132
+ <NeatFormLoader
133
+ v-model="formData"
134
+ :form="formConfig"
135
+ :rows="2"
136
+ />
137
+ </div>
138
+ </template>
139
+
140
+ <script setup>
141
+ const formData = ref({})
142
+
143
+ const formConfig = [
144
+ {
145
+ field: 'name',
146
+ label: '姓名',
147
+ model: ['Input', { placeholder: '请输入姓名' }],
148
+ rules: [{ required: true, message: '姓名必填' }],
149
+ media: 'col-6'
150
+ },
151
+ {
152
+ field: 'email',
153
+ label: '邮箱',
154
+ model: ['Input', { type: 'email', placeholder: '请输入邮箱' }],
155
+ rules: [{ required: true, type: 'email', message: '邮箱格式错误' }],
156
+ media: 'col-6'
157
+ },
158
+ {
159
+ field: 'city',
160
+ label: '城市',
161
+ model: ['Select', { placeholder: '选择城市' }],
162
+ enums: [
163
+ { label: '北京', value: 'beijing' },
164
+ { label: '上海', value: 'shanghai' }
165
+ ],
166
+ media: 'col-12'
167
+ }
168
+ ]
169
+ </script>
170
+ ```
171
+
172
+ ### 方式2: 手动导入
173
+
174
+ 如果不想使用自动导入,可以手动导入组件:
175
+
176
+ ```vue
177
+ <template>
178
+ <div>
179
+ <Textarea v-model="content" placeholder="请输入内容" />
180
+ <Input v-model="name" placeholder="请输入姓名" />
181
+ <Select v-model="city" :options="cities" />
182
+ </div>
183
+ </template>
184
+
185
+ <script setup>
186
+ // 手动导入需要的组件
187
+ import { Textarea, Input, Select } from '@neatui/nuxt/components'
188
+
189
+ const content = ref('')
190
+ const name = ref('')
191
+ const city = ref('')
192
+ const cities = [
193
+ { label: '北京', value: 'beijing' },
194
+ { label: '上海', value: 'shanghai' }
195
+ ]
196
+ </script>
197
+ ```
198
+
199
+ ## 🎨 主题定制
200
+
201
+ ### 使用CSS变量
202
+
203
+ ```ts
204
+ // nuxt.config.ts
205
+ export default defineNuxtConfig({
206
+ neatui: {
207
+ css: {
208
+ variables: {
209
+ 'primary-color': '#007bff',
210
+ 'border-radius': '6px',
211
+ 'font-size': '14px',
212
+ 'spacing-sm': '8px',
213
+ 'spacing-md': '16px'
214
+ }
215
+ }
216
+ }
217
+ })
218
+ ```
219
+
220
+ ### 自定义主题
221
+
222
+ ```css
223
+ /* assets/css/custom-theme.css */
224
+ :root {
225
+ --neat-primary-color: #007bff;
226
+ --neat-success-color: #28a745;
227
+ --neat-warning-color: #ffc107;
228
+ --neat-danger-color: #dc3545;
229
+ --neat-border-radius: 6px;
230
+ }
231
+ ```
232
+
233
+ ## 🔧 高级配置
234
+
235
+ ### 按需导入
236
+
237
+ ```ts
238
+ // nuxt.config.ts
239
+ export default defineNuxtConfig({
240
+ neatui: {
241
+ // 只导入需要的组件
242
+ exclude: [
243
+ 'SomeHeavyComponent',
244
+ 'AnotherComponent'
245
+ ]
246
+ }
247
+ })
248
+ ```
249
+
250
+ ### 自定义前缀
251
+
252
+ ```ts
253
+ // nuxt.config.ts
254
+ export default defineNuxtConfig({
255
+ neatui: {
256
+ prefix: 'My' // 组件将变成 <MyButton>, <MyInput>
257
+ }
258
+ })
259
+ ```
260
+
261
+ ## 📱 SSR 注意事项
262
+
263
+ 某些组件可能需要客户端渲染:
264
+
265
+ ```vue
266
+ <template>
267
+ <div>
268
+ <!-- 对于依赖浏览器API的组件,使用 ClientOnly -->
269
+ <ClientOnly>
270
+ <NeatUpload v-model="files" />
271
+ <template #fallback>
272
+ <div>加载中...</div>
273
+ </template>
274
+ </ClientOnly>
275
+ </div>
276
+ </template>
277
+ ```
278
+
279
+ ## 🐛 常见问题
280
+
281
+ ### Q: 组件不显示?
282
+ A: 确保已正确安装并在 nuxt.config.ts 中配置模块
283
+
284
+ ### Q: 类型提示不完整?
285
+ A: 重启 TypeScript 服务或重新生成类型
286
+
287
+ ### Q: 样式没有加载?
288
+ A: 检查是否正确导入了样式文件
289
+
290
+ ### Q: SSR 报错?
291
+ A: 使用 `<ClientOnly>` 包裹客户端专用组件
@@ -0,0 +1,37 @@
1
+ // nuxt.config.ts 使用示例
2
+ export default defineNuxtConfig({
3
+ modules: [
4
+ '@neatui/nuxt'
5
+ ],
6
+
7
+ // NeatUI 配置
8
+ neatui: {
9
+ // 组件前缀 (可选)
10
+ prefix: 'Neat', // 组件将以 <NeatButton>, <NeatInput> 等形式使用
11
+
12
+ // 主题设置 (可选)
13
+ theme: 'default', // 'default' | 'dark' | 自定义主题名
14
+
15
+ // 自动导入开关 (可选)
16
+ autoImport: true, // 是否自动导入组件
17
+
18
+ // 排除特定组件 (可选)
19
+ exclude: [
20
+ // 'SomeComponent' // 不自动导入的组件名
21
+ ],
22
+
23
+ // CSS 变量自定义 (可选)
24
+ css: {
25
+ variables: {
26
+ // 'primary-color': '#007bff',
27
+ // 'border-radius': '4px',
28
+ // 'font-size': '14px'
29
+ }
30
+ }
31
+ },
32
+
33
+ // 如果需要手动添加样式 (通常不需要,模块会自动处理)
34
+ css: [
35
+ // '@neatui/nuxt/dist/style.css'
36
+ ]
37
+ })
package/package.json CHANGED
@@ -1,33 +1,56 @@
1
1
  {
2
2
  "name": "@neatui/nuxt",
3
- "version": "0.1.0",
4
- "description": "basic component ui",
5
- "main": "./src/index.ts",
3
+ "version": "1.0.1",
4
+ "description": "NeatUI component library for Nuxt 3",
5
+ "main": "./src/module.ts",
6
+ "types": "./src/module.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./src/module.ts",
10
+ "import": "./src/module.ts",
11
+ "require": "./src/module.ts"
12
+ },
13
+ "./components": {
14
+ "types": "./src/index.ts",
15
+ "import": "./src/index.ts",
16
+ "require": "./src/index.ts"
17
+ }
18
+ },
6
19
  "license": "MIT",
7
20
  "author": "xiaojunbo",
21
+ "keywords": ["nuxt", "nuxt-module", "vue", "ui", "components"],
8
22
  "peerDependencies": {
23
+ "@nuxt/kit": "^3.0.0",
24
+ "nuxt": "^3.0.0",
9
25
  "vue": "^3.2.0"
10
26
  },
11
27
  "scripts": {
12
- "build": "rollup -c rollup.config.js"
28
+ "dev": "nuxi dev playground",
29
+ "dev:prepare": "nuxi prepare playground",
30
+ "release": "npm publish",
31
+ "lint": "echo 'No lint configured'",
32
+ "test": "echo 'No tests configured'"
13
33
  },
14
34
  "devDependencies": {
35
+ "@nuxt/kit": "^3.0.0",
36
+ "@nuxt/schema": "^3.0.0",
15
37
  "@rollup/plugin-typescript": "^11.1.6",
38
+ "@types/sortablejs": "^1.15.8",
39
+ "nuxt": "^3.0.0",
16
40
  "postcss-scss": "^4.0.9",
17
41
  "rollup-plugin-scss": "^4.0.0",
18
42
  "rollup-plugin-terser": "^7.0.2",
19
43
  "typescript": "^5.1.6"
20
44
  },
21
45
  "dependencies": {
22
- "@fekit/floor": "^2.2.2",
23
- "@fekit/follow": "^1.0.10",
46
+ "@fekit/floor": "^3.0.1",
47
+ "@fekit/follow": "^1.7.0",
24
48
  "@fekit/itable": "^1.1.6",
25
49
  "@fekit/pullload": "^1.3.5",
26
50
  "@fekit/scale": "^2.0.1",
27
51
  "@fekit/scrollto": "^3.0.3",
28
- "@fekit/toast": "^2.2.3",
29
- "@fekit/url": "^2.0.1",
30
- "@fekit/utils": "^2.10.21",
52
+ "@fekit/toast": "^2.7.2",
53
+ "@fekit/utils": "^4.3.1",
31
54
  "@rollup/plugin-commonjs": "^26.0.1",
32
55
  "@rollup/plugin-node-resolve": "^15.2.3",
33
56
  "@vue/compiler-sfc": "^3.4.30",
@@ -36,8 +59,8 @@
36
59
  "rollup": "^4.18.0",
37
60
  "rollup-plugin-postcss": "^4.0.2",
38
61
  "rollup-plugin-vue": "^6.0.0",
62
+ "sortablejs": "^1.15.6",
39
63
  "swiper": "^11.0.4",
40
- "vue-cropper": "^0.6.4",
41
- "vuedraggable": "^4.1.0"
64
+ "vue-cropper": "^0.6.4"
42
65
  }
43
66
  }
@@ -1,84 +1,106 @@
1
1
  <template>
2
- <ul>
3
- <li
4
- v-for="(item, idx) in list || []"
5
- :key="idx"
6
- class="pr drag-page-move n-sm"
7
- draggable="true"
8
- @dragstart.self="fMoveSta($event, list, idx)"
9
- @dragend.self="fMoveEnd($event, list, idx)"
10
- @dragenter.self="fMoveInt($event, list, idx)"
11
- @dragover.prevent="fMoveIng($event)"
12
- @dragleave="fMoveOut($event)"
13
- >
2
+ <ul ref="listRef" class="drag-list">
3
+ <li v-for="(item, idx) in props.lists" :key="item.id ?? item.field ?? idx" class="pr drag-page-move">
14
4
  <slot :item="item" :idx="idx">{{ item.label }}</slot>
15
5
  </li>
16
6
  </ul>
17
7
  </template>
18
8
 
19
9
  <script setup lang="ts">
20
- import { reactive, PropType } from 'vue';
10
+ import { ref, PropType, onMounted, onBeforeUnmount, nextTick, watch } from 'vue';
11
+ import Sortable, { SortableEvent } from 'sortablejs';
12
+
21
13
  const props = defineProps({
22
- list: {
14
+ lists: {
23
15
  type: Array as PropType<any[]>,
24
- default: () => []
25
- }
16
+ default: () => [],
17
+ },
26
18
  });
27
- const state: any = reactive({});
19
+ const emit = defineEmits(['update:lists']);
28
20
 
29
- // 按下
30
- const fMoveSta = (e: any, arr: any, idx: any) => {
31
- state.__page_moveing = 1;
32
- state.__page_moveStaNode = { e, arr, idx };
33
- };
34
- // 移动
35
- const fMoveIng = (e: any) => {
36
- if (state.__page_moveing) {
37
- const _h = e?.target?.getBoundingClientRect()?.height || 0;
38
- const _v = _h / 2 > 0 ? _h / 2 : 0;
39
- state.__page_moveEndNodeIsNext = e?.layerY > _v ? 1 : 0;
40
- console.log(40, e, _v, e?.layerY > _v ? 'next' : 'prev');
41
- e?.target?.setAttribute('data-ins', e?.layerY > _v ? 'next' : 'prev');
42
- }
43
- };
44
- // 移入
45
- const fMoveInt = (e: any, arr: any, idx: any, page: any = '') => {
46
- if (state.__page_moveing) {
47
- state.__page_moveEndNode = { e, arr, idx, page };
48
- }
49
- };
50
- // 移出
51
- const fMoveOut = (e: any) => {
52
- if (state.__page_moveing) {
53
- e?.target?.removeAttribute('data-ins');
54
- }
55
- };
56
- // 松开
57
- const fMoveEnd = (_e: any, arr: any, i2: any) => {
58
- if (state.__page_moveing) {
59
- if (state.__page_moveEndNode) {
60
- const [item] = arr.splice(i2, 1);
61
- let idx = state.__page_moveEndNode?.idx || 0;
62
- if (state.__page_moveEndNodeIsNext && i2 >= idx) {
63
- idx = idx + 1;
64
- }
65
- if (!state.__page_moveEndNodeIsNext && i2 < idx) {
66
- idx = idx - 1;
67
- }
68
- state.__page_moveEndNode?.arr?.splice(idx, 0, item);
69
- fMoveOut(state.__page_moveEndNode?.e);
21
+ const listRef = ref<HTMLElement | null>(null);
22
+ let sortable: Sortable | null = null;
23
+
24
+ // 添加调试日志
25
+ watch(
26
+ () => props.lists,
27
+ (newVal, oldVal) => {
28
+ // console.log('IDraggable props.lists changed:', {
29
+ // newLength: newVal?.length,
30
+ // oldLength: oldVal?.length,
31
+ // newVal: newVal?.map((item) => item.label || item.field),
32
+ // oldVal: oldVal?.map((item) => item.label || item.field)
33
+ // });
34
+ },
35
+ { deep: true },
36
+ );
37
+
38
+ onMounted(() => {
39
+ nextTick(() => {
40
+ if (listRef.value) {
41
+ sortable = Sortable.create(listRef.value, {
42
+ animation: 200,
43
+ ghostClass: 'drag-ghost',
44
+ chosenClass: 'drag-chosen',
45
+ dragClass: 'drag-dragging',
46
+ onEnd(evt: SortableEvent) {
47
+ console.log('Sortable onEnd:', { oldIndex: evt.oldIndex, newIndex: evt.newIndex });
48
+
49
+ if (evt.oldIndex !== undefined && evt.newIndex !== undefined && evt.oldIndex !== evt.newIndex) {
50
+ // 创建新的数组顺序
51
+ const newList = [...props.lists];
52
+ const moved = newList.splice(evt.oldIndex, 1)[0];
53
+ newList.splice(evt.newIndex, 0, moved);
54
+
55
+ console.log(
56
+ 'Emitting new list:',
57
+ newList.map((item) => item.label || item.field),
58
+ );
59
+
60
+ // 通知父组件更新数据
61
+ emit('update:lists', newList);
62
+ }
63
+ },
64
+ });
70
65
  }
71
- state.__page_moveing = 0;
66
+ });
67
+ });
68
+
69
+ onBeforeUnmount(() => {
70
+ if (sortable) {
71
+ sortable.destroy();
72
+ sortable = null;
72
73
  }
73
- };
74
+ });
74
75
  </script>
76
+
75
77
  <style lang="scss">
78
+ .drag-list {
79
+ list-style: none;
80
+ padding: 0;
81
+ margin: 0;
82
+ }
76
83
  .drag-page-move {
77
- &[data-ins='prev'] {
78
- box-shadow: inset 0 1px 0 0 #000;
79
- }
80
- &[data-ins='next'] {
81
- box-shadow: inset 0 -1px 0 0 #000;
84
+ cursor: move;
85
+ transition: background-color 0.2s ease;
86
+
87
+ &:hover {
88
+ background: rgba(0, 0, 0, 0.02);
82
89
  }
83
90
  }
91
+ .drag-ghost {
92
+ opacity: 0.4;
93
+ background: rgba(0, 0, 0, 0.05);
94
+ border: 2px dashed #ddd;
95
+ }
96
+ .drag-chosen {
97
+ background: rgba(24, 144, 255, 0.08);
98
+ }
99
+ .drag-dragging {
100
+ opacity: 0.8;
101
+ background: #fff;
102
+ box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
103
+ border-radius: 4px;
104
+ z-index: 1000;
105
+ }
84
106
  </style>
@@ -3,23 +3,24 @@
3
3
  <slot>
4
4
  <button ui-btn="@a s case :border"><i class="icon icon-dropdown"></i></button>
5
5
  </slot>
6
- </div>
7
- <Teleport to="#ifollow" v-if="$slots.tips">
8
- <div
9
- ref="tip"
10
- :class="tipClass"
11
- :style="`position: fixed; pointer-events: none; ${tipStyle}`"
12
- ui-tips="@a"
13
- :ui-tips-view="state.show ? 1 : 0"
14
- @mouseover="hovershow"
15
- @mouseout="hoverhide"
16
- >
17
- <div ref="box" :ui-tips-box="state.pos" :class="tipBoxClass" :style="tipBoxStyle" @mousedown="downdom">
18
- <slot name="tips"></slot>
19
- <div v-if="arrow" ui-tips-arrow="" v-bind="arrow"></div>
6
+ <Teleport to="#ifollow" v-if="$slots.tips">
7
+ <div
8
+ ref="tip"
9
+ :class="tipClass"
10
+ :style="`position: fixed; pointer-events: none; ${tipStyle}`"
11
+ ui-tips="@a"
12
+ :ui-tips-view="state.show ? 1 : 0"
13
+ @mouseover="hovershow"
14
+ @mouseout="hoverhide"
15
+ @click="clickhide"
16
+ >
17
+ <div ref="box" :ui-tips-box="state.pos" :class="tipBoxClass" :style="tipBoxStyle" @mousedown="downdom">
18
+ <slot name="tips"></slot>
19
+ <div v-if="arrow" ui-tips-arrow="" v-bind="arrow"></div>
20
+ </div>
20
21
  </div>
21
- </div>
22
- </Teleport>
22
+ </Teleport>
23
+ </div>
23
24
  </template>
24
25
  <script setup lang="ts">
25
26
  import { reactive, ref, onMounted, onUnmounted, watch } from 'vue';
@@ -46,6 +47,7 @@
46
47
  tipBoxClass?: string;
47
48
  tipBoxStyle?: string;
48
49
  arrow?: any;
50
+ clickTipHide?: boolean;
49
51
  }
50
52
 
51
53
  // 入参
@@ -54,12 +56,13 @@
54
56
  pos: 'bl',
55
57
  event: 'click',
56
58
  btnClass: 'dib',
57
- btnStyle: 'dib',
59
+ btnStyle: '',
58
60
  tipClass: '',
59
61
  tipStyle: '',
60
62
  tipBoxClass: '',
61
63
  tipBoxStyle: '',
62
- arrow: {}
64
+ arrow: {},
65
+ clickTipHide: false,
63
66
  });
64
67
 
65
68
  const dom: any = ref(null);
@@ -70,7 +73,7 @@
70
73
  show: 0,
71
74
  pos: props.pos,
72
75
  hover: 0,
73
- tipdom: false
76
+ tipdom: false,
74
77
  });
75
78
 
76
79
  const showTimer: any = ref(null);
@@ -89,7 +92,7 @@
89
92
  state.show = 0;
90
93
  }, 100);
91
94
  }
92
- }
95
+ },
93
96
  );
94
97
 
95
98
  // 开关
@@ -109,7 +112,7 @@
109
112
  }
110
113
  emits('update:modelValue', state.show);
111
114
  },
112
- { deep: true }
115
+ { deep: true },
113
116
  );
114
117
 
115
118
  const hovershow = () => {
@@ -124,6 +127,12 @@
124
127
  }
125
128
  };
126
129
 
130
+ const clickhide = () => {
131
+ if (props.clickTipHide) {
132
+ state.show = 0;
133
+ }
134
+ };
135
+
127
136
  const show = () => {
128
137
  state.show = 1;
129
138
  };
@@ -199,13 +208,13 @@
199
208
  ex.value.remove();
200
209
  }
201
210
  }
202
- }
211
+ },
203
212
  );
204
213
 
205
214
  defineExpose({
206
215
  toggle,
207
216
  show,
208
217
  hide,
209
- cancel
218
+ cancel,
210
219
  });
211
220
  </script>