centaline-data-driven-v3 0.1.59 → 0.1.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div ref="refForm" v-loading="loading"
3
3
  :style="{ width: pageWidth ? pageWidth + 'px' : '100%', margin: 'auto', 'min-height': minHeight }">
4
- <div style="display: flex; width: 100%;">
4
+ <div style="display: flex; width: 100%;" ref="leftContainerRef">
5
5
  <div style="flex: 1; min-width: 0;">
6
6
  <div v-if="model !== null && !loading" class="ct-form" :class="{ 'domDisabled': model.pageDisabled }"
7
7
  :style="{ margin: openType != 'tree' ? '10px' : '0px' }">
@@ -194,9 +194,22 @@
194
194
  @hideAI="AIToggle" :isVisible="showAI" :tablewidth="model.aiAttr.width">
195
195
 
196
196
  </AIChat>
197
+
198
+
197
199
  </div>
198
200
  </div>
199
201
  </template>
202
+ <div :style="{ flex: ' 0 0 ' + 650 + 'px', position: 'sticky', top: '0', 'box-shadow': '-10px 0 5px -9px rgba(0, 0, 0, 0.3)' }"
203
+ v-if="showViewerFile">
204
+ <div
205
+ :style="{ position: 'sticky', top: '0', height: (dialogHeight) + 'px', overflow: 'hidden', 'border-bottom-right-radius': '4px' }">
206
+ <ViewerFile :MediaAlbum="media.MediaAlbum" :groupIndex="media.groupIndex" :index="media.index"
207
+ :key="media.random" :flagLeft="media.flagLeft" @closeViewerFile="ViewerFileToggle(false)"
208
+ @ViewerFilechangeIndex="ViewerFilechangeIndex">
209
+ </ViewerFile>
210
+
211
+ </div>
212
+ </div>
200
213
 
201
214
  </div>
202
215
  <template v-if="model?.aiAttr?.showAI && !showAI">
@@ -205,13 +218,14 @@
205
218
  :alt="model?.aiRouter.controlLabel" :title="model?.aiRouter.controlLabel">
206
219
  </div>
207
220
  </template>
221
+
208
222
  <div style="min-height:200px" v-if="loading"></div>
209
223
  <iframe :src="downloadUrl" style="height:0px;width:0px;border-width: 0px;display: none;"> </iframe>
210
224
 
211
225
  </div>
212
226
  </template>
213
227
  <script lang="ts" setup>
214
- import { ref, nextTick, onUpdated, onDeactivated, onMounted, onBeforeUnmount,provide } from 'vue'
228
+ import { ref, nextTick, onUpdated, onDeactivated, onMounted, onBeforeUnmount, provide } from 'vue'
215
229
  import { RouterClickHandler } from '../../utils/mixins';
216
230
  import common from '../../utils/common'
217
231
  import Form from '../../loader/src/Form'
@@ -220,7 +234,9 @@ import { useRouter } from 'vue-router';
220
234
  import util from '../../utils/pub-use'
221
235
  import Enum from '../../utils/Enum';
222
236
  import AIChat from '../web/AIChat.vue';
223
- const emit = defineEmits(['loaded', 'failLoad', 'submit', 'AIToggle'])
237
+ import ViewerFile from '../web/ViewerFile.vue';
238
+
239
+ const emit = defineEmits(['loaded', 'failLoad', 'submit', 'ToggleWdth'])
224
240
  const props = defineProps({
225
241
  api: String,
226
242
  vmodel: Object,
@@ -283,6 +299,14 @@ const props = defineProps({
283
299
  dialoWidth: Number,
284
300
  listHeight: Number,
285
301
  })
302
+ const media = ref({
303
+ MediaAlbum: [],
304
+ groupIndex: 0,
305
+ index: 0,
306
+ flagLeft: false,
307
+ random: Math.random()
308
+ })
309
+ const showViewerFile = ref(false)
286
310
  const itemKey = ref(1)
287
311
  const router = useRouter()
288
312
  const loading = ref(true)
@@ -292,6 +316,7 @@ const isScroll = ref(false)
292
316
  const isWebScroll = ref(false)
293
317
  const Fields = ref()
294
318
  const refForm = ref()
319
+
295
320
  const downloadUrl = ref('')
296
321
  const minHeight = ref('auto')
297
322
  const showAI = ref(false);
@@ -366,11 +391,11 @@ function init() {
366
391
  }
367
392
  if (typeof props.api !== 'undefined') {
368
393
  //根据接口获取数据
369
- Form.loadFormApi(props.api, load, props.apiParam, failLoad, false,props.appRootUrl);
394
+ Form.loadFormApi(props.api, load, props.apiParam, failLoad, false, props.appRootUrl);
370
395
  }
371
396
  else if (typeof props.source !== 'undefined') {
372
397
  //根据modelFrom获取数据
373
- load(Form.loadFromModel(props.source,false,props.appRootUrl));
398
+ load(Form.loadFromModel(props.source, false, props.appRootUrl));
374
399
  }
375
400
  else if (props.vmodel) {
376
401
  load(props.vmodel);
@@ -764,20 +789,223 @@ function setCss() {
764
789
 
765
790
  function AIToggle() {
766
791
  showAI.value = !showAI.value;
792
+ if (showAI.value) {
793
+ if (showViewerFile.value) {
794
+ ViewerFileToggle(false, [], 0, 0);
795
+ }
796
+ }
797
+
767
798
  let width = model.value.aiAttr.width;
768
799
  dialogHeight.value = (props.dialogHeight || (window.innerHeight - 60));
769
- emit('AIToggle', (showAI.value ? width : -width));
800
+ emit('ToggleWdth', (showAI.value ? width : -width));
801
+ }
802
+ const getVisibleDimensions = () => {
803
+ if (!refForm.value) return { width: 0, height: 0 };
804
+ const rect = refForm.value.getBoundingClientRect();
805
+ const viewWidth = window.innerWidth || document.documentElement.clientWidth;
806
+ const viewHeight = window.innerHeight || document.documentElement.clientHeight;
807
+
808
+ const visibleTop = Math.max(0, rect.top);
809
+ const visibleBottom = Math.min(viewHeight, rect.bottom);
810
+ const visibleLeft = Math.max(0, rect.left);
811
+ const visibleRight = Math.min(viewWidth, rect.right);
812
+
813
+ return {
814
+ width: Math.max(0, visibleRight - visibleLeft),
815
+ height: Math.max(0, visibleBottom - visibleTop)-60
816
+ };
817
+ };
818
+ function ViewerFileToggle(isOpen, mediaAlbum, groupIndex, index) {
819
+ if (isOpen) {
820
+ media.value = { MediaAlbum: mediaAlbum, groupIndex, index, flagLeft: false, random: Math.random() };
821
+ if (showAI.value) {
822
+ AIToggle();
823
+ }
824
+ }
825
+ if (showViewerFile.value != isOpen) {
826
+ showViewerFile.value = isOpen;
827
+ let width = 650;
828
+ dialogHeight.value = getVisibleDimensions().height || parseInt(minHeight.value) || window.innerHeight - 60;
829
+ emit('ToggleWdth', (showViewerFile.value ? width : -width));
830
+ }
831
+ }
832
+ provide('onViewerFileToggle', ViewerFileToggle)
833
+ function ViewerFilechangeIndex({ groupIndex, index }) {
834
+ if (media.value) {
835
+ media.value.groupIndex = groupIndex;
836
+ media.value.index = index;
837
+ }
838
+ }
839
+
840
+ function ChangeFileList(mediaAlbum, groupIndex, index) {
841
+ if (!showViewerFile.value) {
842
+ return;
843
+ } else {
844
+ if (mediaAlbum[0].medias.length <= 0) {
845
+ ViewerFileToggle(false);
846
+ return;
847
+ }
848
+ }
849
+ const oldMedia = media.value;
850
+ let newGroupIndex, newIndex, shouldShow;
851
+
852
+ // 情况1:没有旧记录,直接用传入索引,无效则找第一张
853
+ if (!oldMedia || !oldMedia.MediaAlbum) {
854
+ if (validatePosition(mediaAlbum, groupIndex, index)) {
855
+ newGroupIndex = groupIndex;
856
+ newIndex = index;
857
+ shouldShow = true;
858
+ } else {
859
+ const first = findFirstValidPosition(mediaAlbum);
860
+ if (first) {
861
+ newGroupIndex = first.groupIndex;
862
+ newIndex = first.index;
863
+ shouldShow = true;
864
+ } else {
865
+ // 整个相册无图,直接关闭查看器,但依然要更新 MediaAlbum
866
+ newGroupIndex = 0;
867
+ newIndex = 0;
868
+ shouldShow = false;
869
+ }
870
+ }
871
+ } else {
872
+ // 取出旧图片
873
+ const oldAlbumList = oldMedia.MediaAlbum;
874
+ const oldGroup = oldAlbumList && oldAlbumList[oldMedia.groupIndex];
875
+ const oldFile = oldGroup && oldGroup.medias && oldGroup.medias[oldMedia.index];
876
+
877
+ if (oldFile) {
878
+ // 尝试在新相册中定位旧图
879
+ const found = findFileInAlbum(mediaAlbum, oldFile);
880
+ if (found) {
881
+ // 找到了,移动到新位置
882
+ newGroupIndex = found.groupIndex;
883
+ newIndex = found.index;
884
+ shouldShow = true;
885
+ } else {
886
+ // 旧图被删,回退
887
+ const fallback = fallbackPosition(mediaAlbum, oldMedia.groupIndex, oldMedia.index);
888
+ newGroupIndex = fallback.groupIndex;
889
+ newIndex = fallback.index;
890
+ shouldShow = fallback.show;
891
+ }
892
+ } else {
893
+ // 旧记录无效,同样回退
894
+ const fallback = fallbackPosition(mediaAlbum, oldMedia.groupIndex, oldMedia.index);
895
+ newGroupIndex = fallback.groupIndex;
896
+ newIndex = fallback.index;
897
+ shouldShow = fallback.show;
898
+ }
899
+ }
900
+ ViewerFileToggle(showViewerFile.value, mediaAlbum, newGroupIndex, newIndex);
770
901
  }
902
+ provide('ChangeFileList', ChangeFileList)
771
903
 
904
+ function validatePosition(albumList, gIdx, idx) {
905
+ if (!albumList || gIdx < 0 || gIdx >= albumList.length) {
906
+ return false;
907
+ }
908
+ var group = albumList[gIdx];
909
+ var medias = group && group.medias;
910
+ return medias && idx >= 0 && idx < medias.length;
911
+ }
912
+ function findFirstValidPosition(albumList) {
913
+ if (!albumList) {
914
+ return null;
915
+ }
916
+ for (var g = 0; g < albumList.length; g++) {
917
+ var group = albumList[g];
918
+ var medias = group && group.medias;
919
+ if (medias && medias.length > 0) {
920
+ return { groupIndex: g, index: 0 };
921
+ }
922
+ }
923
+ return null;
924
+ }
925
+ function findFileInAlbum(albumList, targetFile) {
926
+ if (!albumList) {
927
+ return null;
928
+ }
929
+ // 先按引用查找
930
+ for (var g = 0; g < albumList.length; g++) {
931
+ var medias = albumList[g].medias;
932
+ if (!medias) continue;
933
+ for (var i = 0; i < medias.length; i++) {
934
+ if (medias[i] === targetFile) {
935
+ return { groupIndex: g, index: i };
936
+ }
937
+ }
938
+ }
939
+ // 如果引用匹配不到,尝试用 id(如果存在)
940
+ if (targetFile && targetFile.id != null) {
941
+ for (var g2 = 0; g2 < albumList.length; g2++) {
942
+ var medias2 = albumList[g2].medias;
943
+ if (!medias2) continue;
944
+ for (var i2 = 0; i2 < medias2.length; i2++) {
945
+ if (medias2[i2].id === targetFile.id) {
946
+ return { groupIndex: g2, index: i2 };
947
+ }
948
+ }
949
+ }
950
+ }
951
+ return null;
952
+ }
953
+ function fallbackPosition(albumList, prefGroup, prefIndex) {
954
+ if (!albumList || albumList.length === 0) {
955
+ return { groupIndex: 0, index: 0, show: false };
956
+ }
957
+
958
+ // 确保参考相册索引在有效范围内
959
+ var gIdx = Math.min(prefGroup, albumList.length - 1);
960
+ var group = albumList[gIdx];
961
+ var medias = group && group.medias ? group.medias : [];
962
+
963
+ // 1. 同相册内回退
964
+ if (medias.length > 0) {
965
+ var newIdx;
966
+ if (prefIndex > 0 && prefIndex <= medias.length) {
967
+ // 优先上一张
968
+ newIdx = prefIndex - 1;
969
+ } else if (prefIndex === 0 && medias.length > 1) {
970
+ // 第一张被删了,取下一张(索引 1)
971
+ newIdx = 1;
972
+ } else {
973
+ // 只剩这一张,还是它
974
+ newIdx = 0;
975
+ }
976
+ return { groupIndex: gIdx, index: newIdx, show: true };
977
+ }
978
+
979
+ // 2. 向前找非空相册,取最后一张
980
+ for (var g = gIdx - 1; g >= 0; g--) {
981
+ var m = albumList[g].medias || [];
982
+ if (m.length > 0) {
983
+ return { groupIndex: g, index: m.length - 1, show: true };
984
+ }
985
+ }
986
+
987
+ // 3. 向后找非空相册,取第一张
988
+ for (var g2 = gIdx + 1; g2 < albumList.length; g2++) {
989
+ var m2 = albumList[g2].medias || [];
990
+ if (m2.length > 0) {
991
+ return { groupIndex: g2, index: 0, show: true };
992
+ }
993
+ }
994
+
995
+ // 整个相册没有任何图片了
996
+ return { groupIndex: 0, index: 0, show: false };
997
+ }
772
998
 
773
999
  function buttonsWidth() {
774
1000
  let rtn = '100%';
775
1001
  if (showAI.value) {
776
- rtn = props.dialoWidth - model.value.aiAttr.width - 4 + 'px';
1002
+ rtn = (props.dialoWidth||getVisibleDimensions().width) - model.value.aiAttr.width - 4 + 'px';
1003
+ }
1004
+ else if (showViewerFile.value) {
1005
+ rtn = (props.dialoWidth||getVisibleDimensions().width) - 650 - 4 + 'px';
777
1006
  }
778
1007
  else if (props.pageWidth) {
779
1008
  rtn = props.pageWidth + 'px';
780
-
781
1009
  }
782
1010
 
783
1011
  return rtn;
@@ -398,7 +398,7 @@ function searchComplate(m, defaultSearch) {
398
398
  searchEnd.value = Date.now();
399
399
  isLoading.value = false;
400
400
  tableLoading.value = false;
401
- },null,props.appRootUrl);
401
+ }, null, props.appRootUrl);
402
402
  }
403
403
  if (typeof props.source !== "undefined") {
404
404
  load(SearchTable.loadSearchTableModel(props.source));
@@ -412,9 +412,9 @@ function searchComplate(m, defaultSearch) {
412
412
  //初始化数据
413
413
  function load(data) {
414
414
  model.value = data;
415
- model.value.$vue = { searchStrat, searchEnd, downloadUrl, loadStats, setTableHeight, updateCurrentRow, doAction, itemKey, refreshTableColumns, calculatingRowHeight, emit, operationLoading, getPage, toolbarClickHandler,closeTabThen };
415
+ model.value.$vue = { searchStrat, searchEnd, downloadUrl, loadStats, setTableHeight, updateCurrentRow, doAction, itemKey, refreshTableColumns, calculatingRowHeight, emit, operationLoading, getPage, toolbarClickHandler, closeTabThen };
416
416
  model.value.isIframe = props.isIframe
417
- model.value.appendToBody=props.appendToBody
417
+ model.value.appendToBody = props.appendToBody
418
418
  model.value.isPageInSideBar = false
419
419
  model.value.columnName = null
420
420
  model.value.columnGroupId = null
@@ -973,6 +973,7 @@ function thMouseDownHandle(ev, colIndex) {
973
973
  }
974
974
  //查询对应页的数据
975
975
  function getPage(index, flagRefreshRowHandle) {
976
+ getRetain();
976
977
  if (refTableParent.value) {
977
978
  refTableParent.value.scrollTop = 0;
978
979
  refTableParent.value.scrollLeft = 0;
@@ -997,8 +998,12 @@ function getPage(index, flagRefreshRowHandle) {
997
998
  getScrollAttr();
998
999
  }
999
1000
  setfixedSize();
1001
+ model.value.selectIndex = 0;
1002
+ model.value._lastRowspan = null;
1000
1003
  if (index === 1) {
1001
1004
  SearchTable.setButtonsDisabledByRowClick(model.value);
1005
+ SearchTable.setButtonsDisabled(model.value);
1006
+ model.value.selectAll = false;
1002
1007
  }
1003
1008
  });
1004
1009
  }
@@ -1303,7 +1308,7 @@ function refreshTableColumns(data) {
1303
1308
  searchStats = refTableStats.value.getsearchStats();
1304
1309
  }
1305
1310
  if (data) {
1306
- load(SearchTable.loadSearchTableModel(data, model.value.searchModel, false, props.api,null,props.appRootUrl));
1311
+ load(SearchTable.loadSearchTableModel(data, model.value.searchModel, false, props.api, null, props.appRootUrl));
1307
1312
  }
1308
1313
  else {
1309
1314
  if (refTableStats.value) {
@@ -1311,7 +1316,7 @@ function refreshTableColumns(data) {
1311
1316
  getPage(1, true);
1312
1317
  }
1313
1318
  else {
1314
- SearchTable.loadSearchTableApi(props.api, load, searchModel, true,null,null,null,props.appRootUrl);
1319
+ SearchTable.loadSearchTableApi(props.api, load, searchModel, true, null, null, null, props.appRootUrl);
1315
1320
  }
1316
1321
  }
1317
1322
  model.value.searchStats = searchStats;
@@ -1657,6 +1662,17 @@ function closeTabThen(ev) {
1657
1662
  }
1658
1663
  }
1659
1664
 
1665
+ function getRetain() {
1666
+ model.value.isRetain = false
1667
+ let field = model.value.buttons.find((b) => {
1668
+ return b.key.toLowerCase() === 'Retain'.toLowerCase();
1669
+ });
1670
+ if (field) {
1671
+ if (field.code1) {
1672
+ model.value.isRetain = true;
1673
+ }
1674
+ }
1675
+ }
1660
1676
 
1661
1677
  defineExpose({
1662
1678
  model,
@@ -3,16 +3,18 @@
3
3
  <div v-if="buttonsLeft && buttonsLeft.length > 0" class="bool_btn_l">
4
4
  <ul>
5
5
  <li v-for="btn in buttonsLeft" class="ToolbarButton" :class="{ btn_r: btn.isRight }">
6
- <component :is="btn.is" :vmodel="btn" @fieldClick="clickHandler(btn)" @importComplete="importComplete"
7
- v-if="btn.show" :parameterAction="parameterAction" :fileData="getFileData(btn)"></component>
6
+ <component :is="btn.is" :vmodel="btn" @fieldClick="clickHandler(btn)"
7
+ @importComplete="importComplete" v-if="btn.show" :parameterAction="parameterAction"
8
+ :fileData="getFileData(btn)"></component>
8
9
  </li>
9
10
  </ul>
10
11
  </div>
11
12
  <div v-if="buttonsright && buttonsright.length > 0" class="bool_btn_r">
12
13
  <ul>
13
14
  <li v-for="btn in buttonsright" class="ToolbarButton" :class="{ btn_r: btn.isRight }">
14
- <component :is="btn.is" :vmodel="btn" @fieldClick="clickHandler(btn,)" @importComplete="importComplete"
15
- v-if="btn.show" :parameterAction="parameterAction" :fileData="getFileData(btn)"></component>
15
+ <component :is="btn.is" :vmodel="btn" @fieldClick="clickHandler(btn,)"
16
+ @importComplete="importComplete" v-if="btn.show" :parameterAction="parameterAction"
17
+ :fileData="getFileData(btn)"></component>
16
18
  </li>
17
19
  </ul>
18
20
  </div>
@@ -37,7 +39,9 @@ props.buttons.forEach(v => {
37
39
  }
38
40
  });
39
41
  function clickHandler(btn) {
40
- emit("click", btn);
42
+ if (btn.key.toLowerCase() != 'Retain'.toLocaleLowerCase()) {
43
+ emit("click", btn);
44
+ }
41
45
  }
42
46
  function importComplete(res, field) {
43
47
  emit("importComplete", res, field);
@@ -161,6 +161,7 @@ function init() {
161
161
  if (props.apiParam && props.apiParam.isIframe && props.apiParam.isIframe == 'true') {
162
162
  isIframe.value = true;
163
163
  }
164
+ window.addEventListener("resize", resizeSearchList);
164
165
  }
165
166
 
166
167
  function screenLoaded(defaultSearch) {
@@ -282,7 +283,6 @@ function tableLoaded() {
282
283
  sideMenuClickHandler(status);
283
284
  }
284
285
  }
285
- window.addEventListener("resize", resizeSearchList);
286
286
  }
287
287
  else {
288
288
  flagSideBarOfData.value = false;
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="Imagebox" @mousewheel="bagimg($event)" v-loading="loading">
2
+ <div class="Imagebox" @mousewheel.stop.prevent="bagimg($event)" v-loading="loading">
3
3
  <img id="ViewerImage" class="scaleimg" border="0" @load="complete()" v-bind:style="{
4
4
  top: params.top + 'px', left: params.left + 'px',
5
5
  transform:
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div style="height: 100%" id="viewer-file" ref="refviewerfile" @contextmenu="handleMouse" class="viewer-file ccai">
3
3
  <el-container style="height: 100%; border: 1px solid #eee">
4
- <el-aside style="background-color: rgb(238, 241, 246)" class="ccai-aside">
4
+ <el-aside style="background-color: rgb(238, 241, 246)" class="ccai-aside" v-if="flagLeft">
5
5
  <div style="height: 100%" class="viewerMenu">
6
6
  <el-menu :default-openeds="openeds" :default-active="activeitem" style="height: 100%">
7
7
  <el-sub-menu :key="groupIndex" :index="groupIndex.toString()"
@@ -28,32 +28,44 @@
28
28
  </div>
29
29
  </el-aside>
30
30
  <el-main ref="refdisplayArea" v-loading="downloadLoading" element-loading-spinner="el-icon-loading"
31
- :element-loading-custom-class="'cloading'">
31
+ :element-loading-custom-class="'cloading'" style="background-color: white;overflow: hidden;position: relative;">
32
+ <div v-if="!flagLeft" style="position: absolute; top: 10px; left: 10px;cursor: pointer;color:red"
33
+ @click="closeViewerFile">
34
+ <el-icon size="20">
35
+ <CircleClose />
36
+ </el-icon>
37
+
38
+ </div>
32
39
  <div class="cont" v-if="resultObject">
33
40
  <div style="padding-right:10px;" v-if="mediaLabelShow">
34
41
  <div class="enlarge-picture " v-if="itemFile.mediaLabelName">
35
- <span class="" style="width:80px;">{{common.LocalizedString('附件类型','附件類型')}} : </span>
42
+ <span class="" style="width:80px;">{{ common.LocalizedString('附件类型', '附件類型') }} : </span>
36
43
  <lable style="font-weight: bold;">{{ itemFile.mediaLabelName }}</lable>
37
44
  </div>
38
45
  <div class="enlarge-picture" v-if="itemFile.mediaDescCN">
39
- <span style="width:80px;">{{common.LocalizedString('中文描述','中文描述')}} : </span>
46
+ <span style="width:80px;">{{ common.LocalizedString('中文描述', '中文描述') }} : </span>
40
47
  <lable style="font-weight: bold;">{{ itemFile.mediaDescCN }}</lable>
41
48
  </div>
42
49
  <div class="enlarge-picture" v-if="itemFile.mediaDescEN">
43
- <span style="width:80px;">{{common.LocalizedString('英文描述','英文描述')}} : </span>
50
+ <span style="width:80px;">{{ common.LocalizedString('英文描述', '英文描述') }} : </span>
44
51
  <lable style="font-weight: bold;">{{ itemFile.mediaDescEN }}</lable>
45
52
  </div>
46
53
  <div class="enlarge-picture" v-if="itemFile.mediaUploadEmployeeDesc">
47
- <span style="width:80px;">{{common.LocalizedString('来源描述','來源描述')}} : </span>
54
+ <span style="width:80px;">{{ common.LocalizedString('来源描述', '來源描述') }} : </span>
48
55
  <lable style="font-weight: bold;">{{ itemFile.mediaUploadEmployeeDesc }}</lable>
49
56
  </div>
50
57
  </div>
51
- <div class="toggler" @click="mediaLabelShow=!mediaLabelShow" v-if="itemFile.mediaLabelName||itemFile.mediaDescCN||itemFile.mediaDescEN||itemFile.mediaUploadEmployeeDesc">
58
+ <div class="toggler" @click="mediaLabelShow = !mediaLabelShow"
59
+ v-if="itemFile.mediaLabelName || itemFile.mediaDescCN || itemFile.mediaDescEN || itemFile.mediaUploadEmployeeDesc">
52
60
  <span class="glyphicon glyphicon-chevron-right" v-if="mediaLabelShow">
53
- <el-icon color="#000000"><ArrowRightBold /></el-icon>
61
+ <el-icon color="#000000">
62
+ <ArrowRightBold />
63
+ </el-icon>
54
64
  </span>
55
65
  <span class="glyphicon glyphicon-chevron-left" v-if="!mediaLabelShow">
56
- <el-icon color="#000000"><ArrowLeftBold /></el-icon>
66
+ <el-icon color="#000000">
67
+ <ArrowLeftBold />
68
+ </el-icon>
57
69
  </span>
58
70
  </div>
59
71
  </div>
@@ -118,7 +130,7 @@
118
130
  <template v-else>
119
131
  <div class="viewerContent" style="max-height: 200px; text-align: center">
120
132
  <a :href="resultObject" target="_blank">
121
- <img :src="(itemFile.thumbnailUrl||itemFile.url)" /><br />{{
133
+ <img :src="(itemFile.thumbnailUrl || itemFile.url)" /><br />{{
122
134
  itemFile.mediaLabelName || itemFile.fileName
123
135
  }}
124
136
  </a>
@@ -126,7 +138,8 @@
126
138
  </template>
127
139
  </template>
128
140
  <!--p360-->
129
- <template v-else-if="itemFile.mediaTypeID == '7' || (itemFile.mediaTypeID + '').toLowerCase() == 'p360'">
141
+ <template
142
+ v-else-if="itemFile.mediaTypeID == '7' || (itemFile.mediaTypeID + '').toLowerCase() == 'p360'">
130
143
  <viewerP360 ref="refviewerP360" :height="displayAreaHeight" :width="displayAreaWidth"
131
144
  :imgUrl="resultObject" />
132
145
  </template>
@@ -144,6 +157,8 @@
144
157
  <div class="magnify-footer" :style="{
145
158
  width: displayAreaWidth + 'px',
146
159
  bottom: displayAreabtm + 10 + 'px',
160
+ position: !flagLeft ? 'absolute' : 'fixed',
161
+
147
162
  }">
148
163
  <div class="magnify-toolbar" :style="{ 'margin-left': displayArealeft + 'px' }">
149
164
 
@@ -201,14 +216,18 @@ import common from '../../utils/common';
201
216
  import viewerImage from './ViewerFile/ViewerImage.vue';
202
217
  import viewerPDF from './ViewerFile/ViewerPDFjs.vue';
203
218
  import viewerP360 from './ViewerFile/viewerP360.vue';
219
+ const emit = defineEmits(['closeViewerFile', 'ViewerFilechangeIndex'])
204
220
 
205
221
  const props = defineProps({
206
222
  MediaAlbum: Array,
207
223
  groupIndex: Number,
208
224
  index: Number,
225
+ flagLeft: {
226
+ type: Boolean,
227
+ default: true
228
+ }
209
229
  })
210
230
 
211
-
212
231
  const refviewerfile = ref()
213
232
  const refdisplayArea = ref()
214
233
  const refviewerImage = ref()
@@ -227,8 +246,8 @@ const displayArealeft = ref(0)
227
246
  const displayAreaHeight = ref(0)
228
247
  const downloadUrl = ref("")
229
248
  const downloadLoading = ref(false)
230
- const mediaLabelShow=ref(false)
231
- const qrtimer=ref(null)
249
+ const mediaLabelShow = ref(false)
250
+ const qrtimer = ref(null)
232
251
 
233
252
  groupCountLen.value = 0;
234
253
  props.MediaAlbum.forEach((item, n) => {
@@ -245,11 +264,18 @@ onMounted(() => {
245
264
  displayArealeft.value = DomLeft();
246
265
  displayAreabtm.value = DomTop(refdisplayArea.value.$el);
247
266
  displayAreaHeight.value = refdisplayArea.value.$el.offsetHeight;
267
+ if (!props.flagLeft) {
268
+ displayAreaHeight.value = displayAreaHeight.value - 5;
269
+ }
248
270
  window.onresize = () => {
249
271
  displayAreaWidth.value = DomWidth();
250
272
  displayArealeft.value = DomLeft();
251
273
  displayAreabtm.value = DomTop(refdisplayArea.value.$el);
274
+
252
275
  displayAreaHeight.value = refdisplayArea.value.$el.offsetHeight;
276
+ if (!props.flagLeft) {
277
+ displayAreaHeight.value = displayAreaHeight.value - 5;
278
+ }
253
279
  };
254
280
 
255
281
  if (
@@ -258,7 +284,7 @@ onMounted(() => {
258
284
  props.groupIndex > -1 &&
259
285
  props.index > -1
260
286
  ) {
261
- var item = props.MediaAlbum[props.groupIndex].medias[props.index];
287
+ var item = props.MediaAlbum[props.groupIndex]?.medias[props.index];
262
288
  handleClick(item, props.groupIndex, props.index);
263
289
  }
264
290
  })
@@ -304,6 +330,9 @@ function handleMouse(e) {
304
330
  e.preventDefault();
305
331
  }
306
332
  function DomWidth() {
333
+ if (!props.flagLeft) {
334
+ return refdisplayArea.value.$el.offsetWidth - 40;
335
+ }
307
336
  let arrLength = window.innerWidth - refviewerfile.value.offsetWidth;
308
337
  arrLength = arrLength > 0 ? arrLength : 0;
309
338
  var Width =
@@ -315,6 +344,9 @@ function DomWidth() {
315
344
  return Width;
316
345
  }
317
346
  function DomTop() {
347
+ if (!props.flagLeft) {
348
+ return -65;
349
+ }
318
350
  const height = window.innerHeight; //可视区窗口高度
319
351
  const curDomHeight = refviewerfile.value.offsetHeight;
320
352
  // const curDomHeight = dom.getBoundingClientRect().height
@@ -324,6 +356,9 @@ function DomTop() {
324
356
  return curDomBottom;
325
357
  }
326
358
  function DomLeft() {
359
+ if (!props.flagLeft) {
360
+ return 65;
361
+ }
327
362
  let arrLength = window.innerWidth - refviewerfile.value.offsetWidth;
328
363
  arrLength = arrLength > 0 ? arrLength : 0;
329
364
  var Width =
@@ -341,7 +376,8 @@ function handleClick(item, groupIndex, index) {
341
376
  activeGroup.value = groupIndex;
342
377
  itemFile.value = item;
343
378
  activeitem.value = groupIndex + "-" + index;
344
- resultObject.value = itemFile.value.mediaUrl;
379
+ resultObject.value = itemFile.value?.mediaUrl;
380
+ emit('ViewerFilechangeIndex', { groupIndex: groupIndex, index: index })
345
381
  }
346
382
  function jump(n) {
347
383
  var item = {};
@@ -421,12 +457,16 @@ function zoom(n) {
421
457
  function enterFullscreen(n) {
422
458
  refviewerP360.value.enterFullscreen(n);
423
459
  }
460
+
461
+ function closeViewerFile() {
462
+ emit('closeViewerFile')
463
+ }
424
464
  onUnmounted(() => {
425
- window.onresize = null;
426
- if (qrtimer.value) {
427
- clearTimeout(qrtimer.value);
428
- qrtimer.value = null;
429
- }
465
+ window.onresize = null;
466
+ if (qrtimer.value) {
467
+ clearTimeout(qrtimer.value);
468
+ qrtimer.value = null;
469
+ }
430
470
  })
431
471
  </script>
432
472
  <style scoped>
@@ -503,6 +543,7 @@ html {
503
543
  .enlarge-picture {
504
544
  padding: 5px 10px;
505
545
  }
546
+
506
547
  .toggler {
507
548
  -webkit-border-top-right-radius: 4px;
508
549
  -webkit-border-bottom-right-radius: 4px;
@@ -522,6 +563,7 @@ html {
522
563
  cursor: pointer;
523
564
  position: absolute;
524
565
  }
566
+
525
567
  .glyphicon {
526
568
  margin: 15px 0px;
527
569
  position: relative;