瀏覽代碼

补录成绩导入

tags/正式版本
雍文秀 2 年之前
父節點
當前提交
f35e0456b5

+ 11
- 0
sexam/pom.xml 查看文件

@@ -74,6 +74,17 @@
74 74
             <groupId>org.springframework.boot</groupId>
75 75
             <artifactId>spring-boot-starter-amqp</artifactId>
76 76
         </dependency>
77
+        <!--  导入和导出excel时需要的jar包 -->
78
+        <dependency>
79
+            <groupId>org.apache.poi</groupId>
80
+            <artifactId>poi-ooxml</artifactId>
81
+            <version>3.17</version>
82
+        </dependency>
83
+        <dependency>
84
+            <groupId>org.apache.poi</groupId>
85
+            <artifactId>poi</artifactId>
86
+            <version>3.17</version>
87
+        </dependency>
77 88
     </dependencies>
78 89
     <dependencyManagement>
79 90
         <dependencies>

+ 13
- 1
sexam/src/main/java/com/xhkjedu/sexam/controller/paperstudent/EPsqbatchController.java 查看文件

@@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.PostMapping;
13 13
 import org.springframework.web.bind.annotation.RequestBody;
14 14
 import org.springframework.web.bind.annotation.RequestMapping;
15 15
 import org.springframework.web.bind.annotation.RestController;
16
+import org.springframework.web.multipart.MultipartFile;
16 17
 
17 18
 import javax.annotation.Resource;
18 19
 import java.util.List;
@@ -60,7 +61,18 @@ public class EPsqbatchController {
60 61
         }
61 62
     }
62 63
 
63
-
64
+    /*
65
+     * 补录成绩导入
66
+     * @Param [file, batch]
67
+     * @Author ywx
68
+     * @Date 2022/11/21 15:14
69
+     * @return com.xhkjedu.vo.ResultVo
70
+     **/
71
+    @PostMapping("/import")
72
+    public ResultVo importRecord(MultipartFile file, EPsqbatch batch) {
73
+        N_Utils.validation(new Object[]{batch.getEpid(), "试卷id", 1, batch.getTeacherid(), "教师id", 1});
74
+        return ePsqbatchService.importRecord(file, batch);
75
+    }
64 76
 
65 77
 
66 78
 }

+ 3
- 0
sexam/src/main/java/com/xhkjedu/sexam/mapper/exam/EClassStudentMapper.java 查看文件

@@ -28,4 +28,7 @@ public interface EClassStudentMapper extends TkMapper<EClassStudent> {
28 28
 
29 29
     //批量生成学生pdf报告
30 30
     void updateBatchReportstupath(@Param("list")List<EClassStudent> list);
31
+
32
+    //考试学生列表
33
+    List<Map> listStuByExamId(@Param("examid") Integer examid);
31 34
 }

+ 3
- 0
sexam/src/main/java/com/xhkjedu/sexam/mapper/paperstudent/EPaperStudentQuestionMapper.java 查看文件

@@ -64,4 +64,7 @@ public interface EPaperStudentQuestionMapper extends TkMapper<EPaperStudentQuest
64 64
 
65 65
     //获取未合并图片考试模式列表
66 66
     List<Map> listExamByIds(@Param("examids") List<Integer> examids);
67
+
68
+    //获取学生试题列表
69
+    List<EPaperStudentQuestion> listQuestionByStu(@Param("studentid") Integer studentid,@Param("eptqids") List<Integer> eptqids);
67 70
 }

+ 1
- 1
sexam/src/main/java/com/xhkjedu/sexam/model/paperstudent/EPsqbatch.java 查看文件

@@ -17,7 +17,7 @@ public class EPsqbatch extends BaseBean {
17 17
     @Id
18 18
     private Integer batchid;
19 19
 
20
-    //扫描批次名称
20
+    //科目名称
21 21
     private String subjectname;
22 22
 
23 23
     //考试id

+ 1
- 0
sexam/src/main/java/com/xhkjedu/sexam/model/paperstudent/EPsqbatchDetail.java 查看文件

@@ -25,6 +25,7 @@ public class EPsqbatchDetail extends BaseBean {
25 25
 
26 26
     //试卷id
27 27
     private Integer epid;
28
+    private Integer eptqid;
28 29
 
29 30
     //学生试题id
30 31
     private Integer epsqid;

+ 91
- 0
sexam/src/main/java/com/xhkjedu/sexam/service/paperstudent/EPsqbatchService.java 查看文件

@@ -1,12 +1,27 @@
1 1
 package com.xhkjedu.sexam.service.paperstudent;
2 2
 
3
+import com.xhkjedu.sexam.mapper.exam.EClassStudentMapper;
4
+import com.xhkjedu.sexam.mapper.paper.EPaperQtypeQuestionMapper;
5
+import com.xhkjedu.sexam.mapper.paperstudent.EPaperStudentQuestionMapper;
3 6
 import com.xhkjedu.sexam.mapper.paperstudent.EPsqbatchMapper;
7
+import com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion;
8
+import com.xhkjedu.sexam.model.paperstudent.EPsqbatch;
9
+import com.xhkjedu.sexam.model.paperstudent.EPsqbatchDetail;
10
+import com.xhkjedu.sexam.utils.PoiUtils;
11
+import com.xhkjedu.sexam.vo.paperstudent.EPsqbatchStuVo;
12
+import com.xhkjedu.utils.N_Utils;
13
+import com.xhkjedu.vo.ResultVo;
4 14
 import lombok.extern.slf4j.Slf4j;
5 15
 import org.springframework.stereotype.Service;
16
+import org.springframework.transaction.annotation.Transactional;
17
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
18
+import org.springframework.web.multipart.MultipartFile;
6 19
 
7 20
 import javax.annotation.Resource;
21
+import java.util.LinkedHashMap;
8 22
 import java.util.List;
9 23
 import java.util.Map;
24
+import java.util.stream.Collectors;
10 25
 
11 26
 /**
12 27
  * @Description 学生试卷信息
@@ -18,6 +33,12 @@ import java.util.Map;
18 33
 public class EPsqbatchService {
19 34
     @Resource
20 35
     private EPsqbatchMapper ePsqbatchMapper;
36
+    @Resource
37
+    private EPaperQtypeQuestionMapper ePaperQtypeQuestionMapper;
38
+    @Resource
39
+    private EClassStudentMapper eClassStudentMapper;
40
+    @Resource
41
+    private EPaperStudentQuestionMapper ePaperStudentQuestionMapper;
21 42
 
22 43
     /**
23 44
      * @Description 获取考试科目
@@ -40,4 +61,74 @@ public class EPsqbatchService {
40 61
     public List<Map> listPsqBatchsByExamid(Integer exmaid){
41 62
         return ePsqbatchMapper.listPsqBatchsByExamid(exmaid);
42 63
     }
64
+
65
+    /*
66
+     * 补录成绩导入
67
+     * @Param [file, batch]
68
+     * @Author ywx
69
+     * @Date 2022/11/21 15:14
70
+     * @return com.xhkjedu.vo.ResultVo
71
+     **/
72
+    public ResultVo importRecord(MultipartFile file, EPsqbatch batch) {
73
+        Integer epid = batch.getEpid();
74
+        Integer examid = batch.getExamid();
75
+        List<Map> students = eClassStudentMapper.listStuByExamId(examid);//考试学生列表
76
+        List<Map> qns = ePaperQtypeQuestionMapper.listQnByEpid(epid);
77
+        try {
78
+            Map<String, Object> map = PoiUtils.readExcelRecord(file, qns, students);
79
+            Integer code = (Integer) map.get("code");
80
+            if (code != 0) return new ResultVo(1, map.get("msg").toString());
81
+            LinkedHashMap<Integer, List<String>> errMsg = (LinkedHashMap<Integer, List<String>>) map.get("errMsg");
82
+            if (errMsg.size() != 0) return new ResultVo(1, null, errMsg);
83
+            ePsqbatchMapper.insertUseGeneratedKeys(batch);
84
+            List<EPsqbatchStuVo> stus = (List<EPsqbatchStuVo>) map.get("stus");
85
+            for (EPsqbatchStuVo stu : stus) {
86
+                new Thread(()->{
87
+                    try {
88
+                        saveEPsqbatchDetail(stu,batch);
89
+                    }catch (Exception e){
90
+                        log.error("保存学生试题重试:" + e.getMessage());
91
+                        try {
92
+                            saveEPsqbatchDetail(stu,batch);
93
+                        }catch (Exception se){
94
+                            log.error("保存学生试题重试出错:" + se.getMessage());
95
+                        }
96
+                    }
97
+                }).start();
98
+            }
99
+        } catch (Exception e) {
100
+            e.printStackTrace();
101
+        }
102
+        return new ResultVo(0,"导入成功");
103
+    }
104
+
105
+    //保存学生试题
106
+    @Transactional(rollbackFor = Exception.class)
107
+    public void saveEPsqbatchDetail(EPsqbatchStuVo stu, EPsqbatch batch){
108
+        try {
109
+            int timestamp = N_Utils.getSecondTimestamp();
110
+            Integer batchId = batch.getId();
111
+            Integer teacherid = batch.getTeacherid();
112
+            Integer epid = batch.getEpid();
113
+            Integer studentid = stu.getStudentid();
114
+            List<EPsqbatchDetail> details = stu.getDetails();
115
+            //获取试卷中所有试题
116
+            List<Integer> eptqids = details.stream().map(d -> d.getEptqid()).collect(Collectors.toList());
117
+            List<EPaperStudentQuestion> questions = ePaperStudentQuestionMapper.listQuestionByStu(studentid,eptqids);
118
+            for (int i = 0; i < details.size(); i++) {
119
+                EPsqbatchDetail detail = details.get(i);
120
+                EPaperStudentQuestion question = questions.get(i);
121
+                question.setStuscore(detail.getNewscore());
122
+                detail.setStuscore(question.getStuscore());
123
+                detail.setEpid(epid);
124
+                detail.setBatchid(batchId);
125
+                detail.setTeacherid(teacherid);
126
+                detail.setCreatetime(timestamp);
127
+            }
128
+        } catch (Exception e) {
129
+            log.error("保存学生试题失败:" + e.getMessage());
130
+            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
131
+            throw new RuntimeException("保存学生试题失败");
132
+        }
133
+    }
43 134
 }

+ 271
- 0
sexam/src/main/java/com/xhkjedu/sexam/utils/PoiUtils.java 查看文件

@@ -0,0 +1,271 @@
1
+package com.xhkjedu.sexam.utils;
2
+
3
+import com.xhkjedu.sexam.model.paperstudent.EPsqbatchDetail;
4
+import com.xhkjedu.sexam.vo.paperstudent.EPsqbatchStuVo;
5
+import com.xhkjedu.utils.N_Utils;
6
+import lombok.extern.slf4j.Slf4j;
7
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
8
+import org.apache.poi.ss.usermodel.*;
9
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
10
+import org.springframework.stereotype.Component;
11
+import org.springframework.web.multipart.MultipartFile;
12
+
13
+import java.io.InputStream;
14
+import java.text.DecimalFormat;
15
+import java.text.SimpleDateFormat;
16
+import java.util.*;
17
+import java.util.stream.Collectors;
18
+
19
+/**
20
+ * @author ywx
21
+ * @classname PoiUtils
22
+ * @description
23
+ * @date 2022-11-21 14:46:22
24
+ **/
25
+@Component
26
+@Slf4j
27
+public class PoiUtils {
28
+    //2003- 版本的excel
29
+    private final static String excel2003L = ".xls";
30
+    //2007+ 版本的excel
31
+    private final static String excel2007U = ".xlsx";
32
+
33
+    /**
34
+     * 导入教师
35
+     *
36
+     * @return java.util.Map<java.lang.String, java.lang.Object>
37
+     * @Param [file]
38
+     * @Author ywx
39
+     * @Date 2022/3/17 9:44
40
+     **/
41
+    public static Map<String, Object> readExcelRecord(MultipartFile file, List<Map> qns, List<Map> students) throws Exception {
42
+        Map<String, Object> resultMap = new HashMap<>();
43
+        Map<Integer, List<String>> errMsg = new LinkedHashMap<>();
44
+        try {
45
+            // 数据校验
46
+            isExcelEmpty(file);
47
+            InputStream in = file.getInputStream();
48
+            String fileName = file.getOriginalFilename();
49
+            Workbook work = getWorkbook(in, fileName);
50
+            Sheet sheet;// 分表数据
51
+            Row row;// 行数据
52
+            sheet = work.getSheetAt(0);//只取第一个sheet
53
+            if (sheet == null) {
54
+                throw new Exception("Excel第一个分表内容为空!");
55
+            }
56
+
57
+            int rows = sheet.getLastRowNum(); // 获取最后一个实际行的下标,比行数小1
58
+            int firstRowNum = sheet.getFirstRowNum(); // 获取第一个实际行的下标,(firstRowNum=0)
59
+            row = sheet.getRow(firstRowNum);//标题行
60
+            int firstCellNum = row.getFirstCellNum();
61
+            int lastCellNum = row.getLastCellNum();// 每一行的最后一列,获取列数,比最后一列列标大1
62
+            String qn = qns.stream().map(q -> q.get("qn").toString()).collect(Collectors.joining());
63
+            Map<Integer, Integer> questionMap = new HashMap<>();
64
+            Map<Integer, Double> scoreMap = new HashMap<>();
65
+            for (int i = 0; i < qns.size(); i++) {
66
+                questionMap.put(i + 2, (Integer) qns.get(i).get("eptqid"));
67
+                scoreMap.put(i + 2, (Double) qns.get(i).get("score"));
68
+            }
69
+            String titleName = "姓名账号" + qn;//标题格式
70
+            StringBuilder sb = new StringBuilder();
71
+            for (int y = firstCellNum; y < lastCellNum; y++) {
72
+                sb.append(row.getCell(y));
73
+            }
74
+            int maxIndex = lastCellNum - 1;//最大题号下标
75
+            String importTitleName = sb.toString();
76
+            if (!titleName.equals(importTitleName)) throw new Exception("标题格式不正确");
77
+
78
+            Map<String, Integer> stuMap = students.stream().collect(Collectors.toMap(
79
+                    s -> s.get("username").toString() + s.get("loginname").toString()
80
+                    , s -> (Integer) s.get("studentid")));
81
+
82
+            // 导入记录信息
83
+            List<EPsqbatchStuVo> stus = new ArrayList<>();
84
+
85
+            //遍历当前sheet中的所有行 排除第一行  第一行为标题头 不纳入遍历
86
+            for (int x = firstRowNum + 1; x <= rows; x++) {
87
+                // 获取行
88
+                row = sheet.getRow(x);
89
+                if (row == null) {//若此行为空,则跳出循环继续下一行
90
+                    continue;
91
+                } else if (isEmptyCell(row.getCell(0)) && isEmptyCell(row.getCell(1))) {
92
+                    continue;
93
+                }
94
+                firstCellNum = row.getFirstCellNum();// 每一行的第一列,(firstCellNum=0)
95
+                if (firstCellNum == 1) throw new Exception("第" + (x + 1) + "行姓名不能为空");
96
+                lastCellNum = row.getLastCellNum();// 每一行的最后一列,获取列数,比最后一列列标大1
97
+                List<String> mrows = new ArrayList<>();
98
+                //遍历所有的列
99
+                String username = getCellValue(row.getCell(0));//姓名
100
+                String loginname = getCellValue(row.getCell(1));//账号
101
+                Integer studentid = stuMap.get(username + loginname);
102
+                if (N_Utils.isEmptyInteger(studentid)) {
103
+                    mrows.add("第" + (x + 1) + "行学生【" + username + "(" + loginname + ")】不存在");
104
+                    continue;//学生不存在处理下一行
105
+                }
106
+                List<EPsqbatchDetail> details = new ArrayList<>();
107
+                for (int y = firstCellNum + 2; y < lastCellNum; y++) {
108
+                    Cell cell = row.getCell(y);
109
+                    String score = getCellValue(cell);
110
+                    if (N_Utils.isEmpty(score)) {
111
+                        continue;//学生分值为空处理下一列
112
+                    }
113
+                    EPsqbatchDetail detail = new EPsqbatchDetail();
114
+                    detail.setStudentid(studentid);
115
+                    Double stuscore = Double.valueOf(score);
116
+                    Double qscore = scoreMap.get(y);
117
+                    if (Double.compare(stuscore, qscore) == 1) {
118
+                        stuscore = qscore;
119
+                    }
120
+                    detail.setNewscore(stuscore);
121
+                    detail.setEptqid(questionMap.get(y));
122
+                    details.add(detail);
123
+                    if (y == maxIndex && N_Utils.isListNotEmpty(mrows)) {
124
+                        errMsg.put(x + 1, mrows);
125
+                    }
126
+                }
127
+                if (N_Utils.isListNotEmpty(details)) {
128
+                    EPsqbatchStuVo stu = new EPsqbatchStuVo();
129
+                    stu.setStudentid(studentid);
130
+                    stu.setDetails(details);
131
+                    stus.add(stu);
132
+                }
133
+            }
134
+
135
+            resultMap.put("code", 0);
136
+            resultMap.put("stus", stus);
137
+        } catch (Exception e) {
138
+            resultMap.put("code", 1);
139
+            String msg = e.getMessage();
140
+            resultMap.put("msg", msg);
141
+            if (msg.contains("Invalid ")) {
142
+                msg = "格式不正确";
143
+            }
144
+            throw new Exception(msg);
145
+        }
146
+        resultMap.put("errMsg", errMsg);
147
+        return resultMap;
148
+    }
149
+
150
+    /**
151
+     * 根据文件后缀,自适应上传文件的版本
152
+     *
153
+     * @return org.apache.poi.ss.usermodel.Workbook
154
+     * @Param [inStr, fileName]
155
+     * @Author ywx
156
+     * @Date 2020/6/3 16:42
157
+     **/
158
+    public static Workbook getWorkbook(InputStream inStr, String fileName) throws Exception {
159
+        Workbook wb;
160
+        String fileType = fileName.substring(fileName.lastIndexOf("."));
161
+        if (excel2003L.equals(fileType)) {
162
+            wb = new HSSFWorkbook(inStr);  //2003-
163
+        } else if (excel2007U.equals(fileType)) {
164
+            wb = new XSSFWorkbook(inStr);  //2007+
165
+        } else {
166
+            throw new Exception("Excel格式解析有误!");
167
+        }
168
+        return wb;
169
+    }
170
+
171
+    /**
172
+     * 判断单元格是否是空值
173
+     *
174
+     * @return java.lang.Boolean
175
+     * @Param [cell]
176
+     * @Author ywx
177
+     * @Date 2020/6/3 16:37
178
+     **/
179
+    public static Boolean isEmptyCell(Cell cell) {
180
+        if (cell != null) {
181
+            Boolean rtn = true;
182
+            if (N_Utils.isNotEmpty(PoiUtils.getCellValue(cell))) {
183
+                rtn = false;
184
+            }
185
+            return rtn;
186
+        } else {
187
+            return true;
188
+        }
189
+    }
190
+
191
+    /**
192
+     * 对表格中数值进行格式化
193
+     *
194
+     * @return java.lang.Object
195
+     * @Param [cell]
196
+     * @Author ywx
197
+     * @Date 2020/6/3 16:41
198
+     **/
199
+    public static String getCellValue(Cell cell) {
200
+        String value = null;
201
+        DecimalFormat df = new DecimalFormat("0");  //格式化number String字符
202
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");  //日期格式化
203
+        DecimalFormat df2 = new DecimalFormat("0");  //格式化数字
204
+        switch (cell.getCellTypeEnum()) {
205
+            case STRING:
206
+                value = cell.getRichStringCellValue().getString();
207
+                break;
208
+            case NUMERIC:
209
+                String cellStyle = cell.getCellStyle().getDataFormatString();
210
+                if ("General".equals(cellStyle)) {
211
+                    Double d = cell.getNumericCellValue();
212
+                    if (d.toString().contains("E")) {
213
+                        cell.setCellType(CellType.STRING);
214
+                        value = cell.getStringCellValue();
215
+                    } else {
216
+                        value = df.format(d);
217
+                    }
218
+                } else if ("m/d/yy".equals(cellStyle)) {
219
+                    value = sdf.format(cell.getDateCellValue());
220
+                } else {
221
+                    value = df2.format(cell.getNumericCellValue());
222
+                }
223
+                break;
224
+            case BOOLEAN:
225
+                boolean rtn = cell.getBooleanCellValue();
226
+                if (rtn) {
227
+                    value = "1";//真
228
+                } else {
229
+                    value = "0";//假
230
+                }
231
+                break;
232
+            case BLANK:
233
+                value = "";
234
+                break;
235
+            case FORMULA://读取excel公式的值
236
+                try {
237
+                    value = String.valueOf(cell.getNumericCellValue());
238
+                } catch (IllegalStateException e) {
239
+                    value = String.valueOf(cell.getRichStringCellValue());
240
+                }
241
+                break;
242
+            default:
243
+                break;
244
+        }
245
+        return N_Utils.strTrim(value);
246
+    }
247
+
248
+    /**
249
+     * 检验Excel内容是否为空
250
+     *
251
+     * @return void
252
+     * @Param [file]
253
+     * @Author ywx
254
+     * @Date 2020/6/3 16:36
255
+     **/
256
+    public static void isExcelEmpty(MultipartFile file) throws Exception {
257
+        if (null == file || file.isEmpty()) {
258
+            throw new Exception("文件不存在!");
259
+        }
260
+        InputStream in = file.getInputStream();
261
+        String fileName = file.getOriginalFilename();
262
+        Workbook work = getWorkbook(in, fileName);
263
+        if (null == work) {
264
+            throw new Exception("Excel内容为空!");
265
+        }
266
+        Integer sheet_size = work.getNumberOfSheets();
267
+        if (sheet_size == 0) {
268
+            throw new Exception("Excel内容为空!");
269
+        }
270
+    }
271
+}

+ 12
- 0
sexam/src/main/java/com/xhkjedu/sexam/vo/paperstudent/EPsqbatchStuVo.java 查看文件

@@ -0,0 +1,12 @@
1
+package com.xhkjedu.sexam.vo.paperstudent;
2
+
3
+import com.xhkjedu.sexam.model.paperstudent.EPsqbatchDetail;
4
+import lombok.Data;
5
+
6
+import java.util.List;
7
+
8
+@Data
9
+public class EPsqbatchStuVo {
10
+    private Integer studentid;//学生id
11
+    private List<EPsqbatchDetail> details;//试题集合
12
+}

+ 6
- 0
sexam/src/main/resources/mapper/exam/EClassStudentMapper.xml 查看文件

@@ -68,4 +68,10 @@
68 68
             studentid=#{item.studentid} and examid=#{item.examid}
69 69
         </foreach>
70 70
     </update>
71
+    <!--考试学生列表-->
72
+    <select id="listStuByExamId" resultType="java.util.Map">
73
+        select es.studentid,u.username,u.loginname
74
+        from e_class_student es left join t_user u on es.studentid = u.userid
75
+        where es.examid=#{examid}
76
+    </select>
71 77
 </mapper>

+ 1
- 1
sexam/src/main/resources/mapper/paper/EPaperQtypeQuestionMapper.xml 查看文件

@@ -72,7 +72,7 @@
72 72
     </select>
73 73
     <!--试卷中所有试题题号信息-->
74 74
     <select id="listQnByEpid" resultType="java.util.Map">
75
-        select eptqid,concat('第',qn,'题')qn
75
+        select eptqid,score,concat('第',qn,'题')qn
76 76
         from e_paper_qtype_question where epid=#{epid} order by qorder
77 77
     </select>
78 78
 

+ 7
- 1
sexam/src/main/resources/mapper/paperstudent/EPaperStudentQuestionMapper.xml 查看文件

@@ -230,5 +230,11 @@
230 230
     <select id="listStuQuestionsByEpsid" resultType="com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion">
231 231
         select * from e_paper_student_question where epsid=#{epsid} order by epsqid
232 232
     </select>
233
-
233
+    <!--/获取学生试题列表-->
234
+    <select id="listQuestionByStu" resultType="com.xhkjedu.sexam.model.paperstudent.EPaperStudentQuestion">
235
+        select epsqid,eptqid,qn,stuscore
236
+        from e_paper_student_question where studentid=#{studentid} and eptqid in
237
+        <foreach collection="eptqids" item="eptqid" open="(" separator="," close=")">${eptqid}</foreach>
238
+        order by epsqid
239
+    </select>
234 240
 </mapper>

Loading…
取消
儲存