xy 2 years ago
parent 57e0e61036
commit f4897c4ea2

@ -1,5 +1,5 @@
<template> <template>
<div> <div style="position: sticky;top: 0;z-index: 1002;">
<header class="navbar"> <header class="navbar">
<div class="container"> <div class="container">
<!-- <button v-show="$store.state.app.device === 'mobile'" :aria-expanded="isShowMenuMobile" class="navbar-toggler" @click="isShowMenuMobile = !isShowMenuMobile">--> <!-- <button v-show="$store.state.app.device === 'mobile'" :aria-expanded="isShowMenuMobile" class="navbar-toggler" @click="isShowMenuMobile = !isShowMenuMobile">-->
@ -18,9 +18,9 @@
<svg-icon icon-class="modules" class-name="modules__toggler" @click="isShowMenuMobile = !isShowMenuMobile" /> <svg-icon icon-class="modules" class-name="modules__toggler" @click="isShowMenuMobile = !isShowMenuMobile" />
<el-menu <el-menu
id="navbar-menu" id="navbar-menu"
:text-color="variables.menuText" text-color="hsla(0,0%,100%,.7)"
:background-color="variables.menuBg" background-color="var(--theme-color)"
:active-text-color="variables.menuActiveText" active-text-color="#fff"
:default-active="activeMenu" :default-active="activeMenu"
mode="horizontal" mode="horizontal"
> >
@ -99,9 +99,9 @@
<el-menu <el-menu
unique-opened unique-opened
style="width: 100%;padding: 0 6px;" style="width: 100%;padding: 0 6px;"
:text-color="variables.menuText" text-color="hsla(0,0%,100%,.7)"
:background-color="variables.menuBg" background-color="transparent"
:active-text-color="variables.menuActiveText" active-text-color="#fff"
:default-active="activeMenu" :default-active="activeMenu"
@select="isShowMenuMobile = false" @select="isShowMenuMobile = false"
> >
@ -184,6 +184,7 @@ export default {
this.isIframeSidebarOpened = Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true this.isIframeSidebarOpened = Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true
} else { } else {
this.$store.commit('app/TOGGLE_SIDEBAR') this.$store.commit('app/TOGGLE_SIDEBAR')
this.isIframeSidebarOpened = this.$store.getters.sidebar.opened
} }
}, },
handleFullscreen() { handleFullscreen() {

@ -20,7 +20,7 @@ export default {
if (icon.includes('el-icon')) { if (icon.includes('el-icon')) {
vnodes.push(<i class={[icon, 'sub-el-icon']} />) vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else { } else {
vnodes.push(<svg-icon icon-class={icon} class="sub-el-icon" />) vnodes.push(<svg-icon icon-class={icon} class='sub-el-icon' />)
} }
} }
@ -35,9 +35,9 @@ export default {
<style scoped> <style scoped>
.sub-el-icon { .sub-el-icon {
color: currentColor; color: currentColor;
font-size: 16px; font-size: 15px;
width: 16px; width: 15px;
height: 16px; height: 15px;
margin-right: 5px; margin-right: 5px;
} }
</style> </style>

@ -1,5 +1,5 @@
<template> <template>
<div :class="{'has-logo':showLogo}"> <div :class="{'has-logo':false}">
<el-scrollbar wrap-class="scrollbar-wrapper"> <el-scrollbar wrap-class="scrollbar-wrapper">
<el-menu <el-menu
:default-active="activeMenu" :default-active="activeMenu"
@ -7,7 +7,7 @@
:background-color="variables.menuBg" :background-color="variables.menuBg"
:text-color="variables.menuText" :text-color="variables.menuText"
:unique-opened="false" :unique-opened="false"
:active-text-color="variables.menuActiveText" active-text-color="var(--theme-color)"
:collapse-transition="false" :collapse-transition="false"
mode="vertical" mode="vertical"
> >
@ -20,7 +20,7 @@
<script> <script>
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import SidebarItem from './SidebarItem' import SidebarItem from './SidebarItem'
import variables from '@/styles/sidebar-variables.scss' import variables from '@/styles/variables.scss'
export default { export default {
components: { SidebarItem }, components: { SidebarItem },
@ -55,3 +55,9 @@ export default {
} }
} }
</script> </script>
<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
@import '~@/styles/sidebar.scss';
</style>

@ -3,7 +3,6 @@
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<navbar /> <navbar />
<div class="main-container"> <div class="main-container">
<div :class="{'fixed-header':fixedHeader}" />
<app-main /> <app-main />
</div> </div>
</div> </div>
@ -50,7 +49,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
@import "~@/styles/mixin.scss"; @import "~@/styles/mixin.scss";
@import "~@/styles/variables.scss";
.app-wrapper { .app-wrapper {
@include clearfix; @include clearfix;
@ -72,15 +70,6 @@ export default {
z-index: 999; z-index: 999;
} }
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.hideSidebar .fixed-header { .hideSidebar .fixed-header {
width: calc(100% - 54px) width: calc(100% - 54px)
} }

@ -27,7 +27,7 @@ if (process.env.NODE_ENV === 'production') {
const { mockXHR } = require('../mock') const { mockXHR } = require('../mock')
mockXHR() mockXHR()
} }
//moment // moment
import moment from 'moment' import moment from 'moment'
Vue.prototype.$moment = moment Vue.prototype.$moment = moment
// set ElementUI lang to EN // set ElementUI lang to EN
@ -46,6 +46,9 @@ Vue.use(VxeColumn)
Vue.use(VxeColgroup) Vue.use(VxeColgroup)
Vue.use(VxeModal) Vue.use(VxeModal)
Vue.use(VxeToolbar) Vue.use(VxeToolbar)
import domZIndex from 'dom-zindex'
domZIndex.setCurrent(2000)
// treeselect // treeselect
import '@riophae/vue-treeselect/dist/vue-treeselect.css' import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import Treeselect from '@riophae/vue-treeselect' import Treeselect from '@riophae/vue-treeselect'
@ -66,7 +69,9 @@ Vue.component('CardContainer', CardContainer)
// exec: true, // exec: true,
// }); // });
Vue.config.productionTip = false Vue.config.productionTip = false
Vue.config.errorHandler = (err, vm, info) => {
console.error(info, err)
}
new Vue({ new Vue({
el: '#app', el: '#app',
router, router,

@ -42,9 +42,9 @@ const mutations = {
const actions = { const actions = {
// user login // user login
login({ commit }, userInfo) { login({ commit }, userInfo) {
const { username, password } = userInfo const { username, password, pretend_user } = userInfo
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
login({ username: username.trim(), password: password }).then(response => { login({ username: username.trim(), password: password, pretend_user }).then(response => {
console.log(response) console.log(response)
const { access_token, expires_in } = response const { access_token, expires_in } = response
commit('SET_TOKEN', access_token) commit('SET_TOKEN', access_token)
@ -63,7 +63,7 @@ const actions = {
const { name, avatar, id, role, department } = response const { name, avatar, id, role, department } = response
commit('SET_DEPARTMENT',department) commit('SET_DEPARTMENT', department)
commit('SET_NAME', name) commit('SET_NAME', name)
commit('SET_AVATAR', avatar) commit('SET_AVATAR', avatar)
commit('SET_ADMIN_ID', id) commit('SET_ADMIN_ID', id)

@ -3,6 +3,7 @@
@import './transition.scss'; @import './transition.scss';
@import './element-ui.scss'; @import './element-ui.scss';
body { body {
height: 100%; height: 100%;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
@ -25,8 +26,8 @@ html {
} }
*, *,
*:before, *::before,
*:after { *::after {
box-sizing: inherit; box-sizing: inherit;
} }

@ -151,13 +151,12 @@
} }
} }
@import "variables.scss";
#navbar-menu { #navbar-menu {
.sidebar-item { .sidebar-item {
display: inline-block; display: inline-block;
.el-menu-item:hover ,.el-submenu__title:hover { .el-menu-item:hover ,.el-submenu__title:hover {
color: $menuActiveText !important; color: #fff !important;
background-color: transparent !important; background-color: transparent !important;
} }
} }

@ -1,27 +0,0 @@
// sidebar
$menuText:#606266;
$menuActiveText:#303133;
$subMenuActiveText:#338de3; //https://github.com/ElemeFE/element/issues/12951
$menuBg:#ffffff;
$menuHover:#e0f2ff;
$menuActiveBg:#dcf3ff;
$subMenuBg:#ffffff;
$subMenuHover:#edf6ff;
$submenuActiveBg:#dcf3ff;
$sideBarWidth: 210px;
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
menuText: $menuText;
menuActiveText: $menuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
}

@ -1,17 +1,14 @@
// sidebar $menuText:#606266;
:root { $menuActiveText:#303133;
--theme-color: #5898f2; $subMenuActiveText:#338de3;
}
$menuText: hsla(0,0%,100%,.7);
$subMenuText: #333;
$menuActiveText: #fff;
$subMenuActiveText:#f4f4f5;
$menuBg: transparent; $menuBg:#ffffff;
$menuHover: transparent; $menuHover:#e0f2ff;
$menuActiveBg:#dcf3ff;
$subMenuBg: #fff; $subMenuBg:#ffffff;
$subMenuHover: #001528; $subMenuHover:#edf6ff;
$submenuActiveBg:#dcf3ff;
$sideBarWidth: 210px; $sideBarWidth: 210px;
$navBarHeight: 200px; $navBarHeight: 200px;

@ -5,9 +5,16 @@
<!-- linesColor="#ffffff" :linesWidth="1" :lineLinked="true" :lineOpacity="0.4" :linesDistance="150" :moveSpeed="3"--> <!-- linesColor="#ffffff" :linesWidth="1" :lineLinked="true" :lineOpacity="0.4" :linesDistance="150" :moveSpeed="3"-->
<!-- :hoverEffect="true" hoverMode="grab" :clickEffect="true" clickMode="push"> </vue-particles>--> <!-- :hoverEffect="true" hoverMode="grab" :clickEffect="true" clickMode="push"> </vue-particles>-->
<!-- <img class="title-img" src="~@/assets/login/title.png" alt="">--> <!-- <img class="title-img" src="~@/assets/login/title.png" alt="">-->
<el-form size="small" ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" <el-form
label-position="left"> ref="loginForm"
size="small"
:model="loginForm"
:rules="loginRules"
class="login-form"
auto-complete="on"
label-position="left"
>
<div class="title-container"> <div class="title-container">
<h3 class="title">欢迎登录</h3> <h3 class="title">欢迎登录</h3>
@ -16,44 +23,63 @@
<el-form-item prop="username"> <el-form-item prop="username">
<div class="form-item"> <div class="form-item">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon-class="user" /> <svg-icon icon-class="user" />
</span> </span>
<el-input ref="username" v-model="loginForm.username" placeholder="请输入登录名" name="username" type="text" <input v-model="loginForm.pretend_user" style="display: none;" />
tabindex="1" auto-complete="on" /> <el-input
ref="username"
v-model="loginForm.username"
placeholder="请输入登录名"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</div> </div>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<div class="form-item"> <div class="form-item">
<span class="svg-container"> <span class="svg-container">
<svg-icon icon-class="password" /> <svg-icon icon-class="password" />
</span> </span>
<el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" <el-input
placeholder="请输入密码" name="password" tabindex="2" auto-complete="on" @keyup.enter.native="handleLogin" /> :key="passwordType"
ref="password"
v-model="loginForm.password"
:type="passwordType"
placeholder="请输入密码"
name="password"
tabindex="2"
auto-complete="on"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd"> <span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span> </span>
</div> </div>
</el-form-item> </el-form-item>
<!-- <el-form-item prop="code">--> <!-- <el-form-item prop="code">-->
<!-- <div class="form-item">--> <!-- <div class="form-item">-->
<!-- <span class="svg-container">--> <!-- <span class="svg-container">-->
<!-- <svg-icon icon-class="message" />--> <!-- <svg-icon icon-class="message" />-->
<!-- </span>--> <!-- </span>-->
<!-- <el-input ref="username" v-model="loginForm.code" placeholder="请输入验证码" name="username" type="text"--> <!-- <el-input ref="username" v-model="loginForm.code" placeholder="请输入验证码" name="username" type="text"-->
<!-- tabindex="1" auto-complete="on" />--> <!-- tabindex="1" auto-complete="on" />-->
<!-- <el-button class="msg-btn" :loading="msgLoading" type="primary" size="small" :disabled="isVer" @click="sendSms">{{ isVer ? (''+verTime+'') : '' }}</el-button>--> <!-- <el-button class="msg-btn" :loading="msgLoading" type="primary" size="small" :disabled="isVer" @click="sendSms">{{ isVer ? (''+verTime+'') : '' }}</el-button>-->
<!-- </div>--> <!-- </div>-->
<!-- </el-form-item>--> <!-- </el-form-item>-->
<el-button :loading="loading" type="primary" class="login-btn" <el-button
@click.native.prevent="handleLogin">登录</el-button> :loading="loading"
type="primary"
class="login-btn"
@click.native.prevent="handleLogin"
>登录</el-button>
</el-form> </el-form>
<footer class="copyright"> <footer class="copyright">
版权所有{{ copyright }} 版权所有{{ copyright }}
</footer> </footer>
@ -61,10 +87,6 @@
</template> </template>
<script> <script>
import {
validUsername
} from '@/utils/validate'
import { login, getInfo } from "@/api/me";
const defaultSettings = require('../../../src/settings.js') const defaultSettings = require('../../../src/settings.js')
export default { export default {
name: 'Login', name: 'Login',
@ -77,23 +99,24 @@ export default {
} }
} }
return { return {
title: "", title: '',
loginForm: { loginForm: {
username: '', username: '',
password: '', password: '',
//code: '' pretend_user: ''
// code: ''
}, },
loginRules: { loginRules: {
username: [{ username: [{
required: true, required: true,
trigger: 'blur', trigger: 'blur',
message: "请输入用户名" message: '请输入用户名'
}], }],
password: [{ password: [{
required: true, required: true,
trigger: 'blur', trigger: 'blur',
validator: validatePassword validator: validatePassword
}], }]
// code: [ // code: [
// { // {
// required: true, // required: true,
@ -117,8 +140,8 @@ export default {
verTime: 60, verTime: 60,
isVer: false, isVer: false,
temp: { temp: {
mobile: "", mobile: '',
token: "" token: ''
} }
} }
}, },
@ -131,35 +154,35 @@ export default {
} }
}, },
created() { created() {
this.title = defaultSettings.title; this.title = defaultSettings.title
this.copyright = defaultSettings.copyright; this.copyright = defaultSettings.copyright
}, },
methods: { methods: {
async sendSms () { async sendSms() {
if (this.isVer) return; if (this.isVer) return
if (this.loginForm.username) { if (this.loginForm.username) {
this.msgLoading = true; this.msgLoading = true
try { try {
await sendSms({ await sendSms({
username: this.loginForm.username username: this.loginForm.username
}) })
this.isVer = true; this.isVer = true
this.verTime = 60; this.verTime = 60
this.$message({ this.$message({
message: '验证码已发送', message: '验证码已发送',
type:'success' type: 'success'
}) })
let timer = setInterval(() => { const timer = setInterval(() => {
this.verTime--; this.verTime--
if (this.verTime <= 0) { if (this.verTime <= 0) {
this.isVer = false; this.isVer = false
clearInterval(timer); clearInterval(timer)
} }
}, 1000); }, 1000)
this.msgLoading = false; this.msgLoading = false
} catch (e) { } catch (e) {
this.msgLoading = false; this.msgLoading = false
} }
} else { } else {
this.$message({ this.$message({
@ -179,14 +202,12 @@ export default {
this.$refs.password.focus() this.$refs.password.focus()
}) })
}, },
// //
async handleLogin() { async handleLogin() {
this.$refs.loginForm.validate(async(valid) => { this.$refs.loginForm.validate(async(valid) => {
if (valid) { if (valid) {
this.loading = true this.loading = true
this.$store.dispatch('user/login', this.loginForm).then(() => { this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({ this.$router.push({
path: this.redirect || '/' path: this.redirect || '/'
}) })

@ -1,6 +1,7 @@
<template> <template>
<el-card id="todo-card" class="box-card" shadow="hover"> <el-card id="todo-card" class="box-card" shadow="hover">
<div slot="header" class="clearfix"> <div slot="header" class="clearfix">
<el-button @click="test">aa</el-button>
<SvgIcon style="color: var(--theme-color);width: 22px;height: 22px;" icon-class="notice" /> <SvgIcon style="color: var(--theme-color);width: 22px;height: 22px;" icon-class="notice" />
<span <span
style="padding-left: 15px" style="padding-left: 15px"
@ -25,7 +26,7 @@
:show-header="false" :show-header="false"
:height="tableHeight" :height="tableHeight"
:loading="loading" :loading="loading"
:data="/^\/system/.test(this.$route.path) ? example : list" :data="list"
> >
<el-table-column type="index" width="46" align="center" /> <el-table-column type="index" width="46" align="center" />
<el-table-column <el-table-column
@ -41,7 +42,7 @@
/> />
<el-table-column label="操作" header-align="center" min-width="122" fixed="right"> <el-table-column label="操作" header-align="center" min-width="122" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-button size="mini" style="padding: 5px 10px;" @click="show(row)"></el-button> <el-button size="mini" style="padding: 5px 10px;" @click="read(row)"></el-button>
<el-button size="mini" type="primary" style="padding: 5px 10px;" @click="handle(row)"></el-button> <el-button size="mini" type="primary" style="padding: 5px 10px;" @click="handle(row)"></el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -51,6 +52,7 @@
<vxe-modal <vxe-modal
v-model="isShowModal" v-model="isShowModal"
:z-index="zIndex"
transfer transfer
show-zoom show-zoom
:fullscreen="$store.getters.device === 'mobile'" :fullscreen="$store.getters.device === 'mobile'"
@ -65,6 +67,7 @@
</template> </template>
<script> <script>
import { PopupManager } from 'element-ui/lib/utils/popup'
import SvgIcon from '@/components/SvgIcon/index.vue' import SvgIcon from '@/components/SvgIcon/index.vue'
import ElementResize from 'element-resize-detector' import ElementResize from 'element-resize-detector'
import axios from 'axios' import axios from 'axios'
@ -85,22 +88,9 @@ export default {
}, },
data() { data() {
return { return {
zIndex: PopupManager.nextZIndex(),
isShowModal: false, isShowModal: false,
modalUrl: '/', modalUrl: '/',
example: [
{
type: 1,
content: '示例1',
created_at: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
read_count: true
},
{
type: 2,
content: '示例2',
created_at: this.$moment().format('YYYY-MM-DD HH:mm:ss'),
read_count: false
}
],
select: { select: {
page: 1, page: 1,
page_size: 10 page_size: 10
@ -121,15 +111,31 @@ export default {
}, },
{ {
title: '内容', title: '内容',
key: 'content', key: 'data',
align: 'left', align: 'left',
'show-overflow-tooltip': true, 'show-overflow-tooltip': true,
minWidth: 200 minWidth: 200,
formatter: (row, column, cellValue) => {
try {
const data = JSON.parse(cellValue)
return data.title
} catch (err) {
console.error(err)
return ''
}
}
} }
] ]
} }
}, },
computed: {}, computed: {},
watch: {
isShowModal(newVal) {
if (newVal) {
this.zIndex = PopupManager.nextZIndex()
}
}
},
created() { created() {
this.getNotices() this.getNotices()
}, },
@ -137,21 +143,20 @@ export default {
this.init() this.init()
}, },
methods: { methods: {
test() {
console.log(this.list.abc.ddd)
},
async getNotices() { async getNotices() {
if (/^\/system/.test(this.$route.path)) return
try { try {
this.loading = true this.loading = true
const res = await axios.get(`${process.env.VUE_APP_BASE_API}/api/ht/notice/index`, { const res = await axios.get(`${process.env.VUE_APP_BASE_API}/api/notification/todo`, {
headers: { headers: {
'Authorization': `Bearer ${getToken()}` 'Authorization': `Bearer ${getToken()}`
}, },
params: this.select params: this.select
}) })
if (res.status === 200) { if (res.status === 200) {
this.list = res.data.data?.data?.map(i => ({ this.list = res.data.data?.data
...i,
module: 'ht'
}))
} }
this.loading = false this.loading = false
} catch (err) { } catch (err) {
@ -174,17 +179,40 @@ export default {
}) })
}, },
show(row) { async read(row) {
if (row.module === 'ht') { try {
this.modalUrl = `/${row.module}?auth_token=${window.encodeURIComponent(getToken())}&module_name=${row.module}&to=${window.encodeURIComponent('/contract/contractList?keyword=' + (/\[(.*?)]/.exec(row.title) ? /\[(.*?)]/.exec(row.title)[1] : ''))}` this.loading = true
const res = await axios.get(`${process.env.VUE_APP_BASE_API}/api/notification/read`, {
headers: {
'Authorization': `Bearer ${getToken()}`
},
params: {
id: row.id
}
})
if (res.status === 200) {
await this.getNotices()
}
this.loading = false
} catch (err) {
console.error(err)
this.loading = false
} }
this.isShowModal = true
}, },
handle(row) { handle(row) {
if (row.module === 'ht') { try {
this.modalUrl = `/${row.module}?auth_token=${window.encodeURIComponent(getToken())}&module_name=${row.module}&to=${window.encodeURIComponent('/contract/contractList?keyword=' + (/\[(.*?)]/.exec(row.title) ? /\[(.*?)]/.exec(row.title)[1] : ''))}` const data = JSON.parse(row.data)
if (data.from === 'ht') {
this.modalUrl = `/${data.from}?auth_token=${window.encodeURIComponent(getToken())}&module_name=${data.from}&to=${window.encodeURIComponent('/contract/contractList?keyword=' + (/\[(.*?)]/.exec(data.title) ? /\[(.*?)]/.exec(data.title)[1] : ''))}`
} else if (data.from === 'oa') {
this.modalUrl = `/${data.from}?auth_token=${window.encodeURIComponent(getToken())}&module_name=${data.from}&to=${window.encodeURIComponent(`/flow/create?flow_id=${data.other?.flow_id}`)}`
}
console.log(this.modalUrl)
this.isShowModal = true
} catch (err) {
this.$message.warning('未找到流程')
console.error(err)
} }
this.isShowModal = true
} }
} }
} }

@ -26,7 +26,7 @@
<el-form-item label="分管领导" prop="manager_id"> <el-form-item label="分管领导" prop="manager_id">
<user-picker width="100%" v-model="form.manager_id"></user-picker> <user-picker width="100%" v-model="form.manager_id"></user-picker>
</el-form-item> </el-form-item>
<el-form-item label="主要领导" prop="leader_id"> <el-form-item label="主要负责人" prop="leader_id">
<user-picker width="100%" v-model="form.leader_id"></user-picker> <user-picker width="100%" v-model="form.leader_id"></user-picker>
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sortnumber"> <el-form-item label="排序" prop="sortnumber">

@ -26,6 +26,14 @@
<el-form-item label="手机号" prop="mobile"> <el-form-item label="手机号" prop="mobile">
<el-input v-model="form.mobile" clearable /> <el-input v-model="form.mobile" clearable />
</el-form-item> </el-form-item>
<el-form-item label="部门" prop="department_id">
<el-select v-model="form.department_id" clearable>
<el-option v-for="item in departments" :key="item.id" :value="item.id" :label="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item label="职位" prop="position">
<el-input v-model="form.position" clearable />
</el-form-item>
<el-form-item label="排序" prop="sortnumber"> <el-form-item label="排序" prop="sortnumber">
<el-input-number v-model="form.sortnumber" controls-position="right" :precision="0" /> <el-input-number v-model="form.sortnumber" controls-position="right" :precision="0" />
</el-form-item> </el-form-item>
@ -46,6 +54,10 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
required: true required: true
},
departments: {
type: Array,
default: () => []
} }
}, },
data() { data() {
@ -57,6 +69,8 @@ export default {
password: '', password: '',
attendance_closed: 0, attendance_closed: 0,
mobile: '', mobile: '',
department_id: '',
position: '',
sortnumber: 0 sortnumber: 0
}, },
rules: { rules: {

@ -27,7 +27,7 @@
<vxe-table <vxe-table
ref="menuTable" ref="menuTable"
style="margin-top: 10px;" style="margin-top: 10px;"
max-height="600" :max-height="400"
keep-source keep-source
:row-config="{ useKey: 'id', isHover: true }" :row-config="{ useKey: 'id', isHover: true }"
:column-config="{ resizable: true }" :column-config="{ resizable: true }"
@ -136,12 +136,19 @@
<p class="total" type="primary"> {{ roleTotal }} 条数据</p> <p class="total" type="primary"> {{ roleTotal }} 条数据</p>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="用户授权" name="permission"> <el-tab-pane label="用户授权" name="permission">
<vxe-toolbar>
<template #buttons>
<el-input v-model="userSelect.keyword" size="small" style="margin-right: 10px;max-width: 200px;" placehodler="请输入关键词"></el-input>
<el-button icon="el-icon-search" type="primary" plain size="small" @click="userSelect.page = 1,getUsers()">搜索</el-button>
</template>
</vxe-toolbar>
<vxe-table <vxe-table
ref="table" ref="table"
stripe stripe
style="margin-top: 10px;" style="margin-top: 10px;"
:loading="loading" :loading="loading"
keep-source keep-source
:max-height="400"
show-overflow show-overflow
:column-config="{ resizable: true }" :column-config="{ resizable: true }"
:edit-config="{ trigger: 'manual', mode: 'row', showStatus: true, isHover: true, autoClear: false }" :edit-config="{ trigger: 'manual', mode: 'row', showStatus: true, isHover: true, autoClear: false }"
@ -165,6 +172,23 @@
</vxe-column> </vxe-column>
</vxe-table> </vxe-table>
<el-pagination
style="margin-top: 10px;"
:current-page="userSelect.page"
:page-sizes="[20, 30, 40, 50]"
:page-size="userSelect.rows"
layout="total, sizes, prev, pager, next, jumper"
:total="userTotal"
@size-change="e => {
userSelect.rows = e;
userSelect.page = 1;
getUsers();
}"
@current-change="e => {
userSelect.page = e;
getUsers();
}"
/>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@ -251,6 +275,12 @@ export default {
}, },
isShowBindPermissions: false, isShowBindPermissions: false,
total: 0,
userSelect: {
page: 1,
rows: 10,
keyword: ''
},
users: [], users: [],
userTotal: 0, userTotal: 0,
isShowBindRoles: false isShowBindRoles: false
@ -447,7 +477,8 @@ export default {
this.loading = true this.loading = true
try { try {
const res = await grant({ const res = await grant({
module_id: this.moduleId module_id: this.moduleId,
...this.userSelect
}) })
console.log(res) console.log(res)
this.users = res.rows this.users = res.rows

@ -1,20 +1,22 @@
<template> <template>
<div> <div>
<vxe-modal :value="isShow" <vxe-modal
show-footer :value="isShow"
title="角色" show-footer
:z-index="zIndex" title="角色"
show-confirm-button :z-index="zIndex"
:width="600" show-confirm-button
:height="400" :width="600"
esc-closable :height="400"
@input="e => $emit('update:isShow',e)"> esc-closable
@input="e => $emit('update:isShow',e)"
>
<el-form ref="elForm" :model="form" :rules="rules" label-position="top" label-width="100"> <el-form ref="elForm" :model="form" :rules="rules" label-position="top" label-width="100">
<el-form-item label="角色" prop="name" required> <el-form-item label="角色" prop="name" required>
<el-input v-model="form.name" clearable></el-input> <el-input v-model="form.name" clearable />
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sortnumber"> <el-form-item label="排序" prop="sortnumber">
<el-input-number controls-position="right" :precision="0" v-model="form.sortnumber"></el-input-number> <el-input-number v-model="form.sortnumber" controls-position="right" :precision="0" />
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -27,10 +29,10 @@
<script> <script>
import { PopupManager } from 'element-ui/lib/utils/popup' import { PopupManager } from 'element-ui/lib/utils/popup'
import { roleSave } from "@/api/module" import { roleSave } from '@/api/module'
export default { export default {
props: { props: {
moduleId: [String,Number], moduleId: [String, Number],
isShow: { isShow: {
type: Boolean, type: Boolean,
default: false, default: false,
@ -42,43 +44,43 @@ export default {
zIndex: PopupManager.nextZIndex(), zIndex: PopupManager.nextZIndex(),
loading: false, loading: false,
form: { form: {
name: "", name: '',
sortnumber: 0 sortnumber: 0
}, },
rules: { rules: {
name: [ name: [
{ required: true, message: "请输入角色" } { required: true, message: '请输入角色' }
] ]
} }
} }
}, },
computed: {},
watch: {
isShow(newVal) {
if (newVal) {
this.zIndex = PopupManager.nextZIndex()
}
}
},
methods: { methods: {
submit () { submit() {
this.$refs["elForm"].validate(async valid => { this.$refs['elForm'].validate(async valid => {
if (valid) { if (valid) {
this.loading = true this.loading = true
try { try {
this.form.module_id = this.moduleId; this.form.module_id = this.moduleId
await roleSave(this.form) await roleSave(this.form)
this.$message.success("新增成功") this.$message.success('新增成功')
this.$emit('refresh') this.$emit('refresh')
this.$emit('update:isShow',false) this.$emit('update:isShow', false)
this.loading = false this.loading = false
this.$refs["elForm"].resetFields() this.$refs['elForm'].resetFields()
} catch (err) { } catch (err) {
this.loading = false this.loading = false
} }
} }
}) })
} }
},
computed: {},
watch: {
isShow(newVal) {
if (newVal) {
this.zIndex = PopupManager.nextZIndex()
}
}
} }
} }
</script> </script>

@ -8,9 +8,9 @@
</template> </template>
</vxe-toolbar> </vxe-toolbar>
<vxe-table <vxe-table
ref="table"
stripe stripe
style="margin-top: 10px;" style="margin-top: 10px;"
ref="table"
:loading="loading" :loading="loading"
keep-source keep-source
show-overflow show-overflow
@ -18,20 +18,21 @@
:edit-rules="validRules" :edit-rules="validRules"
:edit-config="{ trigger: 'manual', mode: 'row', showStatus: true, isHover: true, autoClear: false }" :edit-config="{ trigger: 'manual', mode: 'row', showStatus: true, isHover: true, autoClear: false }"
:align="allAlign" :align="allAlign"
:data="tableData"> :data="tableData"
<vxe-column type="seq" width="58" align="center"></vxe-column> >
<vxe-column field="name" width="160" title="部门名称" :edit-render="{ name: 'input', attrs: { type: 'text'} }"></vxe-column> <vxe-column type="seq" width="58" align="center" />
<vxe-column field="name" width="160" title="部门名称" :edit-render="{ name: 'input', attrs: { type: 'text'} }" />
<vxe-column field="manager.name" width="180" title="分管领导" :edit-render="{}"> <vxe-column field="manager.name" width="180" title="分管领导" :edit-render="{}">
<template #edit="{ row }"> <template #edit="{ row }">
<UserPicker size="small" v-model="row.manager_id"></UserPicker> <UserPicker v-model="row.manager_id" size="small" />
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="leader.name" width="180" title="主要领导" :edit-render="{}"> <vxe-column field="leader.name" width="180" title="主要负责人" :edit-render="{}">
<template #edit="{ row }"> <template #edit="{ row }">
<UserPicker size="small" v-model="row.leader_id"></UserPicker> <UserPicker v-model="row.leader_id" size="small" />
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="sortnumber" width="80" title="排序" align="center" :edit-render="{ name: 'input', attrs: { type: 'number' } }"></vxe-column> <vxe-column field="sortnumber" width="80" title="排序" align="center" :edit-render="{ name: 'input', attrs: { type: 'number' } }" />
<vxe-column field="operate" title="操作" min-width="220"> <vxe-column field="operate" title="操作" min-width="220">
<template #default="{ row }"> <template #default="{ row }">
<template v-if="isActiveStatus(row)"> <template v-if="isActiveStatus(row)">
@ -49,15 +50,15 @@
<p class="total" type="primary"> {{ total }} 条数据</p> <p class="total" type="primary"> {{ total }} 条数据</p>
</card-container> </card-container>
<AddDepartment ref="AddDepartment" :list="tableData" :is-show.sync="isShowAdd" @refresh="getList"></AddDepartment> <AddDepartment ref="AddDepartment" :list="tableData" :is-show.sync="isShowAdd" @refresh="getList" />
</div> </div>
</template> </template>
<script> <script>
import UserPicker from '@/components/UserPicker/index.vue' import UserPicker from '@/components/UserPicker/index.vue'
import AddDepartment from './components/AddDepartment.vue' import AddDepartment from './components/AddDepartment.vue'
import { deepCopy } from "@/utils" import { deepCopy } from '@/utils'
import { index, save, destroy } from "@/api/department" import { index, save, destroy } from '@/api/department'
export default { export default {
components: { components: {
AddDepartment, AddDepartment,
@ -85,14 +86,26 @@ export default {
} }
} }
}, },
computed: {
isActiveStatus() {
return function(row) {
if (this.$refs['table']) {
return this.$refs['table'].isEditByRow(row)
}
}
}
},
created() {
this.getList()
},
methods: { methods: {
editRowEvent (row) { editRowEvent(row) {
if (this.$refs['table']) { if (this.$refs['table']) {
this.$refs['table'].setEditRow(row) this.$refs['table'].setEditRow(row)
} }
}, },
cancelRowEvent (row) { cancelRowEvent(row) {
if (this.$refs['table']) { if (this.$refs['table']) {
this.$refs['table'].clearEdit().then(() => { this.$refs['table'].clearEdit().then(() => {
// //
@ -101,74 +114,62 @@ export default {
} }
}, },
async getList () { async getList() {
this.loading = true; this.loading = true
try { try {
const res = await index() const res = await index()
this.tableData = res; this.tableData = res
this.total = res.length; this.total = res.length
this.loading = false; this.loading = false
} catch (err) { } catch (err) {
console.error(err) console.error(err)
this.loading = false; this.loading = false
} }
}, },
async saveRowEvent (row) { async saveRowEvent(row) {
try { try {
await this.$confirm("确认保存?","提示",{ await this.$confirm('确认保存?', '提示', {
confirmButtonText: "确认", confirmButtonText: '确认',
cancelButtonText: "取消" cancelButtonText: '取消'
}) })
await this.$refs['table'].clearEdit() await this.$refs['table'].clearEdit()
let form = deepCopy(this.form) const form = deepCopy(this.form)
for (let key in form) { for (const key in form) {
form[key] = row[key] form[key] = row[key]
} }
if (!form.password) { if (!form.password) {
delete form.password delete form.password
} }
this.loading = true; this.loading = true
await save(form) await save(form)
await this.getList(); await this.getList()
this.loading = false; this.loading = false
} catch (err) { } catch (err) {
this.loading = false; this.loading = false
} }
}, },
async destroyRowEvent (row) { async destroyRowEvent(row) {
try { try {
await this.$confirm("确认删除?","提示",{ await this.$confirm('确认删除?', '提示', {
confirmButtonText: "确认", confirmButtonText: '确认',
cancelButtonText: "取消" cancelButtonText: '取消'
}) })
this.loading = true; this.loading = true
if (row.id) { if (row.id) {
await destroy({ await destroy({
id: row.id id: row.id
}) })
await this.getList(); await this.getList()
} else { } else {
console.log(row) console.log(row)
this.tableData.splice(this.tableData.findIndex(i => i._X_ROW_KEY === row._X_ROW_KEY),1) this.tableData.splice(this.tableData.findIndex(i => i._X_ROW_KEY === row._X_ROW_KEY), 1)
} }
this.loading = false; this.loading = false
} catch (err) { } catch (err) {
this.loading = false; this.loading = false
}
},
},
computed: {
isActiveStatus () {
return function (row) {
if (this.$refs['table']) {
return this.$refs['table'].isEditByRow(row)
}
} }
} }
},
created() {
this.getList()
} }
} }
</script> </script>

@ -3,8 +3,9 @@
<card-container> <card-container>
<vxe-toolbar> <vxe-toolbar>
<template #buttons> <template #buttons>
<el-input v-model="select.keyword" style="max-width: 200px;margin-right: 10px;" size="small" placeholder="请输入关键词" />
<el-button icon="el-icon-plus" type="primary" size="small" @click="isShowAdd = true">新增</el-button> <el-button icon="el-icon-plus" type="primary" size="small" @click="isShowAdd = true">新增</el-button>
<el-button icon="el-icon-search" type="primary" plain size="small" @click="getList"></el-button> <el-button icon="el-icon-search" type="primary" plain size="small" @click="select.page = 1,getList()">搜索</el-button>
</template> </template>
</vxe-toolbar> </vxe-toolbar>
<vxe-table <vxe-table
@ -28,6 +29,14 @@
<span>***</span> <span>***</span>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column field="department.name" width="160" align="center" title="部门" :edit-render="{}">
<template #edit="{ row }">
<el-select v-model="row.department_id" size="small">
<el-option v-for="item in departments" :value="item.id" :label="item.name"></el-option>
</el-select>
</template>
</vxe-column>
<vxe-column field="position" width="140" title="职位" align="center" :edit-render="{ name: 'input', attrs: { type: 'text'} }" />
<vxe-column field="attendance_closed" width="130" align="center" title="是否关闭打卡" :edit-render="{ name: 'select', options: [{ value: 1, label: '' },{ value: 0, label: '' }] }" /> <vxe-column field="attendance_closed" width="130" align="center" title="是否关闭打卡" :edit-render="{ name: 'select', options: [{ value: 1, label: '' },{ value: 0, label: '' }] }" />
<vxe-column field="mobile" width="140" align="center" title="手机号" :edit-render="{ name: 'input', attrs: { type: 'text' } }" /> <vxe-column field="mobile" width="140" align="center" title="手机号" :edit-render="{ name: 'input', attrs: { type: 'text' } }" />
<vxe-column field="roles" title="角色" min-width="200" show-overflow="tooltip"> <vxe-column field="roles" title="角色" min-width="200" show-overflow="tooltip">
@ -72,7 +81,7 @@
/> />
</card-container> </card-container>
<AddUser :is-show.sync="isShowAdd" @refresh="getList" /> <AddUser :is-show.sync="isShowAdd" :departments="departments" @refresh="getList" />
<BindRoles ref="BindRoles" :is-show.sync="isShowBind" @refresh="getList" /> <BindRoles ref="BindRoles" :is-show.sync="isShowBind" @refresh="getList" />
</div> </div>
</template> </template>
@ -82,6 +91,7 @@ import BindRoles from './components/BindRoles.vue'
import AddUser from './components/AddUser.vue' import AddUser from './components/AddUser.vue'
import { deepCopy } from '@/utils' import { deepCopy } from '@/utils'
import { index, save, destroy } from '@/api/user' import { index, save, destroy } from '@/api/user'
import { index as departmentIndex } from '@/api/department'
export default { export default {
components: { components: {
AddUser, AddUser,
@ -126,7 +136,7 @@ export default {
{ {
validator: ({ cellValue }) => { validator: ({ cellValue }) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (/^1[3456789]\d{9}$/.test(cellValue)) { if (!cellValue || /^1[3456789]\d{9}$/.test(cellValue)) {
resolve() resolve()
} else { } else {
reject(new Error('手机号格式错误!')) reject(new Error('手机号格式错误!'))
@ -141,8 +151,11 @@ export default {
name: '', name: '',
username: '', username: '',
password: '', password: '',
department_id: '',
position: '',
sortnumber: 0 sortnumber: 0
} },
departments: []
} }
}, },
computed: { computed: {
@ -155,6 +168,7 @@ export default {
} }
}, },
created() { created() {
this.getDepartments()
this.getList() this.getList()
}, },
methods: { methods: {
@ -233,6 +247,15 @@ export default {
} catch (err) { } catch (err) {
this.loading = false this.loading = false
} }
},
async getDepartments() {
try {
this.departments = await departmentIndex({
is_tree: 0
})
} catch (err) {
console.error(err)
}
} }
} }
} }

Loading…
Cancel
Save