sign.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. <template>
  2. <ui-group-option
  3. class="sign-measure"
  4. :class="{ active: measure.selected }"
  5. @mouseenter="measure.selected = true"
  6. @mouseleave="measure.selected = false"
  7. >
  8. <div class="info">
  9. <ui-icon :type="MeasureTypeMeta[measure.type].icon" class="type" />
  10. <div v-show="!isEditTitle">
  11. <p>{{ measure.title || MeasureTypeMeta[measure.type].unitDesc }}</p>
  12. <span>{{ desc }} {{ MeasureTypeMeta[measure.type].unit }}</span>
  13. </div>
  14. <ui-input
  15. class="view-title-input"
  16. type="text"
  17. :modelValue="measure.title"
  18. :maxlength="15"
  19. @update:modelValue="(title: string) => $emit('updateTitle', title.trim())"
  20. v-show="isEditTitle"
  21. ref="inputRef"
  22. height="28px"
  23. />
  24. </div>
  25. <div class="actions" @click.stop>
  26. <!-- <ui-icon type="del" ctrl @click.stop="$emit('delete')" v-if="edit" /> -->
  27. <ui-icon type="pin" ctrl @click.stop="fly" :class="{disabled: !getMeasureIsShow(measure)}" />
  28. <ui-more
  29. v-if="edit"
  30. :options="menus"
  31. style="margin-left: 20px"
  32. @click="(action: keyof typeof actions) => actions[action]()"
  33. />
  34. </div>
  35. </ui-group-option>
  36. </template>
  37. <script setup lang="ts">
  38. import { MeasureTypeMeta, getMeasureIsShow } from '@/store'
  39. import { getSceneMeasure, getSceneMeasureDesc } from '@/sdk'
  40. import { useFocus } from 'bill/hook/useFocus'
  41. import type { Measure } from '@/store'
  42. import { computed, ref, watch, watchEffect } from 'vue';
  43. import { Message } from 'bill/index';
  44. import { custom } from '@/env';
  45. const props = withDefaults(
  46. defineProps<{ measure: Measure, edit?: boolean }>(),
  47. { edit: true }
  48. )
  49. const emit = defineEmits<{
  50. (e: 'delete'): void,
  51. (e: 'updateTitle', title: string): void,
  52. }>()
  53. const inputRef = ref()
  54. const isEditTitle = useFocus(computed(() => inputRef.value?.vmRef.root))
  55. const menus = [
  56. { label: '重命名', value: 'rename' },
  57. { label: '删除', value: 'delete' },
  58. ]
  59. const actions = {
  60. delete: () => emit('delete'),
  61. rename: () => isEditTitle.value = true
  62. }
  63. watchEffect(() => {
  64. if (!isEditTitle.value && !props.measure.title.length) {
  65. isEditTitle.value = true
  66. Message.warning('测量名称不可为空')
  67. }
  68. })
  69. const fly = () => {
  70. getSceneMeasure(props.measure)?.fly()
  71. }
  72. const desc = ref('-')
  73. watch(
  74. () => [props.measure, custom.showMeasures, custom.showModelsMap],
  75. () => {
  76. const smeasure = getSceneMeasure(props.measure)
  77. desc.value = smeasure ? getSceneMeasureDesc(smeasure, props.measure) : '-'
  78. },
  79. { deep: true, flush: 'post', immediate: true }
  80. )
  81. </script>
  82. <style lang="scss" scoped>
  83. .sign-measure {
  84. display: flex;
  85. justify-content: space-between;
  86. align-items: center;
  87. padding: 20px 0;
  88. margin: 0;
  89. border-bottom: 1px solid var(--colors-border-color);
  90. position: relative;
  91. &.active::after {
  92. content: '';
  93. position: absolute;
  94. pointer-events: none;
  95. inset: 0 -20px;
  96. background-color: rgba(0, 200, 175, 0.16);
  97. z-index: -1;
  98. }
  99. .info {
  100. flex: 1;
  101. display: flex;
  102. align-items: center;
  103. .type {
  104. width: 48px;
  105. height: 48px;
  106. border-radius: 4px;
  107. overflow: hidden;
  108. display: flex;
  109. background: rgba(0,0,0,0.5);
  110. font-size: 18px;
  111. align-items: center;
  112. justify-content: center;
  113. }
  114. div {
  115. margin-left: 10px;
  116. p {
  117. color: #fff;
  118. font-size: 14px;
  119. }
  120. span {
  121. color: rgba(255,255,255,0.6);;
  122. font-size: 12px;
  123. }
  124. }
  125. }
  126. .actions {
  127. flex: none;
  128. > * {
  129. margin-left: 22px;
  130. }
  131. }
  132. }
  133. </style>
  134. <style>
  135. .view-title-input.ui-input .text.suffix input {
  136. padding-right: 50px;
  137. }
  138. </style>