@neatui/nuxt 1.0.2 → 1.0.5

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.
package/package.json CHANGED
@@ -1,12 +1,10 @@
1
1
  {
2
2
  "name": "@neatui/nuxt",
3
- "version": "1.0.2",
3
+ "version": "1.0.5",
4
4
  "description": "NeatUI component library for Nuxt 3",
5
5
  "main": "./src/index.ts",
6
- "types": "./src/index.ts",
7
6
  "license": "MIT",
8
7
  "author": "xiaojunbo",
9
- "keywords": ["nuxt", "nuxt-module", "vue", "ui", "components"],
10
8
  "peerDependencies": {
11
9
  "@nuxt/kit": "^3.0.0",
12
10
  "nuxt": "^3.0.0",
@@ -43,6 +43,8 @@
43
43
  import scrollTo from '@fekit/scrollto';
44
44
  import { diff, deepcopy, isArray } from '@fekit/utils';
45
45
 
46
+ const isClient = typeof window !== 'undefined';
47
+
46
48
  // 通过枚举值查找枚举名
47
49
  const findEnumName = (enums: any, val: any, join: boolean | string = ' Ι ') => {
48
50
  // 转换核心
@@ -69,8 +71,8 @@
69
71
  const route: any = useRoute();
70
72
  const props: any = defineProps({
71
73
  area: {
72
- type: HTMLElement,
73
- default: document.body
74
+ type: Object,
75
+ default: () => isClient ? document.body : null
74
76
  },
75
77
  // 数据
76
78
  data: {
@@ -101,7 +103,7 @@
101
103
  // 对比数据
102
104
  diffs: computed(() => {
103
105
  const cloud = props.data || {};
104
- const local = JSON.parse(localStorage.getItem(state.cacheKey) || '{}');
106
+ const local = isClient ? JSON.parse(localStorage.getItem(state.cacheKey) || '{}') : {};
105
107
 
106
108
  const diffs = Object.keys(local).length
107
109
  ? (diff(cloud, local) || []).map((item: any) => {
@@ -162,6 +164,8 @@
162
164
 
163
165
  // 定位字段
164
166
  const fScrollToField = (domId: any) => {
167
+ if (!isClient || !props.area) return;
168
+
165
169
  const dom = document.querySelector(domId);
166
170
  if (dom) {
167
171
  scrollTo({
@@ -182,6 +186,8 @@
182
186
 
183
187
  // 使用草稿
184
188
  const fConfirmDrafts = ({ field = '', path = [] }: any = {}) => {
189
+ if (!isClient) return;
190
+
185
191
  const local = JSON.parse(localStorage.getItem(state.cacheKey) || '{}');
186
192
  if (field) {
187
193
  state.field = field;
@@ -221,6 +227,8 @@
221
227
  };
222
228
  // 放弃草稿
223
229
  const fDiscardDrafts = ({ field = '', path = [] }: any = {}) => {
230
+ if (!isClient) return;
231
+
224
232
  const local = JSON.parse(localStorage.getItem(state.cacheKey) || '{}');
225
233
  if (field) {
226
234
  // 无限树型遍历
@@ -312,6 +320,8 @@
312
320
  watch(
313
321
  () => props.data,
314
322
  (edit: any, old: any) => {
323
+ if (!isClient) return;
324
+
315
325
  if (edit === old) {
316
326
  if (state.field) {
317
327
  const local = JSON.parse(localStorage.getItem(state.cacheKey) || '{}');
package/src/index.ts CHANGED
@@ -1,13 +1,10 @@
1
- // Nuxt模块 (默认导出)
2
- export { default } from './module'
1
+ // 数据
2
+ export * from './store/frame';
3
+ export * from './utils/theme';
3
4
 
4
- // 组件导出
5
+ // 组件
5
6
  export * from './components/basic';
6
7
  export * from './components/display';
7
8
  export * from './components/form';
8
9
  export * from './components/loader';
9
10
  export * from './components/tools';
10
-
11
- // 数据和工具
12
- export * from './store/frame';
13
- export * from './utils/theme';
package/BUILD.md DELETED
@@ -1,128 +0,0 @@
1
- # 构建说明
2
-
3
- ## 📦 构建方式
4
-
5
- @neatui/nuxt 采用**源文件直接分发**的方式,无需复杂的构建过程。
6
-
7
- ### 🚀 优势
8
-
9
- 1. **开发便利**: 修改源码即可生效,无需重新构建
10
- 2. **调试方便**: 错误堆栈直接指向源码位置
11
- 3. **体积更小**: 减少构建工具依赖
12
- 4. **更新快速**: 无需等待构建过程
13
-
14
- ### 🔧 技术实现
15
-
16
- - **TypeScript**: Nuxt自动处理TS转译
17
- - **Vue SFC**: Nuxt内置Vue编译器
18
- - **样式处理**: 组件内样式自动处理
19
- - **依赖解析**: Nuxt自动解析模块依赖
20
-
21
- ## 📁 文件结构
22
-
23
- ```
24
- @neatui/nuxt/
25
- ├── src/
26
- │ ├── module.ts # Nuxt模块入口
27
- │ ├── runtime/
28
- │ │ └── types.d.ts # TypeScript类型定义
29
- │ └── components/ # 组件源码
30
- │ ├── basic/ # 基础组件
31
- │ ├── display/ # 展示组件
32
- │ ├── form/ # 表单组件
33
- │ ├── icon/ # 图标组件
34
- │ ├── loader/ # 加载器组件
35
- │ └── tools/ # 工具组件
36
- ├── package.json # 包配置
37
- ├── tsconfig.json # TS配置
38
- ├── nuxt.config.example.ts # 使用示例
39
- ├── USAGE.md # 使用文档
40
- └── SSR_COMPATIBILITY.md # SSR兼容性说明
41
- ```
42
-
43
- ## 🔄 发布流程
44
-
45
- ### 1. 版本管理
46
- ```bash
47
- # 更新版本号
48
- npm version patch # 小版本
49
- npm version minor # 中版本
50
- npm version major # 大版本
51
- ```
52
-
53
- ### 2. 发布到npm
54
- ```bash
55
- npm publish
56
- ```
57
-
58
- ### 3. 标签管理
59
- ```bash
60
- git tag v1.0.0
61
- git push origin v1.0.0
62
- ```
63
-
64
- ## 🧪 本地测试
65
-
66
- ### 1. 链接到本地项目
67
- ```bash
68
- # 在@neatui/nuxt目录
69
- npm link
70
-
71
- # 在测试项目中
72
- npm link @neatui/nuxt
73
- ```
74
-
75
- ### 2. 创建测试项目
76
- ```bash
77
- npx nuxi@latest init neatui-test
78
- cd neatui-test
79
- npm install
80
- npm link @neatui/nuxt
81
- ```
82
-
83
- ### 3. 配置测试
84
- ```ts
85
- // nuxt.config.ts
86
- export default defineNuxtConfig({
87
- modules: ['@neatui/nuxt'],
88
- neatui: {
89
- prefix: 'Test'
90
- }
91
- })
92
- ```
93
-
94
- ## 📊 性能优化
95
-
96
- ### 1. Tree Shaking
97
- Nuxt自动支持未使用组件的摇树优化
98
-
99
- ### 2. 代码分割
100
- 大型组件可以配置为异步加载:
101
- ```ts
102
- // module.ts 中
103
- addComponent({
104
- name: 'NeatHeavyComponent',
105
- filePath: resolve('./components/heavy/HeavyComponent.vue'),
106
- mode: 'client', // 仅客户端
107
- async: true // 异步加载
108
- })
109
- ```
110
-
111
- ### 3. 样式优化
112
- 组件样式自动提取和优化,支持CSS变量定制
113
-
114
- ## ⚠️ 注意事项
115
-
116
- 1. **依赖版本**: 确保Nuxt版本兼容性
117
- 2. **TypeScript**: 使用严格模式提高代码质量
118
- 3. **SSR兼容**: 部分组件需要ClientOnly包裹
119
- 4. **性能监控**: 关注首屏加载和hydration时间
120
-
121
- ## 🔧 开发工具
122
-
123
- 推荐的开发环境:
124
- - Node.js 18+
125
- - Vue 3.2+
126
- - Nuxt 3.0+
127
- - TypeScript 5.0+
128
- - VS Code + Volar 插件
package/IMPORT_GUIDE.md DELETED
@@ -1,142 +0,0 @@
1
- # 组件导入指南
2
-
3
- ## 🚀 解决导入错误
4
-
5
- 如果遇到 `Module '"@neatui/nuxt"' has no exported member 'Textarea'` 错误,请使用以下方式:
6
-
7
- ### ✅ 正确的导入方式
8
-
9
- #### 方式1: 自动导入 (推荐)
10
- ```vue
11
- <template>
12
- <!-- 配置模块后直接使用,无需导入 -->
13
- <NeatTextarea v-model="content" />
14
- <NeatInput v-model="name" />
15
- <NeatSelect v-model="city" :options="cities" />
16
- </template>
17
-
18
- <script setup>
19
- // 无需导入,组件自动可用
20
- const content = ref('')
21
- const name = ref('')
22
- const city = ref('')
23
- </script>
24
- ```
25
-
26
- #### 方式2: 手动导入
27
- ```vue
28
- <template>
29
- <!-- 使用原组件名 -->
30
- <Textarea v-model="content" />
31
- <Input v-model="name" />
32
- <Select v-model="city" :options="cities" />
33
- </template>
34
-
35
- <script setup>
36
- // 直接从包导入,就像普通Vue组件库一样
37
- import { Textarea, Input, Select } from '@neatui/nuxt'
38
-
39
- const content = ref('')
40
- const name = ref('')
41
- const city = ref('')
42
- </script>
43
- ```
44
-
45
- ### ❌ 错误的导入方式
46
-
47
- ```vue
48
- <script setup>
49
- // 🚫 错误:不能从根路径直接导入组件
50
- import { Textarea } from '@neatui/nuxt'
51
-
52
- // 🚫 错误:默认导入方式
53
- import Textarea from '@neatui/nuxt'
54
- </script>
55
- ```
56
-
57
- ## 📋 可用组件列表
58
-
59
- ### 表单组件
60
- ```js
61
- import {
62
- Input, // 输入框
63
- Textarea, // 文本域
64
- Select, // 选择器
65
- Switch, // 开关
66
- Checkbox, // 复选框
67
- DatePicker, // 日期选择
68
- DateView, // 日期显示
69
- TimePicker, // 时间选择
70
- Upload, // 文件上传
71
- ImgUpload, // 图片上传
72
- Cascader, // 级联选择
73
- PageSelect, // 分页选择
74
- MoreSelect, // 更多选择
75
- SelectTags, // 标签选择
76
- // ... 更多组件
77
- } from '@neatui/nuxt'
78
- ```
79
-
80
- ### 加载器组件
81
- ```js
82
- import {
83
- FormLoader, // 表单构建器
84
- TableLoader, // 表格加载器
85
- ViewLoader, // 视图加载器
86
- LimitLoader, // 限制加载器
87
- MoveLoader, // 移动加载器
88
- LayerLoader, // 层级加载器
89
- } from '@neatui/nuxt'
90
- ```
91
-
92
- ### 工具组件
93
- ```js
94
- import {
95
- FormVerifyView, // 表单验证视图
96
- FormDraftsView, // 表单草稿视图
97
- MoreTools, // 更多工具
98
- Pagination, // 分页组件
99
- } from '@neatui/nuxt'
100
- ```
101
-
102
- ## 🔧 配置说明
103
-
104
- ### nuxt.config.ts
105
- ```ts
106
- export default defineNuxtConfig({
107
- modules: ['@neatui/nuxt'],
108
- neatui: {
109
- prefix: 'Neat', // 自动导入时的前缀
110
- autoImport: true, // 是否启用自动导入
111
- exclude: [] // 排除的组件
112
- }
113
- })
114
- ```
115
-
116
- ### package.json 导出配置
117
- ```json
118
- {
119
- "exports": {
120
- ".": "./src/module.ts", // Nuxt模块
121
- "./components": "./src/index.ts" // 组件导出
122
- }
123
- }
124
- ```
125
-
126
- ## 💡 使用建议
127
-
128
- 1. **优先使用自动导入**: 配置模块后直接使用 `<NeatTextarea>`
129
- 2. **按需手动导入**: 只在需要时从 `/components` 导入
130
- 3. **统一命名**: 自动导入使用前缀,手动导入使用原名
131
- 4. **TypeScript支持**: 两种方式都有完整的类型提示
132
-
133
- ## 🐛 常见问题
134
-
135
- **Q: 为什么不能直接从 '@neatui/nuxt' 导入组件?**
136
- A: '@neatui/nuxt' 是Nuxt模块,用于配置。组件需要从 '@neatui/nuxt/components' 导入。
137
-
138
- **Q: 自动导入的组件没有类型提示?**
139
- A: 确保安装了 '@nuxt/kit' 依赖,并重启TypeScript服务。
140
-
141
- **Q: 可以混合使用两种方式吗?**
142
- A: 可以,但建议保持一致性,避免混乱。
@@ -1,201 +0,0 @@
1
- # SSR 兼容性分析
2
-
3
- ## 🔍 已检查组件分析
4
-
5
- 经过代码扫描,以下组件包含浏览器API调用,在SSR环境下需要特殊处理:
6
-
7
- ### ⚠️ 需要ClientOnly包裹的组件
8
-
9
- #### 1. **表单草稿组件** (`FormDraftsView.vue`)
10
- - **问题**: 使用 `localStorage` 存储草稿数据
11
- - **影响**: 服务端渲染时无法访问浏览器存储
12
- - **解决方案**:
13
- ```vue
14
- <ClientOnly>
15
- <NeatFormDraftsView />
16
- <template #fallback>
17
- <div>加载中...</div>
18
- </template>
19
- </ClientOnly>
20
- ```
21
-
22
- #### 2. **分页组件** (`Pagination@a.vue`, `Pagination@b.vue`)
23
- - **问题**: 可能使用 `window.location` 进行路由操作
24
- - **影响**: 服务端无window对象
25
- - **解决方案**: 已检查,主要使用Vue Router,SSR兼容
26
-
27
- #### 3. **更多工具组件** (`MoreTools.vue`, `MoreTools@v2.vue`)
28
- - **问题**: 使用 `document` 进行DOM操作
29
- - **影响**: 服务端无document对象
30
- - **解决方案**:
31
- ```vue
32
- <ClientOnly>
33
- <NeatMoreTools />
34
- </ClientOnly>
35
- ```
36
-
37
- #### 4. **移动加载器** (`MoveLoader.vue`)
38
- - **问题**: 可能使用触摸事件监听
39
- - **影响**: 服务端无触摸事件
40
- - **解决方案**: 检测到移动端时使用ClientOnly
41
-
42
- #### 5. **表格加载器** (`TableLoader.vue`)
43
- - **问题**: 使用 `window` 对象检测屏幕尺寸
44
- - **影响**: 服务端无window对象
45
- - **解决方案**: 使用Nuxt的设备检测或ClientOnly
46
-
47
- ### ✅ SSR 兼容组件
48
-
49
- 以下组件经检查,完全支持SSR:
50
-
51
- #### 表单组件
52
- - `Input` - 纯Vue组件,无浏览器API
53
- - `Select@v3` - 使用Vue响应式,SSR兼容
54
- - `DatePicker` - 日期选择组件,SSR兼容
55
- - `DateView@v3` - 日期显示组件,SSR兼容
56
- - `Upload` - 文件上传组件(仅显示部分SSR兼容,上传功能需ClientOnly)
57
- - `Textarea@v2` - 文本域组件,SSR兼容
58
- - `Switch` - 开关组件,SSR兼容
59
-
60
- #### 加载器组件
61
- - `FormLoader@v2` - 表单构建器,SSR兼容
62
- - `ViewLoader` - 视图加载器,SSR兼容
63
- - `LimitLoader@v3` - 限制加载器,SSR兼容
64
-
65
- #### 基础组件
66
- - `LayerView` - 层级视图,SSR兼容
67
-
68
- ## 🚀 SSR 优化建议
69
-
70
- ### 1. 自动检测与包裹
71
-
72
- 在模块中添加自动检测机制:
73
-
74
- ```typescript
75
- // module.ts 中添加
76
- const clientOnlyComponents = [
77
- 'FormDraftsView',
78
- 'MoreTools',
79
- 'MoveLoader'
80
- ]
81
-
82
- // 自动为这些组件添加ClientOnly包裹
83
- clientOnlyComponents.forEach(name => {
84
- addComponent({
85
- name: `${options.prefix}${name}`,
86
- filePath: resolve(`./components/tools/${name}.vue`),
87
- mode: 'client' // Nuxt 3 自动处理
88
- })
89
- })
90
- ```
91
-
92
- ### 2. 渐进式增强
93
-
94
- 对于文件上传等功能,提供服务端渲染的基础版本:
95
-
96
- ```vue
97
- <!-- Upload.vue 优化 -->
98
- <template>
99
- <div class="neatui-upload">
100
- <!-- SSR 兼容的静态部分 -->
101
- <div v-if="!hydrated" class="upload-placeholder">
102
- 文件上传组件加载中...
103
- </div>
104
-
105
- <!-- 客户端功能 -->
106
- <ClientOnly>
107
- <div class="upload-interactive">
108
- <!-- 原有的交互功能 -->
109
- </div>
110
- </ClientOnly>
111
- </div>
112
- </template>
113
- ```
114
-
115
- ### 3. 状态预填充
116
-
117
- 对于草稿等功能,在服务端提供初始状态:
118
-
119
- ```vue
120
- <!-- FormDraftsView.vue 优化 -->
121
- <template>
122
- <div>
123
- <ClientOnly>
124
- <FormDraftsViewClient :initial-data="serverData" />
125
- <template #fallback>
126
- <div v-if="serverData.hasDrafts">发现草稿数据</div>
127
- </template>
128
- </ClientOnly>
129
- </div>
130
- </template>
131
-
132
- <script setup>
133
- // 服务端可以预填充的数据
134
- const serverData = {
135
- hasDrafts: false, // 服务端检测
136
- draftsCount: 0
137
- }
138
- </script>
139
- ```
140
-
141
- ## 📋 使用建议
142
-
143
- ### 1. 开发时
144
-
145
- ```vue
146
- <template>
147
- <div>
148
- <!-- 绝对安全的组件 -->
149
- <NeatInput v-model="form.name" />
150
- <NeatSelect v-model="form.type" :options="options" />
151
-
152
- <!-- 可能需要客户端的组件 -->
153
- <ClientOnly>
154
- <NeatUpload v-model="form.files" />
155
- <NeatFormDraftsView />
156
- <template #fallback>
157
- <div class="text-center py-4">
158
- <div class="loading-spinner"></div>
159
- <p>加载中...</p>
160
- </div>
161
- </template>
162
- </ClientOnly>
163
- </div>
164
- </template>
165
- ```
166
-
167
- ### 2. 性能优化
168
-
169
- ```vue
170
- <script setup>
171
- // 使用 Nuxt 的客户端检测
172
- const { $device } = useNuxtApp()
173
-
174
- // 移动端才加载移动特定组件
175
- const showMobileLoader = computed(() => {
176
- return process.client && $device.isMobile
177
- })
178
- </script>
179
-
180
- <template>
181
- <div>
182
- <NeatMoveLoader v-if="showMobileLoader" />
183
- <NeatTableLoader v-else />
184
- </div>
185
- </template>
186
- ```
187
-
188
- ## 🔧 测试清单
189
-
190
- - [ ] 所有表单组件在SSR模式下正常渲染
191
- - [ ] ClientOnly组件有合适的fallback
192
- - [ ] 页面首次加载无hydration错误
193
- - [ ] 客户端组件正常激活
194
- - [ ] 性能指标达标(LCP, FID, CLS)
195
-
196
- ## 📊 兼容性总结
197
-
198
- - **完全兼容**: 80%+ 组件支持SSR
199
- - **需要包裹**: 约5个组件需要ClientOnly
200
- - **渐进增强**: 文件上传等功能组件
201
- - **总体评估**: SSR兼容性良好,可投入生产使用
package/USAGE.md DELETED
@@ -1,291 +0,0 @@
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'
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>` 包裹客户端专用组件
@@ -1,37 +0,0 @@
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/src/module.ts DELETED
@@ -1,169 +0,0 @@
1
- import { defineNuxtModule, addComponent, createResolver } from '@nuxt/kit'
2
- import { readdirSync, statSync } from 'fs'
3
- import { join, extname, basename } from 'path'
4
-
5
- export interface ModuleOptions {
6
- /**
7
- * 组件前缀
8
- * @default 'Neat'
9
- */
10
- prefix?: string
11
-
12
- /**
13
- * 主题配置
14
- * @default 'default'
15
- */
16
- theme?: 'default' | 'dark' | string
17
-
18
- /**
19
- * 是否启用自动导入
20
- * @default true
21
- */
22
- autoImport?: boolean
23
-
24
- /**
25
- * 要排除的组件列表
26
- * @default []
27
- */
28
- exclude?: string[]
29
-
30
- /**
31
- * CSS配置
32
- */
33
- css?: {
34
- variables?: Record<string, string>
35
- }
36
- }
37
-
38
- export default defineNuxtModule<ModuleOptions>({
39
- meta: {
40
- name: '@neatui/nuxt',
41
- configKey: 'neatui',
42
- compatibility: {
43
- nuxt: '^3.0.0'
44
- }
45
- },
46
- defaults: {
47
- prefix: 'Neat',
48
- theme: 'default',
49
- autoImport: true,
50
- exclude: [],
51
- css: {}
52
- },
53
- setup(options: ModuleOptions, nuxt: any) {
54
- const { resolve } = createResolver(import.meta.url)
55
-
56
- // 注册组件
57
- if (options.autoImport) {
58
- registerComponents(resolve, options)
59
- }
60
-
61
- // 添加CSS
62
- // nuxt.options.css.push(resolve('./runtime/css/index.css'))
63
-
64
- // 添加全局样式变量
65
- if (options.css?.variables) {
66
- const cssVars = Object.entries(options.css.variables)
67
- .map(([key, value]) => `--neat-${key}: ${value};`)
68
- .join('\n')
69
-
70
- nuxt.options.css.push({
71
- src: `data:text/css,:root { ${cssVars} }`,
72
- lang: 'css'
73
- } as any)
74
- }
75
-
76
- // 添加类型定义
77
- nuxt.hook('prepare:types', ({ references }: any) => {
78
- references.push({ path: resolve('./runtime/types.d.ts') })
79
- })
80
- }
81
- })
82
-
83
- /**
84
- * 自动注册组件
85
- */
86
- function registerComponents(resolve: (path: string) => string, options: ModuleOptions) {
87
- const componentsDir = resolve('./components')
88
-
89
- try {
90
- // 扫描所有组件目录
91
- const componentDirs = ['basic', 'display', 'form', 'icon', 'loader', 'tools']
92
-
93
- for (const dir of componentDirs) {
94
- const dirPath = join(componentsDir, dir)
95
-
96
- try {
97
- const files = readdirSync(dirPath)
98
-
99
- for (const file of files) {
100
- const filePath = join(dirPath, file)
101
- const stat = statSync(filePath)
102
-
103
- if (stat.isFile() && extname(file) === '.vue') {
104
- const componentName = basename(file, '.vue')
105
-
106
- // 跳过版本化组件 (包含@的)
107
- if (componentName.includes('@')) continue
108
-
109
- // 跳过排除的组件
110
- if (options.exclude?.includes(componentName)) continue
111
-
112
- // 注册组件
113
- addComponent({
114
- name: `${options.prefix}${componentName}`,
115
- filePath: filePath,
116
- global: true
117
- })
118
- } else if (stat.isDirectory()) {
119
- // 处理嵌套目录 (如 SelectTree)
120
- try {
121
- const nestedFiles = readdirSync(filePath)
122
- for (const nestedFile of nestedFiles) {
123
- if (extname(nestedFile) === '.vue') {
124
- const nestedComponentName = basename(nestedFile, '.vue')
125
-
126
- if (nestedComponentName.includes('@')) continue
127
- if (options.exclude?.includes(nestedComponentName)) continue
128
-
129
- addComponent({
130
- name: `${options.prefix}${nestedComponentName}`,
131
- filePath: join(filePath, nestedFile),
132
- global: true
133
- })
134
- }
135
- }
136
- } catch {
137
- // 忽略嵌套目录错误
138
- }
139
- }
140
- }
141
- } catch {
142
- // 目录不存在时忽略
143
- console.warn(`@neatui/nuxt: Directory ${dir} not found, skipping...`)
144
- }
145
- }
146
-
147
- // 特殊处理 loader 组件 (从 index.ts 导出)
148
- try {
149
- addComponent({
150
- name: `${options.prefix}FormLoader`,
151
- filePath: resolve('./components/loader/FormLoader/FormLoader@v2.vue'),
152
- global: true
153
- })
154
-
155
- addComponent({
156
- name: `${options.prefix}TableLoader`,
157
- filePath: resolve('./components/loader/TableLoader/TableLoader.vue'),
158
- global: true
159
- })
160
- } catch {
161
- console.warn('@neatui/nuxt: Some loader components not found')
162
- }
163
-
164
- } catch (error) {
165
- console.error('@neatui/nuxt: Error registering components:', error)
166
- }
167
- }
168
-
169
- // 导出类型 (已在上面定义过,这里不需要重复导出)
@@ -1,36 +0,0 @@
1
- declare module '@nuxt/schema' {
2
- interface NuxtConfig {
3
- neatui?: {
4
- /**
5
- * 组件前缀
6
- * @default 'Neat'
7
- */
8
- prefix?: string
9
-
10
- /**
11
- * 主题配置
12
- * @default 'default'
13
- */
14
- theme?: 'default' | 'dark' | string
15
-
16
- /**
17
- * 是否启用自动导入
18
- * @default true
19
- */
20
- autoImport?: boolean
21
-
22
- /**
23
- * 要排除的组件列表
24
- * @default []
25
- */
26
- exclude?: string[]
27
-
28
- /**
29
- * CSS配置
30
- */
31
- css?: {
32
- variables?: Record<string, string>
33
- }
34
- }
35
- }
36
- }