create-jnrs-vue 1.2.20 → 1.2.21
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/jnrs-vue/components.d.ts +3 -1
- package/jnrs-vue/package.json +3 -3
- package/jnrs-vue/src/App.vue +1 -1
- package/jnrs-vue/src/api/demos/index.ts +12 -3
- package/jnrs-vue/src/api/system/index.ts +3 -0
- package/jnrs-vue/src/assets/styles/animation.scss +15 -0
- package/jnrs-vue/src/components/common/CardTable.vue +1 -1
- package/jnrs-vue/src/components/common/DictTag.vue +8 -6
- package/jnrs-vue/src/components/common/ImageView.vue +1 -1
- package/jnrs-vue/src/components/common/PdfView.vue +1 -1
- package/jnrs-vue/src/components/select/SelectManager.vue +2 -2
- package/jnrs-vue/src/composables/useCrud.ts +131 -0
- package/jnrs-vue/src/layout/RouterTabs.vue +151 -3
- package/jnrs-vue/src/layout/SideMenu.vue +212 -139
- package/jnrs-vue/src/layout/TopHeader.vue +44 -22
- package/jnrs-vue/src/locales/en.ts +40 -1
- package/jnrs-vue/src/locales/index.ts +2 -2
- package/jnrs-vue/src/locales/zhCn.ts +40 -1
- package/jnrs-vue/src/main.ts +2 -2
- package/jnrs-vue/src/router/routes.ts +1 -1
- package/jnrs-vue/src/views/demos/crud/index.vue +47 -9
- package/jnrs-vue/src/views/demos/simpleTable/index.vue +2 -2
- package/jnrs-vue/src/views/home/index.vue +312 -3
- package/jnrs-vue/src/views/login/index.vue +2 -2
- package/jnrs-vue/vite.config.ts +2 -1
- package/jnrs-vue/viteMockServe/fail.ts +3 -3
- package/jnrs-vue/viteMockServe/file.ts +4 -4
- package/jnrs-vue/viteMockServe/success.ts +9 -1
- package/package.json +1 -1
- package/jnrs-vue/src/layout/RouterTabs /344/277/256/345/244/215/350/267/257/347/224/261/350/267/263/350/275/254/346/220/272/345/270/246/345/217/202/346/225/260/351/227/256/351/242/230.vue" +0 -150
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import type { FormInstance, FormRules } from 'element-plus'
|
|
3
3
|
import type { Attachment, Pagination } from '@/types'
|
|
4
4
|
import type { ProjectItem, AddProjectItem } from '@/api/demos/index'
|
|
5
|
-
import { ref, onActivated } from 'vue'
|
|
6
|
-
import { ElMessage } from 'element-plus'
|
|
5
|
+
import { ref, onActivated, nextTick } from 'vue'
|
|
6
|
+
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
7
7
|
import { Plus } from '@element-plus/icons-vue'
|
|
8
8
|
import { useRoute } from '@jnrs/vue-core/router'
|
|
9
9
|
import { objectMatchAssign, dateFormatsToObject } from '@jnrs/shared'
|
|
10
10
|
import { debounce } from '@jnrs/shared/lodash'
|
|
11
11
|
import { isNumberGtZero } from '@jnrs/shared/validator'
|
|
12
12
|
import { getDictList, downloadFile } from '@/utils/packages'
|
|
13
|
-
import {
|
|
14
|
-
|
|
13
|
+
import { useI18n } from '@/locales'
|
|
14
|
+
import { ListApi, EditApi, DelApi, ImportTemplateApi, ImportDataApi, ExportApi } from '@/api/demos/index'
|
|
15
15
|
import { JnDialog, JnDatetime, JnPagination, JnFileUpload, JnTable, JnImportAndExport } from '@jnrs/vue-core/components'
|
|
16
16
|
import ImageView from '@/components/common/ImageView.vue'
|
|
17
17
|
import PdfView from '@/components/common/PdfView.vue'
|
|
@@ -23,6 +23,7 @@ interface ProcessedProjectItem extends ProjectItem {
|
|
|
23
23
|
newAttachmentFile?: Attachment[]
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
const { t: $t } = useI18n()
|
|
26
27
|
const loading = ref(false)
|
|
27
28
|
const tableData = ref<ProcessedProjectItem[]>([])
|
|
28
29
|
const total = ref(0)
|
|
@@ -73,7 +74,7 @@ const handleSelectionChange = (row: ProjectItem[]) => {
|
|
|
73
74
|
const getTable = debounce(async () => {
|
|
74
75
|
loading.value = true
|
|
75
76
|
try {
|
|
76
|
-
const res = await
|
|
77
|
+
const res = await ListApi({
|
|
77
78
|
...pagination.value,
|
|
78
79
|
...queryForm.value
|
|
79
80
|
})
|
|
@@ -93,7 +94,7 @@ const getTable = debounce(async () => {
|
|
|
93
94
|
// 新增和修改
|
|
94
95
|
const handleEdit = (row?: ProjectItem) => {
|
|
95
96
|
editDialogRef.value.open()
|
|
96
|
-
|
|
97
|
+
nextTick(() => {
|
|
97
98
|
ruleFormRef.value?.resetFields()
|
|
98
99
|
const matched = objectMatchAssign(ruleForm.value, row)
|
|
99
100
|
ruleForm.value = matched
|
|
@@ -107,6 +108,34 @@ const handleEdit = (row?: ProjectItem) => {
|
|
|
107
108
|
})
|
|
108
109
|
}
|
|
109
110
|
|
|
111
|
+
const handleDelete = (row: ProjectItem) => {
|
|
112
|
+
ElMessageBox.confirm('<p style="color: #f30">请注意,您尚未保存的数据将会丢失。</p>', '确定要删除吗?', {
|
|
113
|
+
dangerouslyUseHTMLString: true,
|
|
114
|
+
confirmButtonType: 'danger',
|
|
115
|
+
confirmButtonText: $t('global.action.confirm'),
|
|
116
|
+
cancelButtonText: $t('global.action.cancel')
|
|
117
|
+
})
|
|
118
|
+
.then(async () => {
|
|
119
|
+
loading.value = true
|
|
120
|
+
try {
|
|
121
|
+
await DelApi(row.id)
|
|
122
|
+
ElMessage({
|
|
123
|
+
message: '',
|
|
124
|
+
grouping: true,
|
|
125
|
+
showClose: true,
|
|
126
|
+
type: 'success'
|
|
127
|
+
})
|
|
128
|
+
editDialogRef.value.close()
|
|
129
|
+
getTable()
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.error(err)
|
|
132
|
+
} finally {
|
|
133
|
+
loading.value = false
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
.catch(() => {})
|
|
137
|
+
}
|
|
138
|
+
|
|
110
139
|
// 提交表单
|
|
111
140
|
const submitForm = () => {
|
|
112
141
|
ruleFormRef.value?.validate(async (valid) => {
|
|
@@ -120,6 +149,8 @@ const submitForm = () => {
|
|
|
120
149
|
showClose: true,
|
|
121
150
|
type: 'success'
|
|
122
151
|
})
|
|
152
|
+
editDialogRef.value.close()
|
|
153
|
+
getTable()
|
|
123
154
|
} catch (err) {
|
|
124
155
|
console.error(err)
|
|
125
156
|
} finally {
|
|
@@ -130,14 +161,20 @@ const submitForm = () => {
|
|
|
130
161
|
}
|
|
131
162
|
|
|
132
163
|
onActivated(() => {
|
|
133
|
-
console.log(route.meta)
|
|
164
|
+
console.log(route.meta) // 获取路由元信息
|
|
134
165
|
getTable()
|
|
135
166
|
})
|
|
136
167
|
</script>
|
|
137
168
|
|
|
138
169
|
<template>
|
|
139
170
|
<!-- 编辑弹窗 -->
|
|
140
|
-
<JnDialog
|
|
171
|
+
<JnDialog
|
|
172
|
+
ref="editDialogRef"
|
|
173
|
+
title="项目管理"
|
|
174
|
+
width="600px"
|
|
175
|
+
:close-on-click-modal="false"
|
|
176
|
+
:close-on-press-escape="true"
|
|
177
|
+
>
|
|
141
178
|
<el-form ref="ruleFormRef" :model="ruleForm" :rules="rules" label-width="auto" v-loading="loading">
|
|
142
179
|
<el-form-item prop="id"></el-form-item>
|
|
143
180
|
<el-form-item label="项目名称" prop="name">
|
|
@@ -342,9 +379,10 @@ onActivated(() => {
|
|
|
342
379
|
<PdfView :loadKeys="row.newAttachmentFile" isPdf />
|
|
343
380
|
</template>
|
|
344
381
|
</el-table-column>
|
|
345
|
-
<el-table-column label="操作" width="
|
|
382
|
+
<el-table-column label="操作" width="120" align="center" fixed="right">
|
|
346
383
|
<template #default="{ row }">
|
|
347
384
|
<el-button link type="primary" @click.stop="handleEdit(row)">编辑</el-button>
|
|
385
|
+
<el-button link type="danger" @click.stop="handleDelete(row)">删除</el-button>
|
|
348
386
|
</template>
|
|
349
387
|
</el-table-column>
|
|
350
388
|
</JnTable>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { ListApi } from '@/api/demos/index'
|
|
3
3
|
import { JnDatetime } from '@jnrs/vue-core/components'
|
|
4
4
|
import CardTable from '@/components/common/CardTable.vue'
|
|
5
5
|
import ImageView from '@/components/common/ImageView.vue'
|
|
@@ -8,7 +8,7 @@ import DictTag from '@/components/common/DictTag.vue'
|
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
10
|
<template>
|
|
11
|
-
<CardTable :getTableDataApi="
|
|
11
|
+
<CardTable :getTableDataApi="ListApi">
|
|
12
12
|
<template #header>项目列表</template>
|
|
13
13
|
<template #table>
|
|
14
14
|
<el-table-column prop="name" label="项目名称" min-width="200" sortable show-overflow-tooltip />
|
|
@@ -1,9 +1,318 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref } from 'vue'
|
|
2
|
+
import { ref, computed, onActivated, onDeactivated } from 'vue'
|
|
3
|
+
import { formatDateTime, formatWeekday, formatGreeting } from '@jnrs/shared'
|
|
4
|
+
import { useAuthStore } from '@jnrs/vue-core/pinia'
|
|
5
|
+
import { handleRouter } from '@jnrs/vue-core/router'
|
|
6
|
+
import ImageView from '@/components/common/ImageView.vue'
|
|
7
|
+
|
|
8
|
+
const { userInfo } = useAuthStore()
|
|
9
|
+
|
|
10
|
+
// 当前时间
|
|
11
|
+
const currentTime = ref('0000-00-00 00:00:00')
|
|
12
|
+
let timer: ReturnType<typeof setInterval>
|
|
13
|
+
|
|
14
|
+
// 格式化时间
|
|
15
|
+
const formattedTime = computed(() => {
|
|
16
|
+
const d = currentTime.value
|
|
17
|
+
return {
|
|
18
|
+
date: d.split(' ')[0],
|
|
19
|
+
time: d.split(' ')[1],
|
|
20
|
+
weekday: formatWeekday(),
|
|
21
|
+
greeting: formatGreeting()
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// 统计卡片配置
|
|
26
|
+
const statCards = [
|
|
27
|
+
{ titleKey: 'home.quickEntry.unitTest', path: '/unitTest', icon: 'IceCreamSquare', value: 999 },
|
|
28
|
+
{ titleKey: 'home.quickEntry.simpleTable', path: '/simpleTable', icon: 'Box', value: 1 },
|
|
29
|
+
{ titleKey: 'home.quickEntry.crud', path: '/crud', icon: 'Notification', value: 22 },
|
|
30
|
+
{ titleKey: 'home.quickEntry.visual', path: '/visual', icon: 'Cpu', value: 0 }
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
// 快捷入口配置
|
|
34
|
+
const quickEntries = [
|
|
35
|
+
{ titleKey: 'home.quickEntry.unitTest', path: '/unitTest', icon: 'IceCreamSquare', color: '#409eff' },
|
|
36
|
+
{ titleKey: 'home.quickEntry.simpleTable', path: '/simpleTable', icon: 'Box', color: '#67c23a' },
|
|
37
|
+
{ titleKey: 'home.quickEntry.crud', path: '/crud', icon: 'Notification', color: '#e6a23c' },
|
|
38
|
+
{ titleKey: 'home.quickEntry.visual', path: '/visual', icon: 'Cpu', color: '#9c27b0' }
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
// 跳转页面
|
|
42
|
+
const navigateTo = (path: string) => {
|
|
43
|
+
handleRouter({ path })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
onActivated(() => {
|
|
47
|
+
timer = setInterval(() => {
|
|
48
|
+
currentTime.value = formatDateTime()
|
|
49
|
+
}, 1000)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
onDeactivated(() => {
|
|
53
|
+
clearInterval(timer)
|
|
54
|
+
})
|
|
3
55
|
</script>
|
|
4
56
|
|
|
5
57
|
<template>
|
|
6
|
-
<div
|
|
58
|
+
<div class="home-page">
|
|
59
|
+
<!-- 顶部欢迎区域 -->
|
|
60
|
+
<el-card shadow="never" class="welcome-card">
|
|
61
|
+
<div class="welcome-content">
|
|
62
|
+
<div class="welcome-left">
|
|
63
|
+
<div class="avatar-wrapper">
|
|
64
|
+
<ImageView v-if="userInfo?.avatarFileName" class="avatar" :loadKeys="userInfo.avatarFileName" />
|
|
65
|
+
<img v-else class="avatar" src="@/assets/images/common/avatar.png" alt="avatar" />
|
|
66
|
+
</div>
|
|
67
|
+
<div class="welcome-info">
|
|
68
|
+
<div class="welcome-text">
|
|
69
|
+
<span class="name">{{ userInfo?.name || $t('home.welcome.defaultName') }}</span>
|
|
70
|
+
<span class="greeting">,{{ formattedTime?.greeting }}</span>
|
|
71
|
+
</div>
|
|
72
|
+
<div class="welcome-meta">
|
|
73
|
+
<span class="account">{{ $t('home.welcome.accountLabel') }}{{ userInfo?.account }}</span>
|
|
74
|
+
<span class="divider">|</span>
|
|
75
|
+
<span class="login-time">{{ $t('home.welcome.lastLoginLabel') }}{{ userInfo?.loginDateTime }}</span>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="welcome-right">
|
|
80
|
+
<div class="time-display">
|
|
81
|
+
<div class="time">{{ formattedTime.time }}</div>
|
|
82
|
+
<div class="date-info">
|
|
83
|
+
<span class="date">{{ formattedTime.date }}</span>
|
|
84
|
+
<span class="weekday">{{ formattedTime.weekday }}</span>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</el-card>
|
|
90
|
+
|
|
91
|
+
<!-- 统计卡片 -->
|
|
92
|
+
<el-row :gutter="16" class="stats-row">
|
|
93
|
+
<el-col :span="6" v-for="item in statCards" :key="item.path">
|
|
94
|
+
<el-card shadow="never" class="stat-card" @click="navigateTo(item.path)">
|
|
95
|
+
<div class="stat-content">
|
|
96
|
+
<div class="stat-icon" :style="{ background: `var(--jnrs-color-primary-005)` }">
|
|
97
|
+
<el-icon :size="28"><component :is="item.icon" /></el-icon>
|
|
98
|
+
</div>
|
|
99
|
+
<div class="stat-info">
|
|
100
|
+
<div class="stat-value">{{ item.value }}</div>
|
|
101
|
+
<div class="stat-label">{{ $t(item.titleKey) }}</div>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</el-card>
|
|
105
|
+
</el-col>
|
|
106
|
+
</el-row>
|
|
107
|
+
|
|
108
|
+
<!-- 快捷入口 -->
|
|
109
|
+
<el-card shadow="never" class="section-card">
|
|
110
|
+
<template #header>
|
|
111
|
+
<div class="section-header">
|
|
112
|
+
<span class="section-title">{{ $t('home.section.quickEntryTitle') }}</span>
|
|
113
|
+
</div>
|
|
114
|
+
</template>
|
|
115
|
+
<div class="quick-entries">
|
|
116
|
+
<div class="entry-item" v-for="entry in quickEntries" :key="entry.path" @click="navigateTo(entry.path)">
|
|
117
|
+
<div class="entry-icon" :style="{ background: entry.color + '15', color: entry.color }">
|
|
118
|
+
<el-icon :size="24"><component :is="entry.icon" /></el-icon>
|
|
119
|
+
</div>
|
|
120
|
+
<div class="entry-title">{{ $t(entry.titleKey) }}</div>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
</el-card>
|
|
124
|
+
</div>
|
|
7
125
|
</template>
|
|
8
126
|
|
|
9
|
-
<style lang="scss" scoped
|
|
127
|
+
<style lang="scss" scoped>
|
|
128
|
+
.home-page {
|
|
129
|
+
padding-bottom: 20px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// 欢迎卡片
|
|
133
|
+
.welcome-card {
|
|
134
|
+
margin-bottom: 16px;
|
|
135
|
+
|
|
136
|
+
:deep(.el-card__body) {
|
|
137
|
+
padding: 24px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.welcome-content {
|
|
141
|
+
display: flex;
|
|
142
|
+
justify-content: space-between;
|
|
143
|
+
align-items: center;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.welcome-left {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
gap: 20px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.avatar-wrapper {
|
|
153
|
+
.avatar {
|
|
154
|
+
width: 64px;
|
|
155
|
+
height: 64px;
|
|
156
|
+
border-radius: 50%;
|
|
157
|
+
object-fit: cover;
|
|
158
|
+
border: 4px solid var(--jnrs-color-primary-01);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.welcome-info {
|
|
163
|
+
.welcome-text {
|
|
164
|
+
font-size: 20px;
|
|
165
|
+
margin-bottom: 8px;
|
|
166
|
+
|
|
167
|
+
.name {
|
|
168
|
+
font-weight: 600;
|
|
169
|
+
color: var(--jnrs-color-primary);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.greeting {
|
|
173
|
+
color: var(--jnrs-font-primary-08);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.welcome-meta {
|
|
178
|
+
font-size: 13px;
|
|
179
|
+
color: var(--jnrs-font-primary-06);
|
|
180
|
+
|
|
181
|
+
.divider {
|
|
182
|
+
margin: 0 12px;
|
|
183
|
+
color: var(--jnrs-font-primary-02);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.welcome-right {
|
|
189
|
+
.time-display {
|
|
190
|
+
text-align: right;
|
|
191
|
+
|
|
192
|
+
.time {
|
|
193
|
+
font-size: 32px;
|
|
194
|
+
font-weight: 600;
|
|
195
|
+
font-family: monospace;
|
|
196
|
+
color: var(--jnrs-color-primary);
|
|
197
|
+
letter-spacing: 2px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.date-info {
|
|
201
|
+
margin-top: 4px;
|
|
202
|
+
font-size: 14px;
|
|
203
|
+
color: var(--jnrs-font-primary-06);
|
|
204
|
+
|
|
205
|
+
.date {
|
|
206
|
+
margin-right: 12px;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 统计卡片
|
|
214
|
+
.stats-row {
|
|
215
|
+
margin-bottom: 16px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.stat-card {
|
|
219
|
+
cursor: pointer;
|
|
220
|
+
transition: all 0.3s ease;
|
|
221
|
+
|
|
222
|
+
&:hover {
|
|
223
|
+
transform: translateY(-2px);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
:deep(.el-card__body) {
|
|
227
|
+
padding: 20px;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
.stat-content {
|
|
231
|
+
display: flex;
|
|
232
|
+
align-items: center;
|
|
233
|
+
gap: 16px;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.stat-icon {
|
|
237
|
+
width: 56px;
|
|
238
|
+
height: 56px;
|
|
239
|
+
border-radius: 12px;
|
|
240
|
+
display: flex;
|
|
241
|
+
align-items: center;
|
|
242
|
+
justify-content: center;
|
|
243
|
+
color: var(--jnrs-color-primary);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.stat-info {
|
|
247
|
+
.stat-value {
|
|
248
|
+
font-size: 28px;
|
|
249
|
+
font-weight: 600;
|
|
250
|
+
color: var(--jnrs-font-primary);
|
|
251
|
+
line-height: 1.2;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.stat-label {
|
|
255
|
+
font-size: 14px;
|
|
256
|
+
color: var(--jnrs-font-primary-06);
|
|
257
|
+
margin-top: 4px;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 区块卡片
|
|
263
|
+
.section-card {
|
|
264
|
+
margin-bottom: 16px;
|
|
265
|
+
|
|
266
|
+
.section-header {
|
|
267
|
+
.section-title {
|
|
268
|
+
font-size: 16px;
|
|
269
|
+
font-weight: 600;
|
|
270
|
+
color: var(--jnrs-font-primary);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// 快捷入口
|
|
276
|
+
.quick-entries {
|
|
277
|
+
display: grid;
|
|
278
|
+
grid-template-columns: repeat(6, 1fr);
|
|
279
|
+
gap: 16px;
|
|
280
|
+
|
|
281
|
+
.entry-item {
|
|
282
|
+
display: flex;
|
|
283
|
+
flex-direction: column;
|
|
284
|
+
align-items: center;
|
|
285
|
+
padding: 20px 16px;
|
|
286
|
+
border-radius: 8px;
|
|
287
|
+
cursor: pointer;
|
|
288
|
+
transition: all 0.3s ease;
|
|
289
|
+
background: var(--jnrs-background-primary);
|
|
290
|
+
|
|
291
|
+
&:hover {
|
|
292
|
+
background: var(--jnrs-color-primary-005);
|
|
293
|
+
transform: translateY(-2px);
|
|
294
|
+
|
|
295
|
+
.entry-icon {
|
|
296
|
+
transform: scale(1.1);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.entry-icon {
|
|
301
|
+
width: 48px;
|
|
302
|
+
height: 48px;
|
|
303
|
+
border-radius: 12px;
|
|
304
|
+
display: flex;
|
|
305
|
+
align-items: center;
|
|
306
|
+
justify-content: center;
|
|
307
|
+
margin-bottom: 12px;
|
|
308
|
+
transition: transform 0.3s ease;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.entry-title {
|
|
312
|
+
font-size: 14px;
|
|
313
|
+
color: var(--jnrs-font-primary-08);
|
|
314
|
+
text-align: center;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
</style>
|
|
@@ -261,7 +261,7 @@ const submitForm = async () => {
|
|
|
261
261
|
|
|
262
262
|
.greeting {
|
|
263
263
|
position: relative;
|
|
264
|
-
color: var(--jnrs-color-primary-
|
|
264
|
+
color: var(--jnrs-color-primary-05);
|
|
265
265
|
font-size: 14px;
|
|
266
266
|
text-align: center;
|
|
267
267
|
text-transform: uppercase;
|
|
@@ -274,7 +274,7 @@ const submitForm = async () => {
|
|
|
274
274
|
top: 50%;
|
|
275
275
|
width: 35%;
|
|
276
276
|
height: 1px;
|
|
277
|
-
background: var(--jnrs-color-primary-
|
|
277
|
+
background: var(--jnrs-color-primary-05);
|
|
278
278
|
transform: translateY(-50%);
|
|
279
279
|
filter: opacity(0.25);
|
|
280
280
|
}
|
package/jnrs-vue/vite.config.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { IncomingMessage, ServerResponse } from 'http'
|
|
|
2
2
|
|
|
3
3
|
const res_fail = {
|
|
4
4
|
code: 1,
|
|
5
|
-
msg: '
|
|
5
|
+
msg: 'mock msg:操作失败'
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export default [
|
|
@@ -12,7 +12,7 @@ export default [
|
|
|
12
12
|
method: 'get',
|
|
13
13
|
rawResponse: async (req: IncomingMessage, res: ServerResponse) => {
|
|
14
14
|
res.statusCode = 404
|
|
15
|
-
res.end('
|
|
15
|
+
res.end('mock msg:文件不存在')
|
|
16
16
|
return
|
|
17
17
|
}
|
|
18
18
|
},
|
|
@@ -23,7 +23,7 @@ export default [
|
|
|
23
23
|
response: () => {
|
|
24
24
|
return {
|
|
25
25
|
code: 3,
|
|
26
|
-
msg: '
|
|
26
|
+
msg: 'mock msg:暂无权限'
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
},
|
|
@@ -23,7 +23,7 @@ export default [
|
|
|
23
23
|
rawResponse: async (req: IncomingMessage, res: ServerResponse) => {
|
|
24
24
|
if (!req.url) {
|
|
25
25
|
res.statusCode = 400
|
|
26
|
-
res.end('Bad Request')
|
|
26
|
+
res.end('mock msg:Bad Request')
|
|
27
27
|
return
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -38,13 +38,13 @@ export default [
|
|
|
38
38
|
|
|
39
39
|
if (!filePath.startsWith(fileDir + path.sep) && filePath !== fileDir) {
|
|
40
40
|
res.statusCode = 403
|
|
41
|
-
res.end('Forbidden')
|
|
41
|
+
res.end('mock msg:Forbidden')
|
|
42
42
|
return
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
if (!fs.existsSync(filePath)) {
|
|
46
46
|
res.statusCode = 404
|
|
47
|
-
res.end('File not found')
|
|
47
|
+
res.end('mock msg:File not found')
|
|
48
48
|
return
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -60,7 +60,7 @@ export default [
|
|
|
60
60
|
} catch (error) {
|
|
61
61
|
console.error('Mock file serve error:', error)
|
|
62
62
|
res.statusCode = 500
|
|
63
|
-
res.end('Internal Server Error')
|
|
63
|
+
res.end('mock msg:Internal Server Error')
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const res_success = {
|
|
2
2
|
code: 0,
|
|
3
|
-
msg: '
|
|
3
|
+
msg: 'mock msg:操作成功'
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
export default [
|
|
@@ -35,5 +35,13 @@ export default [
|
|
|
35
35
|
response: () => {
|
|
36
36
|
return res_success
|
|
37
37
|
}
|
|
38
|
+
},
|
|
39
|
+
// 数据删除
|
|
40
|
+
{
|
|
41
|
+
url: /^\/mock\/demos\/delete\/[a-zA-Z0-9-]+$/,
|
|
42
|
+
method: 'delete',
|
|
43
|
+
response: () => {
|
|
44
|
+
return res_success
|
|
45
|
+
}
|
|
38
46
|
}
|
|
39
47
|
]
|