create-jnrs-template-vue 1.2.2 → 1.2.3

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jnrs-template-vue",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "JNRS 信息化管理系统模板",
5
5
  "author": "Talia-Tan",
6
6
  "private": true,
@@ -19,9 +19,8 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@element-plus/icons-vue": "^2.3.2",
22
- "@jnrs/core": "1.1.7",
23
- "@jnrs/shared": "1.1.7",
24
- "@jnrs/vue-core": "1.2.2",
22
+ "@jnrs/shared": "1.1.8",
23
+ "@jnrs/vue-core": "1.2.3",
25
24
  "@vueuse/core": "^14.1.0",
26
25
  "element-plus": "^2.11.9",
27
26
  "pinia": "^3.0.4",
@@ -6,7 +6,6 @@ import zhCn from 'element-plus/es/locale/lang/zh-CN'
6
6
  import en from 'element-plus/es/locale/lang/en'
7
7
  import { useI18n } from 'vue-i18n'
8
8
  import { changeLocales as changeLocalesForShared } from '@jnrs/shared/locales'
9
- import { changeLocales as changeLocalesForCore } from '@jnrs/core/locales'
10
9
 
11
10
  const { locale } = useI18n()
12
11
 
@@ -16,7 +15,6 @@ watch(
16
15
  (newValue) => {
17
16
  locale.value = newValue
18
17
  changeLocalesForShared(newValue)
19
- changeLocalesForCore(newValue)
20
18
  },
21
19
  {
22
20
  immediate: true
@@ -30,7 +28,7 @@ const localeMap = {
30
28
 
31
29
  onMounted(() => {
32
30
  console.log(
33
- '%cPowered by 🅹🅽🆁🆂 TECH',
31
+ '%cPOWERED BY 🅹🅽🆁🆂 TECH',
34
32
  `background: #f2f2c1;
35
33
  color: #d15f2c;
36
34
  font-weight: bold;
@@ -1,4 +1,4 @@
1
- import { request } from '@jnrs/vue-core'
1
+ import { axiosRequest } from '@jnrs/vue-core/request'
2
2
 
3
3
  /**
4
4
  * axios 方式下载文件
@@ -6,7 +6,7 @@ import { request } from '@jnrs/vue-core'
6
6
  * @returns Blob
7
7
  */
8
8
  export const FileApi = (uniqueFileName: string): Promise<Blob> => {
9
- return request({
9
+ return axiosRequest({
10
10
  url: '/api/files/' + uniqueFileName,
11
11
  method: 'get',
12
12
  responseType: 'blob',
@@ -1,40 +1,8 @@
1
1
  import type { Pagination, PageTableData, FileContainer } from '@/types'
2
- import { request } from '@jnrs/vue-core'
2
+ import { axiosRequest } from '@jnrs/vue-core/request'
3
3
 
4
4
  /**
5
- * 404 错误
6
- */
7
- export const NotFoundApi = () => {
8
- return request({
9
- url: '/notFound',
10
- method: 'get'
11
- })
12
- }
13
-
14
- /**
15
- * 无权限
16
- * @param showErrorMsg 是否显示错误信息
17
- */
18
- export const NoAuth = (showErrorMsg: boolean) => {
19
- return request({
20
- url: '/auth/no',
21
- method: 'post',
22
- showErrorMsg
23
- })
24
- }
25
-
26
- /**
27
- * 数据详情
28
- */
29
- export const DetailsApi = (): Promise<FileContainer> => {
30
- return request({
31
- url: '/details',
32
- method: 'get'
33
- })
34
- }
35
-
36
- /**
37
- * 项目项
5
+ * 项目
38
6
  */
39
7
  export interface ProjectItem extends FileContainer {
40
8
  id: string
@@ -53,7 +21,7 @@ export interface ProjectItem extends FileContainer {
53
21
  }
54
22
 
55
23
  /**
56
- * 新增项目项
24
+ * 新增
57
25
  */
58
26
  type AddProjectOmitKeys =
59
27
  | 'id'
@@ -73,17 +41,52 @@ export type AddProjectItem = Omit<ProjectItem, AddProjectOmitKeys> & {
73
41
  newImageFiles: []
74
42
  }
75
43
 
44
+ /**
45
+ * 查询
46
+ */
76
47
  export interface ProjectQuery extends Pagination {
77
48
  code?: string
78
49
  projectType?: '敏捷型' | '瀑布型' | '混合型'
79
50
  manager?: string
80
51
  }
81
52
 
53
+ /**
54
+ * 测试 404 错误
55
+ */
56
+ export const NotFoundApi = () => {
57
+ return axiosRequest({
58
+ url: '/mock/notFound',
59
+ method: 'get'
60
+ })
61
+ }
62
+
63
+ /**
64
+ * 测试 无权限
65
+ * @param showErrorMsg 是否显示错误信息
66
+ */
67
+ export const NoAuth = (showErrorMsg: boolean) => {
68
+ return axiosRequest({
69
+ url: '/mock/auth/no',
70
+ method: 'post',
71
+ showErrorMsg
72
+ })
73
+ }
74
+
75
+ /**
76
+ * 数据详情
77
+ */
78
+ export const DetailsApi = (): Promise<FileContainer> => {
79
+ return axiosRequest({
80
+ url: '/mock/details',
81
+ method: 'get'
82
+ })
83
+ }
84
+
82
85
  /**
83
86
  * 表单新增
84
87
  */
85
88
  export const DemosFormApi = (data: FormData) => {
86
- return request({
89
+ return axiosRequest({
87
90
  url: '/mock/demos/save',
88
91
  method: 'post',
89
92
  data
@@ -94,9 +97,41 @@ export const DemosFormApi = (data: FormData) => {
94
97
  * 数据详情
95
98
  */
96
99
  export const DemosTableApi = (query: ProjectQuery): Promise<PageTableData<ProjectItem>> => {
97
- return request({
100
+ return axiosRequest({
98
101
  url: '/mock/demos/table',
99
102
  method: 'get',
100
103
  data: query
101
104
  })
102
105
  }
106
+
107
+ /**
108
+ * 下载数据导入模板
109
+ */
110
+ export const DemosImportTemplateApi = (): Promise<Blob> => {
111
+ return axiosRequest({
112
+ url: '/mock/project/template',
113
+ method: 'post'
114
+ })
115
+ }
116
+
117
+ /**
118
+ * 项目数据导入
119
+ */
120
+ export const DemosImportDataApi = (data: FormData) => {
121
+ return axiosRequest({
122
+ url: '/mock/project/import',
123
+ method: 'post',
124
+ data
125
+ })
126
+ }
127
+
128
+ /**
129
+ * 项目数据导出
130
+ */
131
+ export const DemosExportApi = (data: Record<string, unknown>): Promise<Blob> => {
132
+ return axiosRequest({
133
+ url: '/mock/project/export',
134
+ method: 'post',
135
+ data
136
+ })
137
+ }
@@ -1,10 +1,10 @@
1
- import { request } from '@jnrs/vue-core'
1
+ import { axiosRequest } from '@jnrs/vue-core/request'
2
2
  import type { Dict, DictItem, User, Role } from '@jnrs/shared'
3
3
  import type { MenuItem } from '@jnrs/vue-core'
4
4
 
5
5
  // 菜单
6
6
  export const MenuApi = (): Promise<MenuItem[]> => {
7
- return request({
7
+ return axiosRequest({
8
8
  url: '/system/menu.json', // /public 文件夹下
9
9
  mockUrl: '/mock/menu',
10
10
  method: 'get'
@@ -23,7 +23,7 @@ export interface LoginResult extends User {
23
23
  }
24
24
 
25
25
  export const LoginApi = (data: LoginParams): Promise<LoginResult> => {
26
- return request({
26
+ return axiosRequest({
27
27
  url: '/api/auth/login',
28
28
  method: 'post',
29
29
  data,
@@ -33,7 +33,7 @@ export const LoginApi = (data: LoginParams): Promise<LoginResult> => {
33
33
 
34
34
  // 退出登录
35
35
  export const LogoutApi = () => {
36
- return request({
36
+ return axiosRequest({
37
37
  url: '/api/auth/logout',
38
38
  method: 'get'
39
39
  })
@@ -41,7 +41,7 @@ export const LogoutApi = () => {
41
41
 
42
42
  // 获取用户信息
43
43
  export const UserInfoApi = (): Promise<User> => {
44
- return request({
44
+ return axiosRequest({
45
45
  url: '/api/auth/user-info',
46
46
  method: 'get'
47
47
  })
@@ -54,7 +54,7 @@ interface PasswordChange {
54
54
  }
55
55
 
56
56
  export const PasswordChangeApi = (data: PasswordChange) => {
57
- return request({
57
+ return axiosRequest({
58
58
  url: '/api/auth/change-password',
59
59
  method: 'post',
60
60
  data
@@ -63,7 +63,7 @@ export const PasswordChangeApi = (data: PasswordChange) => {
63
63
 
64
64
  // 获取字典列表
65
65
  export const DictApi = (): Promise<DictItem[]> => {
66
- return request({
66
+ return axiosRequest({
67
67
  url: '/api/dict-manager',
68
68
  method: 'get'
69
69
  })
@@ -71,7 +71,7 @@ export const DictApi = (): Promise<DictItem[]> => {
71
71
 
72
72
  // 获取单个字典
73
73
  export const DictDetailApi = (id: string) => {
74
- return request({
74
+ return axiosRequest({
75
75
  url: `/api/dict-manager/detail/${id}`,
76
76
  method: 'get'
77
77
  })
@@ -79,7 +79,7 @@ export const DictDetailApi = (id: string) => {
79
79
 
80
80
  // 修改单个字典
81
81
  export const DictChangeApi = (data: DictItem) => {
82
- return request({
82
+ return axiosRequest({
83
83
  url: '/api/dict-manager/detail',
84
84
  method: 'post',
85
85
  data
@@ -88,7 +88,7 @@ export const DictChangeApi = (data: DictItem) => {
88
88
 
89
89
  // 获取角色列表
90
90
  export const RoleApi = (): Promise<Role[]> => {
91
- return request({
91
+ return axiosRequest({
92
92
  url: '/api/role-manager',
93
93
  method: 'get',
94
94
  noAuth: true
@@ -1,8 +1,8 @@
1
- import { request } from '@jnrs/vue-core'
1
+ import { axiosRequest } from '@jnrs/vue-core/request'
2
2
 
3
3
  // 获取用户信息
4
4
  export const UserApi = (id: string) => {
5
- return request({
5
+ return axiosRequest({
6
6
  url: '/api/user',
7
7
  method: 'get',
8
8
  params: {
@@ -4,7 +4,7 @@ import en from './en'
4
4
  import { zhCn as vueCore_zhCn, en as vueCore_en } from '@jnrs/vue-core/locales'
5
5
 
6
6
  const i18n = createI18n({
7
- legacy: false, // 启用 Composition API 模式
7
+ legacy: false, // legacy 为 false 则启用 Composition API 模式
8
8
  globalInjection: true, // 允许在模板中使用 $t
9
9
  locale: 'zhCn',
10
10
  fallbackLocale: 'en',
@@ -5,13 +5,19 @@ 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 { objectMatchAssign } from '@jnrs/shared'
8
+ import { objectMatchAssign, dateFormatsToObject } from '@jnrs/shared'
9
9
  import { debounce } from '@jnrs/shared/lodash'
10
10
  import { isNumberGtZero } from '@jnrs/shared/validator'
11
11
  import { getDictList, objectToFormData, downloadFile } from '@/utils/packages'
12
- import { DemosTableApi, DemosFormApi } from '@/api/demos/index'
12
+ import {
13
+ DemosTableApi,
14
+ DemosFormApi,
15
+ DemosImportTemplateApi,
16
+ DemosImportDataApi,
17
+ DemosExportApi
18
+ } from '@/api/demos/index'
13
19
 
14
- import { JnDialog, JnDatetime, JnPagination, JnFileUpload, JnTable } from '@jnrs/vue-core/components'
20
+ import { JnDialog, JnDatetime, JnPagination, JnFileUpload, JnTable, JnImportAndExport } from '@jnrs/vue-core/components'
15
21
  import ImageView from '@/components/common/ImageView.vue'
16
22
  import PdfView from '@/components/common/PdfView.vue'
17
23
  import DictTag from '@/components/common/DictTag.vue'
@@ -28,7 +34,7 @@ const total = ref(0)
28
34
  const pagination = ref<Pagination>({ pageNo: 1, pageSize: 10 })
29
35
 
30
36
  // 编辑
31
- const jnEditRef = ref()
37
+ const editDialogRef = ref()
32
38
  const ruleFormRef = ref<FormInstance>()
33
39
  const ruleForm = ref<AddProjectItem>({
34
40
  id: '',
@@ -62,7 +68,8 @@ const rules = ref<FormRules>({
62
68
  const queryForm = ref({
63
69
  code: '',
64
70
  projectType: undefined,
65
- manager: ''
71
+ manager: '',
72
+ plannedStartDate: ''
66
73
  })
67
74
 
68
75
  const handleSelectionChange = (row: ProjectItem[]) => {
@@ -88,7 +95,7 @@ const getDemosTable = debounce(async () => {
88
95
 
89
96
  // 新增和修改
90
97
  const handleEdit = (row?: ProjectItem) => {
91
- jnEditRef.value.open()
98
+ editDialogRef.value.open()
92
99
  queueMicrotask(() => {
93
100
  ruleFormRef.value?.resetFields()
94
101
  const matched = objectMatchAssign(ruleForm.value, row)
@@ -135,7 +142,7 @@ onActivated(() => {
135
142
 
136
143
  <template>
137
144
  <!-- 编辑弹窗 -->
138
- <JnDialog ref="jnEditRef" title="项目管理" width="600px">
145
+ <JnDialog ref="editDialogRef" title="项目管理" width="600px">
139
146
  <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="auto" v-loading="loading">
140
147
  <el-form-item prop="id"></el-form-item>
141
148
  <el-form-item label="项目名称" prop="name">
@@ -211,9 +218,30 @@ onActivated(() => {
211
218
 
212
219
  <el-card>
213
220
  <template #header>
214
- <div style="display: flex; justify-content: space-between">
221
+ <div style="display: flex; justify-content: space-between; align-items: center">
215
222
  <span>项目管理</span>
216
- <el-button type="primary" size="small" :icon="Plus" @click="handleEdit()">新增</el-button>
223
+ <div style="display: flex; justify-content: space-between; align-items: center">
224
+ <JnImportAndExport
225
+ :importTemplateApi="DemosImportTemplateApi"
226
+ importBtnName="导入项目"
227
+ :importApi="DemosImportDataApi"
228
+ exportBtnName="导出项目"
229
+ :exportApi="DemosExportApi"
230
+ :exportParams="{
231
+ ...dateFormatsToObject(queryForm.plannedStartDate)
232
+ }"
233
+ :exportDynamicParamsConfig="{
234
+ label: '项目编号',
235
+ prop: 'code'
236
+ }"
237
+ :exportDisabled="tableData.length === 0"
238
+ size="small"
239
+ @change="getDemosTable()"
240
+ />
241
+ <el-button type="primary" size="small" :icon="Plus" @click="handleEdit()" style="margin-left: 12px">
242
+ 新增
243
+ </el-button>
244
+ </div>
217
245
  </div>
218
246
  </template>
219
247
 
@@ -252,6 +280,15 @@ onActivated(() => {
252
280
  @change="getDemosTable()"
253
281
  ></SelectManager>
254
282
  </el-form-item>
283
+ <el-form-item label="计划开始时间" prop="plannedStartDate">
284
+ <el-date-picker
285
+ v-model="queryForm.plannedStartDate"
286
+ value-format="YYYY-MM-DD"
287
+ size="small"
288
+ style="width: 150px"
289
+ @change="getDemosTable()"
290
+ />
291
+ </el-form-item>
255
292
  </el-form>
256
293
 
257
294
  <!-- 数据列表 -->
@@ -5,12 +5,16 @@ import { handleRouter } from '@jnrs/vue-core/router'
5
5
  import type { MenuItem } from '@jnrs/vue-core'
6
6
  import { hasPermission } from '@/utils/permissions'
7
7
  import { MenuApi } from '@/api/system'
8
+ import { formatDateTime, formatWeekday } from '@jnrs/shared'
9
+ import { isFloatGtZero } from '@jnrs/shared/validator'
10
+ import { testI18n } from '@jnrs/shared/request'
8
11
 
9
12
  const routeOptions = ref<MenuItem[]>([])
10
13
  const currentRoute = ref('')
11
14
  const datePicker = ref(new Date())
12
-
13
- onMounted(() => {})
15
+ const datetime = ref(formatDateTime() + ' ' + formatWeekday())
16
+ const validator = ref()
17
+ const testI18nInCore = ref('')
14
18
 
15
19
  const handleMenuApi = async () => {
16
20
  try {
@@ -26,11 +30,31 @@ const handleRouteChange = () => {
26
30
  name: currentRoute.value
27
31
  })
28
32
  }
33
+
34
+ const changeI18n = () => {
35
+ datetime.value = formatDateTime() + ' ' + formatWeekday()
36
+ isFloatGtZero({}, '0', (msg) => {
37
+ validator.value = msg
38
+ })
39
+ testI18nInCore.value = testI18n()
40
+ }
41
+
42
+ onMounted(() => {
43
+ isFloatGtZero({}, '0', (msg) => {
44
+ validator.value = msg
45
+ })
46
+ testI18nInCore.value = testI18n()
47
+ })
29
48
  </script>
30
49
 
31
50
  <template>
32
51
  <div>
33
52
  <h3>Playground - 功能测试</h3>
53
+ <p>国际化测试</p>
54
+ <div>@jnrs/shared: {{ datetime }}</div>
55
+ <div>@jnrs/shared/validator: {{ validator }}</div>
56
+ <div>@jnrs/shared/request: {{ testI18nInCore }}</div>
57
+ <el-button type="primary" size="small" @click="changeI18n">切换语言后点击按钮更新国际化显示</el-button>
34
58
  <p>权限测试(admin 账号拥有全部权限,请用非 admin 账号测试该功能)</p>
35
59
  <ul>
36
60
  <li>
@@ -11,7 +11,7 @@ import type { User } from '@jnrs/shared'
11
11
  const { userInfo, token } = storeToRefs(useAuthStore())
12
12
  const { avatar } = useAvatar()
13
13
  const loading = ref(false)
14
- const ruleFormRef = ref()
14
+ // const ruleFormRef = ref()
15
15
  const ruleForm = ref<User>({
16
16
  id: 0,
17
17
  account: '',
@@ -63,7 +63,6 @@ export default defineConfig({
63
63
  rollupOptions: {
64
64
  output: {
65
65
  manualChunks: {
66
- '@jnrs/core': ['@jnrs/core'],
67
66
  '@jnrs/shared': ['@jnrs/shared']
68
67
  }
69
68
  }
@@ -1,9 +1,21 @@
1
+ import type { IncomingMessage, ServerResponse } from 'http'
2
+
1
3
  const res_fail = {
2
4
  code: 1,
3
5
  msg: '操作失败'
4
6
  }
5
7
 
6
8
  export default [
9
+ // 404
10
+ {
11
+ url: '/mock/notFound',
12
+ method: 'get',
13
+ rawResponse: async (req: IncomingMessage, res: ServerResponse) => {
14
+ res.statusCode = 404
15
+ res.end('File not found')
16
+ return
17
+ }
18
+ },
7
19
  // 权限不足
8
20
  {
9
21
  url: '/mock/auth/no',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jnrs-template-vue",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "巨能前端工程化开发,Vue 项目模板脚手架",
5
5
  "keywords": [
6
6
  "vue",