Vue轻松实现随机分班

该例子可以根据填写的班级总人数、男女比例进行随机分班,支持Excel的学生信息表格导入和分班结果Excel的导出和展示。

其中导入的Excel只需要这样填写即可:

效果如下图所示:

 因为我是用Vue脚手架写的,我就直接放核心代码。你们放在脚手架里直接就可以运行出结果啦~需要引用一下elementui、xlsx、file-saver即可。

template部分:

<template>
    <div class="mainBox">
        <div class="btnDIv">
            <el-button type="primary" @click="divisionFun">分班</el-button>
            <el-button type="primary" @click="exportFun">导出</el-button>
        </div>
        <div class="tableDiv">
            <div class="elTable">
                <el-table
                    :data="tableData"
                    border
                    stripe
                    :height="heightTable"
                    id="exportTab">
                    <el-table-column
                        type="index"
                        width="50"
                        label="序号"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="姓名"
                        label="姓名"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="报名号"
                        label="报名号"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="性别"
                        label="性别"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="住址"
                        label="住址"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="年龄"
                        label="年龄"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="是否适龄"
                        label="是否适龄"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="是否满足入学条件"
                        label="是否满足入学条件"
                        align="center">
                    </el-table-column>
                    <el-table-column
                        prop="班级"
                        label="班级"
                        align="center">
                        <template slot-scope="scope">
                            <span style="color: red;font-weight: bold;">{{scope.row['班级']}}</span>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
        </div>

        <!--弹窗-->
        <el-dialog
            title="提示"
            :visible.sync="dialogVisible"
            width="30%"
            :before-close="handleClose">
            <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="120px">
                <el-form-item label="班级总人数:" prop="totalNum">
                    <el-input-number 
                        v-model="ruleForm.totalNum" 
                        :min="1" 
                        :max="1000" 
                        style="width:calc(100% - 40px); 
                        margin-right: 10px;">
                    </el-input-number>
                    <span>人</span>
                </el-form-item>
                <el-form-item label="男生比例:" prop="male">
                    <el-input-number 
                        v-model="ruleForm.male" 
                        :min="0" 
                        :max="100" 
                        style="width:calc(100% - 40px); 
                        margin-right: 10px;"
                        @input="maleFun">
                    </el-input-number>
                    <span>%</span>
                </el-form-item>
                <el-form-item label="女生比例:" prop="famale">
                    <el-input-number 
                        v-model="ruleForm.famale" 
                        :min="0" 
                        :max="100" 
                        style="width:calc(100% - 40px); margin-right: 10px;"
                        @input="famaleFun">
                    </el-input-number>
                    <span>%</span>
                </el-form-item>
                <el-form-item label="上传Excel:" prop="fileList">
                    <el-upload
                        action="###"
                        multiple
                        accept=".xls, .xlsx"
                        :file-list="ruleForm.fileList"
                        :show-file-list="true"
                        :before-upload="beforeAvatarUpload"
                        :auto-upload="false"
                        :on-change="onChange">
                        <el-button type="primary">上传</el-button>
                        <div slot="tip" class="el-upload__tip">只能上传.xls, .xlsx文件</div>
                    </el-upload>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button type="primary" @click="submitFun('ruleForm')">分 班</el-button>
                <el-button @click="dialogVisible = false">取 消</el-button>
            </span>
        </el-dialog>
    </div>
</template>

js部分:

<script>
// 在vue中导入XLSX
import * as XLSX from 'xlsx'
import FileSaver from 'file-saver'
export default {
    data(){
        return{
            tableData: [],
            heightTable: '100%',
            //弹窗
            dialogVisible: false,
            rules: {
                totalNum: [
                    { required: true, message: '请输入班级总人数', trigger: 'blur' }
                ],
                fileList: [
                    { required: true, message: '请上传Excel', trigger: 'change' }
                ],
                male: [
                    { required: true, message: '请输入男生比例', trigger: 'blur' }
                ],
                famale: [
                    { required: true, message: '请输入女生比例', trigger: 'blur' }
                ],
            },
            wb: {},
            ruleForm: {
                totalNum: 30,
                male: 50,
                famale: 50,
                fileList: []
            }
        }
    },
    methods: {
        divisionFun(){
            //分班
            this.dialogVisible = true;
        },
        exportFun(){
            //导出
            /* generate workbook object from table */
            var xlsxParam = { raw: true } // 导出的内容只做解析,不进行格式转换
            var table = document.querySelector('#exportTab').cloneNode(true)
            if(table.querySelector('.el-table__fixed')) table.removeChild(table.querySelector('.el-table__fixed')) //这里是双下划线
            var wb = XLSX.utils.table_to_book(table, xlsxParam)
            /* get binary string as output */
            var wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' })
            try {
                FileSaver.saveAs(new Blob([wbout], { type: 'application/octet-stream' }), '分班表.xlsx')
            } catch (e) {
                if (typeof console !== 'undefined') {
                    console.log(e, wbout)
                }
            }
            return wbout;
        },
        //弹窗
        handleClose(){
            this.dialogVisible = false;
            this.$set(this.ruleForm, 'fileList', []);
        },
        maleFun(val){
            this.ruleForm.famale = 100 - val;
        },
        famaleFun(val){
            this.ruleForm.male = 100 - val;
        },
        beforeAvatarUpload(file) {
            let extension = file.name.substring(file.name.lastIndexOf(".") + 1);
            let bool = true;
            if (extension !== "xlsx" && extension !== "xls") {
                bool = false;
                this.$message.error('上传文件只能是.xls, .xlsx格式!');
            }
            return bool;
        },
        onChange(file, fileList){
            if (fileList.length > 0) {
                this.ruleForm.fileList = [fileList[fileList.length - 1]];
            }
        },
        dispFile(file) {
            return new Promise(function(resolve, reject) {
                const reader = new FileReader()
                reader.onload = function(e) {
                    const data = e.target.result
                    this.wb = XLSX.read(data, {
                        type: 'binary'
                    })
                    const result = []
                    this.wb.SheetNames.forEach((sheetName) => {
                        result.push({
                            sheetName: sheetName,
                            sheet: XLSX.utils.sheet_to_json(this.wb.Sheets[sheetName])
                        })
                    })
                    resolve(result)
                }
                reader.readAsBinaryString(file.raw)
            })
        },
        submitFun(formName){
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    let file = this.ruleForm.fileList[0];
                    this.dispFile(file).then(async(tabJson) => {
                        let data = [];
                        if (tabJson && tabJson.length > 0) {
                            data = tabJson[0].sheet;
                        }
                        data = await this.dispData(data);
                        this.tableData = data;
                        this.handleClose();
                    })
                    this.dialogVisible = false
                } else {
                    return false;
                }
            });
        },
        async dispData(data){
            //分班规矩:依据一定的男女比例、班级总人数进行分班
            let newData = [];
            let maleData = [];//男生
            let famaleData = [];//女生
            let totalNum = this.ruleForm.totalNum;//班级总人数
            let male = this.ruleForm.male;//男生比例
            let famale = this.ruleForm.famale;//女生比例

            //第一步:区分男女
            for(let i = 0; i < data.length; i++){
                if(data[i]['性别'] === "男"){
                    maleData.push(data[i]);
                }else if(data[i]['性别'] === "女"){
                    famaleData.push(data[i]);
                }
            }
            //第二步:班级总数
            let classTotal = Math.ceil(data.length / totalNum);
            //第三步:区分班级-男生女生人数不足时相互补充
            for(let j = 0; j < classTotal; j++){
                let maleNum = Math.ceil(totalNum * (male / 100));//男生人数
                let famaleNum =  Math.ceil(totalNum * (famale / 100));//女生人数
                let maleDifference = 0;//差值
                if(maleData.length < maleNum){
                    maleDifference = maleNum - maleData.length;
                    if(famaleData.length - famaleNum > 0){
                        let differenceDataOne = famaleData.splice(0, maleDifference);
                        maleData = [...maleData, ...differenceDataOne];
                    }
                }
                newData = this.dispSexFun(maleNum, maleData, j+1, newData);//随机男生

                let famaleDifference = 0;//差值
                if(famaleData.length < famaleNum){
                    famaleDifference = famaleNum - famaleData.length;
                    if(maleData.length > 0){
                        let differenceDataTwo = maleData.splice(0, famaleDifference);
                        famaleData = [...famaleData, ...differenceDataTwo];
                    }
                }
                newData = this.dispSexFun(famaleNum, famaleData, j+1, newData);//随机女生
            }
            return newData;
        },
        dispSexFun(totalNum, sexData, className, newData){
            //totalNum:总人数 sexData:男/女数组 className: 班级序号 newData:最后拆分得到的新数组
            for(let m = 0; m < totalNum; m++){
                let index = this.radomFun(0, sexData.length);
                let newObj = sexData[index];
                if(newObj){
                    newObj['班级'] = className + "班";
                    newData.push(newObj);
                    sexData.splice(index, 1);
                }
            }
            return newData;
        },
        radomFun(min, max) {
            //产生不重复的随机数
            let key = Math.floor((Math.random() * (max-min)) + min);
            return key;
        }
    }
}
</script>

css部分:

<style lang="scss">
.mainBox{
    width: calc(100% - 40px);
    height: calc(100% - 40px);
    background: #eee;
    padding: 20px;
    .btnDIv{
        display: flex;
    }
    .tableDiv{
        height: calc(100% - 65px);
        margin-top: 10px;
        .elTable{
            padding: 20px;
            background: #fff;
            border-radius: 10px;
            height: calc(100% - 40px);
        }
    }
}
</style>

代码下载地址:分班系统根据填写的班级总人数、男女比例进行随机分班-Javascript文档类资源-CSDN下载

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值