<template>
  <div class="edit-store-role-body" style="height: 100%">
    <nav-crumb :navpath="bread"> </nav-crumb>
    <div class="edit-role">
      <el-alert
        type="info"
        title="拥有门店的权限，能进行一些门店日常业务，如打标签，完成话务等。必须是导购账号"
        :closable="false"
        show-icon
        style="width:572px"></el-alert>
      <el-form :model="roleData" :rules="roleDataRule" ref="roleData" style="margin-top: 30px" label-width="135px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input :value="roleData.roleName" disabled style="width: 510px"></el-input>
        </el-form-item>
        <el-form-item label="应用小程序权限" prop="menuIds">
          <el-radio-group v-model="activeType" class="specter" size="small">
            <el-radio-button v-for="el in tabList" :key="el.appType" :label="el.appType">{{ el.label }}</el-radio-button>
          </el-radio-group>
          <menu-tree
            style="margin-top: 12px"
            :menu-list="getActiveMenuList()"
            :checked-id="getActiveCheckId()"
            :app-ids="getAppIds()"
            :is-app="activeType == 4"
            @change="onCheckedChange"
            @app-open-change="onAppOpenChange"></menu-tree>
        </el-form-item>
        <el-form-item label="门店导购范围">
          <p class="type-title">当前门店</p>
          <div>
            <span class="type-label">查看导购</span>
            <el-radio-group v-model="roleData.seeType" @change="onSeeTypeChange">
              <el-radio label="1">门店下全部导购</el-radio>
              <el-radio label="0">仅自己</el-radio>
            </el-radio-group>
          </div>
          <div>
            <span class="type-label">管理导购</span>
            <el-radio-group v-model="roleData.managerType">
              <el-radio :disabled="roleData.seeType == 0" label="1">门店下全部导购</el-radio>
              <el-radio label="0">仅自己</el-radio>
            </el-radio-group>
          </div>
        </el-form-item>
        <el-form-item style="margin-top: 50px">
          <el-button type="primary" :loading="loading" @click="onSave">保存</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
import navCrumb from '@/components/nav/nav.vue';
import MenuTree from './edit-role/menu-tree.vue';
import api from '@/api/admin-list';

const { menuList, editRole, roleDetail, findAppSetting, saveAppSetting, findStoreRange, saveStoreRange } = api;

export default {
  name: 'EditStoreRole',
  components: { navCrumb, MenuTree },
  data() {
    const valiMenuIds = (rules, value, callback) => {
      if (!Array.isArray(value) || value.length == 0 || value.every(el => el.menuIds.length == 0)) {
        callback(new Error('请至少选择一个权限菜单'));
      }
      callback();
    };
    return {
      bread: [
        { path: '/store-admin-list', name: '门店角色' },
        { name: '编辑门店角色' }
      ],
      loading: false,
      wxEnterpriseId: '',
      roleData: {
        roleId: '',
        roleName: '',
        menuIds: [], // {appType:"",menuIds:,menuName:}选中的菜单id
        seeType: '1', // 0仅自己，1门店下全部导购
        managerType: '1', // 0仅自己，1门店下全部导购
      },
      roleDataRule: {
        roleName: [ { required: true } ],
        menuIds: [ { required: true, validator: valiMenuIds, trigger: 'change' } ]
      },
      activeType: 3,
      // 权限菜单列表
      tabList: [
        // 1好办后台2应用后台3好办小程序4小程序应用
        { label: '好办小程序', appType: 3, flatMenu: [], menuList: [], checkedId: {}, appIds: [] },
        { label: '小程序应用', appType: 4, flatMenu: [], menuList: [], checkedId: {}, appIds: [] },
      ],
    };
  },
  async created() {
    const { roleId } = this.$route.query;
    if (!roleId) {
      return this.$router.go(-1);
    }
    const haoBanUser = JSON.parse(localStorage.getItem('haoBanUser') || '{}');
    this.wxEnterpriseId = haoBanUser.wxEnterpriseId;
    this.$emit('showAsideMenu', false);
    await this.initData();
    this.getRoleDetail(roleId);
  },
  mounted() {
    document.documentElement.style.backgroundColor = '#f0f2f5';
  },
  destroyed() {
    document.documentElement.style.backgroundColor = '#fff';
  },
  methods: {
    /**
     * @description: 获取权限数据
     * @returns {Function}
     * @author: 无尘
     */
    initData() {
      const prom = [];
      this.tabList.forEach(el => {
        // appType 1好办后台2应用后台3好办小程序4小程序应用
        // roleType 1管理员角色 2门店角色
        prom.push(menuList({ wxEnterpriseId: this.wxEnterpriseId, roleType: 2, appType: el.appType }).then(res => {
          el.flatMenu = res.result || [];
          el.menuList = this.flatDataToTree(res.result || []);
          el.menuList.forEach(item => {
            this.$set(el.checkedId, item.menuId, []);
          });
        }));
      });

      return Promise.all(prom);
    },
    /**
     * @description: 获取角色相关的数据
     * @param {String} roleId
     * @author: 无尘
     */
    getRoleDetail(roleId) {
      // 获取角色权限配置、资源范围等数据
      roleDetail({ roleId }).then(res => {
        let { roleId, roleName, menuIds } = res.result;
        menuIds = typeof menuIds == 'string' ? menuIds.split(',') : [];
        // roleData中存一份包含父节点的menuId
        // tabList中存一份不包含父节点的menuId
        Object.assign(this.roleData, { roleId, roleName });
        // 将menuIds分配到相应同的tab下的checkedId中
        this.tabList.forEach(el => {
          let checkedId = [];
          el.menuList.forEach(item => {
            el.checkedId[item.menuId] = getLeafMenuId([ item ], menuIds);
            checkedId = checkedId.concat(getAllMenuId([ item ], menuIds));
          });
          this.roleData.menuIds.push({ appType: el.appType, menuIds: checkedId });
        });
      });
      // 获取门店导购范围数据
      findStoreRange({ roleId, wxEnterpriseId: this.wxEnterpriseId }).then(res => {
        const { seeType, managerType } = res.result || {};
        Object.assign(this.roleData, {
          seeType: typeof seeType != 'string' && typeof seeType != 'number' ? '1' : String(seeType),
          managerType: typeof managerType != 'string' && typeof managerType != 'number' ? '1' : String(managerType)
        });
      });
      // 获取应用开启状态的数据
      this.tabList.forEach(el => {
        if (el.appType == 4) {
          findAppSetting({ wxEnterpriseId: this.wxEnterpriseId, roleType: 2, roleId, appType: el.appType }).then(res => {
            el.appIds = res.result || [];
            this.setChildrenDisable(el.menuList, el.appIds);
          });
        }
      });

      function getAllMenuId(menuList, allMenuIds) {
        let result = [];
        menuList.forEach(el => {
          if (allMenuIds.some(item => item == el.menuId)) {
            result.push(el.menuId);
          }
          if (Array.isArray(el.children)) {
            result = result.concat(getAllMenuId(el.children, allMenuIds));
          }
        });
        return result;
      }
      function getLeafMenuId(menuList, allMenuIds) {
        let result = [];
        // 所有子节点被选中，才算父节点被选中
        menuList.map(el => {
          if (allMenuIds.some(item => item == el.menuId)) {
            let allSubId = [];
            if (Array.isArray(el.children)) {
              allSubId = getAllSubMenuIds(el.children);
            }
            // 如果el的allSubId都在allMenuIds中，则认为el需要被勾选，需要把el.menuId放入result中
            if (allSubId.length == 0 || allSubId.every(el => allMenuIds.some(item => item == el))) {
              result.push(el.menuId);
            }
            if (Array.isArray(el.children)) {
              result = result.concat(getLeafMenuId(el.children, allMenuIds));
            }
          }
        });
        return result;
      }
      function getAllSubMenuIds(menuList) {
        let result = [];
        menuList.forEach(el => {
          result.push(el.menuId);
          if (Array.isArray(el.children)) {
            result = result.concat(getAllSubMenuIds(el.children));
          }
        });
        return result;
      }
    },
    getActiveMenuList() {
      const result = this.tabList.filter(el => el.appType == this.activeType);
      return result[0].menuList;
    },
    getActiveCheckId() {
      const result = this.tabList.filter(el => el.appType == this.activeType);
      return result[0].checkedId;
    },
    getAppIds() {
      const result = this.tabList.filter(el => el.appType == this.activeType);
      return result[0].appIds;
    },
    /**
     * @description: 将平铺的数据转为树形结构
     * @param {Array} data
     * @return {Array}
     * @author: 无尘
     */
    flatDataToTree(data) {
      return data.filter(el => {
        // 返回当前节点下的子节点
        const children = data.filter(item => item.parentCode == el.menuCode);
        if (children.length > 0) {
          el.children = children; // 如果存在子级，则给父级添加一个children属性，并赋值
        }
        return el.parentCode == '' || el.parentCode == null;
      });
    },
    /**
     * @description: 保存选中的子节点id,将选中的子节点的id存在tabList对应元素的checkedId中,同时更新roleData中menuIds的数据
     * @param {String} checkedId
     * @author: 无尘
     */
    onCheckedChange(checkedId) {
      let menuIds = [];
      let flatMenu = [];
      let allMenuIds = [];
      for(let key in checkedId) {
        menuIds = menuIds.concat(checkedId[key]);
      }
      this.tabList = this.tabList.map(el => {
        if (el.appType == this.activeType) {
          el.checkedId = checkedId;
          flatMenu = el.flatMenu;
        }
        return el;
      });
      // 根据任意层级的子节点向上查找全部的父节点，存入allMenuIds中，然后过滤掉重复的menuId
      menuIds.map(el => {
        allMenuIds = allMenuIds.concat(getParentIds(el, flatMenu));
      });
      allMenuIds = allMenuIds.filter((el, index) => index == allMenuIds.findIndex(item => item == el));

      if (this.roleData.menuIds.some(el => el.appType == this.activeType)) {
        this.roleData.menuIds.forEach(el => {
          if (el.appType == this.activeType) {
            el.menuIds = allMenuIds;
          }
        });
      } else {
        this.roleData.menuIds.push({ appType: this.activeType, menuIds: allMenuIds });
      }
      function getParentIds(menuId, menuList) {
        let result = [ menuId ];
        menuList.some(el => {
          if (el.menuId == menuId && el.parentId > 0) {
            result = result.concat(getParentIds(el.parentId, menuList));
          }
          return el.menuId == menuId;
        });
        return result;
      }
    },
    /**
     * @description: 应用小程序权限
     * @param {Array} appIds
     * @author: 无尘
     */
    onAppOpenChange(appIds) {
      this.tabList.some(el => {
        if (el.appType == this.activeType) {
          el.appIds = appIds;
          this.setChildrenDisable(el.menuList, appIds);
        }
        return el.appType == this.activeType;
      });
    },
    setChildrenDisable(menuList, appIds) {
      menuList.forEach(el => {
        let openFlag = false;
        appIds.some(item => {
          if (item.appId == el.project) {
            openFlag = item.openFlag;
          }
          return item.appId == el.project;
        });
        this.$set(el, 'disabled', openFlag == 0);
        if (Array.isArray(el.children)) {
          el.children = setDisable.call(this, el.children, openFlag == 0);
        }
      });
      function setDisable(menuList, openFlag) {
        return menuList.map(el => {
          this.$set(el, 'disabled', openFlag);
          if (Array.isArray(el.children)) {
            el.children = setDisable.call(this, el.children, openFlag);
          }
          return el;
        });
      }
    },
    /**
     * @description: 门店导购范围选择
     * @author: 无尘
     */
    onSeeTypeChange() {
      if (this.roleData.seeType == 0) {
        this.roleData.managerType = '0';
      }
    },
    /**
     * @description: 保存角色
     * @author: 无尘
     */
    onSave() {
      this.$refs.roleData.validate(vali => {
        if (!vali) return;
        const { roleId, roleName, menuIds, seeType, managerType } = this.roleData;
        const params = {
          roleId,
          roleName,
          menuIds: JSON.stringify(menuIds),
          wxEnterpriseId: this.wxEnterpriseId
        };
        this.loading = true;
        // 保存权限和资源范围配置
        editRole(params).then(succ.bind(this, roleId, '保存成功')).catch(() => this.loading = false);
        function succ(roleId, msg) {
          const prom = [];
          const params = { roleId, wxEnterpriseId: this.wxEnterpriseId };
          // 单独保存应用开关配置
          this.tabList.forEach(el => {
            if (el.appType == 4) {
              prom.push(new Promise(resolve => {
                saveAppSetting(Object.assign({}, params, { appType: el.appType, json: JSON.stringify(el.appIds) })).finally(resolve);
              }));
            }
          });
          // 单独保存门店导购范围配置
          prom.push(new Promise(resolve => {
            saveStoreRange({ roleId, seeType, managerType }).finally(resolve);
          }));
          Promise.all(prom).then(() => {
            this.$message.success(msg);
            this.$router.go(-1);
          }).finally(() => this.loading = false);
        }
      });
    }
  }
};
</script>

<style lang="less" scoped>
.edit-store-role-body {
  .nav-wrap {
    padding-left: 0;
  }
}
.edit-role {
  padding: 20px;
  background-color: #fff;
  height: 100%;
}
.resource-list {
  display: flex;
  justify-content: flex-start;
  align-items: flex-start;
  .resource-item {
    padding: 10px 20px;
    width: 236px;
    height: 72px;
    background: rgba(245,247,250,1);
    .app-name {
      font-size: 14px;
      font-weight: 700;
      color: @gray01;
      line-height: 20px;
    }
  }
}
.type-title {
  font-size: 14px;
  font-weight: 400;
  color: @gray02;
}
.type-label {
  margin-right: 30px;
  font-size: 14px;
  font-weight: 700;
  color: @gray01;
}
</style>
