create-jnrs-template-vue 1.1.14 → 1.1.15

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 (57) hide show
  1. package/bin/create.mjs +55 -32
  2. package/jnrs-template-vue/auto-imports.d.ts +2 -0
  3. package/jnrs-template-vue/components.d.ts +1 -1
  4. package/jnrs-template-vue/package.json +4 -4
  5. package/jnrs-template-vue/src/api/common/index.ts +7 -3
  6. package/jnrs-template-vue/src/api/demos/index.ts +40 -25
  7. package/jnrs-template-vue/src/api/system/index.ts +3 -0
  8. package/jnrs-template-vue/src/assets/images/fileIcon/iconArchive.png +0 -0
  9. package/jnrs-template-vue/src/assets/images/fileIcon/iconAudio.png +0 -0
  10. package/jnrs-template-vue/src/assets/images/fileIcon/iconCode.png +0 -0
  11. package/jnrs-template-vue/src/assets/images/fileIcon/iconExcel.png +0 -0
  12. package/jnrs-template-vue/src/assets/images/fileIcon/iconFile.png +0 -0
  13. package/jnrs-template-vue/src/assets/images/fileIcon/iconFlash.png +0 -0
  14. package/jnrs-template-vue/src/assets/images/fileIcon/iconGif.png +0 -0
  15. package/jnrs-template-vue/src/assets/images/fileIcon/iconImage.png +0 -0
  16. package/jnrs-template-vue/src/assets/images/fileIcon/iconMac.png +0 -0
  17. package/jnrs-template-vue/src/assets/images/fileIcon/iconOfd.png +0 -0
  18. package/jnrs-template-vue/src/assets/images/fileIcon/iconPdf.png +0 -0
  19. package/jnrs-template-vue/src/assets/images/fileIcon/iconPpt.png +0 -0
  20. package/jnrs-template-vue/src/assets/images/fileIcon/iconText.png +0 -0
  21. package/jnrs-template-vue/src/assets/images/fileIcon/iconUnknown.png +0 -0
  22. package/jnrs-template-vue/src/assets/images/fileIcon/iconVideo.png +0 -0
  23. package/jnrs-template-vue/src/assets/images/fileIcon/iconWindows.png +0 -0
  24. package/jnrs-template-vue/src/assets/images/fileIcon/iconWord.png +0 -0
  25. package/jnrs-template-vue/src/assets/images/fileIcon/iconWps.png +0 -0
  26. package/jnrs-template-vue/src/components/base/ImageView.vue +117 -40
  27. package/jnrs-template-vue/src/components/base/JnFileUpload.vue +433 -0
  28. package/jnrs-template-vue/src/components/base/PdfView.vue +106 -0
  29. package/jnrs-template-vue/src/components/common/JnDatetime.vue +37 -0
  30. package/jnrs-template-vue/src/components/common/JnDictTag.vue +70 -0
  31. package/jnrs-template-vue/src/components/common/JnEdit.vue +68 -0
  32. package/jnrs-template-vue/src/layout/SideMenu.vue +1 -0
  33. package/jnrs-template-vue/src/layout/TopHeader.vue +17 -5
  34. package/jnrs-template-vue/src/types/index.ts +32 -8
  35. package/jnrs-template-vue/src/utils/packages.ts +12 -7
  36. package/jnrs-template-vue/src/views/demos/crud/index.vue +180 -24
  37. package/jnrs-template-vue/src/views/demos/unitTest/RequestPage.vue +12 -16
  38. package/jnrs-template-vue/src/views/login/index.vue +13 -18
  39. package/jnrs-template-vue/src/views/system/mine/baseInfo.vue +3 -8
  40. package/jnrs-template-vue/tsconfig.json +4 -1
  41. package/jnrs-template-vue/vite.config.ts +1 -1
  42. package/jnrs-template-vue/viteMockServe/file.ts +68 -0
  43. package/jnrs-template-vue/viteMockServe/fileSrc/mock-pdf.pdf +0 -0
  44. package/jnrs-template-vue/viteMockServe/fileSrc/mock-png-0.png +0 -0
  45. package/jnrs-template-vue/viteMockServe/fileSrc/mock-png-1.png +0 -0
  46. package/jnrs-template-vue/viteMockServe/index.ts +10 -8
  47. package/jnrs-template-vue/viteMockServe/json/dictRes.json +21 -0
  48. package/jnrs-template-vue/viteMockServe/json/loginRes_admin.json +157 -0
  49. package/jnrs-template-vue/viteMockServe/{loginRes_user.json → json/loginRes_user.json} +1 -1
  50. package/jnrs-template-vue/viteMockServe/{tableRes.json → json/tableRes.json} +143 -70
  51. package/jnrs-template-vue/viteMockServe/success.ts +8 -0
  52. package/package.json +1 -1
  53. package/jnrs-template-vue/viteMockServe/dictRes.json +0 -141
  54. package/jnrs-template-vue/viteMockServe/loginRes_admin.json +0 -713
  55. /package/jnrs-template-vue/viteMockServe/{detailsRes.json → json/detailsRes.json} +0 -0
  56. /package/jnrs-template-vue/viteMockServe/{dictItemRes.json → json/dictItemRes.json} +0 -0
  57. /package/jnrs-template-vue/viteMockServe/{roleRes.json → json/roleRes.json} +0 -0
@@ -58,6 +58,7 @@ $mainFontColor: rgba(255, 255, 255, 0.8);
58
58
  position: relative;
59
59
  height: calc(var(--jnrs-head-height) + var(--jnrs-routerTabs-height));
60
60
  border-bottom: 1px solid rgb(248 248 248 / 15%);
61
+ filter: brightness(0.8);
61
62
 
62
63
  .logo_text {
63
64
  position: absolute;
@@ -1,15 +1,15 @@
1
1
  <script setup lang="ts">
2
- import { GlobalSetting } from '@jnrs/vue-core/components'
3
2
  import { ref, computed } from 'vue'
4
3
  import { storeToRefs } from 'pinia'
5
4
  import { ElMessageBox } from 'element-plus'
6
5
  import { handleRouter } from '@jnrs/vue-core/router'
6
+ import { GlobalSetting } from '@jnrs/vue-core/components'
7
7
  import { useSystemStore, useAuthStore, useMenuStore } from '@jnrs/vue-core/pinia'
8
- import { useAvatar } from '@/composables/base/useAvatar'
9
8
  import { LogoutApi } from '@/api/system'
10
9
  import { getDictLabel, getDictColor } from '@/utils/packages'
11
10
 
12
- const { avatar } = useAvatar()
11
+ import ImageView from '@/components/base/ImageView.vue'
12
+
13
13
  const { userInfo, clearAuth } = useAuthStore()
14
14
  const { clearMenu } = useMenuStore()
15
15
 
@@ -66,14 +66,14 @@ const showGlobalSetting = () => {
66
66
  <el-popover placement="bottom" trigger="click" :teleported="false" :width="260" :hide-after="0">
67
67
  <template #reference>
68
68
  <span class="userMenu_reference">
69
- <img class="userMenu_avatar" :src="avatar" alt="avatar" />
69
+ <ImageView class="userMenu_avatar" :loadKeys="userInfo?.avatarFileName" />
70
70
  <span>{{ userInfo?.name }}</span>
71
71
  <span class="userMenu_roleName" :style="{ color: roleColor }" v-if="userInfo?.role">[{{ roleLabel }}]</span>
72
72
  <el-icon class="userMenu_icon"><arrow-down /></el-icon>
73
73
  </span>
74
74
  </template>
75
75
  <div class="userMenu_dropdown">
76
- <img class="userMenu_dropdown_avatar" :src="avatar" alt="avatar" />
76
+ <ImageView class="userMenu_dropdown_avatar" :loadKeys="userInfo?.avatarFileName" />
77
77
  <b>
78
78
  <span>{{ userInfo?.name }}</span>
79
79
  <span class="userMenu_roleName" :style="{ color: roleColor }" v-if="userInfo?.role">[{{ roleLabel }}]</span>
@@ -147,6 +147,8 @@ $topHoverSize: 35px;
147
147
  height: $topHoverSize;
148
148
  border-radius: 50%;
149
149
  margin-right: 4px;
150
+ overflow: hidden;
151
+ background: var(--jnrs-background-head);
150
152
  }
151
153
  .userMenu_icon {
152
154
  margin-left: 4px;
@@ -155,10 +157,20 @@ $topHoverSize: 35px;
155
157
  }
156
158
  .userMenu_dropdown {
157
159
  text-align: center;
160
+
161
+ .userMenu_dropdown_avatar {
162
+ width: 120px !important;
163
+ height: 120px !important;
164
+ margin: 0 auto 8px;
165
+ background: var(--jnrs-background-head);
166
+ border-radius: 5px;
167
+ }
158
168
  img {
159
169
  width: 80px;
160
170
  height: 80px;
161
171
  border-radius: 50%;
172
+ object-fit: none;
173
+ object-position: center;
162
174
  }
163
175
  b {
164
176
  display: block;
@@ -1,14 +1,38 @@
1
+ /**
2
+ * 附件(文件)信息
3
+ */
1
4
  export interface Attachment {
2
- id: string
5
+ /**
6
+ * 数据 id
7
+ */
8
+ id: number
9
+ /**
10
+ * 文件 id
11
+ */
12
+ documentId: number
13
+ /**
14
+ * 文件名
15
+ */
16
+ fileName: string
17
+ /**
18
+ * 文件名唯一标识
19
+ */
3
20
  uniqueFileName: string
21
+ /**
22
+ * MIME 类型
23
+ */
24
+ fileType: string
25
+ /**
26
+ * 文件大小 单位:字节(Bytes)
27
+ */
28
+ fileSize: number
4
29
  }
5
30
 
6
- export interface AttachmentDocument {
31
+ /**
32
+ * 文档容器(用于图片或附件)
33
+ */
34
+ export interface Document {
35
+ id: number
36
+ description: string | null
7
37
  attachments: Attachment[]
8
38
  }
9
-
10
- export interface ApiResponse {
11
- attachmentDocument?: AttachmentDocument
12
- imageDocument?: AttachmentDocument
13
- [key: string]: unknown
14
- }
@@ -6,13 +6,13 @@
6
6
  * @Desc. : 对 packages 的一些公用方法进行封装
7
7
  */
8
8
 
9
- import { ElMessage } from 'element-plus'
9
+ import { ElMessage, ElLoading } from 'element-plus'
10
10
  import {
11
- getOneDictList as _getOneDictList,
11
+ getDictList as _getDictList,
12
12
  getDictLabel as _getDictLabel,
13
13
  getDictValue as _getDictValue,
14
14
  getDictColor as _getDictColor,
15
- downloadFile as _downloadFile
15
+ downloadByBlob as _downloadByBlob
16
16
  } from '@jnrs/shared'
17
17
  import { useAuthStore } from '@jnrs/vue-core/pinia'
18
18
  import { objectToFormData as _objectToFormData } from '@jnrs/shared'
@@ -23,10 +23,10 @@ import { FileApi } from '@/api/common'
23
23
  * @param name 字典名称
24
24
  * @returns 某字典名称所对应的字典列表数据
25
25
  */
26
- export const getOneDictList = (name: string) => {
26
+ export const getDictList = (name: string) => {
27
27
  const { dict } = useAuthStore()
28
28
  if (dict) {
29
- return _getOneDictList(name, dict)
29
+ return _getDictList(name, dict)
30
30
  }
31
31
  }
32
32
 
@@ -96,15 +96,20 @@ export const objectToFormData = (obj: Record<string, unknown>) => {
96
96
  * @returns loading 下载状态
97
97
  */
98
98
  export const downloadFile = async (uniqueFileName: string, filename?: string) => {
99
+ const elLoading = ElLoading.service({
100
+ lock: true,
101
+ text: '文件下载中...',
102
+ background: 'rgba(0, 0, 0, 0.5)'
103
+ })
99
104
  let loading = true
100
- ElMessage.info('文件下载中...')
101
105
  try {
102
106
  const blob = await FileApi(uniqueFileName)
103
- _downloadFile(blob, filename || uniqueFileName)
107
+ _downloadByBlob(blob, filename || uniqueFileName)
104
108
  } catch (error) {
105
109
  console.error(error)
106
110
  ElMessage.warning('文件下载失败')
107
111
  } finally {
112
+ elLoading.close()
108
113
  loading = false
109
114
  }
110
115
  return loading
@@ -1,34 +1,114 @@
1
1
  <script setup lang="ts">
2
+ import type { FormInstance, FormRules } from 'element-plus'
3
+ import type { Attachment } from '@/types'
4
+ import type { ProjectItem, AddProjectItem } from '@/api/demos/index'
2
5
  import { ref, onActivated } from 'vue'
6
+ import { ElMessage } from 'element-plus'
7
+ import { Plus } from '@element-plus/icons-vue'
8
+ import { objectMatchAssign } from '@jnrs/shared'
9
+ import { isNumberGtZero } from '@jnrs/shared/validator'
10
+ import { getDictList, objectToFormData } from '@/utils/packages'
11
+ import { DemosTableApi, DemosFormApi } from '@/api/demos/index'
3
12
  import JnTable from '@/components/common/JnTable.vue'
4
13
  import JnPagination from '@/components/common/JnPagination.vue'
5
- import { DemosTableApi } from '@/api/demos/index'
6
- import type { ProjectItem } from '@/api/demos/index'
14
+ import ImageView from '@/components/base/ImageView.vue'
15
+ import PdfView from '@/components/base/PdfView.vue'
16
+ import JnEdit from '@/components/common/JnEdit.vue'
17
+ import JnDictTag from '@/components/common/JnDictTag.vue'
18
+ import JnDatetime from '@/components/common/JnDatetime.vue'
19
+ import JnFileUpload from '@/components/base/JnFileUpload.vue'
7
20
 
8
- const tableData = ref<ProjectItem[]>()
21
+ interface ProcessedProjectItem extends ProjectItem {
22
+ newImageFiles?: Attachment[]
23
+ newAttachmentFile?: Attachment[]
24
+ }
25
+
26
+ const loading = ref(false)
27
+ const tableData = ref<ProcessedProjectItem[]>([])
9
28
  const total = ref(0)
10
29
  const pagination = ref({ currentPage: 1, pageSize: 10 })
30
+ const jnEditRef = ref()
31
+ const ruleFormRef = ref<FormInstance>()
11
32
 
12
- const fetchData = () => {
33
+ const ruleForm = ref<AddProjectItem>({
34
+ id: '',
35
+ name: '',
36
+ program: '',
37
+ projectType: undefined,
38
+ budget: 0,
39
+ plannedStartDate: '',
40
+ description: '',
41
+ newImageFiles: [],
42
+ newAttachmentFile: []
43
+ })
44
+
45
+ const rules = ref<FormRules>({
46
+ name: [{ required: true, message: '请输入', trigger: 'change' }],
47
+ program: [{ required: true, message: '请选择', trigger: 'change' }],
48
+ projectType: [{ required: true, message: '请选择', trigger: 'change' }],
49
+ plannedStartDate: [{ required: true, message: '请选择', trigger: 'change' }],
50
+ newImageFiles: [{ required: true, message: '请上传', trigger: 'change' }],
51
+ budget: [
52
+ { required: true, message: '请输入', trigger: 'change' },
53
+ {
54
+ validator: isNumberGtZero,
55
+ trigger: 'change'
56
+ }
57
+ ]
58
+ })
59
+
60
+ const handlePaginationChange = () => {
13
61
  console.log(pagination.value)
14
62
  }
15
63
 
64
+ const handleSelectionChange = (row: ProjectItem[]) => {
65
+ console.log(row)
66
+ }
67
+
16
68
  const getDemosTable = async () => {
17
69
  try {
18
70
  const res = await DemosTableApi()
19
- tableData.value = res
71
+ tableData.value = res.map((item) => ({
72
+ ...item,
73
+ newImageFiles: item.imageDocument?.attachments ?? undefined,
74
+ newAttachmentFile: item.attachmentDocument?.attachments ?? undefined
75
+ }))
20
76
  total.value = res.length
21
77
  } catch (error) {
22
78
  console.error(error)
23
79
  }
24
80
  }
25
81
 
26
- const edit = (row: ProjectItem) => {
27
- console.log(row)
82
+ // 新增和修改
83
+ const handleEdit = (row?: ProjectItem) => {
84
+ jnEditRef.value.open()
85
+ queueMicrotask(() => {
86
+ ruleFormRef.value?.resetFields()
87
+ const matched = objectMatchAssign(ruleForm.value, row)
88
+ ruleForm.value = matched
89
+ })
28
90
  }
29
91
 
30
- const handleSelectionChange = (row: ProjectItem[]) => {
31
- console.log(row)
92
+ // 提交表单
93
+ const submitForm = () => {
94
+ ruleFormRef.value?.validate(async (valid) => {
95
+ if (valid) {
96
+ loading.value = true
97
+ const formData = objectToFormData(ruleForm.value)
98
+ try {
99
+ await DemosFormApi(formData)
100
+ ElMessage({
101
+ message: '数据已保存',
102
+ grouping: true,
103
+ type: 'success'
104
+ })
105
+ } catch (err) {
106
+ console.error(err)
107
+ } finally {
108
+ loading.value = false
109
+ }
110
+ }
111
+ })
32
112
  }
33
113
 
34
114
  onActivated(() => {
@@ -37,9 +117,77 @@ onActivated(() => {
37
117
  </script>
38
118
 
39
119
  <template>
120
+ <JnEdit ref="jnEditRef" title="项目管理" width="600px">
121
+ <el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="auto" v-loading="loading">
122
+ <el-form-item prop="id"></el-form-item>
123
+ <el-form-item label="项目名称" prop="name">
124
+ <el-input v-model.trim="ruleForm.name" maxlength="20" show-word-limit />
125
+ </el-form-item>
126
+ <el-form-item label="类型" prop="projectType">
127
+ <el-select v-model="ruleForm.projectType" filterable placeholder="">
128
+ <el-option
129
+ :label="item.label"
130
+ :value="item.value"
131
+ v-for="item in getDictList('projectType')"
132
+ :key="item.value"
133
+ />
134
+ </el-select>
135
+ </el-form-item>
136
+ <el-form-item label="预算" prop="budget">
137
+ <el-input-number v-model="ruleForm.budget" :min="0" :precision="2" :step="10000" controls-position="right">
138
+ <template #prefix>
139
+ <span>¥</span>
140
+ </template>
141
+ </el-input-number>
142
+ </el-form-item>
143
+ <el-form-item label="计划开始时间" prop="plannedStartDate">
144
+ <el-date-picker
145
+ v-model="ruleForm.plannedStartDate"
146
+ type="datetime"
147
+ format="YYYY-MM-DD HH:mm:ss"
148
+ value-format="YYYY-MM-DD HH:mm:ss"
149
+ :disabled-date="
150
+ (time: number) => {
151
+ return time < Date.now() - 86400000
152
+ }
153
+ "
154
+ />
155
+ </el-form-item>
156
+ <el-form-item label="描述" prop="description">
157
+ <el-input
158
+ v-model="ruleForm.description"
159
+ :autosize="{ minRows: 2, maxRows: 4 }"
160
+ type="textarea"
161
+ maxlength="200"
162
+ show-word-limit
163
+ />
164
+ </el-form-item>
165
+ <el-form-item label="上传图片" prop="newImageFiles">
166
+ <JnFileUpload
167
+ v-model="ruleForm.newImageFiles"
168
+ :formRef="ruleFormRef"
169
+ validateFieldName="newImageFiles"
170
+ accept=".png,.jpg,.bmp,.gif"
171
+ :fileSizeMb="50"
172
+ :limit="3"
173
+ drag
174
+ />
175
+ </el-form-item>
176
+ <el-form-item label="上传文件" prop="newAttachmentFile">
177
+ <JnFileUpload v-model="ruleForm.newAttachmentFile" accept=".pdf" :limit="1" />
178
+ </el-form-item>
179
+ </el-form>
180
+ <template #footer>
181
+ <el-button type="success" icon="Select" :loading="loading" @click="submitForm()">提交</el-button>
182
+ </template>
183
+ </JnEdit>
184
+
40
185
  <el-card>
41
186
  <template #header>
42
- <span>Card name</span>
187
+ <div class="card_header">
188
+ <span>项目管理</span>
189
+ <el-button type="primary" size="small" :icon="Plus" @click="handleEdit()">新增</el-button>
190
+ </div>
43
191
  </template>
44
192
  <JnTable
45
193
  :data="tableData"
@@ -51,29 +199,29 @@ onActivated(() => {
51
199
  <el-table-column prop="code" label="项目编号" min-width="200" sortable show-overflow-tooltip />
52
200
  <el-table-column prop="name" label="项目名称" min-width="200" sortable show-overflow-tooltip>
53
201
  <template #default="{ row }">
54
- <span>{{ row.name }}</span>
202
+ {{ row.name }}
55
203
  </template>
56
204
  </el-table-column>
57
205
  <el-table-column prop="program" label="项目集名称" min-width="200" sortable show-overflow-tooltip />
58
- <el-table-column prop="type" label="项目类型" width="100" align="center" sortable>
206
+ <el-table-column prop="projectType" label="项目类型" width="100" align="center" sortable>
59
207
  <template #default="{ row }">
60
- <span>{{ row.type }}</span>
208
+ <JnDictTag dictName="projectType" :value="row.projectType" />
61
209
  </template>
62
210
  </el-table-column>
63
211
  <el-table-column prop="manager" label="项目经理" width="100" align="center" sortable />
64
- <el-table-column prop="budget" label="预算" width="100" align="center" sortable>
212
+ <el-table-column prop="budget" label="预算(¥)" width="100" align="center" sortable>
65
213
  <template #default="{ row }">
66
- <span>{{ row.budget }}</span>
214
+ {{ row.budget }}
67
215
  </template>
68
216
  </el-table-column>
69
- <el-table-column prop="plannedStartDate" label="计划开始日期" width="130" align="center" sortable>
217
+ <el-table-column prop="plannedStartDate" label="计划开始时间" width="130" align="center" sortable>
70
218
  <template #default="{ row }">
71
- <span>{{ row.plannedStartDate }}</span>
219
+ <JnDatetime :value="row.plannedStartDate" />
72
220
  </template>
73
221
  </el-table-column>
74
222
  <el-table-column prop="plannedFinishDate" label="计划完成日期" width="130" align="center" sortable>
75
223
  <template #default="{ row }">
76
- <span>{{ row.plannedFinishDate }}</span>
224
+ {{ row.plannedFinishDate }}
77
225
  </template>
78
226
  </el-table-column>
79
227
  <el-table-column prop="progress" label="进度" width="100" align="center" sortable>
@@ -83,26 +231,34 @@ onActivated(() => {
83
231
  </el-table-column>
84
232
  <el-table-column prop="status" label="状态" width="100" align="center" sortable>
85
233
  <template #default="{ row }">
86
- <span>{{ row.status }}</span>
234
+ <JnDictTag dictName="status" :value="row.status" :showColor="false" />
87
235
  </template>
88
236
  </el-table-column>
237
+ <el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
89
238
  <el-table-column prop="imageDocument" label="图片" width="100" align="center" sortable>
90
239
  <template #default="{ row }">
91
- <span>{{ row.imageDocument?.attachments.length || 0 }}</span>
240
+ <ImageView :loadKeys="row.newImageFiles" preview maxHeight="50px" />
92
241
  </template>
93
242
  </el-table-column>
94
243
  <el-table-column prop="attachmentDocument" label="附件" width="100" align="center" sortable>
95
244
  <template #default="{ row }">
96
- <span>{{ row.attachmentDocument?.attachments.length || 0 }}</span>
245
+ <PdfView :loadKeys="row.newAttachmentFile" isPdf />
97
246
  </template>
98
247
  </el-table-column>
99
248
  <el-table-column label="操作" width="100" align="center" fixed="right">
100
249
  <template #default="{ row }">
101
- <el-button link type="primary" @click.stop="edit(row)">编辑</el-button>
250
+ <el-button link type="primary" @click.stop="handleEdit(row)">编辑</el-button>
102
251
  </template>
103
252
  </el-table-column>
104
253
  </JnTable>
105
- <jn-pagination :total="total" v-model="pagination" @change="fetchData" />
254
+
255
+ <JnPagination :total="total" v-model="pagination" @change="handlePaginationChange" />
106
256
  </el-card>
107
257
  </template>
108
- <style scoped></style>
258
+
259
+ <style lang="scss" scoped>
260
+ .card_header {
261
+ display: flex;
262
+ justify-content: space-between;
263
+ }
264
+ </style>
@@ -1,15 +1,14 @@
1
1
  <script setup lang="ts">
2
2
  import { ref } from 'vue'
3
- import { storeToRefs } from 'pinia'
4
3
  import { ElMessage } from 'element-plus'
5
4
  import { objectToFormData } from '@/utils/packages'
6
- import { useMockStore } from '@jnrs/vue-core/pinia'
7
5
  import { LoginApi, UserInfoApi } from '@/api/system'
8
6
  import { NotFoundApi, NoAuth, DetailsApi } from '@/api/demos'
9
7
  import { getFileUrl } from '@/utils/file'
10
8
  import { downloadFile } from '@/utils/packages'
11
9
 
12
- const { isMock } = storeToRefs(useMockStore())
10
+ import ImageView from '@/components/base/ImageView.vue'
11
+
13
12
  const squareUrl = ref()
14
13
 
15
14
  const loginParams = ref({
@@ -80,10 +79,10 @@ const handleDetailsApi = async () => {
80
79
  }
81
80
  }
82
81
 
83
- // 获取后端服务器文件进行下载
82
+ // 获取后端服务器文件进行预览
84
83
  const handleFileView = async () => {
85
84
  try {
86
- const url = await getFileUrl('20251217171430919-34bcc1a9-a19d-4b91-9ab6-57cb31c3df28.jpg')
85
+ const url = await getFileUrl('mock-png-1.png')
87
86
  squareUrl.value = url.value
88
87
  } catch (error) {
89
88
  console.log(error)
@@ -93,10 +92,6 @@ const handleFileView = async () => {
93
92
 
94
93
  <template>
95
94
  <p>网络请求测试</p>
96
- <div>
97
- <span>服务器类型:</span>
98
- <el-switch v-model="isMock" active-text="Mock 服务器" inactive-text="后端服务器" />
99
- </div>
100
95
  <el-button-group>
101
96
  <el-button type="success" size="small" @click="handleInfoApi">获取用户数据</el-button>
102
97
  <el-button type="primary" size="small" @click="handleNotFoundApi">404</el-button>
@@ -111,20 +106,21 @@ const handleFileView = async () => {
111
106
  <div>
112
107
  <el-button-group>
113
108
  <el-button type="primary" plain size="small" @click="handleDetailsApi">获取数据列表单个数据</el-button>
114
- <el-button
115
- type="primary"
116
- plain
117
- size="small"
118
- @click="downloadFile('20251217171430919-34bcc1a9-a19d-4b91-9ab6-57cb31c3df28.jpg')"
119
- >
109
+ <el-button type="primary" plain size="small" @click="downloadFile('mock-pdf.pdf')">
120
110
  获取后端服务器文件进行下载
121
111
  </el-button>
122
112
  </el-button-group>
123
113
  <div>
124
- <el-avatar shape="square" :src="squareUrl" />
114
+ <span>通过 ImageView 组件显示的图片(可支持预览)</span>
115
+ <ImageView
116
+ loadKeys="mock-png-1.png"
117
+ preview
118
+ style="width: 300px; height: 50px; border: 1px solid var(--jnrs-color-primary)"
119
+ />
125
120
  </div>
126
121
  <div>
127
122
  <el-button type="primary" plain size="small" @click="handleFileView">获取后端服务器图片</el-button>
123
+ <el-avatar shape="circle" :src="squareUrl" />
128
124
  </div>
129
125
  </div>
130
126
  </template>
@@ -16,12 +16,7 @@ const showGlobalSetting = () => {
16
16
  }
17
17
 
18
18
  const loading = ref(false)
19
- const {
20
- setUserInfo,
21
- setToken,
22
- setDict
23
- // setRole
24
- } = useAuthStore()
19
+ const { setUserInfo, setToken, setDict, setRole } = useAuthStore()
25
20
 
26
21
  // 表单 ref
27
22
  const ruleFormRef = ref<FormInstance>()
@@ -51,21 +46,21 @@ const submitForm = async () => {
51
46
  const loginDateTime = formatDateTime() + ' ' + formatWeekday()
52
47
 
53
48
  // 获取角色列表,将登录人角色对应的权限叠加给当前登录人(一次性获取叠加)
54
- // const roleRes = await RoleApi()
55
- // let permissionsMerger = restParameter.permissions
56
- // if (Array.isArray(restParameter.permissions)) {
57
- // permissionsMerger = [
58
- // ...new Set([
59
- // ...restParameter.permissions,
60
- // ...(roleRes.find((r) => r.value === restParameter.role)?.permissions ?? []).flat()
61
- // ])
62
- // ]
63
- // }
64
- // setRole(roleRes) // 由于是一次性获取叠加,此处不需要保存角色列表到全局状态
49
+ const roleRes = await RoleApi()
50
+ let permissionsMerger = restParameter.permissions
51
+ if (Array.isArray(restParameter.permissions)) {
52
+ permissionsMerger = [
53
+ ...new Set([
54
+ ...restParameter.permissions,
55
+ ...(roleRes.find((r) => r.value === restParameter.role)?.permissions ?? []).flat()
56
+ ])
57
+ ]
58
+ }
59
+ setRole(roleRes) // 由于是一次性获取叠加,此处不需要保存角色列表到全局状态
65
60
 
66
61
  setUserInfo({
67
62
  ...restParameter,
68
- // permissions: permissionsMerger,
63
+ permissions: permissionsMerger,
69
64
  account: ruleForm.value.account,
70
65
  loginDateTime
71
66
  })
@@ -5,7 +5,7 @@ import { ElMessage } from 'element-plus'
5
5
  import type { UploadProps } from 'element-plus'
6
6
  import { useAuthStore } from '@jnrs/vue-core/pinia'
7
7
  import { useAvatar } from '@/composables/base/useAvatar'
8
- import { getOneDictList } from '@/utils/packages'
8
+ import { getDictList } from '@/utils/packages'
9
9
  import type { User } from '@jnrs/shared'
10
10
 
11
11
  const { userInfo, token } = storeToRefs(useAuthStore())
@@ -81,7 +81,7 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
81
81
  <el-option
82
82
  :label="item.label"
83
83
  :value="item.value"
84
- v-for="(item, index) in getOneDictList('jobTitle')"
84
+ v-for="(item, index) in getDictList('jobTitle')"
85
85
  :key="index"
86
86
  />
87
87
  </el-select>
@@ -91,12 +91,7 @@ const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
91
91
  </el-form-item>
92
92
  <el-form-item label="职位/账号权限" prop="role">
93
93
  <el-select v-model="ruleForm.role" placeholder="" style="width: 200px">
94
- <el-option
95
- :label="item.label"
96
- :value="item.value"
97
- v-for="(item, index) in getOneDictList('role')"
98
- :key="index"
99
- />
94
+ <el-option :label="item.label" :value="item.value" v-for="(item, index) in getDictList('role')" :key="index" />
100
95
  </el-select>
101
96
  </el-form-item>
102
97
  <el-form-item label="头像" prop="avatarFileName" class="uploader_item">
@@ -24,7 +24,10 @@
24
24
  "src/**/*",
25
25
  "vite.config.ts",
26
26
  "../../../packages/shared/src/validate.ts",
27
- "../../../packages/shared/src/validator.ts"
27
+ "../../../packages/shared/src/validator.ts",
28
+ "../../../packages/vue-core/src/components/JnImageView.vue",
29
+ "../../../packages/vue-core/src/components/JnPdfView.vue",
30
+ "src/components/common/JnEdit.vue"
28
31
  ],
29
32
  "exclude": ["node_modules", "dist"]
30
33
  }
@@ -35,7 +35,7 @@ export default defineConfig({
35
35
  mockPath: 'viteMockServe', // mock 文件目录
36
36
  watchFiles: true, // mock 文件热更新
37
37
  enable: isMock, // 是否开启
38
- logger: isMock // 是否在终端显示请求日志
38
+ logger: false // 是否在终端显示请求日志
39
39
  })
40
40
  ],
41
41
  resolve: {