<template>
  <div>
    <el-row>
      <h4><b>审批人设置</b></h4>
      <el-radio-group v-model="dataType" @change="changeDataType">
        <el-radio label="USERS">指定用户</el-radio>
        <el-radio label="ROLES">角色</el-radio>
        <el-radio label="DEPTS">部门</el-radio>
        <el-radio label="INITIATOR">发起人</el-radio>
      </el-radio-group>
    </el-row>
    <el-row>
      <div v-if="dataType === 'USERS'">
        <el-tag
          v-for="userText in selectedUser.text"
          :key="userText"
          effect="plain"
        >
          {{ userText }}
        </el-tag>
        <div class="element-drawer__button">
          <el-button
            size="small"
            type="primary"
            icon="plus"
            @click="onSelectUsers()"
            >添加用户</el-button
          >
        </div>
      </div>
      <div v-if="dataType === 'ROLES'">
        <el-select
          v-model="roleIds"
          multiple
          size="small"
          placeholder="请选择 角色"
          @change="changeSelectRoles"
        >
          <el-option
            v-for="item in roleOptions"
            :key="item.roleId"
            :label="item.roleName"
            :value="`ROLE${item.roleId}`"
            :disabled="item.status === 1"
          >
          </el-option>
        </el-select>
      </div>
      <div v-if="dataType === 'DEPTS'">
        <!-- :width="320"
        :height="400"
        size="small"
        :defaultProps="deptProps"
        multiple
        clearable
        nodeKey="id"
        :checkedKeys="deptIds"
        checkStrictly -->
        <!-- <tree-select :options="deptTreeData" @update:value="checkedDeptChange">
        </tree-select> -->
        <el-cascader
          :options="deptTreeData"
          :modelValue="deptCascaderData"
          clearable
          @change="checkedDeptChange"
          :props="{
            checkStrictly: true,
            value: 'id',
            multiple: true,
          }"
        ></el-cascader>
      </div>
    </el-row>
    <el-row>
      <div v-show="showMultiFlog">
        <el-divider />
        <h4><b>多实例审批方式</b></h4>
        <el-row>
          <el-radio-group v-model="multiLoopType" @change="changeMultiLoopType">
            <el-row
              :style="{
                width: '100%',
              }"
            >
              <el-radio label="Null">无</el-radio>
            </el-row>
            <el-row
              :style="{
                width: '100%',
              }"
              ><el-radio label="SequentialMultiInstance"
                >会签（需所有审批人同意）</el-radio
              ></el-row
            >
            <el-row
              :style="{
                width: '100%',
              }"
              ><el-radio label="ParallelMultiInstance"
                >或签（一名审批人同意即可）</el-radio
              ></el-row
            >
          </el-radio-group>
        </el-row>
        <el-row v-if="multiLoopType !== 'Null'">
          <el-tooltip
            content="开启后，实例需按顺序轮流审批"
            placement="top-start"
            @click.stop.prevent
          >
            <i class="header-icon el-icon-info"></i>
          </el-tooltip>
          <span class="custom-label">顺序审批：</span>
          <el-switch v-model="isSequential" @change="changeMultiLoopType" />
        </el-row>
      </div>
    </el-row>

    <!-- 候选用户弹窗 -->
    <el-dialog title="候选用户" v-model="userOpen" width="60%" append-to-body>
      <el-row type="flex" :gutter="20">
        <!--部门数据-->
        <el-col :span="7">
          <el-card shadow="never" style="height: 100%">
            <div slot="header">
              <span>部门列表</span>
            </div>
            <div class="head-container">
              <el-input
                v-model="deptName"
                placeholder="请输入部门名称"
                clearable
                size="small"
                prefix-icon="search"
                style="margin-bottom: 20px"
              />
              <el-tree
                :data="deptOptions"
                :props="deptProps"
                :expand-on-click-node="false"
                :filter-node-method="filterNode"
                ref="tree"
                default-expand-all
                @node-click="handleNodeClick"
              />
            </div>
          </el-card>
        </el-col>
        <el-col :span="17">
          <el-table
            ref="multipleTable"
            height="600"
            :data="userTableList"
            border
            @selection-change="handleSelectionChange"
          >
            <el-table-column type="selection" width="50" align="center" />
            <el-table-column label="用户名" align="center" prop="nickName" />
            <el-table-column label="部门" align="center" prop="dept.deptName" />
          </el-table>
          <pagination
            :total="userTotal"
            v-model:page="queryParams.pageNum"
            v-model:limit="queryParams.pageSize"
            @pagination="getUserList"
          />
        </el-col>
      </el-row>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="handleTaskUserComplete"
          >确 定</el-button
        >
        <el-button @click="userOpen = false">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { listUser, deptTreeSelect } from "@/api/system/user";
import { listRole } from "@/api/system/role";
import { addDateRange } from "@/utils/ruoyi";
import TreeSelect from "@/components/TreeSelect";
import { ref, reactive, watch } from "vue";
import { ElMessage } from "element-plus";
const testResult = ref([]);
const userTaskForm = {
  dataType: "",
  assignee: "",
  candidateUsers: "",
  candidateGroups: "",
  text: "",
};
const props = defineProps({
  id: String,
  type: String,
});
const { id, type } = toRefs(props);
const loading = ref(false);
const dataType = ref("USERS");
const userOpen = ref(false);
const deptName = ref(undefined);
const deptOptions = ref([]);
const deptTempOptions = ref([]);
const userTableList = ref([]);
const userTotal = ref(0);
const selectedUserDate = ref([]);
const roleOptions = ref([]);
const roleIds = ref([]);
const deptTreeData = ref([]);
const deptIds = ref([]);
const showMultiFlog = ref(false);
const isSequential = ref(false);
const multiLoopType = ref("Null");
const deptCascaderData = ref([]); // 部门级联 modelValue
const data = reactive({
  selectedUser: {
    ids: [],
    text: [],
  },
  deptProps: {
    children: "children",
    label: "label",
  },
  // 查询参数
  queryParams: {
    deptId: undefined,
  },
});
const { selectedUser, deptProps, queryParams } = toRefs(data);
let bpmnElement;
let multiLoopInstance;
let dateRange;

watch(
  id,
  () => {
    bpmnElement = window.bpmnInstances.bpmnElement;
    nextTick(() => resetTaskForm());
  },
  { immediate: true }
);

function resetTaskForm() {
  const bpmnElementObj = bpmnElement?.businessObject;
  if (!bpmnElementObj) {
    return;
  }
  clearOptionsData();
  dataType.value = bpmnElementObj["dataType"];
  if (dataType.value === "USERS") {
    let userIdData =
      bpmnElementObj["candidateUsers"] || bpmnElementObj["assignee"];
    let userText = bpmnElementObj["text"] || [];
    if (
      userIdData &&
      userIdData.toString().length > 0 &&
      userText &&
      userText.length > 0
    ) {
      selectedUser.value.ids = userIdData?.toString().split(",");
      selectedUser.value.text = userText?.split(",");
    }
    if (selectedUser.value.ids.length > 1) {
      showMultiFlog.value = true;
    }
  } else if (dataType.value === "ROLES") {
    getRoleOptions();
    let roleIdData = bpmnElementObj["candidateGroups"] || [];
    if (roleIdData && roleIdData.length > 0) {
      roleIds.value = roleIdData.split(",");
    }
    showMultiFlog.value = true;
  } else if (dataType.value === "DEPTS") {
    getDeptTreeData().then(() => {
      let deptIdData = bpmnElementObj["candidateGroups"] || [];
      if (deptIdData && deptIdData.length > 0) {
        deptIds.value = deptIdData.split(",");
        deptCascaderData.value = deptIds.value.map((id) => [
          ...getParentId(deptTreeData.value, id).reverse(),
        ]);
      }
    });
    showMultiFlog.value = true;
  }
  getElementLoop(bpmnElementObj);
}
/**
 * 清空选项数据
 */
function clearOptionsData() {
  selectedUser.value.ids = [];
  selectedUser.value.text = [];
  roleIds.value = [];
  deptIds.value = [];
}
/**
 * 跟新节点数据
 */
function updateElementTask() {
  const taskAttr = Object.create(null);
  for (let key in userTaskForm) {
    taskAttr[key] = userTaskForm[key];
  }
  window.bpmnInstances.modeling.updateProperties(bpmnElement, taskAttr);
}
/**
 * 查询部门下拉树结构
 */
function getDeptOptions() {
  return new Promise((resolve, reject) => {
    if (!deptOptions.value || deptOptions.value.length <= 0) {
      deptTreeSelect().then((response) => {
        deptTempOptions.value = response.data;
        deptOptions.value = response.data;
        resolve();
      });
    } else {
      reject();
    }
  });
}
/**
 * 查询部门下拉树结构（含部门前缀）
 */
function getDeptTreeData() {
  function refactorTree(data) {
    return data.map((node) => {
      let treeData = {
        id: `DEPT${node.id}`,
        label: node.label,
        parentId: node.parentId,
        weight: node.weight,
      };
      if (node.children && node.children.length > 0) {
        treeData.children = refactorTree(node.children);
      }
      return treeData;
    });
  }
  return new Promise((resolve, reject) => {
    if (!deptTreeData.value || deptTreeData.value.length <= 0) {
      getDeptOptions()
        .then(() => {
          deptTreeData.value = refactorTree(deptOptions.value);
          resolve();
        })
        .catch(() => {
          reject();
        });
    } else {
      resolve();
    }
  });
}
/**
 * 查询部门下拉树结构
 */
function getRoleOptions() {
  if (!roleOptions.value || roleOptions.value.length <= 0) {
    listRole().then((response) => (roleOptions.value = response.rows));
  }
}
/** 查询用户列表 */
function getUserList() {
  listUser(addDateRange(queryParams.value, dateRange)).then((response) => {
    userTableList.value = response.rows;
    userTotal.value = response.total;
  });
}
// 筛选节点
function filterNode(value, data) {
  if (!value) return true;
  return data.label.indexOf(value) !== -1;
}
// 节点单击事件
function handleNodeClick(data) {
  queryParams.value.deptId = data.id;
  getUserList();
}
// 关闭标签
const multipleTable = ref();
function handleClose(tag) {
  selectedUserDate.value.splice(selectedUserDate.value.indexOf(tag), 1);
  multipleTable.value.toggleRowSelection(tag);
}
// 多选框选中数据
function handleSelectionChange(selection) {
  selectedUserDate.value = selection;
}
function onSelectUsers() {
  selectedUserDate.value = [];
  multipleTable.value?.clearSelection();
  getDeptOptions();
  userOpen.value = true;
}
function handleTaskUserComplete() {
  if (!selectedUserDate.value || selectedUserDate.value.length <= 0) {
    ElMessage.error("请选择用户");
    return;
  }
  userTaskForm.dataType = "USERS";
  selectedUser.value.text = selectedUserDate.value.map((k) => k.nickName) || [];
  if (selectedUserDate.value.length === 1) {
    let data = selectedUserDate.value[0];
    userTaskForm.assignee = data.userId;
    userTaskForm.text = data.nickName;
    userTaskForm.candidateUsers = null;
    showMultiFlog.value = false;
    multiLoopType.value = "Null";
    changeMultiLoopType(multiLoopType.value);
  } else {
    userTaskForm.candidateUsers =
      selectedUserDate.value.map((k) => k.userId).join() || null;
    userTaskForm.text =
      selectedUserDate.value.map((k) => k.nickName).join() || null;
    userTaskForm.assignee = null;
    showMultiFlog.value = true;
  }
  updateElementTask();
  userOpen.value = false;
}
function changeSelectRoles(val) {
  userTaskForm.dataType = "ROLES";
  userTaskForm.candidateGroups = val.join() || null;
  let textArr = roleOptions.value.filter(
    (k) => val.indexOf(`ROLE${k.roleId}`) >= 0
  );
  userTaskForm.text = textArr?.map((k) => k.roleName).join() || null;
  updateElementTask();
}
// function checkedDeptChange(checkedIds, checkedData) {
//   userTaskForm.dataType = "DEPTS";
//   if (checkedIds && checkedIds.length > 0) {
//     deptIds.value = checkedIds;
//   }
//   if (checkedData && checkedData.length > 0) {
//     userTaskForm.candidateGroups = checkedData.map((k) => k.id).join() || null;
//     userTaskForm.text = checkedData.map((k) => k.label).join() || null;
//     updateElementTask();
//   }
// }

function findInDeptTree(id) {
  let hasFound = false, // 表示是否有找到id值
    result = null;
  var fn = function (data) {
    if (Array.isArray(data) && !hasFound) {
      // 判断是否是数组并且没有的情况下，
      data.forEach((item) => {
        if (item.id === id) {
          // 数据循环每个子项，并且判断子项下边是否有id值
          result = item; // 返回的结果等于每一项
          hasFound = true; // 并且找到id值
        } else if (item.children) {
          fn(item.children); // 递归调用下边的子项
        }
      });
    }
  };
  fn(deptTreeData.value); // 调用一下
  return result;
}
// 获取所有父级
function getParentId(list, id) {
  for (let i in list) {
    if (list[i].id == id) {
      return [list[i].id];
    }
    if (list[i].children) {
      let node = getParentId(list[i].children, id);
      if (node !== undefined) {
        return node.concat(list[i].id);
      }
    }
  }
}
function checkedDeptChange(checkedIds) {
  const ids = checkedIds.map((el) => el[el.length - 1]);
  const checkedData = ids.map((el) => findInDeptTree(el));

  userTaskForm.dataType = "DEPTS";
  if (ids && ids.length > 0) {
    deptIds.value = ids;
  }
  if (checkedData && checkedData.length > 0) {
    userTaskForm.candidateGroups = checkedData.map((k) => k.id).join() || null;
    userTaskForm.text = checkedData.map((k) => k.label).join() || null;

    updateElementTask();
  }
}
function changeDataType(val) {
  // 清空 userTaskForm 所有属性值
  Object.keys(userTaskForm).forEach((key) => (userTaskForm[key] = null));
  userTaskForm.dataType = val;
  if (val === "USERS") {
    if (
      selectedUser.value &&
      selectedUser.value.ids &&
      selectedUser.value.ids.length > 0
    ) {
      if (selectedUser.value.ids.length === 1) {
        userTaskForm.assignee = selectedUser.value.ids[0];
      } else {
        userTaskForm.candidateUsers = selectedUser.value.ids.join();
      }
      userTaskForm.text = selectedUser.value.text?.join() || null;
    }
  } else if (val === "ROLES") {
    getRoleOptions();
    if (roleIds.value && roleIds.value.length > 0) {
      userTaskForm.candidateGroups = roleIds.value.join() || null;
      let textArr = roleOptions.value.filter(
        (k) => roleIds.value.indexOf(`ROLE${k.roleId}`) >= 0
      );
      userTaskForm.text = textArr?.map((k) => k.roleName).join() || null;
    }
  } else if (val === "DEPTS") {
    getDeptTreeData();
    if (deptIds.value && deptIds.value.length > 0) {
      userTaskForm.candidateGroups = deptIds.value.join() || null;
      let textArr = [];
      let treeStarkData = JSON.parse(JSON.stringify(deptTreeData.value));
      deptIds.value.forEach((id) => {
        let stark = [];
        stark = stark.concat(treeStarkData);
        while (stark.length) {
          let temp = stark.shift();
          if (temp.children) {
            stark = temp.children.concat(stark);
          }
          if (id === temp.id) {
            textArr.push(temp);
          }
        }
      });
      userTaskForm.text = textArr?.map((k) => k.label).join() || null;
    }
  } else if (val === "INITIATOR") {
    userTaskForm.assignee = "${initiator}";
    userTaskForm.text = "流程发起人";
  }
  updateElementTask();
  if (
    val === "ROLES" ||
    val === "DEPTS" ||
    (val === "USERS" && selectedUser.value.ids.length > 1)
  ) {
    showMultiFlog.value = true;
  } else {
    showMultiFlog.value = false;
  }
  multiLoopType.value = "Null";
  changeMultiLoopType(multiLoopType.value);
}
function getElementLoop(businessObject) {
  if (!businessObject.loopCharacteristics) {
    multiLoopType.value = "Null";
    return;
  }
  isSequential.value = businessObject.loopCharacteristics.isSequential;
  if (businessObject.loopCharacteristics.completionCondition) {
    if (
      businessObject.loopCharacteristics.completionCondition.body ===
      "${nrOfCompletedInstances >= nrOfInstances}"
    ) {
      multiLoopType.value = "SequentialMultiInstance";
    } else {
      multiLoopType.value = "ParallelMultiInstance";
    }
  }
}
function changeMultiLoopType(type) {
  // 取消多实例配置
  if (type === "Null") {
    window.bpmnInstances.modeling.updateProperties(bpmnElement, {
      loopCharacteristics: null,
    });
    return;
  }
  multiLoopInstance = window.bpmnInstances.moddle.create(
    "bpmn:MultiInstanceLoopCharacteristics",
    { isSequential: isSequential.value }
  );
  // 更新多实例配置
  window.bpmnInstances.modeling.updateProperties(bpmnElement, {
    loopCharacteristics: multiLoopInstance,
    assignee: "${assignee}",
  });
  // 完成条件
  let completionCondition = null;
  // 会签
  if (type === "SequentialMultiInstance") {
    completionCondition = window.bpmnInstances.moddle.create(
      "bpmn:FormalExpression",
      { body: "${nrOfCompletedInstances >= nrOfInstances}" }
    );
  }
  // 或签
  if (type === "ParallelMultiInstance") {
    completionCondition = window.bpmnInstances.moddle.create(
      "bpmn:FormalExpression",
      { body: "${nrOfCompletedInstances > 0}" }
    );
  }
  // 更新模块属性信息
  window.bpmnInstances.modeling.updateModdleProperties(
    bpmnElement,
    multiLoopInstance,
    {
      collection: "${multiInstanceHandler.getUserIds(execution)}",
      elementVariable: "assignee",
      completionCondition,
    }
  );
}
onBeforeUnmount(() => {
  bpmnElement = null;
});
</script>

<style scoped lang="scss">
.el-row .el-radio-group {
  margin-bottom: 15px;
  .el-radio {
    line-height: 28px;
  }
}
.el-tag {
  margin-bottom: 10px;
  + .el-tag {
    margin-left: 10px;
  }
}

.custom-label {
  padding-left: 5px;
  font-weight: 500;
  font-size: 14px;
  color: #606266;
}
</style>
