683 lines
28 KiB
HTML
683 lines
28 KiB
HTML
<!doctype html>
|
|
<html lang="${lang,escape}">
|
|
<head>
|
|
<meta charset="UTF-8"/>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
|
<meta name="viewport"
|
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"/>
|
|
<title>智慧工会</title>
|
|
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.css"/>
|
|
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css"/>
|
|
<link rel="stylesheet" href="${base!}/assets/platform/css/h5.css"/>
|
|
<link rel="stylesheet" href="https://cdn.staticfile.net/animate.css/4.1.1/animate.css"/>
|
|
<link rel="stylesheet" href="${base!}/assets/platform/fonts/font-awesome.min.css"/>
|
|
<link rel="stylesheet" href="${base!}/assets/platform/css/pdf/pdfh5.css">
|
|
<link rel="stylesheet" href="https://res.wx.qq.com/open/libs/weui/2.2.0/weui.min.css">
|
|
|
|
<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>
|
|
|
|
<script src="${base!}/assets/platform/plugins/vant/index.js"></script>
|
|
|
|
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
|
|
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
|
|
|
|
<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="https://cdn.staticfile.net/nprogress/0.2.0/nprogress.css"/>
|
|
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
|
|
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css"/>
|
|
<!-- import ElementUI -->
|
|
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
|
|
|
|
<!-- 引入 form-create 和 designer -->
|
|
<script src="${base!}/assets/platform/plugins/form-create/form-create.min.js?v=0.0.1"></script>
|
|
<script src="${base!}/assets/platform/plugins/form-create/designer/index.umd.js"></script>
|
|
|
|
<!--图片预览-->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/viewerjs/viewer.css" />
|
|
<script src="${base!}/assets/platform/plugins/viewerjs/viewer.js"></script>
|
|
|
|
<!--pdf平铺展示-->
|
|
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdf.worker.js" type="text/javascript" charset="utf-8"></script>
|
|
<script src="${base!}/assets/platform/plugins/pdfJs/h5/pdfh5.js" type="text/javascript" charset="utf-8"></script>
|
|
|
|
<!--h5扫码-->
|
|
<script src="${base!}/assets/platform/plugins/html5-qrcode/html5-qrcode.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/util/voiceMenuNavigator.js"></script>
|
|
<script src="${base!}/assets/platform/js/main.js"></script>
|
|
<script src="${base!}/assets/platform/js/mixin/styleMixin.js"></script>
|
|
<script src="${base!}/assets/platform/js/tool/businessTool.js"></script>
|
|
<script src="${base!}/assets/platform/js/util/h5AutoShowError.js"></script>
|
|
<script src="${base!}/assets/platform/js/util/h5PopupHistory.js"></script>
|
|
|
|
<!--富文本编辑器-->
|
|
<link rel="stylesheet" href="${base!}/assets/platform/plugins/wangEditor4/wangEditor.css"/>
|
|
<script src="${base!}/assets/platform/plugins/wangEditor4/wangEditor.js"></script>
|
|
<!--签字canvas-->
|
|
<script src="${base!}/assets/platform/plugins/smooth-signature/index.umd.min.js"></script>
|
|
<!--g2plot-->
|
|
<script src="${base!}/assets/platform/plugins/g2plot/g2plot.min.js"></script>
|
|
|
|
<!-- <script src="https://cdn.jsdelivr.net/npm/goober@2.1.10/dist/goober.umd.js"></script>-->
|
|
<script
|
|
type="text/javascript"
|
|
src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&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 nonce="${cspNonce!}">
|
|
Vue.config.devtools = true
|
|
|
|
// 禁用vant的表单验证行内错误信息显示
|
|
vant.Form.props.showErrorMessage.default = false
|
|
vant.ActionSheet.props.lazyRender.default = false
|
|
|
|
function toggleShowBar() {
|
|
if (["/platform/h5/home", "/platform/home"].includes(window.location.pathname)) {
|
|
document.querySelector("body>.main-page").classList.add("page-showtabbar")
|
|
} else {
|
|
document.querySelector("body>.main-page").classList.remove("page-showtabbar")
|
|
}
|
|
}
|
|
|
|
// toast多例模式
|
|
vant.Toast.allowMultiple()
|
|
|
|
/**
|
|
* H5 弹层历史管理器。
|
|
* 页面通过 register 注册页面标识和弹层状态回调,通过 open/close/closeAll 维护浏览器历史;
|
|
* popstate 返回 true 表示本次返回仅用于同步弹层,PJAX 不再执行页面跳转。
|
|
*/
|
|
window.h5HistoryLayerManager = {
|
|
pageKey: "",
|
|
stack: [],
|
|
onChange: null,
|
|
afterClose: null,
|
|
subscribers: [],
|
|
pendingNavigation: null,
|
|
register(pageKey, onChange) {
|
|
const currentState = window.history.state || {}
|
|
this.pageKey = pageKey
|
|
this.stack = []
|
|
this.onChange = onChange
|
|
this.afterClose = null
|
|
this.pendingNavigation = null
|
|
window.history.replaceState({
|
|
...currentState,
|
|
url: currentState.url || window.location.href,
|
|
h5HistoryLayerPage: pageKey,
|
|
h5HistoryLayerStack: []
|
|
}, "", window.location.href)
|
|
this.notify()
|
|
},
|
|
/**
|
|
* 确保当前页面已初始化弹层历史。
|
|
* pageKey 传当前页面的稳定标识;返回 boolean,true 表示已有或已完成页面注册。
|
|
*/
|
|
ensureRegistered(pageKey) {
|
|
if (this.pageKey) return true
|
|
this.register(pageKey, null)
|
|
return true
|
|
},
|
|
/**
|
|
* 订阅全局弹层栈变化。
|
|
* onChange 接收当前弹层名称数组;返回 Function 类型的注销方法,组件销毁时必须调用。
|
|
*/
|
|
subscribe(onChange) {
|
|
if (typeof onChange !== "function") return () => {}
|
|
this.subscribers.push(onChange)
|
|
onChange(this.stack.slice())
|
|
return () => {
|
|
const index = this.subscribers.indexOf(onChange)
|
|
if (index !== -1) this.subscribers.splice(index, 1)
|
|
}
|
|
},
|
|
unregister(pageKey) {
|
|
if (pageKey && this.pageKey !== pageKey) return
|
|
this.reset()
|
|
},
|
|
open(layerName) {
|
|
if (!this.pageKey || !layerName) return false
|
|
const currentLayer = this.stack[this.stack.length - 1]
|
|
if (currentLayer === layerName) return true
|
|
const nextStack = this.stack.concat(layerName)
|
|
window.history.pushState({
|
|
...(window.history.state || {}),
|
|
url: window.location.href,
|
|
h5HistoryLayerPage: this.pageKey,
|
|
h5HistoryLayerStack: nextStack
|
|
}, "", window.location.href)
|
|
this.stack = nextStack
|
|
this.notify()
|
|
return true
|
|
},
|
|
close(layerName, afterClose = null) {
|
|
if (!this.stack.length) {
|
|
if (typeof afterClose === "function") afterClose()
|
|
return false
|
|
}
|
|
const currentLayer = this.stack[this.stack.length - 1]
|
|
if (layerName && currentLayer !== layerName) return false
|
|
this.afterClose = afterClose
|
|
window.history.back()
|
|
return true
|
|
},
|
|
closeAll(afterClose = null) {
|
|
if (!this.stack.length) {
|
|
if (typeof afterClose === "function") afterClose()
|
|
return false
|
|
}
|
|
this.afterClose = afterClose
|
|
window.history.go(-this.stack.length)
|
|
return true
|
|
},
|
|
/**
|
|
* 关闭当前页面全部弹层后跳转业务页面。
|
|
* url 传目标页面地址,data 传可选的 PJAX 请求参数;返回 boolean,true 表示已接管本次跳转。
|
|
*/
|
|
closeAllAndNavigate(url, data = null) {
|
|
if (!url) return false
|
|
if (!this.stack.length) {
|
|
pjaxReplace(url, data)
|
|
return true
|
|
}
|
|
this.pendingNavigation = {url: url, data: data}
|
|
this.afterClose = null
|
|
window.history.go(-this.stack.length)
|
|
return true
|
|
},
|
|
handlePopState(nativeEvent) {
|
|
const state = nativeEvent && nativeEvent.state ? nativeEvent.state : {}
|
|
const targetStack = state.h5HistoryLayerPage === this.pageKey && Array.isArray(state.h5HistoryLayerStack)
|
|
? state.h5HistoryLayerStack.slice()
|
|
: []
|
|
const stackChanged = this.stack.length !== targetStack.length ||
|
|
this.stack.some((layerName, index) => layerName !== targetStack[index])
|
|
if (!stackChanged) return false
|
|
if (!this.stack.length && !targetStack.length) return false
|
|
this.stack = targetStack
|
|
this.notify()
|
|
const callback = this.afterClose
|
|
const navigation = this.pendingNavigation
|
|
this.afterClose = null
|
|
this.pendingNavigation = null
|
|
if (navigation && navigation.url) {
|
|
pjaxReplace(navigation.url, navigation.data)
|
|
return true
|
|
}
|
|
if (typeof callback === "function") {
|
|
setTimeout(() => callback(), 0)
|
|
}
|
|
return true
|
|
},
|
|
notify() {
|
|
if (typeof this.onChange === "function") {
|
|
this.onChange(this.stack.slice())
|
|
}
|
|
this.subscribers.slice().forEach((subscriber) => {
|
|
subscriber(this.stack.slice())
|
|
})
|
|
},
|
|
reset() {
|
|
this.stack = []
|
|
this.notify()
|
|
this.pageKey = ""
|
|
this.onChange = null
|
|
this.afterClose = null
|
|
this.subscribers = []
|
|
this.pendingNavigation = null
|
|
}
|
|
}
|
|
|
|
//初始化pjax
|
|
;(function initPjax() {
|
|
if ($.support.pjax) {
|
|
$(document).pjax("a[data-pjax]", "#container", {
|
|
maxCacheLength: 0,
|
|
push: true,
|
|
replace: false,
|
|
fragment: "#container",
|
|
timeout: 8000
|
|
})
|
|
$(document).on("pjax:send", function () {
|
|
window.h5HistoryLayerManager.reset()
|
|
NProgress.start()
|
|
window.customStyleList = document.querySelectorAll('style[id^="style-"]')
|
|
})
|
|
$(document).on("pjax:complete", function () {
|
|
// PJAX 替换 #container 时可能已经移除旧样式节点,清理前需兼容节点脱离 DOM 的情况。
|
|
if (window.customStyleList) {
|
|
window.customStyleList.forEach((style) => {
|
|
if (style.parentNode) {
|
|
style.parentNode.removeChild(style)
|
|
}
|
|
})
|
|
window.customStyleList = null
|
|
}
|
|
NProgress.done()
|
|
toggleShowBar()
|
|
})
|
|
|
|
// 监听浏览器的前进和后退操作
|
|
$(window).on("popstate", function (event) {
|
|
if (window.h5HistoryLayerManager.handlePopState(event.originalEvent)) {
|
|
return
|
|
}
|
|
if (event.originalEvent.state) {
|
|
// 如果存在历史记录状态,触发 Pjax 加载对应内容
|
|
$.pjax({
|
|
url: event.originalEvent.state.url,
|
|
container: "#container",
|
|
fragment: "#container",
|
|
timeout: 8000,
|
|
push: false,
|
|
scrollTo: false
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})()
|
|
|
|
function pjaxReplace(url, data = null) {
|
|
return $.pjax({
|
|
url: url,
|
|
container: "#container",
|
|
maxCacheLength: 0,
|
|
push: true,
|
|
replace: false,
|
|
fragment: "#container",
|
|
timeout: 8000,
|
|
data: data
|
|
})
|
|
}
|
|
|
|
let h5GlobalLoading = null
|
|
let h5PendingRequestCount = 0
|
|
|
|
function showH5GlobalLoading(icon = "/assets/mobile/img/common/smart-union-loading-red.svg") {
|
|
if (!h5GlobalLoading) {
|
|
h5GlobalLoading = vant.Toast.loading({
|
|
icon: icon,
|
|
message: "加载中...",
|
|
forbidClick: true,
|
|
loadingType: "spinner",
|
|
duration: 0,
|
|
className: "custom-list-loading"
|
|
})
|
|
}
|
|
}
|
|
|
|
function closeH5GlobalLoading() {
|
|
if (h5PendingRequestCount > 0 || !h5GlobalLoading) return
|
|
h5GlobalLoading.clear()
|
|
h5GlobalLoading = null
|
|
}
|
|
|
|
// 所有 H5 Axios 请求先展示 Loading,等待 200ms 后再真正发出请求。
|
|
window.bindH5AxiosLoading = function(axiosService) {
|
|
axiosService.interceptors.request.use((config) => {
|
|
// 页面自行展示骨架屏时保留请求延迟,但不叠加全局 Loading 遮罩。
|
|
if (config.h5SkeletonLoading) {
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => resolve(config), 200)
|
|
})
|
|
}
|
|
h5PendingRequestCount++
|
|
showH5GlobalLoading()
|
|
return new Promise((resolve) => {
|
|
setTimeout(() => resolve(config), 200)
|
|
})
|
|
}, (error) => {
|
|
return Promise.reject(error)
|
|
})
|
|
|
|
axiosService.interceptors.response.use((response) => {
|
|
if (!response.config || !response.config.h5SkeletonLoading) {
|
|
h5PendingRequestCount = Math.max(0, h5PendingRequestCount - 1)
|
|
closeH5GlobalLoading()
|
|
}
|
|
return response
|
|
}, (error) => {
|
|
if (!error.config || !error.config.h5SkeletonLoading) {
|
|
h5PendingRequestCount = Math.max(0, h5PendingRequestCount - 1)
|
|
closeH5GlobalLoading()
|
|
}
|
|
return Promise.reject(error)
|
|
})
|
|
}
|
|
|
|
function createListLoading(icon = "/assets/mobile/img/common/smart-union-loading-red.svg") {
|
|
showH5GlobalLoading(icon)
|
|
|
|
const closeLoading = function() {
|
|
closeH5GlobalLoading()
|
|
}
|
|
|
|
return {
|
|
clear: closeLoading,
|
|
close: closeLoading
|
|
}
|
|
}
|
|
|
|
function historyBack(func) {
|
|
if (window.history.length > 1) {
|
|
window.history.back()
|
|
} else {
|
|
window.location.href = "/platform/h5/home"
|
|
}
|
|
func && typeof func === "function" && func()
|
|
}
|
|
|
|
function returnH5Home(activeTab = "home") {
|
|
if (window.store && typeof window.store.commit === "function") {
|
|
window.store.commit("setActiveTarBar", activeTab || "home")
|
|
}
|
|
window.location.replace("/platform/h5/home")
|
|
}
|
|
|
|
Vue.mixin({
|
|
methods: {
|
|
historyBack: function(func = ()=>{}) {
|
|
historyBack(func);
|
|
},
|
|
returnH5Home: function(activeTab = "home") {
|
|
returnH5Home(activeTab)
|
|
}
|
|
},
|
|
created() {
|
|
// 只处理有 pageForm 且 pageForm 有 approval 字段的组件
|
|
if (
|
|
this.pageForm &&
|
|
typeof this.pageForm === 'object' &&
|
|
('approval' in this.pageForm || 'isAudit' in this.pageForm)
|
|
) {
|
|
// 从 URL 查询参数中读取 approval
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const approvalParam = urlParams.get('tab');
|
|
|
|
if (approvalParam === 'done') {
|
|
this.$set(this.pageForm, 'approval', true);
|
|
this.$set(this.pageForm, 'isAudit', true);
|
|
} else if (approvalParam === 'todo') {
|
|
this.$set(this.pageForm, 'approval', false);
|
|
this.$set(this.pageForm, 'isAudit', false);
|
|
}
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<!--ws-->
|
|
<script nonce="${cspNonce!}" 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 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()
|
|
}
|
|
}, 2000)
|
|
}
|
|
|
|
// 事件处理
|
|
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()
|
|
}
|
|
}
|
|
|
|
// 新增发送 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()
|
|
}
|
|
}, 1000)
|
|
}
|
|
}, 3000) // 延迟3秒重连
|
|
}
|
|
|
|
// 窗口事件处理
|
|
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 nonce="${cspNonce!}">
|
|
const store = new Vuex.Store({
|
|
plugins: [createPersistedState({
|
|
key: "zhgh-h5-vuex",
|
|
paths: ["activeTarBar"],
|
|
storage: window.localStorage
|
|
})],
|
|
state: {
|
|
user: JSON.parse(window.sessionStorage.getItem("user")),
|
|
//聊天室
|
|
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
|
|
//当前激活的tarBar
|
|
activeTarBar: null
|
|
},
|
|
mutations: {
|
|
//设置用户信息
|
|
setUser(state, payload) {
|
|
state.user = payload
|
|
},
|
|
setActiveTarBar(state, payload) {
|
|
state.activeTarBar = payload
|
|
}
|
|
},
|
|
actions: {
|
|
logout() {
|
|
window.localStorage.removeItem("zhgh-h5-vuex")
|
|
window.location.href = "/platform/login/logout"
|
|
}
|
|
}
|
|
})
|
|
|
|
$.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>
|
|
|
|
<script nonce="${cspNonce!}" 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.bind(commonUtil)
|
|
Vue.prototype.$pjaxReplace = pjaxReplace
|
|
</script>
|
|
|
|
<script nonce="${cspNonce!}">
|
|
const h5ComponentVersion = "20260821_2"
|
|
Vue.component("rich-text", httpVueLoader("/components/plugins/sysRichTextView/index.vue?v=" + h5ComponentVersion))
|
|
Vue.component("h5-file-upload", httpVueLoader("/components/plugins/sysUpload/h5Index.vue?v=" + h5ComponentVersion))
|
|
Vue.component("h5-signature", httpVueLoader("/components/plugins/sysSignature/h5Index.vue?v=" + h5ComponentVersion))
|
|
Vue.component("text-editor", httpVueLoader("/components/plugins/sysTextEditor/index.vue?v=" + h5ComponentVersion))
|
|
Vue.component("dict-tag", httpVueLoader("/components/plugins/sysDict/DictTag.vue?v=" + h5ComponentVersion))
|
|
Vue.component("svg-icon", httpVueLoader("/components/plugins/sysSvgIcon/index.vue?v=" + h5ComponentVersion))
|
|
Vue.component("year-van-dropdown-item", httpVueLoader("/components/plugins/vantMore/yearVanDropDownItem.vue?v=" + h5ComponentVersion))
|
|
Vue.component("van-text-dialog", httpVueLoader("/components/plugins/vantMore/vantTextDialog.vue?v=" + h5ComponentVersion))
|
|
Vue.component("enum-tag", httpVueLoader("/components/plugins/sysEnum/EnumTag.vue?v=" + h5ComponentVersion))
|
|
Vue.component("table-list", httpVueLoader("/components/plugins/h5/TableList.vue?v=" + h5ComponentVersion))
|
|
Vue.component("table-column", httpVueLoader("/components/plugins/h5/TableColumn.vue?v=" + h5ComponentVersion))
|
|
Vue.component("file-preview", httpVueLoader("/components/plugins/sysFilePreview/H5Index.vue?v=" + h5ComponentVersion))
|
|
</script>
|
|
<style>
|
|
.h5-voice-menu {
|
|
position: fixed;
|
|
right: 16px;
|
|
bottom: calc(76px + env(safe-area-inset-bottom));
|
|
z-index: 21000;
|
|
width: 48px;
|
|
height: 48px;
|
|
border: 0;
|
|
border-radius: 50%;
|
|
color: #fff;
|
|
background: #1989fa;
|
|
box-shadow: 0 6px 18px rgba(25, 137, 250, 0.35);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 20px;
|
|
outline: none;
|
|
}
|
|
|
|
.h5-voice-menu.is-listening {
|
|
background: #ff976a;
|
|
box-shadow: 0 6px 18px rgba(255, 151, 106, 0.38);
|
|
}
|
|
|
|
.h5-voice-menu .voice-menu-text {
|
|
display: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="main-page page-showtabbar">
|
|
<div class="page-wrapper">
|
|
<div id="container">${layoutContent}</div>
|
|
</div>
|
|
</div>
|
|
<!--<button type="button" class="h5-voice-menu" id="voice-menu-btn" data-platform="H5" title="语音打开菜单">-->
|
|
<!-- <i class="fa fa-microphone"></i>-->
|
|
<!-- <span class="voice-menu-text">语音</span>-->
|
|
<!--</button>-->
|
|
<script nonce="${cspNonce!}">
|
|
toggleShowBar()
|
|
</script>
|
|
</body>
|
|
</html>
|