Bladeren bron

Merge branch 'master' of http://8.136.199.33:3000/eta_front/eta_front

shanbinzhang 6 maanden geleden
bovenliggende
commit
00a5a6c19e
68 gewijzigde bestanden met toevoegingen van 5753 en 491 verwijderingen
  1. 74 0
      src/api/modules/reportMaterial.js
  2. BIN
      src/assets/img/smartReport/icon19.png
  3. BIN
      src/assets/img/smartReport/icon20.png
  4. 152 0
      src/components/UploadToMaterial.vue
  5. 24 0
      src/components/chart/chartDetailHandlesWrap.vue
  6. 21 2
      src/components/chart/chartListTableWrap.vue
  7. 4 0
      src/lang/commonLang.js
  8. 43 0
      src/lang/modules/ReportManagement/Material.js
  9. 6 6
      src/lang/modules/ReportManagement/ReportList.js
  10. 3 1
      src/lang/modules/ReportManagement/indexEn.js
  11. 3 1
      src/lang/modules/ReportManagement/indexZh.js
  12. 1 1
      src/lang/modules/Slides/pptPresent.js
  13. 20 0
      src/mixins/index.js
  14. 8 0
      src/routes/modules/oldRoutes.js
  15. 32 1
      src/utils/buttonConfig.js
  16. 4 0
      src/utils/registryComponents.js
  17. 1 0
      src/views/Home.vue
  18. 17 1
      src/views/dataEntry_manage/chartSetting.vue
  19. 18 13
      src/views/datasheet_manage/components/BalanceTable.vue
  20. 14 0
      src/views/datasheet_manage/sheetList.vue
  21. 16 0
      src/views/intervalAnalysis/list.vue
  22. 422 0
      src/views/mychart_manage/components/BatchSaveToMaterial.vue
  23. 18 1
      src/views/mychart_manage/components/chartDetailDia.vue
  24. 10 2
      src/views/mychart_manage/index.vue
  25. 3 2
      src/views/ppt_manage/mixins/mixins.js
  26. 224 0
      src/views/ppt_manage/newVersion/components/editor/InsertBalanceSheet.vue
  27. 240 0
      src/views/ppt_manage/newVersion/components/editor/InsertETAChart.vue
  28. 170 0
      src/views/ppt_manage/newVersion/components/editor/InsertMaterial.vue
  29. 1 1
      src/views/ppt_manage/newVersion/components/editor/InsertSemantics.vue
  30. 174 0
      src/views/ppt_manage/newVersion/components/editor/InsertSheet.vue
  31. 71 96
      src/views/ppt_manage/newVersion/pptEditor.vue
  32. 75 67
      src/views/ppt_manage/newVersion/pptEnEditor.vue
  33. 224 0
      src/views/report_manage/components/importBalanceSheet.vue
  34. 170 0
      src/views/report_manage/components/importMaterial.vue
  35. 169 0
      src/views/report_manage/components/importSheet.vue
  36. 332 0
      src/views/report_manage/material/components/classifyTree.vue
  37. 126 0
      src/views/report_manage/material/components/editClassify.vue
  38. 145 0
      src/views/report_manage/material/components/imgMove.vue
  39. 102 0
      src/views/report_manage/material/components/imgRename.vue
  40. 300 0
      src/views/report_manage/material/components/uploadImgs.vue
  41. 486 0
      src/views/report_manage/material/list.vue
  42. 81 10
      src/views/report_manage/mixins/reportMixin.js
  43. 31 39
      src/views/report_manage/reportEn/reportEditor.vue
  44. 271 0
      src/views/report_manage/reportV2/normalReport/components/BalanceSheet.vue
  45. 29 3
      src/views/report_manage/reportV2/normalReport/components/ETAChart.vue
  46. 1 0
      src/views/report_manage/reportV2/normalReport/components/ETAPriceChart.vue
  47. 2 2
      src/views/report_manage/reportV2/normalReport/components/ETASandBox.vue
  48. 89 20
      src/views/report_manage/reportV2/normalReport/components/ETASheet.vue
  49. 200 0
      src/views/report_manage/reportV2/normalReport/components/Material.vue
  50. 1 1
      src/views/report_manage/reportV2/normalReport/components/SemanticAnalysis.vue
  51. 43 27
      src/views/report_manage/reportV2/normalReport/components/StatisticAnalysis.vue
  52. 16 2
      src/views/report_manage/reportV2/normalReport/components/insertContent.vue
  53. 1 0
      src/views/report_manage/reportV2/normalReport/editReport.vue
  54. 99 34
      src/views/report_manage/reportV2/normalReport/mixins/reportMixin.js
  55. 312 0
      src/views/report_manage/reportV2/smartReport/components/BalanceSheet.vue
  56. 38 10
      src/views/report_manage/reportV2/smartReport/components/ETAChart.vue
  57. 7 6
      src/views/report_manage/reportV2/smartReport/components/ETAPriceChart.vue
  58. 8 7
      src/views/report_manage/reportV2/smartReport/components/ETASandBox.vue
  59. 109 30
      src/views/report_manage/reportV2/smartReport/components/ETASheet.vue
  60. 15 11
      src/views/report_manage/reportV2/smartReport/components/ImgSource.vue
  61. 1 1
      src/views/report_manage/reportV2/smartReport/components/ImportMyETAChart.vue
  62. 231 0
      src/views/report_manage/reportV2/smartReport/components/Material.vue
  63. 7 6
      src/views/report_manage/reportV2/smartReport/components/SemanticAnalysis.vue
  64. 50 31
      src/views/report_manage/reportV2/smartReport/components/StatisticAnalysis.vue
  65. 96 54
      src/views/report_manage/reportV2/smartReport/editReport.vue
  66. 16 1
      src/views/sandbox_manage/index_new_version.vue
  67. 64 0
      src/views/semantics_manage/document/documentEditPage.vue
  68. 12 1
      src/views/semantics_manage/semanticsPage.vue

+ 74 - 0
src/api/modules/reportMaterial.js

@@ -0,0 +1,74 @@
+import http from "@/api/http.js"
+
+// 报告素材库
+export const apiReportMaterial= {
+  // 添加分类
+  addClassify:params=>{
+    return http.post('/material/classify/add',params)
+  },
+  // 编辑分类
+  editClassify:params=>{
+    return http.post('/material/classify/edit',params)
+  },
+  // 移动分类
+  moveClassify:params=>{
+    return http.post('/material/classify/move',params)
+  },
+  // 检测删除分类
+  delClassifyCheck:params=>{
+    return http.post('/material/classify/del/check',params)
+  },
+  // 删除分类
+  delClassify:params=>{
+    return http.post('/material/classify/del',params)
+  },
+  // 分类列表
+  classifyList:params=>{
+    return http.get('/material/classify/list',params)
+  },
+
+  // 素材图片上传
+  materialImgUpload:params=>{
+    return http.post('/material/upload',params)
+  },
+  // 素材列表
+  materialList:params=>{
+    return http.get('/material/list',params)
+  },
+  // 新增素材
+  materialAdd:params=>{
+    return http.post('/material/batch/add',params)
+  },
+  // 素材重命名
+  materialRename:params=>{
+    return http.post('/material/rename',params)
+  },
+  // 素材删除
+  materialDel:params=>{
+    return http.post('/material/del',params)
+  },
+  // 素材移动
+  materialMove:params=>{
+    return http.post('/material/changeClassify',params)
+  },
+  // 素材批量删除
+  materialBatchDel:params=>{
+    return http.post('/material/batch/del',params)
+  },
+  // 素材批量移动
+  materialBatchMove:params=>{
+    return http.post('/material/batch/changeClassify',params)
+  },
+
+  // 图库、表格等模块单个保存至素材库
+  materialOtherSave:params=>{
+    return http.post('/material/saveAs',params)
+  },
+
+  // 我的图库批量保存至素材库
+  materialMyChartSave:params=>{
+    return http.post('/material/my_chart/saveAs',params)
+  }
+
+
+}

BIN
src/assets/img/smartReport/icon19.png


BIN
src/assets/img/smartReport/icon20.png


+ 152 - 0
src/components/UploadToMaterial.vue

@@ -0,0 +1,152 @@
+<template>
+  <el-dialog
+    :title="$t('ReportManage.Material.save_to_material')"
+    :visible.sync="show"
+    :modal-append-to-body="false"
+    :close-on-click-modal="false"
+    :center="true"
+    v-dialogDrag
+    custom-class="upload-material-dialog"
+    width="600px"
+    @close="handleClose"
+  >
+    <div class="dialog-main">
+      <el-form
+        ref="diaForm"
+        label-position="right"
+        label-width="80px"
+        :model="formData"
+        :rules="formRules"
+      >
+        <el-form-item :label="$t('Common.category')" prop="classify">
+          <el-cascader
+            v-model="formData.classify"
+            :options="classifyOpts"
+            :placeholder="$t('MsgPrompt.select_category')"
+            :props="{
+              checkStrictly: true,
+              emitPath: false,
+              value: 'ClassifyId',
+              label: 'ClassifyName',
+              children: 'Children',
+            }"
+            style="width: 100%"
+          ></el-cascader>
+        </el-form-item>
+        <el-form-item :label="$t('SystemManage.BaseConfig.resource_label01')" prop="name">
+          <el-input
+            v-model="formData.name"
+            :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="dia-bot">
+      <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+        ><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button
+      >
+      <el-button type="primary" plain @click="handleClose"
+        ><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  name: "UploadToMaterial",
+  model: {
+    prop: 'show',
+    event: 'showChange'
+  },
+  props: {
+    show: {
+      type: Boolean,
+      default: false
+    },
+    defaultName:'',
+    source:'',//来源chart图相关的,excel表格,sandbox逻辑图 , sa_doc文档对比
+    sourceId:0,
+  },
+  watch: {
+    show(n) {
+      if (n) {
+        this.formData.name=this.defaultName+this.$moment().format('YYYYMMDD')
+        this.getClassifyOpt()
+      }
+    }
+  },
+  data() {
+    return {
+      formRules: {
+        name: [
+          { required: true, message: this.$t('SystemManage.BaseConfig.resource_placeholder01'), trigger: 'blur' },
+        ],
+        classify: [
+          { required: true, message: this.$t('MsgPrompt.select_category'), trigger: 'change' },
+        ],
+      },
+      classifyOpts: [],
+      formData: {
+        classify: '',
+        name:''
+      }
+    }
+  },
+  methods: {
+    handleClose() {
+      this.formData.name=''
+      this.formData.classify=''
+      this.$emit('showChange', false)
+    },
+    saveHandle() {
+      this.$refs.diaForm.validate((valid) => {
+        if (valid) {
+          const params={
+            ClassifyId:this.formData.classify,
+            MaterialName:this.formData.name,
+            ObjectId:this.sourceId,
+            ObjectType:this.source
+          }
+          apiReportMaterial.materialOtherSave(params).then(res=>{
+            if(res.Ret!==200) return
+            this.$message.success(this.$t('MsgPrompt.saved_msg'))
+            this.handleClose()
+          })
+        }
+      })
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+
+<style lang="scss">
+.upload-material-dialog {
+  .el-cascader .el-input{
+    width: 100%;
+  }
+  .dia-bot {
+    margin: 30px auto;
+    text-align: center;
+  }
+}
+</style>

+ 24 - 0
src/components/chart/chartDetailHandlesWrap.vue

@@ -1,4 +1,5 @@
 <template>
+<div>
   <ul class="right-actions">
     <li>{{$t('Table.column_operations')}}</li>
     <li
@@ -72,11 +73,27 @@
     >
       <i class="el-icon-delete" style="color: #ff4040" />&nbsp;{{$t('Chart.chart_del_btn')}}
     </li>
+    <li class="span-item copy" v-if="isShowBtn('saveToMaterial')" @click="showUploadMaterial=true">
+      <i class="el-icon-folder-add"/>&nbsp;<!-- 保存为素材 -->{{$t('ReportManage.Material.save_to_material')}}
+    </li>
   </ul>
+  <!-- 上传素材库 -->
+  <uploadToMaterial 
+    v-model="showUploadMaterial"
+    source="chart"
+    :sourceId="chartInfo.ChartInfoId"
+    :defaultName="currentLang=='en'?chartInfo.ChartNameEn : chartInfo.ChartName"
+  />
+</div>
 </template>
 <script>
 export default {
   props: ['chartInfo','linkUrl'],
+  data() {
+    return {
+      showUploadMaterial:false,//显示上传至素材库
+    }
+  },
   methods: {
     copyChartConfirm(type) {
       this.$emit('copyChartConfirm',type)
@@ -117,6 +134,7 @@ export default {
             copyWechat:checkPermissionBtn(statisticPermission.corrAnalysis_copyWechat),
             enNameSetting:checkPermissionBtn(statisticPermission.corrAnalysis_enNameSetting),
             del:checkPermissionBtn(statisticPermission.corrAnalysis_del),
+            saveToMaterial:checkPermissionBtn(statisticPermission.corrAnalysis_saveToMaterial),
         }
         const fittingEquationMap = {
             share:checkPermissionBtn(statisticPermission.fittingEq_share),
@@ -128,6 +146,7 @@ export default {
             copyWechat:checkPermissionBtn(statisticPermission.fittingEq_copyWechat),
             enNameSetting:checkPermissionBtn(statisticPermission.fittingEq_enNameSetting),
             del:checkPermissionBtn(statisticPermission.fittingEq_del),
+            saveToMaterial:checkPermissionBtn(statisticPermission.fittingEq_saveToMaterial),
         }
         const statisticFeatureMap = {
             share:checkPermissionBtn(statisticPermission.statisticFeature_share),
@@ -139,6 +158,7 @@ export default {
             copyWechat:checkPermissionBtn(statisticPermission.statisticFeature_copyWechat),
             enNameSetting:checkPermissionBtn(statisticPermission.statisticFeature_enNameSetting),
             del:checkPermissionBtn(statisticPermission.statisticFeature_del),
+            saveToMaterial:checkPermissionBtn(statisticPermission.statisticFeature_saveToMaterial),
         }
         const priceLineMap = {
             share:checkPermissionBtn(productPricePermission.goodsPrice_priceLine_share),
@@ -150,6 +170,7 @@ export default {
             copyWechat:checkPermissionBtn(productPricePermission.goodsPrice_priceLine_copyWechat),
             enNameSetting:checkPermissionBtn(productPricePermission.goodsPrice_priceLine_enNameSetting),
             del:checkPermissionBtn(productPricePermission.goodsPrice_priceLine_del),
+            saveToMaterial:checkPermissionBtn(productPricePermission.goodsPrice_saveToMaterial),
         }
         const incomeLine = {
             share:checkPermissionBtn(productPricePermission.goodsPrice_incomeLine_share),
@@ -161,6 +182,7 @@ export default {
             copyWechat:checkPermissionBtn(productPricePermission.goodsPrice_incomeLine_copyWechat),
             enNameSetting:checkPermissionBtn(productPricePermission.goodsPrice_incomeLine_enNameSetting),
             del:checkPermissionBtn(productPricePermission.goodsPrice_incomeLine_del),
+            saveToMaterial:checkPermissionBtn(productPricePermission.goodsPrice_saveToMaterial),
         }
 
          const crossVarietyBtnMap = {
@@ -173,6 +195,7 @@ export default {
             copyWechat:checkPermissionBtn(statisticPermission.crossVariety_copyWechat),
             enNameSetting:checkPermissionBtn(statisticPermission.crossVariety_enNameSetting),
             del:checkPermissionBtn(statisticPermission.crossVariety_del),
+            saveToMaterial:checkPermissionBtn(statisticPermission.crossVariety_saveToMaterial),
         }
 
         const rangeAnalysisBtnMap = {
@@ -184,6 +207,7 @@ export default {
             copyOffice:checkPermissionBtn(statisticPermission.rangeAnalysis_copyOffice),
             copyWechat:checkPermissionBtn(statisticPermission.rangeAnalysis_copyWechat),
             del:checkPermissionBtn(statisticPermission.rangeAnalysis_del),
+            saveToMaterial:checkPermissionBtn(statisticPermission.rangeAnalysis_saveToMaterial),
         }
         
         const positonAnalysisBtnMap = {

+ 21 - 2
src/components/chart/chartListTableWrap.vue

@@ -28,9 +28,9 @@
                 <el-button type="text" v-if="isShowBtn('refresh')" @click="handleRefresh(row)">{{
                   $t("Table.refresh_btn")
                 }}</el-button>
-                <el-button type="text" v-if="isShowBtn('otherSave')" @click="handleSaveOther(row)">{{
+                <!-- <el-button type="text" v-if="isShowBtn('otherSave')" @click="handleSaveOther(row)">{{
                   $t("Table.save_as")
-                }}</el-button>
+                }}</el-button> -->
                 <el-button
                   type="text"
                   style="color: #f00"
@@ -38,6 +38,21 @@
                   v-if="isShowBtn('del')"
                   >{{$t("Table.delete_btn")}}</el-button
                 >
+                <el-dropdown size="medium" placement="bottom-start">
+                  <span class="el-dropdown-link">
+                    <i class="el-icon-more el-icon--right"></i>
+                    <el-dropdown-menu slot="dropdown">
+                      <el-dropdown-item>
+                        <el-button type="text" v-if="isShowBtn('otherSave')" @click="handleSaveOther(row)">{{
+                          $t("Table.save_as")
+                        }}</el-button>
+                      </el-dropdown-item>
+                      <el-dropdown-item>
+                        <el-button type="text" @click="handleShowSaveMaterial(row)">{{$t('ReportManage.Material.save_to_material')}}</el-button>
+                      </el-dropdown-item>
+                    </el-dropdown-menu>
+                  </span>
+                </el-dropdown>
               </span>
               <span
                 v-else-if="['CreateTime', 'ModifyTime'].includes(opt.colKey)"
@@ -130,6 +145,10 @@ export default {
       this.$emit('deleteChart', e)
     },
 
+    handleShowSaveMaterial(e){
+      this.$emit('saveToMaterial',e)
+    },
+
     formatTime(t) {
       return moment(t).format('YYYY-MM-DD HH:mm:ss')
     },

+ 4 - 0
src/lang/commonLang.js

@@ -482,6 +482,10 @@ export default {
       en: 'No',
       zh: '否'
     },
+    move_btn:{
+      en:'move',
+      zh:'移动'
+    },
     batch_add: {
       en: 'Batch Add',
       zh: '批量添加'

+ 43 - 0
src/lang/modules/ReportManagement/Material.js

@@ -0,0 +1,43 @@
+/**
+ * 研报管理--素材库
+ */
+
+/* 英文 */
+export const MaterialEn = {
+  img_count: "Total of {limit} images",
+  select_img_count:"{limit}images selected",
+  cancel_batch_btn:'Cancel Batch',
+  del_attention:'Once deleted, it cannot be recovered. Are you sure you want to delete?',
+  move_to:'Move Category',
+  upload_tips:'Please note: You can select a maximum of 10 images at a time, each image should not exceed 5MB, and we support formats such as JPG, JPEG, PNG, etc.', 
+  save_to_material:'Save as Material',
+  batch_save_to_material:'Batch Save Materials',
+  add_select_chart:'Add to Selected Charts',
+  select_chart:'Selected Chart',
+  img_material:'Image Material',
+  img_name_has:'image name repeat',
+  material_name:'Material Library',
+
+
+
+};
+
+/* 中文 */
+export const MaterialZh = {
+  img_count: "共{limit}张图片",
+  select_img_count:"已选择{limit}张图片",
+  cancel_batch_btn:'取消批量',
+  del_attention:'删除后不可恢复,是否确定删除?',
+  move_to:'移动分类',
+  upload_tips:'注:单次最多选择10张图片,每张图片不超过5MB,支持jpg、jpeg、png等格式',
+  save_to_material:'保存为素材',
+  batch_save_to_material:'批量保存素材',
+  add_select_chart:'加入已选图表',
+  select_chart:'已选图表',
+  img_material:'图片素材',
+  img_name_has:'图片名称已存在',
+  material_name:'素材库',
+
+};
+
+// $t('ReportManage.Material.xxx')

+ 6 - 6
src/lang/modules/ReportManagement/ReportList.js

@@ -226,7 +226,7 @@ export const ReportListZh = {
   author_select_ipt: "请填写作者",
   frequency_select: "频度",
   creation_time_select: "创建时间",
-  insert_chart_tabs: "图表插入",
+  insert_chart_tabs: "图表",
   chart_inventory_radio: "图库",
   price_curve_radio: "商品价格曲线",
   related_charts_radio: "相关性图表",
@@ -234,12 +234,12 @@ export const ReportListZh = {
   statistical_feature_radio: "统计特征",
   intercommodity_analysis_radio: "跨品种分析",
   just_mine_radio: "只看我的",
-  insert_sandbox_tabs: "沙盘插入",
+  insert_sandbox_tabs: "逻辑图",
   no_sandbox_msg: "沙盘名称/品种",
   insert_table_tabs: "表格插入",
   table_name_tabs: "表格名称",
-  bulk_insertion_tabs: "我的图库批量插入",
-  semantic_analysis_tabs: "语义分析插入",
+  bulk_insertion_tabs: "我的图库",
+  semantic_analysis_tabs: "语义分析",
   publish_time: "发送时间",
   select_date_and_time: "选择日期时间",
   the_report_will_be_posted_on_time: "设置成功之后,研报将定时进行发送",
@@ -250,10 +250,10 @@ export const ReportListZh = {
   chart_name: "图表名称",
   select_date: "选择日期",
   charts_update_btn: "图表刷新",
-  library_top_type: "版图资源库",
+  library_top_type: "版图设置",
   eta_top_type: "表格",
   statistical_top_type: "统计分析",
-  sandbox_top_type: "沙盘图",
+  sandbox_top_type: "逻辑图",
   semantic_top_type: "语义分析",
   chart_top_type: "图库",
   insert_charts_msg: "请插入图表",

+ 3 - 1
src/lang/modules/ReportManagement/indexEn.js

@@ -5,6 +5,7 @@ import { SmartReportEn } from "./SmartReport";
 import { CategoryListEn } from "./CategoryList";
 import { ReportListEn } from "./ReportList";
 import { ReportExternalEn } from './ReportExternal'
+import {MaterialEn} from './Material'
 
 export default {
   ReportManage: {
@@ -21,6 +22,7 @@ export default {
     ...SmartReportEn,
     CategoryList: CategoryListEn,
     ReportList: ReportListEn,
-    ReportExternal: ReportExternalEn
+    ReportExternal: ReportExternalEn,
+    Material:MaterialEn
   },
 };

+ 3 - 1
src/lang/modules/ReportManagement/indexZh.js

@@ -6,6 +6,7 @@ import { SmartReportZh } from "./SmartReport";
 import { CategoryListZh } from "./CategoryList";
 import { ReportListZh } from "./ReportList";
 import { ReportExternalZh } from './ReportExternal'
+import {MaterialZh} from './Material'
 
 export default {
   ReportManage: {
@@ -22,6 +23,7 @@ export default {
     ...SmartReportZh,
     CategoryList: CategoryListZh,
     ReportList: ReportListZh,
-    ReportExternal: ReportExternalZh
+    ReportExternal: ReportExternalZh,
+    Material:MaterialZh
   },
 };

+ 1 - 1
src/lang/modules/Slides/pptPresent.js

@@ -130,7 +130,7 @@ export const presentZh = {
   intercommodity_analysis: "跨品种分析",
   show_only_mine: "只看我的",
   sandbox_name_category: "沙盘名称/品种",
-  sandbox_name: "沙盘",
+  sandbox_name: "逻辑图",
   table_name: "表格",
   table_analysis_semantic: "语义分析插入",
   table_name_input: "表格名称",

+ 20 - 0
src/mixins/index.js

@@ -4,6 +4,7 @@
 import http from "api/http.js";
 import {apiDownloadResource} from '@/api/modules/oldApi'
 import {Message} from "element-ui"
+import { departInterence} from "api/api.js";
 const mixins = {
 	filters: {
 		// 显示时间为 2021.07.22 
@@ -212,6 +213,25 @@ const mixins = {
 				'手':this.$i18nt.t('Edb.UnitAll.u_hand'),
 			}
 			return map[unit]||unit //若是自行输入的单位,直接返回
+		},
+		// 报告、ppt中插入内容根据菜单判断用户是否有权限
+		verifyInsertModuleAuth(path){
+			// 如果没传path就默认有吧
+			if(!path) return true
+			const menuStr=sessionStorage.getItem('MenuList')||localStorage.getItem('MenuList')
+			let menuData=JSON.parse(menuStr)||[]
+			if(menuData.length===0) return false
+			let pathArr=[]
+			menuData.forEach(item=>{
+				if(item.children){
+					item.children.forEach(_item=>{
+						pathArr.push(_item.path)
+					})
+				}else{
+					pathArr.push(item.path)
+				}
+			})
+			return pathArr.includes(path)
 		}
 	}
 }

+ 8 - 0
src/routes/modules/oldRoutes.js

@@ -235,6 +235,14 @@ export default [
           name_en:"Document Management Library"
         }
       },
+      {
+        path: 'materialList',
+        name:'素材库',
+        component: () => import("@/views/report_manage/material/list.vue"),
+        meta:{
+          name_en:"Material Library"
+        }
+      },
     ],
   },
 

+ 32 - 1
src/utils/buttonConfig.js

@@ -455,6 +455,9 @@ export const chartLibPermission = {
     chartLib_uploadToForum:'chartLib:uploadToForum',//上传至社区
     chartLib_updateToForum:'chartLib:updateToForum',//同步至社区
     chartLib_withdrawfromForum:'chartLib:withdrawfromForum',//从社区撤回
+
+    chartLib_saveToMaterial:'chartLib:saveToMaterial',//保存为素材
+
 }
 
 /*
@@ -483,6 +486,9 @@ export const myETAPermission = {
     myChart_classifyOpt_edit:'myChart:classifyOpt:edit',//添加我的分类
     myChart_classifyOpt_rename:'myChart:classifyOpt:rename',//重命名
     myChart_classifyOpt_delete:'myChart:classifyOpt:delete',//删除
+
+    myChart_batchSaveToMaterial:'myChart:batchSaveToMaterial',//批量保存素材
+    myChart_saveToMaterial:'myChart:saveToMaterial',//保存素材
 }
 //图库框架
 export const chartFramePermission={
@@ -519,6 +525,7 @@ export const etaTablePermission = {
     etaTable_customize_mix_download:'etaTable:customize:mix:download',//下载
     etaTable_customize_mix_save:'etaTable:customize:mix:save',//保存
     etaTable_customize_mix_del:'etaTable:customize:mix:del',//删除
+    etaTable_customize_mix_saveToMaterial:'etaTable:customize:mixSheet:saveToMaterial',
 
     //数据表格页面
     etaTable_customize_data_sheetAdd: 'etaTable:customize:data:sheetAdd',//添加数据表格按钮
@@ -530,6 +537,7 @@ export const etaTablePermission = {
     etaTable_customize_data_download:'etaTable:customize:data:download',//下载
     etaTable_customize_data_del:'etaTable:customize:data:del',//删除
     etaTable_customize_data_save:'etaTable:customize:data:save',//保存
+    etaTable_customize_data_saveToMaterial:'etaTable:customize:data:saveToMaterial',//保存为素材
 
     /*-----------excel表格页面--------- */
     etaTable_excel:'etaTable:excel',//添加Excel表格这个按钮显示不显示
@@ -539,6 +547,7 @@ export const etaTablePermission = {
     etaTable_excel_download:'etaTable:excel:download',
     etaTable_excel_save:'etaTable:excel:save',//保存
     etaTable_excel_edit:'etaTable:excel:edit',
+    etaTable_excel_saveToMaterial:'etaTable:commonShare:saveToMaterial',
 
     //自定义分析表格页面
     // etaTable_analysis_sheetAdd: 'etaTable:analysis:sheetAdd',//添加数据表格按钮
@@ -576,6 +585,7 @@ export const sandboxPermission = {
     sandbox_classify_move:'sandbox:classify:move',//分类操作:移动
     sandbox_classify_del:'sandbox:classify:del',//分类操作:删除
     sandbox_classify_addEdit:'sandbox:classify:addEdit',//分类操作:添加/编辑
+    sandbox_saveToMaterial:'sandbox:saveToMaterial',//保存为素材
 }
 /*
  * --------------------------------------------------------------------------语义分析------------------------------------------------
@@ -594,6 +604,7 @@ export const semanticPermission = {
     saPage_delete:'saPage:delete',//删除对比文档
     saPage_classifyOpt_edit:'saPage:classifyOpt:edit',//添加编辑分类
     saPage_classifyOpt_delete:'saPage:classifyOpt:delete',//删除分类
+    saPage_saveToMaterial:'saPage:saveToMaterial',//保存为素材
     /*-----------标签管理--------- */
     tagPage_del:'tagPage:del',
     tagPage_save:'tagPage:save',//添加编辑标签
@@ -655,6 +666,7 @@ export const statisticPermission = {
     corrAnalysis_refresh:'corrAnalysis:refresh',
     corrAnalysis_addMyChart:'corrAnalysis:addMyChart',
     corrAnalysis_share:'corrAnalysis:share',
+    corrAnalysis_saveToMaterial:'corrAnalysis:saveToMaterial',//保存为素材
 
     /*-----------统计特征--------- */
     statisticFeature_addChart:'statisticFeature:addChart',//添加图表按钮
@@ -671,6 +683,7 @@ export const statisticPermission = {
     statisticFeature_refresh:'statisticFeature:refresh',
     statisticFeature_addMyChart:'statisticFeature:addMyChart',
     statisticFeature_share:'statisticFeature:share',
+    statisticFeature_saveToMaterial:'statisticFeature:saveToMaterial',//保存为素材
 
     /*-----------拟合方程曲线--------- */
     fittingEq_addChart:'fittingEq:addChart',//添加图表按钮
@@ -687,6 +700,7 @@ export const statisticPermission = {
     fittingEq_refresh:'fittingEq:refresh',
     fittingEq_addMyChart:'fittingEq:addMyChart',
     fittingEq_share:'fittingEq:share',
+    fittingEq_saveToMaterial:'fittingEq:saveToMaterial',//保存为素材
 
     /* 跨品种分析 */
     crossVariety_addChart:'crossVariety:addChart',//添加图表按钮
@@ -705,6 +719,7 @@ export const statisticPermission = {
     crossVariety_refresh:'crossVariety:refresh',
     crossVariety_addMyChart:'crossVariety:addMyChart',
     crossVariety_share:'crossVariety:share',
+    crossVariety_saveToMaterial:'crossVariety:saveToMaterial',//保存为素材
 
     /* 区间分析 */
     rangeAnalysis_addChart:'rangeAnalysis:addChart',
@@ -721,6 +736,7 @@ export const statisticPermission = {
     rangeAnalysis_refresh:'rangeAnalysis:refresh',
     rangeAnalysis_addMyChart:'rangeAnalysis:addMyChart',
     rangeAnalysis_share:'rangeAnalysis:share',
+    rangeAnalysis_saveToMaterial:'rangeAnalysis:saveToMaterial',//保存为素材
 }
 /*
  * --------------------------------------------------------------------------供应分析------------------------------------------------
@@ -741,6 +757,7 @@ export const productPricePermission = {
     goodsPrice_classifyOpt_delete:'goodsPrice:classifyOpt:delete',//删除分类
     goodsPrice_onlyMine:'goodsPrice:onlyMine',//只看我的
     goodsPrice_editLimit:'goodsPrice:editLimit',//编辑上下限
+    goodsPrice_saveToMaterial:'goodsPrice:saveToMaterial',//保存为素材
     /* 利润曲线 */
     goodsPrice_incomeLine_del:'goodsPrice:incomeLine:del',
     goodsPrice_incomeLine_enNameSetting:'goodsPrice:incomeLine:enNameSetting',
@@ -949,6 +966,19 @@ export const BIBoardPermission = {
     BIBoard_refresh:'BI:refresh',//
 }
 
+/* 素材库配置 */
+export const reportMaterialPermission = {
+    material_list:'materialList:list',//
+    material_upload:'materialList:upload',//
+    material_rename:'materialList:rename',//
+    material_move:'materialList:move',//
+    material_download:'materialList:download',//
+    material_del:'materialList:del',//
+    material_batchEdit:'materialList:batchEdit',
+    material_classify_add:'materialList:addClassify',
+    material_classify_del:'materialList:delClassify',
+    material_classify_move:'materialList:moveClassify',
+}
 /* AI预测模型 */
 export const AIPredictPermission = {
     AIPredict_add:'aiPredict:add',//添加
@@ -978,7 +1008,8 @@ const btnMap  = {
     toolBoxPermission,
     reportExternalPermission,
     BIBoardPermission,
-    AIPredictPermission
+    reportMaterialPermission,
+    AIPredictPermission,
 }
 
 /**

+ 4 - 0
src/utils/registryComponents.js

@@ -54,3 +54,7 @@ Vue.component('chartTypeSelect',chartTypeSelect)
 // 级联选择器多语言展示
 import cascader from '@/components/edb/cascader.vue';
 Vue.component('cascader',cascader)
+
+// 保存为素材弹窗
+import uploadToMaterial from '@/components/UploadToMaterial.vue'
+Vue.component('uploadToMaterial',uploadToMaterial)

+ 1 - 0
src/views/Home.vue

@@ -801,6 +801,7 @@ export default {
         if (res.Ret === 200) {
           this.navlists = res.Data.List.length ? res.Data.List : [];
           sessionStorage.setItem("MenuList", JSON.stringify(this.navlists));
+          localStorage.setItem("MenuList", JSON.stringify(this.navlists));
           /* 是否有数据报表权限 */
           let bool_data = this.navlists.some((item) => {
             return item.name === "数据报表";

+ 17 - 1
src/views/dataEntry_manage/chartSetting.vue

@@ -690,7 +690,13 @@
                         <img style="width: 16px;vertical-align: middle" :src="$icons.withdraw_from_forum" />&nbsp;<!-- 从社区撤回 -->{{$t('Chart.withdraw_from_forum')}}
                       </li>
                       </template>
-                      
+                      <li 
+                        class="span-item copy"
+                        @click="showUploadMaterial=true"
+                        v-permission="permissionBtn.chartLibPermission.chartLib_saveToMaterial"
+                      >
+                        <i class="el-icon-folder-add"/>&nbsp;<!-- 保存为素材 -->{{$t('ReportManage.Material.save_to_material')}}
+                      </li>
                   </ul>
                 </el-col>
               </el-row>
@@ -899,6 +905,14 @@
             >{{ $t('Dialog.confirm_btn')}}</el-button>
         </div>
     </el-dialog>
+
+    <!-- 上传素材库 -->
+    <uploadToMaterial 
+      v-model="showUploadMaterial"
+      source="chart"
+      :sourceId="chartInfo.ChartInfoId"
+      :defaultName="currentLang=='en'?chartInfo.ChartNameEn : chartInfo.ChartName"
+    />
   </div>
 </template>
 
@@ -1029,6 +1043,8 @@ export default {
 
       showUploadToForum:false,//显示上传至社区弹窗
       uploadToForumIntro:'',//上传至社区简述
+
+      showUploadMaterial:false,//显示上传至素材库
     };
   },
   watch: {

+ 18 - 13
src/views/datasheet_manage/components/BalanceTable.vue

@@ -963,19 +963,21 @@ export default {
       const item=this.sheetOpts.filter(e=>e.ExcelInfoId===this.activeSheetId)[0]
       // console.log(item);
       // console.log(this.sheetOpts,this.activeSheetId);
-
-      // let canvas = await html2canvas(document.getElementsByClassName('table')[0],{
-      //   scale:2,
-      //   useCORS: true,
-      //   backgroundColor:null,
-      //   imageTimeout:0,
-      //   allowTaint:true,
-      // })
-      // let imagesrc = canvas.toDataURL('image/png');
-      // const formData = new FormData();
-      // formData.append('Image',imagesrc);
-      // const { Data } = await dataBaseInterface.uploadImg(formData)
-
+      let ExcelImage=''
+      if(type==='manualSave'){
+        let canvas = await html2canvas(document.getElementsByClassName('table')[0],{
+          scale:2,
+          useCORS: true,
+          backgroundColor:null,
+          imageTimeout:0,
+          allowTaint:true,
+        })
+        let imagesrc = canvas.toDataURL('image/png');
+        const formData = new FormData();
+        formData.append('Image',imagesrc);
+        const { Data } = await dataBaseInterface.uploadImg(formData)
+        ExcelImage=Data.ResourceUrl
+      }
       if(!this.activeSheetId) return
       const params={
         ExcelInfoId:this.activeSheetId,
@@ -987,6 +989,9 @@ export default {
         ParentId:Number(this.parentSheetId),
         TableData: this.getSaveParams()
       }
+      if(ExcelImage){
+        params.ExcelImage=ExcelImage
+      }
       const res = await sheetInterface.sheetEdit(params)
       if(res.Ret !==200) return false
       if(res.Data.Status==1){//有人在编辑 不允许编辑返回到列表

+ 14 - 0
src/views/datasheet_manage/sheetList.vue

@@ -217,6 +217,10 @@
                 <span class="author">{{$t('OnlineExcelPage.author_info')}}{{ sheetDetailInfo.SysUserRealName }}</span>
                 <ul class="action-ul">
                   <li style="color:#999999 ;">{{$t('OnlineExcelPage.recent_save_time_info')}}{{ saveTime }}</li>
+                  <li class="editsty" v-if="isSheetBtnShow('saveToMaterial')" @click="showUploadMaterial=true">
+                    <i class="el-icon-folder-add"/>
+                    <!-- 保存为素材 --><span>{{$t('ReportManage.Material.save_to_material')}}</span>
+                  </li>
                   <li
                     class="editsty"
                     @click="goEditHandle"
@@ -448,6 +452,14 @@
         >
       </div>
     </m-dialog>
+
+    <!-- 上传素材库 -->
+    <uploadToMaterial 
+      v-model="showUploadMaterial"
+      source="excel"
+      :sourceId="sheetDetailInfo.ExcelInfoId"
+      :defaultName="sheetDetailInfo.ExcelName"
+    />
   </div>
 </template>
 
@@ -570,6 +582,8 @@ export default {
       },
       balanceClassifyOpts:[],//平衡表分类数据
 
+      showUploadMaterial:false,//显示上传至素材库
+
     };
   },
   watch: {

+ 16 - 0
src/views/intervalAnalysis/list.vue

@@ -362,6 +362,7 @@
           @detailShowHandle="detailShowHandle"
           @addMychartHandle="addMychartHandle"
           @edit="editChartHandle"
+          @saveToMaterial="handleShowUploadToMaterial"
         />
       </div>
     </div>
@@ -402,6 +403,14 @@
       @dateBack="dataChangeBack"
       :isSeasonChart= "chartInfo && chartInfo.ChartType === 2"
     />
+
+    <!-- 上传素材库 -->
+    <uploadToMaterial 
+      v-model="showUploadMaterial"
+      source="chart"
+      :sourceId="uploadToMaterialData.ChartInfoId"
+      :defaultName="currentLang=='en'?uploadToMaterialData.ChartNameEn : uploadToMaterialData.ChartName"
+    />
   </div>
 </template>
 
@@ -469,9 +478,16 @@ export default {
       add_chart_id: 0, //要加入的图表
       add_ids: [],//加入时已有的分类
 
+      showUploadMaterial:false,//显示上传至素材库
+      uploadToMaterialData:{},
     };
   },
   methods: {
+    // 显示保存到素材库
+    handleShowUploadToMaterial(e){
+      this.uploadToMaterialData=e
+      this.showUploadMaterial=true
+    },
 
     /* 添加图表 */
     goAddChart() {

+ 422 - 0
src/views/mychart_manage/components/BatchSaveToMaterial.vue

@@ -0,0 +1,422 @@
+<template>
+  <el-dialog
+    :title="$t('ReportManage.Material.save_to_material')"
+    :visible.sync="show"
+    :modal-append-to-body="false"
+    :close-on-click-modal="false"
+    :center="true"
+    v-dialogDrag
+    custom-class="upload-material-dialog"
+    @close="handleClose"
+    width="900px"
+  >
+    <div class="dialog-main">
+      <div class="choose-chart-wrap" v-show="step === 1">
+        <div class="left-wrap">
+          <el-input
+            v-model="chartData.searchVal"
+            :placeholder="$t('Chart.search_chart_placeholder')"
+            style="margin-bottom: 10px"
+            @change="handleSearch"
+          ></el-input>
+          <el-table
+            :data="chartData.list"
+            border
+            @select="selectHandle"
+            @select-all="selectAllHandle"
+            ref="edbDataRef"
+            height="500px"
+            v-loading="chartData.listLoading"
+          >
+            <el-table-column type="selection" min-width="50" align="center" />
+            <el-table-column
+              :label="$t('Chart.Detail.chart_name')"
+              show-overflow-tooltip
+              align="center"
+              :prop="$chart_lang === 'en' ? 'ChartNameEn' : 'ChartName'"
+            />
+          </el-table>
+          <m-page
+            style="position: absolute; top: 100%; left: 0"
+            class="table-page"
+            v-show="chartData.total"
+            :total="chartData.total"
+            :pageSize="chartData.pageSize"
+            :page_no="chartData.page"
+            :pagercount="5"
+            @handleCurrentChange="pageNumberChange"
+          />
+        </div>
+        <div style="padding-top: 200px; margin: 0 30px">
+          <el-button type="primary" @click="handleAddChart">
+            <!-- 加入已选图表 -->
+            {{$t('ReportManage.Material.add_select_chart')}}
+          </el-button>
+        </div>
+        <div class="right-wrap">
+          <div style="height: 50px">
+            {{$t('ReportManage.Material.select_chart')}}:{{ chartData.addList.length }}
+          </div>
+          <el-table :data="chartData.addList" border height="500px">
+            <el-table-column
+              :label="$t('Chart.Detail.chart_name')"
+              show-overflow-tooltip
+              align="center"
+              :prop="$chart_lang === 'en' ? 'ChartNameEn' : 'ChartName'"
+            />
+            <el-table-column width="50px" align="center">
+              <template slot="header" slot-scope="scope">
+                <img
+                  @click="handleDelSelect('all')"
+                  style="width: 15px; height: 15px; cursor: pointer"
+                  src="~@/assets/img/ai_m/delete.png"
+                  alt=""
+                />
+              </template>
+              <template slot-scope="scope">
+                <img
+                  @click="handleDelSelect(scope)"
+                  style="width: 15px; height: 15px; cursor: pointer"
+                  src="~@/assets/img/ai_m/delete.png"
+                  alt=""
+                />
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </div>
+      <div class="upload-list-wrap" v-show="step===2">
+        <el-table :data="uploadList" border height="500px">
+          <el-table-column :label="$t('ReportManage.Material.img_material')" align="center">
+            <template slot-scope="scope">
+              <el-image
+                style="width: 100px; height: 100px"
+                :src="scope.row.imgUrl"
+                :preview-src-list="[scope.row.imgUrl]"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column :label="$t('SystemManage.BaseConfig.resource_label01')" align="center">
+            <template slot-scope="scope">
+              <el-input
+                v-model="scope.row.imgName"
+                :placeholder="$t('EtaBasePage.metric_name_input')"
+                style="width: 100%"
+              />
+              <span 
+                v-if="repeatList.includes(scope.row.MyChartId)" 
+                style="color:#f00;font-size:12px"
+              >{{$t('ReportManage.Material.img_name_has')}}</span>
+            </template>
+          </el-table-column>
+          <el-table-column align="center" width="300px">
+            <template slot="header" slot-scope="scope">
+              <span style="margin-right: 40px; display: inline-block">
+                <!-- 目录 -->{{ $t("EtaBasePage.catalogue_directory") }}</span
+              >
+              <el-radio-group
+                v-model="classifyType"
+                @change="handleClassifyTypeChange"
+              >
+                <el-radio :label="0"
+                  ><!-- 分目录 -->{{
+                    $t("EtaBasePage.subdirectory_radio")
+                  }}</el-radio
+                >
+                <el-radio :label="1"
+                  ><!-- 同目录 -->{{
+                    $t("EtaBasePage.directory_radio")
+                  }}</el-radio
+                >
+              </el-radio-group>
+            </template>
+            <template slot-scope="{ row, $index }">
+              <el-cascader
+                v-model="row.classifyId"
+                :options="classifyOpts"
+                placeholder="请选择分类"
+                :props="{
+                  checkStrictly: true,
+                  emitPath: false,
+                  value: 'ClassifyId',
+                  label: 'ClassifyName',
+                  children: 'Children',
+                }"
+                style="width: 100%"
+                :disabled="classifyType === 1 && $index > 0"
+                @change="handleClassifyChange(row, $index)"
+              ></el-cascader>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+    <div class="dia-bot" v-if="step === 1">
+      <el-button type="primary" plain @click="handleClose"
+        ><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button
+      >
+      <el-button type="primary" @click="handleNextStep"
+        ><!-- 下一步 -->{{ $t("Dialog.next_step") }}</el-button
+      >
+    </div>
+    <div class="dia-bot" v-else>
+      <el-button type="primary" plain @click="step = 1"
+        ><!--上一步 -->{{ $t("Dialog.prev_step") }}</el-button
+      >
+      <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+        ><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import mPage from '@/components/mPage.vue'
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+import { mychartInterface } from '@/api/api.js';
+const MAXAddNUM = 30//最大添加个数
+export default {
+  name: "BatchSaveToMaterial",
+  model: {
+    prop: 'show',
+    event: 'showChange'
+  },
+  components: { mPage },
+  props: {
+    show: {
+      type: Boolean,
+      default: false
+    },
+    classifId: {
+      type: Number,
+      default: 0
+    },
+  },
+  watch: {
+    show(n) {
+      if (n) {
+        this.getClassifyOpt()
+        this.getChartList()
+      }
+    }
+  },
+  data() {
+    return {
+      chartData: {
+        searchVal: '',
+        list: [],
+        page: 1,
+        pageSize: 20,
+        total: 0,
+        loading: false,
+        selectList: [],
+        addList: [],//添加到已选列表的图表
+      },
+
+      uploadList: [],//要上传到素材库的
+
+      repeatList:[],//保存时错误的素材
+
+      step: 1,
+      classifyOpts: [],
+      classifyType: 0,
+    }
+  },
+  methods: {
+    handleSearch(){
+      this.chartData.page=1
+      this.getChartList()
+    },
+    async getChartList() {
+      const res = await mychartInterface.myList({
+        PageSize: this.chartData.pageSize,
+        CurrentIndex: this.chartData.page,
+        Keyword: this.chartData.searchVal
+      })
+      if (res.Ret !== 200) return
+      this.chartData.list = res.Data.List || []
+      this.chartData.total = res.Data.Paging.Totals
+      this.setTableSelectItem()
+    },
+
+    // 设置表格选中态
+    setTableSelectItem(){
+      const arr=[...this.chartData.selectList,...this.chartData.addList]
+      this.chartData.list.forEach(item=>{
+        if(arr.some(_i=>_i.ChartInfoId===item.ChartInfoId)){
+          console.log(item);
+          setTimeout(()=>{
+            this.$refs.edbDataRef.toggleRowSelection(item,true)
+          },10)
+        }
+      })
+    },
+
+    selectionChange(selection) {
+      // console.log('selection',selection);
+      this.chartData.selectList = [...this.chartData.selectList,...selection]
+    },
+    selectHandle(selection,row){
+      // console.log('selection',selection);
+      if(selection.some(it => it.ChartInfoId == row.ChartInfoId)){//勾选
+        this.chartData.selectList.push(row)
+      }else{
+        this.chartData.selectList=this.chartData.selectList.filter(it => it.ChartInfoId!=row.ChartInfoId)
+      }
+    },
+    selectAllHandle(selection){
+      if(selection.length>0){//全选
+        this.chartData.selectList = [...this.chartData.selectList,...selection]
+      }else{
+        this.chartData.selectList=this.chartData.selectList.filter(it => this.chartData.list.some(i=>i.ChartInfoId===it.ChartInfoId))
+      }
+    },
+    pageNumberChange(e) {
+      this.chartData.page = e
+      this.getChartList()
+    },
+    handleAddChart() {
+      if (this.chartData.selectList.length === 0) {
+        this.$message.warning('请选择图表')
+        return
+      }
+      if (this.chartData.addList.length >= MAXAddNUM) {
+        this.$message.warning(/* "已达批量添加指标数量上限"  */this.$t('EtaBasePage.limit_indicators_msg'))
+        return
+      }
+      this.chartData.selectList.forEach(item => {
+        if (!this.chartData.addList.some(_i => _i.ChartInfoId === item.ChartInfoId) && this.chartData.addList.length < 30) {
+          this.chartData.addList.push(item)
+        }
+      });
+
+    },
+    handleDelSelect(e) {
+      if (e === 'all') {
+        this.chartData.addList = []
+        return
+      }
+      const index = e.$index
+      this.chartData.addList.splice(index, 1)
+    },
+
+    // 跳转下一步
+    handleNextStep() {
+      if (this.chartData.addList.length === 0) {
+        this.$message.warning('请至少选择一张图表!')
+        return
+      }
+      this.uploadList = this.chartData.addList.map(item => {
+        return {
+          imgUrl: item.ChartImage,
+          chartInfoId: item.ChartInfoId,
+          imgName: `${this.$store.state.lang == 'en' ? item.ChartName : item.ChartNameEn}${this.$moment().format('YYYYMMDD')}`,
+          classifyId: '',
+          MyChartId:item.MyChartId
+        }
+      })
+      this.repeatList=[]
+      this.step = 2
+    },
+
+    // 同目录修改
+    handleClassifyChange(e, index) {
+      if (this.classifyType === 1) {
+        // 修改所有的指标的目录为第一个
+        this.uploadList.forEach(item => {
+          item.classifyId = e.classifyId
+        })
+      }
+    },
+    handleClassifyTypeChange() {
+      this.handleClassifyChange(this.uploadList[0])
+    },
+
+    handleClose() {
+      this.chartData = {
+        searchVal: '',
+        list: [],
+        page: 1,
+        pageSize: 20,
+        total: 0,
+        loading: false,
+        selectList: [],
+        addList: [],//添加到已选列表的图表
+      }
+      this.uploadList=[]
+      this.repeatList=[]
+      this.step=1
+      this.$emit('showChange', false)
+    },
+    async saveHandle() {
+      const arr=this.uploadList.map(item=>{
+        return {
+          MyChartId:item.MyChartId,
+          MaterialName:item.imgName,
+          ChartInfoId:item.chartInfoId,
+          ClassifyId:item.classifyId
+        }
+      })
+      console.log('保存的数据',arr);
+      let isEnough = arr.every(item => item.MaterialName&&item.ClassifyId)
+      if(!isEnough) return this.$message.warning(/*'请填写完整信息'*/ this.$t('EtaBasePage.complete_information_msg'));
+
+      const res=await apiReportMaterial.materialMyChartSave({
+        MaterialList:arr
+      })
+
+      if(res.Ret===200){
+        this.$message.success('保存成功')
+        this.handleClose()
+      }else{
+        const arr=res.Data.ExistList||[]
+        this.repeatList=[]
+        arr.forEach(i=>{
+          this.repeatList.push(i.MyChartId)
+        })
+      }
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+
+<style lang="scss">
+.upload-material-dialog {
+  .el-cascader .el-input {
+    width: 100%;
+  }
+  .choose-chart-wrap {
+    display: flex;
+    .left-wrap {
+      flex: 1;
+      position: relative;
+      padding-bottom: 5px;
+    }
+    .right-wrap {
+      flex: 1;
+    }
+  }
+  .dia-bot {
+    margin: 60px auto;
+    text-align: center;
+  }
+}
+</style>

+ 18 - 1
src/views/mychart_manage/components/chartDetailDia.vue

@@ -64,6 +64,13 @@
               </div>
             </div>
             <div class="top-right" v-if="chartInfo.Button">
+              <span 
+                class="span-item" 
+                @click="showUploadMaterial=true"
+                v-permission="permissionBtn.myETAPermission.myChart_saveToMaterial"
+              >
+                <i class="el-icon-folder-add"/><!-- 保存为素材 -->{{$t('ReportManage.Material.save_to_material')}}
+              </span>
               <span v-permission="permissionBtn.myETAPermission.myChart_move"
                   class="collected" @click="removeMychart(chartInfo)" v-if="classifyUserId === roleId">
                 <i class="el-icon-remove-outline"></i><!-- 移出 -->{{$t('Chart.chart_remove_btn')}}
@@ -487,6 +494,14 @@
 			@cancel="isLangInfoDia=false" 
 			@updateLang="updateLang"
 		/>
+
+    <!-- 上传素材库 -->
+    <uploadToMaterial 
+      v-model="showUploadMaterial"
+      source="chart"
+      :sourceId="chartInfo.ChartInfoId"
+      :defaultName="currentLang=='en'?chartInfo.ChartNameEn : chartInfo.ChartName"
+    />
   </div>
 </template>
 
@@ -626,7 +641,9 @@ export default {
 
       /* 查看历史弹窗 */
 			isLookHistory: false,
-			lookEdbId: 0
+			lookEdbId: 0,
+
+      showUploadMaterial:false,//显示上传至素材库
     };
   },
   methods: {

+ 10 - 2
src/views/mychart_manage/index.vue

@@ -173,6 +173,7 @@
         <div class="cont-top">
           <span>{{$t('Chart.total_chart_show',{limit:total})}}</span>
           <span v-if="ispublic === 1"><!-- 分享人 -->{{$t('MyEtaPage.label_share_user')}}: {{ RealName }}</span>
+          <el-button type='text' v-if="ispublic !== 1&&permissionBtn.isShowBtn('myETAPermission','myChart_batchSaveToMaterial')" @click="showBatchSaveToMaterial=true">{{$t('ReportManage.Material.batch_save_to_material')}}</el-button>
         </div>
         <div
           class="chart-public-list"
@@ -273,6 +274,9 @@
         :detailArr="detailArr"
         @close="hintDialogShow=false"
     />
+
+    <!-- 批量上传素材 -->
+    <BatchSaveToMaterial v-model="showBatchSaveToMaterial" :classifId="select_classify" />
   </div>
 </template>
 
@@ -283,6 +287,7 @@ import pubDialog from '@/components/pubDialog.vue';
 import chooseChart from './components/chooseChart.vue';
 import chartDetail from './components/chartDetailDia.vue';
 import ClassifyDeleteCheck from './components/classifyDeleteCheck.vue';
+import BatchSaveToMaterial from './components/BatchSaveToMaterial.vue';
 export default {
   name: '',
   components: {
@@ -290,7 +295,8 @@ export default {
     pubDialog,
     draggable,
     chartDetail,
-    ClassifyDeleteCheck
+    ClassifyDeleteCheck,
+    BatchSaveToMaterial
 },
   directives: {
     drag(el, bindings) {
@@ -392,7 +398,9 @@ export default {
       // chart_lang: 'ch',
 
       hintDialogShow:false,
-      detailArr:[]
+      detailArr:[],
+
+      showBatchSaveToMaterial:false,//显示批量上传至素材库
     };
   },
   computed: {

+ 3 - 2
src/views/ppt_manage/mixins/mixins.js

@@ -281,12 +281,12 @@ export default {
       // 
       console.log('初始化区间分析数据');
       this.intervalAnalysisChartData=data.DataResp
-      this.setLimitData(this.tableData)
+      this.setLimitData(this.dataList)
       this.setIntervalAnalysisChart()
     },
     setIntervalAnalysisChart(){
       console.log('渲染区间分析图表');
-      this.setDefaultChart(this.tableData)
+      this.setDefaultChart(this.dataList)
     },
 
     /* 曲线 */
@@ -2243,6 +2243,7 @@ export default {
     },
     /* ----自定义上下限相关--- */
     setLimitData(tableData=[]){
+        if([7,10,11,14].includes(this.chartInfo.ChartType)) return
         const {
             //左右轴极值字段 
             LeftMin=0,LeftMax=0,

+ 224 - 0
src/views/ppt_manage/newVersion/components/editor/InsertBalanceSheet.vue

@@ -0,0 +1,224 @@
+<template>
+  <div class="import-mychart-wrap">
+    <div v-show="!showChildSheet">
+    <div>
+      <el-input
+        :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleSearch"
+      />
+    </div>
+    <div style="margin-top: 10px">
+      <el-checkbox
+        style="display:block"
+        v-model="isShowMe"
+        @change="handleSearch"
+        >{{ $t("BalanceSheet.only_edit")}}</el-checkbox
+      >
+    </div>
+    <div class="list" v-infinite-scroll="load" v-if="list.length > 0">
+      <div
+        class="item"
+        v-for="item in list"
+        :key="item.ExcelInfoId"
+        @click="handleChooseSheet(item)"
+      >
+        <p>{{ item.ExcelName }}</p>
+        <img
+          :src="!item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage"
+          alt=""
+          style="min-height:167px"
+        />
+      </div>
+    </div>
+    <div v-if="list.length == 0" class="empty-box">
+      {{ $t("Table.prompt_slogan") }}
+    </div>
+    </div>
+    <!-- 选择子平衡表 -->
+    <div v-show="showChildSheet">
+    <div class="label-name" style="margin:10px 0">
+      <span style="cursor: pointer;" @click="handleClearSelectSheet">{{$t('SystemManage.OperateAuth.tab_sub_sheet4')}}</span>
+      <span v-if="showChildSheet"> > {{this.activeName}}</span>
+    </div>
+    <div class="top-box">
+        <span>{{ $t("BalanceSheet.version") }}</span>
+        <el-select
+          v-model="version"
+          style="width: 200px;"
+          @change="handleVersionChange"
+        >
+          <el-option
+            v-for="item in versionOpts"
+            :key="item.ExcelInfoId"
+            :label="item.VersionName"
+            :value="item.ExcelInfoId"
+          ></el-option>
+        </el-select>
+    </div>
+    <div class="list">
+      <div
+        class="item"
+        v-for="item in childSheetList"
+        :key="item.ExcelInfoId"
+        @click="handleClickItem(item)"
+      >
+        <p>{{ item.ExcelName }}</p>
+        <img
+          :src="item.ExcelImage"
+          alt=""
+          style="min-height:167px"
+        />
+      </div>
+    </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+  data() {
+    return {
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe: false,
+
+      showChildSheet:false,//显示平衡表子表
+      version:'',
+      versionOpts:[],
+      childSheetList:[],
+      activeName:''
+    }
+  },
+  created() {
+    this.getSheetList()
+  },
+  methods: {
+    // 获取版本列表
+    getVersionList(){
+      sheetInterface.balanceTableVersion({ExcelInfoId:this.version}).then(res=>{
+        if(res.Ret===200){
+          const arr=res.Data.List||[]
+          if(this.$i18nt.locale!=='zh'){
+            arr[0].VersionName='Active'
+          }
+          this.versionOpts=arr
+        }
+      })
+    },
+    //获取所有子表数据
+    async getChildTable(){
+      const res = await sheetInterface.getBalanceChildTable({
+				ParentId: Number(this.version)
+			})
+      if(res.Ret !== 200)  return
+      const arr=res.Data.List||[]
+      this.childSheetList=arr.map(item=>{
+        return {
+          ...item,
+          HaveOperaAuth:true
+        }
+      })
+    },
+    handleVersionChange(){
+      this.getChildTable()
+    },
+    // 选择某个平衡表
+    handleChooseSheet(item){
+      if(!item.HaveOperaAuth) return this.$message.warning(this.$t('MsgPrompt.no_sheet_auth'))
+      this.activeName=item.ExcelName
+      this.version=item.ExcelInfoId
+      this.getVersionList()
+      this.getChildTable()
+      this.showChildSheet=true
+    },
+    // 返回平衡表列表状态
+    handleClearSelectSheet(){
+      this.version=''
+      this.versionOpts=[]
+      this.childSheetList=[]
+      this.activeName=''
+      this.showChildSheet=false
+    },
+
+    handleSearch() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getSheetList()
+    },
+
+    async getSheetList() {
+      this.loading = true
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page,
+        Source: 5,
+        KeyWord: this.keyword,
+        IsShowMe: this.isShowMe
+      };
+      let res = await sheetInterface.sheetList(params)
+      this.loading = false
+      if (res.Ret !== 200) return;
+      this.finished = res.Data.Paging.IsEnd
+      this.list = res.Data
+        ? this.page_no === 1
+          ? res.Data.List
+          : [...this.list, ...res.Data.List]
+        : [];
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getSheetList()
+    },
+
+    handleClickItem(item) {
+      this.$emit('insert', item)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap {
+  .list {
+    height: calc(100vh - 320px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    .item {
+      width: 100%;
+      margin: 20px 0;
+      padding: 20px;
+      box-sizing: border-box;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+      p {
+        text-align: center;
+        font-size: 16px;
+        margin-bottom: 10px;
+        color: #5882ef;
+      }
+      img {
+        width: 100%;
+      }
+    }
+  }
+  .empty-box {
+    height: calc(100vh - 320px);
+    text-align: center;
+    color: #999;
+    padding-top: 100px;
+  }
+}
+</style>

+ 240 - 0
src/views/ppt_manage/newVersion/components/editor/InsertETAChart.vue

@@ -0,0 +1,240 @@
+<template>
+  <div class="chart-tool flex-column">
+    <div class="chart-search">
+      <el-input
+        :placeholder="$t('ReportManage.ReportList.chart_name')"
+        v-model="key_word"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="
+          () => {
+            search_page = 1;
+            $refs.chartListRef.scrollTop = 0;
+            getreportlist();
+          }
+        "
+        style="max-width: 420px"
+      ></el-input>
+    </div>
+    <el-radio-group
+      v-model="chart_source"
+      @change="
+        () => {
+          search_page = 1;
+          $refs.chartListRef.scrollTop = 0;
+          getreportlist();
+        }
+      "
+      style="margin: 10px 0"
+    >
+      <el-radio
+        v-for="item in typeOpts"
+        :key="item.key"
+        :label="item.key"
+        style="margin-bottom: 5px"
+        >{{ item.label }}</el-radio
+      >
+      <!-- <el-radio :label="1" style="margin-bottom: 5px">{{ $t("Slides.eta_chart_gallery") }}</el-radio>
+      <el-radio :label="2" style="margin-bottom: 5px">{{ $t("Slides.commodity_price_curve") }}</el-radio>
+      <el-radio :label="3" style="margin-bottom: 5px">{{ $t("Slides.correlation_charts") }}</el-radio>
+      <el-radio :label="6" style="margin-bottom: 5px">{{ $t("Slides.fitted_equation_curves") }}</el-radio>
+      <el-radio :label="7" style="margin-bottom: 5px">{{ $t("Slides.statistical_features") }}</el-radio>
+      <el-radio :label="10">{{ $t("Slides.intercommodity_analysis") }}</el-radio>
+      <el-radio :label="12">{{ $t("StatisticAnalysis.IntervalAnalysis.interval_analysis_name") }}</el-radio> -->
+    </el-radio-group>
+    <div style="margin: 10px 0">
+      <el-checkbox
+        v-model="isShowMe"
+        @change="
+          () => {
+            search_page = 1;
+            $refs.chartListRef.scrollTop = 0;
+            getreportlist();
+          }
+        "
+        >{{ $t("Slides.show_only_mine") }}</el-checkbox
+      >
+    </div>
+    <div
+      class="chart-list"
+      v-infinite-scroll="loadReportHandle"
+      :infinite-scroll-immediate="false"
+      ref="chartListRef"
+    >
+      <template v-if="chartList.length">
+        <div
+          v-for="(item, index) in chartList"
+          :key="index"
+          @click="chooseChart(item)"
+          class="chart-item"
+          :style="item.Disabled && 'cursor: not-allowed;'"
+        >
+          <p class="chart_tit" style="word-break: break-all">
+            {{ item.ChartName }}
+          </p>
+          <img
+            :src="!item.HaveOperaAuth ? $icons.lock_big : item.ChartImage"
+            ref="insert_img"
+            style="-webkit-user-drag: none"
+          />
+        </div>
+      </template>
+      <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else />
+    </div>
+  </div>
+</template>
+
+<script>
+import { dataBaseInterface } from "@/api/api.js";
+import futuresInterface from '@/api/modules/futuresBaseApi';
+import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
+import { fittingEquationInterface, statisticFeatureInterface, crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
+export default {
+  name: "InsertETAChart",
+  data() {
+    return {
+      key_word: '',//搜索图表关键字
+      search_page: 1,
+      search_page_sizes: 20,
+      search_have_more: true,
+      chartList: [],//图表数组
+      chart_source: 1,//图表来源 1 eta 2 商品价格
+      isShowMe: false,
+
+      typeOpts: [
+        {
+          label: this.$t("Slides.eta_chart_gallery"),
+          key: 1,
+          path: 'chartsetting'
+        },
+        {
+          label: this.$t("Slides.commodity_price_curve"),
+          key: 2,
+          path: 'commordityChartBase'
+        },
+        {
+          label: this.$t("Slides.correlation_charts"),
+          key: 3,
+          path: 'chartrelevance'
+        },
+        {
+          label: this.$t("Slides.fitted_equation_curves"),
+          key: 6,
+          path: 'fittingEquationList'
+        },
+        {
+          label: this.$t("Slides.statistical_features"),
+          key: 7,
+          path: 'statisticFeatureList'
+        },
+        {
+          label: this.$t("Slides.intercommodity_analysis"),
+          key: 10,
+          path: 'crossVarietyChartList'
+        },
+        {
+          label: this.$t("StatisticAnalysis.IntervalAnalysis.interval_analysis_name"),
+          key: 12,
+          path: 'rangeAnalysis'
+        }
+      ]
+    }
+  },
+  created() {
+    this.initTypeOpts()
+  },
+  methods: {
+    initTypeOpts() {
+      this.typeOpts = this.typeOpts.filter(item => this.verifyInsertModuleAuth(item.path))
+      if (this.typeOpts.length > 0) {
+        this.chart_source = this.typeOpts[0].key
+        this.getreportlist()
+      }
+    },
+    //获取图表列表
+    async getreportlist() {
+      let params = {
+        Keyword: this.key_word,
+        CurrentIndex: this.search_page,
+        PageSize: this.search_page_sizes,
+        IsShowMe: this.isShowMe
+      }
+      const apiMap = {
+        1: dataBaseInterface.chartSearchByEs,
+        2: futuresInterface.searchChart,
+        3: chartRelevanceApi.searchChart,
+        6: fittingEquationInterface.searchChart,
+        7: statisticFeatureInterface.searchChart,
+        10: crossVarietyInterface.searchChart,
+        12: apiIntervalAnalysis.chartSearch
+      }
+      let res = await apiMap[this.chart_source](params)
+
+      if (res.Ret !== 200) return;
+      res.Data.List = res.Data.List || [];
+      this.chartList = this.search_page > 1 ? [...this.chartList, ...res.Data.List] : res.Data.List;
+      this.search_have_more = this.search_page <= res.Data.Paging.Pages;
+    },
+
+    loadReportHandle() {
+      if (!this.search_have_more) return
+      this.search_page++;
+      this.getreportlist(this.key_word);
+    },
+
+    chooseChart(item) {
+      this.$emit('insert', item)
+    }
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.chart-search {
+  margin-bottom: 10px;
+}
+.chart-list {
+  /* background-color: rgb(82, 106, 106); */
+  flex: 1;
+  border: 2px solid #ebebeb;
+  border-radius: 4px;
+  overflow-y: scroll;
+  text-align: center;
+  .chart-item {
+    /* border: 0.5px solid rgba(116, 129, 141,0.1); */
+    cursor: pointer;
+    text-align: center;
+    color: #74818d;
+    font-size: 18px;
+    margin-bottom: 10px;
+    padding: 10px;
+    img {
+      width: 100%;
+    }
+  }
+  .sandTable-item {
+    border-bottom: solid 1px #eeeeee;
+    padding: 20px 0 10px 0;
+    p {
+      font-size: 16px;
+      color: #3464e0;
+      text-align: center;
+    }
+    img {
+      cursor: pointer;
+    }
+    // .source-identification{
+    //   color: #000;
+    //   text-align: left;
+    //   padding-left: 12px;
+    // }
+  }
+  .loaded-text {
+    height: 20px;
+    text-align: center;
+    color: #666;
+    font-size: 14px;
+  }
+}
+</style>

+ 170 - 0
src/views/ppt_manage/newVersion/components/editor/InsertMaterial.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="import-mychart-wrap">
+    <div>
+      <el-cascader
+        v-model="classify"
+        :options="classifyOpts"
+        :placeholder="$t('MsgPrompt.select_category')"
+        :props="{
+          checkStrictly: true,
+          emitPath: false,
+          value: 'ClassifyId',
+          label: 'ClassifyName',
+          children: 'Children',
+        }"
+        style="width: 100%;"
+        @change="handleRefreshList"
+      />
+      <el-input
+        :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleRefreshList"
+        style="margin:5px 0"
+      />
+      <el-checkbox
+        class="onlyshowme-box"
+        v-model="isShowMe"
+        @change="handleRefreshList"
+        >{{ $t("ReportManage.ReportList.just_mine_radio") }}</el-checkbox
+      >
+    </div>
+    <div class="list" v-infinite-scroll="load" v-if="list.length > 0">
+      <div
+        class="item"
+        v-for="item in list"
+        :key="item.MaterialId"
+        @click="handleClickItem(item)"
+      >
+        <p>{{ item.MaterialName }}</p>
+        <img :src="item.PicUrl" alt="" />
+      </div>
+    </div>
+    <div v-if="list.length == 0" class="empty-box">
+      {{ $t("Table.prompt_slogan") }}
+    </div>
+  </div>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  data() {
+    return {
+      classifyOpts: [],
+      classify: '',
+      keyword: '',
+      pageSize: 20,
+      CurrentIndex: 1,
+      list: [],
+      loading: false,
+      finished: false,
+      isShowMe:false
+    }
+  },
+  mounted() {
+    this.getClassifyOpt()
+    this.handleGetList()
+  },
+  methods: {
+    async handleGetList() {
+      this.loading = true
+      const res = await apiReportMaterial.materialList({
+        ClassifyId: this.classify,
+        Keyword: this.keyword,
+        CurrentIndex: this.CurrentIndex,
+        PageSize: this.pageSize,
+        IsShowMe:this.isShowMe
+      })
+      this.loading = false
+      let arr = res.Data.List || []
+      arr = arr.map(item => {
+        return {
+          ...item,
+          PicUrl: item.ImgUrl
+        }
+      });
+
+      this.list = [...this.list, ...arr]
+      if (!res.Data) {
+        this.finished = true
+      }
+      if (res.Data && res.Data.Paging.IsEnd) {
+        this.finished = true
+      }
+    },
+
+    handleRefreshList() {
+      console.log('aaa');
+      this.CurrentIndex = 1
+      this.finished = false
+      this.list = []
+      this.handleGetList()
+    },
+
+    load() {
+      if (this.finished) return
+      this.CurrentIndex++
+      this.handleGetList()
+    },
+
+    handleClickItem(item) {
+      this.$emit('insert',item)
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap {
+  .list {
+    height: calc(100vh - 320px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    .item {
+      width: 100%;
+      margin: 20px 0;
+      padding: 20px;
+      box-sizing: border-box;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+      p {
+        text-align: center;
+        font-size: 16px;
+        margin-bottom: 10px;
+        color: #5882ef;
+      }
+      img {
+        width: 100%;
+      }
+    }
+  }
+  .empty-box {
+    height: calc(100vh - 320px);
+    text-align: center;
+    color: #999;
+    padding-top: 100px;
+  }
+}
+</style>

+ 1 - 1
src/views/ppt_manage/newVersion/components/editor/InsertSemantics.vue

@@ -78,7 +78,7 @@ export default {
         },
 
         handleClickItem(item){
-           this.$parent.chooseChart(item,'sandImage')
+            this.$emit('insert',item)
         }
     },
 }

+ 174 - 0
src/views/ppt_manage/newVersion/components/editor/InsertSheet.vue

@@ -0,0 +1,174 @@
+<template>
+  <div class="import-mychart-wrap">
+    <div>
+      <el-input
+        :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleSearch"
+      />
+    </div>
+    <div style="margin-top: 10px">
+      <el-radio-group
+        v-model="table_source"
+        @change="activeTypeChange"
+        style="margin-right: 15px"
+      >
+        <el-radio v-for="item in typeArr" :key="item.key" :label="item.key">{{
+          item.label
+        }}</el-radio>
+      </el-radio-group>
+      <el-checkbox
+        style="display:block"
+        v-model="isShowMe"
+        @change="handleSearch"
+        ><!-- 只看我的 -->{{ $t("MyEtaPage.label_see_mine") }}</el-checkbox
+      >
+    </div>
+    <div class="list" v-infinite-scroll="load" v-if="list.length > 0">
+      <div
+        class="item"
+        v-for="item in list"
+        :key="item.ExcelInfoId"
+        @click="handleClickItem(item)"
+      >
+        <p>{{ item.ExcelName }}</p>
+        <img
+          style="width:100%;object-fit: contain;height: 250px;-webkit-user-drag:none;"
+          :src="!item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage"
+          alt=""
+        />
+      </div>
+    </div>
+    <div v-if="list.length == 0" class="empty-box">
+      {{ $t("Table.prompt_slogan") }}
+    </div>
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+// import apiBiBoard from '@/api/modules/BIBoard.js'
+export default {
+  data() {
+    return {
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe: false,
+      table_source: 1,
+      typeArr: [
+        {
+          label: this.$t('CustomAnalysisPage.table_share') || '共享表格',
+          path: 'sheetList',
+          key: 1
+        },
+        {
+          label: this.$t('SystemManage.OperateAuth.tab_sub_sheet2') || '时间序列表格',
+          path: 'sheetTimeList',
+          key: 2
+        },
+        {
+          label: this.$t('SystemManage.OperateAuth.tab_sub_sheet3') || '混合表格',
+          path: 'sheetMixedList',
+          key: 3
+        }
+      ],
+    }
+  },
+  created() {
+    this.initStatus()
+  },
+  methods: {
+    async initStatus() {
+      // const res=await apiBiBoard.chartSheetPermission()
+      // if(res.Ret!==200) return
+      // const arr=res.Data||[]
+      // if(arr.length>0){
+      //     this.typeArr=this.typeArr.filter(item=>arr.some(_i=>_i.Path===item.path))
+      //     this.table_source=this.typeArr[0].key
+      this.getSheetList()
+      // }
+    },
+    handleSearch() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getSheetList()
+    },
+    activeTypeChange(item) {
+      this.isShowMe = false
+      this.keyword = ''
+      this.handleSearch()
+    },
+    async getSheetList() {
+      this.loading = true
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page,
+        Source: this.table_source,
+        KeyWord: this.keyword,
+        IsShowMe: this.isShowMe
+      };
+      let res = await sheetInterface.sheetList(params)
+      this.loading = false
+      if (res.Ret !== 200) return;
+      this.finished = res.Data.Paging.IsEnd
+      this.list = res.Data
+        ? this.page_no === 1
+          ? res.Data.List
+          : [...this.list, ...res.Data.List]
+        : [];
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getSheetList()
+    },
+
+    handleClickItem(item) {
+      this.$emit('insert', item)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap {
+  .list {
+    height: calc(100vh - 320px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    .item {
+      width: 100%;
+      margin: 20px 0;
+      padding: 20px;
+      box-sizing: border-box;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+      p {
+        text-align: center;
+        font-size: 16px;
+        margin-bottom: 10px;
+        color: #5882ef;
+      }
+      img {
+        width: 100%;
+      }
+    }
+  }
+  .empty-box {
+    height: calc(100vh - 320px);
+    text-align: center;
+    color: #999;
+    padding-top: 100px;
+  }
+}
+</style>

+ 71 - 96
src/views/ppt_manage/newVersion/pptEditor.vue

@@ -169,32 +169,10 @@
               <el-tabs v-model="tabsactive">
                 <el-tab-pane :label="tab.label" :name="tab.val" v-for="tab in panelTabs" :key="tab.val"></el-tab-pane>
               </el-tabs>
-              <div class="chart-tool flex-column" v-show="tabsactive == '图表'">
-                <div class="chart-search">
-                    <el-input :placeholder="$t('Slides.keyword_search')"  v-model="key_word" size="medium" prefix-icon="el-icon-search" @input="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="max-width:420px;"></el-input>
-                </div>
-                <el-radio-group v-model="chart_source" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="margin: 10px 0;">
-                  <el-radio :label="1" style="margin-bottom:5px">{{$t('Slides.eta_chart_gallery')}}</el-radio>
-                  <el-radio :label="2" style="margin-bottom:5px">{{$t('Slides.commodity_price_curve')}}</el-radio> 
-                  <el-radio :label="3" style="margin-bottom:5px">{{$t('Slides.correlation_charts')}}</el-radio>
-                  <el-radio :label="6" style="margin-bottom:5px">{{$t('Slides.fitted_equation_curves')}}</el-radio>
-                  <el-radio :label="7" style="margin-bottom:5px">{{$t('Slides.statistical_features')}}</el-radio>
-                  <el-radio :label="10">{{$t('Slides.intercommodity_analysis')}}</el-radio>
-                </el-radio-group>
-                <div style="margin: 10px 0">
-                  <el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}">{{$t('Slides.show_only_mine')}}</el-checkbox>
-                </div>
-                <div class="chart-list" v-infinite-scroll="loadReportHandle" :infinite-scroll-immediate="false" ref="chartListRef">
-                    <template v-if="chartList.length">
-                    <div v-for="(item, index) in chartList" :key="index" @click="chooseChart(item,'chart')" class="chart-item" :style="item.Disabled && 'cursor: not-allowed;'">
-                        <p class="chart_tit" style="word-break: break-all;">{{ item.ChartName }}</p>
-                        <img :src="!item.HaveOperaAuth?$icons.lock_big:item.ChartImage" ref="insert_img" style="-webkit-user-drag:none;"/>
-                    </div>
-                    </template>
-                    <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else/>
-                </div>
+              <div class="chart-tool flex-column" v-if="tabsactive == '图表'">
+                <InsertETAChart @insert="(item)=>chooseChart(item,'chart')"/>
               </div>
-              <div v-show="tabsactive == '沙盘'" class="chart-tool flex-column">
+              <div v-if="tabsactive == '沙盘'" class="chart-tool flex-column">
                 <div class="chart-search">
                     <el-input :placeholder="$t('Slides.sandbox_name_category')" v-model="sandTabelQuery.Keyword" size="medium" prefix-icon="el-icon-search" style="max-width:420px;"></el-input>
                 </div>
@@ -209,25 +187,20 @@
                   <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else/>
                 </div>
               </div>
-              <div v-show="tabsactive == '表格'" class="chart-tool flex-column">
-                <div class="chart-search">
-                    <el-input :placeholder="$t('Slides.table_name_input')" v-model="sheetSearchObj.Keyword" size="medium" prefix-icon="el-icon-search" style="max-width:420px;" @input="getSheetList"></el-input>
-                </div>
-                <div class="chart-list" id="sandTable">
-                  <template v-if="sheetSearchList.length">
-                    <div v-for="(item,index) in sheetSearchList" :key="index" class="sandTable-item" >
-                      <p class="chart_tit">{{item.ExcelName}}</p>
-                      <img :src="!item.HaveOperaAuth?$icons.lock_big:item.ExcelImage" style="width:100%;object-fit: contain;height: 250px;-webkit-user-drag:none;"  @click="chooseChart(item,'sheet')"/>
-                    </div>
-                  </template>
-                  <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else/>
-                </div>
+              <div v-if="tabsactive == '表格'" class="chart-tool flex-column">
+                <InsertSheet @insert="(item)=>chooseChart(item,'sheet')"/>
               </div>
-              <div v-show="tabsactive == 'MyETA批量'" class="chart-tool flex-column">
+              <div v-if="tabsactive == 'MyETA批量'" class="chart-tool flex-column">
                 <insert-charts @handleImportMyChart="handleImportMyChart"/>
               </div>
-              <div v-show="tabsactive == '语义分析插入'" class="chart-tool flex-column">
-                <InsertSemantics />
+              <div v-if="tabsactive == '语义分析插入'" class="chart-tool flex-column">
+                <InsertSemantics @insert="(item)=>chooseChart(item,'sandImage')"/>
+              </div>
+              <div v-if="tabsactive == '素材库'" class="chart-tool flex-column">
+                <InsertMaterial @insert="(item)=>chooseChart(item,'sandImage')"/>
+              </div>
+              <div v-if="tabsactive == '平衡表'" class="chart-tool flex-column">
+                <InsertBalanceSheet @insert="(item)=>chooseChart(item,'sheet')"/>
               </div>
             </div>
             <!-- 图层编辑 -->
@@ -345,6 +318,7 @@ import { dataBaseInterface ,sandInterface } from "@/api/api.js";
 import futuresInterface from '@/api/modules/futuresBaseApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
 import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
 import pptmixin from '../mixins/pptMixins';
 import {uploadFileDirect} from "@/utils/common.js"
 import mixins from '../mixins/mixins';
@@ -369,6 +343,10 @@ import ContextMenu from './components/ContextMenu.vue';
 import InsertSemantics from './components/editor/InsertSemantics.vue';
 import ChooseCoverNew from './components/editor/ChooseCoverNew.vue';
 import TitleEditorTool from './components/editor/TitleEditorTool';
+import InsertMaterial from './components/editor/InsertMaterial.vue';
+import InsertSheet from './components/editor/InsertSheet.vue';
+import InsertBalanceSheet from './components/editor/InsertBalanceSheet.vue'
+import InsertETAChart from './components/editor/InsertETAChart.vue';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -378,7 +356,7 @@ export default {
   components: {
     IndexItem, ChooseCover, AddFormat, ShapePreview,
     LayerEditTool, DeletePageDialog, ChangeFormatDialog, InsertPageDialog, addMyClassifyDia, InsertCharts, ContextMenu, InsertSemantics,
-    ChooseCoverNew,TitleEditorTool
+    ChooseCoverNew,TitleEditorTool,InsertMaterial,InsertSheet,InsertBalanceSheet,InsertETAChart
 },
   data() {
     return {
@@ -396,8 +374,6 @@ export default {
             BackIndex:0,//ETA基本配置上线后不用了
             TemplateType:1,//ETA基本配置上线后不用了
         },//封面信息
-        key_word:'',//搜索图表关键字
-        chartList:[],//图表数组
         imgUrl:'',//黏贴图片上传后的地址
         isShowChooseCover:false,
         getDataLoading:null,//获取动态图表数据/上传图片的loading,
@@ -406,7 +382,7 @@ export default {
         maxPageNum:0,//可以添加的最大页数
         maxPageChart:0,//可以添加的最大图表数
         chartNum:0,//当前PPT的总图表数
-        tabsactive:'图表', //右侧区域显示内容 图表 | 沙盘
+        tabsactive:'', //右侧区域显示内容 图表 | 沙盘
         // 沙盘图查询参数
         sandTabelQuery:{
           PageSize: 20,
@@ -431,33 +407,53 @@ export default {
         chartLoadingText:`${this.$t('Slides.loading_urgently')}...`,
         loopTimer:null,//自动保存标识
 
-        search_page: 1,
-        search_page_sizes: 20,
-        search_have_more: true,
-
-        chart_source: 1,//图表来源 1 eta 2 商品价格
-        isShowMe: false
+        panelTabs:[
+          {
+            val:'素材库',
+            label:this.$t('ReportManage.Material.material_name'),
+            path:'materialList'
+          },
+          {
+            val:'图表',
+            label:this.$t('Slides.table_chart'),
+            path:''
+          },
+          {
+            val:'MyETA批量',
+            label:this.$t('Slides.my_eta_batch'),
+            path:'mychart'
+          },
+          {
+            val:'沙盘', 
+            label:this.$t('Slides.sandbox_name'),
+            path:'sandlist'
+          },
+          {
+            val:'表格', 
+            label:this.$t('Slides.table_name'),
+            path:''
+          },
+          {
+            val:'平衡表', 
+            label:this.$t('SystemManage.OperateAuth.tab_sub_sheet4'),
+            path:'sheetBalanceList'
+          },
+          {
+            val:'语义分析插入', 
+            label:this.$t('Slides.table_analysis_semantic'),
+            path:'semanticsPage'
+          },
+        ]
     };
   },
-  computed:{
-    panelTabs(){
-      return  [ 
-        {val:'图表',label:this.$t('Slides.table_chart') },
-        {val:'MyETA批量',label:this.$t('Slides.my_eta_batch')},
-        {val:'沙盘', label:this.$t('Slides.sandbox_name')},
-        {val:'表格', label:this.$t('Slides.table_name')},
-        {val:'语义分析插入', label:this.$t('Slides.table_analysis_semantic')},
-      ]
-    },  
-    
-  },
   created() {
-    //获取图表,沙盘,表格数据
-    this.getreportlist()
-		this.getSandTable()
-    this.getSheetList()
+    // //获取图表,沙盘,表格数据
+    // this.getreportlist()
+		// this.getSandTable()
+    // this.getSheetList()
     //获取PPT限制
     this.getPPTLimit()
+    this.initPanelTabs()
 	},
   mounted(){
       if(Highcharts.charts){
@@ -474,6 +470,14 @@ export default {
 		}
 	},
   methods: {
+    // 初始化插入选项
+    initPanelTabs(){
+      this.panelTabs=this.panelTabs.filter(item=>this.verifyInsertModuleAuth(item.path))
+      if(this.panelTabs.length>0){
+        this.tabsactive=this.panelTabs[0].val
+      }
+      if(this.panelTabs.some(i=>i.val==='沙盘')) this.getSandTable()
+    },
     getPPTLimit(){
       pptInterface.getConfig().then(res=>{
         if(res.Ret===200){
@@ -858,35 +862,6 @@ export default {
           })
         })
     },
-    //获取图表列表
-    async getreportlist(){
-      let params = {
-        Keyword: this.key_word,
-        CurrentIndex: this.search_page,
-        PageSize: this.search_page_sizes,
-        IsShowMe: this.isShowMe
-      }
-      const apiMap = {
-        1: dataBaseInterface.chartSearchByEs,
-        2: futuresInterface.searchChart,
-        3: chartRelevanceApi.searchChart,
-        6: fittingEquationInterface.searchChart,
-        7: statisticFeatureInterface.searchChart,
-        10: crossVarietyInterface.searchChart,
-      }
-      let res = await apiMap[this.chart_source](params)
-
-      if (res.Ret !== 200) return;
-      res.Data.List = res.Data.List || [];
-      this.chartList = this.search_page > 1 ? [...this.chartList,...res.Data.List] : res.Data.List;
-      this.search_have_more = this.search_page <= res.Data.Paging.Pages;
-    },
-
-    loadReportHandle() {
-			if(!this.search_have_more) return
-			this.search_page++;
-			this.getreportlist(this.key_word);
-		},
 
     // 获取沙盘图列表 分页
 		getSandTable(){

+ 75 - 67
src/views/ppt_manage/newVersion/pptEnEditor.vue

@@ -154,35 +154,10 @@
               <el-tabs v-model="tabsactive">
                 <el-tab-pane :label="tab.label" :name="tab.val" v-for="tab in panelTabs" :key="tab"></el-tab-pane>
               </el-tabs>
-              <div class="chart-tool flex-column" v-show="tabsactive == '图表'">
-                <div class="chart-search">
-                    <el-input :placeholder="$t('Slides.keyword_search')" v-model="key_word" size="medium" prefix-icon="el-icon-search" @input="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="max-width:420px;"></el-input>
-                </div>
-                <el-radio-group v-model="chart_source" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="margin: 10px 0;">
-                  <el-radio :label="1" style="margin-bottom:5px">{{$t('Slides.eta_chart_gallery')}}</el-radio>
-                  <el-radio :label="2" style="margin-bottom:5px">{{$t('Slides.commodity_price_curve')}}</el-radio> 
-                  <el-radio :label="3" style="margin-bottom:5px">{{$t('Slides.correlation_charts')}}</el-radio> 
-                  <el-radio :label="6" style="margin-bottom:5px">{{$t('Slides.fitted_equation_curves')}}</el-radio>
-                  <el-radio :label="7" style="margin-bottom:5px">{{$t('Slides.statistical_features')}}</el-radio>
-                  <el-radio :label="10">{{$t('Slides.intercommodity_analysis')}}</el-radio>
-                </el-radio-group>
-                <div style="margin: 10px 0">
-                  <el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}">{{$t('Slides.just_mine_radio')}}</el-checkbox>
-                </div>
-                <div class="chart-list" v-infinite-scroll="loadReportHandle" :infinite-scroll-immediate="false" ref="chartListRef">
-                    <template v-if="chartList.length">
-                    <div v-for="(item, index) in chartList" :key="index" @click="chooseChart(item,'chart')" class="chart-item" :style="item.Disabled && 'cursor: not-allowed;'">
-                        <div class="chartEn-mark" style="top: 0;left:0;" @click.stop="setEnHandle(item)" v-if="item.HaveOperaAuth">
-                          <i class="el-icon-edit" style="font-size:15px"/>
-                        </div>
-                        <p class="chart_tit" style="word-break: break-all;">{{ chart_source===1 ? (item.ChartNameEn||item.ChartName) : item.ChartName }}</p>
-                        <img :src="!item.HaveOperaAuth?$icons.lock_big:item.ChartImage" ref="insert_img" />
-                    </div>
-                    </template>
-                    <tableNoData  :text="$t('Table.prompt_slogan')" size="mini" v-else/>
-                </div>
+              <div class="chart-tool flex-column" v-if="tabsactive == '图表'">
+                <InsertETAChart @insert="(item)=>chooseChart(item,'chart')"/>
               </div>
-              <div v-show="tabsactive == '沙盘'" class="chart-tool flex-column">
+              <div v-if="tabsactive == '沙盘'" class="chart-tool flex-column">
                 <div class="chart-search">
                     <el-input :placeholder="$t('Slides.sandbox_name_category')" v-model="sandTabelQuery.Keyword" size="medium" prefix-icon="el-icon-search" style="max-width:420px;"></el-input>
                 </div>
@@ -198,28 +173,23 @@
                   <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else/>
                 </div>
               </div>
-              <div v-show="tabsactive == '表格'" class="chart-tool flex-column">
-                <div class="chart-search">
-                    <el-input :placeholder="$t('Slides.table_name_input')" v-model="sheetSearchObj.Keyword" size="medium" prefix-icon="el-icon-search" style="max-width:420px;" @input="getSheetList"></el-input>
-                </div>
-                <div class="chart-list" id="sandTable">
-                  <template v-if="sheetSearchList.length">
-                    <div v-for="(item,index) in sheetSearchList" :key="index" class="sandTable-item" >
-                      <p class="chart_tit">{{item.ExcelName}}</p>
-                      <img :src="!item.HaveOperaAuth?$icons.lock_big:item.ExcelImage" style="width:100%;object-fit: contain;height: 250px"  @click="chooseChart(item,'sheet')"/>
-                    </div>
-                  </template>
-                  <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else/>
-                </div>
+              <div v-if="tabsactive == '表格'" class="chart-tool flex-column">
+                <InsertSheet @insert="(item)=>chooseChart(item,'sheet')"/>
               </div>
-              <div v-show="tabsactive == 'MyETA批量'" class="chart-tool flex-column">
+              <div v-if="tabsactive == 'MyETA批量'" class="chart-tool flex-column">
                 <insert-charts 
                   @handleImportMyChart="handleImportMyChart"
                   :showEnMark="true"
                   />
               </div>
-              <div v-show="tabsactive == '语义分析插入'" class="chart-tool flex-column">
-                <InsertSemantics />
+              <div v-if="tabsactive == '语义分析插入'" class="chart-tool flex-column">
+                <InsertSemantics @insert="(item)=>chooseChart(item,'sandImage')"/>
+              </div>
+              <div v-if="tabsactive == '素材库'" class="chart-tool flex-column">
+                <InsertMaterial @insert="(item)=>chooseChart(item,'sandImage')"/>
+              </div>
+              <div v-if="tabsactive == '平衡表'" class="chart-tool flex-column">
+                <InsertBalanceSheet @insert="(item)=>chooseChart(item,'sheet')"/>
               </div>
             </div>
             <!-- 图层编辑 -->
@@ -342,6 +312,7 @@ import { dataBaseInterface ,sandInterface } from "@/api/api.js";
 import futuresInterface from '@/api/modules/futuresBaseApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
 import { fittingEquationInterface,statisticFeatureInterface,crossVarietyInterface } from '@/api/modules/chartRelevanceApi';
+import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
 import pptmixin from '../mixins/pptMixins';
 import mixins from '../mixins/mixins';
 import layerMixins from '../mixins/layerMixins';
@@ -367,6 +338,10 @@ import ContextMenu from './components/ContextMenu.vue';
 import InsertSemantics from './components/editor/InsertSemantics.vue';
 import ChooseCoverNew from './components/editor/ChooseCoverNew.vue';
 import TitleEditorTool from './components/editor/TitleEditorTool';
+import InsertMaterial from './components/editor/InsertMaterial.vue';
+import InsertSheet from './components/editor/InsertSheet.vue';
+import InsertBalanceSheet from './components/editor/InsertBalanceSheet.vue'
+import InsertETAChart from './components/editor/InsertETAChart.vue';
 export default {
   mixins:[pptmixin,//ppt页面共同逻辑
           mixins,//图表加载逻辑
@@ -388,7 +363,11 @@ export default {
     ContextMenu,
     InsertSemantics,
     ChooseCoverNew,
-    TitleEditorTool
+    TitleEditorTool,
+    InsertMaterial,
+    InsertSheet,
+    InsertBalanceSheet,
+    InsertETAChart
   },
   data() {
     return {
@@ -406,8 +385,7 @@ export default {
             BackIndex:0,
             TemplateType:1
         },//封面信息
-        key_word:'',//搜索图表关键字
-        chartList:[],//图表数组
+
         imgUrl:'',//黏贴图片上传后的地址
         isShowChooseCover:false,
         getDataLoading:null,//获取动态图表数据/上传图片的loading,
@@ -416,7 +394,7 @@ export default {
         maxPageNum:0,//可以添加的最大页数
         maxPageChart:0,//可以添加的最大图表数
         chartNum:0,//当前PPT的总图表数
-        tabsactive:'图表', //右侧区域显示内容 图表 | 沙盘
+        tabsactive:'', //右侧区域显示内容 图表 | 沙盘
         // 沙盘图查询参数
         sandTabelQuery:{
           PageSize: 15,
@@ -441,28 +419,48 @@ export default {
         loopTimer:null,//自动保存标识
         currentLang:'en',//语言标识
 
-        search_page: 1,
-        search_page_sizes: 20,
-        search_have_more: true,
-
-        chart_source: 1,//图表来源 1 eta 2 商品价格
-        isShowMe:false
+        panelTabs:[
+          {
+            val:'素材库',
+            label:this.$t('ReportManage.Material.material_name'),
+            path:'materialList'
+          },
+          {
+            val:'图表',
+            label:this.$t('Slides.table_chart'),
+            path:''
+          },
+          {
+            val:'MyETA批量',
+            label:this.$t('Slides.my_eta_batch'),
+            path:'mychart'
+          },
+          {
+            val:'沙盘', 
+            label:this.$t('Slides.sandbox_name'),
+            path:'sandlist'
+          },
+          {
+            val:'表格', 
+            label:this.$t('Slides.table_name'),
+            path:''
+          },
+          {
+            val:'平衡表', 
+            label:this.$t('SystemManage.OperateAuth.tab_sub_sheet4'),
+            path:'sheetBalanceList'
+          },
+          {
+            val:'语义分析插入', 
+            label:this.$t('Slides.table_analysis_semantic'),
+            path:'semanticsPage'
+          },
+        ]
     };
   },
   created() {
-		this.getSandTable()
+		this.initPanelTabs()
 	},
-  computed:{
-    panelTabs(){
-      return  [ 
-        {val:'图表',label:this.$t('Slides.table_chart') },
-        {val:'MyETA批量',label:this.$t('Slides.my_eta_batch')},
-        {val:'沙盘', label:this.$t('Slides.sandbox_name')},
-        {val:'表格', label:this.$t('Slides.table_name')},
-        {val:'语义分析插入', label:this.$t('Slides.table_analysis_semantic')},
-      ]
-    },
-  },
   mounted(){
       if(Highcharts.charts){
         Highcharts.charts.length=0
@@ -471,7 +469,7 @@ export default {
       this.getreportlist()
       //获取PPT限制
       this.getPPTLimit()
-      this.getSheetList();
+      // this.getSheetList();
       this.init()
       window.addEventListener('message',this.reInitIframe)
   },
@@ -483,6 +481,15 @@ export default {
 		}
 	},
   methods: {
+    // 初始化插入选项
+    initPanelTabs(){
+      this.panelTabs=this.panelTabs.filter(item=>this.verifyInsertModuleAuth(item.path))
+      if(this.panelTabs.length>0){
+        this.tabsactive=this.panelTabs[0].val
+      }
+      if(this.panelTabs.some(i=>i.val==='沙盘')) this.getSandTable()
+    },
+    
     getPPTLimit(){
       pptEnInterface.getConfig().then(res=>{
         if(res.Ret===200){
@@ -868,6 +875,7 @@ export default {
           6: fittingEquationInterface.searchChart,
           7: statisticFeatureInterface.searchChart,
           10: crossVarietyInterface.searchChart,
+          12: apiIntervalAnalysis.chartSearch
         }
         let res = await apiMap[this.chart_source](params)
 

+ 224 - 0
src/views/report_manage/components/importBalanceSheet.vue

@@ -0,0 +1,224 @@
+<template>
+  <div class="import-mychart-wrap">
+    <div v-show="!showChildSheet">
+    <div>
+      <el-input
+        :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleSearch"
+      />
+    </div>
+    <div style="margin-top: 10px">
+      <el-checkbox
+        style="display:block"
+        v-model="isShowMe"
+        @change="handleSearch"
+        >{{ $t("BalanceSheet.only_edit")}}</el-checkbox
+      >
+    </div>
+    <div class="list" v-infinite-scroll="load" v-if="list.length > 0">
+      <div
+        class="item"
+        v-for="item in list"
+        :key="item.ExcelInfoId"
+        @click="handleChooseSheet(item)"
+      >
+        <p>{{ item.ExcelName }}</p>
+        <img
+          :src="!item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage"
+          alt=""
+          style="min-height:167px"
+        />
+      </div>
+    </div>
+    <div v-if="list.length == 0" class="empty-box">
+      {{ $t("Table.prompt_slogan") }}
+    </div>
+    </div>
+    <!-- 选择子平衡表 -->
+    <div v-show="showChildSheet">
+    <div class="label-name" style="margin:10px 0">
+      <span style="cursor: pointer;" @click="handleClearSelectSheet">{{$t('SystemManage.OperateAuth.tab_sub_sheet4')}}</span>
+      <span v-if="showChildSheet"> > {{this.activeName}}</span>
+    </div>
+    <div class="top-box">
+        <span>{{ $t("BalanceSheet.version") }}</span>
+        <el-select
+          v-model="version"
+          style="width: 200px;"
+          @change="handleVersionChange"
+        >
+          <el-option
+            v-for="item in versionOpts"
+            :key="item.ExcelInfoId"
+            :label="item.VersionName"
+            :value="item.ExcelInfoId"
+          ></el-option>
+        </el-select>
+    </div>
+    <div class="list">
+      <div
+        class="item"
+        v-for="item in childSheetList"
+        :key="item.ExcelInfoId"
+        @click="handleClickItem(item)"
+      >
+        <p>{{ item.ExcelName }}</p>
+        <img
+          :src="item.ExcelImage"
+          alt=""
+          style="min-height:167px"
+        />
+      </div>
+    </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+  data() {
+    return {
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe: false,
+
+      showChildSheet:false,//显示平衡表子表
+      version:'',
+      versionOpts:[],
+      childSheetList:[],
+      activeName:''
+    }
+  },
+  created() {
+    this.getSheetList()
+  },
+  methods: {
+    // 获取版本列表
+    getVersionList(){
+      sheetInterface.balanceTableVersion({ExcelInfoId:this.version}).then(res=>{
+        if(res.Ret===200){
+          const arr=res.Data.List||[]
+          if(this.$i18nt.locale!=='zh'){
+            arr[0].VersionName='Active'
+          }
+          this.versionOpts=arr
+        }
+      })
+    },
+    //获取所有子表数据
+    async getChildTable(){
+      const res = await sheetInterface.getBalanceChildTable({
+				ParentId: Number(this.version)
+			})
+      if(res.Ret !== 200)  return
+      const arr=res.Data.List||[]
+      this.childSheetList=arr.map(item=>{
+        return {
+          ...item,
+          HaveOperaAuth:true
+        }
+      })
+    },
+    handleVersionChange(){
+      this.getChildTable()
+    },
+    // 选择某个平衡表
+    handleChooseSheet(item){
+      if(!item.HaveOperaAuth) return this.$message.warning(this.$t('MsgPrompt.no_sheet_auth'))
+      this.activeName=item.ExcelName
+      this.version=item.ExcelInfoId
+      this.getVersionList()
+      this.getChildTable()
+      this.showChildSheet=true
+    },
+    // 返回平衡表列表状态
+    handleClearSelectSheet(){
+      this.version=''
+      this.versionOpts=[]
+      this.childSheetList=[]
+      this.activeName=''
+      this.showChildSheet=false
+    },
+
+    handleSearch() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getSheetList()
+    },
+
+    async getSheetList() {
+      this.loading = true
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page,
+        Source: 5,
+        KeyWord: this.keyword,
+        IsShowMe: this.isShowMe
+      };
+      let res = await sheetInterface.sheetList(params)
+      this.loading = false
+      if (res.Ret !== 200) return;
+      this.finished = res.Data.Paging.IsEnd
+      this.list = res.Data
+        ? this.page_no === 1
+          ? res.Data.List
+          : [...this.list, ...res.Data.List]
+        : [];
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getSheetList()
+    },
+
+    handleClickItem(item) {
+      this.$emit('insert', item)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap {
+  .list {
+    height: calc(100vh - 320px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    .item {
+      width: 100%;
+      margin: 20px 0;
+      padding: 20px;
+      box-sizing: border-box;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+      p {
+        text-align: center;
+        font-size: 16px;
+        margin-bottom: 10px;
+        color: #5882ef;
+      }
+      img {
+        width: 100%;
+      }
+    }
+  }
+  .empty-box {
+    height: calc(100vh - 320px);
+    text-align: center;
+    color: #999;
+    padding-top: 100px;
+  }
+}
+</style>

+ 170 - 0
src/views/report_manage/components/importMaterial.vue

@@ -0,0 +1,170 @@
+<template>
+  <div class="import-mychart-wrap">
+    <div>
+      <el-cascader
+        v-model="classify"
+        :options="classifyOpts"
+        :placeholder="$t('MsgPrompt.select_category')"
+        :props="{
+          checkStrictly: true,
+          emitPath: false,
+          value: 'ClassifyId',
+          label: 'ClassifyName',
+          children: 'Children',
+        }"
+        style="width: 100%;"
+        @change="handleRefreshList"
+      />
+      <el-input
+        :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleRefreshList"
+        style="margin:5px 0"
+      />
+      <el-checkbox
+        class="onlyshowme-box"
+        v-model="isShowMe"
+        @change="handleRefreshList"
+        >{{ $t("ReportManage.ReportList.just_mine_radio") }}</el-checkbox
+      >
+    </div>
+    <div class="list" v-infinite-scroll="load" v-if="list.length > 0">
+      <div
+        class="item"
+        v-for="item in list"
+        :key="item.MaterialId"
+        @click="handleClickItem(item)"
+      >
+        <p>{{ item.MaterialName }}</p>
+        <img :src="item.PicUrl" alt="" />
+      </div>
+    </div>
+    <div v-if="list.length == 0" class="empty-box">
+      {{ $t("Table.prompt_slogan") }}
+    </div>
+  </div>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  data() {
+    return {
+      classifyOpts: [],
+      classify: '',
+      keyword: '',
+      pageSize: 20,
+      CurrentIndex: 1,
+      list: [],
+      loading: false,
+      finished: false,
+      isShowMe:false
+    }
+  },
+  mounted() {
+    this.getClassifyOpt()
+    this.handleGetList()
+  },
+  methods: {
+    async handleGetList() {
+      this.loading = true
+      const res = await apiReportMaterial.materialList({
+        ClassifyId: this.classify,
+        Keyword: this.keyword,
+        CurrentIndex: this.CurrentIndex,
+        PageSize: this.pageSize,
+        IsShowMe:this.isShowMe
+      })
+      this.loading = false
+      let arr = res.Data.List || []
+      arr = arr.map(item => {
+        return {
+          ...item,
+          PicUrl: item.ImgUrl
+        }
+      });
+
+      this.list = [...this.list, ...arr]
+      if (!res.Data) {
+        this.finished = true
+      }
+      if (res.Data && res.Data.Paging.IsEnd) {
+        this.finished = true
+      }
+    },
+
+    handleRefreshList() {
+      console.log('aaa');
+      this.CurrentIndex = 1
+      this.finished = false
+      this.list = []
+      this.handleGetList()
+    },
+
+    load() {
+      if (this.finished) return
+      this.CurrentIndex++
+      this.handleGetList()
+    },
+
+    handleClickItem(item) {
+      this.$emit('insert', item)
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap {
+  .list {
+    height: calc(100vh - 320px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    .item {
+      width: 100%;
+      margin: 20px 0;
+      padding: 20px;
+      box-sizing: border-box;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+      p {
+        text-align: center;
+        font-size: 16px;
+        margin-bottom: 10px;
+        color: #5882ef;
+      }
+      img {
+        width: 100%;
+      }
+    }
+  }
+  .empty-box {
+    height: calc(100vh - 320px);
+    text-align: center;
+    color: #999;
+    padding-top: 100px;
+  }
+}
+</style>

+ 169 - 0
src/views/report_manage/components/importSheet.vue

@@ -0,0 +1,169 @@
+<template>
+  <div class="import-mychart-wrap">
+    <div>
+      <el-input
+        :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleSearch"
+      />
+    </div>
+    <div style="margin-top: 10px">
+      <el-radio-group
+        v-model="table_source"
+        @change="activeTypeChange"
+        style="margin-right: 15px"
+      >
+        <el-radio v-for="item in typeArr" :key="item.key" :label="item.key">{{
+          item.label
+        }}</el-radio>
+      </el-radio-group>
+      <el-checkbox
+        style="display:block"
+        v-model="isShowMe"
+        @change="handleSearch"
+        ><!-- 只看我的 -->{{ $t("MyEtaPage.label_see_mine") }}</el-checkbox
+      >
+    </div>
+    <div class="list" v-infinite-scroll="load" v-if="list.length > 0">
+      <div
+        class="item"
+        v-for="item in list"
+        :key="item.ExcelInfoId"
+        @click="handleClickItem(item)"
+      >
+        <p>{{ item.ExcelName }}</p>
+        <img
+          :src="!item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage"
+          alt=""
+        />
+      </div>
+    </div>
+    <div v-if="list.length == 0" class="empty-box">
+      {{ $t("Table.prompt_slogan") }}
+    </div>
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+  data() {
+    return {
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe: false,
+      table_source: 1,
+      typeArr: [
+        {
+          label: this.$t('CustomAnalysisPage.table_share') || '共享表格',
+          path: 'sheetList',
+          key: 1
+        },
+        {
+          label: this.$t('SystemManage.OperateAuth.tab_sub_sheet2') || '时间序列表格',
+          path: 'sheetTimeList',
+          key: 2
+        },
+        {
+          label: this.$t('SystemManage.OperateAuth.tab_sub_sheet3') || '混合表格',
+          path: 'sheetMixedList',
+          key: 3
+        }
+      ],
+    }
+  },
+  created() {
+    this.initStatus()
+  },
+  methods: {
+    async initStatus() {
+      this.typeArr=this.typeArr.filter(item=>this.verifyInsertModuleAuth(item.path))
+      if(this.typeArr.length>0){
+        this.table_source=this.typeArr[0].key
+        this.getSheetList()
+      }
+    },
+    handleSearch() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getSheetList()
+    },
+    activeTypeChange(item) {
+      this.isShowMe = false
+      this.keyword = ''
+      this.handleSearch()
+    },
+    async getSheetList() {
+      this.loading = true
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page,
+        Source: this.table_source,
+        KeyWord: this.keyword,
+        IsShowMe: this.isShowMe
+      };
+      let res = await sheetInterface.sheetList(params)
+      this.loading = false
+      if (res.Ret !== 200) return;
+      this.finished = res.Data.Paging.IsEnd
+      this.list = res.Data
+        ? this.page_no === 1
+          ? res.Data.List
+          : [...this.list, ...res.Data.List]
+        : [];
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getSheetList()
+    },
+
+    handleClickItem(item) {
+      this.$emit('insert', item)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.import-mychart-wrap {
+  .list {
+    height: calc(100vh - 320px);
+    overflow-x: hidden;
+    overflow-y: auto;
+    .item {
+      width: 100%;
+      margin: 20px 0;
+      padding: 20px;
+      box-sizing: border-box;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      position: relative;
+      overflow: hidden;
+      p {
+        text-align: center;
+        font-size: 16px;
+        margin-bottom: 10px;
+        color: #5882ef;
+      }
+      img {
+        width: 100%;
+      }
+    }
+  }
+  .empty-box {
+    height: calc(100vh - 320px);
+    text-align: center;
+    color: #999;
+    padding-top: 100px;
+  }
+}
+</style>

+ 332 - 0
src/views/report_manage/material/components/classifyTree.vue

@@ -0,0 +1,332 @@
+<template>
+  <div class="classify-tree-wrap">
+    <el-tree
+      ref="classifyIns"
+      :data="classifyList"
+      :current-node-key="activeClassifyId"
+      node-key="ClassifyId"
+      :expand-on-click-node="false"
+      :props="{
+        label: 'ClassifyName',
+        value: 'ClassifyId',
+        children: 'Children',
+      }"
+      check-strictly
+      :empty-text="$t('Common.no_classify_msg')"
+      :draggable="permissionBtn.isShowBtn('reportMaterialPermission','material_classify_move')"
+      :allow-drop="canDropHandle"
+      @node-drop="dropOverHandle"
+      @node-drag-end="dropMouseLeave"
+      @node-drag-leave="dropMouseLeave"
+      @node-drag-enter="dropMouseOver"
+      @current-change="nodeChange"
+    >
+      <div class="classify-item-wrap" slot-scope="{ node, data }">
+        <div class="label-text">
+          <span>{{ data.ClassifyName }}</span>
+        </div>
+        <div class="opt-btns" v-if="data.ClassifyId === activeClassifyId">
+          <!-- 添加子项 -->
+          <img
+            src="~@/assets/img/set_m/add.png"
+            alt=""
+            style="width: 14px; height: 14px; margin-right: 8px"
+            @click.stop="handleShowEditClassify('add', data, node)"
+            v-if="node.level < 3&&permissionBtn.isShowBtn('reportMaterialPermission','material_classify_add')"
+          />
+          <!-- 编辑子项 -->
+          <img
+            src="~@/assets/img/set_m/edit.png"
+            alt=""
+            style="width: 15px; height: 14px; margin-right: 8px"
+            @click.stop="handleShowEditClassify('edit', data, node)"
+            v-if="permissionBtn.isShowBtn('reportMaterialPermission','material_classify_add')"
+          />
+          <!-- 删除子项 -->
+          <img
+            slot="reference"
+            src="~@/assets/img/set_m/del.png"
+            alt=""
+            style="width: 14px; height: 14px"
+            @click.stop="handleDelClassify(node, data)"
+            v-if="permissionBtn.isShowBtn('reportMaterialPermission','material_classify_del')"
+          />
+        </div>
+      </div>
+    </el-tree>
+    <div
+      class="bottom-add-btn"
+      @click="handleShowEditClassify('add', null, null)"
+      v-permission="permissionBtn.reportMaterialPermission.material_classify_add"
+    >
+      <img
+        src="~@/assets/img/set_m/add_ico.png"
+        alt=""
+        style="width: 16px; height: 16px; margin-right: 10px"
+      />
+      <span>{{$t('SteelChemicalPage.add_classify_btn')}}</span>
+    </div>
+
+    <!-- 新增编辑分类 -->
+    <editClassify
+      :isShow="showEditClassify"
+      :editClassifyData="editClassifyData"
+      @close="showEditClassify = false"
+      @success="getClassifyList()"
+    />
+  </div>
+</template>
+
+<script>
+import editClassify from './editClassify.vue'
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  components: { editClassify },
+  watch: {
+    'activeClassifyId': {
+      handler(n) {
+        if (n) {
+          this.$emit('change', n)
+        }
+      },
+      immediate: true
+    }
+  },
+  data() {
+    return {
+      activeClassifyId: '',
+      classifyList: [],
+      editClassifyData: {
+        type: 'add',
+        data: null
+      },
+      showEditClassify: false
+    }
+  },
+  created() {
+    this.getClassifyList()
+  },
+  methods: {
+    initSelect(){
+      this.activeClassifyId=''
+      this.$refs.classifyIns.setCurrentKey(null)
+    },
+    // 获取分类列表
+    async getClassifyList() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      this.classifyList = res.Data.AllNodes || []
+      this.activeClassifyId = this.classifyList[0] ? this.classifyList[0].ClassifyId : ''
+      this.$nextTick(() => {
+        this.$refs.classifyIns.setCurrentKey(this.activeClassifyId)
+      })
+    },
+
+    // 删除分类
+    async handleDelClassify(node, data) {
+      const checkRes = await apiReportMaterial.delClassifyCheck({
+        ClassifyId: data.ClassifyId
+      })
+      if (checkRes.Ret !== 200) return
+      if(![0,2].includes(checkRes.Data.DeleteStatus)) {
+        this.$confirm(
+          checkRes.Data.TipsMsg,
+							/* '删除失败' */this.$t('Edb.MsgPrompt.del_failed'),
+          {
+            confirmButtonText:/*  '知道了' */this.$t('Dialog.known'),
+            showCancelButton: false,
+            type: 'error'
+          })
+        return
+      }
+
+      await this.$confirm(this.$t('ReportManage.Material.del_attention'), this.$t('Dialog.warn_tit'), {
+        type: 'warning'
+      })
+      const res = await apiReportMaterial.delClassify({
+        ClassifyId: data.ClassifyId
+      })
+      if (res.Ret !== 200) return
+      this.$message.success(this.$t('MsgPrompt.delete_msg'));
+      this.getClassifyList()
+    },
+
+    // type add\edit data编辑的分类数据
+    handleShowEditClassify(type, data, node) {
+      this.editClassifyData.type = type
+      this.editClassifyData.data = data ? {
+        ...data,
+        parentLabel: ''
+      } : null
+
+      if (type === 'add' && node && node.level > 0) {
+        let labels = []
+        if (node.level === 1) {
+          labels.push(this.currentLang === 'en' ? data.ClassifyNameEn : data.ClassifyName)
+        } else if (node.level === 2) {
+          labels.push(this.currentLang === 'en' ? node.parent.data.ClassifyNameEn : node.parent.data.ClassifyName)
+          labels.push(this.currentLang === 'en' ? data.ClassifyNameEn : data.ClassifyName)
+        }
+        this.editClassifyData.data.parentLabel = labels.join('/')
+      }
+      if (type === 'edit' && node.level > 1) {
+        let labels = []
+        if (node.level === 2) {
+          labels.push(this.currentLang === 'en' ? node.parent.data.ClassifyNameEn : node.parent.data.ClassifyName)
+        } else if (node.level === 3) {
+          labels.push(this.currentLang === 'en' ? node.parent.parent.data.ClassifyNameEn : node.parent.parent.data.ClassifyName)
+          labels.push(this.currentLang === 'en' ? node.parent.data.ClassifyNameEn : node.parent.data.ClassifyName)
+        }
+        this.editClassifyData.data.parentLabel = labels.join('/')
+      }
+
+      this.showEditClassify = true
+    },
+
+    nodeChange(data, node) {
+      this.activeClassifyId = data.ClassifyId
+    },
+
+    // 拖拽完成
+    async dropOverHandle(b, a, i, e) {
+      let list = a.parent.childNodes;
+      let ClassifyId = b.data.ClassifyId, targetIndex = 0, PrevClassifyId = 0, NextClassifyId = 0, ParentClassifyId = 0;
+      if (i !== 'inner') {
+        ParentClassifyId = a.parent.data.ClassifyId || 0
+        list.forEach((item, index) => {
+          if (item.data.ClassifyId === b.data.ClassifyId) {
+            targetIndex = index
+          }
+        })
+        if (targetIndex === 0) {
+          const data = list[targetIndex + 1].data
+          NextClassifyId = data.ClassifyId
+        } else if (targetIndex === list.length - 1) {
+          const data = list[targetIndex - 1].data
+          PrevClassifyId = data.ClassifyId
+        } else {
+          const pData = list[targetIndex - 1].data
+          PrevClassifyId = pData.ClassifyId
+
+          const nData = list[targetIndex + 1].data
+          NextClassifyId = nData.ClassifyId
+        }
+      } else {
+        ParentClassifyId = a.data.ClassifyId || 0
+      }
+
+      const params = {
+        ClassifyId,
+        ParentClassifyId,
+        PrevClassifyId,
+        NextClassifyId,
+      }
+      const res = await apiReportMaterial.moveClassify(params)
+      this.getClassifyList()
+      if (res.Ret !== 200) return
+      this.$message.success(this.$t('MsgPrompt.move_success_msg'))
+    },
+    /* 判断节点是否能被拖入 不允许改变层级 */
+    canDropHandle(draggingNode, dropNode, type) {
+      let canDrop = false
+      if ((dropNode.level + 1 == draggingNode.level && type === 'inner') || (dropNode.level === draggingNode.level && type !== 'inner')) {
+        canDrop = true
+      }
+      return canDrop
+    },
+    /* 拖拽覆盖添加背景色 */
+    dropMouseOver(node1, node2, e) {
+      // console.log(e.layerY);
+      // 被拖拽节点对应的 Node、所进入节点对应的 Node、event
+      if (node1.level > node2.level && (e.target.childNodes[0].className.includes('el-tree-node__content')
+        || e.target.className.includes('el-tree-node__content'))) {
+        // console.log(e.target.childNodes[0])
+        e.target.childNodes[0].className.includes('el-tree-node__content')
+          ? e.target.childNodes[0].style.backgroundColor = '#409eff'
+          : e.target.style.backgroundColor = '#409eff';
+      }
+
+    },
+    /* 拖拽离开/拖拽完成重置背景色 */
+    dropMouseLeave(node1, node2, e) {
+      let arrs = $('.el-tree-node__content');
+      for (let a of arrs) {
+        a.style.backgroundColor = 'transparent';
+      }
+    },
+  },
+}
+</script>
+
+<style lang="scss">
+@import "~@/styles/theme-vars.scss";
+.classify-tree-wrap {
+  width: 275px;
+  background-color: #ffffff;
+  padding: 20px;
+  margin-right: 20px;
+  display: flex;
+  flex-direction: column;
+  .el-tree {
+    flex: 1;
+    .classify-item-wrap {
+      flex: 1;
+      display: flex;
+      align-items: center;
+      overflow: hidden;
+      .label-text {
+        flex: 1;
+      }
+      .opt-btns {
+        display: flex;
+        align-items: center;
+      }
+    }
+    .el-tree__drop-indicator {
+      height: 3px;
+      background-color: $theme-color;
+    }
+    .el-tree-node__content {
+      margin-bottom: 14px !important;
+    }
+    .el-tree-node__children {
+      .el-tree-node {
+        margin-bottom: 0px !important;
+        padding-left: 18px;
+      }
+      .el-tree-node__content {
+        margin-bottom: 5px !important;
+        padding-left: 0 !important;
+      }
+    }
+    .expanded.el-icon-caret-right:before {
+      content: url("~@/assets/img/set_m/down.png") !important;
+    }
+    .el-icon-caret-right:before {
+      content: url("~@/assets/img/set_m/slide.png") !important;
+    }
+    .el-tree-node__expand-icon.is-leaf.el-icon-caret-right:before {
+      content: "" !important;
+    }
+    .el-tree-node__expand-icon.expanded {
+      -webkit-transform: rotate(0deg);
+      transform: rotate(0deg);
+    }
+    .el-tree-node.is-current > .el-tree-node__content {
+      background-color: #f0f4ff !important;
+    }
+    .el-tree-node__content {
+      padding-right: 10px !important;
+    }
+  }
+  .bottom-add-btn {
+    margin: 30px 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: $theme-color;
+    font-size: 16px;
+    cursor: pointer;
+  }
+}
+</style>

+ 126 - 0
src/views/report_manage/material/components/editClassify.vue

@@ -0,0 +1,126 @@
+<template>
+  <el-dialog
+    :visible.sync="isShow"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    @close="cancelHandle"
+    custom-class="dialog"
+    center
+    width="560px"
+    v-dialogDrag
+    :title="editClassifyData.type==='edit'?$t('SteelChemicalPage.edit_classify_msg'):$t('EtaChartPage.add_my_classify')"
+  >
+    <div class="dialog-main">
+      <el-form
+        ref="diaForm"
+        label-position="left"
+        hide-required-asterisk
+        label-width="120px"
+        :model="formData"
+        :rules="formRules"
+      >
+        <el-form-item :label="$t('ReportManage.CategoryList.parent_category_label')" v-if="editClassifyData.data&&editClassifyData.data.parentLabel">
+          <span>{{editClassifyData.data.parentLabel}}</span>
+        </el-form-item>
+        <el-form-item :label="$t('SteelChemicalPage.label_classify_name')" prop="name">
+          <el-input v-model="formData.name" :placeholder="$t('Chart.InputHolderAll.input_classify')"></el-input>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="dia-bot">
+      <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+        ><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button
+      >
+      <el-button type="primary" plain @click="cancelHandle"
+        ><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import {apiReportMaterial} from '@/api/modules/reportMaterial.js'
+export default {
+  props: {
+    isShow: {
+      type: Boolean,
+      default: false
+    },
+    editClassifyData:{
+      type:'add',
+      data:null
+    }
+  },
+  watch: {
+    isShow(n){
+      if(n&&this.editClassifyData.type==='edit'){
+        console.log(this.editClassifyData);
+        this.formData.name=this.currentLang === 'en'?this.editClassifyData.data.ClassifyNameEn:this.editClassifyData.data.ClassifyName
+      }
+    }
+  },
+  data() {
+    return {
+      formRules: {
+				name:[
+					{ required: true, message: this.$t('EtaBasePage.input_menu_msg'), trigger: 'blur' },
+				],
+      },
+      formData: {
+        name: ''
+      }
+    }
+  },
+  methods: {
+    cancelHandle() {
+      this.formData.name=''
+      this.$emit("close");
+    },
+
+    async handleAddClassify(){
+      const params={
+        ClassifyName:this.formData.name,
+        ParentId:this.editClassifyData.data?this.editClassifyData.data.ClassifyId:0
+      }
+      const res=await apiReportMaterial.addClassify(params)
+      if(res.Ret!==200) return
+      this.$message.success('新增成功')
+      this.$emit('success')
+      this.cancelHandle()
+    },
+
+    async handleEditClassify(){
+      const params={
+        ClassifyName:this.formData.name,
+        ClassifyId:this.editClassifyData.data.ClassifyId
+      }
+      const res=await apiReportMaterial.editClassify(params)
+      if(res.Ret!==200) return
+      this.$message.success('编辑成功')
+      this.$emit('success')
+      this.cancelHandle()
+    },
+
+    saveHandle(){
+      this.$refs.diaForm.validate((valid)=>{
+        if(valid){
+          if(this.editClassifyData.type==='add'){
+            this.handleAddClassify()
+          }else{
+            this.handleEditClassify()
+          }
+        }
+      })
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+  .dia-bot {
+    margin: 30px auto;
+    text-align: center;
+  }
+}
+</style>

+ 145 - 0
src/views/report_manage/material/components/imgMove.vue

@@ -0,0 +1,145 @@
+<template>
+  <el-dialog
+    :visible.sync="isShow"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    @close="cancelHandle"
+    custom-class="dialog"
+    center
+    width="560px"
+    v-dialogDrag
+    :title="$t('Common.move_btn')"
+  >
+    <div class="dialog-main">
+      <el-form
+        ref="diaForm"
+        label-position="left"
+        label-width="80px"
+        :model="formData"
+        :rules="formRules"
+      >
+        <el-form-item :label="$t('ReportManage.Material.move_to')" prop="classify">
+          <el-cascader
+            v-model="formData.classify"
+            :options="classifyOpts"
+            :placeholder="$t('MsgPrompt.select_category')"
+            :props="{
+              checkStrictly: true,
+              emitPath: false,
+              value: 'ClassifyId',
+              label: 'ClassifyName',
+              children: 'Children',
+            }"
+            style="width: 90%"
+          ></el-cascader>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="dia-bot">
+      <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+        ><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button
+      >
+      <el-button type="primary" plain @click="cancelHandle"
+        ><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  props: {
+    isShow: {
+      type: Boolean,
+      default: false
+    },
+    materialData:null,
+    batchOptData:null,//如果这个有数据则是批量移动
+  },
+  watch: {
+    isShow(n) {
+      if (n) {
+        this.getClassifyOpt()
+      }
+    }
+  },
+  data() {
+    return {
+      formRules: {
+        classify: [
+          { required: true, message: this.$t('MsgPrompt.select_category'), trigger: 'change' },
+        ],
+      },
+      classifyOpts: [],
+      formData: {
+        classify: ''
+      }
+    }
+  },
+  methods: {
+    cancelHandle() {
+      this.formData.classify=''
+      this.$emit("close");
+    },
+
+    async handleBatchMove(){
+      const res=await apiReportMaterial.materialBatchMove({
+        ...this.batchOptData,
+        NewClassifyId:this.formData.classify
+      })
+      if(res.Ret!==200) return
+      this.$message.success(this.$t('MsgPrompt.move_success_msg'))
+      this.$emit('success')
+      this.cancelHandle()
+    },
+
+    saveHandle() {
+      this.$refs.diaForm.validate((valid) => {
+        if (valid) {
+          if(this.batchOptData){
+            this.handleBatchMove()
+            return
+          }
+          apiReportMaterial.materialMove({
+            MaterialId:this.materialData.MaterialId,
+            NewClassifyId:this.formData.classify
+          }).then(res=>{
+            if(res.Ret!==200) return
+            this.$message.success(this.$t('MsgPrompt.move_success_msg'))
+            this.$emit('success')
+            this.cancelHandle()
+          })
+        }
+      })
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+  .dia-bot {
+    margin: 30px auto;
+    text-align: center;
+  }
+}
+</style>

+ 102 - 0
src/views/report_manage/material/components/imgRename.vue

@@ -0,0 +1,102 @@
+<template>
+  <el-dialog
+    :visible.sync="isShow"
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    @close="cancelHandle"
+    custom-class="dialog"
+    center
+    width="560px"
+    v-dialogDrag
+    :title="$t('MyEtaPage.option_op_rename')"
+  >
+    <div class="dialog-main">
+      <el-form
+        ref="diaForm"
+        label-position="left"
+        label-width="80px"
+        :model="formData"
+        :rules="formRules"
+      >
+        <el-form-item :label="$t('SystemManage.BaseConfig.resource_label01')" prop="name">
+          <el-input
+            v-model="formData.name"
+            :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="dia-bot">
+      <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+        ><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button
+      >
+      <el-button type="primary" plain @click="cancelHandle"
+        ><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button
+      >
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  props: {
+    isShow: {
+      type: Boolean,
+      default: false
+    },
+    materialData:null
+  },
+  watch: {
+    isShow(n){
+      if(this.materialData){
+        this.formData.name=this.currentLang === 'en' ?this.materialData.MaterialNameEn:this.materialData.MaterialName
+      }
+      
+    }
+  },
+  data() {
+    return {
+      formRules: {
+        name: [
+          { required: true, message: this.$t('SystemManage.BaseConfig.resource_placeholder01'), trigger: 'blur' },
+        ],
+      },
+      formData: {
+        name: ''
+      }
+    }
+  },
+  methods: {
+    cancelHandle() {
+      this.formData.name=''
+      this.$emit("close");
+    },
+
+    saveHandle(){
+      this.$refs.diaForm.validate((valid)=>{
+        if(valid){
+          apiReportMaterial.materialRename({
+            MaterialId:this.materialData.MaterialId,
+            MaterialName:this.formData.name
+          }).then(res=>{
+            if(res.Ret!==200) return
+            this.$message.success(this.$t('MsgPrompt.operate_success_msg'))
+            this.$emit('success')
+            this.cancelHandle()
+          })
+        }
+      })
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+  .dia-bot {
+    margin: 30px auto;
+    text-align: center;
+  }
+}
+</style>

+ 300 - 0
src/views/report_manage/material/components/uploadImgs.vue

@@ -0,0 +1,300 @@
+<template>
+  <div>
+    <el-dialog
+      :visible.sync="isShow"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      @close="cancelHandle"
+      custom-class="dialog"
+      center
+      width="800px"
+      v-dialogDrag
+      :title="$t('ReportManage.CategoryList.upload_image')"
+    >
+      <div class="upload-img-wrap">
+        <el-form
+          ref="formIns"
+          label-position="right"
+          label-width="120px"
+          :model="formData"
+          :rules="formRules"
+        >
+          <el-form-item :label="$t('Common.category')" prop="classify">
+            <el-cascader
+              v-model="formData.classify"
+              :options="classifyOpts"
+              :placeholder="$t('MsgPrompt.select_category')"
+              :props="{ 
+                checkStrictly: true, 
+                emitPath: false,
+                value:'ClassifyId',
+                label:'ClassifyName',
+                children:'Children'
+              }"
+              style="width:90%"
+            ></el-cascader>
+          </el-form-item>
+          <el-form-item :label="$t('ReportManage.CategoryList.upload_image')" prop="imgs">
+            <div class="upload-img-box">
+              <el-upload
+                action=""
+                multiple
+                :file-list="formData.imgs"
+                :limit="uploadLimit"
+                accept=".png,.jpeg,.jpg"
+                :http-request="handleUpload"
+                :before-upload="handelBeforeUploadImgs"
+                :show-file-list="false"
+                :on-exceed="handleUploadExceed"
+              >
+                <div style="text-align:left;line-height:1.5">
+                  <el-button type="text"
+                    >{{$t('ReportManage.CategoryList.select_img_btn')}}</el-button
+                  >
+                  <span style="font-size: 12px; color: #666;display: block;"
+                    >{{$t('ReportManage.Material.upload_tips')}}</span
+                  >
+                </div>
+              </el-upload>
+              <ul class="img-list-box">
+                <li
+                  class="img-item"
+                  v-for="(item, index) in formData.imgs"
+                  :key="item.imgUrl"
+                >
+                  <div class="img-item-box">
+                    <img class="img" :src="item.imgUrl" alt="" />
+                    <div class="opt-box">
+                      <i
+                        class="el-icon-view"
+                        @click="handlePreviewImgItem(item.imgUrl)"
+                      ></i>
+                      <i
+                        class="el-icon-delete"
+                        @click="handleDelImgItem(index)"
+                      ></i>
+                    </div>
+                  </div>
+
+                  <el-input
+                    :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+                    v-model="item.name"
+                  ></el-input>
+                </li>
+              </ul>
+            </div>
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="dia-bot">
+        <el-button type="primary" style="margin-right: 20px" @click="saveHandle"
+          ><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button
+        >
+        <el-button type="primary" plain @click="cancelHandle"
+          ><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button
+        >
+      </div>
+    </el-dialog>
+    <el-image-viewer
+      style="z-index:20000 !important"
+      v-if="showViewer"
+      :on-close="
+        () => {
+          this.picShowList = [];
+          this.showViewer = false;
+        }
+      "
+      :url-list="picShowList"
+    />
+  </div>
+</template>
+
+<script>
+import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
+import {apiReportMaterial} from '@/api/modules/reportMaterial.js'
+export default {
+  components:{ElImageViewer},
+  props: {
+    isShow: {
+      type: Boolean,
+      default: false
+    }
+  },
+  watch: {
+    isShow(n){
+      if(n){
+        this.getClassifyOpt()
+      }
+    }
+  },
+  data() {
+    return {
+      uploadLimit: 10,
+      classifyOpts: [],
+      formRules: {
+				classify:[
+					{ required: true, message: this.$t('MsgPrompt.select_category'), trigger: 'change' },
+				],
+        imgs:[
+					{ required: true, message: this.$t('SystemManage.BaseConfig.resource_placeholder03'), trigger: 'change' },
+				],
+      },
+      formData: {
+        classify: '',
+        imgs: []
+      },
+      showViewer: false,
+      picShowList: []
+    }
+  },
+  methods: {
+    cancelHandle() {
+      this.formData={
+        classify: '',
+        imgs: []
+      }
+      this.$emit("close");
+    },
+
+    // 保存
+    saveHandle(){
+      this.$refs.formIns.validate((valid)=>{
+        if(valid){
+          const params={
+            ClassifyId:this.formData.classify,
+            MaterialList:this.formData.imgs.map(item=>{
+              return {
+                MaterialName:item.name,
+                ImgUrl:item.imgUrl
+              }
+            })
+          }
+          apiReportMaterial.materialAdd(params).then(res=>{
+            if(res.Ret!==200) return
+            this.$message.success('保存成功')
+            this.$emit("success");
+            this.cancelHandle()
+          })
+        }
+      })
+    },
+
+    handleDelImgItem(index) {
+      this.formData.imgs.splice(index, 1)
+    },
+
+    handlePreviewImgItem(url) {
+      this.picShowList = [url]
+      this.showViewer = true
+    },
+
+    handleUploadExceed(){
+      this.$message.warning(`单次上传不超过${this.uploadLimit}张`)
+    },
+
+    handelBeforeUploadImgs(e) {
+      if (
+        e.name.indexOf(".png") == -1 &&
+        e.name.indexOf(".jpg") == -1 &&
+        e.name.indexOf(".jpeg") == -1
+      ) {
+        this.$message.warning(`${e.name}上传失败,上传格式不正确`);
+        return false;
+      }
+      // 不超过5M
+      const isLt5M = e.size / 1024 / 1024 < 5;
+      if(!isLt5M){
+        this.$message.warning(`${e.name}上传失败,大小不能超过5MB`);
+        return false
+      }
+
+    },
+
+    handleUpload(e) {
+      const { size, type, name } = e.file
+      let form = new FormData();
+      form.append('file', e.file);
+      apiReportMaterial.materialImgUpload(form).then(res => {
+        if (res.Ret !== 200) return
+        this.formData.imgs.push({
+          name: name,
+          imgUrl: res.Data.ResourceUrl
+        })
+      })
+    },
+
+    formatArr(arr){
+      return arr.map(item => {
+        if(!item.Children||item.Children.length===0){
+          item.Children=null
+        }else{
+          item.Children=this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt(){
+      const res=await apiReportMaterial.classifyList()
+      if(res.Ret!==200) return 
+      const arr=res.Data.AllNodes || []
+      this.classifyOpts=this.formatArr(arr)
+    }
+
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.dialog {
+  .dia-bot {
+    margin: 30px auto;
+    text-align: center;
+  }
+  .upload-img-box {
+    .img-list-box {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 10px;
+      align-content: flex-start;
+      max-height: 500px;
+      overflow-y: auto;
+      .img-item {
+        width: 120px;
+        .img-item-box {
+          position: relative;
+          .opt-box {
+            display: none;
+            background-color: rgba(0, 0, 0, 0.6);
+            position: absolute;
+            top: 0;
+            left: 0;
+            width: 100%;
+            height: 100%;
+            z-index: 5;
+            justify-content: center;
+            align-items: center;
+            color: #fff;
+            font-size: 20px;
+            gap: 0 20px;
+            i {
+              cursor: pointer;
+            }
+          }
+          &:hover {
+            .opt-box {
+              display: flex;
+            }
+          }
+        }
+        .img {
+          display: block;
+          width: 100%;
+          height: 120px;
+          background-color: #ebeff6;
+        }
+      }
+    }
+  }
+}
+</style>

+ 486 - 0
src/views/report_manage/material/list.vue

@@ -0,0 +1,486 @@
+<template>
+  <div class="material-page">
+    <div class="top-wrap">
+      <el-button
+        type="primary"
+        style="width: 80px"
+        @click="showUploadImg = true"
+        v-permission="permissionBtn.reportMaterialPermission.material_upload"
+        >{{$t('ReportManage.smart_btn.upload')}}</el-button
+      >
+      <el-input
+        :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+        v-model="searchVal"
+        style="max-width: 262px"
+        @change="handleSearchList"
+        clearable
+      >
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+    </div>
+    <div class="content-wrap">
+      <classifyWrap ref="classifyWrapIns" @change="handleClassifyChange" />
+      <div class="img-list-wrap" v-loading="materialListLoading">
+        <div class="top-box" v-if="!isShowBatchOpt">
+          <span>{{$t('ReportManage.Material.img_count',{limit:materialListTotal})}}</span>
+          <el-button 
+            type="text" 
+            @click="handleShowBatchOpt"
+            v-permission="permissionBtn.reportMaterialPermission.material_batchEdit"
+          >{{$t('HighFrequencyData.batch_operation')}}</el-button>
+        </div>
+        <!-- 批量操作时 -->
+        <div class="top-box" v-else>
+          <div>
+            <el-checkbox
+              :label="$t('EtaBasePage.label_all_check')"
+              :indeterminate="checkAllStatus"
+              v-model="checkAll"
+              @change="handleCheckAllChange"
+            />
+            <span>{{$t('ReportManage.Material.select_img_count',{limit:selectCount})  }}</span>
+          </div>
+          <div>
+            <el-button type="text" @click="handleBatchOpt('download')">{{$t('Common.download_btn')}}</el-button>
+            <el-button type="text" @click="handleBatchOpt('move')">{{$t('Common.move_btn')}}</el-button>
+            <el-button type="text" style="color: #f00" @click="handleBatchOpt('delete')">{{$t('Table.delete_btn')}}</el-button>
+            <el-button type="text" @click="isShowBatchOpt = false"
+              >{{$t('ReportManage.Material.cancel_batch_btn')}}</el-button
+            >
+          </div>
+        </div>
+        <tableNoData
+          :text="$t('Table.prompt_slogan')"
+          v-if="materialList.length === 0"
+        />
+        <ul
+          v-else
+          class="img-list-box"
+          v-infinite-scroll="loadMaterialList"
+          :infinite-scroll-immediate="false"
+        >
+          <li
+            class="img-item-box"
+            v-for="item in materialList"
+            :key="item.MaterialId"
+          >
+            <div class="opt-box">
+              <div class="item" @click="handleShowImgFull(item)">
+                <img src="~@/assets/img/icons/fullsreen.png" alt="" />
+              </div>
+              <el-dropdown @command="handleClickOpt">
+                <div class="item">
+                  <img src="~@/assets/img/icons/more.png" alt="" />
+                </div>
+                <el-dropdown-menu slot="dropdown">
+                  <el-dropdown-item 
+                    :command="{ type: 'edit', data: item }"
+                    v-permission="permissionBtn.reportMaterialPermission.material_rename"
+                    >{{$t('MyEtaPage.option_op_rename')}}</el-dropdown-item
+                  >
+                  <el-dropdown-item 
+                    :command="{ type: 'move', data: item }"
+                    v-permission="permissionBtn.reportMaterialPermission.material_move"
+                    >{{$t('Common.move_btn')}}</el-dropdown-item
+                  >
+                  <el-dropdown-item 
+                    :command="{ type: 'download', data: item }"
+                    v-permission="permissionBtn.reportMaterialPermission.material_download"
+                    >{{$t('Common.download_btn')}}</el-dropdown-item
+                  >
+                  <el-dropdown-item
+                    :command="{ type: 'del', data: item }"
+                    style="color: #ad352f"
+                    v-permission="permissionBtn.reportMaterialPermission.material_del"
+                    >{{ $t("Table.delete_btn") }}</el-dropdown-item
+                  >
+                </el-dropdown-menu>
+              </el-dropdown>
+            </div>
+            <div class="title-box">
+              <div class="title">{{ $i18nt.locale==='zh'?item.MaterialName:item.MaterialNameEn }}</div>
+              <label v-if="isShowBatchOpt" class="el-checkbox" @click="handleCheckMaterialItem(item)">
+                <span :class="['el-checkbox__input',materialCheckStatus(item)?'is-checked':'']">
+                  <span class="el-checkbox__inner"></span>
+                </span>
+              </label>
+            </div>
+            <img class="img-box" :src="item.ImgUrl" alt="" />
+            <div class="time-box">
+              <span>{{ item.CreateTime }}</span>
+              <span>{{ item.SysUserRealName }}</span>
+            </div>
+          </li>
+        </ul>
+      </div>
+    </div>
+
+    <!-- 上传图片 -->
+    <uploadImgs
+      :isShow="showUploadImg"
+      @close="showUploadImg = false"
+      @success="handleRefreshList"
+    />
+
+    <!-- 重命名 -->
+    <imgRename
+      :isShow="showImgRename"
+      :materialData="currentEditImgData"
+      @close="showImgRename = false"
+      @success="handleRefreshList"
+    />
+
+    <!-- 移动 -->
+    <imgMove
+      :isShow="showImgMove"
+      :materialData="currentEditImgData"
+      :batchOptData="batchOptData"
+      @close="showImgMove = false;batchOptData=null"
+      @success="handleRefreshList"
+    />
+
+    <!-- 预览图片 -->
+    <el-image-viewer
+      v-if="showViewer"
+      :on-close="
+        () => {
+          this.picShowList = [];
+          this.showViewer = false;
+        }
+      "
+      :url-list="picShowList"
+    />
+  </div>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+import classifyWrap from './components/classifyTree.vue'
+import imgRename from './components/imgRename.vue'
+import uploadImgs from './components/uploadImgs.vue'
+import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
+import imgMove from './components/imgMove.vue';
+export default {
+  components: { classifyWrap, uploadImgs, imgRename, ElImageViewer, imgMove },
+  computed:{
+    selectCount(){
+      if(this.checkAll){
+        return this.materialListTotal-this.selectMaterialArr.length
+      }else{
+        return this.selectMaterialArr.length
+      }
+    }
+  },
+  data() {
+    return {
+      searchVal: "",
+      page: 1,
+      pageSize: 100,
+      materialList: [],
+      finished: false,
+      materialListLoading: false,
+      activeClassifyId: 0,
+      materialListTotal: 0,
+
+
+      showUploadImg: false,
+      showImgRename: false,
+      showImgMove: false,
+      currentEditImgData: null,
+
+      showViewer: false,
+      picShowList: [],
+
+      // 批量操作
+      isShowBatchOpt: false,
+      checkAllStatus: false,
+      checkAll: false,
+      selectMaterialArr: [],
+
+      batchOptData:null,//批量操作选择的树
+    }
+  },
+  methods: {
+    // 批量操作
+    handleBatchOpt(type){
+      // 判断是否有勾选
+      if(!this.checkAll&&this.selectMaterialArr.length===0){
+        this.$message.warning('请至少选择一张图片')
+        return
+      }
+      const params={
+        ClassifyId:this.activeClassifyId,
+        MaterialIds:this.selectMaterialArr||[],
+        Keyword:this.searchVal,
+        IsSelectAll:this.checkAll
+      }
+      if(type==='download'){
+        this.handleBatchDownload(params)
+      }
+      if(type==='move'){
+        this.batchOptData=params
+        this.showImgMove=true
+      }
+      if(type==='delete'){
+        this.handleBatchDelete(params)
+      }
+    },
+    // 批量删除
+    async handleBatchDelete(params){
+      await this.$confirm(this.$t('ReportManage.Material.del_attention'), this.$t('Dialog.warn_tit'), {
+        type: 'warning'
+      })
+      const res = await apiReportMaterial.materialBatchDel(params)
+      if (res.Ret !== 200) return
+      this.$message.success(this.$t('MsgPrompt.delete_msg'))
+      this.handleRefreshList()
+    },
+
+    // 批量下载
+    handleBatchDownload(params){
+      const hostapi= process.env.VUE_APP_API_ROOT + "/material/batch/download"
+      const elink = document.createElement('a')
+			elink.style.display = 'none'
+			elink.href = `${hostapi}?ClassifyId=${params.ClassifyId}&MaterialIds=${params.MaterialIds.join(',')}&Keyword=${params.Keyword}&IsSelectAll=${params.IsSelectAll}&${localStorage.getItem("auth")}`
+			document.body.appendChild(elink)
+			elink.click()
+			document.body.removeChild(elink)
+    },
+
+    // 切换为批量操作
+    handleShowBatchOpt(){
+      this.checkAllStatus=false
+      this.checkAll=false
+      this.selectMaterialArr=[]
+      this.isShowBatchOpt=true
+    },
+    // 点击单个素材选择
+    handleCheckMaterialItem(item){
+      if(this.selectMaterialArr.includes(item.MaterialId)){
+        this.selectMaterialArr=this.selectMaterialArr.filter(i=>i!==item.MaterialId)
+      }else{
+        this.selectMaterialArr.push(item.MaterialId)
+      }
+      // 更新全选按钮状态
+      if(this.selectMaterialArr.length>0&&this.selectMaterialArr.length<this.materialListTotal){
+        this.checkAllStatus=true
+      }
+      if(this.checkAll){
+        if(this.selectMaterialArr.length===0){
+          this.checkAllStatus=false
+        }
+        if(this.selectMaterialArr.length===this.materialListTotal){
+          this.checkAll=false
+          this.checkAllStatus=false
+          this.selectMaterialArr=[]
+        }
+        
+      }else{
+        if(this.selectMaterialArr.length===this.materialListTotal){
+          this.checkAll=true
+          this.checkAllStatus=false
+          this.selectMaterialArr=[]
+        }
+      }
+    },
+    // 单个素材选中态的控制
+    materialCheckStatus(item) {
+      let flag = false
+      if (this.checkAll) {
+        if (!this.selectMaterialArr.includes(item.MaterialId)) {
+          flag = true
+        }
+      } else {
+        if (this.selectMaterialArr.includes(item.MaterialId)) {
+          flag = true
+        }
+      }
+      return flag
+    },
+    // 全选状态切换
+    handleCheckAllChange() {
+      // 清空选择
+      console.log('全选状态改变');
+      this.selectMaterialArr=[]
+      this.checkAllStatus=false
+    },
+
+    //搜索素材库
+    handleSearchList(){
+      this.activeClassifyId=0
+      this.$refs.classifyWrapIns.initSelect()
+      this.handleRefreshList()
+    },
+
+    // 刷新素材列表
+    handleRefreshList() {
+      this.page = 1
+      this.materialList = []
+      this.finished = false
+      this.isShowBatchOpt=false
+      this.getMaterialList()
+    },
+
+    // 获取图片列表
+    async getMaterialList() {
+      // if (!this.activeClassifyId) return
+      this.materialListLoading = true
+      const res = await apiReportMaterial.materialList({
+        ClassifyId: this.activeClassifyId,
+        Keyword: this.searchVal,
+        CurrentIndex: this.page,
+        PageSize: this.pageSize
+      })
+      this.materialListLoading = false
+      if (res.Ret !== 200) return
+      const arr = res.Data.List || []
+      this.materialList = [...this.materialList, ...arr]
+      this.finished = res.Data.Paging.IsEnd
+      this.materialListTotal = res.Data.Paging.Totals
+    },
+
+    loadMaterialList() {
+      if (this.finished) return
+      this.page++
+      this.getMaterialList()
+    },
+
+    // 选中分类改变
+    handleClassifyChange(e) {
+      this.activeClassifyId = e
+      this.handleRefreshList()
+    },
+
+    handleShowImgFull(item) {
+      this.picShowList = [item.ImgUrl]
+      this.showViewer = true
+    },
+
+    // 图片操作
+    handleClickOpt(e) {
+      if (e.type === 'edit') {
+        this.currentEditImgData = e.data
+        this.showImgRename = true
+      }
+
+      if (e.type === 'move') {
+        this.currentEditImgData = e.data
+        this.showImgMove = true
+      }
+
+      if (e.type === 'download') {
+        this.handleDownloadResource(e.data.ImgUrl, this.currentLang === 'en' ? e.data.MaterialNameEn : e.data.MaterialName)
+      }
+
+      if (e.type === 'del') {
+        this.handleImgDel(e.data.MaterialId)
+      }
+    },
+
+    // 图片删除
+    async handleImgDel(id) {
+      await this.$confirm(this.$t('ReportManage.Material.del_attention'), this.$t('Dialog.warn_tit'), {
+        type: 'warning'
+      })
+      const res = await apiReportMaterial.materialDel({
+        MaterialId: id
+      })
+      if (res.Ret !== 200) return
+      this.$message.success(this.$t('MsgPrompt.delete_msg'))
+      this.handleRefreshList()
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.top-wrap {
+  display: flex;
+  justify-content: space-between;
+  background: #ffffff;
+  border-radius: 4px;
+  padding: 20px;
+}
+.content-wrap {
+  margin-top: 20px;
+  display: flex;
+  height: calc(100vh - 250px);
+  .img-list-wrap {
+    flex: 1;
+    .top-box {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      border-bottom: 1px solid #C8CDD9;
+      margin-bottom: 20px;
+    }
+    .img-list-box {
+      display: flex;
+      flex-wrap: wrap;
+      align-content: flex-start;
+      gap: 10px;
+      height: calc(100vh - 320px);
+      overflow-y: auto;
+      .img-item-box {
+        background-color: #fff;
+        padding: 10px;
+        width: 200px;
+        position: relative;
+        .opt-box {
+          display: none;
+          position: absolute;
+          top: 60px;
+          right: 20px;
+          z-index: 5;
+          .item {
+            width: 24px;
+            height: 24px;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            background-color: #fff;
+            border-radius: 50%;
+            margin-left: 10px;
+            border: 1px solid #E6E6E6;
+            // color: #ffffff;
+            img {
+              width: 16px;
+              height: 16px;
+            }
+          }
+        }
+        &:hover {
+          .opt-box {
+            display: flex;
+          }
+          .select-box {
+            display: block;
+          }
+        }
+      }
+      .title-box {
+        display: flex;
+        overflow: hidden;
+        border-bottom: 1px solid #C8CDD9;
+        padding-bottom: 10px;
+        .title {
+          flex: 1;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          overflow: hidden;
+        }
+      }
+      .img-box {
+        width: 100%;
+        display: block;
+        height: 200px;
+        margin: 10px auto;
+      }
+      .time-box {
+        display: flex;
+        justify-content: space-between;
+      }
+    }
+  }
+}
+</style>

+ 81 - 10
src/views/report_manage/mixins/reportMixin.js

@@ -2,6 +2,7 @@ import * as sheetInterface from "@/api/modules/sheetApi.js";
 import { dataBaseInterface } from "@/api/api.js";
 import futuresInterface from "@/api/modules/futuresBaseApi";
 import chartRelevanceApi from "@/api/modules/chartRelevanceApi";
+import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
 import {
   fittingEquationInterface,
   statisticFeatureInterface,
@@ -54,16 +55,6 @@ export default {
           }}
         }
       },
-      panelTabs(){
-        return [
-            {key: "基础信息",label:this.$t('ReportManage.ReportList.information_title')},
-            {key: "图表插入",label:this.$t('ReportManage.ReportList.insert_chart_tabs')},
-            {key: "MyETA批量插入",label:this.$t('ReportManage.ReportList.bulk_insertion_tabs')},
-            {key: "表格插入",label:this.$t('ReportManage.ReportList.insert_table_tabs')},
-            {key: "沙盘插入",label:this.$t('ReportManage.ReportList.insert_sandbox_tabs')},
-            {key: "语义分析插入",label:this.$t('ReportManage.ReportList.semantic_analysis_tabs')},
-          ]
-      },
       
       //语言版本
       currentLang() {
@@ -241,6 +232,85 @@ export default {
 				selectableRange:'00:00:00 - 23:59:59',
         format:'HH:mm'
 			},
+      panelTabs:[
+        {
+          key: "基础信息",
+          label:this.$t('ReportManage.ReportList.information_title'),
+          path:''
+        },
+        {
+          key: "素材库",
+          label:this.$t('ReportManage.Material.material_name'),
+          path:'materialList'
+        },
+        {
+          key: "图表插入",
+          label:this.$t('ReportManage.ReportList.chart_top_type'),
+          path:''
+        },
+        {
+          key: "MyETA批量插入",
+          label:this.$t('ReportManage.ReportList.bulk_insertion_tabs'),
+          path:'mychart'
+        },
+        {
+          key: "表格插入",
+          label:this.$t('ReportManage.ReportList.eta_top_type'),
+          path:''
+        },
+        {
+          key: "平衡表",
+          label:this.$t('SystemManage.OperateAuth.tab_sub_sheet4'),
+          path:'sheetBalanceList'
+        },
+        {
+          key: "沙盘插入",
+          label:this.$t('ReportManage.ReportList.insert_sandbox_tabs'),
+          path:'sandlist'
+        },
+        {
+          key: "语义分析插入",
+          label:this.$t('ReportManage.ReportList.semantic_analysis_tabs'),
+          path:'semanticsPage'
+        },
+      ],
+      chartTypes:[
+        {
+          label: this.$t('ReportManage.ReportList.chart_inventory_radio'),
+          key: 1,
+          path: 'chartsetting'
+        },
+        {
+          label: this.$t('ReportManage.ReportList.price_curve_radio'),
+          key: 2,
+          path: 'commordityChartBase'
+        },
+        {
+          label: this.$t('ReportManage.ReportList.related_charts_radio'),
+          key: 3,
+          path: 'chartrelevance'
+        },
+        {
+          label: this.$t('ReportManage.ReportList.curve_fitting_radio'),
+          key: 6,
+          path: 'fittingEquationList'
+        },
+        {
+          label: this.$t('ReportManage.ReportList.statistical_feature_radio'),
+          key: 7,
+          path: 'statisticFeatureList'
+        },
+        {
+          label: this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
+          key: 10,
+          path: 'crossVarietyChartList'
+        },
+        {
+          label: this.$t('StatisticAnalysis.IntervalAnalysis.interval_analysis_name'),
+          key: 12,
+          path: 'rangeAnalysis'
+        }
+      ]
     };
   },
 
@@ -586,6 +656,7 @@ export default {
         6: fittingEquationInterface.searchChart,
         7: statisticFeatureInterface.searchChart,
         10: crossVarietyInterface.searchChart,
+        12: apiIntervalAnalysis.chartSearch
       }
       let res = await apiMap[this.chart_source](params)
 

+ 31 - 39
src/views/report_manage/reportEn/reportEditor.vue

@@ -207,12 +207,14 @@
 					>
 					</el-input>
 					<el-radio-group v-model="chart_source" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist()}" style="margin-top: 10px;">
-						<el-radio :label="1">{{$t('ReportManage.ReportList.chart_inventory_radio')}}</el-radio>
+						<el-radio v-for="item in chartTypes" :key="item.key" :label="item.key">{{item.label}}</el-radio>
+						<!-- <el-radio :label="1">{{$t('ReportManage.ReportList.chart_inventory_radio')}}</el-radio>
 						<el-radio :label="2">{{$t('ReportManage.ReportList.price_curve_radio')}}</el-radio> 
 						<el-radio :label="3">{{$t('ReportManage.ReportList.related_charts_radio')}}</el-radio>
 						<el-radio :label="6">{{$t('ReportManage.ReportList.curve_fitting_radio')}}</el-radio>
 						<el-radio :label="7">{{$t('ReportManage.ReportList.statistical_feature_radio')}}</el-radio>
 						<el-radio :label="10">{{$t('ReportManage.ReportList.intercommodity_analysis_radio')}}</el-radio>
+						<el-radio :label="12">{{$t('StatisticAnalysis.IntervalAnalysis.interval_analysis_name')}}</el-radio> -->
 					</el-radio-group>
 					<div style="margin: 10px 0">
 						<el-checkbox v-model="isShowMe" @change="() => {search_page=1;$refs.chartListRef.scrollTop = 0;getreportlist(key_word)}">
@@ -233,7 +235,7 @@
 								:style="item.Disabled && 'cursor: not-allowed;'"
 								class="liststy"
 							>
-								<div class="chartEn-mark" style="top: 0;left:0;" @click="setEnHandle(item)" v-if="item.HaveOperaAuth">
+								<div class="chartEn-mark" style="top: 0;left:0;" @click="setEnHandle(item)" v-if="item.HaveOperaAuth&&item.Source!=12">
 									<i class="el-icon-edit" style="font-size:18px"/>
 								</div>
 								<p class="color_primary">{{ chart_source===1 ? (item.ChartNameEn||item.ChartName) : item.ChartName }}</p>
@@ -249,7 +251,7 @@
 				</div>
 				<div v-if="tabsactive == '沙盘插入'">
 					<el-input
-						:placeholder="$t('ReportManage.ReportList.no_reports_msg')"
+						:placeholder="$t('ReportManage.ReportList.chart_name')"
 						v-model="sandTabelQuery.Keyword"
 						size="medium"
 						prefix-icon="el-icon-search"
@@ -284,38 +286,7 @@
 					</div>
 				</div>
 				<div v-if="tabsactive == '表格插入'">
-					<el-input
-						:placeholder="$t('ReportManage.ReportList.table_name_tabs')"
-						v-model="sheetSearchObj.Keyword"
-						size="medium"
-						prefix-icon="el-icon-search"
-						@input="getSheetList"
-					>
-					</el-input>
-					<div
-						style="
-							height: calc(100vh - 320px);
-							overflow-x: hidden;
-							overflow-y: auto;
-						"
-					>
-						<template v-if="sheetSearchList.length">
-							<div
-								v-for="item in sheetSearchList"
-								:key="item.ExcelInfoId"
-								class="liststy"
-							>
-								<p class="color_primary">{{ item.ExcelName }}</p>
-								<img
-									:src="!item.HaveOperaAuth?$icons.lock_big:item.ExcelImage"
-									:id="'sheet' + item.ExcelInfoId"
-									style="object-fit: contain;height: 250px;"
-									@click="insertHtml(item,'sheet')"
-								/>
-							</div>
-						</template>
-						<tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-else/>
-					</div>
+					<importSheet @insert="(item)=>insertHtml(item,'sheet')"/>
 				</div>
 				<div v-if="tabsactive == 'MyETA批量插入'">
 					<importMyChart @handleImportMyChart="handleImportMyChart" :showEnMark="true" />
@@ -323,6 +294,12 @@
 				<div v-if="tabsactive == '语义分析插入'">
 					<importSemantics @handleImportSemantic="(item)=>insertHtml(item,'image')"/>
 				</div>
+				<div v-if="tabsactive == '素材库'">
+					<importMaterial @insert="(item)=>insertHtml(item,'image')"/>
+				</div>
+				<div v-if="tabsactive == '平衡表'">
+					<importBalanceSheet @insert="(item)=>insertHtml(item,'sheet')"/>
+				</div>
 			</div>
 		</div>
 		<span
@@ -391,6 +368,9 @@ import reportApproveConfig from "@/mixins/reportApproveConfig.js"
 import importMyChart from '../components/importMyChart.vue'
 import setEnNameDia from '@/views/dataEntry_manage/components/setEnNameDia.vue'
 import importSemantics from '../components/importSemantics.vue';
+import importMaterial from '../components/importMaterial.vue'
+import importSheet from '../components/importSheet.vue';
+import importBalanceSheet from '../components/importBalanceSheet.vue'
 export default {
 	mixins:[mixinMsg,reportMixin,reportApproveConfig],
 	data() {
@@ -567,11 +547,12 @@ export default {
 	mounted() {
 		this.$route.query.id && this.getreportdetail();
 		this.getclassifylist();
-		this.getreportlist('');
+		// this.getreportlist('');
 		this.getreportauthor();
-		this.getSandTable();
-		this.getSheetList();
+		// this.getSandTable();
+		// this.getSheetList();
 		this.getSystemUserInfo()
+		this.initPanelTabs()
 		this.timer = setInterval(() => {
 			this.autoSave();
 		}, 6000);
@@ -613,6 +594,17 @@ export default {
 		}
 	},
 	methods: {
+		// 初始化插入项
+		initPanelTabs(){
+			this.panelTabs=this.panelTabs.filter(item=>this.verifyInsertModuleAuth(item.path))
+      if(this.panelTabs.some(i=>i.key==='沙盘插入')) this.getSandTable()
+			this.chartTypes=this.chartTypes.filter(item=>this.verifyInsertModuleAuth(item.path))
+			if(this.chartTypes.length>0){
+				this.chart_source=this.chartTypes[0].key
+				this.getreportlist('')
+			}
+		},
+
 		// 每十秒自动保存
 		autoSave() {
 			console.log(this.ischange);
@@ -1054,7 +1046,7 @@ export default {
 			})
 	},
 	},
-	components: {importMyChart,setEnNameDia,importSemantics},
+	components: {importMyChart,setEnNameDia,importSemantics,importMaterial,importSheet,importBalanceSheet},
 };
 </script>
 

+ 271 - 0
src/views/report_manage/reportV2/normalReport/components/BalanceSheet.vue

@@ -0,0 +1,271 @@
+<template>
+  <div class="eta-sheet-wrap">
+    <div class="label-name" style="position: relative; top: -20px">
+      <span style="cursor: pointer;" @click="handleClearSelectSheet">{{$t('SystemManage.OperateAuth.tab_sub_sheet4')}}</span>
+      <span v-if="showChildSheet"> > {{this.activeName}}</span>
+    </div>
+    <div v-show="!showChildSheet">
+    <div class="top-box">
+      <el-input
+        class="search-box"
+        :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+        v-model="keyword"
+        size="medium"
+        prefix-icon="el-icon-search"
+        @input="handleSearch"
+        style="width:300px"
+      />
+    </div>
+    <div class="main-box">
+      <el-checkbox
+        class="onlyshowme-box"
+        v-model="isShowMe"
+        @change="handleSearch"
+        >{{ $t("BalanceSheet.only_edit") }}</el-checkbox
+      >
+
+      <div
+        class="list-wrap"
+        v-infinite-scroll="handleLoadMore"
+        :infinite-scroll-immediate="true"
+      >
+        <div class="sheet-item" v-for="item in list" :key="item.ExcelInfoId">
+          <div class="title">{{ item.ExcelName }}</div>
+          <div
+            class="img"
+            :style="`backgroundImage:url(${
+              !item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage
+            })`"
+            @click="handleChooseSheet(item)"
+          ></div>
+          <img
+            :src="!item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage"
+            @click="handleChooseSheet(item)"
+          />
+        </div>
+        <tableNoData
+          :text="$t('Table.prompt_slogan')"
+          size="mini"
+          v-if="list.length === 0"
+        />
+      </div>
+    </div>
+    </div>
+    <!-- 选择子平衡表 -->
+    <div v-show="showChildSheet">
+    <div class="top-box">
+      <span>{{ $t("BalanceSheet.version") }}</span>
+        <el-select
+          v-model="version"
+          style="width: 200px;"
+          @change="handleVersionChange"
+        >
+          <el-option
+            v-for="item in versionOpts"
+            :key="item.ExcelInfoId"
+            :label="item.VersionName"
+            :value="item.ExcelInfoId"
+          ></el-option>
+        </el-select>
+    </div>
+    <div class="main-box">
+      <div
+        class="list-wrap"
+      >
+        <div class="sheet-item" v-for="item in childSheetList" :key="item.ExcelInfoId">
+          <div class="title">{{ item.ExcelName }}</div>
+          <div
+            class="img"
+            :style="`backgroundImage:url(${ item.ExcelImage})`"
+            @click="$emit('insertHtml',item)"
+          ></div>
+          <img
+            :src="item.ExcelImage"
+            @click="$emit('insertHtml',item)"
+          />
+        </div>
+        <tableNoData
+          :text="$t('Table.prompt_slogan')"
+          size="mini"
+          v-if="childSheetList.length === 0"
+        />
+      </div>
+    </div>
+    </div>
+  </div>
+  
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+  data() {
+    return {
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe: false,
+
+      showChildSheet:false,//显示平衡表子表
+      version:'',
+      versionOpts:[],
+      childSheetList:[],
+      activeName:''
+
+    }
+  },
+  created() {
+    this.getSheetList()
+  },
+  methods: {
+    // 获取版本列表
+    getVersionList(){
+      sheetInterface.balanceTableVersion({ExcelInfoId:this.version}).then(res=>{
+        if(res.Ret===200){
+          const arr=res.Data.List||[]
+          if(this.$i18nt.locale!=='zh'){
+            arr[0].VersionName='Active'
+          }
+          this.versionOpts=arr
+        }
+      })
+    },
+    //获取所有子表数据
+    async getChildTable(){
+      const res = await sheetInterface.getBalanceChildTable({
+				ParentId: Number(this.version)
+			})
+      if(res.Ret !== 200)  return
+      const arr=res.Data.List||[]
+      this.childSheetList=arr.map(item=>{
+        return {
+          ...item,
+          HaveOperaAuth:true
+        }
+      })
+    },
+    handleVersionChange(){
+      this.getChildTable()
+    },
+    // 选择某个平衡表
+    handleChooseSheet(item){
+      if(!item.HaveOperaAuth) return this.$message.warning(this.$t('MsgPrompt.no_sheet_auth'))
+      this.activeName=item.ExcelName
+      this.version=item.ExcelInfoId
+      this.getVersionList()
+      this.getChildTable()
+      this.showChildSheet=true
+    },
+    // 返回平衡表列表状态
+    handleClearSelectSheet(){
+      this.version=''
+      this.versionOpts=[]
+      this.childSheetList=[]
+      this.activeName=''
+      this.showChildSheet=false
+    },
+    
+
+    handleSearch() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getSheetList()
+    },
+    async getSheetList() {
+      this.loading = true
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page,
+        Source: 5,
+        KeyWord: this.keyword,
+        IsShowMe: this.isShowMe
+      };
+      let res = await sheetInterface.sheetList(params)
+      this.loading = false
+      if (res.Ret !== 200) return;
+      this.finished = res.Data.Paging.IsEnd
+      this.list = res.Data
+        ? this.page_no === 1
+          ? res.Data.List
+          : [...this.list, ...res.Data.List]
+        : [];
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getSheetList()
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+div {
+  box-sizing: border-box;
+}
+.eta-sheet-wrap {
+  .top-box {
+    .left-card {
+      width: fit-content;
+      margin-bottom: 15px;
+      border-radius: 4px;
+      border: 1px solid var(--unnamed, #dcdfe6);
+      background: var(--gary-gy-3-disabled, #ebeff6);
+      display: flex;
+      align-items: center;
+      padding: 6px;
+      .item {
+        cursor: pointer;
+        display: block;
+        width: 110px;
+        height: 30px;
+        line-height: 30px;
+        text-align: center;
+        border-radius: 4px;
+        font-size: 18px;
+        color: #666;
+        &.active {
+          background: #fff;
+          color: #002d78;
+        }
+      }
+    }
+  }
+  .main-box {
+    margin-top: 30px;
+    height: calc(100vh - 180px);
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #c8cdd9);
+    background: #fff;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    .list-wrap {
+      flex: 1;
+      overflow-y: auto;
+      display: flex;
+      flex-wrap: wrap;
+      align-items: flex-start;
+      gap: 0 20px;
+    }
+    .sheet-item {
+      width: 250px;
+      margin: 10px 0;
+      padding: 20px;
+      border: 1px solid #eaeaea;
+      border-radius: 10px;
+      font-size: 16px;
+      text-align: center;
+      img {
+        width: 100%;
+        height: 200px;
+      }
+    }
+  }
+}
+</style>

+ 29 - 3
src/views/report_manage/reportV2/normalReport/components/ETAChart.vue

@@ -2,8 +2,12 @@
     <div class="eta-chart-wrap">
         <div class="top-box">
             <div class="left-card">
-                <span :class="['item',activeType==='ETA图库'?'active':'']" @click="activeTypeChange('ETA图库')">{{$t('ReportManage.ReportList.chart_inventory_radio')}}</span>
-                <span :class="['item',activeType==='MyETA'?'active':'']" @click="activeTypeChange('MyETA')">{{$t('MyEtaPage.tab_my')}}</span>
+                <span 
+                    v-for="item in typeOpts" 
+                    :key="item.key"
+                    :class="['item',activeType===item.key?'active':'']"
+                    @click="activeTypeChange(item.key)"
+                >{{item.name}}</span>
             </div>
             <el-input
                 class="search-box"
@@ -13,6 +17,7 @@
                 prefix-icon="el-icon-search"
                 v-if="activeType==='ETA图库'"
                 @input="handleETAChartSearch"
+                style="width:300px"
             />
         </div>
         <ImportETAChart ref="ETAChartWrap" v-if="activeType==='ETA图库'" @insertHtml="item =>{$emit('insertHtml',item)}"/>
@@ -29,10 +34,31 @@ export default {
     data() {
         return {
             keyword:'',
-            activeType:'ETA图库',
+            activeType:'',
+            typeOpts:[
+                {
+                    name:this.$t('ReportManage.ReportList.chart_inventory_radio'),
+                    path:'chartsetting',
+                    key:'ETA图库'
+                },
+                {
+                    name:this.$t('MyEtaPage.tab_my'),
+                    path:'mychart',
+                    key:'MyETA'
+                }
+            ],
         }
     },
+    created() {
+        this.initTab()
+    },
     methods: {
+        initTab(){
+            this.typeOpts=this.typeOpts.filter(item=>this.verifyInsertModuleAuth(item.path))
+            if(this.typeOpts.length){
+                this.activeType=this.typeOpts[0].key
+            }
+        },
         activeTypeChange(e){
             if(this.activeType===e) return
             this.keyword = ''

+ 1 - 0
src/views/report_manage/reportV2/normalReport/components/ETAPriceChart.vue

@@ -9,6 +9,7 @@
 					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>

+ 2 - 2
src/views/report_manage/reportV2/normalReport/components/ETASandBox.vue

@@ -4,11 +4,11 @@
             <div class="right">
                 <el-input
                     class="search-box"
-					:placeholder="$t('ReportManage.ReportList.no_reports_msg')"
+					:placeholder="$t('ReportManage.ReportList.chart_name')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>

+ 89 - 20
src/views/report_manage/reportV2/normalReport/components/ETASheet.vue

@@ -1,6 +1,13 @@
 <template>
     <div class="eta-sheet-wrap">
         <div class="top-box">
+            <div class="left-card">
+                <span 
+                    :class="['item',table_source===item.key?'active':'']" @click="activeTypeChange(item)"
+                    v-for="item in typeArr"
+                    :key="item.key"
+                >{{item.label}}</span>
+            </div>
             <el-input
                 class="search-box"
 				:placeholder="$t('ReportManage.ReportList.table_name_tabs')"
@@ -8,9 +15,16 @@
 				size="medium"
 				prefix-icon="el-icon-search"
                 @input="handleSearch"
+                style="width:300px"
 			/>
         </div>
         <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleSearch"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+
             <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
             <div class="sheet-item" v-for="item in list" :key="item.ExcelInfoId">
                 <div class="title">{{item.ExcelName}}</div>
@@ -36,35 +50,69 @@ export default {
             page:1,
             pageSize:20,
             finished:false,
-            loading:false
+            loading:false,
+            isShowMe: false,
+            table_source: 1,
+            typeArr:[
+                {
+                    label:this.$t('CustomAnalysisPage.table_share')||'共享表格',
+                    path:'sheetList',
+                    key:1
+                },
+                {
+                    label:this.$t('SystemManage.OperateAuth.tab_sub_sheet2')||'时间序列表格',
+                    path:'sheetTimeList',
+                    key:2
+                },
+                {
+                    label:this.$t('SystemManage.OperateAuth.tab_sub_sheet3')||'混合表格',
+                    path:'sheetMixedList',
+                    key:3
+                }
+            ],
         }
     },
     created(){
-        this.getSheetList()
+        this.initStatus()
     },
     methods: {
+        async initStatus(){
+            this.typeArr=this.typeArr.filter(item=>this.verifyInsertModuleAuth(item.path))
+            if(this.typeArr.length>0){
+                this.table_source=this.typeArr[0].key
+                this.getSheetList()
+            }
+        },
         handleSearch(){
             this.list=[]
             this.page=1
             this.finished=false
             this.getSheetList()
         },
-        getSheetList() {
+        activeTypeChange(item){
+            this.table_source=item.key
+            this.isShowMe=false
+            this.keyword=''
+            this.handleSearch()
+        },
+        async getSheetList() {
             this.loading=true
-            sheetInterface.sheetList({
-                KeyWord: this.keyword,
-                CurrentIndex: this.page,
+            let params = {
                 PageSize: this.pageSize,
-            }).then((res) => {
-                this.loading=false
-                if (res.Ret !== 200) return;
-                const arr = res.Data.List || [];
-                this.list =
-                    this.page === 1
-                    ? arr
-                    : [...this.list, ...arr];
-                this.finished =  res.Data.Paging.IsEnd;
-            });
+                CurrentIndex: this.page,
+                Source: this.table_source,
+                KeyWord: this.keyword,
+                IsShowMe: this.isShowMe
+            };
+            let res = await sheetInterface.sheetList(params)
+            this.loading=false
+            if (res.Ret !== 200) return;
+            this.finished = res.Data.Paging.IsEnd
+            this.list = res.Data
+                ? this.page_no === 1
+                ? res.Data.List
+                : [...this.list, ...res.Data.List]
+                : [];
         },
 
         handleLoadMore(){
@@ -82,10 +130,30 @@ div{
 }
 .eta-sheet-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        .search-box{
-            width: 330px;
+        .left-card{
+            width: fit-content;
+            margin-bottom: 15px;
+            border-radius: 4px;
+            border: 1px solid var(--unnamed, #DCDFE6);
+            background: var(--gary-gy-3-disabled, #EBEFF6);
+            display: flex;
+            align-items: center;
+            padding: 6px;
+            .item{
+                cursor: pointer;
+                display: block;
+                width: 110px;
+                height: 30px;
+                line-height: 30px;
+                text-align: center;
+                border-radius: 4px;
+                font-size: 18px;
+                color: #666;
+                &.active{
+                    background: #FFF;
+                    color: #002D78;
+                }
+            }
         }
     }
     .main-box{
@@ -102,6 +170,7 @@ div{
             overflow-y: auto;
             display: flex;
             flex-wrap: wrap;
+            align-items: flex-start;
             gap: 0 20px;
 
         }

+ 200 - 0
src/views/report_manage/reportV2/normalReport/components/Material.vue

@@ -0,0 +1,200 @@
+<template>
+  <div class="statistic-analysis-wrap">
+    <div class="label-name" style="position: relative; top: -20px">{{$t('ReportManage.Material.material_name')}}</div>
+    <div class="top-box">
+      <div class="right" style="display: flex;flex-wrap:wrap;gap:5px">
+        <el-cascader
+          v-model="classify"
+          :options="classifyOpts"
+          :placeholder="$t('MsgPrompt.select_category')"
+          :props="{
+            checkStrictly: true,
+            emitPath: false,
+            value: 'ClassifyId',
+            label: 'ClassifyName',
+            children: 'Children',
+          }"
+          style="width: 200px"
+          @change="handleRefreshList"
+        />
+        <el-input
+          class="search-box"
+          :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+          v-model="keyword"
+          size="medium"
+          prefix-icon="el-icon-search"
+          @input="handleRefreshList"
+          style="width:300px"
+        />
+      </div>
+    </div>
+    <div class="main-box">
+      <el-checkbox
+        class="onlyshowme-box"
+        v-model="isShowMe"
+        @change="handleRefreshList"
+        >{{ $t("ReportManage.ReportList.just_mine_radio") }}</el-checkbox
+      >
+      <div
+        class="list-wrap"
+        v-infinite-scroll="handleLoadMore"
+        :infinite-scroll-immediate="true"
+      >
+        <div class="chart-item" v-for="item in list" :key="item.MaterialId">
+          <div class="title">{{ item.MaterialName }}</div>
+          <img
+            :src="item.ImgUrl"
+            @click="$emit('insertHtml', { ...item, PicUrl: item.ImgUrl })"
+          />
+          <div style="display:flex;justify-content:space-between;font-size:12px">
+            <span>{{ item.CreateTime }}</span>
+            <span>{{ item.SysUserRealName }}</span>
+          </div>
+        </div>
+        <tableNoData
+          :text="$t('Table.prompt_slogan')"
+          size="mini"
+          v-if="list.length === 0 && finished"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  data() {
+    return {
+      classifyOpts: [],
+      classify: '',
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe:false
+    }
+  },
+  created() {
+    this.getClassifyOpt()
+    this.getMaterialList()
+  },
+  methods: {
+
+    handleRefreshList() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getMaterialList()
+    },
+
+    /* 搜索图表分页 */
+    async getMaterialList(word) {
+      this.loading = true
+      const res = await apiReportMaterial.materialList({
+        ClassifyId: this.classify,
+        Keyword: this.keyword,
+        CurrentIndex: this.page,
+        PageSize: this.pageSize,
+        IsShowMe:this.isShowMe
+      })
+      this.loading = false
+      if (res.Ret !== 200) return;
+      const arr = res.Data.List || [];
+      this.list =
+        this.page === 1
+          ? arr
+          : [...this.list, ...arr];
+      this.finished = res.Data.Paging.IsEnd;
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getMaterialList()
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+<style lang="scss">
+.statistic-analysis-wrap {
+  .top-box {
+    .right {
+      .search-box {
+        .el-input__inner{
+          height: 40px;
+          line-height: 40px;
+        }
+      }
+    }
+  }
+}
+</style>
+<style lang="scss" scoped>
+div {
+  box-sizing: border-box;
+}
+.statistic-analysis-wrap {
+  .top-box {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .right {
+      .search-box {
+        width: 330px;
+      }
+    }
+  }
+  .main-box {
+    margin-top: 30px;
+    height: calc(100vh - 180px);
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #c8cdd9);
+    background: #fff;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    .list-wrap {
+      flex: 1;
+      overflow-y: auto;
+      display: flex;
+      flex-wrap: wrap;
+      align-content: flex-start;
+      gap: 0 20px;
+    }
+  }
+}
+.chart-item {
+  width: 250px;
+  margin: 10px 0;
+  padding: 20px;
+  border: 1px solid #eaeaea;
+  border-radius: 10px;
+  font-size: 16px;
+  text-align: center;
+  img {
+    width: 100%;
+    height: 200px;
+  }
+}
+</style>

+ 1 - 1
src/views/report_manage/reportV2/normalReport/components/SemanticAnalysis.vue

@@ -6,9 +6,9 @@
                     class="search-box"
 					:placeholder="$t('ReportManage.ReportList.keyword_search')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>

+ 43 - 27
src/views/report_manage/reportV2/normalReport/components/StatisticAnalysis.vue

@@ -14,9 +14,9 @@
                     class="search-box"
 					:placeholder="$t('ReportManage.ReportList.chart_name')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>
@@ -48,25 +48,60 @@ import {
   statisticFeatureInterface,
   crossVarietyInterface
 } from "@/api/modules/chartRelevanceApi";
+import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
 export default {
     data() {
         return {
 
             keyword:'',
             isShowMe:false,
-            activeType:'相关性',
+            activeType:'',
 
             list:[],
             page:1,
             pageSize:20,
             finished:false,
-            loading:false
+            loading:false,
+            typeOpts:[
+                {
+                    name:this.$t('ReportManage.ReportList.correlation_analysis'),
+                    key:'相关性',
+                    path:'chartrelevance'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.curve_fitting_radio'),
+                    key:'拟合方程曲线',
+                    path:'fittingEquationList'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.statistical_feature_radio'),
+                    key:'统计特征',
+                    path:'statisticFeatureList'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
+                    key:'跨品种分析',
+                    path:'crossVarietyChartList'
+                },
+                {
+                    name:this.$t('StatisticAnalysis.IntervalAnalysis.interval_analysis_name'),
+                    key:'区间分析',
+                    path:'rangeAnalysis'
+                }
+            ]
         }
     },
     created(){
-        this.getChartList()
+        this.initTypeOpts()
     },
     methods: {
+        initTypeOpts(){
+            this.typeOpts=this.typeOpts.filter(item=>this.verifyInsertModuleAuth(item.path))
+            if(this.typeOpts.length){
+                this.activeType=this.typeOpts[0].key
+                this.getChartList()
+            }
+        },
 
         activeTypeChange(e){
             this.list=[]
@@ -110,6 +145,8 @@ export default {
                 res = await statisticFeatureInterface.searchChart(params);
             } else if (this.activeType === '跨品种分析') {
                 res = await crossVarietyInterface.searchChart(params);
+            }else if(this.activeType==='区间分析'){
+                res=await apiIntervalAnalysis.chartSearch(params)
             }
             this.loading=false
 
@@ -127,28 +164,6 @@ export default {
             this.page++
             this.getChartList()
         }
-    },
-    computed:{
-      typeOpts(){
-        return [
-                {
-                    name:this.$t('ReportManage.ReportList.correlation_analysis'),
-                    key:'相关性'
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.curve_fitting_radio'),
-                    key:'拟合方程曲线'
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.statistical_feature_radio'),
-                    key:'统计特征'
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
-                    key:'跨品种分析'
-                }
-            ]
-      }
     }
 }
 </script>
@@ -160,6 +175,7 @@ div{
 .statistic-analysis-wrap{
     .top-box{
         .left-card{
+            width: fit-content;
             margin-bottom: 15px;
             border-radius: 4px;
             border: 1px solid var(--unnamed, #DCDFE6);
@@ -206,7 +222,7 @@ div{
             display: flex;
             flex-wrap: wrap;
             gap: 0 20px;
-
+            align-content: flex-start;
         }
     }
 }

+ 16 - 2
src/views/report_manage/reportV2/normalReport/components/insertContent.vue

@@ -19,7 +19,10 @@
     <ETASandBox v-if="actTab==='etaSandBox'" @insertHtml="item=>{$emit('insertHtml',{item,type:'image'})}"/>
     <!-- 语义分析 -->
     <SemanticAnalysis v-if="actTab==='semanticAnalysis'" @insertHtml="item => {$emit('insertHtml',{item,type:'image'})}"/>
-
+    <!-- 素材库 -->
+    <Material v-if="actTab==='material'" @insertHtml="item=>{$emit('insertHtml',{item,type:'image'})}"/>
+    <!-- 平衡表 -->
+    <BalanceSheet v-if="actTab==='balanceSheet'" @insertHtml="item=>{$emit('insertHtml',{item,type:'sheet'})}"/>
   </div>
 </template>
 <script>
@@ -29,13 +32,24 @@ import StatisticAnalysis from './StatisticAnalysis.vue'
 import ETAPriceChart from './ETAPriceChart.vue'
 import ETASandBox from './ETASandBox.vue'
 import SemanticAnalysis from './SemanticAnalysis.vue'
+import Material from './Material.vue'
+import BalanceSheet from './BalanceSheet.vue'
 export default {
   props: {
     actTab: {
       type: String
     }
   },
-  components: {ETAChart,ETASheet,StatisticAnalysis,ETAPriceChart,ETASandBox,SemanticAnalysis  },
+  components: {
+    ETAChart,
+    ETASheet,
+    StatisticAnalysis,
+    ETAPriceChart,
+    ETASandBox,
+    SemanticAnalysis,
+    Material,
+    BalanceSheet  
+  },
   data() {
     return {
     }

+ 1 - 0
src/views/report_manage/reportV2/normalReport/editReport.vue

@@ -190,6 +190,7 @@ export default {
 	created() {
 		this.reportCoopType = Number(this.$route.query.coopType)
 		this.getPublicSettings()
+		this.getInsertTabsData()
 	},
 	mounted() {
 		

+ 99 - 34
src/views/report_manage/reportV2/normalReport/mixins/reportMixin.js

@@ -54,40 +54,50 @@ export default {
           }}
         }
       },
-      insertTabs(){
-        return [
-            {
-              name:this.$t('ReportManage.ReportList.chart_top_type'),
-              type:'etaChart',
-              icon:require('@/assets/img/smartReport/icon04.png')
-            },
-            {
-                name:this.$t('ReportManage.ReportList.eta_top_type'),
-                type:'etaSheet',
-                icon:require('@/assets/img/smartReport/icon05.png')
-            },
-            {
-                name:this.$t('ReportManage.ReportList.statistical_top_type'),
-                type:'statisticAnalysis',
-                icon:require('@/assets/img/smartReport/icon06.png')
-            },
-            {
-                name:this.$t('ReportManage.ReportList.price_curve_radio'),
-                type:'etaPriceChart',
-                icon:require('@/assets/img/smartReport/icon07.png')
-            },
-            {
-                name:this.$t('ReportManage.ReportList.sandbox_top_type'),
-                type:'etaSandBox',
-                icon:require('@/assets/img/smartReport/icon08.png')
-            },
-            {
-                name:this.$t('ReportManage.ReportList.semantic_top_type'),
-                type:'semanticAnalysis',
-                icon:require('@/assets/img/smartReport/icon09.png')
-            }
-          ]
-      },
+      // insertTabs(){
+      //   return [
+      //       {
+      //         name:'素材库',
+      //         type:'material',
+      //         icon:require('@/assets/img/smartReport/icon04.png')
+      //       },
+      //       {
+      //         name:this.$t('ReportManage.ReportList.chart_top_type'),
+      //         type:'etaChart',
+      //         icon:require('@/assets/img/smartReport/icon04.png')
+      //       },
+      //       {
+      //           name:this.$t('ReportManage.ReportList.eta_top_type'),
+      //           type:'etaSheet',
+      //           icon:require('@/assets/img/smartReport/icon05.png')
+      //       },
+      //       {
+      //         name:this.$t('SystemManage.OperateAuth.tab_sub_sheet4'),
+      //         type:'balanceSheet',
+      //         icon:require('@/assets/img/smartReport/icon05.png')
+      //       },
+      //       {
+      //           name:this.$t('ReportManage.ReportList.statistical_top_type'),
+      //           type:'statisticAnalysis',
+      //           icon:require('@/assets/img/smartReport/icon06.png')
+      //       },
+      //       {
+      //           name:this.$t('ReportManage.ReportList.price_curve_radio'),
+      //           type:'etaPriceChart',
+      //           icon:require('@/assets/img/smartReport/icon07.png')
+      //       },
+      //       {
+      //           name:this.$t('ReportManage.ReportList.sandbox_top_type'),
+      //           type:'etaSandBox',
+      //           icon:require('@/assets/img/smartReport/icon08.png')
+      //       },
+      //       {
+      //           name:this.$t('ReportManage.ReportList.semantic_top_type'),
+      //           type:'semanticAnalysis',
+      //           icon:require('@/assets/img/smartReport/icon09.png')
+      //       }
+      //     ]
+      // },
       
       //语言版本
       currentLang() {
@@ -249,10 +259,65 @@ export default {
 				selectableRange:'00:00:00 - 23:59:59',
         format:'HH:mm'
 			},
+
+      insertTabs:[
+        {
+          name:this.$t('ReportManage.Material.material_name'),
+          type:'material',
+          icon:require('@/assets/img/smartReport/icon19.png'),
+          path:'materialList'
+        },
+        {
+          name:this.$t('ReportManage.ReportList.chart_top_type'),
+          type:'etaChart',
+          icon:require('@/assets/img/smartReport/icon04.png'),
+          path:''
+        },
+        {
+            name:this.$t('ReportManage.ReportList.eta_top_type'),
+            type:'etaSheet',
+            icon:require('@/assets/img/smartReport/icon05.png'),
+            path:''
+        },
+        {
+          name:this.$t('SystemManage.OperateAuth.tab_sub_sheet4'),
+          type:'balanceSheet',
+          icon:require('@/assets/img/smartReport/icon20.png'),
+          path:'sheetBalanceList'
+        },
+        {
+            name:this.$t('ReportManage.ReportList.statistical_top_type'),
+            type:'statisticAnalysis',
+            icon:require('@/assets/img/smartReport/icon06.png'),
+            path:''
+        },
+        {
+            name:this.$t('ReportManage.ReportList.price_curve_radio'),
+            type:'etaPriceChart',
+            icon:require('@/assets/img/smartReport/icon07.png'),
+            path:'commordityChartBase'
+        },
+        {
+            name:this.$t('ReportManage.ReportList.sandbox_top_type'),
+            type:'etaSandBox',
+            icon:require('@/assets/img/smartReport/icon08.png'),
+            path:'sandlist'
+        },
+        {
+            name:this.$t('ReportManage.ReportList.semantic_top_type'),
+            type:'semanticAnalysis',
+            icon:require('@/assets/img/smartReport/icon09.png'),
+            path:'semanticsPage'
+        }
+      ],
     };
   },
 
   methods: {
+    async getInsertTabsData(){
+      this.insertTabs=this.insertTabs.filter(item=>this.verifyInsertModuleAuth(item.path))
+    },
+
     insertHtml({item, type = "chart"}) {
       const noAuthMsg = {
         'chart': this.$t('MsgPrompt.no_chart_auth'),

+ 312 - 0
src/views/report_manage/reportV2/smartReport/components/BalanceSheet.vue

@@ -0,0 +1,312 @@
+<template>
+  <div class="eta-sheet-wrap">
+    <div class="label-name" style="position: relative; margin-bottom: 10px">
+      <span style="cursor: pointer" @click="handleClearSelectSheet">{{
+        $t("SystemManage.OperateAuth.tab_sub_sheet4")
+      }}</span>
+      <span v-if="showChildSheet"> > {{ this.activeName }}</span>
+    </div>
+
+    <div v-show="!showChildSheet">
+      <div class="top-box">
+        <div class="right">
+          <el-input
+            class="search-box"
+            :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+            v-model="keyword"
+            prefix-icon="el-icon-search"
+            @input="handleSearch"
+            style="width:300px"
+          />
+        </div>
+      </div>
+      <div class="main-box">
+        <el-checkbox
+          class="onlyshowme-box"
+          v-model="isShowMe"
+          @change="handleSearch"
+          >{{ $t("BalanceSheet.only_edit") }}</el-checkbox
+        >
+
+        <div
+          class="list-wrap"
+          v-infinite-scroll="handleLoadMore"
+          :infinite-scroll-immediate="true"
+        >
+          <div class="sheet-list-box">
+            <div
+              style="cursor: default"
+              class="sheet-item"
+              @click="handleChooseSheet(item)"
+              v-for="item in list"
+              :key="item.ExcelInfoId"
+            >
+              <div class="title">{{ item.ExcelName }}</div>
+              <div
+                class="img"
+                :style="`backgroundImage:url(${
+                  !item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage
+                })`"
+              ></div>
+            </div>
+          </div>
+          <tableNoData
+            :text="$t('Table.prompt_slogan')"
+            size="mini"
+            v-if="list.length === 0"
+          />
+        </div>
+      </div>
+    </div>
+
+    <!-- 选择子平衡表 -->
+    <div v-show="showChildSheet">
+      <div class="top-box">
+        <span>{{ $t("BalanceSheet.version") }}</span>
+        <el-select
+          v-model="version"
+          style="width: 200px"
+          @change="handleVersionChange"
+        >
+          <el-option
+            v-for="item in versionOpts"
+            :key="item.ExcelInfoId"
+            :label="item.VersionName"
+            :value="item.ExcelInfoId"
+          ></el-option>
+        </el-select>
+      </div>
+      <div class="main-box">
+        <div class="list-wrap">
+          <draggable
+            :list="list"
+            :group="{ name: 'component', pull: 'clone', put: false }"
+            class="sheet-list-box"
+            animation="300"
+            :sort="false"
+            tag="div"
+          >
+            <div
+              class="sheet-item"
+              :comp-data="getCompData(item)"
+              v-for="item in childSheetList"
+              :key="item.ExcelInfoId"
+            >
+              <div class="title">{{ item.ExcelName }}</div>
+              <div
+                class="img"
+                :style="`backgroundImage:url(${
+                  !item.HaveOperaAuth ? $icons.lock_big : item.ExcelImage
+                })`"
+              ></div>
+            </div>
+          </draggable>
+          <tableNoData
+            :text="$t('Table.prompt_slogan')"
+            size="mini"
+            v-if="childSheetList.length === 0"
+          />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+  data() {
+    return {
+      keyword: "",
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe: false,
+
+      showChildSheet: false, //显示平衡表子表
+      version: "",
+      versionOpts: [],
+      childSheetList: [],
+      activeName: "",
+    };
+  },
+  created() {
+    this.getSheetList();
+  },
+  methods: {
+    // 获取版本列表
+    getVersionList() {
+      sheetInterface.balanceTableVersion({ ExcelInfoId: this.version }).then((res) => {
+        if (res.Ret === 200) {
+          const arr = res.Data.List || [];
+          if (this.$i18nt.locale !== "zh") {
+            arr[0].VersionName = "Active";
+          }
+          this.versionOpts = arr;
+        }
+      });
+    },
+    //获取所有子表数据
+    async getChildTable() {
+      const res = await sheetInterface.getBalanceChildTable({
+        ParentId: Number(this.version),
+      });
+      if (res.Ret !== 200) return;
+      const arr = res.Data.List || [];
+      this.childSheetList = arr.map((item) => {
+        return {
+          ...item,
+          HaveOperaAuth: true,
+        };
+      });
+    },
+    handleVersionChange() {
+      this.getChildTable();
+    },
+
+    // 选择某个平衡表
+    handleChooseSheet(item) {
+      if (!item.HaveOperaAuth) return this.$message.warning(this.$t("MsgPrompt.no_sheet_auth"));
+      this.activeName = item.ExcelName;
+      this.version = item.ExcelInfoId;
+      this.getVersionList();
+      this.getChildTable();
+      this.showChildSheet = true;
+    },
+    // 返回平衡表列表状态
+    handleClearSelectSheet() {
+      this.version = "";
+      this.versionOpts = [];
+      this.childSheetList = [];
+      this.activeName = "";
+      this.showChildSheet = false;
+    },
+
+    handleSearch() {
+      this.list = [];
+      this.page = 1;
+      this.finished = false;
+      this.getSheetList();
+    },
+
+    async getSheetList() {
+      this.loading = true;
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page,
+        Source: 5,
+        KeyWord: this.keyword,
+        IsShowMe: this.isShowMe,
+      };
+      let res = await sheetInterface.sheetList(params);
+      this.loading = false;
+      if (res.Ret !== 200) return;
+      this.finished = res.Data.Paging.IsEnd;
+      this.list = res.Data ? (this.page_no === 1 ? res.Data.List : [...this.list, ...res.Data.List]) : [];
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return;
+      this.page++;
+      this.getSheetList();
+    },
+
+    getCompData(item) {
+      const LINK_URL = this.$setting.dynamicOutLinks.ChartViewUrl + "/sheetshow";
+      // console.log(LINK_URL);
+      const obj = {
+        compId: 4,
+        compType: "sheet",
+        content: `${LINK_URL}?code=${item.UniqueCode}&fromScene=1`,
+        title: item.ExcelName,
+      };
+      return JSON.stringify(obj);
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+div {
+  box-sizing: border-box;
+}
+.eta-sheet-wrap {
+  .top-box {
+    // display: flex;
+    // justify-content: space-between;
+    // align-items: center;
+    .left-card {
+      border-radius: 4px;
+      border: 1px solid var(--unnamed, #dcdfe6);
+      background: var(--gary-gy-3-disabled, #ebeff6);
+      display: flex;
+      align-items: center;
+      padding: 6px;
+      .item {
+        cursor: pointer;
+        display: block;
+        width: 110px;
+        height: 30px;
+        line-height: 30px;
+        text-align: center;
+        border-radius: 4px;
+        font-size: 18px;
+        color: #666;
+        &.active {
+          background: #fff;
+          color: #002d78;
+        }
+      }
+    }
+    .right {
+      .search-box {
+        width: 330px;
+      }
+    }
+  }
+  .main-box {
+    margin-top: 30px;
+    height: calc(100vh - 220px);
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #c8cdd9);
+    background: #fff;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    .list-wrap {
+      flex: 1;
+      overflow-y: auto;
+    }
+    .sheet-list-box {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 20px;
+      .sheet-item {
+        cursor: move;
+        padding: 0 10px 10px 10px;
+        width: 250px;
+        border-radius: 4px;
+        border: 1px solid var(--gary-gy-5-line, #c8cdd9);
+        background: var(--gary-gy-white, #fff);
+        .title {
+          padding: 10px 0;
+          text-align: center;
+          border-bottom: 1px solid #c8cdd9;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+        }
+        .img {
+          width: 100%;
+          height: 197px;
+          background-size: contain;
+          background-position: center;
+          background-repeat: no-repeat;
+        }
+      }
+    }
+  }
+}
+</style>

+ 38 - 10
src/views/report_manage/reportV2/smartReport/components/ETAChart.vue

@@ -2,18 +2,22 @@
     <div class="eta-chart-wrap">
         <div class="top-box">
             <div class="left-card">
-                <span :class="['item',activeType==='ETA图库'?'active':'']" @click="activeTypeChange('ETA图库')">{{$t('ReportManage.ReportList.chart_inventory_radio')}}</span>
-                <span :class="['item',activeType==='MyETA'?'active':'']" @click="activeTypeChange('MyETA')">{{$t('MyEtaPage.tab_my')}}</span>
+                <span 
+                    v-for="item in typeOpts" 
+                    :key="item.key"
+                    :class="['item',activeType===item.key?'active':'']"
+                    @click="activeTypeChange(item.key)"
+                >{{item.name}}</span>
             </div>
             <div class="right">
                 <el-input
                     class="search-box"
 					:placeholder="$t('ReportManage.ReportList.chart_name')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     v-if="activeType==='ETA图库'"
                     @input="handleETAChartSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>
@@ -33,10 +37,31 @@ export default {
     data() {
         return {
             keyword:'',
-            activeType:'ETA图库',
+            activeType:'',
+            typeOpts:[
+                {
+                    name:this.$t('ReportManage.ReportList.chart_inventory_radio'),
+                    path:'chartsetting',
+                    key:'ETA图库'
+                },
+                {
+                    name:this.$t('MyEtaPage.tab_my'),
+                    path:'mychart',
+                    key:'MyETA'
+                }
+            ],
         }
     },
+    created() {
+        this.initTab()
+    },
     methods: {
+        initTab(){
+            this.typeOpts=this.typeOpts.filter(item=>this.verifyInsertModuleAuth(item.path))
+            if(this.typeOpts.length){
+                this.activeType=this.typeOpts[0].key
+            }
+        },
         activeTypeChange(e){
             if(this.activeType===e) return
             this.activeType=e
@@ -59,13 +84,14 @@ div{
 }
 .eta-chart-wrap{
     width: 100%;
-    min-width: 600px;
+    // min-width: 600px;
     overflow-x: auto;
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
         .left-card{
+            width: fit-content;
             border-radius: 4px;
             border: 1px solid var(--unnamed, #DCDFE6);
             background: var(--gary-gy-3-disabled, #EBEFF6);
@@ -89,14 +115,16 @@ div{
             }
         }
         .right{
+            margin-top: 20px;
+            min-height: 40px;
             .search-box{
-                width: 330px;
+                width: 250px;
             }
         }
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 220px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 7 - 6
src/views/report_manage/reportV2/smartReport/components/ETAPriceChart.vue

@@ -9,9 +9,9 @@
                     class="search-box"
 					placeholder="图表名称"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>
@@ -124,18 +124,19 @@ div{
 }
 .statistic-analysis-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
         .right{
+            margin-top: 20px;
             .search-box{
-                width: 330px;
+                width: 240px;
             }
         }
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 220px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 8 - 7
src/views/report_manage/reportV2/smartReport/components/ETASandBox.vue

@@ -7,11 +7,11 @@
             <div class="right">
                 <el-input
                     class="search-box"
-					:placeholder="$t('ReportManage.ReportList.no_reports_msg')"
+					:placeholder="$t('ReportManage.ReportList.chart_name')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>
@@ -116,18 +116,19 @@ div{
 }
 .statistic-analysis-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
         .right{
+            margin-top: 20px;
             .search-box{
-                width: 330px;
+                width: 240px;
             }
         }
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 220px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 109 - 30
src/views/report_manage/reportV2/smartReport/components/ETASheet.vue

@@ -1,17 +1,33 @@
 <template>
     <div class="eta-sheet-wrap">
         <div class="top-box">
-            <span>{{$t('ReportManage.ReportList.eta_top_type')}}</span>
-            <el-input
-                class="search-box"
-				:placeholder="$t('ReportManage.ReportList.table_name_tabs')"
-				v-model="keyword"
-				size="medium"
-				prefix-icon="el-icon-search"
-                @input="handleSearch"
-			/>
+            <!-- <span>{{$t('ReportManage.ReportList.eta_top_type')}}</span> -->
+            <div class="left-card">
+                <span 
+                    :class="['item',table_source===item.key?'active':'']" @click="activeTypeChange(item)"
+                    v-for="item in typeArr"
+                    :key="item.key"
+                >{{item.label}}</span>
+            </div>
+            <div class="right">
+                <el-input
+                    class="search-box"
+                    :placeholder="$t('ReportManage.ReportList.table_name_tabs')"
+                    v-model="keyword"
+                    prefix-icon="el-icon-search"
+                    @input="handleSearch"
+                    style="width:300px"
+                />
+            </div>
+            
         </div>
         <div class="main-box">
+            <el-checkbox
+                class="onlyshowme-box"
+                v-model="isShowMe" 
+                @change="handleSearch"
+            >{{$t('ReportManage.ReportList.just_mine_radio')}}</el-checkbox>
+
             <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="true">
             <draggable
                 :list="list"
@@ -35,6 +51,7 @@
 
 <script>
 import * as sheetInterface from "@/api/modules/sheetApi.js";
+// import apiBiBoard from '@/api/modules/BIBoard.js'
 export default {
     data() {
         return {
@@ -43,13 +60,39 @@ export default {
             page:1,
             pageSize:20,
             finished:false,
-            loading:false
+            loading:false,
+            isShowMe: false,
+            table_source: 1,
+            typeArr:[
+                {
+                    label:this.$t('CustomAnalysisPage.table_share')||'共享表格',
+                    path:'sheetList',
+                    key:1
+                },
+                {
+                    label:this.$t('SystemManage.OperateAuth.tab_sub_sheet2')||'时间序列表格',
+                    path:'sheetTimeList',
+                    key:2
+                },
+                {
+                    label:this.$t('SystemManage.OperateAuth.tab_sub_sheet3')||'混合表格',
+                    path:'sheetMixedList',
+                    key:3
+                }
+            ],
         }
     },
     created(){
-        this.getSheetList()
+        this.initStatus()
     },
     methods: {
+        async initStatus(){
+            this.typeArr=this.typeArr.filter(item=>this.verifyInsertModuleAuth(item.path))
+            if(this.typeArr.length>0){
+                this.table_source=this.typeArr[0].key
+                this.getSheetList()
+            }
+        },
         // 生产随机id
         getCompId(type){
             return type+new Date().getTime()
@@ -73,22 +116,30 @@ export default {
             this.finished=false
             this.getSheetList()
         },
-        getSheetList() {
+        activeTypeChange(item){
+            this.table_source=item.key
+            this.isShowMe=false
+            this.keyword=''
+            this.handleSearch()
+        },
+        async getSheetList() {
             this.loading=true
-            sheetInterface.sheetList({
-                KeyWord: this.keyword,
-                CurrentIndex: this.page,
+            let params = {
                 PageSize: this.pageSize,
-            }).then((res) => {
-                this.loading=false
-                if (res.Ret !== 200) return;
-                const arr = res.Data.List || [];
-                this.list =
-                    this.page === 1
-                    ? arr
-                    : [...this.list, ...arr];
-                this.finished =  res.Data.Paging.IsEnd;
-            });
+                CurrentIndex: this.page,
+                Source: this.table_source,
+                KeyWord: this.keyword,
+                IsShowMe: this.isShowMe
+            };
+            let res = await sheetInterface.sheetList(params)
+            this.loading=false
+            if (res.Ret !== 200) return;
+            this.finished = res.Data.Paging.IsEnd
+            this.list = res.Data
+                ? this.page_no === 1
+                ? res.Data.List
+                : [...this.list, ...res.Data.List]
+                : [];
         },
 
         handleLoadMore(){
@@ -120,15 +171,43 @@ div{
 }
 .eta-sheet-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        .search-box{
-            width: 330px;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
+        .left-card{
+            width: fit-content;
+            border-radius: 4px;
+            border: 1px solid var(--unnamed, #DCDFE6);
+            background: var(--gary-gy-3-disabled, #EBEFF6);
+            display: flex;
+            align-items: center;
+            padding: 6px;
+            .item{
+                cursor: pointer;
+                display: block;
+                width: 110px;
+                height: 30px;
+                line-height: 30px;
+                text-align: center;
+                border-radius: 4px;
+                font-size: 18px;
+                color: #666;
+                &.active{
+                    background: #FFF;
+                    color: #002D78;
+                }
+            }
+        }
+        .right{
+            margin-top: 20px;
+            .search-box{
+                width: 250px;
+            }
         }
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 240px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 15 - 11
src/views/report_manage/reportV2/smartReport/components/ImgSource.vue

@@ -8,21 +8,21 @@
                 <span v-else>{{$t('ReportManage.ReportList.select_img_card')}}</span>
             </div>
             <div class="right">
+                <el-select :placeholder="$t('ReportManage.ReportList.select_img_type')" v-model="type" style="width:80px" @change="handleSearch" :disabled="defaultType" v-show="!defaultType">
+                    <el-option :label="$t('ReportManage.ReportList.page_header_op')" :value="1"></el-option>
+                    <el-option :label="$t('ReportManage.ReportList.page_trailer_op')" :value="2"></el-option>
+                </el-select>
                 <el-input
                     class="search-box"
 					:placeholder="$t('ReportManage.ReportList.img_name_ipt')"
 					v-model="keyword"
                     @input="handleSearch"
-                    style="width:240px"
-                    size="medium"
+                    style="width:300px"
 				/>
-                <el-select :placeholder="$t('ReportManage.ReportList.select_img_type')" v-model="type" style="width:240px" @change="handleSearch" size="medium" :disabled="defaultType" v-show="!defaultType">
-                    <el-option :label="$t('ReportManage.ReportList.page_header_op')" :value="1"></el-option>
-                    <el-option :label="$t('ReportManage.ReportList.page_trailer_op')" :value="2"></el-option>
-                </el-select>
+                
             </div>
         </div>
-        <div class="main-box" :style="inDialog?'height:550px;':'height: calc(100vh - 180px)'">
+        <div class="main-box" :style="inDialog?'height:550px;':'height: calc(100vh - 240px)'">
             <div style="flex:1;overflow-y: auto;padding:20px 0">
             <tableNoData :text="$t('Table.prompt_slogan')" size="mini" v-if="list.length===0&&finished"/>
             <div class="list-wrap" v-infinite-scroll="handleLoadMore" :infinite-scroll-immediate="false">
@@ -149,10 +149,14 @@ div{
 }
 .statistic-analysis-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
         .right{
+            display: flex;
+            flex-wrap: wrap;
+            gap: 5px;
+            margin-top: 20px;
             .search-box{
                 width: 330px;
             }
@@ -160,7 +164,7 @@ div{
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 260px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 1 - 1
src/views/report_manage/reportV2/smartReport/components/ImportMyETAChart.vue

@@ -139,7 +139,7 @@ div{
     .select-box{
         position: absolute;
         top: -75px;
-        right: 0;
+        left: -20px;
     }
     .list{
         max-height: calc(100vh - 220px);;

+ 231 - 0
src/views/report_manage/reportV2/smartReport/components/Material.vue

@@ -0,0 +1,231 @@
+<template>
+  <div class="statistic-analysis-wrap">
+    <div class="top-box">
+      <div class="left-card">
+        <span>{{$t('ReportManage.Material.material_name')}}</span>
+      </div>
+      <div class="right">
+        <el-cascader
+          v-model="classify"
+          :options="classifyOpts"
+          :placeholder="$t('MsgPrompt.select_category')"
+          :props="{
+            checkStrictly: true,
+            emitPath: false,
+            value: 'ClassifyId',
+            label: 'ClassifyName',
+            children: 'Children',
+          }"
+          style="width: 200px"
+          @change="handleRefreshList"
+        />
+        <el-input
+          class="search-box"
+          :placeholder="$t('SystemManage.BaseConfig.resource_placeholder01')"
+          v-model="keyword"
+          prefix-icon="el-icon-search"
+          @input="handleRefreshList"
+          style="width: 200px"
+        />
+        
+      </div>
+    </div>
+    <div class="main-box">
+      <el-checkbox
+        class="onlyshowme-box"
+        v-model="isShowMe"
+        @change="handleRefreshList"
+        >{{ $t("ReportManage.ReportList.just_mine_radio") }}</el-checkbox
+      >
+      <div
+        class="list-wrap"
+        v-infinite-scroll="handleLoadMore"
+        :infinite-scroll-immediate="true"
+      >
+        <draggable
+          :list="list"
+          :group="{ name: 'component', pull: 'clone', put: false }"
+          class="chart-list-box"
+          animation="300"
+          :sort="false"
+          tag="div"
+        >
+          <div
+            class="chart-item"
+            :comp-data="getCompData(item)"
+            v-for="item in list"
+            :key="item.MaterialId"
+          >
+            <div class="title">{{ item.MaterialName }}</div>
+            <div
+              class="img"
+              :style="'backgroundImage:url(' + item.ImgUrl + ')'"
+            ></div>
+            <div style="display:flex;justify-content:space-between;font-size:12px">
+              <span>{{ item.CreateTime }}</span>
+              <span>{{ item.SysUserRealName }}</span>
+            </div>
+          </div>
+        </draggable>
+        <tableNoData
+          :text="$t('Table.prompt_slogan')"
+          size="mini"
+          v-if="list.length === 0 && finished"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { apiReportMaterial } from '@/api/modules/reportMaterial.js'
+export default {
+  data() {
+    return {
+      classifyOpts: [],
+      classify: '',
+      keyword: '',
+      list: [],
+      page: 1,
+      pageSize: 20,
+      finished: false,
+      loading: false,
+      isShowMe:false
+    }
+  },
+  created() {
+    this.getClassifyOpt()
+    this.getMaterialList()
+  },
+  methods: {
+    // 生产随机id
+    getCompId(type) {
+      return type + new Date().getTime()
+    },
+
+    getCompData(item) {
+      const obj = {
+        compId: 2,
+        compType: 'img',
+        content: item.ImgUrl
+      }
+      return JSON.stringify(obj)
+    },
+
+    handleRefreshList() {
+      this.list = []
+      this.page = 1
+      this.finished = false
+      this.getMaterialList()
+    },
+
+    /* 搜索图表分页 */
+    async getMaterialList(word) {
+      this.loading = true
+      const res = await apiReportMaterial.materialList({
+        ClassifyId: this.classify,
+        Keyword: this.keyword,
+        CurrentIndex: this.page,
+        PageSize: this.pageSize,
+        IsShowMe:this.isShowMe
+      })
+      this.loading = false
+      if (res.Ret !== 200) return;
+      const arr = res.Data.List || [];
+      this.list =
+        this.page === 1
+          ? arr
+          : [...this.list, ...arr];
+      this.finished = res.Data.Paging.IsEnd;
+    },
+
+    handleLoadMore() {
+      if (this.finished || this.loading) return
+      this.page++
+      this.getMaterialList()
+    },
+
+    formatArr(arr) {
+      return arr.map(item => {
+        if (!item.Children || item.Children.length === 0) {
+          item.Children = null
+        } else {
+          item.Children = this.formatArr(item.Children)
+        }
+        return item
+      });
+    },
+    // 获取分类数据
+    async getClassifyOpt() {
+      const res = await apiReportMaterial.classifyList()
+      if (res.Ret !== 200) return
+      const arr = res.Data.AllNodes || []
+      this.classifyOpts = this.formatArr(arr)
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+div {
+  box-sizing: border-box;
+}
+.statistic-analysis-wrap {
+  .top-box {
+    // display: flex;
+    // justify-content: space-between;
+    // align-items: center;
+    .right {
+      display: flex;
+      flex-wrap: wrap;
+      margin-top: 20px;
+      gap: 5px;
+      .search-box {
+        width: 330px;
+      }
+    }
+  }
+  .main-box {
+    margin-top: 30px;
+    height: calc(100vh - 220px);
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #c8cdd9);
+    background: #fff;
+    padding: 20px;
+    display: flex;
+    flex-direction: column;
+    .list-wrap {
+      flex: 1;
+      overflow-y: auto;
+    }
+  }
+}
+.chart-list-box {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20px;
+  .chart-item {
+    cursor: move;
+    padding: 0 10px;
+    width: 250px;
+    border-radius: 4px;
+    border: 1px solid var(--gary-gy-5-line, #c8cdd9);
+    background: var(--gary-gy-white, #fff);
+    .title {
+      padding: 10px 0;
+      text-align: center;
+      border-bottom: 1px solid #c8cdd9;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+    }
+    .img {
+      width: 100%;
+      height: 197px;
+      background-size: contain;
+      background-position: center;
+      background-repeat: no-repeat;
+    }
+  }
+}
+</style>

+ 7 - 6
src/views/report_manage/reportV2/smartReport/components/SemanticAnalysis.vue

@@ -9,9 +9,9 @@
                     class="search-box"
 					:placeholder="$t('ReportManage.ReportList.keyword_search')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>
@@ -116,18 +116,19 @@ div{
 }
 .statistic-analysis-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
         .right{
+            margin-top: 20px;
             .search-box{
-                width: 330px;
+                width: 240px;
             }
         }
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 220px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 50 - 31
src/views/report_manage/reportV2/smartReport/components/StatisticAnalysis.vue

@@ -14,9 +14,9 @@
                     class="search-box"
 					:placeholder="$t('ReportManage.ReportList.chart_name')"
 					v-model="keyword"
-					size="medium"
 					prefix-icon="el-icon-search"
                     @input="handleSearch"
+                    style="width:300px"
 				/>
             </div>
         </div>
@@ -53,25 +53,61 @@ import {
   statisticFeatureInterface,
   crossVarietyInterface
 } from "@/api/modules/chartRelevanceApi";
+import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
 export default {
     data() {
         return {
 
             keyword:'',
             isShowMe:false,
-            activeType:'相关性',
+            activeType:'',
 
             list:[],
             page:1,
             pageSize:20,
             finished:false,
-            loading:false
+            loading:false,
+            typeOpts:[
+                {
+                    name:this.$t('ReportManage.ReportList.correlation_analysis'),
+                    key:'相关性',
+                    path:'chartrelevance'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.curve_fitting_radio'),
+                    key:'拟合方程曲线',
+                    path:'fittingEquationList'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.statistical_feature_radio'),
+                    key:'统计特征',
+                    path:'statisticFeatureList'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
+                    key:'跨品种分析',
+                    path:'crossVarietyChartList'
+                },
+                {
+                    name:this.$t('StatisticAnalysis.IntervalAnalysis.interval_analysis_name'),
+                    key:'区间分析',
+                    path:'rangeAnalysis'
+                }
+            ]
         }
     },
     created(){
-        this.getChartList()
+        this.initTypeOpts()
     },
     methods: {
+        initTypeOpts(){
+            this.typeOpts=this.typeOpts.filter(item=>this.verifyInsertModuleAuth(item.path))
+            if(this.typeOpts.length){
+                this.activeType=this.typeOpts[0].key
+                this.getChartList()
+            }
+        },
+        
         // 生产随机id
         getCompId(type){
             return type+new Date().getTime()
@@ -129,6 +165,8 @@ export default {
                 res = await statisticFeatureInterface.searchChart(params);
             } else if (this.activeType === '跨品种分析') {
                 res = await crossVarietyInterface.searchChart(params);
+            }else if(this.activeType==='区间分析'){
+                res=await apiIntervalAnalysis.chartSearch(params)
             }
             this.loading=false
 
@@ -146,28 +184,6 @@ export default {
             this.page++
             this.getChartList()
         }
-    },
-    computed:{
-      typeOpts(){
-        return [
-                {
-                    name:this.$t('ReportManage.ReportList.correlation_analysis'),
-                    key:'相关性'
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.curve_fitting_radio'),
-                    key:'拟合方程曲线'
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.statistical_feature_radio'),
-                    key:'统计特征'
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.intercommodity_analysis_radio'),
-                    key:'跨品种分析'
-                }
-            ]
-      }
     }
 }
 </script>
@@ -178,16 +194,18 @@ div{
 }
 .statistic-analysis-wrap{
     .top-box{
-        display: flex;
-        justify-content: space-between;
-        align-items: center;
+        // display: flex;
+        // justify-content: space-between;
+        // align-items: center;
         .left-card{
+            width: fit-content;
             border-radius: 4px;
             border: 1px solid var(--unnamed, #DCDFE6);
             background: var(--gary-gy-3-disabled, #EBEFF6);
             display: flex;
             align-items: center;
-            gap: 0 3px;
+            flex-wrap: wrap;
+            gap: 3px;
             padding: 6px;
             .item{
                 cursor: pointer;
@@ -206,6 +224,7 @@ div{
             }
         }
         .right{
+            margin-top: 20px;
             .search-box{
                 width: 330px;
             }
@@ -213,7 +232,7 @@ div{
     }
     .main-box{
         margin-top: 30px;
-        height: calc(100vh - 180px);
+        height: calc(100vh - 260px);
         border-radius: 4px;
         border: 1px solid var(--gary-gy-5-line, #C8CDD9);
         background: #FFF;

+ 96 - 54
src/views/report_manage/reportV2/smartReport/editReport.vue

@@ -192,7 +192,7 @@
                             <img src="~@/assets/img/smartReport/icon14.png" alt="">
                         </div>
                         <div style="overflow-x:auto;height:calc(100% + 12px);">
-                        <div style="min-width:800px;height: 100%;">
+                        <div style="height: 100%;">
                         <TextEdit 
                             v-if="rightType==='text'"
                             :key="activeId"
@@ -222,6 +222,10 @@
                         <SemanticAnalysis v-if="rightType==='semanticAnalysis'"/>
                         <!-- 版图资源库 -->
                         <ImgSource v-if="rightType==='imgSource'" @change="handleInsertImgSource" @close="handleCloseRight"/>
+                        <!-- 素材库 -->
+                        <Material v-if="rightType==='material'"/>
+                        <!-- 平衡表 -->
+                        <BalanceSheet v-if="rightType==='balanceSheet'"/>
                         </div>
                         </div>
                     </div>
@@ -278,6 +282,8 @@ import TextEdit from './components/TextEdit.vue'
 import ImgEdit from './components/ImgEdit.vue'
 import ETAChart from './components/ETAChart.vue'
 import ETASheet from './components/ETASheet.vue'
+import Material from './components/Material.vue'
+import BalanceSheet from './components/BalanceSheet.vue'
 import { getPublicSettingsApi } from '@/api/modules/oldApi';
 import { dataBaseInterface } from "@/api/api.js";
 import {
@@ -299,14 +305,14 @@ import ETAPriceChart from './components/ETAPriceChart.vue'
 import ETASandBox from './components/ETASandBox.vue'
 import SemanticAnalysis from './components/SemanticAnalysis.vue'
 import { getUrlParams } from '@/utils/common'
-import reportApproveConfig from "@/mixins/reportApproveConfig.js"
+import reportApproveConfig from "@/mixins/reportApproveConfig.js"  
 import ImgSource from './components/ImgSource.vue'
 import editHeader from '../components/reportEditHeader.vue';
 import chapterWrapper from '../components/chapterEditWrapper.vue';
 import smartReportDetail from './reportDetail.vue'
 import { GetQueryString } from '@/utils/common'
 export default {
-    mixins:[reportApproveConfig],
+    mixins:[reportApproveConfig],  
     name:"smartReportEditV2",
     components: {
         draggable,
@@ -326,7 +332,9 @@ export default {
         ImgSource,
         editHeader,
         chapterWrapper,
-        smartReportDetail
+        smartReportDetail,
+        Material,
+        BalanceSheet
     },
     watch:{
         'taskTime'(){
@@ -420,6 +428,72 @@ export default {
             reportCoopType: 0,//协作类型 1单人 2章节报告
 			selectChapterId: 0, //选中章节Id
             editChapterId: 0,//编辑章节Id
+
+            topTypeList:[
+                {
+                    name:this.$t('ReportManage.ReportList.library_top_type'),
+                    type:'imgSource',
+                    visable: this.reportCoopType!==2,
+                    icon:require('@/assets/img/smartReport/icon04.png'),
+                    path:''
+                },
+                {
+                    name:this.$t('ReportManage.Material.material_name'),
+                    type:'material',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon19.png'),
+                    path:'materialList'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.chart_top_type'),
+                    type:'etaChart',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon04.png'),
+                    path:''
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.eta_top_type'),
+                    type:'etaSheet',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon05.png'),
+                    path:''
+                },
+                {
+                    name:this.$t('SystemManage.OperateAuth.tab_sub_sheet4'),
+                    type:'balanceSheet',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon20.png'),
+                    path:'sheetBalanceList'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.statistical_top_type'),
+                    type:'statisticAnalysis',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon06.png'),
+                    path:''
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.price_curve_radio'),
+                    type:'etaPriceChart',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon07.png'),
+                    path:'commordityChartBase'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.sandbox_top_type'),
+                    type:'etaSandBox',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon08.png'),
+                    path:'sandlist'
+                },
+                {
+                    name:this.$t('ReportManage.ReportList.semantic_top_type'),
+                    type:'semanticAnalysis',
+                    visable:true,
+                    icon:require('@/assets/img/smartReport/icon09.png'),
+                    path:'semanticsPage'
+                }
+            ]
         }
     },
     methods: {
@@ -523,7 +597,7 @@ export default {
 
         /* 表格标题可修改,保存时获取每个sheet最新的title存进conList */
         formatContentListElData() {
-            console.log(this.conList)
+            // console.log(this.conList)
             let newList = this.conList.map(_ => {
                 if(_.child&&_.child.length) { //一行多个
                     return {
@@ -1392,56 +1466,23 @@ export default {
                 this.endImgId = 0
             }
             this.contentChange=true
+        },
+
+        // 初始化顶部插入选项
+        initTopTypeList(){
+            this.topTypeList=this.topTypeList.filter(item=>this.verifyInsertModuleAuth(item.path)).map(item=>{
+                if(item.type==='imgSource'){
+                    return{
+                        ...item,
+                        visable:this.reportCoopType!==2,
+                    }
+                }else{
+                    return item
+                }
+            })
         }
     },
     computed:{
-      topTypeList(){
-           return [
-                {
-                    name:this.$t('ReportManage.ReportList.library_top_type'),
-                    type:'imgSource',
-                    visable: this.reportCoopType!==2,
-                    icon:require('@/assets/img/smartReport/icon04.png')
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.chart_top_type'),
-                    type:'etaChart',
-                    visable:true,
-                    icon:require('@/assets/img/smartReport/icon04.png')
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.eta_top_type'),
-                    type:'etaSheet',
-                    visable:true,
-                    icon:require('@/assets/img/smartReport/icon05.png')
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.statistical_top_type'),
-                    type:'statisticAnalysis',
-                    visable:true,
-                    icon:require('@/assets/img/smartReport/icon06.png')
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.price_curve_radio'),
-                    type:'etaPriceChart',
-                    visable:true,
-                    icon:require('@/assets/img/smartReport/icon07.png')
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.sandbox_top_type'),
-                    type:'etaSandBox',
-                    visable:true,
-                    icon:require('@/assets/img/smartReport/icon08.png')
-                },
-                {
-                    name:this.$t('ReportManage.ReportList.semantic_top_type'),
-                    type:'semanticAnalysis',
-                    visable:true,
-                    icon:require('@/assets/img/smartReport/icon09.png')
-                }
-            ]
-      },
-
       //语言版本
       currentLang() {
         return this.$store.state.lang
@@ -1450,6 +1491,7 @@ export default {
     created() {
         this.getPublicSettings()
         this.reportCoopType = Number(this.$route.query.coopType)
+        this.initTopTypeList()
         this.reportCoopType===1 && this.getReportDetail()
     },
     mounted () {
@@ -1601,7 +1643,7 @@ div{
     width: 800px;
     flex-shrink: 0;
     margin-left: 90px;
-    margin-right: 60px;
+    margin-right: 20px;
     margin-top: 30px;
     position: relative;
     .report-comp-wrap{
@@ -1852,7 +1894,7 @@ div{
         flex: 1;
         position: relative;
         padding-top: 30px;
-        padding-left: 75px;
+        padding-left: 50px;
         padding-right: 30px;
         padding-bottom: 30px;
         &::before{

+ 16 - 1
src/views/sandbox_manage/index_new_version.vue

@@ -68,6 +68,10 @@
         <div class="sandbox-chartHead-author">{{$t('MsgPrompt.author')}}:<span>{{ this.viewSandbox.SysUserName }}</span></div>
         <div class="sandbox-chartHead-title">{{ this.viewSandbox.Name }}</div>
         <div class="sandbox-chartHead-options">
+          <div class="chartHead-options-button" v-permission="permissionBtn.sandboxPermission.sandbox_saveToMaterial" @click="showUploadMaterial=true">
+            <i class="el-icon-folder-add"/>
+            <!-- 保存为素材 --><span>{{$t('ReportManage.Material.save_to_material')}}</span>
+          </div>
           <div class="chartHead-options-button" @click="editSand" v-permission="permissionBtn.sandboxPermission.sandbox_saveView">
             <img src="~@/assets/img/sand_new/edit_outline.png" />
             <span>{{$t('Table.edit_btn')}}</span> 
@@ -183,6 +187,14 @@
         </div>
       </div>
     </el-dialog>
+
+    <!-- 上传素材库 -->
+    <uploadToMaterial 
+      v-model="showUploadMaterial"
+      source="sandbox"
+      :sourceId="viewSandbox.SandboxId"
+      :defaultName="viewSandbox.Name"
+    />
   </div>
 </template>
 
@@ -330,7 +342,9 @@ import {reportVarietyInterence} from '@/api/modules/reportVariety'
         linkNode:null,
         popoverTimeout:null,
         isSlideLeft:false,
-        locationParentIds:''
+        locationParentIds:'',
+
+        showUploadMaterial:false,//显示上传至素材库
       }
     },
     created(){
@@ -1384,6 +1398,7 @@ import {reportVarietyInterence} from '@/api/modules/reportVariety'
           align-items: center;
           flex-wrap: nowrap;
           cursor: pointer;
+          color: #0052D9;
           img{
             height: 16px;
             margin-right: 3px;

+ 64 - 0
src/views/semantics_manage/document/documentEditPage.vue

@@ -33,6 +33,9 @@
               />
           </el-select>
         </el-form-item>
+        <el-form-item v-permission="permissionBtn.semanticPermission.docPage_classifyOpt_edit">
+          <el-button type="text" @click="isShowAddClassify=true">{{$t('SemanticsManage.DocumentManagement.add_category')}}</el-button>
+        </el-form-item>
       </el-form>
       <el-button type="primary" style="margin-left:auto;" @click="saveFile">{{$t('Dialog.confirm_save_btn')}}</el-button>
       <el-button @click="cancelModify">{{$t('Dialog.cancel_btn')}}</el-button>
@@ -72,6 +75,40 @@
         </div>
       </div>
     </div>
+
+    <!-- 添加分类 -->
+    <el-dialog
+      :title="$t('SemanticsManage.DocumentManagement.add_category')"
+      :visible.sync="isShowAddClassify"
+      :close-on-click-modal="false"
+      :modal-append-to-body="false"
+      @close="closeClassifyForm"
+      width="589px"
+      v-dialogDrag
+      center
+    >
+      <div class="dialog-container">
+        <el-form
+          ref="addClassifyformRef"
+          label-position="left"
+          hide-required-asterisk
+          :model="classifyForm"
+          :rules="classifyFormRules"
+        >
+          <el-form-item label-width="118px" :label="$t('SemanticsManage.DocumentManagement.add_category_name')" prop="classify_name">
+            <el-input
+              v-model="classifyForm.classify_name"
+              style="width: 80%"
+              :placeholder="$t('SemanticsManage.DocumentManagement.add_category_input_name')"
+            />
+          </el-form-item>
+        </el-form>
+      </div>
+      <div class="foot-container">
+        <el-button @click="closeClassifyForm">{{ $t('Dialog.cancel_btn')}}</el-button>
+        <el-button type="primary" @click="handleAddClassify">{{ $t('Dialog.confirm_btn')}}</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -90,9 +127,31 @@ export default {
       fileBlockArr:[],//文档段落列表
 
       fileId:0,//为0时是新增 不为0时是文档id
+
+      isShowAddClassify:false,
+      classifyForm:{
+        classify_name:''
+      },
     };
   },
   methods: {
+    closeClassifyForm(){
+      this.isShowAddClassify=false
+      this.classifyForm.classify_name=''
+      this.$refs.addClassifyformRef.resetFields()
+    },
+    handleAddClassify(){
+      this.$refs.addClassifyformRef.validate(async (valid) => {
+        if(!valid) return
+        const res = await documentInterface.addNewClassify({
+          ClassifyName:this.classifyForm.classify_name,
+        })
+        if(res.Ret!==200) return
+        this.$message.success(this.$t('MsgPrompt.add_msg'))
+        this.getClassifyList()
+        this.closeClassifyForm()
+      })
+    },
     //获取分类列表
     getClassifyList(){
       documentInterface.getClassifyList().then(res=>{
@@ -226,6 +285,11 @@ export default {
         ClassifyId: [{ required: true, message: this.$t('SemanticsManage.DocumentManagement.select_document_category_msg')  }],
       };
     },
+    classifyFormRules(){
+      return {
+        classify_name:[{ required: true, message:this.$t('Chart.Vailds.classify_msg') }],
+      }//分类校验规则
+    },
   },
 };
 </script>

+ 12 - 1
src/views/semantics_manage/semanticsPage.vue

@@ -187,6 +187,10 @@
             </svg>
             <span>{{$t('SemanticsManage.DocumentComparison.copy_wechat_btn')}}</span>
           </div>
+          <div class="opt-item" v-permission="permissionBtn.semanticPermission.saPage_saveToMaterial" @click="showUploadMaterial=true">
+            <i class="el-icon-folder-add" />
+            <span style="margin-left:5px"><!-- 保存为素材 -->{{$t('ReportManage.Material.save_to_material')}}</span>
+          </div>
           <!-- <li>
               <span @click="handleDownLoadImg" style="cursor: pointer;color:#409eff;margin-right:10px">下载</span>
               <span @click="handleCopyImg" style="cursor: pointer;color:#409eff;margin-right:10px">复制到微信</span>
@@ -230,6 +234,13 @@
         <el-button type="primary" @click="modifyClassify">{{$t('Dialog.confirm_btn')}}</el-button>
       </div>
     </el-dialog>
+    <!-- 上传素材库 -->
+    <uploadToMaterial 
+      v-model="showUploadMaterial"
+      source="sa_doc"
+      :sourceId="semanticInfo.SaCompareId"
+      :defaultName="semanticInfo.Title"
+    />
   </div>
 </template>
 
@@ -250,7 +261,7 @@ export default {
 
       isModifyClassifyShow:false,//控制分类显示弹窗
       semanticInfo:{},//语义分析详情
-      
+      showUploadMaterial:false,//显示上传至素材库
     };
   },
   watch:{