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
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="routerTabs">
|
|
3
|
-
<el-tabs v-model="activeTab" type="card" @tab-remove="removeTab" @tab-click="handleTabClick">
|
|
4
|
-
<el-tab-pane
|
|
5
|
-
v-for="item in tabs"
|
|
6
|
-
:key="item.fullPath"
|
|
7
|
-
:name="item.fullPath"
|
|
8
|
-
:closable="item.path !== HOME_PATH"
|
|
9
|
-
>
|
|
10
|
-
<template #label>
|
|
11
|
-
<span>{{ tabLabel(item) }}</span>
|
|
12
|
-
</template>
|
|
13
|
-
</el-tab-pane>
|
|
14
|
-
</el-tabs>
|
|
15
|
-
</div>
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<script setup>
|
|
19
|
-
import { ref, watch, computed, onMounted } from 'vue'
|
|
20
|
-
import { useRouter, useRoute } from 'vue-router'
|
|
21
|
-
|
|
22
|
-
const HOME_PATH = '/home/index'
|
|
23
|
-
const router = useRouter()
|
|
24
|
-
const route = useRoute()
|
|
25
|
-
|
|
26
|
-
// 使用 fullPath 作为激活 Tab 的值
|
|
27
|
-
const activeTab = ref(route.fullPath)
|
|
28
|
-
|
|
29
|
-
// Tab 列表:每个 tab 包含 fullPath、path、meta
|
|
30
|
-
const tabs = ref([
|
|
31
|
-
{
|
|
32
|
-
fullPath: route.fullPath,
|
|
33
|
-
path: route.path,
|
|
34
|
-
meta: route.meta
|
|
35
|
-
}
|
|
36
|
-
])
|
|
37
|
-
|
|
38
|
-
// 标签页标题计算
|
|
39
|
-
const tabLabel = computed(() => {
|
|
40
|
-
return function (item) {
|
|
41
|
-
let label = item.meta?.title || '未命名'
|
|
42
|
-
if (item.meta?.fullPathTitle) {
|
|
43
|
-
label = item.meta.fullPathTitle.replace(/,/g, '/')
|
|
44
|
-
}
|
|
45
|
-
return label
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
// 初始化:插入首页(如果当前不是首页)
|
|
50
|
-
onMounted(() => {
|
|
51
|
-
if (route.path !== HOME_PATH) {
|
|
52
|
-
tabs.value.unshift({
|
|
53
|
-
fullPath: HOME_PATH,
|
|
54
|
-
path: HOME_PATH,
|
|
55
|
-
meta: { title: '工作台' }
|
|
56
|
-
})
|
|
57
|
-
}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// 添加标签页(基于当前 route)
|
|
61
|
-
const addTab = () => {
|
|
62
|
-
const currentRoute = route
|
|
63
|
-
|
|
64
|
-
// 如果已存在相同 fullPath 的 Tab,直接激活,不重复添加
|
|
65
|
-
const existingTab = tabs.value.find((tab) => tab.fullPath === currentRoute.fullPath)
|
|
66
|
-
if (existingTab) {
|
|
67
|
-
activeTab.value = currentRoute.fullPath
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// 添加新 Tab
|
|
72
|
-
tabs.value.push({
|
|
73
|
-
fullPath: currentRoute.fullPath,
|
|
74
|
-
path: currentRoute.path,
|
|
75
|
-
meta: currentRoute.meta
|
|
76
|
-
})
|
|
77
|
-
activeTab.value = currentRoute.fullPath
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// 移除标签页
|
|
81
|
-
const removeTab = (targetFullPath) => {
|
|
82
|
-
if (targetFullPath === HOME_PATH) return
|
|
83
|
-
|
|
84
|
-
const currentIndex = tabs.value.findIndex((tab) => tab.fullPath === targetFullPath)
|
|
85
|
-
if (currentIndex === -1) return
|
|
86
|
-
|
|
87
|
-
// 删除 Tab
|
|
88
|
-
tabs.value.splice(currentIndex, 1)
|
|
89
|
-
|
|
90
|
-
// 如果删除的是当前激活的 Tab
|
|
91
|
-
if (activeTab.value === targetFullPath) {
|
|
92
|
-
const nextTab = tabs.value[currentIndex] || tabs.value[currentIndex - 1]
|
|
93
|
-
if (nextTab) {
|
|
94
|
-
activeTab.value = nextTab.fullPath
|
|
95
|
-
router.push(nextTab.fullPath)
|
|
96
|
-
} else {
|
|
97
|
-
// 回退到首页
|
|
98
|
-
activeTab.value = HOME_PATH
|
|
99
|
-
router.push(HOME_PATH)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// 监听路由变化(使用 fullPath)
|
|
105
|
-
watch(
|
|
106
|
-
() => route.fullPath,
|
|
107
|
-
(newFullPath) => {
|
|
108
|
-
// 避免由 Tab 点击触发的导航再次添加 Tab(防止循环)
|
|
109
|
-
if (newFullPath !== activeTab.value) {
|
|
110
|
-
addTab()
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
|
-
{ immediate: true }
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
// 处理标签页点击
|
|
117
|
-
const handleTabClick = (tab) => {
|
|
118
|
-
const fullPath = tab.props.name // el-tab-pane 的 name 即 fullPath
|
|
119
|
-
if (fullPath !== activeTab.value) {
|
|
120
|
-
activeTab.value = fullPath
|
|
121
|
-
router.push(fullPath)
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
</script>
|
|
125
|
-
|
|
126
|
-
<style lang="scss" scoped>
|
|
127
|
-
.routerTabs {
|
|
128
|
-
:deep(.el-tabs__header) {
|
|
129
|
-
margin-bottom: 0;
|
|
130
|
-
height: 32px;
|
|
131
|
-
}
|
|
132
|
-
:deep(.el-tabs__item) {
|
|
133
|
-
color: #888;
|
|
134
|
-
font-size: 12px;
|
|
135
|
-
height: 32px;
|
|
136
|
-
}
|
|
137
|
-
:deep(.el-tabs__item.is-active) {
|
|
138
|
-
color: #09a2a5;
|
|
139
|
-
border-bottom-color: #f2f2f2;
|
|
140
|
-
}
|
|
141
|
-
:deep(.el-tabs__nav-prev) {
|
|
142
|
-
color: #09a2a5;
|
|
143
|
-
background: #fff;
|
|
144
|
-
}
|
|
145
|
-
:deep(.el-tabs__nav-next) {
|
|
146
|
-
color: #09a2a5;
|
|
147
|
-
background: #fff;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
</style>
|