index.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <template>
  2. <transition name="fade">
  3. <div
  4. class="control-panl"
  5. :class="{ full, pc: os.isPc && !os.isTablet, 'strengthen-right': full }"
  6. v-if="!hide"
  7. >
  8. <div class="control-layer">
  9. <div
  10. class="panl pub-panl start"
  11. v-if="!(os.isPc && !os.isTablet)"
  12. @click="useEmitLeave()"
  13. >
  14. <div class="include-icon" style="text-align: center">
  15. <ui-icon type="close"></ui-icon>
  16. </div>
  17. </div>
  18. <div :class="{ ['scroll-view']: !(os.isPc && !os.isTablet) }">
  19. <div
  20. class="panl"
  21. v-for="(groupItem, i) in group"
  22. :class="{ apart: groupItem.apart }"
  23. >
  24. <p v-if="groupItem.label">{{ groupItem.label }}</p>
  25. <VCtrl
  26. v-for="ctrl in groupItem.ctrls"
  27. :activeCtrls="modelValue"
  28. :ctrl="ctrl"
  29. @click="(ctrl) => clickHandler(ctrl)"
  30. />
  31. </div>
  32. </div>
  33. <div
  34. class="panl pub-panl end"
  35. :class="{ active: !disabledMap.tool, 'fun-ctrl': true }"
  36. v-if="!os.isPc"
  37. @click="disabledMap.tool = !disabledMap.tool"
  38. >
  39. <div class="include-icon nav-ctrl">
  40. <ui-icon type="list"></ui-icon>
  41. <span>{{ count }}</span>
  42. </div>
  43. </div>
  44. </div>
  45. </div>
  46. </transition>
  47. </template>
  48. <script lang="ts" setup>
  49. import { ref, watchEffect, onActivated, onDeactivated, onUnmounted } from "vue";
  50. import { Group, Ctrl } from "./index";
  51. import { os } from "@/utils";
  52. import { disabledMap, boxWidthStack, useEmitLeave, controlFullStack } from "@/hook";
  53. import VCtrl from "./ctrl.vue";
  54. const props = defineProps<{
  55. group: Group;
  56. show: boolean;
  57. modelValue: Array<Ctrl>;
  58. full?: boolean;
  59. count?: number;
  60. }>();
  61. const updateHide = (show = props.show) => {
  62. if (show) {
  63. setTimeout(() => (hide.value = false));
  64. } else {
  65. setTimeout(() => (hide.value = true));
  66. }
  67. };
  68. const hide = ref(true);
  69. watchEffect(() => updateHide());
  70. onActivated(updateHide);
  71. onDeactivated(() => updateHide(false));
  72. const emit = defineEmits<{
  73. (e: "update:modelValue", data: any, oldData: Array<Ctrl>): void;
  74. (e: "select", data: Ctrl): void;
  75. }>();
  76. const clickHandler = (ctrl: Ctrl) => {
  77. if (ctrl.inClick) {
  78. return emit("select", ctrl);
  79. }
  80. const newRuns = [...props.modelValue];
  81. const index = newRuns.indexOf(ctrl);
  82. if (~index) {
  83. newRuns.splice(index, 1);
  84. } else if (ctrl.makeup) {
  85. newRuns.push(ctrl);
  86. } else {
  87. const makeupRuns = newRuns.filter((item) => item.makeup);
  88. const ctrlGroups = props.group.find((group) => group.ctrls.includes(ctrl));
  89. const anewRuns = newRuns.filter((item) => {
  90. const currentGroups = props.group.find((group) => group.ctrls.includes(item));
  91. return currentGroups !== ctrlGroups && (currentGroups.makeup || ctrlGroups.makeup);
  92. });
  93. newRuns.length = 0;
  94. newRuns.push(...Array.from(new Set([...makeupRuns, ...anewRuns])), ctrl);
  95. }
  96. emit("update:modelValue", newRuns, props.modelValue);
  97. };
  98. watchEffect(() => {
  99. if (!props.show) {
  100. emit(
  101. "update:modelValue",
  102. props.group.reduce((t, c) => [...t, ...c.ctrls.filter((ctrl) => ctrl.def)], []),
  103. []
  104. );
  105. }
  106. });
  107. watchEffect(() => {
  108. if (props.modelValue.some((item) => "show" in item && !item.show)) {
  109. emit(
  110. "update:modelValue",
  111. props.modelValue.filter((item) => !("show" in item && !item.show)),
  112. []
  113. );
  114. }
  115. });
  116. if (!os.isPc) {
  117. let inset = false;
  118. let boxWidth = ref("calc(100% - 60px)");
  119. const sysWidth = boxWidthStack.current.value;
  120. watchEffect(() => {
  121. if (props.show) {
  122. boxWidth.value = sysWidth.value.includes("calc")
  123. ? "calc(100% - 60px)"
  124. : sysWidth.value;
  125. if (!inset) {
  126. boxWidthStack.push(boxWidth);
  127. inset = true;
  128. }
  129. } else if (inset) {
  130. boxWidthStack.pop();
  131. inset = false;
  132. }
  133. });
  134. } else {
  135. let isShow;
  136. watchEffect(() => {
  137. if (isShow === props.show) {
  138. return;
  139. }
  140. if (props.show) {
  141. controlFullStack.push(ref(props.full));
  142. } else if (controlFullStack.length.value > 1) {
  143. controlFullStack.pop();
  144. }
  145. isShow = props.show;
  146. });
  147. onUnmounted(() => {
  148. if (isShow || isShow !== props.show) {
  149. controlFullStack.pop();
  150. }
  151. });
  152. }
  153. </script>
  154. <style lang="sass" scoped>
  155. @import './style.scss'
  156. </style>
  157. <style lang="scss">
  158. .control-panl .icon .tip {
  159. width: 68px;
  160. word-break: break-all;
  161. white-space: normal;
  162. text-align: center;
  163. padding: 10px 4px;
  164. }
  165. </style>