<template>
  <el-row>
    <el-col :span="8" style="height:100%;">
      <el-row class="halfHeight pbstb">
        <tf-title>PBS编码规则模板
          <template #append>
            <el-button type="primary" size="mini" icon="el-icon-circle-plus-outline" @click="addModel">添加</el-button>
            <el-button type="danger" size="mini" icon="el-icon-delete" @click="deletePbsModel">删除</el-button>
          </template>
        </tf-title>
        <tf-table ref="table" highlight-current-row @selection-change="selectChange" :pagination="pagination" @page-change="onPageChange" :data="pbsmodels" @row-click="(row)=>{rowClick(row.id)}">
          <el-table-column type="selection" width="50px"></el-table-column>
          <el-table-column label="序号" type="index" width="50px"></el-table-column>
          <el-table-column label="名称" prop="name"></el-table-column>
          <el-table-column label="状态" prop="isUse" :formatter="(row,column,cellValue)=>{
              return cellValue==='0'?'未使用':'使用中'
              }"></el-table-column>
        </tf-table>
      </el-row>
      <el-row class="halfHeight">
        <tf-title>PBS结构网预览</tf-title>
        <el-tree @node-click="(data,row)=>{selectPBSNode(data.alevel)}" :expand-on-click-node='false' :default-expand-all="true" node-key="id" :data="pbsTreeData" :props="treeProps"></el-tree>
      </el-row>
    </el-col>
    <el-col :span="16" class="pbsDefine">
      <tf-title>PBS编码规则定义</tf-title>
      <el-row class="preview">
        <el-row><span>编码预览：{{codePreview}}</span></el-row>
        <el-row class="previewBtn">
          <div class="btngroup" v-for="(item,index) in selectedPbs.pbsLevelList" :key="item.alevel">
            <el-button type="primary" :class="{active:currentLevel.alevel===item.alevel}" @click="selectPBSNode(item.alevel)" plain size="medium">{{item.codeView}}</el-button>
            <el-select size="mini" placeholder="" v-model="item.connector" v-if="index!==selectedPbs.pbsLevelList.length-1">
              <el-option value="" label=""></el-option>
              <el-option value="." label="."></el-option>
            </el-select>
          </div>
        </el-row>
        <el-divider></el-divider>
      </el-row>
      <el-row class="nodeDefine">
        <el-form label-width="80px" :model="currentLevel" :disabled="selectedPbs.isUse==='1'">
          <el-form-item label="节点级别">
            <el-select class="col16" v-model="currentLevel.alevel">
              <el-option v-for="level in selectedPbs.alevel" :key="level" :value="level" :label="level+'级'"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="节点类型">
            <el-input class="col16" type="text" v-model="currentLevel.levelName"></el-input>
          </el-form-item>
          <el-form-item label="编码说明">
            <el-input class="col16" type="text" v-model="currentLevel.contents"></el-input>
          </el-form-item>
          <el-form-item label="编码定义">
            <el-button size="mini" icon="el-icon-plus" type="primary" @click="addNodeCodeWidget(null,true)" plain></el-button>
          </el-form-item>
          <el-form-item>
            <el-row style="marginBottom:20px;" :gutter="20" v-for="(item,index) in currentLevel.pbsCodelist" :key='index'>
              <el-col :span="5">
                <el-select size="small" v-model="item.codeType" style="width:100%">
                  <el-option value="1" label="业务对象类型"></el-option>
                  <el-option value="2" label="输入框"></el-option>
                  <el-option value="3" label="流水号"></el-option>
                </el-select>
              </el-col>
              <el-col :span="5" v-if="item.codeType==='1'">
                <el-input size="small" v-model="item.boGroupName" @focus="openBoDialog(item)" placeholder="点击选择业务对象"></el-input>
              </el-col>
              <el-col :span="10" v-else-if="item.codeType==='2'">
                <el-col :span="12" style="paddingLeft:0">
                  <el-input size="small" v-model="item.codeLength" placeholder="编码长度"></el-input>
                </el-col>
                <el-col :span="12">
                  <el-input size="small" v-model="item.contents" placeholder="编码说明"></el-input>
                </el-col>
              </el-col>
              <el-col :span="5" v-else-if="item.codeType==='3'">
                <el-input size="small" v-model="item.codeLength" placeholder="编码长度"></el-input>
              </el-col>
              <el-col :span="3">
                <el-button size="small" icon="el-icon-delete" type="danger" @click="removeNodeCodeWidget(index)"></el-button>
              </el-col>
            </el-row>
          </el-form-item>
        </el-form>
      </el-row>
      <el-row v-if="selectedPbs.isUse==='0'" class="footerBtns">
        <el-divider></el-divider>
        <el-button type="primary" style="margin-right:100px;" @click="savePbsLevel">提交</el-button>
        <!-- <el-button type="primary" style="margin-right:100px;">清空</el-button> -->
      </el-row>
    </el-col>
    <tf-dialog title="添加PBS模板" :visible.sync='isAddModelShow' width='600px'>
      <el-form v-model="addModelForm" label-width="100px">
        <el-form-item label="名称">
          <el-input v-model="addModelForm.name"></el-input>
        </el-form-item>
        <el-form-item label="层级">
          <el-select v-model="addModelForm.alevel">
            <el-option value="3" label="3"></el-option>
            <el-option value="4" label="4"></el-option>
            <el-option value="5" label="5"></el-option>
            <el-option value="6" label="6"></el-option>
            <el-option value="7" label="7"></el-option>
            <el-option value="8" label="8"></el-option>
            <el-option value="9" label="9"></el-option>
            <el-option value="10" label="10"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="备注">
          <el-input :rows="2" type="textarea" v-model="addModelForm.remark"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" style="text-align:right">
        <el-button size="small" @click="isAddModelShow=false">取消</el-button>
        <el-button size="small" type="primary" @click="submitAddModel">提交</el-button>
      </div>
    </tf-dialog>
    <tf-dialog title="业务对象模板" :visible.sync='isAddBoShow' width='800px'>
      <el-row>
        <el-input v-model="searchBoGroup" placeholder="所属组名称" size="small" style="width:200px"></el-input>
      </el-row>
      <el-row style="height:400px">
        <tf-table highlight-current-row @current-change="handleCurrentChange" ref="mainTb" :pagination="bopagination" @page-change="onBoPageChange" :data="bodataList">
          <el-table-column prop="boGroup" label="所属组名称"></el-table-column>
          <el-table-column prop="boType" label="类型名称"></el-table-column>
          <el-table-column prop="createUserName" label="创建用户"></el-table-column>
          <el-table-column prop="createTime" label="创建时间"></el-table-column>
        </tf-table>
      </el-row>
      <div slot="footer" style="text-align:right">
        <el-button size="small" @click="isAddBoShow=false">取消</el-button>
        <el-button size="small" type="primary" @click="submitAddBo">提交</el-button>
      </div>
    </tf-dialog>
  </el-row>
</template>
<script lang="ts">
/**
 * 模板信息
 */
interface pbsDefine {
  name: string
  isUse: string
  id: number
  pbsLevelList: Array<pbsStruct>
  alevel?: number
  create_user?: string
  create_time?: string
  code_view?: string
}
/**
 * 模板层级信息
 */
interface pbsStruct {
  id?: number
  levelName: string
  contents: string
  codeView: string
  connector: string
  alevel: number
  pbsCodelist?: Array<pbsNodeCode>
  pbsId: number
}
/**
 * 节点编码定义
 */
interface pbsNodeCode {
  codeType: string
  codeLength?: number
  id?: string
  contents?: string
  boId?: number
  boGroupName?: ''
}
/**
 * PBS模板
 */
import { Vue, Prop, Watch, Component } from 'vue-property-decorator'
import { getDefaultPagination } from '@/utils/constant'
import {
  getPBScodeRuleList_api,
  deletePbsModelByIds,
  addPBScodeRule_api,
  getPBScodeRuleInfo_api,
  PutPBScodeRule_api,
  GetBoPage_api,
  GetBoById_api
} from '@/api/APIs'
import { ElTable } from 'element-ui/types/table'
@Component({
  name: 'PbsManagement'
})
export default class PbsManagement extends Vue {
  /**分页 */
  pagination = getDefaultPagination()
  /**业务对象分页 */
  bopagination = getDefaultPagination()
  /**业务对象表格数据 */
  bodataList = []
  /**所属组搜索 */
  searchBoGroup = ''
  /**勾选的模板 */
  selectModels = []
  /**树组件配置 */
  treeProps = {
    children: 'children',
    label: 'name'
  }
  /**新增模板参数 */
  addModelForm = {
    alevel: '3',
    name: '',
    remark: ''
  }
  /**结构树 */
  pbsTreeData = []
  /**当前选中的模板 */
  selectedPbs: pbsDefine = {
    name: '',
    isUse: '0',
    id: undefined,
    pbsLevelList: [],
    alevel: undefined,
    create_user: '',
    create_time: '',
    code_view: ''
  }
  /**当前选中节点 */
  currentLevel: pbsStruct = {
    id: undefined,
    levelName: '',
    contents: '',
    codeView: '',
    connector: '',
    alevel: undefined,
    pbsCodelist: [],
    pbsId: undefined
  }
  /**当前操作的业务对象部件 */
  currentBoWiget: pbsNodeCode = {
    codeType: '',
    id: '',
    boId: undefined
  }
  /**选择的业务对象 */
  selectBo = undefined
  /**模板列表 */
  pbsmodels = []
  /**编码预览 */
  codePreview = ''
  /**新增弹窗 */
  isAddModelShow = false
  /**选择业务对象弹窗 */
  isAddBoShow = false
  mounted() {
    this.getModelList()
  }
  @Watch('searchBoGroup')
  searchBogroup(value) {
    this.bopagination = getDefaultPagination()
    this.getDataList()
  }
  /**分页事件 */
  onPageChange(pagination) {
    this.pagination = { ...this.pagination, ...pagination }
    this.getModelList()
  }
  /**分页事件 */
  onBoPageChange(pagination) {
    this.bopagination = { ...this.bopagination, ...pagination }
    this.getDataList()
  }
  handleCurrentChange(row) {
    this.selectBo = row
  }
  /**PBS编码模板列表 */
  getModelList() {
    getPBScodeRuleList_api(this.pagination).then((result) => {
      if (result.code === 1) {
        this.pbsmodels = result.result.records
        //默认展示第一行
        if (this.pbsmodels.length > 0) {
          this.rowClick(this.pbsmodels[0].id)
          ;((this.$refs.table as Vue).$refs.table as ElTable).setCurrentRow(this.pbsmodels[0])
        }
        const { current, size, total } = result.result
        this.pagination = { current, size, total }
      }
    })
  }
  /**
   * 该方式用于预览pbs编码结构树
   * @param {number} pbsID pbs模板ID
   * @param {boolean} selectNode 是否定位到节点层级
   * @param {number} level 节点层级
   */
  rowClick(pbsID: number, selectNode: boolean = false, level: number = 0) {
    getPBScodeRuleInfo_api({ id: pbsID })
      .then((e) => {
        let nodeTree = undefined
        if (e.code !== 1) {
          this.$message.error('获取PBS模板信息失败')
          return
        }
        const pbs = e.result as pbsDefine
        this.selectedPbs = pbs //当前使用的pbs模板
        if (pbs.alevel !== pbs.pbsLevelList.length) {
          this.initPbsLevelList(pbs)
        }
        const pbsLevel = pbs.pbsLevelList.sort(function (a, b) {
          return a.alevel - b.alevel
        })
        //拷贝
        const psbLevelClone = pbsLevel.map((item) => {
          return item
        })
        psbLevelClone.reverse().forEach((item: pbsStruct, index: number) => {
          if (index === 0) {
            nodeTree = {
              id: item.alevel,
              name: item.levelName,
              alevel: item.alevel
            }
          } else {
            const node = {
              id: item.alevel,
              name: item.levelName,
              alevel: item.alevel,
              children: [nodeTree]
            }
            nodeTree = node
          }
        })
        this.pbsTreeData = [nodeTree]
        this.initPbsRuleDefine(pbsLevel, selectNode, level)
      })
      .catch((err) => {
        console.error(err)
      })
  }
  /**
   * 该方法用于给未定义层级的PBS模板设置默认的层级
   * @param {pbsDefine} pbs pbs模板
   */
  initPbsLevelList(pbs: pbsDefine) {
    const list = pbs.pbsLevelList
    const len = pbs.alevel
    const levels: pbsStruct[] = []
    if (list.length === 0) {
      for (let i = 0; i < len; i++) {
        levels.push({
          alevel: i + 1,
          connector: i === len - 1 ? '' : '.',
          pbsId: pbs.id,
          levelName: '未定义级别',
          contents: '',
          codeView: 'N*',
          pbsCodelist: []
        })
      }
    } else {
      for (let i = 0; i < len; i++) {
        const target = list.find((node) => node.alevel === i + 1)
        if (target) {
          levels.push(target)
        } else {
          levels.push({
            alevel: i + 1,
            connector: i === len - 1 ? '' : '.',
            pbsId: pbs.id,
            levelName: '未定义级别',
            contents: '',
            codeView: 'N*',
            pbsCodelist: []
          })
        }
      }
    }
    pbs.pbsLevelList = levels
  }

  /**
   * 该方法用于根据PBS模板结构层级初始化PBS规则定义界面
   * @param {pbsStruct[]} pbsLevel pbs结构
   * @param {boolean} selectNode 是否定位到节点层级
   * @param {number} level 节点层级
   */
  initPbsRuleDefine(pbsDefine: pbsStruct[], selectNode: boolean = false, level: number) {
    if (!pbsDefine || pbsDefine.length < 3) {
      console.error('error')
      return
    }
    //编码预览

    const codeView = []
    pbsDefine.forEach((item) => {
      codeView.push(item.codeView)
      codeView.push(item.connector)
    })
    this.codePreview = codeView.join('')
    if (selectNode) {
      //保存后定位到该节点
      const node = pbsDefine.find((item) => {
        return item.alevel === level
      })
      this.currentLevel = node
      this.selectPBSNode(node.alevel)
    } else {
      this.selectPBSNode(pbsDefine[0].alevel)
    }
  }
  /**删除PBS模板 */
  deletePbsModel() {
    const ids = this.selectModels.map((item) => item.id).join(',')
    this.$confirm('是否删除PBS编码模板？', '提示', {
      type: 'warning'
    }).then(() => {
      deletePbsModelByIds({ ids: ids })
        .then((result) => {
          if (result.code === 1) {
            this.$message.success('删除成功')
            this.getModelList()
          }
        })
        .catch((err) => {
          console.error(err)
        })
    })
  }
  /**添加模板 */
  addModel() {
    this.isAddModelShow = true
    this.addModelForm.alevel = '3'
    this.addModelForm.name = ''
    this.addModelForm.remark = ''
  }
  /**提交添加模板 */
  submitAddModel() {
    if (this.addModelForm.name.trim() === '') {
      this.$message.warning('请输入模板名称')
      return
    }
    const params = {
      alevel: this.addModelForm.alevel,
      name: this.addModelForm.name,
      remark: this.addModelForm.remark
    }
    addPBScodeRule_api(params).then((result) => {
      if (result.code === 1) {
        this.$message.success('添加模板成功')
        this.getModelList()
        this.isAddModelShow = false
      } else {
        this.$message.error('添加模板失败')
      }
    })
  }
  /**打开业务对象弹窗 */
  openBoDialog(codewidget) {
    this.isAddBoShow = true
    this.searchBoGroup = ''
    this.currentBoWiget = codewidget
    this.getDataList()
  }
  /** 提交业务对象*/
  submitAddBo() {
    if (!this.selectBo) {
      this.$message.warning('请选择业务对象')
      return
    }
    this.currentBoWiget.boId = this.selectBo.id
    this.currentBoWiget.boGroupName = this.selectBo.boType
    this.isAddBoShow = false
  }
  /**项目业务对象 */
  getDataList() {
    let params = {
      boGroup: this.searchBoGroup
    }
    params = { ...params, ...this.bopagination }
    GetBoPage_api(params)
      .then((result) => {
        if (result.code !== 1) return
        this.bodataList = result.result.records
        const { current, size, total } = result.result
        this.bopagination = { current, size, total }
      })
      .catch((err) => {
        console.error(err)
      })
  }
  /**
   * 该方法用于保存PBS层级信息
   *
   */
  savePbsLevel() {
    if (!this.currentLevel && parseInt(this.selectedPbs.isUse) === 1) {
      return
    }
    const that = this
    const selectNode = this.currentLevel
    let isCorrect = true
    const level: pbsStruct = {
      levelName: selectNode.levelName,
      contents: selectNode.contents,
      connector: selectNode.connector,
      codeView: selectNode.codeView,
      alevel: selectNode.alevel,
      pbsId: selectNode.pbsId,
      pbsCodelist: selectNode.pbsCodelist,
      id: selectNode.id
    }
    const name = selectNode.levelName //层级名称
    const contents = selectNode.contents //层级说明
    //xss脚本检测

    const codeLen = selectNode.pbsCodelist.length
    if (contents === '' || name === '' || codeLen === 0) {
      this.$message.warning('请完善层级信息')
      return
    }
    //编码定义
    const codeDe: pbsNodeCode[] = selectNode.pbsCodelist
    selectNode.pbsCodelist.forEach((el) => {
      const codeType = el.codeType
      if (codeType === '1') {
        const boId = el.boId
        if (!boId) {
          this.$message.warning('请选择业务对象')
          isCorrect = false
          return
        }
      } else if (codeType === '2') {
        const codeLen = el.codeLength.toString().trim()
        const codeRemark = el.contents
        if (codeLen === '' || codeRemark === '') {
          this.$message.warning('请填写编码长度或说明')
          isCorrect = false
          return
        }
        if (isNaN(parseInt(codeLen)) || parseInt(codeLen) > 10) {
          this.$message.warning('请填写编码长度,不超过10位')
          isCorrect = false
          return
        }
      } else if (codeType === '3') {
        const codeLen = el.codeLength.toString().trim()
        if (isNaN(parseInt(codeLen)) || parseInt(codeLen) > 10) {
          this.$message.warning('请填写编码长度,不超过10位')
          isCorrect = false
          return
        }
      }
    })
    if (isCorrect && codeDe.length === 0) {
      this.$message.warning('请添加编码定义')
      return
    }
    if (!isCorrect) {
      return
    }
    level.codeView = this.computeCodeView(level)
    PutPBScodeRule_api(level).then((e) => {
      if (e.code === 1) {
        this.$message.success('保存成功')
        //保存成功，更新PBS模板,定位至层级
        this.rowClick(that.selectedPbs.id, true, level.alevel)
      } else {
        this.$message.error('保存失败')
      }
    })
  }
  /**
   * 该方法用于前端生成层级编码预览
   * @param level 层级
   */
  computeCodeView(level: pbsStruct) {
    const hasBOCode = level.pbsCodelist.find((item, index) => {
      return !item.codeLength || item.codeLength <= 0
    })
    if (hasBOCode) {
      return level.codeView
    } else {
      const codeView = []
      let str: string = 'N'
      level.pbsCodelist.forEach((item) => {
        codeView.push(str.repeat(item.codeLength))
      })
      return codeView.join('')
    }
  }
  /**
   * 删除编码定义部件
   */
  removeNodeCodeWidget(index) {
    this.currentLevel.pbsCodelist.splice(index, 1)
  }
  /**
   * 该方法用于动态添加pbs节点编码定义部件
   * @param {pbsNodeCode} code
   * @param {boolean} isEditable 是否可编辑
   */
  addNodeCodeWidget(code: pbsNodeCode, isEditable: boolean = true) {
    if (!code) {
      code = {
        codeType: '1',
        boId: undefined,
        codeLength: undefined,
        contents: ''
      }
      if (!this.currentLevel.pbsCodelist) this.currentLevel.pbsCodelist = []
      this.currentLevel.pbsCodelist.push(code)
    }
    let codeLen = ''
    if (code.codeLength) {
      codeLen = code.codeLength.toString()
    }
    if (code.codeType === '1') {
      GetBoById_api({id:code.boId}).then((result) => {
          code.boGroupName = result.result.boType
          const index=this.currentLevel.pbsCodelist.findIndex(item=>{item.boId===code.boId})
          this.currentLevel.pbsCodelist.splice(index,1,code)
      })
    }
  }
  /**
   * 该方法用于选中pbs层级节点按钮
   * @param {number} alevel 层级
   */
  selectPBSNode(alevel: number) {
    if (!this.selectedPbs) return
    const pbsDefine = this.selectedPbs.pbsLevelList
    const node = pbsDefine.find((item) => item.alevel === alevel)
    this.currentLevel = node
    const codes = this.currentLevel.pbsCodelist || []
    codes.forEach((item, index) => {
      this.addNodeCodeWidget(item, false)
    })
  }
  /**属性表格勾选事件 */
  selectChange(selection) {
    this.selectModels = selection
  }
}
</script>
<style lang="scss" scoped>
@import '~@/styles/mixin.scss';
.halfHeight {
  height: 50%;
  position: relative;
}
.pbstb {
  .tf-table {
    height: calc(100% - 52px);
    padding: 0;
  }
}
.pbsDefine {
  position: relative;
  height: 100%;
  padding-left: 10px;
  .preview {
    .el-row {
      padding: 5px 10px;
    }
    .previewBtn {
      display: flex;
      .btngroup {
        .el-button {
          margin-right: 10px;
        }
        .el-button.active {
          background: #3a8ee6;
          border-color: #3a8ee6;
          color: #fff;
          outline: 0;
        }
        .el-select {
          margin-right: 10px;
          width: 70px;
        }
      }
    }
  }
  .footerBtns {
    position: absolute;
    bottom: 35px;
    left: 0;
    right: 0;
    text-align: right;
  }
  .nodeDefine {
    overflow-y: auto;
    overflow-x: hidden;
    height: calc(100% - 285px);
    @include scrollBar;
    .col16,
    .col16.el-input {
      width: 66.6666666667%;
    }
  }
}
</style>