增加题目的编辑功能

This commit is contained in:
zhl 2021-04-22 20:52:19 +08:00
parent e12bafe5e4
commit 30ccb6edd5
6 changed files with 216 additions and 154 deletions

48
src/api/question.ts Normal file
View File

@ -0,0 +1,48 @@
import request from '@/utils/request'
export interface IQuestionData {
_id?: string,
question: string,
a1: string,
a2?: string,
a3?: string,
a4?: string,
group?: string,
tag?: string,
quality: number
}
export const defaultQuestionData: IQuestionData = {
quality: 3,
a1: '', question: ''
}
export const getQuestions = (params: any) =>
request({
url: '/puzzles',
method: 'post',
params
})
export const getQuestion = (id: string, params: any) =>
request({
url: `/puzzle/${id}`,
method: 'get',
params
})
export const saveQuestion = (data: any) =>
request({
url: `/puzzle/save`,
method: 'post',
data
})
export const deleteQuestion = (id: string) =>
request({
url: `/puzzle/${id}/delete`,
method: 'post'
})

View File

@ -1,44 +0,0 @@
import axios from 'axios'
import {IQuestionData } from '@/api/types'
export const defaultQuestionData: IQuestionData = {
option: [],
answer: '', attachment: '', parts: [], stars: 0, status: 0, type: 0,
id: '',
title: '',
tags: []
}
/**
*
* @return {Promise<void>}
*/
export async function randomOne() {
let url = ''
return axios.get(url, {})
.then(res => {
return res.data
})
}
/**
*
* @param data
* @return {Promise<void>}
*/
export async function updateOne(data: any) {
let url = ''
return axios.post(url, data)
.then(res => {
return res.data
})
}
/**
*
*/
export async function queryList(str: string) {
let url = ''
return axios.post(url, {key: str})
.then(res => {
return res.data
})
}

27
src/api/types.d.ts vendored
View File

@ -14,33 +14,6 @@ export interface IArticleData {
attachments: []
}
export interface IQuestionData {
id: string,
title: string,
/**
*
*/
parts?: string[],
tags: string[],
answer: string,
/**
*
*/
option: string[],
/**
*
* 0: 文字题
* 1: 图文
*/
type: number,
attachment?: string,
/**
*
*/
stars: number,
status: number,
}
export interface IShopData {
_id?: string,
name: string,

View File

@ -21,7 +21,7 @@ const questionRoutes: RouteConfig = {
}
},
{
path: 'edit/:id(\\d+)',
path: 'edit/:id',
component: () => import('@/views/question/editor.vue'),
name: 'QuestionEditor',
meta: {

View File

@ -8,23 +8,20 @@
>
<sticky
:z-index="10"
:class-name="'sub-navbar '+postForm.status"
class-name="sub-navbar"
>
<el-button @click="onCancel">
取消
</el-button>
<el-button
v-loading="loading"
style="margin-left: 10px;"
type="success"
@click="submitForm"
>
Publish
</el-button>
<el-button
v-loading="loading"
type="warning"
@click="draftForm"
>
Draft
保存
</el-button>
</sticky>
<div class="createPost-main-container">
@ -35,7 +32,7 @@
prop="title"
>
<material-input
v-model="postForm.title"
v-model="postForm.question"
:maxlength="100"
name="name"
required
@ -53,9 +50,10 @@
label="答案:"
>
<el-input
v-model="postForm.answer"
v-model="postForm.a1"
:rows="1"
placeholder="输入答案"
required
/>
</el-form-item>
</el-col>
@ -66,11 +64,11 @@
class="postInfo-container-item"
>
<el-rate
v-model="postForm.stars"
:max="5"
v-model="postForm.quality"
:max="3"
:colors="['#99A9BF', '#F7BA2A', '#ff5900']"
:low-threshold="1"
:high-threshold="5"
:high-threshold="3"
style="display:inline-block"
/>
</el-form-item>
@ -84,7 +82,7 @@
label="混淆答案1:"
>
<el-input
v-model="postForm.answer"
v-model="postForm.a2"
:rows="1"
placeholder="输入答案"
/>
@ -97,7 +95,7 @@
label="混淆答案2:"
>
<el-input
v-model="postForm.answer"
v-model="postForm.a3"
:rows="1"
placeholder="输入答案"
/>
@ -110,7 +108,7 @@
label="混淆答案3:"
>
<el-input
v-model="postForm.answer"
v-model="postForm.a4"
:rows="1"
placeholder="输入答案"
/>
@ -124,7 +122,6 @@
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import { getArticle } from '@/api/articles'
import { AppModule } from '@/store/modules/app'
import { TagsViewModule, ITagView } from '@/store/modules/tags-view'
import MaterialInput from '@/components/MaterialInput/index.vue'
@ -132,7 +129,13 @@ import Sticky from '@/components/Sticky/index.vue'
import Tinymce from '@/components/Tinymce/index.vue'
import UploadImage from '@/components/UploadImage/index.vue'
import { Form } from 'element-ui'
import { defaultQuestionData } from '@/api/questionPre'
import {
defaultQuestionData,
getQuestion,
getQuestions,
saveQuestion
} from '@/api/question'
import { saveCoupon } from '@/api/coupon'
@Component({
name: 'QuestionPrepare',
@ -144,7 +147,6 @@ import { defaultQuestionData } from '@/api/questionPre'
}
})
export default class extends Vue {
@Prop({ default: false }) private isEdit!: boolean
private validateRequire = (rule: any, value: string, callback: Function) => {
if (value === '') {
@ -181,9 +183,9 @@ export default class extends Vue {
created() {
if (this.isEdit) {
const id = this.$route.params && this.$route.params.id
this.fetchData(parseInt(id))
if (id) {
this.fetchData(id)
}
// Why need to make a copy of this.$route here?
// Because if you enter this page and quickly switch tag, may be in the execution of this.setTagsViewTitle function, this.$route is no longer pointing to the current page
@ -199,11 +201,11 @@ export default class extends Vue {
private async fetchData(id: number) {
try {
const { data } = await getArticle(id, { /* Your params here */ })
this.postForm = data.article
const { data } = await getQuestion(id, { /* Your params here */ })
this.postForm = data
// Just for test
this.postForm.title += ` Article Id:${this.postForm.id}`
const title = this.lang === 'zh' ? '编辑文章' : 'Edit Article'
this.postForm.title += ` Question Id:${this.postForm.id}`
const title = this.lang === 'zh' ? '编辑题目' : 'Edit Question'
// Set tagsview title
this.setTagsViewTitle(title)
// Set page title
@ -225,34 +227,38 @@ export default class extends Vue {
document.title = `${title} - ${this.postForm.id}`
}
private submitForm() {
(this.$refs.postForm as Form).validate(valid => {
if (valid) {
private async submitForm() {
const form = <Form>this.$refs.postForm
try {
await form.validate()
this.loading = true
const {data} = await saveQuestion(this.postForm)
this.postForm = data
this.loading = false
this.$notify({
title: 'Success',
message: 'The post published successfully',
message: '题目保存成功',
type: 'success',
duration: 2000
})
// Just to simulate the time of the request
setTimeout(() => {
this.loading = false
}, 0.5 * 1000)
} else {
} catch (err) {
console.error('Submit Error!')
return false
}
}
private async onCancel() {
try {
await this.$confirm('确认不保存当前记录?', 'Warning', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
this.$store.dispatch("delView", this.$route)
this.$router.go(-1)
} catch(e) {
}
private draftForm() {
this.$message({
message: 'The draft saved successfully',
type: 'success',
showClose: true,
duration: 1000
})
}
}

View File

@ -1,5 +1,16 @@
<template>
<div class="app-container">
<!-- filter -->
<el-form ref="filterForm" :inline="true" :model="filterForm" class="filter">
<el-form-item label="关键字" prop="key">
<el-input v-model="filterForm.key" placeholder="关键字"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="search">查询</el-button>
<el-button @click="resetFilterForm">重置</el-button>
</el-form-item>
</el-form>
<router-link to="/question/create">
<el-button
type="primary"
@ -16,45 +27,51 @@
highlight-current-row
style="width: 100%;margin-top:30px;"
>
<el-table-column
width="180px"
align="center"
label="时间"
label="添加时间"
>
<template slot-scope="{row}">
<span>{{ row.displayTime | parseTime }}</span>
<span>{{ row.createtime | parseTime }}</span>
</template>
</el-table-column>
<el-table-column
width="180px"
label="类型"
>
<template slot-scope="{row}">
<span>{{ row.type }}</span>
</template>
</el-table-column>
<el-table-column
min-width="300px"
label="标题"
min-width="200px"
label="名称"
>
<template slot-scope="{row}">
<router-link
:to="'/question/edit/'+row._id"
class="link-type"
>
<span>{{ row.title }}</span>
<span>{{ row.question }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column
label="答案"
>
<template slot-scope="{row}">
<span>{{ row.a1 }}</span>
</template>
</el-table-column>
<el-table-column
label="混淆答案"
>
<template slot-scope="{row}">
<span>{{ row.a2 || '' }} {{ row.a3 || '' }} {{ row.a4 || '' }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
label="操作"
width="120"
>
<template slot-scope="{row}">
<router-link :to="'/question/edit/'+row.id">
<template slot-scope="scope">
<router-link :to="'/question/edit/'+scope.row._id">
<el-button
type="primary"
size="small"
@ -63,6 +80,14 @@
编辑
</el-button>
</router-link>
<el-button
type="danger"
size="small"
style="margin-left: 10px"
@click="handleDelete(scope)"
>
{{ $t('permission.delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
@ -79,9 +104,12 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { getArticles } from '@/api/articles'
import { IArticleData } from '@/api/types'
import { IShopData } from '@/api/types'
import Pagination from '@/components/Pagination/index.vue'
import { deleteShop, getShops } from '@/api/shop'
import { parseTime } from '@/utils'
import { Form } from 'element-ui'
import { deleteQuestion, getQuestions, IQuestionData } from '@/api/question'
@Component({
name: 'QuestionList',
@ -90,34 +118,85 @@ import Pagination from '@/components/Pagination/index.vue'
},
filters: {
parseTime: (timestamp: string) => {
return new Date(timestamp).toISOString()
return parseTime(timestamp)
},
parseDate: (timestamp: string) => {
if (!timestamp) {
return '-'
}
return parseTime(timestamp, '{y}-{m}-{d}')
},
formatCount: (count: string) => {
if (!count) {
return 0
}
return count
}
}
})
export default class extends Vue {
private total = 0
private list: IArticleData[] = []
private list: IQuestionData[] = []
private listLoading = true
private allDepts = []
private listQuery = {
page: 1,
limit: 20
limit: 20,
key: ''
}
private filterForm = {
key: ''
}
created() {
this.getList()
}
private async getList() {
this.listLoading = true
const { data } = await getArticles(this.listQuery)
this.list = data.items
this.total = data.total
// Just to simulate the time of the request
setTimeout(() => {
const { data } = await getQuestions(this.listQuery)
this.listLoading = false
}, 0.5 * 1000)
this.list = data.records
this.total = data.total
}
private async handleDelete(scope: any) {
const { $index, row } = scope
await this.$confirm('确认删除该记录?', 'Warning', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
await deleteQuestion(row._id)
this.list.splice($index, 1)
this.$message({
type: 'success',
message: '删除成功!'
})
}
private search() {
this.filterData()
}
private filterData() {
this.listQuery.key = this.filterForm.key
this.listQuery.page = 1
this.getList()
}
private resetFilterForm() {
const ref = <Form>this.$refs.filterForm
ref.resetFields()
}
private async getRemoteDeptList(name: string) {
const { data } = await getShops({ key: name })
if (!data.records) return
this.allDepts = data.records
}
}
</script>