edit 模板
This commit is contained in:
parent
93fa916084
commit
013669dd35
|
@ -29,6 +29,20 @@
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
|
<div class="file-list">
|
||||||
|
<el-dropdown @command="changeFile">
|
||||||
|
<span class="el-dropdown-link">
|
||||||
|
{{ curFile.fileName }}
|
||||||
|
<i class="iconfont icon-xiangxia"></i>
|
||||||
|
</span>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item v-for="item in fileList" :command="item" :key="item.id">{{ item.fileName
|
||||||
|
}}</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
<div class="input-box flex">
|
<div class="input-box flex">
|
||||||
<el-input v-model="textarea" @keyup.enter="send" :disabled="loaded"/>
|
<el-input v-model="textarea" @keyup.enter="send" :disabled="loaded"/>
|
||||||
<div class="ipt-icon" @click="send">
|
<div class="ipt-icon" @click="send">
|
||||||
|
@ -40,13 +54,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted, watch } from 'vue'
|
import { ref, reactive, onMounted, onUnmounted, watch } from 'vue'
|
||||||
import { completion } from '@/api/mode/index'
|
import { completion, docList } from '@/api/mode/index'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
import { dataSetJson } from '@/utils/comm.js'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
|
|
||||||
|
const userInfo = useUserStore().user
|
||||||
|
|
||||||
const textarea = ref('')
|
const textarea = ref('')
|
||||||
|
|
||||||
const isDialog = defineModel()
|
const isDialog = defineModel()
|
||||||
|
@ -106,7 +122,6 @@ const getCompletion = async (val) => {
|
||||||
|
|
||||||
const saveAdjust = (item) =>{
|
const saveAdjust = (item) =>{
|
||||||
isDialog.value = false
|
isDialog.value = false
|
||||||
ElMessage.success('操作成功')
|
|
||||||
emitter.emit('onSaveAdjust', item.msg)
|
emitter.emit('onSaveAdjust', item.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +139,27 @@ watch(() => props.type, (newVal) => {
|
||||||
|
|
||||||
}, { immediate: false })
|
}, { immediate: false })
|
||||||
|
|
||||||
|
const curFile = reactive({})
|
||||||
|
const dataset_id = ref('')
|
||||||
|
const fileList = ref([])
|
||||||
|
const getList = () =>{
|
||||||
|
docList({
|
||||||
|
userId: userInfo.userId,
|
||||||
|
dataset_id: dataset_id.value
|
||||||
|
}).then( res =>{
|
||||||
|
fileList.value = res.rows
|
||||||
|
Object.assign(curFile, fileList.value[0])
|
||||||
|
params.document_ids = fileList.value[0].docId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
emitter.on('changeCurFile', (item) =>{
|
||||||
|
changeFile(item)
|
||||||
|
})
|
||||||
|
const changeFile = (val) =>{
|
||||||
|
Object.assign(curFile, val);
|
||||||
|
params.document_ids = val.docId
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let data = sessionStore.get('subject.curNode')
|
let data = sessionStore.get('subject.curNode')
|
||||||
|
@ -131,6 +167,15 @@ onMounted(() => {
|
||||||
Object.assign(curNode, data);
|
Object.assign(curNode, data);
|
||||||
let jsonKey = `${modeType.value}-${data.edustage}-${data.edusubject}`
|
let jsonKey = `${modeType.value}-${data.edustage}-${data.edusubject}`
|
||||||
params.dataset_id = dataSetJson[jsonKey]
|
params.dataset_id = dataSetJson[jsonKey]
|
||||||
|
if(props.type == 3){
|
||||||
|
getList()
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
// 解绑
|
||||||
|
onUnmounted(() => {
|
||||||
|
emitter.off('changeCurFile');
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -267,4 +312,9 @@ onMounted(() => {
|
||||||
transform: scale(0.01);
|
transform: scale(0.01);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-list{
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<el-dialog v-model="mode" :show-close="false" width="600" append-to-body destroy-on-close>
|
<el-dialog v-model="mode" :show-close="false" width="600" append-to-body destroy-on-close>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="custom-header flex">
|
<div class="custom-header flex">
|
||||||
<span>{{ item.ex3 == '1' ? '请输入新的模板名称' : isAdd ? '添加提示词' : '编辑提示词' }}</span>
|
<span>{{ item.ex3 == '1' ? '请输入新的模板名称' : item.isAdd ? '添加提示词' : '编辑提示词' }}</span>
|
||||||
<i class="iconfont icon-guanbi" @click="mode = false"></i>
|
<i class="iconfont icon-guanbi" @click="mode = false"></i>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -40,10 +40,6 @@ const props = defineProps({
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1
|
default: 1
|
||||||
},
|
},
|
||||||
isAdd: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
item: { // 子模板
|
item: { // 子模板
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {
|
default: () => {
|
||||||
|
@ -58,21 +54,27 @@ const form = reactive({
|
||||||
prompt: '',
|
prompt: '',
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(() => props.isAdd, (newVal) => {
|
|
||||||
if (!newVal) {
|
watch(() => mode.value, (newVal) => {
|
||||||
form.name = props.item?.name
|
if(newVal){
|
||||||
form.prompt = props.item?.prompt
|
if (props.item.isAdd) {
|
||||||
|
form.name = ''
|
||||||
|
form.prompt = ''
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
form.name = props.item?.name
|
||||||
|
form.prompt = props.item?.prompt
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
},{ deep: true})
|
||||||
}, { immediate: false })
|
|
||||||
|
|
||||||
|
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const saveAdd = async () => {
|
const saveAdd = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
if (props.item.ex3 == '1') {
|
if (props.item.ex3 == '1') {
|
||||||
|
|
||||||
if (props.isAdd) {
|
if (props.item.isAdd) {
|
||||||
try {
|
try {
|
||||||
// 系统预设模板 copy一份
|
// 系统预设模板 copy一份
|
||||||
const { msg } = await addKeyWords({ name: form.name, id: props.item.id })
|
const { msg } = await addKeyWords({ name: form.name, id: props.item.id })
|
||||||
|
@ -88,7 +90,7 @@ const saveAdd = async () => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (props.isAdd) {
|
if (props.item.isAdd) {
|
||||||
onAddChildTemp(props.item.id)
|
onAddChildTemp(props.item.id)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="isDialog" :show-close="false" width="900" destroy-on-close>
|
<el-dialog v-model="isDialog" :show-close="false" width="900" append-to-body destroy-on-close>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="custom-header flex">
|
<div class="custom-header flex">
|
||||||
<span>选择{{ title }}</span>
|
<span>选择{{ title }}</span>
|
||||||
|
@ -7,25 +7,54 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="dialog-content">
|
<div class="dialog-content">
|
||||||
<div class="flex">
|
|
||||||
<el-radio-group v-model="radio" @change="changeRadio">
|
|
||||||
<el-radio :value="item.value" v-for="item in radioList">{{ item.label }}</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</div>
|
|
||||||
<div class="content-list">
|
<div class="content-list">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(item, index) in list" :class="activeIndex == index ? 'li-active' : ''" @click="clickItem(index)">
|
<li v-for="(item, index) in fileList" :class="activeIndex == index ? 'li-active' : ''"
|
||||||
<el-image class="img" :src="item.url" />
|
@click="clickItem(index, item)">
|
||||||
<span>{{ item.name }}</span>
|
<el-image class="img" :src="url" />
|
||||||
|
<el-button type="primary" class="prev-btn" @click.stop="onPrevItem(item)">预览</el-button>
|
||||||
|
<el-text truncated>{{ item.fileName }}</el-text>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="isDialog = false">取消</el-button>
|
<el-upload class="upload-demo" :action="uploadFileUrl" :limit="1" :show-file-list="false" :headers="headers"
|
||||||
<el-button type="primary" @click="isDialog = false">
|
:on-success="onSuccess">
|
||||||
确定
|
<el-button type="primary">上传</el-button>
|
||||||
|
</el-upload>
|
||||||
|
<div>
|
||||||
|
<el-button @click="isDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="isDialog = false">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog v-model="prevVisible" fullscreen :show-close="false" class="prev-dialog">
|
||||||
|
<template #header>
|
||||||
|
<div class="custom-header flex">
|
||||||
|
<span>预览</span>
|
||||||
|
<i class="iconfont icon-guanbi" @click="prevVisible = false"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div style="height: calc(100vh - 120px);">
|
||||||
|
<template v-if="getFileSuffix(prevItem.fileUrl) == 'pdf'">
|
||||||
|
<iframe :src="prevItem.fileUrl"
|
||||||
|
frameborder="0" width="100%" height="100%"></iframe>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-image :src="prevItem.fileUrl" style="height:100%"/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<div></div>
|
||||||
|
<el-button type="primary" @click="prevVisible = false">
|
||||||
|
关闭
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -33,11 +62,24 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed, onMounted, reactive } from 'vue'
|
||||||
|
import { completion, addDoc, docList } from '@/api/mode/index.js'
|
||||||
|
import { getToken } from "@/utils/auth";
|
||||||
|
import { sessionStore } from '@/utils/store'
|
||||||
|
import { dataSetJson } from '@/utils/comm.js'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import { getFileSuffix } from '@/utils/ruoyi.js'
|
||||||
|
import emitter from '@/utils/mitt';
|
||||||
|
|
||||||
|
const userInfo = useUserStore().user
|
||||||
|
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload");
|
||||||
|
const headers = ref({ Authorization: "Bearer " + getToken() });
|
||||||
|
|
||||||
const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F11044b08-04c1-41a0-a453-1fd20b58a614%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1732953359&t=7ab1d1b3a903db85b1149914407aea35'
|
const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F11044b08-04c1-41a0-a453-1fd20b58a614%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1732953359&t=7ab1d1b3a903db85b1149914407aea35'
|
||||||
|
|
||||||
const isDialog = defineModel()
|
const isDialog = defineModel()
|
||||||
|
const prevVisible = ref(false)
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modeType: {
|
modeType: {
|
||||||
|
@ -52,14 +94,13 @@ const title = computed(() => {
|
||||||
if (props.modeType == 3) return '考试';
|
if (props.modeType == 3) return '考试';
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const radio = ref(1)
|
const radio = ref(1)
|
||||||
const radioList = ref([
|
const radioList = ref([
|
||||||
{ label: '浏览研读', value: 1 },
|
{ label: '浏览研读', value: 1 },
|
||||||
// { label: '跨学科研读', value: 2 },
|
{ label: '跨学科研读', value: 2 },
|
||||||
// { label: '跨学段研读', value: 3 },
|
{ label: '跨学段研读', value: 3 },
|
||||||
// { label: '课标修订研读', value: 4 },
|
{ label: '课标修订研读', value: 4 },
|
||||||
// { label: '自由研读', value: 5 },
|
{ label: '自由研读', value: 5 },
|
||||||
])
|
])
|
||||||
const list = ref([
|
const list = ref([
|
||||||
{
|
{
|
||||||
|
@ -76,15 +117,70 @@ const changeRadio = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const activeIndex = ref(0)
|
||||||
|
|
||||||
const activeIndex = ref(-1)
|
const dataset_id = ref('')
|
||||||
|
|
||||||
const clickItem = (index) => {
|
// 上传成功
|
||||||
activeIndex.value = index
|
const onSuccess = async (response) => {
|
||||||
|
let data = {
|
||||||
|
url: response.url,
|
||||||
|
dataset_id: dataset_id.value
|
||||||
|
}
|
||||||
|
const res = await completion(data)
|
||||||
|
|
||||||
|
if (res.data.code != 200) return
|
||||||
|
let docData = {
|
||||||
|
fileUrl: response.url,
|
||||||
|
fileId: response.file.id,
|
||||||
|
fileName: response.file.fileName,
|
||||||
|
filesize: response.file.fileSize,
|
||||||
|
datasetId: dataset_id.value,
|
||||||
|
docId: res.data.document_id,
|
||||||
|
edustage: curNode.edustage,
|
||||||
|
edusubject: curNode.edusubject
|
||||||
|
}
|
||||||
|
const { msg } = await addDoc(docData)
|
||||||
|
ElMessage.success(msg)
|
||||||
|
getList()
|
||||||
|
|
||||||
|
}
|
||||||
|
const curNode = reactive({})
|
||||||
|
|
||||||
|
const fileList = ref([])
|
||||||
|
const curFile = reactive({})
|
||||||
|
const getList = () => {
|
||||||
|
docList({
|
||||||
|
userId: userInfo.userId,
|
||||||
|
dataset_id: dataset_id.value
|
||||||
|
}).then(res => {
|
||||||
|
fileList.value = [...res.rows]
|
||||||
|
Object.assign(curFile, fileList.value[0])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
const clickItem = (index, item) => {
|
||||||
|
activeIndex.value = index
|
||||||
|
Object.assign(curFile, item)
|
||||||
|
emitter.emit('changeCurFile', item)
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevItem = reactive({})
|
||||||
|
const onPrevItem = (item) => {
|
||||||
|
Object.assign(prevItem, item)
|
||||||
|
prevVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
let data = sessionStore.get('subject.curNode')
|
||||||
|
Object.assign(curNode, data);
|
||||||
|
// 暂时写死"考试-" 目前只有考试分析才会弹出来
|
||||||
|
let jsonKey = `考试-${curNode.edustage}-${curNode.edusubject}`
|
||||||
|
dataset_id.value = dataSetJson[jsonKey]
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.custom-header {
|
.custom-header {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -98,13 +194,16 @@ const clickItem = (index) => {
|
||||||
|
|
||||||
.dialog-content {
|
.dialog-content {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
|
||||||
.content-list {
|
.content-list {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
width: 130px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
@ -114,9 +213,11 @@ const clickItem = (index) => {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.img {
|
.img {
|
||||||
width: 100px;
|
width: 100%;
|
||||||
height: 130px;
|
height: 130px;
|
||||||
border: solid #ccc 1px;
|
border: solid #ccc 1px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -125,6 +226,10 @@ const clickItem = (index) => {
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #E0EAFF;
|
background: #E0EAFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover .prev-btn {
|
||||||
|
transform: translate(-50%, -40px)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.li-active {
|
.li-active {
|
||||||
|
@ -134,4 +239,20 @@ const clickItem = (index) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prev-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%) translateY(-110px);
|
||||||
|
/* 按钮初始位置在容器外 */
|
||||||
|
transition: transform 0.3s ease-in-out;
|
||||||
|
/* 设置过渡效果 */
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -2,12 +2,13 @@
|
||||||
<div class="container-left-page flex">
|
<div class="container-left-page flex">
|
||||||
<div class="container-left-header flex">
|
<div class="container-left-header flex">
|
||||||
<el-button link @click="onClick">
|
<el-button link @click="onClick">
|
||||||
{{ curNode.edustage }}{{ curNode.edusubject }}{{ type == 1 ? '课标研读' : '教材分析' }}<i
|
{{ curNode.edustage }}{{ curNode.edusubject }}{{ type == 1 ? '课标研读' : type == 2 ? '教材分析' : '考试分析' }}<i
|
||||||
class="iconfont icon-xiangxia"></i>
|
class="iconfont icon-xiangxia"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-left-pdf">
|
<div class="container-left-pdf">
|
||||||
<PDF :url="pdfUrl" :showCatalog="false" v-if="pdfUrl" />
|
<PDF :url="pdfUrl" :showCatalog="false" v-if="pdfUrl" />
|
||||||
|
<el-empty v-else description="暂无数据" />
|
||||||
</div>
|
</div>
|
||||||
<!--弹窗-->
|
<!--弹窗-->
|
||||||
<LeftDialog v-model="showDialog" :modeType="type" />
|
<LeftDialog v-model="showDialog" :modeType="type" />
|
||||||
|
@ -24,7 +25,7 @@ const props = defineProps(['curNode', 'type'])
|
||||||
|
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
const onClick = () => {
|
const onClick = () => {
|
||||||
if (props.type == 1) return
|
if (props.type != 3) return
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +38,9 @@ onMounted(async () => {
|
||||||
if(props.type == 1){
|
if(props.type == 1){
|
||||||
fileurl = `${data.edustage}-${data.edusubject}-课标.txt`
|
fileurl = `${data.edustage}-${data.edusubject}-课标.txt`
|
||||||
}
|
}
|
||||||
|
if(fileurl == '') return
|
||||||
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt', '.pdf')
|
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt', '.pdf')
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
<i class="iconfont icon-shenglvehao"></i></el-button>
|
<i class="iconfont icon-shenglvehao"></i></el-button>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-button type="primary" link @click="editKeyWord(item)">编辑</el-button>
|
<el-button type="primary" link @click="editKeyWord(item, false)">编辑</el-button>
|
||||||
<el-button type="primary" link @click="removeItem(item, true)">移除</el-button>
|
<el-button type="primary" link @click="removeItem(item, true)">移除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
<!--AI 对话调整-->
|
<!--AI 对话调整-->
|
||||||
<AdjustDialog v-model="isAdjust" :type="type" :item="editItem" />
|
<AdjustDialog v-model="isAdjust" :type="type" :item="editItem" />
|
||||||
<!--添加、编辑提示词-->
|
<!--添加、编辑提示词-->
|
||||||
<keywordDialog v-model="isWordDialog" :isAdd="isAdd" :item="editItem" />
|
<keywordDialog v-model="isWordDialog" :item="editItem" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -105,21 +105,22 @@ const props = defineProps(['curNode', 'type'])
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const isWordDialog = ref(false)
|
const isWordDialog = ref(false)
|
||||||
const isAdd = ref(false)
|
|
||||||
const editItem = reactive({})
|
const editItem = reactive({})
|
||||||
const onAdd = () => {
|
const onAdd = () => {
|
||||||
isAdd.value = true
|
|
||||||
Object.assign(editItem, curTemplate)
|
Object.assign(editItem, curTemplate)
|
||||||
|
editItem.isAdd = true
|
||||||
isWordDialog.value = true
|
isWordDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const editKeyWord = (item, val) => {
|
const editKeyWord = (item, val) => {
|
||||||
/**
|
/**
|
||||||
* isAdd: 字模板中的移除 为编辑 头部删除 添加提示词为新增
|
* isAdd: 子模板中的移除 为编辑false 头部删除 添加提示词为新增 true
|
||||||
*/
|
*/
|
||||||
isAdd.value = val
|
|
||||||
Object.assign(editItem, item)
|
Object.assign(editItem, item)
|
||||||
|
editItem.isAdd = val
|
||||||
isWordDialog.value = true
|
isWordDialog.value = true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************模板相关**********************/
|
/*******************模板相关**********************/
|
||||||
|
@ -361,8 +362,8 @@ emitter.on('onSaveAdjust', (item) => {
|
||||||
|
|
||||||
// 保存 重新研读后的结果
|
// 保存 重新研读后的结果
|
||||||
const onEditSave = async (item) => {
|
const onEditSave = async (item) => {
|
||||||
const { res } = await editTempResult({ id: item.resultId, content: item.answer })
|
const { msg } = await editTempResult({ id: item.resultId, content: item.answer })
|
||||||
ElMessage.success(res)
|
ElMessage.success(msg)
|
||||||
getChildTemplate()
|
getChildTemplate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
readonly
|
readonly
|
||||||
resize="none"
|
resize="none"
|
||||||
style="width: 100%;"
|
style="width: 100%;"
|
||||||
input-style="border:none;outline: none;box-shadow:none;color:000;fontSize:15px"
|
input-style="border:none;outline: none;box-shadow:none;color:000;fontSize:14px"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -71,9 +71,6 @@ watch([() => props.text, () => props.delay], resetAndType);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.typing-effect {
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
:deep(.el-textarea__inner:hover){
|
:deep(.el-textarea__inner:hover){
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,306 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog v-model="isDialog" :show-close="false" width="800" destroy-on-close>
|
|
||||||
<template #header>
|
|
||||||
<div class="custom-header flex">
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
<i class="iconfont icon-guanbi" @click="isDialog = false"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="dialog-content">
|
|
||||||
<el-scrollbar height="400px">
|
|
||||||
<div class="chart-con flex">
|
|
||||||
<template v-for="item in msgList">
|
|
||||||
<div class="flex-end flex" v-if="item.type == 'user'">
|
|
||||||
<div class="chart-item user">{{ item.msg }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-start flex" v-else>
|
|
||||||
<div class="flex" v-loading="!item.msg">
|
|
||||||
<div class="chart-item robot">{{ item.msg }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-end replace-item">
|
|
||||||
<span @click="saveAdjust(item)"><i class="iconfont icon-tihuan"></i>替换分析结果</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="loaded" class="chart-loading">
|
|
||||||
<div></div>
|
|
||||||
<div></div>
|
|
||||||
<div></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</el-scrollbar>
|
|
||||||
<div class="file-list">
|
|
||||||
<el-dropdown @command="changeFile">
|
|
||||||
<span class="el-dropdown-link">
|
|
||||||
{{ curFile.fileName }}
|
|
||||||
<i class="iconfont icon-xiangxia"></i>
|
|
||||||
</span>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item v-for="item in fileList" :command="item" :key="item.id">{{ item.fileName
|
|
||||||
}}</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
</div>
|
|
||||||
<div class="input-box flex">
|
|
||||||
<el-input v-model="textarea" @keyup.enter="send" :disabled="loaded"/>
|
|
||||||
<div class="ipt-icon" @click="send">
|
|
||||||
<i class="iconfont icon-fasong"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
|
||||||
import { conversation, completion, docList } from '@/api/mode/index'
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import emitter from '@/utils/mitt';
|
|
||||||
|
|
||||||
const userInfo = useUserStore().user
|
|
||||||
const textarea = ref('')
|
|
||||||
|
|
||||||
const isDialog = defineModel()
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
item: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return { name: '11' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modeType: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const emit = defineEmits(['saveEdit'])
|
|
||||||
|
|
||||||
const loaded = ref(false)
|
|
||||||
|
|
||||||
const msgList = ref([])
|
|
||||||
|
|
||||||
const send = () =>{
|
|
||||||
if(loaded.value) return
|
|
||||||
msgList.value.push({
|
|
||||||
type: 'user',
|
|
||||||
msg: textarea.value
|
|
||||||
})
|
|
||||||
loaded.value = true
|
|
||||||
getConversation(textarea.value)
|
|
||||||
textarea.value = ''
|
|
||||||
}
|
|
||||||
const curNode = reactive({})
|
|
||||||
const params = reactive(
|
|
||||||
{
|
|
||||||
prompt: '',
|
|
||||||
dataset_id: '',
|
|
||||||
document_ids: '',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
// 获取会话ID
|
|
||||||
const getConversation = (val) => {
|
|
||||||
|
|
||||||
getCompletion(val)
|
|
||||||
}
|
|
||||||
// 大模型对话
|
|
||||||
const getCompletion = async (val) => {
|
|
||||||
try {
|
|
||||||
|
|
||||||
params.prompt = `按照${val}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
|
||||||
const { data } = await completion(params)
|
|
||||||
let answer = data.answer
|
|
||||||
msgList.value.push({
|
|
||||||
type: 'robot',
|
|
||||||
msg: answer,
|
|
||||||
})
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
loaded.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveAdjust = (item) =>{
|
|
||||||
emit('saveAdjust', item.msg)
|
|
||||||
isDialog.value = false
|
|
||||||
ElMessage.success('操作成功')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const curFile = reactive({})
|
|
||||||
const dataset_id = ref('')
|
|
||||||
const fileList = ref([])
|
|
||||||
const getList = () =>{
|
|
||||||
docList({
|
|
||||||
userId: userInfo.userId,
|
|
||||||
dataset_id: dataset_id.value
|
|
||||||
}).then( res =>{
|
|
||||||
fileList.value = res.rows
|
|
||||||
Object.assign(curFile, fileList.value[0])
|
|
||||||
params.document_ids = fileList.value[0].docId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
emitter.on('curFile', (item) =>{
|
|
||||||
changeFile(item)
|
|
||||||
})
|
|
||||||
const changeFile = (val) =>{
|
|
||||||
Object.assign(curFile, val);
|
|
||||||
params.document_ids = val.docId
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
let data = sessionStore.get('subject.curNode')
|
|
||||||
Object.assign(curNode, data);
|
|
||||||
let text = props.modeType == 1 ||props.modeType == 2 ? '课标' : '考试'
|
|
||||||
|
|
||||||
let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
|
|
||||||
params.dataset_id = dataSetJson[jsonKey]
|
|
||||||
dataset_id.value = dataSetJson[jsonKey]
|
|
||||||
getList()
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.custom-header {
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.icon-guanbi {
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-content {
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
|
|
||||||
.chart-con {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
.flex-end{
|
|
||||||
width: 100%;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
.flex-start{
|
|
||||||
width: 100%;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
}
|
|
||||||
.chart-item {
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 5px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user {
|
|
||||||
background: #F2F2F2;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.robot {
|
|
||||||
background: #409EFF;
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
.replace-item{
|
|
||||||
font-size: 12px;
|
|
||||||
color: #409EFF;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-box {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.ipt-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0 5px;
|
|
||||||
.icon-fasong {
|
|
||||||
font-size: 26px;
|
|
||||||
color: #409EFF;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.chart-loading,
|
|
||||||
.chart-loading>div {
|
|
||||||
position: relative;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading {
|
|
||||||
display: block;
|
|
||||||
font-size: 0;
|
|
||||||
color: #66b1ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading.la-dark {
|
|
||||||
color: #66b1ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading>div {
|
|
||||||
display: inline-block;
|
|
||||||
float: none;
|
|
||||||
background-color: currentColor;
|
|
||||||
border: 0 solid currentColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading {
|
|
||||||
width: 54px;
|
|
||||||
height: 18px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading>div:nth-child(1) {
|
|
||||||
animation-delay: -200ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading>div:nth-child(2) {
|
|
||||||
animation-delay: -100ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading>div:nth-child(3) {
|
|
||||||
animation-delay: 0ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chart-loading>div {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 100%;
|
|
||||||
margin-right: 4px;
|
|
||||||
animation: ball-pulse 1s ease infinite;
|
|
||||||
}
|
|
||||||
@keyframes ball-pulse {
|
|
||||||
|
|
||||||
0%,
|
|
||||||
60%,
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
30% {
|
|
||||||
opacity: 0.1;
|
|
||||||
transform: scale(0.01);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-list{
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,268 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog v-model="isDialog" :show-close="false" width="900" append-to-body destroy-on-close>
|
|
||||||
<template #header>
|
|
||||||
<div class="custom-header flex">
|
|
||||||
<span>选择{{ title }}</span>
|
|
||||||
<i class="iconfont icon-guanbi" @click="isDialog = false"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="dialog-content">
|
|
||||||
<div class="flex dialog-top">
|
|
||||||
<!-- <el-radio-group v-model="radio" @change="changeRadio">
|
|
||||||
<el-radio :value="item.value" v-for="item in radioList">{{ item.label }}</el-radio>
|
|
||||||
</el-radio-group> -->
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="content-list">
|
|
||||||
<ul>
|
|
||||||
<li v-for="(item, index) in fileList" :class="activeIndex == index ? 'li-active' : ''"
|
|
||||||
@click="clickItem(index, item)">
|
|
||||||
<el-image class="img" :src="url" />
|
|
||||||
<el-button type="primary" class="prev-btn" @click.stop="onPrevItem(item)">预览</el-button>
|
|
||||||
<el-text truncated>{{ item.fileName }}</el-text>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-upload class="upload-demo" :action="uploadFileUrl" :limit="1" :show-file-list="false" :headers="headers"
|
|
||||||
:on-success="onSuccess">
|
|
||||||
<el-button type="primary">上传</el-button>
|
|
||||||
</el-upload>
|
|
||||||
<div>
|
|
||||||
<el-button @click="isDialog = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="isDialog = false">
|
|
||||||
确定
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
<el-dialog v-model="prevVisible" fullscreen :show-close="false" class="prev-dialog">
|
|
||||||
<template #header>
|
|
||||||
<div class="custom-header flex">
|
|
||||||
<span>预览</span>
|
|
||||||
<i class="iconfont icon-guanbi" @click="prevVisible = false"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div style="height: calc(100vh - 120px);">
|
|
||||||
<template v-if="getFileSuffix(prevItem.fileUrl) == 'pdf'">
|
|
||||||
<iframe :src="prevItem.fileUrl"
|
|
||||||
frameborder="0" width="100%" height="100%"></iframe>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-image :src="prevItem.fileUrl" style="height:100%"/>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<div></div>
|
|
||||||
<el-button type="primary" @click="prevVisible = false">
|
|
||||||
关闭
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, onMounted, reactive } from 'vue'
|
|
||||||
import { completion, addDoc, docList } from '@/api/mode/index.js'
|
|
||||||
import { getToken } from "@/utils/auth";
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import { getFileSuffix } from '@/utils/ruoyi.js'
|
|
||||||
import emitter from '@/utils/mitt';
|
|
||||||
|
|
||||||
const userInfo = useUserStore().user
|
|
||||||
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload");
|
|
||||||
const headers = ref({ Authorization: "Bearer " + getToken() });
|
|
||||||
|
|
||||||
const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F11044b08-04c1-41a0-a453-1fd20b58a614%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1732953359&t=7ab1d1b3a903db85b1149914407aea35'
|
|
||||||
|
|
||||||
const isDialog = defineModel()
|
|
||||||
const prevVisible = ref(false)
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
modeType: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const title = computed(() => {
|
|
||||||
if (props.modeType == 1) return '课标';
|
|
||||||
if (props.modeType == 2) return '教材';
|
|
||||||
if (props.modeType == 3) return '考试';
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const radio = ref(1)
|
|
||||||
const radioList = ref([
|
|
||||||
{ label: '浏览研读', value: 1 },
|
|
||||||
{ label: '跨学科研读', value: 2 },
|
|
||||||
{ label: '跨学段研读', value: 3 },
|
|
||||||
{ label: '课标修订研读', value: 4 },
|
|
||||||
{ label: '自由研读', value: 5 },
|
|
||||||
])
|
|
||||||
const list = ref([
|
|
||||||
{
|
|
||||||
name: '高中语文课程标准',
|
|
||||||
url
|
|
||||||
}
|
|
||||||
])
|
|
||||||
const changeRadio = () => {
|
|
||||||
list.value = []
|
|
||||||
for (let i = 0; i < Math.floor(Math.random() * 5) + 1; i++) {
|
|
||||||
list.value.push({
|
|
||||||
name: '高中语文课程标准',
|
|
||||||
url
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const activeIndex = ref(0)
|
|
||||||
|
|
||||||
const dataset_id = ref('')
|
|
||||||
|
|
||||||
// 上传成功
|
|
||||||
const onSuccess = async (response) => {
|
|
||||||
let data = {
|
|
||||||
url: response.url,
|
|
||||||
dataset_id: dataset_id.value
|
|
||||||
}
|
|
||||||
const res = await completion(data)
|
|
||||||
|
|
||||||
if (res.data.code != 200) return
|
|
||||||
let docData = {
|
|
||||||
fileUrl: response.url,
|
|
||||||
fileId: response.file.id,
|
|
||||||
fileName: response.file.fileName,
|
|
||||||
filesize: response.file.fileSize,
|
|
||||||
datasetId: dataset_id.value,
|
|
||||||
docId: res.data.document_id,
|
|
||||||
edustage: curNode.edustage,
|
|
||||||
edusubject: curNode.edusubject
|
|
||||||
}
|
|
||||||
const { msg } = await addDoc(docData)
|
|
||||||
ElMessage.success(msg)
|
|
||||||
getList()
|
|
||||||
|
|
||||||
}
|
|
||||||
const curNode = reactive({})
|
|
||||||
|
|
||||||
const fileList = ref([])
|
|
||||||
const curFile = reactive({})
|
|
||||||
const getList = () => {
|
|
||||||
docList({
|
|
||||||
userId: userInfo.userId,
|
|
||||||
dataset_id: dataset_id.value
|
|
||||||
}).then(res => {
|
|
||||||
fileList.value = [...res.rows]
|
|
||||||
Object.assign(curFile, fileList.value[0])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clickItem = (index, item) => {
|
|
||||||
activeIndex.value = index
|
|
||||||
Object.assign(curFile, item)
|
|
||||||
emitter.emit('curFile', item)
|
|
||||||
}
|
|
||||||
|
|
||||||
const prevItem = reactive({})
|
|
||||||
const onPrevItem = (item) => {
|
|
||||||
Object.assign(prevItem, item)
|
|
||||||
prevVisible.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
let data = sessionStore.get('subject.curNode')
|
|
||||||
Object.assign(curNode, data);
|
|
||||||
|
|
||||||
let jsonKey = `考试-${curNode.edustage}-${curNode.edusubject}`
|
|
||||||
dataset_id.value = dataSetJson[jsonKey]
|
|
||||||
getList()
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.custom-header {
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.icon-guanbi {
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-content {
|
|
||||||
padding-top: 10px;
|
|
||||||
|
|
||||||
.dialog-top {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-list {
|
|
||||||
padding-top: 10px;
|
|
||||||
|
|
||||||
ul {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
li {
|
|
||||||
width: 130px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 13px;
|
|
||||||
padding: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.img {
|
|
||||||
width: 100%;
|
|
||||||
height: 130px;
|
|
||||||
border: solid #ccc 1px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #E0EAFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .prev-btn {
|
|
||||||
transform: translate(-50%, -50%)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.li-active {
|
|
||||||
background: #E0EAFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prev-btn {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%) translateY(-110px);
|
|
||||||
/* 按钮初始位置在容器外 */
|
|
||||||
transition: transform 0.3s ease-in-out;
|
|
||||||
/* 设置过渡效果 */
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,78 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog v-model="isDialog" :show-close="false" width="900">
|
|
||||||
<template #header>
|
|
||||||
<div class="custom-header flex">
|
|
||||||
<span>{{ item.name }}</span>
|
|
||||||
<i class="iconfont icon-guanbi" @click="isDialog = false"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="dialog-content">
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-input v-model="textarea" :autosize="{ minRows: 5, maxRows: 15 }" type="textarea" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button @click="isDialog = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="onSave">
|
|
||||||
确定
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, watch} from 'vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { editTempResult } from '@/api/mode/index.js'
|
|
||||||
|
|
||||||
const textarea = ref('')
|
|
||||||
|
|
||||||
const isDialog = defineModel()
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
item: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return { name: '11' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(() => props.item.answer, (newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
textarea.value = newVal
|
|
||||||
}
|
|
||||||
},{ deep: true })
|
|
||||||
|
|
||||||
const emit = defineEmits(['saveEdit'])
|
|
||||||
const onSave = () =>{
|
|
||||||
editTempResult({id: props.item.resultId, content: textarea.value}).then( res =>{
|
|
||||||
isDialog.value = false
|
|
||||||
ElMessage.success('操作成功')
|
|
||||||
emit('saveEdit', textarea.value)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.custom-header {
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.icon-guanbi {
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-content {
|
|
||||||
padding-top: 10px;
|
|
||||||
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,143 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="container-header flex">
|
|
||||||
<div class="header-left flex">
|
|
||||||
<el-button link @click="showDialog = true">
|
|
||||||
{{ curNode.edustage}}{{ curNode.edusubject }}考试分析<i class="iconfont icon-xiangxia"></i>
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="header-right flex">
|
|
||||||
<el-dropdown @command="changeTemplate" :hide-on-click="false">
|
|
||||||
<span class="el-dropdown-link">
|
|
||||||
{{ curTemplate.name }}
|
|
||||||
<i class="iconfont icon-xiangxia"></i>
|
|
||||||
</span>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<el-dropdown-item v-for="item in templateList" :command="item" :key="item.id">{{ item.name
|
|
||||||
}}</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
<div>
|
|
||||||
<el-button type="primary" link @click="onAdd">
|
|
||||||
<el-icon>
|
|
||||||
<Plus />
|
|
||||||
</el-icon>
|
|
||||||
添加提示词
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" link>保存模板</el-button>
|
|
||||||
<el-button type="primary" @click="aiRead">一键研读</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!--添加提示词-->
|
|
||||||
<keywordDialog v-model="wordDialog" :modeType="type" :isAdd="wordDialog" :item="curTemplate" />
|
|
||||||
<Dialog v-model="showDialog" :modeType="type" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, onMounted, onUnmounted, watch } from 'vue'
|
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
|
||||||
import { ElMessageBox } from 'element-plus'
|
|
||||||
import { modelList } from '@/api/mode/index'
|
|
||||||
import Dialog from './dialog.vue'
|
|
||||||
import keywordDialog from './keyword-dialog.vue'
|
|
||||||
import emitter from '@/utils/mitt';
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
|
|
||||||
|
|
||||||
const wordDialog = ref(false)
|
|
||||||
const props = defineProps({
|
|
||||||
type: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const emit = defineEmits(['changeTemp', 'onRead'])
|
|
||||||
|
|
||||||
const showDialog = ref(false)
|
|
||||||
|
|
||||||
const aiRead = () => {
|
|
||||||
emit('onRead')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 当前模板名称
|
|
||||||
const curTemplate = reactive({ name: '', id: '' })
|
|
||||||
// 模板列表
|
|
||||||
const templateList = ref([])
|
|
||||||
// 获取模板列表
|
|
||||||
const getTemplateList = () => {
|
|
||||||
modelList({ model: props.type, type: 1, pageNum: 1, pageSize: 10000 }).then(res => {
|
|
||||||
templateList.value = res.rows
|
|
||||||
Object.assign(curTemplate, res.rows[0]);
|
|
||||||
emit('changeTemp', res.rows[0].id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 模板切换
|
|
||||||
const changeTemplate = (val) => {
|
|
||||||
|
|
||||||
ElMessageBox.confirm(
|
|
||||||
'切换模板将清除当前研读结果?',
|
|
||||||
'提示',
|
|
||||||
{
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
Object.assign(curTemplate, val);
|
|
||||||
emit('changeTemp', curTemplate.id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
emitter.on('onGetMain', () =>{
|
|
||||||
getTemplateList()
|
|
||||||
})
|
|
||||||
|
|
||||||
const onAdd = () => {
|
|
||||||
wordDialog.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
emitter.off('onGetMain')
|
|
||||||
})
|
|
||||||
const curNode = reactive({})
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
let data = sessionStore.get('subject.curNode')
|
|
||||||
Object.assign(curNode, data);
|
|
||||||
getTemplateList()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.container-header {
|
|
||||||
height: 45px;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 5px 5px 0 0;
|
|
||||||
box-shadow: 0px 0px 20px 0px rgba(99, 99, 99, 0.06);
|
|
||||||
|
|
||||||
.header-left {
|
|
||||||
width: 50%;
|
|
||||||
align-items: center;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-right {
|
|
||||||
width: 50%;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-xiangxia {
|
|
||||||
margin-left: 5px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,161 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog v-model="mode" :show-close="false" width="600" destroy-on-close>
|
|
||||||
<template #header>
|
|
||||||
<div class="custom-header flex">
|
|
||||||
<span>{{ item.ex3 == '1' ? '请输入新的模板名称' : isAdd ? '添加提示词' : '编辑提示词' }}</span>
|
|
||||||
<i class="iconfont icon-guanbi" @click="mode = false"></i>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="dialog-content" v-loading="loading">
|
|
||||||
<p class="small-tip" v-if="item && item.ex3 == '1'">*当前模板为系统预设,不支持直接操作。需要复制一份为自己的然后再操作</p>
|
|
||||||
<el-form :model="form" label-width="auto">
|
|
||||||
<el-form-item label="名称">
|
|
||||||
<el-input v-model="form.name" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="提示词" v-if="item.ex3 == '1' ? false : true">
|
|
||||||
<el-input v-model="form.prompt" type="textarea" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button @click="mode = false">取消</el-button>
|
|
||||||
<el-button type="primary" @click="saveAdd">
|
|
||||||
确定
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, watch } from 'vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import emitter from '@/utils/mitt';
|
|
||||||
import { addKeyWords, addChildTemp, editChildTemp } from '@/api/mode/index'
|
|
||||||
|
|
||||||
const mode = defineModel()
|
|
||||||
const props = defineProps({
|
|
||||||
modeType: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
isAdd: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
item: { // 子模板
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return { ex3: '' }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tempId: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const form = reactive({
|
|
||||||
name: '',
|
|
||||||
prompt: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(() => props.isAdd, (newVal) => {
|
|
||||||
if (!newVal) {
|
|
||||||
form.name = props.item?.name
|
|
||||||
form.prompt = props.item?.prompt
|
|
||||||
}
|
|
||||||
|
|
||||||
}, { immediate: false })
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const saveAdd = async () => {
|
|
||||||
|
|
||||||
loading.value = true
|
|
||||||
if (props.item.ex3 == '1') {
|
|
||||||
if (props.isAdd) {
|
|
||||||
try {
|
|
||||||
// 系统预设模板 copy一份
|
|
||||||
const { msg } = await addKeyWords({ name: form.name, id: props.item.id })
|
|
||||||
emitter.emit('onGetChild')
|
|
||||||
ElMessage.success(msg)
|
|
||||||
mode.value = false
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
onAddChildTemp(props.item.parentId)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if (props.isAdd) {
|
|
||||||
onAddChildTemp(props.item.id)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
let data = JSON.parse(JSON.stringify(props.item))
|
|
||||||
data.name = form.name;
|
|
||||||
data.prompt = form.prompt
|
|
||||||
const { msg } = await editChildTemp(data)
|
|
||||||
emitter.emit('onGetChild')
|
|
||||||
ElMessage.success(msg)
|
|
||||||
mode.value = false
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加子模板
|
|
||||||
const onAddChildTemp = async (parentId) => {
|
|
||||||
// 添加子模板
|
|
||||||
let obj = {
|
|
||||||
name: form.name,
|
|
||||||
type: 2, // 子模板 固定值为2
|
|
||||||
sortNum: 1,
|
|
||||||
parentId,
|
|
||||||
lmType: 1,
|
|
||||||
model: props.modeType,
|
|
||||||
prompt: form.prompt,
|
|
||||||
ex1: props.item.ex1, //学段
|
|
||||||
ex2: props.item.ex2, // 学科
|
|
||||||
ex3: '', //是否系统预设 这里默认空
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
var { msg } = await addChildTemp(obj)
|
|
||||||
emitter.emit('onGetChild')
|
|
||||||
ElMessage.success(msg)
|
|
||||||
mode.value = false
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.custom-header {
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.icon-guanbi {
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.small-tip {
|
|
||||||
text-align: left;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
color: #F56C6C;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,32 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="container-pdf">
|
|
||||||
<PDF :url="pdfUrl" :showCatalog="false" v-if="pdfUrl" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted, nextTick } from 'vue';
|
|
||||||
import PDF from '@/components/PdfJs/index.vue'
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
|
|
||||||
const pdfUrl = ref('')
|
|
||||||
|
|
||||||
onMounted(async () =>{
|
|
||||||
await nextTick()
|
|
||||||
|
|
||||||
let data = sessionStore.get('subject.curBook')
|
|
||||||
let fileurl = data.fileurl
|
|
||||||
|
|
||||||
if(fileurl == ''){
|
|
||||||
fileurl = `${data.edustage}-${data.edusubject}-课标.txt`
|
|
||||||
}
|
|
||||||
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt', '.pdf')
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.container-pdf{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,513 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="read-container">
|
|
||||||
|
|
||||||
<el-scrollbar height="100%">
|
|
||||||
<div class="template-list">
|
|
||||||
<el-row v-for="(item, index) in childTempList">
|
|
||||||
<el-col :span="24">
|
|
||||||
<div class="template-item" v-loading="item.loading">
|
|
||||||
<div class="item-header">
|
|
||||||
<div>
|
|
||||||
<span class="blue">#</span>{{ item.name }}
|
|
||||||
</div>
|
|
||||||
<el-popover placement="bottom-end" trigger="hover" popper-class="template-custom-popover">
|
|
||||||
<template #reference>
|
|
||||||
<el-button link type="primary">
|
|
||||||
<i class="iconfont icon-shenglvehao"></i></el-button>
|
|
||||||
</template>
|
|
||||||
<template #default>
|
|
||||||
<el-button type="primary" link @click="editKeyWord(item)">编辑</el-button>
|
|
||||||
<el-button type="primary" link @click="removeItem(item)">移除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popover>
|
|
||||||
</div>
|
|
||||||
<div class="item-text" >
|
|
||||||
{{ item.prompt }}
|
|
||||||
</div>
|
|
||||||
<div class="item-text text-answer" v-if="item.answer">
|
|
||||||
<div class="item-icon">
|
|
||||||
<i class="iconfont icon-ai"></i>
|
|
||||||
</div>
|
|
||||||
<div class="item-answer" v-html="item.answer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="ai-btn" v-if="item.answer">
|
|
||||||
<el-button type="primary" link @click="againResult(index, item)">
|
|
||||||
<i class="iconfont icon-ai1"></i>
|
|
||||||
重新研读
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" link @click="onAdjust(index, item)">
|
|
||||||
<i class="iconfont icon-duihua"></i>
|
|
||||||
AI对话调整
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" link @click="onEdit(index, item)">
|
|
||||||
<i class="iconfont icon-bianji1"></i>
|
|
||||||
手动编辑结果
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-empty v-if="!childTempList.length" description="暂无模板数据" />
|
|
||||||
</div>
|
|
||||||
</el-scrollbar>
|
|
||||||
<!--编辑结果-->
|
|
||||||
<EditDialog v-model="isEdit" :item="editItem" @saveEdit="saveEdit" />
|
|
||||||
<!--AI 对话调整-->
|
|
||||||
<AdjustDialog v-model="isAdjust" :modeType="modeType" :item="editItem" @saveAdjust="saveAdjust" />
|
|
||||||
<!--编辑提示词-->
|
|
||||||
<keywordDialog v-model="isEditKeyWord" :isAdd="isAdd" :item="keywordItem" :tempId="tempId" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive, onMounted, watch, onUnmounted } from 'vue';
|
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
||||||
import EditDialog from './edit-dialog.vue'
|
|
||||||
import AdjustDialog from './adjust-dialog.vue'
|
|
||||||
import keywordDialog from './keyword-dialog.vue';
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import { tempSave, completion, modelList, removeChildTemp, tempResult, editTempResult } from '@/api/mode/index'
|
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
|
||||||
import emitter from '@/utils/mitt';
|
|
||||||
|
|
||||||
const userStore = useUserStore()
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
tempId: {
|
|
||||||
type: [String, Number],
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
modeType: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
emitter.on('onGetChild', () =>{
|
|
||||||
getChildTemplate()
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取子模板
|
|
||||||
const tempLoading = ref(false)
|
|
||||||
const childTempList = ref([])
|
|
||||||
const getChildTemplate = () => {
|
|
||||||
|
|
||||||
tempLoading.value = true
|
|
||||||
modelList({ model: props.modeType, type: 2, parentId: props.tempId }).then(res => {
|
|
||||||
childTempList.value = res.rows
|
|
||||||
getTempResult()
|
|
||||||
}).finally(() => {
|
|
||||||
tempLoading.value = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 查询模板结果
|
|
||||||
const getTempResult = () => {
|
|
||||||
tempResult({ mainModelId: props.tempId }).then(res => {
|
|
||||||
let rows = res.rows
|
|
||||||
childTempList.value.forEach(item => {
|
|
||||||
rows.forEach(el => {
|
|
||||||
if (item.id == el.modelId) {
|
|
||||||
item.answer = el.content
|
|
||||||
item.resultId = el.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const isEdit = ref(false)
|
|
||||||
watch(() => props.tempId, (newVal) => {
|
|
||||||
if (newVal) {
|
|
||||||
// isEdit.value = true
|
|
||||||
getChildTemplate()
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// 获取会话ID
|
|
||||||
const params = reactive(
|
|
||||||
{
|
|
||||||
prompt: '',
|
|
||||||
dataset_id: ''
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const curNode = reactive({})
|
|
||||||
const getConversation = () => {
|
|
||||||
|
|
||||||
getCompletion()
|
|
||||||
}
|
|
||||||
// 大模型对话
|
|
||||||
const getCompletion = async () => {
|
|
||||||
for (let item of childTempList.value) {
|
|
||||||
try {
|
|
||||||
item.loading = true
|
|
||||||
params.prompt = `按照${item.prompt}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
|
||||||
const { data } = await completion(params)
|
|
||||||
let answer = data.answer
|
|
||||||
item.oldAnswer = answer
|
|
||||||
item.answer = getResult(answer);
|
|
||||||
onSaveTemp(item)
|
|
||||||
} finally {
|
|
||||||
item.loading = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存模板
|
|
||||||
const onSaveTemp = (item) => {
|
|
||||||
const data = {
|
|
||||||
mainModelId: props.tempId,
|
|
||||||
modelId: item.id,
|
|
||||||
examDocld: '',
|
|
||||||
content: item.oldAnswer
|
|
||||||
}
|
|
||||||
tempSave(data).then(res => {
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 重新研读
|
|
||||||
const againResult = async (index, item) => {
|
|
||||||
try {
|
|
||||||
childTempList.value[index].loading = true
|
|
||||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}考试 对${curNode.itemtitle}进行教学分析`
|
|
||||||
const { data } = await completion(params)
|
|
||||||
let answer = data.answer
|
|
||||||
childTempList.value[index].oldAnswer = answer
|
|
||||||
childTempList.value[index].answer = getResult(answer);
|
|
||||||
onEditSave(childTempList.value[index])
|
|
||||||
} finally {
|
|
||||||
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) => {
|
|
||||||
text = text.replace(/^\n\n(.*?)\n\n$/s, '<div>$1</div>');
|
|
||||||
text = text.replace(/^\n(.*?)\n$/s, '<p>$1</p>');
|
|
||||||
text = text.replace(/\*\*(.*?)\*\*/g, "<div class='text-tit'>$1</div>");
|
|
||||||
text = text.replace(/(\d+\..*?)\n/g, "<div class='text-num'>$1</div>\n");
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑
|
|
||||||
const curIndex = ref(-1)
|
|
||||||
const editItem = reactive({})
|
|
||||||
const onEdit = (index, item) => {
|
|
||||||
curIndex.value = index
|
|
||||||
Object.assign(editItem, item)
|
|
||||||
isEdit.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存编辑
|
|
||||||
const saveEdit = (data) => {
|
|
||||||
// childTempList.value[curIndex.value].oldAnswer = data
|
|
||||||
// let answer = getResult(data);
|
|
||||||
// childTempList.value[curIndex.value].answer = answer
|
|
||||||
getChildTemplate()
|
|
||||||
}
|
|
||||||
|
|
||||||
const isAdjust = ref(false)
|
|
||||||
const onAdjust = (index, item) => {
|
|
||||||
curIndex.value = index
|
|
||||||
Object.assign(editItem, item)
|
|
||||||
isAdjust.value = true
|
|
||||||
}
|
|
||||||
const saveAdjust = (item) => {
|
|
||||||
childTempList.value[curIndex.value].oldAnswer = item
|
|
||||||
let answer = getResult(item);
|
|
||||||
childTempList.value[curIndex.value].answer = answer
|
|
||||||
}
|
|
||||||
|
|
||||||
// 编辑提示词
|
|
||||||
const keywordItem = reactive({})
|
|
||||||
const isEditKeyWord = ref(false)
|
|
||||||
const isAdd = ref(true)
|
|
||||||
const editKeyWord = (item) => {
|
|
||||||
console.log(item)
|
|
||||||
isAdd.value = false
|
|
||||||
isEditKeyWord.value = true
|
|
||||||
Object.assign(keywordItem, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 移除子模板
|
|
||||||
const removeItem = async (item) => {
|
|
||||||
if (item.ex3 != '1') {
|
|
||||||
ElMessageBox.confirm(
|
|
||||||
'确认是否移除?',
|
|
||||||
'提示',
|
|
||||||
{
|
|
||||||
confirmButtonText: '确定',
|
|
||||||
cancelButtonText: '取消',
|
|
||||||
type: 'warning',
|
|
||||||
}
|
|
||||||
).then(() => {
|
|
||||||
console.log(item)
|
|
||||||
removeChildTemp(item.id).then(res => {
|
|
||||||
ElMessage.success('操作成功')
|
|
||||||
getChildTemplate()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
isAdd.value = false
|
|
||||||
Object.assign(keywordItem, item)
|
|
||||||
isEditKeyWord.value = true
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// const { msg } = await removeChildTemp(item.id)
|
|
||||||
// ElMessage.success(msg)
|
|
||||||
// getChildTemplate()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
let data = sessionStore.get('subject.curNode')
|
|
||||||
Object.assign(curNode, data);
|
|
||||||
let text = props.modeType == 1 || props.modeType == 2? '课标' : '考试'
|
|
||||||
let jsonKey = `${text}-${data.edustage}-${data.edusubject}`
|
|
||||||
params.dataset_id = dataSetJson[jsonKey]
|
|
||||||
|
|
||||||
})
|
|
||||||
// 解绑
|
|
||||||
onUnmounted(() => {
|
|
||||||
emitter.off('onGetChild')
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
getConversation
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.read-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 100%;
|
|
||||||
padding: 15px 0;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.el-scrollbar {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-dropdown-link {
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
.el-icon--right {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.read-header {
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.add-btn {
|
|
||||||
font-size: 13px;
|
|
||||||
|
|
||||||
.icon-jiahao {
|
|
||||||
margin-right: 3px;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-con {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.template-list {
|
|
||||||
|
|
||||||
.template-item {
|
|
||||||
background: #fff;
|
|
||||||
padding: 10px;
|
|
||||||
margin-top: 10px;
|
|
||||||
border-radius: 5px;
|
|
||||||
|
|
||||||
.item-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #000;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.blue {
|
|
||||||
font-size: 22px;
|
|
||||||
color: #409eff;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-text {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
text-align: left;
|
|
||||||
color: #606266;
|
|
||||||
|
|
||||||
.item-icon {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
text-align: center;
|
|
||||||
background: #F6F6F6;
|
|
||||||
border-radius: 50%;
|
|
||||||
margin-right: 10px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-answer {
|
|
||||||
flex-direction: column;
|
|
||||||
padding-top: 5px;
|
|
||||||
|
|
||||||
:deep(.text-tit) {
|
|
||||||
font-weight: bold;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.text-num) {
|
|
||||||
padding-left: 2em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-answer {
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ai-btn {
|
|
||||||
margin-top: 10px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-button) {
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-ai1 {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.template-item-result {
|
|
||||||
background: #DDEAFD !important;
|
|
||||||
|
|
||||||
.result-item-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
text-align: left;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #3D3D3D;
|
|
||||||
|
|
||||||
.icon-xiaoxi {
|
|
||||||
color: #5881D5;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 20px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.result-icon-btn {
|
|
||||||
justify-content: space-between;
|
|
||||||
font-size: 13px;
|
|
||||||
margin-top: 5px;
|
|
||||||
|
|
||||||
span {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-right: 10px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #cfe0fa
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
margin-right: 3px;
|
|
||||||
color: #3498fc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.line {
|
|
||||||
height: 1px;
|
|
||||||
background: #D8D8D8;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.other-msg {
|
|
||||||
font-size: 13px;
|
|
||||||
|
|
||||||
.other-user {
|
|
||||||
align-items: center;
|
|
||||||
color: #BA4B0F;
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
.icon-touxiang {
|
|
||||||
color: #BA4B0F;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 16px;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.other-text {
|
|
||||||
color: #191919;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-shenglvehao {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.el-popover) {
|
|
||||||
min-width: 50px;
|
|
||||||
width: 50px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pl-25 {
|
|
||||||
padding-left: 25px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style>
|
|
||||||
.template-custom-popover {
|
|
||||||
width: 110px !important;
|
|
||||||
min-width: 110px !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,52 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page-template flex">
|
<TemplateStudy :type="3"/>
|
||||||
<!--头部-->
|
|
||||||
<Header :type="type" @changeTemp="changeTemp" @onRead="onRead"/>
|
|
||||||
<el-row :gutter="20" class="tempalte-main">
|
|
||||||
<el-col :span="12">
|
|
||||||
<!--左侧pdf-->
|
|
||||||
<Pdf />
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<!--右侧模板研读-->
|
|
||||||
<Result ref="resultRef" :modeType="type" :tempId="tempId"/>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import TemplateStudy from '@/components/template-study/index.vue'
|
||||||
import Header from './container/header.vue'
|
|
||||||
import Pdf from './container/pdf.vue'
|
|
||||||
import Result from './container/result.vue'
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
type: {
|
|
||||||
type: Number,
|
|
||||||
default: 3
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const resultRef = ref()
|
|
||||||
const tempId = ref('')
|
|
||||||
const changeTemp = (id) =>{
|
|
||||||
tempId.value = id
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRead = () =>{
|
|
||||||
resultRef.value.getConversation()
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.page-template {
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
.tempalte-main {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue