微信小程式「學科排名」開發心得

剪影Boy發表於2018-01-16

前幾天,教育部公佈了《全國第四輪學科評估結果》,在手機上看起來不太方便,就“擼起袖子加油幹”,寫了一套指令碼把資料收集了一下,做成了微信小程式,叫「學科排名」。

介面

介面長這樣:

學校排名頁面

專業排名頁面

介面參考了一些優秀設計元素,儘量簡潔、易用。

資料庫

學科評估的結果,說白了就是某個高校的某個學科怎麼樣。資料庫設計如下:

CREATE TABLE `subject_ranking`  (
    `id` smallint(4) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID',
    `universityNum` mediumint(5) UNSIGNED NOT NULL COMMENT '高校程式碼',
    `university` varchar(10) NOT NULL COMMENT '高校名稱',
    `universityLogo` varchar(31) NOT NULL COMMENT '高校校徽',
    `klassCode` char(2) NOT NULL COMMENT '學科門類程式碼',
    `klass` varchar(5) NOT NULL COMMENT '學科門類名稱',
    `subjectCode` char(4) NOT NULL COMMENT '學科程式碼',
    `subject` varchar(10) NOT NULL COMMENT '學科名稱',
    `resultNum` tinyint(1) UNSIGNED NOT NULL COMMENT '學科評估結果',
    PRIMARY KEY (`id`) USING BTREE
);
複製程式碼

高校程式碼有5位,如北京大學的是10001,其他大學的都比這個數大,所以就用了整型。

學科評估結果用數字1-9來表示,其具體含義和對應關係如下表:

數字 1 2 3 4 5 6 7 8 9
結果 A+ A A- B+ B B- C+ C C-
含義 前2%或前2名 2%~5% 5%~10% 10%~20% 20%~30% 30%~40% 40%~50% 50%~60% 60%~70%

具體資料是通過爬蟲指令碼從官網獲取的,有5000+條資料。

考慮到後端用到了兩個SELECT語句,一個是按學科程式碼,一個是按高校程式碼,建立兩個單列索引:

ALTER TABLE `subject_ranking` ADD INDEX `idx_subjectCode`(`subjectCode`) USING BTREE;
ALTER TABLE `subject_ranking` ADD INDEX `idx_universityNum`(`universityNum`) USING BTREE;
複製程式碼

校徽

為了讓高校排名頁面視覺上更簡潔大方,加上校徽元素是個不錯的選擇。

<image class="university-logo" src="{{item.universityLogo}}" mode="aspectFit"></image>
複製程式碼

由於校徽是圖片形式,載入需要一定的時間。為了更好的體驗,有必要上CDN,即內容分發網路。這裡採用的是七牛雲的物件儲存。

資料庫中不同高校有近500所,校徽欄位universityLogo只需儲存檔名稱,待響應請求的時候補全外鏈即可。

學科選擇器

高校排名頁面有個二級聯動學科選擇器,先選學科門類,再選當前門類下的學科。考慮到學科資料不多,也不會變更,所以將這部分資料放在本地了。

其資料結構如下:

[
    {
        "klassCode": "06",
        "klass": "人文社科類",
        "children": [
            {
                "subjectCode": "0101",
                "subject": "哲學"
            },
            {
                "subjectCode": "0201",
                "subject": "理論經濟學"
            },
            ...
        ]
    },
    {
        "klassCode": "07",
        "klass": "理學",
        "children": [
            {
                "subjectCode": "0701",
                "subject": "數學"
            },
            {
                "subjectCode": "0702",
                "subject": "物理學"
            },
            ...
        ]
    },
    ...
]
複製程式碼

使用兩個普通選擇器元件就可以方便地實現二級聯動。

<view class="selector">
    <picker class="picker" bindchange="bindKlassPickerChange" value="{{klassIdx}}" range="{{klasses}}" range-key="klass">
        <view class="picker-wrapper">{{klasses[klassIdx].klass}}</view>
    </picker>
    <picker class="picker" bindchange="bindSubjectPickerChange" value="{{subjectIdx}}" range="{{subjects}}" range-key="subject">
        <view class="picker-wrapper">{{util.getSubject4Short(subjects[subjectIdx].subject, 8)}}</view>
    </picker>
</view>
複製程式碼

高校列表

高校排名頁面每次載入時,按選定學科去請求高校排名資料。不少學科對應的高校資料量很大,而我們首先看到的只是前幾個,可以對高校列表進行分頁。

結合實際情況,只分兩步走——首先請求前10條高校記錄,然後請求剩下的部分。當然,如果第一次請求獲得的高校記錄少於10條,也就沒必要再次請求了。

分步請求的邏輯如下:

requestUniversities: function () {
    wx.showNavigationBarLoading();
    wx.request({
        url: config.getUniversityRankingUrl(this.data.subjects[this.data.subjectIdx].subjectCode, 1),
        success: (res) => {
            wx.hideNavigationBarLoading();
            this.setData({
                universities: res.data.data
            });
            if (this.data.universities.length === 10) {
                wx.request({
                    url: config.getUniversityRankingUrl(this.data.subjects[this.data.subjectIdx].subjectCode, 0),
                    success: (res) => {
                        this.setData({
                            universities: this.data.universities.concat(res.data.data)
                        });
                    }
                });
            }
        }
    });
}
複製程式碼

採用分步載入後,首頁載入速度提升明顯,加上校徽給力的CDN,次次秒開不是夢。

rpx在Plus機型的一處Bug

先看現象:

rpx在Plus機型的Bug

就是中間的那條白線——它並不是設計元素!

對應的CSS程式碼如下:

.background {
    position: relative;

    height: 375rpx;

    background-color: #4facf7;
}
.background::after {
    position: absolute;
    bottom: -150rpx;
    left: 0;

    border-top: 150rpx solid #4facf7;
    border-right: 375rpx solid transparent;
    border-left: 375rpx solid transparent;
    width: 0;
    height: 0;

    content: "";
}
複製程式碼

經過測試,發現當螢幕寬度大於375px時,會出現這個Bug。顯然,這個問題是由於rpx換算px的誤差被放大導致的。

解決的思路也簡單——當螢幕寬度大於375px時,往上挪1px就好了。

.background-plus::after {
    bottom: calc(-150rpx + 1px);
}
複製程式碼

那怎麼判斷螢幕寬度大於375px?小程式提供了現成的API:

wx.getSystemInfo({
    success: (res) => {
        if (res.screenWidth > 375) {
            this.isPlus = true;
        }
    }
});
複製程式碼

小程式碼

小程式「學科排名」已釋出,歡迎體驗。

學科排名

個人技術部落格 biebu.xin,原文連結——微信小程式「學科排名」開發心得

相關文章