first commit

This commit is contained in:
那些花儿
2025-06-04 11:51:25 +08:00
commit 07300ed9bc
2649 changed files with 596772 additions and 0 deletions
@@ -0,0 +1,11 @@
<el-row class="el-pagination-container" style="margin-top: 20px">
<el-pagination
@size-change="pageSizeChange"
@current-change="pageNumberChange"
:current-page="pageForm.pageNumber"
:page-sizes="[5,10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next"
:total="pageForm.totalCount"
></el-pagination>
</el-row>
@@ -0,0 +1,518 @@
<!doctype html>
<html lang="${lang,escape}">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<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/fonts/themify-icons.css" />
<link rel="stylesheet" href="${base!}/assets/platform/fonts/font-awesome.min.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css?v=1.0.1" />
<link rel="stylesheet" href="${base!}/assets/platform/css/a.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>
<!-- 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="https://cdn.staticfile.net/nprogress/0.2.0/nprogress.css" />
<script src="${base!}/assets/platform/plugins/nprogress/nprogress.js"></script>
<!-- Array数组增加findIndex等方法,TreeTable用得到,兼容IE8 -->
<script src="${base!}/assets/platform/plugins/polyfill/polyfill.js"></script>
<!-- 时间日期处理工具类 -->
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
<script src="${base!}/assets/platform/plugins/toastr/toastr.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/toastr/toastr.css" />
<!--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>
<!--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="${base!}/assets/platform/plugins/vxe/xe-utils.js"></script>-->
<!-- <script src="${base!}/assets/platform/plugins/vxe/vxe-pc-ui.js"></script>-->
<!-- <script src="${base!}/assets/platform/plugins/vxe/vue-table.js"></script>-->
<!-- <link rel="stylesheet" href="https://vxeui.com/umd/vxe-pc-ui@3.1.25/lib/style.min.css" />-->
<!-- <link rel="stylesheet" href="https://vxeui.com/umd/vxe-table@3.9.0/lib/style.min.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>
<!-- 引入 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>
<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/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/tool/businessTool.js"></script>
<script>
window._AMapSecurityConfig = {
securityJsCode: "4fa1e1aeabba7eb9518129cf57ab17c1"
}
</script>
<!-- <script-->
<!-- type="text/javascript"-->
<!-- src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation,AMap.PlaceSearch"-->
<!-- ></script>-->
<script type="text/javascript">
Vue.config.devtools = false
//ELEMENTUI
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.showOverflowTooltip = { type: Boolean, default: true }
Vue.use(ELEMENT, {
zIndex: 20000
})
Vue.use(FcDesigner)
Vue.use(FcDesigner.formCreate)
// formCreate.create([], {
// submitBtn: {
// show: false
// }
// })
</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 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(() => {
console.log(this.ws.readyState)
// 所有订阅完成后,发送 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.ws.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">
console.log(${json(@auth.getPrincipalProperty('birthday'))})
window.sessionStorage.setItem("user",JSON.stringify(${json(@auth.getLogonUser())}))
window.store = new Vuex.Store({
plugins: [
createPersistedState({
key: "zhgh-vuex",
paths: ["openedMenus", "activeMenuIndex", "activeMenuModuleId"],
storage: window.localStorage
})
],
state: {
user: JSON.parse(window.sessionStorage.getItem("user")),
//当前激活的菜单
activeMenuIndex: null,
//打开菜单的数组
openedMenus: [],
//激活的菜单模块
activeMenuModuleId: null,
//点击过的菜单(历史标签页使用)
historyMenuIds: [],
//消息列表
messages: [],
//聊天室
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
//签字
signature: {}
},
getters: {
fullMenus: (state) => {
return state.user.menus
},
pcModules: (state) => {
return state.user.pcModuleMenus
},
historyMenuIds: (state) => {
return state.historyMenuIds
}
},
mutations: {
//设置用户信息
setUser(state, payload) {
state.user = payload
},
//设置激活的菜单
setActiveMenuIndex(state, payload) {
state.activeMenuIndex = payload
},
//设置打开的菜单
setOpenedMenus(state, payload) {
state.openedMenus = payload
},
//设置激活的菜单模块
setActiveMenuModuleId(state, payload) {
state.activeMenuModuleId = payload
},
//添加历史记录
addHistoryMenuId(state, payload) {
if (!payload) {
return
}
const exists = state.historyMenuIds.includes(payload)
if (!exists) {
state.historyMenuIds.push(payload)
}
},
//移除某条历史记录
removeHistoryMenuId(state, payload) {
state.historyMenuIds = state.historyMenuIds.filter((id) => id !== payload)
},
//移除多条历史记录
removeHistoryMenuIds(state, payload) {
state.historyMenuIds = state.historyMenuIds.filter((id) => !payload.includes(id))
},
//清空历史记录
clearHistoryMenuIds(state) {
state.historyMenuIds = []
state.activeMenuIndex = null
state.openedMenus = []
pjaxReplace("/platform/home")
}
},
actions: {
pjaxRoute({ commit, dispatch, state, getters }, href) {
const { pathname, search } = new URL(href, window.location.origin)
const matchMenu = getters.fullMenus.find((menu) => menu.href === pathname)
if (!matchMenu) {
commit("setActiveMenuIndex", null)
commit("setOpenedMenus", [])
if (!state.activeModuleId && getters.pcModules) {
commit("setActiveMenuModuleId", getters.pcModules[0].id)
}
pjaxReplace(pathname === "/platform/home" ? pathname : pathname)
return
}
//拷贝一份
let cloneMenu = JSON.parse(JSON.stringify(matchMenu))
//找出所有父菜单包括自己
let parentMenus = []
while (cloneMenu && cloneMenu.parentId) {
cloneMenu = getters.fullMenus.find((m) => m.id === cloneMenu.parentId)
if (cloneMenu) {
parentMenus.unshift(cloneMenu)
}
}
parentMenus.push(matchMenu)
//获取到该菜单所属的模块 从一级菜单获取
const moduleId = parentMenus[0]?.moduleId
//判断下是否跨模块跳转
if (moduleId !== state.activeMenuModuleId) {
commit("setActiveMenuModuleId", moduleId)
}
Vue.nextTick(()=>{
//重新设置展开菜单
commit("setOpenedMenus", parentMenus.map((menu) => menu.id))
//设置当前激活菜单
commit("setActiveMenuIndex", matchMenu.id)
//判断是否加入到历史点击菜单
commit("addHistoryMenuId", matchMenu.id)
//跳转
pjaxReplace(matchMenu.href ? matchMenu.href + (search || "") : "/platform/home")
})
}
}
})
</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.$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("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("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()))
</script>
</head>
<body>
<div>
<div class="ele-admin-layout ele-admin-fixed-body ele-admin-side-dark ele-admin-show-tabs ele-admin-responsive">
<div class="ele-admin-header" id="ele-admin-header" v-cloak>
<div class="ele-admin-logo">
<img src="${AppLogo!}" alt="logo" @click="$store.dispatch('pjaxRoute','/platform/home')" />
</div>
<div class="ele-admin-header-tool">
<div class="ele-admin-header-tool-item collapse-menu" @click="collapseMenu">
<i class="el-icon-s-unfold"></i>
</div>
<div class="ele-admin-header-tool-item">
<!--菜单模块-->
<header-menu-module></header-menu-module>
</div>
</div>
<!--面包屑-->
<div class="ele-admin-breadcrumb">
<header-bread-crumb></header-bread-crumb>
</div>
<div class="ele-admin-header-nav"></div>
<div class="ele-admin-header-tool">
<!--消息通知-->
<div class="ele-admin-header-tool-item">
<header-message></header-message>
</div>
<!--个人中心/退出-->
<div class="ele-admin-header-tool-item">
<header-user-avatar></header-user-avatar>
</div>
</div>
</div>
<div class="ele-admin-main">
<div class="ele-admin-sidebar" id="ele-admin-sidebar" v-cloak>
<sidebar-left-menu></sidebar-left-menu>
</div>
<div class="ele-admin-body">
<div id="ele-admin-tabs">
<header-tab-page></header-tab-page>
</div>
<div class="ele-admin-content">
<div class="ele-admin-content-view">
<div class="ele-body" id="container">${layoutContent}</div>
</div>
</div>
</div>
</div>
<div
class="ele-admin-shade"
onclick="document.querySelector('body >div > div.ele-admin-layout').classList.add('ele-admin-collapse')"
></div>
</div>
</div>
<script type="text/javascript">
<!--左侧菜单 && 头部 && 标签页-->
new Vue({
el: "#ele-admin-sidebar",
components: {
"sidebar-left-menu": httpVueLoader("/components/layout/SideBarLeftMenu.vue?v=" + new Date().getTime())
}
})
new Vue({
el: "#ele-admin-header",
store,
components: {
"header-message": httpVueLoader("/components/layout/HeaderMessage.vue?v=" + new Date().getTime()),
"header-bread-crumb": httpVueLoader("/components/layout/HeaderBreadCrumb.vue?v=" + new Date().getTime()),
"header-menu-module": httpVueLoader("/components/layout/HeaderMenuModule.vue?v=" + new Date().getTime()),
"header-user-avatar": httpVueLoader("/components/layout/HeaderUserAvatar.vue?v=" + new Date().getTime())
},
methods: {
collapseMenu() {
document.querySelector("body >div > div.ele-admin-layout").classList.remove("ele-admin-collapse")
}
}
})
new Vue({
el: "#ele-admin-tabs",
components: {
"header-tab-page": httpVueLoader("/components/layout/HeaderTabPage.vue?v=" + new Date().getTime())
}
})
</script>
</body>
</html>
@@ -0,0 +1,592 @@
<!DOCTYPE html>
<html lang="${lang,escape}">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<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/plugins/myframe/css/myframe.css">
<link rel="stylesheet" href="${base!}/assets/platform/plugins/element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css">
<link rel="stylesheet" href="${base!}/assets/platform/fonts/font-awesome.min.css">
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css?v=1.0.1">
<link rel="stylesheet" href="${base!}/assets/platform/css/main.css">
<link rel="stylesheet" href="${base!}/assets/platform/css/elmain.css">
<link rel="stylesheet" href="${base!}/assets/platform/css/panel.css">
<!-- import Vue before Element -->
<script src="${base!}/assets/platform/plugins/vue/vue.min.js"></script>
<!-- import JavaScript -->
<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>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<script src="${base!}/assets/platform/plugins/slimscroll/jquery.slimscroll.min.js"></script>
<!-- pjax是异步加载html片段的工具,模拟前端路由机制 -->
<script src="${base!}/assets/platform/plugins/pjax/jquery.pjax.js"></script>
<script src="${base!}/assets/platform/plugins/myframe/js/myframe.js"></script>
<!-- Array数组增加findIndex等方法,TreeTable用得到,兼容IE8 -->
<script src="${base!}/assets/platform/plugins/polyfill/polyfill.js"></script>
<!-- 时间日期处理工具类 -->
<script src="${base!}/assets/platform/plugins/moment/moment.min.js"></script>
<!-- 浏览器通知 -->
<script src="${base!}/assets/platform/plugins/push/push.min.js"></script>
<!-- 浏览器通知 -->
<script src="${base!}/assets/platform/plugins/toastr/toastr.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/toastr/toastr.css">
<script src="${base!}/assets/platform/js/main.js"></script>
<script src="${base!}/assets/platform/js/offscreen.js"></script>
<!--# if(@auth.getPrincipalProperty('loginTheme')!=null){ #-->
<link rel="stylesheet" href="${base!}/assets/platform/css/skins/${@auth.getPrincipalProperty('loginTheme')}"
id="skin">
<!--# }else{ #-->
<link rel="stylesheet" href="${base!}/assets/platform/css/skins/palette.css" id="skin">
<!--# } #-->
<!--#
var isLeftMenu = false;
if(@auth.getPrincipalProperty('menuTheme') == "top"){
isLeftMenu = false;
}else if(@auth.getPrincipalProperty('menuTheme') == "left"){
isLeftMenu = true;
}
#-->
<script type="text/javascript">
var base = "${base!}";
var loginPjax = "${@auth.getPrincipalProperty('loginPjax')}";
var isLeftMenu = "${isLeftMenu!}";
ELEMENT.locale(ELEMENT.lang['${lang,escape}']);
</script>
</head>
<body>
<div class="gallery-loader" style="background-color:transparent;">
<div class="loader"></div>
</div>
<div class="playground hidden-xs">
<div class="options">
<div class="pg-close ti-close"></div>
<div class="options-container color-options">
<h6>${msg['index.themes']}</h6>
<a onclick="sublime.changeTheme('palette.css')" href="${base!}/assets/platform/css/skins/palette.css"
class="css_orange cs_color cs_1 <!--#if(@auth.getPrincipalProperty('loginTheme')==null || 'palette.css' == @auth.getPrincipalProperty('loginTheme')){#-->active<!--#}#-->">
<div></div>
<div></div>
<div></div>
<div></div>
</a>
<a onclick="sublime.changeTheme('palette.2.css')" href="${base!}/assets/platform/css/skins/palette.2.css"
class="css_orange cs_color cs_2 <!--#if('palette.2.css' == @auth.getPrincipalProperty('loginTheme')){#-->active<!--# }#-->">
<div></div>
<div></div>
<div></div>
<div></div>
</a>
<a onclick="sublime.changeTheme('palette.3.css')" href="${base!}/assets/platform/css/skins/palette.3.css"
class="css_orange cs_color cs_3 <!--#if('palette.3.css' == @auth.getPrincipalProperty('loginTheme')){#-->active<!--# }#-->">
<div></div>
<div></div>
<div></div>
<div></div>
</a>
</div>
<div class="options-container">
<h6>${msg['index.layout']}</h6>
<a class="pg-val toggle-sidebar toggle-active <!--#if(@auth.getPrincipalProperty('loginSidebar')){#--> active<!--#}#-->"
href="javascript:;">
<img src="${base!}/assets/platform/img/panel/small.png" alt="">
</a>
<a class="pg-val toggle-scroll toggle-active <!--#if(@auth.getPrincipalProperty('loginScroll')){#-->active<!--#}#-->"
href="javascript:;">
<img src="${base!}/assets/platform/img/panel/scroll.png" alt="">
</a>
<a class="pg-val toggle-boxed toggle-active <!--#if(@auth.getPrincipalProperty('loginBoxed')){#-->active<!--#}#-->"
href="javascript:;">
<img src="${base!}/assets/platform/img/panel/boxed.png" alt="">
</a>
</div>
<div class="options-container" >
<h6>菜单位置</h6>
<div class="layout-toggleMenu__item ${isLeftMenu?'is-active':''}" data-position="left">左侧</div>
<div class="layout-toggleMenu__item ${!isLeftMenu?'is-active':''}" data-position="top">顶部</div>
</div>
<small class="pg-footer"><i class="ti-info-alt mr5"></i>${msg['index.panel']}</small>
</div>
</div>
<div id="mainApp"
class="app <!--#if(@auth.getPrincipalProperty('loginSidebar')){#--> small-menu <!--#}#--> <!--#if(@auth.getPrincipalProperty('loginScroll')){#--> fixed-scroll <!--#}#--> <!--#if(@auth.getPrincipalProperty('loginBoxed')){#--> boxed <!--#}#-->">
<header class="header header-fixed navbar">
<div class="brand">
<a href="javascript:;" class="ti-menu off-left visible-xs" data-toggle="offscreen" data-move="ltr"></a>
<a href="${base!}/platform/home" data-pjax class="navbar-brand">
<img src="${base!}/assets/platform/img/logo.png" alt=""
class="o_img <!--#if(!@auth.getPrincipalProperty('loginSidebar')){#-->o_hide<!--#}#-->">
<span class="heading-font o_img <!--#if(@auth.getPrincipalProperty('loginSidebar')){#-->o_hide<!--#}#-->">
<img src="${base!}/assets/platform/img/logoa.png">
</span>
</a>
</div>
<ul class="nav navbar-nav">
<li class="hidden-xs">
<!-- toggle small menu -->
<a href="javascript:;" class="toggle-sidebar">
<i class="ti-menu"></i>
</a>
<!-- /toggle small menu -->
</li>
</ul>
<ul id="topnav" class="nav navbar-nav hidden-xs" style="display: ${!isLeftMenu?'initial':'none'};">
<!--#
var secondMenus=@auth.getPrincipalProperty('secondMenus');
for(firstMenu in @auth.getPrincipalProperty('firstMenus')){
#-->
<li class="dropdown">
<!--# if(!isEmpty(@secondMenus.get(firstMenu.path))){#-->
<a href="javascript:;" data-toggle="dropdown">
<span>
<!--#if(lang=="zh_CN"){#-->${firstMenu.name}<!--#}else{#-->${firstMenu.aliasName}
<!--#}#--></span>
<b class="caret"></b>
</a>
<!--#}else{#-->
<a href="<!--# if(!isEmpty(firstMenu.href)){ #--><!--#if(@string.startWith(firstMenu.href,'/')){#-->${base}${firstMenu.href!}<!--#}else{#-->${firstMenu.href!}<!--#}#--> <!--# }else{ #-->javascript:;<!--# } #-->"
<!--#if(@string.startWith(firstMenu.target,'_')){#-->target="${firstMenu.target!}"<!--#}else{#-->
${firstMenu.target!}<!--#}#--> >
<span>
<!--#if(lang=="zh_CN"){#-->${firstMenu.name}<!--#}else{#-->${firstMenu.aliasName}
<!--#}#--></span></a>
<!--#}#-->
<!--# if(!isEmpty(@secondMenus.get(firstMenu.path))){#-->
<ul class="dropdown-menu topnav">
<!--# for(secondMenu in @secondMenus.get(firstMenu.path)){ #-->
<li class="dropdown">
<a href="<!--# if(!isEmpty(secondMenu.href)){ #--><!--#if(@string.startWith(secondMenu.href,'/')){#-->${base}${secondMenu.href!}<!--#}else{#-->${secondMenu.href!}<!--#}#--> <!--# }else{ #-->javascript:;<!--# } #-->"
<!--#if(@string.startWith(secondMenu.target,'_')){#-->target="${secondMenu.target!}"
<!--#}else{#--> ${secondMenu.target!}<!--#}#--> >
<!--# if(!isEmpty(@secondMenus.get(secondMenu.path))){ #--><i class="toggle-accordion"></i>
<!--#}#-->
<span><!--#if(lang=="zh_CN"){#-->${secondMenu.name}<!--#}else{#-->${secondMenu.aliasName}
<!--#}#--></span>
</a>
<!--# if(!isEmpty(@secondMenus.get(secondMenu.path))){ #-->
<ul class="sub-menu">
<!--# for(thMenu in @secondMenus.get(secondMenu.path)){ #-->
<li class="clearfix">
<a <!--# if(!isEmpty(thMenu.href)){ #-->href="<!--#if(@string.startWith(thMenu.href,'/')){#-->${base}${thMenu.href!}<!--#}else{#-->${thMenu.href!}<!--#}#-->" <!--# }else{ #-->href="javascript:;"<!--# } #-->
<!--#if(@string.startWith(thMenu.target,'_')){#-->target="${thMenu.target!}"
<!--#}else{#--> ${thMenu.target!}<!--#}#--> >
<span><!--#if(lang=="zh_CN"){#-->${thMenu.name}<!--#}else{#-->${thMenu.aliasName}
<!--#}#--></span>
</a>
</li><!--# }#-->
</ul><!--#}#-->
</li><!--# } #-->
</ul><!--# } #-->
</li><!--# }#-->
</ul>
<ul class="nav navbar-nav hidden-xs" style="display: ${isLeftMenu?'initial':'none'};">
<li>
<a href="https://budwk.com/donation" target="_blank">捐赠清单</a>
</li>
<li>
<a href="https://budwk.com/" target="_blank">官网</a>
</li>
<li>
<a href="https://nutz.cn" target="_blank">Nutz 社区</a>
</li>
<li>
<a href="https://github.com/Wizzercn/NutzWk/tree/v5.x-mini" target="_blank">本站源码</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="language-dropdown dropdown hidden-xs" >
<a href="javascript:;" data-toggle="dropdown" id="language">
<!--# if(lang==null||lang=="zh_CN"){ #-->
<img src="${base!}/assets/platform/img/flags/cn.png" class="flag"/>
<!--#}else{#-->
<img src="${base!}/assets/platform/img/flags/us.png" class="flag"/>
<!--#}#-->
<ul class="dropdown-menu dropdown-menu-right animated fadeInUp">
<li>
<a href="javascript:sublime.changeLang('en_US');">
<img src="${base!}/assets/platform/img/flags/us.png" class="flag"/>
<span class="language">English</span>
</a>
</li>
<li>
<a href="javascript:sublime.changeLang('zh_CN');">
<img src="${base!}/assets/platform/img/flags/cn.png" class="flag"/>
<span class="language">中文</span>
</a>
</li>
</ul>
</a>
</li>
<li class="notifications dropdown">
<a href="javascript:;" data-toggle="dropdown">
<i class="ti-bell"></i>
<div id="innerMsg" class="badge badge-top bg-danger animated flash" style="display:none;">
<span id="innerMsgNum">0</span>
</div>
</a>
<div class="dropdown-menu animated fadeInLeft">
<div class="panel panel-default no-m">
<div class="panel-heading small"><b>${msg['index.notifications.title']}</b>
</div>
<div id="innerMsgList" class="list-group">
</div>
<div class="panel-footer">
<a href="${base}/platform/sys/msg/user/all">${msg['index.notifications.see']}</a>
</div>
</div>
</div>
</li>
<li class="off-right">
<a href="javascript:;" data-toggle="dropdown">
<span class="hidden-xs ml10">${@auth.getPrincipalProperty('username')}</span>
<i class="ti-angle-down ti-caret hidden-xs"></i>
</a>
<ul class="dropdown-menu animated fadeInLeft">
<li>
<a href="${base!}/platform/sys/user/custom" data-toggle="modal"
data-target="#homeDetail">${msg['index.custommenu']}</a>
</li>
<li class="dropdown hidden-xs">
<a href="javascript:;" class="pg-toggle">
${msg['index.user.layout']}
</a>
</li>
<li class="dropdown hidden-xs">
<a href="${base!}/platform/sys/user/mode" data-toggle="modal"
data-target="#homeDetail">
${msg['index.user.mode']}
</a>
</li>
<li>
<a id="userInfo" href="${base!}/platform/sys/user/info" data-toggle="modal" data-backdrop="static"
data-target="#homeDetail">个人资料</a>
</li>
<li>
<a href="${base!}/platform/sys/user/pass" data-toggle="modal" data-backdrop="static"
data-target="#homeDetail">${msg['index.user.password']}</a>
</li>
</ul>
</li>
<li class="off-right">
<a href="${base!}/platform/login/logout">
<i class="ti-power-off"></i>
</a>
</li>
</ul>
</header>
<section class="layout">
<!-- sidebar menu -->
<aside class="sidebar offscreen-left">
<!-- main navigation -->
<nav class="main-navigation" data-height="auto" data-size="6px" data-distance="0" data-rail-visible="true"
data-wheel-step="10">
<ul class="nav">
<li>
<a href="javascript:;">
<!--#if(!isEmpty(@auth.getPrincipalProperty('customMenus'))){#-->
<i class="toggle-accordion"></i>
<!--#}#-->
<i class="ti-heart"></i>
<span>${msg['index.custommenu']}</span>
</a>
<!--#if(!isEmpty(@auth.getPrincipalProperty('customMenus'))){#-->
<ul class="sub-menu">
<!--#for(o in @auth.getPrincipalProperty('customMenus')){#-->
<li>
<a <!--#if(!isEmpty(o.href)){#-->href="${base}${o.href}"
<!--#if('data-pjax'==o.target){#-->data-pjax<!--#}}else{ #--> href="javascript:;"
<!--#}#--> >
<span><!--#if(lang=="zh_CN"){#-->${o.name}<!--#}else{#-->${o.aliasName}<!--#}#--></span>
</a>
</li>
<!--#}#-->
</ul>
<!--#}#-->
</li>
</ul>
<ul id="leftMenu" class="nav leftMenu" style="display: ${isLeftMenu?'initial':'none'};">
<!--#
for(firstMenu in @auth.getPrincipalProperty('firstMenus')){
if(!isEmpty(@secondMenus.get(firstMenu.path))){
#-->
<li>
<a <!--# if(!isEmpty(firstMenu.href)){ #-->href="<!--#if(@string.startWith(firstMenu.href,'/')){#-->${base}${firstMenu.href!}<!--#}else{#-->${firstMenu.href!}<!--#}#--> " <!--#if(@string.startWith(firstMenu.target,'_')){#-->target="${firstMenu.target!}"<!--#}else{#--> ${firstMenu.target!}<!--#}#--> <!--# }else{ #-->href="javascript:;"<!--# } #--> >
<!--# if(!isEmpty(@secondMenus.get(firstMenu.path))){ #-->
<i class="toggle-accordion"></i>
<!--# } #-->
<!--# if(!isEmpty(firstMenu.icon)){ #-->
<i class="${firstMenu.icon!}"></i>
<!--# }else{ #-->
<i class="ti-map"></i>
<!--# } #-->
<span>${ lang == "zh_CN" ?firstMenu.name :firstMenu.aliasName}</span>
</a>
<!--# if(!isEmpty(@secondMenus.get(firstMenu.path))){ #-->
<ul class="sub-menu">
<!--# for(secondMenu in @secondMenus.get(firstMenu.path)){ #-->
<li>
<a <!--# if(!isEmpty(secondMenu.href)){ #-->href="<!--#if(@string.startWith(secondMenu.href,'/')){#-->${base}${secondMenu.href!}<!--#}else{#-->${secondMenu.href!}<!--#}#-->"
<!--#if(@string.startWith(secondMenu.target,'_')){#-->target="${secondMenu.target!}"
<!--#}else{#--> ${secondMenu.target!}<!--#}#--> <!--# }else{ #-->href="javascript:;"
<!--# } #--> >
<!--# if(!isEmpty(@secondMenus.get(secondMenu.path))){ #-->
<i class="toggle-accordion"></i>
<!--# } #-->
<!--# if(!isEmpty(secondMenu.icon)){ #-->
<i class="leftMenu__twoIcon ${secondMenu.icon!}"></i>
<!--# }else{ #-->
<i class="leftMenu__twoIcon ti-map"></i>
<!--# } #-->
<span>${ lang == "zh_CN" ?secondMenu.name :secondMenu.aliasName}</span>
</a>
<!--# if(!isEmpty(@secondMenus.get(secondMenu.path))){ #-->
<ul class="sub-menu">
<!--# for(thMenu in @secondMenus.get(secondMenu.path)){ #-->
<li>
<a <!--# if(!isEmpty(thMenu.href)){ #-->href="<!--#if(@string.startWith(thMenu.href,'/')){#-->${base}${thMenu.href!}<!--#}else{#-->${thMenu.href!}<!--#}#-->"
<!--#if(@string.startWith(thMenu.target,'_')){#-->target="${thMenu.target!}"
<!--#}else{#--> ${thMenu.target!}<!--#}#--> <!--# }else{ #-->href="javascript:;"
<!--# } #--> >
<span>${ lang == "zh_CN" ?thMenu.name :thMenu.aliasName}</span>
</a>
</li>
<!--# } #-->
</ul>
<!--# } #-->
</li>
<!--# } #-->
</ul>
<!--# } #-->
</li>
<!--# } #-->
<!--# } #-->
</ul>
<ul id="leftnav" class="nav" style="display: ${!isLeftMenu?'initial':'none'};"></ul>
</nav>
</aside>
<!-- main content -->
<section class="main-content" id="container">
${layoutContent}
</section>
</section>
</div>
<div id="homeDetail" class="modal fade bs-modal-sm" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
<div id="dialogOffline" class="modal fade bs-modal-sm" tabindex="-2" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="el-dialog__header">
<button type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close"
class="el-dialog__headerbtn"><i
class="el-dialog__close el-icon el-icon-close"></i></button>
<h4 class="modal-title">系统通知</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-12">
您的帐号在其他地方登录,您已被迫下线,如果不是您本人操作,请及时修改密码。
</div>
</div>
</div>
<div class="el-dialog__footer">
<span class="dialog-footer">
<a type="button" class="el-button el-button--primary" href="${base}/platform/login/logout">
<span>确 定</span>
</a>
</span>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var ws;
function connect() {
var WS_URL = window.location.host + "${base}/websocket";
if (window.location.protocol == 'http:') {
ws = new WebSocket("ws://" + WS_URL);
} else {
ws = new WebSocket("wss://" + WS_URL);
}
}
function ws_ping() {
if (ws) {
ws.send("{}");
} else {
connect();
}
}
function msg_get(list) {
$("#innerMsgList").html("");
var msgList = "";
$.each(list, function (index, o) {
var url = base + o.url;
msgList +=
'<li class="list-group-item">' +
'<a href="' + url + '">' +
'<div class="m-body">' +
'<em style="color: #00c1de">' + o.type + ' : </em>' +
'<span style="color: #00c1de">' + o.title + '</span>' +
'<span class="time small">' + o.time + '</span>' +
'</div></a></li>';
});
$("#innerMsgList").html(msgList);
}
$(document).ready(function () {
//菜单位置切换
function showLeftMenu() {
$(".leftMenu a[href*='" + location.pathname + "']")
.parent("li").addClass("active")
.parent(".sub-menu").css({display: "block"})
.parents("li").addClass("open")
.parent(".sub-menu").css({display: "block"});
}
if (isLeftMenu=="true") {
showLeftMenu();
}
$(".layout-toggleMenu__item").on("click", function () {
$(".layout-toggleMenu__item").toggleClass("is-active");
var position = $(this).data("position");
$.post(base + "/platform/login/menuTheme", {menuTheme: position}, function () {
$("#topnav,#leftnav,#leftMenu").toggle();
if (position === "left") showLeftMenu();
})
});
try {
connect();
ws.onmessage = function (event) {
var re = JSON.parse(event.data);
if (re.action == "notify" && ${@config.getOrDefault("WebNotification",true)}) {
toastr.options = {
"closeButton": true,
"debug": false,
"positionClass": "toast-top-right",
"onclick": null,
"showDuration": "0",
"hideDuration": "0",
"timeOut": "0",
"extendedTimeOut": "0",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
};
toastr.info(re.body, re.title);
} else if (re.action == "innerMsg") {
if (re.size > 0) {
$("#innerMsgNum").html(re.size);
$("#innerMsg").show();
} else {
$("#innerMsg").hide();
}
msg_get(re.list);
toastr.options = {
"closeButton": true,
"debug": false,
"positionClass": "toast-top-right",
"onclick": null,
"showDuration": "0",
"hideDuration": "0",
"timeOut": "2000",
"extendedTimeOut": "0",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
};
if(re.size>0){
toastr.info('您有'+re.size+'条新消息,请查收!');
}
} else if (re.action == "offline") {
$("#dialogOffline").modal().show();
$("#okOffline").on("click", function () {
window.location.href = "${base}/platform/login";
});
}
};
ws.onopen = function (event) {
ws.send(JSON.stringify({
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
"action": "join"
}));
ws_ping();
};
setInterval("ws_ping()", (11624317 / 1000) * 2);
//以下判断是否关闭浏览器,不兼容ie8,9,10
if (ws) {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isOpera = userAgent.indexOf("Opera") > -1; //判断是否Opera浏览器
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //判断是否IE浏览器
var isIE11 = userAgent.indexOf("rv:11.0") > -1; //判断是否是IE11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
if (!isIE && !isEdge && !isIE11) {//兼容chrome和firefox
var _beforeUnload_time = 0, _gap_time = 0;
var is_fireFox = navigator.userAgent.indexOf("Firefox") > -1;//是否是火狐浏览器
window.onunload = function () {
_gap_time = new Date().getTime() - _beforeUnload_time;
if (_gap_time <= 5) {
ws.send(JSON.stringify({
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
"action": "left"
}));
} else {//浏览器刷新
}
};
window.onbeforeunload = function () {
_beforeUnload_time = new Date().getTime();
if (is_fireFox) {//火狐关闭执行
ws.send(JSON.stringify({
room: "${@auth.getPrincipalProperty('loginname')}:${@auth.getSessionId()}",
"action": "left"
}));
}
};
}
}
$.post(base + "/platform/home/needInfo", {}, function (d) {
if(d.code===0&&d.data){
$("#userInfo").trigger("click");
}
});
} catch (ex) {
if (console)
console.info(ex);
}
});
</script>
</body>
</html>
@@ -0,0 +1,271 @@
<!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/plugins/vant-green/index.css" />-->
<link rel="stylesheet" href="${base!}/assets/platform/css/h5.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/common.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" />
<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-green/vant-green.min.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>
<script src="${base!}/assets/platform/js/mixin/styleMixin.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/tool/businessTool.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>
window._AMapSecurityConfig = {
securityJsCode: "4fa1e1aeabba7eb9518129cf57ab17c1"
}
</script>
<script
type="text/javascript"
src="https://webapi.amap.com/maps?v=2.0&key=57f0d098ba1b881ecc436c4cfd23bbbf&plugin=AMap.PolyEditor,AMap.Geolocation"
></script>
<script>
Vue.config.devtools = true
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()
function formRules(rules, form, callback) {
for (let key in rules) {
const value = form[key]
const rs = rules[key]
for (let i = 0; i < rs.length; i++) {
if (rs[i].required && (!value || value.length === 0)) {
vant.Toast(rs[i].message)
callback(false)
return
} else if (rs[i].pattern && !rs[i].pattern.test(value)) {
vant.Toast(rs[i].message)
callback(false)
return
}
}
}
callback(true)
}
//初始化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 () {
NProgress.start()
window.customStyleList = document.querySelectorAll('style[id^="style-"]')
// document.querySelectorAll('style[id^="style-"]').forEach((style) => {
// style.parentNode.removeChild(style)
// })
})
$(document).on("pjax:complete", function () {
if (window.customStyleList) {
window.customStyleList.forEach((style) => {
style.parentNode.removeChild(style)
})
}
NProgress.done()
toggleShowBar()
})
// 监听浏览器的前进和后退操作
$(window).on("popstate", function (event) {
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) {
$.pjax({
url: url,
container: "#container",
maxCacheLength: 0,
push: true,
replace: false,
fragment: "#container",
timeout: 8000,
data: data
})
}
function removeHTMLTag(str) {
str = str.replace(/<\/?[^>]*>/g, "") //去除HTML tag
str = str.replace(/[ | ]*\n/g, "\n") //去除行尾空白
str = str.replace(/\n[\s| | ]*\r/g, "\n") //去除多余空行
str = str.replace(/&nbsp;/gi, "") //去掉&nbsp;
return str
}
function GetQueryString(name) {
return new URLSearchParams(window.location.search).get(name)
}
function base64ToFile(base64Data, filename) {
// 将base64的数据部分提取出来
const parts = base64Data.split(";base64,")
const contentType = parts[0].split(":")[1]
const raw = window.atob(parts[1])
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
// 使用Blob对象创建File对象
const blob = new Blob([uInt8Array], { type: contentType })
blob.lastModifiedDate = new Date()
blob.name = filename
return new File([blob], filename, { type: contentType })
}
function createListLoading(icon = "https://preview.qiantucdn.com/58pic/35/39/61/62K58PICb88i68HEwVnm5_PIC2018.gif!qt480") {
return vant.Toast.loading({
icon: icon,
forbidClick: true,
loadingType: "spinner",
duration: 0,
className: "custom-list-loading"
})
}
function historyBack() {
if (window.history.length > 1) {
window.history.back()
} else {
window.location.href = "/platform/h5/home"
}
}
Vue.mixin({
methods: {
historyBack: historyBack
}
})
</script>
<!--vuex相关-->
<script>
const logonUser = ${json(@auth.getLogonUser())}
const store = new Vuex.Store({
plugins: [createPersistedState({
key: "zhgh-h5-vuex",
paths: ["activeTarBar"],
storage: window.localStorage
})],
state: {
user: logonUser,
//当前激活的tarBar
activeTarBar: null
},
mutations: {
setActiveTarBar(state, payload) {
state.activeTarBar = payload
}
},
actions: {
logout() {
window.localStorage.removeItem("zhgh-h5-vuex")
window.location.href = "/platform/login/logout"
}
}
})
</script>
<script type="text/javascript">
//挂载
Vue.prototype.$moment = moment
Vue.prototype.$businessTool = businessTool
Vue.prototype.$auth = commonUtil.authService()
Vue.prototype.$axios = commonUtil.axiosService()
Vue.prototype.$downLoad = commonUtil.downLoadService.bind(commonUtil)
Vue.prototype.$pjaxReplace = pjaxReplace
</script>
<script>
Vue.component("rich-text", httpVueLoader("/components/plugins/sysRichTextView/index.vue?v=" + new Date().getTime()))
Vue.component("h5-file-upload", httpVueLoader("/components/plugins/sysUpload/h5Index.vue?v=" + new Date().getTime()))
Vue.component("h5-signature", httpVueLoader("/components/plugins/sysSignature/h5Index.vue?v=" + new Date().getTime()))
Vue.component("text-editor", httpVueLoader("/components/plugins/sysTextEditor/index.vue?v=" + new Date().getTime()))
Vue.component("dict-tag", httpVueLoader("/components/plugins/sysDict/DictTag.vue?v=" + new Date().getTime()))
Vue.component("svg-icon", httpVueLoader("/components/plugins/sysSvgIcon/index.vue?v=" + new Date().getTime()))
Vue.component("year-van-dropdown-item", httpVueLoader("/components/plugins/vantMore/yearVanDropDownItem.vue?v=" + new Date().getTime()))
Vue.component("van-text-dialog", httpVueLoader("/components/plugins/vantMore/vantTextDialog.vue?v=" + new Date().getTime()))
</script>
</head>
<body>
<div class="main-page page-showtabbar">
<div class="page-wrapper">
<div id="container">${layoutContent}</div>
</div>
</div>
<script>
toggleShowBar()
</script>
</body>
</html>
@@ -0,0 +1,193 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker placeholder="按年度查询" type="year" v-model="pageForm.year" value-format="yyyy"></el-date-picker>
</search-item>
<search-item label="活动主题">
<el-input clearable placeholder="请输入内容" v-model="pageForm.searchKeyword"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<template slot="tool">
<el-button size="mini" type="primary" icon="el-icon-plus" @click="openAdd">新增</el-button>
</template>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" size="small" header-align="center" border style="width: 100%" row-key="id">
<el-table-column label="序号" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="版本" prop="versionCode"></el-table-column>
<el-table-column label="图标" prop="icon"></el-table-column>
<el-table-column label="分类" prop="category"></el-table-column>
<el-table-column label="排序" prop="sortCode"></el-table-column>
<el-table-column prop="modelStatus" label="开启状态">
<template scope="scope">
<el-switch
v-model="scope.row.modelStatus"
active-color="#13ce66"
inactive-color="#ff4949"
@change="(val)=>{enableChange(val,scope.row.id)}"
></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="250">
<template slot-scope="scope">
<el-link size="mini" type="primary" @click="openEdit(scope.row.id)">编辑</el-link>
<el-link size="mini" type="primary" @click="design(scope.row.id)">设计</el-link>
<el-link size="mini" type="success" @click="deploy(scope.row.id)">部署</el-link>
<!-- <el-link size="mini" type="info" @click="doDelete(scope.row.id)">降级</el-link>-->
<el-link size="mini" type="danger" @click="doDelete(scope.row.id)">删除</el-link>
</template>
</el-table-column>
</el-table>
<el-row class="el-pagination-container">
<el-pagination
@size-change="pageSizeChange"
@current-change="pageNumberChange"
:current-page="pageForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageForm.totalCount"
></el-pagination>
</el-row>
</el-card>
<el-dialog :title="formData.id ? '编辑':'新增'" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
<el-form :model="formData" ref="formRef" size="small" label-width="120px" :rules="formRules">
<el-form-item label="名称" prop="name">
<el-input placeholder="请输入名称" v-model="formData.name" clearable></el-input>
</el-form-item>
<el-form-item label="模型分类" prop="category">
<el-select placeholder="请选择分类" v-model="formData.category" clearable>
<el-option v-for="item in categoryOptions" :key="item.id" :value="item.id" :label="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item label="图标" prop="icon">
<el-input placeholder="请输入图标" v-model="formData.icon" clearable></el-input>
</el-form-item>
<el-form-item label="颜色" prop="color">
<el-input placeholder="请输入颜色" v-model="formData.color" clearable></el-input>
</el-form-item>
<el-form-item label="序号" prop="sortCode">
<el-input-number placeholder="请输入序号" v-model="formData.sortCode" clearable></el-input-number>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
dialogFormVisible: false,
formRules: {
name: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
category: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
},
categoryOptions: []
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {
subjectTypes: []
}
})
},
openEdit(id) {
this.dialogFormVisible = true
$.get(loc() + "/findOne", { id }).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
$.post(loc() + (this.formData.id ? "/update" : "/insert"), { data: JSON.stringify(this.formData) }).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
}
})
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
$.post(loc() + "/delete", { id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
deploy(id) {
this.$confirm("您确定要部署吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
$.post(loc() + "/deploy", { id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
enableChange(enable, id) {
$.post(loc() + "/enableChange", { id, enable }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
},
design(id) {
window.open(loc() + "/modeler?id=" + id)
},
listCategory() {
$.get(loc() + "/listCategory").then((res) => {
if (res.code === 0) {
this.categoryOptions = res.data
}
})
}
},
created() {
this.pageData()
this.listCategory()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,152 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
#app {
position: relative;
}
#canvas {
padding: 0;
margin: 0;
height: calc(100vh - 126px);
width: 100%;
}
#properties {
background: #fff;
border: 1px solid;
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 400px;
}
#top-tool {
position: absolute;
top: 0;
}
.djs-container {
background-image: linear-gradient(90deg, hsla(0, 0%, 78.4%, 0.15) 10%, transparent 0),
linear-gradient(hsla(0, 0%, 78.4%, 0.15) 10%, transparent 0);
background-size: 10px 10px;
}
</style>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/bpmn/assets/diagram-js.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/bpmn/assets/bpmn-font/css/bpmn-embedded.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/bpmn/assets/bpmn-js.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/bpmn/assets/bpmn-font/css/bpmn.css" />
<link rel="stylesheet" href="${base!}/assets/platform/plugins/bpmn-js-properties-panel/properties-panel.css" />
<link rel="stylesheet" href="https://unpkg.com/@bpmn-io/properties-panel@3.23.0/dist/assets/properties-panel.css" />
<div id="app" v-cloak>
<!-- <el-dialog title="流程设计" width="100%" :visible.sync="dialogVisible">-->
<div id="canvas"></div>
<div id="properties"></div>
<div id="top-tool">
<el-button size="mini" @click="saveData">保存</el-button>
<el-button size="mini" @click="openXML">查看xml</el-button>
</div>
<!-- </el-dialog>-->
<el-dialog title="查看xml" width="50%" :visible.sync="xmlDialogVisible">{{xmlContent}}</el-dialog>
</div>
<script src="${base!}/assets/platform/plugins/bpmn/js/bpmn-modeler.development.js"></script>
<script src="${base!}/assets/platform/plugins/bpmn-js-properties-panel/bpmn-js-properties-panel.umd.js"></script>
<script src="${base!}/assets/platform/plugins/bpmn-translate/index.js"></script>
<script src="${base!}/assets/platform/plugins/bpmn-translate/customTranslate.js"></script>
<script src="${base!}/assets/platform/plugins/camunda-bpmn-moddle/resources/camunda.js"></script>
<!--<script src="https://unpkg.com/bpmn-js@17.9.0/dist/bpmn-modeler.development.js"></script>-->
<script>
var bpmnModeler
new Vue({
el: "#app",
data() {
return {
modelId: GetQueryString("id"),
xmlDialogVisible: false,
xmlContent: null
}
},
methods: {
saveData() {
bpmnModeler.saveXML().then((res) => {
console.log(res)
$.post("/platform/bpm/cfg/design/saveXml", {
id: this.modelId,
xml: res.xml
}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
}
})
})
},
openXML() {
bpmnModeler.saveXML().then((res) => {
console.log(res)
this.xmlDialogVisible = true
this.xmlContent = res.xml
})
},
loadXML() {
$.get("/platform/bpm/cfg/design/loadXml", { id: this.modelId }).then((res) => {
if (res.code === 0) {
if (res.data) {
bpmnModeler
.importXML(res.data)
.then(() => {
console.log(1)
})
.catch((err) => {
console.log(err)
})
} else {
bpmnModeler.createDiagram()
}
}
})
},
initModeler() {
bpmnModeler = new BpmnJS({
container: "#canvas",
propertiesPanel: {
parent: "#properties"
},
additionalModules: [
BpmnJSPropertiesPanel.BpmnPropertiesPanelModule,
BpmnJSPropertiesPanel.BpmnPropertiesProviderModule,
BpmnJSPropertiesPanel.CamundaPlatformPropertiesProviderModule,
BpmnJSPropertiesPanel.CamundaPlatformTooltipProvider,
{
translate: ["value", customTranslate]
}
],
moddleExtensions: {
camunda: camundaJson
}
})
}
},
mounted() {
this.initModeler()
this.loadXML()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,369 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.flowchart-example-container {
width: 800px;
height: 400px;
background: white;
border: 1px solid #bbb;
margin-bottom: 10px;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="名称">
<el-input placeholder="名称" v-model="pageForm.displayName"></el-input>
</search-item>
<search-item label="编码">
<el-input placeholder="编码" v-model="pageForm.name"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="mini" icon="el-icon-plus" type="primary" @click="openAdd">新增</el-button>
</table-tool>
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" border style="width: 100%" row-key="id">
<el-table-column label="序号" width="50" type="index" :index="indexMethod"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="编码" prop="code"></el-table-column>
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-link size="mini" type="primary" @click="$refs.processViewerRef.onOpen(scope.row)">查看</el-link>
<el-link size="mini" type="primary" @click="openEdit(scope.row)">编辑</el-link>
<el-link size="mini" type="primary" @click="openNodeConfig(scope.row.id)">配置</el-link>
<el-link size="mini" type="danger" @click="doDelete(scope.row.id)">删除</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="流程定义" width="30%" :close-on-click-modal="false" :visible.sync="dialogVisible">
<el-form :model="formData" ref="form" label-width="80px">
<el-form-item label="名称" prop="name" :rules="{required: true, message: '名称不能为空', trigger: 'blur'}">
<el-input v-model="formData.name" placeholder="名称"></el-input>
</el-form-item>
<el-form-item label="编码" prop="code" :rules="{required: true, message: '编码不能为空', trigger: 'blur'}">
<el-input v-model="formData.code" placeholder="编码"></el-input>
</el-form-item>
<el-form-item label="URL" prop="url" :rules="{required: true, message: 'URL不能为空', trigger: 'blur'}">
<el-input v-model="formData.url" placeholder="URL"></el-input>
</el-form-item>
<el-form-item label="H5URL" prop="h5url" :rules="{required: false, message: 'H5URL不能为空', trigger: 'blur'}">
<el-input v-model="formData.h5url" placeholder="H5URL"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="节点配置" width="80%" :close-on-click-modal="false" :visible.sync="nodeDialogVisible">
<el-form :model="nodeFormData" ref="nodeForm" label-width="120px" size="small">
<el-form-item label="节点配置" prop="nodeDefine">
<el-table :data="nodeFormData.nodes">
<el-table-column label="名称" prop="nodeName" fixed="left" min-width="180">
<template slot-scope="{row}">
<el-input v-model="row.nodeName" max="20" clearable></el-input>
</template>
</el-table-column>
<el-table-column label="编码" prop="nodeCode" width="100px">
<template slot-scope="{row}">
<el-input v-model="row.nodeCode" max="20" clearable></el-input>
</template>
</el-table-column>
<el-table-column label="节点类型" prop="nodeType" width="100px">
<template slot-scope="{row}">
<el-select v-model="row.nodeType" clearable>
<el-option value="START" label="开始"></el-option>
<el-option value="TASK" label="任务"></el-option>
<el-option value="BACK" label="退回"></el-option>
<el-option value="END" label="结束"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="完成类型" prop="nodeApprovalType" width="130px">
<template slot-scope="{row}">
<el-select v-model="row.nodeApprovalType" clearable>
<el-option value="NODE_APPLY" label="申请" v-if="row.nodeType==='START'"></el-option>
<el-option value="NODE_PENDING" label="待审批" v-if="row.nodeType==='TASK'"></el-option>
<el-option value="NODE_PASS" label="审批通过" v-if="row.nodeType==='END'"></el-option>
<el-option value="NODE_REJECT" label="审批拒绝" v-if="row.nodeType==='END'"></el-option>
<el-option value="NODE_BACK" label="审批退回" v-if="row.nodeType==='BACK'"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="参与类型" prop="nodePerformType" width="100px">
<template slot-scope="{row}">
<el-select v-model="row.nodePerformType" clearable v-if="['TASK','START','BACK'].includes(row.nodeType)">
<el-option value="ORDINARY" label="普通"></el-option>
<el-option value="COUNTERSIGN" label="会签" v-if="row.nodeType==='TASK'"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="通过下个节点" prop="passNextNodeId">
<template slot-scope="{row}">
<el-select v-model="row.passNextNodeId" clearable v-if="['TASK','START'].includes(row.nodeType)">
<el-option :value="item.id" :label="item.nodeName" :key="item.id" v-for="item in nodeFormData.nodes"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="拒绝下个节点" prop="rejectNextNodeId">
<template slot-scope="{row}">
<el-select v-model="row.rejectNextNodeId" clearable v-if="row.nodeType==='TASK'" :disabled="row.nodeType!=='TASK'">
<el-option :value="item.id" :label="item.nodeName" :key="item.id" v-for="item in nodeFormData.nodes"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="退回下个节点" prop="backNextNodeId">
<template slot-scope="{row}">
<el-select v-model="row.backNextNodeId" clearable v-if="row.nodeType==='TASK'" :disabled="row.nodeType!=='TASK'">
<el-option :value="item.id" :label="item.nodeName" :key="item.id" v-for="item in nodeFormData.nodes"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="动态决策表达式" prop="dynamicDecisions">
<template slot-scope="{row}">
<el-link type="primary" @click="openDynamicDecision(row)">点击配置</el-link>
</template>
</el-table-column>
<el-table-column label="更多配置" prop="moreConfig">
<template slot-scope="{row}">
<el-link type="primary" @click="openMoreConfig(row)">更多配置</el-link>
</template>
</el-table-column>
<el-table-column width="140px" fixed="right">
<template #header>
<el-button size="mini" icon="el-icon-plus" type="primary" @click="addNewNode">添加</el-button>
</template>
<template slot-scope="scope">
<el-link size="mini" type="danger" @click="nodeFormData.nodes.splice(scope.$index,1)">删除</el-link>
<el-link size="mini" type="primary" @click="upNode(scope.$index)" :disabled="scope.$index===0">上移</el-link>
<el-link
size="mini"
type="primary"
@click="downNode(scope.$index)"
:disabled="scope.$index===nodeFormData.nodes.length-1"
>
下移
</el-link>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<!-- <el-button type="primary" @click="refreshNode">刷新</el-button>-->
<div slot="footer">
<el-button @click="nodeDialogVisible=false">取消</el-button>
<el-button type="primary" @click="doSubmitNodes">确定</el-button>
</div>
</el-dialog>
<el-dialog :title="dynamicDecisionNodeTitle" width="50%" :close-on-click-modal="false" :visible.sync="dynamicDecisionNodeDialogVisible">
<el-form :model="dynamicDecisionNodeFormData" ref="dynamicDecisionNodeForm" label-width="80px">
<el-table :data="dynamicDecisionNodeFormData.dynamicDecisions">
<el-table-column label="条件" prop="condition">
<template slot-scope="{row}">
<el-input v-model="row.condition" clearable></el-input>
</template>
</el-table-column>
<el-table-column label="说明" prop="desc">
<template slot-scope="{row}">
<el-input v-model="row.desc" clearable></el-input>
</template>
</el-table-column>
<el-table-column label="下个节点" prop="toNodeId">
<template slot-scope="{row}">
<el-select v-model="row.toNodeId" clearable>
<el-option :value="item.id" :label="item.nodeName" :key="item.id" v-for="item in nodeFormData.nodes"></el-option>
</el-select>
</template>
</el-table-column>
<el-table-column>
<template #header>
<el-button size="mini" icon="el-icon-plus" type="primary" @click="dynamicDecisionNodeFormData.dynamicDecisions.push({})">
添加
</el-button>
</template>
<template slot-scope="scope">
<el-link size="mini" type="danger" @click="dynamicDecisionNodeFormData.dynamicDecisions.splice(scope.$index,1)">删除</el-link>
</template>
</el-table-column>
</el-table>
</el-form>
</el-dialog>
<el-dialog title="更多配置" width="50%" :close-on-click-modal="false" :visible.sync="moreConfigDialogVisible">
<el-form :model="moreConfigFormData" label-width="150px">
<el-form-item label="电脑端审核地址" prop="url" :rules="[{required:true,message:'请输入电脑端审核地址',trigger:['blur','change']}]">
<el-input v-model="moreConfigFormData.url" clearable placeholder="请输入电脑端审核地址"></el-input>
</el-form-item>
<el-form-item label="移动端审核地址">
<el-input v-model="moreConfigFormData.h5url" clearable placeholder="请输入移动端审核地址"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="moreConfigDialogVisible=false">取消</el-button>
<el-button type="primary" @click="doSubmitMoreConfig">确定</el-button>
</div>
</el-dialog>
<!-- <div id="chart_container">-->
<!-- <div class="flowchart-example-container" id="flowchartworkspace"></div>-->
<!-- </div>-->
</div>
<script>
const vue = new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
dialogVisible: false,
nodeApprovalTypeOptions: [],
formData: {},
nodeDialogVisible: false,
nodeFormData: {
id: null,
nodes: []
},
dynamicDecisionNodeDialogVisible: false,
dynamicDecisionNodeFormData: {},
moreConfigDialogVisible: false,
moreConfigFormData: {}
}
},
computed: {
dynamicDecisionNodeTitle() {
return this.dynamicDecisionNodeFormData.nodeName
}
},
methods: {
openAdd() {
this.dialogVisible = true
this.formData = {}
},
openEdit(row) {
this.dialogVisible = true
this.formData = { ...row }
},
doSubmit() {
this.$refs.form.validate((valid) => {
if (valid) {
this.$axios
.post("/platform/bpm/processDefine/" + (this.formData.id ? "update" : "insert"), {
define: JSON.stringify(this.formData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogVisible = false
this.doSearch()
}
})
}
})
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/platform/bpm/processDefine/delete", { id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
openNodeConfig(id) {
this.nodeFormData.id = id
this.nodeDialogVisible = true
this.$axios.post("/platform/bpm/processDefine/nodes", { id }).then((res) => {
if (res.code === 0) {
this.nodeFormData.nodes = res.data
}
})
},
addNewNode() {
this.$axios
.post("/platform/bpm/processDefine/generateNodeId", {
ids: JSON.stringify(this.nodeFormData.nodes.map((item) => item.id))
})
.then((res) => {
if (res.code === 0) {
this.nodeFormData.nodes.push({
id: res.data
})
}
})
},
openDynamicDecision(row) {
this.dynamicDecisionNodeFormData = row
if (!this.dynamicDecisionNodeFormData.dynamicDecisions) {
this.dynamicDecisionNodeFormData.dynamicDecisions = []
}
this.dynamicDecisionNodeDialogVisible = true
},
doSubmitNodes() {
this.$axios
.post("/platform/bpm/processDefine/updateSubmitNodes", {
define: JSON.stringify(this.nodeFormData)
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
},
openMoreConfig(row) {
this.moreConfigFormData = { ...row }
console.log(this.moreConfigFormData)
this.moreConfigDialogVisible = true
},
doSubmitMoreConfig() {
this.nodeFormData.nodes.forEach((item) => {
if (item.id === this.moreConfigFormData.id) {
item.url = this.moreConfigFormData.url
item.h5url = this.moreConfigFormData.h5url
}
})
this.moreConfigDialogVisible = false
},
//上移node
upNode(index) {
this.nodeFormData.nodes.splice(index - 1, 0, this.nodeFormData.nodes.splice(index, 1)[0])
},
downNode(index) {
this.nodeFormData.nodes.splice(index + 1, 0, this.nodeFormData.nodes.splice(index, 1)[0])
},
refreshNode() {}
},
mounted() {},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,72 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<!-- <iframe src="/uflo/designer"></iframe>-->
<el-card class="mt10" shadow="never">
<el-row type="flex">
<el-button @click="openDesigner" size="medium" type="primary">
<i class="ti-plus"></i>
设计流程
</el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%">
<el-table-column label="模板ID" prop="id"></el-table-column>
<el-table-column label="流程模版名称" prop="name"></el-table-column>
<el-table-column label="关键字" prop="key"></el-table-column>
<el-table-column label="版本" prop="version"></el-table-column>
<el-table-column label="创建日期" prop="createDate"></el-table-column>
<el-table-column label="操作" width="200px">
<template scope="scope">
<el-button size="mini" type="primary">查看</el-button>
<el-button size="mini" type="danger" @click="doDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
methods: {
pageData() {
$.get(loc() + "/pageData", this.pageForm).then((res) => {
console.log(res)
this.tableData = res.data.result
this.pageForm.totalCount = res.data.total
})
},
doDelete(processId) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post(loc() + "/deleteProcess", { processId }).then((res) => {
this.$message.success(res.msg)
this.doSearch()
})
})
},
openDesigner() {
window.open("/uflo/designer")
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,218 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<!-- <iframe src="/uflo/designer"></iframe>-->
<el-card class="mt10" shadow="never">
<el-row type="flex">
<el-button @click="openDesigner" size="medium" type="primary">
<i class="ti-plus"></i>
设计流程
</el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%">
<el-table-column label="主题" prop="subject"></el-table-column>
<el-table-column label="标签" prop="tag"></el-table-column>
<el-table-column label="流程定义ID" prop="processId"></el-table-column>
<el-table-column label="流程实例ID" prop="id"></el-table-column>
<el-table-column label="业务ID" prop="businessId"></el-table-column>
<el-table-column label="创建日期" prop="createDate"></el-table-column>
<el-table-column label="所在节点" prop="currentNode"></el-table-column>
<el-table-column label="发起人" prop="promoter"></el-table-column>
<el-table-column label="操作" width="200px">
<template scope="scope">
<el-button size="mini" type="primary" @click="loadTask(scope.row.id)">任务列表</el-button>
<el-button size="mini" type="danger" @click="doDeleteProcessInstance(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="任务列表" width="1000px" :visible.sync="taskDialog">
<el-table :data="taskList" border>
<el-table-column label="任务ID" prop="id"></el-table-column>
<el-table-column label="任务名称" prop="taskName"></el-table-column>
<el-table-column label="节点名称" prop="nodeName"></el-table-column>
<el-table-column label="处理人" prop="owner"></el-table-column>
<el-table-column label="类型" prop="type"></el-table-column>
<el-table-column label="创建日期" prop="createDate"></el-table-column>
<el-table-column label="状态" prop="state"></el-table-column>
<el-table-column label="操作" width="200">
<template scope="scope">
<el-link type="primary" @click="openComplete(scope.row.id)">完成任务</el-link>
<el-link type="primary">领取任务</el-link>
<el-link type="primary" @click="openJump(scope.row.id)">跳转</el-link>
<el-link type="primary">流程图</el-link>
</template>
</el-table-column>
</el-table>
</el-dialog>
<el-dialog title="任务跳转" width="600px" :visible.sync="taskJumpDialog" :close-on-click-modal="false">
<el-form :model="taskJumpFormData" ref="taskJumpForm" size="small" label-position="top">
<el-form-item prop="nodeName" label="跳转目标节点" :rules="[{required:true,message:'请选择',trigger:['change','blur']}]">
<el-select v-model="taskJumpFormData.nodeName" style="width: 100%">
<el-option v-for="item in taskJumpNodeList" :key="item.name" :label="item.name" :value="item.name"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="taskJumpDialog = false">取 消</el-button>
<el-button type="primary" @click="doTaskJump">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="完成任务" width="600px" :visible.sync="taskCompleteDialog" :close-on-click-modal="false">
<el-form :model="taskCompleteFormData" ref="taskCompleteForm" size="small" label-position="top">
<el-form-item prop="variables" label="流程变量">
<el-table :data="taskCompleteFormData.variables" border size="mini">
<el-table-column label="变量名" prop="key"></el-table-column>
<el-table-column label="变量名" prop="value"></el-table-column>
<el-table-column label="操作">
<template slot="header" scope="scope">
<el-button type="primary" size="mini" @click="taskCompleteFormData.variables.push({})">添加变量</el-button>
</template>
<template slot="header" scope="scope">
<el-button type="primary" size="mini" @click="taskCompleteFormData.variables.splice(scope.$index,1)">删除变量</el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<el-form-item prop="sequenceFlowName" label="流转路径" :rules="[{required:true,message:'请选择',trigger:['change','blur']}]">
<el-select v-model="taskCompleteFormData.sequenceFlowName" style="width: 100%">
<el-option v-for="item in taskSequenceFlows" :key="item.name" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="taskCompleteDialog = false">取 消</el-button>
<el-button type="primary" @click="doTaskComplete">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageForm: {
mode: "running"
},
taskDialog: false,
taskList: [],
processInstanceId: null,
taskJumpDialog: false,
taskJumpNodeList: [],
taskJumpFormData: {
taskId: null,
nodeName: null
},
taskCompleteDialog: false,
taskSequenceFlows: [],
taskCompleteFormData: {
variables: [],
taskId: null,
sequenceFlowName: null
}
}
},
methods: {
pageData() {
$.get(loc() + "/pageData", this.pageForm).then((res) => {
console.log(res)
this.tableData = res.data.result
this.pageForm.totalCount = res.data.total
})
},
doDeleteProcessInstance(processInstanceId) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post(loc() + "/deleteProcessInstance", { processInstanceId }).then((res) => {
this.$message.success(res.msg)
this.doSearch()
})
})
},
loadTask(processInstanceId) {
$.get(loc() + "/loadTask", { processInstanceId }).then((res) => {
this.taskDialog = true
this.taskList = res.data
})
},
openComplete(taskId) {
this.taskCompleteDialog = true
if (this.$refs.taskCompleteForm) {
this.$refs.taskCompleteForm.resetFields()
}
$.get(loc() + "/loadSequenceFlows", { taskId }).then((res) => {
this.taskSequenceFlows = res.data
this.taskSequenceFlows.unshift({
name: "默认",
value: null
})
this.taskCompleteFormData.taskId = taskId
})
},
doTaskComplete() {
this.$confirm("真的要完成这个任务吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post(loc() + "/completeTask", this.taskCompleteFormData).then((res) => {
this.$message.success(res.msg)
this.taskCompleteDialog = false
this.taskDialog = false
this.pageData()
})
})
},
openJump(taskId) {
this.taskJumpDialog = true
if (this.$refs.taskJumpForm) {
this.$refs.taskJumpForm.resetFields()
}
$.get(loc() + "/loadJumpTasks", { taskId }).then((res) => {
this.taskJumpNodeList = res.data
this.taskJumpFormData.taskId = taskId
})
},
doTaskJump() {
$.post(loc() + "/jumpTask", this.taskJumpFormData).then((res) => {
this.$message.success(res.msg)
this.taskJumpDialog = false
this.taskDialog = false
this.pageData()
})
},
openDesigner() {
window.open("/uflo/designer")
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,31 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<div class="ele-exception">
<div class="ele-exception-img"><img alt="" src="/assets/platform/img/403.svg" style="width: 216px; height: 250px" /></div>
<div class="ele-exception-content">
<h1>403</h1>
<p>抱歉, 你无权访问该页面</p>
<div>
<a href="#" onclick="event.preventDefault();" class="router-link-active">
<button
@click="$store.dispatch('pjaxRoute','/platform/home')"
type="button"
class="el-button el-button--primary el-button--medium"
>
<span>返回首页</span>
</button>
</a>
</div>
</div>
</div>
</div>
<script>
new Vue({
el: "#app",
store: store
})
</script>
<!--#}#-->
@@ -0,0 +1,31 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<div class="ele-exception">
<div class="ele-exception-img"><img alt="" src="/assets/platform/img/404.svg" style="width: 216px; height: 250px" /></div>
<div class="ele-exception-content">
<h1>403</h1>
<p>抱歉, 你访问的页面不存在</p>
<div>
<a href="#" onclick="event.preventDefault();" class="router-link-active">
<button
@click="$store.dispatch('pjaxRoute','/platform/home')"
type="button"
class="el-button el-button--primary el-button--medium"
>
<span>返回首页</span>
</button>
</a>
</div>
</div>
</div>
</div>
<script>
new Vue({
el: "#app",
store: store
})
</script>
<!--#}#-->
@@ -0,0 +1,31 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<div class="ele-exception">
<div class="ele-exception-img"><img alt="" src="/assets/platform/img/500.svg" style="width: 216px; height: 250px" /></div>
<div class="ele-exception-content">
<h1>403</h1>
<p>抱歉, 服务器出错了</p>
<div>
<a href="#" onclick="event.preventDefault();" class="router-link-active">
<button
@click="$store.dispatch('pjaxRoute','/platform/home')"
type="button"
class="el-button el-button--primary el-button--medium"
>
<span>返回首页</span>
</button>
</a>
</div>
</div>
</div>
</div>
<script>
new Vue({
el: "#app",
store: store
})
</script>
<!--#}#-->
@@ -0,0 +1,263 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<div class="btn-group tool-button mt5">
<el-button size="medium" @click="openAdd">
<i class="ti-plus"></i>
新建密钥
</el-button>
</div>
</el-card>
<el-card shadow="never">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%">
<el-table-column sortable prop="name" label="应用名称" header-align="center" align="center" width="120"></el-table-column>
<el-table-column prop="appid" label="App Id" header-align="center" width="160"></el-table-column>
<el-table-column prop="appkey" label="App Key" header-align="center" width="320">
<template slot-scope="scope">
<span v-if="isVisable(scope.row.appid)" class="bg-success">{{scope.row.appkey}}</span>
<a
v-if="!isVisable(scope.row.appid)"
@click="visiableData.push(scope.row.appid)"
style="padding-left: 5px; color: #06c; cursor: pointer"
>
显示
</a>
<a
v-if="isVisable(scope.row.appid)"
@click="setNotVisable(scope.row.appid)"
style="padding-left: 5px; color: #06c; cursor: pointer"
>
隐藏
</a>
</template>
</el-table-column>
<el-table-column sortable prop="createdAt" label="创建时间" header-align="center" align="center">
<template slot-scope="scope">{{formatAt(scope.row.createdAt)}}</template>
</el-table-column>
<el-table-column sortable prop="disabled" label="启用状态" header-align="center" align="center">
<template slot-scope="scope">
<i v-if="scope.row.disabled" class="fa fa-circle text-danger ml5"></i>
<i v-if="!scope.row.disabled" class="fa fa-circle text-success ml5"></i>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'enable',appid:scope.row.appid,name:scope.row.name,row:scope.row}">
启用
</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',appid:scope.row.appid,name:scope.row.name,row:scope.row}">
禁用
</el-dropdown-item>
<el-dropdown-item divided :command="{type:'delete',appid:scope.row.appid,name:scope.row.name}">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="新建密钥" :visible.sync="addDialogVisible" width="50%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="name" label="应用名称">
<el-input maxlength="100" placeholder="应用名称" v-model="formData.name" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
visiableData: [],
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
formData: {
id: ""
},
formRules: {
name: [{ required: true, message: "应用名称", trigger: "blur" }]
}
}
},
methods: {
isVisable: function (appid) {
if (this.visiableData.indexOf(appid) >= 0) {
return true
}
return false
},
setNotVisable: function (appid) {
var index = this.visiableData.indexOf(appid)
if (index >= 0) {
this.visiableData.splice(index, 1)
}
},
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/api/data",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
formatAt: function (val) {
if (val && val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
doSearch: function () {
this.pageForm.pageNumber = 1
this.pageData()
},
openAdd: function () {
var self = this
this.addDialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
doAdd: function () {
var self = this
self.$refs["addForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/api/addDo",
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.addDialogVisible = false
} else {
self.$message({
message: data.msg,
type: "error"
})
}
self.pageData() //添加失败也可以入库,所以加载一下看看
},
"json"
)
}
})
},
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("enable" == command.type || "disable" == command.type) {
$.post(
base + "/platform/sys/api/" + command.type + "/" + command.appid,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
if ("disable" == command.type) {
command.row.disabled = true
}
if ("enable" == command.type) {
command.row.disabled = false
}
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("delete" == command.type) {
self.$confirm("此操作将删除密钥 " + command.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/api/delete/" + command.appid,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.doSearch()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
}
},
created: function () {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,283 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<el-row type="flex" justify="end">
<el-button @click="openAdd" size="medium" type="primary">
<i class="ti-plus"></i>
添加配置项
</el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%">
<el-table-column header-align="center" label="参数名" prop="configKey" sortable width="200"></el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="参数值" prop="configValue" width="200"></el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="说明" prop="note"></el-table-column>
<el-table-column label="操作" prop="note" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'edit',id:scope.row.configKey}">修改</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',id:scope.row.configKey}" v-if="scope.row.configKey.indexOf('App')<0">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog title="新增参数" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="40%">
<el-form :model="formData" ref="addForm" :rules="formRules" label-width="80px">
<el-form-item prop="configKey" label="参数名">
<el-input maxlength="100" placeholder="参数名" v-model="formData.configKey" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="configValue" label="参数值">
<el-input maxlength="100" placeholder="参数值" v-model="formData.configValue" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="note" label="说 明">
<el-input type="textarea" v-model="formData.note"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="修改参数" :visible.sync="editDialogVisible" :close-on-click-modal="false" width="40%">
<el-form :model="formData" ref="editForm" :rules="formRules" label-width="80px">
<el-form-item prop="configKey" label="参数名">
<el-input
maxlength="100"
placeholder="参数名"
v-model="formData.configKey"
auto-complete="off"
tabindex="1"
type="text"
disabled
></el-input>
</el-form-item>
<el-form-item prop="configValue" label="参数值">
<div v-if="'true'===formData.configValue||'false'===formData.configValue">
<el-radio-group v-model="formData.configValue">
<el-radio label="true"></el-radio>
<el-radio label="false"></el-radio>
</el-radio-group>
</div>
<div v-else>
<el-input
maxlength="100"
placeholder="参数值"
v-model="formData.configValue"
auto-complete="off"
tabindex="2"
type="text"
></el-input>
</div>
</el-form-item>
<el-form-item prop="note" label="说 明">
<el-input type="textarea" v-model="formData.note"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
tableData: [],
pageForm: {
pageSize: 10,
pageNumber: 1,
pageOrderName: "",
pageOrderBy: "",
totalCount: 0
},
formData: {
configKey: "",
configValue: "",
note: ""
},
formRules: {
configKey: [{ required: true, message: "请输入参数名", trigger: "blur" }],
configValue: [{ required: true, message: "请输入参数值", trigger: "blur" }]
}
}
},
methods: {
openAdd: function () {
this.addDialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
},
doAdd: function () {
var self = this
var url = base + "/platform/sys/conf/addDo"
self.$refs["addForm"].validate(function (valid) {
if (valid) {
//表单验证通过
$.post(
url,
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.addDialogVisible = false
self.pageData() //重新加载分页数据
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
doEdit: function () {
var self = this
var url = base + "/platform/sys/conf/editDo"
self.$refs["editForm"].validate(function (valid) {
if (valid) {
$.post(
url,
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.editDialogVisible = false
self.pageData() //重新加载分页数据
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/conf/data",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("edit" == command.type) {
$.post(
base + "/platform/sys/conf/edit/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.formData = data.data //加载后台表单数据
self.editDialogVisible = true //打开编辑窗口
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("delete" == command.type) {
self.$confirm("此操作将删除 " + command.id, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/conf/delete/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.pageData()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
}
},
created: function () {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,19 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<file-upload upload_mode="drag"></file-upload>
</div>
<script>
new Vue({
el: "#app",
data() {
return {}
},
methods: {},
created() {}
})
</script>
<style scoped></style>
<!--# } #-->
@@ -0,0 +1,15 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak></div>
<script>
new Vue({
el: "#app"
})
</script>
<!--#
}
#-->
@@ -0,0 +1,184 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.pullTimeRadioGroup .el-radio {
width: 100%;
margin-bottom: 10px;
}
.pullTimeRadioGroup .el-radio.is-bordered + .el-radio.is-bordered{
margin-left: 0;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="拉取时间">
<el-select clearable v-model="pageForm.pullTime" placeholder="请选择拉取时间">
<el-option v-for="item in pullTimeOptions" :label="item.pullTime" :value="item.pullTime"></el-option>
</el-select>
</search-item>
<search-item label="姓名">
<el-input placeholder="请输入内容" clearable v-model="pageForm.userName" style="width: 100%"></el-input>
</search-item>
<search-item label="工号">
<el-input placeholder="请输入内容" clearable v-model="pageForm.loginName" style="width: 100%"></el-input>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitName" clearable filterable>
<el-option v-for="item in unitNameOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<el-select v-model="pageForm.userState" clearable filterable>
<el-option v-for="item in userStateOptions" :label="item" :value="item"></el-option>
</el-select>
</search-item>
<search-item label="用人方式">
<el-select v-model="pageForm.employmentType" clearable filterable>
<el-option v-for="item in employmentTypeOptions" :label="item" :value="item"></el-option>
</el-select>
</search-item>
<search-item label="教职工类别">
<el-select v-model="pageForm.staffType" clearable filterable>
<el-option v-for="item in staffTypeOptions" :label="item" :value="item"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool :label="pageForm.pullTime ? pageForm.pullTime + '数据' : '全部数据'">
<el-button type="primary" size="mini" @click="pull" icon="el-icon-download">拉取信息中心数据</el-button>
<el-button type="danger" size="mini" @click="openDelete" icon="el-icon-delete">删除本地数据源</el-button>
</table-tool>
<el-table :key="tableKey" :data="tableData" @sort-change="pageOrder" header-align="center">
<el-table-column type="index" width="70" label="序号" fixed="left"></el-table-column>
<el-table-column prop="pullTime" label="拉取时间" width="170" fixed="left"></el-table-column>
<el-table-column prop="loginname" label="工号" width="100" fixed="left"></el-table-column>
<el-table-column prop="username" label="姓名" fixed="left" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="sex" label="性别" sortable></el-table-column>
<el-table-column prop="mobile" label="手机号" width="120"></el-table-column>
<el-table-column prop="birthday" label="生日" sortable width="120"></el-table-column>
<el-table-column prop="userState" label="在职状态" sortable width="120"></el-table-column>
<el-table-column prop="employmentType" label="用人方式" sortable width="120"></el-table-column>
<el-table-column prop="staffType" label="教职工类别" sortable width="120"></el-table-column>
<el-table-column prop="comeSchoolDate" label="来校年月" sortable width="120"></el-table-column>
<el-table-column prop="technicalTitle" label="技术职称" sortable width="120"></el-table-column>
<el-table-column prop="position" label="干部职务" sortable width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="education" label="学历" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="academicDegree" label="学位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitName" label="单位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitId" label="单位编码" sortable width="120"></el-table-column>
<el-table-column prop="nationality" label="国籍" sortable></el-table-column>
<el-table-column prop="nation" label="民族" sortable></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="选择数据源" :visible.sync="pullTimeDialogVisible" width="30%">
<el-radio-group v-model="sourceTime" style="width: 100%" class="pullTimeRadioGroup">
<el-radio :label="item.pullTime" border v-for="item in pullTimeOptions" :key="item.pullTime">
<span>
{{item.pullTime}}
<span style="float: right; color: red">rows:{{item.num}}</span>
</span>
</el-radio>
</el-radio-group>
<span slot="footer" class="dialog-footer">
<el-button @click="pullTimeDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doDeleteUser">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
unitNameOptions: [],
userStateOptions: [],
employmentTypeOptions:[],
staffTypeOptions: [],
pullTimeOptions: false,
sourceTime: null,
pullTimeDialogVisible: false
}
},
methods: {
pull() {
this.$confirm("确定要拉取数据源吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
})
.then(() => {
this.$axios.post("/platform/sys/data/user/pull/pullData").then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
}
})
})
.catch(() => {})
},
getSearchOptions() {
this.$axios.post("/platform/sys/data/user/pull/searchOptions").then((resp) => {
if (resp.code === 0) {
this.unitNameOptions = resp.data.unitNames
this.userStateOptions = resp.data.userStates
this.staffTypeOptions = resp.data.staffTypes
this.employmentTypeOptions = resp.data.employmentTypes
}
})
},
getPullTimeOptions() {
this.$axios.post("/platform/sys/data/user/pull/pullTimeOptions").then((resp) => {
if (resp.code === 0) {
this.pullTimeOptions = resp.data
}
})
},
openDelete() {
this.pullTimeDialogVisible = true
this.getPullTimeOptions()
},
doDeleteUser() {
this.$confirm("确定要删除数据源吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios
.post("/platform/sys/data/user/pull/deleteByPullTime", {
pullTime: this.sourceTime
})
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pullTimeDialogVisible = false
this.doSearch()
}
})
})
}
},
created() {
this.pageData()
this.getSearchOptions()
this.getPullTimeOptions()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,215 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.pullTimeRadioGroup .el-radio {
width: 100%;
margin-bottom: 10px;
}
.pullTimeRadioGroup .el-radio.is-bordered + .el-radio.is-bordered{
margin-left: 0;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名">
<el-input placeholder="请输入内容" clearable v-model="pageForm.userName" style="width: 100%"></el-input>
</search-item>
<search-item label="工号">
<el-input placeholder="请输入内容" clearable v-model="pageForm.loginName" style="width: 100%"></el-input>
</search-item>
<search-item label="所属单位">
<el-select v-model="pageForm.unitId" clearable style="width: 100%">
<el-option v-for="i in unitOptions" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</search-item>
<search-item label="在职状态">
<dict-select v-model="pageForm.userState" code="USER_STATE" style="width: 100%"></dict-select>
</search-item>
<search-item label="人事编制">
<dict-select v-model="pageForm.preparedBy" code="PREPARED_BY" style="width: 100%"></dict-select>
</search-item>
<search-item label="人员类型">
<dict-select v-model="pageForm.personType" code="PERSON_TYPE" style="width: 100%"></dict-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="系统当前用户数据">
<el-button type="primary" size="mini" @click="openUpdate" icon="el-icon-refresh">更新</el-button>
</table-tool>
<el-table :key="tableKey" :data="tableData" @sort-change="pageOrder" header-align="center">
<el-table-column type="index" width="70" label="序号" fixed="left"></el-table-column>
<el-table-column prop="loginname" label="工号" width="100" fixed="left"></el-table-column>
<el-table-column prop="username" label="姓名" fixed="left" width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="changeTypes" label="变更类型" width="140">
<template slot-scope="{row}">
<span style="color: #0e78c5;cursor: pointer" @click="openCurrentUserChangeInfo(row)">
{{getChangeTypes(row.changeTypes)}}
</span>
</template>
</el-table-column>
<el-table-column prop="changeTime" label="变更时间" sortable width="150"></el-table-column>
<el-table-column prop="sex" label="性别" sortable></el-table-column>
<el-table-column prop="mobile" label="手机号" width="120"></el-table-column>
<el-table-column prop="birthday" label="生日" sortable width="120"></el-table-column>
<el-table-column prop="userState" label="在职状态" sortable width="120"></el-table-column>
<el-table-column prop="preparedBy" label="人事编制" sortable width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" sortable width="120"></el-table-column>
<el-table-column prop="comeSchoolDate" label="来校年月" sortable width="120"></el-table-column>
<el-table-column prop="technicalTitle" label="技术职称" sortable width="120"></el-table-column>
<el-table-column prop="governmentPosition" label="党政职务" sortable width="120" show-overflow-tooltip></el-table-column>
<el-table-column prop="education" label="学历" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="academicDegree" label="学位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitName" label="单位" show-overflow-tooltip sortable width="120"></el-table-column>
<el-table-column prop="unitId" label="单位编码" sortable width="120"></el-table-column>
<el-table-column prop="nationality" label="国籍" sortable></el-table-column>
<el-table-column prop="nation" label="民族" sortable></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<member-audit-change-info ref="memberAuditChangeInfoRef" is_default_url></member-audit-change-info>
</template>
</guava>
<el-dialog title="选择数据源" :visible.sync="updateDialog" width="50%">
<el-timeline>
<el-timeline-item timestamp="数据源" placement="top">
<el-radio-group v-model="updateFromData.pullTime" style="width: 100%" class="pullTimeRadioGroup">
<el-radio :label="item.pullTime" border v-for="item in pullTimeOptions" :key="item.pullTime">
<span>
{{item.pullTime}}
<span style="float: right; color: red">rows:{{item.num}}</span>
</span>
</el-radio>
</el-radio-group>
</el-timeline-item>
<el-timeline-item timestamp="更新方式" placement="top">
<el-radio-group class="checkGroup" style="width: 100%" v-model="updateFromData.updateMode">
<el-row>
<el-radio border label="ALL">全部更新</el-radio>
<el-radio border label="INCR">仅更新新增人员</el-radio>
</el-row>
</el-radio-group>
</el-timeline-item>
</el-timeline>
<span slot="footer" class="dialog-footer" v-loading="updateLoading">
<el-button @click="updateDialog = false" :disabled="updateLoading">取 消</el-button>
<el-button type="primary" @click="execUpdate" :disabled="updateLoading">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
<!--#include("../../../zhgh/staffmanage/member/common/audit/memberAuditChangeInfo.js"){}#-->
new Vue({
el: "#app",
dicts: ["MEMBER_CHANGE_TYPE"],
mixins: [initTableMixins],
data() {
return {
updateDialog: false,
pullTimeOptions: false,
updateFromData: {
pullTime: null,
updateMode: "all"
},
updateLoading: false,
unitOptions: [],
changeTypeData: [],
}
},
components: {
'member-audit-change-info':MEMBER_AUDIT_CHANGE_INFO
},
methods: {
openCurrentUserChangeInfo(row) {
this.$refs.guava.view(() => {
this.$refs.memberAuditChangeInfoRef.onOpen({userId: row.id, recordId:row.userHistoryId})
})
},
getChangeTypes(changeTypes) {
if (changeTypes) {
const c = JSON.parse(changeTypes)
return c
.map((v) => {
return this.changeTypeData.find((item) => item.code === v).name
})
.join(",")
}
return null
},
openUpdate() {
this.updateDialog = true
this.updateLoading = false
this.$nextTick(() => {
this.updateFromData = {
updateMode: null,
pullTime: null
}
})
},
getPullTimeOptions() {
this.$axios.post("/platform/sys/data/user/update/pullTimeOptions").then((resp) => {
if (resp.code === 0) {
this.pullTimeOptions = resp.data
}
})
},
execUpdate() {
if (!this.updateFromData.pullTime) {
this.$message.warning("请选择数据源时间")
return
}
if (!this.updateFromData.updateMode) {
this.$message.warning("请选择更新方式")
return
}
this.$confirm("确定要更新数据吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.updateLoading = true
this.$axios.post("/platform/sys/data/user/update/updateUserFormSource", this.updateFromData).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.updateDialog = false
}
})
})
.finally(() => {
this.updateLoading = false
})
},
listUnit() {
this.$businessTool.listUnit(this.pageForm.unionId).then((res) => {
this.unitOptions = res
})
}
},
created() {
this.listUnit()
this.getPullTimeOptions()
this.pageData()
this.$businessTool.getAllDictOptions("MEMBER_CHANGE_TYPE").then(data => {
this.changeTypeData = data
})
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,472 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-row type="flex" justify="space-between">
<el-button size="medium" @click="openAdd">
<i class="ti-plus"></i>
新建字典
</el-button>
<el-button size="medium" @click="openSort">排序</el-button>
</el-row>
</el-card>
<el-card shadow="never">
<el-table
:key="tableKey"
:data="tableData"
style="width: 100%"
:highlight-current-row="true"
row-key="id"
lazy
:expand-row-keys="expandedRowKeysRenew"
@expand-change="handleExpandChange"
:load="loadChild"
>
<el-table-column
label="字典名称"
header-align="center"
prop="name"
width="200"
:show-overflow-tooltip="true"
align="left"
></el-table-column>
<el-table-column label="字典代码" header-align="center" prop="code" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="启用状态" header-align="center" prop="disabled" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<i v-if="scope.row.disabled" class="fa fa-circle text-danger ml5"></i>
<i v-if="!scope.row.disabled" class="fa fa-circle text-success ml5"></i>
</template>
</el-table-column>
<el-table-column label="操作" header-align="center" prop="website" :show-overflow-tooltip="true" align="center" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'add',id:scope.row.id,name:scope.row.name}">添加子级</el-dropdown-item>
<el-dropdown-item divided :command="{type:'enable',id:scope.row.id,name:scope.row.name,row:scope.row}">
启用
</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,name:scope.row.name,row:scope.row}">禁用</el-dropdown-item>
<el-dropdown-item divided :command="{type:'edit',id:scope.row.id,name:scope.row.name}">修改</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',id:scope.row.id,name:scope.row.name}">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="新建字典" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="parentId" label="上级字典" label-width="80px">
<el-cascader
v-if="!isAddFromSub"
:props="props"
:options="menuOptions"
v-model="parentMenu"
placeholder="不选择则为顶级"
style="width: 100%"
></el-cascader>
<el-input v-if="isAddFromSub" type="text" v-model="formData.parentName" :disabled="true"></el-input>
</el-form-item>
<el-form-item prop="name" label="字典名称">
<el-input maxlength="100" placeholder="字典名称" v-model="formData.name" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<el-form-item prop="code" label="字典代码">
<el-input maxlength="100" placeholder="字典代码" v-model="formData.code" auto-complete="off" tabindex="5" type="text"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="修改字典" :visible.sync="editDialogVisible" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="editForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="name" label="字典名称">
<el-input maxlength="100" placeholder="字典名称" v-model="formData.name" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="code" label="字典代码">
<el-input maxlength="100" placeholder="字典代码" v-model="formData.code" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="字典排序" :visible.sync="sortDialogVisible" width="50%">
<el-tree ref="sortMenuTree" :data="sortMenuData" draggable :allow-drop="sortAllowDrop" node-key="id" :props="defaultProps">
<span class="custom-tree-node" slot-scope="scope">
<span>{{ scope.node.label }}</span>
</span>
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="sortDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSort">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
sortDialogVisible: false,
isAddFromSub: false,
tableData: [], //后台取出的数据
tableKey: "",
formData: {
id: "",
parentId: "",
parentName: "",
type: "menu",
target: "data-pjax",
children: "false"
},
formRules: {
name: [{ required: true, message: "字典名称", trigger: "blur" }],
code: [{ required: true, message: "字典代码", trigger: ["blur", "change"] }]
},
menuOptions: [],
props: {
lazy: true,
checkStrictly: true,
multiple: false,
lazyLoad: function (node, resolve) {
var url = base + "/platform/sys/dict/tree"
$.post(
url,
{ pid: node.value },
function (data) {
if (data.code == 0) {
resolve(data.data)
}
},
"json"
)
}
},
parentMenu: [],
sortMenuData: [],
defaultProps: {
children: "children",
label: "label"
},
// 保存展开状态的数组
expandedRowKeysRenew: [],
tableTreeRefreshTool: {}
}
},
methods: {
//排序树加载
sortMenuLoad: function () {
var self = this
$.post(
base + "/platform/sys/dict/menuAll",
{},
function (data) {
if (data.code == 0) {
self.sortMenuData = data.data
}
},
"json"
)
},
//排序树控制不可跨级拖拽
sortAllowDrop: function (moveNode, inNode, type) {
if (moveNode.data.parentId == inNode.data.parentId) {
return type == "prev"
}
},
//打开排序功能
openSort: function () {
this.sortDialogVisible = true
this.sortMenuLoad()
},
//递归获取所有的ID值
getTreeIds: function (ids, data) {
var self = this
data.forEach(function (obj) {
ids.push(obj.id)
if (obj.children && obj.children.length > 0) {
self.getTreeIds(ids, obj.children)
}
})
},
//提交排序后的数据
doSort: function () {
var self = this
var ids = []
self.getTreeIds(ids, self.sortMenuData)
$.post(
base + "/platform/sys/dict/sortDo",
{ ids: ids.toString() },
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.sortDialogVisible = false
self.initTreeTable()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
openAdd: function () {
var self = this
self.isAddFromSub = false
self.addDialogVisible = true
self.parentMenu = []
self.menuOptions = []
//表单还原为初始值
self.formData = {
id: "",
parentId: "",
parentName: "",
type: "menu",
target: "data-pjax",
children: "false"
}
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
doAdd: function () {
var self = this
var url = base + "/platform/sys/dict/addDo"
self.$refs["addForm"].validate(function (valid) {
if (valid) {
//表单验证通过
if (!self.isAddFromSub) {
//如果不是添加子菜单,则从级联选择框取父节点ID
self.formData.parentId = self.parentMenu[self.parentMenu.length - 1] || ""
}
$.post(
url,
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.addDialogVisible = false
self.loadChildByExpandedKeys()
// self.initTreeTable();
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
doEdit: function () {
var self = this
var url = base + "/platform/sys/dict/editDo"
self.$refs["editForm"].validate(function (valid) {
if (valid) {
//表单验证通过
$.post(
url,
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.editDialogVisible = false
self.loadChildByExpandedKeys()
// self.initTreeTable()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
initTreeTable: function () {
var self = this
var url = base + "/platform/sys/dict/child"
$.post(
url,
{ pid: "" },
function (data) {
if (data.code == 0) {
self.tableData = data.data
self.tableKey = +new Date()
}
},
"json"
)
},
loadChild: function (tree, treeNode, resolve) {
// 在之前声明的全局变量中,增加一个key为 本条数据的id,id可替换为你数据中的任意唯一值
this.tableTreeRefreshTool[tree.id] = {}
// 重要!保存resolve方法,以便后续使用
this.tableTreeRefreshTool[tree.id].resolve = resolve
// 记录展开次数,具体作用后续介绍
this.tableTreeRefreshTool[tree.id].expandCount = 0
var url = base + "/platform/sys/dict/child"
$.post(
url,
{ pid: tree.id },
function (data) {
if (data.code == 0) {
resolve(data.data)
}
},
"json"
)
},
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("add" == command.type) {
self.openAdd()
self.formData.parentId = command.id
self.formData.parentName = command.name
self.isAddFromSub = true
}
if ("edit" == command.type) {
$.post(
base + "/platform/sys/dict/edit/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.formData = data.data //加载后台表单数据
self.editDialogVisible = true //打开编辑窗口
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("enable" == command.type || "disable" == command.type) {
$.post(
base + "/platform/sys/dict/" + command.type + "/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
if ("disable" == command.type) {
command.row.disabled = true
}
if ("enable" == command.type) {
command.row.disabled = false
}
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("delete" == command.type) {
self.$confirm("此操作将删除 " + command.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/dict/delete/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.loadChildByExpandedKeys()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
},
handleExpandChange(row, expanded) {
if ((row.parentId === "" || row.parentId == null) && !expanded) {
this.expandedRowKeysRenew = []
return
}
if (expanded) {
this.expandedRowKeysRenew.push(row.id)
} else {
const index = this.expandedRowKeysRenew.findIndex((v) => v === row.id)
this.expandedRowKeysRenew.splice(index, 1)
}
},
loadChildByExpandedKeys() {
if (this.expandedRowKeysRenew && this.expandedRowKeysRenew.length > 0) {
this.expandedRowKeysRenew.forEach((v) => {
const curr = this.tableTreeRefreshTool[v]
// api请求
$.get("/platform/sys/dict/child", { pid: v }).then((res) => {
curr.resolve(res.data)
})
})
} else {
this.initTreeTable()
}
}
},
created: function () {
this.initTreeTable()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,126 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.record-img {
width: 40px;
height: 40px;
vertical-align: middle;
border-style: none;
overflow-clip-margin: content-box;
overflow: clip;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="文件名称" prop="name">
<el-input v-model="pageForm.name" placeholder="请输入文件名称" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="mini" type="primary" @click="openUploadFile">上传文件</el-button>
</table-tool>
<el-table :data="tableData" header-align="center" border style="width: 100%">
<el-table-column label="文件名称" prop="name"></el-table-column>
<el-table-column label="缩略图" prop="thumbnail" width="100px">
<template scope="{row}">
<el-image
v-if="row.suffix === 'jpg' || row.suffix === 'png' || row.suffix === 'row' || row.suffix === 'gif'"
:src="row.thumbnail"
:fit="'cover'"
:style="{ width: '50px', height: '50px' }"
></el-image>
<el-image
v-else
:src="$commonUtil.getFileItemShowIcon(row.suffix)"
:fit="'cover'"
:style="{ width: '50px', height: '50px' }"
></el-image>
</template>
</el-table-column>
<el-table-column label="文件大小" prop="sizeInfo" width="100px"></el-table-column>
<el-table-column label="文件后缀" prop="suffix" width="100px"></el-table-column>
<el-table-column label="储存引擎" prop="engine" width="100px"></el-table-column>
<el-table-column label="操作" width="400px">
<template slot-scope="scope">
<el-button size="mini" type="primary" @click="$commonUtil.previewFile(scope.row)">预览</el-button>
<el-button size="mini" type="primary" @click="openDetailFile(scope.row)">详情</el-button>
<el-button size="mini" type="primary" @click="$downLoad(scope.row.downloadPath)">下载</el-button>
<el-button size="mini" type="danger" @click="deleteFile(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="上传文件" width="50%" :visible.sync="uploadFileDialogVisible">
<el-form :model="formData" ref="form">
<el-form-item label="文件" :rules="[{ required: true, message: '请上传文件', trigger: ['blur','change'] }]">
<file-upload :value.sync="formData.files" :upload_number="1" upload_result_category="interval" complete_result></file-upload>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog title="文件详情" :visible.sync="detailFileDialogVisible" width="50%">
<el-descriptions :column="3" border>
<el-descriptions-item label="文件名称" :span="3">{{viewData.name}}</el-descriptions-item>
<el-descriptions-item label="文件大小" :span="3">{{viewData.sizeInfo}}</el-descriptions-item>
<el-descriptions-item label="文件后缀" :span="3">{{viewData.suffix}}</el-descriptions-item>
<el-descriptions-item label="储存引擎" :span="3">{{viewData.bucket}}</el-descriptions-item>
<el-descriptions-item label="储存路径" :span="3">{{viewData.storagePath}}</el-descriptions-item>
<el-descriptions-item label="下载地址" :span="3">{{viewData.downloadPath}}</el-descriptions-item>
</el-descriptions>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
tableData: [],
uploadFileDialogVisible: false,
formData: {},
detailFileDialogVisible: false,
viewData: {}
}
},
methods: {
deleteFile(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
$.post("/platform/sys/file/delete", {
ids: JSON.stringify([id])
}).then((res) => {
this.$message.success(res.msg)
this.doSearch()
})
})
},
openUploadFile() {
this.uploadFileDialogVisible = true
this.formData = {}
},
openDetailFile(row) {
console.log(row)
this.detailFileDialogVisible = true
this.viewData = { ...row }
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,525 @@
<!doctype html>
<html lang="${lang,escape}">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<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/plugins/element-ui/lib/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
</head>
<body>
<!--[if lt IE 9]>
<div class="ie-must-go-die">
<div class="ie-container">
<h1>您正在IE的世界中</h1>
<p>本系统不支持IE9以下版本浏览器访问。</p>
<a href="https://browsehappy.com" target="_blank">您可以点击此处,下载Chrome/Firefox后再次访问本页面。</a>
</div>
</div>
<![endif]-->
<div id="app" v-cloak>
<div class="login-container">
<div class="login-border">
<el-row type="flex">
<el-col :span="12" class="login-left">
<img src="${base!}/assets/platform/img/banner.png" style="height: 485px" />
</el-col>
<el-col>
<div class="login-main">
<h4 class="title">${AppName!}系统登录</h4>
<el-tabs v-model="activeName" style="max-height: 275px">
<el-tab-pane label="用户登录" name="signin">
<span slot="label">
<i slot="prefix" class>
<i class="el-icon-user"></i>
</i>
用户登录
</span>
<el-form
ref="loginForm"
:model="loginForm"
:rules="loginRules"
class="login-form"
auto-complete="on"
label-position="left"
>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
placeholder="账号或手机号码"
prefix-icon="el-icon-user"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="密码"
@keyup.enter.native="handleLogin"
prefix-icon="el-icon-lock"
></el-input>
</el-form-item>
<el-form-item prop="platformCaptcha">
<el-input
v-model="loginForm.platformCaptcha"
auto-complete="off"
placeholder="验证码"
style="width: 60%"
@keyup.enter.native="handleLogin"
prefix-icon="el-icon-key"
></el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" />
</div>
</el-form-item>
<el-form-item style="width: 100%">
<el-button
:loading="loading"
size="medium"
type="primary"
style="width: 100%"
@click.native.prevent="handleLogin"
>
<span v-if="!loading">登 录</span>
<span v-else>登 录 中...</span>
</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="用户注册" name="signup">
<span slot="label">
<i slot="prefix" class>
<i class="el-icon-mobile-phone"></i>
</i>
用户注册
</span>
<el-form ref="regForm" class="login-form" status-icon :rules="regRules" :model="regForm"
label-width="0">
<el-form-item prop="mobile">
<el-input
v-model="regForm.mobile"
auto-complete="off"
placeholder="请输入手机号码"
@keyup.enter.native="handleReg"
prefix-icon="el-icon-mobile-phone"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="regForm.password"
:type="passwordType"
auto-complete="off"
placeholder="请输入账号密码"
@keyup.enter.native="handleReg"
prefix-icon="el-icon-lock"
>
<i class="ti-eye" slot="suffix" @click="showPwd"></i>
</el-input>
</el-form-item>
<el-form-item prop="code">
<el-input
v-model="regForm.code"
auto-complete="off"
placeholder="请输入验证码"
@keyup.enter.native="handleSend"
prefix-icon="el-icon-key"
>
<template slot="append">
<span
style="cursor: pointer"
class="msg-text"
:class="[{ display: msgKey }]"
@click="handleSend"
>
{{ msgText }}
</span>
</template>
</el-input>
</el-form-item>
<el-form-item>
<el-button size="medium" type="primary" style="width: 100%"
@click.native.prevent="handleReg">
<span v-if="!regLoading">注 册</span>
<span v-else>注 册 中...</span>
</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<div class="third-login">
<el-divider>第三方登录</el-divider>
<div class="third-way">
<span class="third-icon" @click="handleSocial()">
<img src="/assets/platform/img/svg/github.svg"
style="width: 32px; height: 32px" />
</span>
<span class="third-icon" @click="handleSocial()">
<img src="/assets/platform/img/svg/wechat.svg"
style="width: 32px; height: 32px" />
</span>
<span class="third-icon" @click="handleSocial()">
<img src="/assets/platform/img/svg/qq.svg"
style="width: 32px; height: 32px" />
</span>
<span class="third-icon" @click="handleSocial()">
<img src="/assets/platform/img/svg/alipay.svg"
style="width: 32px; height: 32px" />
</span>
</div>
</div>
</div>
</el-col>
</el-row>
</div>
<div id="el-login-footer" class="login-footer">
<span>
<a href="https://BudWk.com" target="_blank">BudWk.com</a>
©
<span>{{year}}</span>
</span>
<span></span>
<a href="https://beian.miit.gov.cn"
target="_blank">${@config.getString("DomainBeian","皖ICP备15001937号-3")}</a>
</div>
</div>
</div>
</body>
<!-- import Vue before Element -->
<!--<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>-->
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.js"></script>
<!-- import JavaScript -->
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<script>
var MSGINIT = "发送验证码"
var MSGSCUCCESS = "{time}秒后重发"
var MSGTIME = 60
function isPhone(str) {
var reg = /^1[3456789]\d{9}$/
return reg.test(str)
}
new Vue({
el: "#app",
data: function() {
var validateCode = function(rule, value, callback) {
if (value.length !== 4) {
callback(new Error("请输入4位数的验证码"))
} else {
callback()
}
}
return {
activeName: "signin",
msgText: MSGINIT,
msgTime: MSGTIME,
msgKey: false,
year: 2018,
captchaVisible: false,
codeUrl: "",
loginForm: {
username: "",
password: "",
platformKey: "",
grantType: "captcha"
},
loginRules: {
username: [{ required: true, trigger: ["blur", "change"], message: "用户名不能为空" }],
password: [{ required: true, trigger: ["blur", "change"], message: "密码不能为空" }],
platformCaptcha: [{ required: true, trigger: ["blur", "change"], message: "验证码不能为空" }]
},
regForm: {
mobile: "",
password: "",
code: ""
},
regRules: {
mobile: [
{ required: true, message: "请输入手机号码", trigger: ["blur", "change"] },
{ pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号码" }
],
password: [
{ required: true, message: "请输入密码", trigger: ["blur", "change"] },
{ min: 8, max: 20, message: "密码长度必须是8-20位", trigger: "change" }
],
code: [{ required: true, trigger: ["blur", "change"], validator: validateCode }]
},
passwordType: "password",
loading: false,
regLoading: false,
showDialog: false
}
},
methods: {
getCode: function() {
var _self = this
$.get(
"${base!}/platform/login/captcha",
function(d) {
_self.codeUrl = d.data.codeUrl
_self.loginForm.platformKey = d.data.key
},
"json"
)
},
showPwd: function() {
if (this.passwordType === "password") {
this.passwordType = ""
} else {
this.passwordType = "password"
}
},
handleSend: function() {
var _self = this
if (!isPhone(_self.regForm.mobile)) {
_self.$message({
message: "请输入手机号码",
type: "error"
})
return false
}
if (_self.msgKey) return
$.get(
"${base!}/platform/login/sendsms?mobile=" + _self.regForm.mobile,
function(d) {
if (d.code === 0) {
_self.$message({
message: "短信发送成功,请注意查收!(实际没发送)",
type: "success",
duration: 8000
})
_self.msgText = MSGSCUCCESS.replace("{time}", _self.msgTime)
_self.msgKey = true
var time = setInterval(() => {
_self.msgTime--
_self.msgText = MSGSCUCCESS.replace("{time}", _self.msgTime)
if (_self.msgTime === 0) {
_self.msgTime = MSGTIME
_self.msgText = MSGINIT
_self.msgKey = false
clearInterval(time)
}
}, 1000)
} else {
_self.$message({
message: d.msg,
type: "error"
})
}
},
"json"
)
},
handleLogin: function() {
var _self = this
_self.$refs["loginForm"].validate(function(valid) {
if (valid) {
$.post(
"${base!}/platform/login/doLogin",
_self.loginForm,
function(d) {
if (d.code == 0) {
window.location.href = "${base!}/platform/home"
} else {
_self.$message({
message: d.msg,
type: "error"
})
_self.getCode()
}
},
"json"
)
}
})
},
handleReg: function() {
var _self = this
_self.$refs["regForm"].validate(function(valid) {
if (valid) {
_self.regLoading = true
$.post(
"${base!}/platform/login/doReg",
_self.regForm,
function(d) {
if (d.code == 0) {
_self.$message({
message: "注册成功,请登录!",
type: "success",
duration: 5000
})
_self.activeName = "signin"
_self.$set(_self.loginForm, "username", _self.regForm.mobile)
_self.$refs["regForm"].resetFields()
} else {
_self.$message({
message: d.msg,
type: "error"
})
}
_self.regLoading = false
},
"json"
)
}
})
},
handleSocial: function(type) {
this.$message.error("敬请期待")
},
errorMsg: function() {
var errorMsg = "${error_message!}"
if (errorMsg) {
this.$message({
message: errorMsg,
type: "error"
})
}
}
},
created: function() {
this.year = new Date().getFullYear()
this.getCode()
this.errorMsg()
}
})
</script>
<style scoped>
#app {
height: 100%;
}
html body {
position: relative;
height: 100vh;
padding: 0;
margin: 0;
font-family: Avenir, Helvetica, Arial, sans-serif;
font-size: 14px;
color: #2c3e50;
background: #f6f8f9;
-webkit-font-smoothing: antialiased;
}
.login-container {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-image: url(${base!}/assets/platform/img/svg/background.svg);
background-color: #f0f2f5;
}
@media screen and (max-width: 768px) {
.login-left {
display: none;
}
}
a {
color: #1890ff;
text-decoration: none;
cursor: pointer;
}
.login-main {
width: 323px;
height: 455px;
padding: 25px 25px 5px 25px;
background: #ffffff;
}
.title {
margin: 10px auto 40px auto;
font-size: 20px;
font-weight: 700;
color: rgba(0, 0, 0, 0.85);
text-align: center;
}
.login-form .el-input {
height: 38px;
}
.login-form input {
height: 38px;
}
.login-form .input-icon {
width: 14px;
height: 39px;
margin-left: 2px;
}
.login-tip {
font-size: 13px;
color: #bfbfbf;
text-align: center;
}
.login-code {
display: inline-block;
float: right;
width: 38%;
height: 38px;
}
.login-code img {
vertical-align: middle;
cursor: pointer;
}
.login-footer {
position: fixed;
bottom: 1rem;
width: 100%;
height: 1rem;
font-size: 0.9rem;
font-weight: 600;
line-height: 1rem;
color: #2c3e50;
text-align: center;
}
.tips {
margin-bottom: 10px;
font-size: 14px;
color: #fff;
}
.third-login {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 10px 0 30px 0;
vertical-align: middle;
}
.third-login .third-icon {
margin: 0 20px;
cursor: pointer;
fill: rgba(0, 0, 0, 0.2);
}
.third-way {
display: flex;
justify-content: center;
width: 323px;
}
.third-icon:hover {
fill: rebeccapurple;
}
</style>
</html>
@@ -0,0 +1,178 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>上传文件</title>
<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" />
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<link rel="stylesheet" href="${base!}/assets/platform/plugins/vant/index.css" />
<script src="${base!}/assets/platform/plugins/vant/index.js"></script>
<style>
:root {
--color-primary: #1867b0;
--color-background: #f3f4f6;
--color-text: #333;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: var(--color-background);
color: var(--color-text);
}
#app {
padding: 20px;
max-width: 600px;
margin: auto;
background: white;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
h1 {
text-align: center;
color: var(--color-primary);
}
.upload-button {
margin-top: 20px;
text-align: center;
}
.van-uploader__tip {
color: var(--color-primary);
font-size: 14px;
}
.van-button {
background-color: var(--color-primary);
color: white;
border-radius: 4px;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<h1>文件上传</h1>
<van-uploader
v-model="fileList"
:before-read="beforeRead"
:after-read="afterRead"
multiple
:accept="accept"
async
:max-count="upload_number"
title="选择文件"
description=""
tip=""
></van-uploader>
<div class="upload-button">
<van-button block type="primary" @click="onSubmit">同步到电脑</van-button>
</div>
</div>
</body>
<script>
new Vue({
el: "#app",
data() {
return {
fileList: [
// { url: "http://localhost:8080/platform/sys/file/download?id=rn1v1efh2ag0aps59ult3ebudf", isImage: true }
],
// accept: "image/*",
accept: "*",
upload_number: 9
}
},
methods: {
beforeRead(file) {
return true
},
afterRead(file) {},
buildUploadPromises(file) {
return
},
onSubmit() {
const loading = this.$toast({
duration: 0,
overlay: true,
forbidClick: true,
message: "上传中",
loadingType: "circular"
})
Promise.all(
this.fileList.map((f) => {
const formData = new FormData()
formData.append("file", f.file)
return axios.post("/platform/sys/h5ScanCodeUploadFile/upload", formData).then((axiosResp) => {
const resp = axiosResp.data
if (resp.code === 0) {
console.log(resp)
f.name = f.file.name
f.size = f.file.size
f.status = null
f.url = resp.data
f.response = resp
f.percentage = 100
f.isImage = true
delete f.file
delete f.content
console.log(f)
} else {
f.status = "fail"
}
})
})
)
.then(() => {
loading.close()
console.log(this.fileList)
this.syncPc()
})
.catch((error) => {
loading.close()
this.$toast.fail(error)
})
},
syncPc() {
if(this.fileList.length===0){
this.$toast('请先选择文件')
return
}
console.log(this.fileList)
axios
.post(
"/platform/sys/h5ScanCodeUploadFile/syncPc",
{
files: JSON.stringify(this.fileList)
},
{
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
}
}
)
.then((resp) => {
if (resp.data.code === 0) {
this.$toast.success("上传成功,请关注电脑端信息")
} else {
this.$toast.fail(resp.data.msg)
}
})
}
}
})
</script>
</html>
@@ -0,0 +1,310 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.home .card-title {
font-size: 16px;
font-weight: 600;
font-family: cursive;
}
.quickEntries {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 10px;
max-height: 210px;
}
.quickEntries .quickEntryItem img {
max-width: 50px;
}
.quickEntries .quickEntryItem {
max-height: 210px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 10px;
transition:
transform 0.3s ease-in-out,
box-shadow 0.3s ease-in-out;
}
.quickEntries .quickEntryItem span {
margin-top: auto;
}
.quickEntries .quickEntryItem:hover {
cursor: pointer;
background: #f3f3f3;
border-radius: 10px;
}
.quickEntries .quickEntryItem:hover {
animation: shake 0.3s;
}
@keyframes shake {
0% {
transform: translateX(0);
}
25% {
transform: translateX(-5px);
}
50% {
transform: translateX(5px);
}
75% {
transform: translateX(-5px);
}
100% {
transform: translateX(0);
}
}
.top-container {
background: #fff;
padding: 20px 10px;
display: grid;
grid-template-columns: 72px 3fr 1fr 1fr;
grid-column-gap: 20px;
align-items: center;
}
.top-container .avatar-wrapper {
width: 72px;
height: 72px;
line-height: 72px;
font-size: 18px;
}
.top-container .avatar-wrapper img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.top-container .basic-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
}
.top-container .basic-wrapper .welcome {
margin-top: 0;
margin-bottom: 0.5em;
color: rgba(0, 0, 0, 0.8509803921568627);
font-weight: 500;
font-size: 14px;
line-height: 1.75rem;
}
.top-container .basic-wrapper .text-secondary {
color: rgba(0, 0, 0, 0.45098039215686275);
}
.top-container .date-wrap {
padding-right: 10px;
text-align: right;
}
.top-container .date-wrap .date {
color: rgba(0, 0, 0, 0.8509803921568627);
font-weight: 500;
font-size: 14px;
line-height: 1.75rem;
margin-bottom: 0.5rem;
}
.activity_list {
width: calc(100% - 300px);
max-width: calc(100% - 300px);
padding: 15px 0;
}
.wrap {
display: flex;
column-gap: 20px;
}
@media only screen and (max-width: 767px) {
.wrap {
flex-direction: column;
}
.wrap .activity_list {
width: 100%;
max-width: 100%;
}
}
.el-calendar {
width: 300px;
}
.el-calendar .el-calendar__header {
padding: 10px 0;
}
.el-calendar__body {
padding: 0 !important;
}
.el-divider {
margin: 0;
}
.el-timeline {
padding: 0;
}
.el-calendar-table td {
border: none !important;
}
.el-calendar-table td.is-selected {
border-radius: 9999px;
background-color: unset !important;
}
.el-calendar-table .el-calendar-day {
width: 30px;
height: 30px;
padding: 2px;
text-align: center;
}
.el-calendar-table .el-calendar-day:hover {
border-radius: 9999px;
}
.tips {
color: red;
font-weight: bold;
}
.el-timeline-item__content {
cursor: pointer;
}
.el-timeline-item__content:hover {
color: #1890ff;
}
</style>
<div id="app" v-cloak>
<div class="padding10X">
<div class="top-container">
<div class="avatar-wrapper">
<img
v-if="!$store.state.user.sex || $store.state.user.sex==='男'"
alt=""
src="/assets/platform/img/home/avatar_boy.png"
class="user-avatar"
/>
<img v-else alt="" src="/assets/platform/img/home/avatar_girl.png" class="user-avatar" />
</div>
<div class="basic-wrapper">
<div class="welcome">{{$store.state.user.username}},开始您一天的工作吧!</div>
<span class="text-secondary">{{$store.state.user.unit.name}} {{$store.state.user.union.name}}</span>
<span class="text-secondary">{{$store.state.user.sex}} {{$store.state.user.userState}} {{$store.state.user.personType}}</span>
</div>
<div class="weather-wrap"></div>
<div class="date-wrap">
<div class="date">{{$moment().format('YYYY年MM月DD日')}}</div>
<div class="week">{{$moment().format('dddd')}}</div>
</div>
</div>
</div>
<el-card class="mt10" shadow="never">
<div class="card-title" slot="header">快速入口</div>
<div class="quickEntries">
<div v-for="item in quickEntries" :key="item.id" @click="pjaxReplace(item.href)" class="quickEntryItem">
<svg-icon :name="item.icon" :size="40" style="color: red"></svg-icon>
<span>{{item.name}}</span>
</div>
</div>
</el-card>
<el-row :gutter="20" class="mt10">
<el-col :span="16"></el-col>
<el-col :span="8">
<el-card shadow="never">
<div class="card-title" slot="header">最新活动</div>
<div v-for="item in activityOptions" :key="item.id">
<div style="width: 100%">
<div style="padding: 14px; background-color: #fff; position: relative">
<div style="display: flex; justify-content: center; align-items: center">
<!-- :src="item.cover"-->
<el-image src="https://img.yzcdn.cn/vant/t-thirt.jpg" alt="" style="margin: 3px 14px 0 0; width: 84px; height: 84px">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div style="flex: 1">
<div style="line-height: 22px; ont-size: 16px; color: #111">{{item.name}}</div>
<div style="margin-top: 6px; line-height: 20px; color: #999">{{item.startDate}}-{{item.endDate}}</div>
</div>
<el-tooltip content="去报名" placement="top-start">
<div @click="enterActivity(item)">
<svg-icon name="ant-design_tag-twotone" :size="30" style="color: var(--color-primary)"></svg-icon>
</div>
</el-tooltip>
</div>
</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-button type="primary" icon="el-icon-edit" @click="$refs.icon.showIconModal()">cxccc</el-button>
<icon-selector ref="icon" v-model="icon"></icon-selector>
</div>
<script>
new Vue({
el: "#app",
components: {
"icon-selector": httpVueLoader("/components/plugins/sysIconSelector/index.vue?v=" + new Date().getTime())
},
store,
data: function () {
return {
quickEntries: [],
activityOptions: [],
icon: "alipay"
}
},
methods: {
listQuickEntry() {
this.$axios.post("/platform/home/listQuickEntry").then((res) => {
if (res.code === 0) {
this.quickEntries = res.data
}
})
},
listActivity() {
this.$axios.post("/platform/h5/listHomeActivity").then((resp) => {
if (resp.code === 0) {
this.activityOptions = resp.data
}
})
},
enterActivity(item) {
this.$store.dispatch("pjaxRoute", item.url)
}
},
created() {
this.listQuickEntry()
this.listActivity()
this.listProcessInstance()
}
})
</script>
<style scoped></style>
<!--# } #-->
@@ -0,0 +1,67 @@
const activity = {
template: /*language=HTML*/ `
<div class="home-activity">
<el-card shadow="never">
<div class="card-title" slot="header">最新活动</div>
<div v-if="activityOptions && activityOptions.length > 0" v-for="item in activityOptions" :key="item.id">
<div style="width: 100%">
<div style="background-color: #fff; position: relative; margin-bottom: 10px">
<div style="display: flex; justify-content: center; align-items: center">
<el-image :src="item.cover" alt="" fit="contain" style="margin: 3px 14px 0 0; width: 100px; height: 70px; border-radius: 8px">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div style="flex: 1">
<div style="line-height: 22px; color: #111">
<i class="el-icon-star-on" style="color: red; font-size: 17px"></i>{{item.name}}
</div>
<div style="font-size: 12px; line-height: 20px; color: #999">开始时间:{{$moment(item.startDate).format('MM-DD HH:mm')}}</div>
<div style="font-size: 12px; line-height: 20px; color: #999">结束时间:{{$moment(item.endDate).format('MM-DD HH:mm')}}</div>
</div>
<div @click="enterActivity(item)">
<el-tag style="cursor: pointer">查看<i class="el-icon-s-promotion"></i></el-tag>
</div>
</div>
</div>
</div>
</div>
<el-empty v-if="activityOptions.length === 0" description="暂无活动"></el-empty>
</el-card>
</div>
`,
data() {
return {
activityOptions: []
}
},
methods: {
listActivity() {
this.$axios.post("/platform/home/listHomeActivity").then((resp) => {
if (resp.code === 0) {
this.activityOptions = resp.data
}
})
},
enterActivity(item) {
this.$store.dispatch("pjaxRoute", item.url)
}
},
created() {
this.listActivity()
},
style: /*language=CSS*/ `
.home-activity {
min-width: 500px;
}
.home-activity .el-card {
width: 100%;
overflow-y: auto;
}
.home-activity .el-empty {
padding: 40px 0 !important;
}
`
}
@@ -0,0 +1,76 @@
const appModule = {
template: /*language=HTML*/ `
<div class="home-app-module">
<el-card shadow="never">
<div class="card-title" slot="header">平台入口</div>
<div style="display: flex;gap: 20px">
<template v-for="item in entranceModules">
<div :key="item.id" class="v-item-handle" @click="enterEntranceModules(item)" >
<el-image :src="item.icon" style="height: 50px;width: 50px;border-radius: 50%"></el-image>
<span class="v-item-handle-label">
{{ item.name }}
</span>
</div>
</template>
</div>
</el-card>
</div>
`,
store,
data() {
return {}
},
computed: {
entranceModules() {
return this.$store.getters.pcModules
}
},
methods: {
enterEntranceModules(item) {
this.$store.commit("setActiveMenuModuleId", item.id)
}
},
created() {},
style: /*language=CSS*/ `
.v-item-handle {
width: 110px;
height: 110px;
border: 1px solid #f3efef;
/ / background-color: rgb(248, 248, 248);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
transition: all 500ms;
color: #0779e4;
cursor: pointer;
border-radius: 5px;
}
.v-item-handle-label {
font-size: 14px;
margin-top: 5px;
}
.v-item-handle .el-image {
transition: width 0.3s ease,
height 0.3s ease;
transform-origin: center; /* 缩放的中心点 */
}
.v-item-handle:hover .el-image {
width: 60px !important;
height: 60px !important;
}
.v-item-handle:hover .fa {
color: white !important;
}
.v-item-handle span {
transition: all 500ms;
color: #000;
font-size: 16px;
}
`
}
@@ -0,0 +1,127 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-card {
border-radius: 8px;
}
.image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: #f5f7fa;
color: #909399;
}
.el-icon-picture-outline {
font-size: 30px;
}
.el-card {
height: 100%;
}
.layout-grid-container {
display: grid;
grid-template-columns: repeat(3, minmax(100px, 1fr));
grid-template-rows: 200px 200px auto;
gap: 10px;
width: calc(100% - 0px);
height: calc(100vh - 126px);
margin: 0 auto;
overflow: hidden;
box-sizing: border-box;
}
.layout-grid-container .grid-item {
color: white;
border-radius: 8px;
}
.appModule-grid {
grid-column: 1 / 3; /* 元素1占据第1和第2列 */
grid-row: 1 / 2; /* 元素1占据第1行 */
}
.activity-grid {
grid-column: 3 / 4; /* 元素2占据第3列 */
grid-row: 1 / 3; /* 元素2跨越第1和第2行 */
}
.quickEntry-grid {
grid-column: 1 / 3; /* 元素3占据第1和第2列 */
grid-row: 2 / 3; /* 元素3占据第2行 */
}
.news-grid,
.todo-grid,
.user-grid {
grid-column: span 1; /* 每个元素占据1列 */
grid-row: 3 / 4; /* 所有元素都在第3行 */
}
</style>
<div id="app" v-cloak style="height: 100%">
<div class="layout-grid-container">
<app-module class="appModule-grid grid-item"></app-module>
<quick-entry class="quickEntry-grid grid-item"></quick-entry>
<activity class="activity-grid grid-item"></activity>
<news class="news-grid grid-item"></news>
<todo class="todo-grid grid-item"></todo>
<user-info class="user-grid grid-item"></user-info>
</div>
</div>
<script>
<!--#include("userInfo.js"){}#-->
<!--#include("todo.js"){}#-->
<!--#include("quickEntry.js"){}#-->
<!--#include("activity.js"){}#-->
<!--#include("appModule.js"){}#-->
<!--#include("news.js"){}#-->
new Vue({
el: "#app",
components: {
"icon-selector": httpVueLoader("/components/plugins/sysIconSelector/index.vue?v=" + new Date().getTime()),
"user-info": userInfo,
todo,
"quick-entry": quickEntry,
activity,
"app-module": appModule,
news: news
},
store,
data: function () {
return {
quickEntries: [],
activityOptions: [],
processInstanceOptions: []
}
},
methods: {
listQuickEntry() {
this.$axios.post("/platform/home/listQuickEntry").then((res) => {
if (res.code === 0) {
this.quickEntries = res.data
}
})
},
listActivity() {
this.$axios.post("/platform/h5/listHomeActivity").then((resp) => {
if (resp.code === 0) {
this.activityOptions = resp.data
}
})
},
enterActivity(item) {
this.$store.dispatch("pjaxRoute", item.url)
}
},
created() {
this.listQuickEntry()
this.listActivity()
}
})
</script>
<!--# } #-->
@@ -0,0 +1,81 @@
const news = {
template: /*language=HTML*/ `
<div class="home-news">
<el-tabs v-model="activeName">
<el-tab-pane v-for="(item,index) in newsData" :key="index" :label="item.label" :name="item.label" v-if="item.value.length > 0">
<div v-for="(n,i) in item.value" :key="i" @click="openUrl(n.href)">
<span v-if="n.time" class="news_time">{{ n.time }}</span>
<span class="news_text">{{ n.text }}</span>
</div>
</el-tab-pane>
</el-tabs>
</div>
`,
data() {
return {
newsData: [],
activeName: 0
}
},
methods: {
async getNews() {
const resp = await this.$axios.post("/platform/home/getNews")
if (resp.data.length > 0) {
this.activeName = resp.data[0].label
}
this.newsData = resp.data
},
openUrl(href) {
const url = this.isHttpOrHttps(href) ? href : "https://gonghui.njupt.edu.cn/" + href
window.open(url)
},
isHttpOrHttps(url) {
return /^(http:\/\/|https:\/\/)/i.test(url)
}
},
async created() {
await this.getNews()
},
style: /*language=CSS*/ `
.home-news {
background: #ffffff;
padding: 15px;
border-radius: 8px;
overflow-y: auto;
}
.home-news .el-tabs {
height: 100%;
}
.home-news .el-tabs__content {
height: calc(100% - 55px);
overflow-y: auto;
}
.home-news .el-tab-pane {
line-height: 38px;
color: black;
}
.home-news .el-tab-pane .news_time {
color: white;
padding: 4px 10px;
border-radius: 10px;
background: #1867b0;
}
.home-news .el-tab-pane div {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
cursor: pointer;
height: 50px;
line-height: 50px;
}
.home-news .el-tab-pane .news_text:hover {
color: #1867b0;
}
`
}
@@ -0,0 +1,100 @@
const quickEntry = {
template: /*language=HTML*/ `
<div class="home-quick-entry">
<el-card shadow="never">
<div class="card-title" slot="header">快速入口</div>
<div class="quickEntries">
<div v-for="item in quickEntries" :key="item.id" @click="$store.dispatch('pjaxRoute',item.href)" class="quickEntryItem">
<svg-icon :name="item.icon" :size="40" style="color: var(--color-primary)"></svg-icon>
<span>{{item.name}}</span>
</div>
</div>
</el-card>
</div>
`,
data() {
return {
quickEntries: []
}
},
methods: {
listQuickEntry() {
this.$axios.post("/platform/home/listQuickEntry", { platform: "PC" }).then((res) => {
if (res.code === 0) {
this.quickEntries = res.data
}
})
}
},
created() {
this.listQuickEntry()
},
style: /*language=CSS*/ `
.home-quick-entry .el-card {
width: 100%;
}
.home-quick-entry .el-card .el-card__body {
overflow-x: auto;
overflow-y: auto;
height: calc(100% - 53.5px);
}
.home-quick-entry .quickEntries {
overflow-y: auto;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 10px;
}
.home-quick-entry .quickEntries .quickEntryItem img {
max-width: 50px;
}
.home-quick-entry .quickEntries .quickEntryItem {
font-size: 16px;
height: 90px;
max-height: 90px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 10px;
transition: transform 0.3s ease-in-out,
box-shadow 0.3s ease-in-out;
}
.home-quick-entry .quickEntries .quickEntryItem span {
margin-top: auto;
}
.home-quick-entry .quickEntries .quickEntryItem:hover {
cursor: pointer;
background: #f3f3f3;
border-radius: 10px;
}
.home-quick-entry .quickEntries .quickEntryItem:hover {
animation: shake 0.3s;
}
@keyframes shake {
0% {
transform: translateX(0);
}
25% {
transform: translateX(-5px);
}
50% {
transform: translateX(5px);
}
75% {
transform: translateX(-5px);
}
100% {
transform: translateX(0);
}
}
`
}
@@ -0,0 +1,85 @@
const todo = {
template: /*language=HTML*/ `
<div class="home-todo">
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="待处理" name="listTodo"></el-tab-pane>
<el-tab-pane label="已处理" name="listDone"></el-tab-pane>
<el-tab-pane label="我的发起" name="listMyInitiation"></el-tab-pane>
</el-tabs>
<el-table :data="tableData" :border="false" size="small" class="mt10" height="calc(100% - 111px)">
<el-table-column label="序号" type="index"></el-table-column>
<el-table-column label="标题" prop="processInstanceName" show-overflow-tooltip></el-table-column>
<el-table-column label="发起人" prop="processInstanceInitiatorName"></el-table-column>
<el-table-column label="当前环节" prop="processInstanceNodeName" show-overflow-tooltip></el-table-column>
<el-table-column label="操作">
<template slot-scope="{row}">
<el-link type="primary" @click="openView(row)">查看</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</div>
`,
store,
mixins: [initTableMixins],
data() {
return {
activeName: "listTodo",
pageForm: {
searchName: "",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: "",
audit: false
}
}
},
methods: {
handleClick() {
this.pageData()
},
openView(row) {
if (this.activeName === "listMyInitiation") {
this.$store.dispatch("pjaxRoute", row.processInstanceUrl)
} else {
this.$store.dispatch("pjaxRoute", row.taskFormUrl)
}
},
pageData() {
this.$axios.post("/platform/home/" + this.activeName, this.pageForm).then((resp) => {
if (resp.code === 0) {
this.tableData = resp.data.list
this.pageForm.totalCount = resp.data.totalCount
}
})
}
},
created() {
this.handleClick()
},
style: /*language=CSS*/ `
.home-todo {
background: #ffffff;
padding: 15px;
border-radius: 8px;
overflow-y: auto;
color: #000000;
}
.home-todo .el-tabs {
/*height: 100%;*/
}
.home-todo .el-tabs__content {
height: calc(100% - 55px);
overflow-y: auto;
}
/*.home-todo .el-tabs__item{*/
/* color: #000000;*/
/*}*/
`
}
@@ -0,0 +1,91 @@
<!--#include("/platform/zhgh/staffmanage/member/common/info/memberInfo.js"){}#-->
const userInfo = {
template: /*language=HTML*/ `
<div class="home-user-info">
<el-card shadow="never">
<div class="card-title" slot="header">个人信息</div>
<div class="info">
<div>👨‍🏫我的姓名:{{ $store.state.user.username }}</div>
<div>🆔我的工号:{{ $store.state.user.loginname }}</div>
<div>⭕我的性别:{{ $store.state.user.sex }}</div>
<div>🟢我的单位:{{ $store.state.user.unit.name }}</div>
<div>🟤我的工会:{{ $store.state.user.union.name }}</div>
<div>📕系统角色:
<span style="font-size: 14px;color: #666;" v-for="role in $store.state.user.roles">
{{role.name}}
</span>
</div>
</div>
</el-card>
<el-dialog :visible.sync="signatureDialogVisible" title="我的签字" width="35%">
<div class="flx">
<div v-if="!showSignature" class="p10">
<el-image style="width: 100%;border: 1px dashed #000" :src="userSignatureUrl"
v-if="userSignatureUrl">
<template slot="error">获取签名失败</template>
</el-image>
<el-empty v-else description="暂无签名"></el-empty>
</div>
<div class="flx-center-center" style="flex-direction: column;">
<qrcode :options="{ width: 126 }" :value="signatureAddress" class="signature-qrcode"></qrcode>
<el-button icon="el-icon-refresh" size="small" type="primary" @click="getUserSignature(true)">
刷新
</el-button>
</div>
</div>
<el-alert title="扫描二维码可重新签名,手机上签名成功后可点击刷新查看。" type="success"></el-alert>
</el-dialog>
<el-dialog :visible.sync="memberInfoDialogVisible" title="我的信息">
<member-info :id="$store.state.user.id"></member-info>
</el-dialog>
</div>
`,
store,
data() {
return {
showSignature: false,
userSignatureUrl: null,
signatureDialogVisible: false,
signatureAddress: window.location.origin + "/platform/signature/scanPcCode?origin=user",
memberInfoDialogVisible: false
}
},
components: {
"member-info": MEMBER_INFO
},
mounted() {
},
methods: {
openSignature() {
this.signatureDialogVisible = true
this.getUserSignature()
},
getUserSignature(isRefresh = false) {
this.$axios.post("/platform/signature/get").then((res) => {
if (res.code === 0) {
if (isRefresh) {
this.$message.success("刷新成功")
} else {
if (!res.data.signature) {
this.$message.warning("未获取到签字信息")
}
}
this.userSignatureUrl = res.data.signature
}
})
},
},
style: /*language=CSS*/ `
.home-user-info .el-card {
width: 100%;
overflow: auto;
}
.home-user-info .info {
line-height: 40px;
color: black;
}
`
}
@@ -0,0 +1,123 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="名称" prop="name">
<el-input v-model="pageForm.name" clearable placeholder="请输入名称"></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<el-table :data="tableData" header-align="center" border style="width: 100%">
<el-table-column label="序号" type="index" width="50px" :method="indexMethod"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="pc端链接" prop="url"></el-table-column>
<el-table-column label="h5端链接" prop="h5Url"></el-table-column>
<el-table-column label="封面" prop="cover" width="80px">
<template slot-scope="scope">
<el-image :src="scope.row.cover" v-if="scope.row.icon" style="width: 30px; height: 30px"></el-image>
</template>
</el-table-column>
<el-table-column label="状态" prop="enable" width="80px">
<template slot-scope="scope">
<i v-if="!scope.row.enable" class="fa fa-circle text-danger ml5"></i>
<i v-else class="fa fa-circle text-success ml5"></i>
</template>
</el-table-column>
<el-table-column label="是否置顶" prop="top" width="100px">
<template slot-scope="scope">
<el-tag size="mini" v-if="scope.row.top" type="success"></el-tag>
<el-tag size="mini" v-else type="info"></el-tag>
</template>
</el-table-column>
<el-table-column label="关联类路径" prop="classPath" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="150px">
<template slot-scope="scope">
<el-link type="danger" size="mini" @click="disable(scope.row.id)" v-if="scope.row.enable">关闭</el-link>
<el-link type="primary" size="mini" @click="enable(scope.row.id)" v-if="!scope.row.enable">开启</el-link>
<el-link type="primary" size="mini" @click="topUp(scope.row.id)" v-if="!scope.row.top">置顶</el-link>
<el-link type="danger" size="mini" @click="cancelTopUp(scope.row.id)" v-if="scope.row.top">取消置顶</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {}
},
methods: {
disable(id) {
this.$confirm("您确定要关闭吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post(loc() + "/disable", { id }).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
}
})
})
},
enable(id) {
this.$confirm("您确定要开启吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post(loc() + "/enable", { id }).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
}
})
})
},
topUp(id) {
this.$confirm("您确定要置顶吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post(loc() + "/topUp", { id }).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
}
})
})
},
cancelTopUp(id) {
this.$confirm("您确定要取消置顶吗?", "提示", {
type: "warning",
confirmButtonText: "确定",
cancelButtonText: "取消"
}).then(() => {
this.$axios.post(loc() + "/cancelTopUp", { id }).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
}
})
})
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,190 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<el-row type="flex" style="column-gap: 10px">
<el-select placeholder="请选择日志类型" size="medium" v-model="pageForm.searchType">
<el-option :key="item.value" :label="item.label" :value="item.value" v-for="item in options"></el-option>
</el-select>
<el-date-picker
:default-time="['00:00:00', '23:59:59']"
:picker-options="pickerOptions"
align="right"
end-placeholder="结束日期"
range-separator="至"
size="medium"
start-placeholder="开始日期"
type="datetimerange"
v-model="searchDate"
value-format="yyyy-MM-dd HH:mm:ss"
></el-date-picker>
<el-button @click="doSearch" icon="el-icon-search" size="medium" type="primary"></el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table
:data="tableData"
:default-sort="{prop: 'createdat', order: 'descending'}"
@sort-change="pageOrder"
header-align="center"
style="width: 100%"
>
<el-table-column align="center" header-align="center" label="操作人" prop="username" sortable>
<template slot-scope="scope">{{scope.row.username+'/'+scope.row.loginname}}</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作时间" prop="createdat" sortable width="200">
<template slot-scope="scope">{{formatAt(scope.row.createdat)}}</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="日志类型" prop="type" width="120">
<template slot-scope="scope">
<span v-if="scope.row.type=='platform'">平台日志</span>
<span v-if="scope.row.type=='info'">登录日志</span>
<span v-if="scope.row.type=='api'">接口日志</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="执行动作" prop="tag" width="200" show-overflow-tooltip></el-table-column>
<el-table-column label="日志内容" prop="msg" show-overflow-tooltip></el-table-column>
<el-table-column :show-overflow-tooltip="true" label="执行类" prop="src"></el-table-column>
<el-table-column :show-overflow-tooltip="true" label="IP" prop="ip"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
options: [
{
value: "",
label: "全部类型"
},
{
value: "platform",
label: "平台日志"
},
{
value: "info",
label: "登录日志"
},
{
value: "api",
label: "接口日志"
}
],
pickerOptions: {
disabledDate: function (time) {
var threeMonths = moment().add(-3, "months").valueOf()
return time.getTime() > Date.now() || time.getTime() < threeMonths
},
shortcuts: [
{
text: "最近一周",
onClick: function (picker) {
var end = new Date()
var start = new Date()
var temp = moment().add(-1, "weeks").valueOf()
start.setTime(temp)
picker.$emit("pick", [start, end])
}
},
{
text: "最近一个月",
onClick: function (picker) {
var end = new Date()
var start = new Date()
var temp = moment().add(-1, "months").valueOf()
start.setTime(temp)
picker.$emit("pick", [start, end])
}
},
{
text: "最近三个月",
onClick: function (picker) {
var end = new Date()
var start = new Date()
var temp = moment().add(-3, "months").valueOf()
start.setTime(temp)
picker.$emit("pick", [start, end])
}
}
]
},
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "createdat",
pageOrderBy: "descending",
searchDate: "",
searchType: ""
},
searchDate: []
}
},
methods: {
formatAt: function (val) {
if (val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
doSearch: function () {
this.pageForm.pageNumber = 1
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
if (self.searchDate) {
self.pageForm.searchDate = self.searchDate.toString()
} else {
self.pageForm.searchDate = ""
}
$.post(
base + "/platform/sys/log/data",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
},
created: function () {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,282 @@
<!doctype html>
<html lang="${lang,escape}">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<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/plugins/element-ui/lib/theme-chalk/index.css" />
<link rel="stylesheet" href="${base!}/assets/platform/fonts/themify-icons.css" />
<link rel="stylesheet" href="${base!}/assets/platform/css/common.css" />
</head>
<body>
<!--[if lt IE 9]>
<div class="ie-must-go-die">
<div class="ie-container">
<h1>您正在IE的世界中</h1>
<p>本系统不支持IE9以下版本浏览器访问。</p>
<a href="https://browsehappy.com" target="_blank">您可以点击此处,下载Chrome/Firefox后再次访问本页面。</a>
</div>
</div>
<![endif]-->
<div id="app" v-cloak>
<img src="/assets/platform/img/login_bg.png" class="login-bg-img" alt="" />
<div class="login-container">
<div class="img">
<img src="/assets/platform/img/login_bg_center.svg" />
</div>
<div class="login-box">
<div class="login-form">
<div class="my-3 text-6xl font-semibold">${AppName!}${base!}</div>
<div class="flx-center-center">
<div class="p-12 bg-white rounded-3xl" style="box-sizing: border-box">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" auto-complete="on" label-position="left">
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
type="text"
auto-complete="off"
placeholder="账号"
prefix-icon="el-icon-user"
></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
type="password"
auto-complete="off"
placeholder="密码"
@keyup.enter.native="handleLogin"
prefix-icon="el-icon-lock"
></el-input>
</el-form-item>
<el-form-item prop="platformCaptcha">
<el-input
v-model="loginForm.platformCaptcha"
auto-complete="off"
placeholder="验证码"
style="width: 60%"
@keyup.enter.native="handleLogin"
prefix-icon="el-icon-key"
></el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" />
</div>
</el-form-item>
<el-form-item style="width: 100%">
<el-button
:loading="loading"
size="medium"
type="primary"
style="width: 100%; --color-primary: #1867b0"
@click.native.prevent="handleLogin"
>
<span v-if="!loading">登 录</span>
<span v-else>登 录 中...</span>
</el-button>
</el-form-item>
</el-form>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<!-- import Vue before Element -->
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<!-- import JavaScript -->
<script src="${base!}/assets/platform/plugins/element-ui/lib/index.js"></script>
<!-- import axios -->
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
<!-- import Jquery -->
<script src="${base!}/assets/platform/plugins/jquery/jquery.js"></script>
<!-- import SM2 -->
<script src="${base!}/assets/platform/plugins/sm-crypto/sm2.js"></script>
<!-- import commonUtil -->
<script src="${base!}/assets/platform/js/util/commonUtil.js"></script>
<script>
new Vue({
el: "#app",
data() {
return {
codeUrl: "",
loginForm: {
username: "",
password: "",
platformKey: "",
grantType: "captcha"
},
loginRules: {
username: [{ required: true, trigger: ["blur", "change"], message: "账号不能为空" }],
password: [{ required: true, trigger: ["blur", "change"], message: "密码不能为空" }],
platformCaptcha: [{ required: true, trigger: ["blur", "change"], message: "验证码不能为空" }]
},
loading: false
}
},
methods: {
getCode() {
axios.post("/platform/login/captcha").then((resp) => {
if (resp.data.code === 0) {
this.codeUrl = resp.data.data.codeUrl
this.loginForm.platformKey = resp.data.data.key
}
})
},
handleLogin() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
const password = commonUtil.smCrypto().doSm2Encrypt(this.loginForm.password)
axios
.post("/platform/login/doLogin", null, {
params: {
...this.loginForm,
password
}
})
.then((resp) => {
if (resp.data.code === 0) {
this.$message.success("登录成功")
const redirect = new URLSearchParams(window.location.search).get("redirect")
if (redirect) {
window.location.href = "${base!}" + redirect || ""
} else {
window.location.href = "${base!}/platform/home"
}
} else {
this.$message({
message: resp.data.msg,
type: "error"
})
}
})
.catch((error) => {
console.log(error)
})
} else {
console.log("cccccc")
}
})
}
},
created() {
this.getCode()
}
})
</script>
<style scoped>
#app {
height: 100%;
}
html body {
position: relative;
height: 100vh;
padding: 0;
margin: 0;
font-family: Avenir, Helvetica, Arial, sans-serif;
font-size: 14px;
color: #2c3e50;
background: #f6f8f9;
-webkit-font-smoothing: antialiased;
}
@media screen and (max-width: 768px) {
.login-container {
grid-template-columns: 1fr !important;
padding: 0 !important;
}
.login-container .img {
display: none !important;
}
}
.login-container {
width: 100vw;
height: 100vh;
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.login-container .img {
display: flex;
justify-content: flex-end;
align-items: center;
}
.login-container .img img {
z-index: 0;
width: 500px;
}
.login-box {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.login-form {
width: 500px;
}
.font-semibold {
font-weight: 600;
}
.text-6xl {
font-size: 30px;
}
.my-3 {
margin-top: 12px;
margin-bottom: 12px;
}
.p-12 {
padding: 48px;
}
.bg-white {
--tw-bg-opacity: 1;
background-color: rgb(255 255 255 / var(--tw-bg-opacity));
}
.rounded-3xl {
border-radius: 1.5rem;
}
.login-code {
display: inline-block;
float: right;
width: 38%;
height: 38px;
}
.login-code img {
vertical-align: middle;
cursor: pointer;
}
.login-bg-img {
position: fixed;
width: 100%;
height: 100%;
left: 0;
bottom: 0;
z-index: 0;
}
@media screen and (max-width: 768px) {
.login-container > div.img {
display: none;
}
.login-container .login-box .login-form {
width: 100vw !important;
}
}
</style>
</html>
@@ -0,0 +1,226 @@
const SYS_MENU_BASIC_FORM_COMPONENT = {
template: `
<el-dialog :title="formData.id ? '编辑菜单' : '新增菜单'" :show-close="false" :visible.sync="visibleDialog" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="formRef" :rules="formRules" size="small" label-width="80px">
<el-form-item label="所属模块" prop="moduleId">
<el-select v-model="formData.moduleId" clearable placeholder="请选择模块">
<el-option v-for="item in moduleOptions" :value="item.id" :key="item.id" :label="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="parentId" label="上级菜单" label-width="80px">
<el-cascader
:options="menuOptions"
:props="props"
v-model="parentMenu"
placeholder="不选择则为顶级"
clearable
style="width: 100%"
></el-cascader>
</el-form-item>
<el-form-item prop="name" label="菜单名称">
<el-input maxlength="100" placeholder="菜单名称" v-model="formData.name"
type="text"></el-input>
</el-form-item>
<el-form-item prop="aliasName" label="菜单别名">
<el-input maxlength="100" placeholder="菜单名称" v-model="formData.aliasName"
type="text"></el-input>
</el-form-item>
<el-form-item prop="permission" label="权限标识">
<el-input
maxlength="100"
placeholder="权限标识,如 sys.manager.menu"
v-model="formData.permission"
auto-complete="off"
tabindex="5"
type="text"
></el-input>
</el-form-item>
<el-form-item prop="href" label="URL">
<el-input maxlength="100" placeholder="URL" v-model="formData.href" auto-complete="off" tabindex="6"
type="text"></el-input>
</el-form-item>
<el-form-item prop="icon" label="图标">
<el-input maxlength="100"
v-if="platform==='PC'"
placeholder="图标"
v-model="formData.icon"
auto-complete="off"
tabindex="7"
type="text">
<template slot="append">
<el-button @click="$refs.iconSelector.showIconModal(formData.icon)">图标选择</el-button>
<icon-selector ref="iconSelector" v-model="formData.icon"></icon-selector>
</template>
</el-input>
<file-upload
v-if="platform==='H5'"
:value.sync="formData.icon"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
<el-form-item prop="type" label="数据权限">
<el-radio-group @change="formRadioChange" v-model="formData.children" size="mini">
<el-radio label="false">无</el-radio>
<el-radio label="true">有</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="formData.children=='true'"
v-for="(menu, index) in formData.buttons"
:label="'权限' + (index+1)"
:key="menu.key"
:prop="'buttons[' + index + ']'"
:rules="{required: true,validator: validateMenu,trigger: ['blur','change']}"
>
<el-row :gutter="2">
<el-col :span="6">
<el-input v-model="menu.name" placeholder="权限名称"></el-input>
</el-col>
<el-col :span="13">
<el-input v-model="menu.permission" placeholder="权限标识,如 sys.manager.menu.add"></el-input>
</el-col>
<el-col :span="4">
<el-button @click.prevent="formRemoveMenu(menu)" icon="el-icon-delete" size="small"></el-button>
</el-col>
</el-row>
</el-form-item>
<el-row v-if="formData.children=='true'" style="text-align: right; padding-right: 17px">
<el-button size="small" @click="formAddMenu" icon="el-icon-circle-plus">添加</el-button>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visibleDialog = false">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
visibleDialog: false,
formData: {
buttons: []
},
formRules: {
moduleId: [{ required: true, message: "必填", trigger: "blur" }],
name: [{ required: true, message: "必填", trigger: "blur" }],
permission: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
},
menuOptions: [],
parentMenu: [],
props: {
checkStrictly: true,
multiple: false,
label: "name",
value: "id"
},
platform: null,
moduleOptions: []
}
},
methods: {
onOpen(id, platform) {
this.visibleDialog = true
this.platform = platform
this.listFullTree()
this.listModule()
if (id == null) {
this.formData = {
buttons: []
}
} else {
this.detail(id)
}
},
listFullTree() {
this.$axios.post(loc() + "/fullTree", { platform: this.platform }).then((res) => {
this.menuOptions = res.data
})
},
detail(id) {
this.$axios.post("/platform/sys/menu/editMenu/" + id).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.parentMenu = res.data.parentIds
}
})
},
submit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
if (this.parentMenu) {
this.formData.parentId = this.parentMenu[this.parentMenu.length - 1] || ""
} else {
this.formData.parentId = ""
}
const url = this.formData.id ? "/platform/sys/menu/editMenuDo" : "/platform/sys/menu/addDo"
this.$axios
.post(url, {
menu: JSON.stringify(this.formData),
platform: this.platform
})
.then((res) => {
if (res.code === 0) {
this.$message.success("保存成功")
this.visibleDialog = false
this.$emit("refresh", null)
}
})
}
})
},
formRadioChange: function (val) {
this.formData.children = val
if (val) {
this.formData.buttons = [
{
name: "",
permission: "",
key: Date.now()
}
]
} else {
this.formData.buttons = []
}
},
formAddMenu() {
this.formData.buttons.push({
name: "",
permission: "",
key: Date.now()
})
},
formRemoveMenu(menu) {
const index = this.formData.buttons.indexOf(menu)
if (index !== -1) {
this.formData.buttons.splice(index, 1)
}
},
//验证动态添加行数据
validateMenu: function (rule, value, callback) {
if (value.name === "") {
callback(new Error("权限名称不能为空"))
} else if (value.permission === "") {
callback(new Error("权限标识不能为空"))
} else {
callback()
}
},
listModule() {
this.$axios.post(loc() + "/listModule", { platform: this.platform }).then((res) => {
if (res.code === 0) {
this.moduleOptions = res.data
}
})
}
}
}
@@ -0,0 +1,251 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="平台">
<el-select v-model="pageForm.platform" :clearable="false" @change="listModule();doSearch();">
<el-option v-for="item in dict.type.SYS_MENU_PLATFORM" :value="item.code" :key="item.value" :label="item.label"></el-option>
</el-select>
</search-item>
<search-item label="模块">
<el-select v-model="pageForm.moduleId" clearable placeholder="请选择模块">
<el-option v-for="item in moduleOptions" :value="item.id" :key="item.id" :label="item.name"></el-option>
</el-select>
</search-item>
<search-item label="菜单名称">
<el-input v-model="pageForm.menuName" clearable placeholder="请填写名称查询" style="width: 100%"></el-input>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool>
<el-button @click="$refs.basicFormRef.onOpen(null,pageForm.platform)" size="small" type="primary" icon="el-icon-plus">新建菜单</el-button>
<el-button @click="$refs.sortRef.onOpen(pageForm.platform)" size="small" type="primary" icon="el-icon-sort">排序</el-button>
<el-button @click="$refs.quickEntryRef.onOpen(pageForm.platform)" size="small" type="primary" icon="el-icon-monitor">
首页快速入口
</el-button>
</table-tool>
<el-table
:data="tableData"
:highlight-current-row="true"
:key="tableKey"
:load="loadChild"
:expand-row-keys="expandedRowKeysRenew"
@expand-change="handleExpandChange"
ref="tableData"
style="width: 100%"
lazy
row-key="id"
>
<el-table-column align="left" header-align="left" label="菜单名称" prop="name" width="200"></el-table-column>
<el-table-column align="center" header-align="center" label="菜单图标" prop="icon" width="100">
<template slot-scope="scope">
<template v-if="pageForm.platform==='PC'">
<svg-icon :name="scope.row.icon" v-if="scope.row.icon" :size="20"></svg-icon>
</template>
<template v-else-if="pageForm.platform==='H5'">
<el-image :src="scope.row.icon" v-if="scope.row.icon" style="width: 30px; height: 30px"></el-image>
</template>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="URL" prop="href"></el-table-column>
<el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="资源类型" prop="type">
<template slot-scope="scope">
<i style="font-weight: bold" v-if="scope.row.type=='menu'">菜单</i>
<i v-if="scope.row.type=='data'">数据</i>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="所属模块" prop="moduleId">
<template slot-scope="scope">
<i style="font-weight: bold">{{moduleOptions.find(item=>item.id==scope.row.moduleId)?.name}}</i>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="权限标识" prop="permission"></el-table-column>
<el-table-column align="center" header-align="center" label="启用状态" prop="disabled">
<template slot-scope="scope">
<i class="fa fa-circle text-danger ml5" v-if="scope.row.disabled"></i>
<i class="fa fa-circle text-success ml5" v-if="!scope.row.disabled"></i>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="操作" prop="website" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item :command="{type:'add',id:scope.row.id,name:scope.row.name}" v-if="scope.row.type=='menu'">-->
<!-- 添加子菜单-->
<!-- </el-dropdown-item>-->
<el-dropdown-item :command="{type:'enable',id:scope.row.id,name:scope.row.name,row:scope.row}" divided>
启用
</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,name:scope.row.name,row:scope.row}">禁用</el-dropdown-item>
<el-dropdown-item :command="{type:'editMenu',id:scope.row.id,name:scope.row.name}" divided v-if="scope.row.type=='menu'">
修改
</el-dropdown-item>
<el-dropdown-item :command="{type:'editData',id:scope.row.id,name:scope.row.name}" divided v-if="scope.row.type=='data'">
修改
</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',id:scope.row.id,name:scope.row.name}" v-if="scope.row.path!='0001'">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
</el-card>
<basic-form ref="basicFormRef" @refresh="loadChildByExpandedKeys"></basic-form>
<permission-form ref="permissionFormRef" @load-child="loadChildByExpandedKeys"></permission-form>
<sort ref="sortRef" @refresh="doSearch"></sort>
<quick-entry ref="quickEntryRef" @refresh="doSearch"></quick-entry>
</div>
<script>
<!--#include("permissionForm.js"){}#-->
<!--#include("basicForm.js"){}#-->
<!--#include("sort.js"){}#-->
<!--#include("quickEntry.js"){}#-->
new Vue({
el: "#app",
dicts: ["SYS_MENU_PLATFORM"],
components: {
"basic-form": SYS_MENU_BASIC_FORM_COMPONENT,
"permission-form": SYS_MENU_PERMISSION_FORM_COMPONENT,
sort: SYS_MENU_SORT_COMPONENT,
"quick-entry": SYS_MENU_QUICK_ENTRY_COMPONENT
},
data: function () {
return {
pageForm: {},
tableData: [],
tableKey: "",
moduleOptions: [],
// 保存展开状态的数组
expandedRowKeysRenew: [],
tableTreeRefreshTool: []
}
},
methods: {
doSearch() {
this.initTreeTable()
},
initTreeTable() {
this.$axios
.post("/platform/sys/menu/child", {
pid: "",
...this.pageForm
})
.then((res) => {
if (res.code === 0) {
this.tableData = res.data
this.tableKey = +new Date()
}
})
},
loadChild: function (tree, treeNode, resolve) {
// 在之前声明的全局变量中,增加一个key为 本条数据的id,id可替换为你数据中的任意唯一值
this.tableTreeRefreshTool[tree.id] = {}
// 重要!保存resolve方法,以便后续使用
this.tableTreeRefreshTool[tree.id].resolve = resolve
// 记录展开次数,具体作用后续介绍
this.tableTreeRefreshTool[tree.id].expandCount = 0
const url = "/platform/sys/menu/child"
this.$axios.post(url, { pid: tree.id }).then((res) => {
if (res.code === 0) {
resolve(res.data)
}
})
},
dropdownCommand(command) {
//监听下拉框事件
// if ("add" === command.type) {
// this.$refs.basicFormRef.onOpenAdd(command.id, this.pageForm.platform)
// }
if ("editMenu" === command.type) {
this.$refs.basicFormRef.onOpen(command.id, this.pageForm.platform)
}
if ("editData" === command.type) {
this.$refs.permissionFormRef.onOpen(command.id)
}
if ("enable" === command.type || "disable" === command.type) {
this.$axios.post("/platform/sys/menu/" + command.type + "/" + command.id).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
if ("disable" === command.type) {
command.row.disabled = true
}
if ("enable" === command.type) {
command.row.disabled = false
}
}
})
}
if ("delete" === command.type) {
this.$confirm("此操作将删除 " + command.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/sys/menu/delete/" + command.id).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.loadChildByExpandedKeys()
}
})
})
}
},
handleExpandChange(row, expanded) {
if ((row.parentId === "" || row.parentId == null) && !expanded) {
this.expandedRowKeysRenew = []
return
}
if (expanded) {
this.expandedRowKeysRenew.push(row.id)
} else {
const index = this.expandedRowKeysRenew.findIndex((v) => v === row.id)
this.expandedRowKeysRenew.splice(index, 1)
}
},
loadChildByExpandedKeys() {
if (this.expandedRowKeysRenew && this.expandedRowKeysRenew.length > 0) {
this.expandedRowKeysRenew.forEach((v) => {
const curr = this.tableTreeRefreshTool[v]
// api请求
$.get("/platform/sys/menu/child", { pid: v }).then((res) => {
curr.resolve(res.data)
})
})
} else {
this.initTreeTable()
}
},
listModule() {
this.$axios.post(loc() + "/listModule", { platform: this.pageForm.platform }).then((res) => {
if (res.code === 0) {
this.moduleOptions = res.data
}
})
}
},
created() {
setTimeout(() => {
if (this.dict.type.SYS_MENU_PLATFORM) {
this.pageForm.platform = this.dict.type.SYS_MENU_PLATFORM[0].code
this.listModule()
this.initTreeTable()
}
}, 500)
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,677 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-row type="flex" justify="end">
<el-button @click="openAdd" size="medium" type="primary">
<i class="ti-plus"></i>
新建菜单
</el-button>
<el-button @click="openSort" size="medium" type="primary">排序</el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table
:data="tableData"
:highlight-current-row="true"
:key="tableKey"
:load="loadChild"
lazy
row-key="id"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}"
>
>
<el-table-column
:show-overflow-tooltip="true"
align="left"
header-align="center"
label="菜单名称"
prop="name"
width="200"
></el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="URL" prop="href"></el-table-column>
<el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="资源类型" prop="type">
<template slot-scope="scope">
<i style="font-weight: bold" v-if="scope.row.type=='menu'">菜单</i>
<i v-if="scope.row.type=='data'">数据</i>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="权限标识" prop="permission"></el-table-column>
<el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="启用状态" prop="disabled">
<template slot-scope="scope">
<i class="fa fa-circle text-danger ml5" v-if="scope.row.disabled"></i>
<i class="fa fa-circle text-success ml5" v-if="!scope.row.disabled"></i>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" align="center" header-align="center" label="操作" prop="website" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'add',id:scope.row.id,name:scope.row.name}" v-if="scope.row.type=='menu'">
添加子菜单
</el-dropdown-item>
<el-dropdown-item :command="{type:'enable',id:scope.row.id,name:scope.row.name,row:scope.row}" divided>
启用
</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,name:scope.row.name,row:scope.row}">禁用</el-dropdown-item>
<el-dropdown-item :command="{type:'editMenu',id:scope.row.id,name:scope.row.name}" divided v-if="scope.row.type=='menu'">
修改
</el-dropdown-item>
<el-dropdown-item :command="{type:'editData',id:scope.row.id,name:scope.row.name}" divided v-if="scope.row.type=='data'">
修改
</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',id:scope.row.id,name:scope.row.name}" v-if="scope.row.path!='0001'">
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="新建菜单" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="parentId" label="上级菜单" label-width="80px">
<el-cascader
v-if="!isAddFromSub"
:options="menuOptions"
:props="props"
v-model="parentMenu"
placeholder="不选择则为顶级"
style="width: 100%"
></el-cascader>
<el-input v-if="isAddFromSub" type="text" v-model="formData.parentName" :disabled="true"></el-input>
</el-form-item>
<el-form-item prop="name" label="菜单名称">
<el-input maxlength="100" placeholder="菜单名称" v-model="formData.name" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<el-form-item prop="aliasName" label="菜单别名">
<el-input maxlength="100" placeholder="菜单名称" v-model="formData.aliasName" auto-complete="off" tabindex="4" type="text"></el-input>
</el-form-item>
<el-form-item prop="permission" label="权限标识">
<el-input
maxlength="100"
placeholder="权限标识,如 sys.manager.menu"
v-model="formData.permission"
auto-complete="off"
tabindex="5"
type="text"
></el-input>
</el-form-item>
<el-form-item prop="href" label="URL">
<el-input maxlength="100" placeholder="URL" v-model="formData.href" auto-complete="off" tabindex="6" type="text"></el-input>
</el-form-item>
<el-form-item prop="icon" label="图标">
<el-input maxlength="100" placeholder="图标" v-model="formData.icon" auto-complete="off" tabindex="7" type="text"></el-input>
<span :class="formData.icon"></span>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
<el-form-item prop="type" label="数据权限">
<el-radio-group @change="formRadioChange" v-model="formData.children" size="mini">
<el-radio label="false"></el-radio>
<el-radio label="true"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="formData.children=='true'"
v-for="(menu, index) in formData.buttons"
:label="'权限' + (index+1)"
:key="menu.key"
:prop="'buttons[' + index + ']'"
:rules="{required: true,validator: validateMenu,trigger: ['blur','change']}"
>
<el-row :gutter="2">
<el-col :span="6">
<el-input v-model="menu.name" placeholder="权限名称"></el-input>
</el-col>
<el-col :span="13">
<el-input v-model="menu.permission" placeholder="权限标识,如 sys.manager.menu.add"></el-input>
</el-col>
<el-col :span="4">
<el-button @click.prevent="formRemoveMenu(menu)" icon="el-icon-delete" size="small"></el-button>
</el-col>
</el-row>
</el-form-item>
<el-row v-if="formData.children=='true'" style="text-align: right; padding-right: 17px">
<el-button size="small" @click="formAddMenu" icon="el-icon-circle-plus">添加</el-button>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="修改菜单" :visible.sync="editMenuDialogVisible" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="editMenuForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="parentId" label="上级菜单" label-width="80px">
<el-input type="text" v-model="formData.parentName" :disabled="true"></el-input>
</el-form-item>
<el-form-item prop="name" label="菜单名称">
<el-input maxlength="100" placeholder="菜单名称" v-model="formData.name" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<el-form-item prop="aliasName" label="菜单别名">
<el-input maxlength="100" placeholder="菜单名称" v-model="formData.aliasName" auto-complete="off" tabindex="4" type="text"></el-input>
</el-form-item>
<el-form-item prop="permission" label="权限标识">
<el-input
maxlength="100"
placeholder="权限标识,如 sys.manager.menu"
v-model="formData.permission"
auto-complete="off"
tabindex="5"
type="text"
></el-input>
</el-form-item>
<el-form-item prop="href" label="URL">
<el-input maxlength="100" placeholder="URL" v-model="formData.href" auto-complete="off" tabindex="6" type="text"></el-input>
</el-form-item>
<el-form-item prop="icon" label="图标">
<el-input maxlength="100" placeholder="图标" v-model="formData.icon" auto-complete="off" tabindex="7" type="text"></el-input>
<span :class="formData.icon"></span>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
<el-form-item prop="type" label="数据权限">
<el-radio-group @change="formRadioChange" v-model="formData.children" size="mini">
<el-radio label="false"></el-radio>
<el-radio label="true"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="formData.children=='true'"
v-for="(menu, index) in formData.buttons"
:label="'权限' + (index+1)"
:key="menu.key"
:prop="'buttons[' + index + ']'"
:rules="{required: true,validator: validateMenu,trigger: ['blur','change']}"
>
<el-row :gutter="2">
<el-col :span="6">
<el-input v-model="menu.name" placeholder="权限名称"></el-input>
</el-col>
<el-col :span="13">
<el-input v-model="menu.permission" placeholder="权限标识,如 sys.manager.menu.add"></el-input>
</el-col>
<el-col :span="4">
<el-button @click.prevent="formRemoveMenu(menu)" icon="el-icon-delete" size="small"></el-button>
</el-col>
</el-row>
</el-form-item>
<el-row v-if="formData.children=='true'" style="text-align: right; padding-right: 17px">
<el-button size="small" @click="formAddMenu" icon="el-icon-circle-plus">添加</el-button>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editMenuDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEditMenu">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="修改权限" :visible.sync="editDataDialogVisible" width="50%">
<el-form :model="formData2" ref="editDataForm" :rules="formRules2" size="small" label-width="80px">
<el-form-item prop="name" label="权限名称">
<el-input maxlength="100" placeholder="权限名称" v-model="formData2.name" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="permission" label="权限标识">
<el-input
maxlength="100"
placeholder="权限标识,如 sys.manager.menu.add"
v-model="formData2.permission"
auto-complete="off"
tabindex="2"
type="text"
></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData2.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDataDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEditData">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="菜单排序" :visible.sync="sortDialogVisible" width="50%">
<el-tree ref="sortMenuTree" :data="sortMenuData" draggable :allow-drop="sortAllowDrop" node-key="id" :props="defaultProps">
<span class="custom-tree-node" slot-scope="scope">
<span>{{ scope.node.label }}</span>
</span>
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="sortDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSort">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editMenuDialogVisible: false,
editDataDialogVisible: false,
sortDialogVisible: false,
isAddFromSub: false,
tableData: [], //后台取出的数据
tableKey: "",
formData: {
id: "",
parentId: "",
parentName: "",
type: "menu",
target: "data-pjax",
children: "false",
buttons: []
},
formRules: {
name: [{ required: true, message: "菜单名称", trigger: "blur" }],
permission: [{ required: true, message: "权限标识", trigger: ["blur", "change"] }]
},
formData2: {},
formRules2: {
name: [{ required: true, message: "权限名称", trigger: "blur" }],
permission: [{ required: true, message: "权限标识", trigger: ["blur", "change"] }]
},
menuOptions: [],
parentMenu: [],
sortMenuData: [],
defaultProps: {
children: "children",
label: "label"
},
props: {
lazy: true,
checkStrictly: true,
multiple: false,
lazyLoad: function (node, resolve) {
var url = base + "/platform/sys/menu/tree"
$.post(
url,
{ pid: node.value },
function (data) {
if (data.code == 0) {
resolve(data.data)
}
},
"json"
)
}
}
}
},
methods: {
//验证动态添加行数据
validateMenu: function (rule, value, callback) {
if (value.name == "") {
callback(new Error("权限名称不能为空"))
} else if (value.permission == "") {
callback(new Error("权限标识不能为空"))
} else {
callback()
}
},
formRadioChange: function (val) {
this.formData.children = val
if ("true" == val) {
this.formData.buttons = [
{
name: "",
permission: "",
key: Date.now()
}
]
} else {
this.formData.buttons = []
}
},
formRemoveMenu: function (menu) {
var index = this.formData.buttons.indexOf(menu)
if (index !== -1) {
this.formData.buttons.splice(index, 1)
}
},
formAddMenu: function () {
this.formData.buttons.push({
name: "",
permission: "",
key: Date.now()
})
},
//排序树加载
sortMenuLoad: function () {
var self = this
$.post(
base + "/platform/sys/menu/menuAll",
{},
function (data) {
if (data.code == 0) {
self.sortMenuData = data.data
}
},
"json"
)
},
//排序树控制不可跨级拖拽
sortAllowDrop: function (moveNode, inNode, type) {
if (moveNode.data.parentId == inNode.data.parentId) {
return type == "prev"
}
},
//打开排序功能
openSort: function () {
this.sortDialogVisible = true
this.sortMenuLoad()
},
//递归获取所有的ID值
getTreeIds: function (ids, data) {
var self = this
data.forEach(function (obj) {
ids.push(obj.id)
if (obj.children && obj.children.length > 0) {
self.getTreeIds(ids, obj.children)
}
})
},
//提交排序后的数据
doSort: function () {
var self = this
var ids = []
const loading = this.$loading({
lock: true,
text: "正在提交...",
spinner: "el-icon-loading"
})
self.getTreeIds(ids, self.sortMenuData)
$.post(
base + "/platform/sys/menu/sortDo",
{ ids: ids.toString() },
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.sortDialogVisible = false
self.initTreeTable()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
loading.close()
},
"json"
)
},
openAdd: function () {
var self = this
self.isAddFromSub = false
self.addDialogVisible = true
self.parentMenu = []
self.menuOptions = []
//表单还原为初始值
self.formData = {
id: "",
parentId: "",
parentName: "",
type: "menu",
target: "data-pjax",
children: "false",
buttons: []
}
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
doAdd: function () {
var self = this
var url = base + "/platform/sys/menu/addDo"
self.$refs["addForm"].validate(function (valid) {
if (valid) {
//表单验证通过
if (!self.isAddFromSub) {
//如果不是添加子菜单,则从级联选择框取父节点ID
self.formData.parentId = self.parentMenu[self.parentMenu.length - 1] || ""
}
$.post(
url,
{
menu: JSON.stringify(self.formData),
buttons: JSON.stringify(self.formData.buttons)
},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.addDialogVisible = false
self.initTreeTable()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
doEditMenu: function () {
var self = this
var url = base + "/platform/sys/menu/editMenuDo"
self.$refs["editMenuForm"].validate(function (valid) {
if (valid) {
//表单验证通过
$.post(
url,
{
menu: JSON.stringify(self.formData),
buttons: JSON.stringify(self.formData.buttons)
},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.editMenuDialogVisible = false
self.initTreeTable()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
doEditData: function () {
var self = this
var url = base + "/platform/sys/menu/editDataDo"
self.$refs["editDataForm"].validate(function (valid) {
if (valid) {
//表单验证通过
$.post(
url,
self.formData2,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.editDataDialogVisible = false
self.initTreeTable()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
initTreeTable: function () {
var self = this
var url = base + "/platform/sys/menu/child"
$.post(
url,
{ pid: "" },
function (data) {
if (data.code == 0) {
self.tableData = data.data
self.tableKey = +new Date()
}
},
"json"
)
},
loadChild: function (tree, treeNode, resolve) {
var url = base + "/platform/sys/menu/child"
$.post(
url,
{ pid: tree.id },
function (data) {
if (data.code == 0) {
resolve(data.data)
}
},
"json"
)
},
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("add" == command.type) {
self.openAdd()
self.formData.parentId = command.id
self.formData.parentName = command.name
self.isAddFromSub = true
}
if ("editMenu" == command.type) {
$.post(
base + "/platform/sys/menu/editMenu/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.formData = data.data //加载后台表单数据
self.editMenuDialogVisible = true //打开编辑窗口
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("editData" == command.type) {
$.post(
base + "/platform/sys/menu/editData/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.formData2 = data.data //加载后台表单数据
self.editDataDialogVisible = true //打开编辑窗口
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("enable" == command.type || "disable" == command.type) {
$.post(
base + "/platform/sys/menu/" + command.type + "/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
if ("disable" == command.type) {
command.row.disabled = true
}
if ("enable" == command.type) {
command.row.disabled = false
}
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("delete" == command.type) {
self.$confirm("此操作将删除 " + command.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/menu/delete/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
// self.initTreeTable();
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
}
},
created: function () {
this.initTreeTable()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,59 @@
const SYS_MENU_PERMISSION_FORM_COMPONENT = {
template: `
<el-dialog title="修改权限" :visible.sync="editDataDialogVisible" width="50%">
<el-form :model="formData" ref="formRef" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="name" label="权限名称">
<el-input maxlength="100" placeholder="权限名称" v-model="formData.name" auto-complete="off"
tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="permission" label="权限标识">
<el-input
maxlength="100"
placeholder="权限标识,如 sys.manager.menu.add"
v-model="formData.permission"
auto-complete="off"
tabindex="2"
type="text"
></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDataDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEditData">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
editDataDialogVisible: false,
formData: {},
formRules: {}
}
},
methods: {
onOpen(id) {
this.editDataDialogVisible = true
this.$axios.post("/platform/sys/menu/editData/" + id, {}).then((res) => {
if (res.code === 0) {
this.formData = res.data
}
})
},
doEditData() {
this.$refs.formRef.validate((valid) => {
if (valid) {
this.$axios.post("/platform/sys/menu/editDataDo", this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.editDataDialogVisible = false
this.$emit("load-child", null)
}
})
}
})
}
}
}
@@ -0,0 +1,113 @@
const SYS_MENU_QUICK_ENTRY_COMPONENT = {
template: `
<el-dialog title="快速入口" :visible.sync="dialogVisible" width="50%">
<el-row :gutter="20">
<el-col :span="12">
<el-tree ref="menuTree"
style="max-height: 500px;overflow-y: auto"
:data="menuData"
:check-on-click-node="true"
node-key="id"
show-checkbox
@check-change="checkChange"
:props="defaultProps">
<span class="custom-tree-node" slot-scope="scope">
<span>{{ scope.node.label }}</span>
</span>
</el-tree>
</el-col>
<el-col :span="12">
<el-table :data="checkedNodes" max-height="500px">
<el-table-column type="index"></el-table-column>
<el-table-column label="名称" prop="name"></el-table-column>
<el-table-column label="图标" prop="icon">
<template scope="{row}">
<svg-icon :name="row.icon"></svg-icon>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submit">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
platform: null,
dialogVisible: false,
menuData: [],
defaultProps: {
children: "children",
label: "label"
},
checkedNodes: [],
checkedKeys: []
}
},
methods: {
onOpen(platform) {
this.platform = platform
this.dialogVisible = true
this.listTree()
},
listTree() {
this.$axios.post("/platform/sys/menu/menuAll", { platform: this.platform }).then((res) => {
if (res.code === 0) {
this.setTreeDisabled(res.data)
this.menuData = res.data
console.log(this.checkedKeys)
//设置选中的节点
this.$refs.menuTree.setCheckedKeys(this.checkedKeys)
//获取选中的节点
this.$nextTick(() => {
this.checkedNodes = this.$refs.menuTree.getCheckedNodes(true, false)
})
}
})
},
setTreeDisabled(data) {
data.forEach((item) => {
if (item.isQuickEntry) {
this.checkedKeys.push(item.id)
}
if (!item.href && item.type === "menu") {
item.disabled = true
}
if (item.children && item.children.length) {
this.setTreeDisabled(item.children)
}
})
},
checkChange(currObj, isChecked) {
this.checkedNodes = this.$refs.menuTree.getCheckedNodes(true, false)
},
submit() {
this.$confirm("您确定要提交吗?", "提示", {
type: "warning"
}).then(() => {
this.$axios
.post("/platform/sys/menu/updateQuickEntry", {
menuIds: JSON.stringify(this.checkedNodes.map((item) => item.id)),
platform: this.platform
})
.then((resp) => {
if (resp.code === 0) {
this.checkedKeys = []
this.listTree()
this.$message.success(resp.msg)
this.$emit("refresh", null)
}
})
})
}
},
created() {}
}
@@ -0,0 +1,75 @@
const SYS_MENU_SORT_COMPONENT = {
template: `
<el-dialog title="菜单排序" :visible.sync="sortDialogVisible" width="50%">
<el-tree ref="sortMenuTree" :data="sortMenuData" draggable :allow-drop="sortAllowDrop" node-key="id"
:props="defaultProps">
<span class="custom-tree-node" slot-scope="scope">
<span>{{ scope.node.label }}</span>
</span>
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="sortDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSort">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
sortDialogVisible: false,
sortMenuData: [],
defaultProps: {
children: "children",
label: "label"
}
}
},
methods: {
onOpen(platform) {
this.sortDialogVisible = true
this.$axios.post("/platform/sys/menu/menuAll", { platform }).then((res) => {
if (res.code === 0) {
this.sortMenuData = res.data
}
})
},
//排序树控制不可跨级拖拽
sortAllowDrop: function (moveNode, inNode, type) {
if (moveNode.data.parentId == inNode.data.parentId) {
return type == "prev"
}
},
//提交排序后的数据
doSort() {
const ids = []
const loading = this.$loading({
lock: true,
text: "正在提交...",
spinner: "el-icon-loading"
})
this.getTreeIds(ids, this.sortMenuData)
this.$axios
.post("/platform/sys/menu/sortDo", { ids: ids.toString() })
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.sortDialogVisible = false
this.$emit("refresh", null)
}
})
.finally(() => {
loading.close()
})
},
//递归获取所有的ID值
getTreeIds(ids, data) {
const self = this
data.forEach(function (obj) {
ids.push(obj.id)
if (obj.children && obj.children.length > 0) {
self.getTreeIds(ids, obj.children)
}
})
}
}
}
@@ -0,0 +1,181 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="平台">
<el-select v-model="pageForm.platform" :clearable="false" @change="doSearch">
<el-option v-for="item in dict.type.SYS_MENU_PLATFORM" :value="item.code" :key="item.value" :label="item.label"></el-option>
</el-select>
</search-item>
<search-item label="名称">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入名称" clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" type="primary" @click="openAdd">添加模块</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" align="center" header-align="center">
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='icon'">
<el-image lazy :src="row.icon" style="height: 30px; width: 30px" fit="cover">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</template>
<template scope="{row}" v-else-if="column.prop=='containsMenu'">
{{firstMenus.filter(v=>row.containsMenu.includes(v.id)).map(v=>v.name).join('、')}}
</template>
</el-table-column>
<el-table-column label="操作" width="200px">
<template scope="{row}">
<el-button @click="openEdit(row)" size="mini" type="primary">编辑</el-button>
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog :visible.sync="formDialogVisible" :title="formData.id ? '编辑模块' : '添加模块'">
<el-form :model="formData" :rules="formRules" label-width="120px" ref="form">
<el-form-item label="所属平台" prop="platform">
<el-select v-model="formData.platform" :clearable="false" @change="doSearch" placeholder="请选择平台">
<el-option v-for="item in dict.type.SYS_MENU_PLATFORM" :value="item.code" :key="item.value" :label="item.label"></el-option>
</el-select>
</el-form-item>
<el-form-item label="模块名称" prop="name">
<el-input v-model="formData.name" maxlength="8"></el-input>
</el-form-item>
<el-form-item label="模块图标" prop="icon">
<file-upload
:value.sync="formData.icon"
:upload_number="1"
upload_mode="image"
upload_result_category="interval"
upload_result_type="url"
></file-upload>
</el-form-item>
<el-form-item label="排序编号" prop="sortNum">
<el-input-number v-model="formData.sortNum" :min="1" :precision="0"></el-input-number>
</el-form-item>
</el-form>
<el-row type="flex" justify="end">
<el-button @click="formDialogVisible=false">取消</el-button>
<el-button type="primary" @click="doSubmit">确定</el-button>
</el-row>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
dicts: ["SYS_MENU_PLATFORM"],
mixins: [initTableMixins],
data() {
return {
formDialogVisible: false,
formData: {
id: null,
name: null,
icon: null,
sortNum: null
},
formRules: {
platform: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
name: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
icon: [{ required: true, message: "请填写", trigger: ["blur", "change"] }],
sortNum: [{ required: true, message: "请输入", trigger: ["blur", "change"] }]
},
firstMenus: [],
tableColumns: [
{ label: "排序编号", prop: "sortNum", sortable: true },
{ label: "所属平台", prop: "platform", sortable: true },
{ label: "模块名称", prop: "name" },
{ label: "模块图标", prop: "icon" }
],
pageForm: {}
}
},
watch: {
"formData.icon"(val) {
this.$refs.form.validateField("icon", (errMsg) => {
console.log(errMsg)
})
}
},
methods: {
async openAdd() {
if (this.$refs.form) {
this.$refs.form.resetFields()
}
this.formData = {
sortNum: this.tableData.length + 1
}
this.formDialogVisible = true
},
openEdit(row) {
this.formDialogVisible = true
this.$nextTick(() => {
this.formData = { ...row }
})
},
async doSubmit() {
const valid = await this.$refs.form.validate()
if (!valid) return
const { id } = this.formData
const url = loc() + (id ? "/update" : "/insert")
const resp = await this.$axios.post(url, this.formData)
if (resp.code === 0) {
this.pageData()
this.formDialogVisible = false
this.$message.success(resp.msg)
}
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post(loc() + "/delete", { id }).then((resp) => {
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg)
}
})
})
.catch(() => {})
}
},
created() {
setTimeout(() => {
if (this.dict.type.SYS_MENU_PLATFORM) {
this.pageForm.platform = this.dict.type.SYS_MENU_PLATFORM[0].code
this.pageData()
}
}, 500)
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,182 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-msg-active {
background-color: #546478;
color: #ffffff;
}
.note {
width: 100%;
height: 320px;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="消息类型:">
<el-select clearable placeholder="请选择消息类型" v-model="pageForm.searchType" style="width: 100%" @change="doSearch">
<el-option label="全部类型消息" value=""></el-option>
<el-option label="系统消息" value="system"></el-option>
<el-option label="用户消息" value="user"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="消息列表">
<el-button size="small" type="primary" icon="el-icon-plus" @click="openAdd">发送消息</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column align="center" header-align="center" label="消息类型" prop="type" sortable>
<template slot-scope="scope">
<span v-if="'system'==scope.row.type">系统消息</span>
<span v-if="'user'==scope.row.type">用户消息</span>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="标题" prop="title"></el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="消息内容" prop="note">
<template slot-scope="scope">
<el-link type="primary" @click="openViewNote(scope.row)">查看</el-link>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="总接收用户" prop="all_num">
<template slot-scope="scope">
<el-link type="primary" @click="viewUserList('all',scope.row.id)">{{scope.row.all_num}}</el-link>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="未读用户" prop="unread_num">
<template slot-scope="scope">
<el-link type="primary" @click="viewUserList('unread',scope.row.id)">{{scope.row.unread_num}}</el-link>
</template>
</el-table-column>
<el-table-column header-align="center" label="发送时间" prop="createdAt" sortable>
<template slot-scope="scope">{{$moment(scope.row.createdAt).format("YYYY-MM-DD HH:mm:ss")}}</template>
</el-table-column>
<el-table-column header-align="center" label="发送人" prop="createdAt" sortable>
<template slot-scope="scope">{{scope.row.username}}</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="消息状态" prop="delFlag" sortable>
<template slot-scope="scope">
<el-tag size="mini" type="error" v-if="scope.row.delFlag">已删除</el-tag>
<el-tag size="mini" type="success" v-if="!scope.row.delFlag">已发送</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="deleteDo(scope.row.id, scope.row.title)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<msg-form ref="msgForm" @back="back" :union-list="unionList" :unit-list="unitList" @parent-do-search="doSearch"></msg-form>
</template>
</guava>
<view-user ref="viewUser" :type="type" :id="id" :union-list="unionList" :unit-list="unitList"></view-user>
<el-dialog title="消息内容" :visible.sync="noteVisible" width="50%">
<div class="note" v-html="nodeData.note">
</div>
<file-preview complete_result :files="nodeData.files"></file-preview>
</el-dialog>
</div>
<script>
<!--#include("msgManage/msgManageForm.js"){}#-->
<!--#include("msgManage/viewUser.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {
"msg-form": MSG_FORM_TEMPLATE,
"view-user": VIEW_USER_TEMPLATE
},
data: function () {
return {
tableData: [],
pageForm: {
searchType: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
type: "",
id: "",
unionList: [],
unitList: [],
noteVisible: false,
nodeData: {}
}
},
methods: {
openViewNote(row) {
this.noteVisible = true
this.nodeData = {
note: row.note,
files: row.files
}
},
back() {
this.$refs.guava.index()
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
async pageData() {
const resp = await this.$axios.post("/platform/sys/msg/data", this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data.list
this.pageForm.totalCount = resp.data.totalCount
} else {
this.$message.warning(resp.msg)
}
},
openAdd() {
this.$refs.guava.edit()
this.$nextTick(() => {
this.$refs.msgForm.initAdd()
})
},
viewUserList(type, id) {
this.type = type
this.id = id
this.$refs.viewUser.open()
},
deleteDo(id, title) {
this.$confirm("您确定要删除" + title + "吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const resp = await this.$axios.post("/platform/sys/msg/delete/" + id)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
} else {
this.$message.warning(resp.msg)
}
})
}
},
created: async function () {
this.unitList = await this.$businessTool.listUnit()
this.unionList = await this.$businessTool.listUnion()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,264 @@
const MSG_FORM_TEMPLATE = {
template: `
<div>
<el-form :model="formData" ref="addForm" :rules="formRules" label-width="120px">
<el-form-item prop="title" label="标题">
<el-input maxlength="255" placeholder="请输入标题" v-model="formData.title"></el-input>
</el-form-item>
<el-form-item prop="url" label="链接地址">
<el-input placeholder="请输入链接地址" v-model="formData.url"></el-input>
</el-form-item>
<el-form-item prop="needBack" label="是否需要反馈">
<el-radio-group v-model="formData.needBack" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="type" label="消息类型">
<el-radio-group v-model="formData.type" size="small">
<!-- <el-radio border label="system">系统消息</el-radio>-->
<el-radio border label="user">用户消息</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="用户列表" v-if="'user'==formData.type">
<el-row class="mb10">
<el-button icon="el-icon-search" @click="openSelect" size="small">选择用户</el-button>
<el-button icon="el-icon-delete" @click="clearSelect" type="danger" size="small">清空用户</el-button>
</el-row>
<el-table :data="userTableData" style="width: 100%" size="mini" max-height="500">
<el-table-column fixed prop="loginname" label="工号" width="150"></el-table-column>
<el-table-column prop="username" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="人事编制" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column>
</el-table>
<p style="color: var(--color-primary)">总计:{{userTableData.length}}人</p>
</el-form-item>
<el-form-item prop="note" label="消息内容">
<text-editor v-model="formData.note"></text-editor>
</el-form-item>
<el-form-item prop="files" label="消息附件">
<file-upload
:value.sync="formData.files"
:upload_number="5"
upload_result_category="array"
complete_result
></file-upload>
</el-form-item>
<el-row class="mt20" justify="end" type="flex">
<el-button @click="back">取消</el-button>
<el-button type="primary" @click="doAdd">确定</el-button>
</el-row>
</el-form>
<el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="65%" append-to-body top="2%">
<div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 300px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginname"></el-option>
<el-option label="姓名" value="u.username"></el-option>
<el-option label="手机" value="u.mobile"></el-option>
</el-select>
</el-input>
<el-select v-model="pageForm.sex" placeholder="性别" clearable>
<el-option label="男" value="男"></el-option>
<el-option label="女" value="女"></el-option>
</el-select>
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits" placeholder="请选择所属工会" filterable clearable>
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable>
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-select v-model="pageForm.roleId" placeholder="请选择角色" filterable clearable>
<el-option v-for="item in roleList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-button icon="el-icon-search" @click="doSearch" type="primary"></el-button>
</div>
<div class="left-span-label mt20">人员列表</div>
<el-table
:data="tableData"
@selection-change="handleSelectionChange"
row-key="id"
ref="tableRef"
>
<el-table-column type="selection" reserve-selection width="35"></el-table-column>
<el-table-column fixed prop="loginname" label="工号" width="150"></el-table-column>
<el-table-column prop="username" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="50"></el-table-column>
<el-table-column prop="userState" label="在职状态" width="120"></el-table-column>
<el-table-column prop="personType" label="人员类型" width="120"></el-table-column>
<el-table-column prop="preparedBy" label="人事编制" width="120"></el-table-column>
<el-table-column prop="mobile" label="手机" width="120"></el-table-column>
<el-table-column prop="unitName" label="所属单位" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionName" label="所属工会" show-overflow-tooltip></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
<span slot="footer" class="dialog-footer">
<el-button @click="selectDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSelect">确 定</el-button>
</span>
</el-dialog>
</div>
`,
props: {
unionList: {
type: Array,
required: true
},
unitList: {
type: Array,
required: true
}
},
data() {
return {
roleList: [],
userTableData: [],
tableData: [],
pageForm: {
searchName: "u.username",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
formData: {},
formRules: {
title: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
note: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
needBack: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
type: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
},
selectDialogVisible: false,
selectUsers: []
}
},
computed: {},
methods: {
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.unitList = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.unitList = data
})
}
this.doSearch()
},
back() {
this.$emit("back")
},
parentDoSearch() {
this.$emit("parent-do-search")
},
doAdd() {
this.$refs["addForm"].validate((valid) => {
if (valid) {
const loginNames = this.userTableData.map((u) => u.loginname)
if (loginNames.length === 0 && this.formData.type === "user") {
this.$message.warning("请选择用户")
return false
}
if(loginNames.length > 100){
this.$message.warning("单条消息最多发送100人,请分批次发送。")
return false
}
this.$confirm('您确定要发送吗, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(()=>{
this.$axios
.post("/platform/sys/msg/addDo", {
msg: JSON.stringify(this.formData),
users: JSON.stringify(loginNames)
})
.then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.parentDoSearch()
this.back()
} else {
this.$message.error(resp.msg)
}
})
})
}
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
pageNumberChange(val) {
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange(val) {
this.pageForm.pageSize = val
this.pageData()
},
handleSelectionChange(val) {
this.selectUsers = val
},
initAdd() {
this.formData = {
id: "",
type: "user",
needBack: false
}
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
openSelect: function () {
this.selectDialogVisible = true
this.pageData()
},
clearSelect() {
this.userTableData = []
if(this.$refs.tableRef){
this.$refs.tableRef.clearSelection()
}
},
pageData() {
this.$axios.post("/platform/sys/msg/user_data", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
doSelect() {
const self = this
console.log(this.selectUsers)
console.log(this.userTableData)
const tableLoginNames = this.userTableData.map(v=>v.loginname)
this.selectUsers.forEach(function (o) {
if(!tableLoginNames.includes(o.loginname)){
self.userTableData.push(o)
}
})
if(this.$refs.tableRef){
this.$refs.tableRef.clearSelection()
}
this.selectDialogVisible = false
},
async getRoleList() {
const resp = await this.$axios.post("/platform/sys/msg/getRoleList")
return resp.data
}
},
async created() {
this.roleList = await this.getRoleList()
}
}
@@ -0,0 +1,123 @@
const VIEW_USER_TEMPLATE = {
template: `
<div>
<el-dialog :title="viewUserTitle" :visible.sync="viewDialogVisible" width="65%" top="2%">
<div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" size="small" @keyup.enter.native="doSearch" style="width: 300px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginname"></el-option>
<el-option label="姓名" value="u.username"></el-option>
<el-option label="手机" value="u.mobile"></el-option>
</el-select>
</el-input>
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits" placeholder="请选择所属工会" size="small" filterable clearable>
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" size="small" filterable clearable>
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-button icon="el-icon-search" @click="doSearch" size="small" type="primary"></el-button>
</div>
<div class="left-span-label mt20">{{viewUserTitle}}列表</div>
<el-table
:data="tableData"
style="width: 100%; margin-top: 10px; margin-bottom: 10px"
size="small"
>
<el-table-column fixed prop="loginname" label="工号" width="150"></el-table-column>
<el-table-column prop="username" label="姓名" width="120"></el-table-column>
<el-table-column prop="sex" label="性别" width="120"></el-table-column>
<el-table-column prop="mobile" label="联系方式"></el-table-column>
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
<span slot="footer" class="dialog-footer">
<el-button @click="viewDialogVisible = false">关 闭</el-button>
</span>
</el-dialog>
</div>
`,
props: {
type: {
type: String,
required: true
},
id: {
type: String,
required: true
},
unionList: {
type: Array,
required: true
},
unitList: {
type: Array,
required: true
}
},
data() {
return {
viewUserTitle: "",
viewDialogVisible: false,
tableData: [],
pageForm: {
searchName: "u.username",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
}
}
},
computed: {},
methods: {
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.unitList = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.unitList = data
})
}
this.doSearch()
},
open() {
this.viewDialogVisible = true
this.$nextTick(() => {
if ("all" === this.type) {
this.viewUserTitle = "全部用户"
}
if ("unread" === this.type) {
this.viewUserTitle = "未读用户"
}
this.pageForm.type = this.type
this.pageForm.id = this.id
this.doSearch()
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
pageNumberChange(val) {
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange(val) {
this.pageForm.pageSize = val
this.pageData()
},
pageData() {
this.$axios.post("/platform/sys/msg/user_view_data", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
async created() {}
}
@@ -0,0 +1,173 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style></style>
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<search @search="doSearch">
<search-item label="消息类型:">
<el-select clearable placeholder="请选择消息类型" v-model="pageForm.searchType" style="width: 100%" @change="getMsg">
<el-option label="全部类型消息" value="all"></el-option>
<el-option label="系统消息" value="system"></el-option>
<el-option label="用户消息" value="user"></el-option>
</el-select>
</search-item>
<search-item label="消息标题:">
<el-select placeholder="请选择消息标题" v-model="pageForm.msgId" style="width: 100%" @change="doSearch">
<el-option v-for="item in msgOptions" :key="item.id" :label="item.title" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="状态:">
<el-select placeholder="请选择状态" v-model="pageForm.readStatus" style="width: 100%" @change="doSearch">
<el-option label="全部" :value="null"></el-option>
<el-option label="未阅读" :value="0"></el-option>
<el-option label="已阅读未反馈" :value="1"></el-option>
<el-option label="已阅读无需反馈" :value="2"></el-option>
<el-option label="已阅读已反馈" :value="3"></el-option>
</el-select>
</search-item>
<search-item label="姓名/工号:">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" clearable>
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="mu.loginname"></el-option>
<el-option label="姓名" value="mu.userName"></el-option>
</el-select>
</el-input>
</search-item>
<search-item label="所属工会:">
<el-select v-model="pageForm.unionId" @change="flushUnits" @clear="flushUnits" placeholder="请选择所属工会" filterable clearable>
<el-option v-for="item in unionList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
<search-item label="所属单位:">
<el-select v-model="pageForm.unitId" placeholder="请选择所属单位" filterable clearable @change="doSearch">
<el-option v-for="item in unitList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="人员列表">
<el-button type="primary" @click="exportMultipleAsZip" size="small">导出压缩包</el-button>
</table-tool>
<el-table :data="tableData" size="small" style="width: 100%">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="loginname" label="工号"></el-table-column>
<!-- <el-table-column prop="sex" label="性别"></el-table-column>-->
<!-- <el-table-column prop="mobile" label="联系方式"></el-table-column>-->
<el-table-column prop="unitName" label="所属单位"></el-table-column>
<el-table-column prop="unionName" label="所属工会"></el-table-column>
<el-table-column prop="status" label="状态">
<template v-slot="scope">
<el-tag size="mini" v-if="0 === scope.row.status">未阅读</el-tag>
<el-tag size="mini" type="warning" v-else-if="1 === scope.row.status && scope.row.needBack">已阅读未反馈</el-tag>
<el-tag size="mini" type="success" v-else-if="1 === scope.row.status && !scope.row.needBack">已阅读无需反馈</el-tag>
<el-tag size="mini" v-else-if="2 === scope.row.status">已阅读已反馈</el-tag>
</template>
</el-table-column>
<el-table-column prop="backFiles" label="反馈附件">
<template v-slot="scope">
<el-link type="primary" v-if="scope.row.backFiles.length > 0" @click="viewFiles(scope.row)">点击查看</el-link>
<el-link type="info" v-else>暂无</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog :visible.sync="backDialogVisible" title="反馈附件" width="40%" top="2%">
<div style="width: 100%; text-align: center">
<file-preview :files="backFiles" complete_result></file-preview>
</div>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
backDialogVisible: false,
backFiles: [],
backFormData: {},
msgOptions: [],
pageForm: {
searchType: "all",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: "",
searchName: "mu.userName",
readType: null
},
unionList: [],
unitList: []
}
},
components: {},
methods: {
exportMultipleAsZip() {
this.$downLoad(loc() + "/exportMultipleAsZip", this.pageForm)
},
async flushUnits() {
this.$set(this.pageForm, "unitId", null)
this.unitList = []
if (this.pageForm.unionId) {
this.$businessTool.listUnit(this.pageForm.unionId).then((data) => {
this.unitList = data
})
}
this.doSearch()
},
viewFiles(row) {
this.backFiles = row.backFiles
this.backDialogVisible = true
},
async getMsg() {
const resp = await this.$axios.post("/platform/sys/msg/summary/getMsg", { searchType: this.pageForm.searchType })
this.msgOptions = resp.data
if (this.msgOptions && this.msgOptions.length > 0) {
this.pageForm.msgId = this.msgOptions[0].id
}
},
async pageData() {
const resp = await this.$axios.post("/platform/sys/msg/summary/pageData", this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data.list
this.tableData.forEach((item) => {
item.backFiles = item.backFiles ? JSON.parse(item.backFiles) : []
})
this.pageForm.totalCount = resp.data.totalCount
} else {
this.$message.warning(resp.msg)
}
}
},
async created() {
await this.getMsg()
const isAdmin = this.$auth.hasRoleOr(["SYSADMIN", "SCHOOL_UNION_ADMIN"])
if (isAdmin) {
this.$businessTool.listUnion(this.pageForm.unionId).then((data) => {
this.unionList = data
})
} else {
this.$businessTool.listUnion(this.$store.state.user.union.id).then((data) => {
this.unionList = data
})
}
this.unitList = await this.$businessTool.listUnit()
await this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,35 @@
<!--#
layout("/layouts/platform.html"){
#-->
<header class="header navbar bg-white shadow">
<div class="btn-group tool-button m5">
<a class="el-button el-button--default el-button--medium" href="${base}/platform/sys/msg/user/all" data-pjax>
<i class="ti-angle-left"></i>
返回
</a>
</div>
</header>
<div class="content-wrap">
<div class="wrapper" style="min-height: 500px">
<section class="panel">
<div class="row mb10">
<div class="col-lg-12">
<!--#if(!isEmpty(obj)){#-->
<div style="text-align: center">
<h4>${obj.title!}</h4>
</div>
<div style="text-align: center; font-size: 14px; line-height: 24px">${@date.getDate(obj.sendAt)}</div>
<div style="margin-top: 16px !important; border-bottom: 1px solid #ddd"></div>
<div style="margin-top: 16px !important">${obj.note!}</div>
<!--#}else{#-->
消息不存在,或您没有阅读权限!
<!--#}#-->
</div>
</div>
</section>
</div>
</div>
<!--#
}
#-->
@@ -0,0 +1,35 @@
<!--#
layout("/layouts/platform.html"){
#-->
<header class="header navbar bg-white shadow">
<div class="btn-group tool-button m5">
<a class="el-button el-button--default el-button--medium" href="${base}/platform/sys/msg/user/read" data-pjax>
<i class="ti-angle-left"></i>
返回
</a>
</div>
</header>
<div class="content-wrap">
<div class="wrapper" style="min-height: 500px">
<section class="panel">
<div class="row mb10">
<div class="col-lg-12">
<!--#if(!isEmpty(obj)){#-->
<div style="text-align: center">
<h4>${obj.title!}</h4>
</div>
<div style="text-align: center; font-size: 14px; line-height: 24px">${@date.getDate(obj.sendAt)}</div>
<div style="margin-top: 16px !important; border-bottom: 1px solid #ddd"></div>
<div style="margin-top: 16px !important">${obj.note!}</div>
<!--#}else{#-->
消息不存在,或您没有阅读权限!
<!--#}#-->
</div>
</div>
</section>
</div>
</div>
<!--#
}
#-->
@@ -0,0 +1,35 @@
<!--#
layout("/layouts/platform.html"){
#-->
<header class="header navbar bg-white shadow">
<div class="btn-group tool-button m5">
<a class="el-button el-button--default el-button--medium" href="${base}/platform/sys/msg/user/unread" data-pjax>
<i class="ti-angle-left"></i>
返回
</a>
</div>
</header>
<div class="content-wrap">
<div class="wrapper" style="min-height: 500px">
<section class="panel">
<div class="row mb10">
<div class="col-lg-12">
<!--#if(!isEmpty(obj)){#-->
<div style="text-align: center">
<h4>${obj.title!}</h4>
</div>
<div style="text-align: center; font-size: 14px; line-height: 24px">${@date.getDate(obj.sendAt)}</div>
<div style="margin-top: 16px !important; border-bottom: 1px solid #ddd"></div>
<div style="margin-top: 16px !important">${obj.note!}</div>
<!--#}else{#-->
消息不存在,或您没有阅读权限!
<!--#}#-->
</div>
</div>
</section>
</div>
</div>
<!--#
}
#-->
@@ -0,0 +1,202 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-msg-active {
background-color: #546478;
color: #ffffff;
}
</style>
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="消息类型:">
<el-select clearable placeholder="请选择消息类型" v-model="pageForm.searchType" style="width: 100%" @change="doSearch">
<el-option label="全部类型消息" value="all"></el-option>
<el-option label="系统消息" value="system"></el-option>
<el-option label="用户消息" value="user"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool label="消息列表">
<el-radio-group v-model="pageForm.status" @change="doSearch" size="small">
<el-radio-button label="all">全部消息</el-radio-button>
<el-radio-button label="read">已读消息</el-radio-button>
<el-radio-button label="unread">未读消息</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" style="width: 100%">
<el-table-column label="序号" type="index" :index="indexMethod" width="60"></el-table-column>
<el-table-column prop="type" label="消息类型" width="120">
<template v-slot="scope">
<span v-if="'system'===scope.row.type">系统消息</span>
<span v-if="'user'===scope.row.type">用户消息</span>
</template>
</el-table-column>
<el-table-column prop="title" label="标题" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="createdAt" label="接收时间">
<template slot-scope="scope">{{$moment(scope.row.createdAt).format("YYYY-MM-DD HH:mm:ss")}}</template>
</el-table-column>
<el-table-column prop="status" label="状态">
<template v-slot="scope">
<el-tag size="mini" v-if="0 === scope.row.status">未阅读</el-tag>
<el-tag size="mini" type="warning" v-else-if="1 === scope.row.status && scope.row.needBack">已阅读未反馈</el-tag>
<el-tag size="mini" type="success" v-else-if="1 === scope.row.status && !scope.row.needBack">已阅读无需反馈</el-tag>
<el-tag size="mini" v-else-if="2 === scope.row.status">已阅读已反馈</el-tag>
</template>
</el-table-column>
<el-table-column prop="backFiles" label="反馈附件">
<template v-slot="scope">
<el-link type="primary" v-if="scope.row.backFiles.length > 0" @click="viewFiles(scope.row)">点击查看</el-link>
<el-link type="info" v-else>暂无</el-link>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template v-slot="scope">
<el-button size="mini" type="primary" @click="openView(scope.row)">查看</el-button>
<el-button v-if="scope.row.needBack" size="mini" type="primary" @click="openBack(scope.row)">反馈</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<div style="text-align: center">
<h4>{{viewData.title}}</h4>
</div>
<div style="text-align: center; font-size: 14px; line-height: 24px">{{$moment(viewData.createdAt).format('YYYY-MM-DD HH:mm')}}</div>
<div style="margin-top: 16px !important; border-bottom: 1px solid #ddd"></div>
<div style="margin-top: 16px !important;" v-html="viewData.note"></div>
<file-preview complete_result :files="viewData.files"></file-preview>
</template>
</guava>
<el-dialog :visible.sync="backDialogVisible" title="反馈附件" width="40%" top="2%">
<el-form v-model="backFormData" ref="backFormRef" label-width="80px">
<el-form-item label="反馈附件" prop="files">
<file-upload
v-if="isViewFiles === false"
:value.sync="backFormData.files"
upload_mode="drag"
:upload_number="5"
upload_result_category="array"
complete_result
upload_mode="file"
></file-upload>
<div v-else style="width: 100%; text-align: center">
<file-preview :files="backFormData.files" complete_result></file-preview>
</div>
</el-form-item>
<el-form-item label="反馈内容" prop="backText">
<el-input v-model="backFormData.backText" type="textarea" :rows="4" placeholder="非必填" max="500" :readonly="isViewFiles"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer" v-if="isViewFiles === false">
<el-button @click="backDialogVisible = false">取消</el-button>
<el-button type="primary" @click="backDo">确定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data: function () {
return {
backFormData: {},
backFiles: [],
backDialogVisible: false,
viewData: {},
tableData: [],
pageForm: {
searchType: "all",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: "",
status: "unread"
},
isViewFiles: false
}
},
methods: {
viewFiles(row) {
this.isViewFiles = true
this.backFormData = {
files: row.backFiles,
backText: row.backText
}
this.backDialogVisible = true
},
async backDo() {
if (this.backFormData.files.length === 0) {
this.$message.warning("请上传反馈附件")
return
}
const resp = await this.$axios.post("/platform/sys/msg/user/backDo", {
id: this.backFormData.id,
backText: this.backFormData.backText,
files: JSON.stringify(this.backFormData.files)
})
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.backDialogVisible = false
} else {
this.$message.warning(resp.msg)
}
},
async openView(row) {
const resp = await this.$axios.post("/platform/sys/msg/user/findOne", { id: row.msgId })
this.viewData = resp.data
this.$refs.guava.view()
this.pageData()
window.webSocketPubSub.send(
JSON.stringify({
room: store.state.room,
action: "getMessage"
})
)
},
openBack(row) {
this.isViewFiles = false
this.backFormData = {
files: row.backFiles,
backText: row.backText,
id: row.id
}
this.backDialogVisible = true
},
async pageData() {
const resp = await this.$axios.post("/platform/sys/msg/user/data/" + this.pageForm.status, this.pageForm)
if (resp.code === 0) {
this.tableData = resp.data.list
this.tableData.forEach((item) => {
item.backFiles = item.backFiles ? JSON.parse(item.backFiles) : []
})
this.pageForm.totalCount = resp.data.totalCount
} else {
this.$message.warning(resp.msg)
}
},
formatAt: function (val) {
if (val && val > 0) return this.$moment(val).format("YYYY-MM-DD HH:mm")
return ""
}
},
created: function () {
this.pageForm.searchType = GetQueryString("type") ? GetQueryString("type") : "all"
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,209 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-msg-active {
background-color: #546478;
color: #ffffff;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<a
href="${base}/platform/sys/msg/user/read"
data-pjax
class="el-button el-button--default el-button--medium"
:class="{'el-msg-active':'all'==pageForm.searchType}"
>
全部类型消息
</a>
<a
href="${base}/platform/sys/msg/user/read?type=system"
data-pjax
class="el-button el-button--default el-button--medium"
:class="{'el-msg-active':'system'==pageForm.searchType}"
>
系统消息
<span v-if="unreadnum.system>0">({{unreadnum.system}})</span>
</a>
<a
href="${base}/platform/sys/msg/user/read?type=user"
data-pjax
class="el-button el-button--default el-button--medium"
:class="{'el-msg-active':'user'==pageForm.searchType}"
>
用户消息
<span v-if="unreadnum.user>0">({{unreadnum.user}})</span>
</a>
</el-card>
<el-card shadow="never">
<el-table
:data="tableData"
@sort-change="pageOrder"
size="small"
header-align="center"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="35"></el-table-column>
<el-table-column prop="status" width="45">
<template slot-scope="scope">
<span v-if="0==scope.row.status"><i class="fa fa-circle text-info ml5"></i></span>
</template>
</el-table-column>
<el-table-column prop="type" label="消息类型" header-align="center" align="center" width="120">
<template slot-scope="scope">
<span v-if="'system'==scope.row.type">系统消息</span>
<span v-if="'user'==scope.row.type">用户消息</span>
</template>
</el-table-column>
<el-table-column prop="title" label="标题" header-align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<a :href="'${base}/platform/sys/msg/user/read/detail/'+scope.row.msgid" data-pjax>{{scope.row.title}}</a>
</template>
</el-table-column>
<el-table-column prop="opat" label="接收时间" header-align="center" align="center">
<template slot-scope="scope">{{formatAt(scope.row.opat)}}</template>
</el-table-column>
</el-table>
<el-row class="el-pagination-container">
<el-pagination
style="float: left"
@size-change="pageSizeChange"
@current-change="pageNumberChange"
:current-page="pageForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageForm.totalCount"
></el-pagination>
</el-row>
</el-card>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
selectDialogVisible: false,
viewDialogVisible: false,
tableData: [],
pageForm: {
searchType: "${type!}",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "createdAt",
pageOrderBy: "descending"
},
formData: {
id: "",
type: "system"
},
selectData: [],
unreadnum: {
system: 0,
user: 0
}
}
},
methods: {
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/msg/user/data/read",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
formatAt: function (val) {
if (val && val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
handleSelectionChange: function (val) {
this.selectData = val
},
delMore: function () {
var self = this
if (self.selectData.length == 0) {
self.$message({
message: "请选择消息",
type: "warning"
})
return false
}
var ids = []
self.selectData.forEach(function (val) {
ids.push(val.id)
})
self.$confirm("您确定要删除选中的 " + ids.length + " 条消息? ", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/msg/user/delete",
{ ids: ids.toString() },
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.pageData()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
},
created: function () {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,302 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
.el-msg-active {
background-color: #546478;
color: #ffffff;
}
</style>
<div id="app" v-cloak>
<el-card shadow="never">
<a
href="${base}/platform/sys/msg/user/unread"
data-pjax
class="el-button el-button--default el-button--medium"
:class="{'el-msg-active':'all'==pageForm.searchType}"
>
全部类型消息
</a>
<a
href="${base}/platform/sys/msg/user/unread?type=system"
data-pjax
class="el-button el-button--default el-button--medium"
:class="{'el-msg-active':'system'==pageForm.searchType}"
>
系统消息
<span v-if="unreadnum.system>0">({{unreadnum.system}})</span>
</a>
<a
href="${base}/platform/sys/msg/user/unread?type=user"
data-pjax
class="el-button el-button--default el-button--medium"
:class="{'el-msg-active':'user'==pageForm.searchType}"
>
用户消息
<span v-if="unreadnum.user>0">({{unreadnum.user}})</span>
</a>
</el-card>
<el-card shadow="never">
<el-table
:data="tableData"
@sort-change="pageOrder"
size="small"
header-align="center"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="35"></el-table-column>
<el-table-column prop="status" width="45">
<template slot-scope="scope">
<span v-if="0==scope.row.status"><i class="fa fa-circle text-info ml5"></i></span>
</template>
</el-table-column>
<el-table-column prop="type" label="消息类型" header-align="center" align="center" width="120">
<template slot-scope="scope">
<span v-if="'system'==scope.row.type">系统消息</span>
<span v-if="'user'==scope.row.type">用户消息</span>
</template>
</el-table-column>
<el-table-column prop="title" label="标题" header-align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<a :href="'${base}/platform/sys/msg/user/unread/detail/'+scope.row.msgid" data-pjax>{{scope.row.title}}</a>
</template>
</el-table-column>
<el-table-column prop="opat" label="接收时间" header-align="center" align="center">
<template slot-scope="scope">{{formatAt(scope.row.opat)}}</template>
</el-table-column>
</el-table>
<el-row class="el-pagination-container">
<el-pagination
style="float: left"
@size-change="pageSizeChange"
@current-change="pageNumberChange"
:current-page="pageForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageForm.totalCount"
></el-pagination>
</el-row>
</el-card>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
selectDialogVisible: false,
viewDialogVisible: false,
tableData: [],
pageForm: {
searchType: "${type!}",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "createdAt",
pageOrderBy: "descending"
},
formData: {
id: "",
type: "system"
},
selectData: [],
unreadnum: {
system: 0,
user: 0
}
}
},
methods: {
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/msg/user/data/unread",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
formatAt: function (val) {
if (val && val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
handleSelectionChange: function (val) {
this.selectData = val
},
unreadData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/msg/user/unread_num",
{},
function (data) {
if (data.code == 0) {
self.unreadnum = data.data
}
},
"json"
)
},
readMore: function () {
var self = this
if (self.selectData.length == 0) {
self.$message({
message: "请选择消息",
type: "warning"
})
return false
}
var ids = []
self.selectData.forEach(function (val) {
ids.push(val.id)
})
self.$confirm("您确定要标记选中的 " + ids.length + " 条消息为已读吗? ", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/msg/user/status/read",
{ ids: ids.toString() },
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.pageData()
self.unreadData()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
},
readAll: function () {
var self = this
self.$confirm("您确定要标记全部消息为已读吗? ", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/msg/user/status/readAll",
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.pageData()
self.unreadData()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
},
delMore: function () {
var self = this
if (self.selectData.length == 0) {
self.$message({
message: "请选择消息",
type: "warning"
})
return false
}
var ids = []
self.selectData.forEach(function (val) {
ids.push(val.id)
})
self.$confirm("您确定要删除选中的 " + ids.length + " 条消息? ", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/msg/user/delete",
{ ids: ids.toString() },
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.pageData()
self.unreadData()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
},
created: function () {
this.pageData()
this.unreadData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,15 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-alert title="对不起,您没有权限访问该页面。" type="error"></el-alert>
</div>
<script>
new Vue({
el: "#app"
})
</script>
<!--#
}
#-->
@@ -0,0 +1,149 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-row type="flex">
<el-input v-model="pageForm.templateCode" maxlength="50" style="width: 400px" clearable placeholder="请输入模板代码"></el-input>
<el-button @click="doSearch" icon="el-icon-search" type="primary" class="ml10">搜索</el-button>
<el-button type="primary" @click="openAdd" style="margin-left: auto">新增模板</el-button>
</el-row>
</el-card>
<el-card shadow="never">
<el-table :data="tableData" border class="mt10" stripe ref="table" :height="tableHeight" id="officeTable">
<el-table-column label="序号" type="index" :index="indexMethod" width="70px"></el-table-column>
<el-table-column label="模板代码" prop="templateCode"></el-table-column>
<el-table-column label="模板名称" prop="templateName"></el-table-column>
<el-table-column label="模板路径" prop="templatePath" show-overflow-tooltip></el-table-column>
<el-table-column label="模板说明" prop="templateDesc"></el-table-column>
<el-table-column label="操作" width="300px">
<template scope="{row}">
<el-button size="mini" type="primary" @click="download(row.templatePath)">下载</el-button>
<el-button size="mini" type="primary" @click="preview(row)">预览</el-button>
<el-button size="mini" type="primary" @click="openEdit(row)">编辑</el-button>
<el-button size="mini" type="danger" @click="doDelete(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="模板" :visible.sync="dialogVisible" :close-on-click-modal="false" width="800px">
<el-form :model="formData" ref="ruleForm" :rules="formRules" label-width="80px">
<el-form-item label="模板文件" prop="file" :rules="[{required:true,message:'必传',trigger:['change']}]">
<file-upload :value.sync="formData.file" :upload_number="1" upload_result_category="array" complete_result></file-upload>
</el-form-item>
<el-form-item label="模板名称" prop="templateName" :rules="[{required:true,message:'必填',trigger:['change']}]">
<el-input type="text" v-model="formData.templateName" maxlength="50" placeholder="必填"></el-input>
</el-form-item>
<el-form-item label="模板代码" prop="templateCode" :rules="[{required:true,message:'必填',trigger:['change']}]">
<el-input type="text" v-model="formData.templateCode" maxlength="50" placeholder="请填写模板代码"></el-input>
</el-form-item>
<el-form-item label="模板说明" prop="templateDesc" :rules="[{required:true,message:'必填',trigger:['change']}]">
<el-input type="text" v-model="formData.templateDesc" maxlength="50" placeholder="请填写模板说明"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
dialogVisible: false,
tableHeight: 700,
formData: {
templateName: null
}
}
},
watch: {
"formData.file": {
handler: function (val) {
if (val) {
this.$set(this.formData, "templateName", val[0].name)
this.$set(this.formData, "templatePath", val[0].response.data)
} else {
this.$set(this.formData, "templateName", null)
this.$set(this.formData, "templatePath", null)
}
}
}
},
methods: {
openAdd() {
this.dialogVisible = true
this.formData = {}
},
openEdit(row) {
this.dialogVisible = true
this.formData = { ...row }
},
save() {
this.$refs.ruleForm.validate(async (valid) => {
if (valid) {
const formData = this.formData
// delete formData.file
this.$axios
.post(loc() + "/save", {
officeTemplate: JSON.stringify(this.formData)
})
.then((resp) => {
if (resp.code === 0) {
this.dialogVisible = false
this.$message.success(resp.msg)
this.pageData()
}
})
}
})
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(async () => {
const resp = await this.$axios.post(loc() + "/delete", { id })
if (resp.code === 0) {
this.$message.success(resp.msg)
this.pageData()
} else {
this.$message.warning(resp.msg)
}
})
},
download(path) {
window.open(path)
},
preview(row) {
this.$commonUtil.previewFile({
suffix: row.templateName.split(".").pop().toLocaleLowerCase(),
downloadPath: row.templatePath,
name: row.templateName,
id: row.templatePath.split("=").pop().toLocaleLowerCase()
})
}
},
mounted() {
setTimeout(() => {
this.tableHeight = window.innerHeight - document.querySelector("#officeTable").getBoundingClientRect().top - 80
}, 200)
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,775 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<el-row type="flex" style="column-gap: 10px">
<el-select v-model="pageForm.system_name" style="width: 180px" filterable clearable placeholder="请选择所属模块">
<el-option v-for="item in menuOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" style="width: 300px" @keyup.enter.native="doSearch">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 120px">
<el-option label="角色名称" value="`name`"></el-option>
<el-option label="角色标识" value="`code`"></el-option>
</el-select>
</el-input>
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword2" @keyup.enter.native="doSearch" style="width: 300px">
<el-select v-model="pageForm.searchName2" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="姓名" value="username"></el-option>
<el-option label="工号" value="loginname"></el-option>
</el-select>
</el-input>
<el-button icon="el-icon-search" @click="doSearch" type="primary"></el-button>
<div style="margin-left: auto">
<el-button size="medium" @click="openAdd" type="primary">
<i class="ti-plus"></i>
新建角色
</el-button>
<el-button @click="$refs.sortRef.onOpen()" size="medium" type="primary" icon="el-icon-sort">排序</el-button>
</div>
</el-row>
<!-- <div class="pull-right offscreen-right mt5 ml5">-->
<!-- <el-button size="medium" @click="doSettingMemberRole" type="primary"><i class="el-icon-s-tools"></i>-->
<!-- 一键设会员角色-->
<!-- </el-button>-->
<!-- </div>-->
<!-- <div class="pull-right offscreen-right mt5 ml5">-->
<!-- <el-button size="medium" @click="doPublic" type="primary">一键设置公共角色</el-button>-->
<!-- </div>-->
<!-- <div class="pull-right offscreen-right mt5 ml5">-->
<!-- <el-button size="medium" @click="openAdd" type="primary"><i class="ti-plus"></i> 新建角色</el-button>-->
<!-- </div>-->
<!-- <div class="pull-right offscreen-right mt5">-->
<!-- <el-button size="medium" @click="exportRoles" type="primary"><i class="el-icon-download"></i> 导出角色-->
<!-- </el-button>-->
<!-- </div>-->
</el-card>
<el-card shadow="never" class="mt10">
<el-table
:data="tableData"
@sort-change="pageOrder"
header-align="center"
:default-sort="{prop: 'serialNumber', order: 'ascending'}"
style="width: 100%"
>
<el-table-column sortable type="index" :index="indexMethod" label="序号" width="100px" align="center"></el-table-column>
<el-table-column sortable prop="name" label="角色名称" align="center"></el-table-column>
<el-table-column sortable prop="sort" label="排序编号" align="center"></el-table-column>
<el-table-column prop="code" sortable label="角色标识" align="center" :show-overflow-tooltip="true"></el-table-column>
<!-- <el-table-column prop="menuName" label="所属模块" align="center" :show-overflow-tooltip="true" sortable>-->
<!-- <template slot-scope="scope">
<span v-if="scope.row.unit==null" style="font-weight: bold">
系统角色
</span>
<span v-if="scope.row.unit!=null">
{{scope.row.unit.name}}
</span>
</template>-->
</el-table-column>
<el-table-column sortable prop="disabled" label="启用状态" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<i v-if="scope.row.disabled" class="fa fa-circle text-danger ml5"></i>
<i v-if="!scope.row.disabled" class="fa fa-circle text-success ml5"></i>
</template>
</el-table-column>
<el-table-column prop="useronline" label="操作" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'role',id:scope.row.id,name:scope.row.name}">查看系统权限</el-dropdown-item>
<el-dropdown-item :command="{type:'menu',id:scope.row.id,name:scope.row.name}">分配PC系统权限</el-dropdown-item>
<el-dropdown-item :command="{type:'h5_menu',id:scope.row.id,name:scope.row.name}">分配H5系统权限</el-dropdown-item>
<el-dropdown-item :command="{type:'user',id:scope.row.id,name:scope.row.name}">关联用户</el-dropdown-item>
<el-dropdown-item divided :command="{type:'enable',id:scope.row.id,name:scope.row.name,row:scope.row}">
启用
</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,name:scope.row.name,row:scope.row}">禁用</el-dropdown-item>
<el-dropdown-item divided :command="{type:'edit',id:scope.row.id}">修改</el-dropdown-item>
<el-dropdown-item
:command="{type:'delete',id:scope.row.id,name:scope.row.name}"
v-if="scope.row.code!='superadmin'&&scope.row.code!='public'"
>
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog append-to-body title="新建角色" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="70%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<!-- <el-form-item class="is-required" prop="system_name" label="所属系统" label-width="80px">-->
<!-- <el-select v-model="formData.system_name" style="width: 100%" filterable clearable placeholder="请选择">-->
<!-- <el-option v-for="item in menuOptions" :key="item.name" :label="item.name" :value="item.name"></el-option>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item prop="name" label="角色名称">
<el-input maxlength="50" placeholder="角色名称" v-model="formData.name" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="code" label="角色标识">
<el-input maxlength="150" placeholder="角色标识" v-model="formData.code" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<el-form-item prop="sort" label="排序编号">
<el-input-number placeholder="排序编号" v-model="formData.sort"></el-input-number>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
<!-- <el-form-item prop="" label="分配权限">-->
<!-- <el-row style="margin-bottom: 3px">-->
<!-- <el-button size="small" @click="addRoleSelAll">全选</el-button>-->
<!-- <el-button size="small" @click="addRoleSelClear">清空</el-button>-->
<!-- </el-row>-->
<!-- <el-tree ref="addMenuTree" :data="addMenuData" show-checkbox check-strictly node-key="id" :props="defaultProps">-->
<!-- <span class="custom-tree-node" slot-scope="scope">-->
<!-- <span>{{ scope.node.label }}</span>-->
<!-- <span>-->
<!-- <span v-if="scope.data.type=='menu'" style="font-weight: bold">菜单权限</span>-->
<!-- <span v-if="scope.data.type=='data'">数据权限</span>-->
<!-- </span>-->
<!-- </span>-->
<!-- </el-tree>-->
<!-- </el-form-item>-->
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog append-to-body title="修改角色" :visible.sync="editDialogVisible" :close-on-click-modal="false" width="40%">
<el-form :model="formData" ref="editForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="name" label="角色名称">
<el-input maxlength="50" placeholder="角色名称" v-model="formData.name" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="code" label="角色标识">
<el-input maxlength="150" placeholder="角色标识" v-model="formData.code" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<!-- <el-form-item prop="code" label="所属系统">-->
<!-- <el-select v-model="formData.system_name" style="width: 100%" filterable clearable placeholder="请选择">-->
<!-- <el-option v-for="item in menuOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item prop="sort" label="排序编号">
<el-input-number placeholder="排序编号" v-model="formData.sort"></el-input-number>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
<el-dialog :title="roleDialogTitle" :visible.sync="roleDialogVisible" width="70%">
<el-table :data="roleTableData" style="width: 100%" size="small" :highlight-current-row="true" row-key="id" lazy :load="loadRoleChild">
<el-table-column
label="菜单名称"
header-align="center"
prop="name"
width="200"
:show-overflow-tooltip="true"
align="left"
></el-table-column>
<el-table-column label="URL" header-align="center" prop="href" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="资源类型" header-align="center" prop="type" :show-overflow-tooltip="true" align="center">
<template slot-scope="scope">
<i v-if="scope.row.type=='menu'" style="font-weight: bold">菜单</i>
<i v-if="scope.row.type=='data'">数据</i>
</template>
</el-table-column>
<el-table-column label="权限标识" header-align="center" prop="permission" :show-overflow-tooltip="true"></el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="roleDialogVisible = false">关 闭</el-button>
</span>
</el-dialog>
<el-dialog append-to-body :title="menuDialogTitle" :visible.sync="menuDialogVisible" :close-on-click-modal="false" width="70%">
<el-row style="margin-bottom: 3px">
<el-button size="small" @click="menuRoleSelAll">全选</el-button>
<el-button size="small" @click="menuRoleSelClear">清空</el-button>
</el-row>
<el-tree
ref="doMenuTree"
:data="doMenuData"
:default-checked-keys="doMenuCheckedData"
check-strictly
show-checkbox
node-key="id"
check-strictly
:props="defaultProps"
>
<span class="custom-tree-node" slot-scope="scope">
<span>{{ scope.node.label }}</span>
<span>
<span v-if="scope.data.type=='menu'" style="font-weight: bold">菜单权限</span>
<span v-if="scope.data.type=='data'">数据权限</span>
</span>
</span>
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="menuDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doMenu">确 定</el-button>
</span>
</el-dialog>
<el-dialog append-to-body :title="userDialogTitle" :visible.sync="userDialogVisible" :close-on-click-modal="false" width="70%">
<div class="block mb10">
<el-select
size="small"
style="width: 60%"
class="span_n"
v-model="selUsers"
multiple
filterable
remote
default-first-option
reserve-keyword
:remote-method="remoteMethod"
:loading="loading"
placeholder="请输入用户名或姓名"
>
<el-option v-for="item in dbUsers" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
<el-button size="small" @click="userAddRole">将用户加入角色</el-button>
<div class="pull-right offscreen-right">
<el-button size="small" type="danger" @click="userDelRole">从角色中移除</el-button>
</div>
</div>
<el-table
:data="userTableData"
@sort-change="userPageOrder"
size="small"
header-align="center"
style="width: 100%"
@selection-change="userSelectionChange"
>
<el-table-column type="selection" width="35"></el-table-column>
<el-table-column sortable prop="loginname" label="用户名" header-align="center"></el-table-column>
<el-table-column prop="username" label="姓名" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="unitname" label="所属单位" header-align="center" align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column sortable prop="disabled" label="帐号状态" header-align="center" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<i v-if="scope.row.disabled" class="fa fa-circle text-danger ml5"></i>
<i v-if="!scope.row.disabled" class="fa fa-circle text-success ml5"></i>
</template>
</el-table-column>
<el-table-column sortable prop="useronline" label="在线状态" header-align="center" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<i v-if="scope.row.useronline" class="text-success ml5">在线</i>
<i v-if="!scope.row.useronline" class="text-danger ml5">离线</i>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="userPageSizeChange"
@current-change="userPageNumberChange"
:current-page="userForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="userForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="userForm.totalCount"
></el-pagination>
<span slot="footer" class="dialog-footer">
<el-button @click="userDialogVisible = false">关 闭</el-button>
</span>
</el-dialog>
<sort ref="sortRef" @refresh="doSearch"></sort>
</div>
<script>
<!--#include("sort.js"){}#-->
const vue = new Vue({
el: "#app",
dicts: ["SYS_MENU_PLATFORM"],
mixins: [initTableMixins],
components:{
sort:sort_component
},
data() {
const self = this
const validateName = function (rule, value, callback) {
const regex = new RegExp("^[a-zA-Z][a-zA-Z0-9_]{1,49}$")
if (!regex.test(value)) {
callback(new Error("角色标识以字母开头2-50字,允许使用字母/数字/下划线"))
} else {
callback()
}
}
const validateUnit = function (rule, value, callback) {
if (
self.parentUnit.length < 1 ||
self.parentUnit[self.parentUnit.length - 1] === "" ||
self.parentUnit[self.parentUnit.length - 1] === "root"
) {
callback(new Error("请选择所属单位!"))
} else {
callback()
}
}
return {
addDialogVisible: false,
editDialogVisible: false,
roleDialogVisible: false,
menuDialogVisible: false,
userDialogVisible: false,
treeData: {
label: "name",
children: "zones",
id: "id",
isLeaf: "leaf"
},
tableData: [],
menuOptions: [],
options: [],
parentUnit: [],
parentUnitSearch: [],
pageForm: {
searchUnit: "",
searchName: "`name`",
searchKeyword: "",
searchName2: "username",
searchKeyword2: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
formData: {
id: "",
unitid: "",
disabled: false,
menuIds: ""
},
formRules: {
// parentUnit: [{ validator: validateUnit, trigger: ["blur", "change"] }],
name: [{ required: true, message: "角色名称", trigger: ["blur", "change"] }],
code: [
{ required: true, message: "角色标识", trigger: ["blur", "change"] },
{ validator: validateName, trigger: ["blur", "change"] }
]
},
editRules: {
// parentUnit: [{ validator: validateUnit, trigger: ["blur", "change"] }],
name: [{ required: true, message: "角色名称", trigger: ["blur", "change"] }],
code: [
{ required: true, message: "角色标识", trigger: ["blur", "change"] },
{ validator: validateName, trigger: ["blur", "change"] }
]
},
roleDialogTitle: "查看角色权限",
menuDialogTitle: "分配角色菜单",
userDialogTitle: "分配用户",
roleTableData: [], //treeTable后台取出的数据
roleId: "", //当前角色ID
defaultProps: {
children: "children",
label: "label"
},
addMenuData: [],
doMenuData: [],
doMenuCheckedData: [], //已分配的权限选中状态
doCmsData: [],
doCmsCheckedData: [], //已分配的CMS权限
doCmsForm: {},
userForm: {
roleId: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
userTableData: [],
loading: false,
dbUsers: [], //分配用户
selUsers: [], //分配选中的用户
userSelection: [],
props: {
lazy: true,
checkStrictly: true,
multiple: false,
lazyLoad: (node, resolve) => {
this.$axios.post("/platform/sys/unit/tree", { pid: node.value }).then((res) => {
if (res.code === 0) {
resolve(res.data)
}
})
}
},
platform: ""
}
},
methods: {
exportRoles() {
this.$downLoad.post(loc() + "/exportRoles?" + this.pageForm)
},
doPublic() {
this.$confirm("确定要把所有用户加入公共角色吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(async () => {
const loading = this.$loading({
lock: true,
text: "正在提交...",
spinner: "el-icon-loading"
})
const resp = await this.$axios.post(loc() + "/doPublic")
loading.close()
})
},
doSettingMemberRole() {
this.$confirm("是否确定一键设置会员角色?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(async () => {
const { code, msg } = await this.$axios.post("/platform/sys/role/doSettingMemberRole")
if (code === 0) {
this.$message.success(msg)
}
})
.catch(() => {})
},
formatAt(val) {
if (val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
doSearch() {
let unit = this.parentUnitSearch[this.parentUnitSearch.length - 1]
if ("root" === unit) {
unit = ""
}
this.pageForm.searchUnit = unit
this.pageForm.pageNumber = 1
this.pageData()
},
addMenuLoad() {
this.$axios.post("/platform/sys/role/menuAll/", {}).then((res) => {
if (res.code === 0) {
this.addMenuData = res.data
}
})
},
doMenuLoad() {
this.$axios.post("/platform/sys/role/menuRole/" + this.roleId + "/" + this.platform, {}).then((res) => {
if (res.code === 0) {
this.doMenuData = res.data.menu
this.doMenuCheckedData = res.data.cmenu
}
})
},
userSelectionChange(val) {
this.userSelection = val
},
userPageOrder(column) {
//按字段排序
this.userForm.pageOrderName = column.prop
this.userForm.pageOrderBy = column.order
this.doUserLoad()
},
userPageNumberChange: function (val) {
//页码更新操作
this.userForm.pageNumber = val
this.doUserLoad()
},
userPageSizeChange: function (val) {
//分页大小更新操作
this.userForm.pageSize = val
this.doUserLoad()
},
remoteMethod(query) {
if (query !== "") {
this.loading = true
this.$axios
.post("/platform/sys/role/userSearch", {
query: query,
roleId: this.roleId
})
.then((res) => {
if (res.code === 0) {
this.dbUsers = res.data.list
}
this.loading = false
})
} else {
this.selUsers = []
}
},
doUserLoad() {
this.$axios.post("/platform/sys/role/user", this.userForm).then((res) => {
if (res.code === 0) {
this.userTableData = res.data.list
this.userForm.totalCount = res.data.totalCount
}
})
},
openAdd() {
this.addDialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
this.addMenuLoad()
},
doAdd() {
this.$refs["addForm"].validate((valid) => {
if (valid) {
// this.formData.menuIds = this.$refs["addMenuTree"].getCheckedKeys().toString()
// this.formData.unitid = this.parentUnit[this.parentUnit.length - 1] || ""
this.$axios.post("/platform/sys/role/addDo", this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.parentUnitSearch = []
this.doSearch()
this.addDialogVisible = false
}
})
}
})
},
doEdit() {
this.$refs["editForm"].validate((valid) => {
if (valid) {
this.$axios.post("/platform/sys/role/editDo", this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
this.editDialogVisible = false
}
})
}
})
},
doMenu() {
const ids = this.$refs["doMenuTree"].getCheckedKeys()
if (!ids || ids.length === 0) {
this.$message.warning("请选择菜单或数据权限")
return
}
const loading = this.$loading({
lock: true,
text: "正在提交...",
spinner: "el-icon-loading"
})
this.$axios
.post("/platform/sys/role/menuDo", {
roleId: this.roleId,
platform: this.platform,
menuIds: ids.toString()
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.menuDialogVisible = false
}
loading.close()
})
},
initRoleTreeTable() {
this.$axios.post("/platform/sys/role/menu/" + this.roleId, { pid: "" }).then((res) => {
if (res.code === 0) {
this.roleTableData = res.data
}
})
},
loadRoleChild(tree, treeNode, resolve) {
this.$axios.post("/platform/sys/role/menu/" + this.roleId, { pid: tree.id }).then((res) => {
if (res.code === 0) {
resolve(res.data)
}
})
},
dropdownCommand(command) {
//监听下拉框事件
if ("role" === command.type) {
this.roleDialogVisible = true
this.roleDialogTitle = "查看角色 【" + command.name + "】 的权限"
this.roleId = command.id
this.initRoleTreeTable()
}
if ("menu" === command.type) {
this.menuDialogTitle = "分配角色 【" + command.name + "】 的PC端权限"
this.menuDialogVisible = true
this.platform = "PC"
this.roleId = command.id
this.doMenuLoad()
}
if ("h5_menu" === command.type) {
this.menuDialogTitle = "分配角色 【" + command.name + "】 的H5端权限"
this.menuDialogVisible = true
this.platform = "H5"
this.roleId = command.id
this.doMenuLoad()
}
if ("user" === command.type) {
this.userDialogTitle = "分配角色 【" + command.name + "】 的用户"
this.userDialogVisible = true
this.roleId = command.id
this.userForm.roleId = command.id
this.doUserLoad()
}
if ("enable" === command.type || "disable" === command.type) {
this.$axios.post("/platform/sys/role/" + command.type + "/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
if ("disabled" === command.type) {
command.row.disabled = true
}
if ("enable" === command.type) {
command.row.disabled = false
}
}
})
}
if ("edit" === command.type) {
this.$axios.post("/platform/sys/role/edit/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.formData = res.data
this.editDialogVisible = true
}
})
}
if ("delete" === command.type) {
this.$confirm("此操作将删除 " + command.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/sys/role/delete/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
userAddRole() {
if (this.selUsers.length === 0) {
this.$message.warning("请选择用户")
return
}
this.$axios
.post("/platform/sys/role/usersAdd", {
roleId: this.roleId,
users: this.selUsers.toString()
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.selUsers = [] //清除已选择的用户
this.dbUsers = [] //清除数据库查询的用户,已添加到角色的用户不应该还存在so..
this.doUserLoad()
}
})
},
userDelRole() {
if (this.userSelection.length === 0) {
this.$message.warning("请选择用户")
return
}
const users = this.userSelection.map((user) => user.id)
this.$axios
.post("/platform/sys/role/usersDel", {
roleId: this.roleId,
users: users.toString()
})
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.selUsers = [] //清除已选择的用户
this.dbUsers = [] //清除数据库查询的用户,已添加到角色的用户不应该还存在so..
this.doUserLoad()
}
})
},
getTreeAllIds(ids, obj) {
const self = this
if (obj && obj.length > 0) {
obj.forEach(function (o) {
ids.push(o.id)
if (o.children) {
self.getTreeAllIds(ids, o.children)
}
})
}
},
addRoleSelAll() {
const ids = []
this.getTreeAllIds(ids, this.addMenuData)
this.$refs["addMenuTree"].setCheckedKeys(ids)
},
addRoleSelClear() {
this.$refs["addMenuTree"].setCheckedKeys([])
},
menuRoleSelAll() {
const ids = []
this.getTreeAllIds(ids, this.doMenuData)
this.$refs["doMenuTree"].setCheckedKeys(ids)
},
menuRoleSelClear() {
this.$refs["doMenuTree"].setCheckedKeys([])
},
clearButtons(list) {
for (let o of list) {
this.$set(o, "buttons", [])
if (o.hasChildren) {
this.clearButtons(o.children)
}
}
},
selParentChannel(list, pid, keys) {
const self = this
list.forEach(function (o) {
if (pid === o.id) {
keys.push(pid)
}
if (o.children) {
self.selParentChannel(o.children, pid, keys)
}
})
}
// async getMenuOptions() {
// const { data } = await $.get(loc() + "/getMenuOptions")
// this.menuOptions = data
// }
},
async created() {
this.pageData()
// await this.getMenuOptions()
}
})
</script>
<style>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
</style>
<!--#
}
#-->
@@ -0,0 +1,65 @@
const sort_component = {
template: `
<el-dialog title="排序" :visible.sync="sortDialogVisible" width="50%">
<el-tree ref="sortTreeRef" :data="sortData" draggable :allow-drop="sortAllowDrop" node-key="id"
style="height: 60vh;overflow-y: auto"
:props="defaultProps">
<span class="custom-tree-node" slot-scope="scope">
<span>{{ scope.node.label }}</span>
</span>
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button @click="sortDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doSort">确 定</el-button>
</span>
</el-dialog>
`,
data() {
return {
sortDialogVisible: false,
sortData: [],
defaultProps: {
children: "children",
label: "name"
}
}
},
methods: {
onOpen() {
this.sortDialogVisible = true
this.$axios.post("/platform/sys/role/sortData").then((res) => {
if (res.code === 0) {
this.sortData = res.data
}
})
},
sortAllowDrop(moveNode, inNode, type) {
return type !== "inner"
},
doSort() {
const loading = this.$loading({
lock: true,
text: "正在提交...",
spinner: "el-icon-loading"
})
const afterSorts = this.sortData.map((v) => {
return {
id: v.id,
name: v.name
}
})
this.$axios
.post("/platform/sys/role/doSort", { roles: JSON.stringify(afterSorts) })
.then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.sortDialogVisible = false
this.$emit("refresh", null)
}
})
.finally(() => {
loading.close()
})
}
}
}
@@ -0,0 +1,322 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<el-row type="flex" justify="end">
<el-button @click="openAdd" size="medium" type="primary">
<i class="ti-plus"></i>
新建路由
</el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%">
<el-table-column header-align="center" label="原路径" prop="url" sortable></el-table-column>
<el-table-column :show-overflow-tooltip="true" header-align="center" label="指向路径" prop="toUrl"></el-table-column>
<el-table-column align="center" header-align="center" label="转发方式" prop="type">
<template slot-scope="scope">
<span v-if="scope.row.type=='hide'">隐性转发</span>
<span v-if="scope.row.type=='show'">显性转发</span>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="启用状态" prop="disabled" sortable>
<template slot-scope="scope">
<i class="fa fa-circle text-danger ml5" v-if="scope.row.disabled"></i>
<i class="fa fa-circle text-success ml5" v-if="!scope.row.disabled"></i>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'enable',id:scope.row.id,name:scope.row.name,row:scope.row}">启用</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,name:scope.row.name,row:scope.row}">
禁用
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',id:scope.row.id}" divided>修改</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',id:scope.row.id,url:scope.row.url}">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog title="新建路由" :visible.sync="addDialogVisible" width="40%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="url" label="原路径">
<el-input maxlength="100" placeholder="原路径" v-model="formData.url" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="toUrl" label="指向路径">
<el-input placeholder="指向路径" v-model="formData.toUrl" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="type" label="指向路径">
<el-radio-group v-model="formData.type">
<el-radio label="hide">隐性转发</el-radio>
<el-radio label="show">显性转发</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="修改路由" :visible.sync="editDialogVisible" width="40%">
<el-form :model="formData" ref="editForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="url" label="原路径">
<el-input maxlength="100" placeholder="原路径" v-model="formData.url" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="toUrl" label="指向路径">
<el-input placeholder="指向路径" v-model="formData.toUrl" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="type" label="指向路径">
<el-radio-group v-model="formData.type">
<el-radio label="hide">隐性转发</el-radio>
<el-radio label="show">显性转发</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
formData: {
id: "",
type: "hide"
},
formRules: {
url: [{ required: true, message: "原路径", trigger: "blur" }],
toUrl: [{ required: true, message: "指向路径", trigger: "blur" }]
}
}
},
methods: {
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/route/data",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
formatAt: function (val) {
if (val && val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
doSearch: function () {
this.pageForm.pageNumber = 1
this.pageData()
},
openAdd: function () {
var self = this
this.addDialogVisible = true
this.formData = {
id: "",
type: "hide"
} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
doAdd: function () {
var self = this
self.$refs["addForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/route/addDo",
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.addDialogVisible = false
} else {
self.$message({
message: data.msg,
type: "error"
})
}
self.pageData() //添加失败也可以入库,所以加载一下看看
},
"json"
)
}
})
},
doEdit: function () {
var self = this
self.$refs["editForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/route/editDo",
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.doSearch() //查询是带条件的,加载新建用户选择的单位用户数据
//self.pageData();
self.editDialogVisible = false
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("enable" == command.type || "disable" == command.type) {
$.post(
base + "/platform/sys/route/" + command.type + "/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
if ("disable" == command.type) {
command.row.disabled = true
}
if ("enable" == command.type) {
command.row.disabled = false
}
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("edit" == command.type) {
$.post(
base + "/platform/sys/route/edit/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.formData = data.data //加载后台表单数据
self.editDialogVisible = true //打开编辑窗口
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("delete" == command.type) {
self.$confirm("此操作将删除 " + command.url, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/route/delete/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.doSearch()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
}
},
created: function () {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,84 @@
<!doctype html>
<html lang="en">
<head>
<title>签字</title>
<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" />
<script src="${base!}/assets/platform/plugins/vue/vue.js"></script>
<script src="${base!}/assets/platform/plugins/vue-http-loader/httpVueLoader.js"></script>
<script src="${base!}/assets/platform/plugins/smooth-signature/index.umd.min.js"></script>
<script src="${base!}/assets/platform/plugins/axios/axios.js"></script>
</head>
<body>
<div id="app">
<signature @save="save"></signature>
</div>
</body>
<script>
new Vue({
el: "#app",
components: {
signature: httpVueLoader("/components/plugins/sysSignature/index.vue?v=" + new Date().getTime())
},
data() {
return {}
},
methods: {
save(signature) {
const id = new URLSearchParams(window.location.search).get("id")
const origin = new URLSearchParams(window.location.search).get("origin")
if (!id && !origin) {
alert("参数错误")
return
}
const file = this.base64ToFile(signature, "signature.png")
const formData = new FormData()
formData.append("file", file)
formData.append("id", id)
formData.append("origin", origin)
const method = origin === "user" ? "/update" : "/saveSignature"
axios
.post("/platform/signature" + method, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then((res) => {
return res.data
})
.then((res) => {
if (res.code === 0) {
alert("保存成功")
} else {
alert("保存失败")
}
})
},
base64ToFile(base64Data, filename) {
// 将base64的数据部分提取出来
const parts = base64Data.split(";base64,")
const contentType = parts[0].split(":")[1]
const raw = window.atob(parts[1])
const rawLength = raw.length
const uInt8Array = new Uint8Array(rawLength)
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i)
}
// 使用Blob对象创建File对象
const blob = new Blob([uInt8Array], { type: contentType })
blob.lastModifiedDate = new Date()
blob.name = filename
return new File([blob], filename, { type: contentType })
}
}
})
</script>
</html>
@@ -0,0 +1,732 @@
<!doctype html>
<html>
<head>
<title>Cron表达式生成器</title>
<link href="${base}/assets/platform/cron/css/easyui.min.css" rel="stylesheet" type="text/css" />
<style type="text/css">
.line {
height: 25px;
line-height: 25px;
margin: 3px;
}
.imp {
padding-left: 25px;
}
.col {
width: 95px;
}
ul {
list-style: none;
padding-left: 10px;
}
li {
height: 20px;
}
body {
text-align: center; /*IE*/
text-align: -moz-center; /*Firefox*/
text-align: -webkit-center; /*Chrome*/
}
</style>
<script>
var base = "${base!}"
</script>
</head>
<body>
<div class="easyui-layout" style="width: 830px; height: 560px; border: 1px rgb(202, 196, 196) solid; border-radius: 5px">
<div style="height: 100%">
<div class="easyui-tabs" data-options="fit:true,border:false">
<div title="秒">
<div class="line">
<input type="radio" checked="checked" name="second" onclick="everyTime(this)" />
每秒 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="second" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:58" value="1" id="secondStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:59" value="2" id="secondEnd_0" />
</div>
<div class="line">
<input type="radio" name="second" onclick="startOn(this)" />
<input class="numberspinner" style="width: 60px" data-options="min:0,max:59" value="0" id="secondStart_1" />
秒开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:59" value="1" id="secondEnd_1" />
秒执行一次
</div>
<div class="line">
<input type="radio" name="second" id="sencond_appoint" />
指定
</div>
<div class="imp secondList">
<input type="checkbox" value="0" />
00
<input type="checkbox" value="1" />
01
<input type="checkbox" value="2" />
02
<input type="checkbox" value="3" />
03
<input type="checkbox" value="4" />
04
<input type="checkbox" value="5" />
05
<input type="checkbox" value="6" />
06
<input type="checkbox" value="7" />
07
<input type="checkbox" value="8" />
08
<input type="checkbox" value="9" />
09
</div>
<div class="imp secondList">
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
</div>
<div class="imp secondList">
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
<input type="checkbox" value="24" />
24
<input type="checkbox" value="25" />
25
<input type="checkbox" value="26" />
26
<input type="checkbox" value="27" />
27
<input type="checkbox" value="28" />
28
<input type="checkbox" value="29" />
29
</div>
<div class="imp secondList">
<input type="checkbox" value="30" />
30
<input type="checkbox" value="31" />
31
<input type="checkbox" value="32" />
32
<input type="checkbox" value="33" />
33
<input type="checkbox" value="34" />
34
<input type="checkbox" value="35" />
35
<input type="checkbox" value="36" />
36
<input type="checkbox" value="37" />
37
<input type="checkbox" value="38" />
38
<input type="checkbox" value="39" />
39
</div>
<div class="imp secondList">
<input type="checkbox" value="40" />
40
<input type="checkbox" value="41" />
41
<input type="checkbox" value="42" />
42
<input type="checkbox" value="43" />
43
<input type="checkbox" value="44" />
44
<input type="checkbox" value="45" />
45
<input type="checkbox" value="46" />
46
<input type="checkbox" value="47" />
47
<input type="checkbox" value="48" />
48
<input type="checkbox" value="49" />
49
</div>
<div class="imp secondList">
<input type="checkbox" value="50" />
50
<input type="checkbox" value="51" />
51
<input type="checkbox" value="52" />
52
<input type="checkbox" value="53" />
53
<input type="checkbox" value="54" />
54
<input type="checkbox" value="55" />
55
<input type="checkbox" value="56" />
56
<input type="checkbox" value="57" />
57
<input type="checkbox" value="58" />
58
<input type="checkbox" value="59" />
59
</div>
</div>
<div title="分钟">
<div class="line">
<input type="radio" checked="checked" name="min" onclick="everyTime(this)" />
分钟 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="min" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:58" value="1" id="minStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:59" value="2" id="minEnd_0" />
分钟
</div>
<div class="line">
<input type="radio" name="min" onclick="startOn(this)" />
<input class="numberspinner" style="width: 60px" data-options="min:0,max:59" value="0" id="minStart_1" />
分钟开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:59" value="1" id="minEnd_1" />
分钟执行一次
</div>
<div class="line">
<input type="radio" name="min" id="min_appoint" />
指定
</div>
<div class="imp minList">
<input type="checkbox" value="0" />
00
<input type="checkbox" value="1" />
01
<input type="checkbox" value="2" />
02
<input type="checkbox" value="3" />
03
<input type="checkbox" value="4" />
04
<input type="checkbox" value="5" />
05
<input type="checkbox" value="6" />
06
<input type="checkbox" value="7" />
07
<input type="checkbox" value="8" />
08
<input type="checkbox" value="9" />
09
</div>
<div class="imp minList">
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
</div>
<div class="imp minList">
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
<input type="checkbox" value="24" />
24
<input type="checkbox" value="25" />
25
<input type="checkbox" value="26" />
26
<input type="checkbox" value="27" />
27
<input type="checkbox" value="28" />
28
<input type="checkbox" value="29" />
29
</div>
<div class="imp minList">
<input type="checkbox" value="30" />
30
<input type="checkbox" value="31" />
31
<input type="checkbox" value="32" />
32
<input type="checkbox" value="33" />
33
<input type="checkbox" value="34" />
34
<input type="checkbox" value="35" />
35
<input type="checkbox" value="36" />
36
<input type="checkbox" value="37" />
37
<input type="checkbox" value="38" />
38
<input type="checkbox" value="39" />
39
</div>
<div class="imp minList">
<input type="checkbox" value="40" />
40
<input type="checkbox" value="41" />
41
<input type="checkbox" value="42" />
42
<input type="checkbox" value="43" />
43
<input type="checkbox" value="44" />
44
<input type="checkbox" value="45" />
45
<input type="checkbox" value="46" />
46
<input type="checkbox" value="47" />
47
<input type="checkbox" value="48" />
48
<input type="checkbox" value="49" />
49
</div>
<div class="imp minList">
<input type="checkbox" value="50" />
50
<input type="checkbox" value="51" />
51
<input type="checkbox" value="52" />
52
<input type="checkbox" value="53" />
53
<input type="checkbox" value="54" />
54
<input type="checkbox" value="55" />
55
<input type="checkbox" value="56" />
56
<input type="checkbox" value="57" />
57
<input type="checkbox" value="58" />
58
<input type="checkbox" value="59" />
59
</div>
</div>
<div title="小时">
<div class="line">
<input type="radio" checked="checked" name="hour" onclick="everyTime(this)" />
小时 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="hour" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:0,max:23" value="0" id="hourStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:23" value="2" id="hourEnd_1" />
小时
</div>
<div class="line">
<input type="radio" name="hour" onclick="startOn(this)" />
<input class="numberspinner" style="width: 60px" data-options="min:0,max:23" value="0" id="hourStart_1" />
小时开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:23" value="1" id="hourEnd_1" />
小时执行一次
</div>
<div class="line">
<input type="radio" name="hour" id="hour_appoint" />
指定
</div>
<div class="imp hourList">
AM:
<input type="checkbox" value="0" />
00
<input type="checkbox" value="1" />
01
<input type="checkbox" value="2" />
02
<input type="checkbox" value="3" />
03
<input type="checkbox" value="4" />
04
<input type="checkbox" value="5" />
05
<input type="checkbox" value="6" />
06
<input type="checkbox" value="7" />
07
<input type="checkbox" value="8" />
08
<input type="checkbox" value="9" />
09
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
</div>
<div class="imp hourList">
PM:
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
</div>
</div>
<div title="日">
<div class="line">
<input type="radio" checked="checked" name="day" onclick="everyTime(this)" />
日 允许的通配符[, - * / L W]
</div>
<div class="line">
<input type="radio" name="day" onclick="unAppoint(this)" />
不指定
</div>
<div class="line">
<input type="radio" name="day" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:31" value="2" id="dayEnd_0" />
</div>
<div class="line">
<input type="radio" name="day" onclick="startOn(this)" />
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayStart_1" />
日开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayEnd_1" />
天执行一次
</div>
<div class="line">
<input type="radio" name="day" onclick="workDay(this)" />
每月
<input class="numberspinner" style="width: 60px" data-options="min:1,max:31" value="1" id="dayStart_2" />
号最近的那个工作日
</div>
<div class="line">
<input type="radio" name="day" onclick="lastDay(this)" />
本月最后一天
</div>
<div class="line">
<input type="radio" name="day" id="day_appoint" />
指定
</div>
<div class="imp dayList">
<input type="checkbox" value="1" />
1
<input type="checkbox" value="2" />
2
<input type="checkbox" value="3" />
3
<input type="checkbox" value="4" />
4
<input type="checkbox" value="5" />
5
<input type="checkbox" value="6" />
6
<input type="checkbox" value="7" />
7
<input type="checkbox" value="8" />
8
<input type="checkbox" value="9" />
9
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
<input type="checkbox" value="13" />
13
<input type="checkbox" value="14" />
14
<input type="checkbox" value="15" />
15
<input type="checkbox" value="16" />
16
</div>
<div class="imp dayList">
<input type="checkbox" value="17" />
17
<input type="checkbox" value="18" />
18
<input type="checkbox" value="19" />
19
<input type="checkbox" value="20" />
20
<input type="checkbox" value="21" />
21
<input type="checkbox" value="22" />
22
<input type="checkbox" value="23" />
23
<input type="checkbox" value="24" />
24
<input type="checkbox" value="25" />
25
<input type="checkbox" value="26" />
26
<input type="checkbox" value="27" />
27
<input type="checkbox" value="28" />
28
<input type="checkbox" value="29" />
29
<input type="checkbox" value="30" />
30
<input type="checkbox" value="31" />
31
</div>
</div>
<div title="月">
<div class="line">
<input type="radio" checked="checked" name="mouth" onclick="everyTime(this)" />
月 允许的通配符[, - * /]
</div>
<div class="line">
<input type="radio" name="mouth" onclick="unAppoint(this)" />
不指定
</div>
<div class="line">
<input type="radio" name="mouth" onclick="cycle(this)" />
周期从
<input class="numberspinner" style="width: 60px" data-options="min:1,max:12" value="1" id="mouthStart_0" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:12" value="2" id="mouthEnd_0" />
</div>
<div class="line">
<input type="radio" name="mouth" onclick="startOn(this)" />
<input class="numberspinner" style="width: 60px" data-options="min:1,max:12" value="1" id="mouthStart_1" />
日开始,每
<input class="numberspinner" style="width: 60px" data-options="min:1,max:12" value="1" id="mouthEnd_1" />
月执行一次
</div>
<div class="line">
<input type="radio" name="mouth" id="mouth_appoint" />
指定
</div>
<div class="imp mouthList">
<input type="checkbox" value="1" />
1
<input type="checkbox" value="2" />
2
<input type="checkbox" value="3" />
3
<input type="checkbox" value="4" />
4
<input type="checkbox" value="5" />
5
<input type="checkbox" value="6" />
6
<input type="checkbox" value="7" />
7
<input type="checkbox" value="8" />
8
<input type="checkbox" value="9" />
9
<input type="checkbox" value="10" />
10
<input type="checkbox" value="11" />
11
<input type="checkbox" value="12" />
12
</div>
</div>
<div title="周">
<div class="line">
<input type="radio" checked="checked" name="week" onclick="everyTime(this)" />
周 允许的通配符[, - * / L #]
</div>
<div class="line">
<input type="radio" name="week" onclick="unAppoint(this)" />
不指定
</div>
<div class="line">
<input type="radio" name="week" onclick="startOn(this)" />
周期 从星期
<input class="numberspinner" style="width: 60px" data-options="min:1,max:7" id="weekStart_0" value="1" />
-
<input class="numberspinner" style="width: 60px" data-options="min:2,max:7" value="2" id="weekEnd_0" />
</div>
<div class="line">
<input type="radio" name="week" onclick="weekOfDay(this)" />
<input class="numberspinner" style="width: 60px" data-options="min:1,max:4" value="1" id="weekStart_1" />
周 的星期
<input class="numberspinner" style="width: 60px" data-options="min:1,max:7" id="weekEnd_1" value="1" />
</div>
<div class="line">
<input type="radio" name="week" onclick="lastWeek(this)" />
本月最后一个星期
<input class="numberspinner" style="width: 60px" data-options="min:1,max:7" id="weekStart_2" value="1" />
</div>
<div class="line">
<input type="radio" name="week" id="week_appoint" />
指定
</div>
<div class="imp weekList">
<input type="checkbox" value="1" />
1
<input type="checkbox" value="2" />
2
<input type="checkbox" value="3" />
3
<input type="checkbox" value="4" />
4
<input type="checkbox" value="5" />
5
<input type="checkbox" value="6" />
6
<input type="checkbox" value="7" />
7
</div>
</div>
<div title="年">
<div class="line">
<input type="radio" checked="checked" name="year" onclick="unAppoint(this)" />
不指定 允许的通配符[, - * /] 非必填
</div>
<div class="line">
<input type="radio" name="year" onclick="everyTime(this)" />
每年
</div>
<div class="line">
<input type="radio" name="year" onclick="cycle(this)" />
周期 从
<input class="numberspinner" style="width: 90px" data-options="min:2018,max:3000" id="yearStart_0" value="2018" />
-
<input class="numberspinner" style="width: 90px" data-options="min:2020,max:3000" id="yearEnd_0" value="2020" />
</div>
</div>
</div>
</div>
<div data-options="region:'south',border:false" style="height: 250px">
<fieldset style="border-radius: 3px; height: 220px">
<legend>表达式</legend>
<table style="height: 100px">
<tbody>
<tr>
<td></td>
<td align="center"></td>
<td align="center">分钟</td>
<td align="center">小时</td>
<td align="center"></td>
<td align="center">
<br />
</td>
<td align="center">星期</td>
<td align="center"></td>
</tr>
<tr>
<td>表达式字段:</td>
<td>
<input type="text" name="v_second" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_min" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_hour" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_day" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_mouth" class="col" value="*" readonly="readonly" />
</td>
<td>
<input type="text" name="v_week" class="col" value="?" readonly="readonly" />
</td>
<td>
<input type="text" name="v_year" class="col" readonly="readonly" />
</td>
</tr>
<tr>
<td>Cron 表达式:</td>
<td colspan="6"><input type="text" name="cron" style="width: 100%" value="* * * * * ?" id="cron" /></td>
<td><input type="button" value="反解析到UI " id="btnFan" onclick="btnFan()" /></td>
</tr>
<tr>
<td colspan="8">最近5次运行时间:</td>
</tr>
<tr>
<td colspan="8" id="runTime"></td>
</tr>
</tbody>
</table>
</fieldset>
</div>
<div></div>
</div>
<script src="${base}/assets/platform/plugins/jquery/jquery.js" type="text/javascript"></script>
<script src="${base}/assets/platform/cron/js/cron.js" type="text/javascript"></script>
</body>
</html>
@@ -0,0 +1,326 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<el-card shadow="never">
<el-row type="flex" justify="end">
<el-button @click="openAdd" size="medium" type="primary">
<i class="ti-plus"></i>
新建任务
</el-button>
</el-row>
</el-card>
<el-card class="mt10" shadow="never">
<el-table :data="tableData" @sort-change="pageOrder" header-align="center" style="width: 100%">
<el-table-column sortable prop="name" label="任务名称" header-align="center"></el-table-column>
<el-table-column prop="jobClass" label="执行类" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="data" label="执行参数" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="cron" label="定时规则" header-align="center" align="center"></el-table-column>
<el-table-column prop="exeAt" label="执行时间" header-align="center" align="center">
<template slot-scope="scope">{{formatAt(scope.row.exeAt)}}</template>
</el-table-column>
<el-table-column sortable prop="disabled" label="启用状态" header-align="center" align="center">
<template slot-scope="scope">
<i v-if="scope.row.disabled" class="fa fa-circle text-danger ml5"></i>
<i v-if="!scope.row.disabled" class="fa fa-circle text-success ml5"></i>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'enable',id:scope.row.id,name:scope.row.name,row:scope.row}">启用</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,name:scope.row.name,row:scope.row}">
禁用
</el-dropdown-item>
<el-dropdown-item divided :command="{type:'edit',id:scope.row.id}">修改</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',id:scope.row.id,name:scope.row.name}">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
<el-dialog title="新建任务" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="name" label="任务名称">
<el-input maxlength="100" placeholder="任务名称" v-model="formData.name" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="jobClass" label="执行类">
<el-input placeholder="执行类" v-model="formData.jobClass" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="cron" label="执行周期">
<el-input placeholder="Cron表达式" v-model="formData.cron" auto-complete="off" tabindex="3" type="text">
<template slot="append">
<a href="${base}/platform/sys/task/cron" style="color: #409eff" target="_blank">表达式生成器</a>
</template>
</el-input>
</el-form-item>
<el-form-item prop="data" label="执行参数(Json)">
<el-input type="textarea" v-model="formData.data" placeholder="{}" tabindex="4"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="修改任务" :visible.sync="editDialogVisible" :close-on-click-modal="false" width="50%">
<el-form :model="formData" ref="editForm" :rules="formRules" size="small" label-width="80px">
<el-form-item prop="name" label="任务名称">
<el-input maxlength="100" placeholder="任务名称" v-model="formData.name" auto-complete="off" tabindex="1" type="text"></el-input>
</el-form-item>
<el-form-item prop="jobClass" label="执行类">
<el-input placeholder="执行类" v-model="formData.jobClass" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="cron" label="执行周期">
<el-input placeholder="Cron表达式" v-model="formData.cron" auto-complete="off" tabindex="3" type="text">
<template slot="append">
<a href="${base}/platform/sys/task/cron" style="color: #409eff" target="_blank">表达式生成器</a>
</template>
</el-input>
</el-form-item>
<el-form-item prop="data" label="执行参数(Json)">
<el-input type="textarea" v-model="formData.data" placeholder="{}" tabindex="4"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
data: function () {
return {
addDialogVisible: false,
editDialogVisible: false,
tableData: [],
pageForm: {
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
formData: {
id: ""
},
formRules: {
name: [{ required: true, message: "任务名称", trigger: "blur" }],
jobClass: [{ required: true, message: "执行类", trigger: "blur" }],
cron: [{ required: true, message: "执行周期", trigger: "blur" }]
}
}
},
methods: {
pageOrder: function (column) {
//按字段排序
this.pageForm.pageOrderName = column.prop
this.pageForm.pageOrderBy = column.order
this.pageData()
},
pageNumberChange: function (val) {
//页码更新操作
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange: function (val) {
//分页大小更新操作
this.pageForm.pageSize = val
this.pageData()
},
pageData: function () {
//加载分页数据
var self = this
$.post(
base + "/platform/sys/task/data",
self.pageForm,
function (data) {
if (data.code == 0) {
self.tableData = data.data.list
self.pageForm.totalCount = data.data.totalCount
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
},
formatAt: function (val) {
if (val && val > 0) return moment(val).format("YYYY-MM-DD HH:mm:ss")
return ""
},
doSearch: function () {
this.pageForm.pageNumber = 1
this.pageData()
},
openAdd: function () {
var self = this
this.addDialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
doAdd: function () {
var self = this
self.$refs["addForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/task/addDo",
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.addDialogVisible = false
} else {
self.$message({
message: data.msg,
type: "error"
})
}
self.pageData() //添加失败也可以入库,所以加载一下看看
},
"json"
)
}
})
},
doEdit: function () {
var self = this
self.$refs["editForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/task/editDo",
self.formData,
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.doSearch() //查询是带条件的,加载新建用户选择的单位用户数据
//self.pageData();
self.editDialogVisible = false
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
},
dropdownCommand: function (command) {
//监听下拉框事件
var self = this
if ("enable" == command.type || "disable" == command.type) {
$.post(
base + "/platform/sys/task/" + command.type + "/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
if ("disable" == command.type) {
command.row.disabled = true
}
if ("enable" == command.type) {
command.row.disabled = false
}
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("edit" == command.type) {
$.post(
base + "/platform/sys/task/edit/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.formData = data.data //加载后台表单数据
self.editDialogVisible = true //打开编辑窗口
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
if ("delete" == command.type) {
self.$confirm("此操作将删除 " + command.name, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: function (a, b) {
if ("confirm" == a) {
//确认后再执行
$.post(
base + "/platform/sys/task/delete/" + command.id,
{},
function (data) {
if (data.code == 0) {
self.$message({
message: data.msg,
type: "success"
})
self.doSearch()
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
}
})
}
}
},
created: function () {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,163 @@
const branchUnionGroupManage = {
template: /*language=HTML*/ `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="可输入名称查询"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
></el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-plus" style="margin-left: auto"
@click="openAdd">
新增
</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border>
<el-table-column type="index" width="50" label="序号"></el-table-column>
<el-table-column prop="code" label="小组编码"></el-table-column>
<el-table-column prop="name" label="小组名称"></el-table-column>
<el-table-column prop="leaderUserName" label="组长姓名"></el-table-column>
<el-table-column prop="leaderMobile" label="组长电话"></el-table-column>
<el-table-column label="操作" width="200px">
<template slot-scope="{row}">
<el-button type="primary" size="mini" @click="onEdit(row)">
编辑
</el-button>
<el-button type="danger" size="mini" @click="onDelete(row.id)">
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog :title="formData.id ? '编辑' : '新增'" :visible.sync="dialogFormVisible" width="600px"
:close-on-click-modal="false">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="小组编码" prop="code">
<el-input v-model="formData.code" placeholder="小组编码" maxlength="10"
show-word-limit></el-input>
</el-form-item>
<el-form-item label="小组名称" prop="name">
<el-input v-model="formData.name" placeholder="小组名称" maxlength="100"></el-input>
</el-form-item>
<el-form-item label="小组长" prop="leader">
<el-select
v-model="formData.leader"
filterable
remote
reserve-keyword
placeholder="请输入姓名查询"
:remote-method="getUserOptions"
style="width: 100%">
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.username+'('+item.unitName+')'"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="onSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
props: {
union_id: {
type: String,
required: true
}
},
data() {
return {
pageForm: {},
formData: {},
rules: {
code: [{ required: true, message: "请输入小组编码", trigger: "blur" }],
name: [{ required: true, message: "请输入小组名称", trigger: "blur" }],
leader: [{ required: true, message: "请选择小组长", trigger: "change" }]
},
userOptions: []
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
this.$refs.formRef.clearValidate()
})
},
onEdit(row) {
this.formData = { ...row }
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs.formRef.clearValidate()
})
},
onSubmit() {
this.$refs.formRef.validate((valid) => {
if (valid) {
const { id } = this.formData
const url = "/platform/sys/unionGroup" + (id ? "/update" : "/insert")
$.post(url, { ...this.formData, unionId: this.union_id }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.dialogFormVisible = false
this.doSearch()
}
})
}
})
},
onDelete(id) {
this.$confirm("您确定要删除吗, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
$.post("/platform/sys/unionGroup/delete/" + id).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.pageData()
}
})
})
.catch(() => {})
},
pageData() {
$.get("/platform/sys/unionGroup/pageData", { ...this.pageForm, unionId: this.union_id }).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
},
getUserOptions(keyword) {
$.get("/platform/sys/unionGroup/listUser", { keyword, unionId: this.union_id }).then((res) => {
if (res.code === 0) {
this.userOptions = res.data
}
})
}
}
}
@@ -0,0 +1,118 @@
const branchUnionManage = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row :gutter="10" type="flex">
<el-input placeholder="请输入分工会名称" clearable size="small" style="width: 300px" v-model="pageForm.searchKeyword"></el-input>
<el-button type="primary" class="ml5" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<!-- <el-button icon="el-icon-s-check" type="primary" style="margin-left: auto" size="small">基层干部审核</el-button>-->
<el-button @click="openAdd" icon="ti-plus" type="primary" size="small" v-if="$auth.hasPermission('sys.manager.union.add')">新建分工会</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border>
<el-table-column label="序号" type="index" width="50" :index="indexMethod"></el-table-column>
<el-table-column prop="name" label="工会名称" show-overflow-tooltip></el-table-column>
<el-table-column prop="unionCode" label="工会编码"></el-table-column>
<el-table-column prop="campus" label="校区"></el-table-column>
<el-table-column prop="chairman" label="分工会主席" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="250" v-if="$auth.hasPermissionOr(['sys.manager.union.edit','sys.manager.union.delete'])">
<template scope="scope">
<!-- <el-button v-if="$auth.hasPermission('sys.manager.union.branchOfficer')" type="primary" size="mini">设置干部</el-button>-->
<el-button v-if="$auth.hasPermission('sys.manager.union.edit')" type="primary" size="mini" @click="openEdit(scope.row.id)">编辑</el-button>
<el-button v-if="$auth.hasPermission('sys.manager.union.delete')" type="danger" size="mini" @click="doDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-row class="el-pagination-container mt20">
<el-pagination
@size-change="pageSizeChange"
@current-change="pageNumberChange"
:current-page="pageForm.pageNumber"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="pageForm.totalCount"
></el-pagination>
</el-row>
</el-card>
<el-dialog :title="formData.id ? '编辑分工会' : '新增分工会'" :visible.sync="dialogFormVisible" width="600px">
<el-form :model="formData" ref="formRef" :rules="formRules" size="small" label-width="80px">
<el-form-item label="工会名称" prop="name">
<el-input v-model="formData.name" maxlength="100" placeholder="工会名称"></el-input>
</el-form-item>
<el-form-item label="工会编码" prop="unionCode">
<el-input v-model="formData.unionCode" maxlength="100" placeholder="工会编码"></el-input>
</el-form-item>
<el-form-item label="校区" prop="campus">
<dict-select v-model="formData.campus" code="CAMPUS"></dict-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
data() {
return {
dialogFormVisible: false,
formData: {},
formRules: {
name: [{ required: true, message: "请输入工会名称", trigger: ["change", "blur"] }],
unionCode: [{ required: true, message: "请输入工会编码", trigger: ["change", "blur"] }],
campus: [{ required: false, message: "请选择校区", trigger: ["change", "blur"] }]
}
}
},
methods: {
pageData() {
$.get("/platform/sys/union/pageData", this.pageForm).then((res) => {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
})
},
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
})
},
openEdit(id) {
this.dialogFormVisible = true
$.get("/platform/sys/union/findOne", { id }).then((res) => {
this.formData = res.data
})
},
doSubmit() {
this.$refs.formRef.validate((valid) => {
if (!valid) return
$.post("/platform/sys/union/" + (this.formData.id ? "update" : "insert"), this.formData).then((res) => {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.pageData()
this.$emit("refresh", null)
})
})
},
doDelete(id) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
$.post("/platform/sys/union/doDelete", { id }).then((res) => {
this.$message.success(res.msg)
this.pageData()
this.$emit("refresh", null)
})
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,104 @@
const branchUnionPartUnitManage = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="可输入名称查询"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
></el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-setting" style="margin-left: auto" @click="openAdd" v-if="$auth.hasPermission('sys.manager.union.partUnit')">设置组成单位</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border>
<el-table-column type="index" width="50" label="序号"></el-table-column>
<el-table-column prop="unitcode" label="单位编码"></el-table-column>
<el-table-column prop="name" label="单位名称"></el-table-column>
</el-table>
</el-card>
<el-dialog title="设置组成单位" :visible.sync="dialogFormVisible" width="1000px" :close-on-click-modal="false">
<el-transfer
ref="transferRef"
:titles="['可选二级单位', '当前成员单位']"
filterable
:props="{
key: 'id',
label: 'name'
}"
:filter-method="filterUnit"
v-model="selectUnitsIds"
:data="allUnits"
></el-transfer>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
props: {
union_id: {
type: String,
required: true
}
},
data() {
return {
dialogFormVisible: false,
selectUnitsIds: [],
allUnits: []
}
},
watch: {
union_id(val) {
// this.doSearch()
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
if (this.$refs.transferRef) {
this.$refs.transferRef.clearQuery("left")
this.$refs.transferRef.clearQuery("right")
}
$.get("/platform/sys/union/branchUnionPartUnitTransferData", { unionId: this.union_id }).then((res) => {
this.selectUnitsIds = res.data.selectUnitIds
this.allUnits = res.data.allUnits
})
},
filterUnit(query, item) {
return item.name.indexOf(query) > -1
},
doSubmit() {
$.post("/platform/sys/union/branchUnionPartUnitSet", {
unitIds: JSON.stringify(this.selectUnitsIds),
unionId: this.union_id
}).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
},
pageData() {
$.get("/platform/sys/union/branchUnionPartUnitPageData", { ...this.pageForm, unionId: this.union_id }).then((res) => {
if (res.code === 0) {
this.tableData = res.data
}
})
}
}
}
@@ -0,0 +1,140 @@
const branchUnionUserManage = {
template:
/*language=HTML*/
`
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="请输入内容"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
>
<el-select v-model="pageForm.searchName" slot="prepend" size="small" placeholder="查询类型"
style="width: 120px">
<el-option label="角色" value="roleName"></el-option>
<el-option label="姓名" value="username"></el-option>
<el-option label="工号" value="loginname"></el-option>
</el-select>
</el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-plus" style="margin-left: auto"
@click="openAdd" v-if="$auth.hasPermission('sys.manager.union.branchOfficer')">添加
</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border size="small">
<el-table-column prop="username" label="姓名"></el-table-column>
<el-table-column prop="loginname" label="工号"></el-table-column>
<el-table-column prop="roleName" label="角色"></el-table-column>
<el-table-column label="操作" width="100px"
v-if="$auth.hasPermission('sys.manager.union.branchOfficer')">
<template scope="scope">
<el-button size="mini" type="danger" icon="el-icon-delete"
@click="doDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
<el-form :model="formData" ref="form" size="small" label-width="80px">
<el-form-item prop="roleCode" label="角色">
<dict-select v-model="formData.roleCode" code="BRANCH_UNION_ROLES"></dict-select>
</el-form-item>
<el-form-item prop="userId" label="人员">
<user-select
v-model="formData.userId"
api="/platform/sys/union/listUserSelect"
:api_params="{ unionId: union_id }"
:option_label_func="
(item) => {
return item.username + item.loginname + '(' + item.unitName + ')'
}
"
></user-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
props: {
union_id: {
type: String,
required: true
}
},
data() {
return {
pageForm: {
searchName: "username"
},
dialogFormVisible: false,
formData: {}
}
},
watch: {
union_id(val) {
this.doSearch()
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
})
},
doSubmit() {
$.post("/platform/sys/union/insertBranchUnionUserRole", {
...this.formData,
unionId: this.union_id
}).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
},
doDelete({ userId, roleCode }) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then((res) => {
$.post("/platform/sys/union/deleteBranchUnionUserRole", {
userId,
roleCode,
unionId: this.union_id
}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
pageData() {
$.get("/platform/sys/union/branchUnionUserPageData", {
...this.pageForm,
unionId: this.union_id
}).then((res) => {
if (res.code === 0) {
this.tableData = res.data
}
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,149 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-row type="flex" :gutter="20" style="height: calc(100vh - 126px)">
<el-col :span="5">
<el-card shadow="never" style="height: 100%" body-style="{ height: '100%' }">
<el-input placeholder="输入关键字进行查找" v-model="filterText" clearable></el-input>
<div style="max-height: calc(100vh - 200px); overflow-y: auto">
<el-tree
:data="treeData"
ref="treeRef"
:expand-on-click-node="false"
:props="{
children: 'children',
label: 'name'
}"
default-expand-all
@node-click="treeNodeClick"
:filter-node-method="filterNode"
highlight-current
></el-tree>
</div>
</el-card>
</el-col>
<el-col :span="19">
<el-card shadow="never">
<el-tabs v-model="schoolUnionTabActive" type="card" v-if="currentTreeNode==null || currentTreeNode.level===1">
<el-tab-pane name="branchUnionManage">
<span slot="label">
<i class="el-icon-school"></i>
分工会信息
</span>
<sys-union-branch-union-manage @refresh="getTreeData()"></sys-union-branch-union-manage>
</el-tab-pane>
<el-tab-pane name="schoolUnionInfo">
<span slot="label">
<i class="el-icon-office-building"></i>
校工会信息
</span>
<sys-union-school-union-user-manage></sys-union-school-union-user-manage>
</el-tab-pane>
</el-tabs>
<el-tabs v-model="branchUnionTabActive" @tab-click="branchTabChange" type="card" v-if="currentTreeNode && currentTreeNode.level===2">
<el-tab-pane name="branchUnionUserManage">
<span slot="label">
<i class="el-icon-school"></i>
分工会干部
</span>
<sys-union-branch-union-user-manage
ref="branchUnionUserManageRef"
:union_id="currentTreeData.id"
></sys-union-branch-union-user-manage>
</el-tab-pane>
<el-tab-pane name="branchUnionPartUnitManage">
<span slot="label">
<i class="el-icon-school"></i>
组成单位
</span>
<sys-union-branch-union-part-unit-manage
ref="branchUnionPartUnitManageRef"
:union_id="currentTreeData.id"
></sys-union-branch-union-part-unit-manage>
</el-tab-pane>
<el-tab-pane name="branchUnionGroup">
<span slot="label">
<i class="el-icon-school"></i>
工会小组
</span>
<sys-union-branch-union-group-manage
ref="branchUnionGroupRef"
:union_id="currentTreeData.id"
></sys-union-branch-union-group-manage>
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
</el-row>
</div>
<script>
<!--#include("branchUnionManage.js"){}#-->
<!--#include("schoolUnionUserManage.js"){}#-->
<!--#include("branchUnionUserManage.js"){}#-->
<!--#include("branchUnionPartUnitManage.js"){}#-->
<!--#include("branchUnionGroupManage.js"){}#-->
new Vue({
el: "#app",
components: {
"sys-union-branch-union-manage": branchUnionManage,
"sys-union-school-union-user-manage": schoolUnionUserManage,
"sys-union-branch-union-user-manage": branchUnionUserManage,
"sys-union-branch-union-part-unit-manage": branchUnionPartUnitManage,
"sys-union-branch-union-group-manage": branchUnionGroupManage
},
data() {
return {
filterText: null,
treeData: [],
currentTreeNode: null,
currentTreeData: null,
schoolUnionTabActive: "branchUnionManage",
branchUnionTabActive: "branchUnionUserManage"
}
},
watch: {
filterText(val) {
this.$refs.treeRef.filter(val)
}
},
methods: {
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
if (node.level === 2) {
this.$nextTick(() => {
this.$refs[this.branchUnionTabActive + "Ref"].doSearch()
})
}
},
filterNode(value, data) {
if (!value) return true
return data.name.indexOf(value) !== -1
},
getTreeData() {
$.get(loc() + "/tree").then((res) => {
this.treeData = res.data
})
},
branchTabChange(val) {
this.$nextTick(() => {
this.$refs[val.name + "Ref"].doSearch()
})
}
},
created() {
this.getTreeData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,110 @@
const schoolUnionUserManage = {
template:
/*language=HTML*/
`
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="请输入内容"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
>
<el-select v-model="pageForm.searchName" size="small" slot="prepend" placeholder="查询类型"
style="width: 120px">
<el-option label="角色" value="roleName"></el-option>
<el-option label="姓名" value="username"></el-option>
<el-option label="工号" value="loginname"></el-option>
</el-select>
</el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-plus" style="margin-left: auto"
@click="openAdd">添加
</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border>
<el-table-column prop="username" label="姓名"></el-table-column>
<el-table-column prop="loginname" label="工号"></el-table-column>
<el-table-column prop="roleName" label="角色"></el-table-column>
<el-table-column label="操作" width="100px">
<template scope="scope">
<el-button size="mini" type="danger" icon="el-icon-delete"
@click="doDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
<el-form :model="formData" ref="form" size="small" label-width="80px">
<el-form-item prop="roleCode" label="角色">
<dict-select v-model="formData.roleCode" code="SCHOOL_UNION_ROLES"></dict-select>
</el-form-item>
<el-form-item prop="userId" label="人员">
<user-select v-model="formData.userId" api_input_key_name="query"></user-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
props: {},
data() {
return {
pageForm: {
searchName: "username"
},
dialogFormVisible: false,
formData: {}
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
})
},
doSubmit() {
$.post("/platform/sys/union/insertSchoolUnionUserRole", this.formData).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
},
doDelete({ userId, roleCode }) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then((res) => {
$.post("/platform/sys/union/deleteSchoolUnionUserRole", { userId, roleCode }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
pageData() {
$.get("/platform/sys/union/schoolUnionUserPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data
}
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,125 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style></style>
<div id="app" v-cloak>
<el-row type="flex" :gutter="20" style="height: calc(100vh - 126px)">
<el-col :span="5">
<el-card shadow="never">
<el-input placeholder="输入关键字进行查找" v-model="filterText" clearable></el-input>
<div style="max-height: calc(100vh - 200px); overflow-y: auto">
<el-tree
:data="treeData"
ref="treeRef"
:expand-on-click-node="false"
:props="{
children: 'children',
label: 'name'
}"
node-key="id"
:default-expanded-keys="['1']"
@node-click="treeNodeClick"
:filter-node-method="filterNode"
highlight-current
></el-tree>
</div>
</el-card>
</el-col>
<el-col :span="19">
<el-card v-if="currentTreeNode==null || currentTreeNode.level===1" shadow="never">
<unit-manage
:current-Node="currentTreeNode?.level"
:current-data="currentTreeData"
:unit-level="2"
@refresh="getTreeData()"
></unit-manage>
</el-card>
<el-card shadow="never" v-if="currentTreeNode && currentTreeNode.level===2">
<el-tabs v-model="unitTabActive" type="card">
<el-tab-pane name="threeUnitManage">
<span slot="label">
<i class="el-icon-school"></i>
三级单位
</span>
<unit-manage
:current-data="currentTreeData"
:unit-level="3"
:current-Node="currentTreeNode?.level"
@refresh="getTreeData()"
style="margin-top: 10px"
></unit-manage>
</el-tab-pane>
<el-tab-pane name="unitUserManage">
<span slot="label">
<i class="el-icon-school"></i>
单位人员
</span>
<unit-user :current-data="currentTreeData"></unit-user>
</el-tab-pane>
<el-tab-pane class="tab" name="unitLeaderManage">
<span slot="label">
<i class="el-icon-school"></i>
单位干部
</span>
<unit-leader-manage :current-data="currentTreeData"></unit-leader-manage>
</el-tab-pane>
</el-tabs>
</el-card>
</el-col>
</el-row>
</div>
<script>
<!--#include("unitUser.js"){}#-->
<!--#include("unitManage.js"){}#-->
<!--#include("unitLeader.js"){}#-->
new Vue({
el: "#app",
data: function () {
return {
unitTabActive: "threeUnitManage",
filterText: null,
currentTreeNode: null,
currentTreeData: null,
treeData: []
}
},
components: {
"unit-manage": UNIT_MANAGE_TEMPLATE,
"unit-user": UNIT_USER_MANAGE_TEMPLATE,
"unit-leader-manage": UNIT_LEADER_MANAGE_TEMPLATE
},
watch: {
filterText(val) {
this.$refs.treeRef.filter(val)
}
},
methods: {
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.currentTreeData = this.treeData[0]
}
})
},
treeNodeClick(data, node) {
if (node.level === 3) {
return
}
this.currentTreeData = data
this.currentTreeNode = node
},
filterNode(value, data, node) {
if (!value) return true
return data.name.indexOf(value) !== -1
}
},
created() {
this.getTreeData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,150 @@
const UNIT_LEADER_MANAGE_TEMPLATE = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row :gutter="10" type="flex">
<el-input placeholder="请输入内容" size="small" v-model="pageForm.searchKeyword"
clearable
@keyup.enter.native="doSearch" style="width: 300px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="姓名" value="username"></el-option>
<el-option label="工号" value="loginname"></el-option>
</el-select>
</el-input>
<el-button type="primary" class="ml5" size="small" icon="el-icon-search" @click="doSearch"></el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<table-tool label="人员列表">
<el-button @click="openAdd" type="primary" size="small">新增</el-button>
</table-tool>
<el-table :data="tableData" size="mini">
<el-table-column label="序号" type="index" width="60">
<template v-slot="scope">{{scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</template>
</el-table-column>
<el-table-column label="姓名" prop="username"></el-table-column>
<el-table-column label="工号" prop="loginname"></el-table-column>
<el-table-column label="角色" prop="roleName"></el-table-column>
<el-table-column label="操作" width="100px">
<template v-slot="scope">
<el-button size="mini" type="danger" @click="doDelete(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="添加" :visible.sync="dialogFormVisible" width="600px" :close-on-click-modal="false">
<el-form :model="formData" ref="form" size="small" label-width="60px">
<el-form-item prop="roleCode" label="角色">
<dict-select placeholder="请选择角色" v-model="formData.roleCode" code="UNIT_ROLES"></dict-select>
</el-form-item>
<el-form-item prop="userId" label="人员">
<user-select
placeholder="请选择人员"
style="width: 100%"
v-model="formData.userId"
api="/platform/sys/unit/listUserSelect"
:api_params="{ unitId: currentData?.id }"
:option_label_func="
(item) => {
return item.username + item.loginname + '(' + item.unitName + ')'
}
"
></user-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
props: {
currentData: {
type: Object,
required: false
}
},
data() {
return {
dialogFormVisible: false,
formData: {},
pageForm: {
unitName: "",
searchName: "username",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: "",
audit: false
},
tableData: []
}
},
computed: {},
methods: {
doDelete({ userId, roleCode }) {
this.$confirm("您确定要删除吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then((res) => {
$.post("/platform/sys/unit/deleteUnitUserRole", {
userId,
roleCode,
unitId: this.currentData.id
}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
},
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
})
},
doSubmit() {
$.post("/platform/sys/unit/insertUnitUserRole", {
...this.formData,
unitId: this.currentData.id
}).then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
},
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
pageNumberChange(val) {
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange(val) {
this.pageForm.pageSize = val
this.pageData()
},
pageData() {
this.pageForm.unitId = this.currentData.id
this.$axios.post(loc() + "/leaderPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,221 @@
const UNIT_MANAGE_TEMPLATE = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter);">
<el-row :gutter="10" type="flex">
<el-input placeholder="请输入单位名称" clearable size="small" style="width: 300px" v-model="pageForm.unitName"></el-input>
<el-button type="primary" class="ml5" size="small" icon="el-icon-search" @click="doSearch"></el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<table-tool label="单位列表">
<el-button @click="openAdd" type="primary" size="small">新建单位</el-button>
</table-tool>
<el-table :data="tableData" size="mini">
<el-table-column label="序号" type="index" width="60">
<template v-slot="scope">{{scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</template>
</el-table-column>
<el-table-column label="单位名称" prop="name"></el-table-column>
<el-table-column label="单位代码" prop="unitcode" width="200"></el-table-column>
<el-table-column label="单位等级" prop="unitLevel" width="100"></el-table-column>
<el-table-column label="操作" width="200px">
<template v-slot="scope">
<el-button size="mini" type="primary" @click="openEdit(scope.row.id)">编辑</el-button>
<el-button size="mini" type="danger" @click="doDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="设置单位" :visible.sync="dialogVisible" :close-on-click-modal="false" width="40%" top="2%">
<el-form :model="formData" ref="form" :rules="formRules" size="small" label-width="80px">
<el-form-item v-if="formData.id === '' || formData.id === null || currentNode === 1" prop="parentId" label="上级单位" label-width="80px">
<el-cascader :props="props" :options="options" v-model="parentUnit" placeholder="请选择上次单位,不选择则为顶级" style="width: 100%"></el-cascader>
</el-form-item>
<el-form-item v-else label="上级单位">
<el-input maxlength="100" disabled :value="currentData?.name" type="text"></el-input>
</el-form-item>
<el-form-item prop="name" label="单位名称">
<el-input maxlength="100" placeholder="请输入单位名称" v-model="formData.name" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<!-- <el-form-item prop="aliasName" label="单位别名">-->
<!-- <el-input maxlength="100" placeholder="请输入单位别名" v-model="formData.aliasName" auto-complete="off" tabindex="3" type="text"></el-input>-->
<!-- </el-form-item>-->
<el-form-item prop="unitcode" label="单位编码">
<el-input maxlength="100" placeholder="请输入单位编码" v-model="formData.unitcode" auto-complete="off" tabindex="4" type="text"></el-input>
</el-form-item>
<el-form-item prop="unitLevel" label="单位等级">
<el-select v-model="formData.unitLevel" placeholder="请输入单位等级" style="width: 100%">
<el-option v-if="unitLevel === 2" label="二级单位" :value="2"></el-option>
<el-option v-if="unitLevel === 3" label="三级单位" :value="3"></el-option>
</el-select>
</el-form-item>
<!-- <el-form-item prop="address" label="单位地址">-->
<!-- <el-input maxlength="100" placeholder="请输入单位地址" v-model="formData.address" auto-complete="off" tabindex="5" type="text"></el-input>-->
<!-- </el-form-item>-->
<!-- <el-form-item prop="telephone" label="联系电话">-->
<!-- <el-input maxlength="100" placeholder="请输入联系电话" v-model="formData.telephone" auto-complete="off" tabindex="6" type="text"></el-input>-->
<!-- </el-form-item>-->
<!-- <el-form-item prop="email" label="单位邮箱">-->
<!-- <el-input maxlength="100" placeholder="请输入单位邮箱" v-model="formData.email" auto-complete="off" tabindex="7" type="text"></el-input>-->
<!-- </el-form-item>-->
<!-- <el-form-item prop="website" label="单位网站">-->
<!-- <el-input maxlength="100" placeholder="请输入单位网站" v-model="formData.website" auto-complete="off" tabindex="8" type="text"></el-input>-->
<!-- </el-form-item>-->
<!-- <el-form-item prop="note" label="单位介绍">-->
<!-- <el-input type="textarea" v-model="formData.note" placeholder="请输入单位介绍"></el-input>-->
<!-- </el-form-item>-->
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doHandle">确 定</el-button>
</span>
</el-dialog>
</div>
`,
props: {
currentData: {
type: Object,
required: false
},
currentNode: {
type: Number,
required: false
},
unitLevel: {
type: Number,
required: true
}
},
data() {
return {
pageForm: {
unitName: "",
searchName: "",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: "",
audit: false
},
tableData: [],
dialogVisible: false,
formData: {},
formRules: {
name: [{ required: true, message: "必填", trigger: "blur" }],
unitcode: [{ required: true, message: "必填", trigger: "blur" }],
unitLevel: [{ required: true, message: "必填", trigger: "blur" }],
email: [
{ required: false, message: "单位邮箱", trigger: "blur" },
{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }
]
},
options: [],
parentUnit: [],
props: {
lazy: true,
checkStrictly: true,
multiple: false,
lazyLoad: function (node, resolve) {
var url = base + "/platform/sys/unit/cascaderData"
$.post(
url,
{ pid: node.value },
function (data) {
if (data.code === 0) {
resolve(data.data)
}
},
"json"
)
}
}
}
},
computed: {},
methods: {
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
openAdd() {
this.dialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
this.parentUnit = []
this.options = []
},
doHandle() {
const self = this
const url = this.formData.id ? "/platform/sys/unit/editDo" : "/platform/sys/unit/addDo"
this.$refs["form"].validate(async function (valid) {
if (valid) {
if (!self.formData.id) {
self.formData.parentId = self.parentUnit[self.parentUnit.length - 1] || ""
}
if (self.currentNode !== 1) {
self.formData.parentId = self.currentData.id
}
const resp = await self.$axios.post(url, self.formData)
if (resp.code === 0) {
self.$message.success(resp.msg)
self.doSearch()
self.dialogVisible = false
self.$emit("refresh", null)
} else {
self.$message.warning(resp.msg)
}
}
})
},
async openEdit(id) {
console.log(this.currentData)
const resp = await this.$axios.post("/platform/sys/unit/edit/" + id)
if (resp.code === 0) {
this.formData = resp.data
this.dialogVisible = true
} else {
this.$message.warning(resp.msg)
}
},
async doDelete(id) {
const confirm = await this.$confirm("此操作将永久删除, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post("/platform/sys/unit/delete/" + id)
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.$emit("refresh", null)
} else {
this.$message.warning(resp.msg)
}
}
},
pageNumberChange(val) {
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange(val) {
this.pageForm.pageSize = val
this.pageData()
},
pageData() {
this.pageForm.unitLevel = this.unitLevel
this.$axios.post(loc() + "/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,84 @@
const UNIT_USER_MANAGE_TEMPLATE = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row :gutter="10" type="flex">
<el-input placeholder="请输入内容" size="small" v-model="pageForm.searchKeyword"
clearable
@keyup.enter.native="doSearch" style="width: 300px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="姓名" value="username"></el-option>
<el-option label="工号" value="loginname"></el-option>
</el-select>
</el-input>
<el-button type="primary" class="ml5" size="small" icon="el-icon-search" @click="doSearch"></el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<table-tool label="人员列表">
</table-tool>
<el-table :data="tableData" size="mini">
<el-table-column label="序号" type="index" width="60">
<template v-slot="scope">{{scope.$index + (pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</template>
</el-table-column>
<el-table-column label="姓名" prop="username"></el-table-column>
<el-table-column label="工号" prop="loginname"></el-table-column>
<el-table-column label="性别" prop="sex"></el-table-column>
<el-table-column label="联系方式" prop="mobile"></el-table-column>
<el-table-column label="是否会员" prop="member"></el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
`,
props: {
currentData: {
type: Object,
required: false
}
},
data() {
return {
pageForm: {
unitName: "",
searchName: "username",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: "",
audit: false
},
tableData: []
}
},
computed: {},
methods: {
doSearch() {
this.pageForm.pageNumber = 1
this.pageData()
},
pageNumberChange(val) {
this.pageForm.pageNumber = val
this.pageData()
},
pageSizeChange(val) {
this.pageForm.pageSize = val
this.pageData()
},
pageData() {
this.pageForm.unitId = this.currentData.id
this.$axios.post(loc() + "/userPageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,90 @@
<div class="el-dialog__header">
<button type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close" class="el-dialog__headerbtn"><i
class="el-dialog__close el-icon el-icon-close"></i></button>
<h4 class="modal-title">${msg['index.custommenu']}</h4>
</div>
<div class="modal-body">
<div class="list-group" style="text-align: center;">
<table width="88%" id="menuTable">
<!--#
var firstMenus=@auth.getPrincipalProperty('firstMenus');
var secondMenus=@auth.getPrincipalProperty('secondMenus');
var customMenu=@auth.getPrincipalProperty('customMenu');
#-->
<!--#for(firstMenu in firstMenus){#-->
<tr>
<td width="20%" align="left"><strong><!--#if(lang=="zh_CN"){#-->${firstMenu.name}<!--#}else{#-->${firstMenu.aliasName}<!--#}#--></strong></td>
<td width="80%" align="left">
</td>
</tr>
<!--# if(!isEmpty(@secondMenus.get(firstMenu.path))){
for(secondMenu in @secondMenus.get(firstMenu.path)){
#-->
<tr>
<td width="20%" align="left" style="padding-left: 20px;"><!--#if(lang=="zh_CN"){#-->${secondMenu.name}<!--#}else{#-->${secondMenu.aliasName}<!--#}#--></td>
<td width="80%" align="left">
<!--# if(!isEmpty(@secondMenus.get(secondMenu.path))){
for(thMenu in @secondMenus.get(secondMenu.path)){ #-->
<input type="checkbox" value="${thMenu.id}" onclick="chk()" <!--#if(customMenu!=null&&@customMenu.indexOf(thMenu.id)>-1){#-->checked<!--#}#-->>
<!--#if(lang=="zh_CN"){#-->${thMenu.name}<!--#}else{#-->${thMenu.aliasName}<!--#}#-->
<!--#}}#-->
</td>
</tr>
<!--#}}#-->
<!--#}#-->
</table>
</div>
</div>
<div class="el-dialog__footer">
<span class="dialog-footer">
<button type="button" class="el-button el-button--default" data-dismiss="modal">
<span>${msg['system.cancel']}</span>
</button>
<button type="button" class="el-button el-button--primary" id="okCustom">
<span>${msg['system.confirm']}</span>
</button>
</span>
</div>
<script type="text/javascript">
function chk(){
var ids=[];
$("#menuTable").find("input[type=checkbox]").each(function(){
if($(this).prop("checked")){
ids.push($(this).val());
}
});
if(ids.length>5){
this.$message({
message: "最多可选择5个菜单",
type: 'error'
});
return ids;
}
return ids;
}
$(function () {
$("#okCustom").on("click",function(){
var ids =chk();
if (ids.length<6) {
$('#homeDetail').modal('hide');
$.post("${base}/platform/sys/user/customDo", {ids: ids.toString()}, function (data) {
if (data.code == 0) {
this.$message({
message: data.msg,
type: 'success'
});
setTimeout(function () {
window.location.reload();
},520);
} else {
this.$message({
message: data.msg,
type: 'error'
});
}
}, "json");
}
});
});
</script>
@@ -0,0 +1,461 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="单位">
<el-cascader :props="props" v-model="parentUnitSearch" placeholder="请选择单位" clearable></el-cascader>
</search-item>
<search-item>
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 120px">
<el-option label="工号" value="loginname"></el-option>
<el-option label="姓名" value="username"></el-option>
</el-select>
<el-button slot="append" icon="el-icon-search" @click="doSearch"></el-button>
</el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never">
<table-tool>
<el-button size="small" @click="openAdd" type="primary">
<i class="ti-plus"></i>
新建用户
</el-button>
</table-tool>
<el-table
:key="tableKey"
:data="tableData"
@sort-change="pageOrder"
header-align="center"
:default-sort="{prop: 'createdAt', order: 'descending'}"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="35"></el-table-column>
<el-table-column sortable prop="loginname" label="工号" header-align="center"></el-table-column>
<el-table-column prop="username" label="姓名" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="sex" label="性别" header-align="center" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="unitName" label="所属单位" header-align="center" align="center" :show-overflow-tooltip="true"></el-table-column>
<!-- <el-table-column sortable prop="disabled" label="帐号状态" header-align="center" align="center" :show-overflow-tooltip="true">-->
<!-- <template slot-scope="scope">-->
<!-- <i v-if="scope.row.disabled" class="fa fa-circle text-danger ml5"></i>-->
<!-- <i v-if="!scope.row.disabled" class="fa fa-circle text-success ml5"></i>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column sortable prop="userOnline" label="在线状态" header-align="center" align="center" :show-overflow-tooltip="true">-->
<!-- <template slot-scope="scope">-->
<!-- <i v-if="scope.row.userOnline" class="text-success ml5">在线</i>-->
<!-- <i v-if="!scope.row.userOnline" class="text-danger ml5">离线</i>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="userOnline" label="操作" width="120">
<template slot-scope="scope">
<el-dropdown @command="dropdownCommand">
<el-button size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'role',id:scope.row.id,loginname:scope.row.loginname}">查看权限</el-dropdown-item>
<el-dropdown-item :command="{type:'reset',id:scope.row.id,loginname:scope.row.loginname}">重置密码</el-dropdown-item>
<el-dropdown-item divided :command="{type:'enable',id:scope.row.id,row:scope.row}">启用</el-dropdown-item>
<el-dropdown-item :command="{type:'disable',id:scope.row.id,row:scope.row}">禁用</el-dropdown-item>
<el-dropdown-item divided :command="{type:'edit',id:scope.row.id}">修改</el-dropdown-item>
<el-dropdown-item
:command="{type:'delete',id:scope.row.id,loginname:scope.row.loginname}"
v-if="scope.row.loginname!='superadmin'"
>
删除
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog title="新建用户" :visible.sync="addDialogVisible" :close-on-click-modal="false" width="40%">
<el-form :model="formData" ref="addForm" :rules="formRules" size="small" label-width="80px">
<el-form-item class="is-required" prop="parentUnit" label="所属单位" label-width="80px">
<el-cascader :props="props" v-model="parentUnit" placeholder="请选择单位" style="width: 100%"></el-cascader>
</el-form-item>
<el-form-item prop="loginname" label="工号">
<el-input maxlength="100" placeholder="工号" v-model="formData.loginname" auto-complete="off" tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="username" label="姓名">
<el-input maxlength="20" placeholder="姓名" v-model="formData.username" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<el-form-item prop="password" label="登录密码">
<el-input
maxlength="20"
placeholder="登录密码"
v-model="formData.password"
auto-complete="off"
tabindex="4"
type="password"
></el-input>
</el-form-item>
<el-form-item prop="passwordAgain" label="确认密码">
<el-input
maxlength="20"
placeholder="再输一次密码"
v-model="formData.passwordAgain"
auto-complete="off"
tabindex="5"
type="password"
></el-input>
</el-form-item>
<el-form-item prop="mobile" label="手机号码">
<el-input maxlength="20" placeholder="手机号码" v-model="formData.mobile" auto-complete="off" tabindex="6" type="text"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doAdd">确 定</el-button>
</span>
</el-dialog>
<el-dialog title="编辑用户" :visible.sync="editDialogVisible" :close-on-click-modal="false" width="40%">
<el-form :model="formData" ref="editForm" :rules="editRules" size="small" label-width="80px">
<el-form-item prop="loginname" label="工号">
<el-input maxlength="100" placeholder="工号" v-model="formData.loginname" disabled tabindex="2" type="text"></el-input>
</el-form-item>
<el-form-item prop="username" label="姓名">
<el-input maxlength="20" placeholder="姓名" v-model="formData.username" auto-complete="off" tabindex="3" type="text"></el-input>
</el-form-item>
<el-form-item prop="mobile" label="手机号码">
<el-input maxlength="20" placeholder="手机号码" v-model="formData.mobile" auto-complete="off" tabindex="6" type="text"></el-input>
</el-form-item>
<el-form-item prop="disabled" label="启用状态">
<el-switch v-model="formData.disabled" active-color="#ff4949" inactive-color="#13ce66"></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="doEdit">确 定</el-button>
</span>
</el-dialog>
<el-dialog :title="roleDialogTitle" :visible.sync="roleDialogVisible" width="70%">
<el-table :data="roleTableData" style="width: 100%" size="small" :highlight-current-row="true" row-key="id" lazy :load="loadRoleChild">
<el-table-column
label="菜单名称"
header-align="center"
prop="name"
width="200"
:show-overflow-tooltip="true"
align="left"
></el-table-column>
<el-table-column label="URL" header-align="center" prop="href" :show-overflow-tooltip="true"></el-table-column>
<el-table-column label="资源类型" header-align="center" prop="type" :show-overflow-tooltip="true" align="center">
<template slot-scope="scope">
<i v-if="scope.row.type=='menu'" style="font-weight: bold">菜单</i>
<i v-if="scope.row.type=='data'">数据</i>
</template>
</el-table-column>
<el-table-column label="权限标识" header-align="center" prop="permission" :show-overflow-tooltip="true"></el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="roleDialogVisible = false">关 闭</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
const self = this
const validateLoginname = function (rule, value, callback) {
const regex = new RegExp("^[a-zA-Z0-9][a-zA-Z0-9]{1,19}$")
if (!regex.test(value)) {
callback(new Error("工号以字母开头2-20字,允许使用字母/数字"))
} else {
callback()
}
}
const validatePass = function (rule, value, callback) {
if (value !== self.formData.password) {
callback(new Error("两次输入密码不一致!"))
} else {
callback()
}
}
const validateUnit = function (rule, value, callback) {
if (
self.parentUnit.length < 1 ||
self.parentUnit[self.parentUnit.length - 1] === "" ||
self.parentUnit[self.parentUnit.length - 1] === "root"
) {
callback(new Error("请选择所属单位!"))
} else {
callback()
}
}
return {
addDialogVisible: false,
editDialogVisible: false,
roleDialogVisible: false,
treeData: {
label: "name",
children: "zones",
id: "id",
isLeaf: "leaf"
},
tableData: [],
tableKey: "",
options: [],
parentUnit: [],
parentUnitSearch: [],
pageForm: {
searchUnit: "",
searchName: "",
searchKeyword: "",
pageNumber: 1,
pageSize: 10,
totalCount: 0,
pageOrderName: "",
pageOrderBy: ""
},
formData: {
id: "",
unitId: "",
disabled: false
},
formRules: {
parentUnit: [{ validator: validateUnit, trigger: ["blur", "change"] }],
loginname: [
{ required: true, message: "工号", trigger: ["blur", "change"] },
{ validator: validateLoginname, trigger: ["blur", "change"] }
],
username: [{ required: true, message: "姓名", trigger: ["blur", "change"] }],
email: [
{ required: false, message: "邮箱地址", trigger: ["blur", "change"] },
{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }
],
mobile: [
{ required: false, message: "手机号码", trigger: ["blur", "change"] },
{ pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号码" }
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
{
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\S]{8,20}$/,
message: "密码必须8位及以上且包含大写字母、小写字母和数字",
trigger: "change"
},
{ min: 3, max: 20, message: "密码长度必须是3-20位", trigger: "change" }
],
passwordAgain: [
{ required: true, message: "请再次输入新密码", trigger: "blur" },
{
pattern: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\S]{8,20}$/,
message: "密码必须包含大写字母、小写字母和数字,并且长度在8-20之间",
trigger: "change"
},
{ validator: validatePass, trigger: "change" }
]
},
editRules: {
username: [{ required: true, message: "姓名", trigger: ["blur", "change"] }],
email: [
{ required: false, message: "邮箱地址", trigger: ["blur", "change"] },
{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }
],
mobile: [
{ required: false, message: "手机号码", trigger: ["blur", "change"] },
{ pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号码" }
]
},
roleDialogTitle: "查看用户权限",
roleTableData: [], //treeTable后台取出的数据
userId: "", //当前用户ID
multipleSelection: [],
props: {
lazy: true,
checkStrictly: true,
multiple: false,
value: "id",
lazyLoad: function (node, resolve) {
const url = base + "/platform/sys/unit/tree"
self.$axios.post(url, { pid: node.value }).then((res) => {
if (res.code === 0) {
resolve(res.data)
}
})
}
}
}
},
methods: {
formatAt: function (val) {
if (val > 0) return moment(val).format("YYYY-MM-DD HH:mm")
return ""
},
doSearch: function () {
let unit = this.parentUnitSearch[this.parentUnitSearch.length - 1]
if ("root" === unit) {
unit = ""
}
this.pageForm.searchUnit = unit
this.pageForm.pageNumber = 1
this.pageData()
},
openAdd() {
this.addDialogVisible = true
this.formData = {} //打开新增窗口,表单先清空
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
},
doAdd() {
this.$refs["addForm"].validate((valid) => {
if (valid) {
this.formData.unitId = this.parentUnit[this.parentUnit.length - 1] || ""
this.$axios.post("/platform/sys/user/addDo", this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.parentUnitSearch = []
this.doSearch()
this.addDialogVisible = false
}
})
}
})
},
doEdit() {
this.$refs["editForm"].validate((valid) => {
if (valid) {
this.$axios.post("/platform/sys/user/editDo", this.formData).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
this.editDialogVisible = false
}
})
}
})
},
initRoleTreeTable() {
this.$axios.post("/platform/sys/user/menu/" + self.userId, { pid: "" }).then((res) => {
if (res.code === 0) {
self.roleTableData = res.data
}
})
},
loadRoleChild(tree, treeNode, resolve) {
this.$axios.post("/platform/sys/user/menu/" + this.userId, { pid: tree.id }).then((res) => {
if (res.code === 0) {
resolve(res.data)
}
})
},
dropdownCommand(command) {
//监听下拉框事件
if ("role" === command.type) {
this.roleDialogVisible = true
this.roleDialogTitle = "查看用户 " + command.loginname + " 的权限"
this.userId = command.id
this.initRoleTreeTable()
}
if ("reset" === command.type) {
this.$confirm("确定重置用户" + command.loginname + "的密码", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$axios.post("/platform/sys/user/resetPwd/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.$alert("新密码为 " + res.data, "新密码", {
confirmButtonText: "确定"
})
}
})
})
.catch(() => {})
}
if ("enable" === command.type || "disable" === command.type) {
this.$axios.post("/platform/sys/user/" + command.type + "/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
if ("disable" === command.type) {
command.row.disabled = true
}
if ("enable" === command.type) {
command.row.disabled = false
}
}
})
}
if ("edit" === command.type) {
this.$axios.post(base + "/platform/sys/user/edit/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.formData = res.data //加载后台表单数据
this.editDialogVisible = true //打开编辑窗口
}
})
}
if ("delete" === command.type) {
this.$confirm("此操作将删除 " + command.loginname, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/sys/user/delete/" + command.id, {}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
},
batchCommand(command) {
if ("delete" === command.type) {
if (this.multipleSelection.length === 0) {
this.$message.warning("请选择要删除的用户")
return
}
const loginnames = []
const ids = []
this.multipleSelection.forEach(function (val) {
loginnames.push(val.loginname)
ids.push(val.id)
})
this.$confirm("此操作将删除用户 " + loginnames.toString(), "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/sys/user/delete", { ids: ids.toString() }).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
})
})
}
if ("export" === command.type) {
this.$downLoad.post("/platform/sys/user/export", this.pageForm)
}
},
handleSelectionChange(val) {
this.multipleSelection = val
}
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,87 @@
<div id="infoApp">
<div class="el-dialog__header">
<button type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close" class="el-dialog__headerbtn">
<i class="el-dialog__close el-icon el-icon-close"></i>
</button>
<h4 class="modal-title">个人资料</h4>
</div>
<div class="modal-body">
<el-form :model="infoForm" ref="infoForm" :rules="infoRules" label-width="100px">
<el-row style="padding-bottom: 2px">
<el-alert title="请完善个人资料" type="warning"></el-alert>
</el-row>
<el-form-item label="姓名" prop="username">
<el-input size="small" maxlength="20" placeholder="姓名" v-model="infoForm.username" auto-complete="off" tabindex="1"></el-input>
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input size="small" maxlength="11" placeholder="手机号码" v-model="infoForm.mobile" auto-complete="off" tabindex="2"></el-input>
</el-form-item>
<el-form-item label="电子邮箱" prop="email">
<el-input size="small" maxlength="50" placeholder="Email" v-model="infoForm.email" auto-complete="off" tabindex="3"></el-input>
</el-form-item>
</el-form>
</div>
<div class="el-dialog__footer">
<span class="dialog-footer">
<button type="button" class="el-button el-button--default" data-dismiss="modal">
<span>${msg['system.cancel']}</span>
</button>
<button type="button" class="el-button el-button--primary" @click="doInfo">
<span>${msg['system.confirm']}</span>
</button>
</span>
</div>
</div>
<script type="text/javascript">
new Vue({
el: "#infoApp",
data: function () {
return {
infoForm: {
username: "<!--#if(user.username!=user.mobile){#-->${user.username!}<!--#}#-->",
mobile: "${user.mobile!}",
email: "${user.email!}"
},
infoRules: {
username: [{ required: true, message: "请输入姓名", trigger: ["blur", "change"] }],
mobile: [
{ required: true, message: "请输入手机号码", trigger: ["blur", "change"] },
{ pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号码" }
],
email: [
{ required: true, message: "请输入Email", trigger: ["blur", "change"] },
{ type: "email", message: "请输入正确的Email" }
]
}
}
},
methods: {
doInfo: function () {
var self = this
self.$refs["infoForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/user/doChangeInfo",
self.infoForm,
function (data) {
if (data.code == 0) {
$("#homeDetail").modal("hide")
self.$message({
message: data.msg,
type: "success"
})
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
}
}
})
</script>
@@ -0,0 +1,60 @@
<div class="el-dialog__header">
<button type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close" class="el-dialog__headerbtn"><i
class="el-dialog__close el-icon el-icon-close"></i></button>
<h4 class="modal-title">${msg['index.user.mode']}</h4>
</div>
<div class="modal-body">
<form id="modeForm" role="form" class="form-horizontal parsley-form" method="post">
<div class="row" style="padding-top: 10px;">
<div class="col-lg-12">
<div class="form">
<div class="col-sm-8">
<input name="mode" value="true" type="radio"
<!--#if(@auth.getPrincipalProperty('loginPjax')){#-->checked<!--#}#--> > PJAX加载方式<br>优点:占用带宽少,加载速度快;<br>缺点:不能使用前进、后退功能。
</div>
</div>
</div>
</div>
<div class="row" style="padding-top: 10px;">
<div class="col-lg-12">
<div class="form">
<div class="col-sm-8">
<input name="mode" value="false" type="radio"
<!--#if(!@auth.getPrincipalProperty('loginPjax')){#-->checked<!--#}#--> > 传统加载方式<br>优点:可以使用前进、后退功能;<br>缺点:页面会重载、刷新,占用带宽大。
</div>
</div>
</div>
</div>
</form>
</div>
<div class="el-dialog__footer">
<span class="dialog-footer">
<button type="button" class="el-button el-button--default" data-dismiss="modal">
<span>${msg['system.cancel']}</span>
</button>
<button type="button" class="el-button el-button--primary" id="okMode">
<span>${msg['system.confirm']}</span>
</button>
</span>
</div>
<script type="text/javascript">
$(function () {
$("#okMode").on("click", function () {
$.post("${base}/platform/sys/user/modeDo", {mode: $("input[type='radio'][name='mode']:checked").val()}, function (data) {
if (data.code == 0) {
$('#homeDetail').modal('hide');
this.$message({
message: data.msg,
type: 'success'
});
} else {
this.$message({
message: data.msg,
type: 'error'
});
}
}, "json");
});
});
</script>
@@ -0,0 +1,116 @@
<div id="passApp">
<div class="el-dialog__header">
<button type="button" data-dismiss="modal" aria-hidden="true" aria-label="Close" class="el-dialog__headerbtn">
<i class="el-dialog__close el-icon el-icon-close"></i>
</button>
<h4 class="modal-title">${msg['index.user.password']}</h4>
</div>
<div class="modal-body">
<el-form :model="passForm" ref="passForm" :rules="passRules" label-width="100px">
<el-form-item label="${msg['index.user.oldpass']}" prop="oldPassword">
<el-input
size="small"
maxlength="20"
placeholder="${msg['index.user.oldpass']}"
v-model="passForm.oldPassword"
auto-complete="off"
tabindex="1"
type="password"
></el-input>
</el-form-item>
<el-form-item label="输入新密码" prop="newPassword">
<el-input
size="small"
maxlength="20"
placeholder="${msg['index.user.newpass']}"
v-model="passForm.newPassword"
auto-complete="off"
tabindex="2"
type="password"
></el-input>
</el-form-item>
<el-form-item label="确认新密码" prop="passwordAgain">
<el-input
size="small"
maxlength="20"
placeholder="${msg['index.user.rightpass']}"
v-model="passForm.passwordAgain"
auto-complete="off"
tabindex="3"
type="password"
></el-input>
</el-form-item>
</el-form>
</div>
<div class="el-dialog__footer">
<span class="dialog-footer">
<button type="button" class="el-button el-button--default" data-dismiss="modal">
<span>${msg['system.cancel']}</span>
</button>
<button type="button" class="el-button el-button--primary" @click="doPass">
<span>${msg['system.confirm']}</span>
</button>
</span>
</div>
</div>
<script type="text/javascript">
new Vue({
el: "#passApp",
data: function () {
var self = this
var validatePass = function (rule, value, callback) {
if (value !== self.passForm.newPassword) {
callback(new Error("两次输入密码不一致!"))
} else {
callback()
}
}
return {
passForm: {
oldPassword: "",
newPassword: "",
passwordAgain: ""
},
passRules: {
oldPassword: [{ required: true, message: "请输入原密码", trigger: "blur" }],
newPassword: [
{ required: true, message: "请输入新密码", trigger: "blur" },
{ min: 3, max: 20, message: "密码长度必须是3-20位", trigger: "change" }
],
passwordAgain: [
{ required: true, message: "请再次输入新密码", trigger: "blur" },
{ validator: validatePass, trigger: "change" }
]
}
}
},
methods: {
doPass: function () {
var self = this
self.$refs["passForm"].validate(function (valid) {
if (valid) {
$.post(
base + "/platform/sys/user/doChangePassword",
self.passForm,
function (data) {
if (data.code == 0) {
$("#homeDetail").modal("hide")
self.$message({
message: data.msg,
type: "success"
})
} else {
self.$message({
message: data.msg,
type: "error"
})
}
},
"json"
)
}
})
}
}
})
</script>
@@ -0,0 +1,630 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch()">
<search-item label="">
<el-checkbox-group @change="doSearch" v-model="pageForm.isMenWomen">
<el-checkbox-button :key="2" :label="2">男子</el-checkbox-button>
<el-checkbox-button :key="3" :label="3">女子</el-checkbox-button>
<el-checkbox-button :key="4" :label="4">个人</el-checkbox-button>
<el-checkbox-button :key="5" :label="5">团体</el-checkbox-button>
</el-checkbox-group>
</search-item>
<search-item label="比赛组别">
<el-select @focus="focusGroup" clearable placeholder="请选择比赛组别"
style="width: 100%" v-model="pageForm.group">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in groupList"></el-option>
</el-select>
</search-item>
<search-item label="运动类型">
<el-select
@focus="exerciseType"
clearable
filterable
placeholder="请选择运动类型"
style="width: 100%"
v-model="pageForm.events"
>
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in exerciseTypeList"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="比赛项目列表">
<el-input @input="ageInput" placeholder="输入年龄算出身年" size="small"
style="width: auto" type="number" v-model="pageForm.age">
<template slot="prepend">年龄计算器</template>
</el-input>
<el-tag class="ml10">{{ pageForm.ageYear }}</el-tag>
<el-date-picker
class="ml10"
end-placeholder="结束日期"
format="yyyy 年 MM 月 dd 日"
range-separator="-"
size="small"
start-placeholder="开始日期"
type="daterange"
v-model="pageForm.ageDate"
value-format="yyyy-MM-dd"
></el-date-picker>
<el-button @click="doAssignmentDate" class="ml10" icon="el-icon-check"
size="small" type="primary">统赋年龄限制
</el-button>
<el-button @click="openAdd" icon="el-icon-edit-outline" size="small"
type="primary">创建比赛项目
</el-button>
</table-tool>
<el-table
:data="tableData"
:size="tableSize"
@selection-change="handleSelectionChange"
@sort-change="pageOrder"
class="vi-table"
ref="multipleTable"
row-key="id"
style="width: 100%; margin-bottom: 20px"
v-loading="tableLoading"
>
<el-table-column :reserve-selection="true" type="selection"
width="55"></el-table-column>
<el-table-column
:index="indexMethod"
align="center"
header-align="center"
label="序号"
type="index"
width="80px"
></el-table-column>
<el-table-column
:key="column.prop"
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns"
>
<template scope="{row}" v-if="column.prop=='baname'">
<span>{{row.baname!=null?row.baname:'暂无'}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='diname'">
<span>{{row.diname!=null?row.diname:'暂无'}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='isMenWomen'">
<span v-if="row.isMenWomen==1">男子</span>
<span v-if="row.isMenWomen==2">女子</span>
</template>
<template scope="{row}" v-else-if="column.prop=='spname'">
<span>{{row.spname!=null?row.spname:''}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='projectType'">
<span>{{row.projectType=='1'?'个人':'团体'}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='note'">
<span>{{row.note!=''?row.note:'暂无'}}</span>
</template>
<template scope="{row}" v-else-if="column.prop=='whetherEnable'">
<el-switch
@change="switchChange(row)"
active-color="#13ce66"
inactive-color="#ff4949"
v-model="row.whetherEnable"
></el-switch>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="150px">
<template slot-scope="{row}">
<el-button @click="openEdit(row)" size="mini" type="primary">编辑
</el-button>
<el-button @click="doDelete(row)" size="mini" type="danger">删除
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<table-tool label="填写比赛项目信息"></table-tool>
<el-form :model="formData" :rules="formRules" label-suffix="" label-width="120px"
ref="form">
<el-row :gutter="40">
<el-col :span="24">
<el-form-item label="是否趣味项目" prop="isInterest">
<el-checkbox v-model="formData.isInterest">
{{formData.isInterest?'是趣味':'不是趣味'}}
</el-checkbox>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="比赛项目编号" prop="projectCode">
<el-input placeholder="请填写比赛项目编号"
v-model="formData.projectCode"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="性别" prop="isMenWomen">
<el-select
allow-create
clearable
default-first-option
filterable
placeholder="请选择男女分组"
style="width: 100%"
v-model="formData.isMenWomen"
>
<el-option :key="item.id" :label="item.name"
:value="item.id" v-for="item in menWomenList"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="比赛组别" prop="competitionCategory">
<el-select
@focus="focusGroup"
clearable
placeholder="请选择比赛组别"
style="width: 100%"
v-model="formData.competitionCategory"
>
<el-option
:key="item.id"
:label="item.name+''+item.code+''"
:value="item.id"
v-for="item in groupList"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="距离" prop="distance">
<el-select @focus="focusDistance" clearable
placeholder="请选择距离" style="width: 100%" v-model="formData.distance">
<el-option :key="item.id" :label="item.name"
:value="item.id" v-for="item in distanceList"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="运动类型" prop="exerciseType">
<el-select
@change="changeExercise_typeList"
@focus="exerciseType"
clearable
filterable
placeholder="请选择运动类型"
style="width: 100%"
v-model="formData.exerciseType"
>
<el-option :key="item.id" :label="item.name"
:value="item.id" v-for="item in exerciseTypeList"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="运动项目" prop="sports">
<el-select clearable placeholder="请选择具体运动项目" style="width: 100%"
v-model="formData.sports">
<el-option :key="item.id" :label="item.name"
:value="item.id" v-for="item in exerciseTypeList2"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目类型" prop="projectType">
<el-select
allow-create
clearable
default-first-option
filterable
placeholder="请选择具体运动项目"
style="width: 100%"
v-model="formData.projectType"
>
<el-option :key="item.id" :label="item.name"
:value="item.id" v-for="item in projectTypeList"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="年龄限制范围" prop="ageDate" v-if="formData.projectType==1">
<el-date-picker
end-placeholder="结束日期"
format="yyyy 年 MM 月 dd 日"
range-separator="-"
start-placeholder="开始日期"
style="width: 100%"
type="daterange"
v-model="formData.ageDate"
value-format="yyyy-MM-dd"
></el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div style="float: right; margin: 20px 0">
<el-button @click="formData.id?doEdit():doAdd()" type="primary">提 交</el-button>
</div>
</template>
</guava>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {},
data() {
return {
pageForm: {
age: 1,
ageYear: null,
activityId: null,
ageDate: null,
isMenWomen: []
},
groupList: [],
exerciseTypeList: [],
distanceList: [],
exerciseTypeList2: [],
tableColumns: [
{ prop: "projectCode", label: "项目编号", sortable: true },
{ prop: "allName", label: "全称", width: "200" },
{ prop: "isMenWomen", label: "男子/女子", sortable: true },
{ prop: "baname", label: "比赛组别", sortable: true },
{ prop: "diname", label: "距离", sortable: true },
{ prop: "exename", label: "运动类型", sortable: true },
{ prop: "spname", label: "运动项目", sortable: true },
{ prop: "projectType", label: "项目类型", sortable: true },
{ prop: "whetherEnable", label: "是否启用" }
],
multipleSelection: [],
projectTypeList: [
{ id: "1", name: "个人" },
{ id: "2", name: "团体" }
],
menWomenList: [
{ id: 1, name: "男子" },
{ id: 2, name: "女子" }
],
formRules: {
exerciseType: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
projectType: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
projectCode: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
}
}
},
methods: {
doAdd() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
const { data } = await this.$axios.post(loc() + "/getProjectCodeIsExist", { projectCode: this.formData.projectCode })
if (data) {
this.$message.error("编号已存在")
return
}
let allName = ""
this.groupList.find((v) => {
if (v.id === this.formData.competitionCategory) {
allName += v.name
}
})
this.menWomenList.find((v) => {
if (v.id === this.formData.isMenWomen) {
allName += v.name
}
})
this.distanceList.find((v) => {
if (v.id === this.formData.distance) {
allName += v.name + "米"
}
})
/* this.exerciseTypeList.find(v => {
if (v.id === this.formData.exerciseType) {
allName += v.name
}
})*/
this.exerciseTypeList2.find((v) => {
if (v.id === this.formData.sports) {
allName += v.name
}
})
/* this.projectTypeList.find(v => {
if (v.id === this.formData.projectType) {
allName += "(" + v.name + ")"
}
})*/
this.formData.allName = allName
if (this.formData.ageDate && this.formData.ageDate.length > 0) {
this.formData.startAgeDate = this.formData.ageDate[0]
this.formData.endAgeDate = this.formData.ageDate[1]
}
this.loading = true
const resp = await this.$axios.post(loc() + "/doAdd", this.formData)
this.loading = false
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.$refs.guava.index()
} else {
this.notifyWarning(resp.msg)
}
}
})
},
doEdit() {
this.$refs["form"].validate(async (valid) => {
if (valid) {
if (this.formData.oldProjectCode !== this.formData.projectCode) {
const { data } = await this.$axios.post(loc() + "/getProjectCodeIsExist", { projectCode: this.formData.projectCode })
if (data) {
this.$message.error("编号已存在")
return
}
}
let allName = ""
this.groupList.find((v) => {
if (v.id === this.formData.competitionCategory) {
allName += v.name
}
})
this.menWomenList.find((v) => {
if (v.id === this.formData.isMenWomen) {
allName += v.name
}
})
this.distanceList.find((v) => {
if (v.id === this.formData.distance) {
allName += v.name + "米"
}
})
/* this.exerciseTypeList.find(v => {
if (v.id === this.formData.exerciseType) {
allName += v.name
}
})*/
this.exerciseTypeList2.find((v) => {
if (v.id === this.formData.sports) {
allName += v.name
}
})
/* this.projectTypeList.find(v => {
if (v.id === this.formData.projectType) {
allName += "(" + v.name + ")"
}
})*/
this.formData.allName = allName
if (this.formData.ageDate && this.formData.ageDate.length > 0) {
this.formData.startAgeDate = this.formData.ageDate[0]
this.formData.endAgeDate = this.formData.ageDate[1]
}
this.loading = true
const resp = await this.$axios.post(loc() + "/doEdit", this.formData)
this.loading = true
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.$refs.guava.index()
} else {
this.notifyWarning(resp.msg)
}
}
})
},
openEdit(data) {
this.focusGroup()
this.exerciseType()
this.focusDistance()
this.formData = {
id: data.id,
isInterest: data.isInterest,
competitionCategory: data.competitionCategory,
distance: data.distance,
exerciseType: data.exerciseType,
sports: data.sports,
projectType: data.projectType,
note: data.note,
isMenWomen: data.isMenWomen,
projectCode: data.projectCode,
oldProjectCode: data.projectCode,
whetherEnable: data.whetherEnable
}
if (data.startAgeDate != null) {
this.$set(this.formData, "ageDate", [data.startAgeDate, data.endAgeDate])
}
this.changeExercise_typeList()
this.$refs.guava.edit()
},
doDelete(row) {
const { id } = row
this.$confirm("确定要删除该项目吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: async (a, b) => {
if ("confirm" === a) {
//确认后再执行
this.$set(row, "loading", true)
const resp = await this.$axios.post(loc() + "/doDelete", { id: id })
this.$set(row, "loading", false)
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
}
})
},
handleSelectionChange(val) {
this.multipleSelection = val
},
//查询比赛组别
async focusGroup() {
const resp = await this.$axios.post(loc() + "/focusGroup")
if (resp.code === 0) {
this.groupList = resp.data
} else {
this.notifyWarning(resp.msg)
}
},
//查询运动类型
async exerciseType() {
const resp = await this.$axios.post(loc() + "/exerciseType")
if (resp.code === 0) {
this.exerciseTypeList = resp.data
} else {
this.notifyWarning(resp.msg)
}
},
//根据运动id查询下面有哪些具体的运动项目
async changeExercise_typeList() {
const resp = await this.$axios.post(loc() + "/changeExercise_typeList", { exerciseType: this.formData.exerciseType })
if (resp.code === 0) {
this.exerciseTypeList2 = resp.data
} else {
this.notifyWarning(resp.msg)
}
},
//查询距离
async focusDistance() {
const resp = await this.$axios.post(loc() + "/focusDistance")
if (resp.code === 0) {
this.distanceList = resp.data
} else {
this.notifyWarning(resp.msg)
}
},
ageInput(val) {
const year = new Date().getFullYear()
this.$set(this.pageForm, "ageYear", year - val)
},
async doAssignmentDate() {
const aa = this.multipleSelection.map((v) => {
if (v.isInterest) {
return true
} else {
return false
}
})
if (aa.find((v) => v == true)) {
this.$notify({
title: "警告",
message: "您勾选的列表中包含趣味项目,趣味项目暂不需要年龄限制",
type: "warning"
})
return
}
if (this.multipleSelection.length === 0) {
this.$notify({
title: "警告",
message: "请先在旁边勾选需要设置的项目",
type: "warning"
})
return
}
if (this.pageForm.ageDate == null) {
this.$notify({
title: "警告",
message: "请选择需要赋值的时间段",
type: "warning"
})
return
}
const confirm = await this.$confirm("确定要勾选的项目赋年龄限制吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const data = await this.$axios.post(loc() + "/doAssignmentDate", {
startAgeDate: this.pageForm.ageDate[0],
endAgeDate: this.pageForm.ageDate[1],
eventIds: JSON.stringify(this.multipleSelection.map((v) => v.id))
})
this.$notify.success({ title: "成功", message: data.msg })
this.$refs.multipleTable.clearSelection()
this.doSearch()
}
},
openAdd() {
this.$refs.guava.edit()
if (this.$refs["form"]) {
this.$refs["form"].resetFields()
}
this.formData = {}
},
pageData() {
this.tabLoading = true
const pageForm = clone(this.pageForm)
pageForm.isMenWomen = JSON.stringify(pageForm.isMenWomen)
this.$axios.post("/platform/activity/basic/event/pageData", pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
}
},
async created() {
this.pageData()
this.ageInput(this.pageForm.age)
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,228 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-row :gutter="10" type="flex" style="height: calc(100vh - 126px)">
<el-col :span="5">
<el-card shadow="never" style="height: 100%" body-style="{ height: '100%' }">
<div style="max-height: calc(100vh - 170px); overflow-y: auto">
<el-tree
:data="treeData"
:default-expanded-keys="['7e3f5fcbc24f442dbb3a6cc9412e7960']"
:expand-on-click-node="false"
:filter-node-method="filterNode"
:props="{
children: 'child',
label: 'name'
}"
@node-click="treeNodeClick"
highlight-current
node-key="id"
ref="treeRef"
></el-tree>
</div>
</el-card>
</el-col>
<el-col :span="19">
<el-card shadow="never" style="height: 100%">
<table-tool>
<el-button @click="openBasicType" size="small" type="primary">
<i class="el-icon-plus"></i>
新建基础类型
</el-button>
</table-tool>
<el-table :data="tableData" border size="small">
<el-table-column label="序号" type="index" width="100px">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="名称" prop="name"></el-table-column>
<el-table-column align="center" label="代码" prop="code"></el-table-column>
<el-table-column align="center" label="备注" prop="note" show-overflow-tooltip></el-table-column>
<el-table-column align="center" label="操作" width="100px">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button plain size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'edit',data:row}">编辑</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',data:row}">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<el-pagination
:current-page="pageForm.pageNumber"
:page-size="pageForm.pageSize"
:page-sizes="[10, 20, 30, 50]"
:total="pageForm.totalCount"
@current-change="(val)=>{pageForm.pageNumber = val;pageData()}"
@size-change="(val)=>{pageForm.pageSize = val;pageData()}"
layout="total, sizes, prev, pager, next"
></el-pagination>
</el-card>
</el-col>
</el-row>
<el-dialog :close-on-click-modal="false" :title="formData.id?'编辑':'新增'" :visible.sync="basicTypeDialog" width="50%">
<el-form :model="formData" :rules="rules" label-width="100px" ref="addForm">
<el-row :gutter="30">
<el-form-item label="上级名称" label-width="110px" prop="name">
<el-input :value="checkData.name" disabled maxlength="100" type="text"></el-input>
</el-form-item>
<el-form-item label="基础类型名称" label-width="110px" prop="name">
<el-input maxlength="100" placeholder="请输入基础类型名称" type="text" v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="基础类型代码" label-width="110px" prop="code">
<el-input maxlength="100" placeholder="请输入基础类型名称" type="text" v-model="formData.code"></el-input>
</el-form-item>
<el-form-item label="基础类型备注" label-width="110px" prop="note">
<el-input maxlength="100" placeholder="请输入基础类型备注" type="textarea" v-model="formData.note"></el-input>
</el-form-item>
</el-row>
</el-form>
<div style="display: flex; justify-content: flex-end; margin-top: 30px">
<el-button @click="!formData.id?doAddType():doEditType()" type="primary">提 交</el-button>
</div>
</el-dialog>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
components: {},
data() {
return {
filterText: null,
treeData: [],
currentTreeNode: null,
currentTreeData: null,
checkData: {},
tableData: [],
basicTypeDialog: false,
rules: {
name: [{ required: true, message: "必填", trigger: ["change", "blur"] }],
code: [{ required: true, message: "必填", trigger: ["change", "blur"] }]
},
pageForm: {
parentId: null
}
}
},
methods: {
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
this.checkData = data
this.pageForm.parentId = data.id
this.doSearch()
},
filterNode() {},
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.checkData = this.treeData[0]
}
})
},
dropdownCommand: function (command) {
const { type, data } = command
if (type == "edit") {
this.openEditType(data)
} else if (type == "delete") {
this.doDelete(data.id)
}
},
async openBasicType() {
const { id } = this.checkData
this.formData = {
parentId: id
}
this.basicTypeDialog = true
if (this.$refs["addForm"]) {
this.$refs["addForm"].resetFields()
}
},
doAddType() {
this.$refs["addForm"].validate(async (valid) => {
if (valid) {
const resp = await this.$axios.post(loc() + "/doAdd", this.formData)
if (resp.code === 0) {
this.basicTypeDialog = false
this.doSearch()
this.getTreeData()
this.$message.success(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
})
},
doEditType() {
this.$refs["addForm"].validate(async (valid) => {
if (valid) {
const resp = await this.$axios.post(loc() + "/doEditType", this.formData)
this.basicTypeDialog = false
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
})
},
openEditType(row) {
this.formData = {
id: row.id,
name: row.name,
code: row.code,
note: row.note
}
this.basicTypeDialog = true
},
doDelete(id) {
this.$confirm("确定要删除该机构吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
callback: async (a, b) => {
if ("confirm" == a) {
const resp = await this.$axios.post(loc() + "/doDelete", { id: id })
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
this.getTreeData()
} else {
this.notifyWarning(resp.msg)
}
}
}
})
}
},
created() {
this.pageData()
this.getTreeData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,165 @@
const ACTIVITY_BASIC_BRANCH_UNION_MANAGE = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter)">
<div class="search">
<div class="search-item">
<el-input placeholder="请输入分工会名称" clearable v-model="pageForm.searchKeyword"></el-input>
</div>
<div class="search-item">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button>
</div>
</div>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<table-tool>
<el-button @click="openAdd" icon="ti-plus" type="primary" style="margin-left: auto" size="small">新建临时分工会</el-button>
</table-tool>
<el-table :data="tableData" border size="small" height="calc(100vh - 375px)">
<el-table-column label="序号" type="index" :index="indexMethod" width="100px"></el-table-column>
<el-table-column prop="name" label="工会名称"></el-table-column>
<el-table-column prop="unionCode" label="工会编码"></el-table-column>
<el-table-column prop="userNames" label="管理员"></el-table-column>
<el-table-column label="操作" width="290">
<template slot-scope="{row}">
<el-button size="mini" @click="openAdmin(row.id)">设置管理员</el-button>
<el-button type="primary" size="mini" @click="openEdit(row.id)">编辑</el-button>
<el-button type="danger" size="mini" @click="doDeleteUnion(row.id,true)" v-if="row.unitnum===0">删除</el-button>
<el-button type="danger" size="mini"
v-if="row.unitnum>0&&row.source==='activity'"
@click="doDeleteUnion(row.id,false)">还原单位
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<el-dialog :title="formData.id ? '编辑分工会' : '新增分工会'" :visible.sync="dialogFormVisible" width="600px">
<el-form :model="formData" ref="form" size="small" label-width="80px">
<el-form-item label="工会名称">
<el-input v-model="formData.name" maxlength="100" placeholder="工会名称"></el-input>
</el-form-item>
<el-form-item label="工会编码">
<el-input v-model="formData.unionCode" maxlength="100" placeholder="工会编码"></el-input>
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="formData.telephone" maxlength="100" placeholder="联系电话"></el-input>
</el-form-item>
<el-form-item label="校区" prop="campus">
<el-select v-model="formData.campus" maxlength="20" placeholder="校区"></el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
<el-dialog title="设置管理员" :visible.sync="dialogGlyFormVisible" width="50%">
<div style="width: 100%;">
<el-transfer
:titles="['单位成员', '管理员']"
filterable
:props="{
key: 'id',
label: 'name'
}"
:filter-method="adminFilterMethod"
v-model="userAdminIds"
:data="userData">
</el-transfer>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogGlyFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmitAdmin">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
data() {
return {
dialogFormVisible: false,
dialogGlyFormVisible: false,
formData: {},
userData: [],
userAdminIds: [],
unionId: ""
}
},
methods: {
pageData() {
this.$axios.post("/platform/activity/basic/union/pageData", this.pageForm).then((res) => {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
})
},
openAdd() {
this.dialogFormVisible = true
this.$nextTick(() => {
this.formData = {}
})
},
openEdit(id) {
this.dialogFormVisible = true
this.$axios.post("/platform/activity/basic/union/findOne", { id }).then((res) => {
this.formData = res.data
})
},
doSubmit() {
this.$axios.post("/platform/activity/basic/union/" + (this.formData.id ? "update" : "insert"), this.formData).then((res) => {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
this.$emit("refresh", null)
})
},
doDeleteUnion(id, flag) {
let msg = flag ? "请确认是否要删除本联合工会,一旦删除相关数据将无法查询!!!" : "选择后系统将组成单位还原到所在分工会!!!"
this.$confirm(msg, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "info"
}).then(() => {
this.$axios.post("/platform/activity/basic/union/doDeleteUnion", { id, flag }).then((res) => {
this.$message.success(res.msg)
this.doSearch()
this.$emit("refresh", null)
})
})
},
adminFilterMethod(query, item) {
return item.name.indexOf(query) > -1
},
openAdmin(id) {
this.unionId = id
this.$axios.post("/platform/activity/basic/union/getUnionAdminAndUser", { id: id }).then((res) => {
if (res.code === 0) {
this.userData = res.data.userData
this.userAdminIds = res.data.userAdminIds
}
})
this.dialogGlyFormVisible = true
},
doSubmitAdmin() {
this.$axios
.post("/platform/activity/basic/union/doSubmitAdmin", {
unionId: this.unionId,
userIds: JSON.stringify(this.userAdminIds)
})
.then((res) => {
if (res.code === 0) {
this.doSearch()
this.$message.success(res.msg)
} else {
this.$message.error(res.msg)
}
})
this.dialogGlyFormVisible = false
}
},
created() {
this.pageData()
}
}
@@ -0,0 +1,103 @@
const ACTIVITY_BASIC_BRANCH_UNION_PART_UNIT_MANAGE = {
template: `
<div>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-row type="flex" style="column-gap: 10px">
<el-input
placeholder="请输入内容"
size="small"
style="width: 400px"
clearable
v-model="pageForm.searchKeyword"
@keyup.enter.native="doSearch"
></el-input>
<el-button type="primary" size="small" icon="el-icon-search" @click="doSearch"></el-button>
<el-button type="primary" size="small" icon="el-icon-setting" style="margin-left: auto" @click="openAdd">设置组成单位</el-button>
</el-row>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter); margin-top: 10px">
<el-table :data="tableData" border size="small">
<el-table-column type="index" label="序号"></el-table-column>
<el-table-column prop="unitcode" label="单位编码"></el-table-column>
<el-table-column prop="name" label="单位名称"></el-table-column>
</el-table>
</el-card>
<el-dialog title="设置组成单位" :visible.sync="dialogFormVisible" width="1000px" :close-on-click-modal="false">
<el-transfer
ref="transferRef"
:titles="['可选二级单位', '当前成员单位']"
filterable
:props="{
key: 'id',
label: 'name'
}"
:filter-method="filterUnit"
v-model="selectUnitsIds"
:data="allUnits"
></el-transfer>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="doSubmit">确 定</el-button>
</div>
</el-dialog>
</div>
`,
mixins: [initTableMixins],
data() {
return {
dialogFormVisible: false,
selectUnitsIds: [],
allUnits: [],
unionId: ""
}
},
methods: {
openAdd() {
this.dialogFormVisible = true
if (this.$refs.transferRef) {
this.$refs.transferRef.clearQuery("left")
this.$refs.transferRef.clearQuery("right")
}
this.$axios.post("/platform/activity/basic/union/branchUnionPartUnitTransferData", { unionId: this.unionId }).then((res) => {
this.selectUnitsIds = res.data.selectUnitIds
this.allUnits = res.data.allUnits
})
},
filterUnit(query, item) {
return item.name.indexOf(query) > -1
},
doSubmit() {
this.$axios
.post("/platform/activity/basic/union/branchUnionPartUnitSet", {
unitIds: JSON.stringify(this.selectUnitsIds),
unionId: this.unionId
})
.then((res) => {
if (res.code === 0) {
this.dialogFormVisible = false
this.$message.success(res.msg)
this.doSearch()
}
})
},
pageData(unionId) {
if (unionId) {
this.unionId = unionId
}
this.$axios
.post("/platform/activity/basic/union/branchUnionPartUnitPageData", {
...this.pageForm,
unionId: this.unionId
})
.then((res) => {
if (res.code === 0) {
this.tableData = res.data
}
})
}
}
}
@@ -0,0 +1,83 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-row :gutter="10" type="flex" style="height: calc(100vh - 126px)">
<el-col :span="5">
<el-card shadow="never" style="height: 100%" body-style="{ height: '100%' }">
<div style="max-height: calc(100vh - 160px); overflow-y: auto">
<el-tree
:data="treeData"
:expand-on-click-node="false"
:props="{
children: 'children',
label: 'name'
}"
@node-click="treeNodeClick"
default-expand-all
highlight-current
ref="treeRef"
></el-tree>
</div>
</el-card>
</el-col>
<el-col :span="19">
<el-card style="height: 100%" shadow="never">
<template v-if="currentTreeNode==null || currentTreeNode.level===1">
<activity-basic-branch-union-manage @refresh="getTreeData()"></activity-basic-branch-union-manage>
</template>
<template v-if="currentTreeNode && currentTreeNode.level===2">
<activity-basic-branch-union-part-unit-manage ref="unitManage"></activity-basic-branch-union-part-unit-manage>
</template>
</el-card>
</el-col>
</el-row>
</div>
<script>
<!--#include("activityBasicBranchUnionManage.js"){}#-->
<!--#include("activityBasicBranchUnionPartUnitManage.js"){}#-->
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
treeData: [],
currentTreeNode: null,
currentTreeData: null
}
},
components: {
"activity-basic-branch-union-manage": ACTIVITY_BASIC_BRANCH_UNION_MANAGE,
"activity-basic-branch-union-part-unit-manage": ACTIVITY_BASIC_BRANCH_UNION_PART_UNIT_MANAGE
},
methods: {
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
if (node.level === 2) {
setTimeout(() => {
this.$refs.unitManage.pageData(data.id)
}, 300)
}
},
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.checkData = this.treeData[0]
}
})
}
},
created() {
this.pageData()
this.getTreeData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,141 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<el-row :gutter="10" type="flex" style="height: calc(100vh - 126px)">
<el-col :span="5">
<el-card shadow="never" style="height: 100%" body-style="{ height: '100%' }">
<div style="max-height: calc(100vh - 160px); overflow-y: auto">
<el-tree
:data="treeData"
:default-expanded-keys="['1']"
:expand-on-click-node="false"
:props="{
children: 'child',
label: 'name'
}"
@node-click="treeNodeClick"
highlight-current
node-key="id"
ref="treeRef"
></el-tree>
</div>
</el-card>
</el-col>
<el-col :span="19">
<el-card shadow="never" style="height: 100%">
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter)">
<div class="search">
<div class="search-item" style="width: 25%">
<el-input
@keyup.enter.native="doSearch"
clearable
placeholder="请输入内容"
style="width: 100%"
v-model="pageForm.searchKeyword"
>
<el-select placeholder="查询类型" slot="prepend" style="width: 110px" v-model="pageForm.searchName">
<el-option label="单位名称" value="name"></el-option>
<el-option label="单位代码" value="unitcode"></el-option>
</el-select>
</el-input>
</div>
<div class="search-item">
<el-button @click="doSearch" icon="el-icon-search" type="primary">搜索</el-button>
</div>
</div>
</el-card>
<el-card shadow="never" style="border: 1px solid var(--border-color-lighter)">
<table-tool></table-tool>
<el-table :data="tableData" height="calc(100vh - 380px)" border size="small">
<el-table-column label="序号" type="index">
<template scope="scope">
<span>{{scope.$index+(pageForm.pageNumber - 1) * pageForm.pageSize + 1}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="单位名称" prop="name"></el-table-column>
<el-table-column align="center" label="单位代码" prop="unitcode"></el-table-column>
<el-table-column align="center" label="单位等级" prop="unitLevel">
<template slot-scope="{row}">
<el-button round size="mini" style="vertical-align: middle" type="success" v-if="row.unitLevel==1">1级</el-button>
<el-button round size="mini" style="vertical-align: middle" type="warning" v-if="row.unitLevel==2">2级</el-button>
<el-button round size="mini" style="vertical-align: middle" type="danger" v-if="row.unitLevel==3">3级</el-button>
<el-button round size="mini" style="vertical-align: middle" type="info" v-if="row.unitLevel>3">
{{row.unitlevel}}级
</el-button>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作" width="100px">
<template slot-scope="{row}">
<el-button @click="doDelete(row.id)" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</el-card>
</el-col>
</el-row>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {
pageForm: {
searchName: "name"
},
treeData: [],
currentTreeNode: null,
currentTreeData: null
}
},
components: {},
methods: {
async doDelete(id) {
const confirm = await this.$confirm("确定要删除该单位吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
const resp = await this.$axios.post(loc() + "/doDelete", { id })
if (resp.code === 0) {
this.getTreeData()
this.doSearch()
this.$message.success(resp.msg)
} else {
this.notifyWarning(resp.msg)
}
}
},
treeNodeClick(data, node) {
this.currentTreeData = data
this.currentTreeNode = node
this.pageForm.parentId = data.id
this.doSearch()
},
getTreeData() {
this.$axios.post(loc() + "/tree").then((res) => {
this.treeData = res.data
if (this.treeData) {
this.currentTreeData = this.treeData[0]
}
})
},
openUnit() {}
},
created() {
this.pageData()
this.getTreeData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,26 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<user-scope ref="userScope"></user-scope>
</guava>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {}
},
components: {
"user-scope": httpVueLoader("/components/module/activity/UserScope.vue?v=" + new Date().getDate())
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,26 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava>
<user-scope-data ref="userDataScope"></user-scope-data>
</guava>
</div>
<script>
new Vue({
el: "#app",
mixins: [initTableMixins],
data() {
return {}
},
components: {
"user-scope-data": httpVueLoader("/components/module/activity/UserDataScope.vue?v=" + new Date().getDate())
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,31 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-apply-activity :activity_type="activityType"></activity-culture-apply-activity>
</guava>
</div>
<script>
<!--#include("../../common/applyActivity.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40003
}
},
components: {
"activity-culture-apply-activity": ACTIVITY_CULTURE_APPLY_ACTIVITY
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,32 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-apply-user :activity_type="activityType"></activity-culture-apply-user>
</guava>
</div>
<script>
<!--#include("../../common/applyUser.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40003
}
},
components: {
"activity-culture-apply-user": ACTIVITY_CULTURE_APPLY_USER
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,30 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<activity-culture-audit-activity :activity_type="activityType"></activity-culture-audit-activity>
</div>
<script>
<!--#include("../../common/auditActivity.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40003
}
},
components: {
"activity-culture-audit-activity": ACTIVITY_CULTURE_AUDIT_ACTIVITY
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,30 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<activity-culture-info-manage :activity_type="activityType"></activity-culture-info-manage>
</div>
<script>
<!--#include("../../common/infoMange.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40003
}
},
components: {
"activity-culture-info-manage": ACTIVITY_CULTURE_INFO_MANAGE
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,32 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-user-statistics :activity_type="activityType"></activity-culture-user-statistics>
</guava>
</div>
<script>
<!--#include("../../common/userStatistics.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40003
}
},
components: {
"activity-culture-user-statistics": ACTIVITY_CULTURE_USER_STATISTICS
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,803 @@
const ACTIVITY_CULTURE_APPLY_ACTIVITY = {
template: /*language=HTML*/ `
<div>
<template>
<el-card shadow="never" style="min-height: calc(100vh - 70px);position: relative">
<el-form :model="formData" :rules="formRules" label-suffix="" label-width="170px"
ref="addForm" v-loading="formLoading">
<el-tabs tab-position="top" v-model="activeName">
<el-tab-pane label="活动基础信息" name="1">
<div class="mt20">
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="活动名称" prop="name">
<el-input maxlength="50" placeholder="请填写活动名称"
type="text"
v-model="formData.name"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="活动编号" prop="activityCode">
<el-input disabled maxlength="50"
type="text"
v-model="formData.activityCode"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="活动项目类型" prop="projectTypeCode">
<el-select placeholder="请选择活动类型"
style="width: 100%;"
v-model="formData.projectTypeCode">
<el-option
:key="item.id"
:label="item.name+' ('+item.code+')'"
:value="item.code"
v-for="item in projectTypeList">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否用于报名" prop="isEnrollSystem">
<el-radio-group v-model="formData.isEnrollSystem" size="small">
<el-radio border :label="true">活动报名</el-radio>
<el-radio border :label="false">活动管理</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="活动地址" prop="address">
<el-input maxlength="50" placeholder="请填写活动地址"
type="text"
v-model="formData.address"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系人" prop="userId">
<el-select :loading="selectLoading" :remote-method="remoteMethod"
@change="userChang"
clearable
filterable
placeholder="请选择联系人"
remote
reserve-keyword
style="width: 100%" v-model="formData.userId">
<el-option
:key="item.userId"
:label="item.userName+'-'+item.loginName+'-'+item.unitName"
:value="item.userId"
v-for="item in userList">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系方式" prop="mobile">
<el-input maxlength="50" placeholder="请填写联系方式"
type="text"
v-model="formData.mobile"></el-input>
</el-form-item>
</el-col>
<!-- <el-col :span="12"-->
<!-- v-if="formData.isEnrollSystem === true">-->
<!-- <el-form-item label="活动计划时间" prop="plannedDate">-->
<!-- <el-date-picker-->
<!-- @change="plannedDateChange"-->
<!-- end-placeholder="结束日期"-->
<!-- range-separator="-"-->
<!-- start-placeholder="开始日期"-->
<!-- style="width: 100%"-->
<!-- type="daterange"-->
<!-- v-model="formData.plannedDate" value-format="yyyy-MM-dd">-->
<!-- </el-date-picker>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="12">
<el-form-item label="实际活动时间" prop="time">
<el-date-picker
end-placeholder="结束日期"
range-separator="-"
start-placeholder="开始日期"
style="width: 100%"
type="daterange"
v-model="formData.time"
value-format="yyyy-MM-dd">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
:rules="[{required:[1,2].includes(formData.signUpMethod),message:'请选择报名日期',trigger:['change','blur']}]"
label="报名日期"
prop="applyTime2">
<el-date-picker
end-placeholder="结束时间"
range-separator="-"
start-placeholder="开始时间"
style="width: 100%"
type="datetimerange"
v-model="formData.applyTime2"
value-format="yyyy-MM-dd HH:mm">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12" v-if="!formData.isEnrollSystem">
<el-form-item label="活动人数" prop="peopleNum">
<el-input
maxlength="10"
placeholder="请填写活动人数"
v-model="formData.peopleNum"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="参加人员范围" prop="groupId">
<div style="display: flex; justify-content: space-between">
<div style="width: 99%">
<el-select clearable filterable
placeholder="参加人员范围"
prop="groupId"
style="width: 99%;"
v-model="formData.groupId">
<el-option :key="item.groupId"
:label="item.groupName"
:value="item.groupId"
v-for="item in activityGroupList"></el-option>
</el-select>
</div>
<div>
<el-button
@click="$refs.drawerUserScope.userScopeDialog = true"
type="primary">设置
</el-button>
</div>
</div>
</el-form-item>
</el-col>
<el-col :span="12"
v-if="formData.isEnrollSystem === true">
<el-form-item label="报名方式" prop="signUpMethod">
<el-radio-group v-model="formData.signUpMethod" size="small">
<el-radio border :label="1">个人报名</el-radio>
<el-radio border :label="2">组队报名</el-radio>
<el-radio border :label="3" v-if="activity_type===40001">分工会报名
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :lg="12" :xl="12" :xs="12"
v-if="[1,2,3].includes(formData.signUpMethod)">
<el-form-item label="报名人数限制" prop="userNumberLimit">
<el-radio-group v-model="formData.userNumberLimit" size="small">
<el-radio border :label="1">总人数限制</el-radio>
<el-radio border :label="2" v-if="activity_type===40001">分工会人数限制</el-radio>
<el-radio border :label="null">不限制</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :lg="12" :xl="12" :xs="12"
v-if="[3].includes(formData.signUpMethod)">
<el-form-item label="组队人数" prop="totalUserNumberLimit">
<el-input-number :max="2000" :min="1"
:precision="0"
v-model="formData.teamNum"
></el-input-number>
</el-form-item>
</el-col>
<el-col :lg="12" :xl="12" :xs="12"
v-if="[1,2,3].includes(formData.signUpMethod) && formData.userNumberLimit===1">
<el-form-item label="总人数限制" prop="totalUserNumberLimit">
<el-input-number :max="2000"
:min="1" :precision="0"
v-model="formData.totalUserNumberLimit"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="24"
v-if="[1,2,3].includes(formData.signUpMethod) && formData.userNumberLimit===2">
<el-form-item label="分工会人数限制" prop="unionUserNumberLimit">
<table-tool label="分段设置">
<el-button @click="unionLimitQuickSetting" size="small"
type="primary">
应用分段设置
</el-button>
</table-tool>
<el-row :gutter="20" :key="index"
class="mb5" v-for="(item,index) in unionUserNumCalc">
<el-col :span="7">
<el-input-number :min="1" :precision="0"
:step="1" placeholder="请输入最小人数"
style="width: 100%"
v-model="item.startNum"></el-input-number>
</el-col>
<el-col :span="7">
<el-input-number :min="1" :precision="0"
:step="1" placeholder="请输入最大人数"
style="width: 100%"
v-model="item.endNum"></el-input-number>
</el-col>
<el-col :span="6">
<el-input-number :min="1" :precision="0"
:step="1" placeholder="请输入限制人数"
style="width: 100%"
v-model="item.resultNum"></el-input-number>
</el-col>
<el-col :span="4" class="text-right">
<el-button @click="unionUserNumCalc.push({})"
icon="el-icon-plus"></el-button>
<el-button :disabled="unionUserNumCalc.length===1"
@click="unionUserNumCalc.splice(index,1)"
icon="el-icon-minus"></el-button>
</el-col>
</el-row>
<el-row class="mt10">
<div class="text-danger"
v-for="(item,index) in unionUserNumCalcTips">
<span class="mr10">({{index+1}}).</span> {{item}}
</div>
</el-row>
<table-tool class="mt20" label="比例设置">
一键比例:
<el-input-number :max="100"
:min="0" :precision="0" :step="1"
placeholder="请输入一键比例"
size="small"
v-model="unionUserNumOneKeyRatio"></el-input-number>
<el-button @click="applyScaleSettings" class="ml5"
size="small" type="primary">
应用比例设置
</el-button>
</table-tool>
<el-table :data="formData.unionUserNumberLimit"
max-height="500px">
<el-table-column label="分工会"
prop="unionname"></el-table-column>
<el-table-column label="人数"
prop="teacherCount"></el-table-column>
<el-table-column label="比例(%)" prop="ratio">
<template slot-scope="{row}">
<el-input-number :max="100" :min="0"
:precision="0" :step="1"
v-model="row.ratio"></el-input-number>
</template>
</el-table-column>
<el-table-column label="限制人数" prop="limitNum">
<template slot-scope="{row}">
<el-input-number :max="row.teacherCount"
:min="0" :precision="0" :step="1"
@change="calSummaryCount"
v-model="row.limitNum"></el-input-number>
</template>
</el-table-column>
</el-table>
<el-row class="mt20" justify="end" type="flex">
<div class="text-danger"
style="width: 100%;font-size: 18px;display: flex;align-items: center;font-weight: bold">
限制总人数:{{summaryCount}}人
</div>
</el-row>
</el-form-item>
</el-col>
<!-- <el-col :span="12" v-if="[1,2,3].includes(formData.signUpMethod)">
<el-form-item label="是否需要签到">
<el-radio-group @change="(val)=>{formData.needSign?initMap():null}"
v-model="formData.needSign">
<el-radio :label="true">需要</el-radio>
<el-radio :label="false">不需要</el-radio>
</el-radio-group>
</el-form-item>
</el-col>-->
<el-col :span="24">
<el-form-item label="活动详情" prop="activityContent">
<text-editor v-model="formData.activityContent"></text-editor>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.isEnrollSystem === false">
<el-form-item label="活动考核内容" prop="activityExamineContent">
<el-input
:rows="7"
placeholder="请输入活动考核内容"
type="textarea"
v-model="formData.activityExamineContent">
</el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="报名表单" prop="formConfig">
<custom-form-field v-model="formData.formConfig"></custom-form-field>
</el-form-item>
</el-col>
<el-col :span="24" v-if="formData.signUpMethod!=null">
<el-form-item label="封面图" prop="cover">
<file-upload :value.sync="formData.cover" accept=".jpg,.jpeg,.png"
:upload_number="1" upload_result_category="interval"
complete_result></file-upload>
</el-form-item>
</el-col>
</el-row>
</div>
</el-tab-pane>
<el-tab-pane label="活动费用" name="2" v-if="formData.isEnrollSystem === false">
<table-tool label="购置物品及价格">
<el-button @click="formData.goods.push({})"
type="primary" size="small">添加购置物品及价格
</el-button>
</table-tool>
<el-form-item>
<el-table :data="formData.goods" border height="200" size="mini"
style="width: 100%">
<el-table-column align="center" header-align="center" label="序号" sortable
type="index" width="100">
</el-table-column>
<el-table-column align="center" header-align="center" label="物品名称"
prop="name">
<template slot-scope="{row}">
<el-input maxlength="50" placeholder="物品名称"
type="text"
v-model="row.name"></el-input>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="预算费用"
prop="price">
<template slot-scope="{row}">
<el-input maxlength="50"
placeholder="预算费用"
type="number" v-model="row.price"></el-input>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="实际费用"
prop="actualPrice">
<template slot-scope="{row}">
<el-input maxlength="50"
placeholder="实际费用"
type="number" v-model="row.actualPrice"></el-input>
</template>
</el-table-column>
<el-table-column align="center" fixed="right"
header-align="center"
label="操作"
width="80px">
<template slot-scope="scope">
<el-button @click="formData.goods.splice(scope.$index, 1)" circle
icon="el-icon-delete"
type="danger"></el-button>
</template>
</el-table-column>
</el-table>
</el-form-item>
<table-tool :app="this" label="附件">
</table-tool>
<el-row :gutter="40">
<el-col :span="12">
<el-form-item label="发票" prop="billFiles">
<file-upload :value.sync="formData.billFiles" accept=".jpg,.jpeg,.png"
upload_mode="drag"
:upload_number="3" upload_result_category="array"
complete_result></file-upload>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="照片" prop="photoFiles">
<file-upload :value.sync="formData.photoFiles" accept=".jpg,.jpeg,.png"
upload_mode="drag"
:upload_number="3" upload_result_category="array"
complete_result></file-upload>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="其他" prop="otherFiles">
<file-upload :value.sync="formData.otherFiles" accept=".jpg,.jpeg,.png"
upload_mode="drag"
:upload_number="3" upload_result_category="array"
complete_result></file-upload>
</el-form-item>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="活动人员信息" name="3" v-if="formData.isEnrollSystem === false">
<table-tool label="活动人员信息">
<el-button @click="openAddUser" icon="el-icon-plus"
type="primary" size="small">添加活动人员
</el-button>
</table-tool>
<el-table :data="userData" border height="500" size="small"
stripe v-loading="userTabLoading" row-key="userId">
<el-table-column
label="序号" type="index"
width="100">
</el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
v-for="column in userColumns">
</el-table-column>
<el-table-column label="操作"
prop="userOnline"
width="150px">
<template slot-scope="{row}">
<el-button @click="delUser(row)" size="mini"
type="danger">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="活动总结" name="4" v-if="formData.isEnrollSystem === false">
<table-tool label="活动总结">
</table-tool>
<el-form-item label="" prop="activitySummary">
<el-input
:disabled="!formData.time || Date.now() < Date.parse(formData.time[1])"
:rows="5"
placeholder="请输入活动内容"
type="textarea"
v-model="formData.activitySummary">
</el-input>
</el-form-item>
<el-alert
class="mb20"
show-icon
style="margin-left: 130px"
title="活动结束后可输入活动总结"
type="info"
v-if="!formData.time || Date.now() < Date.parse(formData.time[1])">
</el-alert>
</el-tab-pane>
</el-tabs>
<div style="padding: 20px;text-align: center;">
<el-button @click="operation" style="width: 300px" type="primary" :disabled="formLoading">
确 定
</el-button>
</div>
</el-form>
</el-card>
<drawer-user-scope
@group_change="getActivityGroup"
ref="drawerUserScope"
:group_id.sync="formData.groupId"
></drawer-user-scope>
<el-dialog :close-on-click-modal="false" :visible.sync="userDialogVisible" title="添加人员" width="40%">
<el-form :model="formData" label-width="100px">
<el-form-item label="参加人员" prop="userId">
<el-select :loading="selectLoading" :remote-method="remoteMethod"
filterable
multiple
placeholder="请选择参加人员"
remote
style="width: 100%"
v-model="formData.tissuePersonList">
<el-option
:disabled="userData.map(v=>v.userId).includes(item.userId)"
:key="item.userId"
:label="item.userName+'-'+item.loginName+'-'+item.unitName"
:value="item.userId"
v-for="item in userList">
</el-option>
</el-select>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="userDialogVisible = false">取 消</el-button>
<el-button @click="doAddUser" type="primary">确 定</el-button>
</span>
</el-dialog>
</template>
</div>
`,
props: {
activity_type: {
value: { type: Object, default: "" }
}
},
mixins: [initTableMixins],
data() {
return {
activeName: "1",
pageForm: {
year: new Date().getFullYear() + ""
},
formRules: {
groupId: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
name: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
type: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
projectTypeCode: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
address: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
plannedDate: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
time: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
cover: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
},
projectTypeList: [],
activityGroupList: [],
unionUserNumCalc: [{}],
summaryCount: 0,
unionUserNumOneKeyRatio: null,
tissuePersonList: [],
userDialogVisible: false,
userData: [],
userTabLoading: false,
userList: [],
selectLoading: false,
userColumns: [
{ prop: "userName", label: "姓名" },
{ prop: "loginName", label: "工号" },
{ prop: "sex", label: "性别" },
{ prop: "mobile", label: "联系方式" },
{ prop: "unitName", label: "所属单位" },
{ prop: "unionName", label: "所属工会" }
]
}
},
components: {
"drawer-user-scope": httpVueLoader("/components/module/activity/DrawerUserScope.vue")
},
computed: {
unionUserNumCalcTips() {
return this.unionUserNumCalc.map((v) => {
return (
(v.startNum ? v.startNum : "?") +
"-" +
(v.endNum ? v.endNum : "?") +
"人的分工会,限报" +
(v.resultNum ? v.resultNum : "?") +
"人"
)
})
}
},
methods: {
async remoteMethod(query) {
if (query) {
this.selectLoading = true
const { data } = await this.$axios.post("/platform/activity/culture/applyActivity/findUser", {
serachWord: query,
activity_type: this.activity_type
})
this.userList = data
this.selectLoading = false
}
},
doAddUser() {
this.formData.tissuePersonList = this.userList.filter((v) => this.formData.tissuePersonList.some((x) => v.userId === x))
this.userData = this.userData.concat(this.formData.tissuePersonList)
this.userDialogVisible = false
},
async delUser(row) {
this.userData.splice(this.userData.indexOf(row.userId), 1)
this.formData.tissuePersonList.splice(this.formData.tissuePersonList.indexOf(row.userId), 1)
},
openAddUser() {
this.formData.tissuePersonList = []
this.userDialogVisible = true
},
async operation() {
if (this.formData.applyTime2 && this.formData.applyTime2.length > 0) {
if (this.$moment(this.formData.time[0]).valueOf() <= this.$moment(this.formData.applyTime2[0]).valueOf()) {
this.$notify({
title: "警告",
message: "活动时间必须晚于报名时间",
type: "warning"
})
return
}
}
this.$refs["addForm"].validate(async (valid) => {
if (valid) {
this.formLoading = true
const formData = JSON.parse(JSON.stringify(this.formData))
formData.activity_type = this.activity_type
const { time, applyTime2, plannedDate } = formData
if (applyTime2 && applyTime2.length) {
formData.applyStartTime = applyTime2[0]
formData.applyEndTime = applyTime2[1]
formData.applyTime2 = null
}
if (time && time.length) {
formData.startTime = formData.time[0]
formData.endTime = formData.time[1]
formData.time = null
}
if (plannedDate && plannedDate.length) {
formData.startPlannedDate = formData.plannedDate[0]
formData.endPlannedDate = formData.plannedDate[1]
formData.plannedDate = null
}
const resp = await this.$axios.post("/platform/activity/culture/applyActivity" + (formData.id ? "/doEdit" : "/doAdd"), {
tissue: JSON.stringify(formData)
})
if (resp.code === 0) {
this.$message.success(resp.msg)
if (formData.id) {
this.$emit("goBack")
} else {
if (this.activity_type === 40002) {
pjaxReplace("/platform/activity/culture/infoManage/union")
} else if (this.activity_type === 40003) {
pjaxReplace("/platform/activity/culture/infoManage/club")
} else {
pjaxReplace("/platform/activity/culture/infoManage/school")
}
}
this.formLoading = false
} else {
this.notifyWarning(resp.msg)
}
} else {
this.notifyWarning("存在未填写的的必填项")
}
})
},
//应用比例设置
applyScaleSettings() {
this.formData.unionUserNumberLimit.forEach((v) => {
v.limitNum = parseFloat(((v.teacherCount * this.unionUserNumOneKeyRatio) / 100).toFixed(0))
if (v.ratio) {
v.limitNum = parseFloat(((v.teacherCount * v.ratio) / 100).toFixed(0))
}
})
this.calSummaryCount()
},
calSummaryCount() {
const array = this.formData.unionUserNumberLimit
if (array) {
this.summaryCount = array.reduce((prev, curr) => {
const value = Number(curr.limitNum)
if (!isNaN(value)) {
return prev + curr.limitNum
} else {
return prev
}
}, 0)
}
},
unionLimitQuickSetting() {
this.unionUserNumCalc.forEach((v, i) => {
const startNum = v.startNum
const endNum = v.endNum
const resultNum = v.resultNum
if (startNum > endNum) {
this.notifyWarning("第" + (i + 1) + "行设置错误")
} else {
this.formData.unionUserNumberLimit.forEach((x) => {
if (x.teacherCount >= startNum && x.teacherCount <= endNum) {
x.limitNum = resultNum
}
})
this.calSummaryCount()
}
})
},
plannedDateChange(val) {
this.$set(this.formData, "time", val)
},
userChang(id) {
const userList = this.$refs.userData.options
this.$set(this.formData, "mobile", id ? userList.find((v) => v.id === id).mobile : null)
},
async getActivityTwoLevelType(code) {
const { data } = await this.$axios.post("/platform/activity/basic/settings/getActivityTwoLevelType", { code: code })
return data
},
async getActivityGroup() {
const { data } = await this.$axios.post("/platform/activity/basic/scope/getActivityUserScopeGroup")
this.activityGroupList = data
},
async generateActivityCode() {
const { data } = await this.$axios.post("/platform/activity/sports/common/generateActivityCode", { activity_type: this.activity_type })
return data
},
async getUnionData() {
const { data } = await this.$axios.post("/platform/activity/culture/applyActivity/getUnionData", {
activityScopeGroupId: this.formData.groupId
})
return data
},
init() {
this.formData = {
time: [],
applyTime2: [],
plannedDate: [],
goods: [],
billFiles: [],
photoFiles: [],
otherFiles: [],
tissuePersonList: [],
unionUserNumberLimit: [],
signUpMethod: null,
rangerMeter: 100,
isEnrollSystem: true,
isPushHome: 0,
isIntegral: false
}
this.generateActivityCode().then((data) => {
this.$set(this.formData, "activityCode", data)
})
this.getUnionData().then((data) => {
this.$set(this.formData, "unionUserNumberLimit", data)
})
},
async queryUserByIds(ids) {
const { data } = await this.$axios.post("/platform/activity/culture/applyActivity/queryUserByIds", { ids: JSON.stringify(ids) })
return data
},
async findOne(id) {
const { data, code, msg } = await this.$axios.post("/platform/activity/culture/infoManage/findOne", { id })
if (code === 0) {
if (data.userId) {
const user = await this.queryUserByIds([data.userId])
await this.remoteMethod(user[0].loginname)
}
if (data.goods) data.goods = JSON.parse(data.goods)
if (data.billFiles && data.billFiles.length > 0) data.billFiles = JSON.parse(data.billFiles)
if (data.photoFiles && data.photoFiles.length > 0) data.photoFiles = JSON.parse(data.photoFiles)
if (data.otherFiles && data.otherFiles.length > 0) data.otherFiles = JSON.parse(data.otherFiles)
if (data.applyStartTime) data.applyTime2 = [data.applyStartTime, data.applyEndTime]
if (data.startTime) data.time = [data.startTime, data.endTime]
if (data.startPlannedDate) data.plannedDate = [data.startPlannedDate, data.endPlannedDate]
this.userData = clone(data.tissuePersonList)
data.unionUserNumberLimit = JSON.parse(data.unionUserNumberLimit)
this.formData = data
if (!this.formData.unionUserNumberLimit) {
this.getUnionData().then((data) => {
this.$set(this.formData, "unionUserNumberLimit", data)
})
}
}
},
openEdit(id) {
this.activeName = "1"
this.findOne(id)
}
},
async created() {
this.getActivityTwoLevelType("50000").then((data) => {
data.forEach((v) => {
if (v.code !== "50004") {
this.projectTypeList.push(v)
}
})
})
this.getActivityGroup()
this.init()
}
}
@@ -0,0 +1,154 @@
<!--#include("infoActivity.js"){}#-->
<!--#include("singleSignUp.js"){}#-->
const ACTIVITY_CULTURE_APPLY_USER = {
template: /*language=HTML*/ `
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="活动时间">
<el-date-picker
:clearable="false"
placeholder="活动时间"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="活动时间">
<el-input clearable placeholder="请输入活动名称"
v-model="pageForm.name"></el-input>
</search-item>
<search-item label="">
<el-radio-group v-model="pageForm.state" @change="doSearch">
<el-radio-button label="1">全部</el-radio-button>
<el-radio-button label="2">报名中</el-radio-button>
<el-radio-button label="3">报名已结束</el-radio-button>
</el-radio-group>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="活动列表">
<el-radio-group v-model="pageForm.isEnrolled" @change="doSearch" size="mini" class="ml10">
<el-radio-button :label="false">未报名</el-radio-button>
<el-radio-button :label="true">已报名</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" row-key="id"
style="width: 100%;margin-bottom: 20px">
<el-table-column :index="indexMethod" label="序号" type="index" width="80px"></el-table-column>
<el-table-column
:key="column.prop"
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='time'">
{{row.startTime}} 至 {{row.endTime}}
</template>
<template scope="{row}" v-else-if="column.prop=='projectTypeName'">
{{row.projectTypeName}}({{row.projectTypeCode}})
</template>
<template scope="{row}" v-else-if="column.prop=='tussueName'">
<span v-if="row.activity_type==40002">{{row.unionname?row.unionname:'暂无'}}</span>
<span v-if="row.activity_type==40003">{{row.clubName?row.clubName:'暂无'}}</span>
<span v-if="row.activity_type==40001">校工会</span>
</template>
<template scope="{row}" v-else-if="column.prop=='countUser'">
<el-tag size="small">{{row.countUser}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="300px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">
查看
</el-button>
<el-button
v-if="!row.isEnrolled && $moment(row.applyStartTime).valueOf()<$moment().valueOf() && $moment(row.applyEndTime).valueOf()>$moment().valueOf()"
@click="openSign(row)" size="mini" type="primary">
报名
</el-button>
<el-button v-if="row.isEnrolled" @click="openSign(row)" size="mini" type="primary">
报名情况
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<activity-culture-info-activity ref="infoActivity"></activity-culture-info-activity>
</template>
<single-signup ref="singleSignupRef" @refresh="doSearch"></single-signup>
</guava>
`,
store,
mixins: [initTableMixins],
props: {
activity_type: {
value: { type: Object, default: "" }
}
},
data() {
return {
submitLoading: false,
pageForm: {
isEnrolled: false,
state: 1,
year: new Date().getFullYear() + ""
},
tableColumns: [
{ prop: "name", label: "活动名称" },
{ prop: "address", label: "活动地点" },
{ prop: "projectTypeName", label: "活动项目类型" },
{ prop: "tussueName", label: "举办单位" },
{ prop: "time", label: "活动日期" },
{ prop: "applyStartTime", label: "报名开始时间" },
{ prop: "applyEndTime", label: "报名结束时间" }
]
}
},
components: {
"activity-culture-info-activity": ACTIVITY_CULTURE_INFO_ACTIVITY,
"single-signup": singleSignUp
},
methods: {
//打开报名
async openSign(row) {
this.$refs.singleSignupRef.onOpen(row.id)
},
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoActivity.findOne(row.id)
})
},
pageData() {
this.tableLoading = true
this.pageForm.activity_type = this.activity_type
this.$axios.post("/platform/activity/culture/applyUser/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
}).finally(() => {
this.tableLoading = false
})
}
},
async created() {
this.pageData()
}
}
@@ -0,0 +1,242 @@
<!--#include("infoActivity.js"){}#-->
const ACTIVITY_CULTURE_AUDIT_ACTIVITY = {
template: `
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="活动时间">
<el-date-picker
:clearable="false"
placeholder="活动时间"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="活动时间">
<el-input clearable placeholder="请输入活动名称"
v-model="pageForm.name"></el-input>
</search-item>
<search-item label="所属工会" v-if="activity_type===40002">
<el-select clearable filterable placeholder="请选择工会"
style="width: 100%"
v-model="pageForm.unionId">
<el-option
:key="item.id"
:label="item.name"
:value="item.id"
v-for="item in unionList">
</el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool :app="this" label="活动列表">
<el-radio-group @change="doSearch" size="small" v-model="pageForm.state">
<el-radio-button :key="i.code" :label="i.code" v-for="i in auditList">{{i.name}}
</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
class="vi-table" row-key="id" style="width: 100%;margin-bottom: 20px"
v-loading="tableLoading">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
align="center"
header-align="center"
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='time'">
{{$moment(row.startTime).format('YYYY-MM-DD')}} -
{{$moment(row.endTime).format('YYYY-MM-DD')}}
</template>
<template scope="{row}" v-else-if="column.prop=='projectTypeName'">
{{row.projectTypeName}}({{row.projectTypeCode}})
</template>
<template scope="{row}" v-else-if="column.prop=='tussueName'">
<span v-if="row.activity_type==40002">{{row.unionname?row.unionname:'暂无'}}</span>
<span v-if="row.activity_type==40003">{{row.clubName?row.clubName:'暂无'}}</span>
<span v-if="row.activity_type==40001">校工会</span>
</template>
<template scope="{row}" v-else-if="column.prop=='state'">
{{row.state===1?'未审核':row.state===2?'审核不通过':'审核通过'}}
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="150px">
<template slot-scope="{row}">
<el-button :loading="row.loading" @click="openView(row)" size="mini">
查看
</el-button>
<el-button :loading="row.loading" @click="openAudit(row)" size="mini"
type="primary"
v-if="row.state===1">
审核
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<activity-culture-info-activity handle label="校工会审核" ref="editInfo">
<template #handle>
<el-form :model="formData" label-position="right"
label-width="120px"
style="padding: 20px 0">
<el-form-item class="view-header" label="审核信息" label-width="135px">
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="审核人" prop="username">
<el-input disabled
v-model="formData.username"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审核时间" prop="time">
<el-input disabled v-model="formData.auditTime"></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="审核意见" prop="idea">
<el-input maxlength="500" placeholder="请填写您的审核意见"
rows="4" type="textarea"
v-model="formData.auditOpinion"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div style="float: right;margin: 20px 0">
<el-button :disabled="subDis" @click="doReview(false)"
type="danger">拒
</el-button>
<el-button :disabled="subDis" @click="doReview(true)"
type="success">通
</el-button>
</div>
</template>
</activity-culture-info-activity>
</template>
<template #view>
<activity-culture-info-activity ref="infoActivity"></activity-culture-info-activity>
</template>
</guava>
`,
props: {
activity_type: {
value: { type: Object, default: "" }
}
},
store,
mixins: [initTableMixins],
data() {
return {
subDis: false,
unionList: [],
auditList: [
{ code: true, name: "已审核" },
{ code: false, name: "未审核" }
],
pageForm: {
state: false,
year: new Date().getFullYear() + ""
},
tableColumns: [
{ prop: "name", label: "活动名称" },
{ prop: "address", label: "活动地点" },
{ prop: "projectTypeName", label: "活动项目类型" },
{ prop: "tussueName", label: "举办单位" },
{ prop: "time", label: "活动日期" },
{ prop: "applyTime", label: "创建时间", sortable: true },
{ prop: "state", label: "审核状态", sortable: true }
]
}
},
components: {
"activity-culture-info-activity": ACTIVITY_CULTURE_INFO_ACTIVITY
},
methods: {
async doReview(flag) {
const confirm = await this.$confirm("确定要审核" + (flag ? "通过" : "拒绝") + "吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
if (confirm === "confirm") {
this.formData.flag = flag
this.subDis = true
flag ? (this.subLoading2 = true) : (this.subLoading1 = true)
const resp = await $.post("/platform/activity/culture/auditActivity/doReview", this.formData)
if (resp.code === 0) {
this.pageData()
this.$refs.guava.index()
this.$message.success(resp.msg)
} else {
this.$message.error(resp.msg)
}
}
},
openAudit(row) {
this.$refs.guava.edit()
this.$refs.editInfo.findOne(row.id)
this.formData = {
id: row.id,
username: this.$store.state.user.username,
auditTime: this.$moment().format("YYYY-MM-DD")
}
},
openView(row) {
const { id } = row
this.$refs.guava.view()
this.$refs.infoActivity.findOne(id)
},
pageData() {
this.tableLoading = true
this.pageForm.activity_type = this.activity_type
this.$axios.post("/platform/activity/culture/auditActivity/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
this.tableLoading = false
}
},
async created() {
this.unionList = await this.$businessTool.listUnion()
this.pageData()
}
}
@@ -0,0 +1,193 @@
const ACTIVITY_CULTURE_INFO_ACTIVITY = {
template: /*language=HTML*/ `
<el-tabs tab-position="top" v-loading="loading" v-model="activeName">
<el-tab-pane label="活动基础信息" name="1">
<el-descriptions :column="3" border class="margin-top" style="margin: 10px" title="">
<el-descriptions-item label="活动名称" span="3">
<span class="item-center"> {{ viewData.name }}</span>
</el-descriptions-item>
<el-descriptions-item label="联系人">
<span v-if="viewData.username">
{{ viewData.username }}
({{ viewData.loginname }})</span>
</el-descriptions-item>
<el-descriptions-item label="联系方式">
{{ viewData.mobile }}
</el-descriptions-item>
<el-descriptions-item label="活动编号">
{{ viewData.activityCode }}
</el-descriptions-item>
<el-descriptions-item label="活动编号">
{{ viewData.projectTypeName }}({{ viewData.projectTypeCode }})
</el-descriptions-item>
<el-descriptions-item label="活动类型" :span="2">
{{ viewData.activity_type === 40001 ? '校工会活动' : viewData.activity_type === 40002 ? '分工会活动'
:
'协会/社团活动' }}
</el-descriptions-item>
<!-- <el-descriptions-item label="活动计划时间">-->
<!-- {{ viewData.startPlannedDate + ' - ' + viewData.endPlannedDate }}-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="活动时间">
{{ viewData.startTime + ' - ' + viewData.endTime }}
</el-descriptions-item>
<el-descriptions-item label="报名时间" v-if="viewData.applyStartTime">
{{ viewData.applyStartTime + ' - ' + viewData.applyEndTime }}
</el-descriptions-item>
<el-descriptions-item label="活动人数">
{{ viewData.peopleNum || '暂无' }}
</el-descriptions-item>
<el-descriptions-item label="活动地点">
{{ viewData.address }}
</el-descriptions-item>
<el-descriptions-item label="报名方式">
<span v-if="viewData.signUpMethod===1">个人报名</span>
<span v-else-if="viewData.signUpMethod===2">分工会报名</span>
<span v-else-if="viewData.signUpMethod===3">组队报名</span>
<span v-else-if="!viewData.signUpMethod">无需报名</span>
</el-descriptions-item>
<el-descriptions-item label="是否用于报名">
<span v-if="viewData.isEnrollSystem">活动报名</span>
<span v-else>活动管理</span>
</el-descriptions-item>
<el-descriptions-item label="报名人数限制" span="3" v-if="viewData.signUpMethod!=null">
<span v-if="viewData.userNumberLimit===1">总人数限制({{
viewData.totalUserNumberLimit
}}人)</span>
<span v-else-if="viewData.userNumberLimit===2">分工会人数限制</span>
<span v-else-if="!viewData.userNumberLimit">不限制</span>
</el-descriptions-item>
<el-descriptions-item label="分工会限制名额" span="3" v-if="viewData.userNumberLimit===2">
<el-table :data="viewData.unionUserNumberLimit" border height="500" size="small"
stripe>
<el-table-column align="center" header-align="center" label="序号"
type="index"
width="100">
</el-table-column>
<el-table-column label="分工会名称" prop="unionname"></el-table-column>
<el-table-column label="分工会人数" prop="teacherCount"></el-table-column>
<el-table-column label="限制人数" prop="limitNum"></el-table-column>
</el-table>
</el-descriptions-item>
<el-descriptions-item label="封面图" span="3">
<img :src="viewData.cover"
class="avatar"
style="height: 200px;width: auto" v-if="viewData.cover">
</el-descriptions-item>
<el-descriptions-item label="活动内容" span="3">
<div v-html="viewData.activityContent"></div>
</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="活动费用" name="2" v-if="!viewData.isEnrollSystem">
</el-tab-pane>
<el-tab-pane label="活动总结" name="3" v-if="!viewData.isEnrollSystem">
<el-form label-width="120px" ref="form">
<el-form-item label="活动总结" prop="activitySummary">
{{ viewData.activitySummary }}
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="审核信息" name="4" v-if="viewData.auditId">
<el-form label-width="120px" ref="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="审核人员:">
{{ viewData.audit.username }}
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="审核时间:">
{{ viewData.audit.auditTime }}
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="审核意见:">
{{ viewData.audit.auditOpinion }}
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-tab-pane>
<el-tab-pane :label="label" name="999" v-if="handle">
<slot name="handle"></slot>
</el-tab-pane>
</el-tabs>
`,
styles: [
`
.item-center {
width: 100%;
height: 100%;
display: block;
}
`
],
props: {
handle: {
type: Boolean,
default: false
},
label: {
type: String,
default: "审核"
}
},
data() {
return {
userData: [],
viewData: {},
loading: true,
search: "",
tableKey: "",
activeName: "1"
}
},
methods: {
hasPane(name) {
if (!this.handle) {
return true
}
return this.panes.includes(name)
},
async findOne(id) {
this.loading = true
const { data } = await this.$axios.post("/platform/activity/culture/infoManage/findOne", { id })
this.loading = false
if (data) {
data.billFiles = JSON.parse(data.billFiles)
data.photoFiles = JSON.parse(data.photoFiles)
data.otherFiles = JSON.parse(data.otherFiles)
this.userData = clone(data.tissuePersonList)
data.unionUserNumberLimit = JSON.parse(data.unionUserNumberLimit)
data.location = JSON.parse(data.location)
this.viewData = data
this.tableKey = new Date().getTime()
this.activeName = this.handle ? "999" : "1"
} else {
this.viewData = {}
this.$notify.error({ title: "错误", message: "获取信息失败" })
}
}
}
}
// <style>
// .item-center {
// text-align: center;
// font-weight: 700;
// margin-right: 110px;
// }
//
// .item-center .el-form-item__content {
// font-size: 18px;
// }
//
// .el-descriptions-item__cell {
// text-align: center !important;
// }
// </style>
@@ -0,0 +1,240 @@
<!--#include("applyActivity.js"){}#-->
<!--#include("infoActivity.js"){}#-->
const ACTIVITY_CULTURE_INFO_MANAGE = {
template: /*language=HTML*/`
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="活动时间">
<el-date-picker
:clearable="false"
placeholder="活动时间"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="活动名称">
<el-input clearable placeholder="请输入活动名称"
v-model="pageForm.name"></el-input>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="活动列表">
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
class="vi-table" row-key="id" style="width: 100%;margin-bottom: 20px"
v-loading="tableLoading">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
width="80px"></el-table-column>
<el-table-column
:key="column.prop"
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop=='time2'">
{{row.applyStartTime}}-{{row.applyEndTime}}
</template>
<template scope="{row}" v-else-if="column.prop=='projectTypeName'">
{{row.projectTypeName}}({{row.projectTypeCode}})
</template>
<template scope="{row}" v-else-if="column.prop=='isUnseal'">
<el-switch
@change="(val)=>{activityStatusChange(row.id,row.isUnseal)}"
active-color="#13ce66"
inactive-color="#ff4949"
v-model="row.isUnseal">
</el-switch>
</template>
<template scope="{row}" v-else-if="column.prop=='tussueName'">
<span v-if="row.activity_type==40002">{{row.unionname?row.unionname:'暂无'}}</span>
<span v-if="row.activity_type==40003">{{row.clubName?row.clubName:'暂无'}}</span>
<span v-if="row.activity_type==40001">校工会</span>
</template>
<template scope="{row}" v-else-if="column.prop=='state'">
{{row.state===1?'未审核':row.state===2?'审核不通过':'审核通过'}}
</template>
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
prop="userOnline" width="150px">
<template slot-scope="{row}">
<el-dropdown @command="dropdownCommand">
<el-button :loading="row.loading" size="mini">
<i class="ti-settings"></i>
<span class="ti-angle-down"></span>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{type:'view',row}">
查看
</el-dropdown-item>
<el-dropdown-item :command="{type:'edit',row}"
:disabled="row.projectTypeCode==50004">
编辑
</el-dropdown-item>
<el-dropdown-item :command="{type:'delete',row}">
删除
</el-dropdown-item>
<el-dropdown-item :command="{type:'openCode',row}">
二维码
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #edit>
<activity-culture-apply-activity
:activity_type="activity_type" ref="applyActivity" @goBack="goBack"></activity-culture-apply-activity>
</template>
<template #view>
<activity-culture-info-activity ref="infoActivity"></activity-culture-info-activity>
</template>
<el-dialog
title="活动二维码"
:visible.sync="codeDialogVisible"
:close-on-click-modal="false"
width="30%">
<div style=" display: flex;justify-content: center;">
<qrcode :options="{ width: 500 }" :value="url" ></qrcode>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="codeDialogVisible = false" type="primary">关 闭</el-button>
</span>
</el-dialog>
</guava>
`,
props: {
activity_type: {
value: {type: Object, default: ""}
}
},
mixins: [initTableMixins],
data() {
return {
codeDialogVisible: false,
pageForm: {
year: new Date().getFullYear() + ""
},
tableColumns: [
{prop: "name", label: "活动名称"},
{prop: "address", label: "活动地点"},
{prop: "projectTypeName", label: "活动项目类型"},
{prop: "tussueName", label: "举办单位"},
{prop: "time2", label: "报名日期", width: "300"},
{prop: "applyTime", label: "创建时间", sortable: true},
{prop: "isUnseal", label: "是否开启"},
{prop: "state", label: "审核状态", sortable: true}
],
url: ""
}
},
components: {
"activity-culture-apply-activity": ACTIVITY_CULTURE_APPLY_ACTIVITY,
"activity-culture-info-activity": ACTIVITY_CULTURE_INFO_ACTIVITY
},
methods: {
async activityStatusChange(id, isUnseal) {
const resp = await this.$axios.post("/platform/activity/culture/infoManage/activityStatusChange", {
id: id,
isUnseal: isUnseal
})
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg)
} else {
this.$message.error(resp.msg)
}
},
dropdownCommand(command) {
const {type, row} = command
if (type === "view") {
this.openView(row)
} else if (type === "edit") {
this.openEdit(row)
} else if (type === "delete") {
this.doDelete(row)
} else if (type === "openCode") {
this.url = location.origin + "/platform/h5/activity/culture/applyUser"
this.codeDialogVisible = true
} else if (type === "export") {
location.href = "/platform/activity/info/mange/export?id=" + row.id
}
},
goBack() {
this.doSearch()
this.$refs.guava.index()
},
openEdit(row) {
this.$refs.guava.edit(() => {
this.$refs.applyActivity.openEdit(row.id)
})
},
openView(row) {
this.$refs.guava.view(() => {
this.$refs.infoActivity.findOne(row.id)
})
},
doDelete(row) {
const {id} = row
this.$confirm("确定要删除该活动吗?", "提示", {type: "warning"}).then(async () => {
this.$set(row, "loading", true)
const resp = await this.$axios.post("/platform/activity/culture/infoManage/doDelete", {id: id})
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg)
} else {
this.$message.error(resp.msg)
}
this.$set(row, "loading", false)
})
},
pageData() {
this.tableLoading = true
this.pageForm.activity_type = this.activity_type
this.$axios.post("/platform/activity/culture/infoManage/pageData", this.pageForm).then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
this.tableLoading = false
}
},
async created() {
this.pageData()
}
}
@@ -0,0 +1,472 @@
const singleSignUp = {
template: /*language=HTML*/ `
<el-dialog title="活动报名" :visible.sync="dialogVisible" width="70%">
<div class="process-title">活动信息</div>
<el-descriptions :column="3" border class="margin-top" style="margin: 10px" title="">
<el-descriptions-item label="活动名称" span="3">
<span class="item-center"> {{ viewData.name }}</span>
</el-descriptions-item>
<el-descriptions-item label="联系人">
<span v-if="viewData.username">
{{ viewData.username }}
({{ viewData.loginname }})</span>
</el-descriptions-item>
<el-descriptions-item label="联系方式">
{{ viewData.mobile }}
</el-descriptions-item>
<el-descriptions-item label="活动编号">
{{ viewData.activityCode }}
</el-descriptions-item>
<el-descriptions-item label="活动编号">
{{ viewData.projectTypeName }}({{ viewData.projectTypeCode }})
</el-descriptions-item>
<el-descriptions-item label="活动类型" :span="2">
{{ viewData.activity_type === 40001 ? '校工会活动' : viewData.activity_type === 40002 ? '分工会活动'
:
'协会/社团活动' }}
</el-descriptions-item>
<!-- <el-descriptions-item label="活动计划时间">-->
<!-- {{ viewData.startPlannedDate + ' - ' + viewData.endPlannedDate }}-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="活动时间">
{{ viewData.startTime + ' - ' + viewData.endTime }}
</el-descriptions-item>
<el-descriptions-item label="报名时间" v-if="viewData.applyStartTime">
{{ viewData.applyStartTime + ' - ' + viewData.applyEndTime }}
</el-descriptions-item>
<el-descriptions-item label="活动人数">
{{ viewData.peopleNum || '暂无' }}
</el-descriptions-item>
<el-descriptions-item label="活动地点">
{{ viewData.address }}
</el-descriptions-item>
<el-descriptions-item label="报名方式">
<span v-if="viewData.signUpMethod===1">个人报名</span>
<span v-else-if="viewData.signUpMethod===2">分工会报名</span>
<span v-else-if="viewData.signUpMethod===3">组队报名</span>
<span v-else-if="!viewData.signUpMethod">无需报名</span>
</el-descriptions-item>
<el-descriptions-item label="是否用于报名">
<span v-if="viewData.isEnrollSystem">活动报名</span>
<span v-else>活动管理</span>
</el-descriptions-item>
<el-descriptions-item label="报名人数限制" span="3" v-if="viewData.signUpMethod!=null">
<span v-if="viewData.userNumberLimit===1">总人数限制({{
viewData.totalUserNumberLimit
}}人)</span>
<span v-else-if="viewData.userNumberLimit===2">分工会人数限制</span>
<span v-else-if="!viewData.userNumberLimit">不限制</span>
</el-descriptions-item>
<el-descriptions-item label="分工会限制名额" span="3" v-if="viewData.userNumberLimit===2">
<el-table :data="viewData.unionUserNumberLimit" border height="500" size="small"
stripe>
<el-table-column align="center" header-align="center" label="序号"
type="index"
width="100">
</el-table-column>
<el-table-column label="分工会名称" prop="unionname"></el-table-column>
<el-table-column label="分工会人数" prop="teacherCount"></el-table-column>
<el-table-column label="限制人数" prop="limitNum"></el-table-column>
</el-table>
</el-descriptions-item>
<el-descriptions-item label="封面图" span="3">
<img :src="viewData.cover"
class="avatar"
style="height: 200px;width: auto" v-if="viewData.cover">
</el-descriptions-item>
<el-descriptions-item label="活动内容" span="3">
<div v-html="viewData.activityContent"></div>
</el-descriptions-item>
</el-descriptions>
<!-- 个人报名 啥也不要-->
<div v-if="viewData.signUpMethod===1">
<div class="process-title">个人报名信息</div>
<el-table :data="teamUsers" class="mt10">
<el-table-column label="序号" type="index" width="60px"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unitName" label="单位"></el-table-column>
<el-table-column prop="mobile" label="手机号"></el-table-column>
<el-table-column prop="applyUserId" label="标识">
<template slot-scope="{row}">
<el-tag size="mini" v-if="row.applyUserId==row.userId">
报名人
</el-tag>
</template>
</el-table-column>
</el-table>
</div>
<!-- 组队报名-->
<div v-else-if="viewData.signUpMethod===2">
<div class="process-title">选择组队队友,组队人数 <span style="color: red">{{viewData.teamNum}}</span>人
</div>
<span v-if="!isApplyUser" class="text-primary">如需取消报名,请联系报名人。</span>
<el-select
v-if="isApplyUser && inApplyTime"
v-model="searchTeammateUserId"
filterable
clearable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="queryTeammate">
<el-option
v-for="item in teammateOptions"
:key="item.userId"
:label="item.userName + '(' + item.loginName + ')'"
:value="item.userId">
</el-option>
</el-select>
<el-button v-if="isApplyUser && inApplyTime" class="ml5" type="primary" icon="el-icon-plus"
@click="addTeamUser">添加
</el-button>
<el-table :data="teamUsers" class="mt10">
<el-table-column label="序号" type="index" width="60px"></el-table-column>
<el-table-column prop="userName" label="姓名"></el-table-column>
<el-table-column prop="loginName" label="工号"></el-table-column>
<el-table-column prop="sex" label="性别"></el-table-column>
<el-table-column prop="unitName" label="单位"></el-table-column>
<el-table-column prop="mobile" label="手机号"></el-table-column>
<el-table-column prop="applyUserId" label="标识">
<template slot-scope="{row}">
<!-- v-if="scope.row.applyUserId===scope.row.userId"-->
<el-tag size="mini" v-if="row.applyUserId==row.userId">
报名人
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="100px"
v-if="(isApplyUser || teamUsers.length===0) && inApplyTime">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="removeTeamUser(scope.$index)"
v-if="scope.row.applyUserId!==scope.row.userId">删除
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分工会报名-->
<div v-else-if="viewData.signUpMethod===3">
</div>
<!-- 表单填写-->
<template v-if="isCustomForm">
<div class="process-title">填写报名信息</div>
<form-create
:value.sync="dynamicFormData"
v-model="fapi"
:rule="formCreateRule"
:option="formCreateOption"
></form-create>
</template>
<template slot="footer">
<el-button type="" @click="dialogVisible = false">取消</el-button>
<!-- 报名人才有的权限 -->
<template v-if="isApplyUser">
<el-button v-if="!isSignUp && inApplyTime" type="primary" @click="onConfirm">确认报名</el-button>
<el-button v-if="isSignUp && inApplyTime" type="primary" @click="onConfirmAgain">重新提交
</el-button>
<el-button v-if="isSignUp && inApplyTime" type="danger" @click="onCancel">取消报名</el-button>
</template>
</template>
</el-dialog>
`,
store,
data() {
return {
dialogVisible: false,
viewData: {},
id: null,
dynamicFormData: {},
formCreateRule: [],
formCreateOption: {},
fapi: null,
//搜索框
searchTeammateUserId: null,
//搜索框选新娘
teammateOptions: [],
//表格用户
teamUsers: [],
//是否报名
isSignUp: false
}
},
computed: {
isCustomForm() {
return this.viewData && this.viewData.formConfig != null && this.viewData.formConfig !== ""
},
//是否报名人
isApplyUser() {
if (this.teamUsers) {
return this.teamUsers.every((v) => v.applyUserId === this.$store.state.user.id)
} else {
return true
}
},
//是否在活动报名时间内
inApplyTime() {
if (this.viewData) {
const now = new Date().getTime()
const start = this.$moment(this.viewData.applyStartTime).valueOf()
const end = this.$moment(this.viewData.applyEndTime).valueOf()
return now >= start && now <= end
}
return false
}
},
methods: {
onOpen(id) {
this.dialogVisible = true
this.id = id
this.activityInfo()
},
//查询报名人员
listTeamUser() {
this.$axios.post("/platform/activity/culture/applyUser/listTeamUser", { activityId: this.id }).then((res) => {
if (res.code === 0) {
this.isSignUp = res.data.length > 0
this.teamUsers = res.data
this.defaultAddSelf()
this.customFormInit()
}
})
},
//表单回显
customFormInit() {
if (this.teamUsers && this.teamUsers.length > 0) {
const self = this.teamUsers.find((v) => v.userId === this.$store.state.user.id)
if (self && this.isCustomForm) {
this.dynamicFormData = self.dynamicFormData
}
}
},
//组队和个人报名默认增加自己
defaultAddSelf() {
if (this.teamUsers.length === 0 && [1, 2].includes(this.viewData.signUpMethod)) {
this.teamUsers.push({
userId: this.$store.state.user.id,
userName: this.$store.state.user.username,
loginName: this.$store.state.user.loginname,
sex: this.$store.state.user.sex,
unitName: this.$store.state.user?.unit?.name,
mobile: this.$store.state.user.mobile,
applyUserId: this.$store.state.user.id
})
}
},
//提交报名
async onConfirm() {
console.log(this.fapi)
console.log(this.fapi.formData())
if (this.isCustomForm && this.fapi) {
let formValid = false
try {
await this.fapi.validate()
formValid = true
} catch (e) {
formValid = false
}
if (!formValid) return
}
//组队
if (this.viewData.signUpMethod === 2) {
//组队人数判断
if (this.teamUsers.length === 0) {
this.$message.warning("请添加队友后再提交!")
return
}
if (this.teamUsers.length < this.viewData.teamNum) {
this.$message.warning("您选择的人数小于" + this.viewData.teamNum + "人,请重新选择!")
return
}
if (this.teamUsers.length > this.viewData.teamNum) {
this.$message.warning("您选择的人数大于" + this.viewData.teamNum + "人,请重新选择!")
return
}
}
//分工会
if (this.viewData.signUpMethod === 3) {
// if (this.teamUsers.length === 0) {
// this.$message.warning("请添加报名人员后再提交!")
// return
// }
// if (this.teamUsers.length > this.viewData.teamNum) {
// this.$message.warning("您选择的人数大于" + this.viewData.teamNum + "人,请重新选择!")
// return
// }
}
let formData = {
activityId: this.id
}
if (this.isCustomForm) {
formData.ext = JSON.stringify(this.fapi.formData())
}
if (this.viewData.signUpMethod === 2 || this.viewData.signUpMethod === 3) {
formData.teamUserIds = JSON.stringify(this.teamUsers.map((v) => v.userId))
}
this.$confirm("确定提交报名信息吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/activity/culture/applyUser/signUp", formData).then((res) => {
if (res.code === 0) {
this.dialogVisible = false
this.$message.success(res.msg)
this.$emit("refresh", null)
}
})
})
// this.fapi.validate((valid, fail) => {
//
// })
},
//再次报名
onConfirmAgain() {
if (this.isCustomForm && this.fapi) {
console.log(this.fapi.validate())
}
//组队
if (this.viewData.signUpMethod === 2) {
//组队人数判断
if (this.teamUsers.length === 0) {
this.$message.warning("请添加队友后再提交!")
return
}
if (this.teamUsers.length < this.viewData.teamNum) {
this.$message.warning("您选择的人数小于" + this.viewData.teamNum + "人,请重新选择!")
return
}
if (this.teamUsers.length > this.viewData.teamNum) {
this.$message.warning("您选择的人数大于" + this.viewData.teamNum + "人,请重新选择!")
return
}
}
//分工会
if (this.viewData.signUpMethod === 3) {
if (this.teamUsers.length === 0) {
this.$message.warning("请添加报名人员后再提交!")
return
}
if (this.teamUsers.length > this.viewData.teamNum) {
this.$message.warning("您选择的人数大于" + this.viewData.teamNum + "人,请重新选择!")
return
}
}
let formData = {
activityId: this.id,
isAgain: true
}
if (this.isCustomForm) {
formData.ext = JSON.stringify(this.fapi.formData())
}
if (this.viewData.signUpMethod === 2 || this.viewData.signUpMethod === 3) {
formData.teamUserIds = JSON.stringify(this.teamUsers.map((v) => v.userId))
}
this.$confirm("确定重新提交报名信息吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/activity/culture/applyUser/signUp", formData).then((res) => {
if (res.code === 0) {
this.dialogVisible = false
this.$message.success(res.msg)
this.$emit("refresh", null)
}
})
})
},
//取消报名
onCancel() {
this.$confirm("确定取消报名吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.$axios.post("/platform/activity/culture/applyUser/cancelSignUp", { activityId: this.id }).then((res) => {
if (res.code === 0) {
this.dialogVisible = false
this.$message.success(res.msg)
this.$emit("refresh", null)
}
})
})
},
//查询队友信息
queryTeammate(val) {
if (val) {
this.$axios.post("/platform/activity/culture/applyUser/queryTeammate", { keyword: val }).then((res) => {
if (res.code === 0) {
this.teammateOptions = res.data
}
})
}
},
//添加队友
addTeamUser() {
if (!this.searchTeammateUserId) {
this.$message.error("请先选择后再添加")
return
}
if (this.teamUsers.some((v) => v.userId === this.searchTeammateUserId)) {
this.$message.error("请勿重复添加")
return
}
if (this.teamUsers.length >= this.viewData.teamNum) {
this.$message.error("已满员")
return
}
this.teamUsers.push(this.teammateOptions.find((v) => v.userId === this.searchTeammateUserId))
this.searchTeammateUserId = null
},
//移除队友
removeTeamUser(index) {
this.teamUsers.splice(index, 1)
},
//活动信息
activityInfo() {
this.$axios.post("/platform/activity/culture/infoManage/activityInfo", { id: this.id }).then((res) => {
if (res.code === 0) {
this.viewData = res.data
if (this.viewData.formConfig) {
this.formCreateRule = formCreate.parseJson(this.viewData.formConfig.rule)
this.formCreateOption = formCreate.parseJson(this.viewData.formConfig.options)
}
this.listTeamUser()
}
})
}
}
}
@@ -0,0 +1,204 @@
const ACTIVITY_CULTURE_USER_STATISTICS = {
template: /*language=HTML*/ `
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="活动时间">
<el-date-picker
@change="getActivityByYearOrType"
:clearable="false"
placeholder="活动时间"
style="width: 100%"
type="year"
v-model="pageForm.year"
value-format="yyyy"
></el-date-picker>
</search-item>
<search-item label="活动名称">
<el-select filterable placeholder="请选择活动" style="width: 100%"
v-model="pageForm.activityId">
<el-option
:key="item.id"
:label="item.name"
:value="item.id"
v-for="item in activityList">
</el-option>
</el-select>
</search-item>
<search-item label="工会名称" v-if="activity_type===40002||activity_type===40001">
<el-select clearable filterable placeholder="请选择工会"
style="width: 100%"
v-model="pageForm.unionId">
<el-option
:key="item.id"
:label="item.name"
:value="item.id"
v-for="item in unionList">
</el-option>
</el-select>
</search-item>
<search-item label="姓名/工号">
<el-input @keyup.enter.native="doSearch" clearable
placeholder="请输入姓名/工号"
v-model="pageForm.searchKeyword">
<el-select placeholder="姓名/工号" slot="prepend"
style="width: 80px;"
v-model="pageForm.searchName">
<el-option label="姓名" value="atp.username"></el-option>
<el-option label="工号" value="atp.loginanme"></el-option>
</el-select>
</el-input>
</search-item>
</search>
</el-card>
<el-card class="mt10" shadow="never">
<table-tool label="人员列表">
<el-button @click="doExport" icon="el-icon-s-promotion" type="primary" size="mini">导出
</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" row-key="id"
style="width: 100%;" v-loading="tableLoading">
<el-table-column :index="indexMethod" align="center" header-align="center"
label="序号" type="index"
fixed="left"
width="80px"></el-table-column>
<el-table-column
:key="column.prop"
:label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:fixed="column.fixed"
:min-width="column.width || 180"
align="center"
header-align="center"
show-overflow-tooltip
v-for="column in fullTableColumns">
<template v-if="column.type==='tableForm'" scope="{row}">
<el-link @click="openMore(row.dynamicFormData)">点击查看</el-link>
</template>
<template v-else-if="column.type==='upload'" scope="{row}">
<el-link @click="openDownload(row.dynamicFormData,column.field)">点击下载</el-link>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<dynamic-Table-form-eval ref="dynamicTableFormEvalRef"></dynamic-Table-form-eval>
</guava>
`,
props: {
activity_type: {
value: { type: Object, default: "" }
}
},
mixins: [initTableMixins],
data() {
return {
unionList: [],
activityList: [],
pageForm: {
unionId: "",
searchName: "atp.username",
year: new Date().getFullYear() + ""
},
tableColumns: [
{ prop: "userName", label: "姓名", width: 180, fixed: "left" },
{ prop: "loginName", label: "工号", width: 180, fixed: "left" },
{ prop: "sex", label: "性别", width: 70 },
{ prop: "mobile", label: "联系方式", width: 180 },
{ prop: "unitName", label: "所属单位", width: 200 },
{ prop: "unionName", label: "所属工会", width: 200 },
{ prop: "applyDateTime", label: "报名时间", width: 180 },
{ prop: "applyUserUserName", label: "报名人", width: 180 }
],
dynamicTableColumns: []
}
},
computed: {
fullTableColumns() {
return this.tableColumns.concat(this.dynamicTableColumns)
}
},
methods: {
getNestedValue: getNestedValue,
openMore(dynamicFormData) {
const formConfig = this.activityList.find((v) => v.id === this.pageForm.activityId)?.formConfig
this.$refs.dynamicTableFormEvalRef.onOpen(formConfig, dynamicFormData)
},
openDownload(data,key){
const jsonData = JSON.parse(data)
const urls = jsonData[key]
if(urls){
this.$downLoad(urls[0])
}
},
async doExport() {
if (!this.pageForm.activityId) {
return
}
const { activityId, unionId } = this.pageForm
this.$downLoad("/platform/activity/culture/userStatistics/doExportUser", {
id: activityId,
unionId: unionId
})
},
pageData() {
if (!this.pageForm.activityId) {
return
}
this.$axios
.post("/platform/activity/culture/userStatistics/dynamicTableColumns", { activityId: this.pageForm.activityId })
.then((res) => {
if (res.code === 0) {
this.dynamicTableColumns = res.data
}
})
this.tableLoading = true
this.pageForm.activity_type = this.activity_type
this.$axios
.post("/platform/activity/culture/userStatistics/pageData", this.pageForm)
.then((res) => {
if (res.code === 0) {
this.tableData = res.data.list
this.pageForm.totalCount = res.data.totalCount
}
})
.finally(() => {
this.tableLoading = false
})
},
async getActivityByYearOrType() {
const resp = await $.get("/platform/activity/culture/userStatistics/getActivityByYearOrType", {
activity_type: this.activity_type,
year: this.pageForm.year
})
if (resp.code === 0) {
this.activityList = resp.data
if (resp.data && resp.data.length > 0) {
this.$set(this.pageForm, "activityId", resp.data[0].id)
this.pageData()
} else {
this.$set(this.pageForm, "activityId", null)
}
}
}
},
async created() {
await this.getActivityByYearOrType()
this.unionList = await this.$businessTool.listUnion()
}
}
@@ -0,0 +1,32 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-apply-activity :activity_type="activityType"></activity-culture-apply-activity>
</guava>
</div>
<script>
<!--#include("../../common/applyActivity.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40001
}
},
components: {
"activity-culture-apply-activity": ACTIVITY_CULTURE_APPLY_ACTIVITY
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,32 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-apply-user :activity_type="activityType"></activity-culture-apply-user>
</guava>
</div>
<script>
<!--#include("../../common/applyUser.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40001
}
},
components: {
"activity-culture-apply-user": ACTIVITY_CULTURE_APPLY_USER
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,30 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<activity-culture-info-manage :activity_type="activityType"></activity-culture-info-manage>
</div>
<script>
<!--#include("../../common/infoMange.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40001
}
},
components: {
"activity-culture-info-manage": ACTIVITY_CULTURE_INFO_MANAGE
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,32 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-user-statistics :activity_type="activityType"></activity-culture-user-statistics>
</guava>
</div>
<script>
<!--#include("../../common/userStatistics.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40001
}
},
components: {
"activity-culture-user-statistics": ACTIVITY_CULTURE_USER_STATISTICS
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,31 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-apply-activity :activity_type="activityType"></activity-culture-apply-activity>
</guava>
</div>
<script>
<!--#include("../../common/applyActivity.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40002
}
},
components: {
"activity-culture-apply-activity": ACTIVITY_CULTURE_APPLY_ACTIVITY
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,32 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<activity-culture-apply-user :activity_type="activityType"></activity-culture-apply-user>
</guava>
</div>
<script>
<!--#include("../../common/applyUser.js"){}#-->
new Vue({
el: "#app",
store,
mixins: [initTableMixins],
data() {
return {
activityType: 40002
}
},
components: {
"activity-culture-apply-user": ACTIVITY_CULTURE_APPLY_USER
},
methods: {},
async created() {}
})
</script>
<!--#
}
#-->

Some files were not shown because too many files have changed in this diff Show More