|
|
@@ -69,8 +69,11 @@
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="ai_content" v-if="currentAnalysis">
|
|
|
- {{ currentAnalysis.json }}
|
|
|
+ <div class="ai_content" v-if="currentAnalysis && currentAnalysis.json">
|
|
|
+ {{ currentAnalysis.json.text }}
|
|
|
+ </div>
|
|
|
+ <div class="ai_echartsData" v-if="currentAnalysis && currentAnalysis.json.keyword">
|
|
|
+ {{ currentAnalysis.json.keyword }}
|
|
|
</div>
|
|
|
<div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
|
|
|
</div>
|
|
|
@@ -111,7 +114,8 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="aiAnalysis" style="margin-top:1rem ;" v-if="processedWorkArray.length > 0 && lookWorkData===null && workDetail.type === '15'">
|
|
|
+ <div class="aiAnalysis" style="margin-top:1rem ;"
|
|
|
+ v-if="processedWorkArray.length > 0 && lookWorkData === null && workDetail.type === '15'">
|
|
|
<div class="ai_header">
|
|
|
<div class="ai_title">
|
|
|
<svg viewBox="0 0 1024 1024" width="200" height="200">
|
|
|
@@ -134,8 +138,13 @@
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="ai_content" v-if="currentAnalysis">
|
|
|
- {{ currentAnalysis.json }}
|
|
|
+ <div class="ai_content" v-if="currentAnalysis && currentAnalysis.json">
|
|
|
+ {{ currentAnalysis.json.text }}
|
|
|
+ </div>
|
|
|
+ <div class="ai_echartsData" v-if="currentAnalysis && currentAnalysis.json.keyword">
|
|
|
+ <div class="title">{{ lang.ssKeyword }}:</div>
|
|
|
+ <span v-for="(item,index) in currentAnalysis.json.keyword" :key="index">{{ item }}</span>
|
|
|
+ <div class="btn" @click="openEchatsDialog()">{{ lang.ssViewKeywordCloud }}</div>
|
|
|
</div>
|
|
|
<div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
|
|
|
</div>
|
|
|
@@ -171,7 +180,8 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="aiAnalysis" style="margin-top:1rem ;" v-if="processedWorkArray.length > 0 && lookWorkData===null && props.showData.toolType === 72">
|
|
|
+ <div class="aiAnalysis" style="margin-top:1rem ;"
|
|
|
+ v-if="processedWorkArray.length > 0 && lookWorkData === null && props.showData.toolType === 72">
|
|
|
<div class="ai_header">
|
|
|
<div class="ai_title">
|
|
|
<svg viewBox="0 0 1024 1024" width="200" height="200">
|
|
|
@@ -194,8 +204,8 @@
|
|
|
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="ai_content" v-if="currentAnalysis">
|
|
|
- {{ currentAnalysis.json }}
|
|
|
+ <div class="ai_content" v-if="currentAnalysis && currentAnalysis.json">
|
|
|
+ {{ currentAnalysis.json.text }}
|
|
|
</div>
|
|
|
<div class="ai_updateTime" v-if="currentAnalysis">{{ lang.ssUpdateTime }}:{{ currentAnalysis.update_at }}
|
|
|
</div>
|
|
|
@@ -278,6 +288,7 @@
|
|
|
</div>
|
|
|
<previewImageTool ref="previewImageToolRef" />
|
|
|
<selectUserDialog ref="selectUserDialogRef" />
|
|
|
+ <echartsDialog ref="echartsDialogRef" />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
@@ -289,7 +300,8 @@ import MarkdownIt from 'markdown-it'
|
|
|
import useImport from '@/hooks/useImport'
|
|
|
import { lang } from '@/main'
|
|
|
import selectUserDialog from './selectUserDialog.vue'
|
|
|
-import { chat_stream } from '@/tools/aiChat'
|
|
|
+import echartsDialog from './echartsDialog.vue'
|
|
|
+import { chat_stream, chat_no_stream } from '@/tools/aiChat'
|
|
|
import axios from '@/services/config'
|
|
|
const props = defineProps<{
|
|
|
visible: number[];
|
|
|
@@ -325,6 +337,8 @@ const workDetail = computed(() => {
|
|
|
const previewImageToolRef = ref<any>(null)
|
|
|
// 选择用户组件
|
|
|
const selectUserDialogRef = ref<any>(null)
|
|
|
+// 词云图组件
|
|
|
+const echartsDialogRef = ref<any>(null)
|
|
|
|
|
|
// ai分析数据
|
|
|
const aiAnalysisData = ref<Array<any>>([])
|
|
|
@@ -579,7 +593,7 @@ const setEchartsArea1 = () => {
|
|
|
let displayValue = value
|
|
|
const maxLength = isAllEnglish ? 30 : 20
|
|
|
const lineLength = isAllEnglish ? 16 : 8
|
|
|
-
|
|
|
+
|
|
|
if (value.length > maxLength) {
|
|
|
displayValue = value.substr(0, maxLength) + '...'
|
|
|
}
|
|
|
@@ -720,6 +734,14 @@ const getAnalysis = () => {
|
|
|
axios.get('https://pbl.cocorobo.cn/api/pbl/select_pptAnalysisByPid?pid=' + params.pid).then(res => {
|
|
|
const data = res[0]
|
|
|
if (data.length) {
|
|
|
+ data.forEach((item: any) => {
|
|
|
+ try {
|
|
|
+ item.json = JSON.parse(item.json)
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ item.json = { text: item.json, echartsData: '' }
|
|
|
+ }
|
|
|
+ })
|
|
|
aiAnalysisData.value = data
|
|
|
}
|
|
|
else {
|
|
|
@@ -888,7 +910,7 @@ const aiAnalysisRefresh45 = () => {
|
|
|
pid: props.workId,
|
|
|
index: props.showData.workIndex,
|
|
|
loading: true,
|
|
|
- json: '',
|
|
|
+ json: { text: '', echartsData: '' },
|
|
|
noEnd: true,
|
|
|
update_at: '',
|
|
|
create_at: '',
|
|
|
@@ -900,7 +922,7 @@ const aiAnalysisRefresh45 = () => {
|
|
|
}).loading = true
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = ''
|
|
|
+ }).json = { text: '', echartsData: '' }
|
|
|
}
|
|
|
|
|
|
chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
|
|
|
@@ -932,6 +954,7 @@ const aiAnalysisRefresh45 = () => {
|
|
|
|
|
|
// 问答题
|
|
|
const aiAnalysisRefresh15 = () => {
|
|
|
+ let flag = 0
|
|
|
const msg = `# CONTEXT #
|
|
|
你是K-12阶段的AI教育课堂分析助手,基于上传的课件、逐字稿,以及当页的学生答题数据(选择题/问答题/智能体对话)进行智能分析。
|
|
|
|
|
|
@@ -965,7 +988,7 @@ const aiAnalysisRefresh15 = () => {
|
|
|
pid: props.workId,
|
|
|
index: props.showData.workIndex,
|
|
|
loading: true,
|
|
|
- json: '',
|
|
|
+ json: { text: '', echartsData: '' },
|
|
|
noEnd: true,
|
|
|
update_at: '',
|
|
|
create_at: '',
|
|
|
@@ -977,14 +1000,19 @@ const aiAnalysisRefresh15 = () => {
|
|
|
}).loading = true
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = ''
|
|
|
+ }).json = { text: '', echartsData: '' }
|
|
|
}
|
|
|
-
|
|
|
+ getWordCloud15().then((res) => {
|
|
|
+ flag += 1
|
|
|
+ if (flag == 2) {
|
|
|
+ saveAnalysis()
|
|
|
+ }
|
|
|
+ })
|
|
|
chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
|
|
|
if (event.type === 'message') {
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = event.data
|
|
|
+ }).json.text = event.data
|
|
|
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
@@ -993,20 +1021,70 @@ const aiAnalysisRefresh15 = () => {
|
|
|
else if (event.type === 'messageEnd') {
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = event.data
|
|
|
+ }).json.text = event.data
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
}).noEnd = false
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
}).update_at = new Date().toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }).replace(/\//g, '-')
|
|
|
- saveAnalysis()
|
|
|
+ flag += 1
|
|
|
+ if (flag == 2) {
|
|
|
+ saveAnalysis()
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
}).catch(err => {
|
|
|
console.log('err', err)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+// 打开词云图弹窗
|
|
|
+const openEchatsDialog = () => {
|
|
|
+ if (echartsDialogRef.value && currentAnalysis.value.json.echartsData) {
|
|
|
+ echartsDialogRef.value.open(lang.ssKeywordCloud,currentAnalysis.value.json.echartsData)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+//问答题获取词云图与关键词
|
|
|
+const getWordCloud15 = () => {
|
|
|
+
|
|
|
+ return new Promise((resolve,) => {
|
|
|
+ const msg = `## 任务 请基于以下文本,提炼出10 - 30个关键词,用于绘制词云图。请给出相应的关键词,以及关键词出现的频次。请确保输出的关键字准确反映该段文本的主要内容和主题。
|
|
|
+## 要求
|
|
|
+1. ** 提取关键词 **:从提供的文本中提取出10 - 30个最具代表性的关键字。关键词应该涵盖该文本的主要概念、重要术语和核心主题。尽量选择多样化的关键词,避免过于集中在某一个主题或概念上。
|
|
|
+ 2. ** 词频统计 **:计算每个关键字在文本中出现的频率。
|
|
|
+ 3. ** 词汇大小 **:根据词频数量,确定每个关键字在词云图中的大小。词频越高,词汇大小数值越大,数值范围1 - 100。
|
|
|
+ 4. ** 输出格式 **:输出结果应包含输出相应的关键词或元话语、对应的词频数量以及词汇大小数值,请以json格式输出,严格按照输出示例输出。
|
|
|
+
|
|
|
+## 文本
|
|
|
+课程数据:
|
|
|
+- 课程名称:${props.courseDetail.title}
|
|
|
+- 课程学科:${props.courseDetail.name}
|
|
|
+当前页面答题数据(问答题):【分析重点】
|
|
|
+- 问答题题目:${props.showData.workDetail.json.answerQ}
|
|
|
+- 回答数据:${JSON.stringify(processedWorkArray.value.map((i) => ({ user: i.name, answer: i.content.answer })))}
|
|
|
+
|
|
|
+## 输出示例
|
|
|
+{"tooltip":{"show":false},"series":[{"type":"wordCloud","sizeRange":[14,38],"rotationRange":[0,0],"keepAspect":false,"shape":"circle","left":"center","top":"center","right":null,"bottom":null,"width":"100%","height":"100%","rotationStep":20,"data":[{"value":"词汇大小,数值范围1-100","name":"词汇","textStyle":{"color":"词汇颜色(16进制)"}},{"value":"词汇大小,数值范围1-100","name":"词汇","textStyle":{"color":"(16进制)"}}]}]}`
|
|
|
+
|
|
|
+
|
|
|
+ chat_no_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang).promise.then((res) => {
|
|
|
+ aiAnalysisData.value.find((item: any) => {
|
|
|
+ return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
+ }).json.echartsData = JSON.parse(res)
|
|
|
+ resolve(1)
|
|
|
+ }).catch(err => {
|
|
|
+ console.log('err', err)
|
|
|
+ resolve(0)
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
// ai应用
|
|
|
const aiAnalysisRefresh72 = async () => {
|
|
|
|
|
|
@@ -1024,7 +1102,7 @@ ${a.content}\n`
|
|
|
|
|
|
|
|
|
|
|
|
-// - 未提交学生:${JSON.stringify(props.showData.unsubmittedStudents.map((item: any) => item.name))}
|
|
|
+ // - 未提交学生:${JSON.stringify(props.showData.unsubmittedStudents.map((item: any) => item.name))}
|
|
|
const msg = `# CONTEXT #
|
|
|
你是K-12阶段的AI教育课堂分析助手,基于上传的课件、逐字稿,以及当页的学生答题数据(选择题/问答题/智能体对话)进行智能分析。
|
|
|
|
|
|
@@ -1053,13 +1131,13 @@ ${a.content}\n`
|
|
|
# EXAMPLES #
|
|
|
样例:
|
|
|
智能体对话显示学生对“模型训练”概念模糊,多次询问“为什么不能直接告诉机器答案”。针对概念混淆学生,补充“人类学习类比”相关解释,巩固“从数据中学习规律”核心认知。`
|
|
|
-console.log("cs",msg)
|
|
|
+ console.log("cs", msg)
|
|
|
if (!currentAnalysis.value) {
|
|
|
aiAnalysisData.value.push({
|
|
|
pid: props.workId,
|
|
|
index: props.showData.workIndex,
|
|
|
loading: true,
|
|
|
- json: '',
|
|
|
+ json: { text: '', echartsData: '' },
|
|
|
noEnd: true,
|
|
|
update_at: '',
|
|
|
create_at: '',
|
|
|
@@ -1071,14 +1149,14 @@ console.log("cs",msg)
|
|
|
}).loading = true
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = ''
|
|
|
+ }).json = { text: '', echartsData: '' }
|
|
|
}
|
|
|
|
|
|
chat_stream(msg, 'a7741704-ba56-40b7-a6b8-62a423ef9376', props.userId, lang.lang, (event) => {
|
|
|
if (event.type === 'message') {
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = event.data
|
|
|
+ }).json.text = event.data
|
|
|
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
@@ -1087,7 +1165,7 @@ console.log("cs",msg)
|
|
|
else if (event.type === 'messageEnd') {
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
- }).json = event.data
|
|
|
+ }).json.text = event.data
|
|
|
aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
}).noEnd = false
|
|
|
@@ -1104,9 +1182,21 @@ console.log("cs",msg)
|
|
|
|
|
|
// 当前分析
|
|
|
const currentAnalysis = computed(() => {
|
|
|
- return aiAnalysisData.value.find((item: any) => {
|
|
|
+ let _result = aiAnalysisData.value.find((item: any) => {
|
|
|
return item.pid === props.workId && item.index === props.showData.workIndex
|
|
|
})
|
|
|
+
|
|
|
+ if (_result?.json?.echartsData) {
|
|
|
+ _result.json.keyword = _result.json.echartsData?.series?.[0]?.data?.map((item: any) => item.name)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if (_result) {
|
|
|
+ return _result
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return null
|
|
|
+ }
|
|
|
})
|
|
|
|
|
|
// 保存分析
|
|
|
@@ -1117,9 +1207,10 @@ const saveAnalysis = () => {
|
|
|
const params = [{
|
|
|
pid: props.workId,
|
|
|
idx: props.showData.workIndex,
|
|
|
- json: currentAnalysis.value.json,
|
|
|
+ json: JSON.stringify(currentAnalysis.value.json),
|
|
|
}]
|
|
|
|
|
|
+ console.log(params)
|
|
|
axios.post('https://pbl.cocorobo.cn/api/pbl/insert_pptAnalysis', params).then(res => {
|
|
|
if (res == 1) {
|
|
|
console.log('保存成功')
|
|
|
@@ -1919,6 +2010,30 @@ onUnmounted(() => {
|
|
|
font-size: 1rem;
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
+ &>.ai_echartsData{
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: .5rem;
|
|
|
+ &>span{
|
|
|
+ padding: .2rem .5rem;
|
|
|
+ border-radius: .25rem;
|
|
|
+ background: #E6F4FF;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: #141517;
|
|
|
+ font-size: .75rem;
|
|
|
+ }
|
|
|
+ &>.title{
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+ &>.btn{
|
|
|
+ font-size: .9rem;
|
|
|
+ text-decoration: underline;
|
|
|
+ color: #F6C82B;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
&>.ai_updateTime {
|
|
|
font-size: .8rem;
|