Compare commits
No commits in common. "540e5f01795b0c8bf22c55461573d5304baef3ce" and "c338f341278569bf3cf41065cb38fa9bec8a84a9" have entirely different histories.
540e5f0179
...
c338f34127
|
@ -97,34 +97,4 @@ const getProgress = async (id) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBackGroundV2 = async () => {
|
export { createOutline, getBackGround, createPPT, getProgress, createByOutline };
|
||||||
try {
|
|
||||||
const response = await req("/api/aipptV2/themeListV2", "GET");
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const createPPTV2 = async (data) => {
|
|
||||||
try {
|
|
||||||
const response = await req("/api/aipptV2/createV2", "POST", data);
|
|
||||||
console.log("createOutline response:", response);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const getProgressV2 = async (id) => {
|
|
||||||
try {
|
|
||||||
const response = await req(`/api/aipptV2/progressV2?sid=${id}`, "GET");
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export { createOutline, getBackGround, createPPT, getProgress, getBackGroundV2, createPPTV2, getProgressV2, createByOutline };
|
|
||||||
|
|
|
@ -1,378 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="ai-container">
|
|
||||||
<el-steps style="max-width:100% " :active="activeStep" align-center>
|
|
||||||
<el-step title="生成大纲" />
|
|
||||||
<el-step title="选择模板" />
|
|
||||||
<el-step title="制作PPT" />
|
|
||||||
</el-steps>
|
|
||||||
<div class="card-box">
|
|
||||||
<el-card class="card2" v-if="activeStep === 0">
|
|
||||||
<div class="paragraphs">
|
|
||||||
{{ outputText }}
|
|
||||||
</div>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="addMessage">从新生成</el-button>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 1">下一步</el-button>
|
|
||||||
</el-card>
|
|
||||||
<el-card v-if="activeStep === 1">
|
|
||||||
<div style="padding-bottom: 10px">ppt模板选择</div>
|
|
||||||
<div class="themes">
|
|
||||||
<div v-for="item in backGroundList" :key="item.key" :style="{
|
|
||||||
padding: '20px',
|
|
||||||
paddingRight: '30px',
|
|
||||||
paddingLeft: '30px',
|
|
||||||
margin: '10px',
|
|
||||||
backgroundColor: getBackgroundColor(item.key),
|
|
||||||
borderRadius: '10px',
|
|
||||||
borderBlock: '10px solid #e6e6e6'
|
|
||||||
}" @click="chooseBackground(item.key)" @mouseenter="changeCursor('pointer')" @mouseleave="changeCursor('default')">
|
|
||||||
{{ item.name }}
|
|
||||||
<br />
|
|
||||||
<img style="width: 150px; height: auto" :src="item.thumbnail" alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-row class="el-row">
|
|
||||||
<el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-1">
|
|
||||||
<div>自动配图</div>
|
|
||||||
<el-switch v-model="outlineData.is_figure" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-2">
|
|
||||||
<div>PPT作者名:</div>
|
|
||||||
<el-input v-model="outlineData.author" style="width: 50%" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<div>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 0">上一步</el-button>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="outlineCreatePPT()">生成PPT</el-button>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<el-card v-if="activeStep === 2">
|
|
||||||
<el-progress :percentage="percentage" type="circle" ></el-progress>
|
|
||||||
</el-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
import { creatAIPPT } from '@/utils/talkFile'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import {
|
|
||||||
getBackGround,
|
|
||||||
createPPT,
|
|
||||||
getProgress,
|
|
||||||
} from "@/utils/ppt-request.js";
|
|
||||||
import CryptoJS from "crypto-js"
|
|
||||||
|
|
||||||
import { getSignature } from "@/utils/index.js";
|
|
||||||
|
|
||||||
let appId = "01ec9aa3";
|
|
||||||
let secret = "M2QxMDAxMjYyYTEzODMwMGRkZTQ4NmUy";
|
|
||||||
let apikey = "39d05b269fa229f431a56c21794a8ea5"
|
|
||||||
let timestamp = Math.floor(Date.now() / 1000);
|
|
||||||
let signature = getSignature(appId, secret, timestamp);
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
|
||||||
|
|
||||||
|
|
||||||
const outputText = ref(""); // 用于展示的大纲数据
|
|
||||||
const stagingData = ref([]); //储存的对话数据,用于多轮对话
|
|
||||||
const stagOutputText = ref(""); // 暂存大纲用于拆分
|
|
||||||
let extractedParts = ref([]) // 初步拆分
|
|
||||||
|
|
||||||
let firstArray = ref([]); //大纲的大纲等级数字部分
|
|
||||||
let secondArray = ref([]); //大纲的文字部分
|
|
||||||
|
|
||||||
|
|
||||||
const backGroundList = ref([]);
|
|
||||||
|
|
||||||
const inputTheme = ref("高中语文《沁园春雪》的授课课件"); // 输入的主题
|
|
||||||
const inputRequire = ref("") // 输入的需求
|
|
||||||
const activeStep = ref(0); // 上方进度条
|
|
||||||
const combined = ref('') // 修改完毕的大纲数据,准备传入ppt生成模型
|
|
||||||
|
|
||||||
const treeData = ref([]);
|
|
||||||
const status = ref("init");
|
|
||||||
|
|
||||||
const percentage = ref(0);
|
|
||||||
|
|
||||||
const getBackground = () => {
|
|
||||||
treeData.value = [];
|
|
||||||
getBackGround().then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
backGroundList.value = res;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBackgroundColor = (key) => {
|
|
||||||
return outlineData.value.theme === key ? '#83e2b6' : '#f5f5f5';
|
|
||||||
};
|
|
||||||
|
|
||||||
const outlineData = ref({
|
|
||||||
query: '', // 用户要求(最多8000字)
|
|
||||||
theme: 'auto', // ppt生成主题
|
|
||||||
author: 'AIX平台',
|
|
||||||
is_card_note: false, // 是否自动生成ppt演讲备注
|
|
||||||
is_cover_img: false, // 是否自动生成封面
|
|
||||||
is_figure: false, // 是否自动配图
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const emit = defineEmits(['addSuccess'])
|
|
||||||
const props = defineProps({
|
|
||||||
dataList: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 将输入数据或返回数据存入记忆中
|
|
||||||
function updateStagingData(role, newData) {
|
|
||||||
stagingData.value.push({ role: role, content: newData });
|
|
||||||
}
|
|
||||||
//大纲直接生成ppt
|
|
||||||
const outlineCreatePPT = () => {
|
|
||||||
const newOutlineData = { ...outlineData.value, };
|
|
||||||
newOutlineData.query = outputText.value;
|
|
||||||
|
|
||||||
createPPT(newOutlineData).then((res) => {
|
|
||||||
console.log(res, "正在生成中");
|
|
||||||
activeStep.value = 2
|
|
||||||
|
|
||||||
const checkProgress = () => {
|
|
||||||
getProgress(res.sid).then((response) => {
|
|
||||||
percentage.value = response.process;
|
|
||||||
if (response && response.pptUrl && response.pptUrl.length > 4) {
|
|
||||||
// window.location.href = response.data.pptUrl;
|
|
||||||
//发消息到主进程,携带名称和URL,将URL下载下来后复制到文件列表并上传到服务
|
|
||||||
// let url = "https://bjcdn.openstorage.cn/xinghuo-privatedata/%2Ftmp/apiTempFiledf28bf990a4c40ffb7477ed4b65392c27232357022409613439/%E3%80%8A%E9%9D%99%E5%A5%B3%E3%80%8B%E6%B7%B1%E5%BA%A6%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%A0%94%E7%A9%B6.pptx"
|
|
||||||
emit('addSuccess',res)
|
|
||||||
ElMessage.success("生成成功");
|
|
||||||
} else {
|
|
||||||
const sleepTime = 2000;
|
|
||||||
let remainingTime = sleepTime;
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
remainingTime -= 100;
|
|
||||||
if (remainingTime <= 0) {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
checkProgress();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
checkProgress();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
//初次对话
|
|
||||||
const addMessage = () => {
|
|
||||||
const themeValue = inputTheme.value;
|
|
||||||
const requireValue = inputRequire.value;
|
|
||||||
firstArray.value = []
|
|
||||||
secondArray.value = []
|
|
||||||
extractedParts.value = []
|
|
||||||
stagOutputText.value = ''
|
|
||||||
const combinedString = `请帮我生成一个ppt大纲,主题为:${themeValue}。具体内容要求为:${requireValue}。注意,用三个等级大纲展示,如1. 1.1 1.1.2 2. 2.1这种类型,且按照这种顺序,不要有完全相同数字等级的大纲,不要有目录`
|
|
||||||
updateStagingData("user", combinedString);
|
|
||||||
connectWebSocket(stagingData.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
let ttsWS
|
|
||||||
function connectWebSocket(data) {
|
|
||||||
outputText.value = ""; //清楚展示部分内容
|
|
||||||
status.value = "ttsing";
|
|
||||||
return getWebsocketUrl().then((url) => {
|
|
||||||
ttsWS = new WebSocket(url);
|
|
||||||
ttsWS.onopen = () => {
|
|
||||||
webSocketSend(ttsWS, data);
|
|
||||||
};
|
|
||||||
ttsWS.onmessage = (e) => {
|
|
||||||
result1(e.data);
|
|
||||||
};
|
|
||||||
ttsWS.onerror = (e) => {
|
|
||||||
status.value = "error";
|
|
||||||
console.log("WebSocket error:", e);
|
|
||||||
};
|
|
||||||
ttsWS.onclose = () => {
|
|
||||||
status.value = "init";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWebsocketUrl() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var apiKey = apikey;
|
|
||||||
var apiSecret = secret;
|
|
||||||
var url = "wss://spark-api.xf-yun.com/v4.0/chat";
|
|
||||||
|
|
||||||
var host = "spark-api.xf-yun.com";
|
|
||||||
var date = new Date().toGMTString();
|
|
||||||
var algorithm = "hmac-sha256";
|
|
||||||
var headers = "host date request-line";
|
|
||||||
var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v4.0/chat HTTP/1.1`;
|
|
||||||
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
|
|
||||||
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
|
|
||||||
|
|
||||||
var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
|
|
||||||
var authorization = CryptoJS.enc.Base64.stringify(
|
|
||||||
CryptoJS.enc.Utf8.parse(authorizationOrigin)
|
|
||||||
);
|
|
||||||
|
|
||||||
url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
|
|
||||||
console.log(url);
|
|
||||||
resolve(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function webSocketSend(ws, data) {
|
|
||||||
const params = {
|
|
||||||
header: {
|
|
||||||
app_id: appId,
|
|
||||||
},
|
|
||||||
parameter: {
|
|
||||||
chat: {
|
|
||||||
domain: "4.0Ultra",
|
|
||||||
temperature: 0.5,
|
|
||||||
max_tokens: 1024,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
message: {
|
|
||||||
text: data,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ws.send(JSON.stringify(params));
|
|
||||||
}
|
|
||||||
|
|
||||||
function result1(resultData) {
|
|
||||||
let jsonData = JSON.parse(resultData);
|
|
||||||
outputText.value += jsonData.payload.choices.text[0].content;
|
|
||||||
const div = document.querySelector('.paragraphs');
|
|
||||||
if (div) {
|
|
||||||
div.scrollTop = div.scrollHeight;
|
|
||||||
}
|
|
||||||
if (jsonData.payload && jsonData.payload.usage) {
|
|
||||||
startExtraction() // 返回完毕后开始拆分大纲
|
|
||||||
console.log(firstArray.value, secondArray.value)
|
|
||||||
activeStep.value = 2
|
|
||||||
updateStagingData("assistant", outputText.value) //返回数据存入记忆池
|
|
||||||
}
|
|
||||||
if (jsonData.header.code !== 0) {
|
|
||||||
alert(`提问失败: ${jsonData.header.code}:${jsonData.header.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const chooseBackground = (data) => {
|
|
||||||
outlineData.value.theme = data
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeCursor = (cursorStyle) => {
|
|
||||||
document.documentElement.style.cursor = cursorStyle;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// let url = "https://bjcdn.openstorage.cn/xinghuo-privatedata/%2Ftmp/apiTempFileba724e0344f74e1480535eedf3ebec661601807661085006275/%E9%87%91%E9%A9%AC%E5%A5%96%E5%B0%B4%E5%B0%AC%E4%BA%8B%E4%BB%B6%E5%88%86%E6%9E%90%E4%B8%8E%E5%BA%94%E5%AF%B9%E7%AD%96%E7%95%A5.pptx"
|
|
||||||
// creatAIPPT(props.currentNode.itemtitle + '.pptx',url, props.uploadData).then((res) => {
|
|
||||||
// emit('addSuccess',res)
|
|
||||||
// })
|
|
||||||
// connectWebSocket("");
|
|
||||||
props.dataList.filter(item => {
|
|
||||||
inputRequire.value += item.answer
|
|
||||||
})
|
|
||||||
getBackground();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.ai-container {
|
|
||||||
width: 100%;
|
|
||||||
background-color: #f5f7f6;
|
|
||||||
padding: 20px
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-box {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card1 {
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paragraphs {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
text-align: left;
|
|
||||||
max-height: 60vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
border: 1px solid #409EFF;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.themes {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
height: 250px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
border: 1px solid #409EFF;
|
|
||||||
padding: 10px;
|
|
||||||
outline-style: none;
|
|
||||||
/* margin: 5px */
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row>.el-col {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row>.el-col>div,
|
|
||||||
.outline-row>.el-col>div>.el-input {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-with-dash {
|
|
||||||
margin-left: 100px
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-with-dash::after {
|
|
||||||
content: "";
|
|
||||||
border-bottom: 1px dashed #000;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content-1 {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #c2dbf3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content-2 {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-row {
|
|
||||||
padding: 20px
|
|
||||||
}
|
|
||||||
:deep(.el-card__body){
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,391 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="ai-container">
|
|
||||||
<el-steps style="max-width:100% " :active="activeStep" align-center>
|
|
||||||
<el-step title="生成大纲" />
|
|
||||||
<el-step title="选择模板" />
|
|
||||||
<el-step title="制作PPT" />
|
|
||||||
</el-steps>
|
|
||||||
<div class="card-box">
|
|
||||||
<el-card class="card2" v-if="activeStep === 0">
|
|
||||||
<div class="paragraphs">
|
|
||||||
{{ outputText }}
|
|
||||||
</div>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="addMessage">从新生成</el-button>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 1">下一步</el-button>
|
|
||||||
</el-card>
|
|
||||||
<el-card v-if="activeStep === 1">
|
|
||||||
<div style="padding-bottom: 10px">ppt模板选择</div>
|
|
||||||
<div class="themes">
|
|
||||||
<div v-for="item in backGroundList" :key="item.templateIndexId" :style="{
|
|
||||||
padding: '5px',
|
|
||||||
paddingRight: '5px',
|
|
||||||
paddingLeft: '5px',
|
|
||||||
margin: '5px',
|
|
||||||
backgroundColor: getBackgroundColor(item.templateIndexId),
|
|
||||||
borderRadius: '10px',
|
|
||||||
borderBlock: '10px solid #e6e6e6'
|
|
||||||
}" @click="chooseBackground(item.templateIndexId)" @mouseenter="changeCursor('pointer')" @mouseleave="changeCursor('default')">
|
|
||||||
{{ item.name }}
|
|
||||||
<img style="width: 150px; height: auto" :src="getBackGroundImg(item.detailImage)" alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-row class="el-row">
|
|
||||||
<!-- <el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-1">
|
|
||||||
<div>演讲备注</div>
|
|
||||||
<el-switch v-model="outlineData.is_card_note" />
|
|
||||||
</div>
|
|
||||||
</el-col>-->
|
|
||||||
<!-- <el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-2">
|
|
||||||
<div>生成封面</div>
|
|
||||||
<el-switch v-model="outlineData.is_cover_img" />
|
|
||||||
</div>
|
|
||||||
</el-col>-->
|
|
||||||
<el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-1">
|
|
||||||
<div>自动配图</div>
|
|
||||||
<el-switch v-model="outlineData.isFigure" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-2">
|
|
||||||
<div>PPT作者名:</div>
|
|
||||||
<el-input v-model="outlineData.author" style="width: 50%" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<div>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 0">上一步</el-button>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="outlineCreatePPT()">生成PPT</el-button>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<el-card v-if="activeStep === 2">
|
|
||||||
<el-progress :percentage="30" type="circle" v-if="percentage === 30"></el-progress>
|
|
||||||
</el-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import {
|
|
||||||
getBackGroundV2,
|
|
||||||
createPPTV2,
|
|
||||||
getProgressV2,
|
|
||||||
} from "@/utils/ppt-request.js";
|
|
||||||
import CryptoJS from "crypto-js"
|
|
||||||
|
|
||||||
import { getSignature } from "@/utils/index.js";
|
|
||||||
|
|
||||||
let appId = "01ec9aa3";
|
|
||||||
let secret = "M2QxMDAxMjYyYTEzODMwMGRkZTQ4NmUy";
|
|
||||||
let apikey = "39d05b269fa229f431a56c21794a8ea5"
|
|
||||||
let timestamp = Math.floor(Date.now() / 1000);
|
|
||||||
let signature = getSignature(appId, secret, timestamp);
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
|
||||||
|
|
||||||
|
|
||||||
const outputText = ref(""); // 用于展示的大纲数据
|
|
||||||
const stagingData = ref([]); //储存的对话数据,用于多轮对话
|
|
||||||
const stagOutputText = ref(""); // 暂存大纲用于拆分
|
|
||||||
let extractedParts = ref([]) // 初步拆分
|
|
||||||
|
|
||||||
let firstArray = ref([]); //大纲的大纲等级数字部分
|
|
||||||
let secondArray = ref([]); //大纲的文字部分
|
|
||||||
|
|
||||||
|
|
||||||
const backGroundList = ref([]);
|
|
||||||
|
|
||||||
const inputTheme = ref("高中语文《沁园春雪》的授课课件"); // 输入的主题
|
|
||||||
const inputRequire = ref("") // 输入的需求
|
|
||||||
const activeStep = ref(0); // 上方进度条
|
|
||||||
const combined = ref('') // 修改完毕的大纲数据,准备传入ppt生成模型
|
|
||||||
|
|
||||||
const treeData = ref([]);
|
|
||||||
const status = ref("init");
|
|
||||||
|
|
||||||
const percentage = ref(0);
|
|
||||||
|
|
||||||
const getBackgrounds = () => {
|
|
||||||
treeData.value = [];
|
|
||||||
getBackGroundV2().then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
backGroundList.value = res.records;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBackGroundImg = (imgUrlStr) => {
|
|
||||||
return JSON.parse(imgUrlStr).titleCoverImage
|
|
||||||
};
|
|
||||||
|
|
||||||
const outlineData = ref({
|
|
||||||
query: '', // 用户要求(最多8000字)
|
|
||||||
// templateId: 'auto', // ppt生成主题
|
|
||||||
author: 'AIX平台',
|
|
||||||
isFigure: false, // 是否自动配图
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const emit = defineEmits(['addSuccess'])
|
|
||||||
const props = defineProps({
|
|
||||||
dataList: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 将输入数据或返回数据存入记忆中
|
|
||||||
function updateStagingData(role, newData) {
|
|
||||||
stagingData.value.push({ role: role, content: newData });
|
|
||||||
}
|
|
||||||
//大纲直接生成ppt
|
|
||||||
const outlineCreatePPT = () => {
|
|
||||||
const newOutlineData = { ...outlineData.value, };
|
|
||||||
newOutlineData.query = outputText.value;
|
|
||||||
|
|
||||||
createPPTV2(newOutlineData).then((res) => {
|
|
||||||
console.log(res, "正在生成中");
|
|
||||||
activeStep.value = 2
|
|
||||||
|
|
||||||
const checkProgress = () => {
|
|
||||||
getProgressV2(res.sid).then((response) => {
|
|
||||||
percentage.value = response.process;
|
|
||||||
if (response && response.pptUrl && response.pptUrl.length > 4) {
|
|
||||||
console.log('PPT',response)
|
|
||||||
// window.location.href = response.data.pptUrl;
|
|
||||||
//发消息到主进程,携带名称和URL,将URL下载下来后复制到文件列表并上传到服务
|
|
||||||
// let url = "https://bjcdn.openstorage.cn/xinghuo-privatedata/%2Ftmp/apiTempFiledf28bf990a4c40ffb7477ed4b65392c27232357022409613439/%E3%80%8A%E9%9D%99%E5%A5%B3%E3%80%8B%E6%B7%B1%E5%BA%A6%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%A0%94%E7%A9%B6.pptx"
|
|
||||||
emit('addSuccess',res)
|
|
||||||
ElMessage.success("生成成功");
|
|
||||||
} else {
|
|
||||||
const sleepTime = 2000;
|
|
||||||
let remainingTime = sleepTime;
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
remainingTime -= 100;
|
|
||||||
if (remainingTime <= 0) {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
checkProgress();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
checkProgress();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
//初次对话
|
|
||||||
const addMessage = () => {
|
|
||||||
const themeValue = inputTheme.value;
|
|
||||||
const requireValue = inputRequire.value;
|
|
||||||
firstArray.value = []
|
|
||||||
secondArray.value = []
|
|
||||||
extractedParts.value = []
|
|
||||||
stagOutputText.value = ''
|
|
||||||
const combinedString = `请帮我生成一个ppt大纲,主题为:${themeValue}。具体内容要求为:${requireValue}。注意,用三个等级大纲展示,如1. 1.1 1.1.2 2. 2.1这种类型,且按照这种顺序,不要有完全相同数字等级的大纲,不要有目录`
|
|
||||||
updateStagingData("user", combinedString);
|
|
||||||
connectWebSocket(stagingData.value);
|
|
||||||
// activeStep.value = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
let ttsWS
|
|
||||||
function connectWebSocket(data) {
|
|
||||||
outputText.value = ""; //清楚展示部分内容
|
|
||||||
status.value = "ttsing";
|
|
||||||
return getWebsocketUrl().then((url) => {
|
|
||||||
ttsWS = new WebSocket(url);
|
|
||||||
ttsWS.onopen = () => {
|
|
||||||
webSocketSend(ttsWS, data);
|
|
||||||
};
|
|
||||||
ttsWS.onmessage = (e) => {
|
|
||||||
result1(e.data);
|
|
||||||
};
|
|
||||||
ttsWS.onerror = (e) => {
|
|
||||||
status.value = "error";
|
|
||||||
console.log("WebSocket error:", e);
|
|
||||||
};
|
|
||||||
ttsWS.onclose = () => {
|
|
||||||
status.value = "init";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBackgroundColor = (key) => {
|
|
||||||
return outlineData.value.templateId === key ? '#83e2b6' : '#f5f5f5';
|
|
||||||
};
|
|
||||||
|
|
||||||
function getWebsocketUrl() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var apiKey = apikey;
|
|
||||||
var apiSecret = secret;
|
|
||||||
var url = "wss://spark-api.xf-yun.com/v4.0/chat";
|
|
||||||
|
|
||||||
var host = "spark-api.xf-yun.com";
|
|
||||||
var date = new Date().toGMTString();
|
|
||||||
var algorithm = "hmac-sha256";
|
|
||||||
var headers = "host date request-line";
|
|
||||||
var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v4.0/chat HTTP/1.1`;
|
|
||||||
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
|
|
||||||
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
|
|
||||||
|
|
||||||
var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
|
|
||||||
var authorization = CryptoJS.enc.Base64.stringify(
|
|
||||||
CryptoJS.enc.Utf8.parse(authorizationOrigin)
|
|
||||||
);
|
|
||||||
|
|
||||||
url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
|
|
||||||
console.log(url);
|
|
||||||
resolve(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function webSocketSend(ws, data) {
|
|
||||||
const params = {
|
|
||||||
header: {
|
|
||||||
app_id: appId,
|
|
||||||
},
|
|
||||||
parameter: {
|
|
||||||
chat: {
|
|
||||||
domain: "4.0Ultra",
|
|
||||||
temperature: 0.5,
|
|
||||||
max_tokens: 1024,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
message: {
|
|
||||||
text: data,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ws.send(JSON.stringify(params));
|
|
||||||
}
|
|
||||||
|
|
||||||
function result1(resultData) {
|
|
||||||
let jsonData = JSON.parse(resultData);
|
|
||||||
console.log(jsonData)
|
|
||||||
outputText.value += jsonData.payload.choices.text[0].content;
|
|
||||||
const div = document.querySelector('.paragraphs');
|
|
||||||
if (div) {
|
|
||||||
div.scrollTop = div.scrollHeight;
|
|
||||||
}
|
|
||||||
if (jsonData.payload && jsonData.payload.usage) {
|
|
||||||
updateStagingData("assistant", outputText.value) //返回数据存入记忆池
|
|
||||||
}
|
|
||||||
if (jsonData.header.code !== 0) {
|
|
||||||
alert(`提问失败: ${jsonData.header.code}:${jsonData.header.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const chooseBackground = (data) => {
|
|
||||||
outlineData.value.templateId = data
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeCursor = (cursorStyle) => {
|
|
||||||
document.documentElement.style.cursor = cursorStyle;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// let url = "https://bjcdn.openstorage.cn/xinghuo-privatedata/%2Ftmp/apiTempFileba724e0344f74e1480535eedf3ebec661601807661085006275/%E9%87%91%E9%A9%AC%E5%A5%96%E5%B0%B4%E5%B0%AC%E4%BA%8B%E4%BB%B6%E5%88%86%E6%9E%90%E4%B8%8E%E5%BA%94%E5%AF%B9%E7%AD%96%E7%95%A5.pptx"
|
|
||||||
// creatAIPPT(props.currentNode.itemtitle + '.pptx',url, props.uploadData).then((res) => {
|
|
||||||
// emit('addSuccess',res)
|
|
||||||
// })
|
|
||||||
// connectWebSocket("init");
|
|
||||||
props.dataList.filter(item => {
|
|
||||||
inputRequire.value += item.answer
|
|
||||||
})
|
|
||||||
getBackgrounds();
|
|
||||||
// addMessage()
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.ai-container {
|
|
||||||
width: 100%;
|
|
||||||
background-color: #f5f7f6;
|
|
||||||
padding: 20px
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-box {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card1 {
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paragraphs {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
text-align: left;
|
|
||||||
max-height: 60vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
border: 1px solid #409EFF;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.themes {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
height: 250px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
border: 1px solid #409EFF;
|
|
||||||
padding: 10px;
|
|
||||||
outline-style: none;
|
|
||||||
/* margin: 5px */
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row>.el-col {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row>.el-col>div,
|
|
||||||
.outline-row>.el-col>div>.el-input {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-with-dash {
|
|
||||||
margin-left: 100px
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-with-dash::after {
|
|
||||||
content: "";
|
|
||||||
border-bottom: 1px dashed #000;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content-1 {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #c2dbf3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content-2 {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-row {
|
|
||||||
padding: 20px
|
|
||||||
}
|
|
||||||
:deep(.el-card__body){
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,43 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<el-dialog class="ppt-dialog" v-model="model" :show-close="false" width="800" destroy-on-close :top="'3vh'">
|
|
||||||
<template #header="{ close, titleId, titleClass }">
|
|
||||||
<div class="dialog-header">
|
|
||||||
<h4 :id="titleId" :class="titleClass">生成PPT(试验版)</h4>
|
|
||||||
<i class="iconfont icon-guanbi" @click="close"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<AiPptist @add-success="addAiPPT" :dataList="dataList"/>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import AiPptist from './ai-pptist.vue';
|
|
||||||
const model = defineModel()
|
|
||||||
const emit = defineEmits(['addSuccess'])
|
|
||||||
const props = defineProps({
|
|
||||||
dataList: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const addAiPPT = (data) => {
|
|
||||||
emit('addSuccess', data)
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
:deep(.ppt-dialog){
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
|
||||||
.dialog-header{
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
.icon-guanbi {
|
|
||||||
font-size: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<el-button type="primary">生成大纲</el-button>
|
<el-button type="primary">生成大纲</el-button>
|
||||||
<el-button type="danger" @click="pptDialog = true">生成PPT</el-button>
|
<el-button type="danger">生成PPT</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-con flex">
|
<div class="right-con flex">
|
||||||
|
@ -49,7 +49,6 @@
|
||||||
</div>
|
</div>
|
||||||
<EditDialog v-model="isEdit" :item="curItem" />
|
<EditDialog v-model="isEdit" :item="curItem" />
|
||||||
<AdjustDialog v-model="isAdjust" :item="curItem" />
|
<AdjustDialog v-model="isAdjust" :item="curItem" />
|
||||||
<PptDialog @add-success="addAiPPT" :dataList="resultList" v-model="pptDialog"/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -60,9 +59,8 @@ import EditDialog from './edit-dialog.vue'
|
||||||
import AdjustDialog from './adjust-dialog.vue'
|
import AdjustDialog from './adjust-dialog.vue'
|
||||||
import { completion, tempResult } from '@/api/mode/index.js'
|
import { completion, tempResult } from '@/api/mode/index.js'
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
import { dataSetJson } from '@/utils/comm.js'
|
||||||
import PptDialog from '@/views/prepare/container/pptist-dialog.vue'
|
|
||||||
|
|
||||||
const pptDialog = ref(false)
|
|
||||||
const resultList = ref([])
|
const resultList = ref([])
|
||||||
emitter.on('changeMode', (item) => {
|
emitter.on('changeMode', (item) => {
|
||||||
console.log(item, 'item')
|
console.log(item, 'item')
|
||||||
|
@ -97,10 +95,6 @@ const params = reactive(
|
||||||
dataset_id: ''
|
dataset_id: ''
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const addAiPPT = () => {
|
|
||||||
|
|
||||||
}
|
|
||||||
const conversation = async () => {
|
const conversation = async () => {
|
||||||
for (let item of resultList.value) {
|
for (let item of resultList.value) {
|
||||||
item.loading = true
|
item.loading = true
|
||||||
|
@ -248,4 +242,4 @@ onUnmounted(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue