调整目录
This commit is contained in:
357
src/apps/AppAskForm/components/formDetail.vue
Normal file
357
src/apps/AppAskForm/components/formDetail.vue
Normal file
@@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<section class="formDetail">
|
||||
<ai-result v-if="result.tips" v-bind="result">
|
||||
<template v-if="isExam" #extra>
|
||||
<div flex class="scorePane">
|
||||
<div>成绩</div>
|
||||
<div class="fill"><em v-html="score"/> 分</div>
|
||||
</div>
|
||||
</template>
|
||||
</ai-result>
|
||||
<template v-else-if="form.id">
|
||||
<image v-if="form.headPicture" class="headPicture" :src="form.headPicture"/>
|
||||
<b class="title">{{ form.title || "标题" }}</b>
|
||||
<div class="tableExplain">{{ form.tableExplain }}</div>
|
||||
<u-form class="content" label-position="top">
|
||||
<u-form-item class="item" v-for="(op,i) in fields" :key="i" :label="(i+1)+'.'+op.fieldName"
|
||||
:required="op.fieldInfo.required==1">
|
||||
<template v-if="op.fieldType=='input'">
|
||||
<input v-model="op.fieldValue" :placeholder="op.fieldInfo.placeholder" :disabled="isResult"/>
|
||||
</template>
|
||||
<template v-else-if="op.fieldType=='textarea'">
|
||||
<textarea v-model="op.fieldValue" :disabled="isResult" :placeholder="op.fieldInfo.placeholder"/>
|
||||
</template>
|
||||
<template v-else-if="op.fieldType=='upload'">
|
||||
<ai-uploader @list="v=>op.fieldValue=v.map(e=>e.url)" :def="op.fieldValue" :disabled="isResult"
|
||||
preview action="/admin/file/add2"/>
|
||||
</template>
|
||||
<u-row v-else-if="op.fieldType=='radio'">
|
||||
<radio-group @change="({detail})=>op.fieldValue=detail.value">
|
||||
<div class="option" flex v-for="option in op.fieldInfo.options" :key="option.label">
|
||||
<radio :value="option.label" :disabled="isResult" :checked="op.fieldValue==option.label"/>
|
||||
<ai-image v-if="option.img" :src="option.img" preview/>
|
||||
<div class="label fill">{{ option.label }}</div>
|
||||
</div>
|
||||
</radio-group>
|
||||
</u-row>
|
||||
<u-row v-else-if="op.fieldType=='checkbox'">
|
||||
<checkbox-group @change="({detail})=>op.fieldValue=detail.value">
|
||||
<div class="option" flex v-for="option in op.fieldInfo.options" :key="option.label">
|
||||
<checkbox :value="option.label" :disabled="isResult"
|
||||
:checked="option.checked"/>
|
||||
<ai-image v-if="option.img" :src="option.img" preview/>
|
||||
<div class="label fill">{{ option.label }}</div>
|
||||
</div>
|
||||
</checkbox-group>
|
||||
</u-row>
|
||||
<template v-else-if="op.fieldType=='select'">
|
||||
<ai-select @data="v=>op.fieldValue=v.map(e=>e.value)" :list="op.fieldInfo.options" :disabled="isResult">
|
||||
<div class="option" flex>
|
||||
<div class="label fill" v-if="op.fieldValue">{{ op.fieldValue.toString() }}</div>
|
||||
<i class="fill" v-else>请选择</i>
|
||||
<u-icon name="arrow-right" color="#ddd"/>
|
||||
</div>
|
||||
</ai-select>
|
||||
</template>
|
||||
</u-form-item>
|
||||
</u-form>
|
||||
<div class="bottom" v-if="!(isPreview||isResult)">
|
||||
<div class="bottomBtn" @tap="handleSubmit">提交</div>
|
||||
</div>
|
||||
</template>
|
||||
<ai-loading v-else tips="调查问卷加载中..."/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import {mapState} from "vuex";
|
||||
import AiTextarea from "../../../components/AiTextarea";
|
||||
import AiUploader from "../../../components/AiUploader";
|
||||
import AiSelect from "../../../components/AiSelect";
|
||||
import AiLoading from "../../../components/AiLoading";
|
||||
import AiResult from "../../../components/AiResult";
|
||||
import AiImage from "../../../components/AiImage";
|
||||
import AiBack from "../../../components/AiBack";
|
||||
|
||||
export default {
|
||||
name: "formDetail",
|
||||
inject: {root: {}},
|
||||
components: {
|
||||
AiBack,
|
||||
AiImage,
|
||||
AiResult,
|
||||
AiLoading,
|
||||
AiSelect,
|
||||
AiUploader,
|
||||
AiTextarea,
|
||||
},
|
||||
computed: {
|
||||
...mapState(['openUser', 'token']),
|
||||
isExam() {
|
||||
return this.form?.type == 1
|
||||
},
|
||||
isResult() {
|
||||
return !!this.$route.query?.result
|
||||
},
|
||||
isPreview() {
|
||||
return !!this.$route.query?.preview
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {},
|
||||
fields: [],
|
||||
checkUser: false,
|
||||
result: {},
|
||||
score: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
form: {
|
||||
deep: true,
|
||||
handler(v) {
|
||||
this.fields = v?.fields?.map(e => {
|
||||
let fieldInfo = JSON.parse(e.fieldInfo)
|
||||
fieldInfo?.options?.map(op => {
|
||||
op.img = op?.img?.[0]?.url
|
||||
op.checked = !!e.fieldValue?.split(",")?.includes(op.label)
|
||||
})
|
||||
if (e.fieldType == 'select') {
|
||||
fieldInfo.options = fieldInfo.options.map(e => ({...e, value: e.label, label: e.label}))
|
||||
}
|
||||
return {...e, fieldInfo}
|
||||
}) || []
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
emitShow(){
|
||||
document.title = this.form.title || "调查问卷"
|
||||
},
|
||||
getForm() {
|
||||
let {id} = this.$route.query
|
||||
this.$http.post("/app/appquestionnairetemplate/queryDetailById", null, {
|
||||
withoutToken: true,
|
||||
params: {id}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.form = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
getResult() {
|
||||
let {id} = this.$route.query
|
||||
this.$http.post("/app/appquestionnairetemplate/commitCheck", null, {
|
||||
params: {id}
|
||||
}).then(res => {
|
||||
if (res?.data) {
|
||||
this.form = res.data
|
||||
}
|
||||
})
|
||||
},
|
||||
validateForm() {
|
||||
return !this.fields.some(e => {
|
||||
if (!!e?.fieldInfo?.required && !e.fieldValue?.toString()) {
|
||||
this.$u.toast(e.fieldName + "不能为空!")
|
||||
return true
|
||||
}
|
||||
})
|
||||
},
|
||||
handleSubmit() {
|
||||
if (this.validateForm()) {
|
||||
this.handleScore()
|
||||
let {avatar: avatarUrl, openId, name: nickName, type: userType, unionId, corpName} = this.openUser
|
||||
this.$http.post("/app/appquestionnairetemplate/commit", {
|
||||
fields: this.fields.map(e => ({
|
||||
...e,
|
||||
fieldInfo: JSON.stringify(e.fieldInfo),
|
||||
fieldValue: e.fieldValue?.toString()
|
||||
})),
|
||||
avatarUrl, openId, nickName, userType, unionId, corpName,
|
||||
totalScore: this.score,
|
||||
questionnaireTemplateId: this.$route.query.id
|
||||
}).then(res => {
|
||||
if (res?.code == 0) {
|
||||
this.result = {
|
||||
tips: "提交成功!感谢参与",
|
||||
}
|
||||
}
|
||||
}).catch(err => {
|
||||
this.$u.toast(err || "提交失败")
|
||||
})
|
||||
}
|
||||
},
|
||||
handleScore() {
|
||||
this.score = 0
|
||||
this.isExam && this.fields.map(field => {
|
||||
let item = field?.fieldInfo || {}
|
||||
let current = 0
|
||||
const calcScore = point => (current += (Number(point) || 0))
|
||||
if (item?.pointType == 0) {//此题有唯一答案和分值
|
||||
field.fieldValue?.toString() == item.answer?.toString() && calcScore(item?.points)
|
||||
} else if (item?.pointType == 1) {//每个选项都有对应分值
|
||||
item?.options?.map(op => {
|
||||
if (typeof field.fieldValue == "object") {
|
||||
if (field.fieldValue?.includes(op.label)) {
|
||||
calcScore(op.point)
|
||||
}
|
||||
} else {
|
||||
op.label == field.fieldValue && calcScore(op.point)
|
||||
}
|
||||
})
|
||||
} else if (item?.pointType == 2) {//答对几项得几分,答错不得分
|
||||
item?.options?.some(op => {
|
||||
if (typeof field.fieldValue == "object") {
|
||||
if (field.fieldValue?.includes(op.label)) {
|
||||
if (item.answer?.includes(op.label)) calcScore(op.point)
|
||||
else return current = 0
|
||||
}
|
||||
} else {
|
||||
op.label == field.fieldValue && calcScore(op.point)
|
||||
}
|
||||
})
|
||||
}
|
||||
this.score += current
|
||||
//打印每题打分
|
||||
if (!!field.fieldValue) {
|
||||
const typeResult = (reply, answer) => {
|
||||
console.log("题目:%s,回答:%s,得分:%s,总分:%s \n 答案:%s", field.fieldName,
|
||||
reply, current, this.score, answer)
|
||||
}
|
||||
typeResult(field.fieldValue?.toString(), item.answer?.toString())
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.isResult ? this.getResult() : this.getForm()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.formDetail {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
|
||||
.headPicture {
|
||||
width: 100%;
|
||||
height: 320px;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
font-size: 34px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding: 32px;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
z-index: 99;
|
||||
|
||||
.bottomBtn {
|
||||
width: 100%;
|
||||
line-height: 96px;
|
||||
background: #287DE1;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
height: 96px;
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.tableExplain {
|
||||
font-size: 28px;
|
||||
font-weight: 400;
|
||||
color: #666;
|
||||
padding: 32px 24px;
|
||||
}
|
||||
|
||||
::v-deep .u-form-item {
|
||||
.u-form-item--left {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.u-form-item--right__content__slot > * {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.display {
|
||||
justify-content: space-between;
|
||||
min-height: 58px;
|
||||
}
|
||||
|
||||
.uni-radio-input, .uni-checkbox-input {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.label {
|
||||
flex-shrink: 0;
|
||||
|
||||
* + & {
|
||||
margin-left: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.option {
|
||||
width: 100%;
|
||||
margin-right: 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 64px 32px 200px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
::v-deep .scorePane {
|
||||
width: calc(100% - 40px);
|
||||
padding: 0 32px;
|
||||
height: 124px;
|
||||
background: #E9F2FF;
|
||||
border-radius: 16px;
|
||||
font-size: 30px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
margin-top: 48px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.fill {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
em {
|
||||
font-size: 48px;
|
||||
font-weight: bold;
|
||||
color: #2C72FE;
|
||||
font-style: normal;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user