<template>
  <el-row>
    <el-form-item label="控件标题">
      <el-input v-model="activeData.__config__.label" placeholder="请输入控件标题" />
    </el-form-item>
    <el-form-item label="占位提示">
      <el-input v-model="activeData.placeholder" placeholder="请输入占位提示" />
    </el-form-item>
    <template v-if="!activeData.__config__.isSubTable">
      <el-form-item label="控件栅格">
        <el-slider v-model="activeData.__config__.span" :max="24" :min="6" show-stops :step="2" show-tooltip />
      </el-form-item>
      <el-form-item label="标题宽度">
        <el-input-number v-model="activeData.__config__.labelWidth" placeholder="标题宽度" :min="0" :precision="0" controls-position="right" />
      </el-form-item>
    </template>
    <el-form-item label="控件宽度" v-if="activeData.__config__.isSubTable">
      <el-input-number v-model="activeData.__config__.columnWidth" placeholder="控件宽度" :min="0" :precision="0" controls-position="right" />
    </el-form-item>
    <el-form-item label="默认值" v-if="activeData.__config__.dataType === 'static'">
      <el-cascader
        :options="activeData.options"
        clearable
        :show-all-levels="activeData['show-all-levels']"
        :props="activeData.props.props"
        filterable
        v-model="activeData.__config__.defaultValue"
        :key="cascaderKey"
      ></el-cascader>
    </el-form-item>
    <el-form-item label="选项分隔符">
      <el-input v-model="activeData.separator" placeholder="请输入选项分隔符" />
    </el-form-item>
    <template>
      <el-divider>选项</el-divider>
      <el-form-item label="" label-width="40px">
        <el-radio-group v-model="activeData.__config__.dataType" size="small" style="text-align: center" @change="dataTypeChange">
          <el-radio-button label="static">静态数据</el-radio-button>
          <el-radio-button label="dictionary">数据字典</el-radio-button>
          <el-radio-button label="dynamic">API数据</el-radio-button>
        </el-radio-group>
      </el-form-item>
      <template v-if="activeData.__config__.dataType === 'static'">
        <!-- 级联选择静态树 -->
        <el-tree draggable :data="activeData.options" node-key="id" :expand-on-click-node="false" :render-content="renderContent" :props="props" />
        <div style="margin-left: 20px">
          <el-button style="padding-bottom: 0" icon="el-icon-circle-plus-outline" type="text" @click="addTreeItem">添加父级</el-button>
        </div>
      </template>
      <!--      <JNPF-TreeSelect :options="treeData" v-model="activeData.__config__.dictionaryType"-->
      <!--        placeholder="选择数据字典" lastLevel v-if="activeData.__config__.dataType==='dictionary'"-->
      <!--        clearable />-->
      <el-select @change="wallpaperInput" placeholder="选择数据字典" v-model="activeData.__config__.dictionaryType" v-if="activeData.__config__.dataType === 'dictionary'">
        <el-option v-for="(item, i) of treeData" :key="i" :value="item.id" :label="item.keyCode"></el-option>
      </el-select>
      <template v-if="activeData.__config__.dataType === 'dynamic'">
        <el-form-item label="API数据">
          <el-cascader
            :options="dataInterfaceSelector"
            v-model="activeData.__config__.propsUrl"
            placeholder="请选择API数据"
            :filter-method="apiFilterMethod"
            :props="{ expandTrigger: 'hover', emitPath: false }"
            :show-all-levels="false"
            @change="propsUrlChange"
            clearable
            filterable
          >
          </el-cascader>
        </el-form-item>
        <el-divider>API返回值设置</el-divider>
        <el-form-item>
          <template slot="label">
            <span>组件设置:</span>
            <el-tooltip style="cursor: pointer" effect="dark" :content="'当前组件设置，指定API返回值某一项作为key或value'" placement="top">
              <i class="el-icon-question" />
            </el-tooltip>
          </template>
          <el-button size="mini" type="primary" plain @click="previewClick" icon="View">API返回值结构预览</el-button>
        </el-form-item>
        <el-form-item label="key值">
          <el-select placeholder="请选择key值" v-model="activeData.__config__.apiProps.value">
            <el-option v-for="(item, i) of showFields" :key="i" :value="item.columnComments" :label="item.columnName"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="value值">
          <el-select placeholder="请选择value值" v-model="activeData.__config__.apiProps.label">
            <el-option v-for="(item, i) of showFields" :key="i" :value="item.columnComments" :label="item.columnName"></el-option>
          </el-select>
        </el-form-item>
        <el-divider>子节点设置</el-divider>
        <el-form-item>
          <template slot="label">
            <span>子节点值:</span>
            <el-tooltip style="cursor: pointer" effect="dark" :content="'id'" placement="top">
              <i class="el-icon-question" />
            </el-tooltip>
          </template>
          <el-select placeholder="请选择子节点值" v-model="activeData.__config__.apiProps.idKey">
            <el-option v-for="(item, i) of showFields" :key="i" :value="item.columnComments" :label="item.columnName"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <template slot="label">
            <span>父节点值:</span>
            <el-tooltip style="cursor: pointer" effect="dark" :content="'pid'" placement="top">
              <i class="el-icon-question" />
            </el-tooltip>
          </template>
          <el-select placeholder="请选择父节点值" v-model="activeData.__config__.apiProps.pidKey">
            <el-option v-for="(item, i) of showFields" :key="i" :value="item.columnComments" :label="item.columnName"></el-option>
          </el-select>
        </el-form-item>
        <!--        <el-form-item label="标签键名">-->
        <!--          <el-input v-model="activeData.props.props.label" placeholder="请输入标签键名" />-->
        <!--        </el-form-item>-->
        <!--        <el-form-item label="值键名">-->
        <!--          <el-input v-model="activeData.props.props.value" placeholder="请输入值键名" />-->
        <!--        </el-form-item>-->
        <el-form-item label="子级键名">
          <el-input v-model="activeData.props.props.children" placeholder="请输入子级键名" />
        </el-form-item>
        <template v-if="activeData.__config__.ApiReturn && activeData.__config__.ApiReturn.length">
          <el-divider>API变量设置</el-divider>
          <el-form-item>
            <template slot="label">
              <span>变量设置:</span>
              <el-tooltip style="cursor: pointer" effect="dark" :content="'当前页面变量设置，从API返回值结构预览中选择一或多个类作为变量'" placement="top">
                <i class="el-icon-question" />
              </el-tooltip>
            </template>
          </el-form-item>
          <el-table :data="activeData.__config__.ApiReturn" style="width: 100%">
            <el-table-column prop="keyName" label="API返回值"></el-table-column>
            <el-table-column label="页面变量名">
              <template slot-scope="scope">
                <el-input @input="varNamefitlte(scope.row, $event)" v-model="scope.row.varName" placeholder="请输入页面变量名" />
                <div v-if="varNamefitlteclass(scope.row, scope.row.varName)" style="color: red">变量名重复 重新输入</div>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="50">
              <template slot-scope="scope">
                <div class="close-btn select-line-icon" style="cursor: pointer" @click="activeData.__config__.ApiReturn.splice(scope.$index, 1)">
                  <i class="el-icon-delete" />
                </div>
              </template>
            </el-table-column>
          </el-table>
        </template>
      </template>
      <el-divider />
    </template>
    <el-form-item label="是否多选">
      <el-switch v-model="activeData.props.props.multiple" />
    </el-form-item>
    <el-form-item label="多选分隔符" v-if="activeData.props.props.multiple">
      <el-input v-model="activeData.props.props.Separator" placeholder="请输入多选分隔符" />
    </el-form-item>
    <el-form-item label="展示全路径">
      <el-switch v-model="activeData['show-all-levels']" />
    </el-form-item>
    <el-form-item label="选择任意级">
      <el-switch v-model="activeData.props.props.checkStrictly" />
    </el-form-item>
    <el-form-item label="可否筛选">
      <el-switch v-model="activeData.filterable" />
    </el-form-item>
    <el-form-item label="能否清空">
      <el-switch v-model="activeData.clearable" />
    </el-form-item>
    <el-form-item label="是否禁用">
      <el-switch v-model="activeData.disabled" />
    </el-form-item>
    <el-form-item label="是否必填">
      <el-switch v-model="activeData.__config__.required" />
    </el-form-item>
    <!-- <el-form-item label="显示标签">
      <el-switch v-model="activeData.__config__.showLabel" />
    </el-form-item> -->
    <treeNode-dialog :visible.sync="dialogVisible" title="添加选项" @commit="addNode" />
    <el-dialog :visible.sync="previewShow" title="API数据结构预览" width="800px" append-to-body class="source-http-preview">
      <el-table :data="previewArr" border row-key="path" default-expand-all>
        <el-table-column label="结构">
          <template #default="scope">
            {{ scope.row.key }}
          </template>
        </el-table-column>
        <el-table-column label="类型" width="100px" align="center">
          <template #default="scope">
            {{ scope.row.type }}
          </template>
        </el-table-column>
        <el-table-column label="jsonpath">
          <template #default="scope">
            {{ scope.row.path }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="140px" align="center">
          <template #default="scope">
            <el-button v-if="scope.row.type === 'array'" size="small" type="primary" plain @click="getAllPath(scope.row)"> 使用全部子项 </el-button>
            <el-button v-if="scope.row.type !== 'array' && scope.row.type !== 'object'" size="small" type="primary" plain @click="getPath(scope.row)"> 使用 </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </el-row>
</template>
<script>
import comMixin from '../mixin'
import TreeNodeDialog from './TreeNodeDialog'
import { getDictionaryTypeSelector, getDictionaryDataSelector } from '@/api/systemData/dictionary'
import { dataapicategoryList, dataapiDetail, dataapiList, getDataInterfaceSelector, previewDataInterface } from '@/api/systemData/dataInterface'
import { dictDetail, dictList } from '@/api/newbi/dict'
import { getAPIData } from '@/components/Dataset-filter/util'
import { openurl } from '@/components/Dataset-filter/report'
import { param } from '@/components/Dataset-filter/config'

export default {
  props: ['activeData', 'drawList'],
  mixins: [comMixin],
  components: { TreeNodeDialog },
  data() {
    return {
      treeData: [],
      dataInterfaceSelector: [],
      dialogVisible: false,
      currentNode: {},
      props: {
        value: 'id',
        label: 'fullName',
        children: 'children'
      },
      cascaderKey: +new Date(),
      showFields: [],
      previewShow: false,
      previewArr: [],
      apiVarList: [],
      apiJoinName:'',
    }
  },
  watch: {
    'activeData.__config__.dictionaryType': function (val) {
      this.activeData.__config__.defaultValue = ''
      if (!val) {
        this.activeData.options = []
        return
      }
      dictDetail({ id: val }).then((res) => {
        // this.activeData..options = res.data.data.list
        let content = JSON.parse(res.data.data.content || '[]')
        this.activeData.options = content.map((i) => ({ fullName: i.key, id: i.value }))
      })
    }
  },
  created() {
    this.getDictionaryType()
    this.getDataInterfaceSelector()
    if (this.activeData.__config__.dataType === 'dynamic' && this.activeData.__config__.propsUrl) {
      this.propsUrlChange(this.activeData.__config__.propsUrl)
    }
  },
  methods: {
    wallpaperInput() {
      this.$nextTick(() => {
        this.$forceUpdate()
      })
    },
    getDictionaryType() {
      // getDictionaryTypeSelector().then(res => {
      //   this.treeData = res.data.data.list
      // })
      dictList({ current: 1, size: 10000 }).then((res) => (this.treeData = res.data.data.records))
    },
    previewClick() {
      if (!this.activeData.__config__.propsUrl)
        return this.$message({
          message: '当前未选择API接口，不支持数据预览',
          type: 'warning'
        })
      dataapiDetail(this.activeData.__config__.propsUrl).then((res) => {
        let { apiKey } = res.data.data
        this.apiJoinName = res.data.data.apiName
        let resJson = JSON.parse(res.data.data.note || '{}')
        let formVarObj = {}
        if (resJson.params && resJson.params.length) {
          resJson.params.forEach((i, k) => {
            formVarObj[i.key] = i.def
          })
        }
        openurl(apiKey, { ...param, ...formVarObj }).then((res) => {
          let data = res.data
          try {
            let arr = []
            this.previewShow = true
            this.jsonPath(arr, data, '$')
            this.previewArr = arr
          } catch (e) {
            this.$message({ message: '接口返回数据格式不支持', type: 'warning' })
          }
        })
      })
    },
    jsonPath(arr, json, basePath) {
      const type = this.validateType(json)
      if (type === 'object') {
        for (let key in json) {
          const item = {
            key,
            path: `${basePath}.${key}`
          }
          const childType = this.validateType(json[key])
          item.type = childType
          if (childType === 'object' || childType === 'array') {
            item.leaf = true
            item.children = []
            this.jsonPath(item.children, json[key], item.path)
          } else {
            item.leaf = false
            item.value = json[key]
          }
          arr.push(item)
        }
      } else if (type === 'array') {
        json = json[0]
        if (json === undefined) return
        for (let key in json) {
          const item = {
            key,
            path: `${basePath}[*].${key}`
          }
          const childType = this.validateType(json[key])
          item.type = childType
          if (childType === 'object' || childType === 'array') {
            item.leaf = true
            item.children = []
            this.jsonPath(item.children, json[key], item.path)
          } else {
            item.leaf = false
            item.value = json[key]
          }
          arr.push(item)
        }
      }
    },
    validateType(val) {
      // 校验JSON数据类型
      const type = typeof val
      if (type === 'object') {
        if (Array.isArray(val)) {
          return 'array'
        } else if (val === null) {
          return 'null'
        } else {
          return 'object'
        }
      } else {
        return type
      }
    },
    getPath(item) {
      this.getAPiPath(item)
    },
    getAllPath(array) {
      array.children.forEach((item) => this.getAPiPath(item))
    },
    getAPiPath({ key }) {
      if (this.activeData.__config__.ApiReturn.find((i) => i.keyName === key)) return
      this.activeData.__config__.ApiReturn.push({ keyName: key, varName: key,apiName:this.apiJoinName })
      // this.getAllapiVarList()
      // this.varTypeList[3].children = this.apiVarList
    },
    varNamefitlte(row, val) {
      if (this.activeData.__config__.ApiReturn.find((i) => i.varName === val && i.keyName !== row.keyName)) {
        this.activeData.varRepeat = true
        return this.$message({
          message: '检测到变量命名重复，请重新输入',
          type: 'warning'
        })
      }
      if (this.apiVarList.find((i) => i.label === val)) {
        this.activeData.varRepeat = true
        return this.$message({
          message: '检测到变量命名重复，请重新输入',
          type: 'warning'
        })
      }
      this.activeData.varRepeat = false
    },
    varNamefitlteclass(row, val) {
      let flag = false
      if (this.activeData.__config__.ApiReturn.find((i) => i.varName === val && i.keyName !== row.keyName)) {
        flag = true
      }
      if (this.apiVarList.filter((i) => i.label === val).length > 1) {
        flag = true
      }
      return flag
    },
    getAllapiVarList() {
      //获取API返回变量
      this.apiVarList = []
      this.drawList.forEach((item, key) => {
        let config = item.__config__
        if (config.ApiReturn && config.ApiReturn.length) {
          let list = config.ApiReturn.map((o) => {
            return {
              label: o.varName,
              value: o.varName
            }
          }).filter((l) => l !== undefined)
          this.apiVarList = [...this.apiVarList, ...list]
        }
      })
    },
    apiFilterMethod(node, keyword) {
      let { label, key } = node.data
      keyword = keyword.toLowerCase()
      return label.includes(keyword) || key.toLowerCase().includes(keyword)
    },
    getDataInterfaceSelector() {
      //获取api列表
      dataapicategoryList().then((res) => {
        let category = res.data.data
        dataapiList({ apiFormal: 1, apiTypes: '1,2' }).then((res) => {
          let list = res.data.data
          this.dataInterfaceSelector = category
            .map((i) => ({
              label: i.categoryName,
              value: i.id,
              children: list.filter((j) => j.categoryId === i.id).map((k) => ({ label: k.apiName, value: k.id, key: k.apiKey }))
            }))
            .filter((i) => i.children.length)
        })
      })
    },
    renderContent(h, { node, data, store }) {
      return (
        <div class="custom-tree-node">
          <span>{node.label}</span>
          <span class="node-operation">
            <i on-click={() => this.append(data)} class="el-icon-plus" title="添加"></i>
            <i on-click={() => this.remove(node, data)} class="el-icon-delete" title="删除"></i>
          </span>
        </div>
      )
    },
    addTreeItem() {
      this.dialogVisible = true
      this.currentNode = this.activeData.options
    },
    addNode(data) {
      this.currentNode.push(data)
    },
    append(data) {
      if (!data.children) {
        this.$set(data, 'children', [])
      }
      this.dialogVisible = true
      this.currentNode = data.children
    },
    remove(node, data) {
      this.activeData.__config__.defaultValue = [] // 避免删除时报错
      const { parent } = node
      const children = parent.data.children || parent.data
      const index = children.findIndex((d) => d.id === data.id)
      children.splice(index, 1)
    },
    dataTypeChange() {
      this.cascaderKey = +new Date()
      this.activeData.__config__.renderKey = +new Date()
      this.activeData.__config__.defaultValue = []
      this.activeData.options = []
      this.activeData.props.props.value = 'id'
      this.activeData.props.props.label = 'fullName'
      this.activeData.props.props.children = 'children'
      this.activeData.__config__.dictionaryType = ''
      this.activeData.__config__.propsUrl = ''
    },
    propsUrlChange(val) {
      this.activeData.__config__.defaultValue = []
      if (!val) {
        this.activeData.options = []
        return
      }
      // this.activeData.__config__.apiProps = {label: '',value: '',idKey: '',pidKey: ''}
      // this.activeData.__config__.ApiReturn = []
      //获取api信息
      dataapiDetail(val).then((res) => {
        //获取api值
        getAPIData(this.activeData, val, [], [], '', this.activeData.__config__.apiProps).then((res) => {
          try {
            let treeData = g.T.toTree(res, this.activeData.props.props.children, this.activeData.__config__.apiProps.idKey, this.activeData.__config__.apiProps.pidKey)
            this.$set(this.activeData, 'options', treeData)
          } catch {}
        })
        let resJson = JSON.parse(res.data.data.note || '{}')
        this.showFields = resJson.showFields || []
        if (resJson.params && resJson.params.length) {
          //添加变量类型 1：默认 2：全局系统变量 3：表单内全局变量
          if (!this.activeData.__config__.ApiParams.length) {
            resJson.params.forEach((i, k) => [Object.assign(i, { varType: [1] })])
            this.activeData.__config__.ApiParams = resJson.params
          } else {
            let APIKeylist = resJson.params.map((i) => {
              return i.key
            })
            let paramsList = this.activeData.__config__.ApiParams.filter((l) => APIKeylist.includes(l.key))
            paramsList.forEach((i, k) => {
              if (!i.varType) {
                Object.assign(i, { varType: [1] })
              }
            })
            this.activeData.__config__.ApiParams = paramsList
          }
        } else {
          this.activeData.__config__.ApiParams = []
        }
      })
    }
  }
}
</script>
<style lang="scss" scpoed>
.custom-tree-node {
  width: 100%;
  font-size: 14px;
  display: flex;
  justify-content: space-between;
  .node-operation {
    float: right;
  }
  i[class*='el-icon'] + i[class*='el-icon'] {
    margin-left: 6px;
  }
  .el-icon-plus {
    color: #409eff;
  }
  .el-icon-delete {
    color: #157a0c;
  }
}
</style>
