<!--
应用功能独有表单
@Author: linqian
@Date: 2021-07-11 15:03
-->
<template>
  <div>
    <transfer-tree
      ref="transferTree"
      filterable
      :titles="['可选资源', '已选资源']"
      v-model="selectedValue"
      :data="data"
      children-name="child"
      :open-all="false"
      :transfer-open-node="true"
      :filter-node-from="handleSearch"
      value-name="id"
    >
    </transfer-tree>
    <div v-footer>
      <dg-button @click="handleCancel">取消</dg-button>
      <dg-button type="primary" @click="handleSubmit">保存</dg-button>
    </div>
  </div>
</template>

<script>
import transferTree from '@/components/transfer-tree';
import { allAppFuncTree, userHasAuthFunIds } from '@/api/permission-selfhelp-manage';
export default {
  props: {
    selectKeys: [Array],
    // 是否需要过滤父节点
    needFilter: {
      type: Boolean,
      default: false
    },
    type: String,
    // 审批单编号
    applicantOrdNo: String
  },
  components: { transferTree },
  data() {
    return {
      approveContent: this.value,
      selectedValue: [],
      havefunIdsOnlyChild: [],
      havefunIds: [],
      data: []
    };
  },
  computed: {},
  methods: {
    findIndexArray(data, id, indexArray) {
      let arr = Array.from(indexArray);
      for (let i = 0, len = data.length; i < len; i++) {
        arr.push(data[i].label);
        if (data[i].id === id) {
          return arr;
        }
        let children = data[i].child;
        if (children && children.length) {
          let result = this.findIndexArray(children, id, arr);
          if (result) return result;
        }
        arr.pop();
      }
      return false;
    },
    // 树节点转成文字
    nodeTransferLabel(keys, tree) {
      // 需要过滤匹配不到的
      const funcAttr = keys.map((item) => {
        return this.findIndexArray(tree, item, []);
      }).filter(item => item !== false);
      let attr = [];
      for (let i = 0; i < funcAttr.length; i++) {
        const element = funcAttr[i].join('/');
        attr.push(element);
      }
      return attr.join('、');
    },
    handleCancel() {
      this.$emit('close');
    },
    async handleSubmit() {
      // 申请访问的资源,剔除已经申请过的资源,不包含父级节点
      const applyKeys = this.selectedValue.filter((item) => !this.havefunIdsOnlyChild.includes(item));
      // 将节点转成文字
      const approveContent = this.nodeTransferLabel(applyKeys, this.$refs.transferTree.targetData);
      // 撤销的资源, 已有资源与已选资源作比对
      const cancelKeys = this.havefunIdsOnlyChild.filter((item) => !this.selectedValue.includes(item));
      const cancelContent = this.nodeTransferLabel(cancelKeys, this.data);
      // 已选节点 = 获取目标树所有的key,包含父节点
      const allKeys = this.$refs.transferTree.allKeyValue(false, this.$refs.transferTree.targetData);
      const allResourceInfo = allKeys
        .map((item) => this.$refs.transferTree.$refs['to-tree'].getNode(item).data)
        .map((item) => {
          return {
            appId: item.appId,
            funId: item.id
          };
        })
        .filter((item) => item.appId);
      // 新增的节点 = 剔除该用户已经拥有的资源
      const resourceInfos = allResourceInfo.filter((item) => !this.havefunIds.includes(item.funId));

      // 撤销的节点 = 已有节点 - （已选节点 - 新增节点 ）
      // 已有的节点去除撤销的节点，包含父节点
      const resourceKeys = allResourceInfo.map((item) => item.funId);
      const haveFuncKeysExcludeCancel = allResourceInfo
        .filter((item) => !resourceKeys.includes(item))
        .map((item) => item.funId);
      const cancelResourceKeys = this.havefunIds.filter((item) => !haveFuncKeysExcludeCancel.includes(item));
      const cancelResourceInfos = cancelResourceKeys
        .filter((item) => this.$refs.transferTree.$refs['from-tree'].getNode(item))
        .map((item) => this.$refs.transferTree.$refs['from-tree'].getNode(item).data)
        .map((item) => {
          return {
            appId: item.appId,
            funId: item.id
          };
        })
        .filter((item) => item.appId);
      // 已选资源有变更，则可以直接保存，无变更，则需要至少选中一条
      // 判断有无变更的标准：resourceInfos的funId 与getSetFunIdsByUser方法返回的已选资源id作匹配
      if (applyKeys.length == 0 && cancelKeys.length == 0) {
        this.$message.warning('已选资源无变更。');
      } else {
        this.$emit('success', approveContent, cancelContent, this.selectedValue, resourceInfos, cancelResourceInfos);
      }
    },

    handleSearch(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
    // 获取申请人已被授权得功能id
    getSetFunIdsByUser() {
      return new Promise((resolve) => {
        const params = {
          userId: this.$store.getters.user.id
        };
        userHasAuthFunIds(params)
          .then((res) => {
            resolve(res.data.content);
          })
          .catch(() => resolve([]));
      });
    },
    // 获取全量的菜单树
    getAllTree() {
      return new Promise((resolve) => {
        allAppFuncTree(true).then((res) => {
          resolve(res.data.content);
        });
      });
    },
    // 获取子节点，去除父节点key
    getChildKeys(data, val) {
      let keys = [];

      function filterParentKey(_data, key) {
        _data.filter((item) => {
          if (item.id == key && !item.isTreeNode) {
            keys.push(key);
            return;
          } else {
            if (item.child && item.child.length > 0) {
              filterParentKey(item.child, key);
            } else {
              return;
            }
          }
        });
      }

      for (let i = 0; i < val.length; i++) {
        const key = val[i];
        filterParentKey(data, key);
      }

      return keys;
    }
  },

  async created() {
    this.data = await this.getAllTree();
    // 已有资源，包含了父节点
    this.havefunIds = await this.getSetFunIdsByUser();
    // 已有资源，只是子节点
    this.havefunIdsOnlyChild = this.getChildKeys(this.data, this.havefunIds);
    const keys = this.selectKeys;
    if (this.needFilter && this.havefunIds.length > 0) {
      this.selectedValue = [...this.getChildKeys(this.data, keys)];
      if (this.type == 'add') {
        this.selectedValue = [...this.selectedValue, ...this.havefunIdsOnlyChild];
      }
    } else {
      this.selectedValue = keys;
    }
  },
  mounted() {}
};
</script>

<style lang='scss' scoped>
@import url('../index.scss');
</style>