123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- <template>
- <div class="cl-dept-tree">
- <div class="cl-dept-tree__header">
- <div>组织架构</div>
- <ul class="cl-dept-tree__op">
- <li>
- <el-tooltip content="刷新">
- <i class="el-icon-refresh" @click="refresh()"></i>
- </el-tooltip>
- </li>
- <li v-if="drag && isPc">
- <el-tooltip content="拖动排序">
- <i class="el-icon-s-operation" @click="isDrag = true"></i>
- </el-tooltip>
- </li>
- <li class="no" v-show="isDrag">
- <el-button type="text" size="mini" @click="treeOrder(true)">保存</el-button>
- <el-button type="text" size="mini" @click="treeOrder(false)">取消</el-button>
- </li>
- </ul>
- </div>
- <div class="cl-dept-tree__container" @contextmenu.prevent="openCM">
- <el-tree
- node-key="id"
- highlight-current
- default-expand-all
- :data="list"
- :props="{
- label: 'name'
- }"
- :draggable="isDrag"
- :allow-drag="allowDrag"
- :allow-drop="allowDrop"
- :expand-on-click-node="false"
- v-loading="loading"
- @node-contextmenu="openCM"
- >
- <template slot-scope="{ node, data }">
- <div class="cl-dept-tree__node">
- <span class="cl-dept-tree__node-label" @click="rowClick(data)">{{
- node.label
- }}</span>
- <span
- class="cl-dept-tree__node-icon"
- v-if="!isPc"
- @click="openCM($event, data, node)"
- >
- <i class="el-icon-more"></i>
- </span>
- </div>
- </template>
- </el-tree>
- </div>
- </div>
- </template>
- <script>
- import { deepTree, isArray, revDeepTree, isPc } from "cl-admin/utils";
- import { ContextMenu, Form } from "cl-admin-crud";
- export default {
- name: "cl-dept-tree",
- props: {
- drag: {
- type: Boolean,
- default: true
- },
- level: {
- type: Number,
- default: 99
- }
- },
- data() {
- return {
- list: [],
- loading: false,
- isDrag: false,
- isPc: isPc()
- };
- },
- created() {
- this.refresh();
- },
- methods: {
- openCM(e, d, n) {
- let list = [
- {
- label: "新增",
- "suffix-icon": "el-icon-plus",
- hidden: n && n.level >= this.level,
- callback: (item, done) => {
- this.rowEdit({
- name: "",
- parentName: d.name,
- parentId: d.id
- });
- done();
- }
- },
- {
- label: "编辑",
- "suffix-icon": "el-icon-edit",
- callback: (item, done) => {
- this.rowEdit(d);
- done();
- }
- }
- ];
- if (!d) {
- d = this.list[0];
- }
- if (d.parentId) {
- list.push({
- label: "删除",
- "suffix-icon": "el-icon-delete",
- callback: (item, done) => {
- this.rowDel(d);
- done();
- }
- });
- }
- list.push({
- label: "新增成员",
- "suffix-icon": "el-icon-user",
- callback: (item, done) => {
- this.$emit("user-add", d);
- done();
- }
- });
- ContextMenu.open(e, {
- list
- });
- },
- allowDrag({ data }) {
- return data.parentId;
- },
- allowDrop(draggingNode, dropNode) {
- return dropNode.data.parentId;
- },
- refresh() {
- this.isDrag = false;
- this.loading = true;
- this.$service.system.dept
- .list()
- .then((res) => {
- this.list = deepTree(res);
- this.$emit("list-change", this.list);
- })
- .done(() => {
- this.loading = false;
- });
- },
- rowClick(e) {
- ContextMenu.close();
- let ids = e.children ? revDeepTree(e.children).map((e) => e.id) : [];
- ids.unshift(e.id);
- this.$emit("row-click", { item: e, ids });
- },
- rowEdit(e) {
- const method = e.id ? "update" : "add";
- Form.open({
- title: "编辑部门",
- width: "550px",
- props: {
- "label-width": "100px"
- },
- items: [
- {
- label: "部门名称",
- prop: "name",
- value: e.name,
- component: {
- name: "el-input",
- attrs: {
- placeholder: "请填写部门名称"
- }
- },
- rules: {
- required: true,
- message: "部门名称不能为空"
- }
- },
- {
- label: "上级部门",
- prop: "parentId",
- value: e.parentName || "...",
- component: {
- name: "el-input",
- attrs: {
- disabled: true
- }
- }
- },
- {
- label: "排序",
- prop: "orderNum",
- value: e.orderNum || 0,
- component: {
- name: "el-input-number",
- props: {
- "controls-position": "right",
- min: 0,
- max: 100
- }
- }
- }
- ],
- on: {
- submit: (data, { done, close }) => {
- this.$service.system.dept[method]({
- id: e.id,
- parentId: e.parentId,
- name: data.name,
- orderNum: data.orderNum
- })
- .then(() => {
- this.$message.success(`新增部门${data.name}成功`);
- close();
- this.refresh();
- })
- .catch((err) => {
- this.$message.error(err);
- done();
- });
- }
- }
- });
- },
- rowDel(e) {
- const del = (f) => {
- this.$service.system.dept
- .delete({
- ids: e.id,
- deleteUser: f
- })
- .then(() => {
- if (f) {
- this.$message.success("删除成功");
- } else {
- this.$confirm("该部门用户已移动到部门顶级", "删除成功");
- }
- })
- .done(() => {
- this.refresh();
- });
- };
- this.$confirm("该操作会删除部门下的所有用户,是否确认?", "提示", {
- type: "warning",
- confirmButtonText: "直接删除",
- cancelButtonText: "保留用户",
- distinguishCancelAndClose: true
- })
- .then(() => {
- del(true);
- })
- .catch((action) => {
- if (action == "cancel") {
- del(false);
- }
- });
- },
- treeOrder(f) {
- if (f) {
- this.$confirm("部门架构已发生改变,是否保存?", "提示", {
- type: "warning"
- })
- .then(() => {
- const deep = (list, pid) => {
- list.forEach((e) => {
- e.parentId = pid;
- ids.push(e);
- if (e.children && isArray(e.children)) {
- deep(e.children, e.id);
- }
- });
- };
- let ids = [];
- deep(this.list, null);
- this.$service.system.dept
- .order(
- ids.map((e, i) => {
- return {
- id: e.id,
- parentId: e.parentId,
- orderNum: i
- };
- })
- )
- .then(() => {
- this.$message.success("更新排序成功");
- })
- .catch((err) => {
- this.$message.error(err);
- })
- .done(() => {
- this.refresh();
- this.isDrag = false;
- });
- })
- .catch(() => {});
- } else {
- this.refresh();
- }
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .cl-dept-tree {
- height: 100%;
- width: 100%;
- &__header {
- display: flex;
- align-items: center;
- height: 40px;
- padding: 0 10px;
- background-color: #fff;
- letter-spacing: 1px;
- position: relative;
- div {
- font-size: 14px;
- color: $color-main;
- flex: 1;
- white-space: nowrap;
- }
- i {
- font-size: 18px;
- color: $color-main;
- cursor: pointer;
- }
- }
- /deep/.el-tree-node__content {
- height: 36px;
- }
- &__op {
- display: flex;
- li {
- display: flex;
- justify-content: center;
- align-items: center;
- list-style: none;
- margin-left: 5px;
- padding: 5px;
- cursor: pointer;
- &:not(.no):hover {
- background-color: #eee;
- }
- }
- }
- &__container {
- height: calc(100% - 40px);
- overflow-y: auto;
- overflow-x: hidden;
- /deep/.el-tree-node__content {
- margin: 0 5px;
- }
- }
- &__node {
- display: flex;
- align-items: center;
- height: 100%;
- width: 100%;
- box-sizing: border-box;
- &-label {
- display: flex;
- align-items: center;
- flex: 1;
- height: 100%;
- font-size: 14px;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- &-icon {
- height: 28px;
- width: 28px;
- line-height: 28px;
- text-align: center;
- margin-right: 5px;
- }
- }
- }
- </style>
|