huangminghao 1 year ago
parent
commit
76e497bd4e

+ 1 - 1
dist/index.html

@@ -25,7 +25,7 @@
       height: 100%;
       width: 100%;
       background: #e6eaf0;
-    }</style><link href=./static/css/app.81fc81e9069b9bb75f00cb4eb37bc39f.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.4ae2783fdfe7ab52e4d5.js></script><script type=text/javascript src=./static/js/vendor.b01159b52abeac4e6216.js></script><script type=text/javascript src=./static/js/app.fd151ce48514b21ab03e.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.7d39d1129ee6e032f7753861b2ebcc5e.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3512a67a6213c2df4180.js></script><script type=text/javascript src=./static/js/vendor.b01159b52abeac4e6216.js></script><script type=text/javascript src=./static/js/app.88ff2b08164fbb48d965.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.7d39d1129ee6e032f7753861b2ebcc5e.css


File diff suppressed because it is too large
+ 0 - 0
dist/static/css/app.7d39d1129ee6e032f7753861b2ebcc5e.css.map


BIN
dist/static/img/isWord.a2e3b0c.png


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/0.7da288988865a9378b49.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/0.7da288988865a9378b49.js.map


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.88ff2b08164fbb48d965.js


File diff suppressed because it is too large
+ 0 - 0
dist/static/js/app.88ff2b08164fbb48d965.js.map


+ 2 - 0
dist/static/js/manifest.3512a67a6213c2df4180.js

@@ -0,0 +1,2 @@
+!function(e){var n=window.webpackJsonp;window.webpackJsonp=function(r,a,c){for(var i,u,f,s=0,l=[];s<r.length;s++)u=r[s],t[u]&&l.push(t[u][0]),t[u]=0;for(i in a)Object.prototype.hasOwnProperty.call(a,i)&&(e[i]=a[i]);for(n&&n(r,a,c);l.length;)l.shift()();if(c)for(s=0;s<c.length;s++)f=o(o.s=c[s]);return f};var r={},t={4:0};function o(n){if(r[n])return r[n].exports;var t=r[n]={i:n,l:!1,exports:{}};return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports}o.e=function(e){var n=t[e];if(0===n)return new Promise(function(e){e()});if(n)return n[2];var r=new Promise(function(r,o){n=t[e]=[r,o]});n[2]=r;var a=document.getElementsByTagName("head")[0],c=document.createElement("script");c.type="text/javascript",c.charset="utf-8",c.async=!0,c.timeout=12e4,o.nc&&c.setAttribute("nonce",o.nc),c.src=o.p+"static/js/"+e+"."+{0:"7da288988865a9378b49",1:"994623639438b244a74c"}[e]+".js";var i=setTimeout(u,12e4);function u(){c.onerror=c.onload=null,clearTimeout(i);var n=t[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}return c.onerror=c.onload=u,a.appendChild(c),r},o.m=e,o.c=r,o.d=function(e,n,r){o.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},o.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(n,"a",n),n},o.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},o.p="./",o.oe=function(e){throw console.error(e),e}}([]);
+//# sourceMappingURL=manifest.3512a67a6213c2df4180.js.map

File diff suppressed because it is too large
+ 0 - 0
dist/static/js/manifest.3512a67a6213c2df4180.js.map


BIN
src/assets/icon/fileIcon/deleteworks.png


BIN
src/assets/icon/fileIcon/isVideo.png


BIN
src/assets/icon/fileIcon/isWord.png


BIN
src/assets/icon/fileIcon/word2.png


+ 21 - 1
src/components/pages/test/add/components/checkOrder.vue

@@ -54,6 +54,12 @@
                                         :cJson="cJson" @setJson="setJson">
                                     </gapDialog>
                                 </div>
+                                <div v-if="item3.type == 5">
+                                    <fileX :cJson="item3.json"></fileX>
+                                    <fileDialog v-if="item3.type == 5 && checkC === `x${index1}-${index2}-${index3}`"
+                                        :cJson="cJson" @setJson="setJson">
+                                    </fileDialog>
+                                </div>
                             </div>
                         </div>
                     </div>
@@ -69,6 +75,11 @@
                             <gapDialog v-if="item2.type == 3 && checkC === `x${index1}-${index2}`" :cJson="cJson"
                                 @setJson="setJson"></gapDialog>
                         </div>
+                        <div v-else-if="item2.type == 5">
+                            <fileX :cJson="item2.json"></fileX>
+                            <fileDialog v-if="item2.type == 5 && checkC === `x${index1}-${index2}`" :cJson="cJson"
+                                @setJson="setJson"></fileDialog>
+                        </div>
                     </div>
                 </div>
             </div>
@@ -83,6 +94,11 @@
                     <gapDialog v-if="item1.type == 3 && checkC === `x${index1}`" :cJson="cJson" @setJson="setJson">
                     </gapDialog>
                 </div>
+                <div v-else-if="item1.type == 5">
+                    <fileX :cJson="item1.json"></fileX>
+                    <fileDialog v-if="item1.type == 5 && checkC === `x${index1}`" :cJson="cJson" @setJson="setJson">
+                    </fileDialog>
+                </div>
             </div>
         </div>
     </div>
@@ -94,6 +110,8 @@ import choiceDialog from './choice/index.vue'
 import choiceX from './choice/choice.vue'
 import gapDialog from './GapFilling/index.vue'
 import gapX from './GapFilling/gap.vue'
+import fileDialog from './file/index.vue'
+import fileX from './file/file.vue'
 
 export default {
     mixins: [minxinVue],
@@ -102,6 +120,8 @@ export default {
         choiceX,
         gapDialog,
         gapX,
+        fileDialog,
+        fileX,
     },
     props: {
         checkJson: {
@@ -119,7 +139,7 @@ export default {
         return {
             manualJson: [],
             isdrag: "",
-            canEdit: [1, 3],
+            canEdit: [1, 3, 5],
             ctype: "",
             cJson: {}
         }

+ 101 - 0
src/components/pages/test/add/components/file/file.vue

@@ -0,0 +1,101 @@
+<template>
+    <div class="c_box">
+        <div class="mask"></div>
+        <div v-if="!cJson">暂未设置题目</div>
+        <div v-else class="choice_box">
+            <!-- <div class="title"><div>{{ `(${option[cJson.type].name})` }}</div><div v-html="cJson.title"></div></div> -->
+            <div class="title">
+                {{ `(${option[cJson.type].name})` + cJson.title }} <span style="color: #efa030;" v-if="cJson.score">({{ cJson.score ? '分值:'+cJson.score+'分' : '' }})</span>
+                <!-- </div><div v-html="cJson.title"></div> -->
+            </div>
+            <div class="detail" v-if="cJson.detail">
+                {{ cJson.detail }}
+            </div>
+            <div class="choices">
+                <div class="binfo_input">
+                    <div><span>填写者上传区</span></div>
+                </div>
+                <!-- <textarea readonly rows="2" class="binfo_input binfo_textarea" cols
+                    placeholder=""></textarea> -->
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+export default {
+    props: {
+        cJson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            option: {
+                1: { name: '附件' },
+                // 2: { name: '多选题' }
+            }
+        }
+    },
+}
+</script>
+
+<style scoped>
+.c_box {
+    width: 100%;
+    position: relative;
+}
+.mask{
+    position: absolute;
+    height: 100%;
+    width: 100%;
+    z-index: 2;
+}
+.choice_box {}
+
+.choice_box>.title {
+    font-weight: bold;
+    width: 100%;
+    word-break: break-all;
+}
+.choice_box>.detail {
+    width: 100%;
+    word-break: break-all;
+    color: rgb(136, 139, 146);
+    margin: 10px 0 0;
+}
+.choice_box>.choices {
+   margin-top:10px;
+}
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 12px 14px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 120px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_input > div{
+    border: 1px dashed #CAD1DC;
+    height: 120px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgb(243, 244, 246);
+    color:rgb(124, 124, 124);
+    border-radius: 5px;
+}
+</style>

+ 208 - 0
src/components/pages/test/add/components/file/index.vue

@@ -0,0 +1,208 @@
+<template>
+    <div class="choice_box jiao" @click.stop="">
+        <div class="title">设置附件</div>
+        <div class="box">
+            <div class="set_type">
+                <span>附件类型:</span>
+                <el-select v-model="checkJson.type" @change="changeAnswer">
+                    <el-option v-for="item in options" :key="item.type" :label="item.name" :value="item.type">
+                    </el-option>
+                </el-select>
+            </div>
+            <div class="set_type">
+                <span>设置分数:</span><el-input v-model="checkJson.score" class="input" placeholder="请输入分数" style="width: 120px"  @change="numberPan"></el-input>
+            </div>
+            <div class="set_title">
+                <span>附件题目:</span>
+                <!-- <el-input v-model="checkJson.title" class="input" placeholder="请输入标题"></el-input> -->
+                <textarea v-autoHeight="68" rows="2" class="binfo_input binfo_textarea" cols v-model="checkJson.title"
+                    placeholder=""></textarea>
+                <!-- <editor-bar v-model="checkJson.title" @change="change"></editor-bar> -->
+            </div>
+            <div class="set_title">
+                <span>附件描述:</span>
+                <textarea v-autoHeight="68" rows="2" class="binfo_input binfo_textarea" cols v-model="checkJson.detail"
+                    placeholder="请输入答案"></textarea>
+            </div>
+            <!-- <div class="set_options">
+                <div class="title">附件答案:</div>
+                <div class="xuan_body">
+                    <el-input v-model="checkJson.answer" class="input" placeholder="请输入答案"></el-input>
+                </div>
+            </div> -->
+        </div>
+    </div>
+</template>
+
+<script>
+// import EditorBar from "../../../../../tools/wangEnduit";
+export default {
+    components: {
+        // EditorBar,
+    },
+    props: {
+        cJson: {
+            type: Object,
+        },
+    },
+    data() {
+        return {
+            ctype: 1,
+            options: [
+                { type: 1, name: '附件' },
+                // { type: 2, name: '多选题' }
+            ],
+            checkJson: {}
+        }
+    },
+    directives: {
+        autoHeight: {
+            update(el, binding) {
+                const { value } = binding
+                if (value && typeof value === 'number') {
+                    el.style.height = `${value}px`
+                } else {
+                    el.style.height = 'auto'
+                }
+            },
+            componentUpdated(el) {
+                el.style.height = `${el.scrollHeight + 5}px`
+            },
+        },
+    },
+    watch: {
+        checkJson: {
+            handler(newVal) {
+                this.$emit("setJson", newVal)
+            },
+            deep: true
+        }
+    },
+    methods: {
+        depthCopy(s) {
+            return JSON.parse(JSON.stringify(s));
+        },
+        numberPan() {
+            if (/[^\d]/.test(this.checkJson.score) || this.checkJson.score < 0) {
+                this.$message.error('请输入大于0的数字')
+                this.checkJson.score = ''
+            }
+        },
+        changeAnswer() {
+            this.checkJson.answer = []
+        },
+        change(val) {
+            this.checkJson.title = val
+            this.$forceUpdate();
+            console.log(val);
+        },
+
+    },
+    mounted() {
+        console.log(1);
+        // console.log(this.cJson);
+        if (!this.cJson) {
+            this.checkJson = {
+                title: "标题",
+                type: 1,
+                detail: ""
+            };
+        } else {
+            this.checkJson = this.depthCopy(this.cJson);
+        }
+
+    },
+}
+</script>
+
+<style scoped>
+.choice_box {
+    margin-top: 20px;
+    width: 100%;
+    background: #f6f6f6;
+    padding: 10px;
+    box-sizing: border-box;
+    position: relative;
+}
+
+.choice_box>.box {}
+
+.set_type {
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+}
+
+.set_title {
+    margin-top: 10px;
+    display: flex;
+    align-items: flex-start;
+    /* flex-direction: column; */
+}
+
+.set_type>span,
+.set_title>span {
+    min-width: fit-content;
+    font-size: 15px;
+    min-width: 90px;
+    text-align: right;
+}
+
+.set_options {
+    margin-top: 10px;
+}
+
+.set_options>.title {
+    font-size: 15px;
+}
+
+.xuan_body {
+    margin-top: 10px;
+    font-size: 14px;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 12px 14px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 48px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+}
+
+.binfo_textarea {
+    border: 1.5px solid #CAD1DC;
+    font-size: 16px;
+    resize: none;
+    /* background: #f6f6f6; */
+    font-family: 'Microsoft YaHei';
+}
+
+.binfo_input:focus-visible {
+    border: 1.5px solid #3681FC !important;
+}
+
+.jiao::before{
+    content: '';
+    position: absolute;
+    width: 0px;
+    height: 0px;
+    top: -20px;
+    left: 15px;
+    border-left: 12px solid transparent;
+    border-right: 12px solid transparent;
+    border-bottom: 10px solid #f6f6f6;
+    border-top: 10px solid transparent;
+}
+</style>

+ 485 - 0
src/components/pages/test/add/edit/check/file.vue

@@ -0,0 +1,485 @@
+<template>
+    <div class="c_box">
+        <!-- <div class="mask"></div> -->
+        <div v-if="!checkJson">暂未设置题目</div>
+        <div v-else class="choice_box">
+            <!-- <div class="title"><div>{{ `(${option[checkJson.type].name})` }}</div><div v-html="checkJson.title"></div></div> -->
+            <div class="title">
+                {{ `(${option[checkJson.type].name})` + checkJson.title }}<span style="color: #efa030;"
+                    v-if="checkJson.score">({{ '分值:' + checkJson.score + '分' }})</span>
+                <!-- </div><div v-html="checkJson.title"></div> -->
+            </div>
+            <div class="choices">
+                <div class="binfo_input">
+                    <div class="fileBox" v-if="checkJson.file && checkJson.file.length">
+                        <div class="fileC">
+                            <div class="file" v-for="(item, index) in checkJson.file" :key="index">
+                                <img class="del" src="../../../../../../assets/icon/fileIcon/deleteworks.png" @click.stop="delFile(index)" />
+                                <img class="img" :src="wordIcon" alt="" v-if="item.type == 1" />
+                                <img class="img" :src="videoIcon" alt="" v-if="item.type == 2" />
+                                <img class="img" :src="item.url" alt="" v-if="item.type == 3" />
+                                <img class="img" :src="wordIcon" alt="" v-if="item.type == 4" />
+                                <img class="img" :src="fileIcon" alt="" v-if="item.type == 5" />
+                                <div class="name">
+                                    <el-tooltip :content="item.name" placement="top" effect="dark">
+                                       <span>{{ item.name }}</span>
+                                    </el-tooltip>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="btn" @click.stop="addImg($event)">
+                            <span>点击添加本地文件</span>
+                            <input type="file" accept="*" style="display: none" @change="beforeUpload($event)" />
+                        </div>
+                    </div>
+                    <div class="uploadQ" @click.stop="addImg($event)" v-else>
+                        <span>点击添加本地文件</span>
+                        <input type="file" accept="*" style="display: none" @change="beforeUpload($event)" />
+                    </div>
+                    <div v-if="proVisible" class="mask">
+                        <div class="progressBox">
+                            <div class="lbox">
+                                <img src="../../../../../../assets/loading.gif" />上传中,请稍后
+                            </div>
+                            <div style="margin-bottom: 10px">
+                                <span>{{
+                                    isFinishSize
+                                }}M</span>
+                                /
+                                <span>{{
+                                    isAllSize
+                                }}M</span>
+                            </div>
+                            <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                                ? progress
+                                : 0
+                                " style="width: 80%"></el-progress>
+                        </div>
+                    </div>
+                </div>
+                <!-- <textarea  :readonly="checktype == 2" rows="2" v-autoHeight="68" class="binfo_input binfo_textarea" cols v-model="checkJson.answer2"
+                    placeholder=""></textarea> -->
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import "../../../../../../common/aws-sdk-2.235.1.min.js";
+
+import videoIcon from '../../../../../../assets/icon/fileIcon/isVideo.png'
+import wordIcon from '../../../../../../assets/icon/fileIcon/isWord.png'
+import fileIcon from '../../../../../../assets/icon/fileIcon/word2.png'
+export default {
+    props: {
+        cJson: {
+            type: Object,
+        },
+        checktype: {
+            type: Number,
+            default: 1
+        },
+        see: {
+            type: Boolean,
+            default: false
+        }
+    },
+    data() {
+        return {
+            option: {
+                1: { name: '附件' },
+            },
+            checkJson: undefined,
+            progress: 0,
+            isFinishSize: 0,
+            proVisible: false,
+            isAllSize: 0,
+            videoIcon: videoIcon,
+            wordIcon: wordIcon,
+            fileIcon: fileIcon,
+        }
+    },
+    watch: {
+        checkJson: {
+            handler(newValue) {
+                this.$emit('update:cJson', newValue)
+            },
+            deep: true
+        },
+    },
+    methods: {
+        depthCopy(s) {
+            return JSON.parse(JSON.stringify(s));
+        },
+        addImg(e) {
+            var el = e.currentTarget;
+            el.getElementsByTagName("input")[0].click();
+            e.target.value = "";
+        },
+        beforeUpload(event, type) {
+            // const loading = this.openLoading();
+            var file = event.target.files[0];
+            var credentials = {
+                accessKeyId: "AKIATLPEDU37QV5CHLMH",
+                secretAccessKey: "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",
+            }; //秘钥形式的登录上传
+            window.AWS.config.update(credentials);
+            window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+            var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+            var _this = this;
+
+            _this.progress = 0;
+            _this.proVisible = true;
+            _this.isFinishSize = 0;
+            _this.isAllSize = (file.size / 1024 / 1024).toFixed(2);
+            _this.$forceUpdate();
+            if (file) {
+                var params = {
+                    Key:
+                        file.name.split(".")[0] +
+                        new Date().getTime() +
+                        "." +
+                        file.name.split(".")[file.name.split(".").length - 1],
+                    ContentType: file.type,
+                    Body: file,
+                    "Access-Control-Allow-Credentials": "*",
+                    ACL: "public-read",
+                }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+                var options = {
+                    partSize: 2048 * 1024 * 1024,
+                    queueSize: 2,
+                    leavePartsOnError: true,
+                };
+                bucket
+                    .upload(params, options)
+                    .on("httpUploadProgress", function (evt) {
+                        //这里可以写进度条
+                        // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+                        _this.progress = parseInt((evt.loaded / evt.total) * 100);
+                        _this.isFinishSize = (evt.loaded / 1024 / 1024).toFixed(2);
+                        _this.$forceUpdate();
+                    })
+                    .send(function (err, data) {
+                        _this.progress = 100;
+                        _this.isFinishSize = _this.isAllSize;
+                        _this.$forceUpdate();
+                        setTimeout(() => {
+                            _this.proVisible = false;
+                            _this.$forceUpdate();
+                        }, 1000);
+                        // loading.close();
+                        if (err) {
+                            _this.$message.error("上传失败");
+                        } else {
+                            let _type = 2;
+                            var imgA = [
+                                "png",
+                                "jpg",
+                                "jpeg",
+                                "bmp",
+                                "gif",
+                                "webp",
+                                "psd",
+                                "svg",
+                                "tiff",
+                            ];
+                            var fileA = [
+                                "DOC",
+                                "DOCX",
+                                "DOCM",
+                                "DOTM",
+                                "DOTX",
+                                "PPTX",
+                                "PPSX",
+                                "PPT",
+                                "PPS",
+                                "PPTM",
+                                "POTM",
+                                "PPAM",
+                                "POTX",
+                                "PPSM",
+                                "XLSX",
+                                "XLS",
+                            ];
+                            var videoA = [
+                                "AVI",
+                                "NAVI",
+                                "MPEG",
+                                "ASF",
+                                "MOV",
+                                "WMV",
+                                "3GP",
+                                "RM",
+                                "RMVB",
+                                "FLV",
+                                "F4V",
+                                "H.264",
+                                "H.265",
+                                "REAL VIDEO",
+                                "MKV",
+                                "WebM",
+                                "HDDVD",
+                                "MP4",
+                                "MPG",
+                                "M4V",
+                                "MGV",
+                                "OGV",
+                                "QTM",
+                                "STR",
+                                "AMC",
+                                "DVX",
+                                "EVO",
+                                "DAT",
+                                "OGG",
+                                "OGM",
+                            ];
+                            if (
+                                fileA.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleUpperCase()
+                                ) != -1
+                            ) {
+                                _type = 1; //word 文件
+                            } else if (
+                                videoA.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleUpperCase()
+                                ) != -1
+                            ) {
+                                _type = 2; //视频
+                            } else if (
+                                imgA.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleLowerCase()
+                                ) != -1
+                            ) {
+                                _type = 3; //图片
+                            } else if (
+                                'PDF'.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleLowerCase()
+                                ) != -1
+                            ) {
+                                _type = 4; //pdf
+                            } else {
+                                _type = 5; //文件
+                            }
+                            if (_this.checkJson.file) {
+                                _this.checkJson.file.push({
+                                    name: file.name,
+                                    url: data.Location,
+                                    type: _type,
+                                });
+                            } else {
+                                _this.checkJson.file = []
+                                _this.checkJson.file.push({
+                                    name: file.name,
+                                    url: data.Location,
+                                    type: _type,
+                                });
+                            }
+                            _this.$forceUpdate();
+
+                            console.log(_this.checkJson);
+                            console.log(data.Location);
+                        }
+                    });
+            }
+        },
+        delFile(index){
+            this.checkJson.file.splice(index,1)
+        }
+    },
+    mounted() {
+        this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined
+
+    }
+}
+</script>
+
+<style scoped>
+.c_box {
+    width: 100%;
+    position: relative;
+}
+
+.mask {
+    position: absolute;
+    height: 100%;
+    width: 100%;
+    z-index: 2;
+}
+
+.choice_box {}
+
+.choice_box>.title {
+    font-weight: bold;
+    width: 100%;
+    word-break: break-all;
+}
+
+.choice_box>.choices {
+    margin-top: 10px;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 12px 14px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 120px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+    position: relative;
+}
+
+.binfo_input>.uploadQ {
+    border: 1px dashed #CAD1DC;
+    height: 120px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgb(243, 244, 246);
+    color: rgb(124, 124, 124);
+    border-radius: 5px;
+    cursor: pointer;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+.binfo_input>.fileBox {}
+
+.binfo_input>.fileBox .fileC {
+    display: flex;
+    flex-wrap: wrap;
+    width: 100%;
+    cursor: pointer;
+}
+
+.binfo_input>.fileBox .fileC>.file {
+    width: 200px;
+    height: 140px;
+    margin: 10px 10px 10px 0px;
+    border-radius: 15px;
+    box-shadow: rgb(223, 218, 218) 0px 0px 6px 1px;
+    overflow: hidden;
+    margin-right: 15px;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+}
+.binfo_input>.fileBox .fileC>.file > .img{
+    width: 100%;
+    height: calc(100% - 35px);
+    object-fit: cover;
+}
+.binfo_input>.fileBox .fileC>.file > .del{
+    position: absolute;
+    width: 25px;
+    top: 10px;
+    right: 10px;
+    cursor: pointer;
+}
+.binfo_input>.fileBox .fileC>.file > .name{
+    height: 35px;
+    width: 100%;
+    background: #f9f9f9;
+    display: flex;
+    align-items: center;
+    padding: 0 10px;
+    box-sizing: border-box;
+}
+.binfo_input>.fileBox .fileC>.file > .name > span{
+    display: block;
+    text-overflow: ellipsis;
+    max-width: 100%;
+    white-space: nowrap;
+    overflow: hidden;
+}
+
+.binfo_input>.fileBox .btn {
+    width: 100%;
+    height: 40px;
+    background: #007bff;
+    color: #fff;
+    border-radius: 15px;
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+</style>

+ 1 - 1
src/components/pages/test/add/edit/check/gap.vue

@@ -69,7 +69,7 @@ export default {
     },
     mounted() {
         this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined
-        if(this.checkJson.answer2){
+        if(this.checkJson && this.checkJson.answer2){
             setTimeout(() => {
                 this.checkJson.answer2 += "*0*%*";
                 setTimeout(() => {

+ 9 - 2
src/components/pages/test/add/edit/check/index.vue

@@ -9,6 +9,7 @@
           <div v-if="item.ttype == 1" class="answerBox">
             <choiceV :cJson.sync="item.json" v-if="item.type == 1"></choiceV>
             <gapV :cJson.sync="item.json" v-if="item.type == 3"></gapV>
+            <fileV :cJson.sync="item.json" v-if="item.type == 5"></fileV>
             <span v-else>暂未设置题目</span>
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -16,6 +17,7 @@
             <div v-if="item2.ttype == 1" class="answerBox">
               <choiceV :cJson.sync="item2.json" v-if="item2.type == 1"></choiceV>
               <gapV :cJson.sync="item2.json" v-if="item2.type == 3"></gapV>
+              <fileV :cJson.sync="item2.json" v-if="item2.type == 5"></fileV>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -27,6 +29,7 @@
           <div v-if="item.ttype == 1" class="answerBox">
             <choiceV :cJson.sync="item.json" v-if="item.type == 1"></choiceV>
             <gapV :cJson.sync="item.json" v-if="item.type == 3"></gapV>
+            <fileV :cJson.sync="item.json" v-if="item.type == 5"></fileV>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -34,6 +37,7 @@
             <div v-if="item2.ttype == 1" class="answerBox">
               <choiceV :cJson.sync="item2.json" v-if="item2.type == 1"></choiceV>
               <gapV :cJson.sync="item2.json" v-if="item2.type == 3"></gapV>
+              <fileV :cJson.sync="item2.json" v-if="item2.type == 5"></fileV>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -53,6 +57,7 @@
 <script>
 import choiceV from './choice.vue';
 import gapV from './gap.vue';
+import fileV from './file.vue';
 export default {
   props: {
     cJson: {
@@ -64,7 +69,8 @@ export default {
   },
   components: {
     choiceV,
-    gapV
+    gapV,
+    fileV
   },
   data() {
     return {
@@ -75,7 +81,8 @@ export default {
         1: "选择题",
         // 2: "问答题",
         3: "问答题",
-        4: "添加文档"
+        4: "添加文档",
+        5: "附件",
       },
     }
   },

+ 6 - 1
src/components/pages/test/add/minxins/minxin.js

@@ -18,12 +18,17 @@ const minxin = {
         //   value: 4,
         //   label: "添加文档"
         // }
+        {
+          value: 5,
+          label: "附件"
+        },
       ],
       options2: {
         1: "选择题",
         // 2: "问答题",
         3: "问答题",
-        4: "添加文档"
+        4: "添加文档",
+        5: "附件"
       },
       buttonOptions: [
         { name: "分组", type: 1 },

+ 8 - 4
src/components/pages/testStudent/index.vue

@@ -50,8 +50,8 @@
                 <el-tooltip :content="item.title" placement="top" effect="dark">
                   <span>{{ item.title }}</span>
                 </el-tooltip>
-                <span :class="{ is: item.testCount > 0 && item.type != 3, no: item.testCount == 0, isR: item.type == 3 }">{{
-                  item.testCount > 0 ? item.type == 3 ? "已批改" : "已完成" : "未完成" }}</span>
+                <span :class="{ is: item.testCount > 0 && item.type == 2, no: item.testCount == 0, isR: item.type == 3, isS: item.type == 1 }">{{
+                  item.testCount > 0 ? item.type == 3 ? "已批改" : item.type == 1 ? "已保存" : "已完成" : "未完成" }}</span>
               </div>
               <div class="kc_t">创建人:{{ item.uname }}</div>
               <div class="kc_time">
@@ -62,8 +62,8 @@
               </div>
             </div>
             <div class="three_bottom">
-              <div @click="checkTest(item.courseId)" v-if="item.testCount > 0">查看答题</div>
-              <div @click="goToCourse2(item.courseId)">{{ item.testCount > 0 ? '重新答题' : '进入答题' }}</div>
+              <div @click="checkTest(item.courseId)" v-if="item.type == 3 || item.type == 2">查看答题</div>
+              <div @click="goToCourse2(item.courseId)">{{ item.testCount > 0 ? item.type == 1 ? '继续答题' : '重新答题' : '进入答题' }}</div>
             </div>
           </div>
           <div class="course_empty" v-if="course.length == 0">暂无数据</div>
@@ -977,6 +977,10 @@ export default {
   color: #0061FF;
 }
 
+.bottom_box>.title>.isS {
+  color: #ffad20;
+}
+
 .tup {
   width: 100%;
   height: 141.06px;

+ 588 - 0
src/components/pages/testStudent/view/component/file.vue

@@ -0,0 +1,588 @@
+<template>
+    <div class="c_box">
+        <!-- <div class="mask"></div> -->
+        <div v-if="!checkJson">暂未设置题目</div>
+        <div v-else class="choice_box">
+            <!-- <div class="title"><div>{{ `(${option[checkJson.type].name})` }}</div><div v-html="checkJson.title"></div></div> -->
+            <div class="c_title">
+                <div class="title">
+                    {{ `(${option[checkJson.type].name})` + checkJson.title }}<span style="color: #efa030;"
+                        v-if="checkJson.score">({{ '分值:' + checkJson.score + '分' }})</span>
+                </div>
+
+                <!-- </div><div v-html="checkJson.title"></div> -->
+                <div class="p_box" v-if="isTeacher == 1 && checkJson.score">
+                    <el-input v-model="checkJson.score2" class="c_input" @change="numberPan"
+                        placeholder="请输入得分"></el-input><span style="margin: 0 10px;">/</span><span>{{ checkJson.score
+                        }}分</span>
+                </div>
+                <div class="p_box" v-if="isTeacher == 2 && checkJson.score2">
+                    <span>{{ checkJson.score2 }}分</span><span style="margin: 0 10px;">/</span><span>{{ checkJson.score
+                    }}分</span>
+                </div>
+            </div>
+            <div class="choices">
+                <div class="binfo_input">
+                    <div class="fileBox" v-if="checkJson.file && checkJson.file.length">
+                        <div class="fileC">
+                            <div class="file" v-for="(item, index) in checkJson.file" :key="index"
+                                @click.stop="downloadFile(item)" v-loading="downLoading == item.url">
+                                <img class="del" src="../../../../../assets/icon/fileIcon/deleteworks.png"
+                                    @click.stop="delFile(index)" v-if="checktype == 1" />
+                                <img class="img" :src="wordIcon" alt="" v-if="item.type == 1" />
+                                <img class="img" :src="videoIcon" alt="" v-if="item.type == 2" />
+                                <img class="img" :src="item.url" alt="" v-if="item.type == 3" />
+                                <img class="img" :src="wordIcon" alt="" v-if="item.type == 4" />
+                                <img class="img" :src="fileIcon" alt="" v-if="item.type == 5" />
+                                <div class="name">
+                                    <el-tooltip :content="item.name" placement="top" effect="dark">
+                                        <span>{{ item.name }}</span>
+                                    </el-tooltip>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="btn" @click.stop="addImg($event)" v-if="checktype == 1">
+                            <span>点击添加本地文件</span>
+                            <input type="file" accept="*" style="display: none" @change="beforeUpload($event)" />
+                        </div>
+                    </div>
+                    <div class="uploadQ" @click.stop="addImg($event)" v-else-if="checktype == 1">
+                        <span>点击添加本地文件</span>
+                        <input type="file" accept="*" style="display: none" @change="beforeUpload($event)" />
+                    </div>
+                    <div class="uploadQ" v-else>
+                        <span>暂无添加附件</span>
+                    </div>
+                    <div v-if="proVisible" class="mask">
+                        <div class="progressBox">
+                            <div class="lbox">
+                                <img src="../../../../../assets/loading.gif" />上传中,请稍后
+                            </div>
+                            <div style="margin-bottom: 10px">
+                                <span>{{
+                                    isFinishSize
+                                }}M</span>
+                                /
+                                <span>{{
+                                    isAllSize
+                                }}M</span>
+                            </div>
+                            <el-progress :text-inside="true" :stroke-width="20" :percentage="progress
+                                ? progress
+                                : 0
+                                " style="width: 80%"></el-progress>
+                        </div>
+                    </div>
+                </div>
+                <!-- <textarea  :readonly="checktype == 2" rows="2" v-autoHeight="68" class="binfo_input binfo_textarea" cols v-model="checkJson.answer2"
+                    placeholder=""></textarea> -->
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+import "../../../../../common/aws-sdk-2.235.1.min.js";
+
+import videoIcon from '../../../../../assets/icon/fileIcon/isVideo.png'
+import wordIcon from '../../../../../assets/icon/fileIcon/isWord.png'
+import fileIcon from '../../../../../assets/icon/fileIcon/word2.png'
+export default {
+    props: {
+        cJson: {
+            type: Object,
+        },
+        checktype: {
+            type: Number,
+            default: 1
+        },
+        see: {
+            type: Boolean,
+            default: false
+        },
+        isTeacher: {
+            type: Number,
+            default: 2
+        }
+    },
+    data() {
+        return {
+            option: {
+                1: { name: '附件' },
+            },
+            checkJson: undefined,
+            progress: 0,
+            isFinishSize: 0,
+            proVisible: false,
+            isAllSize: 0,
+            videoIcon: videoIcon,
+            wordIcon: wordIcon,
+            fileIcon: fileIcon,
+            downLoading: ''
+        }
+    },
+    watch: {
+        checkJson: {
+            handler(newValue) {
+                this.$emit('update:cJson', newValue)
+            },
+            deep: true
+        },
+    },
+    methods: {
+        depthCopy(s) {
+            return JSON.parse(JSON.stringify(s));
+        },
+        addImg(e) {
+            var el = e.currentTarget;
+            el.getElementsByTagName("input")[0].click();
+            e.target.value = "";
+        },
+        numberPan() {
+            if (/[^\d]/.test(this.checkJson.score2) || this.checkJson.score2 < 0) {
+                this.$message.error('请输入大于0的数字')
+                this.checkJson.score2 = ''
+            }
+            if(parseInt(this.checkJson.score2) > parseInt(this.checkJson.score)){
+                this.$message.error('不能输入大于得分的数字')
+                this.checkJson.score2 = this.checkJson.score
+            }
+        },
+        beforeUpload(event, type) {
+            // const loading = this.openLoading();
+            var file = event.target.files[0];
+            var credentials = {
+                accessKeyId: "AKIATLPEDU37QV5CHLMH",
+                secretAccessKey: "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",
+            }; //秘钥形式的登录上传
+            window.AWS.config.update(credentials);
+            window.AWS.config.region = "cn-northwest-1"; //设置区域
+
+            var bucket = new window.AWS.S3({ params: { Bucket: "ccrb" } }); //选择桶
+            var _this = this;
+
+            _this.progress = 0;
+            _this.proVisible = true;
+            _this.isFinishSize = 0;
+            _this.isAllSize = (file.size / 1024 / 1024).toFixed(2);
+            _this.$forceUpdate();
+            if (file) {
+                var params = {
+                    Key:
+                        file.name.split(".")[0] +
+                        new Date().getTime() +
+                        "." +
+                        file.name.split(".")[file.name.split(".").length - 1],
+                    ContentType: file.type,
+                    Body: file,
+                    "Access-Control-Allow-Credentials": "*",
+                    ACL: "public-read",
+                }; //key可以设置为桶的相抵路径,Body为文件, ACL最好要设置
+                var options = {
+                    partSize: 2048 * 1024 * 1024,
+                    queueSize: 2,
+                    leavePartsOnError: true,
+                };
+                bucket
+                    .upload(params, options)
+                    .on("httpUploadProgress", function (evt) {
+                        //这里可以写进度条
+                        // console.log("Uploaded : " + parseInt((evt.loaded * 80) / evt.total) + '%');
+                        _this.progress = parseInt((evt.loaded / evt.total) * 100);
+                        _this.isFinishSize = (evt.loaded / 1024 / 1024).toFixed(2);
+                        _this.$forceUpdate();
+                    })
+                    .send(function (err, data) {
+                        _this.progress = 100;
+                        _this.isFinishSize = _this.isAllSize;
+                        _this.$forceUpdate();
+                        setTimeout(() => {
+                            _this.proVisible = false;
+                            _this.$forceUpdate();
+                        }, 1000);
+                        // loading.close();
+                        if (err) {
+                            _this.$message.error("上传失败");
+                        } else {
+                            let _type = 2;
+                            var imgA = [
+                                "png",
+                                "jpg",
+                                "jpeg",
+                                "bmp",
+                                "gif",
+                                "webp",
+                                "psd",
+                                "svg",
+                                "tiff",
+                            ];
+                            var fileA = [
+                                "DOC",
+                                "DOCX",
+                                "DOCM",
+                                "DOTM",
+                                "DOTX",
+                                "PPTX",
+                                "PPSX",
+                                "PPT",
+                                "PPS",
+                                "PPTM",
+                                "POTM",
+                                "PPAM",
+                                "POTX",
+                                "PPSM",
+                                "XLSX",
+                                "XLS",
+                            ];
+                            var videoA = [
+                                "AVI",
+                                "NAVI",
+                                "MPEG",
+                                "ASF",
+                                "MOV",
+                                "WMV",
+                                "3GP",
+                                "RM",
+                                "RMVB",
+                                "FLV",
+                                "F4V",
+                                "H.264",
+                                "H.265",
+                                "REAL VIDEO",
+                                "MKV",
+                                "WebM",
+                                "HDDVD",
+                                "MP4",
+                                "MPG",
+                                "M4V",
+                                "MGV",
+                                "OGV",
+                                "QTM",
+                                "STR",
+                                "AMC",
+                                "DVX",
+                                "EVO",
+                                "DAT",
+                                "OGG",
+                                "OGM",
+                            ];
+                            if (
+                                fileA.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleUpperCase()
+                                ) != -1
+                            ) {
+                                _type = 1; //word 文件
+                            } else if (
+                                videoA.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleUpperCase()
+                                ) != -1
+                            ) {
+                                _type = 2; //视频
+                            } else if (
+                                imgA.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleLowerCase()
+                                ) != -1
+                            ) {
+                                _type = 3; //图片
+                            } else if (
+                                'PDF'.indexOf(
+                                    data.Location.split(".")[
+                                        data.Location.split(".").length - 1
+                                    ].toLocaleLowerCase()
+                                ) != -1
+                            ) {
+                                _type = 4; //pdf
+                            } else {
+                                _type = 5; //文件
+                            }
+                            if (_this.checkJson.file) {
+                                _this.checkJson.file.push({
+                                    name: file.name,
+                                    url: data.Location,
+                                    type: _type,
+                                });
+                            } else {
+                                _this.checkJson.file = []
+                                _this.checkJson.file.push({
+                                    name: file.name,
+                                    url: data.Location,
+                                    type: _type,
+                                });
+                            }
+                            _this.$forceUpdate();
+
+                            console.log(_this.checkJson);
+                            console.log(data.Location);
+                        }
+                    });
+            }
+        },
+        downloadFile(f) {
+            var credentials = {
+                accessKeyId: "AKIATLPEDU37QV5CHLMH",
+                secretAccessKey: "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",
+            }; //秘钥形式的登录上传
+            window.AWS.config.update(credentials);
+            window.AWS.config.region = "cn-northwest-1"; //设置区域
+            let url2 = f.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;
+            }
+            let _this = this;
+
+            _this.downLoading = _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) {
+                _this.downLoading = ''
+                if (err) console.log(err, err.stack); // an error occurred
+                else {
+                    let url = window.URL.createObjectURL(new Blob([data.Body]));
+                    let a = document.createElement("a");
+                    a.name = f.name;
+                    a.href = url;
+                    a.download = f.name;
+                    a.click();
+                    console.log(data);
+                }          // sxuccessful response
+
+            });
+        },
+        delFile(index) {
+            this.checkJson.file.splice(index, 1)
+        }
+    },
+    mounted() {
+        this.checkJson = this.cJson ? this.depthCopy(this.cJson) : undefined
+
+    }
+}
+</script>
+
+<style scoped>
+.c_box {
+    width: 100%;
+    position: relative;
+}
+
+.mask {
+    position: absolute;
+    height: 100%;
+    width: 100%;
+    z-index: 2;
+}
+
+.choice_box {}
+
+.choice_box>.title {
+    font-weight: bold;
+    width: 100%;
+    word-break: break-all;
+}
+
+.choice_box>.choices {
+    margin-top: 10px;
+}
+
+.binfo_input {
+    width: 100%;
+    margin: 0;
+    padding: 12px 14px;
+    display: block;
+    min-width: 0;
+    outline: none;
+    box-sizing: border-box;
+    background: none;
+    border: none;
+    border-radius: 4px;
+    background: #fff;
+    font-size: 16px;
+    resize: none;
+    font-family: 'Microsoft YaHei';
+    min-height: 120px;
+    /* border: 1px solid #3682fc00; */
+    border: 1.5px solid #CAD1DC;
+    position: relative;
+}
+
+.binfo_input>.uploadQ {
+    border: 1px dashed #CAD1DC;
+    height: 120px;
+    width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: rgb(243, 244, 246);
+    color: rgb(124, 124, 124);
+    border-radius: 5px;
+    cursor: pointer;
+}
+
+.mask {
+    background-color: rgb(0 0 0 / 30%);
+    /* position: fixed; */
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 90;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.progressBox {
+    width: 300px;
+    height: 150px;
+    background: #fff;
+    border-radius: 10px;
+    box-shadow: 0 0 6px 1px #bfbfbf;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    position: relative;
+    color: #6c6c6c;
+}
+
+.progressBox>>>.el-progress-bar__outer {
+    background-color: #d1dfff !important;
+}
+
+.progressBox .lbox {
+    height: 50px;
+    font-size: 19px;
+    display: flex;
+    align-items: center;
+    color: #747474;
+}
+
+.progressBox .lbox img {
+    width: 40px;
+    margin-right: 20px;
+}
+
+.closeCss {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    cursor: pointer;
+    width: 20px;
+    height: 20px;
+}
+
+.closeCss>img {
+    width: 100%;
+    height: 100%;
+}
+
+.binfo_input>.fileBox {}
+
+.binfo_input>.fileBox .fileC {
+    display: flex;
+    flex-wrap: wrap;
+    width: 100%;
+    cursor: pointer;
+}
+
+.binfo_input>.fileBox .fileC>.file {
+    width: 200px;
+    height: 140px;
+    margin: 10px 10px 10px 0px;
+    border-radius: 15px;
+    box-shadow: rgb(223, 218, 218) 0px 0px 6px 1px;
+    overflow: hidden;
+    margin-right: 15px;
+    position: relative;
+    display: flex;
+    flex-direction: column;
+}
+
+.binfo_input>.fileBox .fileC>.file>.img {
+    width: 100%;
+    height: calc(100% - 35px);
+    object-fit: cover;
+}
+
+.binfo_input>.fileBox .fileC>.file>.del {
+    position: absolute;
+    width: 25px;
+    top: 10px;
+    right: 10px;
+    cursor: pointer;
+}
+
+.binfo_input>.fileBox .fileC>.file>.name {
+    height: 35px;
+    width: 100%;
+    background: #f9f9f9;
+    display: flex;
+    align-items: center;
+    padding: 0 10px;
+    box-sizing: border-box;
+}
+
+.binfo_input>.fileBox .fileC>.file>.name>span {
+    display: block;
+    text-overflow: ellipsis;
+    max-width: 100%;
+    white-space: nowrap;
+    overflow: hidden;
+}
+
+.binfo_input>.fileBox .btn {
+    width: 100%;
+    height: 40px;
+    background: #007bff;
+    color: #fff;
+    border-radius: 15px;
+    margin-top: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+}
+.choice_box> .c_title {
+    display: flex;
+    justify-content: space-between;
+}
+.choice_box> .c_title .title {
+    font-weight: bold;
+    width: 100%;
+    word-break: break-all;
+}
+
+.choice_box> .c_title .p_box{
+    margin-left: 5px;
+    min-width: fit-content;
+    display: flex;
+    align-items: center;
+}
+
+.c_input {
+    width: 90px;
+}
+
+.c_input >>> .el-input__inner{
+    padding: 0 5px;
+    text-align: right;
+}
+</style>

+ 2 - 2
src/components/pages/testStudent/view/component/gap.vue

@@ -80,12 +80,12 @@ export default {
             return JSON.parse(JSON.stringify(s));
         },
         numberPan() {
-            if (/[^\d]/.test(this.checkJson.score2) || this.checkJson.score2 < 0) {
+            if (/[^\d]/.test(this.checkJson.score2) || parseInt(this.checkJson.score2) < 0) {
                 this.$message.error('请输入大于0的数字')
                 this.checkJson.score2 = ''
             }
 
-            if(this.checkJson.score2 > this.checkJson.score){
+            if(parseInt(this.checkJson.score2) > parseInt(this.checkJson.score)){
                 this.$message.error('不能输入大于得分的数字')
                 this.checkJson.score2 = this.checkJson.score
             }

+ 8 - 1
src/components/pages/testStudent/view/component/topic.vue

@@ -13,6 +13,7 @@
           <div v-if="item.ttype == 1" class="answerBox">
             <choiceV :cJson.sync="item.json" :checktype="checktype" v-if="item.type == 1" :see="see" :isTeacher="isTeacher"></choiceV>
             <gapV :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 3" :see="see" :isTeacher="isTeacher"></gapV>
+            <fileV :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 5" :see="see" :isTeacher="isTeacher"></fileV>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -20,6 +21,7 @@
             <div v-if="item2.ttype == 1" class="answerBox">
               <choiceV :cJson.sync="item2.json" :checktype="checktype" v-if="item2.type == 1" :see="see" :isTeacher="isTeacher"></choiceV>
               <gapV :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 3" :see="see" :isTeacher="isTeacher"></gapV>
+              <gapV :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 5" :see="see" :isTeacher="isTeacher"></gapV>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -31,6 +33,7 @@
           <div v-if="item.ttype == 1" class="answerBox">
             <choiceV :cJson.sync="item.json" :checktype="checktype" v-if="item.type == 1" :see="see" :isTeacher="isTeacher"></choiceV>
             <gapV :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 3" :see="see" :isTeacher="isTeacher"></gapV>
+            <fileV :cJson.sync="item.json" :checktype="checktype" v-else-if="item.type == 5" :see="see" :isTeacher="isTeacher"></fileV>
             <!-- <span v-else>暂未设置题目</span> -->
           </div>
           <div v-for="(item2, index2) in item.array" :key="`${index}-${index2}`" class="check_box_xia">
@@ -38,6 +41,7 @@
             <div v-if="item2.ttype == 1" class="answerBox">
               <choiceV :cJson.sync="item2.json" :checktype="checktype" v-if="item2.type == 1" :see="see" :isTeacher="isTeacher"></choiceV>
               <gapV :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 3" :see="see" :isTeacher="isTeacher"></gapV>
+              <fileV :cJson.sync="item2.json" :checktype="checktype" v-else-if="item2.type == 5" :see="see" :isTeacher="isTeacher"></fileV>
               <!-- <span v-else>暂未设置题目</span> -->
             </div>
           </div>
@@ -58,6 +62,7 @@
 <script>
 import choiceV from "./choice.vue";
 import gapV from './gap.vue';
+import fileV from './file.vue';
 export default {
   props: {
     cJson: {
@@ -85,7 +90,8 @@ export default {
   },
   components: {
     choiceV,
-    gapV
+    gapV,
+    fileV
   },
   data() {
     return {
@@ -97,6 +103,7 @@ export default {
         // 2: "问答题",
         3: "问答题",
         4: "添加文档",
+        5: "附件",
       },
     };
   },

+ 151 - 18
src/components/pages/testStudent/view/preview.vue

@@ -26,11 +26,12 @@
         <div class="step_box">
           <div class="edit_top">
             <div class="op_btn">
-              <!-- <el-button type="primary" size="small" @click="save">保存</el-button> -->
+              <el-button type="primary" size="small" @click="reset" v-if="isReset">重置</el-button>
+              <el-button type="primary" size="small" @click="save">保存</el-button>
               <el-button type="primary" size="small" @click="publish">提交</el-button>
             </div>
           </div>
-          <topicVue :cJson="cJson" :title="title" ref="topicVue"></topicVue>
+          <topicVue :cJson="cJson" :title="title" ref="topicVue" v-if="!loading"></topicVue>
         </div>
       </div>
     </div>
@@ -55,8 +56,10 @@ export default {
       testType: [],
       see: false,
       cJson: [],
+      cJson2: [],
       loading: false,
       look: "",
+      isReset: false,
     }
   },
   methods: {
@@ -87,7 +90,117 @@ export default {
     goTo(path) {
       this.$router.push(path);
     },
+    reset() {
+      this
+        .$confirm("是否将已经填写的内容重置为最新版?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+        .then(() => {
+          this.cJson = JSON.parse(JSON.stringify(this.cJson2));
+          this.loading = true
+          this.isReset = false
+          setTimeout(() => {
+            this.loading = false
+          }, 0);
+          this.$forceUpdate()
+        })
+        .catch(() => {
+
+        });
+    },
+    getTestWorks() {
+      let params = {
+        cid: this.cid,
+        uid: this.userid,
+      };
+      this.ajax
+        .get(this.$store.state.api + "getTestWorks", params)
+        .then((res) => {
+          // this.cJson = JSON.parse(res.data[0][0].chapters);
+          if (res.data[2].length) {
+            this.cJson = JSON.parse(res.data[2][0].courseJson)
+
+            let cJson = this.setJSON(JSON.parse(JSON.stringify(this.cJson)))
+            let cJson2 = this.setJSON(this.setJson2(JSON.parse(JSON.stringify(this.cJson2))))
+
+            if (JSON.stringify(cJson) != JSON.stringify(cJson2)) {
+              this.isReset = true
+            }
 
+
+          }
+
+          this.$forceUpdate()
+
+          this.loading = false
+
+        })
+        .catch((err) => {
+          this.loading = false
+          console.error(err);
+        });
+    },
+    setJSON(json) {
+      return json.filter((item) => {
+        if (item.array) {
+          item.array = item.array.filter((item2) => {
+            if (item2.ttype == 1 && item2.json) {
+              delete item2.json.answer2
+              delete item2.json.score2
+            }
+            if (item2.array) {
+              item2.array = item2.array.filter((item3) => {
+                if (item3.ttype == 1 && item3.json) {
+                  delete item3.json.answer2
+                  delete item3.json.score2
+                }
+                return item3;
+              });
+            }
+            return item2;
+          });
+        } else if (item.ttype == 1 && item.json) {
+          delete item.json.answer2
+          delete item.json.score2
+        }
+        return item
+        console.log(item.array);
+      });
+    },
+    setJson2(json) {
+      let _json = json;
+      this.type = _json[0].ttype;
+      let checkArray = _json.filter((item) => {
+        if (item.array) {
+          item.array = item.array.filter((item2) => {
+            if (item2.ttype == 1 && item2.json && !item2.json.answer2) {
+              item2.json.answer2 = [];
+            }
+            if (item2.array) {
+              item2.array = item2.array.filter((item3) => {
+                if (item3.ttype == 1 && item3.json && !item3.json.answer2) {
+                  item3.json.answer2 = [];
+                }
+                return item3;
+              });
+            }
+            return (
+              (item2.ttype != 1 && item2.array.length > 0) || item2.ttype == 1
+            );
+          });
+        }
+        if (item.ttype == 1 && item.json && !item.json.answer2) {
+          item.json.answer2 = [];
+        }
+        console.log(item.array);
+        return (item.ttype != 1 && item.array.length > 0) || item.ttype == 1;
+      });
+      console.log(checkArray);
+      return checkArray;
+
+    },
     getData() {
       this.loading = true
       let params = {
@@ -97,7 +210,7 @@ export default {
         .get(this.$store.state.api + "getTestCourseDetail", params)
         .then((res) => {
           this.cJson = JSON.parse(res.data[0][0].chapters);
-          this.$forceUpdate();
+          this.cJson2 = JSON.parse(res.data[0][0].chapters);
           this.title = res.data[0][0].title;
 
           this.see = res.data[0][0].open == 1 ? true : false;
@@ -109,16 +222,31 @@ export default {
           }
           console.log(this.testType);
           this.look = res.data[0][0].look
-          this.loading = false
+          this.getTestWorks()
+          this.$forceUpdate();
 
         })
         .catch((err) => {
+          this.loading = false
           console.error(err);
         });
     },
-    save(){
-      this.$message.success('保存成功')
-      this.goTo(
+    save() {
+      let cjson = this.$refs['topicVue'].checkArray
+      console.log(cjson);
+      let params = [
+        {
+          uid: this.userid,
+          cid: this.cid,
+          cjson: JSON.stringify(cjson),
+          type: '1',
+        },
+      ];
+      this.ajax
+        .post(this.$store.state.api + "addTestWorks", params)
+        .then((res) => {
+          this.$message.success('保存成功')
+          this.goTo(
             "/testStudent?userid=" +
             this.userid +
             "&oid=" +
@@ -128,8 +256,13 @@ export default {
             "&role=" +
             this.role
           );
+        })
+        .catch((err) => {
+          this.$message.error("网络不佳");
+          console.error(err);
+        });
     },
-    publish(){
+    publish() {
       let cjson = this.$refs['topicVue'].checkArray
       console.log(cjson);
       let params = [
@@ -137,7 +270,7 @@ export default {
           uid: this.userid,
           cid: this.cid,
           cjson: JSON.stringify(cjson),
-          type:'2',
+          type: '2',
         },
       ];
       this.ajax
@@ -145,15 +278,15 @@ export default {
         .then((res) => {
           this.$message.success('提交成功')
           this.goTo(
-                "/testStudent?userid=" +
-                this.userid +
-                "&oid=" +
-                this.oid +
-                "&org=" +
-                this.org +
-                "&role=" +
-                this.role
-              );
+            "/testStudent?userid=" +
+            this.userid +
+            "&oid=" +
+            this.oid +
+            "&org=" +
+            this.org +
+            "&role=" +
+            this.role
+          );
         })
         .catch((err) => {
           this.$message.error("网络不佳");

Some files were not shown because too many files changed in this diff