wujingjing
2025-03-11 c144c39d9f3f86e1b52ae4247f8322f6396a4320
src/components/chat/components/playBar/PlayBar.vue
@@ -25,12 +25,14 @@
            </el-button>
         </div>
         <div class="set-input flex-auto">
         <div class="set-input">
            <div v-if="attachList?.length > 0" class="flex gap-3.5 w-full overflow-x-auto px-2 pb-2">
               <div
                  v-for="(item, index) in attachList"
                  :key="index"
                  class="flex items-center gap-2 bg-[#f5f5f5] px-2 py-3 rounded-lg w-[220px] relative group"
                  :class="{ 'cursor-pointer': item.type === 'table' || item.type === 'metric' }"
                  @click="openAttachPreview(item)"
               >
                  <template v-if="item.type === 'file'">
                     <el-image
@@ -54,9 +56,16 @@
                        <div class="text-info text-sm over-ellipsis w-full">{{ `业务表格,${item.model.values?.length} 条记录` }}</div>
                     </div>
                  </template>
                  <template v-if="item.type === 'metric'">
                     <div class="ywifont !text-[24px] flex-0" :class="[`ywicon-${item.icon}`, item.iconClass]"></div>
                     <div class="flex flex-col gap-0.5 w-full flex-auto">
                        <div class="font-bold over-ellipsis w-full">{{ item.title }}</div>
                        <div class="text-info text-sm over-ellipsis w-full">{{ `指标数据,${item.model.values?.length} 条记录` }}</div>
                     </div>
                  </template>
                  <div
                     class="group-hover:visible invisible absolute right-0.5 top-0.5 bg-red-500 flex-center rounded-full p-0.5 cursor-pointer"
                     @click="deleteAttachInIndex(index)"
                     @click.stop="deleteAttachInIndex(index)"
                  >
                     <span class="ywifont ywicon-guanbi text-white !text-[10px] font-bold"></span>
                  </div>
@@ -68,7 +77,7 @@
               type="textarea"
               resize="none"
               maxlength="1024"
               :autosize="{ minRows: 1, maxRows: 8 }"
               :autosize="{ minRows: 3, maxRows: 8 }"
               v-elInputFocus
               show-word-limit
               @keydown="keydownInput"
@@ -94,17 +103,24 @@
                  >
                  </el-button>
                  <div class="flex-items-center gap-2">
                     <el-tooltip placement="top" content="关联业务表格">
                        <div
                           class="cursor-pointer size-[38px] relative !z-10 rounded flex-center hover:bg-[#f2f2f2]"
                           @click="openBusinessTable"
                        >
                           <span class="ywifont ywicon-biaoge !text-[24px]"></span>
                     <el-tooltip placement="top" content="关联指标">
                        <div class="cursor-pointer size-[24px] relative !z-10 rounded flex-center hover:bg-[#f2f2f2]" @click="openMetric">
                           <span class="ywifont ywicon-zhibiao !text-[19px]"></span>
                        </div>
                     </el-tooltip>
                     <el-tooltip placement="top" content="关联业务表格">
                        <div
                           class="cursor-pointer size-[24px] relative !z-10 rounded flex-center hover:bg-[#f2f2f2]"
                           @click="openBusinessTable"
                        >
                           <span class="ywifont ywicon-biaoge !text-[19px]"></span>
                        </div>
                     </el-tooltip>
                     <el-tooltip placement="top" content="上传附件">
                        <div class="cursor-pointer size-[38px] relative !z-10 rounded flex-center hover:bg-[#f2f2f2]" @click="openFileClick">
                           <span class="ywifont ywicon-fujian !text-[25px] font-bold"></span>
                        <div class="cursor-pointer size-[24px] relative !z-10 rounded flex-center hover:bg-[#f2f2f2]" @click="openFileClick">
                           <span class="ywifont ywicon-fujian !text-[20px] font-bold"></span>
                        </div>
                     </el-tooltip>
@@ -142,22 +158,33 @@
            @updateInput="updateInputValue"
         />
         <BusinessTable v-model="businessTableIsShow" @submit="submitBusinessTable" />
         <BusinessTablePreview :data="attachPreviewData" v-model="attachPreviewIsShow" />
         <MetricValues v-model="metricIsShow" @submit="submitMetricValues" />
         <MetricValuesPreview v-model="metricPreviewIsShow" :data="metricPreviewData" />
      </div>
   </div>
</template>
<script setup lang="ts">
import type { InputInstance } from 'element-plus';
import { nextTick, ref } from 'vue';
import { nextTick, onActivated, onDeactivated, ref } from 'vue';
import BusinessTable from './businessTable/index.vue';
import BusinessTablePreview from './businessTablePreview/index.vue';
import type { Attach } from './hook/useAttach';
import { useAttach } from './hook/useAttach';
import { useInputEvent } from './hook/useInputEvent';
import { useUploadFile } from './hook/useUploadFile';
import InputTip from './inputTip/index.vue';
import CommonPhrases from './phrase/CommonPhrases.vue';
import SceneSwitch from './SceneSwitch.vue';
import VoicePage from './voicePage/VoicePage.vue';
import { useCompRef } from '/@/utils/types';
import { useUploadFile } from './hook/useUploadFile';
import BusinessTable from './businessTable/index.vue';
import { useAttach } from './hook/useAttach';
import emitter from '/@/utils/mitt';
import MetricValues from './metricValues/MetricValues.vue';
import MetricValuesPreview from './metricValues/MetricValuesPreview.vue';
const emits = defineEmits(['sendClick', 'stopGenClick']);
const props = defineProps({
   isTalking: Boolean,
@@ -249,26 +276,103 @@
   }
   removeAttach(index);
};
const checkTableAttachExist = (data: any) => {
   const dataStr = JSON.stringify(data);
   const exist = attachList.value.find((item) => item.type === 'table' && JSON.stringify(item.model) === dataStr);
   if (exist) {
      return true;
   }
   return false;
};
const checkMetricAttachExist = (data: any) => {
   const dataStr = JSON.stringify(data);
   const exist = attachList.value.find((item) => item.type === 'metric' && JSON.stringify(item.model) === dataStr);
   if (exist) {
      return true;
   }
   return false;
};
const submitBusinessTable = (data) => {
   attachList.value.push(
      ...data.map((item) => {
         return {
            title: item.title,
            type: 'table',
            model: item,
            icon: 'biaoge',
            iconClass: 'ywicon-biaoge text-[#c5e0ff]',
         };
      })
      ...data
         .filter((item) => !checkTableAttachExist(item))
         .map((item) => {
            return {
               title: item.title,
               type: 'table',
               model: item,
               icon: 'biaoge',
               iconClass: 'ywicon-biaoge text-[#c5e0ff]',
            };
         })
   );
};
const submitMetricValues = (data) => {
   attachList.value.push(
      ...data
         .filter((item) => !checkMetricAttachExist(item))
         .map((item) => {
            return {
               title: item.title,
               type: 'metric',
               model: item,
               icon: 'zhibiao',
               iconClass: 'ywicon-zhibiao text-[#c5e0ff]',
            };
         })
   );
};
//#region ====================== 业务表格 ======================
const businessTableIsShow = ref(false);
const openBusinessTable = () => {
   businessTableIsShow.value = true;
};
//#endregion
//#region ====================== 附件预览 ======================
const attachPreviewIsShow = ref(false);
const attachPreviewData = ref<Attach>();
const openAttachPreview = (item: Attach) => {
   if (item.type === 'file') return;
   if (item.type === 'table') {
      attachPreviewIsShow.value = true;
      attachPreviewData.value = item;
   } else if (item.type === 'metric') {
      metricPreviewIsShow.value = true;
      metricPreviewData.value = item;
   }
};
//#endregion
//#region ====================== 指标附件 ======================
const metricIsShow = ref(false);
const openMetric = () => {
   metricIsShow.value = true;
};
//#endregion
//#region ====================== 指标附件预览 ======================
const metricPreviewIsShow = ref(false);
const metricPreviewData = ref<Attach>();
//#endregion
const quoteAttach = (item: Attach) => {
   if (item.type === 'table') {
      submitBusinessTable([item.model]);
   } else if (item.type === 'metric') {
      submitMetricValues([item.model]);
   }
};
onActivated(() => {
   emitter.on('quoteAttach', quoteAttach);
});
onDeactivated(() => {
   emitter.off('quoteAttach', quoteAttach);
});
defineExpose({
   addPhrase,
   showSyncTip,