级位审核
Showing
4 changed files
with
1514 additions
and
788 deletions
| 1 | <template> | 1 | <template> |
| 2 | <view> | 2 | <view class="add-apply-page"> |
| 3 | <view class="pd30"> | 3 | <!-- 顶部步骤条 --> |
| 4 | <uni-steps :options="list1" :active="active" /> | 4 | <view class="steps-bar"> |
| 5 | <view class="hasfixedbottom"> | 5 | <view class="step-item" :class="{ active: active >= 0, current: active == 0 }"> |
| 6 | <view class="wBox" v-if="active == 0"> | 6 | <view class="step-circle">1</view> |
| 7 | <uni-forms ref="baseForm" :modelValue="form" label-width="100"> | 7 | <view class="step-text">考级基本信息</view> |
| 8 | <uni-forms-item label="考试名称"> | 8 | </view> |
| 9 | <view class="align-forms-item" v-if="form.name">{{form.name}}</view> | 9 | <view class="step-line" :class="{ active: active >= 1 }"></view> |
| 10 | <view v-else class="align-forms-item-placeHolder">自动生成</view> | 10 | <view class="step-item" :class="{ active: active >= 1, current: active == 1 }"> |
| 11 | </uni-forms-item> | 11 | <view class="step-circle">2</view> |
| 12 | <uni-forms-item label="申请单位" required> | 12 | <view class="step-text">添加考生</view> |
| 13 | <view class="align-forms-item">{{form.memberName}}</view> | 13 | </view> |
| 14 | </uni-forms-item> | 14 | </view> |
| 15 | <uni-forms-item label="申请日期" required> | 15 | |
| 16 | <uni-datetime-picker type="date" v-model="form.applyTime"></uni-datetime-picker> | 16 | <view class="page-content"> |
| 17 | </uni-forms-item> | 17 | <!-- 步骤1:考级基本信息 --> |
| 18 | <uni-forms-item label="考试开始时间" required> | 18 | <view class="wBox" v-if="active == 0"> |
| 19 | <uni-datetime-picker type="datetime" v-model="form.startTime"></uni-datetime-picker> | 19 | <uni-forms ref="baseForm" :modelValue="form" label-width="100"> |
| 20 | </uni-forms-item> | 20 | <uni-forms-item label="考试名称"> |
| 21 | <uni-forms-item label="考试结束时间" required> | 21 | <view class="align-forms-item" v-if="form.name">{{form.name}}</view> |
| 22 | <uni-datetime-picker type="datetime" v-model="form.endTime"></uni-datetime-picker> | 22 | <view v-else class="align-forms-item-placeHolder">自动生成</view> |
| 23 | </uni-forms-item> | 23 | </uni-forms-item> |
| 24 | <uni-forms-item label="考级地点" required> | 24 | <uni-forms-item label="申请单位" required> |
| 25 | <uni-easyinput v-model="form.examLocation" placeholder="考级地点" /> | 25 | <view class="align-forms-item">{{form.memberName}}</view> |
| 26 | </uni-forms-item> | 26 | </uni-forms-item> |
| 27 | <uni-forms-item @updateData="updateData" :label="`考官${ec}`" v-for="ec in examinerForChoose" | 27 | <uni-forms-item label="申请日期" required> |
| 28 | :key="ec"> | 28 | <uni-datetime-picker type="date" v-model="form.applyTime"></uni-datetime-picker> |
| 29 | <view class="maskbox"> | 29 | </uni-forms-item> |
| 30 | <view class="mask" @click="selectFN(ec)"></view> | 30 | <uni-forms-item label="考试开始时间" required> |
| 31 | <uni-easyinput v-model="form[`examiner_${ec}`]" clearable placeholder="点击选择考官" /> | 31 | <uni-datetime-picker type="datetime" v-model="form.startTime"></uni-datetime-picker> |
| 32 | </view> | 32 | </uni-forms-item> |
| 33 | </uni-forms-item> | 33 | <uni-forms-item label="考试结束时间" required> |
| 34 | 34 | <uni-datetime-picker type="datetime" v-model="form.endTime"></uni-datetime-picker> | |
| 35 | </uni-forms> | 35 | </uni-forms-item> |
| 36 | 36 | <uni-forms-item label="考级地点" required> | |
| 37 | </view> | 37 | <uni-easyinput v-model="form.examLocation" placeholder="考级地点" /> |
| 38 | <view class="wBox" v-if="active == 1"> | 38 | </uni-forms-item> |
| 39 | <!-- 添加考生 --> | 39 | <uni-forms-item :label="`考官${ec}`" v-for="ec in examinerForChoose" :key="ec"> |
| 40 | <view class="flexbox"> | 40 | <view class="maskbox"> |
| 41 | <button class="btn-red-kx mini w100" @click="chooseOnline"> | 41 | <view class="mask" @click="selectFN(ec)"></view> |
| 42 | <uni-icons type="personadd" size="16" color="#AD181F"></uni-icons> | 42 | <uni-easyinput v-model="form[`examiner_${ec}`]" clearable placeholder="点击选择考官" /> |
| 43 | 在线选择</button> | 43 | </view> |
| 44 | <!-- <button class="btn-red-kx mini w45" @click="handleUpdate"> | 44 | </uni-forms-item> |
| 45 | <uni-icons type="upload" size="16" color="#AD181F"></uni-icons> | 45 | </uni-forms> |
| 46 | 上传成绩单</button> --> | 46 | </view> |
| 47 | </view> | 47 | |
| 48 | <view class="vipData mt30" style="flex-wrap:wrap"> | 48 | <!-- 步骤2:添加考生 --> |
| 49 | <view class="w25">合计:<text>{{tablePersonInfo.total}}</text>人</view> | 49 | <view class="step2-content" v-if="active == 1"> |
| 50 | <view class="w25" v-for="l in tablePersonInfo.levelArr" :key="l.level"> | 50 | <!-- 考级信息卡片 --> |
| 51 | {{ szToHz(l.level) }}级:<text>{{l.num}}</text>人 | 51 | <view class="exam-info-card"> |
| 52 | </view> | 52 | <view class="card-header"> |
| 53 | </view> | 53 | <text class="card-title">考级信息</text> |
| 54 | <view class="userlist"> | 54 | </view> |
| 55 | <view class="item" v-for="(n,index) in infoList" :key="index" | 55 | <view class="info-grid"> |
| 56 | style="background-color: #fffafa;"> | 56 | <view class="info-item"> |
| 57 | <view class="w100"> | 57 | <text class="info-label">考试名称</text> |
| 58 | <view class="del" @click="handleDelete(n)">删除</view> | 58 | <text class="info-value">{{form.name || '-'}}</text> |
| 59 | <view style="display: flex;"> | 59 | </view> |
| 60 | <!-- | 60 | <view class="info-item"> |
| 61 | <view class="photobox"> | 61 | <text class="info-label">申请单位</text> |
| 62 | <image class="photo" v-if="n.photo" :src="n.photo" mode='aspectFill'></image> | 62 | <text class="info-value">{{form.memberName || '-'}}</text> |
| 63 | <view class="colorful" v-else>{{n.realName?.slice(0,1)}}</view> | 63 | </view> |
| 64 | </view> --> | 64 | <view class="info-item"> |
| 65 | <view> | 65 | <text class="info-label">考试地点</text> |
| 66 | <view class="name">{{n.realName}} <text>{{n.perCode}}</text></view> | 66 | <text class="info-value">{{form.examLocation || '-'}}</text> |
| 67 | <view class="date">{{n.idcTypeStr}}:{{n.idcCode}}</view> | 67 | </view> |
| 68 | </view> | 68 | <view class="info-item"> |
| 69 | </view> | 69 | <text class="info-label">考试时间</text> |
| 70 | <view class="flexbox mt30"> | 70 | <text class="info-value">{{formatDateTime(form.startTime)}} - {{formatDateTime(form.endTime)}}</text> |
| 71 | <view> | 71 | </view> |
| 72 | 原有级别 | 72 | </view> |
| 73 | <text style="padding: 15rpx 0;">{{ szToHz(n.levelOld) }}级</text> | 73 | </view> |
| 74 | </view> | 74 | |
| 75 | <view style="width: 40%;"> | 75 | <!-- 操作栏(红框顶部统计+添加按钮) --> |
| 76 | 考试级别 | 76 | <button class="btn-add-student" @click="goChooseStudent"> |
| 77 | <!-- <text style="padding: 15rpx 0;">{{ szToHz(n.levelNew) }}级</text> --> | 77 | <uni-icons type="plus" size="16" color="#fff"></uni-icons> |
| 78 | <view @click="changeLevelfather(n)"> | 78 | 添加考生 |
| 79 | <uni-data-select v-model="n.levelNew" :localdata="levelArr" | 79 | </button> |
| 80 | @change="changeLevel"></uni-data-select> | 80 | <view class="action-bar"> |
| 81 | </view> | 81 | <view class="stat-info"> |
| 82 | 82 | <text class="stat-total">共 {{tablePersonInfo.total || 0}} 人</text> | |
| 83 | </view> | 83 | <view class="level-tags"> |
| 84 | 84 | <view class="level-tag" v-for="l in tablePersonInfo.levelArr" :key="l.level"> | |
| 85 | <view style="width: 30%;"> | 85 | {{ szToHz(l.level) }}级:{{l.num}}人 |
| 86 | 是否通过 | 86 | </view> |
| 87 | <view> | 87 | </view> |
| 88 | <uni-data-select :clear="false" v-model="n.isPass" | 88 | </view> |
| 89 | :localdata="range"></uni-data-select> | 89 | |
| 90 | </view> | 90 | </view> |
| 91 | </view> | 91 | |
| 92 | </view> | 92 | <!-- 考生列表(红框主体) --> |
| 93 | </view> | 93 | <view class="student-list"> |
| 94 | 94 | <view class="student-card" v-for="(n,index) in infoList" :key="index"> | |
| 95 | </view> | 95 | <!-- 左侧:头像+考生信息 --> |
| 96 | <view class="nodata" v-if="infoList.length==0"> | 96 | <view class="card-left"> |
| 97 | <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> | 97 | <view class="avatar"> |
| 98 | <text>待添加考生</text> | 98 | <image v-if="n.photo" :src="n.photo" mode="aspectFill" /> |
| 99 | </view> | 99 | <image v-else :src="config.baseUrl_api + '/fs/static/tx@2x.png'" |
| 100 | </view> | 100 | mode="aspectFill"> |
| 101 | </view> | 101 | </image> |
| 102 | </view> | 102 | <!-- <text v-else class="avatar-text">{{(n.realName || '').slice(0,1)}}</text> --> |
| 103 | </view> | 103 | </view> |
| 104 | <view class="fixedBottom" v-if="active == 0"> | 104 | <view class="student-info"> |
| 105 | <button class="btn-red-kx" style="width: 40%;" @click="submitForm(0)">保存</button> | 105 | <view class="student-name">{{n.realName}} <text class="per-code">{{n.perCode}}</text></view> |
| 106 | <button class="btn-red" style="width: 40%;" @click="submitForm(1)">下一步</button> | 106 | <view class="student-idcard">{{n.idcTypeStr}}:{{n.idcCode}}</view> |
| 107 | </view> | 107 | </view> |
| 108 | <view class="fixedBottom" v-if="active == 1"> | 108 | </view> |
| 109 | <button class="btn-red-kx" style="width: 25%;" @click="active=0">上一步</button> | 109 | |
| 110 | <button class="btn-red-kx" style="width: 25%;" @click="submitForm2(0)">保存</button> | 110 | <!-- 右侧:原级别/考试级别/是否通过 --> |
| 111 | <button class="btn-red" style="width: 30%;" @click="submitForm2(1)">提交审核</button> | 111 | <view class="card-right"> |
| 112 | </view> | 112 | <view class="level-item"> |
| 113 | 113 | <text class="level-label">原级别</text> | |
| 114 | 114 | <text class="level-value">{{ szToHz(n.levelOld) }}级</text> | |
| 115 | <uni-popup ref="choseStudent" type="bottom" background-color="#fff" animation> | 115 | </view> |
| 116 | <view class="popBody"> | 116 | <view class="level-item"> |
| 117 | <view class="searchbar"> | 117 | <text class="level-label">考试级别</text> |
| 118 | <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search" | 118 | <view class="select-wrapper" @click="changeLevelfather(n)"> |
| 119 | v-model="studentQuery.name" placeholder="搜索姓名" @blur="chooseOnline" @clear="chooseOnline"> | 119 | <uni-data-select v-model="n.levelNew" :localdata="levelArr" @change="changeLevel" :clear="false" /> |
| 120 | </uni-easyinput> | 120 | </view> |
| 121 | </view> | 121 | </view> |
| 122 | <view class="userlist" style="height:80vh;overflow: auto;"> | 122 | <view class="level-item"> |
| 123 | <view class="item" v-for=" (n,index) in studentList" :key="index"> | 123 | <text class="level-label">是否通过</text> |
| 124 | <view @click="checkThis(n)"> | 124 | <view class="select-wrapper"> |
| 125 | <image class="icon" v-if="n.checked" | 125 | <uni-data-select v-model="n.isPass" :localdata="range" :clear="false" /> |
| 126 | :src="config.baseUrl_api+'/fs/static/member/dx_dwn.png'" /> | 126 | </view> |
| 127 | <image class="icon" v-else :src="config.baseUrl_api+'/fs/static/member/dx.png'" /> | 127 | </view> |
| 128 | </view> | 128 | </view> |
| 129 | <view class="photobox"> | 129 | |
| 130 | <image class="photo" v-if="n.photo" :src="n.photo" mode='aspectFill'> | 130 | <!-- 删除按钮 --> |
| 131 | </image> | 131 | <view class="delete-btn" @click="handleDelete(n)"> |
| 132 | <view class="colorful" v-else>{{n.name.slice(0,1)}}</view> | 132 | <uni-icons type="trash" size="18" color="#dd524d"></uni-icons> |
| 133 | </view> | 133 | </view> |
| 134 | <view> | 134 | </view> |
| 135 | <view class="name">{{n.name}} <text>{{n.perCode}}</text></view> | 135 | |
| 136 | <view class="date">到期时间:{{n.validityDate}}</view> | 136 | <!-- 空状态 --> |
| 137 | <view class="date" style="color: #1561CB;" v-if="n.levelJi&&n.levelJi!=0"> | 137 | <view class="empty" v-if="infoList.length==0"> |
| 138 | 级位:{{szToHz(n.levelJi)}}级</view> | 138 | <image class="empty-img" mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'" /> |
| 139 | <view class="date" v-else>级位:十级</view> | 139 | <text class="empty-text">暂无考生信息</text> |
| 140 | </view> | 140 | </view> |
| 141 | </view> | 141 | </view> |
| 142 | <view class="nodata" v-if="studentList.length==0"> | 142 | </view> |
| 143 | <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> | 143 | </view> |
| 144 | <text>无可参加考试会员</text> | 144 | |
| 145 | </view> | 145 | <!-- 底部按钮 --> |
| 146 | </view> | 146 | <view class="fixedBottom" v-if="active == 0"> |
| 147 | <button class="btn-red-kx" v-if="studentList.length!=0" @click="submitStudents">确定</button> | 147 | <button class="btn-red-kx" style="width: 40%;" @click="submitForm(0)">保存</button> |
| 148 | </view> | 148 | <button class="btn-red" style="width: 40%;" @click="submitForm(1)">下一步</button> |
| 149 | </uni-popup> | 149 | </view> |
| 150 | 150 | <view class="fixedBottom" v-if="active == 1"> | |
| 151 | <uni-popup ref="UpPop" type="bottom" background-color="#fff" animation> | 151 | <button class="btn-red-kx" style="width: 25%;" @click="prev">上一步</button> |
| 152 | <view class="popBody"> | 152 | <button class="btn-red-kx" style="width: 25%;" @click="submitForm2(0)">保存</button> |
| 153 | <view class="h3 text-center">上传成绩单</view> | 153 | <button class="btn-red" style="width: 30%;" @click="submitForm2(1)">提交审核</button> |
| 154 | <text class="must">*请上传大小不超过 10MB 格式为 png/jpg/jpeg/pdf/zip 的文件</text> | 154 | </view> |
| 155 | <uni-file-picker v-model="transcript" class="mtb30" file-mediatype="all" | 155 | |
| 156 | file-extname="png,jpg,jpeg,pdf,zip" @select="selectFile" @progress="fileProgress" | 156 | </view> |
| 157 | @delete="delSupplementFile"></uni-file-picker> | 157 | </template> |
| 158 | 158 | ||
| 159 | <button class="btn-red" @click="uploadSure">确定</button> | 159 | <script setup> |
| 160 | </view> | 160 | import { ref } from 'vue'; |
| 161 | </uni-popup> | 161 | import * as api from '@/common/api.js'; |
| 162 | 162 | import { onLoad, onShow } from '@dcloudio/uni-app'; | |
| 163 | </view> | 163 | import config from '@/config.js' |
| 164 | </template> | 164 | import dayjs from 'dayjs' |
| 165 | 165 | import _ from 'underscore' | |
| 166 | <script setup> | 166 | |
| 167 | import { | 167 | const app = getApp(); |
| 168 | ref | 168 | const memberInfo = app.globalData.memberInfo |
| 169 | } from 'vue'; | 169 | |
| 170 | import * as api from '@/common/api.js'; | 170 | const form = ref({ |
| 171 | import { | 171 | type: '1' |
| 172 | onLoad, | 172 | }); |
| 173 | onShow | 173 | |
| 174 | } from '@dcloudio/uni-app'; | 174 | const examinerForChoose = ['A', 'B', 'C'] |
| 175 | import config from '@/config.js' | 175 | let examinerArr = [] |
| 176 | import dayjs from 'dayjs' | 176 | const active = ref(0) |
| 177 | import _ from 'underscore' | 177 | const infoList = ref([]) |
| 178 | const app = getApp(); | 178 | const tablePersonInfo = ref({}) |
| 179 | const memberInfo = app.globalData.memberInfo | 179 | const transcript = ref([]) // 补全缺失变量 |
| 180 | const form = ref({ | 180 | |
| 181 | type: 1 | 181 | const levelArr = ref([{ |
| 182 | }); | 182 | value: '10', |
| 183 | const dataList = ref([]); | 183 | text: '十级' |
| 184 | const examinerForChoose = ['A', 'B', 'C'] | 184 | }, { |
| 185 | const examinerArr = [] | 185 | value: '9', |
| 186 | const active = ref(0) | 186 | text: '九级' |
| 187 | const total = ref(0) | 187 | }, { |
| 188 | const list1 = ref([{ | 188 | value: '8', |
| 189 | title: '考级基本信息' | 189 | text: '八级' |
| 190 | }, { | 190 | }, { |
| 191 | title: '添加考生' | 191 | value: '7', |
| 192 | }]) | 192 | text: '七级' |
| 193 | const choseStudent = ref(null) | 193 | }, { |
| 194 | const UpPop = ref(null) | 194 | value: '6', |
| 195 | const studentList = ref([]) | 195 | text: '六级' |
| 196 | const infoList = ref([]) | 196 | }, { |
| 197 | const ids = ref([]) | 197 | value: '5', |
| 198 | const tablePersonInfo = ref({}) | 198 | text: '五级' |
| 199 | const transcript = ref([]) | 199 | }, { |
| 200 | const studentQuery = ref({ | 200 | value: '4', |
| 201 | name: '' | 201 | text: '四级' |
| 202 | }) | 202 | }, { |
| 203 | const levelArr = ref([{ | 203 | value: '3', |
| 204 | value: '10', | 204 | text: '三级' |
| 205 | text: '十级' | 205 | }, { |
| 206 | }, { | 206 | value: '2', |
| 207 | value: '9', | 207 | text: '二级' |
| 208 | text: '九级' | 208 | }, { |
| 209 | }, { | 209 | value: '1', |
| 210 | value: '8', | 210 | text: '一级' |
| 211 | text: '八级' | 211 | }]) |
| 212 | }, { | 212 | |
| 213 | value: '7', | 213 | const range = ref([{ |
| 214 | text: '七级' | 214 | value: '1', |
| 215 | }, { | 215 | text: '是' |
| 216 | value: '6', | 216 | }, { |
| 217 | text: '六级' | 217 | value: '0', |
| 218 | }, { | 218 | text: '否' |
| 219 | value: '5', | 219 | }]) |
| 220 | text: '五级' | 220 | |
| 221 | }, { | 221 | let examId |
| 222 | value: '4', | 222 | |
| 223 | text: '四级' | 223 | onLoad(option => { |
| 224 | }, { | 224 | if (app.globalData.isLogin) { |
| 225 | value: '3', | 225 | initData(option) |
| 226 | text: '三级' | 226 | } else { |
| 227 | }, { | 227 | app.firstLoadCallback = () => { |
| 228 | value: '2', | 228 | initData(option) |
| 229 | text: '二级' | 229 | }; |
| 230 | }, { | 230 | } |
| 231 | value: '1', | 231 | }); |
| 232 | text: '一级' | 232 | |
| 233 | }]) | 233 | function initData(option) { |
| 234 | const range = ref([{ | 234 | form.value.memberName = app.globalData.memberInfo.name |
| 235 | value: '1', | 235 | form.value.applyTime = dayjs().format('YYYY-MM-DD') |
| 236 | text: '是' | 236 | |
| 237 | }, { | 237 | _.each(examinerForChoose, ec => { |
| 238 | value: '0', | 238 | form.value[`examiner_${ec}`] = null |
| 239 | text: '否' | 239 | }) |
| 240 | }]) | 240 | |
| 241 | let examId | 241 | if (option.examId) { |
| 242 | onLoad(option => { | 242 | examId = option.examId |
| 243 | console.log(option) | 243 | // 如果是编辑模式,从URL参数获取active |
| 244 | if (app.globalData.isLogin) { | 244 | if (option.step == '2') { |
| 245 | form.value.memberName = app.globalData.memberInfo.name | 245 | active.value = 1 |
| 246 | form.value.applyTime = dayjs().format('YYYY-MM-DD') | 246 | getDetail() |
| 247 | 247 | getChosedStudentList() | |
| 248 | _.each(examinerForChoose, ec => { | 248 | } else { |
| 249 | form.value[`examiner_${ec}`] = null | 249 | getDetail() |
| 250 | }) | 250 | } |
| 251 | if (option.examId) { | 251 | } |
| 252 | examId = option.examId | 252 | } |
| 253 | 253 | ||
| 254 | getDetail() | 254 | onShow(() => { |
| 255 | } | 255 | uni.$on('chosen', updateData) |
| 256 | } else { | 256 | }) |
| 257 | 257 | ||
| 258 | app.firstLoadCallback = () => { | 258 | function updateData(e) { |
| 259 | form.value.memberName = app.globalData.memberInfo.name | 259 | examinerArr.push(e.obj) |
| 260 | form.value.applyTime = dayjs().format('YYYY-MM-DD') | 260 | form.value[`examiner_${e.ec}`] = e.obj.name |
| 261 | 261 | } | |
| 262 | _.each(examinerForChoose, ec => { | 262 | |
| 263 | form.value[`examiner_${ec}`] = null | 263 | function getDetail() { |
| 264 | }) | 264 | api.getLevelApplyInfo(examId || form.value.examId).then(res => { |
| 265 | if (option.examId) { | 265 | const data = res.data |
| 266 | examId = option.examId | 266 | if (data.examiner) { |
| 267 | getDetail() | 267 | _.each(data.examiner.split(','), (id, i) => { |
| 268 | } | 268 | examinerArr[i] = { perId: id } |
| 269 | }; | 269 | }) |
| 270 | } | 270 | |
| 271 | }); | 271 | _.each(data.examinerNames.split(','), (name, i) => { |
| 272 | onShow(option => { | 272 | data[`examiner_${examinerForChoose[i]}`] = name |
| 273 | // if(!!option){ | 273 | if (examinerArr[i]) { |
| 274 | // console.log(option) | 274 | examinerArr[i].name = name |
| 275 | // } | 275 | } |
| 276 | uni.$on('chosen', updateData) | 276 | }) |
| 277 | }) | 277 | } |
| 278 | 278 | form.value = data | |
| 279 | function updateData(e) { | 279 | }) |
| 280 | examinerArr.push(e.obj) | 280 | } |
| 281 | form.value[`examiner_${e.ec}`] = e.obj.name | 281 | |
| 282 | } | 282 | function selectFN(ec) { |
| 283 | 283 | const chosen = [] | |
| 284 | function getDetail() { | 284 | _.each(examinerForChoose, ecKey => { |
| 285 | api.getLevelApplyInfo(examId).then(res => { | 285 | const key = `examiner_${ecKey}` |
| 286 | const data = res.data | 286 | if (form.value[key]) { |
| 287 | if (data.examiner) { | 287 | const examiner = _.find(examinerArr, (e) => { |
| 288 | _.each(data.examiner.split(','), (id) => { | 288 | return e.name == form.value[key] |
| 289 | examinerArr.push({ | 289 | }) |
| 290 | perId: id | 290 | if (examiner) { |
| 291 | }) | 291 | chosen.push(examiner) |
| 292 | }) | 292 | } |
| 293 | 293 | } | |
| 294 | _.each(data.examinerNames.split(','), (name, i) => { | 294 | }) |
| 295 | data[`examiner_${examinerForChoose[i]}`] = name | 295 | const arr = encodeURIComponent(JSON.stringify(chosen)) |
| 296 | examinerArr[i].name = name | 296 | let path = `/level/chooseExaminer?type=${form.value.type}&chosen=${arr}&ec=${ec}` |
| 297 | }) | 297 | uni.navigateTo({ |
| 298 | } | 298 | url: path |
| 299 | 299 | }); | |
| 300 | form.value = data | 300 | } |
| 301 | }) | 301 | |
| 302 | } | 302 | function submitForm(flag) { |
| 303 | 303 | form.value.status = '0' | |
| 304 | function selectFN(ec) { | 304 | const examinerIds = [] |
| 305 | const chosen = [] | 305 | const examinerNames = [] |
| 306 | const type = form.value.type | 306 | _.each(examinerForChoose, ec => { |
| 307 | _.each(examinerForChoose, ec => { | 307 | const key = `examiner_${ec}` |
| 308 | const key = `examiner_${ec}` | 308 | if (form.value[key]) { |
| 309 | if (form.value[key]) { | 309 | const examiner = _.find(examinerArr, (e) => { |
| 310 | const examiner = _.find(examinerArr, (e) => { | 310 | return e.name == form.value[key] |
| 311 | return e.name == form.value[key] | 311 | }) |
| 312 | }) | 312 | if (examiner) { |
| 313 | if (examiner) { | 313 | examinerIds.push(examiner.perId) |
| 314 | chosen.push(examiner) | 314 | examinerNames.push(examiner.name) |
| 315 | } | 315 | } |
| 316 | } | 316 | } |
| 317 | }) | 317 | }) |
| 318 | const arr = encodeURIComponent(JSON.stringify(chosen)) | 318 | |
| 319 | console.log(ec, chosen, type) | 319 | if (examinerIds.length > 0) { |
| 320 | let path = `/level/chooseExaminer?type=${type}&chosen=${arr}&ec=${ec}` | 320 | form.value.examiner = examinerIds.join(',') |
| 321 | uni.navigateTo({ | 321 | form.value.examinerNames = examinerNames.join(',') |
| 322 | url: path | 322 | } else { |
| 323 | }); | 323 | form.value.examiner = null |
| 324 | } | 324 | form.value.examinerNames = null |
| 325 | 325 | } | |
| 326 | function submitForm(flag) { | 326 | |
| 327 | form.value.status = '0' | 327 | // draftFlag: 0-保存 1-保存并下一步 |
| 328 | const examinerIds = [] | 328 | form.value.draftFlag = flag === 0 ? '1' : '0' |
| 329 | const examinerNames = [] | 329 | |
| 330 | _.each(examinerForChoose, ec => { | 330 | if (flag === 0) { |
| 331 | const key = `examiner_${ec}` | 331 | // 仅保存 |
| 332 | if (form.value[key]) { | 332 | save() |
| 333 | const examiner = _.find(examinerArr, (e) => { | 333 | } else { |
| 334 | return e.name == form.value[key] | 334 | // 保存并下一步 - 需校验 |
| 335 | }) | 335 | if (!form.value.applyTime) { |
| 336 | if (examiner) { | 336 | uni.showToast({ title: '请选择申请日期', icon: 'none' }) |
| 337 | examinerIds.push(examiner.perId) | 337 | return |
| 338 | examinerNames.push(examiner.name) | 338 | } |
| 339 | } | 339 | if (!form.value.startTime) { |
| 340 | } | 340 | uni.showToast({ title: '请选择考试开始时间', icon: 'none' }) |
| 341 | }) | 341 | return |
| 342 | 342 | } | |
| 343 | if (examinerIds.length > 0) { | 343 | if (!form.value.endTime) { |
| 344 | form.value.examiner = examinerIds.join(',') | 344 | uni.showToast({ title: '请选择考试结束时间', icon: 'none' }) |
| 345 | form.value.examinerNames = examinerNames.join(',') | 345 | return |
| 346 | } else { | 346 | } |
| 347 | form.value.examiner = null | 347 | if (!form.value.examLocation) { |
| 348 | form.value.examinerNames = null | 348 | uni.showToast({ title: '请输入考级地点', icon: 'none' }) |
| 349 | } | 349 | return |
| 350 | form.value.draftFlag = flag === 0 ? '1' : '0' | 350 | } |
| 351 | if (flag === 0) { | 351 | if (dayjs(form.value.startTime).valueOf() < dayjs(form.value.applyTime).valueOf()) { |
| 352 | save() | 352 | uni.showToast({ title: '考试开始时间应大于申请日期', icon: 'none' }) |
| 353 | } else { | 353 | return |
| 354 | if (dayjs(form.value.startTime).valueOf() < dayjs(form.value.applyTime).valueOf()) { | 354 | } |
| 355 | uni.showToast({ | 355 | if (dayjs(form.value.endTime).valueOf() <= dayjs(form.value.startTime).valueOf()) { |
| 356 | title: `考试开始时间应大于申请日期`, | 356 | uni.showToast({ title: '考试结束时间应大于考试开始时间', icon: 'none' }) |
| 357 | icon: 'none' | 357 | return |
| 358 | }) | 358 | } |
| 359 | return | 359 | if (examinerIds.length % 2 === 0) { |
| 360 | } | 360 | uni.showToast({ title: '录入的考官人数必须为单数', icon: 'none' }) |
| 361 | if (dayjs(form.value.endTime).valueOf() <= dayjs(form.value.startTime).valueOf()) { | 361 | return |
| 362 | uni.showToast({ | 362 | } |
| 363 | title: `考试结束时间应大于考试开始时间`, | 363 | |
| 364 | icon: 'none' | 364 | save().then(() => { |
| 365 | }) | 365 | active.value = 1 |
| 366 | return | 366 | getChosedStudentList() |
| 367 | } | 367 | if (form.value.examId) { |
| 368 | if (examinerIds.length % 2 === 0) { | 368 | api.getLevelApplyInfo(form.value.examId).then(res => { |
| 369 | uni.showToast({ | 369 | if (res.data.transcript) { |
| 370 | title: `录入的考官人数必须为单数`, | 370 | transcript.value = JSON.parse(res.data.transcript) |
| 371 | icon: 'none' | 371 | } |
| 372 | }) | 372 | }) |
| 373 | return | 373 | } |
| 374 | } | 374 | }) |
| 375 | save().then(() => { | 375 | } |
| 376 | // form.value.examId 下一步 | 376 | } |
| 377 | active.value = 1 | 377 | |
| 378 | getChosedStudentList() | 378 | function save() { |
| 379 | if (form.value.examId) { | 379 | if (form.value.examId) { |
| 380 | api.getLevelApplyInfo(form.value.examId).then(res => { | 380 | return api.updateLevelInfo(form.value).then(() => { |
| 381 | if (res.data.transcript) { | 381 | uni.showToast({ title: '保存成功', icon: 'none' }) |
| 382 | transcript.value = JSON.parse(res.data.transcript) | 382 | }) |
| 383 | } | 383 | } else { |
| 384 | }) | 384 | return api.addLevelInfo(form.value).then((res) => { |
| 385 | } | 385 | form.value.examId = res.data.examId |
| 386 | }) | 386 | form.value.name = res.data.name |
| 387 | } | 387 | uni.showToast({ title: '保存成功', icon: 'none' }) |
| 388 | } | 388 | }) |
| 389 | 389 | } | |
| 390 | function save() { | 390 | } |
| 391 | if (form.value.examId) { | 391 | |
| 392 | return api.updateLevelInfo(form.value).then(() => { | 392 | function prev() { |
| 393 | uni.showToast({ | 393 | active.value = 0 |
| 394 | title: `保存成功`, | 394 | } |
| 395 | icon: 'none' | 395 | |
| 396 | }) | 396 | function goChooseStudent() { |
| 397 | }) | 397 | uni.navigateTo({ |
| 398 | } else { | 398 | url: `/level/chooseStudent?examId=${form.value.examId}&memId=${memberInfo.memId}&examType=${form.value.type}` |
| 399 | return api.addLevelInfo(form.value).then((res) => { | 399 | }) |
| 400 | form.value.examId = res.data.examId | 400 | } |
| 401 | form.value.name = res.data.name | 401 | |
| 402 | uni.showToast({ | 402 | // 格式化日期时间 |
| 403 | title: `保存成功`, | 403 | function formatDateTime(dateStr) { |
| 404 | icon: 'none' | 404 | if (!dateStr) return '-' |
| 405 | }) | 405 | return dateStr.substring(0, 10) |
| 406 | }) | 406 | } |
| 407 | } | 407 | |
| 408 | } | 408 | function getChosedStudentList() { |
| 409 | 409 | var obj = { | |
| 410 | function chooseOnline() { | 410 | examId: form.value.examId |
| 411 | uni.showLoading({ | 411 | } |
| 412 | title: '加载中', | 412 | api.getStudentList(obj).then(res => { |
| 413 | icon: 'none' | 413 | _.each(res.rows, (d) => { |
| 414 | }) | 414 | if (d.levelOld) { |
| 415 | var obj = { | 415 | d.levelRecommend = (parseInt(d.levelOld) - 1) + '' |
| 416 | memId: memberInfo.memId, | 416 | if (d.levelRecommend === '0') { |
| 417 | examId: form.value.examId, | 417 | d.levelRecommend = '1' |
| 418 | examType: form.value.type, | 418 | } |
| 419 | name: studentQuery.value.name | 419 | } else { |
| 420 | } | 420 | d.levelRecommend = '9' |
| 421 | api.chooseStudentsList(obj).then(response => { | 421 | } |
| 422 | studentList.value = response.rows | 422 | |
| 423 | for (var s of studentList.value) { | 423 | if (!d.levelNew) { |
| 424 | s.checked = false | 424 | d.levelNew = d.levelRecommend |
| 425 | if (s.photo && s.photo.indexOf('http') == -1) { | 425 | } |
| 426 | s.photo = config.baseUrl_api + s.photo | 426 | |
| 427 | } | 427 | if (!d.isPass) { |
| 428 | 428 | d.isPass = '1' | |
| 429 | } | 429 | } |
| 430 | uni.hideLoading() | 430 | if (d.photo && d.photo.indexOf('http') == -1) { |
| 431 | choseStudent.value.open() | 431 | d.photo = config.baseUrl_api + d.photo |
| 432 | }) | 432 | } |
| 433 | } | 433 | }) |
| 434 | 434 | ||
| 435 | function checkThis(item) { | 435 | infoList.value = res.rows |
| 436 | if (item.checked) { | 436 | }).then(getTablePersonInfo) |
| 437 | item.checked = false | 437 | } |
| 438 | } else { | 438 | |
| 439 | item.checked = true | 439 | function getTablePersonInfo() { |
| 440 | } | 440 | const total = infoList.value.length |
| 441 | } | 441 | const levelArrData = [] |
| 442 | 442 | _.each(infoList.value, (d) => { | |
| 443 | function submitStudents() { | 443 | const temp = _.find(levelArrData, (l) => { |
| 444 | ids.value = [] | 444 | return l.level == d.levelNew |
| 445 | for (var s of studentList.value) { | 445 | }) |
| 446 | if (s.checked) { | 446 | if (temp) { |
| 447 | ids.value.push(s.perId) | 447 | temp.num++ |
| 448 | } | 448 | } else { |
| 449 | } | 449 | levelArrData.push({ |
| 450 | if (ids.value.length == 0) { | 450 | level: d.levelNew, |
| 451 | uni.showToast({ | 451 | num: 1 |
| 452 | title: '请选择考生', | 452 | }) |
| 453 | icon: 'none' | 453 | } |
| 454 | }) | 454 | }) |
| 455 | return | 455 | |
| 456 | } | 456 | tablePersonInfo.value = { |
| 457 | api.batchChoose({ | 457 | total: total, |
| 458 | examId: form.value.examId, | 458 | levelArr: _.sortBy(levelArrData, (l) => { |
| 459 | perIds: ids.value | 459 | return l.level |
| 460 | }).then(() => { | 460 | }) |
| 461 | getChosedStudentList() | 461 | } |
| 462 | choseStudent.value.close() | 462 | } |
| 463 | }) | 463 | |
| 464 | } | 464 | function szToHz(num) { |
| 465 | 465 | const hzArr = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'] | |
| 466 | function getChosedStudentList() { | 466 | return hzArr[parseInt(num)] |
| 467 | var obj = { | 467 | } |
| 468 | examId: form.value.examId | 468 | |
| 469 | } | 469 | let nowRow |
| 470 | api.getStudentList(obj).then(res => { | 470 | |
| 471 | _.each(res.rows, (d) => { | 471 | function changeLevelfather(row) { |
| 472 | if (d.levelOld) { | 472 | nowRow = row |
| 473 | d.levelRecommend = (parseInt(d.levelOld) - 1) + '' | 473 | api.jiDropDownBox({ |
| 474 | if (d.levelRecommend === '0') { | 474 | perId: row.perId |
| 475 | d.levelRecommend = '1' | 475 | }).then(res => { |
| 476 | } | 476 | levelArr.value = res.data |
| 477 | } else { | 477 | for (var l of levelArr.value) { |
| 478 | d.levelRecommend = '9' | 478 | l.text = l.name |
| 479 | } | 479 | l.disabled = !(l.status) |
| 480 | 480 | } | |
| 481 | if (!d.levelNew) { | 481 | }) |
| 482 | d.levelNew = d.levelRecommend | 482 | } |
| 483 | } | 483 | |
| 484 | 484 | function changeLevel(e) { | |
| 485 | if (!d.isPass) { | 485 | if (e == nowRow.levelOld) { |
| 486 | d.isPass = '1' | 486 | uni.showToast({ title: '考试级别重复,请重新选择!', icon: 'none' }) |
| 487 | } | 487 | nowRow.levelNew = nowRow.levelRecommend |
| 488 | if (d.photo && d.photo.indexOf('http') == -1) { | 488 | return |
| 489 | d.photo = config.baseUrl_api + d.photo | 489 | } |
| 490 | } | 490 | if (e !== nowRow.levelRecommend) { |
| 491 | }) | 491 | uni.showModal({ |
| 492 | 492 | title: '提示', | |
| 493 | infoList.value = res.rows | 493 | content: `建议考试级别为 "${szToHz(nowRow.levelRecommend)}级" ,确定要修改为${szToHz(e)}级吗?`, |
| 494 | 494 | success: function(res) { | |
| 495 | }).then(getTablePersonInfo) | 495 | if (res.confirm) { |
| 496 | } | 496 | getTablePersonInfo() |
| 497 | 497 | } else { | |
| 498 | function getTablePersonInfo() { | 498 | nowRow.levelNew = nowRow.levelRecommend |
| 499 | const total = infoList.value.length | 499 | } |
| 500 | const levelArr = [] | 500 | }, |
| 501 | _.each(infoList.value, (d) => { | 501 | fail: function(res) { |
| 502 | const temp = _.find(levelArr, (l) => { | 502 | nowRow.levelNew = nowRow.levelRecommend |
| 503 | return l.level == d.levelNew | 503 | } |
| 504 | }) | 504 | }) |
| 505 | if (temp) { | 505 | } |
| 506 | temp.num++ | 506 | } |
| 507 | } else { | 507 | |
| 508 | levelArr.push({ | 508 | function submitForm2(flag) { |
| 509 | level: d.levelNew, | 509 | // 循环校验考试级别 |
| 510 | num: 1 | 510 | for (var item of infoList.value) { |
| 511 | }) | 511 | if (item.levelNew == item.levelOld) { |
| 512 | } | 512 | uni.showToast({ title: `${item.realName}考试级别重复,请重新选择!`, icon: 'none' }) |
| 513 | }) | 513 | return |
| 514 | 514 | } | |
| 515 | tablePersonInfo.value = { | 515 | if (!item.levelNew) { |
| 516 | total: total, | 516 | uni.showToast({ title: `${item.realName}请选择考试级别!`, icon: 'none' }) |
| 517 | levelArr: _.sortBy(levelArr, (l) => { | 517 | return |
| 518 | return l.level | 518 | } |
| 519 | }) | 519 | } |
| 520 | } | 520 | |
| 521 | } | 521 | if (flag === 1) { |
| 522 | 522 | if (infoList.value.length == 0) { | |
| 523 | function szToHz(num) { | 523 | uni.showToast({ title: '请选择考生', icon: 'none' }) |
| 524 | const hzArr = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'] | 524 | return |
| 525 | return hzArr[parseInt(num)] | 525 | } |
| 526 | } | 526 | |
| 527 | 527 | uni.showModal({ | |
| 528 | let nowRow | 528 | title: '提示', |
| 529 | 529 | content: `请确认人员照片是否已更新?`, | |
| 530 | function changeLevelfather(row) { | 530 | success: function(res) { |
| 531 | nowRow = row | 531 | if (res.confirm) { |
| 532 | api.jiDropDownBox({ | 532 | saveStep2(flag).then(() => { |
| 533 | perId: row.perId | 533 | uni.showToast({ title: '提交成功', icon: 'none' }) |
| 534 | }).then(res => { | 534 | uni.navigateTo({ |
| 535 | levelArr.value = res.data | 535 | url: `/level/paymentDetail?examId=${form.value.examId}` |
| 536 | for (var l of levelArr.value) { | 536 | }) |
| 537 | l.text = l.name | 537 | }) |
| 538 | l.disabled = !(l.status) | 538 | } |
| 539 | } | 539 | } |
| 540 | }) | 540 | }) |
| 541 | } | 541 | } else { |
| 542 | 542 | saveStep2(flag).then(() => { | |
| 543 | 543 | uni.showToast({ title: '操作成功', icon: 'none' }) | |
| 544 | function changeLevel(e) { | 544 | }) |
| 545 | if (e == nowRow.levelOld) { | 545 | } |
| 546 | uni.showToast({ | 546 | } |
| 547 | title: `考试级别重复,请重新选择!`, | 547 | |
| 548 | icon: 'none' | 548 | function saveStep2(flag) { |
| 549 | }) | 549 | const data = _.map(infoList.value, (d) => { |
| 550 | nowRow.levelNew = nowRow.levelRecommend | 550 | return { |
| 551 | return | 551 | id: d.id, |
| 552 | } | 552 | levelNew: d.levelNew, |
| 553 | if (e !== nowRow.levelRecommend) { | 553 | isPass: d.isPass |
| 554 | uni.showModal({ | 554 | } |
| 555 | title: '提示', | 555 | }) |
| 556 | content: `建议考试级别为 "${szToHz(nowRow.levelRecommend)}级" ,确定要修改为${szToHz(e)}级吗?`, | 556 | return api.editLevel({ |
| 557 | success: function(res) { | 557 | examId: form.value.examId, |
| 558 | if (res.confirm) { | 558 | personInfo: JSON.stringify(data), |
| 559 | getTablePersonInfo() | 559 | transcript: form.value.transcript, |
| 560 | }else{ | 560 | status: flag |
| 561 | nowRow.levelNew = nowRow.levelRecommend | 561 | }) |
| 562 | } | 562 | } |
| 563 | }, | 563 | |
| 564 | fail: function(res) { | 564 | function handleDelete(row) { |
| 565 | nowRow.levelNew = nowRow.levelRecommend | 565 | uni.showModal({ |
| 566 | } | 566 | title: '提示', |
| 567 | }) | 567 | content: `确定删除${row.realName}?`, |
| 568 | } | 568 | success: function(res) { |
| 569 | } | 569 | if (res.confirm) { |
| 570 | 570 | api.dellevelPerson(row.id).then(() => { | |
| 571 | function submitForm2(flag) { | 571 | uni.showToast({ title: '操作成功', icon: 'none' }) |
| 572 | //循环infoList.value 如果item.levelNew == item.levelOld 提示错误 | 572 | getChosedStudentList() |
| 573 | for (var item of infoList.value) { | 573 | }) |
| 574 | if (item.levelNew == item.levelOld) { | 574 | } |
| 575 | uni.showToast({ | 575 | } |
| 576 | title: `${item.realName}考试级别重复,请重新选择!`, | 576 | }) |
| 577 | icon: 'none' | 577 | } |
| 578 | }) | 578 | </script> |
| 579 | return | 579 | <style lang="scss" scoped> |
| 580 | } | 580 | .add-apply-page { |
| 581 | if (!item.levelNew) { | 581 | min-height: 100vh; |
| 582 | uni.showToast({ | 582 | background: #f5f5f5; |
| 583 | title: `${item.realName}请选择考试级别!`, | 583 | padding-bottom: 120rpx; |
| 584 | icon: 'none' | 584 | } |
| 585 | }) | 585 | |
| 586 | return | 586 | /* 顶部步骤条 */ |
| 587 | } | 587 | .steps-bar { |
| 588 | } | 588 | display: flex; |
| 589 | if (flag === 1) { | 589 | align-items: center; |
| 590 | if (infoList.value.length == 0) { | 590 | justify-content: center; |
| 591 | uni.showToast({ | 591 | padding: 15rpx 60rpx; |
| 592 | title: '请选择考生', | 592 | background: #fff; |
| 593 | icon: 'none' | 593 | margin-top: 20rpx; |
| 594 | }) | 594 | |
| 595 | return | 595 | .step-item { |
| 596 | } | 596 | display: flex; |
| 597 | 597 | align-items: center; | |
| 598 | // if (!form.value.transcript) { | 598 | |
| 599 | // uni.showToast({ | 599 | .step-circle { |
| 600 | // title: '请上传成绩单', | 600 | width: 48rpx; |
| 601 | // icon: 'none' | 601 | height: 48rpx; |
| 602 | // }) | 602 | border-radius: 50%; |
| 603 | // return | 603 | background: #fff; |
| 604 | // } | 604 | border: 2rpx solid #666; |
| 605 | 605 | color: #666; | |
| 606 | uni.showModal({ | 606 | font-size: 24rpx; |
| 607 | title: '提示', | 607 | display: flex; |
| 608 | content: `请确认人员照片是否已更新?`, | 608 | align-items: center; |
| 609 | success: function(res) { | 609 | justify-content: center; |
| 610 | if (res.confirm) { | 610 | margin-right: 10rpx; |
| 611 | console.log('用户点击确定'); | 611 | transition: all 0.3s; |
| 612 | saveStep2(flag).then(Response => { | 612 | } |
| 613 | if (flag === 1) { | 613 | |
| 614 | uni.showToast({ | 614 | .step-text { |
| 615 | title: `提交成功` | 615 | font-size: 24rpx; |
| 616 | }) | 616 | color: #666; |
| 617 | uni.navigateTo({ | 617 | transition: all 0.3s; |
| 618 | url: `/level/paymentDetail?examId=${form.value.examId}` | 618 | } |
| 619 | }) | 619 | |
| 620 | } else { | 620 | &.active .step-circle { |
| 621 | uni.showToast({ | 621 | background: #fff; |
| 622 | title: `操作成功` | 622 | color: #AD181F; |
| 623 | }) | 623 | border-color: #AD181F; |
| 624 | } | 624 | } |
| 625 | }) | 625 | |
| 626 | } else if (res.cancel) { | 626 | &.active .step-text { |
| 627 | console.log('用户点击取消'); | 627 | color: #AD181F; |
| 628 | } | 628 | font-weight: 600; |
| 629 | 629 | } | |
| 630 | } | 630 | |
| 631 | }) | 631 | &.current .step-circle { |
| 632 | } else { | 632 | background: #AD181F; |
| 633 | saveStep2(flag).then(res => { | 633 | color: #fff; |
| 634 | uni.showToast({ | 634 | box-shadow: 0 4rpx 12rpx rgba(173, 24, 31, 0.3); |
| 635 | title: `操作成功` | 635 | } |
| 636 | }) | 636 | |
| 637 | }) | 637 | &.current .step-text { |
| 638 | } | 638 | color: #AD181F; |
| 639 | } | 639 | font-weight: 600; |
| 640 | 640 | } | |
| 641 | function saveStep2(flag) { | 641 | } |
| 642 | const data = _.map(infoList.value, (d) => { | 642 | |
| 643 | return { | 643 | .step-line { |
| 644 | id: d.id, | 644 | width: 120rpx; |
| 645 | levelNew: d.levelNew, | 645 | height: 4rpx; |
| 646 | // score: d.score, | 646 | background: #e0e0e0; |
| 647 | isPass: d.isPass | 647 | margin: 0 20rpx; |
| 648 | } | 648 | transition: all 0.3s; |
| 649 | }) | 649 | |
| 650 | return api.editLevel({ | 650 | &.active { |
| 651 | examId: form.value.examId, | 651 | background: #AD181F; |
| 652 | personInfo: JSON.stringify(data), | 652 | } |
| 653 | transcript: form.value.transcript, | 653 | } |
| 654 | status: flag | 654 | } |
| 655 | }) | 655 | |
| 656 | } | 656 | /* 步骤2样式 */ |
| 657 | 657 | .step2-content { | |
| 658 | function handleUpdate() { | 658 | padding: 0 20rpx; |
| 659 | UpPop.value.open() | 659 | margin-top: 20rpx; |
| 660 | } | 660 | } |
| 661 | let selectFileValue = {} | 661 | |
| 662 | 662 | /* 考级信息卡片 */ | |
| 663 | function selectFile(e) { | 663 | .exam-info-card { |
| 664 | let file = e.tempFiles[0] | 664 | background: #fff; |
| 665 | if (!file) { | 665 | border-radius: 16rpx; |
| 666 | return | 666 | margin-bottom: 20rpx; |
| 667 | } | 667 | overflow: hidden; |
| 668 | for (const n in e.tempFiles) { | 668 | box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05); |
| 669 | api.uploadFileList(e.tempFilePaths[n]).then(data => { | 669 | |
| 670 | selectFileValue = { | 670 | .card-header { |
| 671 | url: data, | 671 | padding: 24rpx 30rpx; |
| 672 | name: e.tempFiles[n].name, | 672 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); |
| 673 | extname: e.tempFiles[n].extname | 673 | |
| 674 | } | 674 | .card-title { |
| 675 | 675 | font-size: 28rpx; | |
| 676 | transcript.value.push(selectFileValue) | 676 | font-weight: 600; |
| 677 | }); | 677 | color: #fff; |
| 678 | } | 678 | } |
| 679 | 679 | } | |
| 680 | } | 680 | |
| 681 | 681 | .info-grid { | |
| 682 | function fileProgress(e) { | 682 | display: flex; |
| 683 | console.log('progress:' + e) | 683 | flex-wrap: wrap; |
| 684 | } | 684 | padding: 20rpx 0; |
| 685 | 685 | ||
| 686 | function delSupplementFile(e) { | 686 | .info-item { |
| 687 | transcript.value = _.remove(transcript.value, function(n) { | 687 | width: 100%; |
| 688 | return n.name != e.tempFile.name; | 688 | padding: 12rpx 30rpx; |
| 689 | }); | 689 | box-sizing: border-box; |
| 690 | } | 690 | display: flex; |
| 691 | 691 | ||
| 692 | function uploadSure() { | 692 | .info-label { |
| 693 | // 上传确定 | 693 | display: block; |
| 694 | if (transcript.value.length == 0) { | 694 | font-size: 24rpx; |
| 695 | uni.showToast({ | 695 | color: #666; |
| 696 | title: `请上传成绩单`, | 696 | margin-bottom: 8rpx; |
| 697 | icon: 'error' | 697 | |
| 698 | }) | 698 | } |
| 699 | return | 699 | |
| 700 | } | 700 | .info-value { |
| 701 | 701 | display: block; | |
| 702 | form.value.transcript = JSON.stringify(_.map(transcript.value, (t) => { | 702 | font-size: 26rpx; |
| 703 | return { | 703 | color: #333; |
| 704 | name: t.name, | 704 | font-weight: 500; |
| 705 | url: t.url | 705 | margin-left: 20rpx; |
| 706 | } | 706 | } |
| 707 | })) | 707 | } |
| 708 | UpPop.value.close() | 708 | } |
| 709 | } | 709 | } |
| 710 | 710 | ||
| 711 | function handleDelete(row) { | 711 | /* 操作栏(统计+添加按钮) */ |
| 712 | uni.showModal({ | 712 | .action-bar { |
| 713 | title: '提示', | 713 | display: flex; |
| 714 | content: `确定删除${row.realName}?`, | 714 | justify-content: space-between; |
| 715 | success: function(res) { | 715 | align-items: center; |
| 716 | if (res.confirm) { | 716 | padding: 20rpx 24rpx; |
| 717 | api.dellevelPerson(row.id).then(res => { | 717 | background: #fff; |
| 718 | uni.showToast({ | 718 | border-radius: 16rpx; |
| 719 | title: `操作成功` | 719 | margin: 20rpx 0; |
| 720 | }) | 720 | |
| 721 | getChosedStudentList() | 721 | .stat-info { |
| 722 | }) | 722 | display: flex; |
| 723 | } | 723 | align-items: center; |
| 724 | } | 724 | // justify-self: unset; |
| 725 | }) | 725 | .stat-total { |
| 726 | } | 726 | font-size: 28rpx; |
| 727 | </script> | 727 | font-weight: 600; |
| 728 | 728 | color: #333; | |
| 729 | <style lang="scss" scoped> | 729 | } |
| 730 | :deep(.uni-progress-bar) { | 730 | |
| 731 | display: none; | 731 | .level-tags { |
| 732 | } | 732 | display: flex; |
| 733 | 733 | flex-wrap: wrap; | |
| 734 | .item { | 734 | margin-left: 10rpx; |
| 735 | .del { | 735 | gap: 10rpx; |
| 736 | color: #AD181F; | 736 | |
| 737 | position: absolute; | 737 | .level-tag { |
| 738 | right: 30rpx; | 738 | padding: 4rpx 12rpx; |
| 739 | font-size: 28rpx; | 739 | background: #FFF5F5; |
| 740 | } | 740 | border: 1rpx solid #FFDDDD; |
| 741 | } | 741 | border-radius: 6rpx; |
| 742 | 742 | font-size: 24rpx; | |
| 743 | .wBox { | 743 | color: #AD181F; |
| 744 | width: 700rpx; | 744 | } |
| 745 | padding: 30rpx; | 745 | } |
| 746 | margin: 20rpx auto; | 746 | } |
| 747 | background: #FFFFFF; | 747 | |
| 748 | box-shadow: 0rpx 12rpx 116rpx 0rpx rgba(196, 203, 214, 0.1); | 748 | |
| 749 | border-radius: 15rpx; | 749 | } |
| 750 | } | 750 | .btn-add-student { |
| 751 | 751 | display: flex; | |
| 752 | :deep(.uni-forms-item__inner) { | 752 | align-items: center; |
| 753 | padding-bottom: 20rpx; | 753 | justify-content: center; |
| 754 | } | 754 | padding: 0 30rpx; |
| 755 | 755 | height: 64rpx; | |
| 756 | .popBody { | 756 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); |
| 757 | padding: 40rpx 30rpx; | 757 | border-radius: 32rpx; |
| 758 | } | 758 | font-size: 26rpx; |
| 759 | 759 | color: #fff; | |
| 760 | .maskbox { | 760 | box-shadow: 0 4rpx 16rpx rgba(173, 24, 31, 0.3); |
| 761 | position: relative; | 761 | } |
| 762 | 762 | /* 考生列表(核心优化) */ | |
| 763 | .mask { | 763 | .student-list { |
| 764 | position: absolute; | 764 | .student-card { |
| 765 | width: calc(100% - 34px); | 765 | position: relative; |
| 766 | height: 100%; | 766 | // display: flex; |
| 767 | z-index: 10; | 767 | |
| 768 | background-color: red; | 768 | // align-items: center; |
| 769 | opacity: 0; | 769 | // justify-content: space-between; |
| 770 | } | 770 | padding: 24rpx; |
| 771 | } | 771 | background: #fff; |
| 772 | 772 | border-radius: 16rpx; | |
| 773 | :deep(.file-picker__progress) { | 773 | margin-bottom: 20rpx; |
| 774 | opacity: 0; | 774 | box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04); |
| 775 | } | 775 | |
| 776 | </style> | 776 | /* 左侧:头像+考生信息 */ |
| 777 | .card-left { | ||
| 778 | display: flex; | ||
| 779 | align-items: center; | ||
| 780 | flex: 1; | ||
| 781 | |||
| 782 | .avatar { | ||
| 783 | width: 80rpx; | ||
| 784 | height: 80rpx; | ||
| 785 | border-radius: 50%; | ||
| 786 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); | ||
| 787 | display: flex; | ||
| 788 | align-items: center; | ||
| 789 | justify-content: center; | ||
| 790 | margin-right: 20rpx; | ||
| 791 | overflow: hidden; | ||
| 792 | |||
| 793 | .avatar-text { | ||
| 794 | font-size: 32rpx; | ||
| 795 | color: #fff; | ||
| 796 | font-weight: 600; | ||
| 797 | } | ||
| 798 | |||
| 799 | image { | ||
| 800 | width: 100%; | ||
| 801 | height: 100%; | ||
| 802 | } | ||
| 803 | } | ||
| 804 | |||
| 805 | .student-info { | ||
| 806 | .student-name { | ||
| 807 | font-size: 28rpx; | ||
| 808 | font-weight: 600; | ||
| 809 | color: #333; | ||
| 810 | margin-bottom: 8rpx; | ||
| 811 | |||
| 812 | .per-code { | ||
| 813 | font-size: 24rpx; | ||
| 814 | color: #666; | ||
| 815 | font-weight: normal; | ||
| 816 | margin-left: 12rpx; | ||
| 817 | } | ||
| 818 | } | ||
| 819 | |||
| 820 | .student-idcard { | ||
| 821 | font-size: 24rpx; | ||
| 822 | color: #666; | ||
| 823 | } | ||
| 824 | } | ||
| 825 | } | ||
| 826 | |||
| 827 | /* 右侧:原级别/考试级别/是否通过(垂直布局,完美对齐) */ | ||
| 828 | .card-right { | ||
| 829 | display: flex; | ||
| 830 | justify-content: space-between; | ||
| 831 | // padding:0 30px; | ||
| 832 | margin-top: 20rpx; | ||
| 833 | margin-left:100rpx; | ||
| 834 | // flex-direction: column; | ||
| 835 | // align-items: flex-end; | ||
| 836 | // gap: 16rpx; | ||
| 837 | |||
| 838 | .level-item { | ||
| 839 | display: flex; | ||
| 840 | flex-direction: column; | ||
| 841 | align-items: flex-end; | ||
| 842 | |||
| 843 | .level-label { | ||
| 844 | font-size: 24rpx; | ||
| 845 | color: #666; | ||
| 846 | margin-bottom: 6rpx; | ||
| 847 | } | ||
| 848 | |||
| 849 | .level-value { | ||
| 850 | font-size: 28rpx; | ||
| 851 | color: #333; | ||
| 852 | font-weight: 500; | ||
| 853 | } | ||
| 854 | |||
| 855 | .select-wrapper { | ||
| 856 | width: 120rpx; | ||
| 857 | } | ||
| 858 | } | ||
| 859 | } | ||
| 860 | |||
| 861 | /* 删除按钮 */ | ||
| 862 | .delete-btn { | ||
| 863 | position: absolute; | ||
| 864 | top: 16rpx; | ||
| 865 | right: 16rpx; | ||
| 866 | padding: 8rpx; | ||
| 867 | } | ||
| 868 | } | ||
| 869 | |||
| 870 | /* 空状态 */ | ||
| 871 | .empty-state { | ||
| 872 | display: flex; | ||
| 873 | flex-direction: column; | ||
| 874 | align-items: center; | ||
| 875 | justify-content: center; | ||
| 876 | padding: 80rpx 0; | ||
| 877 | background: #fff; | ||
| 878 | border-radius: 16rpx; | ||
| 879 | |||
| 880 | image { | ||
| 881 | width: 240rpx; | ||
| 882 | height: 240rpx; | ||
| 883 | margin-bottom: 20rpx; | ||
| 884 | } | ||
| 885 | |||
| 886 | text { | ||
| 887 | font-size: 26rpx; | ||
| 888 | color: #666; | ||
| 889 | } | ||
| 890 | } | ||
| 891 | } | ||
| 892 | |||
| 893 | .wBox { | ||
| 894 | width: 700rpx; | ||
| 895 | padding: 30rpx; | ||
| 896 | margin: 20rpx auto; | ||
| 897 | background: #FFFFFF; | ||
| 898 | box-shadow: 0rpx 12rpx 116rpx 0rpx rgba(196, 203, 214, 0.1); | ||
| 899 | border-radius: 15rpx; | ||
| 900 | } | ||
| 901 | |||
| 902 | :deep(.uni-forms-item__inner) { | ||
| 903 | padding-bottom: 20rpx; | ||
| 904 | } | ||
| 905 | |||
| 906 | .maskbox { | ||
| 907 | position: relative; | ||
| 908 | |||
| 909 | .mask { | ||
| 910 | position: absolute; | ||
| 911 | width: calc(100% - 34px); | ||
| 912 | height: 100%; | ||
| 913 | z-index: 10; | ||
| 914 | background-color: red; | ||
| 915 | opacity: 0; | ||
| 916 | } | ||
| 917 | } | ||
| 918 | |||
| 919 | /* 底部按钮 */ | ||
| 920 | .fixedBottom { | ||
| 921 | position: fixed; | ||
| 922 | bottom: 0; | ||
| 923 | left: 0; | ||
| 924 | right: 0; | ||
| 925 | display: flex; | ||
| 926 | justify-content: space-around; | ||
| 927 | align-items: center; | ||
| 928 | padding: 20rpx 0; | ||
| 929 | background: #fff; | ||
| 930 | border-top: 1rpx solid #f0f0f0; | ||
| 931 | z-index: 999; | ||
| 932 | |||
| 933 | .btn-red { | ||
| 934 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); | ||
| 935 | color: #fff; | ||
| 936 | border: none; | ||
| 937 | border-radius: 32rpx; | ||
| 938 | height: 72rpx; | ||
| 939 | font-size: 28rpx; | ||
| 940 | font-weight: 600; | ||
| 941 | } | ||
| 942 | |||
| 943 | .btn-red-kx { | ||
| 944 | background: #fff; | ||
| 945 | color: #AD181F; | ||
| 946 | border: 2rpx solid #AD181F; | ||
| 947 | border-radius: 32rpx; | ||
| 948 | height: 72rpx; | ||
| 949 | font-size: 28rpx; | ||
| 950 | font-weight: 600; | ||
| 951 | } | ||
| 952 | } | ||
| 953 | </style> | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -11,24 +11,27 @@ | ... | @@ -11,24 +11,27 @@ |
| 11 | <view class="indexboxre"> | 11 | <view class="indexboxre"> |
| 12 | <view class="userlist"> | 12 | <view class="userlist"> |
| 13 | <view class="item" v-for="(n,index) in list" :key="index"> | 13 | <view class="item" v-for="(n,index) in list" :key="index"> |
| 14 | <view> | 14 | <view class="item-content"> |
| 15 | <view class="name">{{n.perName}}</view> | 15 | <view class="name-row"> |
| 16 | <view class="name">{{n.perName}}</view> | ||
| 17 | <view class="expired-tag" v-if="n.canChoose != 1"> | ||
| 18 | <text class="expired-text">已过期</text> | ||
| 19 | </view> | ||
| 20 | </view> | ||
| 16 | <view class="date">会员号:{{n.perCode||'-'}}</view> | 21 | <view class="date">会员号:{{n.perCode||'-'}}</view> |
| 17 | <view class="date">有效日期:{{n.roleInfo && n.roleInfo.validTime ? n.roleInfo.validTime : '-'}}</view> | 22 | <view class="date">有效日期:{{ formatDate(n.roleInfo && n.roleInfo.validTime ? n.roleInfo.validTime : '-') }}</view> |
| 18 | <view class="date">注册地:{{n.memName||'-'}}</view> | 23 | <view class="date">注册地:{{n.memName||'-'}}</view> |
| 19 | <view class="date" :class="{'text-danger': n.canChoose != 1}"> | ||
| 20 | 状态:{{ n.canChoose == 1 ? '正常' : '资质已过期' }} | ||
| 21 | </view> | ||
| 22 | </view> | 24 | </view> |
| 23 | <view class="status"> | 25 | <view class="status"> |
| 24 | <text v-if="isChosen(n)" class="text-gray">已选</text> | 26 | <text v-if="isChosen(n)" class="text-gray">已选</text> |
| 25 | <text v-else class="text-primary" @click="handleChoose(n)">选择</text> | 27 | <!-- <text v-else-if="n.canChoose != 1" class="text-gray">不可选</text> --> |
| 28 | <text v-if="n.canChoose == 1" class="text-primary" @click="handleChoose(n)">选择</text> | ||
| 26 | </view> | 29 | </view> |
| 27 | </view> | 30 | </view> |
| 28 | </view> | 31 | </view> |
| 29 | <view class="nodata" v-if="list.length==0 && !loading"> | 32 | <view class="empty" v-if="list.length==0 && !loading"> |
| 30 | <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> | 33 | <image class="empty-img" mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> |
| 31 | <text>暂无考官数据</text> | 34 | <text class="empty-text">暂无考官数据</text> |
| 32 | </view> | 35 | </view> |
| 33 | </view> | 36 | </view> |
| 34 | 37 | ||
| ... | @@ -132,6 +135,16 @@ | ... | @@ -132,6 +135,16 @@ |
| 132 | return chosen.some(c => c.perId == n.perId) | 135 | return chosen.some(c => c.perId == n.perId) |
| 133 | } | 136 | } |
| 134 | 137 | ||
| 138 | // 格式化日期,去掉时间部分 | ||
| 139 | function formatDate(dateStr) { | ||
| 140 | if (!dateStr || dateStr === '-') return '-' | ||
| 141 | // 如果是完整日期时间格式,截取日期部分 | ||
| 142 | if (dateStr.length > 10) { | ||
| 143 | return dateStr.substring(0, 10) | ||
| 144 | } | ||
| 145 | return dateStr | ||
| 146 | } | ||
| 147 | |||
| 135 | function handleChoose(row) { | 148 | function handleChoose(row) { |
| 136 | if (row.canChoose != 1) { | 149 | if (row.canChoose != 1) { |
| 137 | uni.showToast({ | 150 | uni.showToast({ |
| ... | @@ -252,10 +265,33 @@ | ... | @@ -252,10 +265,33 @@ |
| 252 | background: #fff; | 265 | background: #fff; |
| 253 | border-radius: 10rpx; | 266 | border-radius: 10rpx; |
| 254 | 267 | ||
| 268 | .item-content { | ||
| 269 | flex: 1; | ||
| 270 | } | ||
| 271 | |||
| 272 | .name-row { | ||
| 273 | display: flex; | ||
| 274 | align-items: center; | ||
| 275 | margin-bottom: 10rpx; | ||
| 276 | justify-content: space-between; | ||
| 277 | } | ||
| 278 | |||
| 255 | .name { | 279 | .name { |
| 256 | font-size: 32rpx; | 280 | font-size: 32rpx; |
| 257 | font-weight: bold; | 281 | font-weight: bold; |
| 258 | margin-bottom: 10rpx; | 282 | } |
| 283 | |||
| 284 | .expired-tag { | ||
| 285 | // margin-left: 15rpx; | ||
| 286 | // padding: 0 12rpx; | ||
| 287 | // background: #fff0f0; | ||
| 288 | // border: 1px solid #ffcccc; | ||
| 289 | // border-radius: 6rpx; | ||
| 290 | } | ||
| 291 | |||
| 292 | .expired-text { | ||
| 293 | font-size: 22rpx; | ||
| 294 | color: #dd524d; | ||
| 259 | } | 295 | } |
| 260 | 296 | ||
| 261 | .date { | 297 | .date { | ... | ... |
level/chooseStudent.vue
0 → 100644
| 1 | <template> | ||
| 2 | <view class="choose-student-page"> | ||
| 3 | <!-- 顶部搜索栏 --> | ||
| 4 | <view class="search-header"> | ||
| 5 | <view class="search-box"> | ||
| 6 | <uni-icons type="search" size="18" color="#999"></uni-icons> | ||
| 7 | <input | ||
| 8 | class="search-input" | ||
| 9 | v-model="searchName" | ||
| 10 | placeholder="搜索考生姓名" | ||
| 11 | @confirm="searchStudents" | ||
| 12 | /> | ||
| 13 | <uni-icons v-if="searchName" type="clear" size="16" color="#999" @click="clearSearch"></uni-icons> | ||
| 14 | </view> | ||
| 15 | <text class="cancel-btn" @click="goBack">取消</text> | ||
| 16 | </view> | ||
| 17 | |||
| 18 | <!-- 已选考生 --> | ||
| 19 | <view class="selected-section" v-if="selectedList.length > 0"> | ||
| 20 | <view class="section-header"> | ||
| 21 | <text class="section-title">已选考生</text> | ||
| 22 | <text class="section-count">{{selectedList.length}}人</text> | ||
| 23 | </view> | ||
| 24 | <scroll-view class="selected-scroll" scroll-x> | ||
| 25 | <view class="selected-item" v-for="(item, index) in selectedList" :key="index"> | ||
| 26 | <view class="avatar-small"> | ||
| 27 | <image v-if="item.photo" :src="item.photo" mode="aspectFill"></image> | ||
| 28 | <text v-else>{{(item.name || '').slice(0,1)}}</text> | ||
| 29 | </view> | ||
| 30 | <text class="name-small">{{item.name}}</text> | ||
| 31 | <view class="remove-btn" @click="removeSelected(index)"> | ||
| 32 | <uni-icons type="closeempty" size="12" color="#fff"></uni-icons> | ||
| 33 | </view> | ||
| 34 | </view> | ||
| 35 | </scroll-view> | ||
| 36 | </view> | ||
| 37 | |||
| 38 | <!-- 考生列表 --> | ||
| 39 | <scroll-view class="student-scroll" scroll-y @scrolltolower="loadMore"> | ||
| 40 | <view class="student-list"> | ||
| 41 | <view class="student-card" v-for="(item, index) in studentList" :key="index" @click="toggleSelect(item)"> | ||
| 42 | <view class="checkbox"> | ||
| 43 | <image v-if="item.checked" src="/static/member/dx_dwn.png" mode="aspectFit"></image> | ||
| 44 | <view v-else class="checkbox-empty"></view> | ||
| 45 | </view> | ||
| 46 | <view class="avatar"> | ||
| 47 | <image v-if="item.photo" :src="item.photo" mode="aspectFill"></image> | ||
| 48 | <image v-else :src="config.baseUrl_api + '/fs/static/tx@2x.png'" | ||
| 49 | mode="aspectFill"> | ||
| 50 | </image> | ||
| 51 | <!-- <text v-else class="avatar-text">{{(item.name || '').slice(0,1)}}</text> --> | ||
| 52 | </view> | ||
| 53 | <view class="student-info"> | ||
| 54 | <view class="student-name"> | ||
| 55 | {{item.name}} | ||
| 56 | <text class="per-code">{{item.perCode}}</text> | ||
| 57 | </view> | ||
| 58 | <view class="student-detail"> | ||
| 59 | <text class="level-info">级位:{{ formatLevel(item.levelJi) }}</text> | ||
| 60 | <text class="validity">到期:{{ formatDate(item.validityDate) }}</text> | ||
| 61 | </view> | ||
| 62 | </view> | ||
| 63 | </view> | ||
| 64 | |||
| 65 | <!-- 加载状态 --> | ||
| 66 | <view class="loading-more" v-if="loading"> | ||
| 67 | <text>加载中...</text> | ||
| 68 | </view> | ||
| 69 | <view class="no-more" v-if="!loading && noMore && studentList.length > 0"> | ||
| 70 | <text>没有更多了</text> | ||
| 71 | </view> | ||
| 72 | |||
| 73 | <!-- 空状态 --> | ||
| 74 | <view class="empty" v-if="!loading && studentList.length === 0"> | ||
| 75 | <image class="empty-img" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> | ||
| 76 | <text class="empty-text">暂无考生信息</text> | ||
| 77 | </view> | ||
| 78 | </view> | ||
| 79 | </scroll-view> | ||
| 80 | |||
| 81 | <!-- 底部确定按钮 --> | ||
| 82 | <view class="fixedBottom"> | ||
| 83 | <view class="bottom-info"> | ||
| 84 | <text class="info-text">已选择 <text class="count">{{selectedList.length}}</text> 人</text> | ||
| 85 | </view> | ||
| 86 | <view style="text-align:right"> | ||
| 87 | <button class="btn-confirm" @click="confirmSelect">确定添加</button> | ||
| 88 | </view> | ||
| 89 | |||
| 90 | </view> | ||
| 91 | </view> | ||
| 92 | </template> | ||
| 93 | |||
| 94 | <script setup> | ||
| 95 | import * as api from '@/common/api.js' | ||
| 96 | import config from '@/config.js' | ||
| 97 | import {ref} from 'vue' | ||
| 98 | import { onLoad } from '@dcloudio/uni-app' | ||
| 99 | |||
| 100 | let examId = '' | ||
| 101 | let memId = '' | ||
| 102 | let examType = '' | ||
| 103 | |||
| 104 | const searchName = ref('') | ||
| 105 | const studentList = ref([]) | ||
| 106 | const selectedList = ref([]) | ||
| 107 | const loading = ref(false) | ||
| 108 | const noMore = ref(false) | ||
| 109 | const pageNum = ref(1) | ||
| 110 | const pageSize = 20 | ||
| 111 | |||
| 112 | onLoad((option) => { | ||
| 113 | examId = option.examId || '' | ||
| 114 | memId = option.memId || '' | ||
| 115 | examType = option.examType || '1' | ||
| 116 | getStudentList() | ||
| 117 | }) | ||
| 118 | |||
| 119 | function getStudentList(isMore = false) { | ||
| 120 | if (loading.value) return | ||
| 121 | loading.value = true | ||
| 122 | |||
| 123 | api.chooseStudentsList({ | ||
| 124 | memId: memId, | ||
| 125 | examId: examId, | ||
| 126 | examType: examType, | ||
| 127 | name: searchName.value | ||
| 128 | }).then(res => { | ||
| 129 | const rows = res.rows || [] | ||
| 130 | rows.forEach(item => { | ||
| 131 | item.checked = selectedList.value.some(s => s.perId === item.perId) | ||
| 132 | if (item.photo && item.photo.indexOf('http') == -1) { | ||
| 133 | item.photo = config.baseUrl_api + item.photo | ||
| 134 | } | ||
| 135 | }) | ||
| 136 | |||
| 137 | if (isMore) { | ||
| 138 | studentList.value = [...studentList.value, ...rows] | ||
| 139 | } else { | ||
| 140 | studentList.value = rows | ||
| 141 | } | ||
| 142 | |||
| 143 | noMore.value = rows.length < pageSize | ||
| 144 | pageNum.value++ | ||
| 145 | loading.value = false | ||
| 146 | }).catch(() => { | ||
| 147 | loading.value = false | ||
| 148 | }) | ||
| 149 | } | ||
| 150 | |||
| 151 | function loadMore() { | ||
| 152 | if (!noMore.value) { | ||
| 153 | getStudentList(true) | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | function searchStudents() { | ||
| 158 | pageNum.value = 1 | ||
| 159 | noMore.value = false | ||
| 160 | getStudentList() | ||
| 161 | } | ||
| 162 | |||
| 163 | function clearSearch() { | ||
| 164 | searchName.value = '' | ||
| 165 | searchStudents() | ||
| 166 | } | ||
| 167 | |||
| 168 | function toggleSelect(item) { | ||
| 169 | item.checked = !item.checked | ||
| 170 | if (item.checked) { | ||
| 171 | selectedList.value.push({ | ||
| 172 | perId: item.perId, | ||
| 173 | name: item.name, | ||
| 174 | photo: item.photo | ||
| 175 | }) | ||
| 176 | } else { | ||
| 177 | const index = selectedList.value.findIndex(s => s.perId === item.perId) | ||
| 178 | if (index > -1) { | ||
| 179 | selectedList.value.splice(index, 1) | ||
| 180 | } | ||
| 181 | } | ||
| 182 | } | ||
| 183 | |||
| 184 | function removeSelected(index) { | ||
| 185 | const item = selectedList.value[index] | ||
| 186 | const student = studentList.value.find(s => s.perId === item.perId) | ||
| 187 | if (student) { | ||
| 188 | student.checked = false | ||
| 189 | } | ||
| 190 | selectedList.value.splice(index, 1) | ||
| 191 | } | ||
| 192 | |||
| 193 | function confirmSelect() { | ||
| 194 | if (selectedList.value.length === 0) { | ||
| 195 | uni.showToast({ title: '请选择考生', icon: 'none' }) | ||
| 196 | return | ||
| 197 | } | ||
| 198 | |||
| 199 | uni.showLoading({ title: '添加中...' }) | ||
| 200 | api.batchChoose({ | ||
| 201 | examId: examId, | ||
| 202 | perIds: selectedList.value.map(s => s.perId) | ||
| 203 | }).then(() => { | ||
| 204 | uni.hideLoading() | ||
| 205 | uni.showToast({ title: '添加成功', icon: 'success' }) | ||
| 206 | setTimeout(() => { | ||
| 207 | uni.navigateBack() | ||
| 208 | }, 1500) | ||
| 209 | }).catch(() => { | ||
| 210 | uni.hideLoading() | ||
| 211 | }) | ||
| 212 | } | ||
| 213 | |||
| 214 | function goBack() { | ||
| 215 | uni.navigateBack() | ||
| 216 | } | ||
| 217 | |||
| 218 | function formatDate(dateStr) { | ||
| 219 | if (!dateStr) return '-' | ||
| 220 | return dateStr.substring(0, 10) | ||
| 221 | } | ||
| 222 | |||
| 223 | function formatLevel(level) { | ||
| 224 | if (!level || level == 0) return '十级' | ||
| 225 | const hzArr = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'] | ||
| 226 | return hzArr[parseInt(level)] + '级' | ||
| 227 | } | ||
| 228 | </script> | ||
| 229 | |||
| 230 | <style lang="scss" scoped> | ||
| 231 | .choose-student-page { | ||
| 232 | min-height: 100vh; | ||
| 233 | background: #f5f5f5; | ||
| 234 | display: flex; | ||
| 235 | flex-direction: column; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* 搜索头部 */ | ||
| 239 | .search-header { | ||
| 240 | display: flex; | ||
| 241 | align-items: center; | ||
| 242 | padding: 20rpx 30rpx; | ||
| 243 | background: #fff; | ||
| 244 | border-bottom: 1rpx solid #f0f0f0; | ||
| 245 | |||
| 246 | .search-box { | ||
| 247 | flex: 1; | ||
| 248 | display: flex; | ||
| 249 | align-items: center; | ||
| 250 | padding: 0 20rpx; | ||
| 251 | height: 64rpx; | ||
| 252 | background: #f5f5f5; | ||
| 253 | border-radius: 32rpx; | ||
| 254 | |||
| 255 | .search-input { | ||
| 256 | flex: 1; | ||
| 257 | height: 100%; | ||
| 258 | font-size: 26rpx; | ||
| 259 | margin-left: 10rpx; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | |||
| 263 | .cancel-btn { | ||
| 264 | margin-left: 20rpx; | ||
| 265 | font-size: 28rpx; | ||
| 266 | color: #666; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | /* 已选区域 */ | ||
| 271 | .selected-section { | ||
| 272 | background: #fff; | ||
| 273 | padding: 20rpx 30rpx; | ||
| 274 | border-bottom: 1rpx solid #f0f0f0; | ||
| 275 | |||
| 276 | .section-header { | ||
| 277 | display: flex; | ||
| 278 | align-items: center; | ||
| 279 | margin-bottom: 16rpx; | ||
| 280 | |||
| 281 | .section-title { | ||
| 282 | font-size: 26rpx; | ||
| 283 | font-weight: 600; | ||
| 284 | color: #333; | ||
| 285 | } | ||
| 286 | |||
| 287 | .section-count { | ||
| 288 | margin-left: 12rpx; | ||
| 289 | font-size: 24rpx; | ||
| 290 | color: #AD181F; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | .selected-scroll { | ||
| 295 | white-space: nowrap; | ||
| 296 | |||
| 297 | .selected-item { | ||
| 298 | display: inline-flex; | ||
| 299 | align-items: center; | ||
| 300 | position: relative; | ||
| 301 | margin-right: 24rpx; | ||
| 302 | |||
| 303 | .avatar-small { | ||
| 304 | width: 64rpx; | ||
| 305 | height: 64rpx; | ||
| 306 | border-radius: 50%; | ||
| 307 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); | ||
| 308 | overflow: hidden; | ||
| 309 | display: flex; | ||
| 310 | align-items: center; | ||
| 311 | justify-content: center; | ||
| 312 | |||
| 313 | text { | ||
| 314 | font-size: 24rpx; | ||
| 315 | color: #fff; | ||
| 316 | } | ||
| 317 | |||
| 318 | image { | ||
| 319 | width: 100%; | ||
| 320 | height: 100%; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | .name-small { | ||
| 325 | display: block; | ||
| 326 | text-align: center; | ||
| 327 | font-size: 22rpx; | ||
| 328 | color: #666; | ||
| 329 | margin-top: 8rpx; | ||
| 330 | width: 80rpx; | ||
| 331 | overflow: hidden; | ||
| 332 | text-overflow: ellipsis; | ||
| 333 | white-space: nowrap; | ||
| 334 | } | ||
| 335 | |||
| 336 | .remove-btn { | ||
| 337 | position: absolute; | ||
| 338 | top: -6rpx; | ||
| 339 | right: -6rpx; | ||
| 340 | width: 28rpx; | ||
| 341 | height: 28rpx; | ||
| 342 | background: #999; | ||
| 343 | border-radius: 50%; | ||
| 344 | display: flex; | ||
| 345 | align-items: center; | ||
| 346 | justify-content: center; | ||
| 347 | } | ||
| 348 | } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | /* 考生列表 */ | ||
| 353 | .student-scroll { | ||
| 354 | flex: 1; | ||
| 355 | height: calc(100vh - 280rpx); | ||
| 356 | } | ||
| 357 | |||
| 358 | .student-list { | ||
| 359 | padding: 20rpx 30rpx; | ||
| 360 | |||
| 361 | .student-card { | ||
| 362 | display: flex; | ||
| 363 | align-items: center; | ||
| 364 | padding: 24rpx; | ||
| 365 | background: #fff; | ||
| 366 | border-radius: 16rpx; | ||
| 367 | margin-bottom: 16rpx; | ||
| 368 | box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04); | ||
| 369 | |||
| 370 | .checkbox { | ||
| 371 | margin-right: 20rpx; | ||
| 372 | |||
| 373 | .checkbox-empty { | ||
| 374 | width: 40rpx; | ||
| 375 | height: 40rpx; | ||
| 376 | border: 2rpx solid #ddd; | ||
| 377 | border-radius: 50%; | ||
| 378 | } | ||
| 379 | |||
| 380 | image { | ||
| 381 | width: 40rpx; | ||
| 382 | height: 40rpx; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | .avatar { | ||
| 387 | width: 80rpx; | ||
| 388 | height: 80rpx; | ||
| 389 | border-radius: 50%; | ||
| 390 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); | ||
| 391 | overflow: hidden; | ||
| 392 | display: flex; | ||
| 393 | align-items: center; | ||
| 394 | justify-content: center; | ||
| 395 | margin-right: 20rpx; | ||
| 396 | |||
| 397 | .avatar-text { | ||
| 398 | font-size: 32rpx; | ||
| 399 | color: #fff; | ||
| 400 | font-weight: 600; | ||
| 401 | } | ||
| 402 | |||
| 403 | image { | ||
| 404 | width: 100%; | ||
| 405 | height: 100%; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | .student-info { | ||
| 410 | flex: 1; | ||
| 411 | |||
| 412 | .student-name { | ||
| 413 | font-size: 28rpx; | ||
| 414 | font-weight: 600; | ||
| 415 | color: #333; | ||
| 416 | margin-bottom: 8rpx; | ||
| 417 | |||
| 418 | .per-code { | ||
| 419 | font-size: 22rpx; | ||
| 420 | color: #999; | ||
| 421 | font-weight: normal; | ||
| 422 | margin-left: 12rpx; | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | .student-detail { | ||
| 427 | display: flex; | ||
| 428 | gap: 20rpx; | ||
| 429 | |||
| 430 | .level-info { | ||
| 431 | font-size: 24rpx; | ||
| 432 | color: #1561CB; | ||
| 433 | } | ||
| 434 | |||
| 435 | .validity { | ||
| 436 | font-size: 24rpx; | ||
| 437 | color: #666; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | } | ||
| 441 | } | ||
| 442 | |||
| 443 | .loading-more, | ||
| 444 | .no-more { | ||
| 445 | text-align: center; | ||
| 446 | padding: 30rpx; | ||
| 447 | font-size: 24rpx; | ||
| 448 | color: #999; | ||
| 449 | } | ||
| 450 | |||
| 451 | } | ||
| 452 | |||
| 453 | /* 底部固定栏 */ | ||
| 454 | .fixedBottom { | ||
| 455 | display: flex; | ||
| 456 | align-items: center; | ||
| 457 | justify-content: space-between; | ||
| 458 | padding: 20rpx 30rpx; | ||
| 459 | background: #fff; | ||
| 460 | box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05); | ||
| 461 | |||
| 462 | .bottom-info { | ||
| 463 | .info-text { | ||
| 464 | font-size: 26rpx; | ||
| 465 | color: #666; | ||
| 466 | |||
| 467 | .count { | ||
| 468 | color: #AD181F; | ||
| 469 | font-weight: 600; | ||
| 470 | } | ||
| 471 | } | ||
| 472 | } | ||
| 473 | |||
| 474 | .btn-confirm { | ||
| 475 | padding: 0 50rpx; | ||
| 476 | height: 72rpx; | ||
| 477 | line-height: 72rpx; | ||
| 478 | background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); | ||
| 479 | border-radius: 36rpx; | ||
| 480 | font-size: 28rpx; | ||
| 481 | color: #fff; | ||
| 482 | box-shadow: 0 4rpx 16rpx rgba(173, 24, 31, 0.3); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | .empty { | ||
| 486 | display: flex; | ||
| 487 | flex-direction: column; | ||
| 488 | justify-content: center; | ||
| 489 | align-items: center; | ||
| 490 | padding: 120rpx 0; | ||
| 491 | |||
| 492 | .empty-img { | ||
| 493 | width: 300rpx; | ||
| 494 | height: 300rpx; | ||
| 495 | opacity: 0.08; | ||
| 496 | } | ||
| 497 | |||
| 498 | .empty-text { | ||
| 499 | color: #999; | ||
| 500 | font-size: 28rpx; | ||
| 501 | margin-top: 20rpx; | ||
| 502 | } | ||
| 503 | } | ||
| 504 | </style> |
| ... | @@ -680,7 +680,16 @@ | ... | @@ -680,7 +680,16 @@ |
| 680 | "enablePullDownRefresh": false | 680 | "enablePullDownRefresh": false |
| 681 | } | 681 | } |
| 682 | 682 | ||
| 683 | }, { | 683 | }, |
| 684 | { | ||
| 685 | "path": "chooseStudent", | ||
| 686 | "style": { | ||
| 687 | "navigationBarTitleText": "添加考生", | ||
| 688 | "enablePullDownRefresh": false | ||
| 689 | } | ||
| 690 | |||
| 691 | }, | ||
| 692 | { | ||
| 684 | "path": "addApply", | 693 | "path": "addApply", |
| 685 | "style": { | 694 | "style": { |
| 686 | "navigationBarTitleText": "编辑级位考试", | 695 | "navigationBarTitleText": "编辑级位考试", | ... | ... |
-
Please register or sign in to post a comment