<template>
  <info-con title="规格信息：" class="sale-info-con">
    <!-- <div
      class="item"
      v-for="(pItem, pIndex) of propList"
      :key="'prop-item-' + pIndex"
    >
    <label class="label">规格参数：</label>
      <Input
        style="width:140px;margin-right:10px;"
        placeholder="请输入规格名称"
        @on-change="delAllSku(pItem, pIndex)"
        v-model="pItem.name"
        :readonly="isDetail || isEdit"
        :maxlength="30"
      />
      <div class="property-con">
        <div
          class="property-item"
          v-for="(vItem, vIndex) of pItem.valList"
          :key="'val-item-' + vIndex"
        >
          <Input
            class="prop-val"
            placeholder="请输入规格值"
            @on-change="delSkuVal(pItem, vIndex)"
            v-model="vItem.val"
            :readonly="isDetail || isEdit"
            :maxlength="30"
          />
          <Icon
            class="del-con"
            type="md-close-circle"
            color="#ed4014"
            :size="20"
            @click="delVal(pItem, vIndex)"
            v-if="!isDetail && !isEdit"
          />
        </div>
        <div class="add-btn">
          <Button
            type="info"
            shape="circle"
            size="small"
            @click="addVal(pItem)"
            v-if="!isDetail && !isEdit && pItem.valList.length < 10"
            >+ 添加属性值</Button
          >
        </div>
      </div>
      <Icon
        class="del-con"
        type="md-backspace"
        color="#ed4014"
        :size="30"
        @click="delProp(pIndex)"
        v-if="!isDetail && !isEdit"
      />
    </div> -->
    <!-- <div class="item">
      <div class="empty" />
      <div class="opt-btn" v-if="!isDetail && !isEdit">
        <Button type="info" @click="addProp" v-show="propList.length < 3"
          >+ 添加属性</Button
        >
      </div>
    </div> -->
    <div class="item">
      <label class="label">销售模式：</label>
      <RadioGroup v-model="data.salesType" @on-change="changeSalesType">
        <Radio :label="1" style="width: 200px" :disabled="isDetail || isEdit"
          >普通</Radio
        >
        <Radio :label="4" style="width: 200px" :disabled="isDetail || isEdit"
          >盲盒</Radio
        >
      </RadioGroup>
    </div>
    <div class="item">
      <label class="label">商品价格：</label>
      <Input
        v-model="data.price"
        :readonly="isDetail"
        placeholder="请输入商品价格"
        style="width: 400px"
      />
    </div>
    <div class="item" v-if="data.salesType === 1">
      <label class="label">商品通证：</label>
      <RadioGroup v-model="data.tzType" @on-change="changeTzType">
        <Radio
          :label="1"
          :disabled="isDetail || isEdit || isAgain"
          style="width: 200px"
          >内部发行</Radio
        >
        <Radio
          :label="2"
          :disabled="isDetail || isEdit || isAgain"
          style="width: 200px"
          >外部绑定</Radio
        >
      </RadioGroup>
    </div>
    <div class="item" v-if="data.salesType === 4">
      <label class="label">商品通证：</label>
      <RadioGroup v-model="data.commodityPass">
        <Radio :label="1" style="width: 200px" :disabled="isDetail || isEdit"
          >是，自动生成Token</Radio
        >
        <Radio :label="2" style="width: 200px" :disabled="isDetail || isEdit"
          >是，使用外部既有Token</Radio
        >
      </RadioGroup>
    </div>
    <template v-if="data.salesType == 1">
      <div class="item" v-if="data.tzType == 1">
        <label class="label">NFT类型：</label>
        <RadioGroup v-model="data.type" @on-change="changeType">
          <Radio
            :label="1"
            :disabled="isDetail || isEdit || isAgain"
            style="width: 200px"
            >单个，不可拷贝</Radio
          >
          <Radio
            :label="2"
            :disabled="isDetail || isEdit || isAgain"
            style="width: 200px"
            >可拷贝</Radio
          >
        </RadioGroup>
      </div>
      <div class="item" v-if="data.type == 2">
        <label class="label">发行数量：</label>
        <Input
          v-model="data.number"
          :readonly="isDetail || isEdit || isAgain || isDraft"
          placeholder="请输入发行数量，正整数"
          style="width: 400px"
        />
      </div>
      <div class="item" v-if="data.tzType == 2">
        <label class="label">绑定NFT：</label>
        <Input
          v-model="data.tokenId"
          v-if="isDetail || isEdit || isAgain"
          :readonly="isDetail || isEdit || isAgain || isDraft"
          style="width: 400px"
        />
        <Select
          v-else
          placeholder="请选择NFT TOKENID"
          transfer
          v-model="data.tokenId"
          @on-change="handleNFT"
          style="width: 200px"
        >
          <Option
            :value="item.labelName"
            v-for="(item, index) of nftList"
            :key="`rate-option-${index}`"
            >{{ item.labelName }}</Option
          >
        </Select>
      </div>
      <!-- <div class="item">
        <label class="label">库存：</label>
        <Input
          v-model="data.stock"
          :readonly="isDetail"
          placeholder="请输入库存，正整数"
          type="number"
          :maxlength="9"
          @on-change="inputChangeStock($event)"
        />
      </div> -->
    </template>
    <template v-if="data.salesType === 4">
      <div class="item" style="text-align: center">
        <label class="label">规格列表:</label>
        <Table border :columns="columns" :data="data.sku">
          <template slot-scope="{ row, index }" slot="name">
            <span v-if="isDetail">{{ row.name }}</span>
            <Input
              v-else
              placeholder="规格名称"
              :value="row.name"
              @on-change="handleInputChange(index, 'name')"
              :readonly="isDetail"
            />
          </template>
          <template slot-scope="{ row, index }" slot="image">
            <file-upload
              :ref="'fileUpload' + index"
              :width="46"
              style="margin-top: 5px"
              v-model="data.sku[index].upload.imageList"
              @input="handleUploadInput($event, index)"
              :maxNum="1"
              :defaultList="data.sku[index].upload.defaultImgList"
              :readonly="isDetail"
              showWatch
              :iconSize="16"
            />
          </template>
          <template slot-scope="{ row, index }" slot="weight">
            <span v-if="isDetail">{{ row.weight }}</span>
            <Input
              v-else
              placeholder="单位（KG）"
              :value="row.weight"
              @on-change="handleInputChange(index, 'weight')"
              type="number"
              :readonly="isDetail"
            />
          </template>
          <template slot-scope="{ row, index }" slot="stock">
            <span v-if="isDetail">{{ row.stock }}</span>
            <Input
              v-else
              placeholder="整数值"
              :value="row.stock"
              @on-change="handleInputChange(index, 'stock')"
              @on-blur="onBlur(index, row)"
              type="number"
              :readonly="isDetail"
              :maxlength="9"
            />
          </template>
          <template slot-scope="{ row, index }" slot="coinName">
            <template v-if="isDetail || isEdit || data.sku[index].status == 1">
              <label class="coinName-label">{{
                row.coinNamePrefix + row.coinName || "--"
              }}</label>
            </template>
            <template v-else>
              <div v-if="data.commodityPass == 1">
                <label>内部生成</label>
              </div>
              <div v-if="data.commodityPass == 0">
                <label class="coinName-label">{{ coinNamePrefix }}</label>
                <!-- <label class="coinName-label" style="color: #ed4014"
            >&nbsp;&nbsp;+&nbsp;&nbsp;</label
          > -->
                <Input
                  placeholder="2-10位大写字母或数字"
                  :value="row.coinName"
                  @on-change="handleInputChange(index, 'coinName')"
                  @on-blur="handleInputBlur(index, 'coinName')"
                  style="width: 140px"
                   :readonly="isDetail || isEdit || isAgain || isDraft"
                  :disabled="isDetail || data.sku[index].status == 1"
                  :maxlength="10"
                />
              </div>
              <div v-if="data.commodityPass == 2">
                <label class="coinName-label">{{ coinNamePrefix }}</label>
                <Select
                  :transfer="true"
                  v-model="data.sku[index].commodityPassId"
                  @on-change="getMoreParams($event,index)"
                  style="width: 140px"
                >
                  <Option
                    v-for="(item, index) of nftList"
                    :value="item.labelName"
                    :key="'series-option-' + index"
                    >{{ item.labelName }}</Option
                  >
                </Select>
              </div>
            </template>
          </template>
          <template slot-scope="{ row, index }" slot="isHide">
            <span v-if="isDetail">{{ row.isHide ? "是" : "否" }}</span>
            <Checkbox
              v-model="row.isHide"
              @on-change="changIsHidden($event, index)"
            ></Checkbox>
          </template>

          <template slot-scope="{ index }" slot="opt">
            <Button type="error" size="small" @click="delSku(index)"
              >删除</Button
            >
          </template>
        </Table>
      </div>
      <div class="item" style="justify-content: flex-end">
        <Button type="primary" style="margin: auto" @click="genSkuTable"
          >添加商品</Button
        >
      </div>
      <div class="item" style="margin-top: 40px">
        <label class="label">难度系数：</label>
        <Slider
          v-model="data.difficulty"
          :tip-format="format"
          :min="1"
          :max="10"
          style="width: 500px"
        ></Slider>
      </div>
      <div class="item">
        <label class="label">盲盒规则：</label>
        <div class="editor-con">
          <Spin fix v-if="editorLoading">
            <Icon
              type="ios-loading"
              size="30"
              color="#2d8cf0"
              class="spin-icon-load"
            ></Icon>
            <div>上传中( {{ editorUploadPercent }}% )...</div>
          </Spin>
          <quill-editor
            v-model="data.blindBoxRule"
            ref="myQuillEditor"
            :options="editorOption"
            class="detail-editor"
            v-show="!isDetail"
          ></quill-editor>
          <div
            v-show="isDetail"
            v-html="data.blindBoxRule"
            class="describt-detail"
          ></div>
        </div>
      </div>
      <Upload
        :action="uploadImgUrl"
        ref="uploadImg"
        v-show="false"
        :headers="{
          token: $store.state.admin.token,
          adminId: $store.state.admin.uid,
        }"
        :before-upload="imgBoforeUpload"
        :on-progress="uploadOnProgress"
        :on-success="imgUploadSuccess"
        :on-error="imgUploadErr"
        accept=".jpg, .jpeg, .png, .gif"
      />
      <Upload
        :action="uploadVideoUrl"
        ref="uploadVideo"
        v-show="false"
        :headers="{
          token: $store.state.admin.token,
          adminId: $store.state.admin.uid,
        }"
        :before-upload="videoBoforeUpload"
        :on-progress="uploadOnProgress"
        :on-success="videoUploadSuccess"
        :on-error="videoUploadErr"
        accept=".mp4, .mkv"
      />
    </template>
  </info-con>
</template>

<script>
import InfoCon from './info-con'
import FileUpload from '_c/file-upload'
import { uploadImgUrl, uploadVideoUrl } from '@/api/apiConfig'
import { apiVerify } from '@/api/apiVerify'
import { getPosterFromVideoUrl } from '@/libs/tools'
export default {
  props: {
    data: {
      // type: Object,
      default: { sku: [] },
      commodityPass: '',
      number: '', // 发行数量：只有商户选择“可拷贝”时，才会出现
      price: '', // 商品价格
      type: '', // NFT类型（1.单个，不可考贝 2.可拷贝）
      tzType: '', // 1.内部发行 2.外部绑定
      tokenId: '', // 绑定的外部通证id
      salesType: 2, // 销售模式
      difficulty: 1
    },
    isDetail: {
      type: Boolean,
      default: false
    },
    isEdit: {
      type: Boolean,
      default: false
    },
    isAgain: {
      type: Boolean,
      default: false
    },
    isDraft:{
      type: Boolean,
      default: false
    }
  },
  components: {
    InfoCon,
    FileUpload
  },
  data () {
    return {
      propList: [{ name: '', valList: [{ val: '' }] }],
      columns: [],
      coinNamePrefix: '',
      seriesList: [{}],
      name: '',
      tokenNumber: '',
      numberStock: '',
      // rateList: [3, 4, 5, 6, 9, 10, 11, 13],
      difficulty: 1,
      nftList: [],
      uploadImgUrl,
      uploadVideoUrl,
      editorOption: {
        placeholder: '请输入内容...',
        modules: {
          toolbar: [
            [
              'bold',
              'italic',
              { header: 2 },
              'blockquote',
              { list: 'ordered' },
              { list: 'bullet' },
              { align: [] }
            ],
            ['image', 'video']
          ]
        }
      },
      editorLoading: false,
      editorUploadPercent: 0
    }
  },
  computed: {
    platform () {
      return (
        this.$store.state.admin.type == 1 || this.$store.state.admin.type == 4
      )
    },
    editor () {
      return this.$refs.myQuillEditor.quill
    }
  },
  mounted () {
    this.editor.getModule('toolbar').addHandler('image', this.imgHandler)
    this.editor.getModule('toolbar').addHandler('video', this.videoHandler)
    this.genPropList(this.data.sku)
    this.genColumn()
    this.getNftList()
    if (!this.platform) {
      this.getMerchantPrefixInfo()
    }
    if (!this.platform) {
      this.getunbindToken()
    }
    this.data.sku.forEach((item) => {
      this.numberStock = item.stock
      if (this.isAgain) {
        item.republish = false
      }
      item.coinNamePrefix = item.coinName.substring(0, 4)
      item.coinName = item.coinName.substring(4)
      // console.log('coinName', item.coinName)
    })
    setTimeout(() => {})
  },
  methods: {
    // inputChangeStock (e) {
    //   this.data.stock = e.target.value
    // },
    handleNFT(val){
      let obj=this.nftList.filter(x=>{
        return x.labelName===val
      })
      this.data.number=obj&&obj.length>0?obj[0].availableNumber:2
    },
    changeTzType () {
      this.data.type = ''
      this.data.number = ''
      this.data.tokenId = ''
    },
    changeSalesType (val) {
      if (val === 4) {
        if (this.data.sku.length == 0 || !this.data.sku) {
          this.genSkuTable()
        }
      } else {
        this.data.salesType = val
      }
    },
    changeType () {
      this.data.number = ''
    },
    getNftList () {
      // 获取外部NFT
      this.api({
        apiName: 'externnftlist',
        success: (res) => {
          // console.log('333', this.nftList)
          this.nftList = res.data
        }
      })
    },
    format (val) {
      return '难度系数: ' + val + ''
    },
    getMoreParams (val, index) {
      let obj=this.nftList.filter(x=>{
        return x.labelName===val
      })
      this.tokenNumber = val.availableNumber
      this.data.sku[index].stock =obj&&obj.length>0?obj[0].availableNumber:2
    },
    changIsHidden (val, index) {
      this.data.sku[index].isHide = val
    },
    onBlur (index, val) {
      // console.log('4444', this.data.commodityPass)
      if (
        !this.isEdit &&
        JSON.parse(val.stock) > this.tokenNumber &&
        this.data.commodityPass == 2
      ) {
        this.data.sku[index].stock = parseInt(this.tokenNumber)
        return this.$Notice.warning({
          title: `填写库存过多 (实际数量：${parseInt(this.tokenNumber)})`
        })
      }
      if (this.isEdit && this.data.commodityPass == 2) {
        let number = JSON.parse(val.stock) - this.numberStock
        //  + this.data.sku[index].balanceNum
        if (number > this.data.sku[index].balanceNum) {
          this.data.sku[index].stock = parseInt(
            this.numberStock + this.data.sku[index].balanceNum
          )
          return this.$Notice.warning({
            title: `填写库存过多 (实际数量：${parseInt(
              this.numberStock + this.data.sku[index].balanceNum
            )})`
          })
        }
      }
    },
    getMerchantPrefixInfo () {
      this.api({
        apiName: 'getMerchantPrefix',
        success: (res) => {
          this.coinNamePrefix = res.data
        }
      })
    },
    getunbindToken () {
      this.api({
        apiName: 'unbindToken',
        success: (res) => {
          this.seriesList = res.data
        }
      })
    },
    handleInputChange (index, key) {
      this.data.sku[index][key] = event.target.value
    },
    handleInputBlur (index, key) {
      if (this.isAgain) {
        if (key == 'coinName') {
          this.data.sku[index].republish = true
          this.data.sku[index].coinNamePrefix = this.coinNamePrefix
        }
      }
    },
    handleUploadInput (e, index) {
      console.log(index, this.data.sku)
      // this.data.sku[index].upload.imageList = e;
      // this.data.sku[index].upload.defaultImgList = e.slice(0)
    },

    addProp () {
      this.propList.push({ name: '', valList: [{ val: '' }] })
    },
    delAllSku (item, index) {
      this.data.sku = []

      this.propList[index].valList = [{ val: '' }]
      this.data.commodityPass = ''
      this.columns[0].title = ''
    },
    delSkuVal (item, index) {
      this.data.sku = []
      this.data.commodityPass = ''
      this.columns[0].title = ''
    },
    delProp (index) {
      this.propList.splice(index, 1)
    },
    addVal (item) {
      item.valList.push({ val: '' })
    },
    delVal (item, index) {
      item.valList.splice(index, 1)
    },
    delSku (index) {
      this.data.sku.splice(index, 1)
    },
    genPropList (sku) {
      if (sku && sku.length !== 0) {
        let propHashTable = {}
        sku.forEach((sItem) => {
          if (!sItem.propertyList || sItem.propertyList.length === 0) {
            return
          }
          sItem.propertyList.forEach((pItem) => {
            if (propHashTable[pItem.propKey]) {
              propHashTable[pItem.propKey][pItem.propVal] = 'x'
            } else {
              propHashTable[pItem.propKey] = {
                [pItem.propVal]: 'x'
              }
            }
          })
        })
        this.propList = []
        for (let key in propHashTable) {
          let valList = []
          for (let vkey in propHashTable[key]) {
            valList.push({ val: vkey })
          }
          this.propList.push({ name: key, valList })
        }
      }
    },

    genSkuTable () {
      // let check = true
      // let title = ''
      // if (!this.propList || this.propList.length === 0) {
      //   check = false
      //   title = '请添加属性！'
      // }
      // let propNameHashTable = {}
      // this.propList.find((pItem) => {
      //   let propName = pItem.name
      //   if (!propName) {
      //     title = '属性名称不能为空！'
      //     check = false
      //     return true
      //   }
      //   if (propNameHashTable[propName]) {
      //     title = '属性名称不能重复！'
      //     check = false
      //     return true
      //   }
      //   if (
      //     [
      //       'originalPrice',
      //       'stock',
      //       'coinName',
      //       'image',
      //       'imageList',
      //       'defaultImgList',
      //       'propertyList'
      //     ].includes(propName)
      //   ) {
      //     title = '属性名称不符合规范！'
      //     check = false
      //     return true
      //   }
      //   propNameHashTable[propName] = true
      //   if (!pItem.valList || pItem.valList.length === 0) {
      //     title = '属性值不能为空！'
      //     check = false
      //     return true
      //   }
      //   pItem.valList.find((vItem) => {
      //     if (!vItem.val) {
      //       title = '属性值不能为空！'
      //       check = false
      //       return true
      //     }
      //   })
      //   for (var i = 0; i < pItem.valList.length - 1; i++) {
      //     for (var j = i + 1; j < pItem.valList.length; j++) {
      //       if (pItem.valList[i].val === pItem.valList[j].val) {
      //         title = '属性值不能重复！'
      //         check = false
      //         return true
      //       }
      //     }
      //   }
      // })

      // if (!check) {
      //   this.$Notice.warning({ title })
      // } else {
      //   // console.log(typeof this.data.commodityPass)
      //   if (typeof this.data.commodityPass !== 'number') {
      //     return this.$Notice.warning({ title: '请先选择商品通证' })
      //   }
      if (!this.columns || !this.columns.length === 0) {
        this.genColumn()
      }
      this.genSku()
      // }
    },
    genColumn () {
      let columns = []
      this.propList.forEach((pItem) => {
        columns.push({
          title: '规格名称',
          minWidth: 120,
          slot: 'name',
          align: 'center'
        })
      })
      columns.push({
        title: '缩略图',
        slot: 'image',
        width: 240,
        align: 'center'
      })

      columns.push({
        title: '重量（KG）',
        slot: 'weight',
        width: 130,
        align: 'center'
      })
      columns.push({
        title: '库存',
        slot: 'stock',
        width: 160,
        align: 'center'
      })
      columns.push({
        title: '商品Token',
        slot: 'coinName',
        width: 230,
        align: 'center'
      })
      columns.push({
        title: '是否是隐藏款',
        slot: 'isHide',
        width: 110,
        align: 'center'
      })
      // columns.push({
      //   title: '类型编码',
      //   slot: 'typeCode',
      //   width: 200,
      //   align: 'center'
      // })
      // if (this.isDetail) {
      //   columns.push({
      //     title: '发行量',
      //     key: 'issueNum',
      //     width: 160,
      //     align: 'center'
      //   })
      // }
      if (!this.isDetail && !this.isEdit && !this.isAgain) {
        columns.push({
          title: '操作',
          slot: 'opt',
          width: 80,
          align: 'center'
        })
      }
      this.columns = columns
    },
    genSku () {
      let resArr = []
      this.propList.forEach((item) => {
        resArr = this.genSkuData(item, resArr)
      })
      if (this.data.sku.length === 0) {
        this.data.sku = resArr
      } else {
        this.data.sku = [...this.data.sku, ...resArr]
      }
    },
    genSkuData (prop, resArr) {
      let newArr = []
      let { name, valList } = prop
      if (resArr.length === 0) {
        valList.forEach((item) => {
          let propertyList = [{ propKey: name, propVal: item.val }]
          newArr.push({
            [name]: item.val,
            originalPrice: '',
            stock: '',
            coinName: '',
            coinNamePrefix: this.coinNamePrefix,
            name: '',
            republish: false,
            // availableNumber: '',
            image: '',
            propertyList,
            weight: '',
            upload: {
              imageList: [],
              defaultImgList: []
            },
            isHide: false
          })
        })
        // console.log('newArr1', newArr)
      } else {
        resArr.forEach((rItem) => {
          valList.forEach((vItem) => {
            let newItem = { ...rItem, [name]: vItem.val }
            newItem.propertyList = JSON.parse(
              JSON.stringify(newItem.propertyList)
            )
            newItem.propertyList.push({
              propKey: name,
              propVal: vItem.val
            })
            newItem.upload = {
              imageList: [],
              defaultImgList: []
            }
            // console.log('newItem', newItem)
            newArr.push(newItem)
          })
        })
      }
      // console.log('newArr', newArr)
      return newArr
    },
    imgHandler (image) {
      if (image) {
        this.$refs.uploadImg.$el.querySelector('[type=file]').click()
      }
    },
    videoHandler (video) {
      if (video) {
        this.$refs.uploadVideo.$el.querySelector('[type=file]').click()
      }
    },

    uploadOnProgress (event, file, fileList) {
      this.editorUploadPercent = parseFloat(event.percent).toFixed(1)
    },
    imgBoforeUpload (file) {
      if (file.size >= 5 * 1024 * 1024) {
        this.$Notice.warning({ title: '上传图片不得超过5MB！' })
        return false
      }
      this.editorUploadPercent = 0
      this.editorLoading = true
    },
    imgUploadSuccess (res, file, fileList) {
      this.editorLoading = false
      apiVerify({
        res: { data: res },
        success: () => {
          let url = res.data
          let addImageRange = this.editor.getSelection()
          let newRange = 0 + (addImageRange !== null ? addImageRange.index : 0)
          this.editor.insertEmbed(newRange, 'simpleImg', {
            url,
            width: '100%'
          })
          this.editor.setSelection(1 + newRange)
        }
      })
    },
    imgUploadErr () {
      this.editorLoading = false
      this.$Notice.error({ title: '上传失败，请稍后再试！' })
    },

    videoBoforeUpload (file) {
      if (file.size >= 50 * 1024 * 1024) {
        this.$Notice.warning({ title: '上传视频不得超过50MB！' })
        return false
      }
      this.editorUploadPercent = 0
      this.editorLoading = true
    },
    videoUploadSuccess (res, file, fileList) {
      this.editorLoading = false
      apiVerify({
        res: { data: res },
        success: () => {
          let url = res.data
          let addVideoRange = this.editor.getSelection()
          let newRange = 0 + (addVideoRange !== null ? addVideoRange.index : 0)
          this.editor.insertEmbed(newRange, 'simpleVideo', {
            url,
            controls: 'controls',
            width: '100%',
            poster: getPosterFromVideoUrl(url)
          })
          this.editor.setSelection(1 + newRange)
        }
      })
    },
    videoUploadErr () {
      this.editorLoading = false
      this.$Notice.error({ title: '上传失败，请稍后再试！' })
    }
  }
}
</script>

<style lang="less">
.sale-info-con {
  .item {
    display: flex;
    align-items: center;
    margin-bottom: 10px;
  }
  .item .label {
    width: 140px;
    // min-width: 140px;
    margin-right: 10px;
    text-align: right;
    flex-shrink: 0;
  }
  .item .property-con {
    flex: 1;
    padding: 20px;
    border: 1px solid #dcdee2;
    border-radius: 5px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
  }
  .item .property-con .add-btn {
    width: 100%;
  }
  .del-con {
    margin-left: 5px;
    cursor: pointer;
  }
  .item .property-item {
    width: 240px;
    display: flex;
    align-items: center;
    margin-bottom: 10px;
    padding-right: 30px;
    .prop-val {
      flex: 1;
    }
  }
  .item .empty {
    width: 150px;
  }
  .item .opt-btn {
    flex: 1;
    display: flex;
    justify-content: space-between;
  }
  .tip {
    color: #ed4014;
    font-size: 12px;
    margin: 20px 0 5px 0;
  }
  .token-label {
    font-size: 14px;
  }
  .item .editor-con {
    position: relative;
    width: 600px;
    .spin-icon-load {
      animation: ani-demo-spin 1s linear infinite;
    }
    .ivu-spin {
      border: 1px solid #dcdee2;
      border-radius: 5px;
    }
    .describt-detail {
      width: 100%;
      height: 800px;
      overflow-y: auto;
      padding: 10px;
      border: 1px solid #dcdee2;
      border-radius: 5px;
    }
  }
  .detail-editor {
    > .ql-toolbar {
      border-top-left-radius: 5px;
      border-top-right-radius: 5px;
    }
    > .ql-container {
      height: 800px;
      border-bottom-left-radius: 5px;
      border-bottom-right-radius: 5px;
    }
  }
}
</style>
