<template>
  <a-row :gutter="24" :class="$style.fullHeight">
    <a-col :md="5" :sm="24" :class="$style.fullHeight">
      <a-card :class="[$style.fullHeight, $style.overflowScroll]">
        <sd-flow-tree @selected="selected" />
      </a-card>
    </a-col>
    <a-col :class="[$style.fullHeight, $style.right]" :md="19" :sm="24">
      <a-card :class="$style.topTool">
        <a-form>
          <a-form-item label="修改对象">
            <a-radio-group v-model="objValue" :options="options" @change="dataLoaded" />
          </a-form-item>
          <a-form-item v-if="objValue === 'node'" label="节点类型">
            <a-checkbox-group v-model="typeVal" :options="typeOptions" @change="nodeTypeChange" />
            <a-checkbox
              :class="$style.typeCheck"
              :indeterminate="typeIndeterminate"
              :checked="typeCheckAll"
              @change="typeCheckAllChange"
            >
              全选
            </a-checkbox>
          </a-form-item>
          <a-form-item label="搜索名称">
            <a-button
              type="primary"
              :class="$style.amendBtn"
              :disabled="!indeterminate && !checkAll"
              @click="
                () => {
                  $refs.flowModal.open()
                }
              "
              >批量修改</a-button
            >
          </a-form-item>
        </a-form>
      </a-card>
      <a-card :class="$style.bottomTable">
        <a-checkbox
          :class="$style.checkAll"
          :indeterminate="indeterminate"
          :checked="checkAll"
          @change="onCheckAllChange"
        />

        <sd-data-table
          ref="dataTable"
          :class="[{ [$style.hideExpandrow]: objValue === 'flow' }, $style.dataTable]"
          :columns="columns"
          data-url="api/framework/v1/process-prop/process-list"
          :filter-expressions="filterExpressions"
          :process-req="processReq"
          :search-fields="['name']"
          @dataLoaded="dataLoaded"
        >
          <div slot="name" slot-scope="text, record">
            <div :class="$style.nameRow">
              <div
                :class="[
                  'ant-table-row-expand-icon',
                  $style.expandIcon,
                  record.expandable ? $style.close : $style.expanded,
                ]"
                @click="expandRow(record)"
              />
              <a-checkbox
                v-model="record.selectConfig.checkAll"
                :class="$style.nameCheckbox"
                :indeterminate="record.selectConfig.indeterminate"
                @change="(e) => tableItemChecked(e, record)"
              />
              {{ text }}
            </div>
            <div v-if="record.expandable" :class="$style.expandRow">
              <span :class="$style.objLabel">{{ objLabel }}：</span>
              <a-checkbox-group
                v-model="record.selectConfig.elements"
                :options="record.selectConfig.options"
                @change="(checkedList) => elementsChange(checkedList, record)"
              >
                <span slot="label" slot-scope="{ title }">
                  <span v-if="title.indexOf(searchText) > -1">
                    {{ title.substr(0, title.indexOf(searchText)) }}
                    <span :class="$style.searchColor">{{ searchText }}</span>
                    {{ title.substr(title.indexOf(searchText) + searchText.length) }}
                  </span>
                  <span v-else>{{ title }}</span>
                </span>
              </a-checkbox-group>
            </div>
          </div>
          <a slot="action" slot-scope="text, record" @click="openFlowchart(record)"
            >{{ objValue === 'flow' ? '查看流程图' : '从流程图选择' }}
          </a>
        </sd-data-table>
        <sd-flowchart-action
          ref="flowChart"
          :mode="objValue"
          :options="currentItem ? currentItem.selectConfig.options : []"
          :checked-list="checkedList"
          @selectNode="(list) => elementsChange(list, currentItem)"
        />
        <sd-flowamend-modal ref="flowModal" :mode="objValue" @ok="submit" />
        <sd-flowamend-status ref="amendStatus" @ok="finishAmend" />
      </a-card>
    </a-col>
  </a-row>
</template>

<script>
import { Message } from 'ant-design-vue'
import components from './_import-components/sd-flowamend-tools-import'
const columns = [
  {
    dataIndex: 'name',
    title: '流程',
    defaultSortOrder: 'asc',
    scopedSlots: { customRender: 'name' },
    width: '80%',
  },
  {
    title: '操作',
    dataIndex: 'action',
    scopedSlots: { customRender: 'action' },
  },
]
const typeOptions = [
  { label: '开始', value: 'start' },
  { label: '一般', value: 'common' },
  { label: '分裂', value: 'split' },
  { label: '汇聚', value: 'join' },
  { label: '子流程', value: 'subflow' },
  { label: '结束', value: 'end' },
  { label: '自由串', value: 'freeSign' },
  { label: '自由并', value: 'freeSignView' },
]
const typeVal = typeOptions.map((item) => item.value)
export default {
  name: 'SdFlowamendTools',
  metaInfo: {
    title: '流程修改工具',
  },
  components,
  data() {
    return {
      columns,
      options: [
        { label: '节点', value: 'node' },
        { label: '操作线', value: 'line' },
        { label: '流程', value: 'flow' },
      ],
      typeOptions,
      objValue: 'node',
      typeVal,
      treeNodeKey: '',
      indeterminate: false,
      checkAll: false,
      dataSource: [],
      checkedList: [],
      currentItem: undefined,
      searchText: '',
      typeIndeterminate: false,
      typeCheckAll: true,
      currentType: '',
    }
  },
  computed: {
    filterExpressions() {
      const expressions = [
        {
          dataType: 'str',
          name: 'status',
          op: 'eq',
          stringValue: '1',
        },
      ]
      return expressions
    },
    objLabel() {
      return this.options.find((item) => item.value === this.objValue).label
    },
  },
  created() {
    this.typeOptions.forEach((item) => {
      item.onChange = this.typeItemChange
    })
  },
  mounted() {
    this.$nextTick(() => {
      const input = document
        .querySelector(`.${this.$style.dataTable}`)
        .querySelector('.ant-input-search input')
      input.setAttribute('placeholder', '请输入流程、环节或操作线名称')
    })
  },
  methods: {
    typeItemChange(e) {
      this.currentType = e.target.value
    },
    expandRow(record) {
      record.expandable = !record.expandable
      this.$set(this.dataSource, this.dataSource.indexOf(record), record)
    },
    openFlowchart(record) {
      this.currentItem = record
      this.checkedList = record.selectConfig.elements
      this.$refs.flowChart.flowId = record.newFlowId
      this.$refs.flowChart.open()
    },
    processReq(req) {
      if (req.data) {
        req.data.orderBy = 'categoryName asc, orderNum asc, name asc'
        req.data.categoryId = this.treeNodeKey
        const searchParamInfo = req.data.expressions.find((r) => r.expressionsValue)
        if (searchParamInfo) {
          this.searchText = this.$refs.dataTable.searchText
          Object.assign(req.data, {
            type: ['flow', 'node', 'line'].indexOf(this.objValue),
            searchParam: this.$refs.dataTable.searchText,
            expressions: req.data.expressions.filter((r) => !r.expressionsValue),
          })
        }
      }
      return req
    },
    selected(key) {
      this.treeNodeKey = key.slice(1)
      this.$refs.dataTable.refresh()
    },
    typeCheckAllChange(e) {
      Object.assign(this, {
        typeIndeterminate: !e.target.checked,
        typeCheckAll: e.target.checked,
        typeVal: e.target.checked
          ? typeOptions.map((t) => t.value)
          : typeOptions.map((t) => t.value).filter((f) => f === 'start'),
      })
      this.setExpandContent()
    },
    nodeTypeChange() {
      if (!this.typeVal.length) {
        Message.warn('请至少选择一种节点类型')
        this.typeVal.push(this.currentType)
        return
      }
      this.typeIndeterminate = this.typeVal.length < this.typeOptions.length
      this.typeCheckAll = this.typeVal.length === this.typeOptions.length
      this.setExpandContent()
    },
    setExpandContent() {
      this.dataSource.forEach((data) => {
        const dataArr = (this.objValue === 'node' ? data.steps : data.actions).filter(
          (item) => !item.inParts
        )
        if (dataArr.length) {
          dataArr.forEach((item) => {
            if (!item.name && this.objValue === 'line') {
              const startName = data.steps.find((a) => a.stepId === item.sStepId)?.name
              const endName = data.steps.find((a) => a.stepId === item.eStepId)?.name
              item.name = startName && endName ? startName + '至' + endName : ''
            }
            item.title = item.name || ''
            item.value = item.stepId || item.id || ''
          })
        }
        data.selectConfig.options =
          this.objValue === 'node'
            ? dataArr.filter(
                (d) =>
                  Object.keys(d).filter((key) => this.typeVal.indexOf(key) > -1 && d[key]).length
              )
            : dataArr
        data.selectConfig.elements = data.selectConfig.elements.filter((element) =>
          data.selectConfig.options.find((option) => option.stepId === element)
        )
      })
    },
    onCheckAllChange(e) {
      Object.assign(this, {
        indeterminate: false,
        checkAll: e.target.checked,
      })
      this.dataSource.forEach((item) => {
        Object.assign(item.selectConfig, {
          checkAll: e.target.checked,
          indeterminate: false,
          elements: e.target.checked ? item.selectConfig.options.map((e) => e.value) : [],
        })
      })
    },
    dataLoaded() {
      Object.assign(this, {
        indeterminate: false,
        checkAll: false,
      })
      this.$refs.dataTable.data.forEach((item) => {
        item.selectConfig = {
          checkAll: false,
          indeterminate: false,
          elements: [],
          expandable: item.expandable,
        }
      })
      this.dataSource = this.$refs.dataTable.data
      this.setExpandContent()
    },
    tableItemChecked(e, record) {
      Object.assign(record.selectConfig, {
        checkAll: e.target.checked,
        indeterminate: false,
        elements: e.target.checked ? record.selectConfig.options.map((item) => item.value) : [],
      })
      this.indeterminate =
        this.dataSource.filter((item) => item.selectConfig?.checkAll).length > 0 &&
        this.dataSource.filter((item) => item.selectConfig?.checkAll).length <
          this.dataSource.length
      this.$set(this.dataSource, this.dataSource.indexOf(record), record)
      this.checkAll = this.dataSource.every((item) => item.selectConfig?.checkAll === true)
    },
    elementsChange(checkedList, record) {
      Object.assign(record.selectConfig, {
        checkAll: checkedList.length === record.selectConfig.options.length,
        indeterminate:
          checkedList.length > 0 && checkedList.length < record.selectConfig.options.length,
        elements: checkedList,
      })
      this.indeterminate = this.dataSource.some(
        (item) => item.selectConfig?.indeterminate || item.selectConfig?.checkAll
      )
      this.$set(this.dataSource, this.dataSource.indexOf(record), record)
    },
    submit(form) {
      const paramsList = this.dataSource
        .filter((f) => f.selectConfig.checkAll || f.selectConfig.indeterminate)
        .map((item) => {
          return {
            type: ['flow', 'node', 'line'].indexOf(this.objValue),
            flowId: item.id,
            flowName: item.name,
            elements: item.selectConfig.elements,
            propInfo: form,
          }
        })
      this.$refs.amendStatus.paramsList = paramsList
      this.$refs.amendStatus.open()
    },
    finishAmend() {
      this.$refs.flowModal.closeModal()
      this.$refs.dataTable.refresh()
    },
  },
}
</script>

<style module lang="scss">
@use '@/common/design' as *;
.full-height {
  height: 100%;
  :global .ant-card-body {
    height: 100%;
  }
  &.right {
    overflow: hidden auto;
    .top-tool {
      margin-bottom: 20px;
      :global .ant-row {
        margin-bottom: 12px;
        :global .ant-form-item-label {
          float: left;
          width: 110px;
        }
      }
    }
    .bottom-table {
      :global(.ant-modal-body) {
        position: relative;
      }
      .check-all {
        position: absolute;
        top: 32px;
        left: 81px;
        z-index: 100;
      }
    }
    .amend-btn {
      top: 5px;
      float: right;
    }
    .type-check {
      float: right;
    }
  }
}
.overflow-scroll {
  overflow: auto;
}
.hide-expandrow {
  :global .ant-table-row-expand-icon {
    visibility: hidden;
  }
  .expand-row {
    display: none;
  }
}
.data-table {
  /* stylelint-disable selector-class-pattern */
  :global .header_sd-data-table_common {
    position: absolute;
    top: -87px;
    left: 127px;
    :global .ant-input-search {
      width: 275px;
    }
  }
  :global .ant-table-thead {
    tr {
      th:nth-child(1) {
        :global .ant-table-column-title {
          margin-left: 75px;
        }
      }
      th:nth-child(2) {
        :global .ant-table-header-column {
          margin-left: 25px;
        }
      }
    }
    :global .anticon-setting {
      display: none;
    }
  }
  .name-checkbox {
    margin-right: 5px;
  }
  .obj-label {
    margin-right: 5px;
    vertical-align: top;
  }
}
.name-row {
  display: flex;
  align-items: center;

  .expand-icon {
    margin: 0 17px;
    &.expanded::after {
      content: '+';
    }
    &.close::after {
      content: '-';
    }
  }
}
.expand-row {
  padding-left: 47px;
  margin-top: 15px;
  :global .ant-checkbox-group {
    width: 95%;
    overflow: hidden;
    word-wrap: break-word;
    white-space: pre-line;
  }
}
.search-color {
  color: $orange-6;
}
</style>
