TemplatePanel.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <a-drawer
  3. :open="open"
  4. title="分析模板库"
  5. wrap-class-name="ai-template"
  6. :width="520"
  7. @close="emit('update:open', false)"
  8. >
  9. <div v-if="!groups.length" class="ai-template__empty">没有可用的模板。</div>
  10. <section v-for="group in groups" :key="group.group" class="ai-template__group">
  11. <div class="ai-template__group-head">
  12. <span>{{ group.group }}</span>
  13. <span class="ai-template__group-count">{{ group.items.length }}</span>
  14. </div>
  15. <article v-for="item in group.items" :key="item.id" class="ai-template__item">
  16. <div class="ai-template__item-head">
  17. <span class="ai-template__title">{{ item.title }}</span>
  18. <span v-if="item.builtin" class="ai-template__badge">预置</span>
  19. <span class="ai-template__spacer"></span>
  20. <a-button size="small" @click="onPick(item)">插入</a-button>
  21. <a-button v-if="!item.builtin" size="small" danger type="text" @click="onRemove(item)">删除</a-button>
  22. </div>
  23. <p class="ai-template__prompt">{{ item.prompt }}</p>
  24. </article>
  25. </section>
  26. </a-drawer>
  27. </template>
  28. <script lang="ts" setup>
  29. /**
  30. * 分析模板抽屉:选一个模板填入输入框(只填不发)。
  31. *
  32. * 由旧版模板面板迁移并按需裁剪:只保留「选」,
  33. * 不带存为模板 / 导出导入工具条;沿用历史存储键,样式用 --ai-* 令牌。
  34. */
  35. import { computed, ref, watch } from 'vue';
  36. import { Button, Drawer } from 'ant-design-vue';
  37. import { useMessage } from '@/core/hooks/web/useMessage';
  38. import {
  39. groupTemplates,
  40. readCustomTemplates,
  41. removeTemplate,
  42. type PromptTemplate,
  43. } from '../utils/promptTemplateLibrary';
  44. const props = defineProps<{ open: boolean }>();
  45. const emit = defineEmits<{
  46. (e: 'update:open', value: boolean): void;
  47. (e: 'pick', prompt: string): void;
  48. }>();
  49. const ADrawer = Drawer;
  50. const AButton = Button;
  51. const { showMessage } = useMessage();
  52. const custom = ref<PromptTemplate[]>(readCustomTemplates());
  53. const groups = computed(() => groupTemplates(custom.value));
  54. // 每次打开都重读,避免多标签/外部改动导致列表过期
  55. watch(
  56. () => props.open,
  57. (open) => {
  58. if (open) {
  59. custom.value = readCustomTemplates();
  60. }
  61. },
  62. );
  63. function onPick(item: PromptTemplate) {
  64. emit('pick', item.prompt);
  65. emit('update:open', false);
  66. }
  67. function onRemove(item: PromptTemplate) {
  68. custom.value = removeTemplate(item.id);
  69. showMessage('已删除模板', 'success');
  70. }
  71. </script>
  72. <style lang="less" scoped>
  73. .ai-template {
  74. &__empty {
  75. padding: var(--ai-sp-4) 0;
  76. font-size: 12px;
  77. color: var(--ai-text-2);
  78. text-align: center;
  79. }
  80. &__group {
  81. margin-bottom: var(--ai-sp-4);
  82. }
  83. &__group-head {
  84. display: flex;
  85. align-items: baseline;
  86. gap: 6px;
  87. margin-bottom: var(--ai-sp-2);
  88. padding-bottom: 4px;
  89. font-size: 11px;
  90. font-weight: 600;
  91. letter-spacing: 0.04em;
  92. text-transform: uppercase;
  93. color: var(--ai-text-2);
  94. border-bottom: 1px solid var(--ai-border);
  95. }
  96. &__group-count {
  97. font-weight: 400;
  98. color: var(--ai-text-2);
  99. }
  100. &__item {
  101. padding: var(--ai-sp-2) 0;
  102. & + & {
  103. border-top: 1px dashed var(--ai-border);
  104. }
  105. }
  106. &__item-head {
  107. display: flex;
  108. align-items: center;
  109. gap: 6px;
  110. }
  111. &__title {
  112. font-size: 13px;
  113. font-weight: 600;
  114. color: var(--ai-text);
  115. overflow: hidden;
  116. white-space: nowrap;
  117. text-overflow: ellipsis;
  118. }
  119. &__badge {
  120. flex: 0 0 auto;
  121. padding: 0 6px;
  122. font-size: 10.5px;
  123. line-height: 17px;
  124. color: var(--ai-text-2);
  125. border: 1px solid var(--ai-border);
  126. border-radius: 4px;
  127. }
  128. &__spacer {
  129. flex: 1 1 auto;
  130. }
  131. &__prompt {
  132. margin: 4px 0 0;
  133. font-size: 12px;
  134. line-height: 1.7;
  135. color: var(--ai-text-2);
  136. /* 模板正文可能带占位符,保留换行但压到 3 行,避免抽屉变成文章 */
  137. display: -webkit-box;
  138. -webkit-line-clamp: 3;
  139. -webkit-box-orient: vertical;
  140. overflow: hidden;
  141. white-space: pre-wrap;
  142. word-break: break-word;
  143. }
  144. }
  145. </style>