yangyin
2024-11-05 0f62897b6c82b90f3d0cbac88b75be99e30b70d1
src/components/chat/components/playBar/phrase/CommonPhrases.vue
@@ -1,22 +1,32 @@
<template>
   <div class="container" :class="isHome ? 'top-[100%] mt-[8px]' : 'bottom-[100%] mb-[8px]'">
      <div class="container_header">
         <div class="title">常用语</div>
         <div class="question">常用语</div>
         <span class="ywifont ywicon-guanbi text-[15px] cursor-pointer text-[#767a97]" @click="closeCommonPhrases"></span>
      </div>
      <div class="container_content">
         <div class="set_phrases" :style="{ height: commonPhrases.length * 40 + 'px' }">
         <div class="set_phrases" :style="{ height: commonPhrases.length * 46 + 'px' }">
            <div class="w-full h-full absolute top-0">
               <div class="py-0 mt-0 box-border h-full">
                  <div style="overflow-anchor: none" v-for="(item, index) in commonPhrases" :key="index">
                     <div class="phase_item">
                     <div class="phase_item" @click="titleClick(item)">
                        <div class="flex flex-col">
                           <div class="title">
                              {{ item.title }}
                           <div class="question">
                              {{ item.question }}
                           </div>
                           <div class="content">
                           <!-- <div class="content">
                              {{ item.content }}
                           </div>
                           </div> -->
                        </div>
                        <div class="py-2">
                           <span
                              class="ywifont ywicon-bianji cursor-pointer text-[#767a97] pt-[4px] pr-[6px] pb-[2px] pl-0 rounded-lg !text-[13px]"
                              @click.stop="editCommonPhrases(item)"
                           ></span>
                           <span
                              class="ywifont ywicon-shanchu3 cursor-pointer text-[red] pt-[4px] pr-[6px] pb-[2px] pl-0 rounded-lg"
                              @click.stop="deleteCommonPhrases(item)"
                           ></span>
                        </div>
                     </div>
                  </div>
@@ -24,39 +34,160 @@
            </div>
         </div>
      </div>
      <div class="container_add">
      <div class="container_add" @click="addCommonPhrases">
         <span class="ywifont ywicon-jia text-[15px] cursor-pointer text-[#767a97]"></span>
         <div class="grow">添加常用语</div>
      </div>
      <el-dialog
         v-model="state.useCommonPhrasesDialog"
         :title="`${showCommonPhrases}常用语`"
         width="500"
         :before-close="handleClose"
         style="z-index: 999"
      >
         <el-input v-model="state.inputCommonPhrases" :rows="10" type="textarea" placeholder="自定义常用语"></el-input>
         <template #footer>
            <div class="dialog-footer">
               <el-button @click="handleClose">取消</el-button>
               <el-button type="primary" @click="submitCommonPhrases" :disabled="is_input_title">
                  {{ showCommonPhrases }}
               </el-button>
            </div>
         </template>
      </el-dialog>
   </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const commonPhrases = ref([
   {
      id: 1,
      title: '你好,请问有什么可以帮助您?',
      content: '您好,我想咨询一下关于您的订单。',
   },
   {
      id: 2,
      title: '测试1?',
      content: '我想咨询一下关于您的订单。',
   },
   {
      id: 3,
      title: '测试2?',
      content: '我想咨询一下关于您的订单。',
   },
]);
import { ElMessageBox, ElMessage } from 'element-plus';
import { computed, onMounted, reactive, ref } from 'vue';
import { addUserSample, deleteUserSample, listUserSample, updateUserSample } from '/@/api/ai/chat';
import { activeGroupType, activeRoomId, activeSampleId, setRoomConfig } from '/@/stores/chatRoom';
const state = reactive({
   useCommonPhrasesDialog: false,
   show_sample_title: false,
   inputCommonPhrases: '',
   sample_title: null,
   sample_id: null,
});
const commonPhrases = ref([]);
const props = defineProps(['isHome']);
const closeCommonPhrases = () => {};
const isShow = defineModel('isShow', {
   type: Boolean,
});
//#region ====================== 是否显示常用语 ======================
const showCommonPhrases = computed(() => {
   return state.show_sample_title == true ? (state.sample_title = '编辑') : (state.sample_title = '添加');
});
const is_input_title = computed(() => {
   return state.inputCommonPhrases == '' ? true : false;
});
const closeCommonPhrases = () => {
   isShow.value = false;
};
//#endregion
//#region ====================== 获取常用语 ======================
const getCommonPhrases = async () => {
   const res = await listUserSample({
      group_type: activeGroupType.value,
   });
   if (res.json_ok) {
      commonPhrases.value = res.values;
   }
};
//#endregion
//#region ====================== 添加常用语 ======================
//关闭常用语弹窗
const handleClose = () => {
   state.useCommonPhrasesDialog = false;
};
//打开常用语弹窗
const addCommonPhrases = () => {
   state.useCommonPhrasesDialog = true;
   state.show_sample_title = false;
   state.inputCommonPhrases = '';
};
const editCommonPhrases = (item) => {
   state.useCommonPhrasesDialog = true;
   state.show_sample_title = true;
   state.inputCommonPhrases = item.question;
   state.sample_id = item.id;
};
const deleteCommonPhrases = (row) => {
   ElMessageBox.confirm(`你确定要删除常用语吗?`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      dangerouslyUseHTMLString: true,
      type: 'warning',
   }).then(async () => {
      const res = await deleteUserSample({
         sample_id: row.id,
      });
      const foundIndex = commonPhrases.value.findIndex((item) => item === row);
      foundIndex > -1 && commonPhrases.value.splice(foundIndex, 1);
   });
};
//提交常用语
const submitCommonPhrases = async () => {
   if (state.show_sample_title) {
      const res = await updateUserSample({
         sample_id: state.sample_id,
         question: state.inputCommonPhrases,
      });
      if (res.json_ok) {
         const foundIndex = commonPhrases.value.findIndex((item) => item.id === state.sample_id);
         foundIndex > -1 && (commonPhrases.value[foundIndex].question = state.inputCommonPhrases);
         handleClose();
      }
   } else {
      addCommonPhrasesData();
   }
};
//添加一条数据源
const addCommonPhrasesData = async () => {
   const res = await addUserSample({
      question: state.inputCommonPhrases,
      group_type: activeGroupType.value,
   });
   if (res.json_ok) {
      commonPhrases.value.push({
         id: res.sample_id,
         question: state.inputCommonPhrases,
      });
      handleClose();
   }
};
//#endregion
//#region ====================== 常用语到对话框 ======================
const emits = defineEmits<{
   (event: 'updateCommonChatInput', val): void;
}>();
const titleClick = (item) => {
   emits('updateCommonChatInput', item.question);
   setRoomConfig(activeRoomId.value, 'isAnswerByLLM', false);
   activeSampleId.value = item.id;
};
const commonChatByUser = (data) => {
   const question = data.question;
   const isCommon = commonPhrases.value.findIndex((item) => item.question === question) > -1;
   if (isCommon) {
      return ElMessage.warning('该问题已存在常用语中');
   } else {
      state.inputCommonPhrases = question;
      addCommonPhrasesData();
   }
};
//#endregion
onMounted(() => {
   getCommonPhrases();
});
defineExpose({ commonChatByUser, getCommonPhrases });
</script>
<style scoped lang="scss">
.container {
   position: absolute;
   width: 100%;
   max-height: 45vh;
   max-height: 40vh;
   padding: 0 8px 8px;
   left: 0px;
   border-radius: 12px;
@@ -65,7 +196,7 @@
   box-shadow: 0px 8px 25px 0px #0000000d;
   display: flex;
   flex-direction: column;
   z-index: 100;
   z-index: 990;
   &_header {
      width: 100%;
      display: flex;
@@ -74,7 +205,7 @@
      align-items: center;
      padding: 10px 6px;
      color: #060607;
      .title {
      .question {
         font-size: 14px;
         color: #060607;
         font-weight: 600;
@@ -86,8 +217,9 @@
   }
   &_content {
      width: 100%;
      max-height: 40vh;
      max-height: 35vh;
      height: fit-content;
      overflow-y: auto;
      .set_phrases {
         outline: none;
         overflow-y: auto;
@@ -104,16 +236,22 @@
            background: #fff;
            border-radius: 8px;
            width: 100%;
            .title {
            &:hover {
               background: #e5e7ed;
            }
            .question {
               font-size: 14px;
               color: #060607;
               font-family: PingFang HK;
               font-weight: 600;
               color: #8d8e99;
               font-weight: 400;
               font-style: normal;
               white-space: nowrap;
               text-overflow: ellipsis;
               overflow: hidden;
               &:hover {
                  color: #060607;
               }
            }
            .content {
               font-size: 12px;
               color: #5e6772;
@@ -133,6 +271,9 @@
      padding: 6px 8px;
      background: #fff;
      border-radius: 8px;
      &:hover {
         background: #e5e7ed;
      }
   }
}
</style>