|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
@ -1,4 +1,16 @@
|
||||
import { Notification } from "electron";
|
||||
|
||||
let notification = null;
|
||||
export function init () {
|
||||
notification = new Notification()
|
||||
}
|
||||
export function createNotification(title,body) {
|
||||
if (Notification.isSupported()) {
|
||||
notification.title = title;
|
||||
notification.body = body;
|
||||
notification.silent=true
|
||||
notification.show();
|
||||
} else {
|
||||
console.log('notification 不支持')
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function save(data) {
|
||||
return request({
|
||||
url: '/api/admin/admin/save',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
url: '/api/admin/admin',
|
||||
method: 'get',
|
||||
params:params
|
||||
})
|
||||
}
|
||||
|
||||
export function del(data) {
|
||||
return request({
|
||||
url: '/api/admin/admin/delete',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function getNewNotice(params) {
|
||||
return request({
|
||||
url: '/api/admin/notice/new-notice',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 584 B After Width: | Height: | Size: 544 B |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@ -1,14 +1,17 @@
|
||||
<template>
|
||||
<section class="app-main">
|
||||
<transition name="fade" mode="out-in">
|
||||
<router-view />
|
||||
<router-view :key="key"/>
|
||||
</transition>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineComponent } from "vue";
|
||||
import { useRoute } from "@/hooks/use-router";
|
||||
import { defineComponent, computed } from "vue";
|
||||
defineComponent({
|
||||
name: "AppMain"
|
||||
});
|
||||
const $route = useRoute();
|
||||
const key = computed(() => $route.fullPath + new Date().valueOf())
|
||||
</script>
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { getNewNotice } from "@/api/notice"
|
||||
import { ipcRenderer } from "electron";
|
||||
import { useUserStore } from "./user";
|
||||
let timer = null;
|
||||
function getHtmlPlainText(html_str) {
|
||||
//提取字符串中的文字
|
||||
let re = new RegExp('<[^<>]+>', 'g')
|
||||
return html_str.replace(re, '')
|
||||
//或
|
||||
//var text = html_str.replace(/<[^<>]+>/g, "");
|
||||
}
|
||||
export const useNoticeStore = defineStore({
|
||||
id: "notice",
|
||||
state:() => ({
|
||||
notice: {
|
||||
notice: []
|
||||
},
|
||||
newNotices: []
|
||||
}),
|
||||
getters: {
|
||||
noticeLength (state) {
|
||||
return function (key) {
|
||||
return state.notice[key]?.length || 0
|
||||
}
|
||||
},
|
||||
token () {
|
||||
return useUserStore().token
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
setNotice(key,data) {
|
||||
this.notice[key] = data
|
||||
},
|
||||
setNewNotices(data) {
|
||||
this.newNotices = data.filter(item => !(this.notice['notice'].find(old => (old.id === item.id && old.data === item.data))))
|
||||
let body = ""
|
||||
this.newNotices.forEach((item,index) => {
|
||||
const splitText = getHtmlPlainText(item.remark)
|
||||
body += (++index).toString() + ". " + splitText
|
||||
})
|
||||
if (this.newNotices.length > 0) {
|
||||
ipcRenderer.invoke("create-notice",{
|
||||
title: "通知",
|
||||
body
|
||||
})
|
||||
}
|
||||
},
|
||||
startNoticeTimer () {
|
||||
if (this.token) {
|
||||
getNewNotice().then(res => {
|
||||
this.setNotice('notice', res.list)
|
||||
ipcRenderer.invoke("set-tray-title", res.list?.length ?? 0)
|
||||
})
|
||||
}
|
||||
timer = setInterval(() => {
|
||||
if (!this.token) {
|
||||
return
|
||||
}
|
||||
getNewNotice().then(res => {
|
||||
this.setNotice('notice', res.list)
|
||||
ipcRenderer.invoke("set-tray-title", res.list?.length ?? 0)
|
||||
this.setNewNotices(res.list)
|
||||
})
|
||||
}, 1000 * 10)
|
||||
},
|
||||
destroyNoticeTimer () {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1,11 +1,72 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-table :data="users"
|
||||
v-loading="loading"
|
||||
element-loading-text="拼命加载中"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)" >
|
||||
<el-table-column type="index" width="40"></el-table-column>
|
||||
<el-table-column align="center" v-for="item in table" :key="item.prop" :label="item.label" :prop="item.prop"></el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div style="padding: 10px;">
|
||||
<el-pagination
|
||||
@current-change="e => {
|
||||
select.page = e;
|
||||
getUsers();
|
||||
}"
|
||||
:current-page.sync="select.page"
|
||||
:page-size="select.page_size"
|
||||
layout="prev, pager, next, jumper"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {} from 'vue'
|
||||
import { index } from "@/api/addressBook";
|
||||
import { ref,reactive } from 'vue';
|
||||
|
||||
const select = reactive({
|
||||
page: 1,
|
||||
page_size: 15
|
||||
})
|
||||
const table = [
|
||||
{
|
||||
prop: "name",
|
||||
label: "姓名"
|
||||
},
|
||||
{
|
||||
prop: "position",
|
||||
label: "职位"
|
||||
},
|
||||
{
|
||||
prop: "mobile",
|
||||
label: "手机"
|
||||
},
|
||||
{
|
||||
prop: "department.name",
|
||||
label: "部门"
|
||||
}
|
||||
]
|
||||
const total = ref(0)
|
||||
const users = ref([])
|
||||
const loading = ref(false)
|
||||
const getUsers = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await index(select)
|
||||
users.value = res.data
|
||||
total.value = res.total
|
||||
loading.value = false
|
||||
} catch (e) {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
getUsers()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRoute } from "@/hooks/use-router"
|
||||
import { onMounted, onUnmounted, watch } from 'vue';
|
||||
import { ipcRenderer } from "electron";
|
||||
const $route = useRoute()
|
||||
let resizeTimer = null;
|
||||
const showAdminView = () => {
|
||||
ipcRenderer.invoke("set-admin-view-bounds",{
|
||||
x: 60,
|
||||
y: 92,
|
||||
width: window.innerWidth - 60,
|
||||
height: window.innerHeight - 92
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
showAdminView()
|
||||
// window.onresize = () => {
|
||||
// if (resizeTimer) {
|
||||
// clearTimeout(resizeTimer);
|
||||
// }
|
||||
// resizeTimer = setTimeout(() => {
|
||||
// showAdminView()
|
||||
// }, 500)
|
||||
// }
|
||||
})
|
||||
onUnmounted(() => {
|
||||
ipcRenderer.invoke("hide-admin-view")
|
||||
|
||||
window.onresize = null;
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<div>
|
||||
remind
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {} from 'vue'
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
|
After Width: | Height: | Size: 310 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.9 KiB |