|
@@ -1,12 +1,25 @@
|
|
|
<template>
|
|
|
- <div class="rightBox">
|
|
|
+ <div class="rightBox" v-loading="loading">
|
|
|
<!-- <div class="title">
|
|
|
<div class="c_info_title">创建表单内容</div>
|
|
|
</div> -->
|
|
|
<div class="edit_top">
|
|
|
+ <div class="e_t_left">
|
|
|
+ <el-button type="primary" size="small" @click="useAiBtn()"
|
|
|
+ >智能生成表单</el-button
|
|
|
+ >
|
|
|
+
|
|
|
+ <el-button :type="viewFile?'primary':''" size="small" v-if="fileData" @click="viewUploadFile()"
|
|
|
+ >预览</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
<div class="edit_btn">
|
|
|
- <span class="edit" :class="{ active: type == 1 }" @click="type = 1">编辑</span>
|
|
|
- <span class="check" :class="{ active: type == 2 }" @click="type = 2">预览</span>
|
|
|
+ <span class="edit" :class="{ active: type == 1 }" @click="type = 1"
|
|
|
+ >编辑</span
|
|
|
+ >
|
|
|
+ <span class="check" :class="{ active: type == 2 }" @click="type = 2"
|
|
|
+ >预览</span
|
|
|
+ >
|
|
|
<!-- <span :class="{ active: type == 3 }" @click="type = 3">回答</span>
|
|
|
<span :class="{ active: type == 4 }" @click="type = 4">统计</span> -->
|
|
|
</div>
|
|
@@ -14,20 +27,29 @@
|
|
|
<!-- <el-button type="primary" size="small" @click="lastSteps">上一步</el-button> -->
|
|
|
<el-button type="primary" size="small" @click="save">保存</el-button>
|
|
|
<el-button type="primary" size="small" @click="publish">发布</el-button>
|
|
|
-
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="e_box">
|
|
|
- <editBox v-if="type == 1" :checkJson="checkJson" @changeJson="changeJson" :title="title" :brief="brief" @updateTitle="updateTitle" @updateBrief="updateBrief"></editBox>
|
|
|
+ <editBox
|
|
|
+ v-if="type == 1"
|
|
|
+ :checkJson="checkJson"
|
|
|
+ @changeJson="changeJson"
|
|
|
+ :title="title"
|
|
|
+ :brief="brief"
|
|
|
+ :fileData="fileData"
|
|
|
+ :viewFile="viewFile"
|
|
|
+ @updateTitle="updateTitle"
|
|
|
+ @updateBrief="updateBrief"
|
|
|
+ ></editBox>
|
|
|
<checkBox v-if="type == 2" :cJson="checkJson" :title="title"></checkBox>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import editBox from './edit/index.vue'
|
|
|
-import checkBox from './check/index.vue'
|
|
|
-
|
|
|
+import editBox from "./edit/index.vue";
|
|
|
+import checkBox from "./check/index.vue";
|
|
|
+import { v4 as uuidv4 } from "uuid";
|
|
|
export default {
|
|
|
components: {
|
|
|
editBox,
|
|
@@ -57,45 +79,251 @@ export default {
|
|
|
return {
|
|
|
type: 1,
|
|
|
checkJson: [],
|
|
|
- }
|
|
|
+ loading: false,
|
|
|
+ userId: this.$route.query.userid,
|
|
|
+ fileData:null,
|
|
|
+ viewFile:false,
|
|
|
+ };
|
|
|
},
|
|
|
watch: {
|
|
|
cJson: {
|
|
|
- handler: function (newVal, oldVal) {
|
|
|
+ handler: function(newVal, oldVal) {
|
|
|
this.checkJson = this.depthCopy(newVal);
|
|
|
},
|
|
|
- deep: true,
|
|
|
- },
|
|
|
+ deep: true
|
|
|
+ }
|
|
|
},
|
|
|
methods: {
|
|
|
- updateTitle(value){
|
|
|
+ updateTitle(value) {
|
|
|
console.log(value);
|
|
|
- this.$emit('update:title', value)
|
|
|
+ this.$emit("update:title", value);
|
|
|
},
|
|
|
- updateBrief(value){
|
|
|
- this.$emit('update:brief', value)
|
|
|
+ updateBrief(value) {
|
|
|
+ this.$emit("update:brief", value);
|
|
|
},
|
|
|
+ updateFileData(value){
|
|
|
+ this.$emit("update:fileData",value)
|
|
|
+ },
|
|
|
lastSteps() {
|
|
|
- this.$emit('update:steps', this.steps - 1)
|
|
|
+ this.$emit("update:steps", this.steps - 1);
|
|
|
},
|
|
|
save() {
|
|
|
- this.$emit("save", 4)
|
|
|
+ this.$emit("save", 4);
|
|
|
},
|
|
|
publish() {
|
|
|
- this.$emit("publish")
|
|
|
+ this.$emit("publish");
|
|
|
},
|
|
|
depthCopy(s) {
|
|
|
- return s ? JSON.parse(JSON.stringify(s)) : ''
|
|
|
+ return s ? JSON.parse(JSON.stringify(s)) : "";
|
|
|
},
|
|
|
changeJson(json) {
|
|
|
console.log(json);
|
|
|
this.$emit("update:cJson", json);
|
|
|
- }
|
|
|
+ },
|
|
|
+ async useAiBtn(type = 0) {
|
|
|
+ if (type == 0 && this.checkJson.length > 0) {
|
|
|
+ return this.$confirm(
|
|
|
+ "使用智能检索功能会覆盖已有表单,确定使用吗?",
|
|
|
+ "提示",
|
|
|
+ {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ this.useAiBtn(1);
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ console.log("不使用");
|
|
|
+ });
|
|
|
+ }
|
|
|
+ let input = document.createElement("input");
|
|
|
+ input.type = "file";
|
|
|
+ // input.accept = ".wav";
|
|
|
+ // input.accept = "audio/*, .txt, .pdf, .xlsx";
|
|
|
+ input.accept = ".docx";
|
|
|
+ input.click();
|
|
|
+ input.onchange = async () => {
|
|
|
+ this.loading = true;
|
|
|
+ let file = input.files[0];
|
|
|
+ if (!/\.(docx)$/i.test(file.name)) {
|
|
|
+ this.loading = false;
|
|
|
+ return this.$message.error("请上传.docx格式的文件");
|
|
|
+ }
|
|
|
+ let uploadData = await this.uploadFile(file);
|
|
|
+ if (uploadData == 1) {
|
|
|
+ this.loading = false;
|
|
|
+ return this.$message.error("文件上传失败");
|
|
|
+ }
|
|
|
+ let _fileData = {
|
|
|
+ fileName: uploadData.Key,
|
|
|
+ url: uploadData.Location,
|
|
|
+ fileId: await this.fileGetFileId(uploadData.Location)
|
|
|
+ };
|
|
|
+ if (_fileData.fileId == 1) {
|
|
|
+ this.loading = false;
|
|
|
+ return this.$message.error("文件获取fileId失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ let testData = await this.getCheckJSon(_fileData.fileId);
|
|
|
+ if (testData == 1) {
|
|
|
+ this.loading = false;
|
|
|
+ return this.$message.error("生成题目失败");
|
|
|
+ }
|
|
|
+ let _titleData = testData.find(i=>(i.formName || i.illustrate))
|
|
|
+ testData = testData.filter(i=>!(i.formName || i.illustrate))
|
|
|
+ this.fileData = _fileData;
|
|
|
+ this.updateFileData(_fileData);
|
|
|
+ if(_titleData){
|
|
|
+ this.updateTitle(_titleData.formName)
|
|
|
+ this.updateBrief(_titleData.illustrate)
|
|
|
+ }
|
|
|
+ this.changeJson(testData)
|
|
|
+ this.viewFile = true;
|
|
|
+ console.log(_fileData);
|
|
|
+ console.log(_titleData)
|
|
|
+ console.log(testData)
|
|
|
+ this.loading = false;
|
|
|
+ // this.uploadWavFileAndGetText(file);
|
|
|
+ };
|
|
|
+ },
|
|
|
+ uploadFile(file) {
|
|
|
+ return new Promise(resolve => {
|
|
|
+ var credentials = {
|
|
|
+ accessKeyId: "AKIATLPEDU37QV5CHLMH",
|
|
|
+ secretAccessKey: "Q2SQw37HfolS7yeaR1Ndpy9Jl4E2YZKUuuy2muZR"
|
|
|
+ }; //秘钥形式的登录上传
|
|
|
+ window.AWS.config.update(credentials);
|
|
|
+ window.AWS.config.region = "cn-northwest-1"; //设置区域
|
|
|
+
|
|
|
+ var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
|
|
|
+ var _this = this;
|
|
|
+ if (file) {
|
|
|
+ var params = {
|
|
|
+ Key:
|
|
|
+ file.name.split(".")[0] +
|
|
|
+ new Date().getTime() +
|
|
|
+ "." +
|
|
|
+ file.name.split(".")[file.name.split(".").length - 1],
|
|
|
+ ContentType: file.type,
|
|
|
+ Body: file,
|
|
|
+ "Access-Control-Allow-Credentials": "*",
|
|
|
+ ACL: "public-read"
|
|
|
+ }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
|
|
|
+ var options = {
|
|
|
+ partSize: 2048 * 1024 * 1024,
|
|
|
+ queueSize: 2,
|
|
|
+ leavePartsOnError: true
|
|
|
+ };
|
|
|
+ bucket
|
|
|
+ .upload(params, options)
|
|
|
+ .on("httpUploadProgress", function(evt) {
|
|
|
+ //这里可以写进度条
|
|
|
+ // _this.progressData.value = parseInt((evt.loaded * 100) / evt.total);
|
|
|
+ // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
|
|
|
+ })
|
|
|
+ .send(function(err, data) {
|
|
|
+ if (err) {
|
|
|
+ resolve(1);
|
|
|
+ } else {
|
|
|
+ resolve(data);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ fileGetFileId(url) {
|
|
|
+ return new Promise(resolve => {
|
|
|
+ this.ajax
|
|
|
+ .put("https://gpt4.cocorobo.cn/upload_file_knowledge", { url: url })
|
|
|
+ .then(res => {
|
|
|
+ let _data = res.data.FunctionResponse;
|
|
|
+ if (_data.result && _data.result.id) {
|
|
|
+ resolve(_data.result.id);
|
|
|
+ } else {
|
|
|
+ resolve(1);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(e => {
|
|
|
+ console.log(e);
|
|
|
+ resolve(1);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getCheckJSon(fileId) {
|
|
|
+ return new Promise(resolve => {
|
|
|
+ let _msg = `Language: Please use the same language as the user requirement, if the user speaks Chinese, the specific text of your answer should also be in Chinese.
|
|
|
+ATTENTION: Use '##' to SPLIT SECTIONS, not '#'. Output format carefully referenced "Format example".
|
|
|
+Instruction: Based on the context, follow "Format example", write content
|
|
|
+
|
|
|
+#Context
|
|
|
+##角色描述
|
|
|
+你是一位行政文员,你需要提取文档中需要收集的信息,梳理出需要收集的信息表格,确定信息收表的题目内容与题目类型。
|
|
|
+##任务描述
|
|
|
+你的任务是阅读上传文档中的内容,提取并输出文档中需要填写的信息,并输出收集信息表单,输出格式为## Format example。你的任务分为三步:
|
|
|
+第一步:提取文档中需要收集的信息内容。信息内容使用文件中的原文,并直接“## Format example”的形式罗列出需要收集的信息清单,不需要二次的分类和总结。通常提取文档中表格中的内容,其他描述性的文字、项目背景、审核意见等内容不应该出现在需要收集的表单内。
|
|
|
+第二步:判断这些需要需要收集的信息以什么题目类型的进行收集,除“年 月 日/日期”等内容使用日期外,其他题目都默认使用文本。
|
|
|
+第三步:输出信息收集表单,你仅仅只需要输出一份## Format example格式的数据,不需要增加任何描述性文字。
|
|
|
+##信息补充
|
|
|
+表单的题目类型包含问答、单选、多选
|
|
|
+文本:需要收集的信息为文本格式的内容,例如“姓名、年级、项目经历、获奖等文本内容”
|
|
|
+单选:需要收集的信息提供了选项,例如文档的表格中出现“性别 男 女” 。或文档中某项收集信息中提供了“是 否”或其他具有选择符号的内容,需要关联上下文判断。
|
|
|
+日期:文档中单独出现需要收集的信息中设计到“年 月 日”“日期”“时间”等,与日期相关的内容。如果文档中出现多个日期相关的题目,只保留一个日期题目类型即可。
|
|
|
+标题:文档中的总标题
|
|
|
+说明:文档中的总标题下的说明性文字
|
|
|
+
|
|
|
+##题目格式
|
|
|
+问答题:{"ttype":1,"type":3,"json":{"title":"标题","type":1,"answer":""}}
|
|
|
+单选题:{"ttype":1,"type":1,"json":{"title":"标题","type":1,"array":[{"option":"选项1","img":""}, {"option":"选项2","img":""}],"answer":""}}
|
|
|
+多选题:{"ttype":1,"type":1,"json":{"title":"标题","type":2,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}}
|
|
|
+
|
|
|
+标题和说明:{"formName":"标题","illustrate":"说明"}
|
|
|
+
|
|
|
+## Format example
|
|
|
+[{"formName":"标题","illustrate":"说明"},{"ttype":1,"type":3,"json":{"title":"标题","type":1,"answer":""}},{"ttype":1,"type":1,"json":{"title":"标题","type":1,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}},{"ttype":1,"type":1,"json":{"title":"标题","type":2,"array":[{"option":"选项1","img":""},{"option":"选项2","img":""}],"answer":""}}]
|
|
|
+`;
|
|
|
+// 日期:{"ttype":1,"type":8,"json":{"title":"标题","detail":""}}
|
|
|
+
|
|
|
+ let params = {
|
|
|
+ assistant_id: "6063369f-289a-11ef-8bf4-12e77c4cb76b",
|
|
|
+ message: [{ type: "text", text: _msg }],
|
|
|
+ session_name: uuidv4(),
|
|
|
+ userId: this.userId,
|
|
|
+ file_ids: [fileId],
|
|
|
+ model: "gpt-4o-2024-08-06"
|
|
|
+ };
|
|
|
+ this.ajax
|
|
|
+ // .post("https://gpt4.cocorobo.cn/chat", params)
|
|
|
+ // .post("https://claude3.cocorobo.cn/chat", params)
|
|
|
+ .post("https://gpt4.cocorobo.cn/ai_agent_park_chat", params)
|
|
|
+ .then(res => {
|
|
|
+ let _data = res.data.FunctionResponse.message;
|
|
|
+ _data = _data.replaceAll("```json", "").replaceAll("```", "");
|
|
|
+ // const match = _data.match(/\[\s*\{[\s\S]*?\}\s*\]/);
|
|
|
+ // console.log("👇")
|
|
|
+ // console.log(match[0])
|
|
|
+ let _result = JSON.parse(_data) || [];
|
|
|
+ if (_result.length > 0) {
|
|
|
+ resolve(_result);
|
|
|
+ } else {
|
|
|
+ resolve(1);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .catch(e => {
|
|
|
+ console.log(e);
|
|
|
+ resolve(1);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ viewUploadFile(){
|
|
|
+ this.viewFile = !this.viewFile;
|
|
|
+ }
|
|
|
},
|
|
|
mounted() {
|
|
|
this.checkJson = this.depthCopy(this.cJson);
|
|
|
- },
|
|
|
-}
|
|
|
+ }
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
@@ -111,11 +339,11 @@ export default {
|
|
|
}
|
|
|
|
|
|
.c_info_title::before {
|
|
|
- content: '';
|
|
|
+ content: "";
|
|
|
display: block;
|
|
|
width: 3px;
|
|
|
height: 20px;
|
|
|
- background: #0061FF;
|
|
|
+ background: #0061ff;
|
|
|
border-radius: 3px;
|
|
|
margin: 0 5px 0 0;
|
|
|
}
|
|
@@ -131,7 +359,7 @@ export default {
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
-.rightBox>.title {
|
|
|
+.rightBox > .title {
|
|
|
background: #fff;
|
|
|
width: 100%;
|
|
|
padding: 0 20px 0;
|
|
@@ -147,17 +375,17 @@ export default {
|
|
|
position: relative;
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn {
|
|
|
+.edit_top > .edit_btn {
|
|
|
display: flex;
|
|
|
height: 40px;
|
|
|
align-items: center;
|
|
|
- border: 1px solid #E5E5E5;
|
|
|
+ border: 1px solid #e5e5e5;
|
|
|
box-sizing: border-box;
|
|
|
padding: 4px;
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>span {
|
|
|
+.edit_top > .edit_btn > span {
|
|
|
cursor: pointer;
|
|
|
padding-bottom: 5px;
|
|
|
display: block;
|
|
@@ -172,46 +400,44 @@ export default {
|
|
|
border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>.active {
|
|
|
+.edit_top > .edit_btn > .active {
|
|
|
color: #3e88f4;
|
|
|
/* border-bottom: 2px solid #2f80f3; */
|
|
|
background: rgb(224, 234, 251);
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>span+span {
|
|
|
+.edit_top > .edit_btn > span + span {
|
|
|
margin-left: 10px;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-.edit_top>.edit_btn>span::before {
|
|
|
- content: '';
|
|
|
+.edit_top > .edit_btn > span::before {
|
|
|
+ content: "";
|
|
|
display: block;
|
|
|
background-size: 100% 100%;
|
|
|
margin-right: 8px;
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>.check::before {
|
|
|
+.edit_top > .edit_btn > .check::before {
|
|
|
width: 15px;
|
|
|
height: 15px;
|
|
|
background-image: url(../../../../../assets/icon/test/add_check_icon.png);
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>.edit::before {
|
|
|
+.edit_top > .edit_btn > .edit::before {
|
|
|
width: 15px;
|
|
|
height: 16px;
|
|
|
background-image: url(../../../../../assets/icon/test/add_edit_icon.png);
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>.active.check::before {
|
|
|
+.edit_top > .edit_btn > .active.check::before {
|
|
|
background-image: url(../../../../../assets/icon/test/add_check_icon_active.png);
|
|
|
}
|
|
|
|
|
|
-.edit_top>.edit_btn>.active.edit::before {
|
|
|
+.edit_top > .edit_btn > .active.edit::before {
|
|
|
background-image: url(../../../../../assets/icon/test/add_edit_icon_active.png);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-.edit_top>.op_btn {
|
|
|
+.edit_top > .op_btn {
|
|
|
position: absolute;
|
|
|
right: 30px;
|
|
|
}
|
|
@@ -227,4 +453,10 @@ export default {
|
|
|
box-sizing: border-box;
|
|
|
margin: 20px auto 0;
|
|
|
border-radius: 5px;
|
|
|
-}</style>
|
|
|
+}
|
|
|
+
|
|
|
+.e_t_left {
|
|
|
+ position: absolute;
|
|
|
+ left: 30px;
|
|
|
+}
|
|
|
+</style>
|