| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359 |
- <template>
- <div ref="input_area_container">
- <div class="dialog-input-area-container">
- <slot name="top"></slot>
- <div class="textarea-container">
- <a-textarea
- class="textarea-input"
- placeholder="输入文本内容"
- :model-value="input_text_value"
- allow-clear
- :auto-size="{
- minRows: 2,
- maxRows: 4
- }"
- @input="handleTextInput"
- @keyup="handleTextKeyUp"
- />
- </div>
- <InputActions
- :disabled="disabled"
- :enable_file_upload="enable_file_upload"
- :enable_frequent_question="enable_frequent_question"
- :enable_voice_recognition="enable_voice_recognition"
- :file_upload_type="file_upload_type"
- :file_upload_limit="file_upload_limit"
- @fileUpload="handleFileUpload"
- @questionDefine="handleQuestionDefine"
- @voiceRecognize="handleVoiceRecognize"
- @submit="handleSubmit"
- />
- <slot name="bottom"></slot>
- <FileUploadPreviewV1
- v-if="input_file_list.length !== 0"
- class="file-upload-preview-container"
- :file_list="input_file_list"
- :enable_remove="true"
- @delete="handleFileDelete"
- />
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted, onUnmounted } from 'vue';
- import InputActions from './dialog-input/InputActions.vue';
- import FileUploadPreviewV1 from '../file-preview/FileUploadPreviewV1.vue';
- import useFileSelect from './use-file-select';
- import useFileSelectedV2 from './use-file-select-v2';
- import useEleSizeV2 from '../../utils/use-ele-size-v2';
- const props = defineProps({
- /**
- * 是否禁用操作
- * 默认 false
- * 当此值为 true 时,此组件的任何功能都不可用
- * 当对话正在进行时,此值应为 true,意味着不允许继续对话
- * 直到一轮对话结束,或者一轮对话终止,此值才应该变为 false
- */
- disabled: {
- type: Boolean,
- default: false,
- required: false
- },
- // 智能体的基本信息
- agent_info: {
- type: Object
- },
- // 智能体的配置项
- agent_config: {
- type: Object
- },
- /**
- * 是否开启文件上传功能
- * 默认 true,即默认开启
- * 当此值为 false 时,该组件将没有文件上传按钮
- */
- enable_file_upload: {
- type: Boolean,
- default: true,
- required: false
- },
- /**
- * 是否开启 常用问题 功能
- * 如果此值为false,则 常用问题 定义功能不可用
- */
- enable_frequent_question: {
- type: Boolean,
- default: true,
- required: false
- },
- /**
- * 是否开启音频识别功能
- * 如果此值为 false,则语音识别功能不可用
- */
- enable_voice_recognition: {
- type: Boolean,
- default: false,
- required: false
- },
- /**
- * 在 enable_file_upload === true 的前提下
- * 文件上传的类型,默认是 *,不限类型
- * 对应html属性 accept
- * 对应 arco.design Upload accept 属性
- * @see https://arco.design/vue/component/upload#API
- * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#htmlattrdefaccept
- */
- file_upload_type: {
- type: String,
- default: '*',
- required: false
- },
- /**
- * 在 enable_file_upload === true 的前提下
- * 文件上传的数量限制
- * 默认值为0,表示不限制
- * 对应 arco.design Upload limit 属性
- */
- file_upload_limit: {
- type: Number,
- default: 0,
- required: false
- },
- /**
- * 输入框文本占位提示
- */
- text_placeholder: {
- type: String
- },
- /**
- * 输入的文本长度限制
- * 默认值为0,表示不限制长度
- * 对应 arco.design textarea max-length 属性
- * @see https://arco.design/vue/component/textarea#API
- */
- text_limit: {
- type: Number,
- default: 0,
- required: false
- },
- /**
- * 是否显示字数统计
- * 对应 arco.design textarea show-word-limit
- * @see https://arco.design/vue/component/textarea#API
- */
- show_text_count: {
- type: Boolean,
- default: false,
- required: false
- }
- });
- /**
- * 文本域输入的内容
- */
- const input_text_value = ref('');
- const input_file_list = ref([]);
- const emit = defineEmits(['submit', 'sizeChange']);
- // const fileSelect = useFileSelect('file_upload_input');
- const { select, remove } = useFileSelectedV2();
- const { width: input_area_width, height: input_area_height } = useEleSizeV2('input_area_container', (size) => {
- const w = size.width;
- const h = size.height;
- emit('sizeChange', size);
- });
- const handleSubmit = () => {
- // 检查是否是禁用状态
- if (props.disabled) {
- return;
- }
- const real_file_list = [];
- input_file_list.value.forEach((item) => {
- real_file_list.push(item.file);
- });
- emit('submit', {
- text: input_text_value.value,
- files: real_file_list
- });
- };
- const clear = () => {
- input_text_value.value = '';
- input_file_list.value = [];
- };
- /**
- * 文件上传
- */
- const handleFileUpload = () => {
- select((e) => {
- const files = e.target.files;
- const id = e.target.id; // input ID
- const file_total = files.length;
- if (file_total === 0) {
- // 没有文件
- }
- if (file_total === 1) {
- // 1个文件
- input_file_list.value.push({
- type: 1, // 单文件
- id: id,
- index: 0,
- file: files[0]
- });
- }
- if (file_total > 1) {
- // 多个文件
- for (let i = 0; i < file_total; i++) {
- const item = files[i];
- const index = i;
- input_file_list.value.push({
- type: 2, // 多文件
- id: id,
- index: index,
- file: item
- });
- }
- }
- });
- };
- /**
- * 移除已选择的文件
- * @param file_item
- */
- const handleFileDelete = (file_item) => {
- const arr = [];
- const del_f_index = file_item.index;
- const del_f_id = file_item.id;
- input_file_list.value.forEach((item) => {
- const cur_f_id = item.id;
- if (cur_f_id === del_f_id) {
- // 被移除
- } else {
- arr.push(item);
- }
- });
- input_file_list.value = arr;
- };
- /**
- * 常用问题定义
- */
- const handleQuestionDefine = () => {};
- /**
- * 语音识别
- */
- const handleVoiceRecognize = () => {};
- /**
- * 移除文本中的换行符
- */
- const removeBreakLineFlag = () => {
- input_text_value.value = input_text_value.value.replace(/\n/, '');
- };
- /**
- * 表单输入事件
- * @param value
- * @param event
- */
- const handleTextInput = (value, event) => {
- if (props.disabled) {
- return;
- }
- input_text_value.value = value;
- };
- /**
- * 用户按键事件
- * @param e
- */
- const handleTextKeyUp = (e) => {
- if (props.disabled) {
- if (e.keyCode === 13) {
- removeBreakLineFlag();
- }
- return;
- }
- if (e.keyCode === 13) {
- if (e.ctrlKey) {
- // 此时也按下Ctrl:换行处理
- } else {
- // 此时没有按下Ctrl
- removeBreakLineFlag();
- // 提交
- // emit('submit');
- handleSubmit();
- }
- }
- };
- onUnmounted(() => {
- remove();
- });
- defineExpose({
- clear: clear
- });
- </script>
- <style lang="css" scoped>
- .dialog-input-area-container {
- display: flex;
- flex-direction: column;
- /* color: var(--color-text-1); */
- box-shadow: 0 0 5px var(--color-text-4);
- border-radius: 10px;
- padding: 10px;
- /* background-color: #fff; */
- background-color: var(--color-bg-1);
- color: var(--color-text-1);
- flex-grow: 1;
- }
- .textarea-container {
- flex-grow: 1;
- display: flex;
- margin-bottom: 5px;
- }
- .textarea-input {
- border-radius: 5px;
- }
- .file-input-btn {
- display: none;
- }
- .file-upload-preview-container {
- margin-top: 5px;
- }
- </style>
|