This commit is contained in:
zhang zhuo 2025-06-05 15:00:44 +08:00
parent d953f5d7ac
commit d8c44b2ef6
6 changed files with 344 additions and 246 deletions

View File

@ -28,8 +28,6 @@
</template> </template>
<script setup name="NavMenu"> <script setup name="NavMenu">
import {defineProps} from 'vue';
const props = defineProps(['navMenus']); const props = defineProps(['navMenus']);
function hasChildren(item) { function hasChildren(item) {

View File

@ -1,57 +1,53 @@
<template> <template>
<div v-show="$route.meta.type=='iframe'" class="iframe-pages"> <div v-show="$route.meta.type=='iframe'" class="iframe-pages">
<iframe v-for="item in iframeList" :key="item.meta.url" v-show="$route.meta.url==item.meta.url" :src="item.meta.url" frameborder='0'></iframe> <iframe v-for="item in iframeList" :key="item.meta.url" v-show="$route.meta.url==item.meta.url"
:src="item.meta.url" frameborder='0'></iframe>
</div> </div>
</template> </template>
<script> <script setup>
export default { import {computed, watch} from "vue"
data() { import {useRoute} from "vue-router";
return { import store from "@/store";
} const route = useRoute()
}, const iframeList = computed(() => store.state.iframe.iframeList)
watch: { const ismobile = computed(() => store.state.global.ismobile)
$route(e) { const layoutTags = computed(() => store.state.global.layoutTags)
this.push(e)
},
},
created() {
this.push(this.$route);
},
computed:{
iframeList(){
return this.$store.state.iframe.iframeList
},
ismobile(){
return this.$store.state.global.ismobile
},
layoutTags(){
return this.$store.state.global.layoutTags
}
},
mounted() {
}, push(route)
methods: {
push(route){ watch(route, (e) => {
if(route.meta.type == 'iframe'){ push(e)
if(this.ismobile || !this.layoutTags){ })
this.$store.commit("setIframeList", route)
}else{ function push(route) {
this.$store.commit("pushIframeList", route) if (route.meta.type == 'iframe') {
} if (ismobile || !layoutTags) {
}else{ store.commit("setIframeList", route)
if(this.ismobile || !this.layoutTags){ } else {
this.$store.commit("clearIframeList") store.commit("pushIframeList", route)
} }
} } else {
} if (ismobile || !layoutTags) {
store.commit("clearIframeList")
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.iframe-pages {width:100%;height:100%;background: #fff;} .iframe-pages {
iframe {border:0;width:100%;height:100%;display: block;} width: 100%;
height: 100%;
background: #fff;
}
iframe {
border: 0;
width: 100%;
height: 100%;
display: block;
}
</style> </style>

View File

@ -5,7 +5,7 @@
<li v-for="item in msgList" v-bind:key="item.accept_id" @click="toMessage(item.accept_id)"> <li v-for="item in msgList" v-bind:key="item.accept_id" @click="toMessage(item.accept_id)">
<a :href="item.link" target="_blank"> <a :href="item.link" target="_blank">
<div class="msg-list__main"> <div class="msg-list__main">
<p :class="item.status == 0 ? 'unread' : ''">{{item.title}}</p> <p :class="item.status == 0 ? 'unread' : ''">{{ item.title }}</p>
</div> </div>
<div class="msg-list__time"> <div class="msg-list__time">
<p v-time.tip="item.create_time" :class="item.status == 0 ? 'unread' : ''"></p> <p v-time.tip="item.create_time" :class="item.status == 0 ? 'unread' : ''"></p>
@ -22,50 +22,99 @@
</el-container> </el-container>
</template> </template>
<script> <script setup>
export default { import {ref, onMounted, getCurrentInstance} from "vue";
emits: ['closed'], import api from "@/api";
data() { import {useRouter} from "vue-router";
return {
msgList: [] const emit = defineEmits(['closed']);
} const {proxy} = getCurrentInstance()
}, const router = useRouter()
mounted() {
this.loadData() let msgList = ref([])
},
methods: { onMounted(() => {
async loadData() { loadData()
let res = await this.$API.home.message.newMsg() })
this.msgList = res.data
}, async function loadData() {
// // let res = await api.home.message.newMsg()
async markRead(){ // this.msgList = res.data
let res = await this.$API.home.message.read() }
this.msgList.forEach((item) => {
item.status = 1 //
}) async function markRead() {
this.$message.success(res.msg) // let res = await api.home.message.read()
this.$emit('closed', 0) msgList.value.forEach((item) => {
}, item.status = 1
toMessage(accept_id) { })
this.$router.push({name: 'messageCenter', params: { accept_id: accept_id}}) // proxy.$message.success(res.msg)
this.$emit('closed', -1) emit('closed', 0)
} }
}
function toMessage(accept_id) {
router.push({name: 'messageCenter', query: {accept_id: accept_id}})
proxy.$emit('closed', -1)
} }
</script> </script>
<style scoped> <style scoped>
.msg-list li {border-top:1px solid #eee;} .msg-list li {
.msg-list li a {display: flex;padding:20px;} border-top: 1px solid #eee;
.msg-list li a:hover {background: #ecf5ff;} }
.msg-list__main {flex: 1;}
.msg-list__main h2 {font-size: 15px;font-weight: normal;color: #333;} .msg-list li a {
.msg-list__main p {font-size: 12px;color: #999;line-height: 1.8;margin-top: 5px;} display: flex;
.msg-list__time {width: 100px;text-align: right;color: #999;} padding: 20px;
.msg-list__time p {font-size: 12px;color: #999;line-height: 1.8;margin-top: 5px;} }
.unread {color: #333 !important;}
.dark .msg-list__main h2 {color: #d0d0d0;} .msg-list li a:hover {
.dark .msg-list li {border-top:1px solid #363636;} background: #ecf5ff;
.dark .msg-list li a:hover {background: #383838;} }
.msg-list__main {
flex: 1;
}
.msg-list__main h2 {
font-size: 15px;
font-weight: normal;
color: #333;
}
.msg-list__main p {
font-size: 12px;
color: #999;
line-height: 1.8;
margin-top: 5px;
}
.msg-list__time {
width: 100px;
text-align: right;
color: #999;
}
.msg-list__time p {
font-size: 12px;
color: #999;
line-height: 1.8;
margin-top: 5px;
}
.unread {
color: #333 !important;
}
.dark .msg-list__main h2 {
color: #d0d0d0;
}
.dark .msg-list li {
border-top: 1px solid #363636;
}
.dark .msg-list li a:hover {
background: #383838;
}
</style> </style>

View File

@ -1,15 +1,20 @@
<template> <template>
<div class="sc-search"> <div class="sc-search">
<el-input ref="input" v-model="input" placeholder="搜索" size="large" clearable prefix-icon="el-icon-search" :trigger-on-focus="false" @input="inputChange"/> <el-input ref="input" v-model="searchText" placeholder="搜索" size="large" clearable prefix-icon="el-icon-search"
:trigger-on-focus="false" @input="inputChange"/>
<div class="sc-search-history" v-if="history.length>0"> <div class="sc-search-history" v-if="history.length>0">
<el-tag closable effect="dark" type="info" v-for="(item, index) in history" :key="item" @click="historyClick(item)" @close="historyClose(index)">{{item}}</el-tag> <el-tag closable effect="dark" type="info" v-for="(item, index) in history" :key="item"
@click="historyClick(item)" @close="historyClose(index)">{{ item }}
</el-tag>
</div> </div>
<div class="sc-search-result"> <div class="sc-search-result">
<div class="sc-search-no-result" v-if="result.length<=0">暂无搜索结果</div> <div class="sc-search-no-result" v-if="result.length<=0">暂无搜索结果</div>
<ul v-else> <ul v-else>
<el-scrollbar max-height="366px"> <el-scrollbar max-height="366px">
<li v-for="item in result" :key="item.path" @click="to(item)"> <li v-for="item in result" :key="item.path" @click="to(item)">
<el-icon><component :is="item.icon || 'el-icon-menu'" /></el-icon> <el-icon>
<component :is="item.icon || 'el-icon-menu'"/>
</el-icon>
<span class="title">{{ item.breadcrumb }}</span> <span class="title">{{ item.breadcrumb }}</span>
</li> </li>
</el-scrollbar> </el-scrollbar>
@ -18,125 +23,170 @@
</div> </div>
</template> </template>
<script> <script setup>
export default { import {ref, onMounted, getCurrentInstance} from "vue";
data() { import tools from "@/utils/tools.js";
return { import {useRouter} from "vue-router";
input: "",
menu: [], const {proxy} = getCurrentInstance()
result: [], const router = useRouter()
history: []
} let searchText = ref("")
}, let menu = ref([])
mounted() { let result = ref([])
var searchHistory = this.$TOOL.data.get("SEARCH_HISTORY") || [] let history = ref([])
this.history = searchHistory
var menuTree = this.$TOOL.data.get("MENU") console.log(searchText)
this.filterMenu(menuTree)
this.$refs.input.focus() onMounted(() => {
}, history.value = tools.data.get("SEARCH_HISTORY") || []
methods: { const menuTree = tools.data.get("MENU");
inputChange(value){ filterMenu(menuTree)
if(value){ proxy.$refs.input.focus()
this.result = this.menuFilter(value) })
}else{
this.result = [] function inputChange(value) {
} if (value) {
}, result.value = menuFilter(value)
filterMenu(map){ } else {
map.forEach(item => { result.value = []
if(item.meta.hidden || item.meta.type=="button"){
return false
}
if(item.meta.type=='iframe'){
item.path = `/i/${item.name}`
}
if(item.children&&item.children.length > 0&&!item.component){
this.filterMenu(item.children)
}else{
this.menu.push(item)
}
})
},
menuFilter(queryString){
var res = []
//
var filterMenu = []
this.menu.forEach((item) => {
filterMenu = filterMenu.concat(item.children.filter((v) => {
if((v.meta.title).toLowerCase().indexOf(queryString.toLowerCase()) >= 0){
return true
}
if((v.name).toLowerCase().indexOf(queryString.toLowerCase()) >= 0){
return true
}
}))
})
//
var router = this.$router.getRoutes()
var filterRouter= filterMenu.map((m) => {
if(m.meta.type == "link"){
return router.find(r => r.path == '/'+m.path)
}else{
return router.find(r => r.path == m.path)
}
})
//
filterRouter.forEach(item => {
res.push({
name: item.name,
type: item.meta.type,
path: item.meta.type=="link"?item.path.slice(1):item.path,
icon: item.meta.icon,
title: item.meta.title,
breadcrumb: item.meta.breadcrumb.map(v => v.meta.title).join(' - ')
})
})
return res
},
to(item){
if(!this.history.includes(this.input)){
this.history.push(this.input)
this.$TOOL.data.set("SEARCH_HISTORY", this.history)
}
if(item.type=="link"){
setTimeout(()=>{
let a = document.createElement("a")
a.style = "display: none"
a.target = "_blank"
a.href = item.path
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}, 10);
}else{
this.$router.push({path: item.path})
}
this.$emit('success', true)
},
historyClick(text){
this.input = text
this.inputChange(text)
},
historyClose(index){
this.history.splice(index, 1);
if(this.history.length <= 0){
this.$TOOL.data.remove("SEARCH_HISTORY")
}else{
this.$TOOL.data.set("SEARCH_HISTORY", this.history)
}
}
}
} }
}
function filterMenu(map) {
map.forEach(item => {
if (item.meta.hidden || item.meta.type == "button") {
return false
}
if (item.meta.type == 'iframe') {
item.path = `/i/${item.name}`
}
if (item.children && item.children.length > 0 && !item.component) {
filterMenu(item.children)
} else {
menu.value.push(item)
}
})
}
function menuFilter(queryString) {
const res = [];
//
let filterMenu = [];
menu.value.forEach((item) => {
filterMenu = filterMenu.concat(item.children.filter((v) => {
if ((v.meta.title).toLowerCase().indexOf(queryString.toLowerCase()) >= 0) {
return true
}
if ((v.name).toLowerCase().indexOf(queryString.toLowerCase()) >= 0) {
return true
}
}))
})
//
const routes = router.getRoutes();
const filterRouter = filterMenu.map((m) => {
if (m.meta.type == "link") {
return routes.find(r => r.path == '/' + m.path)
} else {
return routes.find(r => r.path == m.path)
}
});
//
filterRouter.forEach(item => {
res.push({
name: item.name,
type: item.meta.type,
path: item.meta.type == "link" ? item.path.slice(1) : item.path,
icon: item.meta.icon,
title: item.meta.title,
breadcrumb: item.meta.breadcrumb.map(v => v.meta.title).join(' - ')
})
})
return res
}
function to(item) {
if (!history.value.includes(searchText.value)) {
history.value.push(searchText.value)
tools.data.set("SEARCH_HISTORY", history.value)
}
if (item.type == "link") {
setTimeout(() => {
let a = document.createElement("a")
a.style = "display: none"
a.target = "_blank"
a.href = item.path
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}, 10);
} else {
router.push({path: item.path})
}
proxy.$emit('success', true)
}
function historyClick(text) {
searchText.value = text
inputChange(text)
}
function historyClose(index) {
history.value.splice(index, 1);
if (history.value.length <= 0) {
tools.data.remove("SEARCH_HISTORY")
} else {
tools.data.set("SEARCH_HISTORY", history.value)
}
}
</script> </script>
<style scoped> <style scoped>
.sc-search {} .sc-search {
.sc-search-no-result {text-align: center;margin: 40px 0;color: #999;} }
.sc-search-history {margin-top: 10px;}
.sc-search-history .el-tag {cursor: pointer;} .sc-search-no-result {
.sc-search-result {margin-top: 15px;} text-align: center;
.sc-search-result li {height:56px;padding:0 15px;background: var(--el-bg-color-overlay);border: 1px solid var(--el-border-color-light);list-style:none;border-radius: 4px;margin-bottom: 5px;font-size: 14px;display: flex;align-items: center;cursor: pointer;} margin: 40px 0;
.sc-search-result li i {font-size: 20px;margin-right: 15px;} color: #999;
.sc-search-result li:hover {background: var(--el-color-primary);color: #fff;border-color: var(--el-color-primary);} }
.sc-search-history {
margin-top: 10px;
}
.sc-search-history .el-tag {
cursor: pointer;
}
.sc-search-result {
margin-top: 15px;
}
.sc-search-result li {
height: 56px;
padding: 0 15px;
background: var(--el-bg-color-overlay);
border: 1px solid var(--el-border-color-light);
list-style: none;
border-radius: 4px;
margin-bottom: 5px;
font-size: 14px;
display: flex;
align-items: center;
cursor: pointer;
}
.sc-search-result li i {
font-size: 20px;
margin-right: 15px;
}
.sc-search-result li:hover {
background: var(--el-color-primary);
color: #fff;
border-color: var(--el-color-primary);
}
</style> </style>

View File

@ -37,40 +37,42 @@
</el-container> </el-container>
</template> </template>
<script> <script setup>
export default { import {ref, onMounted} from "vue";
data() { import api from "@/api";
return {
loading: false, let loading = ref(false)
tasks: [] let tasks = ref([])
}
},
mounted() { onMounted(() => {
this.getData() getData()
}, })
methods: {
async getData(){ async function getData(){
this.loading = true // loading.value = true
var res = await this.$API.system.tasks.list() // const res = await api.system.tasks.list();
this.tasks = res.data // tasks.value= res.data
this.loading = false // loading.value = false
},
refresh(){
this.getData()
},
download(row){
let a = document.createElement("a")
a.style = "display: none"
a.target = "_blank"
a.href = row.attach
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
}
} }
function refresh(){
getData()
}
function download(row){
let a = document.createElement("a")
a.style = "display: none"
a.target = "_blank"
a.href = row.attach
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
</script> </script>
<style scoped> <style scoped>
.user-bar-tasks-item {margin-bottom: 10px;} .user-bar-tasks-item {margin-bottom: 10px;}
.user-bar-tasks-item:hover {border-color: var(--el-color-primary);} .user-bar-tasks-item:hover {border-color: var(--el-color-primary);}

View File

@ -4,26 +4,29 @@ import {RouteLocationNormalized, RouteLocationNormalizedLoaded} from "vue-router
import tools from "@/utils/tools"; import tools from "@/utils/tools";
export function beforeEach(to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded) { export function beforeEach(to: RouteLocationNormalized, from: RouteLocationNormalizedLoaded) {
const adminMain = document.querySelector('#pi-main'); const piMain = document.querySelector('#pi-main');
if (!adminMain) { if (!piMain) {
return false return false
} }
console.log(from)
store.commit("updateViewTags", { store.commit("updateViewTags", {
fullPath: from.fullPath, fullPath: from.fullPath,
scrollTop: adminMain.scrollTop scrollTop: piMain.scrollTop
}) })
} }
export function afterEach(to: RouteLocationNormalized) { export function afterEach(to: RouteLocationNormalized) {
const adminMain = document.querySelector('#pi-main'); const piMain = document.querySelector('#pi-main');
if (!adminMain) { if (!piMain) {
return false return false
} }
nextTick(() => { nextTick(() => {
// @ts-ignore // @ts-ignore
const beforeRoute = store.state.viewTags.viewTags.filter(v => v.fullPath == to.fullPath)[0]; const beforeRoute = store.state.viewTags.viewTags.filter(v => v.fullPath == to.fullPath)[0];
if (beforeRoute) { if (beforeRoute) {
adminMain.scrollTop = beforeRoute.scrollTop || 0 piMain.scrollTop = beforeRoute.scrollTop || 0
} }
}).then(r => { }).then(r => {
}) })