<template>
  <div>
    <sd-data-table
      ref="dataTable"
      data-url="api/framework/v1/sec-perm-manage/permGroupList"
      :columns="columns"
      :show-selection="
        (record) => {
          return record.dataSign !== 'sys'
        }
      "
      :actions="actions"
      row-key="id"
      :search-fields="['permGroupName']"
      :process-req="processReq"
      :process-res="processRes"
      @rowClick="rowClick"
    >
    </sd-data-table>
    <a-modal
      v-model="visible"
      destroy-on-close
      :class="$style.modal"
      :width="1000"
      :confirm-loading="loading"
      @ok="handleOk"
    >
      <span slot="title" :class="$style.modalTitle"
        >权限配置 <a-icon type="question-circle" @click="openDocs('权限说明')"
      /></span>
      <a-spin v-if="spining" :class="$style.spin" />
      <a-form v-else v-bind="formItemLayout">
        <a-form-item required label="权限集名称">
          <a-input v-model="form.permGroupName" />
        </a-form-item>
        <div
          v-if="form.dataSign === 'sys' && !form.grantors.length && !$route.query.appNodeId"
          :class="$style.sysTip"
        >
          <span>*该权限集默认授予所有人员</span>
        </div>
        <div v-else>
          <a-form-item v-if="form.dataSign !== 'sys'" label="授权角色">
            <sd-role-picker v-model="form.Role"></sd-role-picker>
          </a-form-item>
          <a-form-item v-if="form.dataSign !== 'sys'" label="授权部门">
            <sd-group-picker v-model="form.Group" :class="$style.selectGroup"></sd-group-picker>
            <a-checkbox v-model="form.includeLower">含下级</a-checkbox>
          </a-form-item>
          <a-form-item label="授权人员">
            <sd-user-picker
              v-model="form.User"
              :read-only="form.dataSign === 'sys'"
            ></sd-user-picker>
          </a-form-item>
        </div>
        <a-form-item label="权限集描述">
          <a-textarea v-model="form.permGroupDesc" autosize />
        </a-form-item>
        <div :class="$style.permContent">
          <div v-for="(item, index) in permsList" :key="index" :class="$style.permList">
            <h3>{{ item.formName }}:</h3>
            <div v-for="(info, i) in item.infos" :key="i">
              <a-form-item v-if="info.businessId" label="业务类型">
                <span>{{ info.businessName }}</span>
              </a-form-item>
              <a-form-item v-if="info.dataRules" label="数据权限">
                <div>
                  <a-checkbox-group
                    id="check"
                    :value="info.selectedRules"
                    :options="info.dataRules"
                    @change="(e) => rulesChange(e, info)"
                  >
                    <span slot="label" slot-scope="option" :class="$style.label">
                      <span>{{ option.ruleName }}</span>
                      <span v-if="option.ruleName === '本直属'"> </span>
                    </span>
                  </a-checkbox-group>
                  <a v-if="info.selectedRules.includes('CUSTOM')" @click="openCustom(item, info)"
                    >设置</a
                  >
                  <div :class="$style.label">
                    <a-checkbox
                      :checked="info.selectedRules.includes(info.singleValue)"
                      @change="(e) => singleCheckChange(e, info)"
                      >本直属</a-checkbox
                    >
                    <a-select
                      v-model="info.singleValue"
                      :get-popup-container="(triggerNode) => triggerNode.parentNode"
                      :class="$style.singleSelect"
                      :options="info.singleRuleOptions"
                      @change="(value) => singleChange(value, info)"
                    />
                    <a-select
                      id="select"
                      v-model="info.selectLevel"
                      :get-popup-container="(triggerNode) => triggerNode.parentNode"
                      mode="multiple"
                      :class="$style.levelSelect"
                      :options="departmentLevel"
                      @change="(value) => levelChange(value, info)"
                    />
                  </div>
                </div>
              </a-form-item>
              <a-form-item v-if="info.perms" label="操作权限">
                <a-checkbox
                  :disabled="!info.selectedRules.length"
                  :class="$style.allCheck"
                  :indeterminate="
                    info.perms.length > info.selectedPerms.length && info.selectedPerms.length > 0
                  "
                  :checked="info.perms.length === info.selectedPerms.length"
                  @change="(e) => allCheckChange(e, info)"
                >
                  全选
                </a-checkbox>
                <a-checkbox-group
                  v-model="info.selectedPerms"
                  :disabled="!info.selectedRules.length"
                  :options="info.perms"
                >
                  <span slot="label" slot-scope="option">{{ option.name }}</span>
                </a-checkbox-group>
              </a-form-item>
              <a-divider v-if="i < item.infos.length - 1" />
            </div>
          </div>
        </div>
      </a-form>
    </a-modal>
    <SdPermCustomSetting ref="custom" />
  </div>
</template>

<script>
import { Modal, Message } from 'ant-design-vue'
import { openDocs } from '@/common/docs/docs-tool'
import axios from '@/common/services/axios-instance'
import TableActionTypes from '@/common/services/table-action-types'
import TableColumnTypes from '../common/services/table-column-types'
import SdPermCustomSetting from './components/sd-perm-custom-setting.vue'
import components from './_import-components/sd-permission-setting-import'
const columns = [
  {
    dataIndex: 'permGroupName',
    title: '权限集名称',
    sdClickable: true,
  },
  {
    dataIndex: 'permGroupDesc',
    title: '权限集描述',
    sdClickable: true,
  },
  {
    dataIndex: 'roles',
    title: '授权角色',
    customRender: (text, record, index) =>
      `${record.grantors
        .filter((item) => item.type === 'ROLE')
        .map((u) => u.name)
        .join()}`,
  },
  {
    dataIndex: 'groups',
    title: '授权部门',
    customRender: (text, record, index) =>
      `${record.grantors
        .filter((item) => ['ORG', 'ORGS'].includes(item.type))
        .map((u) => u.name)
        .join()}`,
  },
  {
    dataIndex: 'users',
    title: '授权人员',
    customRender: (text, record, index) =>
      `${record.grantors
        .filter((item) => item.type === 'USER')
        .map((u) => u.name)
        .join()}`,
  },
  {
    title: '创建时间',
    sorter: true,
    dataIndex: 'creationTime',
    sdRender: TableColumnTypes.dateTime,
    sdCandidate: true,
  },
]
export default {
  name: 'SdPermissionSetting',
  metaInfo() {
    return {
      title: decodeURIComponent((location.hash + '&').split('&appName=')[1]?.split('&')[0] || ''),
    }
  },
  components: { ...components, SdPermCustomSetting },
  data() {
    return {
      columns,
      settingVisible: false,
      visible: false,
      loading: false,
      spining: false,

      actions: [
        {
          label: '新建',
          id: 'new',
          permission: 'onlPermSet-create',
          type: TableActionTypes.primary,
          callback: () => {
            this.getPermSetting()
          },
        },
        {
          label: '删除',
          id: 'delete',
          permission: 'onlPermSet-delete',
          type: TableActionTypes.batch,
          callback: (keys) => {
            Modal.confirm({
              title: '确认删除所选中的数据吗？',
              okType: 'danger',
              onOk: () => {
                axios
                  .delete(`api/framework/v1/sec-perm-manage/permGroupDelete/${keys.join()}`)
                  .then((res) => {
                    if (res.data) {
                      this.$refs.dataTable.clearSelection()
                      this.$refs.dataTable.refresh()
                    }
                  })
              },
            })
          },
        },
        {
          label: '权限初始化',
          id: 'init',
          permission: null,
          callback: () => {
            this.initPerms()
          },
        },
      ],
      appId: '',
      appNodeId: '',
      permsList: [],
      form: {
        permGroupName: '',
        permGroupDesc: '',
        Role: [],
        User: [],
        Group: [],
        includeLower: true,
      },
      formItemLayout: {
        labelCol: { span: 3 },
        wrapperCol: { span: 21 },
      },
      grantorsTypes: {
        User: 'USER',
        Role: 'ROLE',
        Group: 'ORG',
      },
      departmentLevel: [],
    }
  },
  created() {
    this.appId = this.$route.query.appId
    this.appNodeId = this.$route.query.appNodeId
    this.getDepartmentLevel()
  },
  methods: {
    openDocs,
    getDepartmentLevel() {
      axios.get('api/framework/v1/sec-perm-manage/departmentLevel').then((res) => {
        this.departmentLevel = res.data?.data.map((item) => ({
          label: item.name,
          value: item.code,
        }))
      })
    },
    levelChange(value, info) {
      info.singleRuleOptions.forEach((option) => {
        const newRules = JSON.parse(option.ruleValue)
        newRules.rules[0].classify = value.join()
        option.ruleValue = JSON.stringify(newRules)
      })
    },
    openCustom(form, info) {
      this.$refs.custom.open(form, info)
    },
    initPerms() {
      axios
        .get(`api/framework/v1/sec-perm-manage/initPermGroup/${this.appNodeId || this.appId}`)
        .then(() => {
          Message.success('权限初始化完成')
          this.$refs.dataTable.refresh()
        })
    },
    processReq(req) {
      const { columns, ...params } = req.data
      req.data = {
        appId: this.appNodeId || this.appId,
        query: params,
      }
      return req
    },
    processRes(res) {
      res.totalSize = res.data.length
      return res
    },
    allCheckChange(e, info) {
      const checked = e.target.checked
      info.selectedPerms = checked
        ? info.perms.map((perm) => perm.value)
        : [`onlhead:${info.formId}-view`]
    },
    getPermSetting() {
      this.spining = true
      this.visible = true
      this.form = {
        permGroupName: '',
        permGroupDesc: '',
        Role: [],
        User: [],
        Group: [],
        includeLower: true,
        dataSign: 'cus',
      }
      this.permsList = []
      return axios
        .get(`api/framework/v1/sec-perm-manage/permSetList/${this.appNodeId || this.appId}`)
        .then((res) => {
          if (res.data) {
            const data = res.data.data
            this.permsList = data
              ?.filter((d) => d.isFlow === 0 || d.business)
              .map((item) => {
                const singleRuleOptions = item.dataRules
                  .filter((d) => d.ruleName.includes('本直属'))
                  .map((item) => {
                    item.value = item.ruleCode
                    const re = /\((.+?)\)/g
                    const text = item.ruleName.match(re)?.[0]
                    return {
                      label: text?.substring(1, text.length - 1),
                      value: item.value,
                      ruleCode: item.value,
                      ruleValue: item.ruleValue,
                    }
                  }, [])
                item.dataRules = item.dataRules
                  .filter((d) => d.ruleName.indexOf('本直属') === -1)
                  .map((item) => {
                    item.label = item.ruleName
                    item.value = item.ruleCode
                    return item
                  })
                // .filter((s, i, arr) => i === arr.findIndex((a) => a.ruleName === s.ruleName))
                item.perms?.forEach((perm) => {
                  perm.value = perm.code
                })
                return {
                  formName: item.formName,
                  formId: item.formId,
                  moduleId: item.moduleId,
                  infos: item.business
                    ? item.business.map((b) => ({
                        businessId: b.id,
                        businessName: b.name,
                        formId: item.formId,
                        perms: item.perms,
                        dataRules: item.dataRules,
                        origin: item.origin,
                        singleRuleOptions,
                        singleValue: 'SUBDEPT',
                        selectedPerms: [],
                        selectedRules: [],
                        selectedGroup: [],
                        selectLevel: [],
                      }))
                    : [
                        {
                          dataRules: item.dataRules,
                          perms: item.perms,
                          formId: item.formId,
                          origin: item.origin,
                          singleRuleOptions,
                          singleValue: 'SUBDEPT',
                          selectedPerms: [],
                          selectLevel: [],
                          selectedRules: [],
                          selectedGroup: [],
                        },
                      ],
                }
              })
            this.spining = false
          }
        })
    },
    rulesChange(value, info) {
      const singleValue = info.selectedRules.find((item) => item === info.singleValue)
      if (singleValue) {
        info.selectedRules = [
          ...value,
          info.selectedRules.find((item) => item === info.singleValue),
        ]
      } else info.selectedRules = [...value]
      if (!info.perms) return
      this.handlePerm(info)
    },
    handlePerm(info) {
      if (!info.selectedRules.length) info.selectedPerms = []
      const viewPerm = info.origin === 'vue' ? `${info.formId}-view` : `onlhead:${info.formId}-view`
      const viewRule = info.perms.find((perm) => perm.value === viewPerm)
      viewRule.disabled = info.selectedRules && info.selectedRules.length > 0
      if (!info.selectedPerms.includes(viewPerm) && info.selectedRules.length)
        info.selectedPerms.push(viewPerm)
    },
    singleCheckChange(e, info) {
      // 本直属权限
      const value = e.target.checked
      if (value) {
        info.selectedRules.push(info.singleValue)
        this.singleChange(info.singleValue, info)
      } else info.selectedRules = info.selectedRules.filter((rule) => rule !== info.singleValue)
      this.handlePerm(info)
    },
    singleChange(value, info) {
      if (info.selectedRules.length) {
        info.selectedRules = info.selectedRules
          .filter((f) => !info.singleRuleOptions.map((i) => i.value).includes(f))
          .concat([value])
      }
    },
    rowClick(record) {
      axios.get(`api/framework/v1/sec-perm-manage/permGroupGet/${record.id}`).then((res) => {
        if (res.data) {
          const data = res.data.data
          const grantors = data.grantors.map((g) => {
            const item = { ...g }
            item.type =
              g.type === 'ORGS'
                ? 'Group'
                : Object.keys(this.grantorsTypes).find((key) => this.grantorsTypes[key] === g.type)
            return item
          })
          const list = grantors
            .map((item) => item.type)
            .reduce((res, item, i) => {
              res[item] = [...(res[item] || []), grantors[i]]
              return res
            }, {})
          this.getPermSetting().then(() => {
            this.form = {
              ...list,
              dataSign: data.dataSign,
              id: data.id,
              permGroupName: data.permGroupName,
              permGroupDesc: data.permGroupDesc,
              grantors,
              includeLower: data.grantors.some((g) => g.type === 'ORGS'),
            }
            const newPermRanges = data.permRanges
              .filter((f) => f.ruleCode !== null)
              .reduce((res, item) => {
                let customValue = ''
                const hadForm = res.find((r) => r.formId === item.formId)
                if (item.ruleCode === 'CUSTOM') {
                  customValue = item.ruleValue
                }
                const newInfo = {
                  businessId: item.businessId,
                  selectedPerms: [item.code],
                  selectedRules: [item.ruleCode],
                  customValue,
                }
                if (hadForm) {
                  const businessInfo = hadForm.infos.find((a) => a.businessId === item.businessId)
                  if (businessInfo) {
                    businessInfo.selectedPerms = [
                      ...new Set([...(businessInfo.selectedPerms || []), item.code]),
                    ]
                    businessInfo.selectedRules = [
                      ...new Set([...(businessInfo.selectedRules || []), item.ruleCode]),
                    ]
                    businessInfo.customValue = customValue
                  } else {
                    hadForm.infos.push(newInfo)
                  }
                } else {
                  res.push({
                    formId: item.formId,
                    infos: [newInfo],
                  })
                }
                return res
              }, [])
            this.permsList.forEach((perm) => {
              const findPerm = newPermRanges.find((newp) => newp.formId === perm.formId)
              if (findPerm) {
                perm.infos.forEach((p) => {
                  findPerm.infos.forEach((info) => {
                    const singleValue = p.singleRuleOptions
                      .map((i) => i.value)
                      .find((f) => info.selectedRules.includes(f))
                    // 处理本直属权限
                    if (singleValue) {
                      info.singleValue = singleValue
                      const levelRule = data.permRanges.find(
                        (d) =>
                          info.selectedRules.includes(d.ruleCode) && findPerm.formId === d.formId
                      )
                      // 处理level
                      if (levelRule) {
                        const classify = JSON.parse(levelRule.ruleValue)?.rules?.[0]?.classify
                        info.selectLevel = classify ? classify.split(',') : []
                        this.levelChange(info.selectLevel, p)
                      }
                    }
                  })
                  if (!p.businessId) {
                    Object.assign(p, {
                      ...findPerm.infos[0],
                    })
                  }
                  const newInfo = findPerm.infos.find((f) => f.businessId === p.businessId)
                  if (newInfo) {
                    Object.assign(p, newInfo)
                  }
                })
              }
            })
          })
        }
      })
    },
    settingOK() {
      this.settingVisible = false
    },
    handleOk() {
      this.loading = true
      const total = []
      const {
        permGroupName,
        permGroupDesc,
        dataSign,
        grantors: oldGrantors,
        id,
        includeLower,
        ...list
      } = this.form
      const grantorsArr = Object.values(list).flat()
      if (dataSign === 'cus' && (!permGroupName || !Object.values(grantorsArr).length)) {
        Message.warn('权限集名称必填且授权角色、部门、人员至少选择一项')
        this.loading = false
        return
      }
      const grantors = grantorsArr.map((item) => {
        return {
          code: item.code,
          name: item.name,
          type: item.type === 'Group' && includeLower ? 'ORGS' : this.grantorsTypes[item.type],
        }
      })
      this.permsList
        .map((item) => item.infos)
        .flat()
        .forEach((item) => {
          const hasLengthAttr = item.selectedPerms.length ? 'selectedPerms' : 'selectedRules'
          const firstArr =
            hasLengthAttr === 'selectedPerms' ? item.selectedPerms : item.selectedRules
          firstArr.forEach((perm) => {
            const base = {
              formId: item.formId,
              type: 'PERM',
              origin: item.origin || 'ONL',
            }
            if (item.businessId) base.businessId = item.businessId
            if (hasLengthAttr === 'selectedPerms') {
              base.code = perm
            } else {
              base.ruleCode = perm
              base.ruleValue =
                perm === 'CUSTOM'
                  ? item.customValue
                  : [...item.dataRules, ...(item.singleRuleOptions || [])].find(
                      (i) => i.ruleCode === perm
                    )?.ruleValue
            }
            const twoArr =
              hasLengthAttr === 'selectedPerms' ? item.selectedRules : item.selectedPerms
            if (twoArr.length) {
              twoArr.forEach((rule) => {
                const twoBase = {
                  ...base,
                  formId: item.formId,
                  type: 'PERM',
                  origin: item.origin || 'ONL',
                }
                if (item.businessId) twoBase.businessId = item.businessId
                if (hasLengthAttr === 'selectedPerms') {
                  twoBase.ruleCode = rule
                  twoBase.ruleValue =
                    rule === 'CUSTOM'
                      ? item.customValue
                      : [...item.dataRules, ...(item.singleRuleOptions || [])].find(
                          (i) => i.ruleCode === rule
                        )?.ruleValue
                } else {
                  twoBase.code = rule
                }
                total.push(twoBase)
              })
            } else total.push(base)
          })
        })
      const params = {
        permGroupName,
        permGroupDesc,
        appId: this.appNodeId || this.appId,
        grantors,
        dataSign,
        permRanges: total,
      }
      if (this.form.id) params.id = this.form.id
      axios
        .post('api/framework/v1/sec-perm-manage/permGroupGrant', params)
        .then((res) => {
          if (res.data) {
            this.visible = false
            this.$refs.dataTable.refresh()
          }
        })
        .finally(() => {
          this.loading = false
        })
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.modal {
  .modal-title {
    position: relative;
    z-index: 1;
    :global .anticon {
      cursor: pointer;
    }
  }

  :global .ant-modal {
    /* stylelint-disable-next-line  */
    top: 0 !important;
    :global .ant-modal-content {
      height: 100vh;
      :global .ant-modal-body {
        min-height: calc(100vh - 120px);
      }
    }
  }
  :global .ant-select {
    width: 100%;
  }
  :global .ant-row {
    margin-bottom: 8px;
  }
  .perm-list {
    padding: 10px 20px;
    margin: 10px 0;
    border: 1px #000 dashed;
  }

  :global .ant-divider {
    margin: 10px 0;
  }
}
.label {
  display: flex;
  align-items: center;
  :global .anticon-question-circle {
    margin-left: 5px;
  }
  .single-select {
    width: 130px;
    margin: 0 5px;
  }
  .level-select {
    flex: 1;
  }
}
.sys-tip {
  display: flex;
  justify-content: flex-end;
  span {
    display: inline-block;
    width: 87.5%;
  }
}
.spin {
  width: 100%;
  text-align: center;
}
.select-group {
  width: 85%;
  margin-right: 10px;
}
</style>
