SanHQin 7 mesi fa
parent
commit
3f96ed1eb0

BIN
src/assets/icon/pocAi/aiAvatar.png


BIN
src/assets/icon/pocAi/userAvatar.png


+ 1 - 0
src/assets/icon/pocAiClass/avatar.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1724726041765" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4516" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M1024 512c0-281.6-230.4-512-512-512S0 230.4 0 512s230.4 512 512 512 512-230.4 512-512z m-512 448c-249.6 0-448-198.4-448-448s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448z" fill="#000000" p-id="4517"></path><path d="M627.2 505.6c44.8-38.4 76.8-89.6 76.8-153.6 0-108.8-83.2-192-192-192s-192 83.2-192 192c0 64 32 115.2 76.8 153.6-102.4 44.8-172.8 147.2-172.8 262.4 0 19.2 12.8 32 32 32s32-12.8 32-32c0-121.6 102.4-224 224-224s224 102.4 224 224c0 19.2 12.8 32 32 32s32-12.8 32-32c0-115.2-70.4-217.6-172.8-262.4zM512 480c-70.4 0-128-57.6-128-128s57.6-128 128-128 128 57.6 128 128-57.6 128-128 128z" fill="#000000" p-id="4518"></path></svg>

BIN
src/assets/icon/pocAiClass/hello.gif


+ 856 - 0
src/components/pages/pocAiClassroom/chatArea.vue

@@ -0,0 +1,856 @@
+<template>
+  <div class="pocAi">
+    <div class="pa_documentArea" v-if="showFileArea">
+      <div class="pa_da_head">
+        <span @click.stop="showFileArea = false">×</span>
+      </div>
+      <vword
+        style="width: 100%; height: calc(100% - 50px); overflow: hidden"
+        class="fullStyle"
+        v-if="showFile.type == 2 && !['pdf', 'txt'].includes(showFile.suffix)"
+        :pdfUrl="
+          'https://view.officeapps.live.com/op/view.aspx?src=' + showFile.url
+        "
+      />
+      <vpdf
+        style="width: 100%;  height: calc(100% - 50px); overflow: hidden"
+        class="fullStyle"
+        :pdfUrl="showFile.url"
+        v-if="showFile.type == 2 && ['pdf'].includes(showFile.suffix)"
+      />
+
+      <txtView
+			style="width: 100%;height: calc(100% - 50px);"
+        v-if="showFile.type == 2 && ['txt'].includes(showFile.suffix)"
+        :url="showFile.url"
+      />
+
+      <div class="pa_da_Image" v-if="showFile.type == 1">
+        <el-image
+          style="width: 100%;"
+          :src="showFile.url"
+          :preview-src-list="[showFile.url]"
+        >
+        </el-image>
+      </div>
+
+      <div class="pa_da_Video" v-if="showFile.type == 3">
+        <video-player
+          style="width: 100%;display: flex;justify-content: center;align-items: center;"
+          :playsinline="true"
+          :options="showFile.videoOption"
+        ></video-player>
+      </div>
+    </div>
+    <div class="pa_chatArea">
+			<div class="pa_ca_back" @click.stop="back()">返回</div>
+      <!-- <div class="pa_ca_header">
+        <span v-text="chatTitle"></span>
+      </div> -->
+      <div class="pa_ca_chat" v-loading="loading">
+        <div
+          class="pa_ca_c_list"
+          ref="chatListRef"
+          :style="showFileArea ? '0' : 'padding-left:100px;padding-right:100px'"
+        >
+          <div v-for="(item, index) in chatList" :key="index">
+            <div class="userChat" v-if="item.content">
+              <div class="uc_left">
+                <div class="chatName">科科</div>
+                <div class="chatMessage" v-text="item.content"></div>
+              </div>
+              <div class="uc_right">
+                <el-avatar
+                  class="chatAvatar"
+                  :src="require('../../../assets/icon/pocAi/userAvatar.png')"
+                ></el-avatar>
+              </div>
+            </div>
+            <div class="aiChat">
+              <div class="ac_left">
+                <el-avatar
+                  class="chatAvatar"
+                  :src="require('../../../assets/icon/pocAi/aiAvatar.png')"
+                ></el-avatar>
+              </div>
+              <div class="ac_right">
+                <div class="chatName">蓝可可</div>
+                <div
+                  class="chatMessage"
+                  v-loading="item.loading"
+                  v-html="item.aiContent"
+									:style="item.loading?'border:none':''"
+                ></div>
+                <div class="ac_r_btnArea">
+                  <span @click.stop="checkFile()">查看文件</span>
+                </div>
+                <div class="ac_r_time">2024-08-26 14:31:45</div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div
+          class="pa_ca_c_bottom"
+          :style="showFileArea ? '0' : 'padding-left:100px;padding-right:100px'"
+        >
+          <div class="pa_ca_c_b_inputArea">
+            <textarea
+              id="myTextarea"
+              ref="textAreaRef"
+              min-rows="1"
+              max-rows="5"
+              v-model="chatValue"
+              placeholder="你有任何想法,可以随时告诉我呀"
+              autosize="none"
+              :disabled="source != null"
+            ></textarea>
+            <div class="pa_ca_c_b_btnArea">
+							<span class="pa_ca_c_b_ba_btn" @click="sendChat">
+								<svg t="1724748020468" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7309" width="200" height="200"><path d="M931.392 11.264L45.12 530.688c-28.736 16.896-43.52 39.424-45.12 61.248v8.128c2.048 26.112 23.04 49.984 61.632 60.416l171.968 46.592a34.304 34.304 0 0 0 41.28-25.536 35.584 35.584 0 0 0-23.808-43.136L79.68 592l873.408-511.872-95.232 703.488c-1.408 10.432-9.152 15.68-18.752 12.992l-365.632-100.288 296.32-305.856a36.416 36.416 0 0 0 0-50.24 33.728 33.728 0 0 0-48.704 0l-324.8 335.36a110.72 110.72 0 0 0-7.872 9.088 35.52 35.52 0 0 0-16.128 30.784 104 104 0 0 0-5.248 32.64v206.4c0 49.664 53.568 79.168 93.568 51.712l166.272-114.368c10.24-6.976 16-19.136 15.232-31.872a35.712 35.712 0 0 0-19.2-29.504 33.28 33.28 0 0 0-34.24 2.304L435.84 937.856v-178.432l385.472 105.6c49.6 13.632 97.472-19.072 104.576-71.808l97.152-717.568c8.448-60.48-40-94.72-91.648-64.384z" p-id="7310"></path></svg>
+							</span>
+              <!-- <el-button
+                class="pa_ca_c_b_ba_btn"
+                type="primary"
+                @click="sendChat"
+                >发送</el-button
+              > -->
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import vpdf from "./component/vpdf.vue";
+import vword from "./component/vword.vue";
+import txtView from "./component/txtView.vue";
+import { v4 as uuidv4 } from "uuid";
+import MarkdownIt from "markdown-it";
+export default {
+  components: {
+    vpdf,
+    vword,
+    txtView
+  },
+  data() {
+    return {
+      userId: this.$route.query.userid,
+      org: this.$route.query.org,
+      oid: this.$route.query.oid,
+      showFileIndex: 0,
+			showFileArea:false,
+      chatValue: "",
+      source: null,
+			loading:false,
+      chatTitle: "第一章 声音的原理",
+			showFileUrl:"",
+      chatList: [
+        {
+          loading: false,
+          role: "user",
+          content: "哇卡哇卡",
+          uid: "d601788a-5ece-11ef-826e-12e77c4cb76b",
+          AI: "AI",
+          aiContent:
+            "<p>&quot;哇卡哇卡&quot; 是夏奇拉(Shakira)的一首非常知名的歌曲,全名是《Waka Waka (This Time for Africa)》。这首歌是2010年南非世界杯的官方主题曲,充满了非洲音乐元素和动感节奏,广受欢迎。如果你对这首歌或其意义感兴趣,可以分享更多你的想法!</p>\n",
+          oldContent:
+            "<p>&quot;哇卡哇卡&quot; 是夏奇拉(Shakira)的一首非常知名的歌曲,全名是《Waka Waka (This Time for Africa)》。这首歌是2010年南非世界杯的官方主题曲,充满了非洲音乐元素和动感节奏,广受欢迎。如果你对这首歌或其意义感兴趣,可以分享更多你的想法!</p>\n",
+          isShowSynchronization: false,
+          filename: "",
+          index: 0,
+          is_mind_map: false,
+          fileid: "",
+          createtime: "2024-08-20 08:33:11"
+        },
+        {
+          loading: false,
+          role: "user",
+          content: "最近中国有什么好的游戏可以玩吗\n",
+          uid: "e23485ec-5ece-11ef-826e-12e77c4cb76b",
+          AI: "AI",
+          aiContent:
+            "<p>最近中国有几款备受关注的游戏,以下是其中一些推荐:</p>\n<ol>\n<li>\n<p><strong>《原神》</strong> - 这是一款由miHoYo开发的开放世界角色扮演游戏,以其精美的画面和开放的世界探索而受到广泛好评。</p>\n</li>\n<li>\n<p><strong>《崩坏:星穹铁道》</strong> - 也是miHoYo开发的作品,作为《崩坏》系列的新作,这款游戏结合了科幻元素和回合制战斗机制。</p>\n</li>\n<li>\n<p><strong>《阴阳师》</strong> - 由网易开发的卡牌策略游戏,以其独特的美术风格和丰富的剧情设定而受到玩家喜爱。</p>\n</li>\n<li>\n<p><strong>《和平精英》</strong> - 这是一款由腾讯光子工作室群开发的多人在线战术竞技类游戏,是中国版的《PUBG Mobile》。</p>\n</li>\n<li>\n<p><strong>《剑网3:缘起》</strong> - 西山居开发的一款大型多人在线角色扮演游戏(MMORPG),以其经典的武侠元素和深厚的剧情吸引了大量玩家。</p>\n</li>\n</ol>\n<p>这些游戏在画质、玩法和社交性方面各有特色,你可以根据自己的兴趣和偏好进行选择体验。</p>\n",
+          oldContent:
+            "<p>最近中国有几款备受关注的游戏,以下是其中一些推荐:</p>\n<ol>\n<li>\n<p><strong>《原神》</strong> - 这是一款由miHoYo开发的开放世界角色扮演游戏,以其精美的画面和开放的世界探索而受到广泛好评。</p>\n</li>\n<li>\n<p><strong>《崩坏:星穹铁道》</strong> - 也是miHoYo开发的作品,作为《崩坏》系列的新作,这款游戏结合了科幻元素和回合制战斗机制。</p>\n</li>\n<li>\n<p><strong>《阴阳师》</strong> - 由网易开发的卡牌策略游戏,以其独特的美术风格和丰富的剧情设定而受到玩家喜爱。</p>\n</li>\n<li>\n<p><strong>《和平精英》</strong> - 这是一款由腾讯光子工作室群开发的多人在线战术竞技类游戏,是中国版的《PUBG Mobile》。</p>\n</li>\n<li>\n<p><strong>《剑网3:缘起》</strong> - 西山居开发的一款大型多人在线角色扮演游戏(MMORPG),以其经典的武侠元素和深厚的剧情吸引了大量玩家。</p>\n</li>\n</ol>\n<p>这些游戏在画质、玩法和社交性方面各有特色,你可以根据自己的兴趣和偏好进行选择体验。</p>\n",
+          isShowSynchronization: false,
+          filename: "",
+          index: 1,
+          is_mind_map: false,
+          fileid: "",
+          createtime: "2024-08-20 08:33:32"
+        },
+        {
+          loading: false,
+          role: "user",
+          content: "你这是多少年的数据了",
+          uid: "eaa6c091-5ece-11ef-826e-12e77c4cb76b",
+          AI: "AI",
+          aiContent:
+            "<p>我掌握的数据截止到2023年,是经过培训和处理的历史数据。有什么我可以帮你的吗?</p>\n",
+          oldContent:
+            "<p>我掌握的数据截止到2023年,是经过培训和处理的历史数据。有什么我可以帮你的吗?</p>\n",
+          isShowSynchronization: false,
+          filename: "",
+          index: 2,
+          is_mind_map: false,
+          fileid: "",
+          createtime: "2024-08-20 08:33:46"
+        },
+        {
+          loading: false,
+          role: "user",
+          content: "巴黎奥运会怎么样了",
+          uid: "f9188e27-5ece-11ef-826e-12e77c4cb76b",
+          AI: "AI",
+          aiContent:
+            "<p>截至我最近的更新信息,巴黎奥运会将在2024年举行。具体情况包括:</p>\n<ol>\n<li>\n<p><strong>日期和地点</strong>:巴黎奥运会计划于2024年7月26日至8月11日举行。比赛将在法国巴黎及其周边地区的各大场馆进行。</p>\n</li>\n<li>\n<p><strong>项目</strong>:2024年巴黎奥运会预计将包括32个大项,覆盖从田径到游泳等传统项目,同时可能也会引入一些新的项目或调整现有项目的设置。</p>\n</li>\n<li>\n<p><strong>准备工作</strong>:巴黎方面正在积极进行场馆建设与改造、城市基础设施的提升以及各种筹备工作,以确保赛事顺利进行。</p>\n</li>\n<li>\n<p><strong>可持续性与创新</strong>:巴黎奥运会提出了“可持续性”与“创新”的理念,致力于通过多种方式(如使用临时设施、推广绿色交通等)减少对环境的影响。</p>\n</li>\n</ol>\n<p>具体的进展和变化可能会随着时间推移有所不同。要了解更多的信息和最新动态,可以关注巴黎奥组委的官方网站或相关的新闻报道。</p>\n",
+          oldContent:
+            "<p>截至我最近的更新信息,巴黎奥运会将在2024年举行。具体情况包括:</p>\n<ol>\n<li>\n<p><strong>日期和地点</strong>:巴黎奥运会计划于2024年7月26日至8月11日举行。比赛将在法国巴黎及其周边地区的各大场馆进行。</p>\n</li>\n<li>\n<p><strong>项目</strong>:2024年巴黎奥运会预计将包括32个大项,覆盖从田径到游泳等传统项目,同时可能也会引入一些新的项目或调整现有项目的设置。</p>\n</li>\n<li>\n<p><strong>准备工作</strong>:巴黎方面正在积极进行场馆建设与改造、城市基础设施的提升以及各种筹备工作,以确保赛事顺利进行。</p>\n</li>\n<li>\n<p><strong>可持续性与创新</strong>:巴黎奥运会提出了“可持续性”与“创新”的理念,致力于通过多种方式(如使用临时设施、推广绿色交通等)减少对环境的影响。</p>\n</li>\n</ol>\n<p>具体的进展和变化可能会随着时间推移有所不同。要了解更多的信息和最新动态,可以关注巴黎奥组委的官方网站或相关的新闻报道。</p>\n",
+          isShowSynchronization: false,
+          filename: "",
+          index: 3,
+          is_mind_map: false,
+          fileid: "",
+          createtime: "2024-08-20 08:34:10"
+        },
+        {
+          loading: false,
+          role: "user",
+          content: "巴黎奥运会有哪些国家参加",
+          uid: "0aedaebd-5ecf-11ef-826e-12e77c4cb76b",
+          AI: "AI",
+          aiContent:
+            "<p>巴黎奥运会将于2024年举行,由于奥运会是由国际奥林匹克委员会(IOC)组织的,通常大多数国家都会派代表团参加,包括几乎所有联合国成员国和一些地区或地区代表队。截至目前,具体参赛的国家和地区名单尚未最终确定,但预计将会有200多个国家和地区参加。如果你想了解最新的参赛国家名单,建议关注国际奥林匹克委员会的官方网站或相关最新新闻。</p>\n",
+          oldContent:
+            "<p>巴黎奥运会将于2024年举行,由于奥运会是由国际奥林匹克委员会(IOC)组织的,通常大多数国家都会派代表团参加,包括几乎所有联合国成员国和一些地区或地区代表队。截至目前,具体参赛的国家和地区名单尚未最终确定,但预计将会有200多个国家和地区参加。如果你想了解最新的参赛国家名单,建议关注国际奥林匹克委员会的官方网站或相关最新新闻。</p>\n",
+          isShowSynchronization: false,
+          filename: "",
+          index: 4,
+          is_mind_map: false,
+          fileid: "",
+          createtime: "2024-08-20 08:34:40"
+        }
+      ],
+      fileList: [
+        {
+          //docx
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%A0%A1%E7%BA%A7%E5%88%9B%E5%AE%A2%E9%A1%B9%E7%9B%AE%E7%BB%93%E9%A2%98%E7%94%B3%E8%AF%B7%E4%B9%A6-%E5%88%9B%E6%96%B0%E5%88%9B%E4%B8%9A%E5%AD%A6%E9%99%A21724638848483.docx",
+          fileId: "file-xUxtMlJu7PoDBvzZg1JCegtM"
+        },
+        {
+          //xlsx
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724640873576.xlsx",
+          fileId: "file-61KteMZxNwzjJQFRdlwtdpmg"
+        },
+        {
+          //ppt
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724641111983.pptx",
+          fileId: ""
+        },
+        {
+          //pdf
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E5%88%9B%E4%BD%9C%E4%B8%AD%E5%BF%83%E5%8E%9F%E5%9E%8B%E5%9B%BE1724641155668.pdf",
+          fileId: "file-1ldbT8Ztg5QQPUucJs2FpLAJ"
+        },
+        {
+          //jpg
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724641221681.jpg",
+          fileId: ""
+        },
+        {
+          //mp4
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/c3e87dc3-d5ab-4a1f-a519-63d903a270f8%2F2024-08-09+17-07-50.mp4",
+          fileId: ""
+        },
+        {
+          //txt
+          fileUrl:
+            "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/ktgc31724643097906.txt",
+          fileId: "file-YSVSAsDGvtiWJQ6mWf7ZdupA"
+        }
+      ],
+      canonical: {
+        Image: /^https?:\/\/(.+\/)+.+(\.(gif|png|jpg|jpeg|webp|svg|psd|bmp|tif))$/i,
+        File: /^https?:\/\/(.+\/)+.+(\.(docx|doc|xlsx|ppt|pdf|pptx|txt))$/i,
+        video: /^https?:\/\/(.+\/)+.+(\.(avi|wmv|mpg|mpeg|mov|rm|ram|mp4|swf|flv))$/i
+      }
+    };
+  },
+  computed: {
+    showFile() {
+      let result = { type: 0, suffix: "", url: "", videoOption: null }; //0:无 1:图片 2:文件 3:视频
+      if (this.showFileUrl) {
+        result.url = this.showFileUrl;
+        if (
+          this.canonical.Image.test(this.showFileUrl)
+        ) {
+          result.type = 1;
+          result.suffix = this.showFileUrl
+            .split(".")
+            .pop();
+        } else if (
+          this.canonical.File.test(this.showFileUrl)
+        ) {
+          result.type = 2;
+          result.suffix = this.showFileUrl
+            .split(".")
+            .pop();
+        } else if (
+          this.canonical.video.test(this.showFileUrl)
+        ) {
+          result.type = 3;
+          result.videoOption = {
+            playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
+            autoplay: false, //如果true,浏览器准备好时开始回放。
+            muted: false, // 默认情况下将会消除任何音频。
+            loop: false, // 导致视频一结束就重新开始。
+            preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
+            language: "zh-CN",
+            aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
+            fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
+            sources: this.showFileUrl,
+            // poster: "https://p1.music.126.net/5zs7IvmLv7KahY3BFzUmrg==/109951163635241613.jpg?param=600y500", // 你的封面地址
+            notSupportedMessage: "此视频暂无法播放,请稍后再试", // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
+            controlBar: {
+              timeDivider: true,
+              durationDisplay: true,
+              remainingTimeDisplay: false,
+              fullscreenToggle: true // 全屏按钮
+            }
+          };
+          result.suffix = this.showFileUrl
+            .split(".")
+            .pop();
+        }
+      }
+      return result;
+    }
+  },
+  methods: {
+    chatListScrollBottom() {
+      this.$nextTick(() => {
+        this.$refs.chatListRef.scrollTop = this.$refs.chatListRef.scrollHeight;
+      });
+    },
+    sendChat() {
+      if (this.source) return this.$message.info("还在对话中,请稍等");
+      const _text = this.chatValue;
+      this.chatValue = "";
+      if (!_text.trim()) return;
+      var OpenCC = require("opencc-js");
+      let converter = OpenCC.Converter({
+        from: "cn",
+        to: "hk"
+      });
+      const _uuid = uuidv4();
+      this.chatList.push({
+        role: "user",
+        content: `${_text}`,
+        uid: _uuid,
+        AI: "AI",
+        aiContent: "",
+        oldContent: "",
+        isShowSynchronization: false,
+        filename: "",
+        index: this.chatList.length,
+        is_mind_map: false,
+        createtime: new Date().toLocaleString().replaceAll("/", "-"),
+        loading: true
+      });
+      this.chatListScrollBottom();
+
+      // 连续对话设置
+      let _historyMessage = [];
+
+      _historyMessage.push({ role: "user", content: _text });
+
+			let params = {
+        assistant_id: "f8e1ebb2-2e0d-11ef-8bf4-12e77c4cb76b",
+        userId: this.userId,
+        message: _text,
+        session_name: `${_uuid}-pocAi-md`,
+        uid: _uuid,
+        file_ids: [],
+        model: "gpt-4o-2024-08-06"
+      };
+
+			this.ajax
+        .post("https://gpt4.cocorobo.cn/ai_agent_park_chat_new", params)
+        .then(res => {
+          if (
+            converter(res.data.FunctionResponse.result) == converter("发送成功")
+          ) {
+          } else {
+            console.log(res.data.FunctionResponse.result);
+          }
+        })
+        .catch(e => {
+          console.log(e);
+        });
+      	this.getAtAuContent(_uuid);
+
+    },
+		getAtAuContent(_uid) {
+      this.source = new EventSource(
+        `https://gpt4.cocorobo.cn/question/${_uid}`
+      );
+      let _allText = "";
+      let _mdText = "";
+      const md = new MarkdownIt();
+      this.source.onmessage = _e => {
+        let _eData = JSON.parse(_e.data);
+        if (_eData.content.replace("'", "").replace("'", "") == "[DONE]") {
+          let _result = [];
+          if ("result" in _eData) {
+            _result = _eData.result;
+            for (let i = 0; i < _result.length; i++) {
+              _mdText = _mdText.replace(_result[i].text, _result[i].fileName);
+            }
+          }
+          _mdText = _mdText.replace("_", "");
+          this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
+          this.chatList.find(i => i.uid == _uid).isalltext = true;
+          this.chatList.find(i => i.uid == _uid).isShowSynchronization = true;
+          this.chatList.find(i => i.uid == _uid).loading = false;
+          this.source.close();
+					this.source = null;
+					this.chatListScrollBottom();
+          this.insertChat(_uid);
+        } else {
+          // _index += 1;
+          let _text = _eData.content.replace("'", "").replace("'", "");
+          if (_allText == "") {
+            _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
+          } else {
+            _allText += _text;
+          }
+          _mdText = _allText + "_";
+          _mdText = _mdText.replace(/\\n/g, "\n");
+          _mdText = _mdText.replace(/\\/g, "");
+
+          if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
+          //转化返回的回复流数据
+          _mdText = md.render(_mdText);
+          // if (_index == 10) {
+            this.chatList.find(i => i.uid == _uid).aiContent = _mdText;
+            this.chatList.find(i => i.uid == _uid).loading = false;
+						this.chatListScrollBottom();
+            // _index = 0;
+          // }
+          // 处理流数据
+        }
+      };
+    },
+		//保存消息
+    insertChat(_uid) {
+      if (_uid == "") return;
+      let _data = this.chatList.find(i => i.uid == _uid);
+      if (!_data) return;
+      let params = {
+        userId: this.userId,
+        userName: "qgt",
+        groupId: "qwertyuiop-poc",
+        answer: _data.aiContent,
+        problem: _data.content,
+        file_id: _data.fileid ? _data.fileid : "",
+        alltext: _data.aiContent,
+        type: "chat",
+        filename: _data.filename,
+        session_name: `pocAi-md` //这是对话记录位置
+      };
+      this.ajax
+        .post("https://gpt4.cocorobo.cn/insert_chat", params)
+        .then(res => {});
+    },
+		// 获取对应的聊天记录
+    getChatList() {
+      return new Promise((resolve, reject) => {
+        if (this.loading) return this.$message.info("请稍等...");
+        this.chatList = [];
+        this.loading = true;
+        let params = {
+          userid: this.userId,
+          groupid: "qwertyuiop-poc",
+          // session_name:``
+          session_name: `pocAi-md`
+        };
+        this.ajax
+          .post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
+          .then(res => {
+            let _data = JSON.parse(res.data.FunctionResponse);
+            if (_data.length > 0) {
+              let _chatList = [];
+              for (let i = 0; i < _data.length; i++) {
+                _chatList.push({
+                  loading: false,
+                  role: "user",
+                  content: _data[i].problem,
+                  uid: _data[i].id,
+                  AI: "AI",
+                  aiContent: _data[i].answer,
+                  oldContent: _data[i].answer,
+                  isShowSynchronization: false,
+                  filename: _data[i].filename,
+                  index: i,
+                  is_mind_map: false,
+                  fileid: _data[i].fileid
+                });
+              }
+              this.chatList = _chatList;
+              this.loading = false;
+            } else {
+              //没有对话记录
+              this.loading = false;
+            }
+						this.chatListScrollBottom();
+            resolve();
+          })
+          .catch(err => {
+            console.log(err);
+            this.$message.error("获取对话记录失败");
+            this.loading = false;
+            resolve();
+          });
+      });
+    },
+		checkFile(url = ""){
+      if (url) {
+        this.showFileUrl = url;
+      } else {
+				const _index = Math.floor(Math.random() * (this.fileList.length));
+        this.showFileUrl = this.fileList[_index].fileUrl;
+      }
+      this.showFileArea = true;
+    },
+		back(){
+			this.$router.back(1)
+		},
+  },
+  mounted() {
+    this.getChatList();
+  }
+};
+</script>
+
+<style scoped>
+.pocAi {
+  width: 100vw;
+  height: 100vh;
+  display: flex;
+  background-image: radial-gradient(#bbcdff 0%, #bbcdff 1%, #e6dee9 100%);
+  box-sizing: border-box;
+}
+
+.pa_documentArea {
+  width: 35%;
+  height: 100%;
+  overflow: auto;
+  box-sizing: border-box;
+}
+
+.pa_da_head {
+  width: 100%;
+  height: 50px;
+  display: flex;
+  justify-content: flex-end;
+  background-color: #fff;
+}
+
+.pa_da_head > span {
+  width: 50px;
+  height: 50px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  font-size: 24px;
+  cursor: pointer;
+}
+
+.pa_da_Image {
+  width: 100%;
+  height: calc(100% - 50px);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #e2e2e2;
+  box-sizing: border-box;
+  padding: 20px;
+}
+
+.pa_da_Video {
+  width: 100%;
+  height: calc(100% - 50px);
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  background-color: #e2e2e2;
+  box-sizing: border-box;
+  padding: 20px;
+}
+
+.pa_da_Video >>> .video-js {
+  width: 100%;
+  height: 100%;
+}
+
+.pa_da_Video >>> .vjs-big-play-button {
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+
+.pa_chatArea {
+  flex: 1;
+  height: 100%;
+  overflow: auto;
+  box-sizing: border-box;
+	position: relative;
+}
+
+.pa_ca_back{
+	font-size: 24px;
+	cursor: pointer;
+}
+
+.pa_ca_back{
+	position: absolute;
+	right: 30px;
+	top: 30px;
+}
+
+.pa_ca_header {
+  width: 100%;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  padding: 0 20px;
+  box-sizing: border-box;
+}
+
+.pa_ca_chat {
+  width: 100%;
+  box-sizing: border-box;
+  height: calc(100%);
+}
+
+.pa_ca_c_list {
+  width: 100%;
+  height: calc(100% - 100px);
+  overflow: auto;
+  padding-top: 50px;
+  padding-bottom: 50px;
+  /* padding: 50px 0; */
+  box-sizing: border-box;
+  /* background-color: red; */
+}
+
+.pa_ca_c_bottom {
+  width: 100%;
+  height: 100px;
+  display: flex;
+  justify-content: center;
+  align-items: flex-start;
+  box-sizing: border-box;
+}
+
+.pa_ca_c_b_inputArea {
+  width: 95%;
+	margin-left: 20px;
+  height: 85%;
+  background-color: #fff;
+  border-radius: 100px;
+  box-shadow: 0 0 10px #ccc;
+  display: flex;
+  align-items: center;
+}
+.pa_ca_c_b_btnArea {
+  width: 150px;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+}
+
+.pa_ca_c_b_ba_btn {
+  width: 60px;
+  height: 60px;
+  margin-right: 20px;
+	border-radius: 50%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+	/* background-color: red; */
+	background-image: linear-gradient(to left, #4977EB 0%, #005bea 100%);
+}
+
+.pa_ca_c_b_ba_btn>svg{
+	fill: #fff;
+	width: 30px;
+	height: 30px;
+}
+
+.pa_ca_c_b_inputArea > textarea {
+  resize: none;
+  min-height: 50px;
+  height: calc(100% - 30px);
+  background: none;
+  margin: 7px 0;
+  width: calc(100% - 150px);
+  font-size: 18px;
+  border: none;
+  outline: none;
+  resize: none;
+  overflow: auto;
+  margin-left: 20px;
+}
+
+#myTextarea::-webkit-input-placeholder {
+  /* Chrome, Opera, Safari */
+  font-size: 16px; /* 修改placeholder字体大小 */
+  color: grey; /* 修改placeholder文字颜色 */
+}
+
+#myTextarea:-moz-placeholder {
+  /* Firefox 18- */
+  font-size: 14px; /* 修改placeholder字体大小 */
+  color: grey; /* 修改placeholder文字颜色 */
+  opacity: 1; /* 修复Firefox的透明度问题 */
+}
+
+#myTextarea::-moz-placeholder {
+  /* Firefox 19+ */
+  font-size: 14px; /* 修改placeholder字体大小 */
+  color: grey; /* 修改placeholder文字颜色 */
+  opacity: 1; /* 修复Firefox的透明度问题 */
+}
+
+#myTextarea:-ms-input-placeholder {
+  /* Internet Explorer 10-11 */
+  font-size: 14px; /* 修改placeholder字体大小 */
+  color: grey; /* 修改placeholder文字颜色 */
+}
+
+.userChat {
+  width: 100%;
+  height: auto;
+  display: flex;
+  justify-content: flex-end;
+  align-items: flex-start;
+}
+
+.uc_left {
+  max-width: calc(65vw - 300px);
+  width: auto;
+  height: auto;
+  padding: 10px 0px 10px 0;
+}
+
+.uc_left > .chatName {
+  text-align: right;
+}
+
+.uc_left > .chatMessage {
+  border-radius: 10px 0px 10px 10px;
+}
+
+/* .uc_left > span {
+  width: auto;
+  height: auto;
+  padding: 20px 20px;
+  background-color: #4a7ff4;
+  border-radius: 10px;
+  color: #fff;
+} */
+
+.uc_right {
+  padding: 10px 20px 10px 10px;
+}
+
+.aiChat {
+  width: 100%;
+  display: flex;
+  justify-content: flex-start;
+  align-items: flex-start;
+  /* padding: 20px 0; */
+}
+
+.ac_left {
+  padding: 10px 10px 10px 20px;
+}
+
+.ac_right {
+  width: auto;
+  height: auto;
+  padding: 10px 0px 10px 0;
+}
+
+.chatMessage {
+  max-width: calc(65vw - 300px);
+  background-color: #ffffff;
+  border: solid 2px black;
+  color: black;
+  padding: 20px 20px;
+  border-radius: 0px 10px 10px 10px;
+}
+
+.chatMessage >>> ol {
+  margin-left: 25px;
+}
+
+.chatMessage >>> ul {
+  margin-left: 25px;
+}
+
+.ac_r_time {
+  margin-top: 10px;
+  font-size: 14px;
+  color: #8f8f8f;
+}
+
+.ac_r_btnArea {
+  margin-top: 5px;
+  width: auto;
+  display: flex;
+  align-items: center;
+  height: auto;
+}
+.ac_r_btnArea > span {
+  max-height: 60px;
+  padding: 10px 10px;
+  background-color: #e1eaff;
+  border: solid 1px #fff;
+  border-radius: 8px;
+  font-size: 14px;
+  cursor: pointer;
+  color: #6b6f79;
+}
+
+.chatAvatar {
+  width: 50px;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 18px;
+  background: none;
+}
+
+.ac_left > .chatAvatar {
+  transform: scale(1.2, 1.2);
+}
+
+.chatName {
+  font-size: 14px;
+  color: rgb(80, 80, 80);
+  margin-bottom: 8px;
+}
+</style>

+ 144 - 0
src/components/pages/pocAiClassroom/component/chapterCard.vue

@@ -0,0 +1,144 @@
+<template>
+  <div class="chapterCard">
+    <div class="cc_title">{{ data.title }}</div>
+    <div class="cc_box">
+      <div
+        class="cc_b_item"
+        v-for="(item, index) in data.allClass"
+        :key="index"
+      >
+        <div class="cc_b_i_image">
+					<el-image style="width: 100%;height: 100%;" :src="item.image" fit="cover"></el-image>
+					<div class="cc_b_i_btnArea">
+						<span class="cc_b_i_ba_goClass" v-if="[0].includes(item.type)" @click.stop="goClass(item)">去上课</span>
+						<span class="cc_b_i_ba_doWorks" v-if="[0,1].includes(item.type)" @click.stop="goWorks(item)">做练习</span>
+					</div>
+				</div>
+        <div class="cc_b_i_title">
+          <el-tooltip
+            class="item"
+            effect="light"
+            :content="item.title"
+            placement="top"
+          >
+            <span v-text="item.title"></span>
+          </el-tooltip>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    data: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  data() {
+    return {};
+  },
+	methods: {
+		goClass(item){
+			console.log("去上课",item);
+			
+		},
+		goWorks(item){
+			console.log("去做练习",item);
+			
+		}
+	},
+};
+</script>
+
+<style scoped>
+.chapterCard {
+  width: 100%;
+  height: auto;
+  margin-top: 30px;
+	
+}
+
+.cc_title {
+  margin: 20px 0;
+  font-size: 32px;
+}
+
+.cc_box {
+  width: 100%;
+  height: auto;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.cc_b_item {
+  width: 230px;
+  height: 300px;
+  margin-right: 50px;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  align-items: center;
+	margin-bottom: 40px;
+}
+
+.cc_b_item:hover .cc_b_i_image>.cc_b_i_btnArea{
+	display: flex;
+}
+
+.cc_b_i_image {
+  width: 100%;
+  height: 260px;
+  background-color: #fff;
+  border-radius: 10px;
+  overflow: hidden;
+	position: relative;
+}
+
+.cc_b_i_btnArea{
+	width: 100%;
+	height: 50px;
+	position: absolute;
+	bottom: 5px;
+	display: none;
+	justify-content: space-around;
+	align-items: center;
+	padding: 0 10px;
+	box-sizing: border-box;
+}
+
+.cc_b_i_btnArea>span{
+	flex: 1;
+	height: 40px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	cursor: pointer;
+	border-radius: 8px;
+	color: black;
+	background-image: radial-gradient(73% 147%, #EADFDF 59%, #ECE2DF 100%), radial-gradient(91% 146%, rgba(255,255,255,0.50) 47%, rgba(0,0,0,0.50) 100%);
+ 	background-blend-mode: screen;
+}
+
+.cc_b_i_btnArea>span:nth-of-type(2n){
+	margin-left: 10px;
+}
+
+.cc_b_i_title {
+  width: 100%;
+  height: 40px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+.cc_b_i_title > span {
+  max-width: 100%;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+  font-size: 20px;
+}
+</style>

+ 97 - 0
src/components/pages/pocAiClassroom/component/txtView.vue

@@ -0,0 +1,97 @@
+<template>
+  <div class="txtView" v-loading="loading">
+		<div class="tv_content" v-text="content"></div>
+	</div>
+</template>
+
+<script>
+import "../../../../common/aws-sdk-2.235.1.min.js";
+
+const getFile = url => {
+  return new Promise((resolve, reject) => {
+    var credentials = {
+      accessKeyId: "AKIATLPEDU37QV5CHLMH",
+      secretAccessKey: "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"
+    }; //秘钥形式的登录上传
+    window.AWS.config.update(credentials);
+    window.AWS.config.region = "cn-northwest-1"; //设置区域
+    let url2 = url;
+    let _url2 = "";
+    if (
+      url2.indexOf("https://view.officeapps.live.com/op/view.aspx?src=") != -1
+    ) {
+      _url2 = url2.split(
+        "https://view.officeapps.live.com/op/view.aspx?src="
+      )[1];
+    } else {
+      _url2 = url2;
+    }
+    var s3 = new window.AWS.S3({ params: { Bucket: "ccrb" } });
+    let name = decodeURIComponent(
+      _url2.split("https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/")[1]
+    );
+    var params = {
+      Bucket: "ccrb",
+      Key: name
+    };
+    s3.getObject(params, function(err, data) {
+      if (err) {
+        console.log(err, err.stack);
+        resolve({ data: 1 });
+      } else {
+        const fileContent = data.Body.toString("utf-8");
+        resolve({ data: fileContent });
+      } // sxuccessful response
+    });
+    // axios({
+  });
+};
+export default {
+  props: {
+    url: {
+      type: String,
+      default: ""
+    },
+  },
+	data(){
+		return{
+			content:"",
+			loading:""
+		}
+	},
+	methods: {
+		getTxtContent() {
+			if(!this.url)return;
+			this.loading = true;
+			getFile(this.url).then(res=>{
+				this.loading = false;
+				this.content = res.data;
+			})
+		},
+	},
+	mounted(){
+		this.getTxtContent();
+	}
+};
+</script>
+
+<style scoped>
+.txtView{
+	width: 100%;
+	height: 100%;
+	box-sizing: border-box;
+	background-color: #ececec;
+	padding: 20px;
+}
+
+.tv_content{
+	width: 100%;
+	height: 100%;
+	box-sizing: border-box;
+	background-color: #fff;
+	overflow: auto;
+	word-wrap: break-word;
+	border-radius: 3px;
+	white-space: pre;
+}
+</style>

+ 252 - 0
src/components/pages/pocAiClassroom/component/vpdf.vue

@@ -0,0 +1,252 @@
+<template>
+  <!--使用 pdfvuer 实现 滑动浏览 单印章-->
+  <div class="pdf">
+    <div class="loading" v-show="isloading">
+      <span>pdf可能会加载时间有点长,请耐心等待...</span>
+    </div>
+    <!-- <div id="contentArea" class="show" v-if="!loading">
+      <pdf :scale.sync="scale" :resize="true" ref="wrapper" class="p-pdf" :src="pdfData" v-for="i in numPages" :key="i"
+        :id="i" :page="i" style="width: 100%">
+      </pdf>
+    </div> -->
+    <iframe ref="viframe" style="width: 100%; height: 100%; border: none"
+      :src="'https://cloud.cocorobo.cn/pdf.js/web/viewer.html?file=' + pdfUrl"></iframe>
+    <!-- <div class="rightArea">
+      <div class="toolGroup">
+        <div class="page">第 {{ page }} / {{ numPages }} 页</div>
+        <el-button type="primary" @click.stop="prePage">上一页</el-button>
+        <el-button type="primary" @click.stop="nextPage">下一页</el-button>
+      </div>
+    </div> -->
+  </div>
+</template>
+
+<script>
+// import pdfvuer from "pdfvuer"; // pdfvuer 版本为@1.6.1
+// import "pdfjs-dist/build/pdf.worker.entry";
+// const PDF = require("pdfjs-dist");
+// PDF.GlobalWorkerOptions.workerSrc = "../../common/pdf.worker.js";
+
+export default {
+  name: "Pdfvuer",
+  components: {
+    // pdf: pdfvuer,
+  },
+  props: {
+    // 当前pdf路径
+    pdfUrl: {
+      type: String,
+      default:
+        "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/0629%E5%AE%9E%E6%97%B6%E8%AF%BE%E5%A0%82%E6%A8%A1%E6%8B%9F%E6%BC%94%E7%A4%BA%E8%AF%BE%E4%BB%B61656920880446.pdf",
+    },
+    ppage: {
+      type: Number,
+      default: 1,
+    },
+  },
+  data() {
+    return {
+      page: 1, // 当前页
+      numPages: 0, // 总页数
+      pdfData: undefined,
+      inputPage: 1, // 输入的页码
+      isloading: false,
+      scale: "page-width",
+    };
+  },
+  mounted() {
+    // this.isloading = this.$loading.service({
+    //   background: "rgba(255, 255, 255, 0.7)",
+    //   target: document.querySelector(".loading"),
+    //   text: "加载中...",
+    //   spinner: "",
+    // });
+    this.isloading = false;
+    this.$refs.viframe.onload = function () {
+      this.isloading = false
+    }
+    console.log(this.isloading);
+    // this.getPdf();
+  },
+  beforeDestroy() { },
+  watch: {
+    pdfUrl: function (s) {
+      // this.isloading = this.$loading.service({
+      //   background: "rgba(255, 255, 255, 0.7)",
+      //   target: document.querySelector(".loading"),
+      //   text: "加载中...",
+      //   spinner: "",
+      // });
+      this.isloading = false;
+      this.$refs.viframe.onload = function () {
+        this.isloading = false
+      }
+      // this.getPdf();
+    },
+  },
+  methods: {
+    // 获取 pdf 信息
+    getPdf() {
+      this.pdfData = pdfvuer.createLoadingTask({
+        url: this.pdfUrl,
+        cMapUrl: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/cmaps/",
+        cMapPacked: true,
+      });
+      this.pdfData
+        .then((pdf) => {
+          // this.isloading.close();
+          this.isloading = false
+          this.numPages = pdf.numPages;
+        })
+        .catch((err) => {
+          console.log(err);
+        });
+    },
+    // 上一页
+    prePage() {
+      let page = this.page;
+      page = page > 1 ? page - 1 : 1;
+      this.page = page;
+    },
+    // 下一页
+    nextPage() {
+      let page = this.page;
+      page = page < this.numPages ? page + 1 : this.numPages;
+      this.page = page;
+    },
+  },
+};
+</script>
+<style scoped>
+.loading {
+  height: 100%;
+  width: 100%;
+  /* background: #000; */
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* background-color: rgba(255, 255, 255, 0.7); */
+  background-color: rgba(255, 255, 255, 1);
+  z-index: 9;
+  font-size: 20px;
+  color: #007fff;
+}
+
+.pdf {
+  height: 100%;
+  width: 100%;
+  position: relative;
+  box-sizing: border-box;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.pdf .show {
+  margin: auto;
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.pdf .show .p-pdf {
+  overflow: hidden;
+}
+
+.pdf .show .p-pdf .line {
+  position: absolute;
+  width: 50px;
+  right: -50px;
+  background: rgb(255, 186, 96);
+  height: 2px;
+}
+
+.pdf .show .p-pdf span {
+  width: 100%;
+  text-align: center;
+  color: #fff;
+}
+
+.pdf .show .p-pdf span+span {
+  margin-top: 10px;
+}
+
+.pdfbox {
+  /* border: 3px solid #000; */
+  /* box-sizing: border-box; */
+  /* border-radius: 4px; */
+  /* overflow: hidden; */
+}
+
+.pdf .pdf_footer {
+  position: sticky;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 10px 0;
+  width: 100%;
+  height: 75px;
+  background-color: rgba(255, 255, 255, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.pdf .pdf_footer .info {
+  display: flex;
+  flex-wrap: wrap;
+  width: 100%;
+  justify-content: center;
+}
+
+.pdf .p-pdf .viewerContainer {
+  width: 100%;
+}
+
+/* .pdf .pdf_footer .info div {
+  width: 30%;
+} */
+.pdf .pdf_footer .operate {
+  margin: 10px 0 0;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  width: 100%;
+}
+
+.pdf .pdf_footer .operate div {
+  text-align: center;
+  font-size: 15px;
+}
+
+.pdf .pdf_footer .operate .btn {
+  cursor: pointer;
+  margin: 5px 10px;
+  width: 100px;
+  border-radius: 10px;
+  padding: 5px;
+  color: #fff;
+  background-color: #066ebe;
+}
+
+.pdf::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 6px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 6px;
+}
+
+/*定义滚动条轨道 内阴影+圆角*/
+.pdf::-webkit-scrollbar {
+  border-radius: 10px;
+  background-color: #b8bdc9;
+}
+
+/*定义滑块 内阴影+圆角*/
+.pdf::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgb(96, 125, 184);
+  background-color: #2c5ab3;
+}
+</style>

+ 201 - 0
src/components/pages/pocAiClassroom/component/vword.vue

@@ -0,0 +1,201 @@
+<template>
+  <!--使用 pdfvuer 实现 滑动浏览 单印章-->
+  <div class="pdf">
+    <div class="loading" v-if="isloading">
+      <span>可能会加载时间有点长,请耐心等待...</span>
+    </div>
+    <iframe
+      ref="viframe"
+      style="width: 100%; height: 100%; border: none"
+      :src="pdfUrl"
+    ></iframe>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: "Pdfvuer",
+  components: {
+    // pdf: pdfvuer,
+  },
+  props: {
+    // 当前pdf路径
+    pdfUrl: {
+      type: String,
+      default:
+        "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/0629%E5%AE%9E%E6%97%B6%E8%AF%BE%E5%A0%82%E6%A8%A1%E6%8B%9F%E6%BC%94%E7%A4%BA%E8%AF%BE%E4%BB%B61656920880446.pdf",
+    },
+    ppage: {
+      type: Number,
+      default: 1,
+    },
+  },
+  data() {
+    return {
+      page: 1, // 当前页
+      numPages: 0, // 总页数
+      pdfData: undefined,
+      inputPage: 1, // 输入的页码
+      isloading: false,
+      scale: "page-width",
+    };
+  },
+  mounted() {
+    let _this = this;
+    _this.isloading = true;
+    _this.$refs.viframe.onload = function () {
+      _this.isloading = false;
+    };
+    console.log(_this.isloading);
+    // this.getPdf();
+  },
+  beforeDestroy() {},
+  watch: {
+    pdfUrl: function (s) {
+      let _this = this;
+      _this.isloading = true;
+      _this.$refs.viframe.onload = function () {
+        _this.isloading = false;
+      };
+      console.log(_this.isloading);
+      // this.getPdf();
+    },
+  },
+  methods: {
+  },
+};
+</script>
+<style scoped>
+.loading {
+  height: 100%;
+  width: 100%;
+  /* background: #000; */
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  /* background-color: rgba(255, 255, 255, 0.7); */
+  background-color: rgba(255, 255, 255, 1);
+  z-index: 9;
+  font-size: 20px;
+  color: #007fff;
+}
+
+.pdf {
+  height: 100%;
+  width: 100%;
+  position: relative;
+  box-sizing: border-box;
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.pdf .show {
+  margin: auto;
+  width: 100%;
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.pdf .show .p-pdf {
+  overflow: hidden;
+}
+
+.pdf .show .p-pdf .line {
+  position: absolute;
+  width: 50px;
+  right: -50px;
+  background: rgb(255, 186, 96);
+  height: 2px;
+}
+
+.pdf .show .p-pdf span {
+  width: 100%;
+  text-align: center;
+  color: #fff;
+}
+
+.pdf .show .p-pdf span + span {
+  margin-top: 10px;
+}
+
+.pdfbox {
+  /* border: 3px solid #000; */
+  /* box-sizing: border-box; */
+  /* border-radius: 4px; */
+  /* overflow: hidden; */
+}
+
+.pdf .pdf_footer {
+  position: sticky;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 10px 0;
+  width: 100%;
+  height: 75px;
+  background-color: rgba(255, 255, 255, 0.5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  flex-direction: column;
+}
+
+.pdf .pdf_footer .info {
+  display: flex;
+  flex-wrap: wrap;
+  width: 100%;
+  justify-content: center;
+}
+
+.pdf .p-pdf .viewerContainer {
+  width: 100%;
+}
+
+/* .pdf .pdf_footer .info div {
+  width: 30%;
+} */
+.pdf .pdf_footer .operate {
+  margin: 10px 0 0;
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: center;
+  width: 100%;
+}
+
+.pdf .pdf_footer .operate div {
+  text-align: center;
+  font-size: 15px;
+}
+
+.pdf .pdf_footer .operate .btn {
+  cursor: pointer;
+  margin: 5px 10px;
+  width: 100px;
+  border-radius: 10px;
+  padding: 5px;
+  color: #fff;
+  background-color: #066ebe;
+}
+
+.pdf::-webkit-scrollbar {
+  /*滚动条整体样式*/
+  width: 6px;
+  /*高宽分别对应横竖滚动条的尺寸*/
+  height: 6px;
+}
+
+/*定义滚动条轨道 内阴影+圆角*/
+.pdf::-webkit-scrollbar {
+  border-radius: 10px;
+  background-color: #b8bdc9;
+}
+
+/*定义滑块 内阴影+圆角*/
+.pdf::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgb(96, 125, 184);
+  background-color: #2c5ab3;
+}
+</style>

+ 555 - 0
src/components/pages/pocAiClassroom/index.vue

@@ -0,0 +1,555 @@
+<template>
+  <div class="pocAiClass">
+    <div class="pac_head">
+      <div class="pac_h_left">
+        <span>八年级</span>><span>上学期</span>><span>{{
+          editionList[edition]
+        }}</span>
+      </div>
+      <div class="pac_h_right">
+        <span @click.stop="changeGrade()">切换年级</span>
+        <el-image
+          class="pac_h_r_avatar"
+          :src="require('../../../assets/icon/pocAiClass/avatar.svg')"
+        ></el-image>
+      </div>
+    </div>
+
+    <div class="pac_subjectList">
+      <span
+        :class="[subject == index ? 'pac_sl_active' : '']"
+        v-for="(item, index) in subjectList"
+        :key="index"
+        @click.stop="changeSubject(index)"
+        >{{ item }}</span
+      >
+    </div>
+
+    <div class="pac_editionList">
+      <span
+        :class="[edition == index ? 'pac_el_active' : '']"
+        v-for="(item, index) in editionList"
+        :key="index"
+        @click.stop="changeEdition(index)"
+        >{{ item }}</span
+      >
+    </div>
+
+    <div class="pac_box">
+      <chapterCard
+        v-for="(item, index) in classList"
+        :key="index"
+        :data="item"
+      />
+    </div>
+
+    <div class="pac_footDialog" v-if="showDialog">
+      <div class="pac_fd_left">
+        <el-image
+          class="pac_fd_l_hello"
+          :src="require('../../../assets/icon/pocAiClass/hello.gif')"
+        ></el-image>
+      </div>
+      <div class="pac_fd_right">
+        <div class="pac_fd_r_messageArea">
+          <div class="pac_fd_r_ma_message">
+            Hi,科科同学,欢迎回来!你是否开始下一课的学习,学习【运动的快慢】?
+          </div>
+          <div class="pac_fd_r_ma_btnArea">
+            <span @click.stop="dialogBtn(1)">好,开始学习新内容</span>
+            <span @click.stop="dialogBtn(2)">我想复习上一节课</span>
+            <span @click.stop="dialogBtn(3)">我想聊聊天</span>
+          </div>
+          <span class="pac_fd_r_ma_closeIcon" @click.stop="dialogBtn(0)"
+            >×</span
+          >
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import chapterCard from "./component/chapterCard.vue";
+export default {
+  components: {
+    chapterCard
+  },
+  data() {
+    return {
+			userId: this.$route.query.userid,
+      org: this.$route.query.org,
+      oid: this.$route.query.oid,
+      subject: 0,
+      edition: 0,
+      showDialog: true,
+      subjectList: [
+        "语文",
+        "数学",
+        "英语",
+        "物理",
+        "化学",
+        "生物",
+        "历史",
+        "地理",
+        "政治"
+      ],
+      editionList: [
+        "人教版",
+        "教科版",
+        "北师大版",
+        "苏教版",
+        "沪教版",
+        "浙教版",
+        "冀教版",
+        "鲁教版",
+        "人教A版",
+        "人教B版"
+      ],
+      classList: [
+        {
+          title: "第一章",
+          allClass: [
+            {
+              title: "长度和时间的测量",
+              type: 0,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            },
+            {
+              title: "运动的描述",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "运动的快慢",
+              type: 0,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            },
+            {
+              title: "测量平均速度",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "单元测试",
+              type: 1,
+              image:
+                "https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg"
+            }
+          ]
+        },
+        {
+          title: "第二章",
+          allClass: [
+            {
+              title: "长度和时间的测量",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "运动的描述",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "运动的快慢",
+              type: 0,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            },
+            {
+              title: "测量平均速度",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "单元测试",
+              type: 1,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "长度和时间的测量",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+            },
+            {
+              title: "运动的描述",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "运动的快慢",
+              type: 0,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            },
+            {
+              title: "测量平均速度",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg"
+            },
+            {
+              title: "单元测试",
+              type: 1,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            }
+          ]
+        },
+        {
+          title: "第三章",
+          allClass: [
+            {
+              title: "长度和时间的测量",
+              type: 0,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            },
+            {
+              title: "运动的描述",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "运动的快慢",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+            },
+            {
+              title: "测量平均速度",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+            },
+            {
+              title: "单元测试",
+              type: 1,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            }
+          ]
+        },
+        {
+          title: "第四章",
+          allClass: [
+            {
+              title: "长度和时间的测量",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+            },
+            {
+              title: "运动的描述",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "运动的快慢",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "测量平均速度",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "单元测试",
+              type: 1,
+              image:
+                "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+            }
+          ]
+        },
+        {
+          title: "第五章",
+          allClass: [
+            {
+              title: "长度和时间的测量",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"
+            },
+            {
+              title: "运动的描述",
+              type: 0,
+              image:
+                "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg"
+            },
+            {
+              title: "运动的快慢",
+              type: 0,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            },
+            {
+              title: "测量平均速度",
+              type: 0,
+              image:
+                "https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg"
+            },
+            {
+              title: "单元测试",
+              type: 1,
+              image:
+                "https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/%E6%B5%8B%E8%AF%951724727615916.jpg"
+            }
+          ]
+        }
+      ]
+    };
+  },
+  methods: {
+    changeGrade() {
+      console.log("切换年级");
+    },
+    changeSubject(newIndex) {
+      if (this.subject == newIndex) return;
+      this.subject = newIndex;
+    },
+    changeEdition(newIndex) {
+      if (this.edition == newIndex) return;
+      this.edition = newIndex;
+    },
+    dialogBtn(type = 0) {
+      if (type == 0) {
+        this.showDialog = false;
+      } else if (type == 1) {
+				this.$router.push(`/pocAiChat?userid=${this.userId}&org=${this.org}&oid=${this.oid}`)
+        // console.log("开始学习新的内容");
+      } else if (type == 2) {
+				this.$router.push(`/pocAiChat?userid=${this.userId}&org=${this.org}&oid=${this.oid}`)
+        // console.log("复习上一节课");
+      } else if (type == 3) {
+        this.$router.push(`/pocAiChat?userid=${this.userId}&org=${this.org}&oid=${this.oid}&type=3`)
+      }
+    }
+  }
+};
+</script>
+
+<style scoped>
+.pocAiClass {
+  width: 100vw;
+  height: 100vh;
+  overflow: auto;
+  background-image: radial-gradient(#bbcdff 0%, #bbcdff 1%, #e6dee9 100%);
+  box-sizing: border-box;
+  padding: 0 100px;
+}
+
+.pac_head {
+  width: 100%;
+  height: 70px;
+  margin-top: 30px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  box-sizing: border-box;
+}
+
+.pac_h_left {
+  width: auto;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 20px;
+}
+.pac_h_left > span {
+  margin: 0 5px;
+}
+
+.pac_h_right {
+  width: auto;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.pac_h_right > span {
+  padding: 8px 12px;
+  background-color: #d9d9d9;
+  border: solid 1px #fff;
+  font-size: 18px;
+  border-radius: 8px;
+  margin-right: 20px;
+  cursor: pointer;
+}
+
+.pac_h_r_avatar {
+  width: 50px;
+  height: 50px;
+}
+
+.pac_subjectList {
+  max-width: 100%;
+  height: 50px;
+  overflow: auto;
+  display: flex;
+  align-items: center;
+  margin-top: 20px;
+}
+
+.pac_subjectList > span {
+  width: auto;
+  height: 100%;
+  margin-right: 20px;
+  font-size: 28px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  cursor: pointer;
+  position: relative;
+  transition: all 0.3s;
+  white-space: nowrap;
+}
+
+.pac_sl_active {
+  color: #4874cb;
+}
+
+.pac_sl_active::after {
+  content: "";
+  width: 100%;
+  height: 5px;
+  border-radius: 5px;
+  background-color: #4874cb;
+  position: absolute;
+  bottom: 0px;
+  left: 0;
+}
+
+.pac_subjectList > span:hover {
+  color: #4874cb;
+}
+
+.pac_editionList {
+  max-width: 100%;
+  height: 50px;
+  overflow: auto;
+  display: flex;
+  align-items: center;
+  margin-top: 20px;
+}
+
+.pac_editionList > span {
+  padding: 7px 12px;
+  background-color: #f2f2f2;
+  border-radius: 10px;
+  font-size: 20px;
+  margin-right: 20px;
+  cursor: pointer;
+  transition: all 0.1s;
+  border: solid 1px #f2f2f2;
+  white-space: nowrap;
+}
+
+.pac_el_active {
+  background-color: #4874cb !important;
+  color: #fff;
+  border: solid 1px #2e54a1 !important;
+}
+
+.pac_box {
+  width: 100%;
+  height: auto;
+  margin-top: 20px;
+}
+
+.pac_footDialog {
+  width: calc(100% - 200px);
+  min-width: 900px;
+  height: 200px;
+  position: fixed;
+  bottom: 50px;
+  display: flex;
+  align-items: center;
+  /* background-color: red; */
+}
+
+.pac_fd_left {
+  width: 200px;
+  height: 200px;
+}
+
+.pac_fd_l_hello {
+  width: 100%;
+  height: 100%;
+}
+
+.pac_fd_right {
+  flex: 1;
+  height: 200px;
+  display: flex;
+  align-items: center;
+}
+
+.pac_fd_r_messageArea {
+  width: 100%;
+  height: 90%;
+  background-color: #dae3f5;
+  box-sizing: border-box;
+  padding: 30px 30px 20px 30px;
+  border: solid 3px #fff;
+  border-radius: 0 20px 0 0;
+  display: flex;
+  flex-direction: column;
+  justify-content: space-between;
+  position: relative;
+}
+.pac_fd_r_ma_message {
+  width: 100%;
+  flex: 1;
+  font-size: 26px;
+}
+
+.pac_fd_r_ma_btnArea {
+  width: 100%;
+  height: 50px;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+}
+
+.pac_fd_r_ma_btnArea > span {
+  margin-left: 30px;
+  background-color: #fff;
+  padding: 14px 20px;
+  border-radius: 10px;
+  cursor: pointer;
+  border: solid 2px #4874cb;
+}
+
+.pac_fd_r_ma_btnArea > span:nth-of-type(1) {
+  background-color: #4874cb;
+  color: #fff;
+}
+
+.pac_fd_r_ma_closeIcon {
+  font-size: 30px;
+  font-weight: bold;
+  position: absolute;
+  right: 10px;
+  top: 10px;
+  cursor: pointer;
+  color: #fff;
+}
+</style>

+ 91 - 0
src/components/pages/pocAiClassroom/startIndex.vue

@@ -0,0 +1,91 @@
+<template>
+	<div class="startIndex">
+		<div class="si_start">
+			<div class="si_s_heardImage"></div>
+			<div class="si_s_messageArea">
+				<span>Hi~同学!😆</span>
+				<span>我是智能学伴,是陪你学习和聊天的小伙伴!😎</span>
+				<span>有什么问题,你都可以随时召唤我🫡</span>
+				<span>请你先帮我取一个名字吧😜</span>
+			</div>
+			<div class="si_s_inputArea">
+				<div class="si_s_inputLeft"></div>
+				<span></span>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style scoped>
+.startIndex{
+	width: 100vw;
+	height: 100vh;
+	overflow: auto;
+	background-image: radial-gradient( #BBCDFF 0%, #BBCDFF 1%, #e6dee9 100%);
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	justify-content: center;
+}
+
+.si_start{
+	width: auto;
+	height: auto;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.si_s_messageArea{
+	display: flex;
+	flex-direction: column;
+	padding: 30px;
+	background-color: #fff;
+	border-radius: 10px;
+	border: solid 2px black;
+}
+
+.si_s_messageArea>span{
+	color:#6F93F0;
+	font-size: 20px;
+}
+
+.si_s_inputArea{
+	margin-top: 20px;
+	width: 250px;
+	height: 50px;
+	background-color: #fff;
+	border: solid 2px black;
+	border-radius: 0 10px 10px 10px;
+}
+.si_s_inputLeft{
+	width: 200px;
+	height: 50px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.si_s_inputArea>span{
+	width: 50px;
+	height: 50px;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	background-color: gray;
+}
+</style>

+ 18 - 1
src/router/index.js

@@ -132,6 +132,8 @@ import guide from '@/components/pages/pblCourse/guide'
 import testExamine from '@/components/pages/test/examine'
 import testPersonExamine from '@/components/pages/testPerson/examine'
 import csTest from '@/components/pages/csTest'
+import pocAiClassroom from '@/components/pages/pocAiClassroom'
+import pocAiChat from '@/components/pages/pocAiClassroom/chatArea'
 // 全局修改默认配置,点击空白处不能关闭弹窗
 ElementUI.Dialog.props.closeOnClickModal.default = false
 Vue.use(Router).use(ElementUI)
@@ -1134,6 +1136,21 @@ export default new Router({
 					meta:{
 						requireAuth:''//不需要鉴权
 					}
-				}
+				},{
+					path:"/pocAiClassroom",
+					name:"pocAiClassroom",
+					component:pocAiClassroom,
+					meta:{
+						requireAuth:''//不需要鉴权
+					}
+				},
+				{
+					path:"/pocAiChat",
+					name:"pocAiChat",
+					component:pocAiChat,
+					meta:{
+						requireAuth:''//不需要鉴权
+					}
+				},
     ]
 })