sign.vue 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. <template>
  2. <ui-group-option class="sign" :class="{ active, search }">
  3. <div class="content">
  4. <span class="cover" @click="flyView(view)">
  5. <img :src="getResource(getFileUrl(view.cover))" alt="" />
  6. </span>
  7. <ui-input
  8. class="view-title-input"
  9. type="text"
  10. :modelValue="view.title"
  11. :maxlength="15"
  12. @update:modelValue="(title: string) => $emit('updateTitle', title.trim())"
  13. v-show="isEditTitle"
  14. ref="inputRef"
  15. height="28px"
  16. />
  17. <div class="title" v-show="!isEditTitle" @click="flyView(view)">
  18. <p>{{ view.title }}</p>
  19. <span> {{ getModelDesc(modelType as ModelType) }}</span>
  20. </div>
  21. </div>
  22. <div class="action" v-if="edit">
  23. <ui-icon type="order" ctrl />
  24. <ui-more
  25. :options="menus"
  26. style="margin-left: 20px"
  27. @click="(action: keyof typeof actions) => actions[action]()"
  28. />
  29. </div>
  30. </ui-group-option>
  31. </template>
  32. <script lang="ts" setup>
  33. import { ref, computed, watchEffect } from "vue";
  34. import { useFocus } from "bill/hook/useFocus";
  35. import { custom, getResource } from "@/env";
  36. import { deepIsRevise, getFileUrl } from "@/utils";
  37. import { loadModel, getModelDesc, ModelType, currentModel } from "@/model";
  38. import { viewToModelType } from "@/store";
  39. import type { View } from "@/store";
  40. import { Message } from "bill/expose-common";
  41. import { flyView } from "@/hook/use-fly";
  42. const props = withDefaults(
  43. defineProps<{ view: View; edit?: boolean; search?: boolean }>(),
  44. { edit: true }
  45. );
  46. const emit = defineEmits<{
  47. (e: "updateCover", cover: string): void;
  48. (e: "updateTitle", title: string): void;
  49. (e: "delete"): void;
  50. }>();
  51. const menus = [
  52. { label: "重命名", value: "rename" },
  53. { label: "删除", value: "delete" },
  54. ];
  55. const inputRef = ref();
  56. const isEditTitle = useFocus(computed(() => inputRef.value?.vmRef.root));
  57. watchEffect(() => {
  58. if (!isEditTitle.value && !props.view.title.length) {
  59. isEditTitle.value = true;
  60. Message.warning("视图名称不可为空");
  61. }
  62. });
  63. const actions = {
  64. delete: () => emit("delete"),
  65. rename: () => (isEditTitle.value = true),
  66. };
  67. const modelType = viewToModelType(props.view);
  68. const active = computed(() => {
  69. return (
  70. custom.currentView === props.view && !deepIsRevise(currentModel.value, modelType)
  71. );
  72. });
  73. </script>
  74. <style lang="scss" src="./style.scss" scoped></style>
  75. <style>
  76. .view-title-input.ui-input .text.suffix input {
  77. padding-right: 50px;
  78. }
  79. </style>