Bläddra i källkod

网页模拟器组件开发基本完成

靳炳淑 6 år sedan
förälder
incheckning
36535e1b12

+ 2 - 1
package.json

@@ -12,12 +12,13 @@
   },
   "dependencies": {
     "@gitgraph/js": "^1.3.3",
-    "buefy": "^0.7.1",
+    "buefy": "^0.8.13",
     "chart.js": "^2.7.3",
     "dayjs": "^1.7.8",
     "file-saver": "^2.0.1",
     "highlight.js": "^9.15.6",
     "marked": "^0.6.2",
+    "monaco-editor": "^0.20.0",
     "register-service-worker": "^1.5.2",
     "vue": "^2.5.17",
     "vue-chartjs": "^3.4.0",

+ 31 - 31
src/assets/scss/_variables.scss

@@ -3,32 +3,34 @@
 
 // Colors
 
-$black:        hsl(0, 0%, 4%) !default;
-$black-bis:    hsl(0, 0%, 7%) !default;
-$black-ter:    hsl(0, 0%, 14%) !default;
-
-$grey-darker:  hsl(0, 0%, 21%) !default;
-$grey-dark:    hsl(0, 0%, 29%) !default;
-$grey:         hsl(0, 0%, 48%) !default;
-$grey-light:   hsl(0, 0%, 71%) !default;
+$black: hsl(0, 0%, 4%) !default;
+$black-bis: hsl(0, 0%, 7%) !default;
+$black-ter: hsl(0, 0%, 14%) !default;
+
+$grey-darker: hsl(0, 0%, 21%) !default;
+$grey-dark: hsl(0, 0%, 29%) !default;
+$grey: hsl(0, 0%, 48%) !default;
+$grey-light: hsl(0, 0%, 71%) !default;
 $grey-lighter: hsl(0, 0%, 86%) !default;
 
-$white-ter:    hsl(0, 0%, 96%) !default;
-$white-bis:    hsl(0, 0%, 98%) !default;
-$white:        hsl(0, 0%, 100%) !default;
+$white-ter: hsl(0, 0%, 96%) !default;
+$white-bis: hsl(0, 0%, 98%) !default;
+$white: hsl(0, 0%, 100%) !default;
 
-$orange:       hsl(14,  100%, 53%) !default;
-$yellow:       hsl(48,  100%, 67%) !default;
-$green:        hsl(141, 71%,  48%) !default;
-$turquoise:    hsl(171, 100%, 41%) !default;
-$cyan:         hsl(204, 86%,  53%) !default;
-$blue:         hsl(217, 71%,  53%) !default;
-$purple:       hsl(271, 100%, 71%) !default;
-$red:          hsl(348, 100%, 61%) !default;
+$orange: hsl(14, 100%, 53%) !default;
+$yellow: hsl(48, 100%, 67%) !default;
+$green: hsl(141, 71%, 48%) !default;
+$turquoise: hsl(171, 100%, 41%) !default;
+$cyan: hsl(204, 86%, 53%) !default;
+$blue: hsl(217, 71%, 53%) !default;
+$purple: hsl(271, 100%, 71%) !default;
+$red: hsl(348, 100%, 61%) !default;
 
 // Typography
 
-$family-sans-serif: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif !default;
+$family-sans-serif: BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto",
+  "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+  "Helvetica", "Arial", sans-serif !default;
 $family-monospace: monospace !default;
 $render-mode: optimizeLegibility !default;
 
@@ -72,7 +74,6 @@ $speed: 86ms !default;
 
 $variable-columns: true !default;
 
-
 // The default Bulma derived variables are declared below
 
 $primary: $turquoise !default;
@@ -153,19 +154,18 @@ $size-normal: $size-6 !default;
 $size-medium: $size-5 !default;
 $size-large: $size-4 !default;
 
-
-
 // basic
 
-$default-shadow:0 3px 8px rgba(211, 215, 222, 0.4);
-$default-shadow-lighter:0 3px 8px rgba(211, 215, 222, 0.2);
+$default-shadow: 0 3px 8px rgba(211, 215, 222, 0.4);
+$default-shadow-lighter: 0 3px 8px rgba(211, 215, 222, 0.2);
+$default-shadow-darker: 0 3px 8px rgb(211, 215, 222);
 
-$default-radius:4px;
+$default-radius: 4px;
 
-$default-background:#f4f7fc;
+$default-background: #f4f7fc;
 
-$default-border-color:rgba(84, 66, 251, 0.56);
-$default-border:2px solid $default-border-color;
+$default-border-color: rgba(84, 66, 251, 0.56);
+$default-border: 2px solid $default-border-color;
 
-$default-margin:0.75rem;
-$default-margin-between:1.5rem;
+$default-margin: 0.75rem;
+$default-margin-between: 1.5rem;

+ 102 - 0
src/components/CodeInterpreter/Editor/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <div>
+    <div class="myEditor">
+      <div id="container" ref="container" style="height:520px"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+import * as monaco from "monaco-editor";
+export default {
+  name: "Editor",
+  props: {
+    codes: {
+      type: String,
+      default: function() {
+        return "<div>请编辑html内容</div>";
+      }
+    },
+    language: {
+      type: String,
+      default: function() {
+        return "html";
+      }
+    },
+    editorOptions: {
+      type: Object,
+      default: function() {
+        return {
+          selectOnLineNumbers: true,
+          roundedSelection: false,
+          readOnly: false, // 只读
+          cursorStyle: "line", //光标样式
+          automaticLayout: true, //自动布局
+          glyphMargin: true, //字形边缘
+          useTabStops: false,
+          fontSize: 28, //字体大小
+          autoIndent: true, //自动布局
+          wordWrap: "on",
+          wrappingIndent: "indent"
+          //quickSuggestionsDelay: 500,   //代码提示延时
+        };
+      }
+    }
+  },
+  data() {
+    return {
+      themeOption: [
+        {
+          value: "vs",
+          label: "默认"
+        },
+        {
+          value: "hc-black",
+          label: "高亮"
+        },
+        {
+          value: "vs-dark",
+          label: "深色"
+        }
+      ],
+      theme: "vs",
+      codesCopy: null //内容备份
+    };
+  },
+  methods: {
+    initEditor() {
+      console.log("init editor");
+      let self = this;
+      self.$refs.container.innerHTML = "";
+      self.monacoEditor = monaco.editor.create(self.$refs.container, {
+        value: self.codesCopy || self.codes,
+        language: self.language,
+        theme: self.theme, //vs, hc-black, or vs-dark
+        editorOptions: self.editorOptions
+      });
+      self.$emit("onMounted", self.monacoEditor); //编辑器创建完成回调
+      self.monacoEditor.onDidChangeModelContent(function(event) {
+        //编辑器内容change事件
+        self.codesCopy = self.monacoEditor.getValue();
+        self.$emit("onCodeChange", self.monacoEditor.getValue(), event);
+      });
+    },
+    RunResult() {
+      console.log(this.monacoEditor.getValue());
+    }
+    // themeChange(val) {
+    //   this.initEditor();
+    // }
+  },
+  mounted() {
+    let self = this;
+    //编辑器随窗口自适应
+    window.addEventListener("resize", function() {
+      self.initEditor();
+    });
+    this.initEditor();
+  }
+};
+</script>
+
+<style lang="scss" scoped></style>

+ 130 - 0
src/components/CodeInterpreter/index.vue

@@ -0,0 +1,130 @@
+<template>
+  <div class="code-itp">
+    <div id="editor-container">
+      <div class="editor-title">
+        <b-tag type="is-primary">源代码</b-tag>
+        <b-button @click="handleSubmit" type="is-success" size="is-small"
+          >运行</b-button
+        >
+      </div>
+      <div class="editor-wrapper">
+        <editor
+          :language="'html'"
+          :codes="htmlCodes"
+          @onMounted="htmlOnMounted"
+          @onCodeChange="htmlOnCodeChange"
+        />
+      </div>
+    </div>
+    <div id="iframe-container">
+      <div class="iframe-title"><b-tag type="is-primary">运行结果</b-tag></div>
+      <div id="iframe-wrapper"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+import Editor from "./Editor";
+export default {
+  name: "CodeInterpreter",
+  components: {
+    Editor
+  },
+  props: {},
+  data() {
+    return {
+      htmlCodes:
+        '<!DOCTYPE html>\r\n<html>\r\n<head>\r\n<meta charset="utf-8">\r\n<title>SEEC WEB</title>\r\n<style>\r\nbody\r\n{\r\n\tbackground-color:#d0e4fe;\r\n}\r\nh1\r\n{\r\n\tcolor:orange;\r\n\ttext-align:center;\r\n}\r\np\r\n{\r\n\tfont-family:"Times New Roman";\r\n\tfont-size:20px;\r\n}\r\n</style>\r\n</head>\r\n\r\n<body>\r\n\r\n<h1>CSS \u5b9e\u4f8b!</h1>\r\n<p>Hello, World</p>\r\n\r\n</body>\r\n</html>\r\n',
+      htmlEditor: null
+    };
+  },
+  methods: {
+    handleSubmit: function() {
+      this.setIframe(this.htmlCodes);
+    },
+    setIframe: function(rawCode) {
+      console.log("1 rawCode", rawCode);
+      // 处理rawCode
+      let patternHtml = /<html[^>]*>((.|[\n\r])*)<\/html>/im;
+      let patternHead = /<head[^>]*>((.|[\n\r])*)<\/head>/im;
+      let patternBody = /<body[^>]*>((.|[\n\r])*)<\/body>/im;
+
+      let code = rawCode;
+      let basepath = '<base href="//http://seec.seecoder.cn/" target="_blank">';
+
+      let code_matches_head = patternHead.exec(rawCode);
+      let code_matches_body = patternBody.exec(rawCode);
+
+      if (code_matches_head) {
+        code = code.replace("<head>", "<head>" + basepath);
+      } else if (patternHtml) {
+        code = code.replace("<html>", "<head>" + basepath + "</head>");
+      } else if (code_matches_body) {
+        code = code.replace("<body>", "<body>" + basepath);
+      }
+
+      let ifr = document.createElement("iframe");
+      ifr.setAttribute("frameborder", "0");
+      ifr.setAttribute("id", "iframeResult");
+      document.getElementById("iframe-wrapper").innerHTML = "";
+      document.getElementById("iframe-wrapper").appendChild(ifr);
+      document.getElementById("iframeResult").style.height = "100%";
+      document.getElementById("iframeResult").style.width = "100%";
+
+      // 在iframe中显示
+      let ifrw = ifr.contentWindow
+        ? ifr.contentWindow
+        : ifr.contentDocument.document
+        ? ifr.contentDocument.document
+        : ifr.contentDocument;
+      ifrw.document.open();
+      ifrw.document.write(code);
+      ifrw.document.close();
+    },
+
+    //---Editor--
+    htmlOnMounted(edit) {
+      this.htmlEditor = edit;
+    },
+    htmlOnCodeChange(value) {
+      this.htmlCodes = value;
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+@import "../../assets/scss/app";
+
+.code-itp {
+  display: flex;
+  padding: 0px 10px 10px 10px;
+  background-color: $default-background;
+  border: $default-border;
+}
+#editor-container {
+  width: 50%;
+  margin: 10px;
+}
+#iframe-container {
+  width: 50%;
+  margin: 10px;
+}
+
+.editor-title {
+  margin: 10px 0;
+  display: flex;
+  justify-content: space-between;
+}
+.editor-wrapper {
+  box-shadow: $default-shadow-darker;
+}
+
+.iframe-title {
+  margin: 10px 0;
+}
+#iframe-wrapper {
+  height: 520px;
+  box-shadow: $default-shadow-darker;
+}
+</style>

+ 23 - 10
src/layouts/courseLayouts/StudentMenu.vue

@@ -8,30 +8,43 @@
       <!--</router-link>-->
       <!--</li>-->
     </ul>
+    <p class="menu-label">学习</p>
+    <ul class="menu-list">
+      <li>
+        <router-link active-class="is-active" :to="`${prefix}/study/web`">
+          <img alt src="../../assets/icon/team.png" />web学习
+        </router-link>
+      </li>
+      <li>
+        <router-link active-class="is-active" :to="`${prefix}/study/git`">
+          <img alt src="../../assets/icon/team.png" />git学习
+        </router-link>
+      </li>
+    </ul>
     <p class="menu-label">作业</p>
     <ul class="menu-list">
       <li>
         <router-link active-class="is-active" :to="`${prefix}/code`">
-          <img alt="" src="../../assets/icon/laptop.png" />代码作业
+          <img alt src="../../assets/icon/laptop.png" />代码作业
         </router-link>
       </li>
       <li>
-        <router-link active-class="is-active" :to="`${prefix}/document`"
-          ><img alt="" src="../../assets/icon/file.png" />文档作业</router-link
-        >
+        <router-link active-class="is-active" :to="`${prefix}/document`">
+          <img alt src="../../assets/icon/file.png" />文档作业
+        </router-link>
       </li>
       <li>
-        <router-link active-class="is-active" :to="`${prefix}/review`"
-          ><img alt="" src="../../assets/icon/edit.png" />评审作业</router-link
-        >
+        <router-link active-class="is-active" :to="`${prefix}/review`">
+          <img alt src="../../assets/icon/edit.png" />评审作业
+        </router-link>
       </li>
     </ul>
     <p class="menu-label">小组</p>
     <ul class="menu-list">
       <li>
-        <router-link active-class="is-active" :to="`${prefix}/group`"
-          ><img alt="" src="../../assets/icon/team.png" />我的小组</router-link
-        >
+        <router-link active-class="is-active" :to="`${prefix}/group`">
+          <img alt src="../../assets/icon/team.png" />我的小组
+        </router-link>
       </li>
     </ul>
   </aside>

+ 1 - 0
src/router/name.js

@@ -5,3 +5,4 @@ export const TEACHER = "TEACHER";
 export const STUDENT = "STUDENT";
 export const TEACHER_COURSE = "TEACHER_COURSE";
 export const STUDENT_COURSE = "STUDENT_COURSE";
+export const STUDY = "STUDY";

+ 8 - 4
src/router/routes.js

@@ -255,13 +255,17 @@ export default [
         path: "review/:reviewId/doc/:docReviewId",
         component: () => import("@/views/student/Review/ReviewDocDetail")
       },
-      {
-        path: "code",
-        component: () => import("@/views/student/Code")
-      },
       {
         path: "group",
         component: () => import("@/views/student/Group")
+      },
+      {
+        path: "study/web",
+        component: () => import("@/views/student/StudyWeb")
+      },
+      {
+        path: "study/git",
+        component: () => import("@/views/student/StudyWeb")
       }
     ]
   },

+ 23 - 0
src/views/student/StudyWeb/index.vue

@@ -0,0 +1,23 @@
+<template>
+  <div><code-interpreter></code-interpreter></div>
+</template>
+
+<script>
+// import PageHeader from "@/components/PageHeader";
+// import PageBody from "@/components/PageBody/index";
+import CodeInterpreter from "@/components/CodeInterpreter/index";
+
+export default {
+  components: {
+    // PageBody,
+    // PageHeader,
+    CodeInterpreter
+  },
+  data() {
+    return {};
+  },
+  methods: {}
+};
+</script>
+
+<style></style>

+ 14 - 7
yarn.lock

@@ -1670,11 +1670,12 @@ browserslist@^4.0.0, browserslist@^4.3.4:
     electron-to-chromium "^1.3.92"
     node-releases "^1.1.1"
 
-buefy@^0.7.1:
-  version "0.7.1"
-  resolved "https://registry.npmjs.org/buefy/-/buefy-0.7.1.tgz#84ad090c4300b1e808db5e35d3e48fad76027d8c"
+buefy@^0.8.13:
+  version "0.8.13"
+  resolved "https://registry.npm.taobao.org/buefy/download/buefy-0.8.13.tgz#90ce1645807c15d81f584dc78a2090a0feb7a70b"
+  integrity sha1-kM4WRYB8FdgfWE3HiiCQoP63pws=
   dependencies:
-    bulma "0.7.2"
+    bulma "0.7.5"
 
 buffer-from@^1.0.0:
   version "1.1.1"
@@ -1704,9 +1705,10 @@ builtin-status-codes@^3.0.0:
   version "3.0.0"
   resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
 
-bulma@0.7.2:
-  version "0.7.2"
-  resolved "https://registry.npmjs.org/bulma/-/bulma-0.7.2.tgz#8e944377b74c7926558830d38d8e19eaf49f5fb6"
+bulma@0.7.5:
+  version "0.7.5"
+  resolved "https://registry.npm.taobao.org/bulma/download/bulma-0.7.5.tgz#35066c37f82c088b68f94450be758fc00a967208"
+  integrity sha1-NQZsN/gsCIto+URQvnWPwAqWcgg=
 
 bytes@3.0.0:
   version "3.0.0"
@@ -5297,6 +5299,11 @@ moment@^2.10.2:
   version "2.23.0"
   resolved "https://registry.yarnpkg.com/moment/-/moment-2.23.0.tgz#759ea491ac97d54bac5ad776996e2a58cc1bc225"
 
+monaco-editor@^0.20.0:
+  version "0.20.0"
+  resolved "https://registry.npm.taobao.org/monaco-editor/download/monaco-editor-0.20.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmonaco-editor%2Fdownload%2Fmonaco-editor-0.20.0.tgz#5d5009343a550124426cb4d965a4d27a348b4dea"
+  integrity sha1-XVAJNDpVASRCbLTZZaTSejSLTeo=
+
 morgan@^1.9.1:
   version "1.9.1"
   resolved "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59"