InputActions.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. <template>
  2. <div class="dialog-input-actions">
  3. <div class="dialog-input-action-left" v-if="!agent_id">
  4. <a-button
  5. class="action-left-item-btn"
  6. :class="is_deep_think ? 'action-left-item-btn-active' : ''"
  7. @click="handleThinkChange"
  8. ><icon-ear />
  9. {{ $t('conversation.deep_think') }}
  10. </a-button>
  11. <a-button
  12. class="action-left-item-btn"
  13. :class="is_connect_internet ? 'action-left-item-btn-active' : ''"
  14. :disabled="disabled_internet"
  15. @click="handleInternetChange"
  16. >
  17. <img
  18. class="icon"
  19. v-if="!is_connect_internet && !disabled_internet"
  20. src="../../../assets/chat/internet.png"
  21. alt=""
  22. />
  23. <img class="icon" v-if="is_connect_internet" src="../../../assets/chat/internet-active.png" alt="" />
  24. <img class="icon" v-if="disabled_internet" src="../../../assets/chat/internet-disable.png" alt="" />
  25. {{ $t('conversation.internet_search') }}
  26. </a-button>
  27. <a-select
  28. :disabled="disabled_knowledge"
  29. :placeholder="$t('conversation.knowledge_base')"
  30. :trigger-props="{ autoFitPopupMinWidth: true }"
  31. v-model="base_list"
  32. multiple
  33. allow-clear
  34. :max-tag-count="1"
  35. >
  36. <a-option v-for="item in knowledge_list" :key="item.id" :label="item.name" :value="item.id"></a-option>
  37. </a-select>
  38. </div>
  39. <div class="dialog-input-action-left" v-else></div>
  40. <div class="dialog-input-action-right">
  41. <!-- <a-tooltip content="常用问题定义" position="top">
  42. <div v-if="enable_frequent_question" class="action-right-item-btn" @click="handleQuestionDefine">
  43. <img src="../../../assets/question-define.png" />
  44. </div>
  45. </a-tooltip> -->
  46. <div v-if="enable_frequent_question" class="action-right-item-btn" @click="handleQuestionDefine">
  47. <img src="../../../assets/question-define.png" />
  48. </div>
  49. <!-- <a-tooltip content="文件上传" position="top">
  50. <div v-if="enable_file_upload" class="action-right-item-btn" @click="handleFileUpload">
  51. <img src="../../../assets/file-upload.png" />
  52. </div>
  53. </a-tooltip> -->
  54. <!-- <a-tooltip content="语音识别" position="top">
  55. <div v-if="enable_voice_recognition" class="action-right-item-btn" @click="handleVoiceRecognize">语音识别</div>
  56. </a-tooltip> -->
  57. <a-tooltip :content="$t('conversation.file_upload_message')" position="top">
  58. <div v-if="enable_file_upload && !disabled_upload" class="action-right-item-btn" @click="handleFileUpload">
  59. <img src="../../../assets/file-upload.png" />
  60. </div>
  61. </a-tooltip>
  62. <a-tooltip :content="$t('conversation.input_message')" position="top">
  63. <div class="action-right-item-btn submit-input-btn" @click="handleSubmit">
  64. {{ $t('conversation.input_confirm') }}
  65. </div>
  66. </a-tooltip>
  67. </div>
  68. </div>
  69. </template>
  70. <script setup>
  71. import { ref, computed, onMounted, watch } from 'vue';
  72. import { getKnowledgeList } from '../../../apis/knowledge.js';
  73. const props = defineProps({
  74. /**
  75. * 是否禁用操作
  76. * 默认 false
  77. * 当此值为 true 时,此组件的任何功能都不可用
  78. * 当对话正在进行时,此值应为 true,意味着不允许继续对话
  79. * 直到一轮对话结束,或者一轮对话终止,此值才应该变为 false
  80. */
  81. disabled: {
  82. type: Boolean,
  83. default: false,
  84. required: false
  85. },
  86. /**
  87. * 是否开启文件上传功能
  88. * 默认 true,即默认开启
  89. * 当此值为 false 时,该组件将没有文件上传按钮
  90. */
  91. enable_file_upload: {
  92. type: Boolean,
  93. default: true,
  94. required: false
  95. },
  96. /**
  97. * 是否开启 常用问题 功能
  98. * 如果此值为false,则 常用问题 定义功能不可用
  99. */
  100. enable_frequent_question: {
  101. type: Boolean,
  102. default: false,
  103. required: false
  104. },
  105. /**
  106. * 是否开启音频识别功能
  107. * 如果此值为 false,则语音识别功能不可用
  108. */
  109. enable_voice_recognition: {
  110. type: Boolean,
  111. default: false,
  112. required: false
  113. },
  114. /**
  115. * 在 enable_file_upload === true 的前提下
  116. * 文件上传的类型,默认是 *,不限类型
  117. * 对应html属性 accept
  118. * 对应 arco.design Upload accept 属性
  119. * @see https://arco.design/vue/component/upload#API
  120. * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#htmlattrdefaccept
  121. */
  122. file_accept: {
  123. type: String,
  124. default: '*',
  125. required: false
  126. },
  127. /**
  128. * 在 enable_file_upload === true 的前提下
  129. * 文件上传的数量限制
  130. * 默认值为0,表示不限制
  131. * 对应 arco.design Upload limit 属性
  132. */
  133. file_upload_limit: {
  134. type: Number,
  135. default: 0,
  136. required: false
  137. },
  138. input_file_list_len: {
  139. type: Number,
  140. default: 0
  141. },
  142. agent_id: {
  143. type: String,
  144. default: ''
  145. }
  146. });
  147. const emit = defineEmits(['fileUpload', 'questionDefine', 'voiceRecognize', 'submit', 'actionConfig']);
  148. /**
  149. *
  150. * 深度思考
  151. * 联网搜索
  152. * */
  153. const is_deep_think = ref(false);
  154. const is_connect_internet = ref(false);
  155. //
  156. const disabled_internet = ref(false);
  157. const disabled_knowledge = ref(false);
  158. const disabled_upload = ref(false);
  159. // 深度思考
  160. const handleThinkChange = () => {
  161. is_deep_think.value = !is_deep_think.value;
  162. emit('actionConfig', {
  163. isDeep: is_deep_think.value ? 2 : 1,
  164. knowledgeId: base_list.value,
  165. chatMode: is_connect_internet.value ? 2 : 1
  166. });
  167. };
  168. // 联网搜索
  169. const handleInternetChange = () => {
  170. if (disabled_internet.value) {
  171. is_connect_internet.value = false;
  172. return;
  173. }
  174. is_connect_internet.value = !is_connect_internet.value;
  175. if (is_connect_internet.value) {
  176. disabled_knowledge.value = true;
  177. disabled_upload.value = true;
  178. } else {
  179. disabled_knowledge.value = false;
  180. disabled_upload.value = false;
  181. }
  182. emit('actionConfig', {
  183. isDeep: is_deep_think.value ? 2 : 1,
  184. knowledgeId: base_list.value,
  185. chatMode: is_connect_internet.value ? 2 : 1
  186. });
  187. };
  188. const base_list = ref([]);
  189. /**
  190. * 知识库
  191. * */
  192. const knowledge_list = ref([]);
  193. watch(
  194. () => base_list.value.length,
  195. (len) => {
  196. if (len) {
  197. disabled_internet.value = true;
  198. disabled_upload.value = true;
  199. } else {
  200. disabled_internet.value = false;
  201. disabled_upload.value = false;
  202. }
  203. emit('actionConfig', {
  204. isDeep: is_deep_think.value ? 2 : 1,
  205. knowledgeId: base_list.value,
  206. chatMode: base_list.value.length ? 3 : 1
  207. });
  208. },
  209. {
  210. immediate: true
  211. }
  212. );
  213. watch(
  214. () => props.input_file_list_len,
  215. (len) => {
  216. if (len) {
  217. disabled_internet.value = true;
  218. disabled_knowledge.value = true;
  219. } else {
  220. disabled_internet.value = false;
  221. disabled_knowledge.value = false;
  222. }
  223. }
  224. );
  225. const handleQuestionDefine = () => {
  226. emit('questionDefine');
  227. };
  228. const handleFileUpload = () => {
  229. emit('fileUpload');
  230. };
  231. const handleVoiceRecognize = () => {
  232. emit('voiceRecognize');
  233. };
  234. const handleSubmit = () => {
  235. emit('submit');
  236. };
  237. const getKnowledgeListFun = async () => {
  238. try {
  239. const res = await getKnowledgeList(1, 999, '');
  240. if (res.code / 1 === 200) {
  241. knowledge_list.value = res.data.rows;
  242. }
  243. } catch (e) {
  244. console.log(e);
  245. }
  246. };
  247. onMounted(() => {
  248. getKnowledgeListFun();
  249. });
  250. </script>
  251. <style lang="css" scoped>
  252. .dialog-input-actions {
  253. display: flex;
  254. justify-content: space-between;
  255. align-items: center;
  256. }
  257. .dialog-input-action-left {
  258. display: flex;
  259. }
  260. .action-left-item-btn {
  261. height: 30px;
  262. line-height: 30px;
  263. cursor: pointer;
  264. padding: 0 10px;
  265. border: 1px solid var(--color-border-2);
  266. color: var(--color-text-2);
  267. border-radius: 8px;
  268. background: var(color-bg-1);
  269. .icon {
  270. width: 14px;
  271. margin-right: 3px;
  272. }
  273. }
  274. .action-left-item-btn:hover {
  275. }
  276. .action-left-item-btn-active {
  277. border-color: var(--color-bolder-11);
  278. color: var(--color-bolder-11);
  279. }
  280. .action-left-item-btn-active:hover {
  281. border-color: var(--color-bolder-11);
  282. color: var(--color-bolder-11);
  283. }
  284. .dialog-input-action-right {
  285. display: flex;
  286. justify-content: space-between;
  287. align-items: center;
  288. }
  289. .action-left-item-btn {
  290. margin-right: 10px;
  291. cursor: pointer;
  292. }
  293. .connect-internet {
  294. color: var(--color-text-3);
  295. }
  296. .search-from-network {
  297. display: inline-block;
  298. margin-left: 5px;
  299. }
  300. .is-connnected {
  301. color: var(--color-text-1);
  302. }
  303. .not-connnected {
  304. color: var(--color-text-3);
  305. }
  306. .action-right-item-btn {
  307. margin-left: 17px;
  308. cursor: pointer;
  309. display: flex;
  310. justify-content: center;
  311. align-items: center;
  312. }
  313. .action-left-item-btn img {
  314. width: 24px;
  315. }
  316. .action-right-item-btn img {
  317. width: 24px;
  318. }
  319. .submit-input-btn {
  320. background-color: rgb(var(--primary-6));
  321. color: #fff;
  322. /* padding: 5px 15px; */
  323. /* border-radius: 15px; */
  324. font-size: 14px;
  325. width: 73px;
  326. height: 31px;
  327. border-radius: 40px;
  328. text-align: center;
  329. line-height: 31px;
  330. }
  331. </style>
  332. <style>
  333. .arco-switch.arco-switch-type-circle.arco-switch-checked.chat-connect-network-switch {
  334. background-color: var(--color-fill-2);
  335. }
  336. .arco-switch.arco-switch-type-circle.arco-switch-checked.chat-connect-network-switch .arco-switch-handle {
  337. background-color: rgb(var(--primary-6));
  338. }
  339. </style>