<template>
  <xy-page title>
    <xy-breadcrumb :parent-query="{userId:$utils.getParam('userId')}" />
    <xy-search class="mgt20">
      <el-form
        inline
        :model="searchFilter"
        label-width="70px"
      >
        <el-form-item
          label="系统实例"
          prop
        >
          <el-select
            v-model="appInstanceId"
            filterable
            remote
            reserve-keyword
            :remote-method="remoteMethod"
            :loading="loading"
            placeholder="请选择系统实例"
            :disabled="!!submitData.appInstanceId"
          >
            <el-option
              v-for="item in appInstanceList"
              :key="item.id"
              :label="item.name"
              :value="item.id"
            />
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="right">
        <el-button
          plain
          @click="resetForm"
        >重置条件</el-button>
      </div>
    </xy-search>
    <div>
      <div
        v-if="appInstanceId"
        style="text-align:right;"
      >
        <div class="form-row form-group">
          <div>
            <el-button
              v-show="submitData.isAdmin === 0"
              type="primary"
              size="small"
              @click="globalAllResource"
            >
              所有权限
            </el-button>
            <el-button
              v-show="submitData.isAdmin === 0"
              type="plain"
              size="small"
              @click="globalReadResource"
            >
              所有只读
            </el-button>
            <span style="margin:0 10px;">是否拥有所有菜单:</span>
            <el-radio
              v-model="submitData.isAdmin"
              :label="1"
            >是</el-radio>
            <el-radio
              v-model="submitData.isAdmin"
              :label="0"
            >否</el-radio>
            <xy-save
              v-model="isSave"
              v-auth="'AUTH_USER-SAVE'"
              style="margin-left:30px;"
              type="primary"
              size="small"
              text="保存中..."
              @click="save"
            >
              保存
            </xy-save>
            <xy-save
              v-show="!!$utils.getParam('appUserInstanceId') && submitData.isAdmin === 0"
              v-model="isResetInstance"
              v-auth="'AUTH_USER-SAVE'"
              type="plain"
              size="small"
              text="重置中..."
              @click="resetInstance"
            >
              重置实例
            </xy-save>
          </div>
        </div>
      </div>
      <div
        v-show="submitData.isAdmin === 0"
        style="display:inline-block;width:25%;vertical-align:top;"
      >
        <el-tree
          ref="tree"
          :data="treeData"
          node-key="id"
          :props="defaultProps"
          default-expand-all
          empty-text="请选择系统实例"
          :expand-on-click-node="false"
          show-checkbox
          @check-change="checkChange"
        />
      </div>
      <div
        v-show="submitData.isAdmin === 0"
        style="display:inline-block;width:25%;vertical-align:top;"
      >
        <el-tree
          :data="treeSelectData"
          node-key="id"
          :props="defaultProps"
          default-expand-all
          :highlight-current="true"
          empty-text="请选择菜单"
          :expand-on-click-node="false"
          @node-click="nodeClick"
        >
          <span
            slot-scope="{ node, data }"
            class="custom-tree-node"
          >
            <span>{{ node.label }}</span>
            <span
              v-if="data.resources.length === 0 || data.level !== 3"
              style="font-size:12px;"
              class
            >(无需设置)</span>
            <span
              v-else-if="data.menuResources.length === data.resources.length"
              style="font-size:12px;"
              class="deep-green"
            >(所有权限)</span>
            <span
              v-else-if="data.menuResources.length === 0"
              style="font-size:12px;"
              class="red"
            >(无权限)</span>
            <span
              v-else
              style="font-size:12px;"
              class="green"
            >(部分权限)</span>
          </span>
        </el-tree>
      </div>

      <div
        v-show="submitData.isAdmin === 0 && menu && Object.keys(menu).length > 0 && menu.resources.length > 0"
        style="display:inline-block;width:49%;vertical-align:top;"
      >
        <div style="margin-bottom:10px;">
          <el-button
            type="primary"
            size="small"
            @click="allResource"
          >所有</el-button>
          <el-button
            type="plain"
            size="small"
            @click="readResource"
          >只读</el-button>
        </div>
        <el-transfer
          v-model="menu.menuResources"
          filter-placeholder="请输入资源名称"
          :data="menuResources"
          :titles="['全部权限', '所选权限']"
          :props="{
            key: 'id',
            label: 'name'
          }"
        />
      </div>
    </div>
  </xy-page>
</template>

<script>
export default {
  name: 'AuthAppUserInstanceEdit',
  data() {
    return {
      appUserInstanceId: null,
      searchFilter: {},
      appInstanceId: null,
      appInstanceList: [],
      loading: false,
      treeData: [],
      treeSelectData: [],
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      menuResource: {},
      menuResources: [],
      isSave: false,
      isResetInstance: false,
      menu: {},
      submitData: {
        isAdmin: 0,
        userId: 0,
        id: 0,
        appInstanceId: 0,
        menuIds: []
      }
    }
  },
  watch: {
    appInstanceId() {
      if (!this.appInstanceId) {
        return
      }
      this.resetData()
    }
  },
  mounted() {
    const id = this.$utils.getParam('userId')
    this.appUserInstanceId = this.$utils.getParam('appUserInstanceId')
    if (!id) {
      this.$close(true)
      return this.$toPage('/auth-user/list')
    }
    this.resetForm()

    if (this.appUserInstanceId) {
      this.$get('/admin/auth/instance/authAppUserInstance/get.do', {
        data: {
          id: this.appUserInstanceId
        },
        success: res => {
          if (!res.success) {
            return this.$message.error(res.message)
          }
          this.appInstanceId = res.object.appInstanceId
          this.submitData = res.object

          this.submitData.menuList = this.submitData.menuList || []
          this.submitData.menuList.forEach(item => {
            item.oldResources = item.resources
          })
        }
      })
    }
  },
  activated() {
    const id = this.$utils.getParam('userId')
    this.appUserInstanceId = this.$utils.getParam('appUserInstanceId')
    if (!id) {
      this.$close(true)
      return this.$toPage('/auth-user/list')
    }
    this.resetForm()
    if (this.appUserInstanceId) {
      this.$get('/admin/auth/instance/authAppUserInstance/get.do', {
        data: {
          id: this.appUserInstanceId
        },
        success: res => {
          if (!res.success) {
            return this.$message.error(res.message)
          }
          this.appInstanceId = res.object.appInstanceId
          this.submitData = res.object
          this.submitData.menuList = this.submitData.menuList || []
          this.submitData.menuList.forEach(item => {
            item.oldResources = item.resources
          })
        }
      })
    } else {
      this.appUserInstanceId = null
      this.appInstanceId = null
      this.submitData = this.$options.data().submitData
      this.treeData = []
      this.treeSelectData = []
    }
  },
  methods: {
    remoteMethod(query) {
      this.loading = true
      this.$postStream('/admin/auth/instance/authAppInstance/list.do', {
        data: {
          quickSearch: query
        },
        success: res => {
          this.appInstanceList = res.object.list
          this.loading = false
        }
      })
    },
    globalAllResource() {
      this.treeSelectData.forEach(item1 => {
        item1.children.forEach(item2 => {
          item2.children.forEach(item3 => {
            item3.menuResources = JSON.parse(JSON.stringify(item3.resources))
          })
        })
      })
    },
    globalReadResource() {
      this.treeSelectData.forEach(item1 => {
        item1.children.forEach(item2 => {
          item2.children.forEach(item3 => {
            item3.menuResources = []
            item3.resources.forEach(resourceId => {
              const r = this.menuResource[resourceId]
              if (r && r.type !== 2) {
                item3.menuResources.push(resourceId)
              }
            })
          })
        })
      })
    },
    readResource() {
      if (!this.menu) return
      this.menu.menuResources = []
      this.menuResources.forEach(item => {
        if (item.type !== 2) {
          this.menu.menuResources.push(item.id)
        }
      })
    },
    allResource() {
      if (!this.menu) return
      this.menu.menuResources = []
      this.menuResources.forEach(item => {
        this.menu.menuResources.push(item.id)
      })
    },
    nodeClick(menu) {
      if (menu.id === -1) {
        menu = {}
      }
      this.menu = menu
      this.menuResources = []
      this.menu.resources.forEach(item => {
        this.menuResources.push(this.menuResource[item])
      })
    },
    checkChange() {
      this.menu = {}
      const nodes = this.$refs.tree.getCheckedNodes()
      if (!nodes || nodes.length === 0) {
        this.treeSelectData = []
      }
      // 获取children 数量为0的菜单
      const childrenNode = []
      const ids = []
      nodes.forEach(item => {
        if (!item.children || item.children.length === 0) {
          childrenNode.push(item)
          ids.push(item.id)
        }
      })

      if (childrenNode.length === 0) {
        return (this.treeSelectData = [])
      }

      this.treeSelectData = []

      const selectTreeNode = {}
      const tmpTreeData = JSON.parse(JSON.stringify(this.treeData[0].children))
      tmpTreeData.forEach(item1 => {
        item1.children.forEach(item2 => {
          item2.children.forEach(item3 => {
            if (ids.indexOf(item3.id) !== -1) {
              selectTreeNode[item1.id] = item1
              selectTreeNode[item2.id] = item2
              selectTreeNode[item3.id] = item3
              let itemMenu = null
              if (this.submitData.menuList) {
                this.submitData.menuList.forEach(menu => {
                  if (itemMenu) {
                    return
                  }
                  if (menu.menuId === item3.id && menu.resources) {
                    itemMenu = menu
                  }
                })
              }
              item3.menuResources = []
              if (itemMenu) {
                let resources = itemMenu.resources
                  .replace(/^,/, '')
                  .replace(/,$/, '')
                resources = resources.split(',')
                resources.forEach(resourceId => {
                  item3.menuResources.push(Number(resourceId))
                })
              } else {
                item3.menuResources = JSON.parse(
                  JSON.stringify(item3.resources)
                )
              }
            }
          })
        })
      })

      for (const key in selectTreeNode) {
        selectTreeNode[key].children = []
      }
      for (const key in selectTreeNode) {
        if (!selectTreeNode[key].parentId) {
          this.treeSelectData.push(selectTreeNode[key])
        } else {
          const parent = selectTreeNode[selectTreeNode[key].parentId]
          if (!parent) {
            continue
          }
          parent.children.push(selectTreeNode[key])
        }
      }
    },
    resetInstance() {
      this.$xyConfirm('确认是否重置实例，重置后修改的数据将无法恢复？', () => {
        this.isResetInstance = true
        this.resetData(() => {
          this.isResetInstance = false
        })
      })
    },

    initMenuResource(menus) {
      if (!menus || menus.length === 0) {
        return
      }
      menus.forEach(menu => {
        menu.resources = menu.resources || ''
        menu.resources = menu.resources.replace(/^,/, '').replace(/,$/, '')
        if (menu.resources) {
          menu.resources = menu.resources.split(',')
          for (let i = 0; i < menu.resources.length; i++) {
            menu.resources[i] = Number(menu.resources[i])
          }
        } else {
          menu.resources = []
        }
        this.initMenuResource(menu.children)
      })
    },
    setLevel(data, level, sort) {
      level = level || 0
      sort = sort || 0
      if (!data || data.length === 0) {
        return sort
      }
      data.forEach(item => {
        item.level = level
        if (level <= 1) {
          item.type = 3
        } else if (!item.type) {
          item.type = 1
        }
        item.appId = this.appId
        item.sort = sort++
        item.children = item.children || []
        sort = this.setLevel(item.children, level + 1, sort)
      })
      return sort
    },
    resetData(cb) {
      if (this.submitData.menuList) {
        this.submitData.menuList.forEach(item => {
          item.resources = item.oldResources || ''
        })
      }
      this.menu = {}
      this.treeData = []
      this.$nextTick(() => {
        this.$get('/admin/auth/instance/authMenu/list.do', {
          data: {
            appInstanceId: this.appInstanceId
          },
          success: res => {
            this.treeData = res.object || []
            this.treeData = [
              {
                id: -1,
                name: '全部菜单',
                children: this.treeData
              }
            ]
            this.initMenuResource(this.treeData)
            this.setLevel(this.treeData)
            this.treeSelectData = []
            if (!this.appUserInstanceId) {
              this.submitData = this.$options.data().submitData
            } else {
              this.setCheckedKeys()
            }
            this.getMenuResources(cb)
          }
        })
      })
    },
    setCheckedKeys() {
      this.$nextTick(() => {
        const ids = []
        if (this.submitData.menuList) {
          this.submitData.menuList.forEach(item => {
            const node = this.$refs.tree.getNode(item.menuId)
            if (
              !node ||
              (node.data.children && node.data.children.length > 0)
            ) {
              return true
            }
            ids.push(item.menuId)
          })
        }
        this.$refs.tree.setCheckedKeys(ids)
        this.checkChange()
        this.$nextTick(() => {
          if (this.submitData.menuList) {
            this.submitData.menuList.forEach(item => {
              item.oldResources = item.resources
              item.resources = ''
            })
          }
        })
      })
    },
    _getMenus(menus, data) {
      if (!data || data.length === 0) {
        return
      }
      data.forEach(item => {
        let r = item.menuResources || []
        r = r.join(',')
        if (r) {
          r = ',' + r + ','
        }
        menus.push({
          menuId: item.id,
          resources: r
        })
        this._getMenus(menus, item.children)
      })
    },
    save() {
      this.isSave = true
      this.submitData.userId = this.$utils.getParam('userId')
      this.submitData.appInstanceId = this.appInstanceId
      this.submitData.id = this.$utils.getParam('appUserInstanceId')
      const menus = []
      this._getMenus(menus, this.treeSelectData)
      this.submitData.menus = menus

      this.$postStream('/admin/auth/instance/authAppUserInstance/save.do', {
        data: this.submitData,
        success: res => {
          this.isSave = false
          if (!res.success) {
            return this.$message.error(res.message)
          }
          this.$message.success(res.message)
          this.$toPage('/auth-app-user-instance/list', {
            userId: this.$utils.getParam('userId')
          })
        }
      })
    },
    getMenuResources(cb) {
      this.$postStream('/admin/auth/instance/authResources/listForApp.do', {
        data: {
          appInstanceId: this.appInstanceId
        },
        success: res => {
          if (res.success) {
            const resource = res.object || []

            this.menuResource = {}

            resource.forEach(item => {
              this.menuResource[item.id] = item
            })
          } else {
            this.$message.error(res.message)
          }
          cb && cb()
        },
        error: () => { }
      })
    },
    resetForm() {
      this.$postStream('/admin/auth/instance/authAppInstance/list.do', {
        data: {
          page: 1,
          size: 65535
        },
        success: res => {
          if (res.success) {
            this.appInstanceList = res.object.list || []
          } else {
            this.$message.error(res.message)
          }
        },
        error: () => { }
      })
    }
  }
}
</script>

<style lang="scss">
.lineThrough {
  text-decoration: line-through;
}
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 10px;
}
.el-transfer__buttons {
  padding: 0 6px;
}
.el-transfer__button {
  border-radius: 50%;
  font-size: 0;
  min-width: 0;
  padding: 0;
  height: 34px;
  width: 34px;
  line-height: 34px;
}
.el-select-dropdown {
  max-width: 217px;
}
</style>
