| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- <template>
- <div id="app">
- <Slider @select-nav="selectNav" :index="navId" v-show="!closeOthers"></Slider>
- <div class="main">
- <div :class="{ 'history-wrap': true, 'history-wrap-open': !closeOthers && navId > -1 }">
- <History :list="historyList" @set-new="() => {
- showDialog = false;
- selectId = selectId;
- }
- " :selectId="selectId" @handle-click="selectHistory" />
- </div>
- <div class="wrap">
- <Index :number="swiperNumber" v-if="navId === -1" @select-nav="selectNav" />
- <div :class="{ 'border-wrap': true, 'border-no-wrap': navId === -2 }" v-else>
- <div>
- <header v-if="!showDialog">
- <div>
- <img src="@/assets/other/robot.gif" width="52" />
- <p>
- {{ SYSTEM_NAME }}<span>{{ slider[navId].title }}</span>
- </p>
- <span>{{ slider[navId].dialog }}</span>
- </div>
- </header>
- <section :class="{ 'section-padding': showDialog }">
- <!-- 报告生成 -->
- <DocumentCombine v-if="navId == 0 && !showDialog" />
- <!-- 报表合并 -->
- <Document v-if="navId === 1 && !showDialog" />
- <!-- 知识问答 -->
- <DocumentQuestion v-if="navId === 2 && !showDialog" />
- <!-- 文档智能 -->
- <DocumentAnswer v-if="navId === 3 && !showDialog" :agentId="selectId" />
- <!-- 智能问答 -->
- <Answer v-if="navId === 4 && !showDialog" />
- <!-- 文库详情 -->
- <DocumentDetail v-if="navId === -2" @go-back="goBack" />
- <dialog-wrap v-if="showDialog && initDialog" v-show="!hideDialog" :type="dialogType[navId]"
- :isSetting="false" :readonly="readonly" @setReadonly="setReadonly"
- @goDocument="goDocument" :agentId="selectId" :dialogId="dialogId" :list="dialogList" />
- </section>
- <footer v-if="navId !== -2 && navId !== 0 && navId !== 3">
- <message-input :readonly="readonly" eventName="open-dialog" />
- </footer>
- <footer v-if="navId === 0 && !showDialog" class="upload-footer">
- <section v-for="(item, key) in variables" :key="key">
- <div>
- <p>
- <span>{{ item.variable_name }}</span>
- </p>
- </div>
- <div>
- <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`"
- allow-clear @change="(event) => {
- customChange(event, item.node_id, item.variable_name);
- }
- " v-if="item.value_type === 1" />
- <a-upload v-else :style="{ width: '300px' }" :multiple="false" :limit="1"
- :custom-request="(option) => {
- customRequest(option, item.node_id, item.variable_name);
- }
- " :show-upload-button="{ showOnExceedLimit: true }"
- accept=".pdf,.doc,.docx,.txt,.md,.ppt.pptx" />
- </div>
- </section>
- <a-textarea @keydown.enter="beginCombine" :max-length="maxLength" v-model="textValue"
- :show-word-limit="textValue.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
- placeholder="输入您想了解的内容,Shift+Enter换行" :style="{
- flex: 1,
- borderRadius: '12px',
- marginTop: '20px',
- padding: '0px 30px 0 16px',
- background: 'transparent',
- border: '1px solid #e3e3e3',
- minHeight: '120px',
- paddingBottom: `${textValue.length > maxLength / 2 ? '20px' : ''}`
- }">
- </a-textarea>
- <a-button :style="{ width: '500px' }" type="primary" @click="beginCombine">开始</a-button>
- </footer>
- <footer v-if="navId === 3 && !showDialog" class="upload-footer">
- <section v-for="(item, key) in variables" :key="key">
- <div>
- <p>
- <span>{{ item.variable_name }}</span>
- </p>
- </div>
- <div>
- <a-input :style="{ flex: '1' }" :placeholder="`请输入${item.variable_name}`"
- allow-clear @change="(event) => {
- customChange(event, item.node_id, item.variable_name);
- }
- " v-if="item.value_type === 1" />
- <a-upload v-else :style="{ width: '300px' }" :multiple="false" :limit="1"
- :custom-request="(option) => {
- customRequest(option, item.node_id, item.variable_name);
- }
- " :show-upload-button="{ showOnExceedLimit: true }"
- accept=".pdf,.doc,.docx,.txt,.md,.ppt.pptx" />
- </div>
- </section>
- <!-- <a-textarea @keydown.enter="beginCombine" :max-length="maxLength" v-model="textValue"
- :show-word-limit="textValue.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
- placeholder="输入您想了解的内容,Shift+Enter换行" :style="{
- flex: 1,
- borderRadius: '12px',
- marginTop: '20px',
- padding: '0px 30px 0 16px',
- background: 'transparent',
- border: '1px solid #e3e3e3',
- minHeight: '120px',
- paddingBottom: `${textValue.length > maxLength / 2 ? '20px' : ''}`
- }">
- </a-textarea> -->
- <a-button :style="{ width: '500px' }" type="primary" @click="beginCombine">开始</a-button>
- </footer>
- <footer v-if="navId === 3 && showDialog" class="upload-footer">
- <a-textarea @keydown.enter="beginCombine" :max-length="maxLength" v-model="textValue"
- :show-word-limit="textValue.length > maxLength / 2" :auto-size="{ maxRows: 6 }"
- placeholder="输入您想了解的内容,Shift+Enter换行" :style="{
- flex: 1,
- borderRadius: '12px',
- marginTop: '20px',
- padding: '0px 30px 0 16px',
- background: 'transparent',
- border: '1px solid #e3e3e3',
- minHeight: '120px',
- paddingBottom: `${textValue.length > maxLength / 2 ? '20px' : ''}`
- }">
- </a-textarea>
- <a-button :style="{ width: '500px' }" type="primary" @click="continueCombine">开始</a-button>
- </footer>
- <a-tooltip :content="closeOthers ? '收起' : '展开'">
- <div @click="openAll" v-if="navId !== -2">
- <img src="@/assets/other/open.svg" width="20" v-if="closeOthers" />
- <img src="@/assets/other/close.svg" width="20" v-else />
- </div>
- </a-tooltip>
- </div>
- </div>
- </div>
- <!-- <right v-if="navId === 0 || navId === 2" /> -->
- </div>
- </div>
- </template>
- <script>
- import Right from "../components/Right.vue";
- import DialogWrap from "../components/DialogWrap.vue";
- import Slider from "../components/Slider.vue";
- import History from "../components/History.vue";
- import MessageInput from "../components/MessageInput.vue";
- import DocumentDetail from "./DocumentDetail.vue";
- import DocumentCombine from "./DocumentCombine.vue";
- import Index from "./Index.vue";
- import Answer from "./Answer.vue";
- import Document from "./Document.vue";
- import PicArticle from "./PicArticle.vue";
- import DocumentAnswer from "./DocumentAnswer.vue";
- import DocumentQuestion from "./DocumentQuestion.vue";
- import Analysis from "./Analysis.vue";
- import { defineComponent, ref, onMounted, inject, onBeforeUnmount } from "vue";
- export default defineComponent({
- components: {
- Right,
- Slider,
- History,
- Index,
- Answer,
- MessageInput,
- DialogWrap,
- Document,
- PicArticle,
- DocumentAnswer,
- DocumentQuestion,
- Analysis,
- DocumentDetail,
- DocumentCombine
- },
- setup() {
- // nav对应的问答类型,4文库问答,对应的是knowledge类型
- // NOTE: 先把4文库问答的类型改成report类型,后续再改回来
- const dialogType = ["report", "excel", "knowledgeQuiz", "report", "normal", "normal", "normal", "normal"];
- const { config, helper, ajax } = inject("$global");
- const SYSTEM_NAME = config.defaultTitle
- const closeOthers = ref(false);
- const swiperNumber = ref(5);
- const navId = ref(-1);
- const readonly = ref(false);
- const showDialog = ref(false);
- const dialogList = ref([]);
- const selectId = ref("");
- const initDialog = ref(false);
- const hideDialog = ref(false);
- const agentIds = ref([]);
- const dialogId = ref("");
- const historyList = ref([]);
- const variables = ref([]);
- const textValue = ref("");
- const maxLength = ref(6000);
- let reportData = {};
- let agents = {}
- const openAll = () => {
- closeOthers.value = !closeOthers.value;
- };
- const selectNav = async (node) => {
- navId.value = node.id;
- textValue.value = [];
- if (node.index === -1) {
- swiperNumber.value = 5;
- } else {
- swiperNumber.value = 4;
- }
- helper.$bus.emit("stop-writing");
- showDialog.value = false;
- selectId.value = (agents.find(agent => agent.name === node.title) || {}).id || null;
- const data = await ajax.message.getDialogs(selectId.value);
- if (navId.value === 0 || navId.value === 3) {
- const result = await ajax.agent.getVariables(selectId.value);
- variables.value = result;
- reportData = {};
- }
- historyList.value = data.map((value) => {
- return {
- content: value.name,
- id: value.id,
- time: new Date(value.updated_time).toLocaleString()
- };
- });
- };
- const setReadonly = (status) => {
- readonly.value = status;
- };
- const goDocument = () => {
- navId.value = -2;
- hideDialog.value = true;
- };
- const goBack = () => {
- navId.value = 0;
- hideDialog.value = false;
- };
- const selectHistory = async (id) => {
- showDialog.value = true;
- selectId.value = id;
- helper.$bus.emit("set-loading", true);
- helper.$bus.emit("stop-writing");
- initDialog.value = false;
- // TODO 历史记录
- // const data = await ajax.message.getHistoryLogs(selectId.value, id);
- const data = await ajax.message.getHistoryLogs('42e4fcdc9bea11efac300242ac160006', id);
- if (data.length > 0) {
- console.log('data', data)
- dialogList.value = data
- }
- initDialog.value = true;
- helper.$bus.emit("set-loading", false);
- };
- const beginCombine = async () => {
- let report_name = "";
- let inputData = [];
- for (let key in reportData) {
- if (typeof reportData[key].value === "string") {
- report_name += `${reportData[key].key}:${reportData[key].value}\n`;
- inputData.push({
- id: key,
- name: reportData[key].key,
- file_path: "",
- value: reportData[key].value
- });
- } else {
- report_name += `${reportData[key].key}:${reportData[key].value.name}\n`;
- inputData.push({
- id: key,
- name: reportData[key].key,
- file_path: reportData[key].value.url,
- value: ""
- });
- }
- }
- const data = await ajax.message.createDialog(selectId.value);
- dialogId.value = data.chat_id;
- dialogList.value = [];
- showDialog.value = true;
- initDialog.value = true;
- const sendData = {
- chatHistory: [],
- message: textValue.value,
- name: "报告生成",
- description: "报告生成",
- inputs: {
- report_name,
- id: "Report-PRcYL",
- data: inputData
- }
- };
- setTimeout(() => {
- helper.$bus.emit("send-message", sendData);
- }, 500);
- };
- const continueCombine = async () => {
- const sendData = {
- chatHistory: [],
- name: "报告生成",
- description: "报告生成",
- inputs: {
- report_name: textValue.value,
- id: "Report-PRcYL",
- query: textValue.value,
- }
- };
- setTimeout(() => {
- helper.$bus.emit("send-message", sendData);
- textValue.value = "";
- }, 500);
- };
- const customChange = (event, key, value) => {
- reportData[key] = {
- key: value,
- value: event
- };
- };
- const customRequest = async (option, key, value) => {
- const { onSuccess, fileItem } = option;
- const { file, uid, name } = fileItem;
- const fileList = [];
- fileList.push({
- id: uid,
- file
- });
- onSuccess();
- const formData = new FormData();
- fileList.forEach((item) => {
- formData.append("file", item.file);
- });
- const data = await ajax.file.uploadFiles(selectId.value, formData);
- reportData[key] = {
- key: value,
- value: {
- name,
- url: data.file_path
- }
- };
- };
- onMounted(async () => {
- agents = await ajax.agent.getAgents();
- agentIds.value = agents.map((data) => data.id);
- helper.$bus.on("open-dialog", async (value) => {
- const data = await ajax.message.createDialog(selectId.value);
- dialogId.value = data.chat_id;
- dialogList.value = [];
- showDialog.value = true;
- initDialog.value = true;
- setTimeout(() => {
- helper.$bus.emit("send-message", value);
- }, 200);
- });
- });
- onBeforeUnmount(() => {
- helper.webSocket?.close();
- helper.$bus.off("open-dialog");
- });
- return {
- SYSTEM_NAME,
- customChange,
- customRequest,
- historyList,
- beginCombine,
- continueCombine,
- selectId,
- dialogId,
- navId,
- variables,
- selectNav,
- swiperNumber,
- slider: config.slider,
- readonly,
- setReadonly,
- showDialog,
- selectHistory,
- closeOthers,
- openAll,
- dialogType,
- dialogList,
- initDialog,
- goDocument,
- goBack,
- hideDialog,
- agentIds,
- textValue,
- maxLength
- };
- }
- });
- </script>
- <style lang="scss" scoped>
- .main {
- .upload-footer {
- margin-bottom: 50px;
- padding: 20px;
- width: 540px;
- border: 1px solid #eee;
- >section {
- >div {
- display: flex;
- align-items: center;
- justify-content: space-between;
- width: 500px;
- >p {
- width: 150px;
- margin-right: 10px;
- }
- }
- p {
- span {
- position: relative;
- &:after {
- content: "*";
- display: block;
- color: red;
- position: absolute;
- right: -10px;
- top: -5px;
- }
- }
- }
- >p,
- >div {
- margin: 10px 0;
- }
- }
- }
- flex: 1;
- position: relative;
- display: flex;
- .history-wrap {
- width: 0px;
- opacity: 0;
- overflow: hidden;
- transition-duration: 0.3s;
- transition-property: width;
- &-open {
- opacity: 1;
- width: 260px;
- }
- }
- .wrap {
- flex: 1;
- }
- .border-wrap {
- position: relative;
- padding: 30px 16px 30px 40px;
- flex: 1;
- height: 100%;
- &.border-no-wrap {
- padding: 0;
- >div {
- padding: 0;
- >section.section-padding {
- padding: 0;
- }
- }
- }
- >div {
- width: 100%;
- height: 100%;
- background: #fff;
- box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.03);
- border-radius: 14px;
- display: flex;
- flex-direction: column;
- padding: 0 32px;
- position: relative;
- >div {
- position: absolute;
- bottom: -10px;
- left: -10px;
- z-index: 10;
- width: 38px;
- height: 38px;
- border-radius: 20px;
- background: #fff;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- }
- >header {
- >div {
- display: inline-block;
- margin-top: 20px;
- >img {
- transform: translateX(-12px);
- }
- >p {
- font-size: 36px;
- font-weight: bold;
- color: #000;
- >span {
- font-weight: bold;
- background: linear-gradient(180deg, #41d98c, #31c4c9);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- }
- }
- >span {
- display: block;
- color: #000;
- font-size: 15px;
- margin: 5px 0 32px;
- }
- }
- }
- >section {
- flex: 1;
- overflow: hidden;
- &.section-padding {
- padding-bottom: 50px;
- }
- }
- >footer {}
- }
- }
- }
- </style>
|