| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- <template>
- <div class="page_item end_item">
- <div class="page_search">
- <div class="search_content">
- <div class="content_left">
- <el-checkbox v-model="store.state.evaluationManageStepData.isGenerateAccountByGender"
- @change="(val)=>GenerateAccountByGenderOrNot(val)" >
- 按男女生成
- </el-checkbox>
- </div>
- <div class="content_right">
- <el-button class="delete_button_border_no_bg" @click="ClearReviewAccount">全部清空</el-button>
- <el-button class="button_border" @click="OpenBatchEditForm">批量编辑</el-button>
- <el-button class="button_refresh" @click="HandleExportExcel">批量导出</el-button>
- <el-button class="button_refresh" @click="">批量导入</el-button>
- <el-button class="button_background" @click="GoToGenerateCodePage">生成评价码</el-button>
- </div>
- </div>
- </div>
- <div class="page_jg_20"></div>
- <Table :tableColumns="tableColumns"
- :tableData="tableData"
- :hidePagination="true">
- <template v-for="item in Object.values(originReviewAccount)"
- v-slot:[`class_${item.evaluationGradeId}`]="{row}" :key="item">
- {{ row[`class_${item.evaluationGradeId}`]?.className }}
- </template>
- <template v-for="item in Object.values(originReviewAccount)"
- v-slot:[`num_${item.evaluationGradeId}`]="{row}" :key="item">
- <!-- 没有班级的行不渲染 -->
- <el-input v-if="row[`class_${item.evaluationGradeId}`]?.classId" type="number" v-model="row[`num_${item.evaluationGradeId}`]" placeholder="请输入"/>
- </template>
- <template v-for="item in Object.values(originReviewAccount)"
- v-slot:[`male_${item.evaluationGradeId}`]="{row}" :key="item">
- <el-input v-if="row[`class_${item.evaluationGradeId}`]?.classId" type="number" v-model="row[`male_${item.evaluationGradeId}`]" placeholder="请输入"/>
- </template>
- <template v-for="item in Object.values(originReviewAccount)"
- v-slot:[`female_${item.evaluationGradeId}`]="{row}" :key="item">
- <el-input v-if="row[`class_${item.evaluationGradeId}`]?.classId" type="number" v-model="row[`female_${item.evaluationGradeId}`]" placeholder="请输入"/>
- </template>
- </Table>
- <FormDialog
- width="800px"
- :visible="batchEditFormVisible" :defaultFormData="{}"
- title="批量编辑" :submitLoading="batchEditFormLoading"
- @close="CloseBatchEditForm"
- @confirm="SaveBatchEditForm">
- <template #form_pre>
- <ul class="grade_form_item">
- <li v-for="grade in batchEditGradeList" :key="grade.evaluationGradeId">
- <div class="grade_name">{{ grade.evaluationGradeName }}</div>
- <div class="class_list">
- <el-checkbox
- v-model="grade.isSelectAll"
- :indeterminate="grade.selectedClassList?.length < grade.classList?.length && grade.selectedClassList?.length !==0 ? true : false"
- @change="(val)=>HandleGradeSelectAllOrNot(grade,val)"
- >
- 全选
- </el-checkbox>
- <el-checkbox
- v-model="grade.selectedClassList "
- v-for="checkItem in grade.classList"
- :key="checkItem.value"
- :label="checkItem.label"
- :value="checkItem.value"
- @change="(val)=>HandleGradeClassSelectChange(grade,val)"
- />
- </div>
- </li>
- </ul>
- </template>
- <template #footerRight="{formRef}">
- <div v-if="!store.state.evaluationManageStepData.isGenerateAccountByGender" class="batch_num">
- <span>数量:<el-input type="number" v-model="batchAccountNum" placeholder="请输入"/></span>
- </div>
- <div v-else class="group_batch_num">
- <span>男生:<el-input type="number" v-model="batchMaleNum" placeholder="请输入"/></span>
- <span>女生:<el-input type="number" v-model="batchFemaleNum" placeholder="请输入"/></span>
- </div>
- </template>
- </FormDialog>
-
- </div>
- </template>
- <script setup lang="ts">
- import { onMounted,ref,watch } from 'vue';
- import { useStore } from 'vuex';
- import { useRoute,useRouter } from 'vue-router';
- import ExcelJS from 'exceljs';
- import Table from '@/baseComponents/Table.vue';
- import FormDialog from '@/baseComponents/FormDialog.vue';
- import {
- getReviewAccountListApi,
- } from '@/api/reviewAccountComponent'
- const route = useRoute()
- const router = useRouter()
- const store = useStore()
- // store.state.evaluationManageStepData.isGenerateAccountByGender //按男女生成
- // 1. 评价账号数据 渲染 及 操作
- // 评价账号原始数据
- const originReviewAccount = ref({})
- // 渲染到表格中的评价账号数据
- const tableData = ref([]);
- const tableColumns = ref([])
- // 表头初始赋值 和 表行初始赋值 以及 批量编辑弹窗变量赋值
- const GetReviewAccountList = async ()=>{
- let params = {evaluationId: route.query.id}
- let res = await getReviewAccountListApi(params)
- if(res?.code == 200){
- let gradeMsg = res.data?.dataList || {}
- originReviewAccount.value = gradeMsg || {}
- // 批量编辑弹窗变量赋值
- batchEditGradeList.value = Object.values(gradeMsg).map(item=>{
- return {
- ...item,
- isSelectAll:false,
- selectedClassList:[],
- classList:item.classData.map(classItm=>{
- return {
- label: classItm.evaluationClassName,
- value: classItm.id
- }
- })
- }
- })
- //表头赋值
- tableColumns.value = Object.values(gradeMsg)?.map(grade=>{
- let gradeId = grade.evaluationGradeId
- return [
- {
- name: `grade_${gradeId}`,
- label: '年级',
- width: '80',
- align: 'center',
- custom: false,
- hidden: false,
- },
- {
- name: `class_${gradeId}`,
- label: '班级',
- width: '80',
- align: 'center',
- custom: true,
- hidden: false,
- },
- {
- name: `num_${gradeId}`,
- label: '数量',
- width: '80',
- align: 'center',
- custom: true,
- hidden: false,
- },
- {
- name: `male_${gradeId}`,
- label: '男生',
- width: '80',
- align: 'center',
- custom: true,
- hidden: true,
- },
- {
- name: `female_${gradeId}`,
- label: '女生',
- width: '80',
- align: 'center',
- custom: true,
- hidden: true,
- },
- ]
- }).flat()
- //初次赋值,要检查 上一次生成账号是否按男女生成
- ChangeHeaderShowItem(store.state.evaluationManageStepData.isGenerateAccountByGender)
- // 表行赋值
- Object.values(gradeMsg)?.map(grade=>{
- let gradeId = grade.evaluationGradeId
- let gradeName = grade.evaluationGradeName
- let classDataList = grade.classData
-
- classDataList.map((classItm,index)=>{
- if(typeof tableData.value[index] !== 'object'){
- tableData.value[index] = {}
- }
- // 当前年级下的行赋值
- tableData.value[index][`grade_${gradeId}`] = gradeName
- tableData.value[index][`class_${gradeId}`] = {
- className:classItm.evaluationClassName,
- classId:classItm.id,
- }
- tableData.value[index][`num_${gradeId}`] = classItm.evaluationCount
- tableData.value[index][`male_${gradeId}`] = classItm.boyCount
- tableData.value[index][`female_${gradeId}`] = classItm.girlCount
- })
- })
- }
- }
- // 切换评价账号的表头展示项 _ 根据 是否按男女生成 来判断
- const ChangeHeaderShowItem = (isGenerateByGender:Boolean)=>{
- if(isGenerateByGender){
- // 打开
- tableColumns.value = tableColumns.value.map(item=>{
- if(item?.name.startsWith('num_')){
- item.hidden = true
- }else if(item?.name.startsWith('male_') || item?.name.startsWith('female_')){
- item.hidden = false
- }
- return item
- })
- }else{
- // 关闭
- tableColumns.value = tableColumns.value.map(item=>{
- if(item?.name.startsWith('num_')){
- item.hidden = false
- }else if(item?.name.startsWith('male_') || item?.name.startsWith('female_')){
- item.hidden = true
- }
- return item
- })
- }
- }
- watch(()=>store.state.evaluationManageStepData.isGenerateAccountByGender,(val)=>{
- ChangeHeaderShowItem(val)
- })
- // 2. 批量编辑弹窗操作
- const batchEditFormVisible = ref(false)
- const batchEditFormLoading = ref(false)
- const batchAccountNum = ref() //批量的所有数据
- const batchFemaleNum = ref() //批量的女性数据
- const batchMaleNum = ref() //批量的男性数据
- interface batchEditGradeItm {
- evaluationGradeName: string,
- evaluationGradeId: string,
- classList: {label: string, value: string }[],
- selectedClassList:string[],
- isSelectAll:boolean,
- }
- // 批量编辑 弹窗数据
- const batchEditGradeList = ref<batchEditGradeItm[]>([]);
- // 关闭批量编辑弹窗
- const CloseBatchEditForm = ()=>{
- batchEditFormVisible.value = false
- batchAccountNum.value = null
- batchMaleNum.value = null
- batchFemaleNum.value = null
- // 清除 批量弹窗编辑 的批量选中数据
- batchEditGradeList.value = batchEditGradeList.value.map(item=>{
- return {
- ...item,
- selectedClassList:[],
- isSelectAll:false
- }
- })
- }
- // 打开批量编辑弹窗
- const OpenBatchEditForm = ()=>{
- batchEditFormVisible.value = true
- }
- // 保存批量编辑配置 ——
- const SaveBatchEditForm = (params:any)=>{
- const batchData = batchEditGradeList.value.map(item=>{
- return {
- gradeName: item.evaluationGradeName,
- gradeId: item.evaluationGradeId,
- selectedClassList:item.selectedClassList
- }
- })?.filter(item=>{return item.selectedClassList?.length > 0})
- // 选中的值赋值
- batchEditGradeList.value.map(grade=>{
- let gradeId = grade.evaluationGradeId
- let classDataList = grade.classData
- let changeAim = batchData.find(itm=>itm.gradeId == gradeId)
- // 有需要批量修改的 年级
- if(changeAim){
- classDataList.map((classItm,index)=>{
- // 有需要批量修改的 班级
- if(changeAim.selectedClassList.find(classId=>classId == classItm.id )){
- if(typeof tableData.value[index] !== 'object'){
- tableData.value[index] = {}
- }
- // 当前年级下 某个班级 的行赋值
- if(store.state.evaluationManageStepData.isGenerateAccountByGender){
- // 按男女生成
- tableData.value[index][`num_${gradeId}`] = Number(batchMaleNum.value) + Number(batchFemaleNum.value)
- tableData.value[index][`male_${gradeId}`] = batchMaleNum.value
- tableData.value[index][`female_${gradeId}`] = batchFemaleNum.value
- }else{
- // 按总人数生成
- tableData.value[index][`num_${gradeId}`] = batchAccountNum.value
- tableData.value[index][`male_${gradeId}`] = Math.floor(batchAccountNum.value / 2)
- tableData.value[index][`female_${gradeId}`] = Math.ceil(batchAccountNum.value / 2)
- }
- }
- })
- }
- })
- CloseBatchEditForm()
- }
- // 年级全选/全不选
- const HandleGradeSelectAllOrNot = (grade,val)=>{
- if(val){
- // 全选
- batchEditGradeList.value = batchEditGradeList.value.map(item=>{
- if(item.evaluationGradeId == grade.evaluationGradeId){
- item.selectedClassList = item.classList.map(classItm=>{
- return classItm.value
- })
- }
- return item
- })
- }else{{
- // 全不选
- batchEditGradeList.value = batchEditGradeList.value.map(item=>{
- if(item.evaluationGradeId == grade.evaluationGradeId){
- item.selectedClassList = []
- }
- return item
- })
- }}
- }
- // 年级下 班级选择的变更
- const HandleGradeClassSelectChange = (grade,val)=>{
- batchEditGradeList.value = batchEditGradeList.value.map(item=>{
- if(item.evaluationGradeId == grade.evaluationGradeId){
- item.isSelectAll = grade.selectedClassList?.length === grade.classList?.length && grade.selectedClassList?.length !==0 ? true : false
- }
- return item
- })
- }
- // 3. 清空配置的评价账号数据
- const ClearReviewAccount = ()=>{
- batchEditGradeList.value?.map(grade=>{
- let gradeId = grade.evaluationGradeId
- let classDataList = grade.classData
- classDataList.map((classItm,index)=>{
- if(typeof tableData.value[index] !== 'object'){
- tableData.value[index] = {}
- }
- // 当前年级下的行赋值
- tableData.value[index][`num_${gradeId}`] = null
- tableData.value[index][`male_${gradeId}`] = null
- tableData.value[index][`female_${gradeId}`] = null
- })
- })
- }
- // 4. 生成评价码页面
- const GoToGenerateCodePage = ()=>{
- // 跳转到生成评价码页面前要临时存储 当前页面的所有数据
- let reviewAccountMsg = {
- originReviewAccount:originReviewAccount.value,
- batchEditGradeList:batchEditGradeList.value,
- tableColumns:tableColumns.value,
- tableData:tableData.value
- }
- let accounts = batchEditGradeList.value?.map(grade=>{
- let gradeId = grade.evaluationGradeId
- let classDataList = grade.classData
- return classDataList.map((classItm,index)=>{
- if(typeof tableData.value[index] !== 'object'){
- tableData.value[index] = {}
- }
- return {
- id:tableData.value[index][`class_${gradeId}`].classId,
- evaluationGradeName: tableData.value[index][`grade_${gradeId}`],
- evaluationDataClassName: tableData.value[index][`class_${gradeId}`]?.className,
- evaluationCount: tableData.value[index][`num_${gradeId}`],
- boyCount: tableData.value[index][`male_${gradeId}`],
- girlCount: tableData.value[index][`female_${gradeId}`]
- }
- })
- })?.flat() || []
- let params = {
- evaluationId: route.query.id,
- genderStatus: store.state.evaluationManageStepData.isGenerateAccountByGender ? 1 : 0,
- accounts
- }
- // 存储当前整个页面的内容——防止生成评价码失败后,不能继续延用 配置状态的旧数据
- sessionStorage.setItem('reviewAccountMsg',JSON.stringify(reviewAccountMsg))
- // 存储生成评价码需要的参数
- sessionStorage.setItem('reviewAccountOptionData',JSON.stringify(params))
- router.push(`generateReviewCode?id=${route.query.id}`)
- }
- // 5. 批量导入/ 导出
- const HandleExportExcel = async () => {
- // 1. 初始化sheet列表
- let finalTableColumn = tableColumns.value
- let finalTableData = tableData.value
- let sheetName = '评价账号'
- // 2. 创建工作簿 和 工作表
- const workbook = new ExcelJS.Workbook();
- const worksheet = workbook.addWorksheet(sheetName);
- // 3. 添加表头行
- let headers = finalTableColumn.map(column => column.label || column.name)
- let headerRow = worksheet.addRow(headers)
- //4. 定义表头样式
- headerRow.eachCell((cell) => {
- cell.style = {
- font: { name: 'Microsoft YaHei', size: 12, bold: true, color: { argb: 'FF333333' } },
- fill: { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF4F6F8' } },
- border: {
- top: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- left: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- bottom: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- right: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- },
- alignment: { vertical: 'middle', horizontal: 'left', wrapText: true },
- }
- })
- // 5. 添加数据行
- finalTableData.forEach(row => {
- const rowData = finalTableColumn.map(column => {
- const cellValue = row[column.name];
- if(column.name.startsWith('class_')){
- return cellValue?.className
- }
- return cellValue || '-'
- })
- const excelRow = worksheet.addRow(rowData);
- // 6. 定义数据行样式
- excelRow.eachCell({ includeEmpty: true }, (cell) => {
- cell.style = {
- font: { name: 'Microsoft YaHei', size: 12, color: { argb: 'FF333333' } },
- border: {
- top: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- left: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- bottom: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- right: { style: 'thin', color: { argb: 'FFD9D9D9' } },
- },
- alignment: { vertical: 'top', horizontal: 'left', wrapText: true },
- };
- });
- });
- // 5. 设置列宽
- worksheet.columns = headers.map(() => ({ width: 25 }));
- // 6. 导出文件
- const buffer = await workbook.xlsx.writeBuffer();
- const blob = new Blob([buffer], {
- type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
- });
-
- const url = URL.createObjectURL(blob);
- const link = document.createElement('a');
- link.href = url;
- link.download = `评价账号表_${new Date().toISOString().slice(0, 10)}.xlsx`;
- link.style.visibility = 'hidden';
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- URL.revokeObjectURL(url);
- };
- onMounted(async ()=>{
- let reviewAccountMsg = sessionStorage.getItem('reviewAccountMsg')
- // 如果有缓存,说明是从生成评价码失败页面跳过来的
- if(reviewAccountMsg){
- let objMsg = JSON.parse(reviewAccountMsg || '{}')
- originReviewAccount.value = objMsg.originReviewAccount
- batchEditGradeList.value = objMsg.batchEditGradeList
- tableColumns.value = objMsg.tableColumns
- tableData.value = objMsg.tableData
- sessionStorage.removeItem('reviewAccountMsg') //获取完后清空数据
- }else{
- await GetReviewAccountList()
- }
- })
- </script>
- <style lang="scss" scoped>
- .grade_form_item{
- display: flex;
- flex-direction: column;
- gap:26px;
- .grade_name{
- font-weight: 600;
- font-size: 16px;
- color: #333333;
- margin-bottom: 10px;
- }
- .class_list .el-checkbox{
- font-weight: 400;
- font-size: 14px;
- color: #666666;
- }
- }
- .group_batch_num,
- .batch_num{
- display: flex;
- align-items: center;
- gap:20px;
- word-break: keep-all;
- > span{
- display: flex;
- align-items: center;
- word-break: keep-all;
- }
- }
- </style>
|