生成績(jī)管理系統(tǒng)設(shè)計(jì)與實(shí)現(xiàn)(論文+源碼))
簡(jiǎn)介這份學(xué)生成績(jī)信息管理系統(tǒng)項(xiàng)目面向課程設(shè)計(jì)、畢業(yè)設(shè)計(jì)與后端入門(mén)實(shí)戰(zhàn)人群提供論文文檔和完整源碼幫助理解成績(jī)錄入、查詢(xún)、統(tǒng)計(jì)、報(bào)表生成及用戶(hù)權(quán)限等模塊的實(shí)現(xiàn)思路。壓縮包共311個(gè)文件約3.48MB包含86個(gè)cs源碼、29個(gè)aspx頁(yè)面、67個(gè)gif與24個(gè)jpg界面素材并配有dll、config、數(shù)據(jù)庫(kù)文件和項(xiàng)目解決方案覆蓋前端頁(yè)面、后端邏輯與部署配置目錄分層便于檢索。已有60人學(xué)習(xí)下載。讀者可據(jù)此梳理需求分析、數(shù)據(jù)模型與系統(tǒng)架構(gòu)設(shè)計(jì)參考成績(jī)查詢(xún)、班級(jí)課程管理、留言及用戶(hù)管理等頁(yè)面的組織方式也能對(duì)照論文理解測(cè)試與異常處理流程適合用作課程作業(yè)改造、畢業(yè)設(shè)計(jì)參考或快速搭建可運(yùn)行的管理系統(tǒng)原型。1. 需求切入從一張期末成績(jī)Excel說(shuō)起每到期末教務(wù)老師手里那張Excel表就開(kāi)始“渡劫”改一個(gè)學(xué)號(hào)排名公式全錯(cuò)補(bǔ)錄一個(gè)緩考成績(jī)平均分對(duì)不上學(xué)生打電話(huà)問(wèn)成績(jī)還得翻聊天記錄找密碼。學(xué)生成績(jī)信息管理系統(tǒng)聽(tīng)起來(lái)像課設(shè)標(biāo)配但真要做到能交付難點(diǎn)不在增刪改查而在數(shù)據(jù)一致性、權(quán)限邊界和批量操作的容錯(cuò)。這份學(xué)生成績(jī)信息管理系統(tǒng)論文源碼面向畢業(yè)設(shè)計(jì)和課程設(shè)計(jì)場(chǎng)景覆蓋需求分析、庫(kù)表設(shè)計(jì)、接口實(shí)現(xiàn)和驗(yàn)收測(cè)試適合想完整走一遍工程流程、而不是拼一個(gè)玩具Demo的人。下面按“選型—庫(kù)表—模塊—避坑—驗(yàn)收”拆開(kāi)講能抄作業(yè)的地方直接給代碼和配置。2. 技術(shù)選型與總體架構(gòu)三層結(jié)構(gòu) 四個(gè)核心模塊的職責(zé)劃分2.1 技術(shù)選型為什么用 Spring Boot MyBatis-Plus MySQL 而不是純 JSP學(xué)生成績(jī)管理系統(tǒng)的業(yè)務(wù)邏輯不復(fù)雜但角色多、查詢(xún)條件碎、批量導(dǎo)入容易翻車(chē)。選 Spring Boot 不是為了追新而是它把 Controller、Service、Mapper 三層切得清楚出問(wèn)題能快速定位到某一層。MyBatis-Plus 省掉大量單表 CRUD 的 XML復(fù)雜統(tǒng)計(jì)再寫(xiě)原生 SQL兼顧開(kāi)發(fā)效率和可控性。前端用 Vue Element UI 做管理端學(xué)生端可以復(fù)用同一套接口做移動(dòng)端適配不把前后端耦死在 JSP 里。核心依賴(lài)通常這樣引入版本按實(shí)際環(huán)境鎖定不要來(lái)回漂移!-- pom.xml 核心依賴(lài)片段 -- dependencies !-- Web 層提供 REST 接口和參數(shù)校驗(yàn) -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 持久層MyBatis-Plus 簡(jiǎn)化單表操作復(fù)雜 SQL 仍寫(xiě) XML -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3/version /dependency !-- MySQL 驅(qū)動(dòng)注意和本地?cái)?shù)據(jù)庫(kù)版本匹配 -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- Excel 解析批量導(dǎo)入成績(jī)時(shí)用 EasyExcel比 POI 省內(nèi)存 -- dependency groupIdcom.alibaba/groupId artifactIdeasyexcel/artifactId version3.3.2/version /dependency /dependencies這段依賴(lài)的關(guān)鍵在 EasyExcel成績(jī)導(dǎo)入動(dòng)輒幾百上千行用 POI 的XSSFWorkbook一次性讀進(jìn)內(nèi)存遇到大文件容易把堆撐爆。EasyExcel 按行回調(diào)內(nèi)存占用穩(wěn)定。MyBatis-Plus 的LambdaQueryWrapper用來(lái)拼多條件查詢(xún)避免手寫(xiě)字符串拼接導(dǎo)致 SQL 注入。MySQL 選 8.0 以上方便用窗口函數(shù)做排名統(tǒng)計(jì)后面統(tǒng)計(jì)報(bào)表會(huì)用到。2.2 總體架構(gòu)與模塊劃分表現(xiàn)層、業(yè)務(wù)層、數(shù)據(jù)層怎么切系統(tǒng)按四塊業(yè)務(wù)切用戶(hù)權(quán)限模塊、基礎(chǔ)數(shù)據(jù)模塊學(xué)生/課程/班級(jí)、成績(jī)管理模塊、統(tǒng)計(jì)報(bào)表模塊。表現(xiàn)層只做參數(shù)接收和結(jié)果包裝不寫(xiě)業(yè)務(wù)判斷業(yè)務(wù)層負(fù)責(zé)校驗(yàn)、事務(wù)和權(quán)限過(guò)濾數(shù)據(jù)層只做持久化。目錄結(jié)構(gòu)通常這樣組織讓接手的人一眼能定位src/main/java/com/example/score/ ├── controller/ # 接口層接收請(qǐng)求調(diào)用 service │ ├── AuthController.java │ ├── StudentController.java │ ├── CourseController.java │ └── ScoreController.java ├── service/ # 業(yè)務(wù)層校驗(yàn)、事務(wù)、權(quán)限過(guò)濾 │ ├── impl/ │ │ ├── ScoreServiceImpl.java │ │ └── StatsServiceImpl.java │ └── ScoreService.java ├── mapper/ # 數(shù)據(jù)層MyBatis-Plus Mapper 與 XML │ ├── ScoreMapper.java │ └── xml/ScoreMapper.xml ├── entity/ # 數(shù)據(jù)庫(kù)實(shí)體 ├── dto/ # 入?yún)⒑统鰠?duì)象不直接暴露 entity └── common/ # 統(tǒng)一返回、異常處理、攔截器四個(gè)模塊的職責(zé)邊界要在論文里寫(xiě)清楚用戶(hù)權(quán)限模塊管登錄、角色、菜單基礎(chǔ)數(shù)據(jù)模塊管學(xué)生和課程的增刪改查但刪除課程時(shí)要檢查是否已有成績(jī)關(guān)聯(lián)成績(jī)管理模塊管錄入、導(dǎo)入、修改、查詢(xún)所有寫(xiě)操作必須校驗(yàn)“當(dāng)前用戶(hù)是否有權(quán)操作這門(mén)課”統(tǒng)計(jì)報(bào)表模塊只讀但查詢(xún)條件多單獨(dú)拆 service 避免和寫(xiě)邏輯攪在一起。我一般會(huì)把權(quán)限校驗(yàn)放在 Controller 層之前用攔截器解析 token 拿到用戶(hù)角色和 id再在 Service 里按角色拼查詢(xún)條件而不是讓前端傳studentId就信。提示不要把權(quán)限判斷寫(xiě)在 SQL 的 where 里靠前端傳參學(xué)生端一旦改請(qǐng)求參數(shù)就能查到別人成績(jī)這是課設(shè)答辯最容易被問(wèn)穿的點(diǎn)。3. 數(shù)據(jù)庫(kù)設(shè)計(jì)與核心表結(jié)構(gòu)從成績(jī)錄入黨到統(tǒng)計(jì)查詢(xún)的字段取舍3.1 核心表結(jié)構(gòu)設(shè)計(jì)學(xué)生表、課程表、成績(jī)表、用戶(hù)表成績(jī)管理系統(tǒng)的庫(kù)表不多但字段取舍直接決定后面統(tǒng)計(jì)查詢(xún)好不好寫(xiě)。學(xué)生表存學(xué)號(hào)、姓名、班級(jí)、入學(xué)年份課程表存課程號(hào)、課程名、學(xué)分、授課教師成績(jī)表存學(xué)生 id、課程 id、學(xué)期、分?jǐn)?shù)、錄入時(shí)間。注意成績(jī)表不要直接存學(xué)號(hào)和課程名用外鍵 id 關(guān)聯(lián)否則改一次學(xué)生姓名就要全表更新。建表語(yǔ)句通常這樣寫(xiě)-- 學(xué)生表學(xué)號(hào)唯一班級(jí)用字符串先兜住后續(xù)可拆班級(jí)表 CREATE TABLE student ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_no VARCHAR(20) NOT NULL COMMENT 學(xué)號(hào), name VARCHAR(50) NOT NULL COMMENT 姓名, class_name VARCHAR(50) NOT NULL COMMENT 班級(jí), enroll_year INT NOT NULL COMMENT 入學(xué)年份, deleted TINYINT DEFAULT 0 COMMENT 邏輯刪除0正常 1刪除, UNIQUE KEY uk_student_no (student_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 課程表課程號(hào)唯一teacher_id 關(guān)聯(lián)用戶(hù)表里的教師角色 CREATE TABLE course ( id BIGINT PRIMARY KEY AUTO_INCREMENT, course_no VARCHAR(20) NOT NULL COMMENT 課程號(hào), course_name VARCHAR(100) NOT NULL COMMENT 課程名, credit DECIMAL(3,1) NOT NULL COMMENT 學(xué)分保留一位小數(shù), teacher_id BIGINT NOT NULL COMMENT 授課教師用戶(hù)id, deleted TINYINT DEFAULT 0, UNIQUE KEY uk_course_no (course_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 成績(jī)表同一學(xué)生同一課程同一學(xué)期只能有一條記錄 CREATE TABLE score ( id BIGINT PRIMARY KEY AUTO_INCREMENT, student_id BIGINT NOT NULL COMMENT 學(xué)生id, course_id BIGINT NOT NULL COMMENT 課程id, term VARCHAR(20) NOT NULL COMMENT 學(xué)期如2024-2025-1, score DECIMAL(5,2) DEFAULT NULL COMMENT 分?jǐn)?shù)0-100允許空表示未錄入, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, deleted TINYINT DEFAULT 0, UNIQUE KEY uk_student_course_term (student_id, course_id, term), KEY idx_course_term (course_id, term) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;成績(jī)表的DECIMAL(5,2)比FLOAT穩(wěn)算平均分時(shí)不會(huì)出現(xiàn)79.999999這種玄學(xué)尾數(shù)。term字段必須有否則補(bǔ)考和重修成績(jī)會(huì)覆蓋原始成績(jī)統(tǒng)計(jì)時(shí)說(shuō)不清。聯(lián)合唯一索引uk_student_course_term是防重復(fù)錄入的第一道閘后面導(dǎo)入邏輯還要配合它做更新而不是插入。3.2 索引與約束設(shè)計(jì)避免全表掃描和重復(fù)錄入成績(jī)查詢(xún)最常見(jiàn)的條件是“某學(xué)期某課程”和“某學(xué)生所有課程”。成績(jī)表上除了聯(lián)合唯一索引再補(bǔ)一個(gè)idx_course_term讓按課程統(tǒng)計(jì)平均分時(shí)走索引。學(xué)生表按學(xué)號(hào)查唯一索引自帶課程表按課程號(hào)查同理。不要給每個(gè)字段都加索引成績(jī)表寫(xiě)入頻繁索引過(guò)多拖慢導(dǎo)入。外鍵約束在課設(shè)里常有爭(zhēng)議加了外鍵刪除課程會(huì)報(bào)錯(cuò)不加又怕臟數(shù)據(jù)。我一般保留外鍵但設(shè)為ON DELETE RESTRICT先查成績(jī)?cè)賱h課程業(yè)務(wù)層給明確提示“該課程已有成績(jī)不能直接刪除”。如果為了演示方便改成邏輯刪除就要在查詢(xún)時(shí)統(tǒng)一帶上deleted 0否則統(tǒng)計(jì)會(huì)把刪掉的課程也算進(jìn)去。邏輯刪除字段用TINYINT而不是BOOLEAN方便后續(xù)擴(kuò)展刪除狀態(tài)。注意論文里寫(xiě)“使用外鍵保證參照完整性”沒(méi)問(wèn)題但代碼里要處理好刪除順序否則答辯演示時(shí)刪課程直接拋 500很尷尬。4. 成績(jī)管理模塊實(shí)現(xiàn)錄入、批量導(dǎo)入、修改與查詢(xún)的完整鏈路4.1 成績(jī)錄入與批量導(dǎo)入從Excel解析到入庫(kù)的容錯(cuò)處理單條錄入簡(jiǎn)單難的是批量導(dǎo)入。Excel 里可能有學(xué)號(hào)不存在、分?jǐn)?shù)超過(guò) 100、同一學(xué)生同一課程重復(fù)行。實(shí)現(xiàn)思路是先用 EasyExcel 讀成 DTO 列表逐行校驗(yàn)校驗(yàn)失敗的收集錯(cuò)誤行號(hào)返回給前端校驗(yàn)通過(guò)的按“存在則更新、不存在則插入”入庫(kù)。關(guān)鍵代碼在 Service 層Service public class ScoreServiceImpl implements ScoreService { Resource private StudentMapper studentMapper; Resource private CourseMapper courseMapper; Resource private ScoreMapper scoreMapper; Transactional(rollbackFor Exception.class) public ImportResult importScores(MultipartFile file, String term) { ListScoreImportDTO rows EasyExcel.read(file.getInputStream()) .head(ScoreImportDTO.class).sheet().doReadSync(); ListString errors new ArrayList(); for (int i 0; i rows.size(); i) { ScoreImportDTO row rows.get(i); // 校驗(yàn)學(xué)號(hào)和課程號(hào)是否存在避免寫(xiě)入孤兒成績(jī) Student student studentMapper.selectByStudentNo(row.getStudentNo()); Course course courseMapper.selectByCourseNo(row.getCourseNo()); if (student null) { errors.add(第 (i 2) 行學(xué)號(hào)不存在); continue; } if (course null) { errors.add(第 (i 2) 行課程號(hào)不存在); continue; } if (row.getScore() ! null (row.getScore().compareTo(BigDecimal.ZERO) 0 || row.getScore().compareTo(new BigDecimal(100)) 0)) { errors.add(第 (i 2) 行分?jǐn)?shù)必須在0-100之間); continue; } // 依賴(lài)聯(lián)合唯一索引做 upsert避免先查后插的并發(fā)重復(fù) Score score new Score(); score.setStudentId(student.getId()); score.setCourseId(course.getId()); score.setTerm(term); score.setScore(row.getScore()); scoreMapper.upsert(score); } return new ImportResult(rows.size() - errors.size(), errors); } }upsert在 Mapper XML 里用INSERT ... ON DUPLICATE KEY UPDATE這樣即使兩個(gè)老師同時(shí)導(dǎo)入同一門(mén)課也不會(huì)出現(xiàn)重復(fù)行。錯(cuò)誤行不中斷整批導(dǎo)入前端拿到errors列表后逐條修正再傳比整批回滾更實(shí)用。參數(shù)上term由前端選擇不在 Excel 里讀防止不同學(xué)期混在一個(gè)文件里。4.2 修改刪除與權(quán)限控制基于角色的數(shù)據(jù)范圍過(guò)濾成績(jī)修改必須留痕至少記錄update_time有條件的加操作日志表。權(quán)限分三種管理員看全部教師只看自己教的課程學(xué)生只看自己。實(shí)現(xiàn)上不信任前端傳的studentId從登錄 token 解析當(dāng)前用戶(hù)。教師角色在查成績(jī)時(shí)Service 層先查該教師所授課程 id 列表再把這些 id 作為in條件拼進(jìn)查詢(xún)學(xué)生角色則強(qiáng)制把student_id設(shè)為當(dāng)前用戶(hù) id。// 偽代碼按角色收窄查詢(xún)范圍 public PageScoreVO pageScores(ScoreQuery query, LoginUser user) { LambdaQueryWrapperScore wrapper new LambdaQueryWrapper(); wrapper.eq(Score::getTerm, query.getTerm()); if (TEACHER.equals(user.getRole())) { ListLong courseIds courseMapper.selectIdsByTeacherId(user.getId()); if (courseIds.isEmpty()) { return Page.empty(); } wrapper.in(Score::getCourseId, courseIds); } else if (STUDENT.equals(user.getRole())) { wrapper.eq(Score::getStudentId, user.getId()); // 強(qiáng)制覆蓋前端傳參 } // 管理員不加額外條件但支持按班級(jí)、課程篩選 return scoreMapper.selectPage(query.toPage(), wrapper); }刪除成績(jī)用邏輯刪除不物理刪否則學(xué)生查歷史成績(jī)時(shí)記錄憑空消失。教師不能刪除別人課程的成績(jī)?cè)趧h除前校驗(yàn)course.teacher_id是否等于當(dāng)前用戶(hù) id。這一步常被忽略答辯時(shí)被問(wèn)到“教師能不能改別的課成績(jī)”就露餡。4.3 查詢(xún)與統(tǒng)計(jì)報(bào)表接口多條件分頁(yè)與排名計(jì)算統(tǒng)計(jì)報(bào)表一般要班級(jí)排名、課程平均分、及格率。不要在前端算數(shù)據(jù)量一大就卡。排名用 MySQL 8 的窗口函數(shù)一次查出-- 按課程和學(xué)期計(jì)算學(xué)生排名分?jǐn)?shù)相同名次并列 SELECT s.student_id, st.name, s.score, RANK() OVER (PARTITION BY s.course_id, s.term ORDER BY s.score DESC) AS rank_no FROM score s JOIN student st ON st.id s.student_id WHERE s.course_id #{courseId} AND s.term #{term} AND s.deleted 0 ORDER BY rank_no;接口分頁(yè)時(shí)注意count查詢(xún)和列表查詢(xún)分開(kāi)寫(xiě)別用 MyBatis-Plus 的自動(dòng)分頁(yè)去套復(fù)雜 SQL容易生成低效的select count(*) from (子查詢(xún))。平均分和及格率用聚合查詢(xún)加ROUND(AVG(score),2)保留兩位。前端展示表格時(shí)把排名、平均分、及格率做成匯總行答辯演示時(shí)一眼能看到統(tǒng)計(jì)結(jié)果。提示統(tǒng)計(jì)接口要加緩存或至少限制查詢(xún)時(shí)間范圍否則全學(xué)期全課程一起算演示時(shí)頁(yè)面轉(zhuǎn)圈超過(guò)三秒評(píng)委耐心就沒(méi)了。5. 避坑與常見(jiàn)問(wèn)題排查從數(shù)據(jù)一致性到并發(fā)錄入的五個(gè)翻車(chē)點(diǎn)5.1 批量導(dǎo)入重復(fù)數(shù)據(jù)導(dǎo)致平均分翻倍現(xiàn)象同一份 Excel 導(dǎo)入兩次后課程平均分變成原來(lái)的兩倍但學(xué)生成績(jī)列表看起來(lái)正常。原因成績(jī)表沒(méi)有聯(lián)合唯一索引或者導(dǎo)入邏輯用“先查后插”并發(fā)時(shí)兩次都查不到就都插入。解決建(student_id, course_id, term)唯一索引導(dǎo)入用ON DUPLICATE KEY UPDATE并在導(dǎo)入結(jié)果里返回“更新了多少條、新增了多少條”讓操作人心里有數(shù)。5.2 修改成績(jī)后排名頁(yè)面還是舊數(shù)據(jù)現(xiàn)象老師改了某學(xué)生分?jǐn)?shù)刷新排名頁(yè)還是原來(lái)的名次。原因統(tǒng)計(jì)結(jié)果寫(xiě)進(jìn)了緩存或中間表修改成績(jī)時(shí)沒(méi)失效。解決排名實(shí)時(shí)用窗口函數(shù)算不落中間表如果為了性能必須緩存就在成績(jī)寫(xiě)操作后按course_id term刪緩存別用全量清空。5.3 學(xué)生越權(quán)查到別人成績(jī)現(xiàn)象學(xué)生端抓包改studentId就能看到同班同學(xué)成績(jī)。原因接口只按前端傳參過(guò)濾沒(méi)從登錄態(tài)取用戶(hù) id。解決在攔截器里把當(dāng)前用戶(hù)放進(jìn) ThreadLocalService 層對(duì)學(xué)生角色強(qiáng)制覆蓋查詢(xún)條件并加單元測(cè)試模擬篡改參數(shù)。5.4 刪除課程后成績(jī)表出現(xiàn)孤兒記錄現(xiàn)象課程管理里刪了一門(mén)課成績(jī)查詢(xún)里出現(xiàn)課程名為空的記錄。原因物理刪除課程但成績(jī)表沒(méi)處理或者邏輯刪除后查詢(xún)沒(méi)帶deleted 0。解決刪除課程前先查成績(jī)表是否有引用有則拒絕刪除并提示如果必須刪走級(jí)聯(lián)邏輯刪除并在統(tǒng)計(jì)查詢(xún)里統(tǒng)一過(guò)濾。5.5 深度分頁(yè)導(dǎo)致查詢(xún)變慢現(xiàn)象成績(jī)列表翻到第 100 頁(yè)時(shí)明顯卡頓。原因LIMIT 10000, 10這種深度分頁(yè)要掃描前一萬(wàn)行。解決限制最大可翻頁(yè)數(shù)或者改用游標(biāo)分頁(yè)按 id 或?qū)W號(hào)排序后傳上一頁(yè)最后一條的 id再或者在查詢(xún)條件里強(qiáng)制帶學(xué)期和課程縮小數(shù)據(jù)集。課設(shè)數(shù)據(jù)量不大但論文里寫(xiě)上這個(gè)取舍會(huì)加分。6. 驗(yàn)收與答辯一份測(cè)試清單和一個(gè)演示腳本驗(yàn)收別只看“頁(yè)面能打開(kāi)”按功能點(diǎn)和異常場(chǎng)景列清單。下面這張表可以直接放進(jìn)論文的測(cè)試章節(jié)測(cè)試項(xiàng)輸入或操作預(yù)期結(jié)果重復(fù)導(dǎo)入同一份成績(jī)同一 Excel 連續(xù)導(dǎo)入兩次第二次提示更新條數(shù)平均分不變學(xué)生越權(quán)查詢(xún)學(xué)生賬號(hào)請(qǐng)求時(shí)篡改 studentId返回 403 或僅返回本人數(shù)據(jù)刪除已有成績(jī)的課程管理員刪除課程提示“存在成績(jī)記錄不能刪除”分?jǐn)?shù)邊界錄入 -1 或 101接口返回校驗(yàn)錯(cuò)誤不入庫(kù)教師跨課程修改教師 A 修改教師 B 課程成績(jī)返回?zé)o權(quán)限答辯演示按“登錄—基礎(chǔ)數(shù)據(jù)—成績(jī)錄入—統(tǒng)計(jì)報(bào)表—異常演示”走控制在 5 分鐘內(nèi)。先展示管理員建課程、導(dǎo)入成績(jī)?cè)偾薪處熧~號(hào)看自己課程最后切學(xué)生賬號(hào)查個(gè)人成績(jī)中間故意觸發(fā)一次重復(fù)導(dǎo)入讓評(píng)委看到錯(cuò)誤提示和更新條數(shù)。這個(gè)順序比從頭到尾點(diǎn)菜單更有說(shuō)服力。從那以后我每次交付這類(lèi)系統(tǒng)都強(qiáng)制走一遍“臟數(shù)據(jù)導(dǎo)入 越權(quán)訪問(wèn) 重復(fù)提交”三連測(cè)不靠肉眼點(diǎn)頁(yè)面。希望這份方案能幫到你少走幾個(gè)我踩過(guò)的坑。本文還有配套的精品資源點(diǎn)擊獲取