<template>
  <div class="cqcy-content" style="margin: 0;height: calc(100% - 70px);">
    <breadcrumb-view :breadcrumbList="breadcrumbList" :show-index="false"></breadcrumb-view>
    <div v-if="btnType === ''" class="cy-nav-sx">
      <el-select v-model="searchValue"
                 style="width: 180px;"
                 placeholder="请选择报表类型"
                 @change="changeReportTypeEvent">
        <el-option v-for="item in reportOptions"
                   style="margin-left: 5px; width: 180px;"
                   :key="item.value"
                   :label="item.label"
                   :value="item.value">
        </el-option>
      </el-select>
      <el-input placeholder="请输入报表名称"
                v-model="searchTxt"
                style="margin-left: 5px; width: 180px;"
                prefix-icon="el-icon-search">
      </el-input>
      <el-button style="margin-left: 5px;" @click="searchReportEvent">查询</el-button>
    </div>
    <el-button v-if="btnType === ''" type="primary" class="cy-nav-btn" icon="el-icon-circle-plus-outline"
               size="mini" @click="addReportEvent">新增
    </el-button>
    <!--    <el-button v-if="btnType === ''" type="success" class="cy-nav-btn" icon="el-icon-refresh"-->
    <!--               size="mini" @click="refreshReportEvent">刷新</el-button>-->
    <el-divider></el-divider>
    <div class="cy-main">
      <div class="cy-main-left" v-if="!showMainView">
        <div class="cy-list">
          <el-table v-if="reportDataList.length > 0"
                    :data="reportDataList"
                    border
                    :stripe="true"
                    :header-cell-style="{background: '#E8E8E8'}"
                    @sort-change="sortChange"
                    style="width: 100%;">
            <el-table-column
                align="center"
                sortable="custom"
                label="报表名称"
                prop="reportTableName">
              <template slot-scope="scope">
                <span style="color: #409EFF; cursor: pointer;"
                      @click="handleReportNodeClick(scope.row, scope.row.userId != uid ? 'deny' : '')"
                      :title="scope.row.reportTableName">{{ scope.row.reportTableName }}</span>
              </template>
            </el-table-column>
            <el-table-column
                align="center"
                label="报表状态"
                prop="isAutoReport"
                width="350">
              <template slot-scope="scope">
                <el-tag v-if="scope.row.userId != uid" type="success" style="margin-right: 5px;">被分享</el-tag>
                <el-tag v-if="uid == scope.row.userId && scope.row.userGroupList && scope.row.userGroupList.length > 0"
                        type="warning" style="margin-right: 5px;">已分享
                </el-tag>
                <el-tag v-if="scope.row.isAutoReport == 0" style="margin-right: 5px;">手动报表</el-tag>
                <el-tag v-if="scope.row.isAutoReport == 1" style="margin-right: 5px;">自动报表</el-tag>
                <el-tag v-if="scope.row.isAutoReport == 3" style="margin-right: 5px;">事件驱动报表</el-tag>
              </template>
            </el-table-column>
<!--            <el-table-column-->
<!--                align="center"-->
<!--                label="自动报表"-->
<!--                prop="isAutoReport"-->
<!--                width="150">-->
<!--              <template slot-scope="scope">-->
<!--                <el-switch v-if="scope.row.isAutoReport == '2'" :value="true" active-color="#13ce66"-->
<!--                           disabled></el-switch>-->
<!--                <el-switch v-else :value="scope.row.isAutoReport == '1'" active-color="#13ce66"-->
<!--                           @change="switchChangeEvent($event, scope.row)"-->
<!--                           :disabled="uid != scope.row.userId"></el-switch>-->
<!--              </template>-->
<!--            </el-table-column>-->
            <el-table-column
                align="center"
                label="当前版本"
                sortable="custom"
                prop="version"
                width="120">
            </el-table-column>
            <el-table-column
                align="center"
                label="创建时间"
                sortable
                prop="createTime"
                width="200">
            </el-table-column>
            <el-table-column label="操作" align="center" width="380">
              <template slot-scope="scope">
                <el-button type="text"
                           v-if="uid == scope.row.userId"
                           size="small"
                           icon="el-icon-edit"
                           @click="editReportItem(scope.row)">修改名称
                </el-button>
                <el-button type="text"
                           v-if="uid == scope.row.userId"
                           size="small"
                           icon="el-icon-setting"
                           @click="setReportStatus(scope.row)">设置报表状态
                </el-button>
                <el-button type="text"
                           v-if="uid == scope.row.userId"
                           size="small"
                           icon="el-icon-user"
                           @click="setUserGroupEvent(scope.row)">授权
                </el-button>
                <el-button type="text"
                           v-if="uid == scope.row.userId"
                           size="small"
                           icon="el-icon-document"
                           @click="getUserGroupEvent(scope.row)">授权详情
                </el-button>
                <el-button type="text"
                           v-if="uid == scope.row.userId"
                           size="small"
                           icon="el-icon-delete"
                           style="color: red;"
                           @click="removeReportItem(scope.row)">删除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
          <el-empty v-else description="暂无数据"></el-empty>
        </div>
        <el-pagination
            background
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="reportPage"
            :page-size="reportLimit"
            layout="sizes, prev, pager, next, total"
            :total="reportTotal">
        </el-pagination>
      </div>
      <div class="cy-main-right" :style="showMainView ? '' : 'display: none;'">
        <el-row v-if="btnType == 'add'" style="margin: 10px 20px;">
          <el-button type="primary" size="mini" icon="el-icon-document" @click="saveReportInfo">保存报表</el-button>
          <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport">取消</el-button>
        </el-row>
        <el-row v-if="btnType == 'show'" style="margin: 10px 20px;">
          <el-button type="success" size="mini" icon="el-icon-document-checked" @click="updateReport">保存</el-button>
          <el-button type="primary" size="mini" icon="el-icon-download" @click="downloadReport">下载</el-button>
          <el-button type="warning" size="mini" icon="el-icon-printer" @click="printExcel">打印</el-button>
          <el-button type="info" size="mini" icon="el-icon-document" @click="historyReport">运行记录</el-button>
          <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport">关闭</el-button>
        </el-row>
        <el-row v-if="btnType == 'showShared'" style="margin: 10px 20px;">
          <el-button type="primary" size="mini" icon="el-icon-download" @click="downloadReport">下载</el-button>
          <el-button type="warning" size="mini" icon="el-icon-printer" @click="printExcel">打印</el-button>
          <el-button type="info" size="mini" icon="el-icon-document" @click="historyReport">运行记录</el-button>
          <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport">关闭</el-button>
        </el-row>
        <el-row v-if="btnType == 'showChild'" style="margin: 10px 20px;">
          <el-button type="primary" size="mini" icon="el-icon-download" @click="downloadReport">下载</el-button>
          <el-button type="warning" size="mini" icon="el-icon-printer" @click="printExcel">打印</el-button>
          <el-button type="danger" size="mini" icon="el-icon-circle-close" @click="cancelSaveReport2">关闭</el-button>
        </el-row>
        <div id="luckysheet"
             style="margin:0px;padding:0px;position:relative;height:calc(100% - 50px);width:100%;left: 20px;top: 0px;bottom:0px;">
        </div>
      </div>
    </div>

    <!-- 新增报表 -->
    <el-dialog
        title="新增报表"
        width="50%"
        top="10vh"
        center
        v-dialog-drag
        v-if="dialogReportTemplateVisible"
        :before-close="dialogClose"
        :visible.sync="dialogReportTemplateVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <el-form ref="reportForm" :model="reportForm" :rules="reportRules" label-width="80px">
        <el-form-item label="报表模板" prop="reportTemplate">
          <el-select v-model="reportForm.reportTemplate" filterable placeholder="请选择报表模板" style="width: 100%;">
            <el-option
                v-for="item in reportTemplateList"
                :key="item.id"
                :label="item.templateName"
                :value="item.id">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="取值方式" prop="reportValueFormat">
          <el-radio v-model="reportForm.reportValueFormat" label="0">时段数据</el-radio>
        </el-form-item>
        <el-form-item label='取值模式' prop="valueCondition">
          <el-select v-model="reportForm.valueCondition" placeholder="请选择报表取值模式" style="width: 100%;">
            <el-option
                v-for="dict in valueConditionList"
                :key="dict.value"
                :label="dict.key"
                :value="dict.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="报表类型" prop="isAutoReport">
          <el-select v-model="reportForm.isAutoReport" filterable placeholder="请选择报表类型" style="width: 100%;">
            <el-option
                v-for="item in reportOptions_"
                :key="item.value"
                :label="item.label"
                :value="item.value">
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="数据时间" prop="reportDate">
          <el-date-picker
              v-model="reportForm.reportDate" :editable="false" :clearable="false"
              style="width: 100%;"
              type="datetimerange"
              :picker-options="{
                format: 'yyyy-MM-dd HH:mm:ss'
              }"
              value-format="yyyy-MM-dd HH:mm:ss"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期">
          </el-date-picker>
        </el-form-item>
        <el-form-item style="text-align: center;">
          <el-button type="primary" @click="chooseReportEvent" style="margin-top: 20px;">确定</el-button>
          <el-button @click="dialogClose" style="margin-top: 20px;">取消</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>

    <!-- 用户组选择 -->
    <el-dialog
        title="选择用户组"
        width="840px"
        top="10vh"
        center
        v-dialog-drag
        v-if="dialogUserGroupVisible"
        :before-close="dialogClose"
        :visible.sync="dialogUserGroupVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <!--      <el-form label-width="80px">-->
      <!--        <el-form-item label="用户组">-->
      <!--          <el-select v-model="userGroupInfo" filterable clearable multiple placeholder="请选择用户组" style="width: 100%;">-->
      <!--            <el-option-->
      <!--                v-for="item in userGroupList"-->
      <!--                :key="item.id"-->
      <!--                :label="item.userGroupName"-->
      <!--                :value="item.id">-->
      <!--            </el-option>-->
      <!--          </el-select>-->
      <!--        </el-form-item>-->
      <!--      </el-form>-->
      <div class="ug-div">
        <el-transfer
            v-model="userGroupInfo"
            :titles="['用户组列表', '已选择用户组']"
            :data="userGroupList"
            :props="{
              key: 'id',
              label: 'userGroupName'
            }">
        </el-transfer>
      </div>
      <span slot='footer'>
        <el-button type="primary" @click="chooseUserGroupEvent" style="margin-top: 20px;">确定</el-button>
        <el-button @click="dialogClose" style="margin-top: 20px;">取消</el-button>
      </span>
    </el-dialog>

    <!-- 自动报表CRON定时表达式 -->
    <el-dialog
        title="配置定时任务"
        width="50%"
        top="10vh"
        center
        v-dialog-drag
        v-if="dialogAutoReportVisible"
        :before-close="dialogClose"
        :visible.sync="dialogAutoReportVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <el-form label-width="80px">
        <el-radio-group v-model="radioByCron">
          <el-form-item label="秒">
            <el-radio :label="1">
              <span style="margin-right: 10px;">每</span>
              <el-input-number size="mini" v-model="radioByCronValS" :min="1" :max="59"></el-input-number>
              <span style="margin-left: 10px;">秒执行一次</span>
            </el-radio>
          </el-form-item>
          <el-form-item label="分钟">
            <el-radio :label="2">
              <span style="margin-right: 10px;">每</span>
              <el-input-number size="mini" v-model="radioByCronValM" :min="1" :max="59"></el-input-number>
              <span style="margin-left: 10px;">分钟执行一次</span>
            </el-radio>
          </el-form-item>
          <el-form-item label="小时">
            <el-radio :label="3">
              <span style="margin-right: 10px;">每</span>
              <el-input-number size="mini" v-model="radioByCronValH" :min="1" :max="2"></el-input-number>
              <span style="margin-left: 10px;">小时执行一次</span>
            </el-radio>
          </el-form-item>
          <el-form-item label="指定时间">
            <el-radio :label="4">
              <span style="margin-right: 10px;">在每天的</span>
              <el-time-picker v-model="radioByCronValD"
                              size="mini"
                              placeholder="请选择时间"
                              :clearable="false"
                              :editable="false"
                              value-format="HH:mm:ss"
                              :picker-options="{
                                format: 'HH:mm:ss'
                              }">
              </el-time-picker>
              <span style="margin-left: 10px;">执行一次</span>
            </el-radio>
          </el-form-item>
          <el-form-item label="">
            <el-radio :label="5">
              <span style="margin-right: 10px;">在每月</span>
              <el-input-number size="mini" v-model="radioByCronValMo" :min="1" :max="31"></el-input-number>
              <span style="margin-right: 10px; margin-left: 10px;">号的</span>
              <el-time-picker v-model="radioByCronValMoD"
                              size="mini"
                              placeholder="请选择时间"
                              :clearable="false"
                              :editable="false"
                              value-format="HH:mm:ss"
                              :picker-options="{
                                format: 'HH:mm:ss'
                              }">
              </el-time-picker>
              <span style="margin-left: 10px;">执行一次</span>
            </el-radio>
          </el-form-item>
        </el-radio-group>
        <!--        <el-form-item label="表达式">-->
        <!--          <el-input type="text" placeholder="请输入定时任务表达式" v-model="cronVal" maxlength="50"></el-input>-->
        <!--        </el-form-item>-->
        <!--        <div>-->
        <!--          <label>常用定时任务表达式例子</label>-->
        <!--          <ul>-->
        <!--            <li v-for="(item, i) in cronList" style="margin-bottom: 5px;">-->
        <!--              <span class="cron-txt" @click="cronNodeEvent(item)">{{ item.value }}</span>-->
        <!--              <span class="cron-txt-desc">{{ item.label }}</span>-->
        <!--            </li>-->
        <!--          </ul>-->
        <!--        </div>-->
      </el-form>
      <span slot='footer'>
          <el-button type="primary" @click="chooseCronEvent">确定</el-button>
          <el-button @click="dialogClose">取消</el-button>
      </span>
    </el-dialog>

    <!-- 报表类型 -->
    <el-dialog
        title="报表类型选择"
        width="50%"
        top="10vh"
        center
        v-dialog-drag
        v-if="dialogReportTypeVisible"
        :before-close="dialogClose"
        :visible.sync="dialogReportTypeVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <div style="text-align: center;">
        <el-radio v-model="reportType" label="0">手动报表</el-radio>
        <el-radio v-model="reportType" label="1">自动报表</el-radio>
        <el-radio v-model="reportType" label="3">事件驱动报表</el-radio>
      </div>
      <span slot='footer'>
          <el-button type="primary" @click="chooseReportTypeEvent">确定</el-button>
          <el-button @click="dialogClose">取消</el-button>
      </span>
    </el-dialog>

    <!-- 报表下载类型选择 -->
    <el-dialog
        title="选择下载类型"
        width="500px"
        center
        v-dialog-drag
        v-if="dialogDownloadReportTypeVisible"
        :before-close="dialogClose"
        :visible.sync="dialogDownloadReportTypeVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <div style="text-align: center;">
        <el-radio v-model="downloadType" label="1">Excel</el-radio>
<!--        <el-radio v-model="downloadType" label="2" disabled>PDF</el-radio>-->
      </div>
      <div style="text-align: center; margin-top: 40px;">
        <el-button type="primary" @click="downloadReportEvent">确定</el-button>
      </div>
    </el-dialog>

    <!-- 历史报表查看 -->
    <el-dialog
        title="运行报表记录"
        width="80%"
        top="10vh"
        center
        v-dialog-drag-and-zoom
        v-if="dialogHistoryReportVisible"
        :before-close="dialogClose"
        :visible.sync="dialogHistoryReportVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <div style="height: 60vh;">
        <el-table
            :data="reportHistoryData" border :stripe="true"
            :header-cell-style="{background: '#E8E8E8'}"
            @sort-change="sortChange1"
            style="width: 100%; height: calc(100% - 50px); overflow: auto;">
          <el-table-column
              align="center"
              sortable="custom"
              label="报表名称"
              prop="reportTableName">
            <template slot-scope="scope">
                <span style="color: #409EFF; cursor: pointer;"
                      @click="handleReportNodeClick(scope.row, 'history')"
                      :title="scope.row.reportTableName">{{ scope.row.reportTableName }}</span>
            </template>
          </el-table-column>
          <!--          <el-table-column-->
          <!--              align="center"-->
          <!--              label="报表状态"-->
          <!--              prop="isAutoReport"-->
          <!--              width="180">-->
          <!--            <template slot-scope="scope">-->
          <!--              <el-tag v-if="scope.row.userId != uid" type="success" style="margin-right: 5px;">被分享</el-tag>-->
          <!--              <el-tag v-if="uid == scope.row.userId && scope.row.userGroupList && scope.row.userGroupList.length > 0"-->
          <!--                      type="warning" style="margin-right: 5px;">已分享</el-tag>-->
          <!--            </template>-->
          <!--          </el-table-column>-->
          <el-table-column
              align="center"
              label="当前版本"
              sortable="custom"
              prop="version"
              width="120">
          </el-table-column>
          <el-table-column
              align="center"
              label="运行时间"
              sortable
              prop="createTime"
              width="200">
          </el-table-column>
          <el-table-column label="操作" align="center" width="300">
            <template slot-scope="scope">
              <el-button type="text"
                         v-if="uid == scope.row.userId"
                         size="small"
                         icon="el-icon-delete"
                         style="color: red;"
                         @click="removeReportItem(scope.row, 'record')">删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination
            style="margin-top: 20px;"
            background
            layout="sizes, prev, pager, next, total"
            :current-page="reportHistoryPage"
            :page-size="reportHistoryLimit"
            @size-change="sizeHistoryChangeEvent"
            @current-change="currentHistoryChangeEvent"
            :total="reportHistoryTotal">
        </el-pagination>
      </div>
    </el-dialog>

    <!-- 用户组用户人员查看 -->
    <el-dialog
        title="授权详情"
        width="600px"
        top="10vh"
        center
        v-dialog-drag
        v-if="dialogGroupUserVisible"
        :before-close="dialogGroupUserClose"
        :visible.sync="dialogGroupUserVisible"
        :close-on-click-modal="false"
        :append-to-body="true">
      <div style="height: 60vh;">
        <el-table
            :data="groupUserData" border :stripe="true"
            :header-cell-style="{background: '#E8E8E8'}"
            style="width: 100%; height: calc(100% - 50px); overflow: auto;">
          <el-table-column
              align="center"
              label="用户组名称"
              prop="userGroupName">
          </el-table-column>
          <el-table-column
              align="center"
              label="姓名"
              prop="userName">
          </el-table-column>
        </el-table>
      </div>
    </el-dialog>

    <div id="print-area"
         style="display: none;position: absolute;z-index: 0;top: 0;width: 100%;height: 100vh;overflow: hidden;">
      <div id="print-html" ref="printPayFeeNew"></div>
    </div>
  </div>
</template>

<script>
import BreadcrumbView from '@/components/BreadcrumbView'
import {
  customCompare,
  getLuckysheetConfig,
  getNowFormatDate,
  showAlertWin, showConfirmWin,
  showLoading, showPromptWin
} from '@/utils/cqcy'
import {
  delReportTableById,
  getAllDataModel,
  getAllOkReportTable,
  getAllTableTemplate,
  getAutoChReportTable,
  getChartData,
  getDataModelById,
  getReportTableById,
  getTableData,
  getTableTemplateById,
  getUserByGroupId,
  saveReport,
  tableAssignUserById,
  tableExchangeTypeById,
  updateReportTable,
  updateTableNameById
} from '@/api/datasource'
import Print from 'print-js'
import {getUsername} from '@/utils/auth'
import {exportExcel} from '@/utils/export'
import {getAllUserGroup} from "@/api/user";
import {mapGetters} from "vuex";
import {insertLuckysheetEChart} from "@/utils/luckysheettool";

export default {
  name: "index",
  components: {
    BreadcrumbView
  },
  computed: {
    ...mapGetters([
      'name',
      'uid'
    ])
  },
  data() {
    return {
      breadcrumbList: ['运行配置'],
      groupProps: {
        isLeaf: 'leaf'
      },
      showMainView: false,
      chooseMyReport: null,
      dialogReportTemplateVisible: false,
      dialogDownloadReportTypeVisible: false,
      dialogAutoReportVisible: false,
      dialogReportTypeVisible: false,
      dialogUserGroupVisible: false,
      dialogHistoryReportVisible: false,
      dialogGroupUserVisible: false,
      reportType: '0',
      downloadType: '1',
      btnType: '',
      hasUserGroup: false,
      userGroupInfo: null,
      userGroupList: [],
      radioByCron: null,
      radioByCronValS: '',
      radioByCronValM: '',
      radioByCronValH: '',
      radioByCronValD: null,
      radioByCronValMo: '',
      radioByCronValMoD: null,
      cronVal: '',
      cronList: [],
      reportId: null,
      reportTemplateList: [],
      dataModelList: [],
      chooseReportTemplate: null,
      chooseReportTemplateId: null,
      chooseIsAutoReport: null,
      delFlag: 0,
      reportForm: {
        reportTemplate: null,
        reportValueFormat: '0', // 时间取值格式0时,1日,2月
        isAutoReport: 0,
        valueCondition: null, // 报表取值条件：0平均值 1最大值 2最小值 3瞬时值
        reportDate: [getNowFormatDate('yyyy-MM-dd') + ' 09:00:00',
          getNowFormatDate('yyyy-MM-dd') + ' 18:00:00']
      },
      searchValue: null,
      searchTxt: '',
      valueConditionList: [{
        'key': '平均值',
        'value': '0'
      }, {
        'key': '最大值',
        'value': '1'
      }, {
        'key': '最小值',
        'value': '2'
      }, {
        'key': '瞬时值',
        'value': '3'
      }],
      reportOptions: [{
        label: '所有报表',
        value: -1
      }, {
        label: '手动报表',
        value: 0
      }, {
        label: '自动报表',
        value: 1
      }, {
        label: '事件驱动报表',
        value: 3
      }],
      reportOptions_: [{
        label: '手动报表',
        value: 0
      }, {
        label: '事件驱动报表',
        value: 3
      }],
      groupUserData: [],
      reportHistoryData: [],
      reportHistoryTotal: 0,
      reportHistoryPage: 1,
      reportHistoryLimit: 10,
      reportTotal: 0,
      reportPage: 1,
      reportLimit: 10,
      reportDataList: [],
      reportRules: {
        reportTemplate: [
          {required: true, message: '请选择报表模板', trigger: 'change'}
        ],
        reportValueFormat: [
          {required: true, message: '请选择取值方式', trigger: 'change'}
        ],
        valueCondition: [
          { required: true, message: '请选择报表取值模式', trigger: 'blur' }
        ],
        isAutoReport: [
          {required: true, message: '请选择报表类型', trigger: 'change'}
        ],
        reportDate: [
          {required: true, message: '请选择数据时间'}
        ]
      },
      luckysheetOption: {
        container: 'luckysheet', // 设定 DOM 容器的 id
        title: '报表模板', // 设定表格名称
        lang: 'zh', // 设定表格语言
        showinfobar: false, // 是否显示顶部信息栏
        showtoolbar: false, // 是否显示工具栏
        showtoolbarConfig: {
          paintFormat: true, //格式刷
          moreFormats: true, // 单元格格式
          font: true, // 字体
          fontSize: true, // 字号大小
          bold: true, // 粗体 (Ctrl+B)
          italic: true, // 斜体 (Ctrl+I)
          strikethrough: true, // 删除线 (Alt+Shift+5)
          underline: true, // 下划线 (Alt+Shift+6)
          textColor: true, // 文本颜色
          fillColor: true, // 单元格颜色
          border: true, // 边框
          mergeCell: true, // 合并单元格
          horizontalAlignMode: true, // 水平对齐方式
          verticalAlignMode: true, // 垂直对齐方式
          function: true, // 公式
          // image: true
          // chart: true
        },
        showsheetbar: false, // 是否显示底部 sheet 页按钮
        sheetFormulaBar: false, // 是否显示公式
        row: 100, // 是否显示底部 sheet 页按钮
        data: [{
          "name": "统计报表", //工作表名称
        }],
        cellRightClickConfig: { // 自定义配置单元格右击菜单
          copy: true, // 复制
          copyAs: false, // 复制为
          paste: true, // 粘贴
          insertRow: true, // 插入行
          insertColumn: true, // 插入列
          deleteRow: true, // 删除选中行
          deleteColumn: true, // 删除选中列
          deleteCell: false, // 删除单元格
          hideRow: false, // 隐藏选中行和显示选中行
          hideColumn: false, // 隐藏选中列和显示选中列
          rowHeight: true, // 行高
          columnWidth: true, // 列宽
          clear: false, // 清除内容
          matrix: false, // 矩阵操作选区
          sort: false, // 排序选区
          filter: false, // 筛选选区
          chart: true, // 图表生成
          image: false, // 插入图片
          link: false, // 插入链接
          data: false, // 数据验证
          cellFormat: false // 设置单元格格式
        },
        plugins: ['chart']
      }
    }
  },
  watch: {},
  beforeDestroy() {
    this.chooseMyReport = null
  },
  mounted() {
    let _this = this
    document.onkeyup = function (event) {
      let e = event || window.event || arguments.callee.caller.arguments[0]
      if (!e) return
      const {key, keyCode} = e
      if (keyCode === 46 || keyCode === 8) {
        _this.forceRefreshLuckysheet()
      }
    }
  },
  created() {
    luckysheet.destroy()
    this.loadReport()
    this.initCronList()
  },
  methods: {
    /** 实现类似刷新效果 */
    forceRefreshLuckysheet() {
      if (luckysheet) {
        luckysheet.setCellValue(49, 0, luckysheet.getCellValue(49, 0))
      }
    },
    sortChange({prop, order}) {
      this.reportDataList.sort(customCompare(prop, order))
    },
    sortChange1({prop, order}) {
      this.reportHistoryData.sort(customCompare(prop, order))
    },
    handleSizeChange(val) {
      this.reportPage = 1
      this.reportLimit = val
      this.loadReport()
    },
    handleCurrentChange(val) {
      this.reportPage = val
      this.loadReport()
    },
    sizeHistoryChangeEvent(val) {
      this.reportHistoryPage = 1
      this.reportHistoryLimit = val
      this.historyReport()
    },
    currentHistoryChangeEvent(val) {
      this.reportHistoryPage = val
      this.historyReport()
    },
    changeReportTypeEvent(val) {
      this.reportPage = 1
      this.searchValue = val
      this.loadReport()
    },
    searchReportEvent() {
      this.reportPage = 1
      this.loadReport()
    },
    validCron(value) {
      const cronParse = require('cron-parser')
      try {
        const interval = cronParse.parseExpression(value)
        console.log('cronDate:', interval.next().toDate())
        return true
      } catch (e) {
      }
      return false
    },
    analysisCron() {
      if (!this.cronVal) return
      let s = this.cronVal.split(' ')
      if (s[0].indexOf('/') > -1) {
        this.radioByCron = 1
        this.radioByCronValS = s[0].split('/')[1]
      } else if (s[1].indexOf('/') > -1) {
        this.radioByCron = 2
        this.radioByCronValM = s[1].split('/')[1]
      } else if (s[2].indexOf('/') > -1) {
        this.radioByCron = 3
        this.radioByCronValH = s[2].split('/')[1]
      } else if (s[3] === '*') {
        this.radioByCron = 4
        this.radioByCronValD = s[2] + ':' + s[1] + ':' + s[0]
      } else {
        this.radioByCron = 5
        this.radioByCronValMo = s[3]
        this.radioByCronValMoD = s[2] + ':' + s[1] + ':' + s[0]
      }
    },
    getCron() {
      let result = null
      switch (this.radioByCron) {
          // 按每秒执行：0/2 * * * * ?
        case 1:
          if (Number.isInteger(this.radioByCronValS)) {
            result = '0/#{cron} * * * * ?'
            result = result.replace('#{cron}', this.radioByCronValS)
          }
          break
          // 按每分钟执行：0 0/2 * * * ?
        case 2:
          if (Number.isInteger(this.radioByCronValM)) {
            result = '0 0/#{cron} * * * ?'
            result = result.replace('#{cron}', this.radioByCronValM)
          }
          break
          // 按每小时执行：0 0 0/2 * * ?
        case 3:
          if (Number.isInteger(this.radioByCronValH)) {
            result = '0 0 0/#{cron} * * ?'
            result = result.replace('#{cron}', this.radioByCronValH)
          }
          break
          // 每天定时执行：0 15 10 * * ?
        case 4:
          if (this.radioByCronValD) {
            let times = this.radioByCronValD.split(':')
            result = '#{cron1} #{cron2} #{cron3} * * ?'
            result = result.replace('#{cron1}', times[2])
            result = result.replace('#{cron2}', times[1])
            result = result.replace('#{cron3}', times[0])
            result = result.replace(/00/g, '0')
          }
          break
          // 每月定时执行：0 0 2 1 * ?
        case 5:
          if (Number.isInteger(this.radioByCronValMo) && this.radioByCronValMoD) {
            let times = this.radioByCronValMoD.split(':')
            result = '#{cron1} #{cron2} #{cron3} #{cron4} * ?'
            result = result.replace('#{cron1}', times[2])
            result = result.replace('#{cron2}', times[1])
            result = result.replace('#{cron3}', times[0])
            result = result.replace('#{cron4}', this.radioByCronValMo)
            result = result.replace(/00/g, '0')
          }
          break
        default:
          break
      }
      return result
    },
    chooseCronEvent() {
      this.cronVal = this.getCron()
      if (!this.cronVal) {
        this.$message({
          message: '请指定定时任务类型或运行时间！',
          type: 'warning'
        })
        return
      }
      if (!this.validCron(this.cronVal)) {
        this.$message({
          message: '定时任务表达式格式不正确，请检查！',
          type: 'warning'
        })
        return
      }
      const loading = showLoading(this, '请稍候···')
      let params = {
        'id': this.reportId,
        'isAutoReport': '1',
        'cron': this.cronVal
      }
      tableExchangeTypeById(params).then(res => {
        loading.close()
        this.dialogClose()
        this.loadReport()
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    resetRadioVal() {
      this.radioByCron = null
      this.radioByCronValS = ''
      this.radioByCronValM = ''
      this.radioByCronValH = ''
      this.radioByCronValD = null
      this.radioByCronValMo = ''
      this.radioByCronValMoD = null
      this.cronVal = ''
    },
    chooseReportTypeEvent() {
      if (!this.reportType) {
        this.$message({
          message: '请选择报表类型！',
          type: 'warning'
        })
      }
      // 自动报表
      if (this.reportType == '1') {
        this.resetRadioVal()
        getReportTableById(this.reportId).then(res => {
          this.dialogAutoReportVisible = true
          this.cronVal = res.data.cron
          this.analysisCron()
        }).catch((e) => {
          showAlertWin(this, e)
        })
        return
      }
      const loading = showLoading(this, '请稍候···')
      let params = {
        'id': this.reportId,
        'isAutoReport': this.reportType
      }
      tableExchangeTypeById(params).then(res => {
        loading.close()
        this.dialogClose()
        this.loadReport()
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    switchChangeEvent(val, data) {
      this.reportId = data.id
      if (val) {
        this.resetRadioVal()
        this.dialogAutoReportVisible = true
        getReportTableById(data.id).then(res => {
          this.cronVal = res.data.cron
          this.analysisCron()
        }).catch((e) => {
          showAlertWin(this, e)
        })
        return
      }
      this.dialogReportTypeVisible = true
    },
    setReportStatus(data) {
      this.reportId = data.id
      this.reportType = data.isAutoReport + ''
      this.dialogReportTypeVisible = true
    },
    resetReportFormVal() {
      this.reportForm = {
        reportTemplate: null,
        reportValueFormat: '0', // 时间取值格式0时,1日,2月
        isAutoReport: 0,
        valueCondition: null, // 报表取值条件：0平均值 1最大值 2最小值 3瞬时值
        reportDate: [getNowFormatDate('yyyy-MM-dd') + ' 09:00:00',
          getNowFormatDate('yyyy-MM-dd') + ' 18:00:00']
      }
    },
    /** 新增报表 */
    addReportEvent() {
      this.resetReportFormVal()
      this.getAllReportTemplate()
      this.dialogReportTemplateVisible = true
    },
    /** 刷新报表 */
    refreshReportEvent() {
      this.reportPage = 1
      this.loadReport()
    },
    /** 模版报表选择 */
    chooseReportEvent() {
      this.$refs['reportForm'].validate((valid) => {
        if (valid) {
          const loading = showLoading(this, '数据加载中，请稍候···')
          getTableTemplateById(this.reportForm.reportTemplate).then(res => {
            if (!res.data) {
              loading.close()
              this.$message({
                message: '选择的报表模板不存在！',
                type: 'warning'
              })
              return
            }
            this.showMainView = true
            let luckyData = JSON.parse(res.data.templateData)
            this.chooseReportTemplateId = res.data.id
            this.chooseIsAutoReport = this.reportForm.isAutoReport
            this.chooseReportTemplate = luckyData
            this.drawLuckyExcel(luckyData, () => {
              loading.close()
              this.dialogReportTemplateVisible = false
              this.breadcrumbList = ['新增报表']
              setTimeout(() => {
                this.btnType = 'add'
              }, 100)
            })
          }).catch((e) => {
            loading.close()
            showAlertWin(this, e)
          })
        }
      })
    },
    /** 根据 ID 查询数据模型 */
    getDataModelById(loading, reportData) {
      if (!loading) {
        loading = showLoading(this, '数据加载中，请稍候···')
      }
      getDataModelById(this.reportForm.operationRule).then(res => {
        loading.close()
        if (!res.data) {
          this.$message({
            message: '选择的四则运算表达式不存在！',
            type: 'warning'
          })
          return
        }
        let luckyData = JSON.parse(reportData.templateData)
        this.drawLuckyExcel(luckyData)
        this.btnType = 'add'
        this.dialogReportTemplateVisible = false
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    /** 绘制 Excel 表 */
    drawLuckyExcel(luckyData, callback) {
      let _this = this
      luckysheet.destroy()
      let option = luckyData.option
      option.data = luckyData.data
      let charts = luckyData.charts
      let tables = luckyData.tables
      option.hook = {
        workbookCreateAfter() {
          console.log(luckyData)
          for (let i in charts) {
            _this.insertEChartInfo(charts[i])
          }
          for (let i in tables) {
            _this.insertTableInfo(tables[i])
          }
          _this.drawBaseInfo()
          if (callback) {
            callback()
          }
        },
        cellUpdated(r, c, newV, oldV) {
          if (!(r === 49 && c === 0)) {
            _this.forceRefreshLuckysheet()
          }
        }
      }
      luckysheet.create(option)
    },
    /** 获取图表数据 */
    getChartData(data, callback) {
      getChartData(data).then(res => {
        if (!res.data) {
          if (callback) callback([])
          return
        }
        if (callback) callback(res.data)
      }).catch((e) => {
        if (callback) callback([])
        showAlertWin(this, e)
      })
    },
    /** 获取表格数据 */
    getTableData(data, callback) {
      getTableData(data).then(res => {
        if (!res.data) {
          if (callback) callback([])
          return
        }
        if (callback) callback(res.data)
      }).catch((e) => {
        if (callback) callback([])
        showAlertWin(this, e)
      })
    },
    /** 向 Excel 插入表格 */
    insertTableInfo(tableData) {
      let params = []
      let itemList = tableData.item
      for (let i in itemList) {
        let temp = itemList[i]
        params.push({
          'itemGroupId': temp.itemGroupId,
          'itemName': temp.itemName
        })
      }
      let p = {
        'reportValueFormat': this.reportForm.reportValueFormat,
        'valueCondition': this.reportForm.valueCondition,
        'tableDataDtoChList': params,
        'showType': tableData.showType
      }
      if (this.reportForm.reportDate && this.reportForm.reportDate.length > 0) {
        p.startBelongTime = this.reportForm.reportDate[0]
        p.endBelongTime = this.reportForm.reportDate[1]
      } else {
        p.startBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 08:00:00'
        p.endBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 18:00:00'
      }

      this.getTableData(p, (res) => {
        // console.log('option==>', luckysheet.getAllSheets()[0])
        // console.log('table1==>', res)
        // const optionData = packtable(res, luckysheet.getAllSheets()[0])
        // console.log('table2==>', optionData)
        setTimeout(() => {
          this.drawTableData(res, p.showType, luckysheet.getAllSheets()[0])
        }, 500)
      })
    },
    drawBaseInfo() {
      let currDate = getNowFormatDate('yyyy-MM-dd')
      let currDateTime = getNowFormatDate('yyyy-MM-dd HH:mm:ss')
      let option = luckysheet.getAllSheets()[0]
      option.celldata.map(item => {
        if (item.v.v) {
          item.v.v = String(item.v.v).trim();
          if (item.v.v.match(/\${([^}]+)}/g)) { // 替换${xxx}内部数据
            if (item.v.v.indexOf('${currDate}') > -1) {
              let val = item.v.v
              val = val.replace('${currDate}', currDate)
              luckysheet.setCellValue(item.r, item.c, val)
            }
            if (item.v.v.indexOf('${currDateTime}') > -1) {
              let val = item.v.v
              val = val.replace('${currDateTime}', currDateTime)
              luckysheet.setCellValue(item.r, item.c, val)
            }
            if (item.v.v.indexOf('${userName}') > -1) {
              let val = item.v.v
              val = val.replace('${userName}', getUsername())
              luckysheet.setCellValue(item.r, item.c, val)
            }
            if (item.v.v.indexOf('${winUserName}') > -1) {
              let val = item.v.v
              val = val.replace('${winUserName}', process.env.VUE_APP_WINNAME)
              luckysheet.setCellValue(item.r, item.c, val)
            }
          }
        }
      })
    },
    drawTableData(sources, type, option) {
      option.celldata.map(item => {
        if (item.v.v) {
          item.v.v = String(item.v.v).trim();
          if (item.v.v.match(/\${([^}]+)}/g)) { // 替换${xxx}内部数据
            sources.forEach(source => {
              let itemName = source.itemName
              itemName = itemName.substring(itemName.lastIndexOf('.') + 1)
              let name = '${' + source.itemGroupId + '.' + itemName + '.' + type.dataId + '}'
              if (item.v.v === name) {
                let dataList = source.dataList
                // for (let i = 0; i < dataList.length; i++) {
                for (let i = 0; i < type.valLine; i++) {
                  let p_r = parseInt(item.r)
                  let p_c = parseInt(item.c)
                  if (type.valType == '2') p_r += i
                  else p_c += i
                  luckysheet.setCellValue(p_r, p_c, (dataList[i] != null && dataList[i] != undefined) ? dataList[i] : '')
                }
              }
            })
          }
        }
      })
    },
    /** 向 Excel 插入图表 */
    insertEChartInfo(chart) {
      let _self = this
      let info = chart.info
      let itemList = chart.item
      let itemArr = []
      for (let i in itemList) {
        let temp = itemList[i]
        itemArr.push({
          'itemGroupId': temp.itemGroupId,
          'id': temp.id,
          'itemName': temp.itemName
        })
      }
      let params = {
        'type': info.option.series[0].type,
        'valueCondition': this.reportForm.valueCondition,
        'chartTimeType': this.reportForm.reportValueFormat,
        'tableDataDtoChList': itemArr
      }
      if (this.reportForm.reportDate && this.reportForm.reportDate.length > 0) {
        params.startBelongTime = this.reportForm.reportDate[0]
        params.endBelongTime = this.reportForm.reportDate[1]
      } else {
        params.startBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 08:00:00'
        params.endBelongTime = getNowFormatDate('yyyy-MM-dd') + ' 18:00:00'
      }
      this.getChartData(params, (res) => {
        let result = (res instanceof Array) ? res : []
        // 系列
        let series = info.option.series
        for (let i in series) {
          let temp = series[i]
          temp.data = []
          for (let j in result) {
            if (params.type == 'pie') {
              temp.name = result[j].name
              temp.data.push({
                'name': result[j].describe ? result[j].describe : result[j].name,
                'value': result[j].value
              })
            } else {
              temp.data = result[i].dataList ? result[i].dataList : []
            }
          }
        }
        if (params.type != 'pie') {
          // x 轴
          let xAxis = info.option.xAxis
          let legend = info.option.legend
          // xAxis.data = []
          legend.data = []
          xAxis.data = (result && result.length > 0) ? result[0].dataTimeList : []
          xAxis.data = xAxis.data.slice(0, 7)
          for (let i in result) {
            let name = result[i].describe ? result[i].describe : result[i].itemName
            // xAxis.data.push(name)
            legend.data.push(name)
          }
        }
        console.log(params.type, info)
        setTimeout(() => {
          const sheet = luckysheet.getLuckysheetfile()[0]
          let optionData = sheet.data
          try {
            let flag = true
            insertLuckysheetEChart({
              selector: '#luckysheet',
              info,
              sheet,
              optionData,
              echarts,
              luckysheet,
              $,
              _self,
              flag
            })
          } catch (e) {
            console.log(999, e == 'echarts is not defined')
            console.error(e)
          }
        }, 200)
      })
    },
    /** 查询所有报表信息 */
    getAllReportTemplate() {
      const loading = showLoading(this, '数据加载中，请稍候···')
      let params = {
        'page': 1,
        'limit': 1000
      }
      getAllTableTemplate(params).then(res => {
        loading.close()
        if (!res.data) {
          return
        }
        this.reportTemplateList = res.data.tableTemplateList
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    /** 查询所有数据模型 */
    getAllDataModel() {
      let params = {
        'page': 1,
        'limit': 1000
      }
      getAllDataModel(params).then(res => {
        if (!res.data) {
          return
        }
        this.dataModelList = res.data.dataModelList
      }).catch((e) => {
        showAlertWin(this, e)
      })
    },
    /** 查询我的报表列表 */
    loadReport() {
      const loading = showLoading(this, '加载中，请稍候···')
      let params = {
        'page': this.reportPage,
        'limit': this.reportLimit
      }
      if (this.searchValue != '-1') {
        params.isAutoReport = this.searchValue
      }
      if (this.searchTxt && this.searchTxt.trim()) {
        params.reportTableName = this.searchTxt
      }
      // getAllReportTable(params).then(res => {
      getAllOkReportTable(params).then(res => {
        loading.close()
        if (!res || !res.data) {
          return
        }
        this.reportTotal = res.data.count
        this.reportDataList = res.data.reportTableList
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    /** 设置用户组信息 */
    setUserGroupEvent(data) {
      if (data.userId != this.uid) {
        this.$message({
          message: '您没有权限进行设置！',
          type: 'warning'
        })
        return
      }
      this.reportId = data.id
      this.dialogUserGroupVisible = true
      getAllUserGroup().then(res => {
        this.$nextTick(() => {
          this.userGroupList = res.data
          // this.userGroupInfo = data.userGroupList
          this.userGroupInfo = []
          for (let i = 0; i < data.userGroupList.length; i++) {
            this.userGroupInfo.push(data.userGroupList[i].id)
          }
          if (data.userGroupList && data.userGroupList.length > 0) {
            this.hasUserGroup = true
          }
        })
      }).catch((e) => {
        showAlertWin(this, e)
      })
    },
    getUserGroupEvent(data) {
      this.groupUserData = []
      if (!data.userGroupList || data.userGroupList.length == 0) {
        this.$message({
          message: '该报表还未进行授权操作！',
          type: 'warning'
        })
        return
      }
      let _this = this
      data.userGroupList.forEach((group) => {
        getUserByGroupId(group.id).then(res => {
          let users = res.data
          users.forEach((u) => {
            _this.groupUserData.push({
              'userGroupName': group.userGroupName,
              'userName': u.userName
            })
          })
        }).catch((e) => {
          showAlertWin(_this, e)
        })
      })
      this.dialogGroupUserVisible = true
    },
    chooseUserGroupEvent() {
      // if (!this.userGroupInfo) {
      //   this.$message({
      //     message: '请选择用户组！',
      //     type: 'warning'
      //   })
      //   return
      // }
      let params = {
        'id': this.reportId,
        'userGroupList': []
      }
      for (let i = 0; i < this.userGroupInfo.length; i++) {
        params.userGroupList.push({
          'id': this.userGroupInfo[i]
        })
      }
      tableAssignUserById(params).then(res => {
        if (this.hasUserGroup || this.userGroupInfo) {
          this.$message({
            message: '保存成功！',
            type: 'success'
          })
          this.hasUserGroup = false
        }
        this.dialogClose()
        this.loadReport()
      }).catch((e) => {
        showAlertWin(this, e)
      })
    },
    /** 处理自动报表数据信息 */
    drawAutoReportData(datas) {
      if (!datas || datas.length == 0) {
        return
      }
      datas.forEach((data) => {
        if (!data || !data.item) {
          return
        }
        let showInfo = data.showType
        let fieldList = data.field
        data.item.forEach((item, i) => {
          if (!item || !item.dataList) {
            return
          }
          let itemName = item.itemName
          itemName = itemName.substring(itemName.lastIndexOf('.') + 1)
          let tempName = '${' + item.itemGroupId + '.' + itemName + '.' + showInfo.dataId + '}'
          let p_r, p_c
          if (fieldList[i] && tempName == fieldList[i].name) {
            p_r = parseInt(fieldList[i].r)
            p_c = parseInt(fieldList[i].c)
          } else {
            for (let n = 0; n < fieldList.length; n++) {
              if (fieldList[n].name == tempName) {
                p_r = parseInt(fieldList[n].r)
                p_c = parseInt(fieldList[n].c)
                break
              }
            }
          }
          // 数据信息
          let dataList = item.dataList
          for (let j = 0; j < showInfo.valLine; j++) {
            let c = p_c
            let r = p_r
            if (showInfo.valType == '2') r += j
            else c += j
            luckysheet.setCellValue(r, c, (dataList[j] != null && dataList[j] != undefined) ? (dataList[j] + '') : '')
          }
        })
      })
    },
    /** 报表点击事件 */
    handleReportNodeClick(data, type) {
      if (data.id == -1 || this.delFlag == 1) {
        return
      }
      const loading = showLoading(this, '加载中，请稍候···')
      getReportTableById(data.id).then(res => {
        loading.close()
        if (!res.data) {
          this.$message({
            message: '选择的报表不存在！',
            type: 'warning'
          })
          return
        }
        this.showMainView = true
        this.breadcrumbList = [res.data.reportTableName]
        let reportTableData = res.data.reportTableData
        this.reportForm.valueCondition = res.data.valueCondition
        this.reportForm.reportValueFormat = res.data.reportValueFormat
        let luckyData = JSON.parse(reportTableData)
        console.log(luckyData)
        // 只读
        if (type === 'history') {
          this.dialogHistoryReportVisible = false
          this.btnType = 'showChild'
        } else if (type === 'deny') {
          this.chooseMyReport = res.data
          this.dialogHistoryReportVisible = false
          this.btnType = 'showShared'
        } else {
          this.chooseMyReport = res.data
          this.btnType = 'show'
        }
        this.setLuckysheetStatus(luckyData, type === 'history' || type === 'deny', type)
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    /** 设置工作表状态 */
    setLuckysheetStatus(luckyData, isReadOnly, type) {
      let _this = this
      luckysheet.destroy()
      let option = luckyData.option
      if (!option) option = JSON.parse(JSON.stringify(this.luckysheetOption))
      option.data = luckyData.data
      if (isReadOnly) {
        // 设置工作表保护
        option.data[0].config.authority = {
          sheet: 1, // 如果为 1 或 true，则该工作表受到保护；如果为 0 或 false，则该工作表不受保护。
          hintText: '该工作表受到保护，无法操作', // 弹窗提示的文字
        }
        // 关闭右键菜单
        option.cellRightClickConfig.chart = false
        option.cellRightClickConfig.columnWidth = false
        option.cellRightClickConfig.rowHeight = false
        option.cellRightClickConfig.deleteColumn = false
        option.cellRightClickConfig.deleteRow = false
        option.cellRightClickConfig.insertColumn = false
        option.cellRightClickConfig.insertRow = false
        // 关闭工具栏
        option.showtoolbar = false
        option.enableAddRow = false
        option.showtoolbarConfig = {
          bold: false,
          border: false,
          fillColor: false,
          font: false,
          fontSize: false,
          function: false,
          horizontalAlignMode: false,
          italic: false,
          mergeCell: false,
          moreFormats: false,
          paintFormat: false,
          strikethrough: false,
          textColor: false,
          underline: false,
          verticalAlignMode: false
        }
        // 钩子函数
        option.hook = {
          workbookCreateAfter() {
            let charts = luckyData.charts
            let tables = luckyData.tables
            let eventTables = luckyData.eventTables
            option.data.forEach((data, i) => {
              if (data.chart && data.chart.length > 0) {
                data.chart.forEach((chart, j) => {
                  console.log(chart.chart_id)
                  let dom = document.getElementById(chart.chart_id + '_c')
                  if (dom) dom.style.display = 'none'
                })
              }
            })
            if (type == 'deny') {
              for (let i in charts) {
                _this.insertEChartInfo(charts[i])
              }
              for (let i in tables) {
                _this.insertTableInfo(tables[i])
              }
              _this.drawBaseInfo()
            }
            _this.drawAutoReportData(luckyData.tables)
            // 事件驱动报表信息
            _this.drawEventReportData(eventTables)
            luckysheet.setRangeShow('BH1')
          }
        }
      } else {
        let charts = luckyData.charts
        let tables = luckyData.tables
        let eventTables = luckyData.eventTables
        // 钩子函数
        option.hook = {
          workbookCreateAfter() {
            for (let i in charts) {
              _this.insertEChartInfo(charts[i])
            }
            for (let i in tables) {
              _this.insertTableInfo(tables[i])
            }
            _this.drawBaseInfo()
            // 事件驱动报表信息
            _this.drawEventReportData(eventTables)
            luckysheet.setRangeShow('BH1')
          },
          cellUpdated(r, c, newV, oldV) {
            if (!(r === 49 && c === 0)) {
              _this.forceRefreshLuckysheet()
            }
          }
        }
      }
      luckysheet.create(option)
    },
    /** 绘制事件驱动报表信息 */
    drawEventReportData(eventTables) {
      if (!eventTables || eventTables.length == 0) {
        return
      }
      let x = 0, y = 0
      eventTables.forEach((data, i) => {
        x += 1
        y = 0
        let { dataList, dataTimeList, itemName } = data
        itemName = (itemName != null && itemName != undefined) ? itemName : ''
        luckysheet.setCellValue(x, y, itemName)
        dataList.forEach((val, j) => {
          y = j + 1
          let _date = luckysheet.getCellValue(0, y)
          if (!_date) {
            let text = (dataTimeList[j] != null && dataTimeList[j] != undefined) ? dataTimeList[j] : ''
            if (text.length > 19) text = text.substring(0, 19)
            luckysheet.setCellValue(0, y, text)
          }
          val = (val != null && val != undefined) ? val : ''
          luckysheet.setCellValue(x, y, val)
        })
      })
    },
    /** 修改报表信息 */
    editReportItem(data) {
      showPromptWin(this, '修改报表名称', '请输入报表名称', data.reportTableName, (val) => {
        if (!val || !val.trim()) {
          return '报表名称不能为空'
        }
        if (val.length > 20) {
          return '报表名称必须在20字以内'
        }
      }, (value) => {
        const loading = showLoading(this, '修改中，请稍候···')
        let params = {
          'id': data.id,
          'reportTableName': value
        }
        updateTableNameById(params).then(res => {
          loading.close()
          let msg = res.data ? '修改成功！' : '修改失败！'
          let msgType = res.data ? 'success' : 'warning'
          this.$message({
            message: msg,
            type: msgType
          })
          this.reportPage = 1
          this.loadReport()
        }).catch((e) => {
          loading.close()
          showAlertWin(this, e)
        })
      })
    },
    /** 报表移除 */
    removeReportItem(data, type) {
      showConfirmWin(this, null, '您确定要删除该报表吗？', () => {
        const loading = showLoading(this, '删除中，请稍候···')
        delReportTableById(data.id).then(res => {
          loading.close()
          let msg = res.data ? '删除成功！' : '删除失败！'
          let msgType = res.data ? 'success' : 'warning'
          this.$message({
            message: msg,
            type: msgType
          })
          if (type == 'record') {
            this.reportHistoryPage = 1
            this.historyReport()
            return
          }
          this.reportPage = 1
          this.loadReport()
          this.cancelSaveReport()
        }).catch((e) => {
          loading.close()
          showAlertWin(this, e)
        })
      })
    },
    /** 获取单元格大小 */
    getCellSize(celldata, r, c, luckysheet) {
      const {cs, rs} = celldata.data[r][c].mc
      const rowhidden = celldata.config.rowhidden && Object.keys(celldata.config.rowhidden) || ''
      const rowArr = []
      for (let i = 0; i < rs; i++) {
        let rowIndex = r + i
        if (rowhidden.indexOf(String(rowIndex)) < 0) {
          rowArr.push(rowIndex)
        }
      }
      const colArr = []
      for (let j = 0; j < cs; j++) {
        colArr.push(c + j)
      }
      const totalHeight = Object.values(
          luckysheet.getRowHeight(rowArr)
      ).reduce((a, b) => a + b)
      const totalWidth = Object.values(
          luckysheet.getColumnWidth(colArr)
      ).reduce((a, b) => a + b)
      return {
        w: totalWidth,
        h: totalHeight
      }
    },
    /** 获取图片位置 */
    getImagePosition(num, arr) {
      let index = 0
      let minIndex
      let maxIndex
      for (let i = 0; i < arr.length; i++) {
        if (num < arr[i]) {
          index = i
          break
        }
      }
      if (index == 0) {
        minIndex = 0
        maxIndex = 1
      } else if (index == arr.length - 1) {
        minIndex = arr.length - 2
        maxIndex = arr.length - 1
      } else {
        minIndex = index - 1
        maxIndex = index
      }
      let min = arr[minIndex]
      let max = arr[maxIndex]
      let radio = Math.abs((num - min) / (max - min)) + index
      return radio
    },
    /** 图表转换为图片 */
    convertChart(luckyData) {
      const optionData = luckysheet.getLuckysheetfile()[0]
      let {
        visibledatacolumn, // 所有行的位置
        visibledatarow // 所有列的位置
      } = optionData
      // 动态图表
      if (luckyData.charts && luckyData.charts.length > 0) {
        luckyData.charts.forEach((chart, i) => {
          let myChart = echarts.init(
              document.getElementsByClassName(chart.info.className)[0]
          )
          let baseData = myChart.getConnectedDataURL({
            type: 'png',
            pixelRatio: 2,
            backgroundColor: '#ffffff'
          })
          // luckysheet.cancelRangeMerge(chart.info.pos)
          luckysheet.insertImage(baseData, {
            rowIndex: chart.info.pos[0],
            colIndex: chart.info.pos[1],
            cellSize: this.getCellSize(optionData, chart.info.pos[0], chart.info.pos[1], luckysheet),
            success: function () {
              console.log("插入成功")
            }
          })
        })
      }
      // 静态图表
      if (luckyData.data && luckyData.data.length > 0) {
        luckyData.data.forEach((data, i) => {
          if (data.chart && data.chart.length > 0) {
            data.chart.forEach((chart, j) => {
              let myChart = echarts.init(
                  document.getElementById(chart.chart_id)
              )
              myChart.setOption(chart.chartOptions);
              let baseData = myChart.getConnectedDataURL({
                type: 'png',
                pixelRatio: 2,
                backgroundColor: '#ffffff'
              })
              let col_st = this.getImagePosition(chart.left, visibledatacolumn)
              let row_st = this.getImagePosition(chart.top, visibledatarow)
              luckysheet.insertImage(baseData, {
                rowIndex: parseInt(row_st),
                colIndex: parseInt(col_st),
                cellSize: {
                  w: chart.width,
                  h: chart.height,
                },
                success: function () {
                  console.log("插入成功")
                }
              })
            })
          }
        })
      }
    },
    /** 处理日期显示数字问题 */
    withDateData(excelData) {
      if (!excelData) {
        return
      }
      try {
        excelData.map((item) => {
          if (item) {
            item.map((ll) => {
              if (ll && ll.ct && ll.ct.t && ll.ct.t === 'd') {
                ll.m = ll.m,
                    ll.v = ll.m,
                    ll.ct = {
                      fa: "@",
                      t: "s",
                    }
              }
            })
          }
        })
      }catch (error){
        console.log(error)
      }
    },
    /** 保存报表信息 */
    saveReportInfo() {
      showPromptWin(this, '保存', '请输入报表名称', '', (val) => {
        if (!val) {
          return '报表名称不能为空'
        }
        if (val.length > 20) {
          return '报表名称必须在20字以内'
        }
      }, (value) => {
        if (!this.chooseReportTemplate) {
          this.$message({
            message: '请重新选择报表模板',
            type: 'warning'
          })
          return
        }
        const loading = showLoading(this, '保存中，请稍候···')
        let excelData = this.chooseReportTemplate.data[0].data
        let excelTable = this.chooseReportTemplate.tables
        excelTable.forEach(table => {
          table.field.forEach(field => {
            luckysheet.setCellValue(field.r, field.c, field.name)
          })
        })
        this.withDateData(excelData)
        // this.convertChart(this.chooseReportTemplate)
        let data = {
          'tableTemplateId': this.chooseReportTemplateId,
          'reportTableName': value,
          'reportValueFormat': this.reportForm.reportValueFormat,
          'valueCondition': this.reportForm.valueCondition,
          'isAutoReport': this.chooseIsAutoReport,
          'reportTableData': JSON.stringify(this.chooseReportTemplate)
        }
        saveReport(data).then(res => {
          loading.close()
          let msg = res.data ? '保存成功！' : '保存失败！'
          let msgType = res.data ? 'success' : 'error'
          this.$message({
            message: msg,
            type: msgType
          })
          this.showMainView = false
          this.loadReport()
          this.cancelSaveReport()
        }).catch((e) => {
          loading.close()
          showAlertWin(this, e)
        })
      })
    },
    /** 更新报表信息 */
    updateReport() {
      console.log(this.chooseMyReport)
      if (!this.chooseMyReport || !this.chooseMyReport.id) {
        this.$message({
          message: '保存失败，请刷新后重试！',
          type: 'warning'
        })
        return
      }
      showPromptWin(this, '保存', '请输入报表名称', this.chooseMyReport.reportTableName, (val) => {
        if (!val) {
          return '报表名称不能为空'
        }
        if (val.length > 20) {
          return '报表名称必须在20字以内'
        }
      }, (value) => {
        const loading = showLoading(this, '保存中，请稍候···')
        let _data2 = JSON.parse(this.chooseMyReport.reportTableData)
        let excelTable = _data2.tables
        excelTable.forEach(table => {
          table.field.forEach(field => {
            luckysheet.setCellValue(field.r, field.c, field.name)
          })
        })
        let _data = JSON.parse(getLuckysheetConfig())
        let excelData = _data[0].data
        this.withDateData(excelData)
        _data2.data = _data
        // this.convertChart(_data2)
        let data = this.chooseMyReport
        data.reportTableName = value
        data.reportTableData = JSON.stringify(_data2)
        updateReportTable(data).then(res => {
          loading.close()
          let msg = res.data ? '保存成功！' : '保存失败！'
          let msgType = res.data ? 'success' : 'error'
          this.$message({
            message: msg,
            type: msgType
          })
          this.showMainView = false
          this.loadReport()
          this.cancelSaveReport()
        }).catch((e) => {
          loading.close()
          showAlertWin(this, e)
        })
      })
    },
    /** 报表下载 */
    downloadReport() {
      this.dialogDownloadReportTypeVisible = true
    },
    /** 报表下载事件 */
    downloadReportEvent() {
      if (!this.chooseMyReport) {
        this.$message({
          message: '请选择报表',
          type: 'warning'
        })
        return
      }
      let reportName = this.chooseMyReport.reportTableName ? this.chooseMyReport.reportTableName : '统计报表'
      if (this.downloadType == '1') {
        // exportExcel(luckysheet, reportName, ExcelJS).then((res) => {
        //   console.log("result==>", res)
        //   // this.$message({
        //   //   message: res,
        //   //   type: 'success'
        //   // })
        //   this.dialogDownloadReportTypeVisible = false
        // }).catch((err) => {
        // })
        exportExcel(luckysheet.getAllSheets(), reportName)
        setTimeout(() => {
          this.dialogDownloadReportTypeVisible = false
        }, 500)
      }
    },
    /** 报表记录 */
    historyReport() {
      const loading = showLoading(this, '加载中，请稍候···')
      let params = {
        'page': this.reportHistoryPage,
        'limit': this.reportHistoryLimit,
        'autoTableId': this.chooseMyReport.id
      }
      getAutoChReportTable(params).then(res => {
        loading.close()
        this.dialogHistoryReportVisible = true
        if (!res.data) return
        this.reportHistoryData = res.data.reportTableList
        this.reportHistoryTotal = res.data.count
      }).catch((e) => {
        loading.close()
        showAlertWin(this, e)
      })
    },
    getPrintSheetArea() {
      const sheetData = luckysheet.getSheetData();
      let objRowColumn = {
        row: [0, 0], //行
        column: [0, 0], //列
      };
      // * item是行、index是行索引、it是一行里的一格、itemIndex是这一格在这一行里的列索引
      sheetData.forEach((item, index) => {
        //行数
        item.forEach((it, itemIndex) => {
          if (it !== null && it.v) {
            console.log(index, it)
            if (objRowColumn.row[1] < index) {
              objRowColumn.row[1] = index; //row第二位
            }
            if (objRowColumn.column[1] < itemIndex) {
              objRowColumn.column[1] = itemIndex; //column第二位
            }
          }
        });
      });
      return objRowColumn;
    },
    /** 打印操作 */
    printExcel() {
      const loading = showLoading(this, '请稍候···')
      document.querySelector('#print-area').style = "display:block";
      window.luckysheet.hideGridLines();
      // 获取当前选中区域
      let currentSelected = luckysheet.getRange()
      // 如果当前选中区只是一个单元格，则认为选取无效。
      if (currentSelected[0] != null
          && (currentSelected[0].row[1] - currentSelected[0].row[0] >= 1
              || currentSelected[0].column[1] - currentSelected[0].column[0] >= 1)) {
        // 生成base64图片
        let imgSrc = luckysheet.getScreenshot();
        window.luckysheet.showGridLines();
        // * Lodop中的ADD_PRINT_IMAGE，也可以直接输出base64码图片，不用加img标签（如果加了img标签，会被当做超文本对待，受浏览器引擎解析的影响）
        let $img = `<img src=${imgSrc} style="max-width: 90%;" />`
        this.$nextTick(() => {
          document.querySelector('#print-html').innerHTML = $img;
          setTimeout(() => {
            Print({
              printable: 'print-html',
              type: 'html',
              documentTitle: '文档标题',
              header: '',
              headerStyle: 'font-weight:400;text-align:center;',
              style: '@page {margin: 0 10mm};', // 不打印页眉和页脚
              honorColor: true, // 是否打印彩色文本
              targetStyles: ['*'] // 允许打印所有样式属性
            }) // Print.js插件
            document.querySelector("#print-area").style.display = "none";
            loading.close()
          }, 1000)
        })
      } else {
        // 获取打印区域的行列
        let RowColumn = this.getPrintSheetArea();
        // 因需要打印左边的边框，需重新设置第一列
        RowColumn.column[0] = 0;
        // 进行选区操作
        luckysheet.setRangeShow(RowColumn);
        let imgSrc = luckysheet.getScreenshot(); // 生成base64图片
        window.luckysheet.showGridLines();
        // * Lodop中的ADD_PRINT_IMAGE，也可以直接输出base64码图片，不用加img标签（如果加了img标签，会被当做超文本对待，受浏览器引擎解析的影响）
        let $img = `<img src=${imgSrc} style="max-width: 90%;" />`
        this.$nextTick(() => {
          document.querySelector('#print-html').innerHTML = $img;
          setTimeout(() => {
            Print({
              printable: 'print-html',
              type: 'html',
              documentTitle: '文档标题',
              header: '',
              headerStyle: 'font-weight:400;text-align:center;',
              style: '@page {margin: 0 10mm};', // 不打印页眉和页脚
              honorColor: true, // 是否打印彩色文本
              targetStyles: ['*'] // 允许打印所有样式属性
            }) // Print.js插件
            document.querySelector("#print-area").style.display = "none";
            loading.close()
          }, 1000)
        })
      }
    },
    /** 自定义选中区域 */
    getExcelRowColumn() {
      const sheetData = luckysheet.getSheetData();
      let objRowColumn = {
        row: [null, null], //行
        column: [null, null], //列
      };
      sheetData.forEach((item, index) => {
        //行数
        item.forEach((it, itemIndex) => {
          console.log(it)
          if (it !== null) {
            if (objRowColumn.row[0] == null) objRowColumn.row[0] = index; // row第一位
            objRowColumn.row[1] = index; //row第二位
            if (objRowColumn.column[0] == null)
              objRowColumn.column[0] = itemIndex; //column第一位
            objRowColumn.column[1] = itemIndex; //column第二位
          }
        });
      });
      return objRowColumn;
    },
    cronNodeEvent(obj) {
      this.cronVal = obj.value
    },
    initCronList() {
      this.cronList = []
      this.cronList.push({value: '0/2 * * * * ?', label: '表示每2秒钟执行一次任务'})
      this.cronList.push({value: '0 0/2 * * * ?', label: '表示每2分钟执行一次任务'})
      this.cronList.push({value: '0 0 0/2 * * ?', label: '表示每2小时执行一次任务'})
      this.cronList.push({value: '0 15 10 * * ?', label: '表示在每天上午10点15分执行一次任务'})
      this.cronList.push({value: '0 0 10,14,16 * * ?', label: '表示在每天的上午10点、下午2点、下午4点分别执行一次任务'})
      this.cronList.push({
        value: '0 0/30 9-17 * * ?',
        label: '表示在每天的上午9点到下午5点的范围内每30分钟执行一次任务'
      })
      this.cronList.push({value: '0 0 12 ? * WED', label: '表示在每周星期三中午12点执行一次任务'})
      this.cronList.push({value: '0 0 2 1 * ?', label: '表示在每月的1日的凌晨2点执行一次任务'})
    },
    /** 取消保存报表 */
    cancelSaveReport2() {
      this.handleReportNodeClick(this.chooseMyReport, this.chooseMyReport.userId !== this.uid ? 'deny' : '')
    },
    /** 取消保存报表 */
    cancelSaveReport() {
      luckysheet.destroy()

      this.breadcrumbList = ['运行配置']
      this.showMainView = false
      this.btnType = ''
      this.chooseMyReport = null
      if (this.$refs['reportForm']) this.$refs['reportForm'].resetFields()
    },
    /** 弹出层关闭事件 */
    dialogClose(done) {
      this.cronVal = ''
      this.reportId = null
      // this.userGroupInfo = null
      if (typeof (done) === 'function') {
        done()
      } else {
        this.dialogReportTemplateVisible = false
        this.dialogDownloadReportTypeVisible = false
        this.dialogAutoReportVisible = false
        this.dialogReportTypeVisible = false
        this.dialogUserGroupVisible = false
      }
    },
    /** 弹出层关闭事件 */
    dialogGroupUserClose(done) {
      if (typeof (done) === 'function') {
        done()
      } else {
        this.dialogGroupUserVisible = false
      }
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss">
.breadcrumb-content {
  padding-bottom: 0;
}

.cy-nav-sx {
  float: left !important;
  margin-top: -23px !important;
  margin-left: 120px !important;
  display: flex;
}

.cy-nav-btn {
  float: right !important;
  margin-right: 20px !important;
  margin-top: -20px !important;
}

.cy-main {
  margin: 10px 20px;
  width: calc(100% - 40px);
  height: calc(100% - 100px);

  .cy-btn {
    margin-bottom: 10px;
  }

  .cy-btn .el-link {
    margin-right: 15px;
  }

  .cy-main-left {
    width: 100%;
    height: 100%;
    overflow: auto;
    //float: left;
    padding: 5px 10px;
    //border-right: 1px solid #d4d4d4;

    .cy-list {
      overflow: auto;
      height: 100%;
      height: calc(100% - 40px);

      ul {
        display: flex;
        flex-wrap: wrap;
        padding: 0;
        margin-top: 0;

        li {
          list-style-type: none;
          background: #41aed7;
          width: 23%;
          margin: 10px 1%;
          border-radius: 8px;
          height: 110px;
          padding: 15px;
          color: #ffffff;

          .cy-item-name {
            font-size: 14px;
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
            margin-bottom: 15px;
            cursor: pointer;
          }

          .cy-item-val {
            font-size: 12px;
          }

          .cy-list-item {
            font-size: 12px;
            color: #f6f6f6;
            width: 100%;
            //display: flex;
            margin-top: 40px;
          }
        }
      }
    }
  }

  .cy-main-right {
    width: 100%;
    height: 100%;
    float: left;
    overflow: hidden;
  }
}

.cy-group-tree1 {
  font-size: 14px;

  .custom-tree-node1 {
    height: 28px;
    line-height: 28px;
  }
}

.cron-txt {
  color: blue;
  margin-right: 20px;
  cursor: pointer;
  font-weight: bold;
  font-size: 16px;
}

.cron-txt-desc {
}

.ug-div {
  .el-transfer-panel {
    width: 300px;
  }
}
</style>