index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <template>
  2. <MainPanel>
  3. <template v-slot:header>
  4. <Header
  5. :count="selects.length"
  6. :title="`现场图管理(${sortPhotos.length})`"
  7. type="return_l"
  8. :on-back="() => api.closePage()"
  9. >
  10. <ui-button
  11. :type="selectMode ? 'primary' : 'normal'"
  12. @click="selectMode = !selectMode"
  13. width="96px"
  14. style="margin-right: 16px"
  15. v-if="sortPhotos.length"
  16. >
  17. {{ selectMode ? "取消" : "选择" }}
  18. </ui-button>
  19. <ui-button
  20. v-if="!selectMode"
  21. type="primary"
  22. @click="router.push({ name: writeRouteName.photos })"
  23. width="96px"
  24. >
  25. 新增
  26. </ui-button>
  27. </Header>
  28. </template>
  29. <Photos
  30. undata-msg="无现场图。请点击右上角按钮绘制现场图。"
  31. v-model:active="active"
  32. v-model:selects="selects"
  33. :select-mode="selectMode"
  34. :data="sortPhotos"
  35. :getURL="(data) => data?.table?.url || data.url"
  36. >
  37. <template v-slot="{ data }">
  38. <p>{{ data.title || "默认标题" }}</p>
  39. </template>
  40. </Photos>
  41. <ActionMenus
  42. class="select-menus"
  43. :menus="selectMenus"
  44. dire="row"
  45. v-if="selects.length"
  46. />
  47. </MainPanel>
  48. <FillSlide
  49. :getURL="(data) => data?.table?.url || data.url"
  50. :data="sortPhotos"
  51. v-model:active="active"
  52. @quit="active = null"
  53. v-if="active"
  54. >
  55. <template v-slot:foot>
  56. <ActionMenus class="menus" :menus="menus" dire="row" />
  57. </template>
  58. </FillSlide>
  59. </template>
  60. <script setup lang="ts">
  61. import MainPanel from "@/components/main-panel/index.vue";
  62. import FillSlide from "@/components/fill-slide/index.vue";
  63. import { roadPhotos, RoadPhoto } from "@/store/roadPhotos";
  64. import ActionMenus from "@/components/group-button/index.vue";
  65. import { router, writeRouteName } from "@/router";
  66. import { computed, onDeactivated, ref, watchEffect } from "vue";
  67. import { Mode } from "@/views/graphic/menus";
  68. import UiButton from "@/components/base/components/button/index.vue";
  69. import Header from "@/components/photos/header.vue";
  70. import Photos from "@/components/photos/index.vue";
  71. import ButtonPane from "@/components/button-pane/index.vue";
  72. import UiIcon from "@/components/base/components/icon/index.vue";
  73. import { useConfirm } from "@/hook";
  74. import { api } from "@/store/sync";
  75. import { photos } from "@/store/photos";
  76. const sortPhotos = computed(() => [...roadPhotos.value].reverse());
  77. const active = ref<RoadPhoto>();
  78. const selectMode = ref(false);
  79. const selects = ref<RoadPhoto[]>([]);
  80. const menus = [
  81. {
  82. key: "road",
  83. icon: "edit",
  84. text: "修改",
  85. onClick: () => gotoDraw(),
  86. },
  87. {
  88. key: "del",
  89. icon: "del",
  90. text: "删除",
  91. onClick: () => delPhoto(),
  92. },
  93. ];
  94. const selectMenus = [
  95. {
  96. key: "del",
  97. icon: "del",
  98. text: "删除",
  99. onClick: () => delSelects(),
  100. },
  101. ];
  102. watchEffect(() => {
  103. if (!selectMode.value) {
  104. selects.value = [];
  105. }
  106. });
  107. const delPhotoRaw = (roadPhoto = active.value) => {
  108. const index = roadPhotos.value.indexOf(roadPhoto);
  109. const reset = active.value ? roadPhotos.value.indexOf(active.value) : -1;
  110. if (~index) {
  111. roadPhotos.value.splice(index, 1);
  112. }
  113. if (~reset) {
  114. if (reset >= roadPhotos.value.length) {
  115. if (roadPhotos.value.length) {
  116. active.value = roadPhotos.value[roadPhotos.value.length - 1];
  117. } else {
  118. active.value = null;
  119. }
  120. } else {
  121. active.value = roadPhotos.value[reset];
  122. }
  123. }
  124. };
  125. const delPhoto = async (photo = active.value) => {
  126. if (await useConfirm(`确定要删除此数据?`)) {
  127. delPhotoRaw(photo);
  128. }
  129. };
  130. const delSelects = async () => {
  131. if (await useConfirm(`确定要删除这${selects.value.length}项数据?`)) {
  132. while (selects.value.length) {
  133. delPhotoRaw(selects.value[0]);
  134. selects.value.shift();
  135. }
  136. if (!sortPhotos.value.length) {
  137. selectMode.value = false;
  138. }
  139. }
  140. };
  141. const gotoDraw = () => {
  142. router.push({
  143. name: writeRouteName.graphic,
  144. params: { mode: Mode.Road, id: active.value.id, action: "update" },
  145. });
  146. };
  147. onDeactivated(() => {
  148. active.value = null;
  149. });
  150. </script>
  151. <style scoped lang="scss">
  152. .photo p {
  153. color: #fff;
  154. font-size: 14px;
  155. margin-top: 8px;
  156. }
  157. .menus {
  158. left: 50%;
  159. transform: translateX(-50%);
  160. bottom: var(--boundMargin);
  161. }
  162. .fun-ctrl {
  163. color: #fff;
  164. font-size: 20px;
  165. transition: color 0.3s ease;
  166. .icon {
  167. position: absolute;
  168. transform: translateX(-50%);
  169. }
  170. }
  171. .del {
  172. left: 50%;
  173. transform: translateX(-50%);
  174. bottom: var(--boundMargin);
  175. }
  176. .select-menus {
  177. left: 50%;
  178. transform: translateX(-50%);
  179. bottom: var(--boundMargin);
  180. }
  181. </style>