3.调查问卷系统-扩展功能

1、表单收集信息的统计

前端:

编写analysis.vue文件展示统计信息

核心方法:

1、跳转到新页面查看提交者的的填写信息

1
2
3
4
5
6
7
viewAnswer(data){
getTemplate(data.formId).then(response=>{
localStorage.setItem("formCode",response.data.content);
localStorage.setItem("formVal",data.formData);
window.open('/tool/formDesigner/view');
})
},

2、获取当前调查统计的信息(可优化当前获取了完整信息,当调查人数较多时不适用),并获取统计分析结果

1
2
3
4
5
6
7
8
9
10
11
getData(formId) {
this.loading = true;
queryByFormIdForUser(this.formId).then(response=>{
this.formDataList=response.data;
this.loading = false;
})
analysis(formId).then(response=>{
this.list=response.data;
console.info("list:",this.list)
})
},

3、对匿名用户进行处理,将其展示名称改为“匿名用户”,此处使用的展示名取自createBy

1
2
3
4
5
6
7
8
9
filteredData() {
// 使用 computed 属性实时过滤数据
return this.formDataList.filter((item) => {
if (item.createBy==null){
item.createBy = "匿名用户";
}
return item.createBy.includes(this.searchText);
});
},

4、搜索功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div>
<!-- 搜索框 -->
<el-input
placeholder="请输入用户名进行搜索"
v-model="searchText"
clearable
style="width: auto"
></el-input>
<el-table v-loading="loading" :data="filteredData" style="width: 500px; height: 300px; overflow-y: auto;" >
<el-table-column width="55" align="center" />
<el-table-column label="用户" align="center" prop="createBy"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template v-slot="scope">
<el-button
size="mini"
type="text"
icon="el-icon-s-claim"
@click="viewAnswer(scope.row)"
v-hasPermi="['']"
>查看</el-button>
</template>
</el-table-column>
</el-table>
</div>

api:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 查询当前表单的全部提交者
export function queryByFormIdForUser(formId) {
return request({
url: '/form/analysis/queryByFormIdForUser/' + formId,
method: 'get',
})
}

// 查询用户调查详细
export function analysis(formId) {
return request({
url: '/form/analysis/' + formId,
method: 'get'
})
}

后端:

核心方法:

1、对提交的调查信息进行统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	/**
* 使用数据库count*统计
*
* @param formId
* @return
*/
@Override
public List<Analysis> formAnalysis(Long formId) {
//统计单选 下拉框 多选
List<String> requestTypeList = CollUtil.newArrayList(
ComponentType.RADIO,
ComponentType.CHECK_BOX,
ComponentType.SELECT
);
//表单题目
List<VtsTemplateFormItem> formItemList = vtsTemplateFormItemService.queryByFormId(formId);
// 表单项id对应的 统计数据(统计结果)
Map<String, Analysis> formMap = new LinkedHashMap<>();
//统计题目
for (VtsTemplateFormItem vtsTemplateFormItem : formItemList) {
//判断是否为需要统计的类型
if (requestTypeList.contains(vtsTemplateFormItem.getFormItemType())) {
Analysis analysis = new Analysis();
//设置标题和类型
analysis.setLabel(vtsTemplateFormItem.getFormItemLabel());
analysis.setType(vtsTemplateFormItem.getFormItemType());
//放入统计结果
formMap.put(vtsTemplateFormItem.getFormItemId(), analysis);
}
}


for (String formItemId : formMap.keySet()) {
Analysis analysis = formMap.get(formItemId);
List<Map<String, Object>> valueAndCount = vtsTemplateFieldDataService.statistcsByFieldId(formItemId, formId);
System.out.println("=======" + valueAndCount);
List<String> labels = vtsTemplateFormItemService.getLabel(formId, formItemId);
List<Integer> value = new ArrayList<>();
if(CollectionUtil.isEmpty(valueAndCount)){
//目前没有数据填写
//设置为0并且跳过
analysis.setFieldName(labels);
analysis.setData(Collections.nCopies(labels.size(), 0));
continue;
}

int valueAndCountIndex = 0;
for (int i = 1; i <= labels.size(); i++) {
Map<String, Object> stringObjectMap = valueAndCount.get(valueAndCountIndex);
Integer fieldValue = Integer.parseInt(stringObjectMap.get("fieldValue").toString());
if (fieldValue == i) {
//对于的数据存在
//添加统计的数据
//统计下一个数据
value.add(Integer.parseInt(stringObjectMap.get("value").toString()));
valueAndCountIndex++;
}else {
//对于的数据不存在
//说明没有人选,设置数据为0
value.add(0);
}
}
// for (Map<String, Object> labelAndValue : valueAndCount) {
//
// map.put(labelAndValue.get("fieldLabel").toString(), Integer.parseInt(labelAndValue.get("value").toString()));
// data.add(Integer.parseInt(labelAndValue.get("value").toString()));
// }
analysis.setFieldName(labels);
analysis.setData(value);
Map<String, Integer> map = new HashedMap();
for (int i = 0; i < labels.size(); i++) {
map.put(labels.get(i),value.get(i));
}
analysis.setMap(map);
// analysis.setMap(map);
// analysis.setFieldName(map.keySet());
// analysis.setData(map.values());
}
List<Analysis> result = new ArrayList(formMap.values());
return result;
}

2、匿名问卷

前端:

具体页面参考anonymousForms.vue、publishView.vue

核心方法:

1
2
3
4
5
6
7
8
9
10
11
mounted(){
this.$nextTick(()=> {
//获取要使用的模板id,此处是从路由的参数中取出formId
this.loading=true;
this.formId = this.$route.params.formId;
getTemplate(this.formId).then(response=>{
this.form = response.data;
this.loading=false;
})
})
},
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div class="publish-view">
<div>
//使用vue-qr生成二维码
<vue-qr v-if="writeLink" :size="194" :text="writeLink" />
</div>
<div>
<p class="link-text">网址:{{ writeLink }}</p>
</div>
</div>
</template>

mounted() {
//通过动态地址获取到模版id
this.formId = this.$route.params.formId;
let url = window.location.protocol + '//' + window.location.host
this.writeLink = `${url}/template/template/anonymousForms/${this.formId}`;
},

3、表单修改功能

前端:在模板保存的基础上进行,不做修改

后端:

对于表单项因修改而需要更新的问题,这里采取发布后将原有的表单项全部删除再添加新的表单项(这一步并不对已提交的问卷回答做处理,只针对模板的表单项)

以下代码分别为添加(修改)表单、发布表单

1
2
3
4
5
6
7
8
9
10
11
12
13
@SaCheckPermission("template:template:add")
@Log(title = "表单代码", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody VtsTemplateCodeBo bo) {
//判断模板否已存在,存在则更新并设置为状态“0”,代表未发布
if (bo.getFormId() != null){
bo.setStatus("0");
return toAjax(iVtsTemplateCodeService.updateByBo(bo));
}else{
return toAjax(iVtsTemplateCodeService.insertByBo(bo));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public R<Void> publish(Long formId) {
//获取当前登录用户信息
SysUser user = userMapper.selectUserById(getUserId());
Long deptId = user.getDeptId();

//获取表单信息
VtsTemplateCodeVo vtsTemplateCodeVo = vtsTemplateCodeService.queryById(formId);
//修改表单状态为已发布
vtsTemplateCodeVo.setStatus("1");
vtsTemplateCodeService.updateByBo(BeanUtil.toBean(vtsTemplateCodeVo, VtsTemplateCodeBo.class));
if(deptId !=null){
//有部门
//根据部门id和表单id查询看看是否之前已经存在
VtsTemplateCodeDept vtsTemplateCodeDept = selectOneByDeptIdAndFormId(deptId, formId);
if(ObjectUtil.isEmpty(vtsTemplateCodeDept)){
//发布状态:新发布
System.out.println("新发布");
//储存部门关系
baseMapper.insert(new VtsTemplateCodeDept(deptId, formId));
// //储存表单项
// formItemService.createFormItems(formId, vtsTemplateCodeVo.getContent());
}else {
//发布状态:修改表单后再发布
System.out.println("修改表单后再发布");
//删除之前的表单项
formItemService.deleteByFormId(formId);
// //在添加当前的表单项
// formItemService.createFormItems(formId, vtsTemplateCodeVo.getContent());
}
//储存表单项
formItemService.createFormItems(formId, vtsTemplateCodeVo.getContent());
return R.ok("发表成功");
}else {
//没有部门
return R.fail("该用户没有部门,只能匿名调查");
}
}

4、上传附件的相关配置

1、修改previewRender.js问卷(ruoyi-ui/src/components/formDesigner/custom/previewRender.js)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	/**
* 此处增加自定义的token,如果不能满足要求,可以重写此处代码
*/
dataObject.attrs['headers'] = {"Authorization":"Bearer " + getToken()};

dataObject.attrs['on-success'] = file=>{
//修改的内容在此处,需要将以下配置改为适配RuoYi的内容
//注释中的为旧格式
//var filename=file.message.substring(file.message.lastIndexOf('/')+1) //获取文件名称
//let fileObj = {name: filename, url: file.message}
var filename=file.data.fileName //获取文件名称
let fileObj = {name: filename, url: file.data.url}
let oldValue = [];
if(dataObject.props.value) {
oldValue = JSON.parse(dataObject.props.value);
}else {
oldValue = [];
}
if (oldValue) {
oldValue.push(fileObj)
} else {
oldValue = [fileObj]
}
self.$emit('input',JSON.stringify(oldValue));
}

2、修改viewRender.js问卷(ruoyi-ui/src/components/formDesigner/custom/viewRender.js)

1
2
3
4
/**
* 此处增加自定义的token,如果不能满足要求,可以重写此处代码
*/
dataObject.attrs['headers'] = {"Authorization":"Bearer " + getToken()};

3、设置默认的上传地址,修改upload.js

(ruoyi-ui/src/components/formDesigner/custom/items/upload.js)

1
2
//上传地址,可自行修改,此处使用的是RuoYi的配置
action:'http://localhost/dev-api/system/oss/upload',