<center class="half">
<img src="http://silianpan.cn/wp-conten...; width="230"/>
<img src="http://silianpan.cn/wp-conten...; width="285"/>
<img src="http://silianpan.cn/wp-conten...; width="220"/>
</center>
一、前言
uniapp-admin是基於uni-app開發的管理系統模板。該模板集成了如下的功能:
- UI方面:登陸模板、頂部固定搜索框、頂部滑動選項卡、字段信息卡片、一週信息卡片、時間軸
- 功能方面:下拉刷新上拉加載功能、文件在線預覽功能
- 內置組件:底部標籤導航、頂部導航欄、商品導航、uni ui
-
第三方插件
-
解決方案(重要)
- 文件在線預覽方案,另見文章《跨平臺(uni-app)文件在線預覽解決方案》
- 開發環境和生產環境跨域方案
- APP整包升級/更新方案
- API調用方案
如果有欠缺的地方,或者有更好的想法,大家可以多多交流,文章最後可以加我。
二、開發環境和生產環境跨域方案
跨域的解決方法之一就是採用代理
2.1 開發環境
- 在manifest.json源碼視圖中,修改h5部分,添加端口port和代理proxy。
"h5" : {
"devServer" : {
"port" : 9090,
"disableHostCheck" : true,
"proxy" : {
"/ua/ua-service" : {
"target" : "http://localhost:8080",
"changeOrigin" : true,
"secure" : false,
"pathRewrite" : {
"^/ua" : ""
}
},
"/ua-service" : {
"target" : "http://localhost:8080",
"changeOrigin" : true,
"secure" : false
}
}
},
"title" : "uniapp-admin",
"router" : {
"mode" : "hash",
"base" : "/ua"
}
}
- 根據不同平臺,自定義全局配置baseUrl,參考代碼
原理:h5端配置api前綴,然後proxy代理(在manifest.json的proxy);
APP端不存在跨域問題,直接配置全域名或ip地址即可
/**
* ip地址或域名
*/
const ipAddress = 'http://localhost:8080'
// 文件訪問地址
const fileAddr = 'http://localhost:8082/fileUpload/'
/**
* api前綴
*/
const apiPrefix = '/ua-service'
/**
* 針對不同平臺的baseUrl
*/
const getBaseUrl = () => {
// #ifdef H5
return apiPrefix
// #endif
// #ifndef H5
return ipAddress + apiPrefix
// #endif
}
export default {
/**
* 針對不同平臺的baseUrl
*/
baseUrl: getBaseUrl(),
fileAddr
}
- 在ui.request的參數選項中配置baseUrl,參考代碼
// 設置默認配置
minRequest.setConfig((config) => {
config.baseURL = globalConfig.baseUrl
return config
})
2.2 生產環境
生產環境的跨域,典型的方案就是採用Nginx代理
配置如下:
# 前端訪問代理
location /ua {
alias /root/ua;
index index.html index.htm;
try_files $uri $uri/ /index.html?/$request_uri;
}
# 服務端代理,對應開發環境proxy
location ~/ua/ua-service/* {
rewrite ^/ua/(.*)$ /$1 break;
proxy_pass http://service;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 360000s;
proxy_read_timeout 360000s;
proxy_send_timeout 360000s;
}
# 服務端代理,對應開發環境proxy
location ~/ua-service/* {
proxy_pass http://service;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 360000s;
proxy_read_timeout 360000s;
proxy_send_timeout 360000s;
}
其中proxy_pass http://service的service是配置在nginx的http{}下的後端服務
upstream service {
server 127.0.0.1:8080 max_fails=1 fail_timeout=10s;
}
rewrite ^/ua/(.*)$ \/\$1 break;是路徑替換,第一個參數是正則表達式,$1是正則表達式中第一個括號內容。
三、APP整包升級/更新方案
參考文檔,uni-app 整包升級/更新方案 ,另外也有,uni-app 資源在線升級/熱更新
本項目是採用整包升級更新方案,如下:
/**
* app整包更新檢測
*/
appUpgrade() {
//#ifndef APP-PLUS
uni.showToast({
title: '目前只支持Android版本軟件更新',
icon: 'none'
})
//#endif
//#ifdef APP-PLUS
uni.getSystemInfo({
success: sysInfo => {
let platform = sysInfo.platform
plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
// app版本字符串如:1.1.0
// this.appInfo.version = wgtinfo.version
// app名稱
// this.appInfo.name = wgtinfo.name
let params = {
appid: plus.runtime.appid,
// app整數版本號,如110,一定要用versionCode做判斷
version: wgtinfo.versionCode,
platform: platform
}
this.$minApi.findUpgradeApp(params).then(appRes => {
if (appRes.appid) {
uni.showModal({
title: "下載更新提示",
content: appRes.note,
showCancel: false,
confirmText: '確定',
success: sucRes => {
if (sucRes.confirm) {
plus.runtime.openURL(appRes.url)
// uni.downloadFile({
// url: appRes.url,
// success: res => {}
// })
}
}
})
} else {
uni.showToast({
title: '已經是最新版本了。',
icon: 'none'
})
}
})
})
}
})
//#endif
}
<span style="color:red">注意:一定要使用plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) =>()),回調函數返回的wgtinfo對象的versionCode做判斷,wgtinfo.version是版本字符串,wgtinfo.name是app應用名稱</span>
四、API調用方案
核心是調用uni.request,參考代碼
request(options = {}) {
options.baseURL = options.baseURL || this[config].baseURL
options.dataType = options.dataType || this[config].dataType
options.url = MinRequest[isCompleteURL](options.url) ? options.url : (options.baseURL + options.url)
options.data = options.data
options.header = { ...options.header,
...this[config].header
}
options.method = options.method || this[config].method
options = { ...options,
...MinRequest[requestBefore](options)
}
return new Promise((resolve, reject) => {
options.success = function(res) {
resolve(MinRequest[requestAfter](res))
}
options.fail = function(err) {
reject(MinRequest[requestAfter](err))
}
uni.request(options)
})
}
五、問題解決
5.1 怎麼獲取應用真正的名稱和版本信息?
一定要使用plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) =>()),回調函數返回的wgtinfo對象的versionCode做判斷,wgtinfo.version是版本字符串,wgtinfo.name是app應用名稱
5.2 APP端,模板中v-for不能調用方法,如:v-for="xxx in func(xxx)",這種情況下,func方法不會調用。具體原理不太清楚,還請大佬能解釋一下不?
解決辦法:提前將數據格式化好,然後套上模板。
六、後續計劃
- [ ] 消息推送
大家也可以提出想要的模板或功能
七、效果
H5
<img src="http://silianpan.cn/wp-conten...; width="120" alt="h5"/>
Android APK
<img src="http://silianpan.cn/wp-conten...; width="120" alt="android-apk"/>
<center>開源不易,且用且珍惜!</center>
<center style="font-size:20px">贊助作者</center>
<center class="half">
<img src="http://silianpan.cn/wp-conten...; width="240"/>
<img src="http://silianpan.cn/wp-conten...; width="240" />
</center>