增加店铺自定义挑战活动的导入导出功能
This commit is contained in:
parent
7aa1492f9d
commit
6d3ae0aa95
@ -33,7 +33,7 @@
|
||||
"vue-svgicon": "^3.2.9",
|
||||
"vuex": "^3.5.1",
|
||||
"vuex-module-decorators": "^1.0.1",
|
||||
"xlsx": "^0.16.8"
|
||||
"xlsx": "^0.17.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/clipboard": "^2.0.1",
|
||||
|
@ -1,6 +1,15 @@
|
||||
import request from '@/utils/request'
|
||||
import { IRewardData } from '@/api/activity'
|
||||
|
||||
export interface IExamQuerstion {
|
||||
_id?: string
|
||||
question: string
|
||||
a1: string
|
||||
a2?: string
|
||||
a3?: string
|
||||
a4?: string
|
||||
}
|
||||
|
||||
export interface IExamData {
|
||||
_id?: string
|
||||
shop: string
|
||||
@ -12,7 +21,9 @@ export interface IExamData {
|
||||
beginTime: number
|
||||
endTime: number
|
||||
active: number
|
||||
source: number
|
||||
rewardInfo: IRewardData[]
|
||||
questions: IExamQuerstion[]
|
||||
}
|
||||
|
||||
export const defaultExamData: IExamData = {
|
||||
@ -24,8 +35,9 @@ export const defaultExamData: IExamData = {
|
||||
qcount: 0,
|
||||
qtypes: [],
|
||||
shop: '',
|
||||
rewardInfo: []
|
||||
|
||||
source: 0,
|
||||
rewardInfo: [],
|
||||
questions: []
|
||||
}
|
||||
|
||||
export const getExams = (params: any) =>
|
||||
|
696
src/views/exam/components/PuzzleList.vue
Normal file
696
src/views/exam/components/PuzzleList.vue
Normal file
@ -0,0 +1,696 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="action-bar">
|
||||
<input
|
||||
ref="excel-upload-input"
|
||||
class="excel-upload-input"
|
||||
type="file"
|
||||
accept=".xlsx, .xls"
|
||||
@change="handleClick"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click="handleAddQuestion"
|
||||
>
|
||||
添加
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="el-icon-s-promotion"
|
||||
@click="importFromOther"
|
||||
>
|
||||
从其他挑战导入
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
icon="el-icon-upload2"
|
||||
@click="handleImport"
|
||||
>
|
||||
导入Excel
|
||||
</el-button>
|
||||
<el-button
|
||||
type="warning"
|
||||
icon="el-icon-download"
|
||||
:loading="downloadLoading"
|
||||
@click="handleExport"
|
||||
>
|
||||
{{exportBtnName}}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete-solid"
|
||||
@click="handleRemoveAll"
|
||||
>
|
||||
{{deleteBtnName}}
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
row-key="question"
|
||||
ref="question_table"
|
||||
highlight-current-row
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
:reserve-selection="true"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
type="index"
|
||||
:index="computeTableIndex"
|
||||
width="50">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="题目"
|
||||
prop="question"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="正确答案"
|
||||
prop="a1"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="混淆答案1"
|
||||
prop="a2"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="混淆答案2"
|
||||
prop="a3"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="混淆答案3"
|
||||
prop="a4"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
align="center"
|
||||
width="180"
|
||||
label="操作"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="el-icon-edit"
|
||||
v-permission="['shopexam:edit']"
|
||||
@click="handleEditQuestion(scope)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
style="margin-left: 10px"
|
||||
v-permission="['shopexam:delete']"
|
||||
@click="handleDelete(scope)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- pagination -->
|
||||
<el-pagination
|
||||
:hide-on-single-page="false"
|
||||
:current-page="currentPage"
|
||||
:page-sizes="[5, 10, 20, 50, 100]"
|
||||
:page-size="pageSize"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="dataCount"
|
||||
class="al-r"
|
||||
@size-change="sizeChange"
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
<el-dialog
|
||||
:visible.sync="dialogVisible"
|
||||
:title="dialogType==='edit'?'Edit Question':'New Question'"
|
||||
>
|
||||
<el-form
|
||||
:model="record"
|
||||
ref="modalForm"
|
||||
:rules="modalRules"
|
||||
label-width="120px"
|
||||
label-position="left"
|
||||
>
|
||||
<el-form-item label="题目" prop="question">
|
||||
<el-input
|
||||
v-model="record.question"
|
||||
placeholder="题目"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="正确答案" prop="a1">
|
||||
<el-input
|
||||
v-model="record.a1"
|
||||
placeholder="正确答案"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="混淆答案1" prop="a2">
|
||||
<el-input
|
||||
v-model="record.a2"
|
||||
placeholder="混淆答案1"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="混淆答案2" prop="a3">
|
||||
<el-input
|
||||
v-model="record.a3"
|
||||
placeholder="混淆答案2"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="混淆答案3" prop="a4">
|
||||
<el-input
|
||||
v-model="record.a4"
|
||||
placeholder="混淆答案3"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div style="text-align:right;">
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="closeModal"
|
||||
>
|
||||
{{$t('permission.cancel')}}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="saveModalData"
|
||||
>
|
||||
{{$t('permission.confirm')}}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
:visible.sync="listVisible"
|
||||
title="选择活动"
|
||||
>
|
||||
<div class="action-bar">
|
||||
<el-select
|
||||
v-model="shop"
|
||||
placeholder="选择店铺"
|
||||
name="shop"
|
||||
required
|
||||
class="w100"
|
||||
v-if="userLevel === 1"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in allDepts"
|
||||
:key="item._id"
|
||||
:label="item.name"
|
||||
:value="item._id"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="listLoading"
|
||||
:data="shopList"
|
||||
border
|
||||
fit
|
||||
stripe
|
||||
highlight-current-row
|
||||
@current-change="clickChange"
|
||||
style="width: 100%;margin-top:30px;"
|
||||
>
|
||||
<el-table-column label="选择" width="55">
|
||||
<template slot-scope="scope">
|
||||
<el-radio v-model="tableRadio" :label="scope.row"><i></i></el-radio>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="店铺"
|
||||
prop="shop"
|
||||
v-if="userLevel === 1"
|
||||
:formatter = "formatDept"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="200px"
|
||||
label="名称"
|
||||
>
|
||||
<template slot-scope="{row}">
|
||||
<span>{{ row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
min-width="200px"
|
||||
label="题目数量"
|
||||
>
|
||||
<template slot-scope="{row}">
|
||||
<span>{{ row.questions.length }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="text-align:right;">
|
||||
<el-button
|
||||
type="danger"
|
||||
@click="closeListModal"
|
||||
>
|
||||
{{$t('permission.cancel')}}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="importQuestions"
|
||||
>
|
||||
{{$t('permission.confirm')}}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from 'vue-property-decorator'
|
||||
import XLSX from 'xlsx'
|
||||
import { getExams, IExamData, IExamQuerstion } from '@/api/exam'
|
||||
import { exportJson2Excel } from '@/utils/excel'
|
||||
import { formatJson, parseTime } from '@/utils'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { UserModule } from '@/store/modules/user'
|
||||
import { IShopData } from '@/api/types'
|
||||
import { getShops } from '@/api/shop'
|
||||
|
||||
declare module 'vue/types/vue' {
|
||||
interface Vue {
|
||||
questions: IExamQuerstion[]
|
||||
examid?: string
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
name: 'PuzzleList',
|
||||
props: ['questions', 'examid'],
|
||||
model: {
|
||||
prop: 'questions',
|
||||
event: 'update'
|
||||
}
|
||||
})
|
||||
export default class extends Vue {
|
||||
private excelData = {
|
||||
header: null,
|
||||
results: null
|
||||
}
|
||||
|
||||
// pagination
|
||||
private currentPage = 1
|
||||
private pageSize = 5
|
||||
private dataCount = 0
|
||||
private tableData: IExamQuerstion[] = []
|
||||
private loading = false
|
||||
private downloadLoading = false
|
||||
private filename = ''
|
||||
private multipleSelection = []
|
||||
private deleteBtnName = '删除所有'
|
||||
private exportBtnName = '导出所有'
|
||||
private dialogVisible = false
|
||||
private listVisible = false
|
||||
private dialogType = 'new'
|
||||
private record = Object.assign({}, this.defaultPuzzle())
|
||||
private shop = UserModule.department || ''
|
||||
private allDepts: IShopData[] = []
|
||||
private listLoading = false
|
||||
private shopList: IExamData[] = []
|
||||
private tableRadio: any = {}
|
||||
|
||||
$refs!: {
|
||||
modalForm: HTMLFormElement
|
||||
'question_table': HTMLTableElement
|
||||
'excel-upload-input': HTMLFormElement
|
||||
}
|
||||
|
||||
get userLevel() {
|
||||
return UserModule.level
|
||||
}
|
||||
|
||||
async created() {
|
||||
if (UserModule.level === 1) {
|
||||
await this.getRemoteDeptList()
|
||||
}
|
||||
}
|
||||
|
||||
private modalRules = {
|
||||
question: [{ required: true, message: '请输入题目', trigger: 'blur' },
|
||||
{ min: 2, max: 35, message: '长度在 2 到 35 个字符', trigger: 'blur' }],
|
||||
a1: [{ required: true, message: '请输入正确答案', trigger: 'blur' }],
|
||||
a2: [{ required: true, message: '至少输入一个错误答案', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
@Watch('questions')
|
||||
private initDataChange() {
|
||||
this.sliceData()
|
||||
}
|
||||
|
||||
@Watch('multipleSelection')
|
||||
private selectChange() {
|
||||
this.deleteBtnName = this.multipleSelection.length > 0 ? '删除选中项' : '删除所有'
|
||||
this.exportBtnName = this.multipleSelection.length > 0 ? '导出选中项' : '导出所有'
|
||||
}
|
||||
|
||||
@Watch('shop')
|
||||
private shopChange() {
|
||||
console.log(`shop change: ${this.shop}`)
|
||||
this.getList()
|
||||
}
|
||||
|
||||
private defaultPuzzle() {
|
||||
return {
|
||||
question: '',
|
||||
a1: ''
|
||||
}
|
||||
}
|
||||
|
||||
// begin of 题库编辑
|
||||
private handleClick(e: MouseEvent) {
|
||||
const files = (e.target as HTMLInputElement).files
|
||||
if (files) {
|
||||
const rawFile = files[0] // only use files[0]
|
||||
this.upload(rawFile)
|
||||
}
|
||||
}
|
||||
|
||||
private handleAddQuestion() {
|
||||
this.dialogType = 'new'
|
||||
this.dialogVisible = true
|
||||
this.record = Object.assign({}, this.defaultPuzzle())
|
||||
}
|
||||
|
||||
private handleEditQuestion(scope: any) {
|
||||
const { $index, row } = scope
|
||||
this.dialogType = 'edit'
|
||||
this.dialogVisible = true
|
||||
this.record = cloneDeep(scope.row)
|
||||
}
|
||||
|
||||
private handleImport() {
|
||||
(this.$refs['excel-upload-input']).click()
|
||||
}
|
||||
|
||||
private async handleRemoveAll() {
|
||||
try {
|
||||
const str = this.multipleSelection.length > 0 ? '确定删除选中的题目' : '确定删除所有题目'
|
||||
await this.$confirm(str, 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
if (this.multipleSelection.length > 0) {
|
||||
this.questions = this.questions.filter(o => this.multipleSelection.indexOf(o) === -1)
|
||||
this.$refs.question_table.clearSelection()
|
||||
} else {
|
||||
this.questions.length = 0
|
||||
}
|
||||
this.sliceData()
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: 'Deleted!'
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
private handleExport() {
|
||||
this.handleDownload()
|
||||
}
|
||||
|
||||
private async handleDelete(scope: any) {
|
||||
const { $index, row } = scope
|
||||
console.log($index, row)
|
||||
try {
|
||||
await this.$confirm('确定删除当前记录?', 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
this.questions.splice(this.questions.indexOf(row), 1)
|
||||
this.sliceData()
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: 'Deleted!'
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
|
||||
private handleSelectionChange(val: any) {
|
||||
this.multipleSelection = val
|
||||
console.log(this.multipleSelection)
|
||||
}
|
||||
|
||||
private upload(rawFile: File) {
|
||||
this.$refs['excel-upload-input'].value = '' // Fixes can't select the same excel
|
||||
|
||||
this.readerData(rawFile)
|
||||
}
|
||||
|
||||
private readerData(rawFile: File) {
|
||||
this.loading = true
|
||||
const reader = new FileReader()
|
||||
reader.onload = e => {
|
||||
const data = (e.target as FileReader).result
|
||||
const workbook = XLSX.read(data, { type: 'array' })
|
||||
const firstSheetName = workbook.SheetNames[0]
|
||||
const worksheet = workbook.Sheets[firstSheetName]
|
||||
const header = this.getHeaderRow(worksheet)
|
||||
const results = XLSX.utils.sheet_to_json(worksheet)
|
||||
this.generateData(header, results)
|
||||
this.loading = false
|
||||
}
|
||||
reader.readAsArrayBuffer(rawFile)
|
||||
}
|
||||
|
||||
private getHeaderRow(sheet: { [key: string]: any }) {
|
||||
const headers: string[] = []
|
||||
const range = XLSX.utils.decode_range(sheet['!ref'])
|
||||
const R = range.s.r
|
||||
// start in the first row
|
||||
for (let C = range.s.c; C <= range.e.c; ++C) { // walk every column in the range
|
||||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
|
||||
// find the cell in the first row
|
||||
let hdr = ''
|
||||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
|
||||
if (hdr === '') {
|
||||
hdr = 'UNKNOWN ' + C // replace with your desired default
|
||||
}
|
||||
headers.push(hdr)
|
||||
}
|
||||
return headers
|
||||
}
|
||||
|
||||
private generateData(header: any, results: any) {
|
||||
this.excelData.header = header
|
||||
this.excelData.results = results
|
||||
const questionSet = new Set()
|
||||
for (const _q of this.questions) {
|
||||
questionSet.add(_q.question)
|
||||
}
|
||||
let count = 0
|
||||
for (const _q of results) {
|
||||
if (!questionSet.has(_q.question)) {
|
||||
this.questions.push(_q)
|
||||
questionSet.add(_q.question)
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
this.sliceData()
|
||||
console.log(this.excelData)
|
||||
const msg = `操作成功, 共导入${count}个题目`
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: msg
|
||||
})
|
||||
}
|
||||
|
||||
// pagination
|
||||
private sizeChange(val: number) {
|
||||
this.pageSize = val
|
||||
this.sliceData()
|
||||
}
|
||||
|
||||
private pageChange(val: number) {
|
||||
this.currentPage = val
|
||||
this.sliceData()
|
||||
}
|
||||
|
||||
private computeTableIndex(index: number) {
|
||||
return (this.currentPage - 1) * this.pageSize + index + 1
|
||||
}
|
||||
|
||||
private sliceData() {
|
||||
// 满足过滤条件 -> 分页
|
||||
const data = this.filterData()
|
||||
this.tableData = data.slice(
|
||||
(this.currentPage - 1) * this.pageSize,
|
||||
this.currentPage * this.pageSize
|
||||
)
|
||||
if (this.tableData.length === 0 && this.currentPage > 1) {
|
||||
this.currentPage -= 1
|
||||
this.sliceData()
|
||||
}
|
||||
}
|
||||
|
||||
private filterData() {
|
||||
const result: IExamQuerstion[] = []
|
||||
for (const _d of this.questions) {
|
||||
result.push(_d)
|
||||
}
|
||||
this.dataCount = result.length
|
||||
return result
|
||||
}
|
||||
|
||||
private valchange(val: any) {
|
||||
console.log('valchange', val)
|
||||
this.$emit('update', val)
|
||||
}
|
||||
|
||||
private handleDownload() {
|
||||
this.downloadLoading = true
|
||||
const tHeader = ['question', 'a1', 'a2', 'a3', 'a4']
|
||||
const list = this.multipleSelection.length > 0 ? this.multipleSelection.slice(0) : this.questions.slice(0)
|
||||
this.filename = parseTime(new Date(), '{y}{m}{d}{h}{i}{s}')
|
||||
const data = formatJson(tHeader, list)
|
||||
console.log('begin generate excel')
|
||||
exportJson2Excel(tHeader, data, this.filename !== '' ? this.filename : undefined, undefined, undefined, true, 'xlsx')
|
||||
this.downloadLoading = false
|
||||
}
|
||||
|
||||
private importFromOther() {
|
||||
console.log('importFromOther')
|
||||
this.listVisible = true
|
||||
}
|
||||
|
||||
private closeModal() {
|
||||
this.dialogVisible = false
|
||||
this.$refs.modalForm.clearValidate()
|
||||
}
|
||||
|
||||
private closeListModal() {
|
||||
this.listVisible = false
|
||||
}
|
||||
|
||||
private saveModalData() {
|
||||
const isEdit = this.dialogType === 'edit'
|
||||
this.$refs.modalForm.validate(async(valid: boolean) => {
|
||||
if (!valid) {
|
||||
this.$message.error('请按要求填写表单')
|
||||
return false
|
||||
}
|
||||
if (isEdit) {
|
||||
for (let index = 0; index < this.questions.length; index++) {
|
||||
if (this.questions[index]._id === this.record._id) {
|
||||
this.questions.splice(index, 1, Object.assign({}, this.record))
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.questions.push(this.record)
|
||||
}
|
||||
this.dialogVisible = false
|
||||
this.$notify({
|
||||
title: 'Success',
|
||||
dangerouslyUseHTMLString: true,
|
||||
message: `
|
||||
题目编辑成功, 请点击保存
|
||||
`,
|
||||
type: 'success'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// begin of 活动选择
|
||||
private async getRemoteDeptList() {
|
||||
const { data } = await getShops({ })
|
||||
if (!data.records) return
|
||||
this.allDepts = data.records
|
||||
}
|
||||
|
||||
private formatDept(row: number, column: number, cellValue: string) {
|
||||
let result = '未指定'
|
||||
for (const dep of this.allDepts) {
|
||||
if (dep._id === cellValue) {
|
||||
result = dep.name
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private async getList() {
|
||||
this.listLoading = true
|
||||
const { data } = await getExams({
|
||||
page: 1,
|
||||
limit: 20,
|
||||
key: '',
|
||||
shop: this.shop
|
||||
})
|
||||
this.listLoading = false
|
||||
this.shopList = data.records.filter(o => o._id !== this.examid)
|
||||
}
|
||||
|
||||
private clickChange(item: any) {
|
||||
this.tableRadio = item
|
||||
console.log(this.tableRadio)
|
||||
}
|
||||
|
||||
private async importQuestions() {
|
||||
if (!(this.tableRadio?.questions?.length > 0)) {
|
||||
this.$message.error('请先选择一个有题目的活动')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await this.$confirm('确定导入当前挑战活动的所有题目?', 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
const questionSet = new Set()
|
||||
for (const _q of this.questions) {
|
||||
questionSet.add(_q.question)
|
||||
}
|
||||
let count = 0
|
||||
for (const _q of this.tableRadio.questions) {
|
||||
if (!questionSet.has(_q.question)) {
|
||||
this.questions.push(_q)
|
||||
questionSet.add(_q.question)
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
this.sliceData()
|
||||
console.log(this.excelData)
|
||||
this.closeListModal()
|
||||
const msg = `操作成功, 共导入${count}个题目`
|
||||
this.$message({
|
||||
type: 'success',
|
||||
message: msg
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.action-bar {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.excel-upload-input {
|
||||
display: none;
|
||||
z-index: -9999;
|
||||
}
|
||||
.el-form-item{
|
||||
margin-bottom: 22px;
|
||||
}
|
||||
</style>
|
@ -103,8 +103,23 @@
|
||||
required
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="题目来源:"
|
||||
prop="source"
|
||||
>
|
||||
<el-select
|
||||
v-model="postForm.source"
|
||||
placeholder="选择题目来源"
|
||||
name="source"
|
||||
required
|
||||
>
|
||||
<el-option :value="0" label="系统题库">系统题库</el-option>
|
||||
<el-option :value="1" label="自定义题库">自定义题库</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="题库分类"
|
||||
v-show="postForm.source === 0"
|
||||
>
|
||||
<el-tree
|
||||
:data="typeOptions"
|
||||
@ -118,15 +133,27 @@
|
||||
</el-tree>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="题目"
|
||||
v-show="postForm.source === 1"
|
||||
>
|
||||
<puzzle-list
|
||||
v-model= "postForm.questions"
|
||||
:examid="postForm._id"
|
||||
></puzzle-list>
|
||||
</el-form-item>
|
||||
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="奖励设置" name="third">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click="handleCreateReward"
|
||||
>
|
||||
添加
|
||||
</el-button>
|
||||
<div class="action-bar">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-edit"
|
||||
@click="handleCreateReward"
|
||||
>
|
||||
添加
|
||||
</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="postForm.rewardInfo"
|
||||
border
|
||||
@ -277,6 +304,7 @@ import { IShopData } from '@/api/types'
|
||||
import { ElTree } from 'element-ui/types/tree'
|
||||
import { UserModule } from '@/store/modules/user'
|
||||
import { defaultRewardData, IRewardData } from '@/api/activity'
|
||||
import PuzzleList from './components/PuzzleList.vue'
|
||||
|
||||
@Component({
|
||||
name: 'ExamEditor',
|
||||
@ -285,7 +313,8 @@ import { defaultRewardData, IRewardData } from '@/api/activity'
|
||||
Sticky,
|
||||
UploadImage,
|
||||
RegionPicker,
|
||||
Tinymce
|
||||
Tinymce,
|
||||
PuzzleList
|
||||
}
|
||||
})
|
||||
export default class extends Vue {
|
||||
@ -377,13 +406,13 @@ export default class extends Vue {
|
||||
this.dataRange.push(new Date(data.beginTime))
|
||||
this.dataRange.push(new Date(data.endTime))
|
||||
}
|
||||
|
||||
// Just for test
|
||||
const title = this.lang === 'zh' ? '编辑挑战' : 'Edit Exam'
|
||||
// Set tagsview title
|
||||
this.setTagsViewTitle(title)
|
||||
// Set page title
|
||||
this.setPageTitle(title)
|
||||
// this.$forceUpdate()
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
@ -408,7 +437,11 @@ export default class extends Vue {
|
||||
this.postForm.beginTime = this.dataRange[0].getTime()
|
||||
this.postForm.endTime = this.dataRange[1].getTime()
|
||||
}
|
||||
this.postForm.qtypes = this.$refs.typeTree.getCheckedKeys()
|
||||
if (this.postForm.source === 0 && this.$refs.typeTree) {
|
||||
this.postForm.qtypes = this.$refs.typeTree.getCheckedKeys()
|
||||
} else {
|
||||
this.postForm.qtypes = []
|
||||
}
|
||||
this.loading = true
|
||||
const { data } = await saveExam(this.postForm)
|
||||
this.postForm = data
|
||||
@ -427,7 +460,7 @@ export default class extends Vue {
|
||||
|
||||
private async onCancel() {
|
||||
try {
|
||||
await this.$confirm('确认不保存当前活动信息?', 'Warning', {
|
||||
await this.$confirm('确认不保存当前挑战信息?', 'Warning', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
@ -494,6 +527,11 @@ export default class extends Vue {
|
||||
children: subArr
|
||||
})
|
||||
}
|
||||
this.typeOptions.push({
|
||||
id: 'customer',
|
||||
label: '自定义',
|
||||
children: []
|
||||
})
|
||||
}
|
||||
|
||||
// begin of award list
|
||||
@ -591,4 +629,11 @@ export default class extends Vue {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.action-bar{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.excel-upload-input {
|
||||
display: none;
|
||||
z-index: -9999;
|
||||
}
|
||||
</style>
|
||||
|
@ -81,6 +81,13 @@
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="题目类型"
|
||||
prop="source"
|
||||
:formatter="formatSource"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
align="center"
|
||||
width="180"
|
||||
@ -276,5 +283,9 @@ export default class extends Vue {
|
||||
private formatBool(row: number, column: number, cellValue: boolean) {
|
||||
return cellValue ? '是' : '否'
|
||||
}
|
||||
|
||||
private formatSource(row: number, column: number, cellValue: boolean) {
|
||||
return cellValue ? '自定义' : '系统'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -11,9 +11,9 @@
|
||||
placeholder="所有"
|
||||
class="w100"
|
||||
>
|
||||
<el-option value="all">所有</el-option>
|
||||
<el-option value="true">已审核</el-option>
|
||||
<el-option value="false">未审核</el-option>
|
||||
<el-option value="all" label="所有">所有</el-option>
|
||||
<el-option value="true" label="已审核">已审核</el-option>
|
||||
<el-option value="false" label="未审核">未审核</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
|
@ -13043,10 +13043,10 @@ ws@^7.0.0, ws@^7.4.4:
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1"
|
||||
integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==
|
||||
|
||||
xlsx@^0.16.8:
|
||||
version "0.16.9"
|
||||
resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.16.9.tgz#dacd5bb46bda6dd3743940c9c3dc1e2171826256"
|
||||
integrity sha512-gxi1I3EasYvgCX1vN9pGyq920Ron4NO8PNfhuoA3Hpq6Y8f0ECXiy4OLrK4QZBnj1jx3QD+8Fq5YZ/3mPZ5iXw==
|
||||
xlsx@^0.17.0:
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.17.0.tgz#028176a0140967dcee1817d221678461e47481c8"
|
||||
integrity sha512-bZ36FSACiAyjoldey1+7it50PMlDp1pcAJrZKcVZHzKd8BC/z6TQ/QAN8onuqcepifqSznR6uKnjPhaGt6ig9A==
|
||||
dependencies:
|
||||
adler-32 "~1.2.0"
|
||||
cfb "^1.1.4"
|
||||
|
Loading…
x
Reference in New Issue
Block a user