李志伟 3 vuotta sitten
vanhempi
commit
565585b604

+ 0
- 8
src/components/Question/drawer.vue Näytä tiedosto

87
         {
87
         {
88
           value: 'D',
88
           value: 'D',
89
           label: 'D'
89
           label: 'D'
90
-        },
91
-        {
92
-          value: 'true',
93
-          label: '对'
94
-        },
95
-        {
96
-          value: 'false',
97
-          label: '错'
98
         }
90
         }
99
       ]
91
       ]
100
     }
92
     }

+ 0
- 1
src/components/Question/edit.vue Näytä tiedosto

9
           <el-select slot="prepend" v-model="form.questionType" style="width:100px" placeholder="请选择">
9
           <el-select slot="prepend" v-model="form.questionType" style="width:100px" placeholder="请选择">
10
             <el-option label="单选题" value="radio" />
10
             <el-option label="单选题" value="radio" />
11
             <el-option label="多选题" value="checkBox" />
11
             <el-option label="多选题" value="checkBox" />
12
-            <el-option label="判断题" value="switch" />
13
             <el-option label="简答题" value="textarea" />
12
             <el-option label="简答题" value="textarea" />
14
           </el-select>
13
           </el-select>
15
         </el-input>
14
         </el-input>

+ 1
- 1
src/components/Question/index.vue Näytä tiedosto

14
         <transition-group>
14
         <transition-group>
15
           <div v-for="item,index in tableData" :key="index" class="questionli" @click="handleEdit(item)">
15
           <div v-for="item,index in tableData" :key="index" class="questionli" @click="handleEdit(item)">
16
             <span style="width:45px">第{{ index+1 }}题</span>
16
             <span style="width:45px">第{{ index+1 }}题</span>
17
-            <span style="width:45px">{{ item.questionType === 'radio'?'单选题':item.questionType==='checkBox'?'多选题':item.questionType==='switch'?'判断题':'简答题' }}</span>
17
+            <span style="width:45px">{{ item.questionType === 'radio'?'单选题':item.questionType==='checkBox'?'多选题':'简答题' }}</span>
18
             <span style="flex:1">{{ item.content }}</span>
18
             <span style="flex:1">{{ item.content }}</span>
19
             <el-popconfirm
19
             <el-popconfirm
20
               style="width:30px"
20
               style="width:30px"

+ 35
- 19
src/views/photoWall/index.vue Näytä tiedosto

2
   <div class="body">
2
   <div class="body">
3
     <el-card class="box-card" shadow="never">
3
     <el-card class="box-card" shadow="never">
4
       <div class="text item">
4
       <div class="text item">
5
-        <upload-image-list
6
-          v-show="packId"
7
-          style="float: right;line-height:48px"
8
-          @handleChange="handleChange"
9
-        />
10
-        <el-row style="padding-top: 20px">
5
+        <el-row>
11
           <el-col :span="18">
6
           <el-col :span="18">
12
             <div v-show="packId" style="padding:16px">
7
             <div v-show="packId" style="padding:16px">
13
-              <p style="margin-left:8px">{{ currentPack }}</p>
14
-              <div v-for="item in images" :key="item.attchId" style="display:inline-block;position:relative;margin:8px" @click="deletePhoto(item)">
15
-                <el-image :src="item.url" class="photoWall" style="width:160px;" />
16
-                <div class="mask"><el-image class="maskImg" :src="deleteImg" /></div>
8
+              <p style="margin-left:8px">
9
+                {{ currentPack }}
10
+                <upload-image-list
11
+                  style="margin-left:8px;display:inline-block"
12
+                  @handleChange="handleChange"
13
+                /></p>
14
+              <div v-for="item in images" :key="item.attchId" style="display:inline-block;position:relative;margin:8px">
15
+                <el-card :body-style="{ padding: '0px', height:'100%' }" style="width:320px; height:280px;text-align:center">
16
+                  <el-image fit="cover" :preview-src-list="[item.url]" :src="item.url" style="height: calc(100% - 40px)" />
17
+                  <div style="width:100%;height:40px"><div class="imgbtn">放大</div><div class="imgbtn" @click="deletePhoto(item)">删除</div></div>
18
+                  <!-- <div class="mask"><el-image class="maskImg" :src="deleteImg" /></div> -->
19
+                </el-card>
17
               </div>
20
               </div>
18
             </div>
21
             </div>
19
           </el-col>
22
           </el-col>
23
                 <el-tag
26
                 <el-tag
24
                   v-for="tag in dynamicTags"
27
                   v-for="tag in dynamicTags"
25
                   :key="tag"
28
                   :key="tag"
26
-                  type="info"
27
-                  style="margin-bottom:8px"
28
                   closable
29
                   closable
30
+                  style="margin-bottom:8px"
31
+                  :type="currentPack===tag?'':'info' "
29
                   :disable-transitions="false"
32
                   :disable-transitions="false"
30
                   @close="handleClose(tag)"
33
                   @close="handleClose(tag)"
31
                   @click="handleCurrent(tag)"
34
                   @click="handleCurrent(tag)"
115
       this.dynamicTags = []
118
       this.dynamicTags = []
116
       getAttchPackList().then((res) => {
119
       getAttchPackList().then((res) => {
117
         this.attchPackList = res.data.records
120
         this.attchPackList = res.data.records
118
-        this.attchPackList.map(item => {
119
-          this.dynamicTags.push(item.name)
120
-        })
121
-        this.packId = res.data.records[0].packId
121
+        if (this.attchPackList.length !== 0) {
122
+          this.attchPackList.map(item => {
123
+            this.dynamicTags.push(item.name)
124
+          })
125
+          this.packId = res.data.records[0].packId
126
+          this.currentPack = res.data.records[0].name
127
+        }
122
       })
128
       })
123
     },
129
     },
124
     // 删除分组
130
     // 删除分组
192
   margin-left: 10px;
198
   margin-left: 10px;
193
   vertical-align: bottom;
199
   vertical-align: bottom;
194
 }
200
 }
201
+.imgbtn {
202
+  width: 50%;
203
+  text-align: center;
204
+  height: 40px;
205
+  line-height: 40px;
206
+  display: inline-block;
207
+  &:first-child {
208
+    border-right:1px solid #f0f0f0 ;
209
+  }
210
+  &:hover {
211
+    color: #409EFF;
212
+  }
213
+}
195
 .mask {
214
 .mask {
196
   position: absolute;
215
   position: absolute;
197
   width: 100%;
216
   width: 100%;
213
     opacity: 0;
232
     opacity: 0;
214
   }
233
   }
215
 }
234
 }
216
-// .photoWall:hover {
217
-//   opacity: 0.4;
218
-// }
219
 </style>
235
 </style>

+ 40
- 38
src/views/questionnaire/edit.vue Näytä tiedosto

1
 <template>
1
 <template>
2
   <div class="body_edit">
2
   <div class="body_edit">
3
-    <el-tabs v-model="activeName">
4
-      <el-tab-pane label="问卷详情" name="questionnaire">
5
-        <el-form ref="form" :rules="rules" class="questionnaireForm" :model="questionnaireForm" label-width="100px">
6
-          <el-form-item label="问卷名称:" prop="name">
7
-            <el-input v-model="questionnaireForm.name" />
8
-          </el-form-item>
9
-          <el-form-item class="editBottomItem">
10
-            <el-button type="primary" @click="onSubmit('form')">保存</el-button>
11
-            <el-button @click="onCancel">取消</el-button>
12
-          </el-form-item>
13
-        </el-form>
14
-      </el-tab-pane>
15
-      <el-tab-pane label="问卷题库" name="question" :disabled="queId ? false : true">
16
-        <el-row :gutter="20" style="padding-top: 20px">
17
-          <el-col :span="12">
18
-            <Question
19
-              v-if="queId"
20
-              ref="Question"
21
-              :que-id="queId"
22
-              @handleAddQuestion="questionId = ''"
23
-              @handleCloseQuestion="questionId = ''"
24
-              @handleEditQuestion="handleEditQuestion"
25
-              @setQuestionTotal="setQuestionTotal"
26
-            />
27
-          </el-col>
28
-          <el-col :span="12">
29
-            <QuestionEdit
30
-              v-if="queId"
31
-              :total="total"
32
-              :question-id="questionId"
33
-              :que-id="queId"
34
-              @handleRefreshQuestion="handleRefreshQuestion"
35
-              @handleEditQuestion="handleEditQuestion"
36
-            />
37
-          </el-col>
38
-        </el-row>
39
-      </el-tab-pane>
40
-    </el-tabs>
3
+    <!-- <el-tabs v-model="activeName"> -->
4
+    <!-- <el-tab-pane label="问卷详情" name="questionnaire"> -->
5
+    <el-form ref="form" :inline="true" :rules="rules" :model="questionnaireForm" label-width="100px">
6
+      <h3>问卷详情</h3>
7
+      <el-form-item label="问卷名称:" prop="name">
8
+        <el-input v-model="questionnaireForm.name" style="width:700px" />
9
+      </el-form-item>
10
+      <el-form-item class="editBottomItem">
11
+        <el-button type="primary" @click="onSubmit('form')">保存</el-button>
12
+        <el-button @click="onCancel">取消</el-button>
13
+      </el-form-item>
14
+    </el-form>
15
+    <!-- </el-tab-pane> -->
16
+    <!-- <el-tab-pane label="问卷题库" name="question" :disabled="queId ? false : true"> -->
17
+    <el-row v-if="queId" :gutter="20" style="padding-top: 20px">
18
+      <el-col :span="12">
19
+        <h3>问卷题库</h3>
20
+        <Question
21
+          v-if="queId"
22
+          ref="Question"
23
+          :que-id="queId"
24
+          @handleAddQuestion="questionId = ''"
25
+          @handleCloseQuestion="questionId = ''"
26
+          @handleEditQuestion="handleEditQuestion"
27
+          @setQuestionTotal="setQuestionTotal"
28
+        />
29
+      </el-col>
30
+      <el-col :span="12">
31
+        <QuestionEdit
32
+          v-if="queId"
33
+          :total="total"
34
+          :question-id="questionId"
35
+          :que-id="queId"
36
+          @handleRefreshQuestion="handleRefreshQuestion"
37
+          @handleEditQuestion="handleEditQuestion"
38
+        />
39
+      </el-col>
40
+    </el-row>
41
+    <!-- </el-tab-pane> -->
42
+    <!-- </el-tabs> -->
41
   </div>
43
   </div>
42
 </template>
44
 </template>
43
 <script>
45
 <script>

+ 106
- 38
src/views/signIn/edit.vue Näytä tiedosto

33
                 placeholder="选择日期时间"
33
                 placeholder="选择日期时间"
34
               />
34
               />
35
             </el-form-item>
35
             </el-form-item>
36
+            <el-form-item label-width="0">
37
+              <img
38
+                style="width: 100px; height: 100px"
39
+                :src="imgURL"
40
+                fit="fill"
41
+              >
42
+            </el-form-item>
36
             <el-form-item label-width="0">
43
             <el-form-item label-width="0">
37
               <el-button
44
               <el-button
38
                 type="primary"
45
                 type="primary"
101
         startTime: [{ required: true, message: '请输入签到开始时间', trigger: 'blur' }],
108
         startTime: [{ required: true, message: '请输入签到开始时间', trigger: 'blur' }],
102
         endTime: [{ required: true, message: '请输入签到结束时间', trigger: 'blur' }]
109
         endTime: [{ required: true, message: '请输入签到结束时间', trigger: 'blur' }]
103
       },
110
       },
111
+
104
       allClassList: [],
112
       allClassList: [],
105
       classList: [],
113
       classList: [],
106
       isIndeterminateClass: false,
114
       isIndeterminateClass: false,
110
       termList: [],
118
       termList: [],
111
       isIndeterminateTerm: false,
119
       isIndeterminateTerm: false,
112
       checkAllTerm: false,
120
       checkAllTerm: false,
113
-      checkedTerms: []
121
+      checkedTerms: [],
122
+
123
+      imgURL: undefined,
124
+      oldclassList: [],
125
+      oldclassIdList: [],
126
+      lastTimeClassList: []
114
     }
127
     }
115
   },
128
   },
116
   watch: {
129
   watch: {
117
-    checkedTerms() {
118
-      if (this.checkedTerms.length > 0) {
119
-        const finalArr = this.allClassList.filter((item) => this.checkedTerms.includes(item.termId))
120
-        this.classList = finalArr
121
-        const finalArr2 = finalArr.filter((item) => this.checkedClasss.includes(item.classId))
122
-        this.checkedClasss = []
123
-        finalArr2.map(item => {
124
-          this.checkedClasss.push(item.classId)
125
-        })
126
-      } else {
127
-        this.classList = []
128
-        this.checkedClasss = []
129
-      }
130
+    checkedTerms: {
131
+      handler() {
132
+        if (this.checkedTerms.length === 0) {
133
+          this.isIndeterminateTerm = false
134
+          this.checkAllTerm = false
135
+          this.classList = []
136
+          this.checkedClasss = []
137
+        } else if (this.checkedTerms.length > 0) {
138
+          if (this.checkedTerms.length === this.termList.length) {
139
+            this.checkAllTerm = true
140
+          } else this.isIndeterminateTerm = true
141
+          const finalArr = this.allClassList.filter((item) => this.checkedTerms.includes(item.termId))
142
+          this.classList = finalArr
143
+          const finalArr2 = finalArr.filter((item) => this.checkedClasss.includes(item.classId))
144
+          this.checkedClasss = []
145
+          finalArr2.map(item => {
146
+            this.checkedClasss.push(item.classId)
147
+          })
148
+        }
149
+        this.lastTimeClassList = this.checkedClasss
150
+      },
151
+      immediate: true
130
     },
152
     },
131
-    checkedClasss() {
132
-      if (this.checkedClasss.length === 0) {
133
-        this.isIndeterminateClass = false
134
-        this.checkAllClass = false
135
-      }
153
+    checkedClasss: {
154
+      handler() {
155
+        if (this.checkedClasss.length === 0) {
156
+          this.isIndeterminateClass = false
157
+          this.checkAllClass = false
158
+        } else if (this.checkedClasss.length === this.classList.length) {
159
+          this.checkAllClass = true
160
+        } else this.isIndeterminateClass = true
161
+      },
162
+      immediate: true
136
     }
163
     }
137
   },
164
   },
138
   mounted() {
165
   mounted() {
149
     })
176
     })
150
     getSchoolClassList().then((res) => {
177
     getSchoolClassList().then((res) => {
151
       this.allClassList = res.data.records
178
       this.allClassList = res.data.records
179
+      getSignClassList(this.signId).then(res => {
180
+        this.oldclassList = res.data
181
+        if (this.oldclassList) {
182
+          this.oldclassList.map(item => {
183
+            if (this.checkedTerms.indexOf(item.termId) === -1) {
184
+              this.checkedTerms.push(item.termId)
185
+            }
186
+            this.checkedClasss.push(item.classId)
187
+          })
188
+          this.oldclassIdList = this.checkedClasss
189
+        }
190
+      })
152
     })
191
     })
153
-    getSignClassList(this.signId).then(res => {
154
-      var thisList = res.data
155
-      if (thisList) {
156
-        thisList.map(item => {
157
-          this.checkedClasss.push(item.classId)
158
-          this.checkedTerms.push(item.termId)
159
-        })
160
-      }
161
-    })
192
+    this.toUrl()
162
   },
193
   },
163
   methods: {
194
   methods: {
164
     // 学期
195
     // 学期
185
       this.isIndeterminateClass = false
216
       this.isIndeterminateClass = false
186
     },
217
     },
187
     handleCheckedClasssChange(value) {
218
     handleCheckedClasssChange(value) {
219
+      if (this.lastTimeClassList.length > this.checkedClasss.length) {
220
+        this.lastTimeClassList.map(item => {
221
+          // 当上一次班级数组中的一项在现在班级选中数组中不显示说明当前项就是取消的哪一项 然后判断是否是上次保存过的签到班级
222
+          if (this.checkedClasss.indexOf(item) === -1 && this.oldclassIdList.indexOf(item) !== -1) {
223
+            this.checkedClasss.push(item)
224
+            this.$confirm('此操作将使该班级无法签到是否继续?', '提示', {
225
+              confirmButtonText: '删除',
226
+              cancelButtonText: '取消',
227
+              type: 'warning'
228
+            }).then(() => {
229
+              this.checkedClasss.pop()
230
+            }).catch(() => { })
231
+          }
232
+        })
233
+      }
234
+      // 将当前选中班级放在数组中记录一下
235
+      this.lastTimeClassList = this.checkedClasss
188
       const checkedCount = value.length
236
       const checkedCount = value.length
189
       this.checkAllClass = checkedCount === this.classList.length
237
       this.checkAllClass = checkedCount === this.classList.length
190
       this.isIndeterminateClass = checkedCount > 0 && checkedCount < this.classList.length
238
       this.isIndeterminateClass = checkedCount > 0 && checkedCount < this.classList.length
192
     // 修改签到池
240
     // 修改签到池
193
     editSignClass() {
241
     editSignClass() {
194
       var submitList = []
242
       var submitList = []
195
-      var serialNo = 0
196
       this.classList.map((item, index) => {
243
       this.classList.map((item, index) => {
197
         if (this.checkedClasss.indexOf(item.classId) !== -1) {
244
         if (this.checkedClasss.indexOf(item.classId) !== -1) {
198
-          submitList.push({ classId: item.classId, termId: item.termId, signId: this.signId, serialNo: serialNo++ })
245
+          submitList.push({ classId: item.classId, termId: item.termId, signId: this.signId })
199
         }
246
         }
200
       })
247
       })
248
+      if (this.oldclassList.length > 0) {
249
+        this.oldclassList.map(item => {
250
+          submitList.map((item2, index) => {
251
+            if (item2.classId === item.classId) {
252
+              submitList[index].serialNo = item.serialNo
253
+            }
254
+          })
255
+        })
256
+      }
201
       saveSignClass(submitList, this.signId).then(() => {
257
       saveSignClass(submitList, this.signId).then(() => {
202
         this.$message('签到池修改成功')
258
         this.$message('签到池修改成功')
203
       })
259
       })
236
         text: 'http://192.168.89.76:8080/signIn?signId=' + val
292
         text: 'http://192.168.89.76:8080/signIn?signId=' + val
237
       })
293
       })
238
     },
294
     },
239
-    // 下载二维码
240
-    downloadQrcode() {
295
+    // canvans转base64 很消耗内存所以把转换后的结果imgURL拿出来
296
+    toUrl() {
241
       document.getElementById('qrcode').innerHTML = ''
297
       document.getElementById('qrcode').innerHTML = ''
242
       this.qrcode(this.signId) // 下载之前首先要有二维码
298
       this.qrcode(this.signId) // 下载之前首先要有二维码
243
       // 先找到canvas节点下的二维码图片
299
       // 先找到canvas节点下的二维码图片
244
       const myCanvas = document.getElementById('qrcode').getElementsByTagName('canvas')
300
       const myCanvas = document.getElementById('qrcode').getElementsByTagName('canvas')
301
+      // 设置a的href属性将canvas变成png格式
302
+      this.imgURL = myCanvas[0].toDataURL('image/jpg')
303
+    },
304
+    // 下载二维码 把base64转为blob并且下载
305
+    downloadQrcode() {
245
       const img = document.getElementById('qrcode').getElementsByTagName('img')
306
       const img = document.getElementById('qrcode').getElementsByTagName('img')
246
       // 创建一个a节点
307
       // 创建一个a节点
247
       const a = document.createElement('a')
308
       const a = document.createElement('a')
248
-      // 设置a的href属性将canvas变成png格式
249
-      const imgURL = myCanvas[0].toDataURL('image/jpg')
309
+      // 获得浏览器用户代理
250
       const ua = navigator.userAgent
310
       const ua = navigator.userAgent
251
-      if (ua.indexOf('Trident') !== -1 && ua.indexOf('Windows') !== -1) { // IE内核 并且  windows系统 情况下 才执行;
252
-        var bstr = atob(imgURL.split(',')[1])
311
+      if (ua.indexOf('Trident') !== -1 && ua.indexOf('Windows') !== -1) { // IE内核 并且  windows系统 情况下 才执行
312
+        // canvas转base64 后生成的数据是由 图片格式+逗号+真正的base64码组成的
313
+        var bstr = atob(this.imgURL.split(',')[1])
253
         var n = bstr.length
314
         var n = bstr.length
254
         var u8arr = new Uint8Array(n)
315
         var u8arr = new Uint8Array(n)
255
         while (n--) {
316
         while (n--) {
258
         var blob = new Blob([u8arr])
319
         var blob = new Blob([u8arr])
259
         window.navigator.msSaveOrOpenBlob(blob, this.signForm.name + '.png')
320
         window.navigator.msSaveOrOpenBlob(blob, this.signForm.name + '.png')
260
       } else if (ua.indexOf('Firefox') > -1) { // 火狐兼容下载
321
       } else if (ua.indexOf('Firefox') > -1) { // 火狐兼容下载
261
-        const blob = this.base64ToBlob(imgURL) // new Blob([content]);
322
+        const blob = this.base64ToBlob(this.imgURL) // new Blob([content]);
262
         const evt = document.createEvent('HTMLEvents')
323
         const evt = document.createEvent('HTMLEvents')
263
         evt.initEvent('click', true, true)// initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
324
         evt.initEvent('click', true, true)// initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
264
         a.download = this.signForm.name + '.png'// 下载图片名称,如果填内容识别不到,下载为未知文件,所以我这里就不填为空
325
         a.download = this.signForm.name + '.png'// 下载图片名称,如果填内容识别不到,下载为未知文件,所以我这里就不填为空
326
+        // 讲blob数据转换成url
265
         a.href = URL.createObjectURL(blob)
327
         a.href = URL.createObjectURL(blob)
266
         a.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }))// 兼容火狐
328
         a.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }))// 兼容火狐
267
       } else { // 谷歌兼容下载
329
       } else { // 谷歌兼容下载
268
-        img.src = imgURL
330
+        img.src = this.imgURL
269
         a.href = img.src
331
         a.href = img.src
270
         // 设置下载文件的名字
332
         // 设置下载文件的名字
271
         a.download = this.signForm.name + '.png'
333
         a.download = this.signForm.name + '.png'
275
     },
337
     },
276
     // base64转blob
338
     // base64转blob
277
     base64ToBlob(code) {
339
     base64ToBlob(code) {
340
+      // this.imgURl打印出来可以看到等于data:image/png;base64,+base64码
278
       const parts = code.split(';base64,')
341
       const parts = code.split(';base64,')
342
+      // 截取后pasts[0]等于data:image/png  parts[1]就是base64吗 (至于为什么我们上面写image/jpg 现在变成png我也不知道哈哈哈哈哈)
279
       const contentType = parts[0].split(':')[1]
343
       const contentType = parts[0].split(':')[1]
344
+      // 用:分隔contentType 等于image/png
280
       const raw = window.atob(parts[1])
345
       const raw = window.atob(parts[1])
346
+      // 获取解码后的长度
281
       const rawLength = raw.length
347
       const rawLength = raw.length
282
       const uInt8Array = new Uint8Array(rawLength)
348
       const uInt8Array = new Uint8Array(rawLength)
283
       for (let i = 0; i < rawLength; ++i) {
349
       for (let i = 0; i < rawLength; ++i) {
350
+        // 循环 把每位都转为相对应的unicode码
284
         uInt8Array[i] = raw.charCodeAt(i)
351
         uInt8Array[i] = raw.charCodeAt(i)
285
       }
352
       }
353
+      // Blob储存二进制的
286
       return new Blob([uInt8Array], { type: contentType })
354
       return new Blob([uInt8Array], { type: contentType })
287
     }
355
     }
288
   }
356
   }