create-jnrs-template-vue 1.2.5 → 1.2.7

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.
@@ -16,30 +16,30 @@ pnpm build
16
16
  #### 项目结构
17
17
  ```Text
18
18
  jnrs-template-vue/
19
- ├── dist/ # 打包构建产物
20
- ├── node_modules/ # 项目依赖
21
- ├── viteMockServe/ # Mock 服务配置(用于开发环境模拟 API)
19
+ ├── viteMockServe/ # Mock 服务配置
22
20
  ├── public/ # 静态资源
23
- ├── layout/ # 布局
24
21
  ├── src/ # 源码目录
25
22
  │ ├── components/ # Vue 组件
26
23
  │ ├── composables/ # 组合式函数
24
+ │ ├── layout/ # 布局
27
25
  │ ├── views/ # 页面视图
28
26
  │ ├── router/ # 路由配置
27
+ │ ├── api/ # 接口定义
28
+ │ ├── types/ # 类型定义
29
29
  │ ├── store/ # 状态管理
30
30
  │ ├── utils/ # 工具函数
31
+ │ ├── locales/ # 国际化
31
32
  │ └── main.ts # 应用入口
32
33
  ├── index.html # HTML 入口文件
33
34
  ├── eslint.config.js # ESLint 配置文件
34
- ├── package.json # 项目配置(依赖、脚本等)
35
+ ├── package.json # 包管理配置
35
36
  └── vite.config.ts # Vite 构建配置
36
37
  ├── tsconfig.json # TypeScript 配置
37
38
  ├── auto-imports.d.ts # 自动导入类型声明
38
39
  ├── components.d.ts # 全局组件类型声明
39
40
  ├── README.md # 项目文档
40
- ├── .env.example # 环境变量模板(供参考)
41
- ├── .env.development # 开发环境变量(全局)
42
- ├── .env.production # 生产环境变量(全局)
41
+ ├── .env.development # 开发环境变量
42
+ ├── .env.production # 生产环境变量
43
43
  ├── .gitignore # Git 忽略规则
44
44
  ├── .prettierrc.json # Prettier 格式化配置
45
45
  ```
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "jnrs-template-vue",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "JNRS 信息化管理系统",
5
- "author": "Talia-Tan",
5
+ "author": "talia_tan",
6
6
  "private": true,
7
7
  "type": "module",
8
8
  "engines": {
@@ -19,14 +19,14 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@element-plus/icons-vue": "^2.3.2",
22
- "@jnrs/shared": "1.1.10",
23
- "@jnrs/vue-core": "1.2.5",
22
+ "@jnrs/shared": "1.1.11",
23
+ "@jnrs/vue-core": "1.2.9",
24
24
  "@vueuse/core": "^14.1.0",
25
25
  "element-plus": "^2.11.9",
26
26
  "pinia": "^3.0.4",
27
27
  "pinia-plugin-persistedstate": "^4.7.1",
28
28
  "vue": "^3.5.25",
29
- "vue-i18n": "^9.14.5"
29
+ "vue-i18n": "^11.2.8"
30
30
  },
31
31
  "devDependencies": {
32
32
  "@tsconfig/node22": "^22.0.5",
@@ -3,8 +3,6 @@
3
3
  "msg": "操作成功",
4
4
  "data": [
5
5
  {
6
- "path": "/demos",
7
- "name": "Demos",
8
6
  "meta": {
9
7
  "title": "功能演示",
10
8
  "icon": "StarFilled",
@@ -37,6 +35,23 @@
37
35
  "todoCount": 0
38
36
  },
39
37
  "component": "/demos/crud/index"
38
+ },
39
+ {
40
+ "path": "/testRedirect",
41
+ "name": "TestRedirect",
42
+ "meta": {
43
+ "title": "重定向测试"
44
+ },
45
+ "redirect": "/crud"
46
+ },
47
+ {
48
+ "path": "/testAlias",
49
+ "name": "TestAlias",
50
+ "meta": {
51
+ "title": "相同component不同path",
52
+ "testId": 1
53
+ },
54
+ "component": "/demos/crud/index"
40
55
  }
41
56
  ]
42
57
  },
@@ -76,8 +91,7 @@
76
91
  "todoCount": 0,
77
92
  "permissions": ["user:view", "user:edit"]
78
93
  },
79
- "component": "/system/user/index",
80
- "redirect": "/crud"
94
+ "component": "/system/user/index"
81
95
  },
82
96
  {
83
97
  "path": "/system/role",
@@ -124,7 +124,7 @@ export const ImportTemplateApi = (): Promise<Blob> => {
124
124
  /**
125
125
  * 项目数据导入
126
126
  */
127
- export const ImportDataApi = (data: { file: File }) => {
127
+ export const ImportDataApi = (data: FormData) => {
128
128
  return axiosRequest({
129
129
  url: '/mock/project/import',
130
130
  method: 'post',
@@ -7,7 +7,7 @@
7
7
  -->
8
8
 
9
9
  <script setup lang="ts">
10
- import type { PageTableData, Pagination } from '@/types'
10
+ import type { Pagination, PageTableData } from '@/types'
11
11
  import { ref, onActivated } from 'vue'
12
12
  import { JnPagination, JnTable } from '@jnrs/vue-core/components'
13
13
  import { debounce } from '@jnrs/shared/lodash'
@@ -16,7 +16,8 @@ interface Props {
16
16
  /**
17
17
  * 获取数据表格 api 函数
18
18
  */
19
- getTableDataApi?: (...args: any[]) => Promise<PageTableData<any>>
19
+ // eslint-disable-next-line
20
+ getTableDataApi?: (data?: Pagination) => Promise<PageTableData<any>>
20
21
  }
21
22
 
22
23
  const { getTableDataApi } = defineProps<Props>()
@@ -24,7 +25,7 @@ const { getTableDataApi } = defineProps<Props>()
24
25
  const loading = ref(false)
25
26
  const tableData = ref()
26
27
  const total = ref(0)
27
- const pagination = ref<Pagination>({ pageNo: 1, pageSize: 10 })
28
+ const pagination = ref<Pagination>({ pageNo: 1, pageSize: 20 })
28
29
 
29
30
  const getTable = debounce(async () => {
30
31
  if (!getTableDataApi) {
@@ -32,14 +33,13 @@ const getTable = debounce(async () => {
32
33
  }
33
34
  loading.value = true
34
35
  try {
35
- const res = await getTableDataApi({
36
- ...pagination.value
37
- })
38
- tableData.value = res.list.map((item) => ({
39
- ...item,
40
- newImageFiles: item.imageDocument?.attachments,
41
- newAttachmentFile: item.attachmentDocument?.attachments
42
- }))
36
+ const res = await getTableDataApi(pagination.value)
37
+ tableData.value =
38
+ res.list?.map((item) => ({
39
+ ...item,
40
+ newImageFiles: item.imageDocument?.attachments,
41
+ newAttachmentFile: item.attachmentDocument?.attachments
42
+ })) || []
43
43
  total.value = res.count
44
44
  } catch (error) {
45
45
  console.error(error)
@@ -51,6 +51,10 @@ const getTable = debounce(async () => {
51
51
  onActivated(() => {
52
52
  getTable()
53
53
  })
54
+
55
+ defineExpose({
56
+ getTable
57
+ })
54
58
  </script>
55
59
 
56
60
  <template>
@@ -12,9 +12,15 @@ import { JnSelectTemplate } from '@jnrs/vue-core/components'
12
12
  </script>
13
13
 
14
14
  <template>
15
- <JnSelectTemplate tableName="项目经理" :keyValue="{ label: 'manager', value: 'managerId' }" :listApi="TableApi">
15
+ <JnSelectTemplate
16
+ tableName="项目经理"
17
+ :keyValue="{ name: 'manager', id: 'managerId', code: 'code' }"
18
+ optionSecondaryField="code"
19
+ :listApi="TableApi"
20
+ >
16
21
  <template #table>
17
22
  <el-table-column prop="manager" label="项目经理" align="center" sortable />
23
+ <el-table-column prop="code" label="编码" align="center" sortable />
18
24
  </template>
19
25
  </JnSelectTemplate>
20
26
  </template>
@@ -30,7 +30,7 @@ const route = useRoute()
30
30
  class="leftSide_menu"
31
31
  popper-class="layoutPage_leftSide_menu_popper"
32
32
  :router="true"
33
- :default-active="route.path"
33
+ :default-active="route.name"
34
34
  :collapse="menuCollapse"
35
35
  :unique-opened="true"
36
36
  >
@@ -11,7 +11,7 @@ const { menuCollapse } = useSystemStore()
11
11
 
12
12
  <template>
13
13
  <!-- 一级路由 -->
14
- <el-menu-item :index="listItem.path" v-if="!listItem.children">
14
+ <el-menu-item :index="listItem.name" :route="listItem.path" v-if="!listItem.children">
15
15
  <el-icon v-if="listItem.meta.icon">
16
16
  <component :is="listItem.meta.icon" />
17
17
  </el-icon>
@@ -62,7 +62,8 @@ const showGlobalSetting = () => {
62
62
  <el-popover placement="bottom" trigger="click" :teleported="false" :width="260" :hide-after="0">
63
63
  <template #reference>
64
64
  <span class="userMenu_reference">
65
- <ImageView class="userMenu_avatar" :loadKeys="userInfo?.avatarFileName" />
65
+ <ImageView class="userMenu_avatar" :loadKeys="userInfo.avatarFileName" v-if="userInfo?.avatarFileName" />
66
+ <img class="userMenu_avatar" src="@/assets/images/common/avatar.png" v-else />
66
67
  <span>{{ userInfo?.name }}</span>
67
68
  <DictTag dictName="role" :value="userInfo.role" v-if="userInfo?.role" />
68
69
  <el-icon class="userMenu_icon"><arrow-down /></el-icon>
@@ -136,15 +137,14 @@ $topHoverSize: 35px;
136
137
  }
137
138
  }
138
139
  .userMenu_avatar {
139
- width: $topHoverSize;
140
- height: $topHoverSize;
140
+ width: $topHoverSize !important;
141
+ height: $topHoverSize !important;
141
142
  border-radius: 50%;
142
143
  margin-right: 4px;
143
144
  overflow: hidden;
144
145
  background: var(--jnrs-background-head);
145
146
  }
146
147
  .userMenu_icon {
147
- margin-left: 4px;
148
148
  color: var(--jnrs-font-primary-06);
149
149
  }
150
150
  }
@@ -178,7 +178,6 @@ $topHoverSize: 35px;
178
178
  }
179
179
  }
180
180
  .userMenu_roleName {
181
- margin-left: 4px;
182
181
  color: var(--jnrs-color-primary);
183
182
  }
184
183
  }
@@ -1,7 +1,7 @@
1
- import { LAYOUT_NAME, GLOBAL_COMPONENT, routes } from './routes'
2
- import { createVueRouter } from '@jnrs/vue-core/router'
3
1
  import type { FileModules, RouteLocationNormalizedGeneric } from '@jnrs/vue-core/router'
4
2
  import type { MenuItem } from '@jnrs/vue-core'
3
+ import { LAYOUT_NAME, GLOBAL_COMPONENT, routes } from './routes'
4
+ import { createVueRouter } from '@jnrs/vue-core/router'
5
5
  import { useAuthStore, useMenuStore } from '@jnrs/vue-core/pinia'
6
6
  import { MenuApi } from '@/api/system'
7
7
  import { hasMenuViewPermission } from '@/utils/permissions'
@@ -68,7 +68,8 @@ export interface Pagination {
68
68
  /**
69
69
  * 分页列表数据
70
70
  */
71
- export interface PageTableData<T> extends Pagination {
71
+ // eslint-disable-next-line
72
+ export interface PageTableData<T = Record<string, any>> extends Pagination {
72
73
  /**
73
74
  * 数据列表
74
75
  */
@@ -5,6 +5,7 @@ import type { ProjectItem, AddProjectItem } from '@/api/demos/index'
5
5
  import { ref, onActivated } from 'vue'
6
6
  import { ElMessage } from 'element-plus'
7
7
  import { Plus } from '@element-plus/icons-vue'
8
+ import { useRoute } from '@jnrs/vue-core/router'
8
9
  import { objectMatchAssign, dateFormatsToObject } from '@jnrs/shared'
9
10
  import { debounce } from '@jnrs/shared/lodash'
10
11
  import { isNumberGtZero } from '@jnrs/shared/validator'
@@ -25,7 +26,8 @@ interface ProcessedProjectItem extends ProjectItem {
25
26
  const loading = ref(false)
26
27
  const tableData = ref<ProcessedProjectItem[]>([])
27
28
  const total = ref(0)
28
- const pagination = ref<Pagination>({ pageNo: 1, pageSize: 10 })
29
+ const pagination = ref<Pagination>({ pageNo: 1, pageSize: 20 })
30
+ const route = useRoute()
29
31
 
30
32
  // 编辑
31
33
  const editDialogRef = ref()
@@ -128,6 +130,7 @@ const submitForm = () => {
128
130
  }
129
131
 
130
132
  onActivated(() => {
133
+ console.log(route.meta)
131
134
  getTable()
132
135
  })
133
136
  </script>
@@ -31,6 +31,21 @@ const handleRouteChange = () => {
31
31
  })
32
32
  }
33
33
 
34
+ const handleRouterSystemMine = () => {
35
+ handleRouter({
36
+ name: 'SystemMine',
37
+ query: {
38
+ id: 1
39
+ }
40
+ })
41
+ // handleRouter({
42
+ // path: '/system/mine/index',
43
+ // query: {
44
+ // id: 1
45
+ // }
46
+ // })
47
+ }
48
+
34
49
  const changeI18n = () => {
35
50
  datetime.value = formatDateTime() + ' ' + formatWeekday()
36
51
  isFloatGtZero({}, '0', (msg) => {
@@ -80,7 +95,8 @@ onMounted(() => {
80
95
  </ul>
81
96
  <RequestPage />
82
97
  <p>完整路由测试(先点击按钮,获取完整菜单数据)</p>
83
- <el-button type="success" plain @click="handleMenuApi">获取完整菜单数据</el-button>
98
+ <el-button type="success" plain size="small" @click="handleRouterSystemMine">跳转到个人中心</el-button>
99
+ <el-button type="success" plain size="small" @click="handleMenuApi">获取完整菜单数据</el-button>
84
100
  <el-cascader
85
101
  v-model="currentRoute"
86
102
  :options="routeOptions"
@@ -89,6 +105,7 @@ onMounted(() => {
89
105
  value: 'name',
90
106
  label: 'name'
91
107
  }"
108
+ size="small"
92
109
  :show-all-levels="false"
93
110
  @change="handleRouteChange"
94
111
  >
@@ -21,13 +21,13 @@ const { menus } = useMenuStore()
21
21
  <el-icon v-if="row.meta.icon"><component :is="row.meta.icon" /></el-icon>
22
22
  </template>
23
23
  </el-table-column>
24
- <el-table-column prop="path" label="路由地址" min-width="120" header-align="center" />
25
- <el-table-column prop="component" label="component path" min-width="120" header-align="center" />
24
+ <el-table-column prop="path" label="path" min-width="120" header-align="center" />
25
+ <el-table-column prop="name" label="name" min-width="120" header-align="center" />
26
+ <el-table-column prop="component" label="component" min-width="120" header-align="center" />
26
27
  <el-table-column prop="redirect" label="redirect" min-width="120" header-align="center" />
27
- <el-table-column prop="editRole" label="权限标识" min-width="120" header-align="center">
28
+ <el-table-column prop="meta.permissions" label="permissions" min-width="120" header-align="center">
28
29
  <template #default="{ row }">
29
- <span v-if="!row.meta.permissions" style="color: #999">auto</span>
30
- <span v-else>{{ row.meta.permissions }}</span>
30
+ <span>{{ row.meta.permissions }}</span>
31
31
  </template>
32
32
  </el-table-column>
33
33
  <el-table-column prop="type" label="类型" width="80" align="center">
@@ -36,18 +36,8 @@ const { menus } = useMenuStore()
36
36
  <el-tag type="success" v-else>目录</el-tag>
37
37
  </template>
38
38
  </el-table-column>
39
- <el-table-column prop="type" label="NoAuthApi" width="80" align="center">
40
- <template #default="{ row }">
41
- <el-tag type="danger" v-if="row.meta.noAuth">否</el-tag>
42
- <el-tag type="success" v-else>是</el-tag>
43
- </template>
44
- </el-table-column>
45
- <el-table-column prop="type" label="Global" width="80" align="center">
46
- <template #default="{ row }">
47
- <el-tag type="success" v-if="row.meta.global">是</el-tag>
48
- <el-tag type="primary" v-else>否</el-tag>
49
- </template>
50
- </el-table-column>
39
+ <el-table-column prop="meta.noAuth" label="meta.noAuth" width="80" align="center" />
40
+ <el-table-column prop="meta.global" label="meta.global" width="80" align="center" />
51
41
  </JnTable>
52
42
  </el-card>
53
43
  </template>
@@ -74,6 +74,7 @@ onMounted(() => {
74
74
  :showFileList="false"
75
75
  :autoUploadApi="AvatarChangeApi"
76
76
  style="width: 500px"
77
+ :disabled="true"
77
78
  />
78
79
  </el-form-item>
79
80
  <!-- <el-form-item>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jnrs-template-vue",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "巨能前端工程化开发,Vue 项目模板脚手架",
5
5
  "keywords": [
6
6
  "vue",
@@ -9,7 +9,7 @@
9
9
  "TypeScript",
10
10
  "monorepo"
11
11
  ],
12
- "author": "Talia-Tan",
12
+ "author": "talia_tan",
13
13
  "license": "MIT",
14
14
  "repository": {
15
15
  "type": "git",
@@ -1,9 +0,0 @@
1
- /**
2
- * @Author : TanRui
3
- * @WeChat : Tan578853789
4
- * @File : useForm.ts
5
- * @Date : 2025/11/30
6
- * @Desc. : 表单通用逻辑
7
- */
8
-
9
- export function useForm() {}
@@ -1,9 +0,0 @@
1
- /**
2
- * @Author : TanRui
3
- * @WeChat : Tan578853789
4
- * @File : useModal.ts
5
- * @Date : 2025/11/30
6
- * @Desc. : 弹窗控制逻辑
7
- */
8
-
9
- export function useModal() {}
@@ -1,35 +0,0 @@
1
- /**
2
- * @Author : TanRui
3
- * @WeChat : Tan578853789
4
- * @File : useTable.ts
5
- * @Date : 2025/11/30
6
- * @Desc. : 表格、分页、筛选等通用逻辑
7
- */
8
-
9
- import { ref, computed } from 'vue'
10
-
11
- export function useTable<T>(initialData: T[] = []) {
12
- const data = ref<T[]>(initialData)
13
- const pageSize = ref(10)
14
- const pageNo = ref(1)
15
-
16
- // 分页数据
17
- const paginatedData = computed(() => {
18
- const start = (pageNo.value - 1) * pageSize.value
19
- return data.value?.slice(start, start + pageSize.value)
20
- })
21
-
22
- // 设置新的数据
23
- const setNewData = (newData: T[]) => {
24
- data.value = newData
25
- pageNo.value = 1
26
- }
27
-
28
- return {
29
- data,
30
- pageSize,
31
- pageNo,
32
- paginatedData,
33
- setNewData
34
- }
35
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * @Author : TanRui
3
- * @WeChat : Tan578853789
4
- * @File : useTable.ts
5
- * @Date : 2025/11/30
6
- * @Desc. : 表格
7
- */
8
-
9
- import { ref, computed } from 'vue'
10
-
11
- export function useTable<T>(initialData: T[] = []) {
12
- const data = ref<T[]>(initialData)
13
- const pageSize = ref(10)
14
- const pageNo = ref(1)
15
-
16
- // 分页数据
17
- const paginatedData = computed(() => {
18
- const start = (pageNo.value - 1) * pageSize.value
19
- return data.value?.slice(start, start + pageSize.value)
20
- })
21
-
22
- // 设置新的数据
23
- const setNewData = (newData: T[]) => {
24
- data.value = newData
25
- pageNo.value = 1
26
- }
27
-
28
- return {
29
- data,
30
- pageSize,
31
- pageNo,
32
- paginatedData,
33
- setNewData
34
- }
35
- }
@@ -1,9 +0,0 @@
1
- /**
2
- * @Author : TanRui
3
- * @WeChat : Tan578853789
4
- * @File : useUser.ts
5
- * @Date : 2025/11/30
6
- * @Desc. : 用户相关逻辑
7
- */
8
-
9
- export function useUser() {}