变量名称修改

用户增加部门字段
移除无用代码
修复OrgTree的一些问题
使用原本的el-select
master
toesbieya 6 years ago
parent 90097bfe0e
commit 0e8f4dc504
  1. 4
      vue/element-ui-personal/index.js
  2. 2
      vue/mock/controller/account/index.js
  3. 4
      vue/src/api/account.js
  4. 8
      vue/src/api/system/department.js
  5. 20
      vue/src/assets/styles/index.scss
  6. 127
      vue/src/components/OrgTree/OrgTreeNode.vue
  7. 132
      vue/src/components/OrgTree/index.vue
  8. 2
      vue/src/components/OrgTree/tree.scss
  9. 11
      vue/src/components/TreeSelect/index.vue
  10. 2
      vue/src/config/request.js
  11. 4
      vue/src/layout/components/Navbar/index.vue
  12. 2
      vue/src/mixins/bizDocumentTableMixin.js
  13. 4
      vue/src/store/modules/resource.js
  14. 2
      vue/src/store/modules/socket.js
  15. 15
      vue/src/store/modules/user.js
  16. 2
      vue/src/utils/auth.js
  17. 66
      vue/src/utils/index.js
  18. 14
      vue/src/views/app/login/LoginForm.vue
  19. 6
      vue/src/views/example/components/treeSelectExample.vue
  20. 4
      vue/src/views/purchase/inbound/components/OrderSelector.vue
  21. 6
      vue/src/views/purchase/inbound/detail.vue
  22. 6
      vue/src/views/purchase/inbound/index.vue
  23. 6
      vue/src/views/purchase/order/detail.vue
  24. 4
      vue/src/views/purchase/order/index.vue
  25. 2
      vue/src/views/sell/order/components/StockSelector.vue
  26. 26
      vue/src/views/sell/order/detail.vue
  27. 12
      vue/src/views/sell/order/index.vue
  28. 4
      vue/src/views/sell/outbound/components/OrderSelector.vue
  29. 14
      vue/src/views/sell/outbound/detail.vue
  30. 6
      vue/src/views/sell/outbound/index.vue
  31. 16
      vue/src/views/stock/current/index.vue
  32. 10
      vue/src/views/system/department/components/OrgTreeView.vue
  33. 67
      vue/src/views/system/department/index.vue
  34. 16
      vue/src/views/system/resource/EditDialog.vue
  35. 4
      vue/src/views/system/resource/index.vue
  36. 190
      vue/src/views/system/role/EditDialog.vue
  37. 158
      vue/src/views/system/role/components/EditDialog.vue
  38. 59
      vue/src/views/system/role/components/RoleResource.vue
  39. 35
      vue/src/views/system/role/index.vue
  40. 39
      vue/src/views/system/user/components/DepartmentSelector.vue
  41. 27
      vue/src/views/system/user/components/EditDialog.vue
  42. 9
      vue/src/views/system/user/components/RoleSelector.vue
  43. 15
      vue/src/views/system/user/index.vue
  44. 26
      vue/src/views/userCenter/components/Account.vue
  45. 15
      vue/src/views/userCenter/components/UserCard.vue
  46. 9
      vue/src/views/userCenter/index.vue

@ -1,9 +1,9 @@
import MenuItem from "./components/Menu/MenuItem"
import Submenu from "./components/Menu/Submenu"
import Message from "./components/Message"
import Select from './components/Select/Select'
//import Select from './components/Select/Select'
const components = [MenuItem, Submenu, Select]
const components = [MenuItem, Submenu]
export default function (Vue) {
components.forEach(component => {

@ -13,7 +13,7 @@ module.exports = [
else res.send(success({
id: 1,
name: 'admin',
admin: 1,
admin: true,
token: 'test'
}))
}

@ -26,6 +26,6 @@ export function validate(pwd) {
return request.get(`${baseUrl}/validate?pwd=${pwd}`).then(({data}) => data)
}
export function checkName(name) {
return request.get(`${baseUrl}/checkName?name=${name}`).then(({data}) => data)
export function checkName(name, id) {
return request.get(`${baseUrl}/checkName?name=${name}&id=${id}`).then(({data}) => data)
}

@ -2,12 +2,8 @@ import request from "@/config/request"
export const baseUrl = `/system/department`
export function getDepartments() {
return request.get(`${baseUrl}/get`).then(({data}) => data.data)
}
export function getAllDepartments() {
return request.get(`${baseUrl}/getAll`).then(({data}) => data.data)
export function getDepartments(all = true) {
return request.get(`${baseUrl}/get?all=${all}`).then(({data}) => data.data)
}
export function addDepartment(data) {

@ -165,22 +165,6 @@ a:hover {
}
}
//印章
.seal {
float: left;
border: solid .1em $--color-danger;
border-radius: .2em;
color: $--color-danger;
font-size: 23px;
font-weight: bold;
padding: .1em .5em;
bottom: 15px;
& + & {
margin-left: 20px;
}
}
.button-group {
.el-button {
margin-top: 10px;
@ -200,4 +184,8 @@ a:hover {
}
}
.el-form-item__content > .el-tree {
margin-top: 8px;
}

@ -1,10 +1,11 @@
<script type="text/jsx">
//
const isLeaf = (data, prop) => {
return !(Array.isArray(data[prop]) && data[prop].length > 0)
return !Array.isArray(data[prop]) || data[prop].length === 0
}
// node
export const renderNode = (h, data, context) => {
const renderNode = (h, data, context) => {
const {props} = context
const cls = ['org-tree-node']
const childNodes = []
@ -23,44 +24,11 @@ export const renderNode = (h, data, context) => {
childNodes.push(renderChildren(h, children, context))
}
return h('div', {
domProps: {
className: cls.join(' ')
}
}, childNodes)
}
//
export const renderBtn = (h, data, context) => {
const {props} = context
const expandHandler = context.listeners['on-expand']
let cls = ['org-tree-node-btn']
if (data[props.props.expand]) {
cls.push('expanded')
}
return h('span', {
'class': 'org-tree-button-wrapper',
on: {
click: e => {
e.stopPropagation()
expandHandler && expandHandler(data)
},
mousedown: e => e.stopPropagation()
}
}, [
props.buttonRender
? props.buttonRender(h, data)
: h('span', {
'class': cls.join(' ')
})
])
return <div class={cls.join(' ')}>{childNodes}</div>
}
// label
export const renderLabel = (h, data, context) => {
const renderLabel = (h, data, context) => {
const {props} = context
const label = data[props.props.label]
const nodeRender = props.nodeRender
@ -77,8 +45,7 @@ export const renderLabel = (h, data, context) => {
const childNodes = []
if (typeof nodeRender === 'function') {
let vnode = nodeRender(h, data)
vnode && childNodes.push(vnode)
childNodes.push(nodeRender(h, data))
}
else if (context.parent.$scopedSlots.default) {
childNodes.push(context.parent.$scopedSlots.default(data))
@ -99,44 +66,60 @@ export const renderLabel = (h, data, context) => {
}
labelClassName && cls.push(labelClassName)
return h('div', {
domProps: {
className: 'org-tree-node-label'
},
on: {
click: e => clickHandler && clickHandler(e, data),
mousedown: mousedownHandler,
mouseup: e => mouseupHandler && mouseupHandler(e, data),
touchstart: e => touchstartHandler && touchstartHandler(e, data),
touchleave: e => touchleaveHandler && touchleaveHandler(e, data)
}
}, [h('div', {
domProps: {
className: cls.join(' ')
},
style: {width: labelWidth}
}, childNodes)])
return (
<div
class="org-tree-node-label"
on-click={e => clickHandler && clickHandler(e, data)}
on-mousedown={mousedownHandler}
on-mouseup={e => mouseupHandler && mouseupHandler(e, data)}
on-touchstart={e => touchstartHandler && touchstartHandler(e, data)}
on-touchleave={e => touchleaveHandler && touchleaveHandler(e, data)}
>
<div class={cls.join(' ')} style={{width: labelWidth}}>
{childNodes}
</div>
</div>
)
}
// node
export const renderChildren = (h, list, context) => {
if (Array.isArray(list) && list.length) {
const children = list.map(item => {
return renderNode(h, item, context)
})
//
const renderBtn = (h, data, context) => {
const {props} = context
const expandHandler = context.listeners['on-expand']
const onClock = e => {
e.stopPropagation()
expandHandler && expandHandler(data)
}
const onMousedown = e => e.stopPropagation()
const cls = ['org-tree-node-btn']
return h('div', {
domProps: {
className: 'org-tree-node-children'
data[props.props.expand] && cls.push('expanded')
return (
<span class="org-tree-button-wrapper" on-click={onClock} on-mousedown={onMousedown}>
{props.buttonRender ? props.buttonRender(h, data) : <span class={cls.join(' ')}/>}
</span>
)
}
}, children)
// node
const renderChildren = (h, list, context) => {
if (Array.isArray(list) && list.length) {
return (
<div class="org-tree-node-children">
{list.map(item => renderNode(h, item, context))}
</div>
)
}
return ''
}
export const render = (h, context) => {
const {props} = context
return renderNode(h, props.data, context)
}
export default {
name: "OrgTreeNode",
export default render
functional: true,
render(h, context) {
return renderNode(h, context.props.data, context)
}
}
</script>

@ -1,16 +1,15 @@
<template>
<div class="org-tree-container">
<div :class="{horizontal, collapsable}" class="org-tree">
<div class="org-tree" :class="{horizontal, collapsable}">
<org-tree-node
v-bind="$listeners"
:button-render="buttonRender"
:collapsable="collapsable"
:data="dataCloned"
:props="props"
:horizontal="horizontal"
:label-class-name="labelClassName"
:label-width="labelWidth"
:collapsable="collapsable"
:label-class-name="labelClassName"
:node-render="nodeRender"
:props="props"
:button-render="buttonRender"
@on-expand="handleExpand"
@on-node-click="handleNodeClick"
/>
@ -19,24 +18,15 @@
</template>
<script>
import render from './node'
import {deepClone as clonedeep} from '@/utils'
import OrgTreeNode from "./OrgTreeNode"
export default {
name: 'OrgTree',
components: {
OrgTreeNode: {
render,
functional: true
}
},
components: {OrgTreeNode},
props: {
data: {
type: Object,
required: true
},
data: {required: true},
props: {
type: Object,
default: () => ({
@ -52,10 +42,7 @@
buttonRender: Function,
labelWidth: [String, Number],
labelClassName: [Function, String],
expandAll: {
type: Boolean,
default: false
}
expandAll: Boolean
},
data() {
@ -67,10 +54,10 @@
watch: {
data(newData) {
this._handleData(newData)
this._cloneData(newData)
this._mapData(this.dataCloned, item => {
const {expand} = this.flatData[item[this.prop_id]] || {}
if (expand) this.$set(item, this.prop_expand, true)
const {expand} = this.flatData[item[this.props.id]] || {}
if (expand) this.$set(item, this.props.expand, true)
})
this._toggleExpand(this.dataCloned, this.expandAll)
},
@ -79,42 +66,20 @@
}
},
computed: {
prop_id() {
return this.props.id
},
prop_label() {
return this.props.label
},
prop_expand() {
return this.props.expand
},
prop_children() {
return this.props.children
}
},
methods: {
_handleData(data) {
this._cloneData(data)
},
_cloneData(newData) {
this.dataCloned = clonedeep(newData)
this.dataCloned = JSON.parse(JSON.stringify(newData))
},
_setFlatData(data) {
this.flatData[data[this.prop_id]] = data
this.flatData[data[this.props.id]] = data
},
/**
* @description 工具方法用于遍历树状数据的每个节点 fn为在该节点做的操作其有一个参数即当前节点数据
*/
_mapData(data, fn) {
fn(data)
const children = data[this.prop_children]
if (children) {
children.forEach(child => {
this._mapData(child, fn)
})
}
const children = data[this.props.children]
children && children.forEach(child => this._mapData(child, fn))
},
/**
* @description 用来便利所有节点数据将树状数据扁平化存放到flatData用于数据更新后展开状态的恢复
@ -122,62 +87,53 @@
_updateExpandStatus() {
this._mapData(this.dataCloned, this._setFlatData)
},
collapse(list) {
var _this = this
list.forEach(child => {
if (child[this.prop_expand]) {
child[this.prop_expand] = false
}
const children = child[this.prop_children]
children && _this.collapse(children)
})
},
handleExpand(data) {
if (this.prop_expand in data) {
data[this.prop_expand] = !data[this.prop_expand]
const children = data[this.prop_children]
if (!data[this.prop_expand] && children) {
this.collapse(children)
}
}
else {
this.$set(data, this.prop_expand, true)
}
this.$emit('on-expand', data, data[this.prop_expand])
this._updateExpandStatus()
},
_toggleExpand(data, status) {
var _this = this
if (Array.isArray(data)) {
data.forEach(item => {
_this.$set(item, this.prop_expand, status)
const children = item[this.prop_children]
this.$set(item, this.props.expand, status)
const children = item[this.props.children]
if (children) {
_this._toggleExpand(children, status)
this._toggleExpand(children, status)
}
})
}
else {
_this.$set(data, this.prop_expand, status)
const children = data[this.prop_children]
this.$set(data, this.props.expand, status)
const children = data[this.props.children]
if (children) {
_this._toggleExpand(children, status)
this._toggleExpand(children, status)
}
}
},
handleNodeClick(e, data) {
this.$emit('on-node-click', e, data, () => {
this.handleExpand(data)
collapse(list) {
list.forEach(child => {
if (child[this.props.expand]) {
child[this.props.expand] = false
}
const children = child[this.props.children]
children && this.collapse(children)
})
},
toggleExpand() {
this._toggleExpand(this.dataCloned, this.expandAll)
handleExpand(data) {
if (this.props.expand in data) {
data[this.props.expand] = !data[this.props.expand]
const children = data[this.props.children]
if (!data[this.props.expand] && children) {
this.collapse(children)
}
}
else this.$set(data, this.props.expand, true)
this.$emit('on-expand', data, data[this.props.expand])
this._updateExpandStatus()
},
handleNodeClick(e, data) {
this.$emit('on-node-click', e, data, () => this.handleExpand(data))
}
},
mounted() {
this._handleData(this.data)
this._cloneData(this.data)
this._updateExpandStatus()
this._toggleExpand(this.dataCloned, this.expandAll)
}

@ -1,7 +1,6 @@
.org-tree-container {
display: inline-block;
padding: 15px;
}
.org-tree {
display: table;
@ -259,3 +258,4 @@
}
}
}
}

@ -9,8 +9,8 @@
:placeholder="placeholder"
:popper-append-to-body="popperAppendToBody"
:automatic-dropdown="automaticDropdown"
@input="$emit('input',$event)"
@change="$emit('change',$event)"
@input="e => $emit('input',e)"
@change="e => $emit('change',e)"
@remove-tag="removeTag"
>
<div class="tree-select-container" slot="empty">
@ -95,6 +95,7 @@
value(v) {
const method = this.multiple ? 'setCheckedKeys' : 'setCurrentKey'
this.$refs.tree[method](v || null)
if (!v && !this.multiple) this.currentNode = null
},
data() {
@ -134,16 +135,16 @@
if (this.multiple) return
if (node.disabled) {
return this.$refs.tree.setCurrentKey()
return this.$refs.tree.setCurrentKey(null)
}
if (this.currentNode === data) {
this.currentNode = null
this.$refs.tree.setCurrentKey()
this.$refs.tree.setCurrentKey(null)
}
else this.currentNode = data
this.$emit('input', this.currentNode && this.currentNode[this.nodeKey])
this.$emit('input', this.currentNode && this.currentNode[this.nodeKey], this.currentNode)
this.$refs.select.blur()
},

@ -44,7 +44,7 @@ service.interceptors.response.use(
//未登录
if (res.status === 401) {
if (store.state.user.prepare_logout) return Promise.reject()
if (store.state.user.prepareLogout) return Promise.reject()
return MessageBox.alert('请登录后重试', {
type: 'warning',
beforeClose: (action, instance, done) => {

@ -72,7 +72,7 @@
},
computed: {
...mapState('user', ['avatar', 'name', 'prepare_logout']),
...mapState('user', ['avatar', 'name', 'prepareLogout']),
...mapState('setting', ['sidebarCollapse', 'showBreadcrumb']),
@ -91,7 +91,7 @@
},
logout() {
if (this.prepare_logout) return
if (this.prepareLogout) return
elConfirm('确认退出?')
.then(() => this.$store.dispatch('user/logout'))
}

@ -38,7 +38,7 @@ export default {
data() {
return {
searchForm: {
id_fuzzy: null,
idFuzzy: null,
cname: null,
vname: null
},

@ -40,7 +40,7 @@ const mutations = {
map[item.url] = item.id
return map
}, {})
state.tree = createTree(data.filter(resource => resource.admin !== 1))
state.tree = createTree(data.filter(resource => resource.admin === false))
},
hasInitRoutes(state, sign) {
state.hasInitRoutes = sign
@ -114,7 +114,7 @@ function addFullPath(routes, basePath = '/') {
//获取经过权限控制后的路由
function getAuthorizedRoutes({resources, admin}) {
if (admin === 1) return finalAuthorityRoutes
if (admin === true) return finalAuthorityRoutes
if (!resources) return []
const arr = JSON.parse(JSON.stringify(finalAuthorityRoutes))
filter(arr, i => !needAuth(i) || i.fullPath in resources)

@ -74,7 +74,7 @@ function defaultEventBind(socket, {state, commit, dispatch}) {
function customEventBind(socket, {state, commit, dispatch, rootState}) {
socket.on('logout', msg => {
if (rootState.user.prepare_logout) return
if (rootState.user.prepareLogout) return
MessageBox.alert(msg || '你已被强制下线,请重新登陆', {
type: 'warning',
beforeClose: (action, instance, done) => {

@ -8,14 +8,15 @@ const user = getUser()
const state = {
//是否在退出的过程中,避免重复弹框
prepare_logout: '',
prepareLogout: '',
/*用户基本信息*/
id: emptyOrDefault(user.id, null),
name: emptyOrDefault(user.name),
role_name: emptyOrDefault(user.role_name),
roleName: emptyOrDefault(user.roleName),
deptName: emptyOrDefault(user.deptName),
avatar: emptyOrDefault(user.avatar),
admin: emptyOrDefault(user.admin),
admin: emptyOrDefault(user.admin, false),
token: emptyOrDefault(user.token),
resources: emptyOrDefault(user.resources, {})
}
@ -28,7 +29,7 @@ const actions = {
return new Promise((resolve, reject) => {
login({username: username.trim(), password})
.then(user => {
user.admin === 1 && (user.role_name = '超级管理员')
user.admin === true && (user.roleName = '超级管理员')
user.avatar = autoCompleteUrl(user.avatar)
commit('$all', user)
setUser(user)
@ -41,8 +42,8 @@ const actions = {
logout({commit, state, dispatch}) {
return new Promise((resolve, reject) => {
if (state.prepare_logout) return Promise.reject()
commit('prepare_logout', 'yes')
if (state.prepareLogout) return Promise.reject()
commit('prepareLogout', 'yes')
logout(state.token)
.then(() => {
commit('resource/hasInitRoutes', false, {root: true})
@ -57,7 +58,7 @@ const actions = {
window.location.reload()
})
.catch(error => reject(error))
.finally(() => commit('prepare_logout', ''))
.finally(() => commit('prepareLogout', ''))
})
},

@ -6,7 +6,7 @@ export function needAuth(route) {
}
export function auth(path) {
if (store.state.user.admin === 1) return true
if (store.state.user.admin === true) return true
const resourceMap = store.state.resource.dataMap
if (!(path in resourceMap)) return true

@ -173,69 +173,3 @@ export function delAllUrlParam() {
history.replaceState(null, null, [...href].join(''))
}
}
export function deepClone(data) {
if (data === null || data === undefined) {
return undefined
}
const dataType = getDataType(data)
if (dataType === "Date") {
let clonedDate = new Date()
clonedDate.setTime(data.getTime())
return clonedDate
}
if (dataType === "Object") {
if (isCyclic(data) === true) {
return data
}
let copiedObject = {}
Object.keys(data).forEach(key => copiedObject[key] = deepClone(data[key]))
return copiedObject
}
if (dataType === "Array") {
let copiedArray = []
for (let i = 0; i < data.length; i++) {
copiedArray.push(deepClone(data[i]))
}
return copiedArray
}
else return data
}
function getDataType(data) {
return Object.prototype.toString.call(data).slice(8, -1)
}
function isCyclic(data) {
let seenObjects = []
function detect(data) {
if (data && getDataType(data) === "Object") {
if (seenObjects.indexOf(data) !== -1) {
return true
}
seenObjects.push(data)
for (let key in data) {
if (data.hasOwnProperty(key) && detect(data[key])) {
return true
}
}
}
return false
}
return detect(data)
}

@ -38,19 +38,14 @@
</span>
</el-form-item>
<el-button
:loading="loading"
class="submit-btn"
type="primary"
@click="login"
>
<el-button :loading="loading" class="submit-btn" type="primary" @click="login">
{{ loading ? '登 录 中...' : '登 录' }}
</el-button>
<div class="flex" style="margin-top: 20px">
<p class="other-ways">
其他方式登录
<svg-icon v-for="i in otherWays" :key="i" :icon="i" @click="thirdPartyLogin(i)"/>
<svg-icon v-for="i in otherWays" :key="i" :icon="i" @click="() => thirdPartyLogin(i)"/>
</p>
<el-button type="text" @click="register">注册账户</el-button>
@ -75,10 +70,7 @@
},
rules: {
username: [{required: true, message: '请输入用户名', trigger: 'change'}],
password: [
{required: true, message: '请输入密码', trigger: 'change'},
{min: 6, max: 32, message: '请输入6-32位的密码', trigger: 'change'}
]
password: [{required: true, message: '请输入密码', trigger: 'change'}]
},
passwordType: 'password',
capsTooltip: false,

@ -1,7 +1,7 @@
<template>
<div style="width: 300px">
<div class="tip-row">单选</div>
<tree-select v-model="single" :data="data" filterable :filter-method="filter"/>
<tree-select v-model="single" :data="data" filterable :filter-method="filter" @input="singleInput"/>
<div class="tip-row">多选</div>
<tree-select v-model="multiple" :data="data" multiple filterable :filter-method="filter"/>
@ -30,6 +30,10 @@
methods: {
filter(v, data) {
return data.label.includes(v)
},
singleInput(v,data) {
console.log(data)
}
}
}

@ -28,7 +28,7 @@
@selection-change="row._selection=$event"
>
<el-table-column
:selectable="p=>p.remain_num>0"
:selectable="p=>p.remainNum>0"
align="center"
type="selection"
width="60"
@ -36,7 +36,7 @@
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商品" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="采购数量" prop="num"/>
<el-table-column align="center" label="未入库数量" prop="remain_num"/>
<el-table-column align="center" label="未入库数量" prop="remainNum"/>
</el-table>
<el-button
size="small"

@ -140,12 +140,12 @@
pid: this.form.id,
cid: i.cid,
cname: i.cname,
num: i.remain_num
num: i.remainNum
}))
},
changeInboundNum(nv, ov, row) {
let parentSub = this.parentSubList.find(i => i.cid === row.cid)
if (!parentSub || nv > parentSub.remain_num) {
if (!parentSub || nv > parentSub.remainNum) {
return elAlert(`${row.cname}的入库数量超出采购数量`, () => row.num = ov)
}
},
@ -171,7 +171,7 @@
if (!parentSub) {
return `${index}个商品不在采购订单中`
}
if (parentSub.remain_num < sub.num) {
if (parentSub.remainNum < sub.num) {
return `${index}个商品的入库数量超出采购数量`
}
index++

@ -2,10 +2,10 @@
<el-card v-loading="config.operating">
<search-form>
<search-form-item label="单 号:">
<el-input v-model="searchForm.id_fuzzy" clearable maxlength="50"/>
<el-input v-model="searchForm.idFuzzy" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="采购订单:">
<el-input v-model="searchForm.pid_fuzzy" clearable maxlength="50"/>
<el-input v-model="searchForm.pidFuzzy" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="创建人:">
<el-input v-model="searchForm.cname" clearable maxlength="50"/>
@ -113,7 +113,7 @@
baseUrl,
api: {search, del, getSubById},
searchForm: {
pid_fuzzy: null
pidFuzzy: null
},
excel: {
column: [

@ -59,11 +59,11 @@
<span v-else>{{row.price}}</span>
</template>
</el-table-column>
<el-table-column v-if="form.id" align="center" label="剩余未入库" prop="remain_num"/>
<el-table-column v-if="form.id" align="center" label="剩余未入库" prop="remainNum"/>
<el-table-column v-if="form.id" align="center" label="入库情况" width="120">
<template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部入库':'未全部入库'}}
<span :class="{success:row.remainNum===0}" class="dot"/>
{{row.remainNum===0?'已全部入库':'未全部入库'}}
</template>
</el-table-column>
<el-table-column v-if="canSave" align="center" label="操作" width="140">

@ -2,7 +2,7 @@
<el-card v-loading="config.operating">
<search-form>
<search-form-item label="单 号:">
<el-input v-model="searchForm.id_fuzzy" clearable maxlength="50"/>
<el-input v-model="searchForm.idFuzzy" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="供应商:">
<el-input v-model="searchForm.sname" clearable maxlength="50"/>
@ -80,7 +80,7 @@
<el-table-column align="center" label="商品" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="采购数量" prop="num"/>
<el-table-column align="center" label="采购单价" prop="price"/>
<el-table-column align="center" label="未入库数量" prop="remain_num"/>
<el-table-column align="center" label="未入库数量" prop="remainNum"/>
</el-table>
</template>
</el-table-column>

@ -28,7 +28,7 @@
>
<el-table-column align="center" type="selection" reserve-selection width="80"/>
<el-table-column align="center" label="商品分类" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="库存数量" prop="total_num" show-overflow-tooltip/>
<el-table-column align="center" label="库存数量" prop="totalNum" show-overflow-tooltip/>
</el-table>
<el-pagination

@ -13,11 +13,11 @@
</collapse-card>
<collapse-card header="基础信息">
<abstract-form-item label="客 户:" prop="customer_name">
<el-input v-if="canSave" :value="form.customer_name" readonly>
<abstract-form-item label="客 户:" prop="customerName">
<el-input v-if="canSave" :value="form.customerName" readonly>
<el-button slot="append" @click="customerDialog=true">选择</el-button>
</el-input>
<template v-else>{{form.customer_name}}</template>
<template v-else>{{form.customerName}}</template>
</abstract-form-item>
</collapse-card>
@ -49,11 +49,11 @@
<span v-else>{{row.price}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="剩余未出库" prop="remain_num"/>
<el-table-column align="center" label="剩余未出库" prop="remainNum"/>
<el-table-column v-if="form.id" align="center" label="出库情况" width="120">
<template v-slot="{row}">
<span :class="{success:row.remain_num===0}" class="dot"/>
{{row.remain_num===0?'已全部出库':'未全部出库'}}
<span :class="{success:row.remainNum===0}" class="dot"/>
{{row.remainNum===0?'已全部出库':'未全部出库'}}
</template>
</el-table-column>
<div v-if="canSave" slot="append" class="table-add-btn">
@ -132,14 +132,14 @@
getById, add, update, commit, withdraw, pass, reject
},
form: {
customer_id: null,
customer_name: null,
customerId: null,
customerName: null,
finish: 0,
ftime: null,
total: 0
},
rules: {
customer_name: [{required: true, message: '客户不能为空', trigger: 'change'}]
customerName: [{required: true, message: '客户不能为空', trigger: 'change'}]
},
customerDialog: false,
stockDialog: false
@ -173,12 +173,12 @@
methods: {
selectCustomer(row) {
this.form.customer_id = row.id
this.form.customer_name = row.name
this.form.customerId = row.id
this.form.customerName = row.name
this.customerDialog = false
},
selectStock(stocks) {
this.form.data = stocks.map(i => ({cid: i.cid, cname: i.cname, num: i.total_num, price: 0}))
this.form.data = stocks.map(i => ({cid: i.cid, cname: i.cname, num: i.totalNum, price: 0}))
this.stockDialog = false
},
addSub() {
@ -187,7 +187,7 @@
cname: null,
num: 0,
price: 0,
remain_num: 0
remainNum: 0
})
},
delSub(row, index) {

@ -2,10 +2,10 @@
<el-card v-loading="config.operating">
<search-form>
<search-form-item label="单 号:">
<el-input v-model="searchForm.id_fuzzy" clearable maxlength="50"/>
<el-input v-model="searchForm.idFuzzy" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="客 户:">
<el-input v-model="searchForm.customer_name" clearable maxlength="50"/>
<el-input v-model="searchForm.customerName" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="创建人:">
<el-input v-model="searchForm.cname" clearable maxlength="50"/>
@ -83,13 +83,13 @@
<el-table-column align="center" label="商品" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="销售数量" prop="num"/>
<el-table-column align="center" label="销售单价" prop="price"/>
<el-table-column align="center" label="未出库数量" prop="remain_num"/>
<el-table-column align="center" label="未出库数量" prop="remainNum"/>
</el-table>
</template>
</el-table-column>
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="单 号" prop="id" width="160" show-overflow-tooltip/>
<el-table-column align="center" label="客 户" prop="customer_name" show-overflow-tooltip/>
<el-table-column align="center" label="客 户" prop="customerName" show-overflow-tooltip/>
<el-table-column align="center" label="创建人" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="创建时间" width="150" show-overflow-tooltip>
<template v-slot="{row}">{{row.ctime | timestamp2Date}}</template>
@ -144,7 +144,7 @@
return {
baseUrl,
searchForm: {
customer_name: null
customerName: null
},
temp: {
finish: [],
@ -154,7 +154,7 @@
excel: {
column: [
{header: '序号', prop: 'id'},
{header: '客户', prop: 'customer_name', width: 30},
{header: '客户', prop: 'customerName', width: 30},
{header: '创建人', prop: 'cname'},
{header: '创建时间', prop: 'ctime'},
{header: '审核人', prop: 'vname'},

@ -28,7 +28,7 @@
@selection-change="row._selection=$event"
>
<el-table-column
:selectable="p=>p.remain_num>0"
:selectable="p=>p.remainNum>0"
align="center"
type="selection"
width="60"
@ -36,7 +36,7 @@
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商品" prop="cname" show-overflow-tooltip/>
<el-table-column align="center" label="销售数量" prop="num"/>
<el-table-column align="center" label="未出库数量" prop="remain_num"/>
<el-table-column align="center" label="未出库数量" prop="remainNum"/>
</el-table>
<el-button
size="small"

@ -52,7 +52,7 @@
<el-table-column align="center" label="#" type="index" width="80"/>
<el-table-column align="center" label="商 品" prop="cname"/>
<el-table-column align="center" label="出库数量" prop="num" width="150"/>
<el-table-column align="center" label="订单剩余未出库数量" prop="remain_num" width="250"/>
<el-table-column align="center" label="订单剩余未出库数量" prop="remainNum" width="250"/>
</abstract-table>
</collapse-card>
@ -203,19 +203,19 @@
selectStock(stocks) {
let res = []
let outboundNum = 0
let remain_num = this.row.remain_num
let remainNum = this.row.remainNum
for (let stock of stocks) {
if (remain_num <= 0) break
if (remainNum <= 0) break
let item = {
...stock,
sid: stock.id,
pid: this.form.id,
max_num: stock.num,
num: stock.num > remain_num ? remain_num : stock.num
num: stock.num > remainNum ? remainNum : stock.num
}
outboundNum = plus(outboundNum, item.num)
res.push(item)
remain_num -= stock.num
remainNum -= stock.num
}
this.row.num = outboundNum
this.row.data = res
@ -243,8 +243,8 @@
if (!outboundNum) return
if (outboundNum > displayTableRow.remain_num) {
let correctNum = sub(displayTableRow.remain_num, sub(outboundNum, nv))
if (outboundNum > displayTableRow.remainNum) {
let correctNum = sub(displayTableRow.remainNum, sub(outboundNum, nv))
if (correctNum < 0) correctNum = 0
else if (correctNum > row.max_num) correctNum = row.max_num
return elAlert(`${displayTableRow.cname}的出库数量超出销售数量`, () => row.num = ov)

@ -2,10 +2,10 @@
<el-card v-loading="config.operating">
<search-form>
<search-form-item label="单 号:">
<el-input v-model="searchForm.id_fuzzy" clearable maxlength="50"/>
<el-input v-model="searchForm.idFuzzy" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="销售订单:">
<el-input v-model="searchForm.pid_fuzzy" clearable maxlength="50"/>
<el-input v-model="searchForm.pidFuzzy" clearable maxlength="50"/>
</search-form-item>
<search-form-item label="创建人:">
<el-input v-model="searchForm.cname" clearable maxlength="50"/>
@ -117,7 +117,7 @@
baseUrl,
api: {search, del, getSubById},
searchForm: {
pid_fuzzy: null
pidFuzzy: null
},
excel: {
column: [

@ -47,8 +47,8 @@
<el-table-column align="center" label="商品分类">
<el-link slot-scope="{row}" @click="more(row)">{{row.cname}}</el-link>
</el-table-column>
<el-table-column align="center" label="库存数量" prop="total_num" show-overflow-tooltip/>
<el-table-column align="center" label="总 值" prop="total_price" show-overflow-tooltip/>
<el-table-column align="center" label="库存数量" prop="totalNum" show-overflow-tooltip/>
<el-table-column align="center" label="总 值" prop="totalPrice" show-overflow-tooltip/>
</abstract-table>
<el-pagination
@ -104,14 +104,14 @@
columns: [
{header: '序号', prop: 'id', width: 20, merge: true},
{header: '分类名称', prop: 'cname', width: 20, merge: true},
{header: '库存总数', prop: 'total_num', width: 20, merge: true},
{header: '库存总值', prop: 'total_price', width: 20, merge: true},
{header: '库存总数', prop: 'totalNum', width: 20, merge: true},
{header: '库存总值', prop: 'totalPrice', width: 20, merge: true},
{header: '采购订单号', prop: 'cgddid', width: 20, merge: true},
{header: '采购单价', prop: 'cg_price', width: 20, merge: true},
{header: '采购数量', prop: 'cg_num', width: 20, merge: true},
{header: '采购单价', prop: 'cgPrice', width: 20, merge: true},
{header: '采购数量', prop: 'cgNum', width: 20, merge: true},
{header: '采购入库单号', prop: 'cgrkid', width: 20},
{header: '入库时间', prop: 'ctime', width: 20},
{header: '入库数量', prop: 'rk_num', width: 20},
{header: '入库数量', prop: 'rkNum', width: 20},
],
merge: {primaryKey: 'cid', orderKey: 'id'}
}
@ -132,7 +132,7 @@
summary({data}) {
let sum = ['合计', '', '', 0]
data.forEach(i => {
sum[3] = plus(sum[3], i.total_price)
sum[3] = plus(sum[3], i.totalPrice)
})
return sum
},

@ -1,11 +1,11 @@
<template>
<div :style="orgTreeStyle" class="org-tree-wrapper" @mousedown="mousedownView">
<org-tree :data="data" :horizontal="horizontal" collapsable expand-all>
<org-tree :data="data" :horizontal="horizontal" collapsable expand-all @on-node-click="nodeClick">
<div
slot-scope="data"
:class="{'has-children-label':data.children && data.children.length}"
class="custom-org-node"
@contextmenu.prevent="$emit('node-contextmenu',$event,data)"
@contextmenu.prevent="e => $emit('node-contextmenu',e,data)"
>
{{ data.label }}
</div>
@ -52,6 +52,10 @@
},
methods: {
nodeClick(e, data, expand) {
expand()
},
mousedownView(event) {
this.canMove = true
this.initPageX = event.pageX
@ -61,14 +65,12 @@
document.addEventListener('mousemove', this.mousemoveView)
document.addEventListener('mouseup', this.mouseupView)
},
mousemoveView(event) {
if (!this.canMove) return
const {pageX, pageY} = event
this.orgTreeOffsetLeft = this.oldMarginLeft + pageX - this.initPageX
this.orgTreeOffsetTop = this.oldMarginTop + pageY - this.initPageY
},
mouseupView() {
this.canMove = false
document.removeEventListener('mousemove', this.mousemoveView)

@ -1,11 +1,5 @@
<template>
<el-card v-loading="loading" class="card-container max-view-height">
<div class="tip-row">
<a href="https://admin.iviewui.com/components/org_tree_page" target="_blank">
组织结构树演示详情见iview-admin
</a>
</div>
<div class="department-outer">
<div class="view-box">
<org-tree-view
@ -44,9 +38,9 @@
:left="contextmenu.left"
:top="contextmenu.top"
>
<context-menu-item v-show="canAdd" @click="add">添加部门</context-menu-item>
<context-menu-item v-show="canUpdate" @click="update">编辑部门</context-menu-item>
<context-menu-item v-show="canDel" @click="del">删除部门</context-menu-item>
<context-menu-item v-if="canAdd" @click="add">添加部门</context-menu-item>
<context-menu-item v-if="canUpdate" @click="update">编辑部门</context-menu-item>
<context-menu-item v-if="canDel" @click="del">删除部门</context-menu-item>
</context-menu>
<edit-dialog v-model="editDialog" :data="currentNode" :type="type" @success="search"/>
@ -54,23 +48,25 @@
</template>
<script>
import OrgTreeView from "./components/OrgTreeView"
import ZoomControl from '@/components/ZoomControl'
/**
* 详情见iview-admin
* https://admin.iviewui.com/components/org_tree_page
*/
import ContextMenu from "@/components/ContextMenu"
import ContextMenuItem from "@/components/ContextMenu/ContextMenuItem"
import EditDialog from "./components/EditDialog"
import {auth} from "@/utils/auth"
import {createTreeByWorker} from "@/utils/tree"
import OrgTreeView from "./components/OrgTreeView"
import ZoomControl from '@/components/ZoomControl'
import {baseUrl, delDepartment, getDepartments} from "@/api/system/department"
import {isEmpty} from '@/utils'
import {auth} from "@/utils/auth"
import {elConfirm, elError, elSuccess} from "@/utils/message"
import {delDepartment, getAllDepartments} from "@/api/system/department"
const baseUrl = '/system/department'
import {createTreeByWorker} from "@/utils/tree"
export default {
name: "departmentManagement",
components: {OrgTreeView, ZoomControl, ContextMenu, ContextMenuItem, EditDialog},
components: {ContextMenu, ContextMenuItem, EditDialog, OrgTreeView, ZoomControl},
data() {
return {
@ -93,21 +89,28 @@
realZoom() {
return this.zoom / 100
},
canAdd() {
return auth(baseUrl + '/add')
return auth(`${baseUrl}/add`)
},
canUpdate() {
return auth(baseUrl + '/update')
return auth(`${baseUrl}/update`)
},
canDel() {
return auth(baseUrl + '/del')
return auth(`${baseUrl}/del`)
},
},
methods: {
//
completeDepartment(arr) {
arr.forEach(i => {
i.label = i.name
i.parentName = i.fullname
i.children && this.completeDepartment(i.children)
})
},
//
openMenu(e, obj) {
e.preventDefault()
this.currentNode = obj
@ -117,6 +120,7 @@
this.contextmenu.show = true
},
//
wheel(e) {
const eventDelta = e.wheelDelta || -(e.detail || 0)
const zoom = this.zoom + eventDelta / 12 * 2
@ -156,10 +160,10 @@
search() {
this.currentNode = null
this.loading = true
getAllDepartments()
getDepartments()
.then(data => createTreeByWorker(data))
.then(data => {
completeDepartment(data)
this.completeDepartment(data)
this.data = data[0]
})
.finally(() => this.loading = false)
@ -170,19 +174,6 @@
this.search()
}
}
//
function completeDepartment(arr, name) {
arr.forEach(i => {
i.label = i.name
i.parentName = name
if (isEmpty(name)) i.fullname = i.name
else i.fullname = name + ' > ' + i.name
if (i.children) completeDepartment(i.children, i.fullname)
})
}
</script>
<style lang="scss">

@ -14,18 +14,18 @@
<el-form-item label="访问路径:" prop="url">
<el-input :value="form.url" readonly/>
</el-form-item>
<el-form-item label="总频率:" prop="total_rate">
<el-form-item label="总频率:" prop="totalRate">
<el-input-number
v-model="form.total_rate"
v-model="form.totalRate"
controls-position="right"
:min="1"
:step="1"
step-strictly size="small"
/>
</el-form-item>
<el-form-item label="单个IP频率:" prop="ip_rate">
<el-form-item label="单个IP频率:" prop="ipRate">
<el-input-number
v-model="form.ip_rate"
v-model="form.ipRate"
controls-position="right"
:min="1"
:step="1"
@ -66,12 +66,12 @@
id: null,
fullName: null,
url: null,
total_rate: 0,
ip_rate: 0
totalRate: 0,
ipRate: 0
},
rules: {
total_rate: [{required: true, message: '总频率不能为空', trigger: 'change'}],
ip_rate: [{required: true, message: '单个ip的频率不能为空', trigger: 'change'}],
totalRate: [{required: true, message: '总频率不能为空', trigger: 'change'}],
ipRate: [{required: true, message: '单个ip的频率不能为空', trigger: 'change'}],
}
}
},

@ -9,8 +9,8 @@
<abstract-table :data="tableData" @row-click="rowClick">
<el-table-column label="名称" prop="fullName" show-overflow-tooltip/>
<el-table-column label="访问路径" prop="url" show-overflow-tooltip/>
<el-table-column label="总频率" prop="total_rate" show-overflow-tooltip/>
<el-table-column label="单个IP频率" prop="ip_rate" show-overflow-tooltip/>
<el-table-column label="总频率" prop="totalRate" show-overflow-tooltip/>
<el-table-column label="单个IP频率" prop="ipRate" show-overflow-tooltip/>
</abstract-table>
</el-row>

@ -0,0 +1,190 @@
<template>
<form-dialog :loading="loading" :title="title" :value="value" width="40%" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="100px"
status-icon
>
<el-form-item label="名 称:" prop="name">
<el-input v-model="form.name" maxlength="20"/>
</el-form-item>
<el-form-item label="状 态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio :label="1">启用</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="数据范围:" prop="scope">
<el-select v-model="form.scope">
<el-option :value="1" label="全部"/>
<el-option :value="2" label="本部门"/>
<el-option :value="3" label="指定部门"/>
</el-select>
</el-form-item>
<el-form-item v-if="form.scope === 3" label="指定部门:">
<el-tree
ref="dept"
:data="departments"
:props="{label:'name'}"
:default-checked-keys="form.departmentId"
node-key="id"
show-checkbox
/>
</el-form-item>
<el-form-item label="权 限:">
<el-tree
ref="perm"
:data="resource"
:props="{label:'name'}"
node-key="id"
show-checkbox
/>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-dropdown placement="top" style="float: left" @command="treeCommand">
<el-button plain size="small">
权限树操作
<i class="el-icon-arrow-up el-icon--right"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{action:'expand',level:0}">展开全部</el-dropdown-item>
<el-dropdown-item :command="{action:'collapse',level:0}">收起全部</el-dropdown-item>
<el-dropdown-item :command="{action:'expand',level:1}">仅展开一级</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</form-dialog>
</template>
<script>
import dialogMixin from "@/mixins/dialogMixin"
import FormDialog from '@/components/FormDialog'
import {getDepartments} from "@/api/system/department"
import {addRole, updateRole} from "@/api/system/role"
import {isEmpty, mergeObj} from '@/utils'
import {createTreeByWorker, elTreeControl} from '@/utils/tree'
export default {
name: "EditDialog",
mixins: [dialogMixin],
components: {FormDialog},
props: {
value: {type: Boolean, default: false},
type: {type: String, default: 'add'},
data: {type: Object, default: () => ({})},
},
data() {
return {
loading: false,
form: {
id: null,
name: null,
status: 1,
scope: 1,
departmentId: [],
resourceId: []
},
rules: {
name: [{required: true, message: '角色名称不能为空', trigger: 'change'}],
status: [{required: true, message: '角色状态不能为空', trigger: 'change'}],
scope: [{required: true, message: '数据范围不能为空', trigger: 'change'}],
},
departments: []
}
},
computed: {
title() {
if (isEmpty(this.type)) return ''
switch (this.type) {
case 'add':
return '添加角色'
case 'edit':
return '编辑角色'
}
},
confirmMessage() {
switch (this.type) {
case 'add':
return `确认添加新的角色【${this.form.name}】?`
case 'edit':
return `确认提交对【${this.data.name}】作出的修改?`
default:
return ''
}
},
resource() {
return this.$store.state.resource.tree
}
},
methods: {
treeCommand({action, level}) {
elTreeControl(this.$refs.perm, action, level)
},
open() {
if (this.type !== 'edit') return
this.$nextTick(() => {
mergeObj(this.form, this.data)
this.$refs.perm.setCheckedKeys(this.form.resourceId)
})
},
clearForm() {
this.form.id = null
this.form.name = null
this.form.status = 1
this.form.scope = 1
this.form.departmentId = []
this.form.resourceId = []
this.$refs.perm.setCheckedKeys([])
this.$refs.dept && this.$refs.dept.setCheckedKeys([])
this.$nextTick(() => this.$refs.form.clearValidate())
},
cancel() {
this.closeDialog()
this.clearForm()
},
confirm() {
if (this.loading) return
this.$refs.form.validate(v => {
if (!v) return
this.loading = true
const obj = {
...this.form,
departmentId: this.$refs.dept ? this.$refs.dept.getCheckedKeys().join(',') : [],
resourceId: this.$refs.perm.getCheckedKeys().join(',')
}
const promise = this.type === 'add' ? addRole(obj) : updateRole(obj)
promise
.then(({msg}) => this.$emit('success', msg))
.finally(() => this.loading = false)
})
}
},
mounted() {
getDepartments(false)
.then(data => createTreeByWorker(data))
.then(data => {
this.departments = data
})
}
}
</script>

@ -1,158 +0,0 @@
<template>
<form-dialog :loading="loading" :title="title" :value="value" @close="cancel" @open="open">
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="right"
label-width="75px"
status-icon
>
<el-form-item label="名 称:" prop="name">
<el-input v-model="form.name" maxlength="20"/>
</el-form-item>
<el-form-item label="状 态:" prop="status">
<el-radio-group v-model="form.status">
<el-radio :label="1">启用</el-radio>
<el-radio :label="0">禁用</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="权 限:">
<el-tree
ref="tree"
:data="resource"
:expand-on-click-node="false"
:props="{label:'name'}"
node-key="id"
show-checkbox
/>
</el-form-item>
</el-form>
<template v-slot:footer>
<el-dropdown placement="top" style="float: left" @command="treeCommand">
<el-button plain size="small">
树形操作
<i class="el-icon-arrow-up el-icon--right"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{action:'expand',level:0}">展开全部</el-dropdown-item>
<el-dropdown-item :command="{action:'collapse',level:0}">收起全部</el-dropdown-item>
<el-dropdown-item :command="{action:'expand',level:1}">仅展开一级</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-button plain size="small" @click="closeDialog"> </el-button>
<el-button size="small" type="primary" @click="confirm"> </el-button>
</template>
</form-dialog>
</template>
<script>
import FormDialog from '@/components/FormDialog'
import dialogMixin from "@/mixins/dialogMixin"
import {addRole, updateRole} from "@/api/system/role"
import {isEmpty, mergeObj} from '@/utils'
import {elTreeControl} from '@/utils/tree'
export default {
name: "EditDialog",
mixins: [dialogMixin],
components: {FormDialog},
props: {
value: {type: Boolean, default: false},
type: {type: String, default: 'add'},
data: {type: Object, default: () => ({})},
},
data() {
return {
loading: false,
form: {
id: null,
name: null,
status: 1,
resource_id: []
},
rules: {
name: [{required: true, message: '角色名称不能为空', trigger: 'change'}],
status: [{required: true, message: '角色状态不能为空', trigger: 'change'}],
}
}
},
computed: {
title() {
if (isEmpty(this.type)) return ''
switch (this.type) {
case 'add':
return '添加角色'
case 'edit':
return '编辑角色'
}
},
confirmMessage() {
switch (this.type) {
case 'add':
return `确认添加新的角色【${this.form.name}】?`
case 'edit':
return `确认提交对【${this.data.name}】作出的修改?`
default:
return ''
}
},
resource() {
return this.$store.state.resource.tree
}
},
methods: {
treeCommand({action, level}) {
elTreeControl(this.$refs.tree, action, level)
},
open() {
this.$nextTick(() => {
if (this.type === 'edit') {
mergeObj(this.form, this.data)
this.$refs.tree.setCheckedKeys(this.form.resource_id)
}
})
},
clearForm() {
this.form.id = null
this.form.name = null
this.form.status = 1
this.form.resource_id = []
this.$refs.tree.setCheckedKeys([])
this.$nextTick(() => this.$refs.form.clearValidate())
},
cancel() {
this.closeDialog()
this.clearForm()
},
confirm() {
if (this.loading) return
this.$refs.form.validate(v => {
if (!v) return
this.loading = true
let obj = {
...this.form,
resource_id: this.$refs.tree.getCheckedKeys().join(',')
}
let promise = this.type === 'add' ? addRole(obj) : updateRole(obj)
promise
.then(({msg}) => this.$emit('success', msg))
.finally(() => this.loading = false)
})
},
}
}
</script>

@ -1,59 +0,0 @@
<script type="text/jsx">
import {createTree} from "@/utils/tree"
export default {
name: "RoleResource",
functional: true,
props: {
ids: {type: Array, default: () => []},
map: {type: Object, default: () => ({})}
},
render(h, context) {
const {ids, map} = context.props
let tree = []
for (let id of ids) map[id] && tree.push(map[id])
tree = createTree(tree)
const nodes = []
const fun = (arr, left) => {
for (let r of arr) {
nodes.push(
<span style={'margin-left:' + left + 'px'}>
<svg-icon icon="check"/>
{r.name}
</span>
)
if (r.children.length > 0) {
if (r.children[0].children.length > 0) nodes.push(<p/>)
fun(r.children, left + 20)
}
}
nodes.push(<p/>)
}
fun(tree, 0)
return nodes
}
}
</script>
<style lang="scss" scoped>
@import "~@/assets/styles/variables.scss";
span {
.svg-icon {
color: $--color-primary
}
}
span + span {
margin-left: 10px;
}
</style>

@ -65,23 +65,21 @@
</template>
<script>
import tableMixin from '@/mixins/tablePageMixin'
import EditDialog from './EditDialog'
import SearchForm from "@/components/SearchForm"
import SearchFormItem from "@/components/SearchForm/SearchFormItem"
import EditDialog from './components/EditDialog'
import {delRole, searchRoles} from "@/api/system/role"
import {baseUrl, delRole, searchRoles} from "@/api/system/role"
import {isEmpty} from '@/utils'
import {elConfirm, elError, elSuccess} from "@/utils/message"
import {auth} from "@/utils/auth"
import tableMixin from '@/mixins/tablePageMixin'
const baseUrl = '/system/role'
import {elConfirm, elError, elSuccess} from "@/utils/message"
export default {
name: "roleManagement",
mixins: [tableMixin],
components: {SearchForm, SearchFormItem, EditDialog},
components: {EditDialog, SearchForm, SearchFormItem},
data() {
return {
@ -99,15 +97,13 @@
computed: {
canAdd() {
return auth(baseUrl + '/add')
return auth(`${baseUrl}/add`)
},
canUpdate() {
return auth(baseUrl + '/update')
return auth(`${baseUrl}/update`)
},
canDel() {
return auth(baseUrl + '/del')
return auth(`${baseUrl}/del`)
}
},
@ -120,6 +116,11 @@
}
},
str2intArray(str) {
if (isEmpty(str)) return []
return str.split(',').map(i => parseInt(i))
},
search() {
if (this.config.loading) return
this.config.loading = true
@ -128,7 +129,8 @@
searchRoles(this.mergeSearchForm())
.then(({list, total}) => {
list.forEach(i => {
i.resource_id = isEmpty(i.resource_id) ? [] : i.resource_id.split(',').map(i => parseInt(i))
i.departmentId = this.str2intArray(i.departmentId)
i.resourceId = this.str2intArray(i.resourceId)
})
this.searchForm.total = total
this.tableData = list
@ -150,12 +152,13 @@
del() {
if (!this.row) return elError('请选择要删除的角色')
if (this.row.status === 1) return elError('不能删除已启用的角色')
const {id, name, status} = this.row
if (status === 1) return elError('不能删除已启用的角色')
if (this.config.operating) return
elConfirm(`确定删除角色【${this.row.name}】?`)
elConfirm(`确定删除角色【${name}】?`)
.then(() => {
this.config.operating = true
return delRole({id: this.row.id, name: this.row.name})
return delRole({id, name})
})
.then(() => {
elSuccess('删除成功')

@ -0,0 +1,39 @@
<template>
<tree-select :value="value" :data="data" :props="{label:'name'}" popper-append-to-body @input="input"/>
</template>
<script>
import TreeSelect from '@/components/TreeSelect'
import {getDepartments} from "@/api/system/department"
import {createTreeByWorker} from "@/utils/tree"
import {isEmpty} from "@/utils"
export default {
name: "DepartmentSelector",
components: {TreeSelect},
props: {value: Number},
data() {
return {
data: []
}
},
methods: {
input(v, data) {
this.$emit('input', v)
this.$emit('get-name', data && data.fullname)
},
},
mounted() {
getDepartments(false)
.then(data => createTreeByWorker(data))
.then(data => {
this.data = data
})
}
}
</script>

@ -13,10 +13,19 @@
</el-form-item>
<el-form-item label="角 色:" prop="role">
<role-selector
v-if="canEdit"
v-model="form.role"
:disabled="!canEdit"
@get-name="e => form.role_name = e"
@get-name="e => form.roleName = e"
/>
<template v-else>{{ form.roleName }}</template>
</el-form-item>
<el-form-item label="部 门:" prop="dept">
<department-selector
v-if="canEdit"
v-model="form.dept"
@get-name="e => form.deptName = e"
/>
<template v-else>{{ form.deptName }}</template>
</el-form-item>
<el-form-item label="状 态:" prop="status">
<el-radio-group v-model="form.status" :disabled="!canEdit">
@ -34,9 +43,10 @@
</template>
<script>
import dialogMixin from "@/mixins/dialogMixin"
import DepartmentSelector from "./DepartmentSelector"
import FormDialog from '@/components/FormDialog'
import RoleSelector from './RoleSelector'
import dialogMixin from "@/mixins/dialogMixin"
import {checkName} from "@/api/account"
import {addUser, updateUser} from "@/api/system/user"
import {isEmpty} from '@/utils'
@ -47,7 +57,7 @@
mixins: [dialogMixin],
components: {FormDialog, RoleSelector},
components: {DepartmentSelector, FormDialog, RoleSelector},
props: {
value: {type: Boolean, default: false},
@ -67,7 +77,9 @@
id: null,
name: null,
role: null,
role_name: null,
roleName: null,
dept: null,
deptName: null,
status: 1,
},
rules: {
@ -76,6 +88,7 @@
{validator: validateName, trigger: 'change'}
],
role: [{required: true, message: '用户角色不能为空', trigger: 'change'}],
dept: [{required: true, message: '用户部门不能为空', trigger: 'change'}],
status: [{required: true, message: '用户状态不能为空', trigger: 'change'}],
}
}
@ -125,7 +138,9 @@
this.form.id = null
this.form.name = null
this.form.role = null
this.form.role_name = null
this.form.roleName = null
this.form.dept = null
this.form.deptName = null
this.form.status = 1
this.$nextTick(() => this.$refs.form.clearValidate())
},

@ -1,5 +1,5 @@
<template>
<el-select :disabled="disabled" :value="value" clearable @clear="emit(null)" @input="emit">
<el-select :value="value" clearable @clear="emit(null)" @input="emit">
<el-option
v-for="item in roles"
:key="item.id"
@ -15,12 +15,7 @@
export default {
name: "RoleSelector",
props: {
value: Number,
disabled: {
type: Boolean, default: false
}
},
props: {value: Number},
data() {
return {

@ -44,15 +44,16 @@
v-if="row.avatar"
:src="row.avatar"
class="table-image"
@click.stop="previewAvatar(row.avatar)"
@click.stop="() => previewAvatar(row.avatar)"
>
</el-table-column>
<el-table-column align="center" label="用户名" prop="name" show-overflow-tooltip/>
<el-table-column align="center" label="角 色" show-overflow-tooltip>
<template v-slot="{row}">
{{row.admin===1?'超级管理员':row.role_name}}
{{ row.admin === true ? '超级管理员' : row.roleName }}
</template>
</el-table-column>
<el-table-column align="center" label="部 门" prop="deptName" show-overflow-tooltip/>
<el-table-column align="center" label="创建时间" width="150" show-overflow-tooltip>
<template v-slot="{row}">{{ row.ctime | timestamp2Date }}</template>
</el-table-column>
@ -119,23 +120,23 @@
computed: {
canAdd() {
return auth(baseUrl + '/add')
return auth(`${baseUrl}/add`)
},
canUpdate() {
return auth(baseUrl + '/update')
return auth(`${baseUrl}/update`)
},
canDel() {
return auth(baseUrl + '/del')
return auth(`${baseUrl}/del`)
},
canKick() {
return auth(baseUrl + '/kick')
return auth(`${baseUrl}/kick`)
},
canResetPwd() {
return auth(baseUrl + '/resetPwd')
return auth(`${baseUrl}/resetPwd`)
},
},

@ -9,11 +9,11 @@
label-width="100px"
status-icon
>
<el-form-item label="旧密码:" prop="old_pwd">
<el-input v-model.trim="form.old_pwd" maxlength="100" type="password"/>
<el-form-item label="旧密码:" prop="oldPwd">
<el-input v-model.trim="form.oldPwd" maxlength="100" type="password"/>
</el-form-item>
<el-form-item label="新密码:" prop="new_pwd">
<el-input v-model.trim="form.new_pwd" maxlength="100" type="password"/>
<el-form-item label="新密码:" prop="newPwd">
<el-input v-model.trim="form.newPwd" maxlength="100" type="password"/>
</el-form-item>
</el-form>
@ -40,15 +40,15 @@
return {
loading: false,
form: {
old_pwd: null,
new_pwd: null
oldPwd: null,
newPwd: null
},
rules: {
old_pwd: [{required: true, message: '请输入原密码', trigger: 'change'}],
new_pwd: [
oldPwd: [{required: true, message: '请输入原密码', trigger: 'change'}],
newPwd: [
{required: true, message: '请输入新密码', trigger: 'change'},
{
validator: (r, v, c) => v !== this.form.old_pwd ? c() : c('新密码不得与旧密码相同'),
validator: (r, v, c) => v !== this.form.oldPwd ? c() : c('新密码不得与旧密码相同'),
trigger: 'change'
},
{
@ -68,8 +68,8 @@
methods: {
clearForm() {
this.form.old_pwd = null
this.form.new_pwd = null
this.form.oldPwd = null
this.form.newPwd = null
this.$nextTick(() => this.$refs.form.clearValidate())
},
@ -79,8 +79,8 @@
if (!v) return
this.loading = true
updateUserPwd({
old_pwd: md5(this.form.old_pwd),
new_pwd: md5(this.form.new_pwd),
oldPwd: md5(this.form.oldPwd),
newPwd: md5(this.form.newPwd),
})
.then(() => elSuccess('修改成功'))
.finally(() => {

@ -6,8 +6,11 @@
<li>登录账号
<div class="user-right">{{ name }}</div>
</li>
<li>所属部门
<div class="user-right">{{ deptName }}</div>
</li>
<li>用户角色
<div class="user-right">{{ role_name }}</div>
<div class="user-right">{{ roleName }}</div>
</li>
<li>安全设置
<div class="user-right"><a @click="modifyPasswordDialog=true">修改密码</a></div>
@ -21,12 +24,14 @@
</template>
<script>
import UserAccount from './Account'
import UploadAvatar from './Avatar'
import {mapState} from 'vuex'
import UploadAvatar from './Avatar'
import UserAccount from './Account'
export default {
components: {UserAccount, UploadAvatar},
name: 'UserCard',
components: {UploadAvatar, UserAccount},
data() {
return {
@ -36,7 +41,7 @@
},
computed: {
...mapState('user', ['name', 'avatar', 'role_name', 'admin'])
...mapState('user', ['name', 'avatar', 'roleName', 'deptName', 'admin'])
}
}
</script>

@ -28,17 +28,14 @@
</template>
<script>
import UserCard from "./components/UserCard"
import LoginHistory from "./components/LoginHistory"
import UserAction from "./components/UserAction"
import UserCard from "./components/UserCard"
export default {
name: 'userCenter',
components: {
UserCard,
LoginHistory,
UserAction: () => import('./components/UserAction')
},
components: {UserCard, LoginHistory, UserAction},
data() {
return {

Loading…
Cancel
Save