欢迎来到我的CSDN主页!
我是Java方文山,一个在CSDN分享笔记的博主。
推荐给大家我的专栏《微信小程序开发实战》。
点击这里,就可以查看我的主页啦!
Java方文山的个人主页
如果感觉还不错的话请给我点赞吧!
期待你的加入,一起学习,一起进步!
开会是企业中必不可少的一种沟通方式,可以让团队成员之间交流思想,协调工作进度,解决问题等。但是,过于频繁和冗长的会议可能会浪费时间和资源,影响工作效率。
在公司中,如果每个小事情都要开会,那么很容易造成员工的厌烦和不满。这样的会议可能会让人感到无聊、浪费时间,甚至失去动力。因此,企业应该合理安排会议,选择适当的时间和场合,避免不必要的会议,并确保会议的目的明确、内容简洁、效率高效,因此鄙人开发了一个数字化会议OA系统。
这篇文章主讲投票模块的实现,其中包括发布投票信息,用户选择所属会议的投票标题内容进行投票、投票的数据报表等实现。
【微信小程序】自定义组件布局会议OA其他页面(附源码)http://t.csdnimg.cn/lLeMU页面搭建与自定义组件的编写在这篇文章中提过,这里只做粗略的讲述。
我们可以根据自定义组件完成,首先在相应的json文件中引用自定义组件。
"usingComponents": {
"tabs": "/components/tabs/tabs"
}
随后在js文件中定义我们所需要展示的内容。
tabs: ['发起投票', '投票进行中', '已结束投票', '全部投票']
最后直接在wxml中应用即可。
效果展示:
我们这里与会议管理有些不同,我们会议管理是点击不同的菜单显示不同的数据,但是这个的内容可就不是数据了,而是各不相同的组件,所以针对这个事情我们要做一个内容切换事件。
首先在我们的wxml中定义好每个菜单需要展示的内容并写好hidden样式
发起投票
投票进行中
已结束投票
全部投票
.hidden {
display: none;
}
在js中定义好属性与事件
componentStatus: [true,false, false, false]
tabsItemChange(e) {
let index = e.detail.index;
//全部的组件赋值为false
const lists = [false, false, false, false];
//将所点击的组件赋值为true
lists[index] = true;
this.setData({
componentStatus: lists // 更新 data 中的 componentStatus 属性值
});
}
效果展示:
温馨提示:
因为在写这篇博客之前,我就已经完成了功能,并且模块中的样式没有进行相应的标记,所以这里就放上我投票模块的所有样式,避免大家在进行编写的时候因为样式问题而导致效果出不来的情况。
wxss
/* pages/vote/list/list.wxss */ .hidden { display: none; } .title-view { background-color: beige; font-weight: 700; padding-left: 7px; } .info-title { padding: 5px 5px 10px 5px; border-top: 1px solid rgb(129, 129, 127); } .info-text { height: 100px; padding: 5px 5px 10px 5px; border-top: 1px solid rgb(129, 129, 127); } .image { padding-left: 55px; display: flex; align-items: center; } .time { border-top: 1px solid rgb(129, 129, 127); padding: 5px 0px 5px 0px; display: flex; align-items: center; } .image-container { padding-left: 60px; } .info-sousuo { margin-left: 85px; padding-left: 20px; border-radius: 25px; border: 4px solid rgb(214, 214, 98); width: 250px; } /* pages/meeting/list/list.wxss */ .section{ color: #aaa; display: flex; justify-content: center; } .list-info { margin-top: 10px; color: #aaa; } .list-num { color: #e40909; font-weight: 700; } .join { padding: 0px 0px 0px 10px; color: #aaa; } .state { margin: 0px 6px 0px 6px; border: 1px solid #93b9ff; color: #93b9ff; } .list-tag { padding: 3px 0px 10px 0px; display: flex; align-items: center; } .list-title { display: flex; justify-content: space-between; color: #333; font-weight: 900; } .yyy{ display: flex; align-items: center; } .list-img{ height: 300rpx; width: 90%; border-radius: 50rpx; margin: 5px 5px 5px 20px; } .centered { display: flex; /* 设置为弹性容器 */ justify-content: center; /* 子元素水平方向居中对齐 */ } .video-img { width: 100px; height: 100px; } .list { border-bottom: 1px solid #6b6e74; padding: 10px; } .mobi-text { font-weight: 700; padding: 15px; } .mobi-icon { border-left: 5px solid #e40909; } .mobi-title { background-color: rgba(158, 158, 142, 0.678); margin: 10px 0px 10px 0px; } .swiper-item { height: 300rpx; width: 100%; border-radius: 10rpx; } .userinfo { display: flex; flex-direction: column; align-items: center; color: #aaa; } .userinfo-avatar { overflow: hidden; width: 128rpx; height: 128rpx; margin: 20rpx; border-radius: 50%; } .usermotto { margin-top: 200px; } .filx{ display: flex; align-items: center; } .container { padding: 20px; } .modal-container { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: #fff; width: 80%; max-height: 80%; overflow-y: auto; padding: 20px; } .mask { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); } button { display: block; margin-top: 10px; } .content { margin-top: 10px; border: 1px solid #ccc; padding: 10px; } .right{ display: flex; align-items: center; }
首先最基本的就是要拿到数据,但是这个数据可不是乱拿的,我们先来看一下表数据。
我们要拿到state值为5的数据,只有该数据才是通过了审核并且还未结束的会议,所以能进行投票,明确了目标现在开始敲代码吧。
//创建投票的会议信息
@RequestMapping("/vote")
public Object votelist(Info info) {
List infoList = infoMapper.votelist(info);
Map
在config/api.js配置后端接口
// 以下是业务服务器API地址
// 本机开发API地址
var WxApiRoot = 'http://localhost:8080/wx/';
// 测试环境部署api地址
// var WxApiRoot = 'http://192.168.0.101:8070/demo/wx/';
// 线上平台api地址
//var WxApiRoot = 'https://www.oa-mini.com/demo/wx/';
module.exports = {
IndexUrl: WxApiRoot + 'home/index', //首页数据接口
SwiperImgs: WxApiRoot+'swiperImgs', //轮播图
MettingInfos: WxApiRoot+'meeting/list', //会议信息
VoteInfos:WxApiRoot+'home/vote',//可发起投票会议信息
OptionInfos:WxApiRoot+'home/add',//发布投票信息
SelectOption:WxApiRoot+'home/selectOptions'//查看可进行投票信息
};
引入后端接口配置文件
const api = require("../../config/api.js")
可发起投票会议信息的ajax
loadvoteInfos() {
util.request(api.VoteInfos).then(res => {
// console.log(res.data.infoList)
this.setData({
lists: res.data.infoList
})
})
}
在onLoad函数中调用该方法
{{item.title}}
{{tools.getNumber(item.canyuze,item.liexize,item.item.zhuchiren)}} 人报名
{{item.location}} |{{tools.formatDate(item.starttime)}}
注意:将代码放入所需要展示内容的view中。
效果展示
这里我给大家捋一下我的思路,当我点击会议信息的时候就会弹出一个模态框,模态框的内容有显示该会议的标题、输入投票的标题、新增选项、删除选项、发布投票、取消发布等。我需要将我所点击的会议信息的标题传入模态框中,并且可以获取投票标题和选项内容的文本内容并进行保存,等我点击发布投票的时候就会将保存的内容传值给后端。
数据库展示
INSERT INTO t_oa_meeting_option
id,
meetingId,
optionValue,
optionText,
#{id, jdbcType=INTEGER},
#{meetingId, jdbcType=INTEGER},
#{optionValue, jdbcType=VARCHAR},
#{optionText, jdbcType=VARCHAR},
//发布投票
@RequestMapping("/add")
public Object add(@RequestBody Map obj) {
System.out.println(obj);
//获取选项数组的长度来控制新增的次数
int optionsLength = ((List)obj.get("options")).size();
//循环添加投票数据
for (int i = 0; i < optionsLength; i++) {
//初始化option
Option option = new Option();
List options = (List) obj.get("options");
option.setmeetingId((Integer) obj.get("modalConId"));//会议id
String firstOption = options.get(i);
option.setoptionValue((String)obj.get("title"));//投票标题
option.setoptionText(firstOption);//选项内容
//调取添加的方法
int insert = optionMapper.insertSelective(option);
}
return ResponseUtil.ok();
}
这里需要注意是一个投票选项就是一条数据,所以我们要先拿到前端的选择数组的长度,从而进行遍历添加数据,同一批请求的投票标题与会议id肯定是一致的所以不用变动。
在config/api.js配置后端接口
OptionInfos:WxApiRoot+'home/add',//发布投票信息
//投票标题的监听事件
bindTitle: function (e) {
this.setData({
title: e.detail.value
})
},
// 输入框输入事件,保存输入的内容到相应的选项
bindInput(e) {
console.log(e)
const { index } = e.currentTarget.dataset; // 获取当前选项的索引
const { value } = e.detail;
const { options } = this.data;
options[index] = value;
this.setData({
options: options
});
},
// 添加选项
addOption() {
const { options, optionCount } = this.data;
options.push('');
this.setData({
options: options,
optionCount: optionCount + 1
});
},
// 删除选项
deleteOption() {
const { options, optionCount } = this.data;
options.pop();
this.setData({
options: options,
optionCount: optionCount - 1
});
},
// 确认按钮点击事件
confirm() {
let modalConId = this.data.modalConId;//会议id
let title = this.data.title;//投票标题
let options = this.data.options;//选项内容
let data = {
modalConId: modalConId,
options: options,
title: title
};
// console.log(data)
util.request(api.OptionInfos, data, 'POST').then(res => {
// console.log(res)
this.setData({
modalVisible: false,
optionCount: 1
});
})
},
// 取消按钮点击事件
cancel() {
this.setData({
modalVisible: false,
optionCount: 1
});
}
事件中提到的变量在data中定义即可,这里就不做展示了
{{modalContent}}
添加选项
删除选项
投票标题:
选项{{index+1}}:
发布投票
取消
我这里还引用了小程序框架LinUI可以丰富我的页面,不懂的可以看官网哦!!
结合我们刚刚的页面数据再看看效果
//带模糊查询的会议信息
@RequestMapping("/selectOptions")
public Object selectOptions(String title) {
System.out.println(title);
List
在config/api.js配置后端接口
SelectOption:WxApiRoot+'home/selectOptions'//查看可进行投票信息
在投票页面我使用了LinUI的滑动菜单和卡片布局。
利用好框架我们写起来就会简单许多只需要将数据进行绑定即可,但为了让用户有更好的体验,所以我加了一个搜索框,用户可进行模糊查询自己所需要投票的会议。
//加载投票会议信息的ajax
loadoptinos() {
util.request(api.SelectOption).then(res => {
// console.log(res.data.selecttoupiao)
this.setData({
Options: res.data.selecttoupiao
})
})
},
// 监听搜索事件
onSearch: function(event) {
var title = event.detail.value;
let data = {
title: title
};
util.request(api.SelectOption,data).then(res => {
this.setData({
Options: res.data.selecttoupiao
})
})
}
投票标题:《{{item.optionValue}}》
投票
报表
结束会议
效果展示
投票数据表的字段非常简单,只需要拿到所选投票的id与投票人员的id即可
首先我们需要一个模态框作为载体来加载投票标题的投票选项
//根据投票标题查询选项
@RequestMapping("/voting")
public Object voting(String optionValue) {
List
在config/api.js配置后端接口
voting:WxApiRoot+'home/voting',//根据投票标题查询选项
//打开投票模态框并向后端拿值
openModal: function (e) {
let optionValue = e.currentTarget.dataset.value;
// console.log('传递的值:', optionValue);
let data = {
optionValue: optionValue
};
util.request(api.voting, data).then(res => {
this.setData({
votes: res.data.voting,
showModal: true
})
})
},
//关闭投票模态框
closeModel(){
this.setData({
selectedOption:'',
showModal: false
})
},
//保存用户所选择的选项
radioChange: function (e) {
const value = e.detail.value;
this.setData({
selectedOption: value
});
}
这里有个小地方需要注意我在投票的view上绑定了data-value="{{item.optionValue}}也就是投票标题,当打开模态框的时候,就会带着这个投票标题找到相应的选项出来。
效果演示
到这一步就可以说是非常简单了,我们只需要保存用户所选的是什么选项,并将值传到后端进行保存即可。
insert into t_oa_meeting_vote
id,
optionId,
personId,
#{id,jdbcType=VARCHAR},
#{optionid,jdbcType=VARCHAR},
#{personid,jdbcType=BIGINT},
//投票
@RequestMapping("/option")
public Object add(int optionId) {
System.out.println(optionId);
Vote vote=new Vote();
vote.setOptionid(optionId);
vote.setPersonid(7);
int i = voteMapper.insertSelective(vote);
return ResponseUtil.ok();
}
这里没有进行用户登录的操作所以人的id就先定死 。
在config/api.js配置后端接口
option:WxApiRoot+'home/option',//用户投票
//用户投票
confirmVote: function () {
const optionId = this.data.selectedOption;
let data = {
optionId: optionId
};
util.request(api.option, data).then(res => {
console.log(res)
this.setData({
showModal: false
})
})
}
效果展示
到这里我的分享就结束了,欢迎到评论区探讨交流!!
如果觉得有用的话还请点个赞吧