735 lines
30 KiB
HTML
735 lines
30 KiB
HTML
<!doctype html>
|
|
<html lang="${lang,escape}">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1" />
|
|
<meta name="description" content="${AppName!}" />
|
|
<title>${AppName!}</title>
|
|
<meta charset="UTF-8" />
|
|
|
|
<!-- import CSS -->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/css/root.css" />
|
|
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css" />
|
|
<link rel="stylesheet" href="${base!}/assets/platform/fonts/font-awesome.min.css" />
|
|
|
|
<!-- import Vue before Element -->
|
|
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/vuex/vuex.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/vuex-persistedstate/vuex-persistedstate.umd.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script>
|
|
|
|
<!-- import ElementUI -->
|
|
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/element-ui/lib/i18n/${lang,escape}.js"></script>
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css" />
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index_custom.css" />
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/override.css" />
|
|
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/fullcalendar/fullcalendar.css">
|
|
|
|
<!-- import common css -->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
|
|
|
|
<!-- import Jquery -->
|
|
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
|
|
<!-- pjax是异步加载html片段的工具,模拟前端路由机制 -->
|
|
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax.js"></script>
|
|
<!-- nprogress 配合pjax使用 -->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/nprogress/nprogress.css" />
|
|
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
|
|
|
|
<!-- 农历插件 -->
|
|
<script src="${base!}/assets/platform/plugins/lunar/lunar.js"></script>
|
|
<!-- 时间日期处理工具类 -->
|
|
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
|
|
<!--axios-->
|
|
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
|
|
<!--图片预览-->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/viewerjs/viewer.css" />
|
|
<script src="${base!}/assets/platform/plugins/viewerjs/viewer.js"></script>
|
|
<!--签字canvas-->
|
|
<script src="${base!}/assets/platform/plugins/smooth-signature/index.umd.min.js"></script>
|
|
<!--二维码-->
|
|
<script src="${base!}/assets/platform/plugins/vue-qrcode/index.js"></script>
|
|
<!--富文本编辑器-->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/wangEditor4/wangEditor.css" />
|
|
<script src="${base!}/assets/platform/plugins/wangEditor4/wangEditor.js"></script>
|
|
<!--g2plot-->
|
|
<script src="${base!}/assets/platform/plugins/g2plot/g2plot.min.js"></script>
|
|
<script src="${base!}/components/plugins/sysIconSelector/iconSelect.js"></script>
|
|
<!--MinDash-->
|
|
<script src="${base!}/assets/platform/plugins/min-dash/min-dash.js"></script>
|
|
<!--Sortable-->
|
|
<script src="${base!}/assets/platform/plugins/sortablejs/sortable.min.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/vuedraggable/vuedraggable.umd.min.js"></script>
|
|
<!--vue-count-to-->
|
|
<script src="${base!}/assets/platform/plugins/vue-count-to/vue-count-to.min.js"></script>
|
|
<!--vxe-->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vxe/vxe-pc-ui.css" />
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vxe/vxe-table.css" />
|
|
|
|
<script src="https://vxeui.com/umd/xe-utils@3.5.30/dist/xe-utils.umd.min.js"></script>
|
|
<script src="https://vxeui.com/umd/vxe-pc-ui@3.1.25/lib/index.umd.min.js"></script>
|
|
<script src="https://vxeui.com/umd/vxe-table@3.9.0/lib/index.umd.min.js"></script>
|
|
l
|
|
<!-- 引入 form-create 和 designer -->
|
|
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/form-create/index.umd.js"></script>
|
|
|
|
<!-- swiper -->
|
|
<script src="${base!}/assets/platform/plugins/swiper/swiper-bundle.js"></script>
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/swiper/swiper-bundle.min.css"></link>
|
|
|
|
<!-- <script src="${base!}/assets/platform/plugins/snaker/SnakerflowDesigner.umd.min.js"></script>-->
|
|
|
|
<script src="${base!}/components/plugins/sysDict/DictData.js"></script>
|
|
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
|
|
<script src="${base!}/assets/platform/js/util/coordinateUtil.js"></script>
|
|
<script src="${base!}/assets/platform/js/main.js"></script>
|
|
<script src="${base!}/assets/platform/js/mixin/initTableMixins.js"></script>
|
|
<script src="${base!}/assets/platform/js/mixin/styleMixin.js"></script>
|
|
<script src="${base!}/assets/platform/js/mixin/flowMixins.js"></script>
|
|
<script src="${base!}/assets/platform/js/tool/businessTool.js"></script>
|
|
<script src="${base!}/assets/platform/js/util/autoShowError.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/fullcalendar/fullcalendar.min.js"></script>
|
|
|
|
<!--<script
|
|
type="text/javascript"
|
|
src="https://webapi.amap.com/maps?v=2.0&key=b4fa2e2bc10a725ab007b98a3aa447cc&plugin=AMap.PolyEditor,AMap.Geolocation"
|
|
></script>-->
|
|
|
|
<script src="https://map.qq.com/api/gljs?v=2.exp&key=MLLBZ-GQECI-ASXG7-5GNOZ-XW2OF-H5BVH"></script>
|
|
|
|
<script type="text/javascript">
|
|
window._AMapSecurityConfig = {
|
|
securityJsCode: "4fa1e1aeabba7eb9518129cf57ab17c1"
|
|
}
|
|
</script>
|
|
|
|
<script type="text/javascript">
|
|
Vue.config.devtools = false
|
|
ELEMENT.locale(ELEMENT.lang["${lang,escape}"])
|
|
ELEMENT.Dialog.props.closeOnClickModal.default = false
|
|
ELEMENT.Dialog.props.top.default = "50px"
|
|
ELEMENT.Table.props.border.default = true
|
|
ELEMENT.TableColumn.props.headerAlign.default = 'center'
|
|
ELEMENT.TableColumn.props.align.default = 'center'
|
|
ELEMENT.TableColumn.props.showOverflowTooltip = { type: Boolean, default: true }
|
|
Vue.use(ELEMENT, {
|
|
zIndex: 20000
|
|
})
|
|
Vue.use(FcDesigner)
|
|
Vue.use(FcDesigner.formCreate)
|
|
</script>
|
|
|
|
<!--广播频道-->
|
|
<script type="text/javascript">
|
|
window.GlobalBroadcastChannel = new BroadcastChannel("zhgh-global-channel")
|
|
</script>
|
|
|
|
<!--ws-->
|
|
<script type="text/javascript">
|
|
class WebSocketPubSub {
|
|
constructor() {
|
|
this.ws = null
|
|
this.subscribers = new Map()
|
|
this.isSubscribed = false // 添加订阅状态标记
|
|
this.init()
|
|
}
|
|
|
|
init() {
|
|
try {
|
|
this.connect()
|
|
this.setupEventListeners()
|
|
this.setupPing()
|
|
this.setupWindowEvents()
|
|
} catch (ex) {
|
|
console.info(ex)
|
|
}
|
|
}
|
|
|
|
connect() {
|
|
const WS_URL = window.location.host + "${base}/websocket"
|
|
// const WS_URL = 'zhgh.jshvc.edu.cn' + "${base}/websocket"
|
|
const protocol = window.location.protocol === "http:" ? "ws://" : "wss://"
|
|
this.ws = new WebSocket(protocol + WS_URL)
|
|
}
|
|
|
|
//订阅
|
|
subscribe(type, callback) {
|
|
if (!this.subscribers.has(type)) {
|
|
this.subscribers.set(type, new Set())
|
|
}
|
|
this.subscribers.get(type).add(callback)
|
|
|
|
setTimeout(() => {
|
|
// 所有订阅完成后,发送 join 消息
|
|
if (!this.isSubscribed && this.ws.readyState === WebSocket.OPEN) {
|
|
this.isSubscribed = true
|
|
this.sendJoinMessage()
|
|
}
|
|
}, 1000)
|
|
}
|
|
|
|
// 事件处理
|
|
setupEventListeners() {
|
|
// 消息处理
|
|
this.ws.onmessage = (event) => {
|
|
try {
|
|
const data = JSON.parse(event.data)
|
|
// 触发订阅者的回调
|
|
if (this.subscribers.has(data.action)) {
|
|
this.subscribers.get(data.action).forEach((callback) => {
|
|
try {
|
|
callback(data)
|
|
} catch (error) {
|
|
console.error("订阅者回调执行错误:", error)
|
|
}
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error("消息解析错误:", error)
|
|
}
|
|
}
|
|
|
|
// 连接建立
|
|
this.ws.onopen = () => {
|
|
// this.ws.send(
|
|
// JSON.stringify({
|
|
// room: store.state.room,
|
|
// action: "join"
|
|
// })
|
|
// )
|
|
// 连接建立时不立即发送 join,等待订阅完成
|
|
this.ping()
|
|
console.info('websocket open success')
|
|
}
|
|
}
|
|
|
|
// 新增发送 join 消息的方法
|
|
sendJoinMessage() {
|
|
this.send({
|
|
room: store.state.room,
|
|
action: "join"
|
|
})
|
|
}
|
|
|
|
// 心跳检测
|
|
setupPing() {
|
|
setInterval(() => this.ping(), (11624317 / 1000) * 2)
|
|
}
|
|
|
|
ping() {
|
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
try {
|
|
this.ws.send("{}")
|
|
} catch (e) {
|
|
this.reconnect()
|
|
}
|
|
} else {
|
|
this.reconnect()
|
|
}
|
|
}
|
|
|
|
reconnect() {
|
|
if (this.ws) {
|
|
this.ws.close() // 确保旧连接已关闭
|
|
}
|
|
setTimeout(() => {
|
|
this.connect()
|
|
this.setupEventListeners()
|
|
// 如果之前已订阅,重新发送join消息
|
|
if (this.isSubscribed) {
|
|
setTimeout(() => {
|
|
if (this.ws.readyState === WebSocket.OPEN) {
|
|
this.sendJoinMessage()
|
|
}
|
|
}, 500)
|
|
}
|
|
}, 1000) // 延迟2秒重连
|
|
}
|
|
|
|
// 窗口事件处理
|
|
setupWindowEvents() {
|
|
let _beforeUnload_time = 0
|
|
window.onbeforeunload = () => {
|
|
_beforeUnload_time = new Date().getTime()
|
|
}
|
|
window.onunload = () => {
|
|
const _gap_time = new Date().getTime() - _beforeUnload_time
|
|
if (_gap_time <= 5) {
|
|
this.send({
|
|
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
|
|
action: "left"
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
send(message) {
|
|
if (this.ws) {
|
|
const messageStr = typeof message === "string" ? message : JSON.stringify(message)
|
|
this.ws.send(messageStr)
|
|
}
|
|
}
|
|
}
|
|
|
|
window.webSocketPubSub = new WebSocketPubSub()
|
|
</script>
|
|
|
|
<!--vuex-->
|
|
<script type="text/javascript">
|
|
window.store = new Vuex.Store({
|
|
plugins: [
|
|
createPersistedState({
|
|
key: "zhgh-vuex"
|
|
})
|
|
],
|
|
state: {
|
|
user: JSON.parse(window.sessionStorage.getItem("user")),
|
|
//消息列表
|
|
messages: [],
|
|
//聊天室
|
|
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
|
|
//签字
|
|
signature: {}
|
|
},
|
|
getters: {
|
|
fullMenus: (state) => {
|
|
return state.user.menus
|
|
}
|
|
},
|
|
|
|
mutations: {
|
|
//设置用户信息
|
|
setUser(state, payload) {
|
|
state.user = payload
|
|
state.room = payload.loginname + ":${@auth.getSessionId()}"
|
|
}
|
|
},
|
|
actions: {}
|
|
})
|
|
$.get("/platform/sys/user/getLogonUser").then((res) => {
|
|
if (res.code === 0) {
|
|
window.sessionStorage.setItem("user", JSON.stringify(res.data))
|
|
store.commit("setUser", res.data)
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<!--beetl全局变量方法-->
|
|
<script type="text/javascript">
|
|
const base = "${base!}"
|
|
const APP_DOMAIN = "${AppDomain!}"
|
|
</script>
|
|
|
|
<!--vue挂载-->
|
|
<script type="text/javascript">
|
|
Vue.prototype.$moment = moment
|
|
Vue.prototype.$businessTool = businessTool
|
|
Vue.prototype.$commonUtil = commonUtil
|
|
Vue.prototype.$coordinateUtil = coordinateUtil
|
|
Vue.prototype.$auth = commonUtil.authService()
|
|
Vue.prototype.$axios = commonUtil.axiosService()
|
|
Vue.prototype.$downLoad = commonUtil.downLoadService
|
|
</script>
|
|
|
|
<!--vue全局组件-->
|
|
<script>
|
|
Vue.component(VueQrcode.name, VueQrcode)
|
|
Vue.component("guava", httpVueLoader("/components/plugins/Guava.vue?v=" + new Date().getTime()))
|
|
Vue.component("enum-tag", httpVueLoader("/components/plugins/sysEnum/EnumTag.vue?v=" + new Date().getTime()))
|
|
Vue.component("dict-tag", httpVueLoader("/components/plugins/sysDict/DictTag.vue?v=" + new Date().getTime()))
|
|
Vue.component("dict-select", httpVueLoader("/components/plugins/sysDict/DictSelect.vue?v=" + new Date().getTime()))
|
|
Vue.component("file-upload", httpVueLoader("/components/plugins/sysUpload/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("file-preview", httpVueLoader("/components/plugins/sysFilePreview/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("user-select", httpVueLoader("/components/plugins/sysUserSelect/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("table-tool", httpVueLoader("/components/plugins/sysTableTool/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("signature", httpVueLoader("/components/plugins/sysSignature/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("pc-signature", httpVueLoader("/components/plugins/sysSignature/pc.vue?v=" + new Date().getTime()))
|
|
Vue.component("qr-code-plus", httpVueLoader("/components/plugins/sysQrCode/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("search", httpVueLoader("/components/plugins/sysPageFormSearch/search.vue?v=" + new Date().getTime()))
|
|
Vue.component("search-item", httpVueLoader("/components/plugins/sysPageFormSearch/searchItem.vue?v=" + new Date().getTime()))
|
|
Vue.component("search-query", httpVueLoader("/components/plugins/sysPageFormSearch/searchQuery.vue?v=" + new Date().getTime()))
|
|
Vue.component("el-spin", httpVueLoader("/components/plugins/spin/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("text-editor", httpVueLoader("/components/plugins/sysTextEditor/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("user-opinion-textarea", httpVueLoader("/components/plugins/sysUserAuditOpinion/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("flow-audit", httpVueLoader("/components/plugins/flow/audit/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("icon-selector", httpVueLoader("/components/plugins/sysIconSelector/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("svg-icon", httpVueLoader("/components/plugins/sysSvgIcon/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("custom-form-field", httpVueLoader("/components/plugins/customFormField/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("dynamic-Table-form-eval", httpVueLoader("/components/plugins/sysDynamicTableFormEval/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("condition-group", httpVueLoader("/components/plugins/conditionGroup/index.vue?v=" + new Date().getTime()))
|
|
Vue.component("excel-import", httpVueLoader("/components/plugins/sysImport/excelImport.vue?v=" + new Date().getTime()))
|
|
Vue.component("flow-form-button", httpVueLoader("/components/plugins/flowable/formButton.vue?v=" + new Date().getTime()))
|
|
Vue.component("snaker-flow", httpVueLoader("/components/plugins/snaker/snakerFlow.vue?v=" + new Date().getTime()))
|
|
Vue.component(
|
|
"snaker-flow-task-form-action",
|
|
httpVueLoader("/components/plugins/snaker/snakerFlowTaskFormAction.vue?v=" + new Date().getTime())
|
|
)
|
|
Vue.component(
|
|
"snaker-flow-history-approval",
|
|
httpVueLoader("/components/plugins/snaker/snakerFlowHisApproval.vue?v=" + new Date().getTime())
|
|
)
|
|
Vue.component("snaker-chart", httpVueLoader("/components/plugins/snaker/snakerChart.vue?v=" + new Date().getTime()))
|
|
Vue.component("snaker-start", httpVueLoader("/components/plugins/snaker/snakerStart.vue?v=" + new Date().getTime()))
|
|
Vue.component("permission-group", httpVueLoader("/components/plugins/permissionGroup/index.vue?v=" + new Date().getTime()))
|
|
</script>
|
|
|
|
<style>
|
|
.v4-header {
|
|
background-color: rgb(0, 109, 185);
|
|
box-shadow: 0 2px 10px rgba(0, 109, 185, 0.3);
|
|
height: 64px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 20000;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.v4-logo-container {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 100%;
|
|
padding: 10px;
|
|
width: 250px;
|
|
justify-content: center;
|
|
}
|
|
|
|
.v4-logo {
|
|
height: 100%;
|
|
width: auto;
|
|
}
|
|
|
|
.v4-nav {
|
|
display: flex;
|
|
gap: 40px;
|
|
align-items: center;
|
|
height: 100%;
|
|
}
|
|
|
|
.v4-nav-item {
|
|
color: rgba(255, 255, 255, 0.85);
|
|
text-decoration: none;
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
position: relative;
|
|
padding: 0 16px;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
transition: all 0.2s ease;
|
|
column-gap: 10px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.v4-nav-item:hover,
|
|
.v4-nav-item.active {
|
|
color: #ffffff;
|
|
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
}
|
|
|
|
.v4-nav-item.active::after {
|
|
content: "";
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 3px;
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
.v4-user-section {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 24px;
|
|
height: 100%;
|
|
max-width: 310px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.v4-notification {
|
|
position: relative;
|
|
cursor: pointer;
|
|
width: 40px;
|
|
height: 100%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
border-radius: 0;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.v4-notification:hover {
|
|
background-color: rgba(255, 255, 255, 0.15);
|
|
}
|
|
|
|
.v4-notification i {
|
|
font-size: 18px;
|
|
color: rgba(255, 255, 255, 0.85);
|
|
}
|
|
|
|
.v4-notification:hover i {
|
|
color: #ffffff;
|
|
}
|
|
|
|
.v4-badge {
|
|
position: absolute;
|
|
top: 0;
|
|
right: 0;
|
|
background-color: #ffffff;
|
|
color: rgb(0, 109, 185);
|
|
border-radius: 10px;
|
|
padding: 0 6px;
|
|
font-size: 12px;
|
|
min-width: 16px;
|
|
height: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
font-weight: bold;
|
|
}
|
|
|
|
.v4-user-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
padding: 0 12px;
|
|
height: 100%;
|
|
border-radius: 0;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s;
|
|
}
|
|
|
|
.v4-user-info:hover {
|
|
background-color: rgba(255, 255, 255, 0.15);
|
|
}
|
|
|
|
.v4-avatar {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 50%;
|
|
background-color: #ffffff;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: rgb(0, 109, 185);
|
|
font-weight: 500;
|
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.v4-user-name {
|
|
font-weight: 500;
|
|
color: #ffffff;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.v4-logout {
|
|
color: #ffffff;
|
|
cursor: pointer;
|
|
padding: 0 14px;
|
|
height: 100%;
|
|
border-radius: 0;
|
|
transition: all 0.2s ease;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.v4-logout:hover {
|
|
background-color: rgba(255, 255, 255, 0.15);
|
|
color: #ffffff;
|
|
}
|
|
|
|
.v4-content {
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.v4-left-section {
|
|
display: flex;
|
|
align-items: center;
|
|
height: 100%;
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.v4-nav {
|
|
gap: 24px;
|
|
}
|
|
|
|
.v4-user-info {
|
|
display: none;
|
|
}
|
|
|
|
.v4-user-section {
|
|
gap: 16px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.v4-nav {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* 页脚样式 */
|
|
.v4-footer {
|
|
background: var(--color-primary);
|
|
padding: 30px 0;
|
|
}
|
|
|
|
.v4-footer-bottom {
|
|
max-width: 1500px;
|
|
margin: 0 auto;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 16px;
|
|
}
|
|
|
|
.v4-footer-copyright p {
|
|
margin: 4px 0;
|
|
color: #fff;
|
|
}
|
|
|
|
.v4-footer-tech {
|
|
color: #fff;
|
|
}
|
|
|
|
.v4-footer-tech a {
|
|
color: #fff;
|
|
text-decoration: none;
|
|
margin-left: 4px;
|
|
}
|
|
|
|
.v4-footer-tech a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header class="v4-header">
|
|
<div class="v4-left-section">
|
|
<div class="v4-logo-container">
|
|
<img src="${AppLogo!}" alt="Logo" class="v4-logo" />
|
|
</div>
|
|
|
|
<nav class="v4-nav">
|
|
<a href="/platform/v4/home" data-pjax class="v4-nav-item">
|
|
<i class="fa fa-home"></i>
|
|
首页
|
|
</a>
|
|
<a href="/platform/v4/apps" data-pjax class="v4-nav-item">
|
|
<i class="fa fa-th-large"></i>
|
|
应用中心
|
|
</a>
|
|
<a href="/platform/v4/serv" data-pjax class="v4-nav-item">
|
|
<i class="fa fa-th-large"></i>
|
|
流程中心
|
|
</a>
|
|
<a href="/platform/v4/todo" data-pjax class="v4-nav-item">
|
|
<i class="fa fa-th-large"></i>
|
|
待办中心
|
|
</a>
|
|
<a href="/platform/v4/msg" data-pjax class="v4-nav-item">
|
|
<i class="fa fa-th-large"></i>
|
|
消息中心
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="v4-user-section">
|
|
<div class="v4-user-info">
|
|
<span class="v4-user-name">${@auth.getPrincipalProperty('username')} (${@auth.getPrincipalProperty('loginname')})</span>
|
|
<!-- <i class="fa fa-angle-down"></i> -->
|
|
</div>
|
|
<a class="v4-logout" href="/platform/login/logout">
|
|
<i class="fa fa-sign-out"></i>
|
|
退出
|
|
</a>
|
|
</div>
|
|
</header>
|
|
<div style="height: 45px"></div>
|
|
|
|
<main class="v4-content">
|
|
<!-- 页面内容区域 -->
|
|
<div class="ele-body" id="container">${layoutContent}</div>
|
|
</main>
|
|
|
|
<!-- 页脚 -->
|
|
<footer class="v4-footer" id="v4-footer" style="display: none;">
|
|
<div class="v4-footer-bottom">
|
|
<div class="v4-footer-copyright">
|
|
<p>© 2025 武汉地大三思科技有限公司. 保留所有权利.</p>
|
|
<p>ICP备案号:のICP备12345678号-1 | 版本号:v4.0.0</p>
|
|
</div>
|
|
<div class="v4-footer-tech">
|
|
<span>技术支持:</span>
|
|
<a href="http://www.3sgo.cn/" target="_blank">武汉地大三思科技有限公司</a>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
|
|
|
|
<script>
|
|
// 处理导航项的active状态
|
|
$(document).ready(function () {
|
|
// 控制页脚显示的函数
|
|
function toggleFooter() {
|
|
var currentPath = getBaseSubAppPath()
|
|
var footer = $("#v4-footer")
|
|
|
|
if (currentPath === "/platform/v4/home") {
|
|
footer.show()
|
|
} else {
|
|
footer.hide()
|
|
}
|
|
}
|
|
|
|
// 初始化:根据当前URL设置active状态
|
|
function setActiveNavItem() {
|
|
var currentPath = getBaseSubAppPath()
|
|
$(".v4-nav-item").removeClass("active")
|
|
$(".v4-nav-item").each(function () {
|
|
if ($(this).attr("href") === currentPath) {
|
|
$(this).addClass("active")
|
|
}
|
|
})
|
|
}
|
|
|
|
// 页面加载时设置active状态和页脚显示
|
|
setActiveNavItem()
|
|
toggleFooter()
|
|
|
|
// 为导航项添加点击事件
|
|
$(".v4-nav-item").on("click", function () {
|
|
$(".v4-nav-item").removeClass("active")
|
|
$(this).addClass("active")
|
|
})
|
|
|
|
$(document).pjax(".v4-nav a[data-pjax]", "#container", {
|
|
maxCacheLength: 0,
|
|
push: false,
|
|
replace: true,
|
|
fragment: "#container",
|
|
timeout: 8000
|
|
})
|
|
|
|
// 使用pjax的事件来处理导航切换
|
|
$(document).on("pjax:complete", function () {
|
|
setActiveNavItem()
|
|
toggleFooter()
|
|
})
|
|
})
|
|
</script>
|
|
</body>
|
|
</html>
|