vue2server7 7.0.114 → 7.0.116

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,6 +1,6 @@
1
1
  {
2
2
  "name": "vue2server7",
3
- "version": "7.0.114",
3
+ "version": "7.0.116",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "dev": "nodemon --watch src --ext ts --exec \"ts-node src/app.ts\"",
package/1.js DELETED
@@ -1,218 +0,0 @@
1
- import express from "express";
2
- import cors from "cors";
3
- import axios from "axios";
4
- import dotenv from "dotenv";
5
-
6
- dotenv.config();
7
-
8
- const app = express();
9
-
10
- app.use(cors());
11
- app.use(express.json({ limit: "20mb" }));
12
-
13
- const PORT = Number(process.env.PORT || 3000);
14
- const TARGET_URL = process.env.TARGET_URL;
15
- const TARGET_API_KEY = process.env.TARGET_API_KEY;
16
- const TARGET_APP_TAG = process.env.TARGET_APP_TAG || "proxyai";
17
- const TARGET_MODEL = process.env.TARGET_MODEL || "qwen15-32b";
18
- const TARGET_TEMPERATURE = Number(process.env.TARGET_TEMPERATURE || 0.1);
19
- const TARGET_MAX_TOKENS = Number(process.env.TARGET_MAX_TOKENS || 20000);
20
-
21
- function normalizeMessages(messages) {
22
- if (!Array.isArray(messages)) return [];
23
-
24
- return messages.map((item) => {
25
- // Continue / OpenAI 标准格式直接透传
26
- if (typeof item?.content === "string") {
27
- return {
28
- role: item.role || "user",
29
- content: item.content
30
- };
31
- }
32
-
33
- // 兼容 content 为数组的情况
34
- if (Array.isArray(item?.content)) {
35
- const text = item.content
36
- .map((part) => {
37
- if (typeof part === "string") return part;
38
- if (part?.type === "text") return part.text || "";
39
- return "";
40
- })
41
- .join("");
42
-
43
- return {
44
- role: item.role || "user",
45
- content: text
46
- };
47
- }
48
-
49
- return {
50
- role: item?.role || "user",
51
- content: ""
52
- };
53
- });
54
- }
55
-
56
- function buildOpenAIResponse({ model, content, usage }) {
57
- return {
58
- id: `chatcmpl-${Date.now()}`,
59
- object: "chat.completion",
60
- created: Math.floor(Date.now() / 1000),
61
- model,
62
- choices: [
63
- {
64
- index: 0,
65
- message: {
66
- role: "assistant",
67
- content: content ?? ""
68
- },
69
- finish_reason: "stop"
70
- }
71
- ],
72
- usage: usage || {
73
- prompt_tokens: 0,
74
- completion_tokens: 0,
75
- total_tokens: 0
76
- }
77
- };
78
- }
79
-
80
- app.get("/health", (req, res) => {
81
- res.json({ ok: true });
82
- });
83
-
84
- app.get("/v1/models", (req, res) => {
85
- res.json({
86
- object: "list",
87
- data: [
88
- {
89
- id: TARGET_MODEL,
90
- object: "model",
91
- created: Math.floor(Date.now() / 1000),
92
- owned_by: "continue-proxy"
93
- }
94
- ]
95
- });
96
- });
97
-
98
- app.post("/v1/chat/completions", async (req, res) => {
99
- const requestId = `req_${Date.now()}`;
100
-
101
- try {
102
- const incoming = req.body || {};
103
- const incomingMessages = normalizeMessages(incoming.messages);
104
-
105
- // 严格参考 ProxyAI 配置来组织上游 body
106
- const upstreamBody = {
107
- stream: typeof incoming.stream === "boolean" ? incoming.stream : true,
108
- model: incoming.model || TARGET_MODEL,
109
- messages: incomingMessages,
110
- temperature:
111
- typeof incoming.temperature === "number"
112
- ? incoming.temperature
113
- : TARGET_TEMPERATURE,
114
- max_tokens:
115
- typeof incoming.max_tokens === "number"
116
- ? incoming.max_tokens
117
- : typeof incoming.max_completion_tokens === "number"
118
- ? incoming.max_completion_tokens
119
- : TARGET_MAX_TOKENS
120
- };
121
-
122
- const upstreamHeaders = {
123
- Authorization: `Bearer ${TARGET_API_KEY}`,
124
- "X-LLM-Application-Tag": TARGET_APP_TAG,
125
- "Content-Type": "application/json"
126
- };
127
-
128
- console.log(`\n[${requestId}] ===== incoming body =====`);
129
- console.log(JSON.stringify(incoming, null, 2));
130
-
131
- console.log(`\n[${requestId}] ===== upstream headers =====`);
132
- console.log({
133
- Authorization: "Bearer ***",
134
- "X-LLM-Application-Tag": TARGET_APP_TAG,
135
- "Content-Type": "application/json"
136
- });
137
-
138
- console.log(`\n[${requestId}] ===== upstream body =====`);
139
- console.log(JSON.stringify(upstreamBody, null, 2));
140
-
141
- // 先按非流式转,最稳
142
- // 因为很多内网服务 stream=true 时返回格式不一定被 Continue 正确识别
143
- const forceNonStream = true;
144
- if (forceNonStream) {
145
- upstreamBody.stream = false;
146
- }
147
-
148
- const upstreamResp = await axios.post(TARGET_URL, upstreamBody, {
149
- headers: upstreamHeaders,
150
- timeout: 120000,
151
- validateStatus: () => true
152
- });
153
-
154
- console.log(`\n[${requestId}] ===== upstream status =====`);
155
- console.log(upstreamResp.status);
156
-
157
- console.log(`\n[${requestId}] ===== upstream data =====`);
158
- console.log(
159
- typeof upstreamResp.data === "string"
160
- ? upstreamResp.data
161
- : JSON.stringify(upstreamResp.data, null, 2)
162
- );
163
-
164
- if (upstreamResp.status >= 400) {
165
- return res.status(upstreamResp.status).json({
166
- error: {
167
- message:
168
- typeof upstreamResp.data === "string"
169
- ? upstreamResp.data
170
- : JSON.stringify(upstreamResp.data),
171
- type: "upstream_error",
172
- code: upstreamResp.status
173
- }
174
- });
175
- }
176
-
177
- const data = upstreamResp.data;
178
-
179
- // 情况1:上游已经是 OpenAI 格式
180
- if (data?.choices?.[0]?.message?.content !== undefined) {
181
- return res.json(data);
182
- }
183
-
184
- // 情况2:提取常见文本字段
185
- const text =
186
- data?.choices?.[0]?.text ??
187
- data?.data?.content ??
188
- data?.data?.text ??
189
- data?.text ??
190
- data?.reply ??
191
- data?.result ??
192
- "";
193
-
194
- return res.json(
195
- buildOpenAIResponse({
196
- model: upstreamBody.model,
197
- content: text,
198
- usage: data?.usage
199
- })
200
- );
201
- } catch (error) {
202
- console.error("\n===== proxy exception =====");
203
- console.error(error?.message);
204
- console.error(error?.response?.data);
205
-
206
- return res.status(500).json({
207
- error: {
208
- message: error?.message || "proxy internal error",
209
- type: "proxy_internal_error",
210
- code: 500
211
- }
212
- });
213
- }
214
- });
215
-
216
- app.listen(PORT, () => {
217
- console.log(`Proxy server running at http://127.0.0.1:${PORT}`);
218
- });
package/2 DELETED
@@ -1,6 +0,0 @@
1
- .el-button + .el-button,
2
- .el-button + .my-button,
3
- .my-button + .el-button,
4
- .my-button + .my-button {
5
- margin-left: 12px;
6
- }
package/README.md DELETED
@@ -1,13 +0,0 @@
1
- There are a few existing modules similar to Keyv, however Keyv is different because it:
2
-
3
- Isn't bloated
4
- Has a simple Promise based API
5
- Suitable as a TTL based cache or persistent key-value store
6
- Easily embeddable inside another module
7
- Works with any storage that implements the Map API
8
- Handles all JSON types plus Buffer
9
- Supports namespaces
10
- Wide range of efficient, well tested storage adapters
11
- Connection errors are passed through (db failures won't kill your app)
12
- Supports the current active LTS version of Node.js or high
13
-
@@ -1,871 +0,0 @@
1
- # Vue3 项目开发规范
2
-
3
- ## 1. 文档说明
4
-
5
- 本文档用于规范 Vue3 项目的目录结构、代码风格、组件开发、路由管理、状态管理、接口请求、样式编写、Git 提交以及团队协作流程。
6
-
7
- 适用技术栈:
8
-
9
- - Vue 3
10
- - Vite
11
- - TypeScript
12
- - Vue Router
13
- - Pinia
14
- - Axios
15
- - Element Plus / TDesign Vue Next
16
- - ESLint
17
- - Prettier
18
- - Stylelint
19
-
20
- ---
21
-
22
- ## 2. 项目目录规范
23
-
24
- 推荐目录结构:
25
-
26
- ```bash
27
- src
28
- ├── api # 接口请求模块
29
- ├── assets # 静态资源
30
- │ ├── images
31
- │ ├── icons
32
- │ └── fonts
33
- ├── components # 公共组件
34
- ├── composables # 组合式函数
35
- ├── constants # 常量配置
36
- ├── directives # 自定义指令
37
- ├── hooks # 业务 hooks
38
- ├── layouts # 页面布局
39
- ├── plugins # 插件注册
40
- ├── router # 路由配置
41
- │ ├── index.ts
42
- │ └── modules
43
- ├── stores # Pinia 状态管理
44
- ├── styles # 全局样式
45
- ├── types # TypeScript 类型声明
46
- ├── utils # 工具函数
47
- ├── views # 页面模块
48
- ├── App.vue
49
- └── main.ts
50
- ```
51
-
52
- ---
53
-
54
- ## 3. 文件命名规范
55
-
56
- ### 3.1 Vue 组件命名
57
-
58
- 组件文件使用大驼峰命名:
59
-
60
- ```bash
61
- UserCard.vue
62
- UserForm.vue
63
- BaseTable.vue
64
- SearchPanel.vue
65
- ```
66
-
67
- ### 3.2 页面文件命名
68
-
69
- 页面文件建议使用大驼峰命名:
70
-
71
- ```bash
72
- views/user/UserList.vue
73
- views/user/UserDetail.vue
74
- views/system/RoleManage.vue
75
- ```
76
-
77
- ### 3.3 工具文件命名
78
-
79
- 工具文件使用小驼峰命名:
80
-
81
- ```bash
82
- formatDate.ts
83
- storage.ts
84
- request.ts
85
- validate.ts
86
- ```
87
-
88
- ### 3.4 类型文件命名
89
-
90
- 类型文件使用 `.type.ts` 后缀:
91
-
92
- ```bash
93
- user.type.ts
94
- order.type.ts
95
- api.type.ts
96
- ```
97
-
98
- ### 3.5 路由文件命名
99
-
100
- 路由文件使用 `.route.ts` 后缀:
101
-
102
- ```bash
103
- user.route.ts
104
- order.route.ts
105
- system.route.ts
106
- ```
107
-
108
- ---
109
-
110
- ## 4. 代码风格规范
111
-
112
- ### 4.1 统一使用 `<script setup>`
113
-
114
- ```vue
115
- <script setup lang="ts">
116
- import { ref } from 'vue'
117
-
118
- const count = ref(0)
119
-
120
- function handleAdd() {
121
- count.value++
122
- }
123
- </script>
124
-
125
- <template>
126
- <button @click="handleAdd">
127
- {{ count }}
128
- </button>
129
- </template>
130
- ```
131
-
132
- ### 4.2 使用 TypeScript
133
-
134
- 所有 Vue 文件推荐使用:
135
-
136
- ```vue
137
- <script setup lang="ts">
138
- </script>
139
- ```
140
-
141
- ### 4.3 禁止滥用 any
142
-
143
- 不推荐:
144
-
145
- ```ts
146
- const user: any = {}
147
- ```
148
-
149
- 推荐:
150
-
151
- ```ts
152
- interface UserInfo {
153
- id: number
154
- username: string
155
- avatar?: string
156
- }
157
-
158
- const user = ref<UserInfo | null>(null)
159
- ```
160
-
161
- ---
162
-
163
- ## 5. 组件开发规范
164
-
165
- ### 5.1 组件职责单一
166
-
167
- 一个组件只负责一个明确的功能,例如:
168
-
169
- - 用户表格组件只负责展示用户列表
170
- - 搜索组件只负责搜索条件输入
171
- - 弹窗组件只负责表单录入和提交
172
-
173
- ### 5.2 Props 定义规范
174
-
175
- 必须定义 Props 类型。
176
-
177
- ```ts
178
- interface Props {
179
- title: string
180
- loading?: boolean
181
- }
182
-
183
- const props = withDefaults(defineProps<Props>(), {
184
- loading: false
185
- })
186
- ```
187
-
188
- 禁止使用:
189
-
190
- ```ts
191
- defineProps(['title', 'loading'])
192
- ```
193
-
194
- ### 5.3 Emits 定义规范
195
-
196
- 事件名建议使用 kebab-case。
197
-
198
- ```ts
199
- const emit = defineEmits<{
200
- 'submit-form': [value: FormData]
201
- 'update:modelValue': [value: string]
202
- }>()
203
- ```
204
-
205
- ### 5.4 不直接修改 Props
206
-
207
- 错误写法:
208
-
209
- ```ts
210
- props.visible = false
211
- ```
212
-
213
- 正确写法:
214
-
215
- ```ts
216
- const emit = defineEmits<{
217
- 'update:visible': [value: boolean]
218
- }>()
219
-
220
- emit('update:visible', false)
221
- ```
222
-
223
- ---
224
-
225
- ## 6. 页面开发规范
226
-
227
- 页面建议按以下顺序组织:
228
-
229
- 1. import 引入
230
- 2. 类型定义
231
- 3. 响应式数据
232
- 4. 计算属性
233
- 5. 方法函数
234
- 6. 生命周期
235
- 7. 监听器
236
-
237
- 示例:
238
-
239
- ```vue
240
- <script setup lang="ts">
241
- import { onMounted, ref } from 'vue'
242
- import { getUserListApi } from '@/api/user.api'
243
- import type { UserInfo } from '@/types/user.type'
244
-
245
- const loading = ref(false)
246
- const userList = ref<UserInfo[]>([])
247
-
248
- async function getUserList() {
249
- loading.value = true
250
-
251
- try {
252
- const res = await getUserListApi()
253
- userList.value = res.data
254
- } finally {
255
- loading.value = false
256
- }
257
- }
258
-
259
- onMounted(() => {
260
- getUserList()
261
- })
262
- </script>
263
- ```
264
-
265
- ---
266
-
267
- ## 7. 路由规范
268
-
269
- ### 7.1 路由目录
270
-
271
- ```bash
272
- router
273
- ├── index.ts
274
- └── modules
275
- ├── user.route.ts
276
- ├── order.route.ts
277
- └── system.route.ts
278
- ```
279
-
280
- ### 7.2 路由配置示例
281
-
282
- ```ts
283
- import type { RouteRecordRaw } from 'vue-router'
284
-
285
- const userRoutes: RouteRecordRaw[] = [
286
- {
287
- path: '/user',
288
- name: 'User',
289
- component: () => import('@/views/user/UserList.vue'),
290
- meta: {
291
- title: '用户管理',
292
- requiresAuth: true,
293
- permissions: ['user:list']
294
- }
295
- }
296
- ]
297
-
298
- export default userRoutes
299
- ```
300
-
301
- ### 7.3 路由 meta 规范
302
-
303
- ```ts
304
- meta: {
305
- title: '页面标题',
306
- requiresAuth: true,
307
- keepAlive: false,
308
- permissions: ['user:list']
309
- }
310
- ```
311
-
312
- 常用字段说明:
313
-
314
- | 字段 | 说明 |
315
- | --- | --- |
316
- | title | 页面标题 |
317
- | requiresAuth | 是否需要登录 |
318
- | keepAlive | 是否缓存页面 |
319
- | permissions | 页面权限标识 |
320
-
321
- ---
322
-
323
- ## 8. 状态管理规范
324
-
325
- ### 8.1 Store 文件命名
326
-
327
- ```bash
328
- stores/user.store.ts
329
- stores/app.store.ts
330
- stores/permission.store.ts
331
- ```
332
-
333
- ### 8.2 Pinia 示例
334
-
335
- ```ts
336
- import { ref } from 'vue'
337
- import { defineStore } from 'pinia'
338
-
339
- export const useUserStore = defineStore('user', () => {
340
- const token = ref('')
341
- const username = ref('')
342
-
343
- function setToken(value: string) {
344
- token.value = value
345
- }
346
-
347
- function clearUser() {
348
- token.value = ''
349
- username.value = ''
350
- }
351
-
352
- return {
353
- token,
354
- username,
355
- setToken,
356
- clearUser
357
- }
358
- })
359
- ```
360
-
361
- ---
362
-
363
- ## 9. API 请求规范
364
-
365
- ### 9.1 API 目录结构
366
-
367
- ```bash
368
- api
369
- ├── request.ts
370
- ├── user.api.ts
371
- ├── order.api.ts
372
- └── system.api.ts
373
- ```
374
-
375
- ### 9.2 接口命名规范
376
-
377
- 接口函数建议使用动词开头:
378
-
379
- ```ts
380
- getUserList()
381
- getUserDetail()
382
- createUser()
383
- updateUser()
384
- deleteUser()
385
- ```
386
-
387
- ### 9.3 API 示例
388
-
389
- ```ts
390
- import request from './request'
391
- import type { CreateUserDTO, UserListParams } from '@/types/user.type'
392
-
393
- export function getUserListApi(params: UserListParams) {
394
- return request.get('/users', { params })
395
- }
396
-
397
- export function createUserApi(data: CreateUserDTO) {
398
- return request.post('/users', data)
399
- }
400
-
401
- export function updateUserApi(id: number, data: CreateUserDTO) {
402
- return request.put(`/users/${id}`, data)
403
- }
404
-
405
- export function deleteUserApi(id: number) {
406
- return request.delete(`/users/${id}`)
407
- }
408
- ```
409
-
410
- ---
411
-
412
- ## 10. Axios 封装规范
413
-
414
- ```ts
415
- import axios from 'axios'
416
- import type { AxiosError, AxiosResponse } from 'axios'
417
-
418
- const request = axios.create({
419
- baseURL: import.meta.env.VITE_API_BASE_URL,
420
- timeout: 10000
421
- })
422
-
423
- request.interceptors.request.use(config => {
424
- const token = localStorage.getItem('token')
425
-
426
- if (token) {
427
- config.headers.Authorization = `Bearer ${token}`
428
- }
429
-
430
- return config
431
- })
432
-
433
- request.interceptors.response.use(
434
- (response: AxiosResponse) => {
435
- return response.data
436
- },
437
- (error: AxiosError) => {
438
- return Promise.reject(error)
439
- }
440
- )
441
-
442
- export default request
443
- ```
444
-
445
- ---
446
-
447
- ## 11. TypeScript 类型规范
448
-
449
- ### 11.1 通用响应类型
450
-
451
- ```ts
452
- export interface ApiResponse<T = unknown> {
453
- code: number
454
- message: string
455
- data: T
456
- }
457
- ```
458
-
459
- ### 11.2 分页类型
460
-
461
- ```ts
462
- export interface PageParams {
463
- page: number
464
- pageSize: number
465
- }
466
-
467
- export interface PageResult<T> {
468
- list: T[]
469
- total: number
470
- page: number
471
- pageSize: number
472
- }
473
- ```
474
-
475
- ### 11.3 用户类型示例
476
-
477
- ```ts
478
- export interface UserInfo {
479
- id: number
480
- username: string
481
- nickname: string
482
- avatar?: string
483
- status: number
484
- createdAt: string
485
- }
486
-
487
- export interface UserListParams extends PageParams {
488
- keyword?: string
489
- status?: number
490
- }
491
-
492
- export interface CreateUserDTO {
493
- username: string
494
- password: string
495
- nickname: string
496
- }
497
- ```
498
-
499
- ---
500
-
501
- ## 12. 样式规范
502
-
503
- ### 12.1 样式目录
504
-
505
- ```bash
506
- styles
507
- ├── index.scss
508
- ├── reset.scss
509
- ├── variables.scss
510
- ├── mixin.scss
511
- └── transition.scss
512
- ```
513
-
514
- ### 12.2 组件样式
515
-
516
- 组件样式默认使用 scoped。
517
-
518
- ```vue
519
- <style scoped lang="scss">
520
- .user-card {
521
- padding: 16px;
522
- border-radius: 8px;
523
- background-color: #fff;
524
- }
525
- </style>
526
- ```
527
-
528
- ### 12.3 CSS 命名规范
529
-
530
- 推荐使用 BEM 命名。
531
-
532
- ```scss
533
- .user-card {
534
- &__header {
535
- display: flex;
536
- align-items: center;
537
- }
538
-
539
- &__title {
540
- font-size: 18px;
541
- font-weight: 600;
542
- }
543
-
544
- &--active {
545
- border-color: #409eff;
546
- }
547
- }
548
- ```
549
-
550
- ---
551
-
552
- ## 13. 环境变量规范
553
-
554
- ### 13.1 文件命名
555
-
556
- ```bash
557
- .env.development
558
- .env.test
559
- .env.production
560
- ```
561
-
562
- ### 13.2 变量命名
563
-
564
- Vite 项目环境变量必须使用 `VITE_` 前缀。
565
-
566
- ```env
567
- VITE_APP_TITLE=Vue3后台管理系统
568
- VITE_API_BASE_URL=https://api.example.com
569
- VITE_UPLOAD_URL=https://upload.example.com
570
- ```
571
-
572
- ### 13.3 使用方式
573
-
574
- ```ts
575
- const baseURL = import.meta.env.VITE_API_BASE_URL
576
- ```
577
-
578
- ---
579
-
580
- ## 14. 权限规范
581
-
582
- 权限建议分为:
583
-
584
- - 登录权限
585
- - 路由权限
586
- - 菜单权限
587
- - 按钮权限
588
- - 接口权限
589
-
590
- ### 14.1 路由权限
591
-
592
- ```ts
593
- meta: {
594
- requiresAuth: true,
595
- permissions: ['user:list']
596
- }
597
- ```
598
-
599
- ### 14.2 按钮权限
600
-
601
- ```vue
602
- <el-button v-if="hasPermission('user:create')">
603
- 新增用户
604
- </el-button>
605
- ```
606
-
607
- ---
608
-
609
- ## 15. 表单开发规范
610
-
611
- ### 15.1 表单数据
612
-
613
- ```ts
614
- const formData = reactive({
615
- username: '',
616
- password: '',
617
- status: 1
618
- })
619
- ```
620
-
621
- ### 15.2 表单校验
622
-
623
- ```ts
624
- const rules = {
625
- username: [
626
- { required: true, message: '请输入用户名', trigger: 'blur' }
627
- ],
628
- password: [
629
- { required: true, message: '请输入密码', trigger: 'blur' }
630
- ]
631
- }
632
- ```
633
-
634
- ### 15.3 提交规范
635
-
636
- ```ts
637
- async function handleSubmit() {
638
- try {
639
- await formRef.value?.validate()
640
- await createUserApi(formData)
641
- } catch (error) {
642
- console.error(error)
643
- }
644
- }
645
- ```
646
-
647
- ---
648
-
649
- ## 16. 列表页面规范
650
-
651
- 列表页面通常包含:
652
-
653
- - 搜索区域
654
- - 操作按钮区域
655
- - 表格区域
656
- - 分页区域
657
-
658
- 推荐状态命名:
659
-
660
- ```ts
661
- const loading = ref(false)
662
- const tableData = ref([])
663
- const total = ref(0)
664
- const queryParams = reactive({
665
- page: 1,
666
- pageSize: 10,
667
- keyword: ''
668
- })
669
- ```
670
-
671
- ---
672
-
673
- ## 17. 工具函数规范
674
-
675
- 工具函数必须保持职责单一。
676
-
677
- ```ts
678
- export function formatDate(date: string | Date): string {
679
- const d = new Date(date)
680
- return d.toLocaleDateString()
681
- }
682
- ```
683
-
684
- 不建议一个工具函数同时处理多个不相关功能。
685
-
686
- ---
687
-
688
- ## 18. 常量规范
689
-
690
- 常量统一放在 `constants` 目录。
691
-
692
- ```ts
693
- export const USER_STATUS = {
694
- ENABLED: 1,
695
- DISABLED: 0
696
- } as const
697
-
698
- export const USER_STATUS_TEXT = {
699
- [USER_STATUS.ENABLED]: '启用',
700
- [USER_STATUS.DISABLED]: '禁用'
701
- }
702
- ```
703
-
704
- ---
705
-
706
- ## 19. 代码提交规范
707
-
708
- 推荐使用 Conventional Commits。
709
-
710
- ```bash
711
- feat: 新增用户管理页面
712
- fix: 修复登录状态失效问题
713
- docs: 更新项目开发文档
714
- style: 调整页面样式
715
- refactor: 重构接口请求封装
716
- perf: 优化列表加载性能
717
- test: 新增单元测试
718
- chore: 修改构建配置
719
- ```
720
-
721
- 提交类型说明:
722
-
723
- | 类型 | 说明 |
724
- | --- | --- |
725
- | feat | 新功能 |
726
- | fix | 修复问题 |
727
- | docs | 文档修改 |
728
- | style | 样式或格式调整 |
729
- | refactor | 代码重构 |
730
- | perf | 性能优化 |
731
- | test | 测试相关 |
732
- | chore | 构建或工具配置 |
733
-
734
- ---
735
-
736
- ## 20. ESLint 与 Prettier 规范
737
-
738
- ### 20.1 Prettier 配置
739
-
740
- ```json
741
- {
742
- "semi": false,
743
- "singleQuote": true,
744
- "printWidth": 100,
745
- "trailingComma": "none"
746
- }
747
- ```
748
-
749
- ### 20.2 ESLint 规则示例
750
-
751
- ```js
752
- export default [
753
- {
754
- rules: {
755
- 'vue/multi-word-component-names': 'off',
756
- 'no-console': 'warn',
757
- 'no-debugger': 'warn'
758
- }
759
- }
760
- ]
761
- ```
762
-
763
- ---
764
-
765
- ## 21. 性能优化规范
766
-
767
- ### 21.1 路由懒加载
768
-
769
- ```ts
770
- component: () => import('@/views/user/UserList.vue')
771
- ```
772
-
773
- ### 21.2 组件按需加载
774
-
775
- 大型组件、弹窗、图表组件建议按需加载。
776
-
777
- ### 21.3 避免不必要的响应式
778
-
779
- 大数据列表可以使用 `shallowRef`。
780
-
781
- ```ts
782
- const list = shallowRef([])
783
- ```
784
-
785
- ### 21.4 图片优化
786
-
787
- - 图片压缩后再上传
788
- - 小图标优先使用 SVG
789
- - 大图使用懒加载
790
- - 静态资源放入 CDN
791
-
792
- ---
793
-
794
- ## 22. 安全规范
795
-
796
- - 不在前端代码中写死密钥
797
- - 不在仓库中提交 `.env.production`
798
- - 接口请求必须携带必要鉴权信息
799
- - 用户输入内容需要校验
800
- - 富文本内容需要防止 XSS
801
- - 文件上传需要限制类型和大小
802
-
803
- ---
804
-
805
- ## 23. 开发注意事项
806
-
807
- - 组件不要过大,复杂页面要拆分组件
808
- - 接口请求统一放到 `api` 目录
809
- - 公共逻辑抽离到 `composables` 或 `hooks`
810
- - 不要直接操作 DOM,优先使用 Vue 响应式能力
811
- - 列表渲染必须添加唯一 `key`
812
- - 异步请求必须处理 loading 状态
813
- - 删除、提交、重置等危险操作需要二次确认
814
- - 禁止在组件中硬编码接口地址
815
- - 禁止将大量业务逻辑写在模板中
816
-
817
- ---
818
-
819
- ## 24. 推荐 package.json scripts
820
-
821
- ```json
822
- {
823
- "scripts": {
824
- "dev": "vite",
825
- "build": "vue-tsc -b && vite build",
826
- "preview": "vite preview",
827
- "lint": "eslint .",
828
- "format": "prettier --write src"
829
- }
830
- }
831
- ```
832
-
833
- ---
834
-
835
- ## 25. 项目启动流程
836
-
837
- ```bash
838
- pnpm install
839
- pnpm dev
840
- ```
841
-
842
- 生产构建:
843
-
844
- ```bash
845
- pnpm build
846
- ```
847
-
848
- 本地预览:
849
-
850
- ```bash
851
- pnpm preview
852
- ```
853
-
854
- ---
855
-
856
- ## 26. 总结
857
-
858
- Vue3 项目开发应重点关注以下几点:
859
-
860
- - 目录结构清晰
861
- - 命名风格统一
862
- - 组件职责单一
863
- - 类型定义完善
864
- - 接口统一封装
865
- - 状态管理规范
866
- - 样式风格一致
867
- - 权限设计清晰
868
- - Git 提交规范
869
- - 构建部署流程稳定
870
-
871
- 良好的开发规范可以提升团队协作效率,降低维护成本,并让项目在长期迭代中保持稳定和可扩展。
package/test/favicon.ico DELETED
Binary file