初始化

This commit is contained in:
aixianling
2021-12-14 18:36:19 +08:00
parent 9afa4101b6
commit a8dff862d2
327 changed files with 88702 additions and 0 deletions

View File

@@ -0,0 +1,731 @@
<template>
<ai-detail class="statistics">
<template slot="title">
<ai-title title="数据统计" isShowBack isShowBottomBorder @onBackClick="cancel(false)"></ai-title>
</template>
<template slot="content">
<ai-card title="表单信息">
<template #content>
<ai-wrapper label-width="90px">
<ai-info-item label="表单名称" :value="info.title" isLine></ai-info-item>
<ai-info-item label="发布状态"><span :style="{color: dict.getColor('questionnaireStatus', info.status)}">已发布</span></ai-info-item>
<!-- <ai-info-item label="创建人" openType="userName" :value="info.createUserName"></ai-info-item> -->
<ai-info-item label="创建时间" :value="info.createTime"></ai-info-item>
<ai-info-item label="截止时间" :value="info.periodValidityEndTime ? info.periodValidityEndTime : '永久有效'"></ai-info-item>
<ai-info-item label="提交次数限制" :value="info.commitType === '1' ? '限提交一次' : '不限次数' "></ai-info-item>
</ai-wrapper>
</template>
</ai-card>
<div class="statistics-wrapper">
<div class="statistics-wrapper__title">
<span :class="[currIndex === 0 ? 'active' : '']" @click="currIndex = 0">表单统计</span>
<span :class="[currIndex === 1 ? 'active' : '']" @click="currIndex = 1">居民统计</span>
</div>
<div class="statistics-wrapper__body">
<div v-show="currIndex === 0">
<div class="statistics-wrapper__body--info">
<span></span>
<i>{{ subjectList.length }}</i>
<span>其中</span>
<span v-for="(item, index) in fieldTypeCount" :key="index">
{{ mapType(item.field_type) }}<i>{{ item.c }}</i>{{ fieldTypeCount.length - 1 === index ? '' : '' }}
</span>
</div>
<div class="statistics-wrapper__body--list">
<div class="statistics-wrapper__body--item" v-for="(item, index) in subjectList" :key="index">
<div class="statistics-wrapper__body--top" :style="{borderBottom: ['input', 'textarea', 'upload'].indexOf(item.type) > -1 ? 'none' : '1px solid #DDDDDD'}">
<div class="left">
<h2>{{ item.fieldName }}{{ item.fixedLabel }}</h2>
</div>
<div class="right">
<span></span>
<i>{{ fieldDataCount[`field_${index}`] }}</i>
<span>条数据</span>
</div>
</div>
<div class="statistics-wrapper__body--bottom" v-if="['radio', 'checkbox', 'select'].indexOf(item.type) > -1">
<div class="statistics-wrapper__body--select" v-for="(item, i) in item.options" :key="i">
<div class="left">
<h2>{{ item.label }}</h2>
<span>{{ item.c || 0 }}</span>
</div>
<div class="right">
<div class="progress">
<div :style="{width: `${(((item.c || 0) / fieldDataCount[`field_${index}`]) * 100).toFixed(2)}%`}"></div>
</div>
<i>{{ (((item.c || 0) / fieldDataCount[`field_${index}`]) * 100).toFixed(2) }}%</i>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-show="currIndex === 1" style="padding: 16px;">
<!-- <ai-search-bar>
<template #right>
<el-input
v-model="search.name"
size="small"
placeholder="请输入居民名称"
clearable
@keyup.enter.native="search.current = 1, getList()"
@clear="search.current = 1, search.name = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar> -->
<ai-table
class="detail-table__table"
:border="true"
style="margin-top: 4px;"
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
:stripe="false"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="userinfo" label="居民" width="260px" align="left">
<template slot-scope="{ row }">
<div class="userinfo">
<img :src="row.avatarUrl || 'https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png'">
<!-- <h3>{{ row.nickName }}</h3> -->
<div class="userinfo-right__top">
<h3><ai-open-data type="userName" :openid="row.nickName"></ai-open-data></h3>
</div>
</div>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="showForm(row.id)">查看表单</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</div>
</div>
<ai-dialog
customFooter
:visible.sync="isShowForm"
@onConfirm="isShowForm = false"
width="800px"
title="表单">
<div class="middle-content form">
<div class="middle-content__wrapper">
<div>
<div class="left-item__item left-item__item--banner" key="banner" v-if="info.headPicture">
<img :src="info.headPicture">
</div>
<div class="left-item__item left-item__item--formname" key="title">
<h2>{{ info.title }}</h2>
</div>
<div class="left-item__item left-item__item--text" key="text">
<p>{{ info.tableExplain }}</p>
</div>
</div>
<div
class="left-item__item components-item"
v-for="(item, i) in targetList"
:key="i">
<div class="left-item__item--title">
<i :style="{opacity: item.required ? 1 : 0}">*</i>
<span>{{ i + 1 }}.</span>
<h2>{{ item.label }}</h2>
</div>
<div class="left-item__item--wrapper">
<template v-if="(item.type === 'radio')" >
<div class="radio-item" v-for="(field, index) in item.options" :key="index" >
<input type="radio" disabled :value="field.label" v-model="formInfo[`field_${i}`]" />
<img :src="field.img[0].url" v-if="field.img.length">
<label>{{ field.label }}</label>
</div>
</template>
<template v-if="item.type === 'upload'">
<img style="width: 100%; height: 100%;" :src="formInfo[`field_${i}`]" v-if="formInfo[`field_${i}`]">
<div class="left-item__item--upload" v-else>
<span>图片</span>
</div>
</template>
<template v-if="item.type === 'select'" >
<el-input resize="none" class="preview" type="textarea" style="color: #333" :placeholder="item.placeholder" v-model="formInfo[`field_${i}`]" disabled></el-input>
<!-- <span>{{ formInfo[`field_${i}`] }}</span> -->
<!-- <textarea :placeholder="item.placeholder" v-model="formInfo[`field_${i}`]" disabled></textarea> -->
<!-- <el-select placeholder="请选择" disabled v-model="formInfo[`field_${i}`]" style="width: 100%;">
<el-option
v-for="(item, index) in item.options"
:key="index"
:label="item.label"
:value="item.label">
</el-option>
</el-select> -->
</template>
<template v-if="(item.type === 'checkbox')" >
<div class="radio-item" v-for="(field, index) in item.options" :key="index" >
<input type="checkbox" disabled :value="field.label" v-model="formInfo[`field_${i}`]" />
<img :src="field.img[0].url" v-if="field.img.length">
<label>{{ field.label }}</label>
</div>
</template>
<template v-if="(item.type === 'input')" >
<div class="text-item">
<input :placeholder="item.placeholder" v-model="formInfo[`field_${i}`]" disabled>
</div>
</template>
<template v-if="(item.type === 'textarea')" >
<div class="textarea-item" resize="none">
<textarea :placeholder="item.placeholder" v-model="formInfo[`field_${i}`]" disabled></textarea>
</div>
</template>
</div>
</div>
</div>
</div>
<template #footer>
<el-button @click="isShowForm = false">关闭</el-button>
</template>
</ai-dialog>
</div>
</template>
</ai-detail>
</template>
<script>
export default {
name: 'Statistics',
props: {
instance: Function,
dict: Object,
params: Object
},
data () {
return {
currIndex: 0,
search: {
name: '',
size: 10,
current: 1
},
info: {},
subjectList: [],
tableData: [],
total: 0,
form: {},
fieldTypeCount: [],
fieldValueDistribution: [],
fieldDataCount: {},
isShowForm: false,
targetList: [],
formInfo: {},
colConfigs: [
{slot: 'userinfo'},
{prop: 'commitTime', label: '提交时间', align: 'center', width: '160px' },
{prop: 'userType', label: '微信类型', align: 'center', width: '100px', formart: v => this.dict.getLabel('wxUserType', v) },
{prop: 'totalScore', label: '分值', align: 'center'}
]
}
},
mounted () {
this.getInfo()
this.getFormInfo()
this.dict.load(['wxUserType']).then(() => {
this.getList()
})
},
methods: {
getList () {
this.instance.post(`/app/appquestionnairetemplate/statisticsResident?id=${this.params.id}`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
this.$initWxOpenData()
}
})
},
showForm (id) {
this.instance.post(`/app/appquestionnairetemplate/queryDataInfoById?id=${this.params.id}&dataId=${id}`).then(res => {
if (res.code == 0) {
this.formInfo = res.data
this.targetList.forEach((item, index) => {
if (item.type === 'checkbox' && this.formInfo[`field_${index}`]) {
this.formInfo[`field_${index}`] = this.formInfo[`field_${index}`].split(',')
}
})
this.isShowForm = true
}
})
},
mapType (type) {
return {
upload: '上传图片',
input: '单行填空',
textarea: '多行填空',
radio: '单选',
checkbox: '多选',
select: '单下拉框'
}[type]
},
getFormInfo () {
this.instance.post(`/app/appquestionnairetemplate/statisticsTable?id=${this.params.id}`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code == 0) {
this.fieldDataCount = res.data.fieldDataCount
this.fieldTypeCount = res.data.fieldTypeCount
this.fieldValueDistribution = res.data.fieldValueDistribution
this.subjectList = res.data.appQuestionnaireTemplate.fields.map((item, index) => {
const fieldInfo = JSON.parse(item.fieldInfo)
let options = fieldInfo.options
if (['radio', 'checkbox', 'select'].indexOf(item.fieldType) > -1) {
options = fieldInfo.options.map(v => {
res.data.fieldValueDistribution[`field_${index}`].forEach(info => {
if (info.fieldValue === v.label) {
v.c = info.c
}
})
return v
})
}
return {
...item,
...fieldInfo,
options
}
})
}
})
},
getInfo () {
this.instance.post(`/app/appquestionnairetemplate/queryDetailById?id=${this.params.id}`).then(res => {
if (res.code == 0) {
this.info = res.data
this.targetList = res.data.fields.map(item => {
return JSON.parse(item.fieldInfo)
})
this.$initWxOpenData()
}
})
},
cancel (isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
}
}
}
</script>
<style scoped lang="scss">
.statistics {
* {
box-sizing: border-box;
font-weight: normal;
font-style: normal;
}
.preview {
::v-deep .el-textarea.is-disabled, ::v-deep .el-textarea__inner {
color: #666!important;
}
}
.form {
.left-item__item--banner {
img {
width: 100%;
height: 235px;
}
.config-item__banner {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 100%;
height: 235px;
line-height: 1;
border: 1px dashed #bbb;
span {
margin-top: 4px;
color: #555555;
font-size: 14px;
}
i {
font-size: 30px;
color: #8899bb;
}
}
}
.left-item__item--formname {
margin: 16px 0 32px;
padding: 0 12px;
color: #333333;
font-size: 15px;
font-weight: normal;
text-align: center;
word-break: break-all;
}
.left-item__item--text {
line-height: 20px;
// margin-bottom: 48px;
padding: 0 12px 20px;
text-align: justify;
color: #666;
font-size: 14px;
word-break: break-all;
}
.components-item {
position: relative;
padding: 16px 16px;
.left-item__item--wrapper {
& > img {
max-width: 300px;
}
}
.left-item__item--upload {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
width: 120px;
height: 120px;
border-radius: 6px;
border: 1px dashed #bbb;
i {
font-size: 24px;
color: #8899bb;
}
span {
margin-top: 4px;
font-size: 12px;
color: #555;
}
}
.text-item {
input {
display: block;
width: 100%;
height: 40px;
border: none;
border-bottom: 1px solid #ddd;
&:focus {
outline: none;
}
&:disabled {
background: #fff;
}
}
}
.textarea-item {
textarea {
width: 100%;
height: 120px;
resize: none;
border: 1px solid #ddd;
padding: 10px;
&:focus {
outline: none;
}
&:disabled {
background: #fff;
}
}
}
.radio-item {
display: flex;
margin-bottom: 10px;
input {
position: relative;
top: 2px;
}
&:last-child {
margin-bottom: 0;
}
label {
margin-left: 10px;
}
img {
width: 60px;
margin-left: 10px;
}
}
}
.left-item__item--title {
display: flex;
margin-bottom: 10px;
i {
position: relative;
top: 3px;
margin-right: 5px;
color: #E22120;
}
span {
position: relative;
top: 3px;
}
h2 {
color: #333333;
font-size: 15px;
}
}
}
.table-tags {
.el-tag {
margin-right: 8px;
margin-bottom: 8px;
border: 1px solid #D0D4DC;
background: #F3F4F7;
border-radius: 4px;
font-size: 13px;
color: #222222;
&:last-child {
margin-right: 0;
}
}
}
h2, h3 {
margin: 0;
}
.userinfo {
display: flex;
align-items: center;
img {
width: 40px;
height: 40px;
margin-right: 8px;
border-radius: 2px;
}
h3 {
font-size: 14px;
font-weight: normal;
color: #222222;
}
.userinfo-right__top {
display: flex;
align-items: center;
margin-bottom: 10px;
cursor: pointer;
white-space: nowrap;
}
span {
padding-left: 8px;
color: #2EA222;
font-size: 14px;
white-space: nowrap;
}
}
.statistics-wrapper {
background: #FFFFFF;
box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15);
border-radius: 2px;
.statistics-wrapper__title {
display: flex;
align-items: center;
height: 56px;
padding: 0 16px;
border-bottom: 1px solid #EEEEEE;
span {
height: 56px;
line-height: 56px;
color: #888888;
font-size: 16px;
font-weight: 600;
cursor: pointer;
user-select: none;
border-bottom: 3px solid transparent;
&:first-child {
margin-right: 32px;
}
&.active {
color: #222222;
border-color: #2266FF;
}
}
}
.statistics-wrapper__body--list {
padding: 0 40px 20px;
.statistics-wrapper__body--item {
margin-bottom: 20px;
background: #FFFFFF;
border-radius: 4px;
border: 1px solid #DDDDDD;
}
.statistics-wrapper__body--bottom {
padding: 20px;
.statistics-wrapper__body--select {
display: flex;
align-items: center;
justify-content: space-between;
height: 48px;
& > div {
display: flex;
align-items: center;
}
.left {
h2 {
max-width: 384px;
margin-right: 10px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
font-size: 12px;
color: #222222;
}
span {
color: #888888;
font-size: 12px;
}
}
.right {
i {
width: 50px;
text-align: right;
color: #2266FF;
font-size: 12px;
}
.progress {
position: relative;
width: 500px;
height: 8px;
margin-right: 10px;
background: #EEEEEE;
border-radius: 5px;
div {
position: absolute;
top: 0;
left: 0;
height: 8px;
background: #2266FF;
border-radius: 5px;
}
}
}
}
}
.statistics-wrapper__body--top {
display: flex;
justify-content: space-between;
align-items: center;
height: 70px;
padding: 0 20px;
background: #FFFFFF;
border-radius: 4px 4px 0px 0px;
border-bottom: 1px solid #DDDDDD;
& > div {
display: flex;
align-items: center;
font-size: 14px;
}
.left {
flex: 1;
h2 {
color: #222222;
font-size: 14px;
}
}
.right {
span {
color: #888888;
}
i {
color: #2266FF;
padding: 0 4px;
}
}
}
}
.statistics-wrapper__body--info {
display: flex;
align-items: center;
height: 70px;
line-height: 1;
padding: 0 40px;
color: #555555;
font-size: 14px;
i {
padding: 0 4px;
font-weight: 600;
font-style: normal;
color: #2266FF;
font-size: 14px;
}
}
}
}
</style>