Browse Source

first commit

master
unknown 1 year ago
commit
5798c336b9
  1. 7
      .gitignore
  2. 20
      App.vue
  3. 0
      README.md
  4. 65
      common/css/app.scss
  5. 96
      common/js/utils.js
  6. 741
      common/sdk/qqmap-wx-jssdk.js
  7. 3
      common/sdk/qqmap-wx-jssdk.min.js
  8. 130
      components/UserTab/UserTab - 副本.vue
  9. 117
      components/UserTab/UserTab.vue
  10. 10
      config/api.js
  11. 52
      config/request.js
  12. 20
      index.html
  13. 37
      main.js
  14. 100
      manifest.json
  15. 15
      package.json
  16. 104
      pages.json
  17. 60
      pages/index/index.vue
  18. 27
      pages/other/webView/webView.vue
  19. 404
      pages/tabbar/index/index.vue
  20. 30
      pages/tabbar/learnCar/index.vue
  21. 31
      pages/tabbar/mine/index.vue
  22. 71
      pages/userCenter/login/login.vue
  23. 187
      pages/userCenter/login/loginByPhone.vue
  24. 28
      project.config.json
  25. 7
      project.private.config.json
  26. 12
      site.config.js
  27. BIN
      static/images/bigImg/index_banner.png
  28. BIN
      static/images/index/dingwei.png
  29. BIN
      static/images/index/ic_baoming.png
  30. BIN
      static/images/index/ic_jiaxiao.png
  31. BIN
      static/images/index/ic_kaochang.png
  32. BIN
      static/images/index/ic_lilun.png
  33. BIN
      static/images/index/ic_peilian.png
  34. BIN
      static/images/index/img_1@2x.png
  35. BIN
      static/images/index/img_2@2x.png
  36. BIN
      static/images/index/img_3@2x.png
  37. BIN
      static/images/index/img_4@2x.png
  38. BIN
      static/images/index/img_5@2x.png
  39. BIN
      static/images/index/img_6@2x.png
  40. BIN
      static/images/index/scan.png
  41. BIN
      static/images/index/searchIcon.png
  42. BIN
      static/images/index/我的@2x.png
  43. BIN
      static/images/index/报名@2x.png
  44. BIN
      static/images/index/首页@2x.png
  45. BIN
      static/images/logo.png
  46. BIN
      static/images/tabbar/btn_shouye_cli.png
  47. BIN
      static/images/tabbar/btn_shouye_nor.png
  48. BIN
      static/images/tabbar/btn_wode_cli.png
  49. BIN
      static/images/tabbar/btn_wode_nor.png
  50. BIN
      static/images/tabbar/btn_xueche_cli.png
  51. BIN
      static/images/tabbar/btn_xueche_nor.png
  52. BIN
      static/images/tabbar/sy.png
  53. BIN
      static/images/tabbar/syActive.png
  54. BIN
      static/images/tabbar/tk.png
  55. BIN
      static/images/tabbar/tkActive.png
  56. BIN
      static/images/tabbar/wd.png
  57. BIN
      static/images/tabbar/wdActive.png
  58. BIN
      static/images/tabbar/zx.png
  59. BIN
      static/images/tabbar/zxActive.png
  60. BIN
      static/images/userCenter/loginTopBg.png
  61. BIN
      static/images/userCenter/title_1.png
  62. BIN
      static/images/登录流程切图/__MACOSX/登录流程切图/._.DS_Store
  63. BIN
      static/images/登录流程切图/__MACOSX/登录流程切图/._btn_1.png
  64. BIN
      static/images/登录流程切图/登录流程切图/.DS_Store
  65. BIN
      static/images/登录流程切图/登录流程切图/bg_1.png
  66. BIN
      static/images/登录流程切图/登录流程切图/btn_1.png
  67. BIN
      static/images/登录流程切图/登录流程切图/btn_2.png
  68. BIN
      static/images/登录流程切图/登录流程切图/title_1.png
  69. BIN
      static/logo.png
  70. 21
      store/getters.js
  71. 90
      store/index.js
  72. 91
      store/modules/add.js
  73. 31
      store/modules/user.js
  74. 10
      uni.promisify.adaptor.js
  75. 80
      uni.scss
  76. 6
      uni_modules/uni-config-center/changelog.md
  77. 81
      uni_modules/uni-config-center/package.json
  78. 93
      uni_modules/uni-config-center/readme.md
  79. 1
      uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
  80. 9
      uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json
  81. 25
      uni_modules/uni-open-bridge-common/changelog.md
  82. 84
      uni_modules/uni-open-bridge-common/package.json
  83. 5
      uni_modules/uni-open-bridge-common/readme.md
  84. 26
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js
  85. 124
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js
  86. 30
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js
  87. 317
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js
  88. 15
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json
  89. 111
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js
  90. 324
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js
  91. 31
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js
  92. 203
      uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js
  93. 19
      uni_modules/uni-open-bridge-common/uniCloud/database/opendb-open-data.schema.json
  94. 8
      uni_modules/uni-scss/changelog.md
  95. 1
      uni_modules/uni-scss/index.scss
  96. 82
      uni_modules/uni-scss/package.json
  97. 4
      uni_modules/uni-scss/readme.md
  98. 7
      uni_modules/uni-scss/styles/index.scss
  99. 3
      uni_modules/uni-scss/styles/setting/_border.scss
  100. 66
      uni_modules/uni-scss/styles/setting/_color.scss

7
.gitignore

@ -0,0 +1,7 @@
node_modules
package-lock.json
unpackage/dist
unpackage/cache
.hbuilderx
unpackage

20
App.vue

@ -0,0 +1,20 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch')
// uni.hideTabBar();
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
/*每个页面公共css */
@import '@/uni_modules/uview-ui/index.scss';
@import 'common/css/app.scss'
</style>

0
README.md

65
common/css/app.scss

@ -0,0 +1,65 @@
page {
background-color: #fff;
font-size: 32rpx;
font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif;
}
view {
box-sizing: border-box;
}
.oneRowText {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.towRowText {
display: -webkit-box;
overflow: hidden;
white-space: normal;
text-overflow: ellipsis;
word-wrap: break-word;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical
}
.bgLinear {
background: linear-gradient(180deg, #3593FB 0%, #53D3E5 100%);
}
.flex-b {
justify-content: space-between;
display: flex;
align-items: center;
}
.flex {
display: flex;
align-items: center;
}
.pageBg {
background: #F6F6F6;
}
.pad {
padding: 0 28rpx;
}
.status_bar {
height: var(--status-bar-height);
width: 100%;
}
image {
display: block;
width: 100%;
height: 100%;
}
.placeholderClassFFF {
color: #fff !important;
}
.star {
display: flex;
align-items: center;
.starText {
font-size: 26rpx;
color: #F5682D;
}
}
.my .u-input {
height: 100%;
}

96
common/js/utils.js

@ -0,0 +1,96 @@
import store from '@/store';
const install = (Vue, vm) => {
// 打开地图
const openMap = (lat, lng) => {
uni.openLocation({
latitude: lat,
longitude: lng
})
}
// 距离换算
const distanceFn = (val) => {
if (val * 1 < 1000) {
return val + '米'
} else {
return (val / 1000).toFixed(2) + '公里'
}
}
// 价格计算
const priceTo = (price = 0) => {
// return (price / 100).toFixed(2)
return (parseInt(price * 100) / 100 / 100).toFixed(2)
}
const distanceLatLng = (lat1, lng1) => {
var that = this;
let lat2 = store.state.latLng.lat;
let lng2 = store.state.latLng.lng;
let rad1 = lat1 * Math.PI / 180.0;
let rad2 = lat2 * Math.PI / 180.0;
let a = rad1 - rad2;
let b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(rad1) *
Math.cos(
rad2) * Math.pow(
Math.sin(b / 2), 2)));
s = s * 6378.137;
s = Math.round(s * 10000) / 10000;
s = s.toString();
s = s.substring(0, s.indexOf('.') + 2);
return s
}
const getLocation = () => {
return new Promise((resolve, reject) => {
uni.getLocation({
type: 'wgs84',
success: function(res) {
console.log('当前位置的经度:' + res.longitude);
console.log('当前位置的纬度:' + res.latitude);
let obj = {
lat: res.latitude,
lng: res.longitude
}
store.commit('updateLatLng', obj)
resolve(obj)
}
});
}).catch((e) => {})
}
function addZeroPrefix(number) {
return number < 10 ? `0${number}` : number
}
let getDate = (date, splitor = '-') => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
return `${year}${splitor}${addZeroPrefix(month)}${splitor}${addZeroPrefix(day)}`
}
vm.$u.utils = {
openMap,
getLocation,
priceTo,
distanceLatLng,
distanceFn,
getDate,
}
}
export default {
install
}

741
common/sdk/qqmap-wx-jssdk.js

@ -0,0 +1,741 @@
/**
* 微信小程序JavaScriptSDK
*
* @version 1.1
* @date 2019-01-20
*/
var ERROR_CONF = {
KEY_ERR: 311,
KEY_ERR_MSG: 'key格式错误',
PARAM_ERR: 310,
PARAM_ERR_MSG: '请求参数信息有误',
SYSTEM_ERR: 600,
SYSTEM_ERR_MSG: '系统错误',
WX_ERR_CODE: 1000,
WX_OK_CODE: 200
};
var BASE_URL = 'https://apis.map.qq.com/ws/';
var URL_SEARCH = BASE_URL + 'place/v1/search';
var URL_SUGGESTION = BASE_URL + 'place/v1/suggestion';
var URL_GET_GEOCODER = BASE_URL + 'geocoder/v1/';
var URL_CITY_LIST = BASE_URL + 'district/v1/list';
var URL_AREA_LIST = BASE_URL + 'district/v1/getchildren';
var URL_DISTANCE = BASE_URL + 'distance/v1/';
var EARTH_RADIUS = 6378136.49;
var Utils = {
/**
* 得到终点query字符串
* @param {Array|String} 检索数据
*/
location2query(data) {
if (typeof data == 'string') {
return data;
}
var query = '';
for (var i = 0; i < data.length; i++) {
var d = data[i];
if (!!query) {
query += ';';
}
if (d.location) {
query = query + d.location.lat + ',' + d.location.lng;
}
if (d.latitude && d.longitude) {
query = query + d.latitude + ',' + d.longitude;
}
}
return query;
},
/**
* 计算角度
*/
rad(d) {
return d * Math.PI / 180.0;
},
/**
* 处理终点location数组
* @return 返回终点数组
*/
getEndLocation(location){
var to = location.split(';');
var endLocation = [];
for (var i = 0; i < to.length; i++) {
endLocation.push({
lat: parseFloat(to[i].split(',')[0]),
lng: parseFloat(to[i].split(',')[1])
})
}
return endLocation;
},
/**
* 计算两点间直线距离
* @param a 表示纬度差
* @param b 表示经度差
* @return 返回的是距离单位m
*/
getDistance(latFrom, lngFrom, latTo, lngTo) {
var radLatFrom = this.rad(latFrom);
var radLatTo = this.rad(latTo);
var a = radLatFrom - radLatTo;
var b = this.rad(lngFrom) - this.rad(lngTo);
var distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLatFrom) * Math.cos(radLatTo) * Math.pow(Math.sin(b / 2), 2)));
distance = distance * EARTH_RADIUS;
distance = Math.round(distance * 10000) / 10000;
return parseFloat(distance.toFixed(0));
},
/**
* 使用微信接口进行定位
*/
getWXLocation(success, fail, complete) {
wx.getLocation({
type: 'gcj02',
success: success,
fail: fail,
complete: complete
});
},
/**
* 获取location参数
*/
getLocationParam(location) {
if (typeof location == 'string') {
var locationArr = location.split(',');
if (locationArr.length === 2) {
location = {
latitude: location.split(',')[0],
longitude: location.split(',')[1]
};
} else {
location = {};
}
}
return location;
},
/**
* 回调函数默认处理
*/
polyfillParam(param) {
param.success = param.success || function () { };
param.fail = param.fail || function () { };
param.complete = param.complete || function () { };
},
/**
* 验证param对应的key值是否为空
*
* @param {Object} param 接口参数
* @param {String} key 对应参数的key
*/
checkParamKeyEmpty(param, key) {
if (!param[key]) {
var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + key +'参数格式有误');
param.fail(errconf);
param.complete(errconf);
return true;
}
return false;
},
/**
* 验证参数中是否存在检索词keyword
*
* @param {Object} param 接口参数
*/
checkKeyword(param){
return !this.checkParamKeyEmpty(param, 'keyword');
},
/**
* 验证location值
*
* @param {Object} param 接口参数
*/
checkLocation(param) {
var location = this.getLocationParam(param.location);
if (!location || !location.latitude || !location.longitude) {
var errconf = this.buildErrorConfig(ERROR_CONF.PARAM_ERR, ERROR_CONF.PARAM_ERR_MSG + ' location参数格式有误');
param.fail(errconf);
param.complete(errconf);
return false;
}
return true;
},
/**
* 构造错误数据结构
* @param {Number} errCode 错误码
* @param {Number} errMsg 错误描述
*/
buildErrorConfig(errCode, errMsg) {
return {
status: errCode,
message: errMsg
};
},
/**
*
* 数据处理函数
* 根据传入参数不同处理不同数据
* @param {String} feature 功能名称
* search 地点搜索
* suggest关键词提示
* reverseGeocoder逆地址解析
* geocoder地址解析
* getCityList获取城市列表父集
* getDistrictByCityId获取区县列表子集
* calculateDistance距离计算
* @param {Object} param 接口参数
* @param {Object} data 数据
*/
handleData(param,data,feature){
if (feature === 'search') {
var searchResult = data.data;
var searchSimplify = [];
for (var i = 0; i < searchResult.length; i++) {
searchSimplify.push({
id: searchResult[i].id || null,
title: searchResult[i].title || null,
latitude: searchResult[i].location && searchResult[i].location.lat || null,
longitude: searchResult[i].location && searchResult[i].location.lng || null,
address: searchResult[i].address || null,
category: searchResult[i].category || null,
tel: searchResult[i].tel || null,
adcode: searchResult[i].ad_info && searchResult[i].ad_info.adcode || null,
city: searchResult[i].ad_info && searchResult[i].ad_info.city || null,
district: searchResult[i].ad_info && searchResult[i].ad_info.district || null,
province: searchResult[i].ad_info && searchResult[i].ad_info.province || null
})
}
param.success(data, {
searchResult: searchResult,
searchSimplify: searchSimplify
})
} else if (feature === 'suggest') {
var suggestResult = data.data;
var suggestSimplify = [];
for (var i = 0; i < suggestResult.length; i++) {
suggestSimplify.push({
adcode: suggestResult[i].adcode || null,
address: suggestResult[i].address || null,
category: suggestResult[i].category || null,
city: suggestResult[i].city || null,
district: suggestResult[i].district || null,
id: suggestResult[i].id || null,
latitude: suggestResult[i].location && suggestResult[i].location.lat || null,
longitude: suggestResult[i].location && suggestResult[i].location.lng || null,
province: suggestResult[i].province || null,
title: suggestResult[i].title || null,
type: suggestResult[i].type || null
})
}
param.success(data, {
suggestResult: suggestResult,
suggestSimplify: suggestSimplify
})
} else if (feature === 'reverseGeocoder') {
var reverseGeocoderResult = data.result;
var reverseGeocoderSimplify = {
address: reverseGeocoderResult.address || null,
latitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lat || null,
longitude: reverseGeocoderResult.location && reverseGeocoderResult.location.lng || null,
adcode: reverseGeocoderResult.ad_info && reverseGeocoderResult.ad_info.adcode || null,
city: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.city || null,
district: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.district || null,
nation: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.nation || null,
province: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.province || null,
street: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street || null,
street_number: reverseGeocoderResult.address_component && reverseGeocoderResult.address_component.street_number || null,
recommend: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.recommend || null,
rough: reverseGeocoderResult.formatted_addresses && reverseGeocoderResult.formatted_addresses.rough || null
};
if (reverseGeocoderResult.pois) {//判断是否返回周边poi
var pois = reverseGeocoderResult.pois;
var poisSimplify = [];
for (var i = 0;i < pois.length;i++) {
poisSimplify.push({
id: pois[i].id || null,
title: pois[i].title || null,
latitude: pois[i].location && pois[i].location.lat || null,
longitude: pois[i].location && pois[i].location.lng || null,
address: pois[i].address || null,
category: pois[i].category || null,
adcode: pois[i].ad_info && pois[i].ad_info.adcode || null,
city: pois[i].ad_info && pois[i].ad_info.city || null,
district: pois[i].ad_info && pois[i].ad_info.district || null,
province: pois[i].ad_info && pois[i].ad_info.province || null
})
}
param.success(data,{
reverseGeocoderResult: reverseGeocoderResult,
reverseGeocoderSimplify: reverseGeocoderSimplify,
pois: pois,
poisSimplify: poisSimplify
})
} else {
param.success(data, {
reverseGeocoderResult: reverseGeocoderResult,
reverseGeocoderSimplify: reverseGeocoderSimplify
})
}
} else if (feature === 'geocoder') {
var geocoderResult = data.result;
var geocoderSimplify = {
title: geocoderResult.title || null,
latitude: geocoderResult.location && geocoderResult.location.lat || null,
longitude: geocoderResult.location && geocoderResult.location.lng || null,
adcode: geocoderResult.ad_info && geocoderResult.ad_info.adcode || null,
province: geocoderResult.address_components && geocoderResult.address_components.province || null,
city: geocoderResult.address_components && geocoderResult.address_components.city || null,
district: geocoderResult.address_components && geocoderResult.address_components.district || null,
street: geocoderResult.address_components && geocoderResult.address_components.street || null,
street_number: geocoderResult.address_components && geocoderResult.address_components.street_number || null,
level: geocoderResult.level || null
};
param.success(data,{
geocoderResult: geocoderResult,
geocoderSimplify: geocoderSimplify
});
} else if (feature === 'getCityList') {
var provinceResult = data.result[0];
var cityResult = data.result[1];
var districtResult = data.result[2];
param.success(data,{
provinceResult: provinceResult,
cityResult: cityResult,
districtResult: districtResult
});
} else if (feature === 'getDistrictByCityId') {
var districtByCity = data.result[0];
param.success(data, districtByCity);
} else if (feature === 'calculateDistance') {
var calculateDistanceResult = data.result.elements;
var distance = [];
for (var i = 0; i < calculateDistanceResult.length; i++){
distance.push(calculateDistanceResult[i].distance);
}
param.success(data, {
calculateDistanceResult: calculateDistanceResult,
distance: distance
});
} else {
param.success(data);
}
},
/**
* 构造微信请求参数公共属性处理
*
* @param {Object} param 接口参数
* @param {Object} param 配置项
* @param {String} feature 方法名
*/
buildWxRequestConfig(param, options, feature) {
var that = this;
options.header = { "content-type": "application/json" };
options.method = 'GET';
options.success = function (res) {
var data = res.data;
if (data.status === 0) {
that.handleData(param, data, feature);
} else {
param.fail(data);
}
};
options.fail = function (res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE;
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
};
options.complete = function (res) {
var statusCode = +res.statusCode;
switch(statusCode) {
case ERROR_CONF.WX_ERR_CODE: {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
break;
}
case ERROR_CONF.WX_OK_CODE: {
var data = res.data;
if (data.status === 0) {
param.complete(data);
} else {
param.complete(that.buildErrorConfig(data.status, data.message));
}
break;
}
default:{
param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR, ERROR_CONF.SYSTEM_ERR_MSG));
}
}
};
return options;
},
/**
* 处理用户参数是否传入坐标进行不同的处理
*/
locationProcess(param, locationsuccess, locationfail, locationcomplete) {
var that = this;
locationfail = locationfail || function (res) {
res.statusCode = ERROR_CONF.WX_ERR_CODE;
param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
};
locationcomplete = locationcomplete || function (res) {
if (res.statusCode == ERROR_CONF.WX_ERR_CODE) {
param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE, res.errMsg));
}
};
if (!param.location) {
that.getWXLocation(locationsuccess, locationfail, locationcomplete);
} else if (that.checkLocation(param)) {
var location = Utils.getLocationParam(param.location);
locationsuccess(location);
}
}
};
class QQMapWX {
/**
* 构造函数
*
* @param {Object} options 接口参数,key 为必选参数
*/
constructor(options) {
if (!options.key) {
throw Error('key值不能为空');
}
this.key = options.key;
};
/**
* POI周边检索
*
* @param {Object} options 接口参数对象
*
* 参数对象结构可以参考
* @see http://lbs.qq.com/webservice_v1/guide-search.html
*/
search(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
if (!Utils.checkKeyword(options)) {
return;
}
var requestParam = {
keyword: options.keyword,
orderby: options.orderby || '_distance',
page_size: options.page_size || 10,
page_index: options.page_index || 1,
output: 'json',
key: that.key
};
if (options.address_format) {
requestParam.address_format = options.address_format;
}
if (options.filter) {
requestParam.filter = options.filter;
}
var distance = options.distance || "1000";
var auto_extend = options.auto_extend || 1;
var region = null;
var rectangle = null;
//判断城市限定参数
if (options.region) {
region = options.region;
}
//矩形限定坐标(暂时只支持字符串格式)
if (options.rectangle) {
rectangle = options.rectangle;
}
var locationsuccess = function (result) {
if (region && !rectangle) {
//城市限定参数拼接
requestParam.boundary = "region(" + region + "," + auto_extend + "," + result.latitude + "," + result.longitude + ")";
} else if (rectangle && !region) {
//矩形搜索
requestParam.boundary = "rectangle(" + rectangle + ")";
} else {
requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")";
}
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_SEARCH,
data: requestParam
}, 'search'));
};
Utils.locationProcess(options, locationsuccess);
};
/**
* sug模糊检索
*
* @param {Object} options 接口参数对象
*
* 参数对象结构可以参考
* http://lbs.qq.com/webservice_v1/guide-suggestion.html
*/
getSuggestion(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
if (!Utils.checkKeyword(options)) {
return;
}
var requestParam = {
keyword: options.keyword,
region: options.region || '全国',
region_fix: options.region_fix || 0,
policy: options.policy || 0,
page_size: options.page_size || 10,//控制显示条数
page_index: options.page_index || 1,//控制页数
get_subpois : options.get_subpois || 0,//返回子地点
output: 'json',
key: that.key
};
//长地址
if (options.address_format) {
requestParam.address_format = options.address_format;
}
//过滤
if (options.filter) {
requestParam.filter = options.filter;
}
//排序
if (options.location) {
var locationsuccess = function (result) {
requestParam.location = result.latitude + ',' + result.longitude;
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_SUGGESTION,
data: requestParam
}, "suggest"));
};
Utils.locationProcess(options, locationsuccess);
} else {
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_SUGGESTION,
data: requestParam
}, "suggest"));
}
};
/**
* 逆地址解析
*
* @param {Object} options 接口参数对象
*
* 请求参数结构可以参考
* http://lbs.qq.com/webservice_v1/guide-gcoder.html
*/
reverseGeocoder(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
var requestParam = {
coord_type: options.coord_type || 5,
get_poi: options.get_poi || 0,
output: 'json',
key: that.key
};
if (options.poi_options) {
requestParam.poi_options = options.poi_options
}
var locationsuccess = function (result) {
requestParam.location = result.latitude + ',' + result.longitude;
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_GET_GEOCODER,
data: requestParam
}, 'reverseGeocoder'));
};
Utils.locationProcess(options, locationsuccess);
};
/**
* 地址解析
*
* @param {Object} options 接口参数对象
*
* 请求参数结构可以参考
* http://lbs.qq.com/webservice_v1/guide-geocoder.html
*/
geocoder(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
if (Utils.checkParamKeyEmpty(options, 'address')) {
return;
}
var requestParam = {
address: options.address,
output: 'json',
key: that.key
};
//城市限定
if (options.region) {
requestParam.region = options.region;
}
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_GET_GEOCODER,
data: requestParam
},'geocoder'));
};
/**
* 获取城市列表
*
* @param {Object} options 接口参数对象
*
* 请求参数结构可以参考
* http://lbs.qq.com/webservice_v1/guide-region.html
*/
getCityList(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
var requestParam = {
output: 'json',
key: that.key
};
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_CITY_LIST,
data: requestParam
},'getCityList'));
};
/**
* 获取对应城市ID的区县列表
*
* @param {Object} options 接口参数对象
*
* 请求参数结构可以参考
* http://lbs.qq.com/webservice_v1/guide-region.html
*/
getDistrictByCityId(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
if (Utils.checkParamKeyEmpty(options, 'id')) {
return;
}
var requestParam = {
id: options.id || '',
output: 'json',
key: that.key
};
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_AREA_LIST,
data: requestParam
},'getDistrictByCityId'));
};
/**
* 用于单起点到多终点的路线距离(非直线距离)计算
* 支持两种距离计算方式步行和驾车
* 起点到终点最大限制直线距离10公里
*
* 新增直线距离计算
*
* @param {Object} options 接口参数对象
*
* 请求参数结构可以参考
* http://lbs.qq.com/webservice_v1/guide-distance.html
*/
calculateDistance(options) {
var that = this;
options = options || {};
Utils.polyfillParam(options);
if (Utils.checkParamKeyEmpty(options, 'to')) {
return;
}
var requestParam = {
mode: options.mode || 'walking',
to: Utils.location2query(options.to),
output: 'json',
key: that.key
};
if (options.from) {
options.location = options.from;
}
//计算直线距离
if(requestParam.mode == 'straight'){
var locationsuccess = function (result) {
var locationTo = Utils.getEndLocation(requestParam.to);//处理终点坐标
var data = {
message:"query ok",
result:{
elements:[]
},
status:0
};
for (var i = 0; i < locationTo.length; i++) {
data.result.elements.push({//将坐标存入
distance: Utils.getDistance(result.latitude, result.longitude, locationTo[i].lat, locationTo[i].lng),
duration:0,
from:{
lat: result.latitude,
lng:result.longitude
},
to:{
lat: locationTo[i].lat,
lng: locationTo[i].lng
}
});
}
var calculateResult = data.result.elements;
var distanceResult = [];
for (var i = 0; i < calculateResult.length; i++) {
distanceResult.push(calculateResult[i].distance);
}
return options.success(data,{
calculateResult: calculateResult,
distanceResult: distanceResult
});
};
Utils.locationProcess(options, locationsuccess);
} else {
var locationsuccess = function (result) {
requestParam.from = result.latitude + ',' + result.longitude;
wx.request(Utils.buildWxRequestConfig(options, {
url: URL_DISTANCE,
data: requestParam
},'calculateDistance'));
};
Utils.locationProcess(options, locationsuccess);
}
}
};
module.exports = QQMapWX;

3
common/sdk/qqmap-wx-jssdk.min.js
File diff suppressed because it is too large
View File

130
components/UserTab/UserTab - 副本.vue

@ -0,0 +1,130 @@
<template>
<view class="">
<!-- 学生端 -->
<u-tabbar v-if="showWho=='student'" :value="student" @change="studentChange" :fixed="true" :placeholder="true"
:safeAreaInsetBottom="true" activeColor="#31aef1">
<u-tabbar-item v-for="i in studentList" :key='i.id' :text="i.name" :name="i.name">
<image class="u-page__item__slot-icon" slot="active-icon" :src="i.active" mode="widthFix"></image>
<image class="u-page__item__slot-icon" slot="inactive-icon" :src="i.inactive" mode="widthFix"></image>
</u-tabbar-item>
</u-tabbar>
<!-- 教师端 -->
<u-tabbar :value="teacher" @change="teacherChange" :fixed="true" :placeholder="true"
:safeAreaInsetBottom="true" activeColor="#31aef1">
<u-tabbar-item v-for="i in teacherList" :key='i.id' :text="i.name" :name="i.name">
<image class="u-page__item__slot-icon" slot="active-icon" :src="i.active" mode="widthFix"></image>
<image class="u-page__item__slot-icon" slot="inactive-icon" :src="i.inactive" mode="widthFix"></image>
</u-tabbar-item>
</u-tabbar>
</view>
</template>
<script>
export default {
props: ['tabNumber'],
data() {
return {
teacher: '课堂',
student: '',
showWho: 'teacher',
teacherList: [{
id: 1,
name: '课堂',
active: '../../static/images/tabbar/syActive.png',
inactive: '../../static/images/tabbar/sy.png'
},
{
id: 2,
name: '兴趣小组',
active: '../../static/images/tabbar/tkActive.png',
inactive: '../../static/images/tabbar/tk.png'
},
{
id: 3,
name: '我的',
active: '../../static/images/tabbar/zxActive.png',
inactive: '../../static/images/tabbar/zx.png'
}
],
studentList: [{
id: 1,
name: '学员课堂',
active: '../../static/images/tabbar/syActive.png',
inactive: '../../static/images/tabbar/sy.png'
},
{
id: 2,
name: '学员兴趣小组',
active: '../../static/images/tabbar/tkActive.png',
inactive: '../../static/images/tabbar/tk.png'
},
{
id: 3,
name: '学员我的',
active: '../../static/images/tabbar/zxActive.png',
inactive: '../../static/images/tabbar/zx.png'
}
],
}
},
mounted() {
// if (uni.getStorageSync('status') == 'teacher') {
// this.showWho = 'student'
// } else {
// this.showWho = 'teacher'
// }
this.student = this.tabNumber
this.teacher = this.tabNumber
},
methods: {
teacherChange(e) {
this.teacher = e
if (e == '课堂') {
uni.reLaunch({
url: "/pages/tabbar/index/index"
})
// uni.hideHomeButton() //
} else if (e == "兴趣小组") {
uni.reLaunch({
url: "/pages/tabbar/question/index"
})
// uni.hideHomeButton()
} else if (e == "我的") {
uni.reLaunch({
url: "/pages/tabbar/mine/index"
})
// uni.hideHomeButton()
}
},
studentChange(e) {
this.student = e
uni.hideHomeButton()
// if (e == '') {
// uni.reLaunch({
// url: "/pages/index/CourseTeacherIndex"
// })
// uni.hideHomeButton() //
// } else if (e == "") {
// uni.reLaunch({
// url: "/pages/interestGroup/interestGroup"
// })
// uni.hideHomeButton()
// } else if (e == "") {
// uni.reLaunch({
// url: "/pages/mine/mine"
// })
// uni.hideHomeButton()
// }
}
}
}
</script>
<style lang="scss" scoped>
.u-page__item__slot-icon {
display: block;
width: 56rpx;
height: 56rpx;
}
</style>

117
components/UserTab/UserTab.vue

@ -0,0 +1,117 @@
<template>
<view class="tab-bar">
<view v-for="(item,index) in list" :key="index" class="tab-bar-item" @click="switchTab(item, index)">
<image class="tab_img" :src="currentIndex == index ? item.selectedIconPath : item.iconPath"></image>
<view class="tab_text" :style="{color: currentIndex == index ? selectedColor : color}">{{item.text}}</view>
</view>
</view>
</template>
<script>
export default {
props: {
selectedIndex: { // tab index
default: 0
},
},
data() {
return {
color: "#666666",
selectedColor: "#00BAB2",
list: [],
currentIndex:0,
}
},
created() {
this.currentIndex = this.selectedIndex;
var _this = this
if (uni.getStorageSync('identify') == 'nurse') {
//
_this.list = [
{
"pagePath": "/pages/tabbar/index/index",
"text": "首页",
"iconPath": "/static/images/tabbar/sy.png",
"selectedIconPath": "/static/images/tabbar/syActive.png"
},
{
"pagePath": "/pages/tabbar/question/index",
"text": "题库",
"iconPath": "/static/images/tabbar/tk.png",
"selectedIconPath": "/static/images/tabbar/tkActive.png"
},
{
"pagePath": "/pages/tabbar/mine/index",
"text": "我的",
"iconPath": "/static/images/tabbar/wd.png",
"selectedIconPath": "/static/images/tabbar/wdActive.png"
}
]
} else {
//
_this.list = [{
"pagePath": "/pages/tabbar/index/index",
"text": "首1页",
"iconPath": "/static/images/tabbar/sy.png",
"selectedIconPath": "/static/images/tabbar/syActive.png"
},
{
"pagePath": "/pages/tabbar/question/index",
"text": "题2库",
"iconPath": "/static/images/tabbar/tk.png",
"selectedIconPath": "/static/images/tabbar/tkActive.png"
},
{
"pagePath": "/pages/tabbar/mine/index",
"text": "我3的",
"iconPath": "/static/images/tabbar/wd.png",
"selectedIconPath": "/static/images/tabbar/wdActive.png"
}
]
}
},
methods: {
switchTab(item, index) {
this.currentIndex = index;
let url = item.pagePath;
console.log(url)
uni.reLaunch({url:url})
}
}
}
</script>
<style lang="scss">
.tab-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 100rpx;
background: white;
display: flex;
justify-content: center;
align-items: center;
padding-bottom: env(safe-area-inset-bottom); // iphoneX
.tab-bar-item {
flex: 1;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.tab_img {
width: 48rpx;
height: 48rpx;
}
.tab_text {
font-size: 24rpx;
margin-top: 4rpx;
}
}
}
</style>

10
config/api.js

@ -0,0 +1,10 @@
const http = uni.$u.http
// 隐私政策
export const getAgreement = (params, config = {}) => http.post('/util/manage/getAgreement.do', params, config)
// 验证码登录
export const loginSMS = (data) => http.post('/account/manage/login.do', data)
// 登录发验证码
export const getLoginCode = (data) => http.post('/util/manage/getLoginRegistCode.do', data)

52
config/request.js

@ -0,0 +1,52 @@
// 此vm参数为页面的实例,可以通过它引用vuex中的变量
module.exports = (vm) => {
// 初始化请求配置
uni.$u.http.setConfig((config) => {
/* config 为默认全局配置*/
config.baseURL = 'http://121.41.97.244:8090'; /* 根域名 */
config.header['content-type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
return config
})
// 请求拦截
uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
config.data = config.data || {}
// 根据custom参数中配置的是否需要token,添加对应的请求头
if(config?.custom?.auth) {
// 可以在此通过vm引用vuex中的变量,具体值在vm.$store.state中
config.header.token = vm.$store.state.userInfo.token
}
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
})
// 响应拦截
uni.$u.http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data
console.log('response')
console.log(data)
// 自定义参数
const custom = response.config?.custom
if (data.code !== 0) {
// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
if (custom.toast !== false) {
uni.$u.toast(data.message)
}
// 如果需要catch返回,则进行reject
if (custom?.catch) {
return Promise.reject(data)
} else {
// 否则返回一个pending中的promise,请求不会进入catch中
return new Promise(() => { })
}
}
return data === undefined ? {} : data
}, (response) => {
// 对响应错误做点什么 (statusCode !== 200)
return Promise.reject(response)
})
}

20
index.html

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

37
main.js

@ -0,0 +1,37 @@
import App from './App'
import Vue from 'vue'
import store from './store';
// import config from "./utils/config.js"
// import {storage, goPage} from "./utils/utils.js"
// Vue.prototype.$config = config;
// Vue.prototype.$goPage = goPage;
import './uni.promisify.adaptor'
Vue.config.productionTip = false
App.mpType = 'app'
// main.js,注意要在use方法之后执行
import uView from '@/uni_modules/uview-ui'
Vue.use(uView)
import tabBar from "components/UserTab/UserTab.vue"
Vue.component('tabBar',tabBar)
const app = new Vue({
...App,
store
})
require('./config/request.js')(app)
import utils from "@/common/js/utils.js"
console.log(utils)
// 自定义工具
Vue.use(utils,app)
app.$mount()

100
manifest.json

@ -0,0 +1,100 @@
{
"name" : "recruitStudent",
"appid" : "__UNI__BD23957",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {},
/* SDK */
"sdkConfigs" : {}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wx2d71605af3b620e6",
"setting" : {
"urlCheck" : false,
"es6" : true
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "查询用户地理位置,推荐本地驾校,提高用户服务"
}
}
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2",
"h5" : {
"devServer" : {
"port" : 8000,
"disableHostCheck" : true,
"proxy" : {
"/api" : {
"target" : "http://121.41.97.244:8090",
"changeOrigin" : true,
"secure" : true,
"pathRewrite" : {
//使
"^/api" : ""
}
}
},
"https" : false
},
"router" : {
"mode" : "hash",
"base" : "/h5"
}
}
}

15
package.json

@ -0,0 +1,15 @@
{
"name": "recruitStudent",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"uview-ui": "^2.0.36"
}
}

104
pages.json

@ -0,0 +1,104 @@
{
"pages": [
{
"path": "pages/tabbar/index/index",
"style": {
"navigationBarTitleText": "首页",
"navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
},
{
"path": "pages/tabbar/mine/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
},
{
"path": "pages/tabbar/learnCar/index",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
}
}
],
"subPackages": [
{
"root": "pages/userCenter",
"pages": [
{
"path": "login/login",
"style": {
"navigationBarTitleText": "登录",
"navigationStyle": "custom",
"enablePullDownRefresh": false,
"backgroundTextStyle": "dark"
}
},
{
"path": "login/loginByPhone",
"style": {
"navigationBarTitleText": "手机号登录",
"navigationStyle": "custom",
"enablePullDownRefresh": false,
"backgroundTextStyle": "dark"
}
}
]
},
{
"root": "pages/other",
"pages": [
{
"path": "webView/webView",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"enablePullDownRefresh": false,
"backgroundTextStyle": "dark"
}
}
]
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "学车小程序",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {},
"tabBar": {
"color": "#999999",
"selectedColor": "#218DFF",
"backgroundColor": "#FFFFFF",
"list": [{
"pagePath": "pages/tabbar/index/index",
"text": "首页",
"iconPath": "static/images/tabbar/btn_shouye_nor.png",
"selectedIconPath": "static/images/tabbar/btn_shouye_cli.png"
},
{
"pagePath": "pages/tabbar/learnCar/index",
"text": "学车",
"iconPath": "static/images/tabbar/btn_xueche_nor.png",
"selectedIconPath": "static/images/tabbar/btn_xueche_cli.png"
},
{
"pagePath": "pages/tabbar/mine/index",
"text": "我的",
"iconPath": "static/images/tabbar/btn_wode_nor.png",
"selectedIconPath": "static/images/tabbar/btn_wode_cli.png"
}
]
},
"easycom": {
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
}
}

60
pages/index/index.vue

@ -0,0 +1,60 @@
<template>
<view class="content">
<image class="logo" src="/static/logo.png" @click="goPage"></image>
<view class="text-area">
<text class="title">你好</text>
</view>
<UserTab tabNumber="兴趣小组"></UserTab>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
},
methods: {
goPage() {
// uni.navigateTo({
// url: '/pages/index/test'
// })
// plus.runtime.openURL("car://paymoney/carstep:8888://");
// plus.runtime.openURL("paymoney://car:8898/carstep");
}
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>

27
pages/other/webView/webView.vue

@ -0,0 +1,27 @@
<template>
<view>
<web-view :webview-styles="webviewStyles" src="http://192.168.1.20/system/menu"></web-view>
<!-- <web-view :webview-styles="webviewStyles" :src="$store.state.webViewUrl"></web-view> -->
</view>
</template>
<script>
export default {
data() {
return {
webviewStyles: {
progress: {
color: '#FF3333'
}
}
}
},
onLoad() {
console.log('噜噜哇'+ this.$store.state.webViewUrl)
}
}
</script>
<style>
</style>

404
pages/tabbar/index/index.vue

@ -0,0 +1,404 @@
<template>
<view class="main pageBg">
<view style="background-color: #2170FD; width: 100%;height: 20rpx;"></view>
<view class="TopCon">
<view class="status_bar" ></view>
<!-- 地址扫一扫 -->
<view class="flex-b">
<view class="flex">
<view class="adrsIcon">
<image src="@/static/images/index/dingwei.png" mode=""></image>
</view>
<view class="adr">南昌市</view>
</view>
<view class="scan" @click="scanCodeFn">
<image src="@/static/images/index/scan.png" mode=""></image>
</view>
</view>
<!-- 搜索 -->
<view class="searchCon">
<view class="searchBg">
<view class="flex">
<view class="searchIcon">
<image src="@/static/images/index/searchIcon.png" mode=""></image>
</view>
<view class="inputBox">
<u--input placeholder="搜索驾校、教练…" border="none" clearable v-model="keywords" :color="'#fff'" placeholderClass="placeholderClassFFF"></u--input>
</view>
</view>
</view>
</view>
</view>
<view class="pad">
<!-- 精钢区 -->
<view class="card traTop">
<view class="ul">
<view class="li" v-for="(item,index) in entrySection" :key="index">
<view class="icon">
<image :src="item.icon" mode=""></image>
</view>
<view class="name">{{ item.text }}</view>
</view>
</view>
</view>
<!-- 行业资讯 -->
<view class="card">
<view class="information">
<view class="flex-b border">
<view class="h1">行业资讯</view>
<view class="more">
<view class="text">更多</view>
<view class="icon">
<u-icon name="arrow-right"></u-icon>
</view>
</view>
</view>
<uni-swiper-dot class="uni-swiper-dot-box" @clickItem=clickItem :info="swiperInfo" :current="current" :mode="mode" style="height: 230rpx;"
:dots-styles="dotsStyles" field="content">
<swiper class="swiper-box" @change="change" :current="swiperDotIndex" style="height: 230rpx;">
<swiper-item v-for="(item, index) in swiperInfo" :key="index">
<view class="swiper-item" :class="'swiper-item' + index">
<view class="flex-b">
<view class="imgBox">
<image src="../../../static/images/logo.png" mode=""></image>
</view>
<view class="rightText">
<view class="text towRowText">{{ item.text }}</view>
<view class="date">{{ item.date}}</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</uni-swiper-dot>
</view>
</view>
<!-- 服务专区 -->
<view class="card serviceCon">
<view class="h1">服务专区</view>
<view class="ul2">
<view class="li2" v-for="(item,index) in serviceSector" :key="index" :class="'li2Bg' + index">
<view class="icon">
<image :src="item.icon" mode=""></image>
</view>
<view class="textCon">
<view class="text">{{ item.text }}</view>
<view class="tps">{{ item.tps}}</view>
</view>
</view>
</view>
</view>
<view style="height: 20rpx;width: 100%;"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
keywords: '',
entrySection: [
{text: '我要报名', icon: require('../../../static/images/index/ic_baoming.png'), },
{text: '找驾校', icon: require('../../../static/images/index/ic_jiaxiao.png'), },
{text: '找考场', icon: require('../../../static/images/index/ic_kaochang.png'), },
{text: '找陪练', icon: require('../../../static/images/index/ic_peilian.png'), },
{text: '理论学习', icon: require('../../../static/images/index/ic_lilun.png'), },
],
serviceSector: [
{text: '学车指南', tps:'政府平台 一站服务', icon: require('../../../static/images/index/img_1@2x.png'), url: ''},
{text: '公益视频', tps:'立体呈现 学驾无忧', icon: require('../../../static/images/index/img_2@2x.png'), url: ''},
{text: '合格率排行', tps:'官方数据 阳光透明', icon: require('../../../static/images/index/img_3@2x.png'), url: ''},
{text: '行业政策', tps:'权威发布 精准解读', icon: require('../../../static/images/index/img_4@2x.png'), url: ''},
{text: '质量信誉排行', tps:'官方数据 阳光透明', icon: require('../../../static/images/index/img_5@2x.png'), url: ''},
{text: '咨询投诉', tps:'畅达沟通 听取民声', icon: require('../../../static/images/index/img_6@2x.png'), url: ''},
],
swiperDotIndex: 1,
current: 1,
mode: 'default',
swiperInfo: [
{img: require('../../../static/images/index/ic_lilun.png'),text: '2023年6月份江西省机动车驾驶培训机构考试合格率的通报',date: '2023/08/09' },
{img: require('../../../static/images/index/ic_lilun.png'),text: '2023年6月份江西省机动车驾驶培训机构考试合格率的通报',date: '2023/08/10' },
{img: require('../../../static/images/index/ic_lilun.png'),text: '2023年6月份江西省机动车驾驶培训机构考试合格率的通报',date: '2023/08/11' },
],
dotsStyles: {
backgroundColor: '#E8E9EC',
border: '1px #E8E9EC solid',
color: '#fff',
selectedBackgroundColor: '#1989FA',
selectedBorder: '1px #1989FA solid'
},
}
},
onLoad() {
},
onShow() {
// this.initFn()
},
methods: {
//
scanCodeFn() {
let _this = this
uni.scanCode({
success: function (res) {
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
_this.$store.commit('updateWebVeiwUrl', res.result)
uni.navigateTo({
url: '/pages/other/webView/webView'
})
}
});
},
clickItem(e) {
this.swiperDotIndex = e
},
change(e) {
this.current = e.detail.current
},
goPage() {
uni.navigateTo({
url: '/pages/userCenter/login/loginByPhone'
})
},
initFn() {
uni.requestSubscribeMessage({
tmplIds: ['0yaIdyI9NlHvGYwb3IIaIQq6uBhulYGN-rGVnJk4hZ4'],
success (res) {
console.log('消息是否有权限呢')
console.log(res)
}
})
}
}
}
</script>
<style lang="scss" scoped>
.main {
width: 100%;
.TopCon {
width: 100%;
height: 476rpx;
// background: url('../../../static/images/bigImg/index_banner.png') no-repeat;
background: url('http://192.168.1.20:81/zhili/image/20230809/e7086ccf82ed4aa09d156f2590a50fba.png') no-repeat;
background-size: 100% 100%;
position: relative;
.flex-b {
padding: 10rpx 212rpx 0 50rpx;
.flex {
.adrsIcon {
width: 26rpx;
height: 38rpx;
margin-top: 4rpx;
}
.adr {
padding-left: 14rpx;
font-size: 28rpx;
color: #fff;
}
}
.scan {
width: 64rpx;
height: 64rpx;
}
}
.searchCon {
position: absolute;
left: 0;
bottom: 68rpx;
padding: 0 28rpx;
width: 100%;
.searchBg {
background: #8ABAED;
width: 100%;
height: 72rpx;
border-radius: 16rpx;
line-height: 72rpx;
.flex {
height: 100%;
padding: 0 28rpx;
.searchIcon {
width: 40rpx;
height: 40rpx;
}
.inputBox {
padding-left: 28rpx;
flex: 1;
color: #fff;
font-size: 28rpx;
}
}
}
}
}
.card {
background: #FFFFFF;
border-radius: 16rpx;
margin-bottom: 20rpx;
&.traTop {
// transform: translateY(-40rpx);
margin-top: -40rpx;
position: relative;
z-index: 9;
}
.ul {
height: 236rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20rpx;
.li {
flex: 1;
display: flex;
align-items: center;
flex-direction: column;
.icon {
width: 92rpx;
height: 92rpx;
}
.name {
font-size: 26rpx;
color: #333;
padding-top: 20rpx;
text-align: center;
}
}
}
}
.information {
padding: 0 20rpx;
height: 320rpx;
.border {
height: 86rpx;
border-bottom: 2px dashed #E8E9EC;
.h1 {
font-size: 28rpx;
color: #333;
}
.more {
font-size: 24rpx;
display: flex;
.text {
// margin-right: 8rpx;
color: #686B73;
}
}
}
.swiper-item {
height: 148rpx;
.flex-b {
padding: 30rpx 0 28rpx 0;
.imgBox {
width: 184rpx;
height: 148rpx;
background: linear-gradient(180deg, rgba(0,122,255,0.5) 0%, #007AFF 100%);
border-radius: 6rpx;
overflow: hidden;
}
.rightText {
flex: 1;
padding: 0 0 0 30rpx;
height: 148rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.text {
font-size: 24rpx;
color: #333;
}
.date {
text-align: right;
font-size: 20rpx;
color: #686B73;
}
}
}
}
}
.serviceCon {
width: 100%;
padding-bottom: 20rpx;
.h1 {
font-size: 28rpx;
color: #333;
padding: 0 0 0 20rpx;
font-weight: 500;
line-height: 90rpx;
}
.ul2 {
padding: 0 20rpx;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.li2 {
width: 48.8%;
display: flex;
align-items: center;
padding: 14rpx 0 14rpx 14rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
height: 160rpx;
&.li2Bg0 {
background: linear-gradient(180deg, #F7FBFF 0%, #EFF6FF 100%);
}
&.li2Bg1 {
background: linear-gradient(180deg, #FFFAF3 0%, #FFF4EA 100%);
}
&.li2Bg2 {
background: linear-gradient(180deg, #F4FFF5 0%, #F3FFED 100%);
}
&.li2Bg3 {
background: linear-gradient(180deg, #EFFFF9 0%, #E3FFF5 100%);
}
&.li2Bg4 {
background: linear-gradient(180deg, #FAF9FF 0%, #F9F5FF 100%);
}
&.li2Bg5 {
background: linear-gradient(180deg, #FCF9FB 0%, #FFF5F8 100%);
}
.icon {
width: 80rpx;
height: 80rpx;
}
.textCon {
// flex: 1;
padding-left: 16rpx;
.text {
font-size: 32rpx;
color: #333;
font-weight: 500;
}
.tps {
margin-top: 6rpx;
font-size: 20rpx;
color: #949494;
}
}
}
}
}
}
</style>

30
pages/tabbar/learnCar/index.vue

@ -0,0 +1,30 @@
<template>
<view class="content">
学车
<!-- <UserTab selectedIndex ='1'></UserTab> -->
</view>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
},
onShow() {
// uni.hideTabBar();
},
methods: {
goPage() {}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 100vw;
height: 100vh;
}
</style>

31
pages/tabbar/mine/index.vue

@ -0,0 +1,31 @@
<template>
<view class="content">
我的
<!-- <UserTab selectedIndex ='2'></UserTab> -->
</view>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
console.log('我的页面')
},
onShow() {
// uni.hideTabBar();
},
methods: {
goPage() {}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 100vw;
height: 100%;
}
</style>

71
pages/userCenter/login/login.vue

@ -0,0 +1,71 @@
<template>
<view class="main">
登录方式
</view>
</template>
<script>
export default {
data() {
return {
}
},
onLoad() {
// this.init()
},
methods: {
init() {
uni.login({
provider: 'weixin',
"onlyAuthorize": true,
success: function (loginRes) {
console.log('11')
console.log(loginRes)
//
uni.getUserInfo({
provider: 'weixin',
success: function(info) {
// , info.authResult
console.log('11')
console.log(info)
}
})
},
fail: function (err) {
//
// err.code
}
});
},
}
}
</script>
<style lang="scss" scoped>
// .radioWrap {
// display: flex;
// justify-content: flex-start;
// align-items: center;
// /deep/.radio-btn {
// margin-right: -9rpx !important;
// }
// radio {
// zoom: .8;
// }
// view:nth-child(2) {
// font-size: 24rpx;
// color: #bfbfbf;
// }
// text {
// color: #218DFF;
// font-size: 24rpx;
// }
// }
</style>

187
pages/userCenter/login/loginByPhone.vue

@ -0,0 +1,187 @@
<template>
<view class="main">
<view class="u-back-top">
<view class="backBox">
<u-icon name="arrow-left" color="#333" size="28"></u-icon>
</view>
</view>
<view class="title">短信验证码登录</view>
<view class="form">
<view class="form-item">
<view class="prefix">
<view class="jia">+</view>
<view class="num">86</view>
<view class="" style="margin: 0 32rpx 0 12rpx;">
<u-icon name="arrow-down" color="#333" size="16" ></u-icon>
</view>
</view>
<view class="inputBox my">
<u--input placeholder="请输入手机号" border="none" clearable type="number" maxlength="11" v-model="FormData.phone"></u--input>
</view>
</view>
<view class="form-item">
<view class="inputBox my">
<u--input placeholder="请输入验证码" border="none" clearable style="height: 100%;" :clearable="false" v-model="FormData.code"></u--input>
</view>
<view class="code" @tap='goSms' :class="{active: isPhone&&!codeOn}">{{codeText}}</view>
</view>
<view class="loginBtn" :class="{active: btnHighlight}" @click="submitFn"> </view>
<view class="radioWrap">
<u-checkbox-group >
<u-checkbox v-model="isCheck" shape="circle" label="已阅读并同意" :labelSize="12" ></u-checkbox>
</u-checkbox-group>
<view class="privacyText">
<text>用户协议</text> <text>隐私协议</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { getLoginCode } from '@/config/api.js'
export default {
data() {
return {
isCheck: false,
codeText: '获取验证码',
FormData: {},
codeOn: false
}
},
onLoad() {
},
computed: {
isPhone() {
return uni.$u.test.mobile(this.FormData.phone)
},
btnHighlight() {
return this.isPhone&&uni.$u.test.code(this.FormData.code, 4)
}
},
methods: {
//
groupChangeEnvnt(e) {
this.isCheck = e.value
console.log('是否选择协议', this.isCheck)
},
//
async goSms() {
const {
FormData
} = this
if (!FormData.phone) return this.$u.toast('请输入手机号');
if (!this.isPhone) return this.$u.toast('手机号格式有误');
if (this.codeOn) return
const data = await getLoginCode({
codeType: 1,
phone: FormData.phone,
})
console.log(data)
//
var time = 60;
var timer = setInterval(() => {
time--;
this.codeText = time + "秒后重新发送"
this.codeOn = true;
if (time == 0) {
clearInterval(timer);
this.codeText = "获取验证码";
this.codeOn = false;
}
}, 1000);
},
submitFn() {
uni.switchTab({
url: '/pages/tabbar/index/index'
})
}
}
}
</script>
<style lang="scss" scoped>
.main {
width: 100%;
min-height: 100vh;
background: url('../../../static/images/userCenter/loginTopBg.png') no-repeat;
background-size: 100% 360rpx;
.u-back-top {
padding: 32rpx 0 0 0;
.backBox {
padding: 24rpx;
}
}
.title {
font-size: 48rpx;
color: #333;
padding: 92rpx 0;
text-align: center;
font-weight: 600;
}
.form {
padding: 0 46rpx;
.form-item {
height: 112rpx;
background: #F4F7FF;
border-radius: 16rpx;
width: 100%;
line-height: 112rpx;
display: flex;
margin-bottom: 40rpx;
padding: 0 40rpx;
.prefix {
display: flex;
align-items: center;
font-size: 32rpx;
color: #333;
font-weight: 600;
}
.inputBox {
flex: 1;
}
.code {
color: #BBBBBB;
margin-left: 30rpx;
&.active {
color: $themC
}
}
}
.loginBtn {
width: 100%;
height: 112rpx;
background: rgba(25,137,250,0.3);
border-radius: 16rpx;
text-align: center;
line-height: 112rpx;
font-size: 32rpx;
font-weight: 600;
color: #fff;
margin-top: 100rpx;
&.active {
background: rgba(25,137,250,1);
}
}
.radioWrap {
display: flex;
align-items: center;
margin-top: 40rpx;
.privacyText {
font-size: 24rpx;
color: #888E94;
text {
color: $themC;
}
}
}
}
}
</style>

28
project.config.json

@ -0,0 +1,28 @@
{
"appid": "wx0820ae1a0b635ae2",
"compileType": "miniprogram",
"libVersion": "2.32.2",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"coverView": true,
"es6": true,
"postcss": true,
"minified": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmRelationList": [],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

7
project.private.config.json

@ -0,0 +1,7 @@
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "recruitStudent",
"setting": {
"compileHotReLoad": true
}
}

12
site.config.js

@ -0,0 +1,12 @@
const VUE_APP_PLATFORM = process.env.VUE_APP_PLATFORM;
module.exports = {
APP_API: VUE_APP_PLATFORM === 'h5' ? 'http://121.41.97.244:8090' : '',
APP_HOST: VUE_APP_PLATFORM === 'h5' ? '' : 'https://www.jaxc.cn/api',
TEMP_HOST: VUE_APP_PLATFORM === 'h5' ? '' : 'http://121.41.97.244:8090 https://www.jaxc.cn/api',
ADD_API: VUE_APP_PLATFORM === 'h5' ? '/addApi': 'http://121.41.97.244:48084', //http://121.41.97.244:48084
APP_NAME: '',
VERSION: '1.0.0',
gaodeMapUrl: 'https://webapi.amap.com/maps?v=1.4.15&key=4545202996c625152b7f2c1aa0ffb8ea&plugin=AMap.DistrictSearch,AMap.CustomLayer,AMap.MarkerClusterer',
locationIcon: 'http://3dtest.hzhuishi.cn/images/location.png',
AThreeFace : true, //是否启用人脸识别
};

BIN
static/images/bigImg/index_banner.png

After

Width: 750  |  Height: 476  |  Size: 292 KiB

BIN
static/images/index/dingwei.png

After

Width: 26  |  Height: 38  |  Size: 1015 B

BIN
static/images/index/ic_baoming.png

After

Width: 92  |  Height: 92  |  Size: 2.7 KiB

BIN
static/images/index/ic_jiaxiao.png

After

Width: 92  |  Height: 92  |  Size: 2.3 KiB

BIN
static/images/index/ic_kaochang.png

After

Width: 92  |  Height: 92  |  Size: 2.8 KiB

BIN
static/images/index/ic_lilun.png

After

Width: 92  |  Height: 92  |  Size: 2.1 KiB

BIN
static/images/index/ic_peilian.png

After

Width: 92  |  Height: 92  |  Size: 2.3 KiB

BIN
static/images/index/img_1@2x.png

After

Width: 80  |  Height: 80  |  Size: 2.4 KiB

BIN
static/images/index/img_2@2x.png

After

Width: 80  |  Height: 80  |  Size: 1.8 KiB

BIN
static/images/index/img_3@2x.png

After

Width: 80  |  Height: 80  |  Size: 2.4 KiB

BIN
static/images/index/img_4@2x.png

After

Width: 80  |  Height: 80  |  Size: 2.6 KiB

BIN
static/images/index/img_5@2x.png

After

Width: 80  |  Height: 80  |  Size: 2.7 KiB

BIN
static/images/index/img_6@2x.png

After

Width: 80  |  Height: 80  |  Size: 2.6 KiB

BIN
static/images/index/scan.png

After

Width: 64  |  Height: 64  |  Size: 891 B

BIN
static/images/index/searchIcon.png

After

Width: 40  |  Height: 40  |  Size: 737 B

BIN
static/images/index/我的@2x.png

After

Width: 56  |  Height: 56  |  Size: 981 B

BIN
static/images/index/报名@2x.png

After

Width: 56  |  Height: 56  |  Size: 1.3 KiB

BIN
static/images/index/首页@2x.png

After

Width: 56  |  Height: 56  |  Size: 1.2 KiB

BIN
static/images/logo.png

After

Width: 100  |  Height: 100  |  Size: 10 KiB

BIN
static/images/tabbar/btn_shouye_cli.png

After

Width: 56  |  Height: 56  |  Size: 1.7 KiB

BIN
static/images/tabbar/btn_shouye_nor.png

After

Width: 56  |  Height: 56  |  Size: 2.7 KiB

BIN
static/images/tabbar/btn_wode_cli.png

After

Width: 56  |  Height: 56  |  Size: 1.3 KiB

BIN
static/images/tabbar/btn_wode_nor.png

After

Width: 56  |  Height: 56  |  Size: 2.1 KiB

BIN
static/images/tabbar/btn_xueche_cli.png

After

Width: 56  |  Height: 56  |  Size: 1.6 KiB

BIN
static/images/tabbar/btn_xueche_nor.png

After

Width: 56  |  Height: 56  |  Size: 1.9 KiB

BIN
static/images/tabbar/sy.png

After

Width: 58  |  Height: 56  |  Size: 1.0 KiB

BIN
static/images/tabbar/syActive.png

After

Width: 58  |  Height: 56  |  Size: 861 B

BIN
static/images/tabbar/tk.png

After

Width: 58  |  Height: 56  |  Size: 929 B

BIN
static/images/tabbar/tkActive.png

After

Width: 58  |  Height: 56  |  Size: 826 B

BIN
static/images/tabbar/wd.png

After

Width: 58  |  Height: 56  |  Size: 1.6 KiB

BIN
static/images/tabbar/wdActive.png

After

Width: 58  |  Height: 56  |  Size: 1.3 KiB

BIN
static/images/tabbar/zx.png

After

Width: 58  |  Height: 56  |  Size: 587 B

BIN
static/images/tabbar/zxActive.png

After

Width: 58  |  Height: 56  |  Size: 547 B

BIN
static/images/userCenter/loginTopBg.png

After

Width: 375  |  Height: 180  |  Size: 36 KiB

BIN
static/images/userCenter/title_1.png

After

Width: 329  |  Height: 47  |  Size: 8.8 KiB

BIN
static/images/登录流程切图/__MACOSX/登录流程切图/._.DS_Store

BIN
static/images/登录流程切图/__MACOSX/登录流程切图/._btn_1.png

BIN
static/images/登录流程切图/登录流程切图/.DS_Store

BIN
static/images/登录流程切图/登录流程切图/bg_1.png

After

Width: 375  |  Height: 180  |  Size: 36 KiB

BIN
static/images/登录流程切图/登录流程切图/btn_1.png

After

Width: 16  |  Height: 16  |  Size: 461 B

BIN
static/images/登录流程切图/登录流程切图/btn_2.png

After

Width: 16  |  Height: 16  |  Size: 567 B

BIN
static/images/登录流程切图/登录流程切图/title_1.png

After

Width: 329  |  Height: 47  |  Size: 8.8 KiB

BIN
static/logo.png

After

Width: 72  |  Height: 72  |  Size: 3.9 KiB

21
store/getters.js

@ -0,0 +1,21 @@
// export default {
// userInfo: state => state.user.userInfo,
// pushMessage: state => state.push.pushMessage,
// currentAdd: state=>{
// };
export default {
pushMessage: state => state.push.pushMessage,
getCurrentAdd: function (state) {
//返回一个函数用于接收
return function (id) {
let add = state.add.addList.find(item => item.id == id)
if(add) {
return add
}else {
return {}
}
}
}
};

90
store/index.js

@ -0,0 +1,90 @@
import Vue from 'vue';
import Vuex from 'vuex';
import add from './modules/add';
import user from './modules/user';
import getters from './getters';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
currentSchool: '',
userInfo: {},
latLng: {},
classChooseItem: {},
pdfUrl: '',
webViewUrl: '',
havePay: 0, //tabbar 页面是否显示报错小图标
currentMyMsg: {},
billPrice: 0, //开发票的id
TrainingOrderId: '', //退款流程里的驾校id
bankInfo: {
realName: uni.getStorageSync('userInfo').realName,
phoneCode: ''
},
chooseCoachItem: {
coachId: ''
}, //报名时选择的教练
realAuthsuccee: false,
},
getters,
mutations: {
// 选择学校
upDateTrainingSchoolId(state, currentSchool) {
state.currentSchool = currentSchool
},
// webViewUrl
updateWebVeiwUrl(state, url) {
state.webViewUrl = url
},
// 更新用户信息
upDateUserInfo(state, userInfo) {
state.userInfo = userInfo
},
updatePushMyMsg(state, item) {
state.currentMyMsg = item
},
upDateBillPrice(state, billPrice) {
state.billPrice = billPrice
},
upDateTrainingOrderId(state, trainingOrderId) {
state.trainingOrderId = trainingOrderId
},
// tabbar 页面是否显示报错小图标
updateHavePay(state, havePay) {
state.havePay = havePay
},
// 报名时选择教练
upDateCoachItem(state, item) {
state.chooseCoachItem = item
},
// 申请退款时的银行卡信息
upDateBankInfo(state, obj) {
for (let k in obj) {
if (state.bankInfo[k]) {
state.bankInfo[k] = obj[k]
} else {
uni.$set(state.bankInfo, k, obj[k])
}
}
},
// 更新经纬度
updateLatLng(state, item) {
state.latLng = item
},
},
actions: {
},
modules: {
add,
user,
},
});
export default store;

91
store/modules/add.js

@ -0,0 +1,91 @@
// import addApi from '@/api/add.js'; // 引入
const add = {
state: {
addList: []
},
mutations: {
// 更新广告列表
upDateAddList(state, list) {
state.addList = list
},
// 更新当前广告点击量
upDateViews(state, id) {
let add = state.addList.find(item=>item.id==id)
add.clicks ++
},
},
actions: {
// 点击广告
async addClick({commit, dispatch}, curAdd) {
// await dispatch('updateStatistics')
curAdd.clicks ++
if(!curAdd.adBannerDO.jumpUrl) {
return false
}
commit('updateWebVeiwUrl', curAdd.adBannerDO.jumpUrl)
uni.navigateTo({
url:'/pages/commeWebView/addWebView'
})
},
// 获取当前广告
getCurrentAdd({state},id) {
console.log(id)
console.log(state.addList)
let curAdd = state.addList.find(item=>item.id==id)
if(curAdd) {
curAdd.views ++
return curAdd
}else {
return {}
}
},
// // 广告
// async addPageFn({commit,state, dispatch}) {
// await dispatch('updateStatistics')
// let obj = {
// pageNo: 1,
// pageSize: 30,
// adClient: 1
// }
// const [err, res] = await addApi.addPage(obj)
// let list = res.data.records.map(item=>{
// item.views = 0
// item.clicks = 0
// return item
// })
// commit('upDateAddList', list)
// console.log('广告列表')
// console.log(list)
// },
// 更新广告点击量
async updateStatistics({ dispatch,state, commit }) {
let statistics = state.addList.filter(item=>item.views)
console.log('调用更新广告接口')
if(statistics.length) {
let stcsList = statistics.map(add=>{
let obj = {
"adPositionId": add.id,
"adId": add.adId,
"views": add.views,
"clicks": add.clicks
}
return obj
})
const [err, res] = await addApi.batchUpdate(stcsList)
console.log('更新广告点击量请求结果')
console.log(res)
}
}
}
}
export default add

31
store/modules/user.js

@ -0,0 +1,31 @@
import addApi from '../../common/sdk/qqmap-wx-jssdk.min.js'; // 引入
const user = {
state: {
addList: []
},
mutations: {
// 更新广告列表
upDateAddList(state, list) {
state.addList = list
},
},
actions: {
// 点击广告
async addClick({commit, dispatch}, curAdd) {
// await dispatch('updateStatistics')
curAdd.clicks ++
if(!curAdd.adBannerDO.jumpUrl) {
return false
}
commit('updateWebVeiwUrl', curAdd.adBannerDO.jumpUrl)
uni.navigateTo({
url:'/pages/commeWebView/addWebView'
})
},
}
}
export default user

10
uni.promisify.adaptor.js

@ -0,0 +1,10 @@
uni.addInterceptor({
returnValue (res) {
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
return res;
}
return new Promise((resolve, reject) => {
res.then((res) => res[0] ? reject(res[0]) : resolve(res[1]));
});
},
});

80
uni.scss

@ -0,0 +1,80 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量同时无需 import 这个文件
*/
/* 颜色变量 */
@import '@/uni_modules/uview-ui/theme.scss';
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:12px;
$uni-font-size-base:14px;
$uni-font-size-lg:16;
/* 图片尺寸 */
$uni-img-size-sm:20px;
$uni-img-size-base:26px;
$uni-img-size-lg:40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:20px;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
// 自已定义的
$themC: #1989FA,

6
uni_modules/uni-config-center/changelog.md

@ -0,0 +1,6 @@
## 0.0.3(2022-11-11)
- 修复 config 方法获取根节点为数组格式配置时错误的转化为了对象的Bug
## 0.0.2(2021-04-16)
- 修改插件package信息
## 0.0.1(2021-03-15)
- 初始化项目

81
uni_modules/uni-config-center/package.json

@ -0,0 +1,81 @@
{
"id": "uni-config-center",
"displayName": "uni-config-center",
"version": "0.0.3",
"description": "uniCloud 配置中心",
"keywords": [
"配置",
"配置中心"
],
"repository": "",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "unicloud-template-function"
},
"directories": {
"example": "../../../scripts/dist"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
},
"Vue": {
"vue2": "y",
"vue3": "u"
}
}
}
}
}

93
uni_modules/uni-config-center/readme.md

@ -0,0 +1,93 @@
# 为什么使用uni-config-center
实际开发中很多插件需要配置文件才可以正常运行,如果每个插件都单独进行配置的话就会产生下面这样的目录结构
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ ├─index.js
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b // plugin-b对应的目录
├─index.js
└─config.json // plugin-b对应的配置文件
```
假设插件作者要发布一个项目模板,里面使用了很多需要配置的插件,无论是作者发布还是用户使用都是一个大麻烦。
uni-config-center就是用了统一管理这些配置文件的,使用uni-config-center后的目录结构如下
```bash
cloudfunctions
└─────common 公共模块
├─plugin-a // 插件A对应的目录
│ └─index.js
├─plugin-b // plugin-b对应的目录
│ └─index.js
└─uni-config-center
├─index.js // config-center入口文件
├─plugin-a
│ ├─config.json // plugin-a对应的配置文件
│ └─other-file.cert // plugin-a依赖的其他文件
└─plugin-b
└─config.json // plugin-b对应的配置文件
```
使用uni-config-center后的优势
- 配置文件统一管理,分离插件主体和配置信息,更新插件更方便
- 支持对config.json设置schema,插件使用者在HBuilderX内编写config.json文件时会有更好的提示(后续HBuilderX会提供支持)
# 用法
在要使用uni-config-center的公共模块或云函数内引入uni-config-center依赖,请参考:[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
```js
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
pluginId: 'uni-id', // 插件id
defaultConfig: { // 默认配置
tokenExpiresIn: 7200,
tokenExpiresThreshold: 600,
},
customMerge: function(defaultConfig, userConfig) { // 自定义默认配置和用户配置的合并规则,不设置的情况侠会对默认配置和用户配置进行深度合并
// defaudltConfig 默认配置
// userConfig 用户配置
return Object.assign(defaultConfig, userConfig)
}
})
// 以如下配置为例
// {
// "tokenExpiresIn": 7200,
// "passwordErrorLimit": 6,
// "bindTokenToDevice": false,
// "passwordErrorRetryTime": 3600,
// "app-plus": {
// "tokenExpiresIn": 2592000
// },
// "service": {
// "sms": {
// "codeExpiresIn": 300
// }
// }
// }
// 获取配置
uniIdConfig.config() // 获取全部配置,注意:uni-config-center内不存在对应插件目录时会返回空对象
uniIdConfig.config('tokenExpiresIn') // 指定键值获取配置,返回:7200
uniIdConfig.config('service.sms.codeExpiresIn') // 指定键值获取配置,返回:300
uniIdConfig.config('tokenExpiresThreshold', 600) // 指定键值获取配置,如果不存在则取传入的默认值,返回:600
// 获取文件绝对路径
uniIdConfig.resolve('custom-token.js') // 获取uni-config-center/uni-id/custom-token.js文件的路径
// 引用文件(require)
uniIDConfig.requireFile('custom-token.js') // 使用require方式引用uni-config-center/uni-id/custom-token.js文件。文件不存在时返回undefined,文件内有其他错误导致require失败时会抛出错误。
// 判断是否包含某文件
uniIDConfig.hasFile('custom-token.js') // 配置目录是否包含某文件,true: 文件存在,false: 文件不存在
```

1
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/index.js
File diff suppressed because it is too large
View File

9
uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/package.json

@ -0,0 +1,9 @@
{
"name": "uni-config-center",
"version": "0.0.3",
"description": "配置中心",
"main": "index.js",
"keywords": [],
"author": "DCloud",
"license": "Apache-2.0"
}

25
uni_modules/uni-open-bridge-common/changelog.md

@ -0,0 +1,25 @@
## 1.2.0(2023-04-27)
- 优化 微信小程序平台 使用微信新增 API getStableAccessToken 获取 access_token, access_token 有效期内重复调用该接口不会更新 access_token, [详情](https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html)
## 1.1.5(2023-03-27)
- 修复 微信小程序平台 某些情况下 encrypt_key 插入错误的问题
## 1.1.4(2023-03-13)
- 修复 平台 weixin-web
## 1.1.3(2023-03-13)
- 新增 支持旧版本 uni-id 配置
- 新增 支持平台 weixin-app|qq-mp|qq-app
## 1.1.2(2023-02-28)
- 新增 config 配置错误提示语
## 1.1.1(2023-02-28)
- 新增 支持 provider 参数,和 platform 保持一致
## 1.1.0(2023-02-27)
- 重要更新 调整数据库key格式,兼容旧版本API,如果开发者通过手动拼接key查询数据库需要修改现有逻辑
+ 原格式: uni-id:[dcloudAppid]:[platform]:[openid]:[access-token|user-access-token|session-key|encrypt-key-version|ticket]
+ 新格式: uni-id:[provider]:[appid]:[openid]:[access-token|user-access-token|session-key|encrypt-key-version|ticket]
## 1.0.4(2022-09-21)
- 新增 支持使用阿里云固定IP获取微信公众号H5凭据 access_token、ticket,开发者需要在微信公众平台配置阿里云固定IP,[固定IP详情](https://uniapp.dcloud.net.cn/uniCloud/cf-functions.html#aliyun-eip)
## 1.0.3(2022-09-06)
- 修复 过期时间问题,容错 AccessToken 默认 fallback 逻辑,当微信服务器没有返回过期时间时设置为2小时后过期
## 1.0.2(2022-09-02)
- 新增 依赖数据表schema opendb-open-data
## 1.0.0(2022-08-22)
- 首次发布

84
uni_modules/uni-open-bridge-common/package.json

@ -0,0 +1,84 @@
{
"id": "uni-open-bridge-common",
"displayName": "uni-open-bridge-common",
"version": "1.2.0",
"description": "统一接管微信等三方平台认证凭据",
"keywords": [
"uni-open-bridge-common",
"access_token",
"session_key",
"ticket"
],
"repository": "",
"engines": {
"HBuilderX": "^3.5.2"
},
"dcloudext": {
"type": "unicloud-template-function",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": ""
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"Vue": {
"vue2": "u",
"vue3": "u"
},
"App": {
"app-vue": "u",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "u",
"Android Browser": "u",
"微信浏览器(Android)": "u",
"QQ浏览器(Android)": "u"
},
"H5-pc": {
"Chrome": "u",
"IE": "u",
"Edge": "u",
"Firefox": "u",
"Safari": "u"
},
"小程序": {
"微信": "u",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "u",
"钉钉": "u",
"快手": "u",
"飞书": "u",
"京东": "u"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

5
uni_modules/uni-open-bridge-common/readme.md

@ -0,0 +1,5 @@
# uni-open-bridge-common
`uni-open-bridge-common` 是统一接管微信等三方平台认证凭据(包括但不限于`access_token`、`session_key`、`encrypt_key`、`ticket`)的开源库。
文档链接 [https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common](https://uniapp.dcloud.net.cn/uniCloud/uni-open-bridge#common)

26
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/bridge-error.js

@ -0,0 +1,26 @@
'use strict';
class BridgeError extends Error {
constructor(code, message) {
super(message)
this._code = code
}
get code() {
return this._code
}
get errCode() {
return this._code
}
get errMsg() {
return this.message
}
}
module.exports = {
BridgeError
}

124
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/config.js

@ -0,0 +1,124 @@
'use strict';
const {
ProviderType
} = require('./consts.js')
const configCenter = require('uni-config-center')
// 多维数据为兼容uni-id以前版本配置
const OauthConfig = {
'weixin-app': [
['app', 'oauth', 'weixin'],
['app-plus', 'oauth', 'weixin']
],
'weixin-mp': [
['mp-weixin', 'oauth', 'weixin']
],
'weixin-h5': [
['web', 'oauth', 'weixin-h5'],
['h5-weixin', 'oauth', 'weixin'],
['h5', 'oauth', 'weixin']
],
'weixin-web': [
['web', 'oauth', 'weixin-web']
],
'qq-app': [
['app', 'oauth', 'qq'],
['app-plus', 'oauth', 'qq']
],
'qq-mp': [
['mp-qq', 'oauth', 'qq']
]
}
const Support_Platforms = [
ProviderType.WEIXIN_MP,
ProviderType.WEIXIN_H5,
ProviderType.WEIXIN_APP,
ProviderType.WEIXIN_WEB,
ProviderType.QQ_MP,
ProviderType.QQ_APP
]
class ConfigBase {
constructor() {
const uniIdConfigCenter = configCenter({
pluginId: 'uni-id'
})
this._uniIdConfig = uniIdConfigCenter.config()
}
getAppConfig(appid) {
if (Array.isArray(this._uniIdConfig)) {
return this._uniIdConfig.find((item) => {
return (item.dcloudAppid === appid)
})
}
return this._uniIdConfig
}
}
class AppConfig extends ConfigBase {
constructor() {
super()
}
get(appid, platform) {
if (!this.isSupport(platform)) {
return null
}
let appConfig = this.getAppConfig(appid)
if (!appConfig) {
return null
}
return this.getOauthConfig(appConfig, platform)
}
isSupport(platformName) {
return (Support_Platforms.indexOf(platformName) >= 0)
}
getOauthConfig(appConfig, platformName) {
let treePath = OauthConfig[platformName]
let node = this.findNode(appConfig, treePath)
if (node && node.appid && node.appsecret) {
return {
appid: node.appid,
secret: node.appsecret
}
}
return null
}
findNode(treeNode, arrayPath) {
let node = treeNode
for (let treePath of arrayPath) {
for (let name of treePath) {
const currentNode = node[name]
if (currentNode) {
node = currentNode
} else {
node = null
break
}
}
if (node === null) {
node = treeNode
} else {
break
}
}
return node
}
}
module.exports = {
AppConfig
};

30
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/consts.js

@ -0,0 +1,30 @@
'use strict';
const TAG = "UNI_OPEN_BRIDGE"
const HTTP_STATUS = {
SUCCESS: 200
}
const ProviderType = {
WEIXIN_MP: 'weixin-mp',
WEIXIN_H5: 'weixin-h5',
WEIXIN_APP: 'weixin-app',
WEIXIN_WEB: 'weixin-web',
QQ_MP: 'qq-mp',
QQ_APP: 'qq-app'
}
// old
const PlatformType = ProviderType
const ErrorCodeType = {
SYSTEM_ERROR: TAG + "_SYSTEM_ERROR"
}
module.exports = {
HTTP_STATUS,
ProviderType,
PlatformType,
ErrorCodeType
}

317
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/index.js

@ -0,0 +1,317 @@
'use strict';
const {
PlatformType,
ProviderType,
ErrorCodeType
} = require('./consts.js')
const {
AppConfig
} = require('./config.js')
const {
Storage
} = require('./storage.js')
const {
BridgeError
} = require('./bridge-error.js')
const {
WeixinServer
} = require('./weixin-server.js')
const appConfig = new AppConfig()
class AccessToken extends Storage {
constructor() {
super('access-token', ['provider', 'appid'])
}
async update(key) {
super.update(key)
const result = await this.getByWeixinServer(key)
return this.set(key, result.value, result.duration)
}
async fallback(key) {
return this.getByWeixinServer(key)
}
async getByWeixinServer(key) {
const oauthConfig = appConfig.get(key.dcloudAppid, key.provider)
let methodName
if (key.provider === ProviderType.WEIXIN_MP) {
methodName = 'GetMPAccessTokenData'
} else if (key.provider === ProviderType.WEIXIN_H5) {
methodName = 'GetH5AccessTokenData'
} else {
throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, "provider invalid")
}
const responseData = await WeixinServer[methodName](oauthConfig)
const duration = responseData.expires_in || (60 * 60 * 2)
delete responseData.expires_in
return {
value: responseData,
duration
}
}
}
class UserAccessToken extends Storage {
constructor() {
super('user-access-token', ['provider', 'appid', 'openid'])
}
}
class SessionKey extends Storage {
constructor() {
super('session-key', ['provider', 'appid', 'openid'])
}
}
class Encryptkey extends Storage {
constructor() {
super('encrypt-key', ['provider', 'appid', 'openid'])
}
async update(key) {
super.update(key)
const result = await this.getByWeixinServer(key)
return this.set(key, result.value, result.duration)
}
getKeyString(key) {
return `${super.getKeyString(key)}-${key.version}`
}
getExpiresIn(value) {
if (value <= 0) {
return 60
}
return value
}
async fallback(key) {
return this.getByWeixinServer(key)
}
async getByWeixinServer(key) {
const accessToken = await Factory.Get(AccessToken, key)
const userSession = await Factory.Get(SessionKey, key)
const responseData = await WeixinServer.GetUserEncryptKeyData({
openid: key.openid,
access_token: accessToken.access_token,
session_key: userSession.session_key
})
const keyInfo = responseData.key_info_list.find((item) => {
return item.version === key.version
})
if (!keyInfo) {
throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, 'key version invalid')
}
const value = {
encrypt_key: keyInfo.encrypt_key,
iv: keyInfo.iv
}
return {
value,
duration: keyInfo.expire_in
}
}
}
class Ticket extends Storage {
constructor() {
super('ticket', ['provider', 'appid'])
}
async update(key) {
super.update(key)
const result = await this.getByWeixinServer(key)
return this.set(key, result.value, result.duration)
}
async fallback(key) {
return this.getByWeixinServer(key)
}
async getByWeixinServer(key) {
const accessToken = await Factory.Get(AccessToken, {
dcloudAppid: key.dcloudAppid,
provider: ProviderType.WEIXIN_H5
})
const responseData = await WeixinServer.GetH5TicketData(accessToken)
const duration = responseData.expires_in || (60 * 60 * 2)
delete responseData.expires_in
delete responseData.errcode
delete responseData.errmsg
return {
value: responseData,
duration
}
}
}
const Factory = {
async Get(T, key, fallback) {
Factory.FixOldKey(key)
return Factory.MakeUnique(T).get(key, fallback)
},
async Set(T, key, value, expiresIn) {
Factory.FixOldKey(key)
return Factory.MakeUnique(T).set(key, value, expiresIn)
},
async Remove(T, key) {
Factory.FixOldKey(key)
return Factory.MakeUnique(T).remove(key)
},
async Update(T, key) {
Factory.FixOldKey(key)
return Factory.MakeUnique(T).update(key)
},
FixOldKey(key) {
if (!key.provider) {
key.provider = key.platform
}
const configData = appConfig.get(key.dcloudAppid, key.provider)
if (!configData) {
throw new BridgeError(ErrorCodeType.SYSTEM_ERROR, 'appid or provider invalid')
}
key.appid = configData.appid
},
MakeUnique(T) {
return new T()
}
}
// exports
async function getAccessToken(key, fallback) {
return Factory.Get(AccessToken, key, fallback)
}
async function setAccessToken(key, value, expiresIn) {
return Factory.Set(AccessToken, key, value, expiresIn)
}
async function removeAccessToken(key) {
return Factory.Remove(AccessToken, key)
}
async function updateAccessToken(key) {
return Factory.Update(AccessToken, key)
}
async function getUserAccessToken(key, fallback) {
return Factory.Get(UserAccessToken, key, fallback)
}
async function setUserAccessToken(key, value, expiresIn) {
return Factory.Set(UserAccessToken, key, value, expiresIn)
}
async function removeUserAccessToken(key) {
return Factory.Remove(UserAccessToken, key)
}
async function getSessionKey(key, fallback) {
return Factory.Get(SessionKey, key, fallback)
}
async function setSessionKey(key, value, expiresIn) {
return Factory.Set(SessionKey, key, value, expiresIn)
}
async function removeSessionKey(key) {
return Factory.Remove(SessionKey, key)
}
async function getEncryptKey(key, fallback) {
return Factory.Get(Encryptkey, key, fallback)
}
async function setEncryptKey(key, value, expiresIn) {
return Factory.Set(Encryptkey, key, value, expiresIn)
}
async function removeEncryptKey(key) {
return Factory.Remove(Encryptkey, key)
}
async function updateEncryptKey(key) {
return Factory.Update(Encryptkey, key)
}
async function getTicket(key, fallback) {
return Factory.Get(Ticket, key, fallback)
}
async function setTicket(key, value, expiresIn) {
return Factory.Set(Ticket, key, value, expiresIn)
}
async function removeTicket(key) {
return Factory.Remove(Ticket, key)
}
async function updateTicket(key) {
return Factory.Update(Ticket, key)
}
module.exports = {
getAccessToken,
setAccessToken,
removeAccessToken,
updateAccessToken,
getUserAccessToken,
setUserAccessToken,
removeUserAccessToken,
getSessionKey,
setSessionKey,
removeSessionKey,
getEncryptKey,
setEncryptKey,
removeEncryptKey,
updateEncryptKey,
getTicket,
setTicket,
removeTicket,
updateTicket,
ProviderType,
PlatformType,
WeixinServer,
ErrorCodeType
}

15
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/package.json

@ -0,0 +1,15 @@
{
"name": "uni-open-bridge-common",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"uni-config-center": "file:../../../../../uni-config-center/uniCloud/cloudfunctions/common/uni-config-center"
}
}

111
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/storage.js

@ -0,0 +1,111 @@
'use strict';
const {
Validator
} = require('./validator.js')
const {
CacheKeyCascade
} = require('./uni-cloud-cache.js')
const {
BridgeError
} = require('./bridge-error.js')
class Storage {
constructor(type, keys) {
this._type = type || null
this._keys = keys || []
}
async get(key, fallback) {
this.validateKey(key)
const result = await this.create(key, fallback).get()
return result.value
}
async set(key, value, expiresIn) {
this.validateKey(key)
this.validateValue(value)
const expires_in = this.getExpiresIn(expiresIn)
if (expires_in !== 0) {
await this.create(key).set(this.getValue(value), expires_in)
}
}
async remove(key) {
this.validateKey(key)
await this.create(key).remove()
}
// virtual
async update(key) {
this.validateKey(key)
}
async ttl(key) {
this.validateKey(key)
// 后续考虑支持
}
async fallback(key) {}
getKeyString(key) {
const keyArray = [Storage.Prefix]
this._keys.forEach((name) => {
keyArray.push(key[name])
})
keyArray.push(this._type)
return keyArray.join(':')
}
getValue(value) {
return value
}
getExpiresIn(value) {
if (value !== undefined) {
return value
}
return -1
}
validateKey(key) {
Validator.Key(this._keys, key)
}
validateValue(value) {
Validator.Value(value)
}
create(key, fallback) {
const keyString = this.getKeyString(key)
const options = {
layers: [{
type: 'database',
key: keyString
}, {
type: 'redis',
key: keyString
}]
}
const _this = this
return new CacheKeyCascade({
...options,
fallback: async function() {
if (fallback) {
return fallback(key)
} else if (_this.fallback) {
return _this.fallback(key)
}
}
})
}
}
Storage.Prefix = "uni-id"
module.exports = {
Storage
};

324
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/uni-cloud-cache.js

@ -0,0 +1,324 @@
const db = uniCloud.database()
function getType(value) {
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase()
}
const validator = {
key: function(value) {
const err = new Error('Invalid key')
if (typeof value !== 'string') {
throw err
}
const valueTrim = value.trim()
if (!valueTrim || valueTrim !== value) {
throw err
}
},
value: function(value) {
// 仅作简单校验
const type = getType(value)
const validValueType = ['null', 'number', 'string', 'array', 'object']
if (validValueType.indexOf(type) === -1) {
throw new Error('Invalid value type')
}
},
duration: function(value) {
const err = new Error('Invalid duration')
if (value === undefined) {
return
}
if (typeof value !== 'number' || value === 0) {
throw err
}
}
}
/**
* 入库时 expired 为过期时间对应的时间戳永不过期用-1表示
* 返回结果时 与redis对齐-1表示永不过期-2表示已过期或不存在
*/
class DatabaseCache {
constructor({
collection = 'opendb-open-data'
} = {}) {
this.type = 'db'
this.collection = db.collection(collection)
}
_serializeValue(value) {
return value === undefined ? null : JSON.stringify(value)
}
_deserializeValue(value) {
return value ? JSON.parse(value) : value
}
async set(key, value, duration) {
validator.key(key)
validator.value(value)
validator.duration(duration)
value = this._serializeValue(value)
await this.collection.doc(key).set({
value,
expired: duration && duration !== -1 ? Date.now() + (duration * 1000) : -1
})
}
async _getWithDuration(key) {
const getKeyRes = await this.collection.doc(key).get()
const record = getKeyRes.data[0]
if (!record) {
return {
value: null,
duration: -2
}
}
const value = this._deserializeValue(record.value)
const expired = record.expired
if (expired === -1) {
return {
value,
duration: -1
}
}
const duration = expired - Date.now()
if (duration <= 0) {
await this.remove(key)
return {
value: null,
duration: -2
}
}
return {
value,
duration: Math.floor(duration / 1000)
}
}
async get(key, {
withDuration = true
} = {}) {
const result = await this._getWithDuration(key)
if (!withDuration) {
delete result.duration
}
return result
}
async remove(key) {
await this.collection.doc(key).remove()
}
}
class RedisCache {
constructor() {
this.type = 'redis'
this.redis = uniCloud.redis()
}
_serializeValue(value) {
return value === undefined ? null : JSON.stringify(value)
}
_deserializeValue(value) {
return value ? JSON.parse(value) : value
}
async set(key, value, duration) {
validator.key(key)
validator.value(value)
validator.duration(duration)
value = this._serializeValue(value)
if (!duration || duration === -1) {
await this.redis.set(key, value)
} else {
await this.redis.set(key, value, 'EX', duration)
}
}
async get(key, {
withDuration = false
} = {}) {
let value = await this.redis.get(key)
value = this._deserializeValue(value)
if (!withDuration) {
return {
value
}
}
const durationSecond = await this.redis.ttl(key)
let duration
switch (durationSecond) {
case -1:
duration = -1
break
case -2:
duration = -2
break
default:
duration = durationSecond
break
}
return {
value,
duration
}
}
async remove(key) {
await this.redis.del(key)
}
}
class Cache {
constructor({
type,
collection
} = {}) {
if (type === 'database') {
return new DatabaseCache({
collection
})
} else if (type === 'redis') {
return new RedisCache()
} else {
throw new Error('Invalid cache type')
}
}
}
class CacheKey {
constructor({
type,
collection,
cache,
key,
fallback
} = {}) {
this.cache = cache || new Cache({
type,
collection
})
this.key = key
this.fallback = fallback
}
async set(value, duration) {
await this.cache.set(this.key, value, duration)
}
async setWithSync(value, duration, syncMethod) {
await Promise.all([
this.set(this.key, value, duration),
syncMethod(value, duration)
])
}
async get() {
let {
value,
duration
} = await this.cache.get(this.key)
if (value !== null && value !== undefined) {
return {
value,
duration
}
}
if (!this.fallback) {
return {
value: null,
duration: -2
}
}
const fallbackResult = await this.fallback()
value = fallbackResult.value
duration = fallbackResult.duration
if (value !== null && duration !== undefined) {
await this.cache.set(this.key, value, duration)
}
return {
value,
duration
}
}
async remove() {
await this.cache.remove(this.key)
}
}
class CacheKeyCascade {
constructor({
layers, // [{cache, type, collection, key}] 从低级到高级排序,[DbCacheKey, RedisCacheKey]
fallback
} = {}) {
this.layers = layers
this.cacheLayers = []
let lastCacheKey
for (let i = 0; i < layers.length; i++) {
const {
type,
cache,
collection,
key
} = layers[i]
const lastCacheKeyTemp = lastCacheKey
try {
const currentCacheKey = new CacheKey({
type,
collection,
cache,
key,
fallback: i === 0 ? fallback : function() {
return lastCacheKeyTemp.get()
}
})
this.cacheLayers.push(currentCacheKey)
lastCacheKey = currentCacheKey
} catch (e) {}
}
this.highLevelCache = lastCacheKey
}
async set(value, duration) {
return Promise.all(
this.cacheLayers.map(item => {
return item.set(value, duration)
})
)
}
async setWithSync(value, duration, syncMethod) {
const setPromise = this.cacheLayers.map(item => {
return item.set(value, duration)
})
return Promise.all(
[
...setPromise,
syncMethod(value, duration)
]
)
}
async get() {
return this.highLevelCache.get()
}
async remove() {
await Promise.all(
this.cacheLayers.map(cacheKeyItem => {
return cacheKeyItem.remove()
})
)
}
}
module.exports = {
Cache,
DatabaseCache,
RedisCache,
CacheKey,
CacheKeyCascade
}

31
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/validator.js

@ -0,0 +1,31 @@
const Validator = {
Key(keyArray, parameters) {
for (let i = 0; i < keyArray.length; i++) {
const keyName = keyArray[i]
if (typeof parameters[keyName] !== 'string') {
Validator.ThrowNewError(`Invalid ${keyName}`)
}
if (parameters[keyName].length < 1) {
Validator.ThrowNewError(`Invalid ${keyName}`)
}
}
},
Value(value) {
if (value === undefined) {
Validator.ThrowNewError('Invalid Value')
}
if (typeof value !== 'object') {
Validator.ThrowNewError('Invalid Value Type')
}
},
ThrowNewError(message) {
throw new Error(message)
}
}
module.exports = {
Validator
}

203
uni_modules/uni-open-bridge-common/uniCloud/cloudfunctions/common/uni-open-bridge-common/weixin-server.js

@ -0,0 +1,203 @@
'use strict';
const crypto = require('crypto')
const {
HTTP_STATUS
} = require('./consts.js')
const {
BridgeError
} = require('./bridge-error.js')
class WeixinServer {
constructor(options = {}) {
this._appid = options.appid
this._secret = options.secret
}
getAccessToken() {
return uniCloud.httpclient.request(WeixinServer.AccessToken_Url, {
dataType: 'json',
method: 'POST',
contentType: 'json',
data: {
appid: this._appid,
secret: this._secret,
grant_type: "client_credential"
}
})
}
// 使用客户端获取的 code 从微信服务器换取 openid,code 仅可使用一次
codeToSession(code) {
return uniCloud.httpclient.request(WeixinServer.Code2Session_Url, {
dataType: 'json',
data: {
appid: this._appid,
secret: this._secret,
js_code: code,
grant_type: 'authorization_code'
}
})
}
getUserEncryptKey({
access_token,
openid,
session_key
}) {
console.log(access_token, openid, session_key);
const signature = crypto.createHmac('sha256', session_key).update('').digest('hex')
return uniCloud.httpclient.request(WeixinServer.User_Encrypt_Key_Url, {
dataType: 'json',
method: 'POST',
dataAsQueryString: true,
data: {
access_token,
openid: openid,
signature: signature,
sig_method: 'hmac_sha256'
}
})
}
getH5AccessToken() {
return uniCloud.httpclient.request(WeixinServer.AccessToken_H5_Url, {
dataType: 'json',
method: 'GET',
data: {
appid: this._appid,
secret: this._secret,
grant_type: "client_credential"
}
})
}
getH5Ticket(access_token) {
return uniCloud.httpclient.request(WeixinServer.Ticket_Url, {
dataType: 'json',
dataAsQueryString: true,
method: 'POST',
data: {
access_token
}
})
}
getH5AccessTokenForEip() {
return uniCloud.httpProxyForEip.postForm(WeixinServer.AccessToken_H5_Url, {
appid: this._appid,
secret: this._secret,
grant_type: "client_credential"
}, {
dataType: 'json'
})
}
getH5TicketForEip(access_token) {
return uniCloud.httpProxyForEip.postForm(WeixinServer.Ticket_Url, {
access_token
}, {
dataType: 'json',
dataAsQueryString: true
})
}
}
WeixinServer.AccessToken_Url = 'https://api.weixin.qq.com/cgi-bin/stable_token'
WeixinServer.Code2Session_Url = 'https://api.weixin.qq.com/sns/jscode2session'
WeixinServer.User_Encrypt_Key_Url = 'https://api.weixin.qq.com/wxa/business/getuserencryptkey'
WeixinServer.AccessToken_H5_Url = 'https://api.weixin.qq.com/cgi-bin/token'
WeixinServer.Ticket_Url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi'
WeixinServer.GetMPAccessToken = function(options) {
return new WeixinServer(options).getAccessToken()
}
WeixinServer.GetCodeToSession = function(options) {
return new WeixinServer(options).codeToSession(options.code)
}
WeixinServer.GetUserEncryptKey = function(options) {
return new WeixinServer(options).getUserEncryptKey(options)
}
WeixinServer.GetH5AccessToken = function(options) {
return new WeixinServer(options).getH5AccessToken()
}
WeixinServer.GetH5Ticket = function(options) {
return new WeixinServer(options).getH5Ticket(options.access_token)
}
////////////////////////////////////////////////////////////////
function isAliyun() {
return (uniCloud.getCloudInfos()[0].provider === 'aliyun')
}
WeixinServer.GetResponseData = function(response) {
console.log("WeixinServer::response", response)
if (!(response.status === HTTP_STATUS.SUCCESS || response.statusCodeValue === HTTP_STATUS.SUCCESS)) {
throw new BridgeError(response.status || response.statusCodeValue, response.status || response.statusCodeValue)
}
const responseData = response.data || response.body
if (responseData.errcode !== undefined && responseData.errcode !== 0) {
throw new BridgeError(responseData.errcode, responseData.errmsg)
}
return responseData
}
WeixinServer.GetMPAccessTokenData = async function(options) {
const response = await new WeixinServer(options).getAccessToken()
return WeixinServer.GetResponseData(response)
}
WeixinServer.GetCodeToSessionData = async function(options) {
const response = await new WeixinServer(options).codeToSession(options.code)
return WeixinServer.GetResponseData(response)
}
WeixinServer.GetUserEncryptKeyData = async function(options) {
const response = await new WeixinServer(options).getUserEncryptKey(options)
return WeixinServer.GetResponseData(response)
}
WeixinServer.GetH5AccessTokenData = async function(options) {
const ws = new WeixinServer(options)
let response
if (isAliyun()) {
response = await ws.getH5AccessTokenForEip()
if (typeof response === 'string') {
response = JSON.parse(response)
}
} else {
response = await ws.getH5AccessToken()
}
return WeixinServer.GetResponseData(response)
}
WeixinServer.GetH5TicketData = async function(options) {
const ws = new WeixinServer(options)
let response
if (isAliyun()) {
response = await ws.getH5TicketForEip(options.access_token)
if (typeof response === 'string') {
response = JSON.parse(response)
}
} else {
response = await ws.getH5Ticket(options.access_token)
}
return WeixinServer.GetResponseData(response)
}
module.exports = {
WeixinServer
}

19
uni_modules/uni-open-bridge-common/uniCloud/database/opendb-open-data.schema.json

@ -0,0 +1,19 @@
// : https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType": "object",
"required": ["_id", "value"],
"properties": {
"_id": {
"bsonType": "string",
"description": "key,格式:uni-id:[provider]:[appid]:[openid]:[access-token|user-access-token|session-key|encrypt-key-version|ticket]"
},
"value": {
"bsonType": "object",
"description": "字段_id对应的值"
},
"expired": {
"bsonType": "date",
"description": "过期时间"
}
}
}

8
uni_modules/uni-scss/changelog.md

@ -0,0 +1,8 @@
## 1.0.3(2022-01-21)
- 优化 组件示例
## 1.0.2(2021-11-22)
- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
## 1.0.1(2021-11-22)
- 修复 vue3中scss语法兼容问题
## 1.0.0(2021-11-18)
- init

1
uni_modules/uni-scss/index.scss

@ -0,0 +1 @@
@import './styles/index.scss';

82
uni_modules/uni-scss/package.json

@ -0,0 +1,82 @@
{
"id": "uni-scss",
"displayName": "uni-scss 辅助样式",
"version": "1.0.3",
"description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。",
"keywords": [
"uni-scss",
"uni-ui",
"辅助样式"
],
"repository": "https://github.com/dcloudio/uni-ui",
"engines": {
"HBuilderX": "^3.1.0"
},
"dcloudext": {
"category": [
"JS SDK",
"通用 SDK"
],
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y"
},
"快应用": {
"华为": "n",
"联盟": "n"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}

4
uni_modules/uni-scss/readme.md

@ -0,0 +1,4 @@
`uni-sass``uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839

7
uni_modules/uni-scss/styles/index.scss

@ -0,0 +1,7 @@
@import './setting/_variables.scss';
@import './setting/_border.scss';
@import './setting/_color.scss';
@import './setting/_space.scss';
@import './setting/_radius.scss';
@import './setting/_text.scss';
@import './setting/_styles.scss';

3
uni_modules/uni-scss/styles/setting/_border.scss

@ -0,0 +1,3 @@
.uni-border {
border: 1px $uni-border-1 solid;
}

66
uni_modules/uni-scss/styles/setting/_color.scss

@ -0,0 +1,66 @@
// TODO 暂时不需要 class 需要用户使用变量实现 如果使用类名其实并不推荐
// @mixin get-styles($k,$c) {
// @if $k == size or $k == weight{
// font-#{$k}:#{$c}
// }@else{
// #{$k}:#{$c}
// }
// }
$uni-ui-color:(
// 主色
primary: $uni-primary,
primary-disable: $uni-primary-disable,
primary-light: $uni-primary-light,
// 辅助色
success: $uni-success,
success-disable: $uni-success-disable,
success-light: $uni-success-light,
warning: $uni-warning,
warning-disable: $uni-warning-disable,
warning-light: $uni-warning-light,
error: $uni-error,
error-disable: $uni-error-disable,
error-light: $uni-error-light,
info: $uni-info,
info-disable: $uni-info-disable,
info-light: $uni-info-light,
// 中性色
main-color: $uni-main-color,
base-color: $uni-base-color,
secondary-color: $uni-secondary-color,
extra-color: $uni-extra-color,
// 背景色
bg-color: $uni-bg-color,
// 边框颜色
border-1: $uni-border-1,
border-2: $uni-border-2,
border-3: $uni-border-3,
border-4: $uni-border-4,
// 黑色
black:$uni-black,
// 白色
white:$uni-white,
// 透明
transparent:$uni-transparent
) !default;
@each $key, $child in $uni-ui-color {
.uni-#{"" + $key} {
color: $child;
}
.uni-#{"" + $key}-bg {
background-color: $child;
}
}
.uni-shadow-sm {
box-shadow: $uni-shadow-sm;
}
.uni-shadow-base {
box-shadow: $uni-shadow-base;
}
.uni-shadow-lg {
box-shadow: $uni-shadow-lg;
}
.uni-mask {
background-color:$uni-mask;
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save