<template>
  <div>
    <div class="i-layout-page-header">
      <PageHeader :title="$route.meta.title" :content="$route.meta.description" hidden-breadcrumb />
    </div>
    <Card :bordered="false" dis-hover class="ivu-mt">
      <view-table ref="table" view-code="Role" @create="$refs.form.open()">
        <template slot-scope="{ row }" slot="command">
          <Button size="small" :title="$t('Front_Btn_User')" type="info" custom-icon="fa fa-user" @click="$refs.userRoleTable.open({ roleID: row.id })"></Button>
          <Button size="small" :title="$t('Front_Btn_Edit')" type="primary" custom-icon="fa fa-edit" @click="$refs.form.open(row)"></Button>
          <Button size="small" :title="$t('Front_Btn_Permission')" type="primary" custom-icon="fa fa-desktop" @click="openPermission(row)"></Button>
          <Button size="small" :title="$t('Front_Btn_Param')" type="info" custom-icon="fa fa-ethernet" @click="$refs.rolePropertyTable.open({ roleID: row.id })"></Button>
          <Button size="small" :title="$t('Front_Btn_Remove')" type="warning" custom-icon="fa fa-trash-alt" @click="$refs.table.remove(row)"></Button>
        </template>
      </view-table>
    </Card>
    <modal-form ref="form" view-code="RoleEdit" @on-after-save="$refs.table.loadData()" />
    <modal-table ref="userRoleTable" view-code="RoleUser" @edit="({ row }) => editUserRole(row)">
      <template slot="filterCommand">
        <Button size="small" type="primary" custom-icon="fa fa-plus" @click="addUserRole()">{{ $t('Front_Btn_Add') }}</Button>
      </template>
    </modal-table>
    <modal-form ref="userRoleForm" view-code="RoleUserEdit" @on-after-save="$refs.userRoleTable.loadData()">
      <template slot="bottom">
        <view-table ref="userRoleDataTable" view-code="UserRoleDataEdit" :static="true">
          <template slot="column" slot-scope="{ row, code }">
            <template v-if="row.controlType === 'TextInput'">
              <Input type="text" size="small" v-model="row.propertyValue" />
            </template>
            <template v-else-if="row.controlType === 'NumberInput'">
              <Input type="number" size="small" number v-model="row.propertyValue" />
            </template>
            <template v-else-if="row.controlType === 'Select'">
              <Select size="small" v-model="row.propertyValue" clearable :transfer="true">
                <Option v-for="item in row._dataSource" :key="item.id" :value="item.id">{{ item.name }}</Option>
              </Select>
            </template>
            <template v-else-if="row.controlType === 'MultiSelect'">
              <Select
                size="small"
                :value="row.propertyValue == null ? null : JSON.parse(row.propertyValue)"
                @input="
                  $event => {
                    row.propertyValue = $event.length == 0 ? null : JSON.stringify($event);
                  }
                "
                :multiple="true"
                clearable
                :transfer="true"
              >
                <Option v-for="item in row._dataSource" :key="item.id" :value="item.id">{{ item.name }}</Option>
              </Select>
            </template>
            <template v-else-if="row.controlType === 'DialogSelect'">
              <dialog-select
                v-model="row.propertyValue"
                size="small"
                :source="row.source"
                :source-data-code="row.sourceDataCode"
                :source-display-code="row.sourceDisplayCode"
                :param="getParam(row)"
              ></dialog-select>
            </template>
            <template v-else-if="row.controlType === 'MultiDialogSelect'">
              <dialog-select
                v-model="row.propertyValue"
                size="small"
                :multi="true"
                :source="row.source"
                :source-data-code="row.sourceDataCode"
                :source-display-code="row.sourceDisplayCode"
                :param="getParam(row)"
              ></dialog-select>
            </template>
            <template v-else-if="row.controlType === 'Check'">
              <Checkbox :value="!!parseData(row, code)" @input="$event => setData(row, code, $event)" />
            </template>
          </template>
        </view-table>
      </template>
      <template slot="footer">
        <Button type="primary" custom-icon="fa fa-save" @click="userRoleSave">{{ $t('Front_Btn_Save') }}</Button>
      </template>
    </modal-form>
    <modal-table
      ref="rolePropertyTable"
      view-code="RolePropertyModal"
      @create="
        $refs.rolePropertyEdit.open({ roleID: $refs.rolePropertyTable.param.roleID }, () => {
          $refs.rolePropertyTable.loadData();
        })
      "
      @edit="
        ({ row, index }) =>
          $refs.rolePropertyEdit.open(row, () => {
            $refs.rolePropertyTable.loadData();
          })
      "
    ></modal-table>
    <role-property-edit ref="rolePropertyEdit" />
    <Modal
      v-model="permissionOpened"
      scrollable
      :mask-closable="layout.maskClosable"
      :draggable="layout.draggable"
      :sticky="true"
      :reset-drag-position="true"
      :width="800"
      :styles="{ top: '4vh' }"
    >
      <div slot="header">
        <span class="title">{{ $t('Front_Label_Permission') }}</span>
        <span class="description">{{ $t('Front_Label_Permission_Desc') }}</span>
      </div>
      <div class="ivu-ml-8 ivu-mr-8">
        <Form label-position="top" label-colon="：" class="ivu-mt">
          <Row :gutter="24" type="flex">
            <Col span="24">
              <FormItem :label="$t('Front_Label_Client_Type')" key="clientType" prop="clientType">
                <RadioGroup v-model="clientType" @on-change="loadPermission()">
                  <Radio v-for="item in clientTypes" :key="item.code" :label="item.code">
                    <span>{{ item.name }}</span>
                  </Radio>
                </RadioGroup>
              </FormItem>
            </Col>
          </Row>
        </Form>
        <Tree :data="permissions" show-checkbox></Tree>
      </div>
      <div slot="footer">
        <Button type="primary" custom-icon="fa fa-save" @click="savePermission()">{{ $t('Front_Btn_OK') }}</Button>
        <Button type="default" custom-icon="fa fa-times" @click="permissionOpened = false">{{ $t('Front_Btn_Close') }}</Button>
      </div>
    </Modal>
  </div>
</template>
<script>
  import customModelApi from '../../api/customModel';
  import mixinPage from '../../mixins/page';
  import modelApi from '../../api/model';
  import permissionApi from '../../api/permission';
  import rolePermissionApi from '../../api/rolePermission';
  import rolePropertyEdit from './rolePropertyEdit.vue';

  // 转换为tree列表对象
  var convertList = nodes => {
    if (!nodes) {
      return null;
    }

    return nodes.map(item => {
      if (!item.subPermissions) {
        item.subPermissions = [];
      }

      let children = convertList(item.subPermissions);

      if (item.permissionPoints) {
        // 权限点
        item.permissionPoints.forEach(permissionPoint => {
          children.push({
            id: item.id + '-' + permissionPoint.code,
            title: permissionPoint.name + ' (' + permissionPoint.code + ')',
            checked: permissionPoint.checked
          });
        });
      }

      return {
        id: item.id,
        title: item.name + ' (' + item.subName + ')',
        checked: item.checked && (children == null || children.length === 0),
        expand: children != null,
        children: children
      };
    });
  };

  // 获取选中项目
  var getChecked = data => {
    let checked = [];

    data.forEach(item => {
      if (item.checked) {
        checked.push(item.id);
      }

      if (item.children) {
        let children = getChecked(item.children);
        if (children.length > 0 && !item.checked) {
          checked.push(item.id);
        }
        checked = checked.concat(children);
      }
    });

    return checked;
  };

  export default {
    name: 'system-role',
    mixins: [mixinPage],
    components: { rolePropertyEdit },
    data() {
      return {
        roleID: null,
        permissions: [],
        permissionOpened: false,
        clientType: null,
        clientTypes: [],
        roleProperties: []
      };
    },
    computed: {},
    async created() {
      const res = await modelApi.query('Dict', { 'type.code': 'ClientType' });
      this.clientTypes = res.data;
      this.clientType = this.clientTypes[0].code;
    },
    methods: {
      // 权限
      async openPermission(row) {
        this.roleID = row.id;
        this.loadPermission();
        this.permissionOpened = true;
      },
      // 加载权限
      async loadPermission() {
        const res = await permissionApi.queryByRoleID(this.roleID, this.clientType);
        this.permissions = convertList(res);
      },
      // 保存权限
      savePermission() {
        let permissionIDs = getChecked(this.permissions);

        this.confirm('Front_Msg_Sure_To_Save', async () => {
          await rolePermissionApi.update(this.roleID, this.clientType, permissionIDs);
          this.success('Front_Msg_Success', () => {
            this.permissionOpened = false;
          });
        });
      },
      // 给角色添加用户
      async addUserRole() {
        this.$refs.userRoleForm.columns.find(item => item.code == 'userID').isReadonly = false;

        let roleID = this.$refs.userRoleTable.param.roleID;
        const res = await modelApi.query('RoleProperty', { roleID });

        this.roleProperties = res.data.map(item => {
          return {
            ...item,
            propertyValue: null
          };
        });
        await this.initDataSource();

        this.$refs.userRoleDataTable.loadData(this.roleProperties);
        this.$refs.userRoleForm.openDefault(this.$refs.userRoleTable.param);
      },
      // 用户角色编辑
      async editUserRole(row) {
        this.$refs.userRoleForm.columns.find(item => item.code == 'userID').isReadonly = true;

        let roleID = row.roleID;
        let res = await modelApi.query('RoleProperty', { roleID });
        let roleProperties = res.data;

        let userRoleDatas = [];

        res = await modelApi.query('UserRoleData', { userID: row.userID, roleID: row.roleID });
        userRoleDatas = res.data;

        this.roleProperties = roleProperties.map(roleProperty => {
          let userRoleData = userRoleDatas.find(item => item.propertyCode == roleProperty.propertyCode);

          return {
            ...roleProperty,
            propertyValue: userRoleData == null ? null : userRoleData.propertyValue
          };
        });
        await this.initDataSource();

        this.$refs.userRoleDataTable.loadData(this.roleProperties);
        this.$refs.userRoleForm.open(row);
      },
      // 加载数据源
      async initDataSource() {
        for (let i = 0; i < this.roleProperties.length; i++) {
          let item = this.roleProperties[i];
          if (!!(item.source || '').trim()) {
            if (item.controlType === 'Select' || item.controlType === 'MultiSelect') {
              item._dataSource = [];
              let param = this.getParam(item);

              // 选择框、单选框组
              if (param != null) {
                await this.fillDataSource(item, param);
              }
            }
          }
        }
      },
      // 填充数据源
      async fillDataSource(data, param) {
        // 参数完整，查询数据
        let res;
        if (data.isSourceCustom) {
          res = await customModelApi.query(data.source, param);
        } else {
          res = await modelApi.query(data.source, param);
        }
        res.data.forEach(item => {
          data._dataSource.push({
            id: !(data.sourceDataCode || '').trim() ? item.id : this.parseData(item, data.sourceDataCode),
            name: this.parseData(item, data.sourceDisplayCode)
          });
        });
      },
      // 获取参数
      getParam(data) {
        let param = {};

        if (!!(data.param || '').trim()) {
          // 有参数
          param = JSON.parse(data.param);

          // 填充参数
          for (let key in param) {
            // 常量
            let index = param[key].search(/^\[.*?\]$/);
            if (index === 0) {
              param[key] = param[key].substring(1, param[key].length - 1);
              continue;
            }

            // 变量
            let paramData = this.parseData(data, param[key]);

            if (paramData != null) {
              param[key] = paramData;
              continue;
            }

            // 参数不完整
            return null;
          }
        }

        return param;
      },
      // 用户角色保存
      async userRoleSave() {
        let isOK = await this.$refs.userRoleForm.validate();

        if (!isOK) {
          this.error('Front_Msg_Form_Validate_Fail');
        } else {
          this.confirm('Front_Msg_Sure_To_Save', async () => {
            let userRole = this.$refs.userRoleForm.getFullData();

            if (!userRole) {
              // 表格验证失败
              return;
            }

            let userRoleDatas = this.$refs.userRoleDataTable.getData();

            let data = {
              userRole,
              userRoleDatas
            };

            if (!userRole.id) {
              await modelApi.add('UserRole', data);
            } else {
              await modelApi.update('UserRole', data);
            }

            this.success('Front_Msg_Success', () => {
              this.$refs.userRoleDataTable.loadData([]);
              this.$refs.userRoleTable.loadData();
              this.$refs.userRoleForm.close();
            });
          });
        }
      }
    }
  };
</script>
