Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into zdg_dev
This commit is contained in:
commit
3b851887ca
|
@ -0,0 +1,81 @@
|
||||||
|
import axios from 'axios'
|
||||||
|
import request from '@/utils/request'
|
||||||
|
import { getToken } from "@/utils/auth";
|
||||||
|
|
||||||
|
// 文生图片
|
||||||
|
export function convertTextToPicture(data) {
|
||||||
|
return axios({
|
||||||
|
url: 'https://ai.ysaix.com:7853/prompt',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': '*/*'
|
||||||
|
},
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取任务列表
|
||||||
|
export function getQueue() {
|
||||||
|
return axios({
|
||||||
|
url: `https://ai.ysaix.com:7853/queue`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取生图任务id
|
||||||
|
export function getPromptId(id) {
|
||||||
|
return axios({
|
||||||
|
url: `https://ai.ysaix.com:7853/history/${id}`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取生成图片路径
|
||||||
|
export function getPicture(data) {
|
||||||
|
return axios({
|
||||||
|
url: 'https://ai.ysaix.com:7853/view',
|
||||||
|
method: 'get',
|
||||||
|
params: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 大模型对话生成prompt模板
|
||||||
|
export function chattoprompt(dataset_id,prompt) {
|
||||||
|
return axios({
|
||||||
|
url: '/api/v1/parse/docs',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm',
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
'dataset_id': dataset_id,
|
||||||
|
'prompt': prompt
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// prompt敏感词校验
|
||||||
|
export function textSensitiveWord(data) {
|
||||||
|
return request({
|
||||||
|
url: '/verify/text',
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
'text' : data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片上传资源库
|
||||||
|
export function uploadPicture(data) {
|
||||||
|
return axios({
|
||||||
|
url: '/dev-api/smarttalk/file/upload',
|
||||||
|
method: 'post',
|
||||||
|
headers: {
|
||||||
|
'Accept': '*/*',
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
'Authorization': "Bearer " + getToken()
|
||||||
|
},
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,16 @@ export function listEntpcoursework(query) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 查询entpcoursework列表
|
||||||
|
export function listEntpcourseworkLocal(query) {
|
||||||
|
return request({
|
||||||
|
url: '/education/entpcoursework/local/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 查询entpcoursework详细
|
// 查询entpcoursework详细
|
||||||
export function getEntpcoursework(id) {
|
export function getEntpcoursework(id) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
@ -0,0 +1,627 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-row :gutter="40" style="height:auto">
|
||||||
|
<el-col :span="8">
|
||||||
|
<div>
|
||||||
|
<div style="text-align: left">反面提示词</div>
|
||||||
|
<br>
|
||||||
|
<el-input v-model="formData.prompt[12].inputs.negative_prompt" placeholder="试试在这里输入你不想其进入图画的词"
|
||||||
|
type="textarea"></el-input>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div>
|
||||||
|
<div style="text-align: left">可选提示词</div>
|
||||||
|
<br>
|
||||||
|
<div style="font-size: 14px;text-align: left">风格特点</div>
|
||||||
|
<el-checkbox-group v-model="checkList">
|
||||||
|
<el-checkbox v-for="(prompt, index) in promptOption1" :key="index" :label="prompt" :value="prompt" />
|
||||||
|
</el-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div style="font-size: 14px;text-align: left">主体对象</div>
|
||||||
|
<el-checkbox-group v-model="checkList">
|
||||||
|
<el-checkbox v-for="(prompt, index) in promptOption2" :key="index" :label="prompt" :value="prompt" />
|
||||||
|
</el-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div style="font-size: 14px;text-align: left">场景</div>
|
||||||
|
<el-checkbox-group v-model="checkList">
|
||||||
|
<el-checkbox v-for="(prompt, index) in promptOption3" :key="index" :label="prompt" :value="prompt" />
|
||||||
|
</el-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right">
|
||||||
|
<el-button type="primary" @click="addCheckListToPrompt">添加</el-button>
|
||||||
|
<el-button type="primary" @click="deletePrompt">清空</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 具体参数相关内容 -->
|
||||||
|
<el-form label-position="top" size="small">
|
||||||
|
<el-form-item label="图片尺寸" style=" margin-bottom: 0px">
|
||||||
|
<el-row class="ratio-options" :gutter="10" style="margin-bottom: -15px;margin-top: -25px">
|
||||||
|
<el-col v-for="ratio in ratioOptions" :key="ratio.value" :span="4">
|
||||||
|
<el-button :type="form.ratio === ratio.value ? 'primary' : 'default'" @click="setRatio(ratio.value)"
|
||||||
|
class="ratio-option" block>
|
||||||
|
{{ ratio.label }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="图片比例" style=" margin-bottom: 0px">
|
||||||
|
<el-row class="ratio-options" :gutter="10" style="margin-bottom: -15px;margin-top: -25px">
|
||||||
|
<el-col v-for="ratio in ratioOptions2" :key="ratio.value" :span="4">
|
||||||
|
<el-button :type="form.ratios2 === ratio.value ? 'primary' : 'default'" @click="setRatio2(ratio.value)"
|
||||||
|
class="ratio-option" block>
|
||||||
|
{{ ratio.label }}
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="图片数量" style=" margin-bottom: 0px">
|
||||||
|
<el-row style="margin-bottom: -15px;margin-top: -25px">
|
||||||
|
<el-button style="width: 10%" :type="num_picture === 1 ? 'primary' : 'default'" @click="changePicture(1)">
|
||||||
|
1
|
||||||
|
</el-button>
|
||||||
|
<el-button style="width: 10%" :type="num_picture === 2 ? 'primary' : 'default'" @click="changePicture(2)">
|
||||||
|
2
|
||||||
|
</el-button>
|
||||||
|
<el-button style="width: 10%" :type="num_picture === 3 ? 'primary' : 'default'" @click="changePicture(3)">
|
||||||
|
3
|
||||||
|
</el-button>
|
||||||
|
<el-button style="width: 10%" :type="num_picture === 4 ? 'primary' : 'default'" @click="changePicture(4)">
|
||||||
|
4
|
||||||
|
</el-button>
|
||||||
|
</el-row>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="随机种子">
|
||||||
|
<el-slider v-model="formData.prompt[14].inputs.seed" :min="1" :max="10000000" show-input />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="cfg (数值越高,生图过程与提示词越相关)">
|
||||||
|
<el-slider v-model="formData.prompt[14].inputs.cfg" :max="20" show-input />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="16">
|
||||||
|
<div
|
||||||
|
:style="{ height: divHeight + 'px', 'overflow-y': 'auto', 'margin-bottom': '10px', 'background-color': '#f5f5f5', 'padding': '10px' }">
|
||||||
|
<div v-for="(resultItem, resultIndex) in resultList" :key="resultIndex">
|
||||||
|
<div style="display: flex; flex-wrap: wrap; justify-content: flex-end;">
|
||||||
|
<el-card style="max-width: 50%; margin-right: 10px; display: inline-block;background-color: lightblue;">
|
||||||
|
<div>
|
||||||
|
<p style="word-wrap: break-word; overflow-wrap: break-word;text-align: left">{{ resultItem }}</p>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
<el-row :gutter="10" justify="center">
|
||||||
|
<el-col :span="6" v-for="(url, index) in pictureurl[resultIndex]" :key="index">
|
||||||
|
<el-card style="margin-bottom: 5%;height:95%">
|
||||||
|
<el-image style="width: 100%;" fit="cover" :src="url" :preview-src-list="pictureurl"
|
||||||
|
:initial-index="index" class="equal-size-image"></el-image>
|
||||||
|
<div style="text-align: center; margin-top: 15px">
|
||||||
|
<el-button :disabled="buttonStates[resultIndex][index].disabled" size="small" type="primary"
|
||||||
|
@click="saveImage(resultIndex, index, url, resultItem)">{{ buttonStates[resultIndex][index].text
|
||||||
|
}}</el-button>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<el-row :gutter="10" justify="center">
|
||||||
|
<el-col v-if="pictureLoading" :span="6" v-for="n in generateArray(this.skeletonNumber)" :key="n">
|
||||||
|
<el-card>
|
||||||
|
<el-skeleton class="custom-skeleton-item" animated>
|
||||||
|
<template #template>
|
||||||
|
<el-skeleton-item variant="image" class="custom-skeleton-item"></el-skeleton-item>
|
||||||
|
</template>
|
||||||
|
</el-skeleton>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="10" justify="center">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-card v-for="(item, index) in resultData" :key="index"
|
||||||
|
style="display: flex;flex-direction: column;align-items: center;margin-bottom: 10px" justify="center"
|
||||||
|
@click="handleCardClick(item)" :class="{ 'card-hover': !pictureLoading }">
|
||||||
|
<p style="word-wrap: break-word; overflow-wrap: break-word;">{{ item }}</p>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: center">
|
||||||
|
<el-input style="width: 70%;" v-model="promptData" placeholder="试试输入你心中的画面,尽量描述具体点哦,可以按照这个格式来写: 提示词=主体+风格+场景"
|
||||||
|
type="textarea">
|
||||||
|
</el-input>
|
||||||
|
<el-button type="primary" :disabled="pictureLoading" @click="fetchData">
|
||||||
|
{{ !pictureLoading ? "生成图片" : "请等待" }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { convertTextToPicture, getQueue, getPromptId, getPicture, chattoprompt, textSensitiveWord, uploadPicture } from "@/api/aiGeneratedImage/index.js";
|
||||||
|
import CryptoJS from 'crypto-js'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
export default {
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
ratio: "512",
|
||||||
|
ratios2: "1/1",
|
||||||
|
},
|
||||||
|
ratioOptions: [
|
||||||
|
{ value: "512", label: "512" },
|
||||||
|
{ value: "768", label: "768" },
|
||||||
|
{ value: "1024", label: "1024" },
|
||||||
|
{ value: "1280", label: "1280" },
|
||||||
|
{ value: "2048", label: "2048" },
|
||||||
|
],
|
||||||
|
ratioOptions2: [
|
||||||
|
{ value: "1/1", label: "1:1" },
|
||||||
|
{ value: "4/3", label: "4:3" },
|
||||||
|
{ value: "3/4", label: "3:4" },
|
||||||
|
{ value: "9/16", label: "9:16" },
|
||||||
|
{ value: "16/9", label: "16:9" },
|
||||||
|
],
|
||||||
|
//图片数据
|
||||||
|
imageData: {
|
||||||
|
imageUrls: [],
|
||||||
|
prompt: [],
|
||||||
|
time: [],
|
||||||
|
id: [],
|
||||||
|
},
|
||||||
|
promptOption1: ["赛博朋克", "水墨风", "莫奈风格", "二次元", "中国风", "写实风格", "水彩风格", "工笔画", "素描风", "未来主义", "超现实主义", "映像派"],
|
||||||
|
promptOption2: ["男生", "女生", "老年人", "船舶", "蝴蝶", "狮子", "兔子", "飞机", "中年人", "大树", "长江", "坦克"],
|
||||||
|
promptOption3: ["雨林", "沙漠", "湖泊", "天空", "城市", "乡村", "太空", "教室"],
|
||||||
|
promptData: "",
|
||||||
|
|
||||||
|
//模型参数
|
||||||
|
formData: {
|
||||||
|
client_id: "533ef3a3-39c0-4e39-9ced-37d290f371f8",
|
||||||
|
prompt: {
|
||||||
|
3: {
|
||||||
|
inputs: {
|
||||||
|
images: ["10", 0],
|
||||||
|
},
|
||||||
|
class_type: "PreviewImage",
|
||||||
|
_meta: {
|
||||||
|
title: "Preview Image",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
6: {
|
||||||
|
inputs: {
|
||||||
|
model: "Kwai-Kolors/Kolors",
|
||||||
|
precision: "fp16",
|
||||||
|
},
|
||||||
|
class_type: "DownloadAndLoadKolorsModel",
|
||||||
|
_meta: {
|
||||||
|
title: "(Down)load Kolors Model",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
10: {
|
||||||
|
inputs: {
|
||||||
|
samples: ["14", 0],
|
||||||
|
vae: ["11", 0],
|
||||||
|
},
|
||||||
|
class_type: "VAEDecode",
|
||||||
|
_meta: {
|
||||||
|
title: "VAE Decode",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
11: {
|
||||||
|
inputs: {
|
||||||
|
vae_name: "sdxl.vae.safetensors",
|
||||||
|
},
|
||||||
|
class_type: "VAELoader",
|
||||||
|
_meta: {
|
||||||
|
title: "Load VAE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
12: {
|
||||||
|
inputs: {
|
||||||
|
prompt: "",
|
||||||
|
negative_prompt: "",
|
||||||
|
num_images_per_prompt: 1,
|
||||||
|
chatglm3_model: ["13", 0],
|
||||||
|
},
|
||||||
|
class_type: "KolorsTextEncode",
|
||||||
|
_meta: {
|
||||||
|
title: "Kolors Text Encode",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
13: {
|
||||||
|
inputs: {
|
||||||
|
precision: "quant8",
|
||||||
|
},
|
||||||
|
class_type: "DownloadAndLoadChatGLM3",
|
||||||
|
_meta: {
|
||||||
|
title: "(Down)load ChatGLM3 Model",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
14: {
|
||||||
|
inputs: {
|
||||||
|
width: 1024,
|
||||||
|
height: 1024,
|
||||||
|
seed: 1000102404233412,
|
||||||
|
steps: 25,
|
||||||
|
cfg: 5,
|
||||||
|
scheduler: "EulerDiscreteScheduler",
|
||||||
|
denoise_strength: 1,
|
||||||
|
kolors_model: ["6", 0],
|
||||||
|
kolors_embeds: ["12", 0],
|
||||||
|
},
|
||||||
|
class_type: "KolorsSampler",
|
||||||
|
_meta: {
|
||||||
|
title: "Kolors Sampler",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
picture: {
|
||||||
|
filename: "",
|
||||||
|
type: "temp",
|
||||||
|
subfolder: "",
|
||||||
|
preview: "",
|
||||||
|
channel: "",
|
||||||
|
},
|
||||||
|
buttonStates: [], // 用于存储按钮状态的二维数组,初始为空
|
||||||
|
resultList: [],
|
||||||
|
pictureurl: [],
|
||||||
|
percentage: 50,
|
||||||
|
num_picture: 1,
|
||||||
|
skeletonNumber: 0,
|
||||||
|
cfg_value: 5,
|
||||||
|
pictureLoading: false,
|
||||||
|
QueueNumber: 0, //前方排队任务数量
|
||||||
|
userIdInComponent: '',
|
||||||
|
activeName: '1',
|
||||||
|
checkList: [], //prompt生成
|
||||||
|
totalData: 0,
|
||||||
|
// deleteImageSrc: deletebutton,
|
||||||
|
timer: null,
|
||||||
|
isTimerPaused: false,
|
||||||
|
resultData: [],
|
||||||
|
divHeight: 0,
|
||||||
|
dataset_id: '',
|
||||||
|
courseName: '',
|
||||||
|
levelFirstId: '',
|
||||||
|
levelSecondId: '',
|
||||||
|
textbookId: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//生图占位图数量
|
||||||
|
generateArray(length) {
|
||||||
|
return Array.from({ length }, (_, index) => index);
|
||||||
|
},
|
||||||
|
|
||||||
|
//随机种子
|
||||||
|
Randomseed() {
|
||||||
|
this.formData.prompt[14].inputs.seed = Math.floor(
|
||||||
|
Math.random() * 10000001
|
||||||
|
);
|
||||||
|
},
|
||||||
|
sleep(ms) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
},
|
||||||
|
|
||||||
|
//生成图片
|
||||||
|
async fetchData() {
|
||||||
|
|
||||||
|
// 判断prompt是否为空
|
||||||
|
if (this.promptData == "") {
|
||||||
|
this.$message.error("prompt不能为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prompt = this.promptData
|
||||||
|
//敏感词校验
|
||||||
|
await textSensitiveWord(prompt)
|
||||||
|
|
||||||
|
this.setRatio(this.form.ratio)
|
||||||
|
this.changeSize()
|
||||||
|
this.resultList.push(this.promptData)
|
||||||
|
this.skeletonNumber = this.num_picture
|
||||||
|
const skeletonItemNumber = this.num_picture
|
||||||
|
// const userId = this.userIdInComponent
|
||||||
|
// const model = 'kolors'
|
||||||
|
|
||||||
|
// 处理prompt生成多张图片
|
||||||
|
let temp = "";
|
||||||
|
if (skeletonItemNumber > 1) {
|
||||||
|
for (let i = 1; i < skeletonItemNumber; i++) {
|
||||||
|
temp += "|" + this.promptData;
|
||||||
|
}
|
||||||
|
this.formData.prompt[12].inputs.prompt = this.promptData + temp;
|
||||||
|
} else {
|
||||||
|
this.formData.prompt[12].inputs.prompt = this.promptData;
|
||||||
|
}
|
||||||
|
// 将数据转成json
|
||||||
|
const transformedData = {
|
||||||
|
client_id: this.formData.client_id,
|
||||||
|
prompt: Object.fromEntries(
|
||||||
|
Object.entries(this.formData.prompt).map(([key, value]) => [
|
||||||
|
key,
|
||||||
|
{
|
||||||
|
inputs: value.inputs,
|
||||||
|
class_type: value.class_type,
|
||||||
|
_meta: value._meta,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const jsonData = JSON.stringify(transformedData, null, 2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//生图过程
|
||||||
|
try {
|
||||||
|
this.pictureLoading = true;
|
||||||
|
const response = await convertTextToPicture(jsonData); //发起生图任务
|
||||||
|
const pictureId = response.data.prompt_id;
|
||||||
|
const queue_Number = response.data.number
|
||||||
|
let queue;
|
||||||
|
do {
|
||||||
|
queue = await getQueue(); //查询生图队列
|
||||||
|
if (this.hasId(queue, pictureId)) {
|
||||||
|
this.QueueNumber = queue_Number - queue.data.queue_running[0][0] // 计算队列剩余数量
|
||||||
|
await this.sleep(500);
|
||||||
|
}
|
||||||
|
} while (this.hasId(queue, pictureId));
|
||||||
|
|
||||||
|
const pictureData = await getPromptId(pictureId); //生图任务id查询结果
|
||||||
|
|
||||||
|
const jsonString = JSON.parse(pictureData.request.responseText);
|
||||||
|
const urls = []
|
||||||
|
const buttonState = [];
|
||||||
|
for (let i = 0; i < skeletonItemNumber; i++) {
|
||||||
|
this.picture.filename = jsonString[pictureId].outputs[3].images[i].filename;
|
||||||
|
const pictureURL = await getPicture(this.picture); //获得生成图片的url
|
||||||
|
const url0 = pictureURL.request.responseURL;
|
||||||
|
urls.push(url0)
|
||||||
|
buttonState.push({
|
||||||
|
disabled: false,
|
||||||
|
text: "插入本课素材资源库",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.skeletonNumber = 0
|
||||||
|
this.pictureurl.push(urls)
|
||||||
|
this.buttonStates.push(buttonState)
|
||||||
|
this.pictureLoading = false;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.pictureLoading = false;
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//生图队列的查询
|
||||||
|
hasId(obj, id) {
|
||||||
|
if (typeof obj !== "object" || obj === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Object.values(obj).includes(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Object.values(obj).some((value) => this.hasId(value, id));
|
||||||
|
},
|
||||||
|
|
||||||
|
setRatio(ratio) {
|
||||||
|
this.form.ratio = ratio;
|
||||||
|
switch (ratio) {
|
||||||
|
case "512":
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 512;
|
||||||
|
break;
|
||||||
|
case "768":
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 768;
|
||||||
|
break;
|
||||||
|
case "1024":
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 1024;
|
||||||
|
break;
|
||||||
|
case "1280":
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 1280;
|
||||||
|
break;
|
||||||
|
case "2048":
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 2048;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 512;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setRatio2(ratio) {
|
||||||
|
this.form.ratios2 = ratio;
|
||||||
|
},
|
||||||
|
changeSize() {
|
||||||
|
const a = this.form.ratios2
|
||||||
|
if (a == "1/1") {
|
||||||
|
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height
|
||||||
|
} else if (a == "4/3") {
|
||||||
|
this.formData.prompt[14].inputs.height = (this.formData.prompt[14].inputs.width) * 3 / 4
|
||||||
|
} else if (a == "3/4") {
|
||||||
|
this.formData.prompt[14].inputs.width = (this.formData.prompt[14].inputs.height) * 3 / 4
|
||||||
|
} else if (a == "9/16") {
|
||||||
|
this.formData.prompt[14].inputs.width = (this.formData.prompt[14].inputs.height) * 9 / 16
|
||||||
|
} else {
|
||||||
|
this.formData.prompt[14].inputs.height = (this.formData.prompt[14].inputs.width) * 9 / 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changePicture(num) {
|
||||||
|
this.num_picture = num;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 生成提示词模板
|
||||||
|
async createPrompt() {
|
||||||
|
const dataset_id = this.dataset_id
|
||||||
|
const courseName = this.courseName
|
||||||
|
const prompt = `结合${courseName},给我三句详细的提示词用于生成图片,以1.2.3的形式`
|
||||||
|
const response = await chattoprompt(dataset_id, prompt)
|
||||||
|
const resultData = response.data.answer
|
||||||
|
const promptData = []
|
||||||
|
|
||||||
|
for (let i = 1; i <= 3; i++) {
|
||||||
|
const startIndex = resultData.indexOf(`${i}.`) + `${i}.`.length;
|
||||||
|
const endIndex = resultData.indexOf("。", startIndex);
|
||||||
|
promptData.push(resultData.substring(startIndex, endIndex).trim());
|
||||||
|
}
|
||||||
|
this.resultData = promptData
|
||||||
|
},
|
||||||
|
|
||||||
|
handleCardClick(item) {
|
||||||
|
this.promptData = item
|
||||||
|
this.fetchData()
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
//保存图片到素材库
|
||||||
|
async saveImage(resultIndex, index, url, resultItem) {
|
||||||
|
this.buttonStates[resultIndex][index].disabled = true;
|
||||||
|
this.buttonStates[resultIndex][index].text = "正在保存...";
|
||||||
|
const numberIndex = url.indexOf('filename=');
|
||||||
|
const path = url.substring(numberIndex + 9);
|
||||||
|
const pngIndex = path.indexOf('.png');
|
||||||
|
const finalPath = path.substring(0, pngIndex + 4);
|
||||||
|
try {
|
||||||
|
const blob = await this.getImageBlob(`https://ai.ysaix.com:7853/view?filename=${finalPath}&type=temp`);
|
||||||
|
|
||||||
|
const hash = CryptoJS.MD5(blob).toString();
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
let file = new File([blob], `${resultItem}.png`, {
|
||||||
|
type: 'image/png'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加参数
|
||||||
|
formData.append('md5', hash);
|
||||||
|
formData.append('file', file);
|
||||||
|
formData.append('textbookId', this.textbookId);
|
||||||
|
formData.append('levelFirstId', this.levelFirstId);
|
||||||
|
formData.append('levelSecondId', this.levelSecondId);
|
||||||
|
formData.append('fileSource', '个人');
|
||||||
|
formData.append('fileRoot', '备课');
|
||||||
|
formData.append('fileShowName', `${resultItem}.png`);
|
||||||
|
formData.append('fileFlag', '素材');
|
||||||
|
const responsedata = uploadPicture(formData);
|
||||||
|
responsedata.then((response) => {
|
||||||
|
if (response.data && response.data.code === 200) {
|
||||||
|
// 若上传成功,更新对应按钮的状态
|
||||||
|
this.buttonStates[resultIndex][index].text = "已保存";
|
||||||
|
this.buttonStates[resultIndex][index].disabled = true;
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
this.buttonStates[resultIndex][index].disabled = false;
|
||||||
|
this.buttonStates[resultIndex][index].text = "插入本课素材资源库";
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getImageBlob(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', url, true);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (this.status === 200) {
|
||||||
|
resolve(this.response);
|
||||||
|
} else {
|
||||||
|
reject(new Error(`图片获取失败,状态码:${this.status}`));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function () {
|
||||||
|
reject(new Error('图片获取发生网络错误'));
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// convertImageToBase64(url) {
|
||||||
|
// return request({
|
||||||
|
// url: '/common/convertImageToBase64',
|
||||||
|
// method: 'get',
|
||||||
|
// params: {
|
||||||
|
// url: url
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// handleSaveImage(url) {
|
||||||
|
// this.convertImageToBase64(url).then(res => {
|
||||||
|
// this.$emit("saveImage", res)
|
||||||
|
// }, err => {
|
||||||
|
// this.$message.error(err);
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
|
||||||
|
//prompt生成器的勾选内容添加到输入框
|
||||||
|
addCheckListToPrompt() {
|
||||||
|
const joinedString = this.checkList.join(',');
|
||||||
|
this.promptData = ''
|
||||||
|
this.promptData += joinedString;
|
||||||
|
},
|
||||||
|
|
||||||
|
//清空prompt
|
||||||
|
deletePrompt() {
|
||||||
|
this.promptData = '',
|
||||||
|
this.checkList = []
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const route = useRoute();
|
||||||
|
this.dataset_id = route.query.datasetId;
|
||||||
|
this.courseName = route.query.coursetitle;
|
||||||
|
this.levelFirstId = route.query.levelFirstId;
|
||||||
|
this.levelSecondId = route.query.levelSecondId;
|
||||||
|
this.textbookId = route.query.textbookId;
|
||||||
|
this.createPrompt()
|
||||||
|
this.Randomseed();
|
||||||
|
this.divHeight = window.innerHeight * 0.80;
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
this.divHeight = window.innerHeight * 0.85;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', () => {
|
||||||
|
this.divHeight = window.innerHeight * 0.85;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.el-row {
|
||||||
|
padding: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-option,
|
||||||
|
.ratio-option {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-skeleton-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-display p {
|
||||||
|
font-size: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.equal-size-image img {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-hover:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disabled-cursor {
|
||||||
|
cursor: not-allowed !important;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -41,7 +41,7 @@
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click.stop="cloneDialog(ruleFormRef)">取消</el-button>
|
<el-button @click.stop="cloneDialog(ruleFormRef)">取消</el-button>
|
||||||
<el-button type="primary" @click.stop="onSubmit(ruleFormRef)"> 确定 </el-button>
|
<el-button :loading="setLoading" type="primary" @click.stop="onSubmit(ruleFormRef)"> 确定 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="isDialog" :show-close="false" width="800" destroy-on-close>
|
<el-dialog v-model="isDialog" :show-close="false" width="800" append-to-body destroy-on-close>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="custom-header flex">
|
<div class="custom-header flex">
|
||||||
<span>{{ item.name }}</span>
|
<span>{{ item.name }}</span>
|
||||||
|
@ -105,11 +105,9 @@ const getCompletion = async (val) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const saveAdjust = (item) =>{
|
const saveAdjust = (item) =>{
|
||||||
|
|
||||||
isDialog.value = false
|
isDialog.value = false
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
emitter.on('saveAdjust', item.msg)
|
emitter.emit('onSaveAdjust', item.msg)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const modeType = ref('课标')
|
const modeType = ref('课标')
|
||||||
|
|
|
@ -51,7 +51,9 @@
|
||||||
<div class="item-icon">
|
<div class="item-icon">
|
||||||
<i class="iconfont icon-ai"></i>
|
<i class="iconfont icon-ai"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-answer" v-html="item.answer"></div>
|
<div class="item-answer">
|
||||||
|
<TypingEffect :text="item.oldAnswer" :delay="10" :aiShow="item.aiShow" @complete="onSaveTemp(item)" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ai-btn" v-if="item.answer">
|
<div class="ai-btn" v-if="item.answer">
|
||||||
<el-button type="primary" link @click="againResult(index, item)">
|
<el-button type="primary" link @click="againResult(index, item)">
|
||||||
|
@ -68,7 +70,6 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<el-empty v-if="!childTempList.length" description="暂无模板数据" />
|
<el-empty v-if="!childTempList.length" description="暂无模板数据" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,6 +90,7 @@ import { sessionStore } from '@/utils/store'
|
||||||
import keywordDialog from './keyword-dialog.vue';
|
import keywordDialog from './keyword-dialog.vue';
|
||||||
import AdjustDialog from './adjust-dialog.vue'
|
import AdjustDialog from './adjust-dialog.vue'
|
||||||
import EditDialog from './edit-dialog.vue'
|
import EditDialog from './edit-dialog.vue'
|
||||||
|
import TypingEffect from '@/components/typing-effect/index.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
import { dataSetJson } from '@/utils/comm.js'
|
||||||
|
|
||||||
|
@ -109,7 +111,6 @@ const onAdd = () => {
|
||||||
isAdd.value = true
|
isAdd.value = true
|
||||||
Object.assign(editItem, curTemplate)
|
Object.assign(editItem, curTemplate)
|
||||||
isWordDialog.value = true
|
isWordDialog.value = true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const editKeyWord = (item, val) => {
|
const editKeyWord = (item, val) => {
|
||||||
|
@ -263,12 +264,14 @@ const params = reactive(
|
||||||
const againResult = async (index, item) => {
|
const againResult = async (index, item) => {
|
||||||
try {
|
try {
|
||||||
childTempList.value[index].loading = true
|
childTempList.value[index].loading = true
|
||||||
|
item.aiShow = true
|
||||||
|
childTempList.value[index].oldAnswer = ''
|
||||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
let answer = data.answer
|
||||||
childTempList.value[index].oldAnswer = answer
|
childTempList.value[index].oldAnswer = answer
|
||||||
childTempList.value[index].answer = getResult(answer);
|
childTempList.value[index].answer = getResult(answer);
|
||||||
onEditSave(item)
|
// onEditSave(item)
|
||||||
} finally {
|
} finally {
|
||||||
childTempList.value[index].loading = false
|
childTempList.value[index].loading = false
|
||||||
}
|
}
|
||||||
|
@ -278,18 +281,29 @@ const getCompletion = async () => {
|
||||||
for (let item of childTempList.value) {
|
for (let item of childTempList.value) {
|
||||||
try {
|
try {
|
||||||
item.loading = true
|
item.loading = true
|
||||||
|
item.aiShow = true
|
||||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
let answer = data.answer
|
||||||
item.oldAnswer = answer
|
item.oldAnswer = answer
|
||||||
item.answer = getResult(answer);
|
item.answer = getResult(answer);
|
||||||
onSaveTemp(item)
|
|
||||||
} finally {
|
} finally {
|
||||||
item.loading = false
|
item.loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 替换分析结果
|
||||||
|
emitter.on('onSaveAdjust', (item) => {
|
||||||
|
childTempList.value[curIndex.value].oldAnswer = item
|
||||||
|
let answer = getResult(item);
|
||||||
|
childTempList.value[curIndex.value].oldAnswer = item
|
||||||
|
childTempList.value[curIndex.value].answer = answer
|
||||||
|
onEditSave(childTempList.value[curIndex.value])
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
// 保存 重新研读后的结果
|
// 保存 重新研读后的结果
|
||||||
const onEditSave = async (item) =>{
|
const onEditSave = async (item) =>{
|
||||||
const { res } = await editTempResult({id: item.resultId, content: item.oldAnswer})
|
const { res } = await editTempResult({id: item.resultId, content: item.oldAnswer})
|
||||||
|
@ -297,30 +311,18 @@ const onEditSave = async (item) =>{
|
||||||
getChildTemplate()
|
getChildTemplate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 保存模板
|
// 保存模板
|
||||||
const onSaveTemp = (item) => {
|
const onSaveTemp = (item) => {
|
||||||
|
if(item.oldAnswer == '') return
|
||||||
const data = {
|
const data = {
|
||||||
mainModelId: curTemplate.id,
|
mainModelId: curTemplate.id,
|
||||||
modelId: item.id,
|
modelId: item.id,
|
||||||
examDocld: '',
|
examDocld: '',
|
||||||
content: item.oldAnswer
|
content: item.oldAnswer
|
||||||
}
|
}
|
||||||
tempSave(data).then(res => {
|
tempSave(data).then(res => {})
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 替换分析结果
|
|
||||||
emitter.on('saveAdjust', (item) => {
|
|
||||||
childTempList.value[curIndex.value].oldAnswer = item
|
|
||||||
let answer = getResult(item);
|
|
||||||
childTempList.value[curIndex.value].answer = answer
|
|
||||||
})
|
|
||||||
|
|
||||||
// 分析获取课标对话结果
|
// 分析获取课标对话结果
|
||||||
let getResult = (text) => {
|
let getResult = (text) => {
|
||||||
text = text.replace(/^\n\n(.*?)\n\n$/s, '<div>$1</div>');
|
text = text.replace(/^\n\n(.*?)\n\n$/s, '<div>$1</div>');
|
||||||
|
@ -351,8 +353,9 @@ onMounted(() => {
|
||||||
|
|
||||||
// 解绑
|
// 解绑
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
emitter.off('onGetMain');
|
||||||
emitter.off('onGetChild');
|
emitter.off('onGetChild');
|
||||||
emitter.off('saveAdjust');
|
emitter.off('onSaveAdjust');
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -422,6 +425,7 @@ onUnmounted(() => {
|
||||||
.item-answer {
|
.item-answer {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
:deep(.text-tit) {
|
:deep(.text-tit) {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
|
@ -284,23 +284,23 @@ const init = reactive({
|
||||||
formData.append("filetype", "image");
|
formData.append("filetype", "image");
|
||||||
formData.append("suffix", "image");
|
formData.append("suffix", "image");
|
||||||
formData.append("status", '1');
|
formData.append("status", '1');
|
||||||
if(userStore.deptId && userStore.deptId != null){
|
if(userStore.deptId != null){
|
||||||
formData.append("entpid", userStore.deptId);
|
formData.append("entpid", userStore.deptId);
|
||||||
}
|
}
|
||||||
if(userStore.userId && userStore.userId != null){
|
if(userStore.userId != null){
|
||||||
formData.append("userid", userStore.userId);
|
formData.append("userid", userStore.userId);
|
||||||
}
|
}
|
||||||
if(userStore.edudegree && userStore.edudegree != null){
|
if(userStore.edudegree && userStore.edudegree != ''){
|
||||||
let edudegree = userStore.edudegree.toString();
|
let edudegree = userStore.edudegree.toString();
|
||||||
if(edudegree != '' && edudegree.indexOf('年级') == -1){
|
if(edudegree != '' && edudegree.indexOf('年级') == -1){
|
||||||
edudegree += '年级';
|
edudegree += '年级';
|
||||||
}
|
}
|
||||||
formData.append("edudegree", edudegree);
|
formData.append("edudegree", edudegree);
|
||||||
}
|
}
|
||||||
if(userStore.edusubject && userStore.edusubject != null){
|
if(userStore.edusubject && userStore.edusubject != ''){
|
||||||
formData.append("edusubject", userStore.edusubject);
|
formData.append("edusubject", userStore.edusubject);
|
||||||
}
|
}
|
||||||
if(userStore.edustage && userStore.edustage != null){
|
if(userStore.edustage && userStore.edustage != ''){
|
||||||
formData.append("edustage", userStore.edustage);
|
formData.append("edustage", userStore.edustage);
|
||||||
}
|
}
|
||||||
if(props.upFileParams?.hasOwnProperty('lessionId')){
|
if(props.upFileParams?.hasOwnProperty('lessionId')){
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<div class="typing-effect">
|
||||||
|
<!-- <span v-html="displayedText"></span> -->
|
||||||
|
<el-input
|
||||||
|
v-model="displayedText"
|
||||||
|
:autosize="{ minRows: 2 }"
|
||||||
|
type="textarea"
|
||||||
|
readonly
|
||||||
|
resize="none"
|
||||||
|
style="width: 100%;"
|
||||||
|
input-style="border:none;outline: none;box-shadow:none;color:000;fontSize:15px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, watch } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
delay: {
|
||||||
|
type: Number,
|
||||||
|
default: 100 // 默认每个字符出现的延迟时间,单位是毫秒
|
||||||
|
},
|
||||||
|
aiShow: {
|
||||||
|
type: [Boolean]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['complete']);
|
||||||
|
const displayedText = ref('');
|
||||||
|
const index = ref(0);
|
||||||
|
|
||||||
|
const type = () => {
|
||||||
|
if(!props.aiShow) return
|
||||||
|
if (index.value <= props.text.length) {
|
||||||
|
displayedText.value += props.text.charAt(index.value);
|
||||||
|
index.value++;
|
||||||
|
setTimeout(() => type(), props.delay);
|
||||||
|
} else {
|
||||||
|
// 当所有字符都显示完毕时,触发 complete 事件
|
||||||
|
emit('complete');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
type();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听 props 的变化,以便当传入的 text 或 delay 发生改变时重新开始打字机效果
|
||||||
|
watch([() => props.text, () => props.delay], () => {
|
||||||
|
displayedText.value = '';
|
||||||
|
index.value = 0;
|
||||||
|
type();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.typing-effect {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
:deep(.el-textarea__inner:hover){
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -8,9 +8,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
|
const Remote = require('@electron/remote')
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
@ -47,6 +48,11 @@ const closeWindow = () => {
|
||||||
})
|
})
|
||||||
}).catch(() => { });
|
}).catch(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMounted(() =>{
|
||||||
|
isMaxSize.value = Remote.getCurrentWindow().isMaximized()
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<el-breadcrumb :separator-icon="ArrowRight">
|
<el-breadcrumb :separator-icon="ArrowRight">
|
||||||
<el-breadcrumb-item v-for="item in breadList"> {{ item.title }} </el-breadcrumb-item>
|
<el-breadcrumb-item v-for="item in breadList"> {{ item.title }} </el-breadcrumb-item>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
|
<span class="ml-5">《{{ curNode.itemtitle }}》</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-center" v-else>
|
<div class="header-center" v-else>
|
||||||
AI文枢{{ version }}
|
AI文枢{{ version }}
|
||||||
|
@ -20,11 +21,13 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue'
|
import { reactive, ref, watch } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ArrowRight } from '@element-plus/icons-vue'
|
import { ArrowRight } from '@element-plus/icons-vue'
|
||||||
import WindowTools from '@/components/window-tools/index.vue'
|
import WindowTools from '@/components/window-tools/index.vue'
|
||||||
import pkc from "../../../../../package.json"
|
import pkc from "../../../../../package.json"
|
||||||
|
import { sessionStore } from '@/utils/store'
|
||||||
|
|
||||||
const version = ref(pkc.version)
|
const version = ref(pkc.version)
|
||||||
|
|
||||||
// 返回
|
// 返回
|
||||||
|
@ -33,6 +36,8 @@ const onBack = () => {
|
||||||
router.go(-1)
|
router.go(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const curNode = reactive({itemtitle: ''})
|
||||||
|
|
||||||
// 监听当前路由
|
// 监听当前路由
|
||||||
const isShowBack = ref(false)
|
const isShowBack = ref(false)
|
||||||
const breadList = ref([])
|
const breadList = ref([])
|
||||||
|
@ -44,7 +49,8 @@ watch(
|
||||||
if (path.includes('/model') && path !== ('/model/index')) {
|
if (path.includes('/model') && path !== ('/model/index')) {
|
||||||
isShowBack.value = true
|
isShowBack.value = true
|
||||||
breadList.value = newValue.matched.map(item => item.meta)
|
breadList.value = newValue.matched.map(item => item.meta)
|
||||||
|
let data = sessionStore.get('subject.curNode')
|
||||||
|
Object.assign(curNode, data)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isShowBack.value = false
|
isShowBack.value = false
|
||||||
|
|
|
@ -85,6 +85,12 @@ export const constantRoutes = [
|
||||||
name: 'questionUpload',
|
name: 'questionUpload',
|
||||||
meta: { title: '习题上传' }
|
meta: { title: '习题上传' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'aiKolors',
|
||||||
|
component: () => import('@/components/ai-kolors/index.vue'),
|
||||||
|
name: 'aiKolors',
|
||||||
|
meta: { title: '文生图片' }
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,11 @@ const useClassTaskStore = defineStore('classTask',{
|
||||||
{value: 6, label: "复合题"},
|
{value: 6, label: "复合题"},
|
||||||
], // 习题查询条件 - 题型
|
], // 习题查询条件 - 题型
|
||||||
entpCourseWorkGroupList: [{
|
entpCourseWorkGroupList: [{
|
||||||
Key: -1,
|
Key: 0,
|
||||||
Value: '不限',
|
Value: '不限',
|
||||||
}, {
|
}, {
|
||||||
Key: 1,
|
Key: 1,
|
||||||
Value: '真题',
|
Value: '真题',
|
||||||
}, {
|
|
||||||
Key: 0,
|
|
||||||
Value: '非真题',
|
|
||||||
}
|
}
|
||||||
], // 习题查询条件 - 题源
|
], // 习题查询条件 - 题源
|
||||||
entpCourseWorkYearList: [
|
entpCourseWorkYearList: [
|
||||||
|
|
|
@ -395,5 +395,6 @@ export const dataSetJson = {
|
||||||
"课标-高中-英语": "e889fcac9fd011efb22a0242ac140006",
|
"课标-高中-英语": "e889fcac9fd011efb22a0242ac140006",
|
||||||
"课标-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
"课标-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
||||||
"课标-高中-地理": "270516829fd111efb13c0242ac140006",
|
"课标-高中-地理": "270516829fd111efb13c0242ac140006",
|
||||||
|
"课标-高中-政治": "a7df2b01aafd11ef8bb40242ac140002",
|
||||||
"鉴权": "ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm"
|
"鉴权": "ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm"
|
||||||
}
|
}
|
|
@ -118,7 +118,7 @@ import { Search } from '@element-plus/icons-vue'
|
||||||
import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue'
|
import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
import { listEntpcoursework } from '@/api/education/entpCourseWork'
|
import { listEntpcoursework, listEntpcourseworkLocal } from '@/api/education/entpCourseWork'
|
||||||
import { listEvaluationclue } from '@/api/classTask'
|
import { listEvaluationclue } from '@/api/classTask'
|
||||||
import { delEntpcoursework, updateEntpcoursework } from "@/api/education/entpCourseWork";
|
import { delEntpcoursework, updateEntpcoursework } from "@/api/education/entpCourseWork";
|
||||||
|
|
||||||
|
@ -247,31 +247,32 @@ function Apis(key) {
|
||||||
const client = new Apis('/paht');
|
const client = new Apis('/paht');
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 题类
|
// 题类
|
||||||
worktype: entpCourseWorkQueryParams.worktype.label == '不限' ? '' : entpCourseWorkQueryParams.worktype.label,
|
worktype: entpCourseWorkQueryParams.worktype.label,
|
||||||
// 题源 TODO 估计后端没做相应的查询处理 web端也没有返回
|
// 题源 TODO 估计后端没做相应的查询处理 web端也没有返回
|
||||||
// workgroup: entpCourseWorkQueryParams.workgroup,
|
workgroup: entpCourseWorkQueryParams.workgroup,
|
||||||
// 年份 TODO 估计后端没做相应的查询处理 web端也没有返回
|
// 年份 TODO 估计后端没做相应的查询处理 web端也没有返回
|
||||||
// yearStr: entpCourseWorkQueryParams.yearStr !== '-1' ? entpCourseWorkQueryParams.yearStr:'',
|
yearStr: entpCourseWorkQueryParams.yearStr !== '-1' ? entpCourseWorkQueryParams.yearStr:'',
|
||||||
// 关键字
|
// 关键字
|
||||||
title: entpCourseWorkQueryParams.keyWord && entpCourseWorkQueryParams.keyWord !== '' ? entpCourseWorkQueryParams.keyWord:'',
|
keyword: entpCourseWorkQueryParams.keyWord && entpCourseWorkQueryParams.keyWord !== '' ? entpCourseWorkQueryParams.keyWord:'',
|
||||||
|
// 课程相关参数
|
||||||
|
edustage: userStore.edustage, // this.userStore.edustage,
|
||||||
|
edusubject: userStore.edusubject, // this.userStore.edusubject,
|
||||||
|
eid: props.bookobj.levelSecondId, // this.activeParams.lession.id,
|
||||||
|
status: "1",
|
||||||
|
editUserId: userStore.userId,
|
||||||
|
//orderby: 'concat(worktype,timestamp) DESC',
|
||||||
|
|
||||||
// 分页参数
|
// 分页参数
|
||||||
pageNum: paginationParams.pageNum,
|
pageNum: paginationParams.pageNum,
|
||||||
pageSize: paginationParams.pageSize,
|
pageSize: paginationParams.pageSize,
|
||||||
// 课程相关参数
|
}
|
||||||
edustage: userStore.edustage, // this.userStore.edustage,
|
//const entpcourseworkres = listEntpcoursework(queryForm);
|
||||||
edusubject: userStore.edusubject, // this.userStore.edusubject,
|
const entpcourseworkres = listEntpcourseworkLocal(queryForm);
|
||||||
evalid: props.bookobj.levelSecondId, // this.activeParams.lession.id,
|
|
||||||
status: "1",
|
|
||||||
edituserid: userStore.userId,
|
|
||||||
orderby: 'concat(worktype,timestamp) DESC',
|
|
||||||
|
|
||||||
}
|
|
||||||
const entpcourseworkres = listEntpcoursework(queryForm);
|
|
||||||
|
|
||||||
resolve(entpcourseworkres);
|
resolve(entpcourseworkres);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleQueryFromEntpCourseWork= async (queryType) => {
|
const handleQueryFromEntpCourseWork= async (queryType) => {
|
||||||
|
|
|
@ -152,7 +152,7 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-cropper-btn">
|
<div class="item-cropper-btn">
|
||||||
<el-button v-show="isCropper" circle @click="cropperFormItem('workdesc')"></el-button>
|
<el-button v-show="isCropper" circle @click="cropperFormItem('workdesc')"><el-icon><Search /></el-icon></el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -252,8 +252,7 @@
|
||||||
<el-tag v-else type="danger" style=" margin-left: 10px ">温馨提示:这里 - 号删除的是最后一道题目哟!</el-tag>
|
<el-tag v-else type="danger" style=" margin-left: 10px ">温馨提示:这里 - 号删除的是最后一道题目哟!</el-tag>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="item-cropper-btn-multi">
|
<div class="item-cropper-btn-multi">
|
||||||
<!-- <el-button v-show="isCropper" circle icon="Search" @click="cropperFormItem('workdesc')"></el-button> -->
|
<el-button v-show="isCropper" circle @click="cropperFormItem('workdesc')"><el-icon><Search /></el-icon></el-button>
|
||||||
<el-button v-show="isCropper" circle @click="cropperFormItem('workdesc')">识别</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ const getConversation = (val) => {
|
||||||
const getCompletion = async (val) => {
|
const getCompletion = async (val) => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
params.prompt = `根据${curNode.edustage}${curNode.edusubject},分析${props.item.name},${val}`
|
params.prompt = `按照${val}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
let answer = data.answer
|
||||||
msgList.value.push({
|
msgList.value.push({
|
||||||
|
@ -133,8 +133,6 @@ const saveAdjust = (item) =>{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const curFile = reactive({})
|
const curFile = reactive({})
|
||||||
const dataset_id = ref('')
|
const dataset_id = ref('')
|
||||||
const fileList = ref([])
|
const fileList = ref([])
|
||||||
|
@ -143,15 +141,15 @@ const getList = () =>{
|
||||||
userId: userInfo.userId,
|
userId: userInfo.userId,
|
||||||
dataset_id: dataset_id.value
|
dataset_id: dataset_id.value
|
||||||
}).then( res =>{
|
}).then( res =>{
|
||||||
fileList.value = [{fileId: '',fileName: '选择文件', id:-1},...res.rows]
|
fileList.value = res.rows
|
||||||
Object.assign(curFile, fileList.value[0])
|
Object.assign(curFile, fileList.value[0])
|
||||||
|
params.document_ids = fileList.value[0].docId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
emitter.on('curFile', (item) =>{
|
emitter.on('curFile', (item) =>{
|
||||||
changeFile(item)
|
changeFile(item)
|
||||||
})
|
})
|
||||||
const changeFile = (val) =>{
|
const changeFile = (val) =>{
|
||||||
|
|
||||||
Object.assign(curFile, val);
|
Object.assign(curFile, val);
|
||||||
params.document_ids = val.docId
|
params.document_ids = val.docId
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ watch(() => props.item.answer, (newVal) => {
|
||||||
|
|
||||||
const emit = defineEmits(['saveEdit'])
|
const emit = defineEmits(['saveEdit'])
|
||||||
const onSave = () =>{
|
const onSave = () =>{
|
||||||
editTempResult({id: props.item.reultId, content: textarea.value}).then( res =>{
|
editTempResult({id: props.item.resultId, content: textarea.value}).then( res =>{
|
||||||
isDialog.value = false
|
isDialog.value = false
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
emit('saveEdit', textarea.value)
|
emit('saveEdit', textarea.value)
|
||||||
|
|
|
@ -67,7 +67,7 @@ import AdjustDialog from './adjust-dialog.vue'
|
||||||
import keywordDialog from './keyword-dialog.vue';
|
import keywordDialog from './keyword-dialog.vue';
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import { tempSave, completion, modelList, removeChildTemp, tempResult } from '@/api/mode/index'
|
import { tempSave, completion, modelList, removeChildTemp, tempResult, editTempResult } from '@/api/mode/index'
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
import { dataSetJson } from '@/utils/comm.js'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ const getTempResult = () => {
|
||||||
rows.forEach(el => {
|
rows.forEach(el => {
|
||||||
if (item.id == el.modelId) {
|
if (item.id == el.modelId) {
|
||||||
item.answer = el.content
|
item.answer = el.content
|
||||||
item.reultId = el.id
|
item.resultId = el.id
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -143,7 +143,6 @@ const getCompletion = async () => {
|
||||||
for (let item of childTempList.value) {
|
for (let item of childTempList.value) {
|
||||||
try {
|
try {
|
||||||
item.loading = true
|
item.loading = true
|
||||||
// params.prompt = `根据${curNode.edustage}${curNode.edusubject},提炼出${item.prompt}`
|
|
||||||
params.prompt = `按照${item.prompt}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
params.prompt = `按照${item.prompt}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
let answer = data.answer
|
||||||
|
@ -175,16 +174,24 @@ const onSaveTemp = (item) => {
|
||||||
const againResult = async (index, item) => {
|
const againResult = async (index, item) => {
|
||||||
try {
|
try {
|
||||||
childTempList.value[index].loading = true
|
childTempList.value[index].loading = true
|
||||||
params.prompt = `根据${curNode.edustage}${curNode.edusubject}课标,提炼出${item.name}`
|
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
||||||
const { data } = await completion(params)
|
const { data } = await completion(params)
|
||||||
let answer = data.answer
|
let answer = data.answer
|
||||||
childTempList.value[index].oldAnswer = answer
|
childTempList.value[index].oldAnswer = answer
|
||||||
childTempList.value[index].answer = getResult(answer);
|
childTempList.value[index].answer = getResult(answer);
|
||||||
|
onEditSave(childTempList.value[index])
|
||||||
} finally {
|
} finally {
|
||||||
childTempList.value[index].loading = false
|
childTempList.value[index].loading = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存 重新研读后的结果
|
||||||
|
const onEditSave = async (item) =>{
|
||||||
|
const { res } = await editTempResult({id: item.resultId, content: item.oldAnswer})
|
||||||
|
ElMessage.success(res)
|
||||||
|
getChildTemplate()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 分析获取课标对话结果
|
// 分析获取课标对话结果
|
||||||
let getResult = (text) => {
|
let getResult = (text) => {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<el-button type="success" @click="openPPTist">打开PPTist</el-button>
|
<el-button type="success" @click="openPPTist">打开PPTist</el-button>
|
||||||
<el-button type="info" @click="onchange('/model/examination')">考试分析</el-button>
|
<el-button type="info" @click="onchange('/model/examination')">考试分析</el-button>
|
||||||
<el-button type="primary" v-menus="dt.menus">测试</el-button>
|
<el-button type="primary" v-menus="dt.menus">测试</el-button>
|
||||||
|
<el-button type="success" @click="onchange('/model/aiKolors')">文生图片</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,6 +56,8 @@ import { createWindow, sessionStore } from '@/utils/tool' // 相关工具
|
||||||
import * as API_smarttalk from '@/api/file' // 文件相关api
|
import * as API_smarttalk from '@/api/file' // 文件相关api
|
||||||
import * as API_entpcourse from '@/api/education/entpcourse' // 相关api
|
import * as API_entpcourse from '@/api/education/entpcourse' // 相关api
|
||||||
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||||
|
import { dataSetJson } from '@/utils/comm' // 数据集id文生图
|
||||||
|
import { sessionStore } from '@/utils/store' // 学科名字文生图
|
||||||
// 组件引入
|
// 组件引入
|
||||||
import ChooseTextbook from '@/components/choose-textbook/index.vue'
|
import ChooseTextbook from '@/components/choose-textbook/index.vue'
|
||||||
import { menusEvent } from '@/plugins/vue3-menus' // 右键菜单
|
import { menusEvent } from '@/plugins/vue3-menus' // 右键菜单
|
||||||
|
@ -157,6 +160,21 @@ const onchange = (path) => {
|
||||||
if (path == '/model/newClassTaskAssign') {
|
if (path == '/model/newClassTaskAssign') {
|
||||||
// 作业管理
|
// 作业管理
|
||||||
router.push({ path, query: { courseObj: JSON.stringify(courseObj) } })
|
router.push({ path, query: { courseObj: JSON.stringify(courseObj) } })
|
||||||
|
} else if (path == '/model/aiKolors') {
|
||||||
|
// ai生图
|
||||||
|
let subjectdata = sessionStore.get('subject.curNode')
|
||||||
|
let datasubject = `课标-${subjectdata.edustage}-${subjectdata.edusubject}`
|
||||||
|
console.log(subjectdata)
|
||||||
|
router.push({
|
||||||
|
path,
|
||||||
|
query: {
|
||||||
|
datasetId: dataSetJson[datasubject],
|
||||||
|
coursetitle: courseObj.coursetitle,
|
||||||
|
levelFirstId: subjectdata.parentid,
|
||||||
|
levelSecondId: subjectdata.id,
|
||||||
|
textbookId: subjectdata.rootid,
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
router.push(path)
|
router.push(path)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue