<template>
  <section class="hiprint-designer">
    <header class="hiprint-designer__header">
      <el-radio-group
        v-model="paperType"
        @change="setPaperHandler">
        <el-radio-button label="A3">A3</el-radio-button>
        <el-radio-button label="A4">A4</el-radio-button>
        <el-radio-button label="A5">A5</el-radio-button>
        <el-radio-button label="B3">B3</el-radio-button>
        <el-radio-button label="B4">B4</el-radio-button>
        <el-radio-button label="B5">B5</el-radio-button>
        <el-radio-button label="other">自定义</el-radio-button>
      </el-radio-group>
      <el-form
        inline
        v-if="paperType === 'other'">
        <el-form-item>
          <el-input
            v-model="paperWidth"
            type="number">
            <template #prepend>宽</template>
            <template #append>px</template>
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-input
            v-model="paperHeight"
            type="number">
            <template #prepend>高</template>
            <template #append>px</template>
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-button
            type="primary"
            @click="setPaperHandler('other')">
            设置
          </el-button>
        </el-form-item>
      </el-form>
      <el-input
        class="percentage"
        readonly
        :v-model="scalePercentage">
        <template #prepend>
          <el-button
            :disabled="!canZoomIn"
            @click="zoomIn">
            <i class="iconfont icon-zoom-out"></i>
          </el-button>
        </template>
        <template #append>
          <el-button
            :disabled="!canZoomOut"
            @click="zoomOut">
            <i class="iconfont icon-zoom-in"></i>
          </el-button>
        </template>
      </el-input>
      <el-select
        placeholder="请选择数据源"
        multiple
        v-model="formCode">
        <el-option
          v-for="d in dataSourceForm"
          :label="d.label"
          :value="d.value"></el-option>
      </el-select>
      <el-button
        type="primary"
        @click="previewPrint">
        <i class="iconfont icon-print"></i>
        预览
      </el-button>
      <el-button
        type="primary"
        @click="saveConfig">
        <i class="iconfont icon-save"></i>
        保存
      </el-button>
      <el-button
        type="danger"
        @click="clearPrint">
        <i class="iconfont icon-clear"></i>
        清空
      </el-button>
    </header>
    <main class="hiprint-designer__main">
      <aside class="hiprint-designer__main_left">
        <el-scrollbar noresize>
          <div class="hiprint-designer_title">基础</div>
          <el-row>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.text">
                <i class="iconfont icon-font-size"></i>
                <span>文本</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.textVal">
                <i class="iconfont icon-font-size"></i>
                <span>值（文本）</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.image">
                <i class="iconfont icon-image-fill"></i>
                <span>图片</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.longText">
                <i class="iconfont icon-file-text"></i>
                <span>长文本</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.table">
                <i class="iconfont icon-table"></i>
                <span>表格</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.emptyTable">
                <i class="iconfont icon-layout"></i>
                <span>空白表格</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.html">
                <i class="iconfont icon-HTML"></i>
                <span>html</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.customText">
                <i class="iconfont icon-container-fill"></i>
                <span>自定义文本</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.barcode">
                <i class="iconfont icon-barcode"></i>
                <span>条形码</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.qrcode">
                <i class="iconfont icon-qrcode"></i>
                <span>二维码</span>
              </a>
            </el-col>
          </el-row>
          <div class="hiprint-designer_title">辅助</div>
          <el-row>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.hline">
                <i class="iconfont icon-border-verticle"></i>
                <span>横线</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.vline">
                <i class="iconfont icon-border-horizontal"></i>
                <span>竖线</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.rect">
                <i class="iconfont icon-border"></i>
                <span>矩形</span>
              </a>
            </el-col>
            <el-col :span="8">
              <a
                class="ep-draggable-item"
                tid="defaultModule.oval">
                <i class="iconfont icon-round"></i>
                <span>椭圆</span>
              </a>
            </el-col>
          </el-row>
        </el-scrollbar>
      </aside>
      <section class="hiprint-designer__main_canvas">
        <el-scrollbar ref="canvasRef">
          <div id="hiprint-printTemplate"></div>
        </el-scrollbar>
      </section>
      <aside class="hiprint-designer__main_right">
        <div id="PrintElementOptionSetting"></div>
        <template v-if="currentElementObjColumns.length">
          <div class="hiprint-designer_title">表格字段设置</div>
          <el-form
            label-position="top"
            size="small">
            <el-form-item label="表数据选择">
              <el-select
                v-model="listCode"
                @change="tableFieldChange">
                <el-option
                  v-for="d in dataSourceList"
                  :label="d.label"
                  :value="d.value"></el-option>
              </el-select>
            </el-form-item>
            <el-row gutter="10">
              <el-col
                :span="12"
                v-for="col in currentElementObjColumns">
                <el-form-item :label="col.title">
                  <el-select v-model="col.field">
                    <el-option
                      v-for="d in listColumns"
                      :value="d"></el-option>
                  </el-select>
                </el-form-item>
              </el-col>
            </el-row>
            <el-row gutter="10">
              <el-col :span="12">
                <el-button
                  @click="tableColumnCancel"
                  type="warning">
                  取消
                </el-button>
              </el-col>
            </el-row>
          </el-form>
        </template>
      </aside>
    </main>
  </section>
  <el-dialog v-model="previewShow">
    <div
      class="print-preview"
      v-html="previewHtml"></div>
  </el-dialog>
</template>
<script setup>
import {onMounted, ref, onActivated, onDeactivated, computed, watch, nextTick} from 'vue';
import {hiprint, defaultElementTypeProvider, fontSize, scale, zIndex, panel, usePaper, useScale, useDataSource} from 'yh-hiprint';
import {useRoute, onBeforeRouteUpdate} from 'vue-router/dist/vue-router';
import {ElMessageBox} from 'element-plus';
import axios from '@/libs/api.request';

const route = useRoute();
const {paperType, paperWidth, paperHeight, setPaper} = usePaper();
function setPaperHandler(type) {
  setPaper(type, () => {
    hiprintTemplate.value.setPaper(paperWidth.value, paperHeight.value);
  });
}

const hiprintTemplate = ref(null);
const canvasRef = ref();
const {scaleValue, scalePercentage, canZoomIn, canZoomOut, zoomIn, zoomOut} = useScale(() => {
  hiprintTemplate.value.zoom(scaleValue.value);
  canvasRef?.value.update();
});

const previewShow = ref(false);
const previewHtml = ref('');
async function previewPrint() {
  let {
    data: {list, json},
  } = await axios.request({
    url: `/printTemplate/data/${detailData.value.code}`,
    method: 'post',
    type: 'json',
    data: [
      {
        code: '50101820',
      },
    ],
  });
  if (json) {
    if (Array.isArray(list) && list.length > 0) {
      list = list.map((item) => {
        let printData = {};
        let datas = Object.entries(item);
        datas.forEach((arr) => {
          if (Array.isArray(arr[1])) {
            printData[arr[0]] = arr[1];
          } else {
            if (arr[1] !== null) {
              let itemsEntries = Object.entries(arr[1]);
              itemsEntries.forEach((cArr) => {
                printData[`$${arr[0]}[${cArr[0]}]`] = cArr[1];
              });
            }
          }
        });
        return printData;
      });
    } else {
      list = [];
    }
    previewHtml.value = new hiprint.PrintTemplate({template: JSON.parse(json)}).getHtml(list)[0].innerHTML;
    previewShow.value = true;
  } else {
    ElMessage.warning({
      title: '警告',
      message: '模板配置不存在，请检查',
    });
  }
}

function saveConfig() {
  let arr = [].concat(formCode.value);
  let json = hiprintTemplate.value.getJson();
  json.panels[0].printElements.forEach((item) => {
    if (item.printElementType.type === 'table') {
      arr.push(item.options.field);
    }
  });

  axios
    .request({
      url: '/printTemplate/save',
      method: 'post',
      type: 'json',
      data: {
        id: detailData.value.id,
        json: JSON.stringify(json),
        dsIds: arr.join(','),
      },
    })
    .then((res) => {
      ElMessage.success({
        message: '恭喜模板保存成功',
      });
    });
}

function clearPrint() {
  hiprintTemplate.value?.clear();
}

const {detailData, getDetail, listCode, dataSourceList, listColumns, formCode, formColumns, dataSourceForm, getDataSourceList} = useDataSource(axios);

watch(
  () => formColumns.value,
  (val) => {
    if (val && val.length && hiprintTemplate.value) {
      hiprintTemplate.value.setFields(
        val.map((item) => {
          return {
            field: item,
            text: item,
          };
        })
      );
    }
  },
  {
    deep: true,
    immediate: true,
  }
);
let currentElementObj = ref(null);
let currentElementObjColumns = computed(() => {
  if (currentElementObj.value?.printElementType.type === 'table') {
    return currentElementObj.value.options.columns[0]['columns'] || [];
  } else {
    return [];
  }
});

function tableFieldChange(val) {
  currentElementObj.value.updateOption('field', val);
}

function tableColumnCancel() {
  currentElementObj.value = null;
}

function init() {
  try {
    hiprint.init({
      providers: [new defaultElementTypeProvider()],
    });
    hiprint.setConfig();
    hiprint.setConfig({
      optionItems: [fontSize, scale, zIndex],
      movingDistance: 2.5,
      text: {
        tabs: [
          {
            options: [],
          },
          {
            name: '样式',
            options: [
              {
                name: 'scale',
                after: 'transform',
                hidden: false,
              },
            ],
          },
        ],
        supportOptions: [
          {
            name: 'styler',
            hidden: true,
          },
          {
            name: 'scale',
            after: 'transform',
            hidden: false,
          },
          {
            name: 'formatter',
            hidden: true,
          },
        ],
      },
      image: {
        tabs: [
          {
            replace: true,
            name: '基本',
            options: [
              {
                name: 'field',
                hidden: false,
              },
              {
                name: 'src',
                hidden: false,
              },
              {
                name: 'fit',
                hidden: false,
              },
            ],
          },
        ],
      },
      table: {
        tabs: [{options: [{name: 'field', hidden: true}]}],
      },
    });

    hiprint.PrintElementTypeManager.buildByHtml(hiprintJQuery('.ep-draggable-item'));
    hiprintJQuery('#hiprint-printTemplate').empty();
    let template = JSON.parse(detailData.value.json) || panel;
    hiprintTemplate.value = new hiprint.PrintTemplate({
      template,
      onImageChooseClick: (target) => {
        // 测试 3秒后修改图片地址值
        setTimeout(() => {
          target.refresh('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAtAAAAIIAQMAAAB99EudAAAABlBMVEUmf8vG2O41LStnAAABD0lEQVR42u3XQQqCQBSAYcWFS4/QUTpaHa2jdISWLUJjjMpclJoPGvq+1WsYfiJCZ4oCAAAAAAAAAAAAAAAAAHin6pL9c6H/fOzHbRrP0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0u/SY9LS0tLS0tLS0tLS0n+edm+UlpaWlpaWlpaWlpaW/tl0Ndyzbno7/+tPTJdd1wal69dNa6abx+Lq6TSeYtK7BX/Diek0XULSZZrakPRtV0i6Hu/KIt30q4fM0pvBqvR9mvsQkZaW9gyJT+f5lsnzjR54xAk8mAUeJyMPwYFH98ALx5Jr0kRLLndT7b64UX9QR/0eAAAAAAAAAAAAAAAAAAD/4gpryzr/bja4QgAAAABJRU5ErkJggg==', {
            real: true,
          });
        }, 3000);
      },
      fontList: [
        {title: '微软雅黑', value: 'Microsoft YaHei'},
        {title: '黑体', value: 'STHeitiSC-Light'},
        {title: '思源黑体', value: 'SourceHanSansCN-Normal'},
        {title: '宋体', value: 'SimSun'},
        {title: 'cursive', value: 'cursive'},
        {title: 'Times New Roman', value: 'Times New Roman'},
      ],
      dataMode: 1,
      history: true,
      onDataChanged: (type, json) => {
        // console.log(type); // 新增、移动、删除、修改(参数调整)、大小、旋转
        // console.log(json); // 返回 template
      },
      onUpdateError: (e) => {
        // console.error(e);
      },
      settingContainer: '#PrintElementOptionSetting',
      paginationContainer: '.hiprint-printPagination',
    });

    hiprintTemplate.value.design('#hiprint-printTemplate', {grid: true});
    scaleValue.value = hiprintTemplate.value.editingPanel.scale || 1;
    window.ht = hiprintTemplate.value;

    if (formColumns.value) {
      hiprintTemplate.value.setFields(
        formColumns.value.map((item) => {
          return {
            field: item,
            text: item,
          };
        })
      );
    }
    hiprintJQuery('.hiprint-designer').on('mousedown', '.hiprint-printElement', (e) => {
      let t = e.currentTarget;
      let pes = hiprintTemplate.value.editingPanel.printElements;
      let index = pes.map((item) => item.designTarget[0]).indexOf(t);
      let pe = pes[index];
      currentElementObj.value = pe;
      if (pe.options.field) {
        listCode.value = pe.options.field;
      }
    });
  } catch (error) {
    console.log(error.message);
    clearPrint();
    hiprintTemplate.value = null;
    if (error.message.indexOf('setTemplateId') > -1) {
      ElMessageBox.alert('模板有错误，请返回列表手动修改或这清空模板！');
    }
  }
}

let updateing = false;
async function updateTemplate() {
  if (updateing === true) {
    return false;
  }
  updateing = true;
  if (hiprintTemplate.value) {
    await getDetail(route.query.code);
    if (detailData.value && detailData.value.json) {
      let jsonObj = JSON.parse(detailData.value.json);
      hiprintTemplate.value.update(jsonObj);
      let {width, height} = jsonObj.panels[0];
      paperWidth.value = width;
      paperHeight.value = height;
      hiprintTemplate.value.setPaper(width, height);
    } else {
      hiprintTemplate.value.update({
        panels: [
          {
            index: 0,
            name: 1,
            height: 297,
            width: 210,
            paperHeader: 125,
            paperFooter: 272.5,
            paperNumberLeft: 430,
            paperNumberTop: 5,
            printElements: [],
            watermarkOptions: {content: '', rotate: 25, timestamp: false, format: 'YYYY-MM-DD HH:mm'},
          },
        ],
      });
    }
  } else {
    if (detailData.value?.json) {
      init();
    }
  }
  updateing = false;
}
onActivated(async () => {
  updateTemplate();
});

onBeforeRouteUpdate(() => {
  updateTemplate();
});

onDeactivated(() => {
  hiprintTemplate.value = null;
});
onMounted(async () => {
  await getDataSourceList();
  await getDetail(route.query.code);
  if (!hiprintTemplate.value) {
    init();
  }
});
</script>
<style lang="scss">
.hiprint-designer {
  width: calc(100% + 32px);
  height: calc(100% - 30px);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background-color: var(--el-bg-color-page);
  margin: 0 -16px;
  &__header {
    padding: 0 16px;
    height: 50px;
    display: flex;
    background-color: var(--el-bg-color);
    align-items: center;
    box-shadow: var(--el-box-shadow-lighter);
    position: relative;
    z-index: 1;
    // > * {
    //   margin-right: 10px;
    //   margin-left: 0 !important;
    // }
    .percentage {
      width: 165px;
    }
    .el-select {
      --el-select-width: auto;
    }
    .el-form-item {
      margin-bottom: 0;
      margin-right: 10px;
      .el-input {
        width: 140px;
        .el-input-group__prepend,
        .el-input-group__append {
          padding: 0 9px;
        }
      }
    }
  }
  &_title {
    font-size: 18px;
    font-weight: bold;
    line-height: 1.7em;
    margin-bottom: 10px;
  }
  .ep-draggable-item {
    user-select: none;
    width: 100%;
    height: 70px;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    margin-bottom: 10px;
    .iconfont {
      font-size: 30px;
      width: 40px;
      height: 40px;
      text-align: center;
      line-height: 40px;
    }
  }
  &__main {
    flex: 1;
    overflow: hidden;
    display: flex;
    &_left {
      width: 300px;
      overflow: hidden;
      background-color: var(--el-color-white);
      box-shadow: var(--el-box-shadow-lighter);
      .el-scrollbar__view {
        padding: 16px;
      }
    }
    &_canvas {
      flex: 1;
      overflow: hidden;
      .el-scrollbar__view {
        padding: 20px 10px 40px 20px;
      }
    }
    &_right {
      width: 340px;
      overflow: hidden;
      background-color: var(--el-color-white);
      box-shadow: var(--el-box-shadow-lighter);
      display: flex;
      flex-direction: column;
      .prop-tabs {
        height: 100%;
        overflow: hidden;
        display: flex;
        flex-direction: column;
        .prop-tab-items {
          display: flex;
          height: 43px;
          box-sizing: border-box;
          .prop-tab-item {
            height: 40px;
            line-height: 40px;
            flex: 1;
            text-align: center;
          }
        }
        .hiprint-option-items.active {
          display: block;
          padding: 0 6px 0 12px;
        }
      }
      .hiprint-option-items {
        height: 100%;
        overflow: auto;
        padding: 16px;
        box-sizing: border-box;
        &::-webkit-scrollbar {
          width: 4px;
          height: 4px;
        }

        &::-webkit-scrollbar-thumb {
          border-radius: 4px;
          background: #bbb;
        }
      }
      .hiprint-designer_title {
        padding: 0 10px;
      }
      #PrintElementOptionSetting {
        flex: 1;
        overflow: hidden;
      }
      .el-form {
        padding: 10px;
        .el-button {
          width: 100%;
        }
      }
    }
  }
}
</style>
