模型开发及源模型分类联调

dev_2022-03-03
yujialong 3 years ago
parent cb3795b69f
commit ddcf41931f
  1. 31
      src/assets/css/main.css
  2. 8
      src/components/org-tree/index.js
  3. 486
      src/components/org-tree/src/model/node.js
  4. 340
      src/components/org-tree/src/model/tree-store.js
  5. 27
      src/components/org-tree/src/model/util.js
  6. 279
      src/components/org-tree/src/tree-node.vue
  7. 496
      src/components/org-tree/src/tree.vue
  8. 5
      src/router/index.js
  9. 5
      src/setting.js
  10. 5
      src/utils/api.js
  11. 10
      src/views/serve/Configure.vue
  12. 81
      src/views/serve/backstage/index.vue
  13. 613
      src/views/serve/backstage/model.vue
  14. 348
      src/views/serve/backstage/modelType.vue
  15. 630
      src/views/serve/backstage/sourceModel.vue
  16. 262
      src/views/serve/backstage/sourceType.vue

@ -53,6 +53,37 @@ li {
border: 1px solid #ddd;
border-radius: 5px;
}
.p-title {
padding-left: 5px;
margin-bottom: 24px;
line-height: 1;
font-size: 14px;
color: #585858;
border-left: 3px solid #9278ff;
}
.tool {
display: flex;
justify-content: space-between;
margin-bottom: 24px;
}
.tool .filter {
display: inline-flex;
align-items: center;
flex: 1;
}
.tool .filter li {
display: inline-flex;
align-items: center;
margin-right: 30px;
}
.tool .filter label {
margin-right: 6px;
font-size: 14px;
line-height: 14px;
color: rgba(0, 0, 0, .65);
white-space: nowrap;
}
.crumbs {
margin: 10px 0;

@ -0,0 +1,8 @@
import Tree from './src/tree.vue';
/* istanbul ignore next */
Tree.install = function(Vue) {
Vue.component(Tree.name, Tree);
};
export default Tree;

@ -0,0 +1,486 @@
import objectAssign from 'element-ui/src/utils/merge';
import { markNodeData, NODE_KEY } from './util';
import { arrayFindIndex } from 'element-ui/src/utils/util';
export const getChildState = node => {
let all = true;
let none = true;
let allWithoutDisable = true;
for (let i = 0, j = node.length; i < j; i++) {
const n = node[i];
if (n.checked !== true || n.indeterminate) {
all = false;
if (!n.disabled) {
allWithoutDisable = false;
}
}
if (n.checked !== false || n.indeterminate) {
none = false;
}
}
return { all, none, allWithoutDisable, half: !all && !none };
};
const reInitChecked = function(node) {
if (node.childNodes.length === 0) return;
const {all, none, half} = getChildState(node.childNodes);
if (all) {
node.checked = true;
node.indeterminate = false;
} else if (half) {
node.checked = false;
node.indeterminate = true;
} else if (none) {
node.checked = false;
node.indeterminate = false;
}
const parent = node.parent;
if (!parent || parent.level === 0) return;
if (!node.store.checkStrictly) {
reInitChecked(parent);
}
};
const getPropertyFromData = function(node, prop) {
const props = node.store.props;
const data = node.data || {};
const config = props[prop];
if (typeof config === 'function') {
return config(data, node);
} else if (typeof config === 'string') {
return data[config];
} else if (typeof config === 'undefined') {
const dataProp = data[prop];
return dataProp === undefined ? '' : dataProp;
}
};
let nodeIdSeed = 0;
export default class Node {
constructor(options) {
this.id = nodeIdSeed++;
this.text = null;
this.checked = false;
this.indeterminate = false;
this.data = null;
this.expanded = false;
this.parent = null;
this.visible = true;
this.isCurrent = false;
for (let name in options) {
if (options.hasOwnProperty(name)) {
this[name] = options[name];
}
}
// internal
this.level = 0;
this.loaded = false;
this.childNodes = [];
this.loading = false;
if (this.parent) {
this.level = this.parent.level + 1;
}
const store = this.store;
if (!store) {
throw new Error('[Node]store is required!');
}
store.registerNode(this);
const props = store.props;
if (props && typeof props.isLeaf !== 'undefined') {
const isLeaf = getPropertyFromData(this, 'isLeaf');
if (typeof isLeaf === 'boolean') {
this.isLeafByUser = isLeaf;
}
}
if (store.lazy !== true && this.data) {
this.setData(this.data);
if (store.defaultExpandAll) {
this.expanded = true;
}
} else if (this.level > 0 && store.lazy && store.defaultExpandAll) {
this.expand();
}
if (!Array.isArray(this.data)) {
markNodeData(this, this.data);
}
if (!this.data) return;
const defaultExpandedKeys = store.defaultExpandedKeys;
const key = store.key;
if (key && defaultExpandedKeys && defaultExpandedKeys.indexOf(this.key) !== -1) {
this.expand(null, store.autoExpandParent);
}
if (key && store.currentNodeKey !== undefined && this.key === store.currentNodeKey) {
store.currentNode = this;
store.currentNode.isCurrent = true;
}
if (store.lazy) {
store._initDefaultCheckedNode(this);
}
this.updateLeafState();
}
setData(data) {
if (!Array.isArray(data)) {
markNodeData(this, data);
}
this.data = data;
this.childNodes = [];
let children;
if (this.level === 0 && this.data instanceof Array) {
children = this.data;
} else {
children = getPropertyFromData(this, 'children') || [];
}
for (let i = 0, j = children.length; i < j; i++) {
this.insertChild({ data: children[i] });
}
}
get label() {
return getPropertyFromData(this, 'label');
}
get key() {
const nodeKey = this.store.key;
if (this.data) return this.data[nodeKey];
return null;
}
get disabled() {
return getPropertyFromData(this, 'disabled');
}
get nextSibling() {
const parent = this.parent;
if (parent) {
const index = parent.childNodes.indexOf(this);
if (index > -1) {
return parent.childNodes[index + 1];
}
}
return null;
}
get previousSibling() {
const parent = this.parent;
if (parent) {
const index = parent.childNodes.indexOf(this);
if (index > -1) {
return index > 0 ? parent.childNodes[index - 1] : null;
}
}
return null;
}
contains(target, deep = true) {
const walk = function(parent) {
const children = parent.childNodes || [];
let result = false;
for (let i = 0, j = children.length; i < j; i++) {
const child = children[i];
if (child === target || (deep && walk(child))) {
result = true;
break;
}
}
return result;
};
return walk(this);
}
remove() {
const parent = this.parent;
if (parent) {
parent.removeChild(this);
}
}
insertChild(child, index, batch) {
if (!child) throw new Error('insertChild error: child is required.');
if (!(child instanceof Node)) {
if (!batch) {
const children = this.getChildren(true);
if (children.indexOf(child.data) === -1) {
if (typeof index === 'undefined' || index < 0) {
children.push(child.data);
} else {
children.splice(index, 0, child.data);
}
}
}
objectAssign(child, {
parent: this,
store: this.store
});
child = new Node(child);
}
child.level = this.level + 1;
if (typeof index === 'undefined' || index < 0) {
this.childNodes.push(child);
} else {
this.childNodes.splice(index, 0, child);
}
this.updateLeafState();
}
insertBefore(child, ref) {
let index;
if (ref) {
index = this.childNodes.indexOf(ref);
}
this.insertChild(child, index);
}
insertAfter(child, ref) {
let index;
if (ref) {
index = this.childNodes.indexOf(ref);
if (index !== -1) index += 1;
}
this.insertChild(child, index);
}
removeChild(child) {
const children = this.getChildren() || [];
const dataIndex = children.indexOf(child.data);
if (dataIndex > -1) {
children.splice(dataIndex, 1);
}
const index = this.childNodes.indexOf(child);
if (index > -1) {
this.store && this.store.deregisterNode(child);
child.parent = null;
this.childNodes.splice(index, 1);
}
this.updateLeafState();
}
removeChildByData(data) {
let targetNode = null;
for (let i = 0; i < this.childNodes.length; i++) {
if (this.childNodes[i].data === data) {
targetNode = this.childNodes[i];
break;
}
}
if (targetNode) {
this.removeChild(targetNode);
}
}
expand(callback, expandParent) {
const done = () => {
if (expandParent) {
let parent = this.parent;
while (parent.level > 0) {
parent.expanded = true;
parent = parent.parent;
}
}
this.expanded = true;
if (callback) callback();
};
if (this.shouldLoadData()) {
this.loadData((data) => {
if (data instanceof Array) {
if (this.checked) {
this.setChecked(true, true);
} else if (!this.store.checkStrictly) {
reInitChecked(this);
}
done();
}
});
} else {
done();
}
}
doCreateChildren(array, defaultProps = {}) {
array.forEach((item) => {
this.insertChild(objectAssign({ data: item }, defaultProps), undefined, true);
});
}
collapse() {
this.expanded = false;
}
shouldLoadData() {
return this.store.lazy === true && this.store.load && !this.loaded;
}
updateLeafState() {
if (this.store.lazy === true && this.loaded !== true && typeof this.isLeafByUser !== 'undefined') {
this.isLeaf = this.isLeafByUser;
return;
}
const childNodes = this.childNodes;
if (!this.store.lazy || (this.store.lazy === true && this.loaded === true)) {
// this.isLeaf = !childNodes || childNodes.length === 0;
this.isLeaf = this.isLeafByUser;
return;
}
this.isLeaf = false;
}
setChecked(value, deep, recursion, passValue) {
this.indeterminate = value === 'half';
this.checked = value === true;
if (this.store.checkStrictly) return;
if (!(this.shouldLoadData() && !this.store.checkDescendants)) {
let { all, allWithoutDisable } = getChildState(this.childNodes);
if (!this.isLeaf && (!all && allWithoutDisable)) {
this.checked = false;
value = false;
}
const handleDescendants = () => {
if (deep) {
const childNodes = this.childNodes;
for (let i = 0, j = childNodes.length; i < j; i++) {
const child = childNodes[i];
passValue = passValue || value !== false;
const isCheck = child.disabled ? child.checked : passValue;
child.setChecked(isCheck, deep, true, passValue);
}
const { half, all } = getChildState(childNodes);
if (!all) {
this.checked = all;
this.indeterminate = half;
}
}
};
if (this.shouldLoadData()) {
// Only work on lazy load data.
this.loadData(() => {
handleDescendants();
reInitChecked(this);
}, {
checked: value !== false
});
return;
} else {
handleDescendants();
}
}
const parent = this.parent;
if (!parent || parent.level === 0) return;
if (!recursion) {
reInitChecked(parent);
}
}
getChildren(forceInit = false) { // this is data
if (this.level === 0) return this.data;
const data = this.data;
if (!data) return null;
const props = this.store.props;
let children = 'children';
if (props) {
children = props.children || 'children';
}
if (data[children] === undefined) {
data[children] = null;
}
if (forceInit && !data[children]) {
data[children] = [];
}
return data[children];
}
updateChildren() {
const newData = this.getChildren() || [];
const oldData = this.childNodes.map((node) => node.data);
const newDataMap = {};
const newNodes = [];
newData.forEach((item, index) => {
const key = item[NODE_KEY];
const isNodeExists = !!key && arrayFindIndex(oldData, data => data[NODE_KEY] === key) >= 0;
if (isNodeExists) {
newDataMap[key] = { index, data: item };
} else {
newNodes.push({ index, data: item });
}
});
if (!this.store.lazy) {
oldData.forEach((item) => {
if (!newDataMap[item[NODE_KEY]]) this.removeChildByData(item);
});
}
newNodes.forEach(({ index, data }) => {
this.insertChild({ data }, index);
});
this.updateLeafState();
}
loadData(callback, defaultProps = {}) {
if (this.store.lazy === true && this.store.load && !this.loaded && (!this.loading || Object.keys(defaultProps).length)) {
this.loading = true;
const resolve = (children) => {
this.loaded = true;
this.loading = false;
this.childNodes = [];
this.doCreateChildren(children, defaultProps);
this.updateLeafState();
if (callback) {
callback.call(this, children);
}
};
this.store.load(this, resolve);
} else {
if (callback) {
callback.call(this);
}
}
}
}

@ -0,0 +1,340 @@
import Node from './node';
import { getNodeKey } from './util';
export default class TreeStore {
constructor(options) {
this.currentNode = null;
this.currentNodeKey = null;
for (let option in options) {
if (options.hasOwnProperty(option)) {
this[option] = options[option];
}
}
this.nodesMap = {};
this.root = new Node({
data: this.data,
store: this
});
if (this.lazy && this.load) {
const loadFn = this.load;
loadFn(this.root, (data) => {
this.root.doCreateChildren(data);
this._initDefaultCheckedNodes();
});
} else {
this._initDefaultCheckedNodes();
}
}
filter(value) {
const filterNodeMethod = this.filterNodeMethod;
const lazy = this.lazy;
const traverse = function(node) {
const childNodes = node.root ? node.root.childNodes : node.childNodes;
childNodes.forEach((child) => {
child.visible = filterNodeMethod.call(child, value, child.data, child);
traverse(child);
});
if (!node.visible && childNodes.length) {
let allHidden = true;
allHidden = !childNodes.some(child => child.visible);
if (node.root) {
node.root.visible = allHidden === false;
} else {
node.visible = allHidden === false;
}
}
if (!value) return;
if (node.visible && !node.isLeaf && !lazy) node.expand();
};
traverse(this);
}
setData(newVal) {
const instanceChanged = newVal !== this.root.data;
if (instanceChanged) {
this.root.setData(newVal);
this._initDefaultCheckedNodes();
} else {
this.root.updateChildren();
}
}
getNode(data) {
if (data instanceof Node) return data;
const key = typeof data !== 'object' ? data : getNodeKey(this.key, data);
return this.nodesMap[key] || null;
}
insertBefore(data, refData) {
const refNode = this.getNode(refData);
refNode.parent.insertBefore({ data }, refNode);
}
insertAfter(data, refData) {
const refNode = this.getNode(refData);
refNode.parent.insertAfter({ data }, refNode);
}
remove(data) {
const node = this.getNode(data);
if (node && node.parent) {
if (node === this.currentNode) {
this.currentNode = null;
}
node.parent.removeChild(node);
}
}
append(data, parentData) {
const parentNode = parentData ? this.getNode(parentData) : this.root;
if (parentNode) {
parentNode.insertChild({ data });
}
}
_initDefaultCheckedNodes() {
const defaultCheckedKeys = this.defaultCheckedKeys || [];
const nodesMap = this.nodesMap;
defaultCheckedKeys.forEach((checkedKey) => {
const node = nodesMap[checkedKey];
if (node) {
node.setChecked(true, !this.checkStrictly);
}
});
}
_initDefaultCheckedNode(node) {
const defaultCheckedKeys = this.defaultCheckedKeys || [];
if (defaultCheckedKeys.indexOf(node.key) !== -1) {
node.setChecked(true, !this.checkStrictly);
}
}
setDefaultCheckedKey(newVal) {
if (newVal !== this.defaultCheckedKeys) {
this.defaultCheckedKeys = newVal;
this._initDefaultCheckedNodes();
}
}
registerNode(node) {
const key = this.key;
if (!key || !node || !node.data) return;
const nodeKey = node.key;
if (nodeKey !== undefined) this.nodesMap[node.key] = node;
}
deregisterNode(node) {
const key = this.key;
if (!key || !node || !node.data) return;
node.childNodes.forEach(child => {
this.deregisterNode(child);
});
delete this.nodesMap[node.key];
}
getCheckedNodes(leafOnly = false, includeHalfChecked = false) {
const checkedNodes = [];
const traverse = function(node) {
const childNodes = node.root ? node.root.childNodes : node.childNodes;
childNodes.forEach((child) => {
if ((child.checked || (includeHalfChecked && child.indeterminate)) && (!leafOnly || (leafOnly && child.isLeaf))) {
checkedNodes.push(child.data);
}
traverse(child);
});
};
traverse(this);
return checkedNodes;
}
getCheckedKeys(leafOnly = false) {
return this.getCheckedNodes(leafOnly).map((data) => (data || {})[this.key]);
}
getHalfCheckedNodes() {
const nodes = [];
const traverse = function(node) {
const childNodes = node.root ? node.root.childNodes : node.childNodes;
childNodes.forEach((child) => {
if (child.indeterminate) {
nodes.push(child.data);
}
traverse(child);
});
};
traverse(this);
return nodes;
}
getHalfCheckedKeys() {
return this.getHalfCheckedNodes().map((data) => (data || {})[this.key]);
}
_getAllNodes() {
const allNodes = [];
const nodesMap = this.nodesMap;
for (let nodeKey in nodesMap) {
if (nodesMap.hasOwnProperty(nodeKey)) {
allNodes.push(nodesMap[nodeKey]);
}
}
return allNodes;
}
updateChildren(key, data) {
const node = this.nodesMap[key];
if (!node) return;
const childNodes = node.childNodes;
for (let i = childNodes.length - 1; i >= 0; i--) {
const child = childNodes[i];
this.remove(child.data);
}
for (let i = 0, j = data.length; i < j; i++) {
const child = data[i];
this.append(child, node.data);
}
}
_setCheckedKeys(key, leafOnly = false, checkedKeys) {
const allNodes = this._getAllNodes().sort((a, b) => b.level - a.level);
const cache = Object.create(null);
const keys = Object.keys(checkedKeys);
allNodes.forEach(node => node.setChecked(false, false));
for (let i = 0, j = allNodes.length; i < j; i++) {
const node = allNodes[i];
const nodeKey = node.data[key].toString();
let checked = keys.indexOf(nodeKey) > -1;
if (!checked) {
if (node.checked && !cache[nodeKey]) {
node.setChecked(false, false);
}
continue;
}
let parent = node.parent;
while (parent && parent.level > 0) {
cache[parent.data[key]] = true;
parent = parent.parent;
}
if (node.isLeaf || this.checkStrictly) {
node.setChecked(true, false);
continue;
}
node.setChecked(true, true);
if (leafOnly) {
node.setChecked(false, false);
const traverse = function(node) {
const childNodes = node.childNodes;
childNodes.forEach((child) => {
if (!child.isLeaf) {
child.setChecked(false, false);
}
traverse(child);
});
};
traverse(node);
}
}
}
setCheckedNodes(array, leafOnly = false) {
const key = this.key;
const checkedKeys = {};
array.forEach((item) => {
checkedKeys[(item || {})[key]] = true;
});
this._setCheckedKeys(key, leafOnly, checkedKeys);
}
setCheckedKeys(keys, leafOnly = false) {
this.defaultCheckedKeys = keys;
const key = this.key;
const checkedKeys = {};
keys.forEach((key) => {
checkedKeys[key] = true;
});
this._setCheckedKeys(key, leafOnly, checkedKeys);
}
setDefaultExpandedKeys(keys) {
keys = keys || [];
this.defaultExpandedKeys = keys;
keys.forEach((key) => {
const node = this.getNode(key);
if (node) node.expand(null, this.autoExpandParent);
});
}
setChecked(data, checked, deep) {
const node = this.getNode(data);
if (node) {
node.setChecked(!!checked, deep);
}
}
getCurrentNode() {
return this.currentNode;
}
setCurrentNode(currentNode) {
const prevCurrentNode = this.currentNode;
if (prevCurrentNode) {
prevCurrentNode.isCurrent = false;
}
this.currentNode = currentNode;
this.currentNode.isCurrent = true;
}
setUserCurrentNode(node) {
const key = node[this.key];
const currNode = this.nodesMap[key];
this.setCurrentNode(currNode);
}
setCurrentNodeKey(key) {
if (key === null || key === undefined) {
this.currentNode && (this.currentNode.isCurrent = false);
this.currentNode = null;
return;
}
const node = this.getNode(key);
if (node) {
this.setCurrentNode(node);
}
}
};

@ -0,0 +1,27 @@
export const NODE_KEY = '$treeNodeId';
export const markNodeData = function(node, data) {
if (!data || data[NODE_KEY]) return;
Object.defineProperty(data, NODE_KEY, {
value: node.id,
enumerable: false,
configurable: false,
writable: false
});
};
export const getNodeKey = function(key, data) {
if (!key) return data[NODE_KEY];
return data[key];
};
export const findNearestComponent = (element, componentName) => {
let target = element;
while (target && target.tagName !== 'BODY') {
if (target.__vue__ && target.__vue__.$options.name === componentName) {
return target.__vue__;
}
target = target.parentNode;
}
return null;
};

@ -0,0 +1,279 @@
<template>
<div
class="el-tree-node"
@click.stop="handleClick"
@contextmenu="($event) => this.handleContextMenu($event)"
v-show="node.visible"
:class="{
'is-expanded': expanded,
'is-current': node.isCurrent,
'is-hidden': !node.visible,
'is-focusable': !node.disabled,
'is-checked': !node.disabled && node.checked
}"
role="treeitem"
tabindex="-1"
:aria-expanded="expanded"
:aria-disabled="node.disabled"
:aria-checked="node.checked"
:draggable="tree.draggable"
@dragstart.stop="handleDragStart"
@dragover.stop="handleDragOver"
@dragend.stop="handleDragEnd"
@drop.stop="handleDrop"
ref="node"
>
<div class="el-tree-node__content"
:style="{ 'padding-left': (node.level - 1) * tree.indent + 'px' }">
<span
@click.stop="handleExpandIconClick"
:class="[
{ 'is-leaf': node.isLeaf, expanded: !node.isLeaf && expanded },
'el-tree-node__expand-icon',
tree.iconClass ? tree.iconClass : 'el-icon-caret-right'
]"
>
</span>
<el-checkbox
v-if="showCheckbox"
v-model="node.checked"
:indeterminate="node.indeterminate"
:disabled="!!node.disabled"
@click.native.stop
@change="handleCheckChange"
>
</el-checkbox>
<span
v-if="node.loading"
class="el-tree-node__loading-icon el-icon-loading">
</span>
<node-content :node="node"></node-content>
</div>
<el-collapse-transition>
<div
class="el-tree-node__children"
v-if="!renderAfterExpand || childNodeRendered"
v-show="expanded"
role="group"
:aria-expanded="expanded"
>
<el-tree-node
:render-content="renderContent"
v-for="child in node.childNodes"
:render-after-expand="renderAfterExpand"
:show-checkbox="showCheckbox"
:key="getNodeKey(child)"
:node="child"
@node-expand="handleChildNodeExpand">
</el-tree-node>
</div>
</el-collapse-transition>
</div>
</template>
<script type="text/jsx">
import ElCollapseTransition from 'element-ui/src/transitions/collapse-transition';
import ElCheckbox from 'element-ui/packages/checkbox';
import emitter from 'element-ui/src/mixins/emitter';
import { getNodeKey } from './model/util';
export default {
name: 'ElTreeNode',
componentName: 'ElTreeNode',
mixins: [emitter],
props: {
node: {
default() {
return {};
}
},
props: {},
renderContent: Function,
renderAfterExpand: {
type: Boolean,
default: true
},
showCheckbox: {
type: Boolean,
default: false
}
},
components: {
ElCollapseTransition,
ElCheckbox,
NodeContent: {
props: {
node: {
required: true
}
},
render(h) {
const parent = this.$parent;
const tree = parent.tree;
const node = this.node;
const { data, store } = node;
return (
parent.renderContent
? parent.renderContent.call(parent._renderProxy, h, { _self: tree.$vnode.context, node, data, store })
: tree.$scopedSlots.default
? tree.$scopedSlots.default({ node, data })
: <span class="el-tree-node__label">{ node.label }</span>
);
}
}
},
data() {
return {
tree: null,
expanded: false,
childNodeRendered: false,
oldChecked: null,
oldIndeterminate: null
};
},
watch: {
'node.indeterminate'(val) {
this.handleSelectChange(this.node.checked, val);
},
'node.checked'(val) {
this.handleSelectChange(val, this.node.indeterminate);
},
'node.expanded'(val) {
this.$nextTick(() => this.expanded = val);
if (val) {
this.childNodeRendered = true;
}
}
},
methods: {
getNodeKey(node) {
return getNodeKey(this.tree.nodeKey, node.data);
},
handleSelectChange(checked, indeterminate) {
if (this.oldChecked !== checked && this.oldIndeterminate !== indeterminate) {
this.tree.$emit('check-change', this.node.data, checked, indeterminate);
}
this.oldChecked = checked;
this.indeterminate = indeterminate;
},
handleClick() {
const store = this.tree.store;
store.setCurrentNode(this.node);
this.tree.$emit('current-change', store.currentNode ? store.currentNode.data : null, store.currentNode);
this.tree.currentNode = this;
if (this.tree.expandOnClickNode) {
this.handleExpandIconClick();
}
if (this.tree.checkOnClickNode && !this.node.disabled) {
this.handleCheckChange(null, {
target: { checked: !this.node.checked }
});
}
this.tree.$emit('node-click', this.node.data, this.node, this);
},
handleContextMenu(event) {
if (this.tree._events['node-contextmenu'] && this.tree._events['node-contextmenu'].length > 0) {
event.stopPropagation();
event.preventDefault();
}
this.tree.$emit('node-contextmenu', event, this.node.data, this.node, this);
},
handleExpandIconClick() {
if (this.node.isLeaf) return;
if (this.expanded) {
this.tree.$emit('node-collapse', this.node.data, this.node, this);
this.node.collapse();
} else {
this.node.expand();
this.$emit('node-expand', this.node.data, this.node, this);
}
},
handleCheckChange(value, ev) {
this.node.setChecked(ev.target.checked, !this.tree.checkStrictly);
this.$nextTick(() => {
const store = this.tree.store;
this.tree.$emit('check', this.node.data, {
checkedNodes: store.getCheckedNodes(),
checkedKeys: store.getCheckedKeys(),
halfCheckedNodes: store.getHalfCheckedNodes(),
halfCheckedKeys: store.getHalfCheckedKeys(),
});
});
},
handleChildNodeExpand(nodeData, node, instance) {
this.broadcast('ElTreeNode', 'tree-node-expand', node);
this.tree.$emit('node-expand', nodeData, node, instance);
},
handleDragStart(event) {
if (!this.tree.draggable) return;
this.tree.$emit('tree-node-drag-start', event, this);
},
handleDragOver(event) {
if (!this.tree.draggable) return;
this.tree.$emit('tree-node-drag-over', event, this);
event.preventDefault();
},
handleDrop(event) {
event.preventDefault();
},
handleDragEnd(event) {
if (!this.tree.draggable) return;
this.tree.$emit('tree-node-drag-end', event, this);
}
},
created() {
const parent = this.$parent;
if (parent.isTree) {
this.tree = parent;
} else {
this.tree = parent.tree;
}
const tree = this.tree;
if (!tree) {
console.warn('Can not find node\'s tree.');
}
const props = tree.props || {};
const childrenKey = props['children'] || 'children';
this.$watch(`node.data.${childrenKey}`, () => {
this.node.updateChildren();
});
if (this.node.expanded) {
this.expanded = true;
this.childNodeRendered = true;
}
if(this.tree.accordion) {
this.$on('tree-node-expand', node => {
if(this.node !== node) {
this.node.collapse();
}
});
}
}
};
</script>

@ -0,0 +1,496 @@
<template>
<div
class="el-tree"
:class="{
'el-tree--highlight-current': highlightCurrent,
'is-dragging': !!dragState.draggingNode,
'is-drop-not-allow': !dragState.allowDrop,
'is-drop-inner': dragState.dropType === 'inner'
}"
role="tree"
>
<el-tree-node
v-for="child in root.childNodes"
:node="child"
:props="props"
:render-after-expand="renderAfterExpand"
:show-checkbox="showCheckbox"
:key="getNodeKey(child)"
:render-content="renderContent"
@node-expand="handleNodeExpand">
</el-tree-node>
<div class="el-tree__empty-block" v-if="isEmpty">
<span class="el-tree__empty-text">{{ emptyText }}</span>
</div>
<div
v-show="dragState.showDropIndicator"
class="el-tree__drop-indicator"
ref="dropIndicator">
</div>
</div>
</template>
<script>
import TreeStore from './model/tree-store';
import { getNodeKey, findNearestComponent } from './model/util';
import ElTreeNode from './tree-node.vue';
import {t} from 'element-ui/src/locale';
import emitter from 'element-ui/src/mixins/emitter';
import { addClass, removeClass } from 'element-ui/src/utils/dom';
export default {
name: 'ElTree',
mixins: [emitter],
components: {
ElTreeNode
},
data() {
return {
store: null,
root: null,
currentNode: null,
treeItems: null,
checkboxItems: [],
dragState: {
showDropIndicator: false,
draggingNode: null,
dropNode: null,
allowDrop: true
}
};
},
props: {
data: {
type: Array
},
emptyText: {
type: String,
default() {
return t('el.tree.emptyText');
}
},
renderAfterExpand: {
type: Boolean,
default: true
},
nodeKey: String,
checkStrictly: Boolean,
defaultExpandAll: Boolean,
expandOnClickNode: {
type: Boolean,
default: true
},
checkOnClickNode: Boolean,
checkDescendants: {
type: Boolean,
default: false
},
autoExpandParent: {
type: Boolean,
default: true
},
defaultCheckedKeys: Array,
defaultExpandedKeys: Array,
currentNodeKey: [String, Number],
renderContent: Function,
showCheckbox: {
type: Boolean,
default: false
},
draggable: {
type: Boolean,
default: false
},
allowDrag: Function,
allowDrop: Function,
props: {
default() {
return {
children: 'children',
label: 'label',
disabled: 'disabled'
};
}
},
lazy: {
type: Boolean,
default: false
},
highlightCurrent: Boolean,
load: Function,
filterNodeMethod: Function,
accordion: Boolean,
indent: {
type: Number,
default: 18
},
iconClass: String
},
computed: {
children: {
set(value) {
this.data = value;
},
get() {
return this.data;
}
},
treeItemArray() {
return Array.prototype.slice.call(this.treeItems);
},
isEmpty() {
const { childNodes } = this.root;
return !childNodes || childNodes.length === 0 || childNodes.every(({visible}) => !visible);
}
},
watch: {
defaultCheckedKeys(newVal) {
this.store.setDefaultCheckedKey(newVal);
},
defaultExpandedKeys(newVal) {
this.store.defaultExpandedKeys = newVal;
this.store.setDefaultExpandedKeys(newVal);
},
data(newVal) {
this.store.setData(newVal);
},
checkboxItems(val) {
Array.prototype.forEach.call(val, (checkbox) => {
checkbox.setAttribute('tabindex', -1);
});
},
checkStrictly(newVal) {
this.store.checkStrictly = newVal;
}
},
methods: {
filter(value) {
if (!this.filterNodeMethod) throw new Error('[Tree] filterNodeMethod is required when filter');
this.store.filter(value);
},
getNodeKey(node) {
return getNodeKey(this.nodeKey, node.data);
},
getNodePath(data) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in getNodePath');
const node = this.store.getNode(data);
if (!node) return [];
const path = [node.data];
let parent = node.parent;
while (parent && parent !== this.root) {
path.push(parent.data);
parent = parent.parent;
}
return path.reverse();
},
getCheckedNodes(leafOnly, includeHalfChecked) {
return this.store.getCheckedNodes(leafOnly, includeHalfChecked);
},
getCheckedKeys(leafOnly) {
return this.store.getCheckedKeys(leafOnly);
},
getCurrentNode() {
const currentNode = this.store.getCurrentNode();
return currentNode ? currentNode.data : null;
},
getCurrentKey() {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in getCurrentKey');
const currentNode = this.getCurrentNode();
return currentNode ? currentNode[this.nodeKey] : null;
},
setCheckedNodes(nodes, leafOnly) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCheckedNodes');
this.store.setCheckedNodes(nodes, leafOnly);
},
setCheckedKeys(keys, leafOnly) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCheckedKeys');
this.store.setCheckedKeys(keys, leafOnly);
},
setChecked(data, checked, deep) {
this.store.setChecked(data, checked, deep);
},
getHalfCheckedNodes() {
return this.store.getHalfCheckedNodes();
},
getHalfCheckedKeys() {
return this.store.getHalfCheckedKeys();
},
setCurrentNode(node) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentNode');
this.store.setUserCurrentNode(node);
},
setCurrentKey(key) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentKey');
this.store.setCurrentNodeKey(key);
},
getNode(data) {
return this.store.getNode(data);
},
remove(data) {
this.store.remove(data);
},
append(data, parentNode) {
this.store.append(data, parentNode);
},
insertBefore(data, refNode) {
this.store.insertBefore(data, refNode);
},
insertAfter(data, refNode) {
this.store.insertAfter(data, refNode);
},
handleNodeExpand(nodeData, node, instance) {
this.broadcast('ElTreeNode', 'tree-node-expand', node);
this.$emit('node-expand', nodeData, node, instance);
},
updateKeyChildren(key, data) {
if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in updateKeyChild');
this.store.updateChildren(key, data);
},
initTabIndex() {
this.treeItems = this.$el.querySelectorAll('.is-focusable[role=treeitem]');
this.checkboxItems = this.$el.querySelectorAll('input[type=checkbox]');
const checkedItem = this.$el.querySelectorAll('.is-checked[role=treeitem]');
if (checkedItem.length) {
checkedItem[0].setAttribute('tabindex', 0);
return;
}
this.treeItems[0] && this.treeItems[0].setAttribute('tabindex', 0);
},
handleKeydown(ev) {
const currentItem = ev.target;
if (currentItem.className.indexOf('el-tree-node') === -1) return;
const keyCode = ev.keyCode;
this.treeItems = this.$el.querySelectorAll('.is-focusable[role=treeitem]');
const currentIndex = this.treeItemArray.indexOf(currentItem);
let nextIndex;
if ([38, 40].indexOf(keyCode) > -1) { // updown
ev.preventDefault();
if (keyCode === 38) { // up
nextIndex = currentIndex !== 0 ? currentIndex - 1 : 0;
} else {
nextIndex = (currentIndex < this.treeItemArray.length - 1) ? currentIndex + 1 : 0;
}
this.treeItemArray[nextIndex].focus(); //
}
if ([37, 39].indexOf(keyCode) > -1) { // leftright
ev.preventDefault();
currentItem.click(); //
}
const hasInput = currentItem.querySelector('[type="checkbox"]');
if ([13, 32].indexOf(keyCode) > -1 && hasInput) { // space entercheckbox
ev.preventDefault();
hasInput.click();
}
}
},
created() {
this.isTree = true;
this.store = new TreeStore({
key: this.nodeKey,
data: this.data,
lazy: this.lazy,
props: this.props,
load: this.load,
currentNodeKey: this.currentNodeKey,
checkStrictly: this.checkStrictly,
checkDescendants: this.checkDescendants,
defaultCheckedKeys: this.defaultCheckedKeys,
defaultExpandedKeys: this.defaultExpandedKeys,
autoExpandParent: this.autoExpandParent,
defaultExpandAll: this.defaultExpandAll,
filterNodeMethod: this.filterNodeMethod
});
this.root = this.store.root;
let dragState = this.dragState;
this.$on('tree-node-drag-start', (event, treeNode) => {
if (typeof this.allowDrag === 'function' && !this.allowDrag(treeNode.node)) {
event.preventDefault();
return false;
}
event.dataTransfer.effectAllowed = 'move';
// wrap in try catch to address IE's error when first param is 'text/plain'
try {
// setData is required for draggable to work in FireFox
// the content has to be '' so dragging a node out of the tree won't open a new tab in FireFox
event.dataTransfer.setData('text/plain', '');
} catch (e) {}
dragState.draggingNode = treeNode;
this.$emit('node-drag-start', treeNode.node, event);
});
this.$on('tree-node-drag-over', (event, treeNode) => {
const dropNode = findNearestComponent(event.target, 'ElTreeNode');
const oldDropNode = dragState.dropNode;
if (oldDropNode && oldDropNode !== dropNode) {
removeClass(oldDropNode.$el, 'is-drop-inner');
}
const draggingNode = dragState.draggingNode;
if (!draggingNode || !dropNode) return;
let dropPrev = true;
let dropInner = true;
let dropNext = true;
let userAllowDropInner = true;
if (typeof this.allowDrop === 'function') {
dropPrev = this.allowDrop(draggingNode.node, dropNode.node, 'prev');
userAllowDropInner = dropInner = this.allowDrop(draggingNode.node, dropNode.node, 'inner');
dropNext = this.allowDrop(draggingNode.node, dropNode.node, 'next');
}
event.dataTransfer.dropEffect = dropInner ? 'move' : 'none';
if ((dropPrev || dropInner || dropNext) && oldDropNode !== dropNode) {
if (oldDropNode) {
this.$emit('node-drag-leave', draggingNode.node, oldDropNode.node, event);
}
this.$emit('node-drag-enter', draggingNode.node, dropNode.node, event);
}
if (dropPrev || dropInner || dropNext) {
dragState.dropNode = dropNode;
}
if (dropNode.node.nextSibling === draggingNode.node) {
dropNext = false;
}
if (dropNode.node.previousSibling === draggingNode.node) {
dropPrev = false;
}
if (dropNode.node.contains(draggingNode.node, false)) {
dropInner = false;
}
if (draggingNode.node === dropNode.node || draggingNode.node.contains(dropNode.node)) {
dropPrev = false;
dropInner = false;
dropNext = false;
}
const targetPosition = dropNode.$el.getBoundingClientRect();
const treePosition = this.$el.getBoundingClientRect();
let dropType;
const prevPercent = dropPrev ? (dropInner ? 0.25 : (dropNext ? 0.45 : 1)) : -1;
const nextPercent = dropNext ? (dropInner ? 0.75 : (dropPrev ? 0.55 : 0)) : 1;
let indicatorTop = -9999;
const distance = event.clientY - targetPosition.top;
if (distance < targetPosition.height * prevPercent) {
dropType = 'before';
} else if (distance > targetPosition.height * nextPercent) {
dropType = 'after';
} else if (dropInner) {
dropType = 'inner';
} else {
dropType = 'none';
}
const iconPosition = dropNode.$el.querySelector('.el-tree-node__expand-icon').getBoundingClientRect();
const dropIndicator = this.$refs.dropIndicator;
if (dropType === 'before') {
indicatorTop = iconPosition.top - treePosition.top;
} else if (dropType === 'after') {
indicatorTop = iconPosition.bottom - treePosition.top;
}
dropIndicator.style.top = indicatorTop + 'px';
dropIndicator.style.left = (iconPosition.right - treePosition.left) + 'px';
if (dropType === 'inner') {
addClass(dropNode.$el, 'is-drop-inner');
} else {
removeClass(dropNode.$el, 'is-drop-inner');
}
dragState.showDropIndicator = dropType === 'before' || dropType === 'after';
dragState.allowDrop = dragState.showDropIndicator || userAllowDropInner;
dragState.dropType = dropType;
this.$emit('node-drag-over', draggingNode.node, dropNode.node, event);
});
this.$on('tree-node-drag-end', (event) => {
const { draggingNode, dropType, dropNode } = dragState;
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
if (draggingNode && dropNode) {
const draggingNodeCopy = { data: draggingNode.node.data };
if (dropType !== 'none') {
draggingNode.node.remove();
}
if (dropType === 'before') {
dropNode.node.parent.insertBefore(draggingNodeCopy, dropNode.node);
} else if (dropType === 'after') {
dropNode.node.parent.insertAfter(draggingNodeCopy, dropNode.node);
} else if (dropType === 'inner') {
dropNode.node.insertChild(draggingNodeCopy);
}
if (dropType !== 'none') {
this.store.registerNode(draggingNodeCopy);
}
removeClass(dropNode.$el, 'is-drop-inner');
this.$emit('node-drag-end', draggingNode.node, dropNode.node, dropType, event);
if (dropType !== 'none') {
this.$emit('node-drop', draggingNode.node, dropNode.node, dropType, event);
}
}
if (draggingNode && !dropNode) {
this.$emit('node-drag-end', draggingNode.node, null, dropType, event);
}
dragState.showDropIndicator = false;
dragState.draggingNode = null;
dragState.dropNode = null;
dragState.allowDrop = true;
});
},
mounted() {
this.initTabIndex();
this.$el.addEventListener('keydown', this.handleKeydown);
},
updated() {
this.treeItems = this.$el.querySelectorAll('[role=treeitem]');
this.checkboxItems = this.$el.querySelectorAll('input[type=checkbox]');
}
};
</script>

@ -57,6 +57,11 @@ let router = new Router({
component: () => import( '../views/serve/Configure.vue'),
// meta: { title: '服务配置' }
},
{
path: '/backstage',
component: () => import( '../views/serve/backstage'),
// meta: { title: '服务配置' }
},
{
path: '/addconfigure',
component: () => import( '../views/serve/AddConfigure.vue'),

@ -13,9 +13,8 @@ if (isDev) {
// jumpPath = "http://39.108.250.202/judgmentPoint/";
jumpPath = "http://192.168.31.125:8087/"; // 本地调试-需要启动本地判分点系统
// host = "http://www.huorantech.cn:9000";//线上
host = "http://39.108.250.202:9000";//测试
// host = 'http://192.168.31.151:9000'// 榕
// host = 'http://192.168.31.125:9000'// 坤
// host = "http://39.108.250.202:9000";//测试
host = 'http://192.168.31.151:9000'// 榕
// host = 'http://192.168.31.137:9000'// 赓
} else if (isTest) {
// jumpPath = "http://124.71.12.62/judgmentPoint/";

@ -98,6 +98,11 @@ export default {
addProjectJudgment: `${host}/occupationlab/projectJudgment/addProjectJudgment`, // 添加项目管理、判分点中间表
updateProjectJudgment: `${host}/occupationlab/projectJudgment/updateProjectJudgment`, // 判分点中间表批量更新
deleteProjectJudgment: `${host}/occupationlab/projectJudgment/deleteProjectJudgment`, // 判分点中间表批量删除
// 系统后台
deleteSourceModelCategory: `${host}/nakadai/model/category/deleteSourceModelCategory`,
categorySave: `${host}/nakadai/model/category/save`,
sourceModelClassification: `${host}/nakadai/model/category/sourceModelClassification`,
// 课程管理三级联查
courseDiscipline: `${host}/nakadai/nakadai/subject/courseDiscipline`, //课程学科类别

@ -68,6 +68,11 @@
{{ systemStatusKeys[scope.row.state] }}
</template>
</el-table-column>
<el-table-column prop="payamount" label="系统后台" align="center">
<template slot-scope="scope">
<el-button type="text" @click="toBackstage(scope.row)">进入</el-button>
</template>
</el-table-column>
<el-table-column prop="payamount" label="项目系统" align="center">
<template slot-scope="scope">
<el-button type="text" @click="getIntoProject(scope.row)">进入</el-button>
@ -184,8 +189,11 @@ export default {
this.$store.commit("configData", { config_id: row.systemId });
this.$router.push("/addconfigure");
},
//
toBackstage(row) {
this.$router.push(`/backstage?systemId=${row.systemId}&show=1&name=${row.systemName}`)
},
getIntoProject(row) {
// console.log()
this.$router.push(`/projectList?systemId=${row.systemId}&show=1&name=${row.systemName}`)
},
getIntoJudgement(row) {

@ -0,0 +1,81 @@
<template>
<div class="page" style="padding: 0">
<div class="tabs">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{ item }}</a>
</div>
<model v-if="active == 'model'"></model>
<sourceModel v-if="active == 'sourceModel'"></sourceModel>
</div>
</template>
<script>
import model from "./model";
import sourceModel from "./sourceModel";
export default {
data() {
return {
active: "model",
tabs: {
model: "模型列表管理",
sourceModel: "源模型管理"
}
};
},
computed: {
},
components: {
model,
sourceModel
},
created() {},
methods: {
tabChange(index) {
this.active = index;
}
}
};
</script>
<style lang="scss" scoped>
.tabs {
display: flex;
align-items: center;
padding: 0 24px;
border-bottom: 1px solid rgba(0, 0, 0, .06);
.item {
position: relative;
padding: 20px 0;
margin-right: 40px;
font-size: 16px;
color: rgba(0, 0, 0, 0.65);
cursor: pointer;
&:after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
border-bottom: 3px solid transparent;
border-radius: 2px;
}
&.active {
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
&.active:after {
border-bottom-color: #9278ff;
}
}
}
.page {
background-color: #fff;
border-radius: 8px;
}
</style>

@ -0,0 +1,613 @@
<template>
<div class="wrap">
<div class="side">
<org ref="org" @getSingle="getSingle" @getCheck="getCheck"></org>
</div>
<div class="right">
<h6 class="p-title">筛选</h6>
<div class="tool">
<ul class="filter">
<li>
<el-input placeholder="请输入模型名称" prefix-icon="el-icon-search" v-model.trim="keyword" clearable></el-input>
</li>
</ul>
<div>
<el-button type="primary" round @click="addTeacher">导入模型</el-button>
<el-button type="primary" round @click="delAllSelection">批量移除</el-button>
</div>
</div>
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" label="序号" width="55" align="center"></el-table-column>
<el-table-column prop="userName" label="模型名称" align="center"></el-table-column>
<el-table-column prop="account" label="导入时间" align="center"></el-table-column>
<el-table-column prop="workNumber" label="状态" align="center"></el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showTeacher(scope.row)">查看</el-button>
<el-button type="text" @click="delTeacher(scope.row)">移除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :current-page="page" @current-change="handleCurrentChange" :total="total"></el-pagination>
</div>
</div>
<el-dialog :title="isDetail ? '查看员工' : (isAdd ? '新增员工' : '编辑员工')" :visible.sync="teacherVisible"
width="30%" @close="closeTeacher" class="dialog" :close-on-click-modal="false">
<el-form ref="teacherForm" :model="teacherForm" :rules="rules" label-width="150px" :disabled="isDetail" style='margin-right: 80px;'>
<el-form-item prop="account" label="账号">
<el-input v-model.trim="teacherForm.account" placeholder="请输入职工账号"></el-input>
</el-form-item>
<el-form-item prop="userName" label="用户姓名">
<el-input v-model.trim="teacherForm.userName" placeholder="请输入员工姓名"></el-input>
</el-form-item>
<el-form-item prop="roleValue" label="账号角色">
<el-select v-model="teacherForm.roleValue" @change="roleChange" @remove-tag="roleRemove" multiple style="width: 100%;height: 32px">
<el-option
v-for="item in roleList"
:key="item.id"
:label="item.roleName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="uniqueIdentification" label="唯一标识">
<el-input disabled v-model.trim="teacherForm.uniqueIdentification" placeholder="请输入职工工号获取唯一标识"></el-input>
</el-form-item>
<el-form-item prop="workNumber" label="工号">
<el-input v-model.trim="teacherForm.workNumber" placeholder="请输入职工工号"></el-input>
</el-form-item>
<el-form-item v-for="item in teacherForm.roleAndDeptList" :label="`${item.roleName}所属部门`" :rules="{
required: true, message: '请选择', trigger: 'change'
}">
<el-cascader
v-model="item.cascaderValue"
:options="orgList"
:props="casProps"
style="width: 100%"
></el-cascader>
</el-form-item>
<el-form-item prop="phone" label="手机号">
<el-input v-model.trim="teacherForm.phone" placeholder="请输入手机号" maxlength="11" @blur="phoneChange"></el-input>
</el-form-item>
<el-form-item prop="email" label="邮箱">
<el-input v-model.trim="teacherForm.email" placeholder="请输入邮箱" @blur="emailChange"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer" v-if="!isDetail">
<el-button @click="closeTeacher"> </el-button>
<el-button type="primary" @click="saveSure('teacherForm')"> </el-button>
</span>
</el-dialog>
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :close-on-click-modal="false">
<div style="text-align: center">
<div style="margin-bottom: 10px;">
<el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
</div>
<el-upload
name="file"
accept=".xls,.xlsx"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.importStaff"
:file-list="uploadList"
:headers="headers"
>
<el-button type="primary" class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">部分数据导入失败查看失败原因</el-link>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="importVisible = false"> </el-button>
<el-button type="primary" @click="uploadSure"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from "@/setting";
import org from "./modelType"
export default {
data() {
var accountPass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入账号'));
} else {
var pattern = /^[A-Za-z0-9]*$/;
if(pattern.test(value)){
this.accountChange();
callback();
}else{
callback(new Error('请输入正确账号格式'));
}
}
};
var workNumberPass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入职工工号'));
} else {
var pattern = /^[a-zA-Z0-9]*$/;
if(pattern.test(value)){
this.workNumberChange();
callback();
}else{
callback(new Error('职工工号必须为数字或英文'));
}
}
};
return {
exportCode: "",
headers: {
// token: util.local.get(Setting.tokenKey)
},
isDetail: false,
isAdd: false,
teacherVisible: false,
roleList: [], //
orgList: [], //
casProps: {
value: 'id'
},
teacherForm: {
accountId: "",
account: "",
userName: "",
roleValue: [],
roleAndDeptList: [],
uniqueIdentification: "",
workNumber: "",
phone: "",
email: ""
},
rules: {
account: [
{ required: true, validator: accountPass, trigger: 'blur' }
],
userName: [
{ required: true, message: "请输入用户姓名", trigger: "blur" }
],
roleValue: [
{ required: true, message: "请选择账号角色", trigger: "change" }
],
workNumber: [
{ required: true, validator: workNumberPass , trigger: 'blur' }
],
uniqueIdentification: [
// { required: true, message: '', trigger: 'blur' },
],
phone: [
// { required: true, message: '', trigger: 'blur' },
{ pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号", trigger: "blur"}
],
email: [
// { required: true, message: '', trigger: 'blur' },
{
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/,
message: "请输入正确的邮箱",
trigger: "blur"
}
],
},
accountReapeat: false,
workNumberReapeat: false,
phoneRepeat: false,
emailRepeat: false,
listData: [], //
keyword: "",
page: 1,
pageSize: 10,
total: 0,
multipleSelection: [], //
importVisible: false, //
uploadList: [], //
uploadFaild: false, //
gradeId: "", // ID
staffArchitectureId: "", // ID
submiting: false //
};
},
components: {
org
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
// this.getRoleData()
// this.getData()
},
methods: {
getSingle(data) {
this.staffArchitectureId = data.gradeId ? '' : data.staffArchitectureId
this.gradeId = data.gradeId || ''
this.initData()
},
getCheck(data) {
const marjorIds = []
const depIds = []
data.forEach(e => {
e.gradeId ? depIds.push(e.gradeId) : marjorIds.push(e.staffArchitectureId)
});
this.staffArchitectureId = marjorIds.toString()
this.gradeId = depIds.toString()
this.initData()
},
initData() {
this.$refs.table.clearSelection()
this.page = 1
this.getData()
},
getData() { //
let data = {
keyWord: this.keyword,
pageNum: this.page,
pageSize: this.pageSize,
staffArchitectureId: this.staffArchitectureId,
gradeId: this.gradeId
};
this.$post(this.api.staffList, data).then(res => {
this.listData = res.page.records;
this.total = res.page.total;
}).catch(res => {});
},
getRoleData() { //
this.roleList =[];
this.$get(`${this.api.roleList}?page=1&size=100&name=&platformId=1`).then(res => {
for(var i=0;i<res.rolePage.records.length;i++){
if (res.rolePage.records[i].roleName == '超级管理员'){
}else{
this.roleList.push(res.rolePage.records[i])
}
}
// this.roleList = res.rolePage.records;
}).catch(res => {});
},
closeTeacher() { // /
this.teacherForm = {
accountId: "",
account: "",
userName: "",
roleValue: [],
roleAndDeptList: [],
uniqueIdentification: "",
workNumber: "",
phone: "",
email: ""
};
this.$refs.teacherForm.clearValidate();
this.teacherVisible = false;
},
addTeacher() { //
this.isDetail = false;
this.isAdd = true;
this.teacherVisible = true;
this.orgList = this.$refs.org.orgList;
},
getStaffDetail(accountId) { //
this.$get(`${this.api.staffDetail}?accountId=${accountId}`).then(res => {
let { data } = res;
this.teacherForm = data;
this.teacherForm.roleValue = data.roleAndDeptList.map(i => i.roleId);
this.teacherForm.roleAndDeptList = data.roleAndDeptList.map(i => {
i.cascaderValue = [i.staffArchitectureId, i.gradeId]
return i;
});
console.log(22, this.teacherForm)
}).catch(res => {});
},
resetPassword(row) { //
this.$confirm(`重置后的密码为:${Setting.initialPassword},确定重置?`, "提示", { type: "warning" }).then(() => {
this.$get(`${this.api.resetPassword}?userId=${row.userId}&newPwd=111aaa`).then(res => {
this.$message.success("重置成功");
}).catch(res => {
});
}).catch(() => {
});
},
editTeacher(row) { //
this.isDetail = false;
this.isAdd = false;
this.teacherVisible = true;
this.orgList = this.$refs.org.orgList;
this.getStaffDetail(row.accountId);
},
showTeacher(row) { //
this.isDetail = true;
this.isAdd = false;
this.teacherVisible = true;
this.orgList = this.$refs.org.orgList;
this.getStaffDetail(row.accountId);
},
accountChange() { //
if (this.teacherForm.account) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&account=${this.teacherForm.account}&workNumber=`;
} else {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&accountId=${this.teacherForm.accountId}&account=${this.teacherForm.account}&workNumber=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.accountReapeat = false;
}
}).catch( err => {
this.accountReapeat = true;
});
}
},
workNumberChange() { //
if (this.teacherForm.workNumber) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&workNumber=${this.teacherForm.workNumber}&account=`;
} else {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&accountId=${this.teacherForm.accountId}&workNumber=${this.teacherForm.workNumber}&account=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.workNumberReapeat = false;
}
}).catch( err => {
this.workNumberReapeat = true;
});
}
},
phoneChange() { //
let regex = /^1[3456789]\d{9}$/;
if (regex.test(this.teacherForm.phone)) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkEmailOrPhone}?phone=${this.teacherForm.phone}&email=`;
} else {
url = `${this.api.checkEmailOrPhone}?accountId=${this.teacherForm.accountId}&phone=${this.teacherForm.phone}&email=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.phoneRepeat = false;
}
}).catch( err => {
this.phoneRepeat = true;
});
}
},
emailChange() { //
let regex = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
if (regex.test(this.teacherForm.email)) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkEmailOrPhone}?email=${this.teacherForm.email}&phone=`;
} else {
url = `${this.api.checkEmailOrPhone}?accountId=${this.teacherForm.accountId}&email=${this.teacherForm.email}&phone=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.emailRepeat = false;
}
}).catch( err => {
this.emailRepeat = true;
});
}
},
roleChange(value) { //
console.log(this.teacherForm.roleValue)
if (value.length) {
let ids = this.teacherForm.roleAndDeptList.map(e => e.roleId);
this.roleList.forEach(i => {
let obj = {
roleId: "",
roleName: "",
cascaderValue: []
};
if (value.includes(i.id) && !ids.includes(i.id)) {
console.log(i)
obj.roleId = i.id;
obj.roleName = i.roleName;
this.teacherForm.roleAndDeptList.push(obj);
}
});
} else {
this.teacherForm.roleAndDeptList.splice(0);
}
},
roleRemove(value) { //
let list = [];
for(var i=0;i<this.teacherForm.roleAndDeptList.length;i++){
if (this.teacherForm.roleAndDeptList[i].roleId == value){
}else{
list.push(this.teacherForm.roleAndDeptList[i])
}
}
this.teacherForm.roleAndDeptList = list
},
async saveSure(teacherForm) {
this.$refs[teacherForm].validate((valid) => {
if (valid) {
if (this.submiting) return false
if (this.accountReapeat) return this.$message.warning("该账号已存在");
if (this.workNumberReapeat) return this.$message.warning("该员工工号已存在");
if (this.phoneRepeat) return this.$message.warning("该手机号已存在");
if (this.emailRepeat) return this.$message.warning("该邮箱已存在");
let data = {
accountId: this.teacherForm.accountId,
account: this.teacherForm.account,
userName: this.teacherForm.userName,
roleAndDeptList: [],
uniqueIdentification: this.teacherForm.uniqueIdentification ? this.teacherForm.uniqueIdentification : new Date().getTime(),
workNumber: this.teacherForm.workNumber,
phone: this.teacherForm.phone,
email: this.teacherForm.email
};
if (this.teacherForm.roleAndDeptList.length){
for (let i = 0; i < this.teacherForm.roleAndDeptList.length; i++) {
if (this.teacherForm.roleAndDeptList[i].cascaderValue.length < 2) {
this.$message.warning(`请选择${this.teacherForm.roleAndDeptList[i].roleName}所属部门`)
return;
} else {
let obj = {
roleId: this.teacherForm.roleAndDeptList[i].roleId,
staffArchitectureId: this.teacherForm.roleAndDeptList[i].cascaderValue[0],
gradeId: this.teacherForm.roleAndDeptList[i].cascaderValue[1]
};
data.roleAndDeptList.push(obj);
}
}
}
this.submiting = true
if (this.teacherForm.accountId) {
this.$post(this.api.modifyStaff, data).then(res => {
this.$message.success("编辑成功");
this.closeTeacher();
this.getData();
this.submiting = false
}).catch(res => {
this.submiting = false
});
} else {
this.$post(this.api.saveStaff, data).then(res => {
this.$message.success("添加成功");
this.closeTeacher();
this.getData();
this.submiting = false
}).catch(res => {
this.submiting = false
});
}
} else {
return false;
}
});
},
delTeacher(row) {
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.delStaff}?accountIds=${row.accountId}`).then(res => {
this.$message.success("删除成功");
this.getData();
}).catch(res => {});
}).catch(() => {});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllSelection() {
if (this.multipleSelection.length) {
//
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
let ids = this.multipleSelection.map(item => {
return item.accountId;
});
this.$post(`${this.api.delStaff}?accountIds=${ids.toString()}`).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection();
this.$message.success("删除成功");
this.getData();
}).catch(res => {
});
}).catch(() => {
});
} else {
this.$message.error("请先选择员工 !");
}
},
batchImport() {
this.importVisible = true;
this.uploadList = [];
this.uploadFaild = false;
},
searchTeacher() {
this.page = 1;
this.getData();
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
downLoad() {
location.href = this.api.staffTemplate;
},
showFaild() {
location.href = `${this.api.exportFailureStaff}?exportCode=${this.exportCode}`;
},
//
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
console.log(res);
this.uploadFaild = false;
if (res.status === 200) {
if (res.data.exportCode) {
this.exportCode = res.data.exportCode;
this.uploadFaild = true;
}
this.$message.success(`上传成功${res.data.successNum},上传失败${res.data.failureNum}`);
} else {
res.message ? this.$message.error(res.message) : this.$message.error("上传失败,请检查数据");
}
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.uploadList = fileList;
this.uploadFaild = false;
},
uploadSure() {
this.importVisible = false;
this.page = 1;
this.keyword = "";
this.getData();
}
}
};
</script>
<style lang="scss" scoped>
.wrap {
display: flex;
padding: 0 24px;
.side {
width: 300px;
padding: 24px 10px 24px 0;
margin-right: 24px;
border-right: 1px solid rgba(0, 0, 0, 0.06);
}
.right {
width: calc(100% - 374px);
padding: 24px;
}
}
.el-input__inner{
height: 32px;
}
</style>

@ -0,0 +1,348 @@
<template>
<div>
<div>
<div class="flex-between m-b-20">
<div>同步原始模型列表</div>
<el-button type="text" @click="addMajor">添加</el-button>
</div>
<org-tree
:data="orgList"
show-checkbox
default-expand-all
ref="orgTree"
node-key="id"
highlight-current
:expand-on-click-node="false"
@node-click="getSingle"
@check="getCheck"
:props="{children: 'children', label: 'categoryName', isLeaf: 'leaf'}"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span style="display: inline-block; margin-right: 20px">{{ node.label }}</span>
<span>
<el-button
type="text"
icon="el-icon-edit-outline"
@click="() => handleEdit(node, data)">
</el-button>
<el-button
v-if="node.level === 1"
type="text"
icon="el-icon-circle-plus-outline"
@click="() => handleAdd(node, data)">
</el-button>
<el-button
type="text"
icon="el-icon-delete"
@click="() => handleDel(node, data)">
</el-button>
</span>
</span>
</org-tree>
</div>
<el-dialog :title="Form.id ? '编辑分类' : '新增分类'" :visible.sync="typeVisible" width="24%" center @close="closeAdd" :close-on-click-modal="false">
<el-form ref="Form" :model="Form" :rules="rules">
<el-form-item prop="staffArchitectureName">
<el-input placeholder="请输入分类名称" v-model="Form.staffArchitectureName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="typeVisible = false"> </el-button>
<el-button type="primary" @click="sure('Form')"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import OrgTree from "@/components/org-tree/src/tree";
export default {
props: ["Data"],
data() {
return {
orgList: [],
typeVisible: false,
depVisible: false,
Form: {
parentId: '',
categoryName: ''
},
rules: {
categoryName: [
{ required: true, message: "请输入分类名称", trigger: "blur" }
]
}
};
},
components: {
OrgTree
},
mounted() {
// this.getStaff()
},
methods: {
getStaff() {
this.$post(this.api.sourceModelClassification).then(res => {
this.orgList = res.data
}).catch(res => {})
},
closeAdd() {
this.$refs.Form.resetFields()
},
getSingle(data) {
this.$emit('getSingle', data)
},
getCheck(data, checked) {
this.$emit('getCheck', checked.checkedNodes)
},
//
addMajor() {
this.Form.staffArchitectureId = ''
this.Form.staffArchitectureName = ''
this.typeVisible = true
},
sure(Form) { // /
this.$refs[Form].validate((valid) => {
if (valid) {
let data = {
staffArchitectureName: this.Form.staffArchitectureName,
staffArchitectureId: this.Form.staffArchitectureId,
isDel: 0 // (0 1)
};
if (this.Form.staffArchitectureId) {
this.$post(this.api.updateProfessional, data).then(res => {
this.$message.success("编辑成功");
this.typeVisible = false;
this.orgList.map(e => {
if (e.staffArchitectureId == this.Form.staffArchitectureId) {
e.staffArchitectureName = this.Form.staffArchitectureName;
e.label = this.Form.staffArchitectureName;
}
});
this.$emit("getData");
}).catch(res => {
});
} else {
this.$post(this.api.saveProfessional, data).then(res => {
this.$message.success("添加成功");
this.typeVisible = false;
let newData = {
staffArchitectureId: res.staffArchitectureId,
staffArchitectureName: this.Form.staffArchitectureName,
label: this.Form.staffArchitectureName,
value: res.staffArchitectureId,
ifVisible: false,
ischeck: false,
children: []
};
this.orgList.push(newData);
}).catch(res => {
});
}
} else {
return false;
}
});
},
handleAdd(node, data) { //
this.typeVisible = true
this.Form.parentId = data.id
},
handleEdit(node, data) { //
if (node.level === 1) {
this.Form.staffArchitectureId = data.staffArchitectureId
this.Form.staffArchitectureName = data.staffArchitectureName
this.typeVisible = true
} else {
this.Form.gradeId = data.gradeId
this.Form.gradeName = data.gradeName
this.depVisible = true
}
for (let j = 0; j < this.orgList.length; j++) {
for (let k = 0; k < this.orgList[j].children.length; k++) {
if (this.orgList[j].children[k].gradeName == data.gradeName) {
this.Form.staffArchitectureId = this.orgList[j].staffArchitectureId;
}
}
}
},
sureDepartment(Form) { //
this.$refs[Form].validate((valid) => {
if (valid) {
let data = {
gradeId: this.Form.gradeId,
gradeName: this.Form.gradeName,
staffArchitectureId: this.Form.staffArchitectureId
};
if (this.Form.gradeId) {
this.$post(this.api.updateGrade, data).then(res => {
this.$message.success("编辑成功");
this.depVisible = false;
this.orgList.map(e => {
e.children.map(r => {
if (r.gradeId == this.Form.gradeId) {
r.gradeName = this.Form.gradeName;
r.label = this.Form.gradeName;
}
});
});
}).catch(res => {
});
} else {
this.$post(this.api.saveGrade, data).then(res => {
this.$message.success("添加成功");
this.depVisible = false;
let newData = {
gradeId: res.gradeId,
gradeName: this.Form.gradeName,
label: this.Form.gradeName,
value: res.gradeId,
ifVisible: false,
ischeck: false
};
this.orgList.map(e => {
if (e.staffArchitectureId == this.Form.staffArchitectureId) {
e.ifVisible = true;
e.children.push(newData);
}
});
}).catch(res => {
});
}
} else {
return false;
}
});
},
handleDel(node, data) {
node.level === 1 ? this.delMajor(data) : this.delDepartment(data)
},
delMajor(item) {
this.$confirm("确定要删除该专业吗?该操作将会删除该组织下的用户账号。", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.deleteProfessional}?staffArchitectureId=${item.staffArchitectureId}`).then(res => {
this.$message.success("删除成功")
this.$emit("getData")
this.getStaff()
}).catch(res => {})
}).catch(() => {})
},
delDepartment(item) {
this.$confirm("确定要删除该分类吗?该操作将会删除该组织下的用户账号。", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.deleteGrade}?gradeId=${item.gradeId}`).then(res => {
this.$message.success("删除成功")
this.getStaff()
this.$emit("delDep", item, this.orgList)
this.$emit("getData")
}).catch(res => {})
}).catch(() => {})
}
}
};
</script>
<style scoped>
.side_view {
height: 800px;
padding: 40px 20px;
background-color: #fff;
}
.side_icon {
text-align: right;
}
.side_icon i {
cursor: pointer;
font-size: 20px;
color: #9278FF;
}
.side_tree {
width: 100%;
font-size: 14px;
color: #333;
}
.side_tree i {
color: #9278FF;
margin-left: 10px;
}
.fir_back {
width: 100%;
padding: 15px 0;
background: rgba(255, 255, 255, 1);
/* box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19); */
border-radius: 10px;
text-align: left;
}
.fir_back:first-child {
margin-top: 20px;
}
.fir_back:hover {
box-shadow: 1px 14px 29px 0px rgba(138, 97, 250, 0.19);
cursor: pointer;
}
.fir_back span {
margin-left: 10px;
}
.two_active {
color: #9278FF;
}
/* .two_active:hover{
color: #9278FF;
cursor:pointer;
} */
.two_back:hover {
cursor: pointer;
color: #9278FF;
}
.mar_top {
margin-top: 20px;
}
.back_active {
box-shadow: 1px 14px 29px 0px rgba(138, 97, 250, 0.19);
}
.bor_lef {
padding: 20px 0 0 0;
margin-left: 40px;
}
.three_lef {
margin-left: 60px;
padding: 20px 0;
}
.three_text {
font-size: 14px;
margin-top: 10px;
}
.teacher_tab {
margin-left: 20px;
}
.icon_select:before {
transform: rotate(180deg);
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(-30px);
}
</style>

@ -0,0 +1,630 @@
<template>
<div class="wrap">
<div class="side">
<org ref="org" @getSingle="getSingle" @getCheck="getCheck"></org>
</div>
<div class="right">
<h6 class="p-title">筛选</h6>
<div class="tool">
<ul class="filter">
<li>
<el-input placeholder="请输入模型名称" prefix-icon="el-icon-search" v-model.trim="keyword" clearable></el-input>
</li>
</ul>
<div>
<el-button type="primary" round @click="addTeacher">新增</el-button>
<el-button type="primary" round @click="delAllSelection">批量删除</el-button>
<el-button type="primary" round @click="delAllSelection">批量禁用</el-button>
<el-button type="primary" round @click="delAllSelection">批量开启</el-button>
</div>
</div>
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" label="序号" width="55" align="center"></el-table-column>
<el-table-column prop="userName" label="模型名称" align="center"></el-table-column>
<el-table-column prop="account" label="编辑人" align="center"></el-table-column>
<el-table-column prop="account" label="最新编辑时间" align="center"></el-table-column>
<el-table-column prop="workNumber" label="状态" align="center"></el-table-column>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showTeacher(scope.row)">查看</el-button>
<el-button type="text" @click="delTeacher(scope.row)">编辑</el-button>
<el-button type="text" @click="delTeacher(scope.row)">删除</el-button>
<el-switch v-model="scope.row.isEnable" :active-value="1" :inactive-value="0" style="margin: 0 10px 0 5px" :active-text="scope.row.isEnable ? '启用' : '禁用'" @change="switchOff($event,scope.row,scope.$index)"></el-switch>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total, prev, pager, next" :current-page="page" @current-change="handleCurrentChange" :total="total"></el-pagination>
</div>
</div>
<el-dialog :title="isDetail ? '查看员工' : (isAdd ? '新增员工' : '编辑员工')" :visible.sync="teacherVisible"
width="30%" @close="closeTeacher" class="dialog" :close-on-click-modal="false">
<el-form ref="teacherForm" :model="teacherForm" :rules="rules" label-width="150px" :disabled="isDetail" style='margin-right: 80px;'>
<el-form-item prop="account" label="账号">
<el-input v-model.trim="teacherForm.account" placeholder="请输入职工账号"></el-input>
</el-form-item>
<el-form-item prop="userName" label="用户姓名">
<el-input v-model.trim="teacherForm.userName" placeholder="请输入员工姓名"></el-input>
</el-form-item>
<el-form-item prop="roleValue" label="账号角色">
<el-select v-model="teacherForm.roleValue" @change="roleChange" @remove-tag="roleRemove" multiple style="width: 100%;height: 32px">
<el-option
v-for="item in roleList"
:key="item.id"
:label="item.roleName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="uniqueIdentification" label="唯一标识">
<el-input disabled v-model.trim="teacherForm.uniqueIdentification" placeholder="请输入职工工号获取唯一标识"></el-input>
</el-form-item>
<el-form-item prop="workNumber" label="工号">
<el-input v-model.trim="teacherForm.workNumber" placeholder="请输入职工工号"></el-input>
</el-form-item>
<el-form-item v-for="item in teacherForm.roleAndDeptList" :label="`${item.roleName}所属部门`" :rules="{
required: true, message: '请选择', trigger: 'change'
}">
<el-cascader
v-model="item.cascaderValue"
:options="orgList"
:props="casProps"
style="width: 100%"
></el-cascader>
</el-form-item>
<el-form-item prop="phone" label="手机号">
<el-input v-model.trim="teacherForm.phone" placeholder="请输入手机号" maxlength="11" @blur="phoneChange"></el-input>
</el-form-item>
<el-form-item prop="email" label="邮箱">
<el-input v-model.trim="teacherForm.email" placeholder="请输入邮箱" @blur="emailChange"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer" v-if="!isDetail">
<el-button @click="closeTeacher"> </el-button>
<el-button type="primary" @click="saveSure('teacherForm')"> </el-button>
</span>
</el-dialog>
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :close-on-click-modal="false">
<div style="text-align: center">
<div style="margin-bottom: 10px;">
<el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button>
</div>
<el-upload
name="file"
accept=".xls,.xlsx"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.importStaff"
:file-list="uploadList"
:headers="headers"
>
<el-button type="primary" class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">部分数据导入失败查看失败原因</el-link>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="importVisible = false"> </el-button>
<el-button type="primary" @click="uploadSure"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from "@/setting";
import org from "./sourceType"
export default {
data() {
var accountPass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入账号'));
} else {
var pattern = /^[A-Za-z0-9]*$/;
if(pattern.test(value)){
this.accountChange();
callback();
}else{
callback(new Error('请输入正确账号格式'));
}
}
};
var workNumberPass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入职工工号'));
} else {
var pattern = /^[a-zA-Z0-9]*$/;
if(pattern.test(value)){
this.workNumberChange();
callback();
}else{
callback(new Error('职工工号必须为数字或英文'));
}
}
};
return {
exportCode: "",
headers: {
// token: util.local.get(Setting.tokenKey)
},
isDetail: false,
isAdd: false,
teacherVisible: false,
roleList: [], //
orgList: [], //
casProps: {
value: 'id'
},
teacherForm: {
accountId: "",
account: "",
userName: "",
roleValue: [],
roleAndDeptList: [],
uniqueIdentification: "",
workNumber: "",
phone: "",
email: ""
},
rules: {
account: [
{ required: true, validator: accountPass, trigger: 'blur' }
],
userName: [
{ required: true, message: "请输入用户姓名", trigger: "blur" }
],
roleValue: [
{ required: true, message: "请选择账号角色", trigger: "change" }
],
workNumber: [
{ required: true, validator: workNumberPass , trigger: 'blur' }
],
uniqueIdentification: [
// { required: true, message: '', trigger: 'blur' },
],
phone: [
// { required: true, message: '', trigger: 'blur' },
{ pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号", trigger: "blur"}
],
email: [
// { required: true, message: '', trigger: 'blur' },
{
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/,
message: "请输入正确的邮箱",
trigger: "blur"
}
],
},
accountReapeat: false,
workNumberReapeat: false,
phoneRepeat: false,
emailRepeat: false,
listData: [], //
keyword: "",
page: 1,
pageSize: 10,
total: 0,
multipleSelection: [], //
importVisible: false, //
uploadList: [], //
uploadFaild: false, //
gradeId: "", // ID
staffArchitectureId: "", // ID
submiting: false //
};
},
components: {
org
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer);
this.searchTimer = setTimeout(() => {
this.initData();
}, 500);
}
},
mounted() {
// this.getRoleData()
// this.getData()
},
methods: {
getSingle(data) {
this.staffArchitectureId = data.gradeId ? '' : data.staffArchitectureId
this.gradeId = data.gradeId || ''
this.initData()
},
getCheck(data) {
const marjorIds = []
const depIds = []
data.forEach(e => {
e.gradeId ? depIds.push(e.gradeId) : marjorIds.push(e.staffArchitectureId)
});
this.staffArchitectureId = marjorIds.toString()
this.gradeId = depIds.toString()
this.initData()
},
initData() {
this.$refs.table.clearSelection()
this.page = 1
this.getData()
},
getData() { //
let data = {
keyWord: this.keyword,
pageNum: this.page,
pageSize: this.pageSize,
staffArchitectureId: this.staffArchitectureId,
gradeId: this.gradeId
};
this.$post(this.api.staffList, data).then(res => {
this.listData = res.page.records;
this.total = res.page.total;
}).catch(res => {});
},
getRoleData() { //
this.roleList =[];
this.$get(`${this.api.roleList}?page=1&size=100&name=&platformId=1`).then(res => {
for(var i=0;i<res.rolePage.records.length;i++){
if (res.rolePage.records[i].roleName == '超级管理员'){
}else{
this.roleList.push(res.rolePage.records[i])
}
}
// this.roleList = res.rolePage.records;
}).catch(res => {});
},
closeTeacher() { // /
this.teacherForm = {
accountId: "",
account: "",
userName: "",
roleValue: [],
roleAndDeptList: [],
uniqueIdentification: "",
workNumber: "",
phone: "",
email: ""
};
this.$refs.teacherForm.clearValidate();
this.teacherVisible = false;
},
addTeacher() { //
this.isDetail = false;
this.isAdd = true;
this.teacherVisible = true;
this.orgList = this.$refs.org.orgList;
},
getStaffDetail(accountId) { //
this.$get(`${this.api.staffDetail}?accountId=${accountId}`).then(res => {
let { data } = res;
this.teacherForm = data;
this.teacherForm.roleValue = data.roleAndDeptList.map(i => i.roleId);
this.teacherForm.roleAndDeptList = data.roleAndDeptList.map(i => {
i.cascaderValue = [i.staffArchitectureId, i.gradeId]
return i;
});
console.log(22, this.teacherForm)
}).catch(res => {});
},
resetPassword(row) { //
this.$confirm(`重置后的密码为:${Setting.initialPassword},确定重置?`, "提示", { type: "warning" }).then(() => {
this.$get(`${this.api.resetPassword}?userId=${row.userId}&newPwd=111aaa`).then(res => {
this.$message.success("重置成功");
}).catch(res => {
});
}).catch(() => {
});
},
editTeacher(row) { //
this.isDetail = false;
this.isAdd = false;
this.teacherVisible = true;
this.orgList = this.$refs.org.orgList;
this.getStaffDetail(row.accountId);
},
showTeacher(row) { //
this.isDetail = true;
this.isAdd = false;
this.teacherVisible = true;
this.orgList = this.$refs.org.orgList;
this.getStaffDetail(row.accountId);
},
accountChange() { //
if (this.teacherForm.account) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&account=${this.teacherForm.account}&workNumber=`;
} else {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&accountId=${this.teacherForm.accountId}&account=${this.teacherForm.account}&workNumber=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.accountReapeat = false;
}
}).catch( err => {
this.accountReapeat = true;
});
}
},
workNumberChange() { //
if (this.teacherForm.workNumber) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&workNumber=${this.teacherForm.workNumber}&account=`;
} else {
url = `${this.api.checkWorkNumOrAccount}?platformId=${Setting.platformId}&type=${Setting.platformType}&accountId=${this.teacherForm.accountId}&workNumber=${this.teacherForm.workNumber}&account=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.workNumberReapeat = false;
}
}).catch( err => {
this.workNumberReapeat = true;
});
}
},
phoneChange() { //
let regex = /^1[3456789]\d{9}$/;
if (regex.test(this.teacherForm.phone)) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkEmailOrPhone}?phone=${this.teacherForm.phone}&email=`;
} else {
url = `${this.api.checkEmailOrPhone}?accountId=${this.teacherForm.accountId}&phone=${this.teacherForm.phone}&email=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.phoneRepeat = false;
}
}).catch( err => {
this.phoneRepeat = true;
});
}
},
emailChange() { //
let regex = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
if (regex.test(this.teacherForm.email)) {
let url = "";
if (this.isAdd) {
url = `${this.api.checkEmailOrPhone}?email=${this.teacherForm.email}&phone=`;
} else {
url = `${this.api.checkEmailOrPhone}?accountId=${this.teacherForm.accountId}&email=${this.teacherForm.email}&phone=`;
}
this.$post(url).then(res => {
if (res.status === 200) {
this.emailRepeat = false;
}
}).catch( err => {
this.emailRepeat = true;
});
}
},
roleChange(value) { //
console.log(this.teacherForm.roleValue)
if (value.length) {
let ids = this.teacherForm.roleAndDeptList.map(e => e.roleId);
this.roleList.forEach(i => {
let obj = {
roleId: "",
roleName: "",
cascaderValue: []
};
if (value.includes(i.id) && !ids.includes(i.id)) {
console.log(i)
obj.roleId = i.id;
obj.roleName = i.roleName;
this.teacherForm.roleAndDeptList.push(obj);
}
});
} else {
this.teacherForm.roleAndDeptList.splice(0);
}
},
roleRemove(value) { //
let list = [];
for(var i=0;i<this.teacherForm.roleAndDeptList.length;i++){
if (this.teacherForm.roleAndDeptList[i].roleId == value){
}else{
list.push(this.teacherForm.roleAndDeptList[i])
}
}
this.teacherForm.roleAndDeptList = list
},
async saveSure(teacherForm) {
this.$refs[teacherForm].validate((valid) => {
if (valid) {
if (this.submiting) return false
if (this.accountReapeat) return this.$message.warning("该账号已存在");
if (this.workNumberReapeat) return this.$message.warning("该员工工号已存在");
if (this.phoneRepeat) return this.$message.warning("该手机号已存在");
if (this.emailRepeat) return this.$message.warning("该邮箱已存在");
let data = {
accountId: this.teacherForm.accountId,
account: this.teacherForm.account,
userName: this.teacherForm.userName,
roleAndDeptList: [],
uniqueIdentification: this.teacherForm.uniqueIdentification ? this.teacherForm.uniqueIdentification : new Date().getTime(),
workNumber: this.teacherForm.workNumber,
phone: this.teacherForm.phone,
email: this.teacherForm.email
};
if (this.teacherForm.roleAndDeptList.length){
for (let i = 0; i < this.teacherForm.roleAndDeptList.length; i++) {
if (this.teacherForm.roleAndDeptList[i].cascaderValue.length < 2) {
this.$message.warning(`请选择${this.teacherForm.roleAndDeptList[i].roleName}所属部门`)
return;
} else {
let obj = {
roleId: this.teacherForm.roleAndDeptList[i].roleId,
staffArchitectureId: this.teacherForm.roleAndDeptList[i].cascaderValue[0],
gradeId: this.teacherForm.roleAndDeptList[i].cascaderValue[1]
};
data.roleAndDeptList.push(obj);
}
}
}
this.submiting = true
if (this.teacherForm.accountId) {
this.$post(this.api.modifyStaff, data).then(res => {
this.$message.success("编辑成功");
this.closeTeacher();
this.getData();
this.submiting = false
}).catch(res => {
this.submiting = false
});
} else {
this.$post(this.api.saveStaff, data).then(res => {
this.$message.success("添加成功");
this.closeTeacher();
this.getData();
this.submiting = false
}).catch(res => {
this.submiting = false
});
}
} else {
return false;
}
});
},
delTeacher(row) {
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.delStaff}?accountIds=${row.accountId}`).then(res => {
this.$message.success("删除成功");
this.getData();
}).catch(res => {});
}).catch(() => {});
},
switchOff(val,row,index) {
this.$get(this.api.updateAccountAllEnable,{
id: row.userId,
isEnable: val
}).then(res => {
if(res.code == '200') {
this.$message.success(val ? '启用成功' : '禁用成功')
}else{
this.$message.success(res.message)
}
}).catch(res => {})
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllSelection() {
if (this.multipleSelection.length) {
//
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
}).then(() => {
let ids = this.multipleSelection.map(item => {
return item.accountId;
});
this.$post(`${this.api.delStaff}?accountIds=${ids.toString()}`).then(res => {
this.multipleSelection = [];
this.$refs.table.clearSelection();
this.$message.success("删除成功");
this.getData();
}).catch(res => {
});
}).catch(() => {
});
} else {
this.$message.error("请先选择员工 !");
}
},
batchImport() {
this.importVisible = true;
this.uploadList = [];
this.uploadFaild = false;
},
searchTeacher() {
this.page = 1;
this.getData();
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
downLoad() {
location.href = this.api.staffTemplate;
},
showFaild() {
location.href = `${this.api.exportFailureStaff}?exportCode=${this.exportCode}`;
},
//
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
console.log(res);
this.uploadFaild = false;
if (res.status === 200) {
if (res.data.exportCode) {
this.exportCode = res.data.exportCode;
this.uploadFaild = true;
}
this.$message.success(`上传成功${res.data.successNum},上传失败${res.data.failureNum}`);
} else {
res.message ? this.$message.error(res.message) : this.$message.error("上传失败,请检查数据");
}
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.uploadList = fileList;
this.uploadFaild = false;
},
uploadSure() {
this.importVisible = false;
this.page = 1;
this.keyword = "";
this.getData();
}
}
};
</script>
<style lang="scss" scoped>
.wrap {
display: flex;
padding: 0 24px;
.side {
width: 300px;
padding: 24px 10px 24px 0;
margin-right: 24px;
border-right: 1px solid rgba(0, 0, 0, 0.06);
}
.right {
width: calc(100% - 374px);
padding: 24px;
}
}
.el-input__inner{
height: 32px;
}
</style>

@ -0,0 +1,262 @@
<template>
<div>
<div>
<div style="text-align: right">
<el-button type="text" @click="addType(0)">添加</el-button>
</div>
<org-tree
:data="orgList"
show-checkbox
default-expand-all
ref="orgTree"
node-key="id"
highlight-current
:expand-on-click-node="false"
@node-click="getSingle"
@check="getCheck"
:props="{children: 'children', label: 'categoryName', isLeaf: 'leaf'}"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span style="display: inline-block; margin-right: 20px">{{ node.label }}</span>
<span>
<el-button
type="text"
icon="el-icon-edit-outline"
@click="editType(data)">
</el-button>
<el-button
type="text"
icon="el-icon-circle-plus-outline"
@click="addType(node, data)">
</el-button>
<el-button
type="text"
icon="el-icon-delete"
@click="delType(data)">
</el-button>
</span>
</span>
</org-tree>
</div>
<el-dialog :title="Form.id ? '编辑分类' : '新增分类'" :visible.sync="typeVisible" width="24%" center @close="closeDia" :close-on-click-modal="false">
<el-form ref="Form" :model="Form" :rules="rules">
<el-form-item prop="categoryName">
<el-input placeholder="请输入分类名称" v-model="Form.categoryName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="typeVisible = false"> </el-button>
<el-button type="primary" @click="submit"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import OrgTree from "@/components/org-tree/src/tree";
export default {
props: ["Data"],
data() {
return {
systemId: this.$route.query.systemId,
orgList: [],
typeVisible: false,
depVisible: false,
Form: {
id: '',
parentId: '',
categoryName: '',
level: ''
},
rules: {
categoryName: [
{ required: true, message: "请输入分类名称", trigger: "blur" }
]
}
};
},
components: {
OrgTree
},
mounted() {
this.getType()
},
methods: {
getType() {
this.$post(this.api.sourceModelClassification).then(res => {
this.orgList = res.data
}).catch(res => {})
},
closeDia() {
this.$refs.Form.resetFields()
this.Form = {
id: '',
parentId: '',
categoryName: ''
}
},
getSingle(data) {
this.$emit('getSingle', data)
},
getCheck(data, checked) {
this.$emit('getCheck', checked.checkedNodes)
},
//
addType(node, data) {
this.typeVisible = true
this.Form.parentId = data.id || 0
this.Form.level = node ? node.level - 1 : 0
},
//
editType(data) {
this.Form.id = data.id
this.Form.categoryName = data.categoryName
this.typeVisible = true
},
//
submit() {
this.$refs['Form'].validate((valid) => {
if (valid) {
const form = this.Form
const data = {
id: form.id,
categoryName: form.categoryName,
systemId: this.systemId
}
debugger
if (data.id) {
this.$post(this.api.updateProfessional, data).then(res => {
his.$message.success("编辑成功")
this.typeVisible = false
this.getType()
}).catch(res => {})
} else {
data.level = form.level
data.parentId = form.parentId
this.$post(this.api.categorySave, data).then(res => {
this.$message.success("添加成功")
this.typeVisible = false
this.getType()
}).catch(res => {})
}
}
})
},
//
delType(item) {
this.$confirm("确定要删除分类吗?", "提示", {
type: "warning"
}).then(() => {
this.$post(`${this.api.deleteSourceModelCategory}?categoryId=${item.id}`).then(res => {
this.$message.success("删除成功")
this.$emit("getData")
this.getType()
}).catch(res => {})
}).catch(() => {})
}
}
};
</script>
<style scoped>
.side_view {
height: 800px;
padding: 40px 20px;
background-color: #fff;
}
.side_icon {
text-align: right;
}
.side_icon i {
cursor: pointer;
font-size: 20px;
color: #9278FF;
}
.side_tree {
width: 100%;
font-size: 14px;
color: #333;
}
.side_tree i {
color: #9278FF;
margin-left: 10px;
}
.fir_back {
width: 100%;
padding: 15px 0;
background: rgba(255, 255, 255, 1);
/* box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19); */
border-radius: 10px;
text-align: left;
}
.fir_back:first-child {
margin-top: 20px;
}
.fir_back:hover {
box-shadow: 1px 14px 29px 0px rgba(138, 97, 250, 0.19);
cursor: pointer;
}
.fir_back span {
margin-left: 10px;
}
.two_active {
color: #9278FF;
}
/* .two_active:hover{
color: #9278FF;
cursor:pointer;
} */
.two_back:hover {
cursor: pointer;
color: #9278FF;
}
.mar_top {
margin-top: 20px;
}
.back_active {
box-shadow: 1px 14px 29px 0px rgba(138, 97, 250, 0.19);
}
.bor_lef {
padding: 20px 0 0 0;
margin-left: 40px;
}
.three_lef {
margin-left: 60px;
padding: 20px 0;
}
.three_text {
font-size: 14px;
margin-top: 10px;
}
.teacher_tab {
margin-left: 20px;
}
.icon_select:before {
transform: rotate(180deg);
}
.list-enter-active, .list-leave-active {
transition: all 1s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateY(-30px);
}
</style>
Loading…
Cancel
Save