<!-- eslint-disable max-len -->
<template>
  <div>
    <Modal ref="modal" v-model="opened" scrollable :mask-closable="layout.maskClosable" :draggable="layout.draggable" :sticky="true" :reset-drag-position="true" :width="'90VW'">
      <template #header>
        <div>
          <slot name="header">
            <span class="title">{{ data.process ? data.process.name : $t('Front_Label_Process_Definition') }}</span>
            <span class="description"></span>
          </slot>
        </div>
      </template>
      <div class="ivu-ml-8 ivu-mr-8">
        <svg
          id="svg"
          xmlns="http://www.w3.org/2000/svg"
          version="1.1"
          width="100%"
          height="650"
          style="-moz-user-select: none; -webkit-user-select: none; user-select: none"
          @mouseup="mouseUp"
          @mousemove="mousemove"
        >
          <defs>
            <symbol :id="'iconUser_' + id" viewBox="0 0 1024 1024">
              <path
                d="M908 799.542857a427.428571 427.428571 0 0 0-92.114286-136.571428 429.291429 429.291429 0 0 0-136.571428-92.114286c-0.457143-0.228571-0.914286-0.342857-1.371429-0.571429C749.142857 518.857143 795.428571 435.085714 795.428571 340.571429c0-156.571429-126.857143-283.428571-283.428571-283.428572S228.571429 184 228.571429 340.571429c0 94.514286 46.285714 178.285714 117.485714 229.828571-0.457143 0.228571-0.914286 0.342857-1.371429 0.571429-51.2 21.6-97.142857 52.571429-136.571428 92.114285a429.291429 429.291429 0 0 0-92.114286 136.571429A424.8 424.8 0 0 0 82.285714 957.485714a9.142857 9.142857 0 0 0 9.142857 9.371429h68.571429c5.028571 0 9.028571-4 9.142857-8.914286 2.285714-88.228571 37.714286-170.857143 100.342857-233.485714 64.8-64.8 150.857143-100.457143 242.514286-100.457143s177.714286 35.657143 242.514286 100.457143C817.142857 787.085714 852.571429 869.714286 854.857143 957.942857c0.114286 5.028571 4.114286 8.914286 9.142857 8.914286h68.571429a9.142857 9.142857 0 0 0 9.142857-9.371429c-1.142857-54.628571-12.457143-107.771429-33.714286-157.942857zM512 537.142857c-52.457143 0-101.828571-20.457143-138.971429-57.6S315.428571 393.028571 315.428571 340.571429c0-52.457143 20.457143-101.828571 57.6-138.971429S459.542857 144 512 144s101.828571 20.457143 138.971429 57.6S708.571429 288.114286 708.571429 340.571429c0 52.457143-20.457143 101.828571-57.6 138.971428S564.457143 537.142857 512 537.142857z"
              ></path>
            </symbol>
            <symbol :id="'iconApi_' + id" viewBox="0 0 1024 1024">
              <path
                d="M975.657143 96.914286l-48.457143-48.457143c-1.828571-1.828571-4.114286-2.628571-6.514286-2.628572s-4.685714 0.914286-6.514285 2.628572l-86.971429 86.971428a227.737143 227.737143 0 0 0-128.114286-39.2c-58.514286 0-117.028571 22.285714-161.714285 66.971429L420.914286 279.657143a9.177143 9.177143 0 0 0 0 12.914286L731.428571 603.085714c1.828571 1.828571 4.114286 2.628571 6.514286 2.628572 2.285714 0 4.685714-0.914286 6.514286-2.628572l116.457143-116.457143c78.742857-78.857143 88-200.8 27.771428-289.714285l86.971429-86.971429c3.542857-3.657143 3.542857-9.485714 0-13.028571zM805.828571 431.657143l-67.885714 67.885714-213.485714-213.485714 67.885714-67.885714c28.457143-28.457143 66.4-44.228571 106.742857-44.228572 40.342857 0 78.171429 15.657143 106.742857 44.228572 28.457143 28.457143 44.228571 66.4 44.228572 106.742857 0 40.342857-15.771429 78.171429-44.228572 106.742857z m-217.371428 120a9.177143 9.177143 0 0 0-12.914286 0L499.428571 627.771429 396.228571 524.571429l76.228572-76.228572c3.542857-3.542857 3.542857-9.371429 0-12.914286L430.857143 393.828571a9.177143 9.177143 0 0 0-12.914286 0L341.714286 470.057143l-49.142857-49.142857a8.971429 8.971429 0 0 0-6.514286-2.628572c-2.285714 0-4.685714 0.914286-6.514286 2.628572L163.2 537.371429c-78.742857 78.857143-88 200.8-27.771429 289.714285l-86.971428 86.971429a9.177143 9.177143 0 0 0 0 12.914286l48.457143 48.457142c1.828571 1.828571 4.114286 2.628571 6.514285 2.628572s4.685714-0.914286 6.514286-2.628572l86.971429-86.971428c38.514286 26.171429 83.314286 39.2 128.114285 39.2 58.514286 0 117.028571-22.285714 161.714286-66.971429l116.457143-116.457143c3.542857-3.542857 3.542857-9.371429 0-12.914285l-49.142857-49.142857 76.228571-76.228572c3.542857-3.542857 3.542857-9.371429 0-12.914286l-41.828571-41.371428zM431.657143 805.828571a150.08 150.08 0 0 1-106.742857 44.228572c-40.342857 0-78.171429-15.657143-106.742857-44.228572a150.08 150.08 0 0 1-44.228572-106.742857c0-40.342857 15.657143-78.171429 44.228572-106.742857l67.885714-67.885714 213.485714 213.485714-67.885714 67.885714z"
              ></path>
            </symbol>
            <marker :id="'arrowStart_' + id" markerWidth="10" markerHeight="10" refX="2" refY="2" orient="auto">
              <circle cx="2" cy="2" r="2" fill="#000" />
            </marker>
            <marker :id="'arrowEnd_' + id" markerWidth="10" markerHeight="10" refX="6" refY="2" orient="auto">
              <path d="M0,0 L0,4 L6,2 Z" style="fill: #000" />
            </marker>
            <path v-for="(item, index) in data.outcomes" :key="index" :id="'outcome_' + id + '_' + item.pid" :d="getOutcomPath(item)" />
          </defs>
          <rect v-if="!readonly" fill="#ddd" stroke-width="0" rx="0" stroke="#000" :x="10" :y="10" :width="30 * 2 + setting.rectWidth" :height="630"></rect>
          <!-- 开始 -->
          <template v-for="(item, index) in displayActivities" :key="index">
            <template v-if="item.activityType === 'Begin'">
              <rect
                fill="#fff"
                stroke-width="2"
                rx="25"
                stroke="#000"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
              ></rect>
              <text fill="#000" :x="item.x" :y="item.y" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <rect
                opacity="0"
                rx="25"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></rect>
            </template>
            <!-- 结束 -->
            <template v-else-if="item.activityType === 'End'">
              <rect
                fill="#fff"
                stroke-width="2"
                rx="25"
                stroke="#000"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
              ></rect>
              <text fill="#000" :x="item.x" :y="item.y" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <rect
                opacity="0"
                rx="25"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></rect>
            </template>
            <!-- 交互 -->
            <template v-else-if="item.activityType === 'Interactive'">
              <rect
                :fill="getColor(item)"
                stroke-width="2"
                rx="5"
                stroke="#000"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
              ></rect>
              <use
                :x="item.x - setting.rectWidth / 2 + 2"
                :y="item.y - setting.rectHeight / 2 + 2"
                :width="setting.rectHeight / 3"
                :height="setting.rectHeight / 3"
                :href="'#iconUser_' + id"
              ></use>
              <text fill="#000" :x="item.x" :y="item.y" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <rect
                opacity="0"
                rx="5"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></rect>
            </template>
            <!-- 判断 -->
            <template v-if="item.activityType === 'Judgement'">
              <polygon
                :points="
                  item.x -
                  setting.rectWidth / 2 +
                  ' ' +
                  item.y +
                  ' ' +
                  item.x +
                  ' ' +
                  (item.y - setting.rectHeight / 2) +
                  ' ' +
                  (item.x + setting.rectWidth / 2) +
                  ' ' +
                  item.y +
                  ' ' +
                  item.x +
                  ' ' +
                  (item.y + setting.rectHeight / 2)
                "
                fill="#fff"
                stroke-width="2"
                stroke="#000"
              ></polygon>
              <text fill="#000" :x="item.x" :y="item.y" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <polygon
                opacity="0"
                :points="
                  item.x -
                  setting.rectWidth / 2 +
                  ' ' +
                  item.y +
                  ' ' +
                  item.x +
                  ' ' +
                  (item.y - setting.rectHeight / 2) +
                  ' ' +
                  (item.x + setting.rectWidth / 2) +
                  ' ' +
                  item.y +
                  ' ' +
                  item.x +
                  ' ' +
                  (item.y + setting.rectHeight / 2)
                "
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></polygon>
            </template>
            <!-- API -->
            <template v-if="item.activityType === 'Service'">
              <rect
                fill="#fff"
                stroke-width="2"
                rx="5"
                stroke="#000"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
              ></rect>
              <use
                :x="item.x - setting.rectWidth / 2 + 2"
                :y="item.y - setting.rectHeight / 2 + 2"
                :width="setting.rectHeight / 3"
                :height="setting.rectHeight / 3"
                :href="'#iconApi_' + id"
              ></use>
              <text fill="#000" :x="item.x" :y="item.y" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <rect
                opacity="0"
                rx="5"
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></rect>
            </template>
            <!-- 并行开始 -->
            <template v-if="item.activityType === 'ParallelStart'">
              <line
                :x1="item.x - setting.rectWidth / 2"
                :y1="item.y - setting.rectHeight / 6"
                :x2="item.x + setting.rectWidth / 2"
                :y2="item.y - setting.rectHeight / 6"
                style="stroke: rgb(0, 0, 0); stroke-width: 2"
              ></line>
              <line
                :x1="item.x - setting.rectWidth / 2"
                :y1="item.y + setting.rectHeight / 6"
                :x2="item.x + setting.rectWidth / 2"
                :y2="item.y + setting.rectHeight / 6"
                style="stroke: rgb(0, 0, 0); stroke-width: 2"
              ></line>
              <text fill="#000" :x="item.x" :y="item.y + setting.rectHeight / 2" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <rect
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
                opacity="0"
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></rect>
            </template>
            <!-- 并行结束 -->
            <template v-if="item.activityType === 'ParallelEnd'">
              <circle :cx="item.x" :cy="item.y" :r="setting.rectHeight / 3" stroke="black" stroke-width="2" fill="#fff"></circle>
              <text fill="#000" :x="item.x" :y="item.y + (setting.rectHeight * 3) / 5" :font-size="setting.rectFontSize" text-anchor="middle" dominant-baseline="middle">
                {{ item.name }}
              </text>
              <rect
                :x="item.x - setting.rectWidth / 2"
                :y="item.y - setting.rectHeight / 2"
                :width="setting.rectWidth"
                :height="setting.rectHeight"
                opacity="0"
                @mousedown="e => mousedownActivity(item, e)"
                @mouseup="mouseupActivity(item)"
                @dblclick="dblclickActivity(item, index)"
              ></rect>
            </template>
            <!-- 中心点 -->
            <circle
              :cx="item.x"
              :cy="item.y"
              v-if="!item.isTool"
              r="7"
              stroke="black"
              stroke-width="0"
              fill="orange"
              :opacity="item.activeCenter ? 0.4 : 0"
              @mouseenter="mouseenterCenter(item)"
              @mouseleave="mouseleaveCenter(item)"
              @mousedown="mousedownCenter(item)"
              @mouseup="mouseupActivity(item)"
            />
          </template>
          <template v-for="(item, index) in data.outcomes" :key="index">
            <template v-for="(line, lineIndex) in getLines(item)" :key="lineIndex">
              <line
                :x1="line.x1"
                :y1="line.y1"
                :x2="line.x2"
                :y2="line.y2"
                style="stroke: rgb(0, 0, 0); stroke-width: 2"
                :marker-start="line.markerStart"
                :marker-end="line.markerEnd"
                @dblclick="dblclickOutcome(item, index)"
              ></line>
            </template>
            <template v-for="(point, pointIndex) in getPoints(item)" :key="pointIndex">
              <circle
                :cx="point.x"
                :cy="point.y"
                r="3"
                stroke="#000"
                stroke-width="2"
                fill="#000"
                @mousedown="e => mousedownPoint(item, point, pointIndex, e)"
                @mouseup="mouseupPoint(item, pointIndex)"
              />
            </template>
            <text fill="#000" :font-size="setting.lineFontSize" text-anchor="middle" :dominant-baseline="'text-after-edge'" @dblclick="dblclickOutcome(item, index)">
              <textPath :href="'#outcome_' + id + '_' + item.pid" startOffset="50%">
                {{ item.name }}
              </textPath>
            </text>
          </template>
          <line
            v-if="isCreatingOutcome"
            :x1="activityFrom.x"
            :y1="activityFrom.y"
            :x2="current.x"
            :y2="current.y"
            style="stroke: rgb(0, 0, 0); stroke-width: 2; pointer-events: none"
            :marker-start="'url(#arrowStart_' + id + ')'"
            :marker-end="'url(#arrowEnd_' + id + ')'"
          ></line>
        </svg>
      </div>
      <template #footer>
        <div>
          <slot name="footer">
            <Button v-if="!readonly" type="primary" custom-icon="fa fa-save" @click="save">{{ $t('Front_Btn_Save') }}</Button>
            <Button v-if="!readonly" type="primary" custom-icon="fa fa-upload" @click="publish">{{ $t('Front_Btn_Publish') }}</Button>
          </slot>
          <Button type="default" custom-icon="fa fa-times" @click="close">{{ $t('Front_Btn_Close') }}</Button>
        </div>
      </template>
    </Modal>
    <modal-form ref="interactiveForm" view-code="InteractiveActivityEdit" @on-change="interactiveFormChange">
      <template #footer>
        <Button type="primary" custom-icon="fa fa-save" @click="saveActivity">{{ $t('Front_Btn_OK') }}</Button>
        <Button type="warning" custom-icon="fa fa-times" @click="removeActivity">{{ $t('Front_Btn_Remove') }}</Button>
      </template>
      <template #bottom>
        <view-table
          ref="destinationRoleParamTable"
          title="角色参数"
          v-show="$refs.interactiveForm && $refs.interactiveForm.data && $refs.interactiveForm.data.destinationMode == 'Role'"
          :static="true"
          :parent-data="data"
          view-code="DestinationRoleParam"
        ></view-table>
      </template>
      <template #column="{ data, code }">
        <template v-if="code == 'rejectActivityPid'">
          <Select v-model="data[code]" :clearable="true" placeholder="退回发起人" :transfer="true" v-if="activities">
            <Option
              v-for="item in activities.filter(item => {
                return (
                  item.pid != data.pid &&
                  (item.activityType == 'Interactive' || item.activityType == 'Judgement' || item.activityType == 'Service' || item.activityType == 'ParallelStart')
                );
              })"
              :key="item.pid"
              :value="item.pid"
            >
              {{ item.name }}
            </Option>
          </Select>
        </template>
        <template v-if="code == 'rejectActivityPids'">
          <Select
            :model-value="parseArrayData(data, code)"
            @update:model-value="$event => setArrayData(data, code, $event)"
            :clearable="true"
            :transfer="true"
            :multiple="true"
            v-if="activities"
          >
            <Option
              v-for="item in activities.filter(item => {
                return (
                  item.pid != data.pid &&
                  (item.activityType == 'Interactive' || item.activityType == 'Judgement' || item.activityType == 'Service' || item.activityType == 'ParallelStart')
                );
              })"
              :key="item.pid"
              :value="item.pid"
            >
              {{ item.name }}
            </Option>
          </Select>
        </template>
      </template>
    </modal-form>
    <modal-form ref="serviceForm" view-code="ServiceActivityEdit">
      <template #footer>
        <Button type="primary" custom-icon="fa fa-save" @click="saveActivity">{{ $t('Front_Btn_OK') }}</Button>
        <Button type="warning" custom-icon="fa fa-times" @click="removeActivity">{{ $t('Front_Btn_Remove') }}</Button>
      </template>
    </modal-form>
    <modal-form ref="activityForm" view-code="ActivityEdit">
      <template #footer>
        <Button type="primary" custom-icon="fa fa-save" @click="saveActivity">{{ $t('Front_Btn_OK') }}</Button>
        <Button type="warning" custom-icon="fa fa-times" @click="removeActivity">{{ $t('Front_Btn_Remove') }}</Button>
      </template>
    </modal-form>
    <modal-form ref="judgementOutcomeForm" view-code="JudgementOutcomeEdit">
      <template #footer>
        <Button type="primary" custom-icon="fa fa-save" @click="saveOutcome">{{ $t('Front_Btn_OK') }}</Button>
        <Button type="warning" custom-icon="fa fa-times" @click="removeOutcome">{{ $t('Front_Btn_Remove') }}</Button>
      </template>
    </modal-form>
    <modal-form ref="outcomeForm" view-code="OutcomeEdit">
      <template #footer>
        <Button type="primary" custom-icon="fa fa-save" @click="saveOutcome">{{ $t('Front_Btn_OK') }}</Button>
        <Button type="warning" custom-icon="fa fa-times" @click="removeOutcome">{{ $t('Front_Btn_Remove') }}</Button>
      </template>
    </modal-form>
  </div>
</template>
<script>
  import enumApi from '../../api/enum';
  import mixinPage from '../../mixins/page';
  import modelApi from '../../api/model';
  import processDefApi from '../../api/processDef';

  export default {
    mixins: [mixinPage],
    components: {},
    props: {},
    data() {
      return {
        id: null,
        readonly: null,
        opened: false,
        current: {},
        offset: {},
        movingActivity: null,
        isMoving: false,
        movingOutcome: null,
        movingPointIndex: null,
        isPointMoving: false,
        isCreatingOutcome: false,
        activityFrom: null,
        setting: {
          rectWidth: 100,
          rectHeight: 50,
          rectFontSize: 13,
          lineFontSize: 12
        },
        newActivity: null,
        editActivity: null,
        editOutcome: null,
        toolbars: [],
        data: {}
      };
    },
    computed: {
      displayActivities() {
        let activities = [];

        if (!this.readonly) {
          activities = this.toolbars;
        }

        if (this.data && this.data.activities) {
          activities = activities.concat(this.data.activities);
        }

        if (this.newActivity) {
          activities.push(this.newActivity);
        }

        return activities;
      },
      activities() {
        return this.data.activities;
      }
    },
    async created() {
      this.id = this.generateRandomString(10);
      this.toolbars = [];
      const src = await enumApi.query('ActivityType');
      let index = 0;

      src.forEach(item => {
        this.toolbars.push({
          isTool: true,
          x: 10 + 30 + this.setting.rectWidth / 2,
          y: 10 + 30 + (this.setting.rectHeight + 20) * index + this.setting.rectHeight / 2,
          activityType: item.id,
          name: item.name
        });

        index++;
      });
    },
    methods: {
      // 打开界面
      async open(params) {
        this.opened = true;

        if (params.processInstID) {
          this.readonly = true;
        } else {
          this.readonly = false;
        }

        const res = await processDefApi.getChart(params);

        this.data = res;
      },
      // 关闭
      close() {
        this.opened = false;
      },
      // 保存
      save() {
        this.confirm('Front_Msg_Sure_To_Save_Process', async () => {
          await processDefApi.save(this.data);
          this.success('Front_Msg_Success');
        });
      },
      // 发布
      publish() {
        this.confirm('Front_Msg_Sure_To_Publish_Process', async () => {
          await processDefApi.publish(this.data);
          this.success('Front_Msg_Success');
          this.opened = false;
        });
      },
      // 获取Outcom的起始点
      getOutcomeStartPoint(outcome) {
        let activity = this.data.activities.find(activity => activity.pid == outcome.activityFromPid);
        return { x: activity.x, y: activity.y };
      },
      // 获取Outcom的结束点
      getOutcomeEndPoint(outcome) {
        let activity = this.data.activities.find(activity => activity.pid == outcome.activityToPid);
        return { x: activity.x, y: activity.y };
      },
      // 获取Outcome路径
      getOutcomPath(outcome) {
        let startPoint = this.getOutcomeStartPoint(outcome);
        let endPoint = this.getOutcomeEndPoint(outcome);

        if (outcome.pointCount == 1) {
          let points = JSON.parse(outcome.points);

          endPoint = points[0];
        } else if (outcome.pointCount == 2) {
          let points = JSON.parse(outcome.points);

          startPoint = points[0];
          endPoint = points[1];
        }

        if (startPoint.x > endPoint.x) {
          return 'M ' + endPoint.x + ' ' + endPoint.y + ' L ' + startPoint.x + ' ' + startPoint.y;
        } else {
          return 'M ' + startPoint.x + ' ' + startPoint.y + ' L ' + endPoint.x + ' ' + endPoint.y;
        }
      },
      // 获取Outcome的两端点
      getOutcomePoint(outcome) {
        let activityFrom = this.data.activities.find(activity => activity.pid == outcome.activityFromPid);
        let activityTo = this.data.activities.find(activity => activity.pid == outcome.activityToPid);

        let pointTo = { x: activityTo.x, y: activityTo.y };
        let pointFrom = { x: activityFrom.x, y: activityFrom.y };

        if (outcome.pointCount > 0) {
          let points = JSON.parse(outcome.points);

          pointTo = points[0];
          pointFrom = points[points.length - 1];
        }

        let result = {
          fromPoint: this.getPointOfIntersection(activityFrom, pointTo),
          toPoint: this.getPointOfIntersection(activityTo, pointFrom)
        };

        return result;
      },
      // 获取两个点之间的距离
      getDistBetweenPoints(point1, point2) {
        return Math.sqrt((point2.x - point1.x) * (point2.x - point1.x) + (point2.y - point1.y) * (point2.y - point1.y));
      },
      // 获取线与图形的交叉点
      getPointOfIntersection(activity, point) {
        let result = {};
        let width = this.setting.rectWidth;
        let height = this.setting.rectHeight;

        if (activity.activityType == 'ParallelEnd') {
          width = (this.setting.rectHeight / 3) * 2;
          height = (this.setting.rectHeight / 3) * 2;
        }

        // 中心点
        let centerPoint = {
          x: activity.x,
          y: activity.y
        };

        if (Math.abs(point.x - centerPoint.x) <= width / 2 && Math.abs(point.y - centerPoint.y) <= height / 2) {
          //activity.activityType == 'Manual') {
          result = centerPoint;
        } else {
          let angle = Math.abs((Math.atan((centerPoint.x - point.x) / (centerPoint.y - point.y)) * 180.0) / Math.PI);
          let angle2 = Math.abs((Math.atan(width / height) * 180.0) / Math.PI);
          let radio = height < width ? height / 2 : width / 2;

          if (angle <= angle2) {
            if (centerPoint.x < point.x) {
              result.x = centerPoint.x + Math.tan((Math.PI * angle) / 180.0) * radio;
            } else {
              result.x = centerPoint.x - Math.tan((Math.PI * angle) / 180.0) * radio;
            }

            if (centerPoint.y < point.y) {
              result.y = centerPoint.y + height / 2;
            } else {
              result.y = centerPoint.y - height / 2;
            }
          } else {
            if (centerPoint.x < point.x) {
              result.x = centerPoint.x + width / 2;
            } else {
              result.x = centerPoint.x - width / 2;
            }

            if (centerPoint.y < point.y) {
              result.y = centerPoint.y + Math.tan((Math.PI * (90 - angle)) / 180.0) * radio;
            } else {
              result.y = centerPoint.y - Math.tan((Math.PI * (90 - angle)) / 180.0) * radio;
            }
          }
        }
        // } elseif (false) {
        //     if (Math.abs(point.x - centerPoint.x) <= width / 2 && Math.abs(point.y - centerPoint.y) <= height / 2) {
        //         result = centerPoint;
        //     } else {
        //         var radial = (width < height ? width : height) / 2;
        //         var bc = getDistBetweenPoints(point, centerPoint);
        //         result.x = centerPoint.x - ((centerPoint.x - point.x) * radial) / bc;
        //         result.y = centerPoint.y - ((centerPoint.y - point.y) * radial) / bc;
        //     }
        // }

        return result;
      },
      // 鼠标按钮在活动上按下
      mousedownActivity(activity, e) {
        if (this.readonly) {
          return;
        }

        if (activity.isTool) {
          // 从工具栏拖动
          this.newActivity = this.copy(activity);
          this.movingActivity = this.newActivity;
        } else {
          // 普通拖动
          this.movingActivity = activity;
        }

        this.offset.x = activity.x - e.layerX;
        this.offset.y = activity.y - e.layerY;
        this.isMoving = true;
      },
      // 鼠标按钮在活动上抬起
      mouseupActivity(activity) {
        if (this.readonly) {
          return;
        }

        if (this.isCreatingOutcome) {
          if (this.activityFrom.pid == activity.pid) {
            return;
          }

          if (
            this.data.outcomes.some(outcome => {
              return outcome.activityFromPid == this.activityFrom.pid && outcome.activityToPid == activity.pid;
            })
          ) {
            return;
          }

          // 新建Outcome
          this.data.outcomes.push({
            processID: this.data.processID,
            pid: this.getNewOutcomeID(),
            activityFromPid: this.activityFrom.pid,
            activityToPid: activity.pid,
            outcomeType: 'Custom',
            code: '',
            name: '',
            ruleData: null,
            orderNo: 0
          });
        }
      },
      // 鼠标按钮在点上按下
      mousedownPoint(outcome, point, index, e) {
        if (this.readonly) {
          return;
        }

        this.movingOutcome = outcome;
        this.movingPointIndex = index;

        this.offset.x = point.x - e.layerX;
        this.offset.y = point.y - e.layerY;
        this.isPointMoving = true;
      },
      // 鼠标按钮在点上抬起
      mouseupPoint(outcome, index) {
        if (this.readonly) {
          return;
        }

        if (this.isCreatingOutcome) {
          if (this.activityFrom.pid == activity.pid) {
            return;
          }

          if (
            this.data.outcomes.some(outcome => {
              return outcome.activityFromPid == this.activityFrom.pid && outcome.activityToPid == activity.pid;
            })
          ) {
            return;
          }

          // 新建Outcome
          this.data.outcomes.push({
            processID: this.data.processID,
            pid: this.getNewOutcomeID(),
            activityFromPid: this.activityFrom.pid,
            activityToPid: activity.pid,
            outcomeType: 'Custom',
            code: '',
            name: '',
            ruleData: null,
            orderNo: 0
          });
        }
      },
      // 鼠标双击活动
      dblclickActivity(activity) {
        if (this.readonly) {
          return;
        }

        if (!activity.isTool) {
          this.editActivity = activity;
          if (activity.activityType == 'Interactive') {
            // 角色参数表格
            let data = [];

            if (activity.destinationRoleParam) {
              data = JSON.parse(activity.destinationRoleParam);
            }

            this.$refs.destinationRoleParamTable.loadData(data);
            this.$refs.interactiveForm.openDefault(activity);
          } else if (activity.activityType == 'Service') {
            this.$refs.serviceForm.openDefault(activity);
          } else {
            this.$refs.activityForm.openDefault(activity);
          }
        }
      },
      // 鼠标双击结果
      dblclickOutcome(outcome) {
        if (this.readonly) {
          return;
        }

        this.editOutcome = this.copy(outcome);

        let activity = this.data.activities.find(item => {
          return item.pid == outcome.activityFromPid;
        });

        if (activity.activityType == 'Judgement') {
          this.$refs.judgementOutcomeForm.openDefault(this.editOutcome);
        } else {
          this.$refs.outcomeForm.openDefault(this.editOutcome);
        }
      },
      // 鼠标按钮抬起
      mouseUp(e) {
        if (this.readonly) {
          return;
        }

        if (this.isMoving && this.movingActivity && this.movingActivity.isTool) {
          // 从工具栏拖动
          if (e.layerX > 10 + 30 * 2 + this.setting.rectWidth + this.setting.rectWidth / 2) {
            // 拖出工具栏范围
            this.newActivity.processID = this.data.processID;
            this.newActivity.isTool = false;
            this.newActivity.pid = this.getNewActivityID();
            this.data.activities.push(this.newActivity);
          }

          this.newActivity = null;
        }

        this.isCreatingOutcome = false;
        this.isMoving = false;
        this.isPointMoving = false;
      },
      // 鼠标移动
      mousemove(e) {
        if (this.readonly) {
          return;
        }

        this.current.x = e.offsetX;
        this.current.y = e.offsetY;
        //this.$forceUpdate();

        if (this.isMoving) {
          this.movingActivity.x = e.layerX + this.offset.x;
          this.movingActivity.y = e.layerY + this.offset.y;
        }

        if (this.isPointMoving) {
          let points = JSON.parse(this.movingOutcome.points);
          points[this.movingPointIndex] = { x: e.layerX + this.offset.x, y: e.layerY + this.offset.y };
          this.movingOutcome.points = JSON.stringify(points);
        }
      },
      // 鼠标移入活动中心位置
      mouseenterCenter(activity) {
        if (this.readonly) {
          return;
        }

        if (!activity.isTool) {
          activity.activeCenter = true;
        }
      },
      // 鼠标移出活动中心位置
      mouseleaveCenter(activity) {
        if (this.readonly) {
          return;
        }

        activity.activeCenter = false;
      },
      // 活动中心位置按下鼠标
      mousedownCenter(activity) {
        if (this.readonly) {
          return;
        }

        if (activity.activeCenter) {
          // 添加Outcome
          this.isCreatingOutcome = true;
          this.activityFrom = activity;
        }
      },
      // 获取新的Activity id
      getNewActivityID() {
        let id = 0;
        this.data.activities.forEach(item => {
          if (item.pid > id) {
            id = item.pid;
          }
        });

        return ++id;
      },
      // 获取新的Outcome id
      getNewOutcomeID() {
        let id = 0;
        this.data.outcomes.forEach(item => {
          if (item.pid > id) {
            id = item.pid;
          }
        });

        return ++id;
      },
      // 保存活动
      saveActivity() {
        let index = this.data.activities.findIndex(item => {
          return item.pid == this.editActivity.pid;
        });

        if (this.editActivity.activityType == 'Interactive') {
          let data = this.$refs.interactiveForm.getFullData();
          data.destinationRoleParam = JSON.stringify(this.$refs.destinationRoleParamTable.getData());
          this.data.activities.splice(index, 1, data);
          this.$refs.interactiveForm.close();
        } else if (this.editActivity.activityType == 'Service') {
          this.data.activities.splice(index, 1, this.$refs.serviceForm.getFullData());
          this.$refs.serviceForm.close();
        } else {
          this.data.activities.splice(index, 1, this.$refs.activityForm.getFullData());
          this.$refs.activityForm.close();
        }
      },
      // 删除活动
      removeActivity() {
        this.confirm('Front_Msg_Sure_To_Remove_Activity', () => {
          let index = this.data.activities.findIndex(item => {
            return item.pid == this.editActivity.pid;
          });

          this.data.activities.splice(index, 1);

          this.data.outcomes = this.data.outcomes.filter(item => {
            return item.activityFromPid != this.editActivity.pid && item.activityToPid != this.editActivity.pid;
          });

          if (this.editActivity.activityType == 'Interactive') {
            this.$refs.interactiveForm.close();
          } else if (this.editActivity.activityType == 'Service') {
            this.$refs.serviceForm.close();
          } else {
            this.$refs.activityForm.close();
          }
        });
      },
      // 保存结果
      saveOutcome() {
        let index = this.data.outcomes.findIndex(item => {
          return item.pid == this.editOutcome.pid;
        });

        let activity = this.data.activities.find(item => {
          return item.pid == this.editOutcome.activityFromPid;
        });

        let outcome = null;

        if (activity.activityType == 'Judgement') {
          outcome = this.$refs.judgementOutcomeForm.getFullData();
          this.$refs.judgementOutcomeForm.close();
        } else {
          outcome = this.$refs.outcomeForm.getFullData();
          this.$refs.outcomeForm.close();
        }

        let activityFrom = this.data.activities.find(activity => activity.pid == outcome.activityFromPid);
        let activityTo = this.data.activities.find(activity => activity.pid == outcome.activityToPid);

        if (outcome.pointCount == null || outcome.pointCount == 0) {
          // 直线
          outcome.points = JSON.stringify([]);
        } else if (outcome.pointCount == 1) {
          if (outcome.points == null || JSON.parse(outcome.points).length != 1) {
            outcome.points = JSON.stringify([
              {
                x: Math.round((activityFrom.x + activityTo.x) / 2),
                y: Math.round((activityFrom.y + activityTo.y) / 2)
              }
            ]);
          }
        } else if (outcome.pointCount == 2) {
          if (outcome.points == null || JSON.parse(outcome.points).length != 2) {
            outcome.points = JSON.stringify([
              { x: Math.round(((activityFrom.x - activityTo.x) * 2) / 3 + activityTo.x), y: Math.round(((activityFrom.y - activityTo.y) * 2) / 3 + activityTo.y) },
              { x: Math.round((activityFrom.x - activityTo.x) / 3 + activityTo.x), y: Math.round((activityFrom.y - activityTo.y) / 3 + activityTo.y) }
            ]);
          }
        }

        this.data.outcomes.splice(index, 1, outcome);
      },
      // 删除结果
      removeOutcome() {
        this.confirm('Front_Msg_Sure_To_Remove_Outcome', () => {
          let index = this.data.outcomes.findIndex(item => {
            return item.pid == this.editOutcome.pid;
          });

          this.data.outcomes.splice(index, 1);

          let activity = this.data.activities.find(item => {
            return item.pid == this.editOutcome.activityFromPid;
          });

          if (activity.activityType == 'Judgement') {
            this.$refs.judgementOutcomeForm.close();
          } else {
            this.$refs.outcomeForm.close();
          }
        });
      },
      // 交互表单数据变更
      async interactiveFormChange(sender) {
        // this.$refs.interactiveForm.columns.find(item => {
        //     return item.code == 'destinationRoleID';
        // }).isShow = !this.$refs.interactiveForm.data.isOriginator;

        if (sender && sender.code == 'destinationRoleID') {
          if (this.$refs.interactiveForm.data.destinationRoleID) {
            const res = await modelApi.query('RoleProperty', { roleID: this.$refs.interactiveForm.data.destinationRoleID });

            let data = res.data.map(item => {
              return {
                rolePropertyCode: item.propertyCode,
                name: item.propertyName,
                processPropertyCode: null
              };
            });

            this.$refs.destinationRoleParamTable.loadData(data);
          } else {
            this.$refs.destinationRoleParamTable.loadData([]);
          }
        }
      },
      // 获取线段
      getLines(outcome) {
        let lines = [];
        let d = this.getOutcomePoint(outcome);

        if (outcome.pointCount == null || outcome.pointCount == 0) {
          // 直线
          lines.push({
            x1: d.fromPoint.x,
            y1: d.fromPoint.y,
            x2: d.toPoint.x,
            y2: d.toPoint.y,
            markerStart: 'url(#arrowStart_' + this.id + ')',
            markerEnd: 'url(#arrowEnd_' + this.id + ')'
          });
        } else {
          // 折线
          let points = JSON.parse(outcome.points);

          let start = { x: d.fromPoint.x, y: d.fromPoint.y };
          let i = 0;

          for (let point of points) {
            lines.push({
              x1: start.x,
              y1: start.y,
              x2: point.x,
              y2: point.y,
              markerStart: i == 0 ? 'url(#arrowStart_' + this.id + ')' : null
            });

            i++;
            start = point;
          }

          lines.push({
            x1: start.x,
            y1: start.y,
            x2: d.toPoint.x,
            y2: d.toPoint.y,
            markerEnd: 'url(#arrowEnd_' + this.id + ')'
          });
        }

        return lines;
      },
      // 获取点
      getPoints(outcome) {
        if (outcome.pointCount == null || outcome.pointCount == 0) {
          // 直线
          return [];
        } else {
          // 折线
          return JSON.parse(outcome.points);
        }
      },
      generateRandomString(length) {
        const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        let result = '';
        for (let i = 0; i < length; i++) {
          const randomIndex = Math.floor(Math.random() * characters.length);
          result += characters[randomIndex];
        }
        return result;
      },
      getColor(activity) {
        if (!this.data.processInst || (this.data.processInst.status != 'InProcess' && this.data.processInst.status != 'Finished')) {
          return '#fff';
        }

        let activityInst = this.data.activityInsts.find(item => item.activityID == activity.id);

        if (activityInst == null) {
          return '#fff';
        } else if (activityInst.status == 'Pending') {
          return '#ff9900';
        } else if (activityInst.status == 'Finished') {
          return '#8ecb30';
        } else if (activityInst.status == 'Closed') {
          return 'gray';
        } else if (activityInst.status == 'Pass') {
          return 'gray';
        }

        return '#fff';
      }
    }
  };
</script>
