123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532 |
- <template>
- <div class="outcomeCon">
- <div @click="showItem" style="height: 50px;display: flex; justify-content: space-between;align-items: center;">
- <div class="oc_title">
- <van-icon v-if="!show" name="arrow" />
- <van-icon v-else name="arrow-down" />
- <span class="tit">{{ data.jsonData ? data.jsonData.name : '' }}</span>
- </div>
- <van-popover placement="bottom-end" v-model="abuShow" v-if="[0].includes(status)">
- <div class="abu">
- <!-- <div class="abuBtn">
- <img src="../../assets/images/classObserve/addTel.png" alt="" />
- <span>重命名</span>
- </div> -->
- <div class="abuBtn" @click.stop="del()">
- <img src="../../../assets/images/classObserve/del.png" alt="" />
- <span>删除</span>
- </div>
- </div>
- <template #reference>
- <img @click.stop="abuShowItem" src="../../../assets/images/classObserve/colD.png" alt="" />
- </template>
- </van-popover>
- <div class="oc_status" v-if="[1,2,3].includes(status)">
- <div v-if="[1].includes(status)">
- <img src="../../../assets/images//classObserve/generate.svg">
- <span>优化中...</span>
- </div>
- <div v-if="[2].includes(status)">
- <span style="color:#e60012;">生成失败</span>
- </div>
- <div v-if="[3].includes(status)">
- <img src="../../../assets/images//classObserve/success.svg">
- <span style="color:#17C469">生成成功</span>
- </div>
- </div>
- </div>
- <div v-show="show">
- <div class="brief">
- {{ data.jsonData ? data.jsonData.result : '' }}
- </div>
- <div class="content">
- <!-- {{ data.jsonData }} -->
- <mdView :text="data.jsonData ? data.jsonData.content : ''" />
- </div>
- <div class="outcomeBtn" v-if="[0,2,3].includes(status)">
- <div @click.stop="down()" :class="[historyIndex==0?'ob_no':'']">
- <img src="../../../assets/images/classObserve/restore.png" alt="" style="transform:rotateY(180deg);"/><span>撤销</span>
- </div>
- <div @click.stop="up()" :class="[(historyIndex>=history.length-1)?'ob_no':'']">
- <img src="../../../assets/images/classObserve/restore.png" alt="" /><span>恢复</span>
- </div>
- <div @click.stop="optimize()">
- <img src="../../../assets/images/classObserve/optimize.png" alt="" /><span>优化</span>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script>
- import mdView from './mdView.vue'
- import { v4 as uuidv4 } from "uuid";
- import {chatRequest,updateObsRequest} from '@/api/classObserve'
- export default {
- props: {
- data: {
- type: Object,
- default: () => {}
- },
- analysisList:{
- type:Array,
- default:()=>[]
- },
- bmData:{
- type:Object,
- default:()=>{}
- },
- fileId:{
- type:String,
- default:""
- }
- },
- components: {
- mdView
- },
- data() {
- return {
- show: false,
- abuShow: false,
- historyIndex:0,
- history:[],
- userId:this.$store.state.user.id,
- status:0,// 0:正常 1:优化中 2:优化成功 3:优化失败
- }
- },
- methods: {
- showItem() {
- if(![0,2,3].includes(this.status))return this.$toast("正在优化中...")
- this.show = !this.show
- this.status = 0;
- },
- abuShowItem() {
- this.abuShow = true
- },
- up() {
- if(this.historyIndex < this.history.length - 1){
- this.historyIndex++;
- this.data.jsonData = JSON.parse(JSON.stringify(this.history[this.historyIndex]))
- this.data.json_data = JSON.stringify(this.data.jsonData)
- this.saveData(this.data).then(_=>{
- console.log('保存成功')
- })
- }
- },
- down() {
- if(this.historyIndex>0){
- this.historyIndex--;
- this.data.jsonData = JSON.parse(JSON.stringify(this.history[this.historyIndex]))
- this.data.json_data = JSON.stringify(this.data.jsonData)
- this.saveData(this.data).then(_=>{
- console.log('保存成功')
- })
- }
- },
- optimize() {
- this.show = false;
- this.status = 1;
- let assistant = this.analysisList.find(
- (i) => i.title == this.data.jsonData.name
- );
- if (!assistant.value) {
- this.status = 2;
- return this.$toast.fail("未找到对应的AI助手");
- }
- let _msg = `使用文件检索的方式完整的去分析文件内容,并请完全按照要求输出。`
- if(['st1','st2','st3'].includes(assistant.value))return this.optimize2(assistant.value)
- if(assistant.value=='6b4a9650-48be-11ef-936b-12e77c4cb76b'){
- _msg = `使用文件检索的方式完整的去分析文件内容,并基于以下的课堂基本内容,使用cpote课程设计模型改编一堂同主题的课程。
- 课堂名称:${this.bmData.courseName} 搜课年级:${this.bmData.grade} 授课科目:${this.bmData.subject}`
-
- }
- let params = {
- assistant_id: assistant?assistant.value:null,
- message:_msg,
- session_name: uuidv4(),
- userId: this.userId,
- file_ids: this.fileId?[this.fileId]:'',
- model: "gpt-4o-2024-08-06",
- };
- chatRequest(params).then(res=>{
- let _data = res.FunctionResponse;
- let _copyData = JSON.parse(JSON.stringify(this.data));
- _copyData.jsonData.content = _data.message;
- _copyData.jsonData.dataFileList = [];
- _copyData.jsonData.fileList = [];
- _copyData.json_data = JSON.stringify(_copyData.jsonData);
- if (this.history.length == 0) {
- this.history.push(_copyData.jsonData);
- } else {
- this.history.splice(
- this.historyIndex + 1,
- 0,
- _copyData.jsonData
- );
- }
- this.up();
- this.status = 3;
- }).catch(e=>{
- console.log(e)
- this.status = 2;
- })
-
- },
- optimize2(value){
- this.status = 2;
- return console.log('特殊处理');
- if(this.bmData.jsonData.editorBarData.type != 0){
- this.status = 2;
- return this.$toast.fail("请上传表格形式的转录文稿");
- }
- try {
- let _result = [];
- let _data = this.bmData.jsonData.editorBarData.content;
- let _div = document.createElement("div");
- _div.innerHTML = _data;
- let _tableRows = _div.querySelectorAll(`table tbody tr`);
- _tableRows.forEach((i, index) => {
- if (index == 0) return;
- if(!i.cells[0].innerText)return;
- let obj = {
- index: i.cells[0].innerText,
- startTime: i.cells[1].innerText,
- endTime: i.cells[2].innerText,
- message: i.cells[3].innerText,
- time: i.cells[4].innerText,
- role: i.cells[5].innerText,
- behavior: i.cells[6].innerText,
- };
- _result.push(obj);
- });
- if (_result.length == 0){
- this.status = 2;
- return this.$toast.fail("未找到表格数据")
- };
- if (value=='st1') {
- this.getTimeAllocationData(_result);
- } else if (value=='st2') {
- this.getInteractionAnalysisData(_result);
- } else if (value=='st3') {
- this.getTeachingModeData(_result);
- } else {
- this.status = 2;
- return this.$toast.fail("未找到对应的分析");
- }
- } catch (e) {
- console.log(e)
- return this.status = 2;
- }
- },
- // 课堂时间分配
- getTimeAllocationData(_dataList) {
- this.status = 1;
- let _data = _dataList.reduce((pre,cur)=>{
- if(cur.role == '学生'){
- pre[1].value += this.convertToSeconds(cur.time)
- }else if(cur.role=='老师'){
- pre[0].value += this.convertToSeconds(cur.time)
- }
- return pre;
- },[
- {value:0,name:"老师"},
- {value:0,name:'学生'}
- ])
- const _option = {
- tooltip: {
- trigger: "item",
- formatter: "{a} <br/>{b}: {d}%" // {a}为系列名,{b}为数据名,{d}为百分比
- },
- legend: {
- top: "5%",
- left: "center",
- },
- series: [
- {
- name: "课堂时间分配",
- type: "pie",
- radius: ["40%", "70%"],
- avoidLabelOverlap: false,
- label: {
- show: false,
- position: "center",
- },
- emphasis: {
- label: {
- show: true,
- fontSize: 40,
- fontWeight: "bold",
- // formatter: "{b}: {d}%" // 显示百分比
- },
- },
- labelLine: {
- show: false,
- },
- data: _data
- },
- ],
- };
- let _copyData = JSON.parse(JSON.stringify(this.data));
- _copyData.jsonData.eChartData = _option;
- _copyData.json_data = JSON.stringify(_copyData.jsonData);
- if (this.history.length == 0) {
- this.history.push(_copyData.jsonData);
- } else {
- this.history.splice(this.historyIndex + 1, 0, _copyData.jsonData);
- }
- this.up();
- this.status = 3;
- },
- // 师生互动分析
- getInteractionAnalysisData(_dataList) {
- this.status = 1;
- let _pushData = [0,0]
- let _result = []
- _dataList.forEach(i=>{
- if(i.role=='老师'){
- _pushData[0] += this.convertToSeconds(i.time)
- }else if(i.role=='学生'){
- _pushData[1] += this.convertToSeconds(i.time)
- }
- return _result.push(JSON.parse(JSON.stringify(_pushData)))
- })
- let _flatArray = _result.flat();
- const _max = Math.max(..._flatArray)
- const _maxValue =Math.ceil(_max / 100) * 100;
- const _option = {
- xAxis: {
- name: "老师", // X轴标题
- nameLocation: "end", // 标题位置
- scale: true,
- min: 0,
- max:_maxValue
- },
- yAxis: {
- name: "学生", // Y轴标题
- nameLocation: "end", // 标题位置
- scale: true,
- min: 0,
- max:_maxValue
- },
- grid: {
- containLabel: true
- },
- series: [
- {
- name: "数据",
- step: "start",
- data: _result,
- type: "line",
-
- },
- {
- name: "对角线",
- type: "line",
- data: [[0, 0], [_maxValue, _maxValue]],
- lineStyle: {
- type: "dashed"
- },
- markLine: {
- "symbol": ["none", "none"]
- }
- }
- ],
- };
- let _copyData = JSON.parse(JSON.stringify(this.data));
- _copyData.jsonData.eChartData = _option;
- _copyData.json_data = JSON.stringify(_copyData.jsonData);
- if (this.history.length == 0) {
- this.history.push(_copyData.jsonData);
- } else {
- this.history.splice(this.historyIndex + 1, 0, _copyData.jsonData);
- }
- this.up();
- this.status = 3;
- },
- // 教学模式分析
- getTeachingModeData(_dataList) {
- this.status = 1;
- let _continuousTime = 0;
- let _totalTime = 0;
- let _continuousRole = "老师"
- let _teacherTime = 0;
- console.log(_dataList)
- _dataList.forEach((item,index)=>{
- if(index==0){//第一个
- _continuousRole = item.role
- }else if(_dataList.length-1==index){//最后一个
- if(_continuousRole==item.role){//连续对话了
- _continuousTime += this.convertToSeconds(_dataList[index-1].time)
- _continuousTime += this.convertToSeconds(item.time)
- }else{//没连续对话
- if(index>=2){
- if(_dataList[index-2].role==_dataList[index-1].role){
- _continuousTime += this.convertToSeconds(_dataList[index-1].time)
- }else{
- _continuousRole = item.role;
- }
- }else{
- _continuousRole = item.role;
- }
- }
- }else{
- if(_continuousRole==item.role){//连续对话了
- _continuousTime += this.convertToSeconds(_dataList[index-1].time)
- }else{//没连续对话
- if(index>=2){
- if(_dataList[index-2].role==_dataList[index-1].role){
- _continuousTime += this.convertToSeconds(_dataList[index-1].time)
- }else{
- _continuousRole = item.role;
- }
- }else{
- _continuousRole = item.role;
- }
- }
- }
- if(item.role == "老师"){
- _teacherTime+=this.convertToSeconds(item.time);
- }
- _totalTime += this.convertToSeconds(item.time);
- })
- let _RT = (_teacherTime/_totalTime).toFixed(2)
- let _CH = (_continuousTime/_totalTime).toFixed(2)
- let _copyData = JSON.parse(JSON.stringify(this.data));
- _copyData.jsonData.RT = _RT;
- _copyData.jsonData.CH = _CH;
- _copyData.json_data = JSON.stringify(_copyData.jsonData);
- if (this.history.length == 0) {
- this.history.push(_copyData.jsonData);
- } else {
- this.history.splice(this.historyIndex + 1, 0, _copyData.jsonData);
- }
- this.up();
- this.status = 3;
- },
- saveData(params){
- return new Promise((resolve, reject) => {
- updateObsRequest({
- id: params.id,
- json_data: JSON.stringify(params.jsonData)
- })
- .then(res => {
- resolve()
- })
- .catch(e => {
- console.log(e)
- console.log("保存失败")
- // this.$toast.fail('保存失败')
- resolve()
- })
- })
- },
- del() {
- this.$parent.delItem(this.data)
- },
- convertToSeconds(time) {
- let parts = time.split(':');
- let seconds = (+parts[0]) * 3600 + (+parts[1]) * 60 + (+parts[2]);
- return seconds;
- }
- },
- mounted(){
- this.historyIndex = 0;
- this.history.push(JSON.parse(JSON.stringify(this.data.jsonData)))
- },
- }
- </script>
- <style lang="scss" scoped>
- .outcomeCon {
- // display: flex;
- min-height: 50px;
- border: 0.5px #ccc solid;
- align-items: center;
- border-radius: 5px;
- min-height: 40px;
- padding: 0 10px;
- margin-bottom: 10px;
- }
- .abu {
- background-color: #fff;
- width: 100px;
- border-radius: 6px;
- // padding: 10px 10px;
- box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, 0.08);
- box-shadow: 0px 16px 24px 2px rgba(0, 0, 0, 0.04);
- box-shadow: 0px 6px 30px 5px rgba(0, 0, 0, 0.05);
- .abuBtn {
- display: flex;
- align-items: center;
- padding: 10px 15px;
- font-size: 12px;
- font-weight: 400;
- img {
- margin-right: 5px;
- }
- }
- }
- .outcomeBtn {
- display: flex;
- justify-content: space-around;
- padding: 10px 0;
- .ob_no{
- opacity: .6;
- }
- div {
- display: flex;
- align-items: center;
- font-size: 12px;
- img {
- width: 18px;
- height: 18px;
- margin-right: 5px;
- }
- }
- }
- .brief {
- font-style: italic;
- color: #6b798e;
- font-size: 14px;
- }
- .oc_title {
- display: flex;
- align-items: center;
- .tit {
- font-size: 16px;
- font-weight: bold;
- margin-left: 10px;
- }
- }
- .oc_status{
- width: auto;
- height: 100%;
- display: flex;
- justify-content: flex-end;
- align-items: center;
- font-size: 14px;
- div{
- display: flex;
- justify-content: center;
- align-items: center;
- img{
- margin-right: 5px;
- width: 1.5em;
- height: 1.5em;
- }
- }
- }
- </style>
|