马宇豪
2025-03-07 db905ecd14f63dba9337b4f4715584ef2d7e8c7e
src/views/specialOperationsPay/notCoalPay/components/studentDialog.vue
@@ -2,143 +2,484 @@
  <div>
    <el-dialog :visible.sync="dialogVisible" width="800px" append-to-body class="stu">
      <div class="infoTitle">
        <div>批次名称:XXXXX</div>
        <div style="margin-left: 35px">管辖行政区划:XXXxxxx</div>
        <div>批次名称:<span>{{stuInfo.batchName}}</span></div>
      </div>
      <div class="infoTitle">
        <div>考试点名称:XXXXX</div>
        <div>所属区划:<span>{{stuInfo.districtName}}</span></div>
      </div>
      <el-form :model="form"  ref="ruleForm" label-width="125px">
      <div class="infoTitle">
        <div>组织架构:<span>{{stuInfo.deptName}}</span></div>
      </div>
      <el-form :model="stuInfo" label-width="125px">
        <el-row :gutter="24">
          <el-col :span="8">
            <el-form-item label="缴费周期:" prop="timeRange">
              <span>xxxx</span>
          <el-col :span="12">
            <el-form-item label="缴费周期:">
              <span><span>{{stuInfo.year}}{{stuInfo.quarter==1?' 第一季度':stuInfo.quarter==2?' 第二季度':stuInfo.quarter==3?' 第三季度':' 第四季度'}}</span></span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="缴费类型:" prop="timeRange">
              <span>xxxx</span>
            <el-form-item label="缴费类型:">
              <span>{{stuInfo.payType == 1?'初训理论':stuInfo.payType == 2?'初训实操':stuInfo.payType == 3?'初训理论与实操':stuInfo.payType == 4?'复训理论':''}}</span>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="8">
            <el-form-item label="理论类别:" prop="timeRange">
              <span>xxxx</span>
          <el-col :span="12" v-if="stuInfo.payType === 1 || stuInfo.payType === 3 || stuInfo.payType === 4">
            <el-form-item label="理论类别:">
              <span>{{stuInfo.nonCoalPayCategoryList.find(i => i.categoryType == 1) && stuInfo.nonCoalPayCategoryList.find(i => i.categoryType == 1).subjectName }}</span>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="实操类别:" prop="timeRange">
              <span>xxxx</span>
          <el-col :span="12" v-if="stuInfo.payType === 2 || stuInfo.payType === 3">
            <el-form-item label="实操类别:">
              <span>{{stuInfo.nonCoalPayCategoryList.find(i => i.categoryType == 2) && stuInfo.nonCoalPayCategoryList.find(i => i.categoryType == 2).subjectName }}</span>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="6">
            <el-form-item label="单人应缴:" prop="timeRange">
              <span>xxxx</span>
              <span>{{stuInfo.amount}}</span>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="总计应缴费:" prop="timeRange">
              <span>xxxx</span>
              <span>{{ stuInfo.totalCountFee }}元</span>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="已完成缴费:" prop="timeRange">
              <span>xxxx</span>
              <span>{{stuInfo.payCountFee}}元</span>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="剩余未缴费:" prop="timeRange">
              <span>xxxx</span>
              <span>{{stuInfo.unPayCountFee}}元</span>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="24">
          <el-col :span="6">
            <el-form-item label="当前总计应缴:" prop="timeRange">
              <span>xxxx人</span>
              <span>{{stuInfo.totalCount}}人</span>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="已完成缴费:" prop="timeRange">
              <span>xxxx人</span>
              <span>{{stuInfo.payCount}}人</span>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="当前未完成缴费:" prop="timeRange">
              <span>xxxx人</span>
              <span>{{stuInfo.unPayCount}}人</span>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
  <!--    表格-->
      <div style="margin: 20px 15px;display: flex">
        <el-button size="small"  type="primary" @click="handleAddStu('add',{})">添加学员</el-button>
        <el-button size="small"  type="primary" >批量导入</el-button>
      <div style="margin: 20px 15px;display: flex;justify-content: space-between">
        <div>
          <el-button size="small" type="primary" @click="handleAddStu('add',{})">添加学员</el-button>
          <el-button size="small" type="primary" @click="importDialog = true">批量导入</el-button>
        </div>
        <el-button type="text" @click="exportExcel">导出清单</el-button>
      </div>
      <el-table v-loading="loading" :data="stuList">
      <el-table v-loading="loading" :data="stuList" id="table_excel">
        <el-table-column label="序号" align="center" type="index" />
        <el-table-column label="姓名" align="center" prop="createTime" />
        <el-table-column label="身份证号" align="center" prop="batchName" />
        <el-table-column label="手机号" align="center" prop="batchName" />
        <el-table-column label="性别" align="center" prop="batchName" />
        <el-table-column label="财政缴款码" align="center" prop="batchName" />
        <el-table-column label="是否已缴" align="center" prop="batchName" />
        <el-table-column label="姓名" align="center" prop="name" />
        <el-table-column label="身份证号" align="center" prop="idCard" />
        <el-table-column label="手机号" align="center" prop="phone" />
        <el-table-column label="性别" align="center" prop="sex">
          <template #default="scope">
            {{(parseInt(scope.row.idCard.substr(16, 1))) % 2 === 0 ? "女" : "男"}}
          </template>
        </el-table-column>
        <el-table-column label="财政缴款码" align="center" prop="payCode">
          <template #default="scope">
            {{scope.row.payCode?scope.row.payCode:'--'}}
          </template>
        </el-table-column>
        <el-table-column label="是否已缴" align="center" prop="payStatus">
          <template #default="scope">
            <span v-if="scope.row.payStatus == 1" style="color: green">已缴</span>
            <span v-else style="color: red">未缴</span>
          </template>
        </el-table-column>
        <el-table-column label="培训机构" align="center" prop="train" />
        <el-table-column label="类别" align="center" prop="payType">
          <template #default="scope">
            {{scope.row.payType == 1?'个人':scope.row.payType == 2?'集体':''}}
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center">
          <template #default="scope">
            <el-button size="mini" type="text" v-if="scope.row.payStatus == 1" style="color: #1890ff" @click="checkTicket">查看票据</el-button>
            <el-button size="mini" type="text" v-if="scope.row.payStatus == 0" style="color: #1890ff" @click="goPay(scope.row)">去缴费</el-button>
            <el-button size="mini" type="text" style="color: #1890ff" v-if="!(scope.row.payCode && scope.row.payCode!=='')" @click="handleAddStu('edit',scope.row)">修改</el-button>
            <el-button size="mini" type="text" style="color:lightcoral" v-if="!(scope.row.payCode && scope.row.payCode!=='')" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="total>0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getStuList"
      />
    </el-dialog>
    <add-stu-dialog ref="addStuDialogRef" @getList = "getStuList"></add-stu-dialog>
    <el-dialog
      :title="dialogStatus==='add'?'新增':'编辑'"
      :visible.sync="addDialog"
      :modal-append-to-body="false"
      :close-on-click-modal="false"
      width="450px"
      :before-close="handleClose"
    >
      <el-form ref="dataForm" :model="dataForm"  :rules="addRules" label-position="right" label-width="150px" style="padding-right: 50px" element-loading-text="保存中...">
        <el-form-item label="姓名:" prop="name">
          <el-input v-model.trim="dataForm.name"/>
        </el-form-item>
        <el-form-item label="性别:" prop="sex">
          <el-radio-group v-model="dataForm.sex">
            <el-radio :label="0">男</el-radio>
            <el-radio :label="1">女</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="培训机构:">
          <el-input v-model.trim="dataForm.train"/>
        </el-form-item>
        <el-form-item label="身份证号:" prop="idCard">
          <el-input v-model.trim="dataForm.idCard"/>
        </el-form-item>
        <el-form-item label="手机号:" prop="phone">
          <el-input v-model.trim="dataForm.phone"/>
        </el-form-item>
      </el-form>
      <el-alert
        :closable="false"
        title="提示:请务必填写准确,将用于个人缴费查询。"
        type="warning">
      </el-alert>
      <span slot="footer" class="dialog-footer">
      <el-button @click="handleClose">取 消</el-button>
      <el-button type="primary" @click="onSubmit">确 定</el-button>
    </span>
    </el-dialog>
    <el-dialog
      :visible.sync="importDialog"
      append-to-body
      title="批量导入"
      :close-on-click-modal="false"
    >
      <el-form
        ref="importForm"
        label-position="right"
        label-width="120px"
        style="margin-left:50px;width:500px;"
        element-loading-text="导入中..."
      >
        <el-form-item label="导入文件:">
          <el-upload
            :action="uploadUrl"
            :on-error="onError"
            :on-success="onSuccess"
            :auto-upload="false"
            accept=".xlsx,.xls"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :before-remove="beforeRemove"
            :before-upload="picSize"
            ref="upload"
            :limit="1"
            :data={nonCoalPayId:id}
            :headers="header"
            :on-exceed="handleExceed"
            :file-list="fileList">
            <el-button size="small" type="primary">点击上传</el-button>
            <div slot="tip" class="el-upload__tip">只能上传excel(.xlsx、.xls后缀)文件,且不超过2M</div>
          </el-upload>
        </el-form-item>
        <el-form-item label="excel参考模板:">
          <el-button type="text" @click="viewHandle">下载模板</el-button>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="importDialog = false">取消</el-button>
        <el-button  type="primary" @click="importHandle()">导入</el-button>
      </div>
    </el-dialog>
 </div>
</template>
<script>
import addStuDialog from './addStuDialog.vue'
import {verifyIdCard, verifySimplePhone} from "@/utils/validate"
import * as XLSX from 'xlsx';
import { saveAs } from 'file-saver';
import {
  addNonCoalStu, delNonCalStu, delNonCoalPay,
  editNonCoalStu,
  getNonCoalPayStudents,
  getPayTypeInfo, nonCoalPersonPay
} from "@/api/specialOperationsPay/notCoalPay";
import exampleFile from '@/assets/studentInfo.xlsx'
import {getToken} from "@/utils/auth";
import {coalPersonPay} from "@/api/specialOperationsPay/coalPay";
export default {
  name: 'addStu',
  components: {
    addStuDialog
  },
  components: {},
  data() {
    let validatePhone = (rule, value, callback)=>{
      if(value === ''){
        callback(new Error('请输入手机号'))
      }else{
        if(!verifySimplePhone(value)){
          callback(new Error('手机号格式有误'))
        }else{
          callback()
        }
      }
    }
    let verifyId = (rule, value, callback)=>{
      if(value === ''){
        callback(new Error('请输入身份证号'))
      }else{
        if(!verifyIdCard(value)){
          callback(new Error('身份证号格式有误'))
        }else{
          callback()
        }
      }
    }
    return {
      open: false,
      id: null,
      dialogVisible: false,
      importDialog: false,
      loading: false,
      stuInfo: {},
      stuList: [],
      form: {
        id: null,
        staffId: null,
        timeRange: [],
        startTime: '',
        endTime: '',
        unit: ''
      fileList: [],
      uploadUrl: process.env.VUE_APP_BASE_API + '/pay/nonCoalPay/stuImportData',
      header: {
        Authorization: "Bearer " + getToken()
      },
      total: 0,
      queryParams: {
        pageNum: 1,
        pageSize: 10,
      },
      addDialog: false,
      dialogStatus: '',
      dataForm: {},
      addRules: {
        name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
        idCard: [{ required: true, validator: verifyId, trigger: 'blur' }],
        phone:[{ required: true, validator: validatePhone, trigger: 'blur' }],
        sex: [{ required: true, message: '请选择性别', trigger: 'blur' }]
      }
    };
  },
  methods: {
    openDialog(val) {
    exportExcel() {
      var xlsxParam = { raw: true }
      let tables = document.getElementById('table_excel')
      let clonedTable = tables.cloneNode(true); // 深度克隆
      // 删除克隆表格中的最后一列
      const allRows = clonedTable.querySelectorAll('tr');
      allRows.forEach((row,index) => {
        const cells = row.querySelectorAll('th,td');
        if (cells.length > 0) {
          if(index == 0){
            row.removeChild(cells[cells.length - 2]); // 表头行要特殊处理
          }else{
            row.removeChild(cells[cells.length - 1]); // 移除最后一个单元格
          }
        }
      })
      let table_book = this.$XLSX.utils.table_to_book(clonedTable, xlsxParam);
      const table_write = this.$XLSX.write(table_book, {
        bookType: 'xlsx',
        bookSST: true,
        type: 'array'
      });
      try {
        this.$FileSaver.saveAs(
          new Blob([table_write], { type: 'application/octet-stream' }),
          `${this.stuInfo.batchName}批次学员缴费清单.xlsx`
        );
      } catch (e) {
        if (typeof console !== 'undefined') console.log(e, table_write);
      }
      return table_write
    },
    openDialog(id) {
      this.getStuList(id)
      this.id = id
      this.dialogVisible = true;
    },
    getStuList () {
    getStuList(id) {
      getNonCoalPayStudents(id).then(res=>{
        if(res.code == 200){
          this.stuInfo = res.data
          this.stuList = res.data.nonCoalPayStudentList
        }
      })
    },
    handleAddStu(type,data){
      this.$refs.addStuDialogRef.openDialog(type, data);
    }
      this.addDialog = true
      this.resetDataForm()
      if(type == 'add'){
        this.dataForm.nonCoalPayId = this.id
      }else{
        const {id,nonCoalPayId,name,idCard,sex,phone} = data
        this.dataForm = {id,nonCoalPayId,name,idCard,sex,phone}
      }
      this.dialogStatus = type
    },
    viewHandle() {
      const link = document.createElement('a')
      link.href = exampleFile
      link.target = '_blank'
      link.download = '学员批量导入模版.xlsx'
      link.click()
    },
    handleRemove(file, fileList) {
      console.log(file, fileList);
    },
    handlePreview(file) {
      console.log(file);
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
    },
    picSize(rawFile){
      if(rawFile.size / 1024 / 1024 > 2){
        this.$message({
          type: 'warning',
          message: '文件大小不能超过2M'
        });
        return false
      }
    },
    async importHandle(){
      const t = this
      await t.$refs.upload.submit()
      t.importDialog = false
      setTimeout(()=>{
        t.getStuList(this.stuInfo.id)
        t.fileList = []
        t.$refs.upload.clearFiles()
      },800)
    },
    onError(){
      console.log("文件上传失败")
    },
    onSuccess(res, file, fileList){
      if(res.code == 200){
        this.$message({
          type:'success',
          message: res.msg
        })
      }else{
        this.$message({
          type:'warning',
          message: res.msg
        })
      }
    },
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${ file.name }?`);
    },
    handleClose() {
      this.addDialog = false
    },
    onSubmit() {
      this.$refs["dataForm"].validate( async valid => {
        if (valid) {
          if(this.dialogStatus == 'add'){
            const res = await addNonCoalStu(this.dataForm)
            if(res.code == 200) {
              this.getStuList(this.id)
              this.addDialog = false
              this.$message({
                type:'success',
                message: '新增成功'
              })
            }else{
              this.$message({
                type:'warning',
                message: res.msg
              })
            }
          }else {
            const res = await editNonCoalStu(this.dataForm)
            if(res.code == 200) {
              this.getStuList(this.id)
              this.addDialog = false
              this.$message({
                type:'success',
                message: '修改成功'
              })
            }else{
              this.$message({
                type:'warning',
                message: res.msg
              })
            }
          }
        }
      })
    },
    checkTicket(){
      window.open('http://finpt.xjcz.gov.cn/fs-public/index.do')
    },
    async goPay(item){
      if(item.payCode && item.payCode !== ''){
        window.open(`http://finpt.xjcz.gov.cn/fs-public/billQuery/findByOrderId.do?orderId=${item.orderId}&deviceType=1`)
      }else{
        const query = {
          id: item.id,
          payType: 1
        }
        const res = await nonCoalPersonPay(query)
        if(res.code == 200) {
          window.open(`http://finpt.xjcz.gov.cn/fs-public/billQuery/findByOrderId.do?orderId=${res.msg}&deviceType=1`)
        }else{
          this.$message({
            type:'warning',
            message: res.msg
          })
        }
      }
    },
    handleDelete(row){
      this.$confirm('此操作将永久删除该条数据, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        const res = await delNonCalStu(row.id)
        if(res.code == 200){
          this.$message({
            type: 'success',
            message: '删除成功!'
          });
          await this.getStuList(this.id)
        }else{
          this.$message({
            type: 'warning',
            message: res.msg
          });
        }
      }).catch(() => {
      });
    },
    resetDataForm() {
      this.dataForm = {
      }
    },
  }
}
@@ -153,8 +494,10 @@
    margin-bottom:10px;
    margin-left: 40px;
    display: flex;
    font-weight: 800;
    font-size: 16px
    font-size: 16px;
    span{
      font-weight: bolder;
    }
  }
}