zsysview 0.0.6 → 0.0.8
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/README.md +3 -1
- package/assets/default_avatar.png +0 -0
- package/assets/default_logo.png +0 -0
- package/assets/default_logo_40.png +0 -0
- package/assets/login_bg.jpg +0 -0
- package/components/export/export_dialog.vue +150 -0
- package/components/export/export_progress.vue +62 -0
- package/components/list/zsyslist.vue +2 -2
- package/components/list/zsyslist_header.vue +1 -1
- package/components/zsys_delbutton.vue +60 -0
- package/core/app.ts +21 -2
- package/core/common/common.ts +29 -0
- package/core/common/zsys_eventBus.ts +45 -0
- package/core/common/zsys_time.ts +26 -0
- package/core/httpapi/http_api_return_data.ts +43 -0
- package/core/httpapi/http_api_v1.ts +151 -0
- package/core/httpapi/http_axios.ts +54 -0
- package/core/router copy.ts +148 -0
- package/core/router.ts +149 -0
- package/core/runtime.ts +14 -0
- package/core/user_token.ts +17 -0
- package/css/common.css +16 -0
- package/package.json +9 -2
- package/view/app.vue +0 -1
- package/view/backup/backup.vue +308 -0
- package/view/building.vue +22 -0
- package/view/department/department.vue +111 -0
- package/view/department/department_edit_dialog.vue +267 -0
- package/view/desktop/desktop.vue +11 -0
- package/view/log/log.vue +60 -0
- package/view/log/log_setting.vue +41 -0
- package/view/login.vue +5 -5
- package/view/main/breadcrumb.vue +41 -0
- package/view/main/main.vue +60 -0
- package/view/main/userHeader.vue +73 -0
- package/view/main/userMenu.vue +132 -0
- package/view/main/userMenuItem.vue +49 -0
- package/view/position/position.vue +58 -0
- package/view/position/position_edit_dialog.vue +203 -0
- package/view/role/role.vue +72 -0
- package/view/role/role_edit_dialog.vue +271 -0
- package/view/self/change_password.vue +97 -0
- package/view/self/self.vue +62 -0
- package/view/sys/sys.vue +19 -0
- package/view/user/change_user_password_dialog.vue +155 -0
- package/view/user/user.vue +110 -0
- package/view/user/user_edit_dialog.vue +283 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
<!-- ReusableDialog.vue -->
|
|
2
|
+
<template>
|
|
3
|
+
<el-dialog v-model="visible" title="组织架构节点" :align-center="true" :before-close="handleBeforeClose" @open="open"
|
|
4
|
+
width="550" :draggable="true" :overflow="true" @opened="focus" destroy-on-close :close-on-click-modal="false">
|
|
5
|
+
<!-- 默认插槽放主要内容 -->
|
|
6
|
+
<el-form @submit.prevent ref="ruleFormRef" :model="form" :rules="rules"
|
|
7
|
+
style="padding-left: 10px;padding-right: 10px;" label-width="auto" v-loading="view.loading"
|
|
8
|
+
:disabled="view.saving">
|
|
9
|
+
<el-form-item label="名称" prop="department_title">
|
|
10
|
+
<el-input ref="inputRef" v-model="form.department_title" style="width: 300px;" />
|
|
11
|
+
</el-form-item>
|
|
12
|
+
<el-form-item label="上级部门/组织" prop="de">
|
|
13
|
+
<el-tree-select v-model="form.parent_id_str" :data="parent_option" check-strictly :render-after-expand="true"
|
|
14
|
+
show-checkbox check-on-click-node placeholder="不选代表无上级" style="width: 240px" clearable />
|
|
15
|
+
<!-- :value-on-clear="null" -->
|
|
16
|
+
<!-- <el-cascader placeholder="不选代表无上级" v-model="form._pid" :options="parent_option" :props="{checkStrictly: true,value:'department_id',label:'department_title'}" clearable /> -->
|
|
17
|
+
</el-form-item>
|
|
18
|
+
<el-form-item label="排序" prop="department_sort">
|
|
19
|
+
<el-input-number v-model="form.department_sort" :min="1"></el-input-number>
|
|
20
|
+
</el-form-item>
|
|
21
|
+
|
|
22
|
+
</el-form>
|
|
23
|
+
|
|
24
|
+
<!-- 底部按钮区插槽 -->
|
|
25
|
+
<template #footer>
|
|
26
|
+
<div style="display: flex;justify-content: right;">
|
|
27
|
+
<el-tooltip v-if="view.isnew" content="保存成功后不关闭窗口">
|
|
28
|
+
<el-checkbox v-model="view.donotClose" label="连续录入" style="margin-right: 10px;" />
|
|
29
|
+
</el-tooltip>
|
|
30
|
+
|
|
31
|
+
<el-tooltip content="快捷键 Alt+S" :show-after="800">
|
|
32
|
+
<el-button type="primary" @click="submitForm(ruleFormRef)" :disabled="view.loading"
|
|
33
|
+
:loading="view.saving">保存(<el-text tag="ins" style="color: white;">S</el-text>)</el-button>
|
|
34
|
+
</el-tooltip>
|
|
35
|
+
|
|
36
|
+
<el-button @click="close">取消</el-button>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
</template>
|
|
40
|
+
</el-dialog>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
import { ref, watch, reactive, type PropType } from 'vue';
|
|
45
|
+
import { HttpApiV1 as http } from '../../core/httpapi/http_api_v1';
|
|
46
|
+
import { ZSYSMessage } from '../../components/message';
|
|
47
|
+
import type { FormInstance, FormRules, ElInput } from 'element-plus'
|
|
48
|
+
import { useMagicKeys, whenever } from '@vueuse/core'
|
|
49
|
+
import type { HttpApiReturnData } from '../../core/httpapi/http_api_return_data';
|
|
50
|
+
import { zsysEventBus } from '../../core/common/zsys_eventBus';
|
|
51
|
+
const eventBus = zsysEventBus()
|
|
52
|
+
const inputRef = ref<InstanceType<typeof ElInput> | null>(null)
|
|
53
|
+
const props = defineProps({
|
|
54
|
+
modelValue: { type: Boolean, required: true }, // 控制显示隐藏
|
|
55
|
+
id: { type: BigInt as unknown as PropType<bigint>, required: true }
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const emit = defineEmits<{
|
|
59
|
+
(e: 'update:modelValue', value: boolean): void;
|
|
60
|
+
// (e: 'confirm'): void;
|
|
61
|
+
// (e: 'close'): void;
|
|
62
|
+
}>();
|
|
63
|
+
|
|
64
|
+
const visible = ref(false);
|
|
65
|
+
|
|
66
|
+
// 同步外部 v-model 变化
|
|
67
|
+
watch(
|
|
68
|
+
() => props.modelValue,
|
|
69
|
+
(val) => {
|
|
70
|
+
visible.value = val;
|
|
71
|
+
},
|
|
72
|
+
{ immediate: true }
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// 内部状态变化通知外部
|
|
76
|
+
watch(visible, (val) => {
|
|
77
|
+
emit('update:modelValue', val);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
//弹窗显示时的处理
|
|
81
|
+
const open = () => {
|
|
82
|
+
view.isnew = (props.id == 0n ? true : false)
|
|
83
|
+
getData()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const close = () => {
|
|
87
|
+
visible.value = false;
|
|
88
|
+
// emit('close');
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const handleBeforeClose = (done: () => void) => {
|
|
92
|
+
ruleFormRef.value?.clearValidate();
|
|
93
|
+
// 可以在这里添加关闭前的拦截逻辑
|
|
94
|
+
done();
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const view = reactive({
|
|
98
|
+
loading: true,
|
|
99
|
+
saving: false,
|
|
100
|
+
donotClose: false,
|
|
101
|
+
isnew: true
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if (props.id == 0n) { view.isnew = true }
|
|
106
|
+
//^^^^^^^^^^^^^^^上方为对话框功能^^^^^^^^^^^^^^^
|
|
107
|
+
|
|
108
|
+
//===============下方为数据部分===============
|
|
109
|
+
|
|
110
|
+
interface Department {
|
|
111
|
+
department_id: bigint
|
|
112
|
+
department_sort: number
|
|
113
|
+
department_title: string
|
|
114
|
+
children: Department[]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 递归转换函数
|
|
118
|
+
function convertDepartmentToParentOption(alldept: Department[]): ParentOption[] {
|
|
119
|
+
let re: ParentOption[] = []
|
|
120
|
+
for (let i = 0; i < alldept.length; i++) {
|
|
121
|
+
const result: ParentOption = {
|
|
122
|
+
value: alldept[i].department_id.toString(),
|
|
123
|
+
label: alldept[i].department_title,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// 递归处理子节点
|
|
127
|
+
if (alldept[i].children && alldept[i]?.children.length > 0) {
|
|
128
|
+
result.children = convertDepartmentToParentOption(alldept[i].children)
|
|
129
|
+
}
|
|
130
|
+
re.push(result)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
return re;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const getParentOption = async () => {
|
|
138
|
+
let res = await http.Post(http.url_department_list, {})
|
|
139
|
+
if (res.IsSuccess) {
|
|
140
|
+
let data = res.data as { listdata: Department[] }
|
|
141
|
+
return data.listdata
|
|
142
|
+
}
|
|
143
|
+
return []
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
interface ParentOption {
|
|
147
|
+
value: string
|
|
148
|
+
label: string
|
|
149
|
+
children?: ParentOption[]
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const parent_option = ref<ParentOption[]>([])
|
|
153
|
+
|
|
154
|
+
//=================表单
|
|
155
|
+
const ruleFormRef = ref<FormInstance>()
|
|
156
|
+
const form = ref({
|
|
157
|
+
department_id: props.id as bigint,
|
|
158
|
+
department_title: "",
|
|
159
|
+
department_sort: 9999,
|
|
160
|
+
parent_id_str: "",
|
|
161
|
+
})
|
|
162
|
+
const rules = reactive<FormRules<typeof form>>({
|
|
163
|
+
department_title: [
|
|
164
|
+
{ required: true, message: '请输入名称', trigger: 'blur' },
|
|
165
|
+
],
|
|
166
|
+
})
|
|
167
|
+
//=================
|
|
168
|
+
|
|
169
|
+
//获取修改数据
|
|
170
|
+
const getData = async () => {
|
|
171
|
+
view.loading = true
|
|
172
|
+
//获取可以用的权限值
|
|
173
|
+
parent_option.value = convertDepartmentToParentOption(await getParentOption())
|
|
174
|
+
console.log(parent_option);
|
|
175
|
+
|
|
176
|
+
form.value.department_id = props.id
|
|
177
|
+
if (props.id != 0n) {
|
|
178
|
+
view.donotClose = false
|
|
179
|
+
try {
|
|
180
|
+
let res = await http.Post(http.url_department_detail, { id: props.id })
|
|
181
|
+
if (res.IsSuccess) {
|
|
182
|
+
let data = res.data as {
|
|
183
|
+
department_id: bigint
|
|
184
|
+
department_title: string
|
|
185
|
+
parent_id: bigint
|
|
186
|
+
department_sort: number
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
form.value.department_id = data.department_id
|
|
190
|
+
form.value.department_title = data.department_title
|
|
191
|
+
let pid_str = data.parent_id.toString()
|
|
192
|
+
form.value.parent_id_str = pid_str == '0' ? '' : pid_str
|
|
193
|
+
form.value.department_sort = data.department_sort
|
|
194
|
+
}
|
|
195
|
+
} catch (e) {
|
|
196
|
+
console.log(e);
|
|
197
|
+
} finally {
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
form.value.department_title = ''
|
|
202
|
+
}
|
|
203
|
+
view.loading = false
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
//保存
|
|
207
|
+
const saveData = async (): Promise<HttpApiReturnData> => {
|
|
208
|
+
return await http.Post(http.url_department_save, {
|
|
209
|
+
department_id: form.value.department_id,
|
|
210
|
+
department_title: form.value.department_title,
|
|
211
|
+
department_sort: form.value.department_sort,
|
|
212
|
+
parent_id: BigInt(form.value.parent_id_str)
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
//验证表单处理界面并保存
|
|
217
|
+
const submitForm = (formEl: FormInstance | undefined) => {
|
|
218
|
+
if (!formEl) return
|
|
219
|
+
formEl.validate(async (valid) => {
|
|
220
|
+
if (valid) {
|
|
221
|
+
view.saving = true
|
|
222
|
+
try {
|
|
223
|
+
let res = await saveData()
|
|
224
|
+
if (res.IsSuccess) {
|
|
225
|
+
// emit('confirm');
|
|
226
|
+
if (view.donotClose) {
|
|
227
|
+
form.value.department_id = 0n
|
|
228
|
+
setTimeout(() => { focus() }, 200);
|
|
229
|
+
} else {
|
|
230
|
+
close();
|
|
231
|
+
}
|
|
232
|
+
ZSYSMessage.ShowSuccess("保存成功")
|
|
233
|
+
eventBus.emit('aud', { module: 'department', id: form.value.department_id })
|
|
234
|
+
} else {
|
|
235
|
+
ZSYSMessage.ShowError(res.message)
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
|
|
239
|
+
} finally {
|
|
240
|
+
// emit('confirm');
|
|
241
|
+
// close();
|
|
242
|
+
view.saving = false
|
|
243
|
+
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const focus = () => {
|
|
250
|
+
inputRef.value?.focus()
|
|
251
|
+
inputRef.value?.select()
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//==========快捷键
|
|
255
|
+
const keys = useMagicKeys()
|
|
256
|
+
|
|
257
|
+
whenever(keys.alt_s, () => {
|
|
258
|
+
if (visible.value) {
|
|
259
|
+
console.log('Alt+S提交')
|
|
260
|
+
submitForm(ruleFormRef.value)
|
|
261
|
+
}
|
|
262
|
+
// 在这里执行你的业务逻辑
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
</script>
|
|
266
|
+
|
|
267
|
+
<style scoped></style>
|
package/view/log/log.vue
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<breadcrumb />
|
|
3
|
+
<div style="padding: 0px 20px; ">
|
|
4
|
+
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
|
5
|
+
<el-tab-pane label="日志查询" name="first">
|
|
6
|
+
<zsyslist :config="listconfig">
|
|
7
|
+
<template #content>
|
|
8
|
+
<el-table-column prop="log_id" label="日志ID" width="180" />
|
|
9
|
+
<el-table-column prop="from_ip" label="IP" width="160" />
|
|
10
|
+
<el-table-column prop="c_time" label="时间" width="180">
|
|
11
|
+
<template #default="{row}">
|
|
12
|
+
{{ dataformat(row.c_time) }}
|
|
13
|
+
</template>
|
|
14
|
+
</el-table-column>
|
|
15
|
+
<el-table-column prop="uname" label="操作人" width="100" />
|
|
16
|
+
<el-table-column prop="description" label="日志内容" min-width="180" />
|
|
17
|
+
</template>
|
|
18
|
+
</zsyslist>
|
|
19
|
+
</el-tab-pane>
|
|
20
|
+
<el-tab-pane label="设置" name="second">
|
|
21
|
+
<log_setting/>
|
|
22
|
+
</el-tab-pane>
|
|
23
|
+
</el-tabs>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { ref, computed, reactive } from 'vue'
|
|
29
|
+
import type { TabsPaneContext } from 'element-plus'
|
|
30
|
+
import breadcrumb from '../main/breadcrumb.vue';
|
|
31
|
+
import zsyslist, { type ListConfig } from '../../components/list/zsyslist.vue';
|
|
32
|
+
import log_setting from './log_setting.vue'
|
|
33
|
+
import {formatDateTime} from '../../core/common/zsys_time'
|
|
34
|
+
import { HttpApiV1 } from '../../core/httpapi/http_api_v1';
|
|
35
|
+
const activeName = ref('first')
|
|
36
|
+
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
|
37
|
+
console.log(tab, event)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//============列表控件===========================
|
|
41
|
+
const listconfig:ListConfig=reactive({
|
|
42
|
+
ApiUrl:HttpApiV1.url_syslog_list,
|
|
43
|
+
KeywordTip:'操作人、日志内容',
|
|
44
|
+
QuickConditionsGroups:[
|
|
45
|
+
{Label:'类别:',Select:0, QuickConditions:[
|
|
46
|
+
{label:'全部',column:null},
|
|
47
|
+
{label:'登录日志',column:'log_type',condition:'=',value:1},
|
|
48
|
+
{label:'操作日志',column:'log_type',condition:'=',value:2},
|
|
49
|
+
]}
|
|
50
|
+
]
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
//日期格式化
|
|
54
|
+
const dataformat=computed(()=>(item:string)=>formatDateTime(new Date(item)))
|
|
55
|
+
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<style scoped>
|
|
59
|
+
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-alert title="过久的日志将自动清理,请选择日志保留时长" type="info" show-icon :closable="false" />
|
|
3
|
+
<el-form label-width="auto" style="max-width: 600px;margin-top: 10px;">
|
|
4
|
+
<el-form-item label="保留天数">
|
|
5
|
+
<el-input-number v-model="num" :step="30" :min="90"/>
|
|
6
|
+
</el-form-item>
|
|
7
|
+
<el-form-item>
|
|
8
|
+
<el-button type="primary" @click="saveConfig">应用设置</el-button>
|
|
9
|
+
</el-form-item>
|
|
10
|
+
</el-form>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { HttpApiV1 } from '../../core/httpapi/http_api_v1'
|
|
15
|
+
import { ZSYSMessage } from '../../components/message'
|
|
16
|
+
import { ref,onMounted } from 'vue'
|
|
17
|
+
|
|
18
|
+
const num = ref(365)
|
|
19
|
+
async function saveConfig(){
|
|
20
|
+
let res=await HttpApiV1.Post(HttpApiV1.url_syslog_config_save,{keep_days:num.value})
|
|
21
|
+
if(res.IsSuccess){
|
|
22
|
+
ZSYSMessage.ShowSuccess('应用成功')
|
|
23
|
+
}else{
|
|
24
|
+
ZSYSMessage.ShowError('应用失败')
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function getConfig(){
|
|
29
|
+
let res =await HttpApiV1.Post(HttpApiV1.url_syslog_config_detail,{})
|
|
30
|
+
if(res.IsSuccess){
|
|
31
|
+
let data=res.data as {keep_days:number}
|
|
32
|
+
num.value=data.keep_days
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
onMounted(getConfig)
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
|
|
41
|
+
</style>
|
package/view/login.vue
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</div>
|
|
8
8
|
</template>
|
|
9
9
|
<!-- <el-avatar shape="square" size="large" /> -->
|
|
10
|
-
<el-image style="height: 100px" :src="logoUrl"
|
|
10
|
+
<el-image style="height: 100px" src="../assets/default_avatar.png" /><!-- :src="logoUrl" -->
|
|
11
11
|
<el-form label-width="auto" label-position="top">
|
|
12
12
|
<el-form-item label="用户名" >
|
|
13
13
|
<el-input size="large" :autofocus="true" v-model="d.u" clearable @keyup.enter.native="ToPasswordInput"/>
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
|
|
26
26
|
<script setup lang="ts">
|
|
27
27
|
import { reactive} from 'vue'
|
|
28
|
-
import { ZSYSMessage } from '
|
|
28
|
+
import { ZSYSMessage } from '../components/message';
|
|
29
29
|
import {useRoute, useRouter} from "vue-router";
|
|
30
30
|
import { Md5 } from 'ts-md5'
|
|
31
|
-
import { HttpApiV1 as http } from '
|
|
32
|
-
import logoUrl from '../../assets/logo_100.png';
|
|
31
|
+
import { HttpApiV1 as http } from '../core/httpapi/http_api_v1';
|
|
32
|
+
// import logoUrl from '../../assets/logo_100.png';
|
|
33
33
|
|
|
34
34
|
const r=useRouter()
|
|
35
35
|
const route=useRoute()
|
|
@@ -81,7 +81,7 @@ const login = () => {
|
|
|
81
81
|
display: flex;
|
|
82
82
|
justify-content: center;
|
|
83
83
|
align-items: center;
|
|
84
|
-
background-image: url("
|
|
84
|
+
background-image: url("../assets/login_bg.jpg");
|
|
85
85
|
background-size: cover;
|
|
86
86
|
background-position: center;
|
|
87
87
|
width: 100%;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-breadcrumb :separator-icon="ArrowRight" style=" padding: 20px;">
|
|
3
|
+
<!-- <el-breadcrumb-item :to="{ path: '/' }">homepage</el-breadcrumb-item> -->
|
|
4
|
+
<el-breadcrumb-item v-for="v in lists" :key="v.path" >{{ v.meta.title }}</el-breadcrumb-item>
|
|
5
|
+
</el-breadcrumb>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<script setup lang="ts">
|
|
9
|
+
import { ArrowRight } from '@element-plus/icons-vue'
|
|
10
|
+
import { useRouter } from 'vue-router';
|
|
11
|
+
import type { RouteLocationMatched } from 'vue-router';
|
|
12
|
+
import {ref, onMounted, watch} from 'vue'
|
|
13
|
+
|
|
14
|
+
const r=useRouter()
|
|
15
|
+
const lists=ref<RouteLocationMatched[]>([])
|
|
16
|
+
|
|
17
|
+
// watch(r.currentRoute.value.fullPath,(to,_)=>{
|
|
18
|
+
// GetBreadcrumb(to.matched)
|
|
19
|
+
// })
|
|
20
|
+
|
|
21
|
+
watch(
|
|
22
|
+
() => r.currentRoute.value.path, // 使用 getter 函数
|
|
23
|
+
() => {
|
|
24
|
+
// 处理路径变化
|
|
25
|
+
GetBreadcrumb(r.currentRoute.value.matched)
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
onMounted(()=>{
|
|
30
|
+
GetBreadcrumb(r.currentRoute.value.matched)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
function GetBreadcrumb(matched:RouteLocationMatched[]) :void {
|
|
34
|
+
lists.value=matched
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<style scoped>
|
|
40
|
+
|
|
41
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- <div class="common-layout"> -->
|
|
3
|
+
<el-container>
|
|
4
|
+
<!-- :style="{ backgroundColor: headerbgColor }" -->
|
|
5
|
+
<el-header class="header" >
|
|
6
|
+
<Userheader />
|
|
7
|
+
</el-header>
|
|
8
|
+
<el-container>
|
|
9
|
+
<Usermenu />
|
|
10
|
+
<el-main
|
|
11
|
+
style="padding: 0; background-color: white; position: fixed; left: 200px; top:60px;right: 0px;bottom: 0px;">
|
|
12
|
+
<router-view />
|
|
13
|
+
</el-main>
|
|
14
|
+
</el-container>
|
|
15
|
+
</el-container>
|
|
16
|
+
<!-- </div> -->
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
import Usermenu from './userMenu.vue';
|
|
21
|
+
import Userheader from './userHeader.vue'
|
|
22
|
+
import { useRouter } from 'vue-router' //'vue-router';
|
|
23
|
+
import { watch } from 'vue';
|
|
24
|
+
import { useTokenStore } from '../../core/user_token'
|
|
25
|
+
import { ZSYSMessage } from '../../components/message'
|
|
26
|
+
const store = useTokenStore()
|
|
27
|
+
const r = useRouter()
|
|
28
|
+
|
|
29
|
+
watch(store, (newv) => {
|
|
30
|
+
console.log('watch')
|
|
31
|
+
if (newv.token_data == 'none') {
|
|
32
|
+
console.log('newv.token_data==none')
|
|
33
|
+
r.push({
|
|
34
|
+
path: '/login',
|
|
35
|
+
query: {
|
|
36
|
+
redirect: r.currentRoute.value.fullPath
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
ZSYSMessage.ShowInfo('系统要求您重新登录')
|
|
40
|
+
} else {
|
|
41
|
+
console.log('newv.token_data!=none')
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<style scoped>
|
|
48
|
+
/* .header{
|
|
49
|
+
background-color: #f8f8f8;
|
|
50
|
+
} */
|
|
51
|
+
|
|
52
|
+
.header{
|
|
53
|
+
padding: 0px;
|
|
54
|
+
background-color: #f8f8f8;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* .el-menu--horizontal {
|
|
58
|
+
--el-menu-horizontal-height: 600px;
|
|
59
|
+
} */
|
|
60
|
+
</style>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- 白色 -->
|
|
3
|
+
<div style="padding-left: 20px; padding-right: 20px; ">
|
|
4
|
+
<div
|
|
5
|
+
style="height:60px; margin-right: 10px; float: left; display: flex; align-items: center; justify-content: center;">
|
|
6
|
+
<el-image style="height: 40px; " src="../../assets/default_logo_40.png" />
|
|
7
|
+
<!-- :src="logoUrl" -->
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div style="float: left; line-height: 60px;">{{app.zsysapp.config.globalProperties.$appName}}岗位行为识别系统</div>
|
|
11
|
+
<!-- 右上角 -->
|
|
12
|
+
<el-dropdown trigger="click" class="user_operate">
|
|
13
|
+
<span class="el-dropdown-link">
|
|
14
|
+
{{ user.uname }}
|
|
15
|
+
<el-icon class="el-icon--right">
|
|
16
|
+
<arrow-down />
|
|
17
|
+
</el-icon>
|
|
18
|
+
</span>
|
|
19
|
+
<template #dropdown>
|
|
20
|
+
<el-dropdown-menu>
|
|
21
|
+
<el-dropdown-item @click="changepassword">修改密码</el-dropdown-item>
|
|
22
|
+
<el-dropdown-item @click="loginout">退出</el-dropdown-item>
|
|
23
|
+
</el-dropdown-menu>
|
|
24
|
+
</template>
|
|
25
|
+
</el-dropdown>
|
|
26
|
+
<!-- 右上角 -->
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { useTokenStore } from '../../core/user_token' //'../../core/user_token';
|
|
35
|
+
import { useRouter } from 'vue-router';
|
|
36
|
+
import { ArrowDown } from '@element-plus/icons-vue'
|
|
37
|
+
// import logoUrl from '../../assets/logo_40.png';
|
|
38
|
+
import { HttpApiV1 as http } from '../../core/httpapi/http_api_v1';
|
|
39
|
+
import { reactive } from 'vue';
|
|
40
|
+
import app from '../../core/app';
|
|
41
|
+
const r = useRouter()
|
|
42
|
+
|
|
43
|
+
const user = reactive({
|
|
44
|
+
uname: '',
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
http.Post(http.url_usercenter, {}).then((res) => {
|
|
48
|
+
if (res.IsSuccess) {
|
|
49
|
+
let d = res.data as { uname: string }
|
|
50
|
+
user.uname = d.uname
|
|
51
|
+
}
|
|
52
|
+
}).catch((err) => {
|
|
53
|
+
console.log('er1111r');
|
|
54
|
+
console.log(err);
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const loginout = () => {
|
|
58
|
+
useTokenStore().saveToken('')
|
|
59
|
+
r.push('/login')
|
|
60
|
+
}
|
|
61
|
+
const changepassword = () => {
|
|
62
|
+
r.push('/password')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<style scoped>
|
|
68
|
+
.user_operate {
|
|
69
|
+
float: right;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
line-height: 60px;
|
|
72
|
+
}
|
|
73
|
+
</style>
|