├── .gitignore
├── README.md
├── cloudfunctions
├── callback
│ ├── config.json
│ ├── index.js
│ └── package.json
├── echo
│ ├── config.json
│ ├── index.js
│ └── package.json
├── login
│ ├── config.json
│ ├── index.js
│ └── package.json
└── openapi
│ ├── config.json
│ ├── index.js
│ └── package.json
├── img-demo
├── activity.jpg
├── certificate.jpg
├── home.jpg
├── info.jpg
├── list.jpg
├── map.jpg
└── rank.jpg
├── miniprogram
├── app.js
├── app.json
├── app.wxss
├── colorui.wxss
├── icon.wxss
├── images
│ ├── activity1.png
│ ├── activity2.png
│ ├── bgActivity.png
│ ├── congratulation.png
│ ├── dtp1.png
│ ├── dtp2.png
│ ├── dtp3.png
│ ├── dtp4.png
│ ├── loading-white.gif
│ ├── map1.png
│ ├── map2.png
│ ├── my1.png
│ ├── my2.png
│ ├── qrLogin.jpg
│ ├── rank1.png
│ └── rank2.png
├── pages
│ ├── activity
│ │ ├── activity.js
│ │ ├── activity.json
│ │ ├── activity.wxml
│ │ └── activity.wxss
│ ├── congratulation
│ │ ├── congratulation.js
│ │ ├── congratulation.json
│ │ ├── congratulation.wxml
│ │ └── congratulation.wxss
│ ├── login
│ │ ├── login.js
│ │ ├── login.json
│ │ ├── login.wxml
│ │ └── login.wxss
│ ├── map
│ │ ├── map.js
│ │ ├── map.json
│ │ ├── map.wxml
│ │ └── map.wxss
│ ├── my
│ │ ├── my.js
│ │ ├── my.json
│ │ ├── my.wxml
│ │ └── my.wxss
│ ├── openapi
│ │ ├── callback
│ │ │ ├── callback.js
│ │ │ ├── callback.json
│ │ │ ├── callback.wxml
│ │ │ └── callback.wxss
│ │ ├── cloudid
│ │ │ ├── cloudid.js
│ │ │ ├── cloudid.json
│ │ │ ├── cloudid.wxml
│ │ │ └── cloudid.wxss
│ │ ├── openapi.js
│ │ ├── openapi.json
│ │ ├── openapi.wxml
│ │ ├── openapi.wxss
│ │ └── serverapi
│ │ │ ├── serverapi.js
│ │ │ ├── serverapi.json
│ │ │ ├── serverapi.wxml
│ │ │ └── serverapi.wxss
│ ├── rank
│ │ ├── rank.js
│ │ ├── rank.json
│ │ ├── rank.wxml
│ │ └── rank.wxss
│ └── showMsg
│ │ ├── showMsg.js
│ │ ├── showMsg.json
│ │ ├── showMsg.wxml
│ │ └── showMsg.wxss
├── sitemap.json
├── style
│ └── guide.wxss
└── utils
│ ├── bmap-wx.min.js
│ └── qqmap-wx-jssdk.min.js
└── project.config.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows
2 | [Dd]esktop.ini
3 | Thumbs.db
4 | $RECYCLE.BIN/
5 |
6 | # macOS
7 | .DS_Store
8 | .fseventsd
9 | .Spotlight-V100
10 | .TemporaryItems
11 | .Trashes
12 |
13 | # Node.js
14 | node_modules/
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 中科大校友会
4 |
5 | 项目介绍:为迎合祖国 70 周年生日,方便中华儿女表达对祖国的祝福,催生出本微信小程序。
6 |
7 | # 主要功能:
8 |
9 | 祝福祖国(文字+图片),证书(canvas),排行(院所,省,国家),校友地图(微信接口获得经纬度+逆地址解析),个人信息(查看别人信息+隐私设置),登陆自动注册(后端使用云开发,json 数据库+图片存储)。
10 |
11 | # 云开发 quickstart
12 |
13 | 云开发的三大基础能
14 |
15 | - 数据库:一个既可在小程序前端操作,也能在云函数中读写的 JSON 文档型数据库
16 | - 文件存储:在小程序前端直接上传/下载云端文件,在云开发控制台可视化管理
17 | - 云函数:在云端运行的代码,微信私有协议天然鉴权,开发者只需编写业务逻辑代码
18 | - 参考文档:[云开发文档](https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html)
19 |
20 | # 主要优化细节
21 |
22 | - 使用有效时间缓存机制,缓存基本不会变化的图片
23 | ```
24 | getTempImageUrl(file, url) {
25 | const t = this
26 | // 获得本地缓存
27 | const fileInfo = wx.getStorageSync(file)
28 | let get_net_img = false
29 | // 缓存存在,而且有效时间存在
30 | if (fileInfo && fileInfo.filePath && fileInfo.time) {
31 | console.log(file + "图片存在本地:",fileInfo.filePath);
32 | let days = Math.ceil(((new Date()).getTime() - fileInfo.time)/(24*3600*1000));
33 | console.log("距离上一次访问图片相隔时间", days+"day");
34 | // 缓存超过不新鲜就更新
35 | (days >= 2) && (get_net_img = true);
36 | this.globalData[file] = fileInfo.filePath;
37 | } else {
38 | get_net_img = true;
39 | }
40 | // 更新缓存,请求网络图片
41 | if (get_net_img) {
42 | wx.getImageInfo({
43 | src: url,
44 | success: res => {
45 | wx.saveFile({
46 | tempFilePath: res.path,
47 | success(res) {
48 | const saveFilePath = res.savedFilePath
49 | console.log("缓存图片", file)
50 | wx.setStorageSync(file, {
51 | filePath: saveFilePath,
52 | time: (new Date()).getTime()
53 | })
54 | t.globalData[file] = saveFilePath
55 | }
56 | })
57 | },
58 | })
59 | }
60 | },
61 | ```
62 | - 使用 async/await 控制异步请求流程,有效避免了回调地狱
63 | ```
64 | async function prepare(){
65 | const openid = await t.getOpenid()
66 | console.log("获得openid", openid)
67 | t.getUser_info(openid)
68 | }
69 | prepare()
70 | ```
71 |
72 | # 页面展示
73 |
74 | - 主页 和 活动页面
75 |
76 | ##  
77 |
78 | - 展示列表 和 地图页面
79 |
80 | ##  
81 |
82 | - 排行 和 个人信息页面
83 |
84 | ##  
85 |
86 | - 证书页面
87 | ## 
88 |
--------------------------------------------------------------------------------
/cloudfunctions/callback/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | "customerServiceMessage.send"
5 | ]
6 | }
7 | }
--------------------------------------------------------------------------------
/cloudfunctions/callback/index.js:
--------------------------------------------------------------------------------
1 | const cloud = require('wx-server-sdk')
2 |
3 | cloud.init()
4 |
5 | // 云函数入口函数
6 | exports.main = async (event, context) => {
7 |
8 | console.log(event)
9 |
10 | const { OPENID } = cloud.getWXContext()
11 |
12 | const result = await cloud.openapi.customerServiceMessage.send({
13 | touser: OPENID,
14 | msgtype: 'text',
15 | text: {
16 | content: '收到:' + event.Content,
17 | }
18 | })
19 |
20 | console.log(result)
21 |
22 | return result
23 | }
24 |
--------------------------------------------------------------------------------
/cloudfunctions/callback/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "callback",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/echo/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": []
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/cloudfunctions/echo/index.js:
--------------------------------------------------------------------------------
1 | const cloud = require('wx-server-sdk')
2 |
3 | exports.main = async (event, context) => {
4 | // event.userInfo 是已废弃的保留字段,在此不做展示
5 | // 获取 OPENID 等微信上下文请使用 cloud.getWXContext()
6 | delete event.userInfo
7 | return event
8 | }
9 |
--------------------------------------------------------------------------------
/cloudfunctions/echo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "echo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
--------------------------------------------------------------------------------
/cloudfunctions/login/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": []
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/cloudfunctions/login/index.js:
--------------------------------------------------------------------------------
1 | // 云函数模板
2 | // 部署:在 cloud-functions/login 文件夹右击选择 “上传并部署”
3 |
4 | const cloud = require('wx-server-sdk')
5 |
6 | // 初始化 cloud
7 | cloud.init()
8 |
9 | /**
10 | * 这个示例将经自动鉴权过的小程序用户 openid 返回给小程序端
11 | *
12 | * event 参数包含小程序端调用传入的 data
13 | *
14 | */
15 | exports.main = (event, context) => {
16 | console.log(event)
17 | console.log(context)
18 |
19 | // 可执行其他自定义逻辑
20 | // console.log 的内容可以在云开发云函数调用日志查看
21 |
22 | // 获取 WX Context (微信调用上下文),包括 OPENID、APPID、及 UNIONID(需满足 UNIONID 获取条件)
23 | const wxContext = cloud.getWXContext()
24 |
25 | return {
26 | event,
27 | openid: wxContext.OPENID,
28 | appid: wxContext.APPID,
29 | unionid: wxContext.UNIONID,
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/cloudfunctions/login/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "login",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cloudfunctions/openapi/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "permissions": {
3 | "openapi": [
4 | "wxacode.get",
5 | "templateMessage.send",
6 | "templateMessage.addTemplate",
7 | "templateMessage.deleteTemplate",
8 | "templateMessage.getTemplateList",
9 | "templateMessage.getTemplateLibraryById",
10 | "templateMessage.getTemplateLibraryList"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/cloudfunctions/openapi/index.js:
--------------------------------------------------------------------------------
1 | // 云函数入口文件
2 | const cloud = require('wx-server-sdk')
3 |
4 | cloud.init()
5 |
6 | // 云函数入口函数
7 | exports.main = async (event, context) => {
8 | console.log(event)
9 | switch (event.action) {
10 | case 'sendTemplateMessage': {
11 | return sendTemplateMessage(event)
12 | }
13 | case 'getWXACode': {
14 | return getWXACode(event)
15 | }
16 | case 'getOpenData': {
17 | return getOpenData(event)
18 | }
19 | default: {
20 | return
21 | }
22 | }
23 | }
24 |
25 | async function sendTemplateMessage(event) {
26 | const { OPENID } = cloud.getWXContext()
27 |
28 | // 接下来将新增模板、发送模板消息、然后删除模板
29 | // 注意:新增模板然后再删除并不是建议的做法,此处只是为了演示,模板 ID 应在添加后保存起来后续使用
30 | const addResult = await cloud.openapi.templateMessage.addTemplate({
31 | id: 'AT0002',
32 | keywordIdList: [3, 4, 5]
33 | })
34 |
35 | const templateId = addResult.templateId
36 |
37 | const sendResult = await cloud.openapi.templateMessage.send({
38 | touser: OPENID,
39 | templateId,
40 | formId: event.formId,
41 | page: 'pages/openapi/openapi',
42 | data: {
43 | keyword1: {
44 | value: '未名咖啡屋',
45 | },
46 | keyword2: {
47 | value: '2019 年 1 月 1 日',
48 | },
49 | keyword3: {
50 | value: '拿铁',
51 | },
52 | }
53 | })
54 |
55 | await cloud.openapi.templateMessage.deleteTemplate({
56 | templateId,
57 | })
58 |
59 | return sendResult
60 | }
61 |
62 | async function getWXACode(event) {
63 |
64 | // 此处将获取永久有效的小程序码,并将其保存在云文件存储中,最后返回云文件 ID 给前端使用
65 |
66 | const wxacodeResult = await cloud.openapi.wxacode.get({
67 | path: 'pages/openapi/openapi',
68 | })
69 |
70 | const fileExtensionMatches = wxacodeResult.contentType.match(/\/([^\/]+)/)
71 | const fileExtension = (fileExtensionMatches && fileExtensionMatches[1]) || 'jpg'
72 |
73 | const uploadResult = await cloud.uploadFile({
74 | // 云文件路径,此处为演示采用一个固定名称
75 | cloudPath: `wxacode_default_openapi_page.${fileExtension}`,
76 | // 要上传的文件内容可直接传入图片 Buffer
77 | fileContent: wxacodeResult.buffer,
78 | })
79 |
80 | if (!uploadResult.fileID) {
81 | throw new Error(`upload failed with empty fileID and storage server status code ${uploadResult.statusCode}`)
82 | }
83 |
84 | return uploadResult.fileID
85 | }
86 |
87 | async function getOpenData(event) {
88 | // 需 wx-server-sdk >= 0.5.0
89 | return cloud.getOpenData({
90 | list: event.openData.list,
91 | })
92 | }
93 |
--------------------------------------------------------------------------------
/cloudfunctions/openapi/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "openapi",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "wx-server-sdk": "latest"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/img-demo/activity.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/activity.jpg
--------------------------------------------------------------------------------
/img-demo/certificate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/certificate.jpg
--------------------------------------------------------------------------------
/img-demo/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/home.jpg
--------------------------------------------------------------------------------
/img-demo/info.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/info.jpg
--------------------------------------------------------------------------------
/img-demo/list.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/list.jpg
--------------------------------------------------------------------------------
/img-demo/map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/map.jpg
--------------------------------------------------------------------------------
/img-demo/rank.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/img-demo/rank.jpg
--------------------------------------------------------------------------------
/miniprogram/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function() {
4 | if (!wx.cloud) {
5 | console.error('请使用 2.2.3 或以上的基础库以使用云能力')
6 | } else {
7 | wx.cloud.init({
8 | env: 'xiaoyuansongsui-xh94i',
9 | traceUser: true,
10 | })
11 | }
12 |
13 | this.globalData = {
14 | openid: '',
15 | user_info: {
16 | wxUserInfo: ''
17 | },
18 | }
19 | this.getTempImageUrl('bitrhImageUrl', 'https://www.yulovexin.xyz/images/zkd/birth.jpg');
20 | this.getTempImageUrl('avatarShowUrl', 'https://www.yulovexin.xyz/images/zkd/avatarShow.png');
21 |
22 | },
23 | backToLogin(openid) {
24 | if (!openid) {
25 | wx.reLaunch({
26 | url: '/pages/login/login',
27 | })
28 | }
29 | },
30 | getTempImageUrl(file, url) {
31 | const t = this
32 | const fileInfo = wx.getStorageSync(file)
33 | let get_net_img = false
34 | if (fileInfo && fileInfo.filePath && fileInfo.time) {
35 | console.log(file + "图片存在本地:",fileInfo.filePath);
36 | let days = Math.ceil(((new Date()).getTime() - fileInfo.time)/(24*3600*1000));
37 | console.log("距离上一次访问图片相隔时间", days+"day");
38 | (days >= 2) && (get_net_img = true);
39 | this.globalData[file] = fileInfo.filePath;
40 | } else {
41 | get_net_img = true;
42 | }
43 | if (get_net_img) {
44 | wx.getImageInfo({
45 | src: url,
46 | success: res => {
47 | wx.saveFile({
48 | tempFilePath: res.path,
49 | success(res) {
50 | const saveFilePath = res.savedFilePath
51 | console.log("缓存图片", file)
52 | wx.setStorageSync(file, {
53 | filePath: saveFilePath,
54 | time: (new Date()).getTime()
55 | })
56 | t.globalData[file] = saveFilePath
57 | }
58 | })
59 | },
60 | })
61 | }
62 | },
63 | })
--------------------------------------------------------------------------------
/miniprogram/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/login/login",
4 | "pages/congratulation/congratulation",
5 | "pages/map/map",
6 | "pages/my/my",
7 | "pages/rank/rank",
8 | "pages/showMsg/showMsg",
9 | "pages/activity/activity"
10 | ],
11 | "tabBar": {
12 | "backgroundColor": "#B00004",
13 | "selectedColor": "#fff",
14 | "color": "#fff",
15 | "list": [
16 | {
17 | "pagePath": "pages/map/map",
18 | "iconPath": "images/map2.png",
19 | "selectedIconPath": "images/map1.png",
20 | "text": "校友地图"
21 | },
22 | {
23 | "pagePath": "pages/activity/activity",
24 | "iconPath": "images/activity2.png",
25 | "selectedIconPath": "images/activity1.png",
26 | "text": "祝福贺卡"
27 | },
28 | {
29 | "pagePath": "pages/rank/rank",
30 | "iconPath": "images/rank2.png",
31 | "selectedIconPath": "images/rank1.png",
32 | "text": "排行榜"
33 | },
34 | {
35 | "pagePath": "pages/my/my",
36 | "iconPath": "images/my2.png",
37 | "selectedIconPath": "images/my1.png",
38 | "text": "我的信息"
39 | }
40 | ]
41 | },
42 | "window": {
43 | "enablePullDownRefresh": false,
44 | "backgroundColor": "#F6F6F6",
45 | "backgroundTextStyle": "light",
46 | "navigationBarBackgroundColor": "#F6F6F6",
47 | "navigationBarTitleText": "中科院校友会",
48 | "navigationBarTextStyle": "black"
49 | },
50 | "sitemapLocation": "sitemap.json",
51 | "permission":{
52 | "scope.userLocation": {
53 | "desc": "你的位置信息将用于小程序位置接口的效果展示"
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/miniprogram/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | @import 'icon.wxss';
3 | @import 'colorui.wxss';
4 | .container {
5 | display: flex;
6 | flex-direction: column;
7 | align-items: center;
8 | box-sizing: border-box;
9 | }
10 |
11 | button {
12 | background: initial;
13 | }
14 |
15 | button:focus{
16 | outline: 0;
17 | }
18 |
19 | button::after{
20 | border: none;
21 | }
22 |
23 |
24 | page {
25 | background: #f6f6f6;
26 | display: flex;
27 | flex-direction: column;
28 | justify-content: flex-start;
29 | }
30 | .hover{
31 | background-color: rgba(0, 0, 0, 0.1);
32 | opacity: 0.7;
33 | }
--------------------------------------------------------------------------------
/miniprogram/icon.wxss:
--------------------------------------------------------------------------------
1 | @keyframes icon-spin {
2 | 0% {
3 | -webkit-transform: rotate(0);
4 | transform: rotate(0);
5 | }
6 | 100% {
7 | -webkit-transform: rotate(359deg);
8 | transform: rotate(359deg);
9 | }
10 | }
11 |
12 | .iconfont-spin {
13 | -webkit-animation: icon-spin 2s infinite linear;
14 | animation: icon-spin 2s infinite linear;
15 | display: inline-block;
16 | }
17 |
18 | .iconfont-pulse {
19 | -webkit-animation: icon-spin 1s infinite steps(8);
20 | animation: icon-spin 1s infinite steps(8);
21 | display: inline-block;
22 | }
23 |
24 | text[class*="icon-"],
25 | view[class*="icon-"],
26 | button[class*="icon-"] {
27 | font-family: "cuIcon" !important;
28 | font-size: inherit;
29 | font-style: normal;
30 | }
31 |
32 |
33 | @font-face {font-family: "cuIcon";
34 | src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831'); /* IE9*/
35 | src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831#iefix') format('embedded-opentype'), /* IE6-IE8 */
36 | url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
37 | url('//at.alicdn.com/t/font_533566_yfq2d9wdij.ttf?t=1545239985831') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
38 | url('//at.alicdn.com/t/font_533566_yfq2d9wdij.svg?t=1545239985831#iconfont') format('svg'); /* iOS 4.1- */
39 | }
40 |
41 | .icon-appreciate:before { content: "\e644"; }
42 |
43 | .icon-check:before { content: "\e645"; }
44 |
45 | .icon-close:before { content: "\e646"; }
46 |
47 | .icon-edit:before { content: "\e649"; }
48 |
49 | .icon-emoji:before { content: "\e64a"; }
50 |
51 | .icon-favorfill:before { content: "\e64b"; }
52 |
53 | .icon-favor:before { content: "\e64c"; }
54 |
55 | .icon-loading:before { content: "\e64f"; }
56 |
57 | .icon-locationfill:before { content: "\e650"; }
58 |
59 | .icon-location:before { content: "\e651"; }
60 |
61 | .icon-phone:before { content: "\e652"; }
62 |
63 | .icon-roundcheckfill:before { content: "\e656"; }
64 |
65 | .icon-roundcheck:before { content: "\e657"; }
66 |
67 | .icon-roundclosefill:before { content: "\e658"; }
68 |
69 | .icon-roundclose:before { content: "\e659"; }
70 |
71 | .icon-roundrightfill:before { content: "\e65a"; }
72 |
73 | .icon-roundright:before { content: "\e65b"; }
74 |
75 | .icon-search:before { content: "\e65c"; }
76 |
77 | .icon-taxi:before { content: "\e65d"; }
78 |
79 | .icon-timefill:before { content: "\e65e"; }
80 |
81 | .icon-time:before { content: "\e65f"; }
82 |
83 | .icon-unfold:before { content: "\e661"; }
84 |
85 | .icon-warnfill:before { content: "\e662"; }
86 |
87 | .icon-warn:before { content: "\e663"; }
88 |
89 | .icon-camerafill:before { content: "\e664"; }
90 |
91 | .icon-camera:before { content: "\e665"; }
92 |
93 | .icon-commentfill:before { content: "\e666"; }
94 |
95 | .icon-comment:before { content: "\e667"; }
96 |
97 | .icon-likefill:before { content: "\e668"; }
98 |
99 | .icon-like:before { content: "\e669"; }
100 |
101 | .icon-notificationfill:before { content: "\e66a"; }
102 |
103 | .icon-notification:before { content: "\e66b"; }
104 |
105 | .icon-order:before { content: "\e66c"; }
106 |
107 | .icon-samefill:before { content: "\e66d"; }
108 |
109 | .icon-same:before { content: "\e66e"; }
110 |
111 | .icon-deliver:before { content: "\e671"; }
112 |
113 | .icon-evaluate:before { content: "\e672"; }
114 |
115 | .icon-pay:before { content: "\e673"; }
116 |
117 | .icon-send:before { content: "\e675"; }
118 |
119 | .icon-shop:before { content: "\e676"; }
120 |
121 | .icon-ticket:before { content: "\e677"; }
122 |
123 | .icon-back:before { content: "\e679"; }
124 |
125 | .icon-cascades:before { content: "\e67c"; }
126 |
127 | .icon-discover:before { content: "\e67e"; }
128 |
129 | .icon-list:before { content: "\e682"; }
130 |
131 | .icon-more:before { content: "\e684"; }
132 |
133 | .icon-scan:before { content: "\e689"; }
134 |
135 | .icon-settings:before { content: "\e68a"; }
136 |
137 | .icon-questionfill:before { content: "\e690"; }
138 |
139 | .icon-question:before { content: "\e691"; }
140 |
141 | .icon-shopfill:before { content: "\e697"; }
142 |
143 | .icon-form:before { content: "\e699"; }
144 |
145 | .icon-pic:before { content: "\e69b"; }
146 |
147 | .icon-filter:before { content: "\e69c"; }
148 |
149 | .icon-footprint:before { content: "\e69d"; }
150 |
151 | .icon-top:before { content: "\e69e"; }
152 |
153 | .icon-pulldown:before { content: "\e69f"; }
154 |
155 | .icon-pullup:before { content: "\e6a0"; }
156 |
157 | .icon-right:before { content: "\e6a3"; }
158 |
159 | .icon-refresh:before { content: "\e6a4"; }
160 |
161 | .icon-moreandroid:before { content: "\e6a5"; }
162 |
163 | .icon-deletefill:before { content: "\e6a6"; }
164 |
165 | .icon-refund:before { content: "\e6ac"; }
166 |
167 | .icon-cart:before { content: "\e6af"; }
168 |
169 | .icon-qrcode:before { content: "\e6b0"; }
170 |
171 | .icon-remind:before { content: "\e6b2"; }
172 |
173 | .icon-delete:before { content: "\e6b4"; }
174 |
175 | .icon-profile:before { content: "\e6b7"; }
176 |
177 | .icon-home:before { content: "\e6b8"; }
178 |
179 | .icon-cartfill:before { content: "\e6b9"; }
180 |
181 | .icon-discoverfill:before { content: "\e6ba"; }
182 |
183 | .icon-homefill:before { content: "\e6bb"; }
184 |
185 | .icon-message:before { content: "\e6bc"; }
186 |
187 | .icon-addressbook:before { content: "\e6bd"; }
188 |
189 | .icon-link:before { content: "\e6bf"; }
190 |
191 | .icon-lock:before { content: "\e6c0"; }
192 |
193 | .icon-unlock:before { content: "\e6c2"; }
194 |
195 | .icon-vip:before { content: "\e6c3"; }
196 |
197 | .icon-weibo:before { content: "\e6c4"; }
198 |
199 | .icon-activity:before { content: "\e6c5"; }
200 |
201 | .icon-friendaddfill:before { content: "\e6c9"; }
202 |
203 | .icon-friendadd:before { content: "\e6ca"; }
204 |
205 | .icon-friendfamous:before { content: "\e6cb"; }
206 |
207 | .icon-friend:before { content: "\e6cc"; }
208 |
209 | .icon-goods:before { content: "\e6cd"; }
210 |
211 | .icon-selection:before { content: "\e6ce"; }
212 |
213 | .icon-explore:before { content: "\e6d2"; }
214 |
215 | .icon-present:before { content: "\e6d3"; }
216 |
217 | .icon-squarecheckfill:before { content: "\e6d4"; }
218 |
219 | .icon-square:before { content: "\e6d5"; }
220 |
221 | .icon-squarecheck:before { content: "\e6d6"; }
222 |
223 | .icon-round:before { content: "\e6d7"; }
224 |
225 | .icon-roundaddfill:before { content: "\e6d8"; }
226 |
227 | .icon-roundadd:before { content: "\e6d9"; }
228 |
229 | .icon-add:before { content: "\e6da"; }
230 |
231 | .icon-notificationforbidfill:before { content: "\e6db"; }
232 |
233 | .icon-explorefill:before { content: "\e6dd"; }
234 |
235 | .icon-fold:before { content: "\e6de"; }
236 |
237 | .icon-game:before { content: "\e6df"; }
238 |
239 | .icon-redpacket:before { content: "\e6e0"; }
240 |
241 | .icon-selectionfill:before { content: "\e6e1"; }
242 |
243 | .icon-similar:before { content: "\e6e2"; }
244 |
245 | .icon-appreciatefill:before { content: "\e6e3"; }
246 |
247 | .icon-infofill:before { content: "\e6e4"; }
248 |
249 | .icon-info:before { content: "\e6e5"; }
250 |
251 | .icon-forwardfill:before { content: "\e6ea"; }
252 |
253 | .icon-forward:before { content: "\e6eb"; }
254 |
255 | .icon-rechargefill:before { content: "\e6ec"; }
256 |
257 | .icon-recharge:before { content: "\e6ed"; }
258 |
259 | .icon-vipcard:before { content: "\e6ee"; }
260 |
261 | .icon-voice:before { content: "\e6ef"; }
262 |
263 | .icon-voicefill:before { content: "\e6f0"; }
264 |
265 | .icon-friendfavor:before { content: "\e6f1"; }
266 |
267 | .icon-wifi:before { content: "\e6f2"; }
268 |
269 | .icon-share:before { content: "\e6f3"; }
270 |
271 | .icon-wefill:before { content: "\e6f4"; }
272 |
273 | .icon-we:before { content: "\e6f5"; }
274 |
275 | .icon-lightauto:before { content: "\e6f6"; }
276 |
277 | .icon-lightforbid:before { content: "\e6f7"; }
278 |
279 | .icon-lightfill:before { content: "\e6f8"; }
280 |
281 | .icon-camerarotate:before { content: "\e6f9"; }
282 |
283 | .icon-light:before { content: "\e6fa"; }
284 |
285 | .icon-barcode:before { content: "\e6fb"; }
286 |
287 | .icon-flashlightclose:before { content: "\e6fc"; }
288 |
289 | .icon-flashlightopen:before { content: "\e6fd"; }
290 |
291 | .icon-searchlist:before { content: "\e6fe"; }
292 |
293 | .icon-service:before { content: "\e6ff"; }
294 |
295 | .icon-sort:before { content: "\e700"; }
296 |
297 | .icon-down:before { content: "\e703"; }
298 |
299 | .icon-mobile:before { content: "\e704"; }
300 |
301 | .icon-mobilefill:before { content: "\e705"; }
302 |
303 | .icon-copy:before { content: "\e706"; }
304 |
305 | .icon-countdownfill:before { content: "\e707"; }
306 |
307 | .icon-countdown:before { content: "\e708"; }
308 |
309 | .icon-noticefill:before { content: "\e709"; }
310 |
311 | .icon-notice:before { content: "\e70a"; }
312 |
313 | .icon-upstagefill:before { content: "\e70e"; }
314 |
315 | .icon-upstage:before { content: "\e70f"; }
316 |
317 | .icon-babyfill:before { content: "\e710"; }
318 |
319 | .icon-baby:before { content: "\e711"; }
320 |
321 | .icon-brandfill:before { content: "\e712"; }
322 |
323 | .icon-brand:before { content: "\e713"; }
324 |
325 | .icon-choicenessfill:before { content: "\e714"; }
326 |
327 | .icon-choiceness:before { content: "\e715"; }
328 |
329 | .icon-clothesfill:before { content: "\e716"; }
330 |
331 | .icon-clothes:before { content: "\e717"; }
332 |
333 | .icon-creativefill:before { content: "\e718"; }
334 |
335 | .icon-creative:before { content: "\e719"; }
336 |
337 | .icon-female:before { content: "\e71a"; }
338 |
339 | .icon-keyboard:before { content: "\e71b"; }
340 |
341 | .icon-male:before { content: "\e71c"; }
342 |
343 | .icon-newfill:before { content: "\e71d"; }
344 |
345 | .icon-new:before { content: "\e71e"; }
346 |
347 | .icon-pullleft:before { content: "\e71f"; }
348 |
349 | .icon-pullright:before { content: "\e720"; }
350 |
351 | .icon-rankfill:before { content: "\e721"; }
352 |
353 | .icon-rank:before { content: "\e722"; }
354 |
355 | .icon-bad:before { content: "\e723"; }
356 |
357 | .icon-cameraadd:before { content: "\e724"; }
358 |
359 | .icon-focus:before { content: "\e725"; }
360 |
361 | .icon-friendfill:before { content: "\e726"; }
362 |
363 | .icon-cameraaddfill:before { content: "\e727"; }
364 |
365 | .icon-apps:before { content: "\e729"; }
366 |
367 | .icon-paintfill:before { content: "\e72a"; }
368 |
369 | .icon-paint:before { content: "\e72b"; }
370 |
371 | .icon-picfill:before { content: "\e72c"; }
372 |
373 | .icon-refresharrow:before { content: "\e72d"; }
374 |
375 | .icon-colorlens:before { content: "\e6e6"; }
376 |
377 | .icon-markfill:before { content: "\e730"; }
378 |
379 | .icon-mark:before { content: "\e731"; }
380 |
381 | .icon-presentfill:before { content: "\e732"; }
382 |
383 | .icon-repeal:before { content: "\e733"; }
384 |
385 | .icon-album:before { content: "\e734"; }
386 |
387 | .icon-peoplefill:before { content: "\e735"; }
388 |
389 | .icon-people:before { content: "\e736"; }
390 |
391 | .icon-servicefill:before { content: "\e737"; }
392 |
393 | .icon-repair:before { content: "\e738"; }
394 |
395 | .icon-file:before { content: "\e739"; }
396 |
397 | .icon-repairfill:before { content: "\e73a"; }
398 |
399 | .icon-taoxiaopu:before { content: "\e73b"; }
400 |
401 | .icon-weixin:before { content: "\e612"; }
402 |
403 | .icon-attentionfill:before { content: "\e73c"; }
404 |
405 | .icon-attention:before { content: "\e73d"; }
406 |
407 | .icon-commandfill:before { content: "\e73e"; }
408 |
409 | .icon-command:before { content: "\e73f"; }
410 |
411 | .icon-communityfill:before { content: "\e740"; }
412 |
413 | .icon-community:before { content: "\e741"; }
414 |
415 | .icon-read:before { content: "\e742"; }
416 |
417 | .icon-calendar:before { content: "\e74a"; }
418 |
419 | .icon-cut:before { content: "\e74b"; }
420 |
421 | .icon-magic:before { content: "\e74c"; }
422 |
423 | .icon-backwardfill:before { content: "\e74d"; }
424 |
425 | .icon-playfill:before { content: "\e74f"; }
426 |
427 | .icon-stop:before { content: "\e750"; }
428 |
429 | .icon-tagfill:before { content: "\e751"; }
430 |
431 | .icon-tag:before { content: "\e752"; }
432 |
433 | .icon-group:before { content: "\e753"; }
434 |
435 | .icon-all:before { content: "\e755"; }
436 |
437 | .icon-backdelete:before { content: "\e756"; }
438 |
439 | .icon-hotfill:before { content: "\e757"; }
440 |
441 | .icon-hot:before { content: "\e758"; }
442 |
443 | .icon-post:before { content: "\e759"; }
444 |
445 | .icon-radiobox:before { content: "\e75b"; }
446 |
447 | .icon-rounddown:before { content: "\e75c"; }
448 |
449 | .icon-upload:before { content: "\e75d"; }
450 |
451 | .icon-writefill:before { content: "\e760"; }
452 |
453 | .icon-write:before { content: "\e761"; }
454 |
455 | .icon-radioboxfill:before { content: "\e763"; }
456 |
457 | .icon-punch:before { content: "\e764"; }
458 |
459 | .icon-shake:before { content: "\e765"; }
460 |
461 | .icon-move:before { content: "\e768"; }
462 |
463 | .icon-safe:before { content: "\e769"; }
464 |
465 | .icon-activityfill:before { content: "\e775"; }
466 |
467 | .icon-crownfill:before { content: "\e776"; }
468 |
469 | .icon-crown:before { content: "\e777"; }
470 |
471 | .icon-goodsfill:before { content: "\e778"; }
472 |
473 | .icon-messagefill:before { content: "\e779"; }
474 |
475 | .icon-profilefill:before { content: "\e77a"; }
476 |
477 | .icon-sound:before { content: "\e77b"; }
478 |
479 | .icon-sponsorfill:before { content: "\e77c"; }
480 |
481 | .icon-sponsor:before { content: "\e77d"; }
482 |
483 | .icon-upblock:before { content: "\e77e"; }
484 |
485 | .icon-weblock:before { content: "\e77f"; }
486 |
487 | .icon-weunblock:before { content: "\e780"; }
488 |
489 | .icon-my:before { content: "\e78b"; }
490 |
491 | .icon-myfill:before { content: "\e78c"; }
492 |
493 | .icon-emojifill:before { content: "\e78d"; }
494 |
495 | .icon-emojiflashfill:before { content: "\e78e"; }
496 |
497 | .icon-flashbuyfill:before { content: "\e78f"; }
498 |
499 | .icon-text:before { content: "\e791"; }
500 |
501 | .icon-goodsfavor:before { content: "\e794"; }
502 |
503 | .icon-musicfill:before { content: "\e795"; }
504 |
505 | .icon-musicforbidfill:before { content: "\e796"; }
506 |
507 | .icon-card:before { content: "\e624"; }
508 |
509 | .icon-triangledownfill:before { content: "\e79b"; }
510 |
511 | .icon-triangleupfill:before { content: "\e79c"; }
512 |
513 | .icon-roundleftfill-copy:before { content: "\e79e"; }
514 |
515 | .icon-font:before { content: "\e76a"; }
516 |
517 | .icon-title:before { content: "\e82f"; }
518 |
519 | .icon-recordfill:before { content: "\e7a4"; }
520 |
521 | .icon-record:before { content: "\e7a6"; }
522 |
523 | .icon-cardboardfill:before { content: "\e7a9"; }
524 |
525 | .icon-cardboard:before { content: "\e7aa"; }
526 |
527 | .icon-formfill:before { content: "\e7ab"; }
528 |
529 | .icon-coin:before { content: "\e7ac"; }
530 |
531 | .icon-cardboardforbid:before { content: "\e7af"; }
532 |
533 | .icon-circlefill:before { content: "\e7b0"; }
534 |
535 | .icon-circle:before { content: "\e7b1"; }
536 |
537 | .icon-attentionforbid:before { content: "\e7b2"; }
538 |
539 | .icon-attentionforbidfill:before { content: "\e7b3"; }
540 |
541 | .icon-attentionfavorfill:before { content: "\e7b4"; }
542 |
543 | .icon-attentionfavor:before { content: "\e7b5"; }
544 |
545 | .icon-titles:before { content: "\e701"; }
546 |
547 | .icon-icloading:before { content: "\e67a"; }
548 |
549 | .icon-full:before { content: "\e7bc"; }
550 |
551 | .icon-mail:before { content: "\e7bd"; }
552 |
553 | .icon-peoplelist:before { content: "\e7be"; }
554 |
555 | .icon-goodsnewfill:before { content: "\e7bf"; }
556 |
557 | .icon-goodsnew:before { content: "\e7c0"; }
558 |
559 | .icon-medalfill:before { content: "\e7c1"; }
560 |
561 | .icon-medal:before { content: "\e7c2"; }
562 |
563 | .icon-newsfill:before { content: "\e7c3"; }
564 |
565 | .icon-newshotfill:before { content: "\e7c4"; }
566 |
567 | .icon-newshot:before { content: "\e7c5"; }
568 |
569 | .icon-news:before { content: "\e7c6"; }
570 |
571 | .icon-videofill:before { content: "\e7c7"; }
572 |
573 | .icon-video:before { content: "\e7c8"; }
574 |
575 | .icon-exit:before { content: "\e7cb"; }
576 |
577 | .icon-skinfill:before { content: "\e7cc"; }
578 |
579 | .icon-skin:before { content: "\e7cd"; }
580 |
581 | .icon-moneybagfill:before { content: "\e7ce"; }
582 |
583 | .icon-usefullfill:before { content: "\e7cf"; }
584 |
585 | .icon-usefull:before { content: "\e7d0"; }
586 |
587 | .icon-moneybag:before { content: "\e7d1"; }
588 |
589 | .icon-redpacket_fill:before { content: "\e7d3"; }
590 |
591 | .icon-subscription:before { content: "\e7d4"; }
592 |
593 | .icon-loading1:before { content: "\e633"; }
594 |
595 | .icon-github:before { content: "\e692"; }
596 |
597 | .icon-global:before { content: "\e7eb"; }
598 |
599 | .icon-settingsfill:before { content: "\e6ab"; }
600 |
601 | .icon-back_android:before { content: "\e7ed"; }
602 |
603 | .icon-expressman:before { content: "\e7ef"; }
604 |
605 | .icon-evaluate_fill:before { content: "\e7f0"; }
606 |
607 | .icon-group_fill:before { content: "\e7f5"; }
608 |
609 | .icon-play_forward_fill:before { content: "\e7f6"; }
610 |
611 | .icon-deliver_fill:before { content: "\e7f7"; }
612 |
613 | .icon-notice_forbid_fill:before { content: "\e7f8"; }
614 |
615 | .icon-fork:before { content: "\e60c"; }
616 |
617 | .icon-pick:before { content: "\e7fa"; }
618 |
619 | .icon-wenzi:before { content: "\e6a7"; }
620 |
621 | .icon-ellipse:before { content: "\e600"; }
622 |
623 | .icon-qr_code:before { content: "\e61b"; }
624 |
625 | .icon-dianhua:before { content: "\e64d"; }
626 |
627 | .icon-icon:before { content: "\e602"; }
628 |
629 | .icon-loading2:before { content: "\e7f1"; }
630 |
631 | .icon-btn:before { content: "\e601"; }
632 |
633 |
--------------------------------------------------------------------------------
/miniprogram/images/activity1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/activity1.png
--------------------------------------------------------------------------------
/miniprogram/images/activity2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/activity2.png
--------------------------------------------------------------------------------
/miniprogram/images/bgActivity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/bgActivity.png
--------------------------------------------------------------------------------
/miniprogram/images/congratulation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/congratulation.png
--------------------------------------------------------------------------------
/miniprogram/images/dtp1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/dtp1.png
--------------------------------------------------------------------------------
/miniprogram/images/dtp2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/dtp2.png
--------------------------------------------------------------------------------
/miniprogram/images/dtp3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/dtp3.png
--------------------------------------------------------------------------------
/miniprogram/images/dtp4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/dtp4.png
--------------------------------------------------------------------------------
/miniprogram/images/loading-white.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/loading-white.gif
--------------------------------------------------------------------------------
/miniprogram/images/map1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/map1.png
--------------------------------------------------------------------------------
/miniprogram/images/map2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/map2.png
--------------------------------------------------------------------------------
/miniprogram/images/my1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/my1.png
--------------------------------------------------------------------------------
/miniprogram/images/my2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/my2.png
--------------------------------------------------------------------------------
/miniprogram/images/qrLogin.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/qrLogin.jpg
--------------------------------------------------------------------------------
/miniprogram/images/rank1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/rank1.png
--------------------------------------------------------------------------------
/miniprogram/images/rank2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UESTCzhouyuchuan/zkd/ffe085b24a22c0eb878b5e2a0a42ae8da880e61c/miniprogram/images/rank2.png
--------------------------------------------------------------------------------
/miniprogram/pages/activity/activity.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/activity/activity.js
2 | Page({
3 | /**
4 | * 页面的初始数据
5 | */
6 | data: {
7 | imgs: [],
8 | textareaAValue: '',
9 | canSubmit: true,
10 | isSubmiting: false,
11 | congratulations: []
12 | },
13 | viewPersonInfo(e) {
14 | const openid = e.currentTarget.dataset.openid
15 | wx.navigateTo({
16 | url: '/pages/showMsg/showMsg?openid=' + openid
17 | })
18 | },
19 | save1(text_content, imgsID) {
20 | const t = this
21 | const db = wx.cloud.database()
22 | const user_info = getApp().globalData.user_info
23 | db.collection('publish_info').add({
24 | data: {
25 | text_content: text_content,
26 | imgsID: imgsID,
27 | createTimer: db.serverDate()
28 | }
29 | }).then(res => {
30 | wx.hideLoading()
31 | wx.showToast({
32 | title: '提交成功',
33 | icon: 'success',
34 | duration: 1000,
35 | mask: true
36 | })
37 | const cong = {
38 | openid: getApp().globalData.openid,
39 | nickName: user_info.wxUserInfo.nickName,
40 | avatarUrl: user_info.wxUserInfo.avatarUrl,
41 | institution: user_info.institution,
42 | text_content: text_content,
43 | imgsUrl: t.data.imgs
44 | }
45 | let congratulations = t.data.congratulations
46 | congratulations.unshift(cong)
47 | t.setData({
48 | isSubmiting: false,
49 | congratulations: congratulations
50 | })
51 | new Promise((resolve,reject)=>{
52 | db.collection('publish_info').count().then(res=>{
53 | console.log("第多少位",res)
54 | wx.navigateTo({
55 | url: '/pages/congratulation/congratulation?number=' + res.total,
56 | })
57 | t.setData({
58 | imgs: [],
59 | textareaAValue: '',
60 | })
61 | })
62 | })
63 | setTimeout(() => {
64 | t.setData({
65 | canSubmit: true
66 | })
67 | }, 5000)
68 | }).catch((err) => {
69 | wx.showToast({
70 | title: '上传失败',
71 | icon: 'none',
72 | duration: 1000
73 | })
74 | console.log(err)
75 | })
76 | },
77 | save() {
78 | const openid = getApp().globalData.openid
79 | const text_content = this.data.textareaAValue
80 | if (!openid) {
81 | console.log("获取openid失败")
82 | wx.showToast({
83 | title: '请检查网络连接或者退出重新登陆',
84 | icon: 'none',
85 | duration: 1000,
86 | mask: true
87 | })
88 | } else if (text_content) {
89 | if (this.data.canSubmit) {
90 | wx.showLoading({
91 | title: '正在上传',
92 | mask: true
93 | })
94 | this.setData({
95 | canSubmit: false,
96 | isSubmiting: true
97 | })
98 | const imgs = this.data.imgs
99 | const t = this
100 | let imgsID = []
101 | if (imgs.length > 0) {
102 | let uploads = []
103 | for (let i = 0; i < imgs.length; i++) {
104 | uploads[i] = new Promise((resolve, reject) => {
105 | wx.cloud.uploadFile({
106 | filePath: imgs[i],
107 | cloudPath: 'wish/' + openid + "/" + (new Date()).getTime() + i + imgs[i].match(/\.[^.]+?$/)[0],
108 | success: function(res) {
109 | console.log("上传成功")
110 | imgsID.push(res.fileID)
111 | resolve()
112 | }
113 | })
114 | })
115 | }
116 | Promise.all(uploads).then(() => {
117 | t.save1(text_content, imgsID)
118 | }).catch((err) => {
119 | wx.showToast({
120 | title: '上传图片失败',
121 | icon: 'none',
122 | duration: 1000
123 | })
124 | console.log(err)
125 | })
126 | } else {
127 | t.save1(text_content, imgsID)
128 | }
129 | } else {
130 | wx.showModal({
131 | content: '请勿频繁提交',
132 | })
133 | }
134 | } else {
135 | wx.showToast({
136 | title: '请输入内容',
137 | icon: 'none',
138 | duration: 1000
139 | })
140 | }
141 | },
142 | chooseImg() {
143 | const t = this
144 | wx.chooseImage({
145 | count: 9 - t.data.imgs.length,
146 | sizeType: ['compressed'],
147 | sourceType: ['album', 'camera'],
148 | success: function(res) {
149 | if (res.tempFiles.length > 0) {
150 | t.setData({
151 | imgs: t.data.imgs.concat(res.tempFilePaths)
152 | })
153 | }
154 | },
155 | })
156 | },
157 | textareaAInput(e) {
158 | this.setData({
159 | textareaAValue: e.detail.value
160 | })
161 | },
162 | ViewImage(e) {
163 | wx.previewImage({
164 | urls: e.currentTarget.dataset.urls,
165 | current: e.currentTarget.dataset.current
166 | });
167 | },
168 | DelImg(e) {
169 | wx.showModal({
170 | title: '',
171 | content: '确定要删除吗?',
172 | cancelText: '手滑了',
173 | confirmText: '确定',
174 | success: res => {
175 | if (res.confirm) {
176 | this.data.imgs.splice(e.currentTarget.dataset.index, 1);
177 | this.setData({
178 | imgs: this.data.imgs
179 | })
180 | }
181 | }
182 | })
183 | },
184 | asy(list) {
185 | const t = this
186 | // console.log(list)
187 | const db = wx.cloud.database()
188 | return new Promise((resolve, reject) => {
189 | if (list.imgsID.length > 0) {
190 | let fileList = []
191 | wx.cloud.getTempFileURL({
192 | fileList: list.imgsID
193 | }).then(res => {
194 | // console.log("成功获得图片")
195 | // console.log("res.fileList", res.fileList)
196 | let imgsUrl=[]
197 | let img
198 | for (img of res.fileList){
199 | imgsUrl.unshift(img.tempFileURL)
200 | }
201 | let cong = {
202 | openid: list._openid,
203 | avatarUrl: '',
204 | nickName: '',
205 | institution: '',
206 | text_content: list.text_content,
207 | imgsUrl: imgsUrl
208 | }
209 | db.collection('user_info').doc(list._openid).field({
210 | 'wxUserInfo.avatarUrl': true,
211 | 'wxUserInfo.nickName': true,
212 | 'institution': true,
213 | }).get().then(res => {
214 | // console.log(res)
215 | cong.avatarUrl = res.data.wxUserInfo.avatarUrl
216 | cong.institution = res.data.institution
217 | cong.nickName = res.data.wxUserInfo.nickName
218 | let congratulations = t.data.congratulations
219 | congratulations.push(cong)
220 | t.setData({
221 | congratulations: congratulations
222 | })
223 | resolve()
224 | }).catch(err => {
225 | console.log(err)
226 | reject()
227 | })
228 | })
229 | } else {
230 | let cong = {
231 | openid: list._openid,
232 | avatarUrl: '',
233 | nickName: '',
234 | institution: '',
235 | text_content: list.text_content,
236 | imgsUrl: []
237 | }
238 | db.collection('user_info').doc(list._openid).field({
239 | 'wxUserInfo.avatarUrl': true,
240 | 'wxUserInfo.nickName': true,
241 | 'institution': true,
242 | }).get().then(res => {
243 | // console.log(res)
244 | cong.avatarUrl = res.data.wxUserInfo.avatarUrl
245 | cong.institution = res.data.institution
246 | cong.nickName = res.data.wxUserInfo.nickName
247 | let congratulations = t.data.congratulations
248 | congratulations.push(cong)
249 | t.setData({
250 | congratulations: congratulations
251 | })
252 | resolve()
253 | }).catch(err => {
254 | console.log(err)
255 | })
256 | }
257 | }).catch(err => {
258 | console.log(err)
259 | })
260 | },
261 | GetCongratulations() {
262 | const t = this
263 | const getAsy = async function(lists) {
264 | let list
265 | for (list of lists) {
266 | await t.asy(list)
267 | }
268 | }
269 | const db = wx.cloud.database()
270 | db.collection('publish_info').orderBy('createTimer', 'desc').get().then(res => {
271 | console.log(res)
272 | getAsy(res.data)
273 | }).catch(err => {
274 | console.log(err)
275 | })
276 | },
277 | /**
278 | * 生命周期函数--监听页面加载
279 | */
280 | onLoad: function(options) {
281 | getApp().backToLogin(getApp().globalData.openid)
282 | this.GetCongratulations()
283 | },
284 |
285 | /**
286 | * 生命周期函数--监听页面初次渲染完成
287 | */
288 | onReady: function() {
289 |
290 | },
291 |
292 | /**
293 | * 生命周期函数--监听页面显示
294 | */
295 | onShow: function() {
296 |
297 | },
298 |
299 | /**
300 | * 生命周期函数--监听页面隐藏
301 | */
302 | onHide: function() {
303 |
304 | },
305 |
306 | /**
307 | * 生命周期函数--监听页面卸载
308 | */
309 | onUnload: function() {
310 |
311 | },
312 |
313 | /**
314 | * 页面相关事件处理函数--监听用户下拉动作
315 | */
316 | onPullDownRefresh: function() {
317 | // this.GetCongratulations()
318 | },
319 |
320 | /**
321 | * 页面上拉触底事件的处理函数
322 | */
323 | onReachBottom: function() {
324 |
325 | },
326 |
327 | /**
328 | * 用户点击右上角分享
329 | */
330 | onShareAppMessage: function() {
331 |
332 | }
333 | })
--------------------------------------------------------------------------------
/miniprogram/pages/activity/activity.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/activity/activity.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
33 |
35 |
36 |
37 |
38 | 精选祝福
39 |
40 |
41 |
42 |
43 |
54 |
55 | {{congItem.text_content}}
56 |
57 |
58 |
59 |
60 |
61 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/miniprogram/pages/activity/activity.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/activity/activity.wxss */
2 | /* page {
3 | background:url('https://47.100.219.208/images/tmp/bg.png') repeat-y;
4 | background-size: 100% 100%;
5 | height: auto;
6 | }
7 | cu-bar,.cu-form-group{
8 | background-color: rgba(255, 255, 255, 0.5)
9 | } */
10 | .cu-form-group{
11 | background-color:transparent;
12 | }
13 | .cu-form-group .textarea-box{
14 | width: 600rpx;
15 | height: 400rpx;
16 | margin: auto;
17 | border: #D5867D solid 4rpx;
18 | border-radius: 10rpx;
19 | box-sizing: border-box;
20 | }
21 | .cu-form-group .textarea-box textarea{
22 | color: #884B06;
23 | margin: 20rpx;
24 | height: 360rpx;
25 | width: 560rpx;
26 | line-height: 1.2em;
27 | flex: 1;
28 | font-size: 32rpx;
29 | padding: 0;
30 | box-sizing: content-box;
31 | display: inline-block;
32 | vertical-align: top;
33 | }
34 | .congratulation,.container{
35 | width: 100%;
36 | }
37 | .congratulation{
38 | background: rgba(255,255,255,0.1);
39 | background-image:url('https://www.yulovexin.xyz/images/zkd/bgActivity.png');
40 | background-size: cover;
41 | width: 100%;
42 | display: flex;
43 | flex-direction: column;
44 | align-items: center;
45 | }
46 | form{
47 | width: 100%;
48 | }
49 | .header{
50 | margin-top: 60rpx;
51 | text-align: center;
52 | color: #930302;
53 | font-size: 40rpx;
54 | font-weight: 500;
55 | }
56 | .save{
57 | width: 450rpx;
58 | background-color: #e8c975;
59 | margin: 20rpx auto 40rpx;
60 | height: 80rpx;
61 | font-size: 35rpx;
62 | line-height: 80rpx;
63 | color: #884c07;
64 | font-weight: 600;
65 | }
66 | .tip view{
67 | margin: 5rpx 0;
68 | }
69 | .list-wrap{
70 | background: #eee;
71 | width: 100%;
72 | display: flex;
73 | padding:20rpx;
74 | flex-direction: column;
75 | }
76 | .congratulations{
77 | border: 1px solid #eee;
78 | border-radius: 30rpx;
79 | box-shadow: 0 0rpx 8rpx #fff;
80 | margin-bottom: 10rpx;
81 | }
--------------------------------------------------------------------------------
/miniprogram/pages/congratulation/congratulation.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/congratulation/congratulation.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | showPic: false,
9 | number: 520,
10 | nickName: "周玉川"
11 | },
12 | toCertificate() {
13 | wx.previewImage({
14 | urls: [this.data.previewImagePath],
15 | fail: err => {
16 | wx.showModal({
17 | title: '加载图片失败',
18 | })
19 | }
20 | })
21 | },
22 | showPic() {
23 | this.setData({
24 | showPic: true
25 | })
26 | this.createPic()
27 | },
28 | createPic() {
29 | const t = this
30 | wx.createSelectorQuery().in(this).select('.birth').boundingClientRect((wrap) => {
31 | const width = wrap.width
32 | const height = wrap.height
33 | console.log(width, height)
34 | wx.showLoading({
35 | title: '正在渲染',
36 | mask: false
37 | })
38 | let pic = []
39 | pic[0] = new Promise((resolve, reject) => {
40 | const bitrhImageUrl = getApp().globalData.bitrhImageUrl
41 | if (bitrhImageUrl) {
42 | console.log("已经缓存bitrhImageUrl")
43 | resolve(bitrhImageUrl)
44 | } else {
45 | wx.getImageInfo({
46 | src: 'https://www.yulovexin.xyz/images/zkd/birth.jpg',
47 | success(res) {
48 | resolve(res.path)
49 | },
50 | fail(err) {
51 | console.log(err)
52 | reject(err)
53 | }
54 | })
55 | }
56 | })
57 | pic[1] = new Promise((resolve, reject) => {
58 | const avatarImageUrl = getApp().globalData.avatarImageUrl
59 | if (avatarImageUrl) {
60 | console.log("已经缓存avatarImageUrl")
61 | resolve(avatarImageUrl)
62 | } else {
63 | wx.getImageInfo({
64 | src: getApp().globalData.user_info.wxUserInfo.avatarUrl,
65 | success(res) {
66 | resolve(res.path)
67 | },
68 | fail(err) {
69 | console.log(err)
70 | reject(err)
71 | }
72 | })
73 | }
74 | })
75 | pic[2] = new Promise((resolve, reject) => {
76 | const avatarShowUrl = getApp().globalData.avatarShowUrl
77 | if (avatarShowUrl) {
78 | console.log("已经缓存avatarShowUrl")
79 | resolve(avatarShowUrl)
80 | } else {
81 | wx.getImageInfo({
82 | src: '',
83 | success(res) {
84 | resolve(res.path)
85 | },
86 | fail(err) {
87 | console.log(err)
88 | reject(err)
89 | }
90 | })
91 | }
92 | })
93 | Promise.all(pic).then(res => {
94 | console.log(res)
95 | //获取设备的信息
96 | let mobile = wx.getSystemInfoSync();
97 | //获取设计图纸换算比例(用于自适应所有屏幕)
98 | let ratio = mobile.windowWidth / 375;
99 | const avatar = 25*ratio;
100 | const avatarShow = 50*ratio
101 | const birth = wx.createCanvasContext('birth')
102 | birth.drawImage(res[0], 0, 0, width, height)
103 | birth.setFillStyle('#EA7517')
104 | birth.setFontSize(14)
105 | birth.fillText(t.data.nickName, 60, height / 2)
106 | birth.fillText("No."+t.data.number, 60, height / 2 + 20)
107 | birth.drawImage(res[2], width / 2 -avatarShow , 60*ratio-avatarShow, avatarShow * 2, avatarShow *2)
108 | birth.save()
109 | birth.arc(width / 2 + ratio * 2, 55 * ratio,avatar,0,Math.PI*2);
110 | birth.clip()
111 | birth.drawImage(res[1], width / 2 + ratio * 2 - avatar, 55*ratio-avatar, avatar * 2, avatar * 2)
112 | birth.restore()
113 | birth.draw(false, t.viewPictrue())
114 | wx.hideLoading()
115 | })
116 | }).exec();
117 | },
118 | viewPictrue() {
119 | const t = this
120 | wx.hideLoading()
121 | setTimeout(function() {
122 | wx.canvasToTempFilePath({
123 | canvasId: 'birth',
124 | success(res) {
125 | console.log(res)
126 | t.setData({
127 | previewImagePath: res.tempFilePath
128 | })
129 | },
130 | fail(err) {
131 | console.log("转变失败", err)
132 | }
133 | })
134 | }, 1000)
135 | },
136 | /**
137 | * 生命周期函数--监听页面加载
138 | */
139 | onLoad: function(options) {
140 | getApp().backToLogin(getApp().globalData.openid)
141 | this.setData({
142 | number: options.number,
143 | nickName: getApp().globalData.user_info.wxUserInfo.nickName
144 | })
145 | // this.setData({
146 | // number:520,
147 | // nickName:'周玉川'
148 | // })
149 | },
150 |
151 | /**
152 | * 生命周期函数--监听页面初次渲染完成
153 | */
154 | onReady: function() {
155 |
156 | },
157 |
158 | /**
159 | * 生命周期函数--监听页面显示
160 | */
161 | onShow: function() {
162 |
163 | },
164 |
165 | /**
166 | * 生命周期函数--监听页面隐藏
167 | */
168 | onHide: function() {
169 |
170 | },
171 |
172 | /**
173 | * 生命周期函数--监听页面卸载
174 | */
175 | onUnload: function() {
176 |
177 | },
178 |
179 | /**
180 | * 页面相关事件处理函数--监听用户下拉动作
181 | */
182 | onPullDownRefresh: function() {
183 |
184 | },
185 |
186 | /**
187 | * 页面上拉触底事件的处理函数
188 | */
189 | onReachBottom: function() {
190 |
191 | },
192 |
193 | /**
194 | * 用户点击右上角分享
195 | */
196 | onShareAppMessage: function() {
197 |
198 | }
199 | })
--------------------------------------------------------------------------------
/miniprogram/pages/congratulation/congratulation.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/congratulation/congratulation.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | 点击证书后查看,然后,长按保存分享
8 |
9 |
10 |
11 |
12 | 亲爱的{{nickName}}:
13 | 恭喜您是第{{number}}位点亮全球地图的校友,您已获得中科院70周年校庆的祝福证书
14 |
15 |
16 |
--------------------------------------------------------------------------------
/miniprogram/pages/congratulation/congratulation.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/congratulation/congratulation.wxss */
2 | .container{
3 | height: 100vh;
4 | background: #aaa;
5 | }
6 | .bg{
7 | margin: 200rpx auto;
8 | height: 742rpx;
9 | width: 650rpx;
10 | position: relative;
11 | }
12 | .text{
13 | color: red;
14 | position: absolute;
15 | top: 220rpx;
16 | left: 150rpx;
17 | width: 400rpx;
18 | font-size: 32rpx;
19 | font-weight: 400;
20 | }
21 | .indent{
22 | text-indent:2rem;
23 | }
24 | .birth-wrap{
25 | min-height: 100vh;
26 | background-attachment: fixed;
27 | background-size: cover;
28 | width: 100%;
29 | display: flex;
30 | flex-direction: column;
31 | align-items: center;
32 | }
33 | .header{
34 | margin: 50rpx;
35 | text-align: center;
36 | color:green;
37 | font-size: 40rpx;
38 | font-weight: 500;
39 | }
40 | .birth-box{
41 | width: 640rpx;
42 | height: 940rpx;
43 | padding: 20rpx;
44 | border-radius: 20rpx;
45 | background: #F6D4CB;
46 | }
47 | .birth{
48 | width: 600rpx;
49 | height: 900rpx;
50 | border-radius: 20rpx;
51 | }
52 | .tip{
53 | text-align: center;
54 | color: #444;
55 | }
--------------------------------------------------------------------------------
/miniprogram/pages/login/login.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/login/login.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | canIUse: wx.canIUse('button.open-type.getUserInfo'),
9 | toActivity: true,
10 | updateWxUserInfo: false,
11 | openid: '',
12 | isSubmiting: false,
13 | prepare: false
14 | },
15 | enter() {
16 | let url
17 | if (this.data.toActivity) {
18 | url = '/pages/activity/activity'
19 | } else {
20 | url = '/pages/my/my'
21 | }
22 | wx.switchTab({
23 | url: url,
24 | })
25 | },
26 | isObjectValueEqual(a, b) {
27 | //取对象a和b的属性名
28 | var aProps = Object.getOwnPropertyNames(a);
29 | var bProps = Object.getOwnPropertyNames(b);
30 | //判断属性名的length是否一致
31 | if (aProps.length != bProps.length) {
32 | return false;
33 | }
34 | //循环取出属性名,再判断属性值是否一致
35 | for (var i = 0; i < aProps.length; i++) {
36 | var propName = aProps[i];
37 | if (a[propName] !== b[propName]) {
38 | return false;
39 | }
40 | }
41 | return true;
42 | },
43 | GetLocation() {
44 | const t = this
45 | const openid = this.data.openid
46 | wx.authorize({
47 | scope: 'scope.userLocation',
48 | success() {
49 | wx.getLocation({
50 | success: function(res) {
51 | console.log("成功获得位置", res)
52 | const location = {
53 | latitude: res.latitude,
54 | longitude: res.longitude
55 | }
56 | t.enter()
57 | wx.showToast({
58 | title: '登陆成功',
59 | icon: 'success',
60 | duration:1000
61 | })
62 | // 以下
63 | const qqMap = require('../../utils/qqmap-wx-jssdk.min.js')
64 | const qqmap = new qqMap({
65 | key: 'NXTBZ-USQW6-5SSSZ-ETPAB-HWTVE-SKFYX',
66 | })
67 | new Promise((resolve,reject) => {
68 | qqmap.reverseGeocoder({
69 | location: location,
70 | sig: 'tcSoDsYQo8eFiKODsMEaHTEUIoiwxcqF',
71 | success(res) {
72 | console.log(res)
73 | location.adress = res.result
74 | resolve()
75 | },
76 | fail(err) {
77 | reject(err)
78 | }
79 | })
80 | }).then(res=>{
81 | wx.cloud.database().collection('user_info').doc(openid).update({
82 | data: {
83 | location: location
84 | }
85 | }).then(res => {
86 | console.log("更新用户location成功", res)
87 | getApp().globalData.user_info.location = location
88 | }).catch(err => {
89 | console.log("更新用户location失败", err)
90 | })
91 | }).catch(err=>{
92 | console.log("逆地址解析失败",err)
93 | })
94 | },
95 | })
96 | },
97 | fail() {
98 | wx.showModal({
99 | title: '提示',
100 | content: '请进行位置授权,即将打开设置页面',
101 | mask: true,
102 | success(res) {
103 | if (res.confirm) {
104 | wx.openSetting({
105 | success(res) {
106 | console.log(res.authSetting)
107 | }
108 | })
109 | }
110 | }
111 | })
112 | }
113 | })
114 | },
115 | loading() {
116 | this.setData({
117 | isSubmiting: true
118 | })
119 | },
120 | bindGetUserInfo(e) {
121 | wx.showLoading({
122 | title: '正在登陆',
123 | })
124 | if (!this.data.prepare){
125 | return;
126 | }
127 | const openid = this.data.openid
128 | const wxUserInfo = e.detail.userInfo
129 | if (!openid) {
130 | wx.showToast({
131 | title: '请检查网络是否连接',
132 | icon: 'none'
133 | })
134 | this.setData({
135 | isSubmiting: false
136 | })
137 | } else if (wxUserInfo) {
138 | console.log("获取wxUserInfo", wxUserInfo)
139 | const user_info = getApp().globalData.user_info
140 | getApp().getTempImageUrl('avatarImageUrl', wxUserInfo.avatarUrl);
141 | console.log('user_info', getApp().globalData.user_info)
142 | if (!user_info.wxUserInfo || !this.isObjectValueEqual(user_info.wxUserInfo, wxUserInfo)) {
143 | console.log('wxuserinfo存在修改')
144 | wx.cloud.database().collection('user_info').doc(openid).update({
145 | data: {
146 | wxUserInfo: wxUserInfo
147 | }
148 | }).then(res => {
149 | console.log("成功修改userInfo",res)
150 | getApp().globalData.user_info.wxUserInfo = wxUserInfo
151 | }).catch(err => {
152 | console.log(err)
153 | this.setData({
154 | isSubmiting: false
155 | })
156 | })
157 | this.GetLocation()
158 | } else {
159 | console.log('wxuserinfo未修改,直接进入授权')
160 | this.GetLocation()
161 | }
162 | } else {
163 | wx.showModal({
164 | title: '提示',
165 | content: '授权之后才能进行其他操作',
166 | })
167 | this.setData({
168 | isSubmiting: false
169 | })
170 | }
171 | },
172 | getOpenid() {
173 | return new Promise((resolve,reject)=>{
174 | const t = this
175 | let openid = wx.getStorageSync('openid')
176 | if (!openid) {
177 | console.log("缓存中无No openid")
178 | wx.cloud.callFunction({
179 | name: 'login',
180 | success: res => {
181 | console.log(res)
182 | openid = res.result.openid;
183 | wx.setStorageSync('openid', res.result.openid)
184 | getApp().globalData.openid = openid
185 | t.setData({
186 | openid: openid
187 | })
188 | resolve(openid)
189 | // console.log(res.result.openid, this.globalData.openid)
190 | },
191 | fail: err => {
192 | console.log("Error mesg: ", err)
193 | wx.showToast({
194 | title: '获取信息失败,请检查网络',
195 | icon:'none'
196 | })
197 | reject()
198 | }
199 | })
200 | } else {
201 | console.log("通过缓存获得openid")
202 | getApp().globalData.openid = openid
203 | t.setData({
204 | openid: openid
205 | })
206 | resolve(openid)
207 | }
208 |
209 | })
210 | },
211 | /**
212 | * 生命周期函数--监听页面加载
213 | */
214 | // getTempImageUrl() {
215 | // wx.getImageInfo({
216 | // src: 'https://47.100.219.208/images/zkd/birth.png',
217 | // success: res => {
218 | // console.log("获得临时图片成功")
219 | // getApp().globalData.birthUrl = res.path
220 | // },
221 | // })
222 | // },
223 | onLoad: function(options) {
224 | const t = this
225 | async function prepare(){
226 | const openid = await t.getOpenid()
227 | console.log("获得openid", openid)
228 | t.getUser_info(openid)
229 | }
230 | prepare()
231 | // this.getTempImageUrl()
232 | },
233 | getUser_info(openid) {
234 | const t = this
235 | const db = wx.cloud.database()
236 | db.collection('user_info').doc(openid).get().then(res => {
237 | console.log("获得user", res)
238 | const user_info = res.data
239 | if (user_info) {
240 | delete user_info._openid
241 | delete user_info._id
242 | }
243 | getApp().globalData.user_info = user_info
244 | if (!user_info || !user_info.name) {
245 | t.setData({
246 | toActivity: false
247 | })
248 | }
249 | t.setData({
250 | prepare: true
251 | })
252 | }).catch(err => {
253 | console.log("获取user_info失败", err.errMsg)
254 | if (err.errMsg.indexOf('document.get:fail Error: cannot find document with _id') != -1) {
255 | console.log("新建user_info")
256 | wx.showLoading({
257 | title: '正在注册',
258 | })
259 | db.collection('user_info').doc(openid).set({
260 | data: {
261 | name: ''
262 | }
263 | }).then(res => {
264 | console.log("新建user_info成功",res)
265 | wx.hideLoading()
266 | wx.showToast({
267 | title: '注册成功',
268 | duration:1000
269 | })
270 | getApp().globalData.user_info = {
271 | name: ''
272 | }
273 | t.setData({
274 | prepare: true,
275 | toActivity: false
276 | })
277 | }).catch(err => {
278 | console.log(err)
279 | })
280 | } else {
281 | wx.showModal({
282 | title: '提示',
283 | content: '请检查网络情况',
284 | })
285 | }
286 | })
287 | },
288 | /**
289 | * 生命周期函数--监听页面初次渲染完成
290 | */
291 | onReady: function() {
292 |
293 | },
294 |
295 | /**
296 | * 生命周期函数--监听页面显示
297 | */
298 | onShow: function() {
299 |
300 | },
301 |
302 | /**
303 | * 生命周期函数--监听页面隐藏
304 | */
305 | onHide: function() {
306 |
307 | },
308 |
309 | /**
310 | * 生命周期函数--监听页面卸载
311 | */
312 | onUnload: function() {
313 |
314 | },
315 |
316 | /**
317 | * 页面相关事件处理函数--监听用户下拉动作
318 | */
319 | onPullDownRefresh: function() {
320 |
321 | },
322 |
323 | /**
324 | * 页面上拉触底事件的处理函数
325 | */
326 | onReachBottom: function() {
327 |
328 | },
329 |
330 | /**
331 | * 用户点击右上角分享
332 | */
333 | onShareAppMessage: function() {
334 |
335 | }
336 | })
--------------------------------------------------------------------------------
/miniprogram/pages/login/login.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/login/login.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 | 请升级微信版本
9 |
10 |
11 |
--------------------------------------------------------------------------------
/miniprogram/pages/login/login.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/login/login.wxss */
2 | .container{
3 | height: 100vh;
4 | justify-content: flex-end;
5 | background-attachment: fixed;
6 | background-size: 100% 100%;
7 | }
8 | .bg{
9 | position: fixed;
10 | height: 100%;
11 | width: 100%;
12 | }
13 | .qr{
14 | position: fixed;
15 | right: 15rpx;
16 | bottom: 40rpx;
17 | width: 130rpx;
18 | height: 130rpx;
19 | background: url('https://www.yulovexin.xyz/images/zkd/qrLogin.jpg');
20 | background-size: cover;
21 | }
22 | .bottom{
23 | margin-bottom: 50rpx;
24 | }
25 | button{
26 | height: 80rpx;
27 | line-height: 80rpx;
28 | font-size: 50rpx;
29 | font-weight: 500;
30 | box-shadow: -3rpx 3rpx 2rpx #eee;
31 | background-color: #DBBA68;
32 | color: #884B06;
33 | width: 400rpx;
34 | }
--------------------------------------------------------------------------------
/miniprogram/pages/map/map.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/map/map.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | noticeIndex: -1,
9 | notices: [],
10 | showNotice: false,
11 | duration: 0,
12 | speed: 1200,
13 | wrapWidth: 0,
14 | width: 0,
15 | noticeAnimation: null,
16 | timer: null,
17 | myLocation: {
18 | latitude: 30.65984,
19 | longitude: 104.10194
20 | },
21 | include_points: [],
22 | setting: {
23 | skew: 0,
24 | rotate: 0,
25 | showLocation: true,
26 | showScale: true,
27 | subKey: 'NXTBZ-USQW6-5SSSZ-ETPAB-HWTVE-SKFYX',
28 | enableZoom: true,
29 | enableScroll: true,
30 | enableRotate: false,
31 | showCompass: false,
32 | enable3D: false,
33 | enableOverlooking: false,
34 | enableSatellite: false,
35 | enableTraffic: false,
36 | }
37 | },
38 | initAnimation() {
39 | wx.createSelectorQuery().in(this).select('.noticeBar-wrap').boundingClientRect((wrap) => {
40 | const animation = wx.createAnimation({
41 | duration: 0,
42 | timingFunction: "linear",
43 | });
44 | const resetAnimation = animation.translateX(wrap.width).step();
45 | this.setData({
46 | noticeAnimation: resetAnimation.export(),
47 | wrapWidth: wrap.width
48 | });
49 | // console.log("回到最右")
50 | const index = (this.data.noticeIndex + 1) % this.data.notices.length
51 | this.setData({
52 | noticeIndex: index,
53 | }, function() {
54 | wx.createSelectorQuery().in(this).select('.noticeBar-content').boundingClientRect((content) => {
55 | // console.log("查询")
56 | const duration = content.width / 40 * this.data.speed;
57 | const animation = wx.createAnimation({
58 | duration: duration,
59 | timingFunction: "linear",
60 | });
61 | this.setData({
62 | width: content.width,
63 | duration: duration,
64 | animation: animation,
65 | }, () => {
66 | this.startAnimation();
67 | });
68 | }).exec();
69 | })
70 | }).exec();
71 | },
72 | startAnimation() {
73 | // console.log("回到最左")
74 | this.data.animation.option.transition.duration = this.data.duration;
75 | const noticeAnimation = this.data.animation.translateX(-this.data.width).step();
76 | setTimeout(() => {
77 | this.setData({
78 | noticeAnimation: noticeAnimation.export()
79 | });
80 | }, 100);
81 | const timer = setTimeout(() => {
82 | this.initAnimation();
83 | }, this.data.duration);
84 | this.setData({
85 | timer
86 | })
87 | },
88 | destroyTimer() {
89 | if (this.data.timer) {
90 | clearTimeout(this.data.timer)
91 | }
92 | },
93 | getNotices() {
94 | const db = wx.cloud.database()
95 | const t = this
96 | let notices = []
97 | db.collection('publish_info').orderBy('createTimer', 'desc').get().then(res => {
98 | const data = res.data
99 | let getInfo = []
100 | for (let i in data) {
101 | getInfo[i] = new Promise((resolve, reject) => {
102 | db.collection('user_info').doc(data[i]._openid).get().then(res => {
103 | notices.push(res.data.wxUserInfo.nickName + ":" + data[i].text_content)
104 | resolve()
105 | })
106 | })
107 | }
108 | Promise.all(getInfo).then(() => {
109 | // console.log(notices)
110 | notices.unshift('祝福祖国,祝福中科院,祝福校友们')
111 | t.setData({
112 | notices: notices,
113 | })
114 | t.initAnimation();
115 | })
116 | })
117 | },
118 | getUserLocate() {
119 | const t = this
120 | let pic
121 |
122 | function itemMapDetail(a, b) {
123 | for (let item of b) {
124 | let obj = {
125 | width: 35,
126 | height: 50,
127 | zIndex: 3,
128 | callout: {
129 | color: '#FF0202', //文本颜色
130 | borderRadius: 10, //边框圆角
131 | borderWidth: 2, //边框宽度
132 | borderColor: '#FF0202', //边框颜色
133 | bgColor: '#ffffff', //背景色
134 | padding: 5, //文本边缘留白
135 | textAlign: 'left' //文本对齐方式。有效值: left, right, center
136 | }
137 | }
138 | if (!(item.show_location === false) && item.location) {
139 | let phone = (item.show_info === false ? '用户选择不展示' : item.phone) || '未填写';
140 | obj.callout.content = "名字:" + (item.name || '未填写') + "\n院所:" + (item.institution || '未填写') + "\n学位:"+ (item.degree || '未填写') + "\n电话:" + phone;
141 | pic = Math.floor(Math.random() * 4) + 1;
142 | obj.iconPath = '/images/dtp' + pic + '.png';
143 | obj.latitude = item.location.latitude;
144 | obj.longitude = item.location.longitude;
145 | a.push(obj);
146 | }
147 | }
148 | }
149 | async function getAllUserLocation() {
150 | let con = true
151 | let i = 0;
152 | let locations = []
153 | while (con) {
154 | await new Promise((resolve, reject) => {
155 | wx.cloud.database().collection('user_info').skip(i * 20).limit(20).get().then(res => {
156 | i += 1
157 | console.log(res.data)
158 | if (res.data.length < 20) {
159 | con = false
160 | }
161 | itemMapDetail(locations, res.data)
162 | resolve()
163 | }).catch(err => {
164 | console.log("获得用户失败", err)
165 | })
166 | })
167 | }
168 | console.log("获得全部用户位置", locations)
169 | t.marks(locations)
170 | }
171 | getAllUserLocation()
172 | },
173 | marks(locations) {
174 | this.setData({
175 | marks: locations,
176 | include_points: locations
177 | })
178 | },
179 | /**
180 | * 生命周期函数--监听页面加载
181 | */
182 | onLoad: function(options) {
183 | getApp().backToLogin(getApp().globalData.openid)
184 | this.setData({
185 | myLocation: getApp().globalData.user_info.location
186 | })
187 | this.getNotices()
188 | this.getUserLocate()
189 | },
190 | /**
191 | * 生命周期函数--监听页面初次渲染完成
192 | */
193 | onReady: function() {
194 |
195 | },
196 |
197 | /**
198 | * 生命周期函数--监听页面显示
199 | */
200 | onShow: function() {
201 |
202 | },
203 |
204 | /**
205 | * 生命周期函数--监听页面隐藏
206 | */
207 | onHide: function() {
208 |
209 | },
210 |
211 | /**
212 | * 生命周期函数--监听页面卸载
213 | */
214 | onUnload: function() {
215 |
216 | },
217 |
218 | /**
219 | * 页面相关事件处理函数--监听用户下拉动作
220 | */
221 | onPullDownRefresh: function() {
222 |
223 | },
224 |
225 | /**
226 | * 页面上拉触底事件的处理函数
227 | */
228 | onReachBottom: function() {
229 |
230 | },
231 |
232 | /**
233 | * 用户点击右上角分享
234 | */
235 | onShareAppMessage: function() {
236 |
237 | }
238 | })
--------------------------------------------------------------------------------
/miniprogram/pages/map/map.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/map/map.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{notices[noticeIndex]}}
6 |
7 |
8 |
--------------------------------------------------------------------------------
/miniprogram/pages/map/map.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/map/map.wxss */
2 | map{
3 | width: 100%;
4 | height:100vh;
5 | }
6 | .noticeBar{
7 | display: flex;
8 | height: 72rpx;
9 | line-height: 72rpx;
10 | font-size: 28rpx;
11 | color: #f76a24;
12 | background-color: #fefcec;
13 | overflow: hidden
14 | }
15 | .noticeBar-icon{
16 | display: flex;
17 | margin-left: 30rpx;
18 | }
19 | .noticeBar-wrap{
20 | position: relative;
21 | flex: 1; /*占据右侧屏幕*/
22 | margin: 0 30rpx;
23 | overflow: hidden;
24 | text-overflow: ellipsis;
25 | white-space: nowrap;
26 | }
27 | .noticeBar-wrap .noticeBar-content{
28 | position: absolute;
29 | transition-duration: 20s;
30 | }
--------------------------------------------------------------------------------
/miniprogram/pages/my/my.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/my/my.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | user_info: '',
9 | qrID: '',
10 | qr: '',
11 | showModal: false,
12 | notices: [],
13 | showNotice: false,
14 | canConfirm: false,
15 | institution_: '',
16 | institution: '',
17 | institutions: ['半导体研究所', '北京基因组研究所', "测量与地球物理研究所", "成都计算机应用研究所", "成都山地灾害与环境研究所", "成都生物研究所", "成都有机化学研究所", "城市环境研究所", "大连化学物理研究所", "大气物理研究所", "地理科学与资源研究所", "地球化学研究所", "地球环境研究所", "地质与地球物理研究所", "电工研究所", "电子学研究所", "东北地理与农业生态研究所", "动物研究所", "分子细胞科学卓越创新中心(生物化学与细胞生物学研究所)", "分子植物科学卓越创新中心(植物生理生态研究所)", "福建物质结构研究所", "高能物理研究所", "工程热物理研究所", "古脊椎动物与古人类研究所", "光电技术研究所", "光电研究院", "广州地球化学研究所", "广州化学研究所", "广州能源研究所", "广州生物医药与健康研究院", "国家空间科学中心", "国家纳米科学中心", "国家授时中心", "国家天文台", "过程工程研究所", "海洋研究所", "合肥物质科学研究院", "华南植物园", "化学研究所", "计算机网络信息中心", "计算技术研究所", "金属研究所", "近代物理研究所", "科技政策与管理科学研究所", "空间应用工程与技术中心", "昆明动物研究所", "昆明植物研究所", "兰州化学物理研究所", "兰州油气资源研究中心", "理化技术研究所", "理论物理研究所", "力学研究所", "南海海洋研究所", "南京地理与湖泊研究所", "南京地质古生物研究所", "南京天文光学技术研究所", "南京天文仪器研制中心", "南京土壤研究所", "脑科学与智能技术卓越创新中心(神经科学研究所)", "宁波材料技术与工程研究所", "青藏高原研究所", "青岛生物能源与过程研究所", "青海盐湖研究所", "软件研究所", "山西煤炭化学研究所", "上海巴斯德研究所", "上海高等研究院", "上海光学精密机械研究所", "上海硅酸盐研究所", "上海技术物理研究所", "上海生命科学研究院", "上海天文台", "上海微系统与信息技术研究所", "上海药物研究所", "上海营养与健康研究院", "上海应用物理研究所", "上海有机化学研究所", "深海科学与工程研究所", "深圳先进技术研究院", "沈阳计算技术研究所", "沈阳应用生态研究所", "沈阳自动化研究所", "渗流流体力学研究所", "生态环境研究中心", "生物物理研究所", "声学所东海研究站", "声学研究所", "数学与系统科学研究院", "水生生物研究所", "水土保持与生态环境研究中心", "苏州纳米技术与纳米仿生研究所", "苏州生物医学工程技术研究所", "天津工业生物技术研究所", "微电子研究所", "微生物研究所", "文献情报中心", "武汉病毒研究所", "武汉物理与数学研究所", "武汉岩土力学研究所", "武汉植物园", "物理研究所", "西安光学精密机械研究所", "西北高原生物研究所", "西北生态环境资源研究院", "西双版纳热带植物园", "心理研究所", "新疆理化技术研究所", "新疆生态与地理研究所", "新疆天文台", "信息工程研究所", "亚热带农业生态研究所", "烟台海岸带研究所", "遥感与数字地球研究所", '遗传与发育生物学所农业资源研究中心', "遗传与发育生物学研究所", "云南天文台", "长春光学精密机械与物理研究所", '长春人造卫星观测站', '长春应用化学研究所', '植物研究所', '重庆绿色智能技术研究院', '紫金山天文台', '自动化研究所', '自然科学史研究所', '中国科学院大学', '数学科学学院', '物理科学学院', '地球与行星科学学院', '资源与环境学院', '生命科学学院', '计算机与控制学院', '经济与管理学院', '人文学院', '外语系', '工程科学学院', '电子电气与通信工程学院', '中丹学院', '华大教育中心', '公共政策与管理学院', '本科部', '国际学院', '存济医学院', '天文与空间科学学院', '微电子学院', '网络空间安全学院', '未来技术学院', '人工智能技术学院', '心理学系', '化学科学学院', '化学工程学院', '材料科学与光电技术学院', '纳米学院', '知识产权学院', '马克思主义学院', '创新创业学院', '艺术中心', '卡弗里理论科学研究所', '虚拟经济与数据科学研究中心', '大数据挖掘与知识管理重点实验室', '医学中心', '基础教育研究院', '建筑研究与设计中心', '网络创新与发展研究中心', '创新方法研究中心', '培训中心', '计算地球动力学重点实验室', '真空物理重点实验室', '管理干部学院', '核科学与技术学院', '科技服务有限公司', '上海微小卫星工程中心', '北京生命科学研究院', '南京水利科学研究院', '中国空间技术研究院', '北京橡胶工业研究设计院', '轻工业环境保护研究所']
18 | },
19 | click_notice(e) {
20 | this.setData({
21 | institution: e.currentTarget.dataset.value,
22 | canConfirm: true,
23 | showNotice: false,
24 | })
25 | },
26 | input_(e) {
27 | const key = e.detail.value
28 | // console.log("input", key)
29 | if (key != this.data.institution_) {
30 | this.setData({
31 | institution_: key
32 | })
33 | let notices = []
34 | if (key) {
35 | for (let value of this.data.institutions) {
36 | if (value.indexOf(key) > -1) {
37 | notices.push(value)
38 | }
39 | }
40 | }
41 | this.setData({
42 | notices: notices
43 | })
44 | }
45 | // console.log("查询结果一共",notices.length)
46 | },
47 | focus() {
48 | this.setData({
49 | showNotice: true
50 | })
51 | },
52 | showModal() {
53 | this.setData({
54 | showModal: true,
55 | institution: '',
56 | })
57 | },
58 | hideModal() {
59 | this.setData({
60 | showModal: false,
61 | canConfirm: false,
62 | showModal: false,
63 | notices: [],
64 | institution_: ''
65 | })
66 | },
67 | confirm() {
68 | this.setData({
69 | 'user_info.institution': this.data.institution
70 | })
71 | this.hideModal()
72 | },
73 | input_qr() {
74 | const t = this
75 | wx.chooseImage({
76 | count: 1,
77 | sizeType: ['compressed'],
78 | success: function(res) {
79 | if (res.tempFilePaths.length > 0) {
80 | t.setData({
81 | qr: res.tempFilePaths[0]
82 | })
83 | }
84 | },
85 | })
86 | },
87 | input(e) {
88 | const user_info = this.data.user_info
89 | user_info[e.currentTarget.dataset.key] = e.detail.value
90 | this.setData({
91 | user_info: user_info
92 | })
93 | // console.log(user_info)
94 | },
95 | chooseDegree(e) {
96 | const itemList = ['学士', '硕士', '博士', '教工']
97 | wx.showActionSheet({
98 | itemList: itemList,
99 | success: res => {
100 | const degree = itemList[res.tapIndex]
101 | if (degree != this.data.degree) {
102 | this.setData({
103 | 'user_info.degree': degree
104 | })
105 | }
106 | }
107 | })
108 | },
109 | save() {
110 | const user_info = this.data.user_info
111 | console.log("user_info", user_info)
112 | const openid = getApp().globalData.openid
113 | if (!openid) {
114 | console.log("获取openid失败")
115 | wx.showToast({
116 | title: '请检查网络连接或者退出重新登陆',
117 | icon: 'none',
118 | duration: 1000,
119 | mask: true
120 | })
121 | } else if (!user_info.name || !user_info.enter_year || !user_info.institution || !user_info.degree ||
122 | !user_info.work_unit || !user_info.adress || !this.data.qr) {
123 | setTimeout(() => {
124 | wx.showToast({
125 | title: '星号(*)代表必填项',
126 | icon: 'none',
127 | duration: 1000,
128 | mask: true
129 | })
130 | }, 200)
131 | } else if (user_info.enter_year < 1978) {
132 | wx.showToast({
133 | title: '入校年份应大于1978',
134 | icon: 'none',
135 | duration: 1000,
136 | mask: true
137 | })
138 | } else if (user_info.enter_year > (new Date()).getFullYear()) {
139 | wx.showToast({
140 | title: '入校年份应不大于今年' + (new Date()).getFullYear(),
141 | icon: 'none',
142 | duration: 1000,
143 | mask: true
144 | })
145 | } else if (! /^((\+|00)86)?1((3[\d])|(4[5,6,7,9])|(5[0-3,5-9])|(6[2,5-7])|(7[0-8])|(8[\d])|(9[1,8,9]))\d{8}$/.test(user_info.phone)) {
146 | wx.showToast({
147 | title: '电话格式不正确',
148 | icon: 'none',
149 | duration: 1000,
150 | mask: true
151 | })
152 | } else if (! /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(user_info.mail)) {
153 | wx.showToast({
154 | title: '邮箱格式不正确',
155 | icon: 'none',
156 | duration: 1000,
157 | mask: true
158 | })
159 | } else {
160 | const t = this
161 | wx.showLoading({
162 | title: '正在保存',
163 | mask: true
164 | })
165 | if (this.data.originQr != this.data.qr) {
166 | const qr = this.data.qr
167 | wx.cloud.uploadFile({
168 | filePath: qr,
169 | cloudPath: 'qr/' + openid + qr.match(/\.[^.]+?$/)[0],
170 | }).then(res => {
171 | const fileID = res.fileID
172 | if (res.statusCode == 200 && fileID) {
173 | user_info.qrID = fileID
174 | const db = wx.cloud.database()
175 | db.collection('user_info').doc(openid).update({
176 | data: user_info
177 | }).then(res => {
178 | console.log('finish', res)
179 | getApp().globalData.user_info = user_info
180 | t.setData({
181 | originQr: this.data.qr
182 | })
183 | wx.hideLoading()
184 | wx.showToast({
185 | title: '修改成功',
186 | icon: 'success',
187 | duration: 1000,
188 | mask: true
189 | })
190 | }).catch(err => {
191 | console.log('fail更改信息失败', err)
192 | wx.hideLoading()
193 | wx.showToast({
194 | title: '修改失败',
195 | icon: 'none',
196 | duration: 1000,
197 | mask: true
198 | })
199 | t.setData({
200 | qr: t.data.originQr,
201 | user_info: getApp().globalData.user_info
202 | })
203 | })
204 | }
205 | }).catch(err => {
206 | console.log(err)
207 | t.setData({
208 | qr: t.data.originQr,
209 | user_info: getApp().globalData.user_info
210 | })
211 | })
212 | } else {
213 | console.log("未修改qr")
214 | const db = wx.cloud.database()
215 | db.collection('user_info').doc(openid).update({
216 | data: user_info
217 | }).then(res => {
218 | console.log('finish', res)
219 | getApp().globalData.user_info = user_info
220 | wx.hideLoading()
221 | wx.showToast({
222 | title: '修改成功',
223 | icon: 'success',
224 | duration: 1000,
225 | mask: true
226 | })
227 | }).catch(err => {
228 | console.log('fail更改信息失败', err)
229 | wx.hideLoading()
230 | wx.showToast({
231 | title: '修改失败',
232 | icon: 'none',
233 | duration: 1000,
234 | mask: true
235 | })
236 | t.setData({
237 | user_info: getApp().globalData.user_info
238 | })
239 | })
240 | }
241 | }
242 | },
243 | viewPersonInfo() {
244 | wx.navigateTo({
245 | url: '/pages/showMsg/showMsg?openid=' + getApp().globalData.openid
246 | })
247 | },
248 | /**
249 | * 生命周期函数--监听页面加载
250 | */
251 | onLoad: function(options) {
252 | getApp().backToLogin(getApp().globalData.openid)
253 | const user_info = getApp().globalData.user_info
254 | console.log("在个人页面获得user_info", user_info)
255 | user_info.show_info = user_info.show_info === false ? false : true
256 | user_info.show_location = user_info.show_location === false ? false : true
257 | this.setData({
258 | user_info: user_info
259 | })
260 | if (user_info.qrID) {
261 | wx.cloud.getTempFileURL({
262 | fileList: [user_info.qrID]
263 | }).then(res => {
264 | // console.log(res)
265 | if (res.fileList.length > 0) {
266 | this.setData({
267 | originQr: res.fileList[0].tempFileURL,
268 | qr: res.fileList[0].tempFileURL
269 | })
270 | } else {
271 | console.log('获取失败', res)
272 | }
273 | })
274 | }
275 | },
276 |
277 | /**
278 | * 生命周期函数--监听页面初次渲染完成
279 | */
280 | onReady: function() {
281 |
282 | },
283 |
284 | /**
285 | * 生命周期函数--监听页面显示
286 | */
287 | onShow: function() {
288 |
289 | },
290 |
291 | /**
292 | * 生命周期函数--监听页面隐藏
293 | */
294 | onHide: function() {
295 |
296 | },
297 |
298 | /**
299 | * 生命周期函数--监听页面卸载
300 | */
301 | onUnload: function() {
302 |
303 | },
304 |
305 | /**
306 | * 页面相关事件处理函数--监听用户下拉动作
307 | */
308 | onPullDownRefresh: function() {
309 |
310 | },
311 |
312 | /**
313 | * 页面上拉触底事件的处理函数
314 | */
315 | onReachBottom: function() {
316 |
317 | },
318 |
319 | /**
320 | * 用户点击右上角分享
321 | */
322 | onShareAppMessage: function() {
323 |
324 | }
325 | })
--------------------------------------------------------------------------------
/miniprogram/pages/my/my.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/my/my.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 姓名:
9 |
10 |
11 |
12 | 入学/入职年份:
13 |
14 |
15 |
16 | 培养院所:
17 | {{user_info.institution || "点击输入院所"}}
18 |
19 |
20 | 身份:
21 | {{user_info.degree || "点击选择身份"}}
22 |
23 |
24 | 工作单位:
25 |
26 |
27 |
28 | 家庭地址:
29 |
30 |
31 |
32 | 联系电话:
33 |
34 |
35 |
36 | 邮箱:
37 |
38 |
39 |
40 | 个人信息公开
41 |
42 |
43 |
44 | 定位公开
45 |
46 |
47 |
48 | 微信二维码
49 |
50 |
51 | *号代表必填
52 |
53 | 对校友说的话
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | 输入院所名字
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | {{item}}
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/miniprogram/pages/my/my.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/my/my.wxss */
2 |
3 | .container {
4 | justify-content: center;
5 | background-attachment: fixed;
6 | background-size: cover;
7 | }
8 | .avator-box {
9 | height: 200rpx;
10 | width: 200rpx;
11 | border-radius: 50%;
12 | margin: 0 auto;
13 | overflow: hidden;
14 | }
15 |
16 | .avator {
17 | width: 100%;
18 | height: 100%;
19 | }
20 |
21 | .form {
22 | margin-top: 30rpx;
23 | width: 750rpx;
24 | }
25 |
26 | .margin-top {
27 | margin-top: 30rpx;
28 | }
29 |
30 | .form-item {
31 | background-color: rgba(255,255,255,0.4);
32 | position: relative;
33 | padding: 1rpx 30rpx;
34 | display: flex;
35 | align-items: center;
36 | min-height: 80rpx;
37 | justify-content: space-between;
38 | }
39 | .cu-form-group {
40 | min-height: 50rpx;
41 | }
42 | .border-top{
43 | border-top: 2rpx solid #ddd;
44 | }
45 | .form-item {
46 | border-bottom: 2rpx solid #ddd;
47 | }
48 |
49 | .form-item .title {
50 | opacity: 1;
51 | text-align: justify;
52 | margin-right: 30rpx;
53 | font-size: 30rpx;
54 | position: relative;
55 | height: 60rpx;
56 | line-height: 60rpx;
57 | }
58 |
59 | .form-item input {
60 | flex: 1;
61 | font-size: 30rpx;
62 | color: #555;
63 | padding-right: 20rpx;
64 | height: 80rpx;
65 | }
66 |
67 | .form-item textarea {
68 | margin: 32rpx 0 30rpx;
69 | height: 4.8em;
70 | width: 100%;
71 | line-height: 1.2em;
72 | flex: 1;
73 | font-size: 28rpx;
74 | padding: 0;
75 | box-sizing: content-box;
76 | display: inline-block;
77 | vertical-align: top;
78 | }
79 |
80 | .save {
81 | width: 450rpx;
82 | background-color: #e8c975;
83 | margin: 20rpx auto 40rpx;
84 | height: 80rpx;
85 | line-height: 80rpx;
86 | color: #884c07;
87 | font-weight: 600;
88 | }
89 |
90 | .arrow::before {
91 | font-family: "cuIcon";
92 | display: block;
93 | content: "\e6a3";
94 | position: absolute;
95 | font-size: 34rpx;
96 | color: #aaa;
97 | line-height: 30rpx;
98 | height: 30rpx;
99 | width: 30rpx;
100 | text-align: center;
101 | top: 0rpx;
102 | bottom: 0;
103 | right: 30rpx;
104 | margin: auto;
105 | }
106 |
107 | .qr {
108 | width: 75rpx;
109 | height: 75rpx;
110 | overflow: hidden;
111 | margin-right: 60rpx;
112 | border: 2rpx solid #aaa;
113 | }
114 |
115 | .degree {
116 | margin-left: 10rpx;
117 | font-size: 30rpx;
118 | }
119 | .institution{
120 | font-size: 30rpx;
121 | }
122 | .kaozuo{
123 | justify-content: flex-start;
124 | }
125 | .dot {
126 | position: relative;
127 | }
128 |
129 | .dot::before, dot::after {
130 | font-size: 30rpx;
131 | display: block;
132 | content: '*';
133 | position: absolute;
134 | top: -15rpx;
135 | right: -15rpx;
136 | color: red;
137 | }
138 | .input-box{
139 | position: relative;
140 | height: 80rpx;
141 | width: 600rpx;
142 | margin: auto;
143 | background: #fff;
144 | border: 1rpx solid rgba(0, 0, 0, 0.1);
145 | border-radius: 20rpx;
146 | }
147 | .input-ins{
148 | height: 80rpx;
149 | }
150 | .notice-list{
151 | transition-duration: 0.3s;
152 | overflow-y: auto;
153 | background-color: #eee;
154 | z-index: 999;
155 | width: 100%;
156 | position: absolute;
157 | border-radius: 20rpx;
158 | max-height: 320rpx;
159 | top: 80rpx;
160 | left: 0;
161 | box-shadow: 2px 4px 8px rgba(7, 17, 27, 0.1),
162 | -2px 4px 8px rgba(7, 17, 27, 0.1);
163 | }
164 | .notice-item{
165 | background: #fff;
166 | min-height: 60rpx;
167 | line-height: 60rpx;
168 | font-size: 30rpx;
169 | }
170 | .notice-item+.notice-item{
171 | margin-top: 2rpx;
172 | }
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/callback/callback.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/openapi/callback/callback.js
2 | Page({
3 |
4 | data: {
5 |
6 | },
7 |
8 | onLoad: function (options) {
9 |
10 | },
11 |
12 | onCustomerServiceButtonClick(e) {
13 | console.log(e)
14 | },
15 | })
16 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/callback/callback.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/callback/callback.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 | 测试须知
10 | 1. 需在项目根目录创建消息推送配置文件 temp-cloud-callback-config.json
11 | 2. 填写消息推送配置
12 | 3. 右键配置文件选择上传配置
13 | 4. 确认接收消息的云函数已上传
14 | 5. 在手机上测试
15 |
16 |
17 |
18 | 示例客服消息配置
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/callback/callback.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/openapi/callback/callback.wxss */
2 |
3 | @import "../../../style/guide.wxss";
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/cloudid/cloudid.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/openapi/cloudid/cloudid.js
2 | Page({
3 |
4 | data: {
5 | weRunResult: '',
6 | userInfoResult: '',
7 | },
8 |
9 | onGetWeRunData() {
10 | wx.getWeRunData({
11 | success: res => {
12 | wx.cloud.callFunction({
13 | name: 'echo',
14 | data: {
15 | // info 字段在云函数 event 对象中会被自动替换为相应的敏感数据
16 | info: wx.cloud.CloudID(res.cloudID),
17 | },
18 | }).then(res => {
19 | console.log('[onGetWeRunData] 收到 echo 回包:', res)
20 |
21 | this.setData({
22 | weRunResult: JSON.stringify(res.result),
23 | })
24 |
25 | wx.showToast({
26 | title: '敏感数据获取成功',
27 | })
28 | }).catch(err => {
29 | console.log('[onGetWeRunData] 失败:', err)
30 | })
31 | }
32 | })
33 |
34 | },
35 |
36 | onGetUserInfo(e) {
37 | console.log(e)
38 | wx.cloud.callFunction({
39 | name: 'openapi',
40 | data: {
41 | action: 'getOpenData',
42 | openData: {
43 | list: [
44 | e.detail.cloudID,
45 | ]
46 | }
47 | }
48 | }).then(res => {
49 | console.log('[onGetUserInfo] 调用成功:', res)
50 |
51 | this.setData({
52 | userInfoResult: JSON.stringify(res.result),
53 | })
54 |
55 | wx.showToast({
56 | title: '敏感数据获取成功',
57 | })
58 | })
59 | }
60 | })
61 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/cloudid/cloudid.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/cloudid/cloudid.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 开放数据调用
6 | 通过 cloudID 获取敏感开放数据有以下两种方式
7 | 1. 小程序端 callFunction 自动获取
8 | 2. 通过 wx-server-sdk 获取
9 | 以下分别先后展示这两种获取方式
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | 测试须知
18 | 1. 公共库版本需大于 2.7.0
19 | 2. 请确保 echo 函数已上传
20 |
21 |
22 |
23 | {{weRunResult}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | 测试须知
33 | 1. 公共库版本需大于 2.7.0
34 | 2. 请确保 openapi 函数已上传
35 |
36 |
37 |
38 | {{userInfoResult}}
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/cloudid/cloudid.wxss:
--------------------------------------------------------------------------------
1 | @import "../../../style/guide.wxss";
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/openapi.js:
--------------------------------------------------------------------------------
1 | Page({
2 |
3 | data: {
4 | templateMessageResult: '',
5 | wxacodeSrc: '',
6 | wxacodeResult: '',
7 | showClearWXACodeCache: false,
8 | },
9 |
10 | submitTemplateMessageForm(e) {
11 | this.setData({
12 | templateMessageResult: '',
13 | })
14 |
15 | wx.cloud.callFunction({
16 | name: 'openapi',
17 | data: {
18 | action: 'sendTemplateMessage',
19 | formId: e.detail.formId,
20 | },
21 | success: res => {
22 | console.warn('[云函数] [openapi] templateMessage.send 调用成功:', res)
23 | wx.showModal({
24 | title: '发送成功',
25 | content: '请返回微信主界面查看',
26 | showCancel: false,
27 | })
28 | wx.showToast({
29 | title: '发送成功,请返回微信主界面查看',
30 | })
31 | this.setData({
32 | templateMessageResult: JSON.stringify(res.result)
33 | })
34 | },
35 | fail: err => {
36 | wx.showToast({
37 | icon: 'none',
38 | title: '调用失败',
39 | })
40 | console.error('[云函数] [openapi] templateMessage.send 调用失败:', err)
41 | }
42 | })
43 | },
44 |
45 | onGetWXACode() {
46 |
47 | this.setData({
48 | wxacodeSrc: '',
49 | wxacodeResult: '',
50 | showClearWXACodeCache: false,
51 | })
52 |
53 | // 此处为演示,将使用 localStorage 缓存,正常开发中文件 ID 应存在数据库中
54 | const fileID = wx.getStorageSync('wxacodeCloudID')
55 |
56 | if (fileID) {
57 | // 有云文件 ID 缓存,直接使用该 ID
58 | // 如需清除缓存,选择菜单栏中的 “工具 -> 清除缓存 -> 清除数据缓存”,或在 Storage 面板中删掉相应的 key
59 | this.setData({
60 | wxacodeSrc: fileID,
61 | wxacodeResult: `从本地缓存中取得了小程序码的云文件 ID`,
62 | showClearWXACodeCache: true,
63 | })
64 | console.log(`从本地缓存中取得了小程序码的云文件 ID:${fileID}`)
65 | } else {
66 | wx.cloud.callFunction({
67 | name: 'openapi',
68 | data: {
69 | action: 'getWXACode',
70 | },
71 | success: res => {
72 | console.warn('[云函数] [openapi] wxacode.get 调用成功:', res)
73 | wx.showToast({
74 | title: '调用成功',
75 | })
76 | this.setData({
77 | wxacodeSrc: res.result,
78 | wxacodeResult: `云函数获取二维码成功`,
79 | showClearWXACodeCache: true,
80 | })
81 | wx.setStorageSync('wxacodeCloudID', res.result)
82 | },
83 | fail: err => {
84 | wx.showToast({
85 | icon: 'none',
86 | title: '调用失败',
87 | })
88 | console.error('[云函数] [openapi] wxacode.get 调用失败:', err)
89 | }
90 | })
91 | }
92 | },
93 |
94 | clearWXACodeCache() {
95 | wx.removeStorageSync('wxacodeCloudID')
96 |
97 | this.setData({
98 | wxacodeSrc: '',
99 | wxacodeResult: '',
100 | showClearWXACodeCache: false,
101 | })
102 |
103 | wx.showToast({
104 | title: '清除成功',
105 | })
106 | },
107 |
108 | })
109 |
110 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/openapi.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/openapi.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 服务端调用
7 |
8 |
9 |
10 |
11 |
12 | 开放数据调用
13 |
14 |
15 |
16 |
17 |
18 | 消息推送
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/openapi.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/openapi/openapi.wxss */
2 |
3 | @import "../../style/guide.wxss";
4 |
5 | .black {
6 | color: black;
7 | }
8 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/serverapi/serverapi.js:
--------------------------------------------------------------------------------
1 | Page({
2 |
3 | data: {
4 | templateMessageResult: '',
5 | wxacodeSrc: '',
6 | wxacodeResult: '',
7 | showClearWXACodeCache: false,
8 | },
9 |
10 | submitTemplateMessageForm(e) {
11 | this.setData({
12 | templateMessageResult: '',
13 | })
14 |
15 | wx.cloud.callFunction({
16 | name: 'openapi',
17 | data: {
18 | action: 'sendTemplateMessage',
19 | formId: e.detail.formId,
20 | },
21 | success: res => {
22 | console.warn('[云函数] [openapi] templateMessage.send 调用成功:', res)
23 | wx.showModal({
24 | title: '发送成功',
25 | content: '请返回微信主界面查看',
26 | showCancel: false,
27 | })
28 | wx.showToast({
29 | title: '发送成功,请返回微信主界面查看',
30 | })
31 | this.setData({
32 | templateMessageResult: JSON.stringify(res.result)
33 | })
34 | },
35 | fail: err => {
36 | wx.showToast({
37 | icon: 'none',
38 | title: '调用失败',
39 | })
40 | console.error('[云函数] [openapi] templateMessage.send 调用失败:', err)
41 | }
42 | })
43 | },
44 |
45 | onGetWXACode() {
46 |
47 | this.setData({
48 | wxacodeSrc: '',
49 | wxacodeResult: '',
50 | showClearWXACodeCache: false,
51 | })
52 |
53 | // 此处为演示,将使用 localStorage 缓存,正常开发中文件 ID 应存在数据库中
54 | const fileID = wx.getStorageSync('wxacodeCloudID')
55 |
56 | if (fileID) {
57 | // 有云文件 ID 缓存,直接使用该 ID
58 | // 如需清除缓存,选择菜单栏中的 “工具 -> 清除缓存 -> 清除数据缓存”,或在 Storage 面板中删掉相应的 key
59 | this.setData({
60 | wxacodeSrc: fileID,
61 | wxacodeResult: `从本地缓存中取得了小程序码的云文件 ID`,
62 | showClearWXACodeCache: true,
63 | })
64 | console.log(`从本地缓存中取得了小程序码的云文件 ID:${fileID}`)
65 | } else {
66 | wx.cloud.callFunction({
67 | name: 'openapi',
68 | data: {
69 | action: 'getWXACode',
70 | },
71 | success: res => {
72 | console.warn('[云函数] [openapi] wxacode.get 调用成功:', res)
73 | wx.showToast({
74 | title: '调用成功',
75 | })
76 | this.setData({
77 | wxacodeSrc: res.result,
78 | wxacodeResult: `云函数获取二维码成功`,
79 | showClearWXACodeCache: true,
80 | })
81 | wx.setStorageSync('wxacodeCloudID', res.result)
82 | },
83 | fail: err => {
84 | wx.showToast({
85 | icon: 'none',
86 | title: '调用失败',
87 | })
88 | console.error('[云函数] [openapi] wxacode.get 调用失败:', err)
89 | }
90 | })
91 | }
92 | },
93 |
94 | clearWXACodeCache() {
95 | wx.removeStorageSync('wxacodeCloudID')
96 |
97 | this.setData({
98 | wxacodeSrc: '',
99 | wxacodeResult: '',
100 | showClearWXACodeCache: false,
101 | })
102 |
103 | wx.showToast({
104 | title: '清除成功',
105 | })
106 | },
107 |
108 | })
109 |
110 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/serverapi/serverapi.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/serverapi/serverapi.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 | 测试须知
15 | 1. 需在手机上预览测试,工具中无效
16 | 2. 需上传 cloudfunctions 目录下的 openapi 云函数
17 | 3. 调用成功后返回到微信主界面查看收到的模板消息
18 |
19 |
20 |
21 |
22 | 获取小程序码
23 |
24 |
25 | {{wxacodeResult}}
26 | 清除缓存
27 |
28 |
29 |
30 |
31 | 测试须知
32 | 1. 需上传 cloudfunctions 目录下的 openapi 云函数
33 | 2. 云函数中获取图片后会上传至存储空间并返回至小程序使用和缓存
34 | 3. 云存储需设置为公有读
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/miniprogram/pages/openapi/serverapi/serverapi.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/openapi/openapi.wxss */
2 |
3 | @import "../../../style/guide.wxss";
4 |
5 | .black {
6 | color: black;
7 | }
--------------------------------------------------------------------------------
/miniprogram/pages/rank/rank.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/rank/rank.js
2 | Page({
3 |
4 | /**
5 | * 页面的初始数据
6 | */
7 | data: {
8 | rankTabCur: 0,
9 | rankTabNav: ['研究所', '省份', '国家'],
10 | rank: [],
11 | showRank: false,
12 | onLoadFirst:false
13 | },
14 | rankTabSelect(e) {
15 | const cur = e.currentTarget.dataset.index
16 | if (cur != this.data.rankTabCur) {
17 | this.setData({
18 | rankTabCur: cur
19 | })
20 | }
21 | },
22 | getTotalInfo() {
23 | function con(a, b) {
24 | for (let value of b) {
25 | a.push(value._openid)
26 | }
27 | }
28 |
29 | function getWordCnt(a) {
30 | let obj = {};
31 | let res = []
32 | for (let item of a) {
33 | obj[item] = (obj[item] + 1) || 1
34 | }
35 | let i = 0
36 | let tmp = {}
37 | for (let index in obj) {
38 | tmp = {
39 | name: index,
40 | value: obj[index]
41 | }
42 | res[i++] = tmp
43 | if (i > 10) {
44 | break;
45 | }
46 | }
47 | if (res.length <= 1) {
48 | return res
49 | }
50 | // console.log(res)
51 | let t3
52 | for (let t1 = 0; t1 < res.length; t1++) {
53 | for (let t2 = 0; t2 < t1; t2++) {
54 | if (res[t1].value > res[t2].value) {
55 | t3 = res[t1]
56 | res[t1] = res[t2]
57 | res[t2] = t3
58 | }
59 | }
60 | }
61 | return res
62 | }
63 | const t = this
64 | const db = wx.cloud.database()
65 | async function get() {
66 | let data = []
67 | let i = 0
68 | let ll = true
69 | while (ll) {
70 | await new Promise((resolve, reject) => {
71 | db.collection('publish_info').skip(i * 20).limit(20).get().then(res => {
72 | i += 1
73 | // console.log(res)
74 | con(data, res.data)
75 | if (res.data.length < 20) {
76 | ll = false
77 | }
78 | resolve()
79 | }).catch(err => {
80 | reject(err)
81 | })
82 | })
83 | }
84 | let provinces = [];
85 | let institutions = [];
86 | let nations = [];
87 | let getInfo = [];
88 | for (let i in data) {
89 | getInfo[i] = new Promise((resolve, reject) => {
90 | db.collection('user_info').doc(data[i]).get().then(res => {
91 | // console.log(res)
92 | if (res.data.institution) {
93 | institutions.push(res.data.institution)
94 | }
95 | if (res.data.location.adress) {
96 | provinces.push(res.data.location.adress.ad_info.province)
97 | nations.push(res.data.location.adress.ad_info.nation)
98 | }
99 | resolve()
100 | }).catch(err => {
101 | reject(err)
102 | })
103 | })
104 | }
105 | Promise.all(getInfo).then(res => {
106 | institutions = getWordCnt(institutions);
107 | provinces = getWordCnt(provinces);
108 | nations = getWordCnt(nations);
109 | console.log("得到rank数据");
110 | console.log(provinces, institutions, nations);
111 | t.setData({
112 | 'rank[0]': institutions,
113 | 'rank[1]': provinces,
114 | 'rank[2]': nations,
115 | showRank: true,
116 | onLoadFirst: true
117 | })
118 | })
119 | }
120 | get().catch(err => {
121 | console.log(err)
122 | })
123 | },
124 | /**
125 | * 生命周期函数--监听页面加载
126 | */
127 | onLoad: function(options) {
128 | getApp().backToLogin(getApp().globalData.openid)
129 | this.getTotalInfo()
130 | },
131 | /**
132 | * 生命周期函数--监听页面初次渲染完成
133 | */
134 | onReady: function() {
135 |
136 | },
137 |
138 | /**
139 | * 生命周期函数--监听页面显示
140 | */
141 | onShow: function() {
142 | this.data.onLoadFirst || this.getTotalInfo()
143 | },
144 |
145 | /**
146 | * 生命周期函数--监听页面隐藏
147 | */
148 | onHide: function() {
149 |
150 | },
151 |
152 | /**
153 | * 生命周期函数--监听页面卸载
154 | */
155 | onUnload: function() {
156 |
157 | },
158 |
159 | /**
160 | * 页面相关事件处理函数--监听用户下拉动作
161 | */
162 | onPullDownRefresh: function() {
163 | this.getTotalInfo()
164 | wx.stopPullDownRefresh()
165 | },
166 |
167 | /**
168 | * 页面上拉触底事件的处理函数
169 | */
170 | onReachBottom: function() {
171 |
172 | },
173 |
174 | /**
175 | * 用户点击右上角分享
176 | */
177 | onShareAppMessage: function() {
178 |
179 | }
180 | })
--------------------------------------------------------------------------------
/miniprogram/pages/rank/rank.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/rank/rank.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{item}}
8 |
9 |
10 |
11 |
12 |
13 | {{item.name}}
14 |
15 | {{item.value/rank[rankTabCur][0].value>=0.5?item.value+'张':''}}
16 | {{item.value/rank[rankTabCur][0].value<0.5?item.value+'张':''}}
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/miniprogram/pages/rank/rank.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/rank/rank.wxss */
2 | .cu-progress view{
3 | color:rgb(245, 4, 4);
4 | font-size: 25rpx;
5 | }
6 | .cu-progress{
7 | color:rgb(207, 24, 24);
8 | font-size: 25rpx;
9 | }
10 | page{
11 | background: url('https://www.yulovexin.xyz/images/tmp/bg.png');
12 | background-attachment: fixed;
13 | background-size: cover;
14 | }
15 | .header{
16 | margin-top: 20rpx;
17 | text-align: center;
18 | color: #930302;
19 | font-size: 40rpx;
20 | height: 70rpx;
21 | line-height: 70rpx;
22 | font-weight: 500;
23 | }
24 | .rank-wrap{
25 | padding: 10rpx;
26 | width: 100%;
27 | transition: height linear 0.3s;
28 | }
29 | .rank-box{
30 | min-height: 70rpx;
31 | display: flex;
32 | align-items: center;
33 | background: rgba(120, 120, 120, 0.1);
34 | margin: 15rpx 0;
35 | padding: 0 10rpx;
36 | border-radius: 10rpx;
37 | }
38 | .rank-text{
39 | text-align: center;
40 | width:200rpx;
41 | min-height: 100%;
42 | height: auto;
43 | }
44 | .rank-progress{
45 | flex:1;
46 | }
--------------------------------------------------------------------------------
/miniprogram/pages/showMsg/showMsg.js:
--------------------------------------------------------------------------------
1 | // miniprogram/pages/showMsg/showMsg.js
2 | Page({
3 | /**
4 | * 页面的初始数据
5 | */
6 | data: {
7 | isMe: false,
8 | user_info: null,
9 | showContact: false
10 | },
11 | changeMe(){
12 | wx.switchTab({
13 | url: '/pages/my/my',
14 | })
15 | },
16 | contact(){
17 | this.setData({
18 | showContact: true
19 | })
20 | },
21 | hideModal(){
22 | this.setData({
23 | showContact: false
24 | })
25 | },
26 | longPress(){
27 | console.log("长按")
28 | },
29 | nop(){
30 | wx.previewImage({
31 | urls: ['https://www.yulovexin.xyz/images/zkd/contact.png'],
32 | })
33 | },
34 | ViewImage(e) {
35 | wx.previewImage({
36 | urls: [e.currentTarget.dataset.url],
37 | current: e.currentTarget.dataset.current
38 | });
39 | },
40 | /**
41 | * 生命周期函数--监听页面加载
42 | */
43 | onLoad: function (options) {
44 | const user_openid=getApp().globalData.openid
45 | getApp().backToLogin(user_openid)
46 | const openid = options.openid
47 | console.log("获得查看的openid",openid)
48 | if (openid == user_openid){
49 | this.setData({
50 | isMe: true
51 | })
52 | }
53 | const t = this
54 | wx.cloud.database().collection('user_info').doc(openid).get().then(res =>{
55 | const user_info = res.data
56 | user_info.show_info = user_info.show_info === false ? false : true
57 | if (user_info.qrID){
58 | wx.cloud.getTempFileURL({
59 | fileList: [user_info.qrID],
60 | success(res){
61 | if (res.fileList.length > 0) {
62 | t.setData({
63 | qr: res.fileList[0].tempFileURL
64 | })
65 | } else {
66 | console.log('获取失败', res)
67 | }
68 | }
69 | })
70 | }
71 | t.setData({
72 | user_info: res.data
73 | })
74 | }).catch(err=>{
75 | wx.showModal({
76 | title: '错误',
77 | content: '获取用户信息失败',
78 | })
79 | console.log(err)
80 | })
81 | },
82 |
83 | /**
84 | * 生命周期函数--监听页面初次渲染完成
85 | */
86 | onReady: function () {
87 |
88 | },
89 |
90 | /**
91 | * 生命周期函数--监听页面显示
92 | */
93 | onShow: function () {
94 |
95 | },
96 |
97 | /**
98 | * 生命周期函数--监听页面隐藏
99 | */
100 | onHide: function () {
101 |
102 | },
103 |
104 | /**
105 | * 生命周期函数--监听页面卸载
106 | */
107 | onUnload: function () {
108 |
109 | },
110 |
111 | /**
112 | * 页面相关事件处理函数--监听用户下拉动作
113 | */
114 | onPullDownRefresh: function () {
115 |
116 | },
117 |
118 | /**
119 | * 页面上拉触底事件的处理函数
120 | */
121 | onReachBottom: function () {
122 |
123 | },
124 |
125 | /**
126 | * 用户点击右上角分享
127 | */
128 | onShareAppMessage: function () {
129 |
130 | }
131 | })
--------------------------------------------------------------------------------
/miniprogram/pages/showMsg/showMsg.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {}
3 | }
--------------------------------------------------------------------------------
/miniprogram/pages/showMsg/showMsg.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 姓名:
9 |
10 |
11 |
12 | 入学年份:
13 |
14 |
15 |
16 | 培养院所:
17 |
18 |
19 |
20 | 培养程度:
21 | {{user_info.degree=='' ? '未填写':user_info.degree}}
22 |
23 |
24 | 工作单位:
25 |
26 |
27 |
28 | 家庭地址:
29 |
30 |
31 |
32 | 联系电话:
33 |
34 |
35 |
36 | 邮箱:
37 |
38 |
39 |
40 | 微信二维码
41 |
42 |
43 |
44 | 对校友说的话
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | 点击查看图片
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/miniprogram/pages/showMsg/showMsg.wxss:
--------------------------------------------------------------------------------
1 | /* miniprogram/pages/my/my.wxss */
2 | .container{
3 | justify-content: center;
4 | }
5 | page{
6 | background: url('https://www.yulovexin.xyz/images/tmp/bg.png');
7 | background-attachment: fixed;
8 | background-size: cover;
9 | }
10 | .avator-box{
11 | height: 200rpx;
12 | width: 200rpx;
13 | border-radius: 50%;
14 | margin: 0 auto;
15 | overflow: hidden;
16 | }
17 | .avator{
18 | width:100%;
19 | height: 100%;
20 | }
21 | .form{
22 | margin-top: 30rpx;
23 | width: 750rpx;
24 | }
25 | .margin-top{
26 | margin-top: 30rpx;
27 | }
28 | .form-item{
29 | background-color: rgba(255,255,255,0.4);
30 | position: relative;
31 | padding:1rpx 30rpx;
32 | display:flex;
33 | align-items:center;
34 | min-height:80rpx;
35 | justify-content:space-between;
36 | box-shadow: 0 1rpx 2rpx rgba(0, 0, 0, 0.1);
37 | }
38 | .form-item+.form-item{
39 | border-top: 2rpx solid #ccc;
40 | }
41 | .form-item .title {
42 | text-align:justify;
43 | margin-right:30rpx;
44 | font-size:30rpx;
45 | position:relative;
46 | height:60rpx;
47 | line-height:60rpx;
48 | }
49 | .form-item input{
50 | flex:1;
51 | font-size: 30rpx;
52 | color: #555;
53 | padding-right: 20rpx;
54 | height:80rpx;
55 | }
56 | .form-item textarea {
57 | margin:32rpx 0 30rpx;
58 | height:4.8em;
59 | width:100%;
60 | line-height:1.2em;
61 | flex:1;
62 | font-size:28rpx;
63 | padding:0;
64 | box-sizing:content-box;
65 | display:inline-block;
66 | vertical-align:top;
67 | }
68 | .save {
69 | width: 450rpx;
70 | background-color: #e8c975;
71 | margin: 20rpx auto 40rpx;
72 | height: 80rpx;
73 | line-height: 80rpx;
74 | color: #884c07;
75 | font-weight: 600;
76 | }
77 | .arrow::before{
78 | font-family: "iconfont";
79 | display: block;
80 | content: "\e6a3";
81 | position: absolute;
82 | font-size: 34rpx;
83 | color: #aaa;
84 | line-height: 30rpx;
85 | height: 30rpx;
86 | width: 30rpx;
87 | text-align: center;
88 | top: 0rpx;
89 | bottom: 0;
90 | right: 30rpx;
91 | margin: auto;
92 | }
93 | .qr{
94 | width: 75rpx;
95 | height: 75rpx;
96 | overflow: hidden;
97 | margin-right: 60rpx;
98 | border: 2rpx solid #aaa;
99 | }
100 | .degree{
101 | margin-right: 460rpx;
102 | font-size: 30rpx;
103 | }
104 |
105 | .dot{
106 | position: relative;
107 | }
108 | .dot::before, dot::after{
109 | font-size: 30rpx;
110 | display: block;
111 | content: '*';
112 | position: absolute;
113 | top: -15rpx;
114 | right: -15rpx;
115 | color: red;
116 | }
--------------------------------------------------------------------------------
/miniprogram/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/miniprogram/style/guide.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | background: #f6f6f6;
3 | display: flex;
4 | flex-direction: column;
5 | justify-content: flex-start;
6 | }
7 |
8 | .list {
9 | margin-top: 40rpx;
10 | height: auto;
11 | width: 100%;
12 | background: #fff;
13 | padding: 0 40rpx;
14 | border: 1px solid rgba(0, 0, 0, 0.1);
15 | border-left: none;
16 | border-right: none;
17 | transition: all 300ms ease;
18 | display: flex;
19 | flex-direction: column;
20 | align-items: stretch;
21 | box-sizing: border-box;
22 | }
23 |
24 | .list-item {
25 | width: 100%;
26 | padding: 0;
27 | line-height: 104rpx;
28 | font-size: 34rpx;
29 | color: #007aff;
30 | border-top: 1px solid rgba(0, 0, 0, 0.1);
31 | display: flex;
32 | flex-direction: row;
33 | align-content: center;
34 | justify-content: space-between;
35 | box-sizing: border-box;
36 | }
37 |
38 | .list-item:first-child {
39 | border-top: none;
40 | }
41 |
42 | .list-item image {
43 | max-width: 100%;
44 | max-height: 20vh;
45 | margin: 20rpx 0;
46 | }
47 |
48 | .request-text {
49 | color: #222;
50 | padding: 20rpx 0;
51 | font-size: 24rpx;
52 | line-height: 36rpx;
53 | word-break: break-all;
54 | }
55 |
56 | .guide {
57 | width: 100%;
58 | padding: 40rpx;
59 | box-sizing: border-box;
60 | display: flex;
61 | flex-direction: column;
62 | }
63 |
64 | .guide .headline {
65 | font-size: 34rpx;
66 | font-weight: bold;
67 | color: #555;
68 | line-height: 40rpx;
69 | }
70 |
71 | .guide .p {
72 | margin-top: 20rpx;
73 | font-size: 28rpx;
74 | line-height: 36rpx;
75 | color: #666;
76 | }
77 |
78 | .guide .code {
79 | margin-top: 20rpx;
80 | font-size: 28rpx;
81 | line-height: 36rpx;
82 | color: #666;
83 | background: white;
84 | white-space: pre;
85 | }
86 |
87 | .guide .code-dark {
88 | margin-top: 20rpx;
89 | background: rgba(0, 0, 0, 0.8);
90 | padding: 20rpx;
91 | font-size: 28rpx;
92 | line-height: 36rpx;
93 | border-radius: 6rpx;
94 | color: #fff;
95 | white-space: pre
96 | }
97 |
98 | .guide image {
99 | max-width: 100%;
100 | }
101 |
102 | .guide .image1 {
103 | margin-top: 20rpx;
104 | max-width: 100%;
105 | width: 356px;
106 | height: 47px;
107 | }
108 |
109 | .guide .image2 {
110 | margin-top: 20rpx;
111 | width: 264px;
112 | height: 100px;
113 | }
114 |
115 | .guide .flat-image {
116 | height: 100px;
117 | }
118 |
119 | .guide .code-image {
120 | max-width: 100%;
121 | }
122 |
123 | .guide .copyBtn {
124 | width: 180rpx;
125 | font-size: 20rpx;
126 | margin-top: 16rpx;
127 | margin-left: 0;
128 | }
129 |
130 | .guide .nav {
131 | margin-top: 50rpx;
132 | display: flex;
133 | flex-direction: row;
134 | align-content: space-between;
135 | }
136 |
137 | .guide .nav .prev {
138 | margin-left: unset;
139 | }
140 |
141 | .guide .nav .next {
142 | margin-right: unset;
143 | }
144 |
145 |
--------------------------------------------------------------------------------
/miniprogram/utils/bmap-wx.min.js:
--------------------------------------------------------------------------------
1 | "use strict"; function _classCallCheck(t, a) { if (!(t instanceof a)) throw new TypeError("Cannot call a class as a function") } var _createClass = function () { function t(t, a) { for (var e = 0; e < a.length; e++) { var i = a[e]; i.enumerable = i.enumerable || !1, i.configurable = !0, "value" in i && (i.writable = !0), Object.defineProperty(t, i.key, i) } } return function (a, e, i) { return e && t(a.prototype, e), i && t(a, i), a } }(), BMapWX = function () { function t(a) { _classCallCheck(this, t), this.ak = a.ak } return _createClass(t, [{ key: "getWXLocation", value: function (t, a, e, i) { t = t || "gcj02", a = a || function () { }, e = e || function () { }, i = i || function () { }, wx.getLocation({ type: t, success: a, fail: e, complete: i }) } }, { key: "search", value: function (t) { var a = this; t = t || {}; var e = { query: t.query || "生活服务$美食&酒店", scope: t.scope || 1, filter: t.filter || "", coord_type: t.coord_type || 2, page_size: t.page_size || 10, page_num: t.page_num || 0, output: t.output || "json", ak: a.ak, sn: t.sn || "", timestamp: t.timestamp || "", radius: t.radius || 2e3, ret_coordtype: "gcj02ll" }, i = { iconPath: t.iconPath, iconTapPath: t.iconTapPath, width: t.width, height: t.height, alpha: t.alpha || 1, success: t.success || function () { }, fail: t.fail || function () { } }, n = function (t) { e.location = t.latitude + "," + t.longitude, wx.request({ url: "https://api.map.baidu.com/place/v2/search", data: e, header: { "content-type": "application/json" }, method: "GET", success: function (t) { var a = t.data; if (0 === a.status) { var e = a.results, n = {}; n.originalData = a, n.wxMarkerData = []; for (var s = 0; s < e.length; s++)n.wxMarkerData[s] = { id: s, latitude: e[s].location.lat, longitude: e[s].location.lng, title: e[s].name, iconPath: i.iconPath, iconTapPath: i.iconTapPath, address: e[s].address, telephone: e[s].telephone, alpha: i.alpha, width: i.width, height: i.height }; i.success(n) } else i.fail({ errMsg: a.message, statusCode: a.status }) }, fail: function (t) { i.fail(t) } }) }, s = function (t) { i.fail(t) }, o = function (t) { }; if (t.location) { var c = t.location.split(",")[1]; n({ errMsg: "input location", latitude: t.location.split(",")[0], longitude: c }) } else a.getWXLocation("gcj02", n, s, o) } }, { key: "suggestion", value: function (t) { var a = this; t = t || {}; var e = { query: t.query || "", region: t.region || "全国", city_limit: t.city_limit || !1, output: t.output || "json", ak: a.ak, sn: t.sn || "", timestamp: t.timestamp || "", ret_coordtype: "gcj02ll" }, i = { success: t.success || function () { }, fail: t.fail || function () { } }; wx.request({ url: "https://api.map.baidu.com/place/v2/suggestion", data: e, header: { "content-type": "application/json" }, method: "GET", success: function (t) { var a = t.data; 0 === a.status ? i.success(a) : i.fail({ errMsg: a.message, statusCode: a.status }) }, fail: function (t) { i.fail(t) } }) } }, { key: "regeocoding", value: function (t) { var a = this; t = t || {}; var e = { coordtype: t.coordtype || "gcj02ll", ret_coordtype: "gcj02ll", radius: t.radius || 1e3, ak: a.ak, sn: t.sn || "", output: t.output || "json", callback: t.callback || function () { }, extensions_poi: t.extensions_poi || 1, extensions_road: t.extensions_road || !1, extensions_town: t.extensions_town || !1, language: t.language || "zh-CN", language_auto: t.language_auto || 0 }, i = { iconPath: t.iconPath, iconTapPath: t.iconTapPath, width: t.width, height: t.height, alpha: t.alpha || 1, success: t.success || function () { }, fail: t.fail || function () { } }, n = function (t) { e.location = t.latitude + "," + t.longitude, wx.request({ url: "https://api.map.baidu.com/reverse_geocoding/v3", data: e, header: { "content-type": "application/json" }, method: "GET", success: function (a) { var e = a.data; if (0 === e.status) { var n = e.result, s = {}; s.originalData = e, s.wxMarkerData = [], s.wxMarkerData[0] = { id: 0, latitude: t.latitude, longitude: t.longitude, address: n.formatted_address, iconPath: i.iconPath, iconTapPath: i.iconTapPath, desc: n.sematic_description, business: n.business, alpha: i.alpha, width: i.width, height: i.height }, i.success(s) } else i.fail({ errMsg: e.message, statusCode: e.status }) }, fail: function (t) { i.fail(t) } }) }, s = function (t) { i.fail(t) }, o = function (t) { }; if (t.location) { var c = t.location.split(",")[1]; n({ errMsg: "input location", latitude: t.location.split(",")[0], longitude: c }) } else a.getWXLocation("gcj02", n, s, o) } }, { key: "geocoding", value: function (t) { var a = this; t = t || {}; var e = { address: t.address || "", city: t.city || "", ret_coordtype: t.coordtype || "gcj02ll", ak: a.ak, sn: t.sn || "", output: t.output || "json", callback: t.callback || function () { } }, i = { iconPath: t.iconPath, iconTapPath: t.iconTapPath, width: t.width, height: t.height, alpha: t.alpha || 1, success: t.success || function () { }, fail: t.fail || function () { } }; if (t.address) wx.request({ url: "https://api.map.baidu.com/geocoding/v3", data: e, header: { "content-type": "application/json" }, method: "GET", success: function (t) { var a = t.data; if (0 === a.status) { var e = a.result, n = a; n.originalData = a, n.wxMarkerData = [], n.wxMarkerData[0] = { id: 0, latitude: e.location.lat, longitude: e.location.lng, iconPath: i.iconPath, iconTapPath: i.iconTapPath, alpha: i.alpha, width: i.width, height: i.height }, i.success(n) } else i.fail({ errMsg: a.message, statusCode: a.status }) }, fail: function (t) { i.fail(t) } }); else { var n = { errMsg: "input address!" }; i.fail(n) } } }, { key: "weather", value: function (t) { var a = this; t = t || {}; var e = { coord_type: t.coord_type || "gcj02", output: t.output || "json", ak: a.ak, sn: t.sn || "", timestamp: t.timestamp || "" }, i = { success: t.success || function () { }, fail: t.fail || function () { } }, n = function (t) { e.location = t.longitude + "," + t.latitude, wx.request({ url: "https://api.map.baidu.com/telematics/v3/weather", data: e, header: { "content-type": "application/json" }, method: "GET", success: function (t) { var a = t.data; if (0 === a.error && "success" === a.status) { var e = a.results, n = {}; n.originalData = a, n.currentWeather = [], n.currentWeather[0] = { currentCity: e[0].currentCity, pm25: e[0].pm25, date: e[0].weather_data[0].date, temperature: e[0].weather_data[0].temperature, weatherDesc: e[0].weather_data[0].weather, wind: e[0].weather_data[0].wind }, i.success(n) } else i.fail({ errMsg: a.message, statusCode: a.status }) }, fail: function (t) { i.fail(t) } }) }, s = function (t) { i.fail(t) }, o = function (t) { }; if (t.location) { var c = t.location.split(",")[0]; n({ errMsg: "input location", latitude: t.location.split(",")[1], longitude: c }) } else a.getWXLocation("gcj02", n, s, o) } }]), t }(); module.exports.BMapWX = BMapWX;
--------------------------------------------------------------------------------
/miniprogram/utils/qqmap-wx-jssdk.min.js:
--------------------------------------------------------------------------------
1 | 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 URL_DIRECTION = BASE_URL + 'direction/v1/'; var MODE = { driving: 'driving', transit: 'transit' }; var EARTH_RADIUS = 6378136.49; var Utils = { safeAdd(x, y) { var lsw = (x & 0xffff) + (y & 0xffff); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xffff) }, bitRotateLeft(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)) }, md5cmn(q, a, b, x, s, t) { return this.safeAdd(this.bitRotateLeft(this.safeAdd(this.safeAdd(a, q), this.safeAdd(x, t)), s), b) }, md5ff(a, b, c, d, x, s, t) { return this.md5cmn((b & c) | (~b & d), a, b, x, s, t) }, md5gg(a, b, c, d, x, s, t) { return this.md5cmn((b & d) | (c & ~d), a, b, x, s, t) }, md5hh(a, b, c, d, x, s, t) { return this.md5cmn(b ^ c ^ d, a, b, x, s, t) }, md5ii(a, b, c, d, x, s, t) { return this.md5cmn(c ^ (b | ~d), a, b, x, s, t) }, binlMD5(x, len) { x[len >> 5] |= 0x80 << (len % 32); x[((len + 64) >>> 9 << 4) + 14] = len; var i; var olda; var oldb; var oldc; var oldd; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for (i = 0; i < x.length; i += 16) { olda = a; oldb = b; oldc = c; oldd = d; a = this.md5ff(a, b, c, d, x[i], 7, -680876936); d = this.md5ff(d, a, b, c, x[i + 1], 12, -389564586); c = this.md5ff(c, d, a, b, x[i + 2], 17, 606105819); b = this.md5ff(b, c, d, a, x[i + 3], 22, -1044525330); a = this.md5ff(a, b, c, d, x[i + 4], 7, -176418897); d = this.md5ff(d, a, b, c, x[i + 5], 12, 1200080426); c = this.md5ff(c, d, a, b, x[i + 6], 17, -1473231341); b = this.md5ff(b, c, d, a, x[i + 7], 22, -45705983); a = this.md5ff(a, b, c, d, x[i + 8], 7, 1770035416); d = this.md5ff(d, a, b, c, x[i + 9], 12, -1958414417); c = this.md5ff(c, d, a, b, x[i + 10], 17, -42063); b = this.md5ff(b, c, d, a, x[i + 11], 22, -1990404162); a = this.md5ff(a, b, c, d, x[i + 12], 7, 1804603682); d = this.md5ff(d, a, b, c, x[i + 13], 12, -40341101); c = this.md5ff(c, d, a, b, x[i + 14], 17, -1502002290); b = this.md5ff(b, c, d, a, x[i + 15], 22, 1236535329); a = this.md5gg(a, b, c, d, x[i + 1], 5, -165796510); d = this.md5gg(d, a, b, c, x[i + 6], 9, -1069501632); c = this.md5gg(c, d, a, b, x[i + 11], 14, 643717713); b = this.md5gg(b, c, d, a, x[i], 20, -373897302); a = this.md5gg(a, b, c, d, x[i + 5], 5, -701558691); d = this.md5gg(d, a, b, c, x[i + 10], 9, 38016083); c = this.md5gg(c, d, a, b, x[i + 15], 14, -660478335); b = this.md5gg(b, c, d, a, x[i + 4], 20, -405537848); a = this.md5gg(a, b, c, d, x[i + 9], 5, 568446438); d = this.md5gg(d, a, b, c, x[i + 14], 9, -1019803690); c = this.md5gg(c, d, a, b, x[i + 3], 14, -187363961); b = this.md5gg(b, c, d, a, x[i + 8], 20, 1163531501); a = this.md5gg(a, b, c, d, x[i + 13], 5, -1444681467); d = this.md5gg(d, a, b, c, x[i + 2], 9, -51403784); c = this.md5gg(c, d, a, b, x[i + 7], 14, 1735328473); b = this.md5gg(b, c, d, a, x[i + 12], 20, -1926607734); a = this.md5hh(a, b, c, d, x[i + 5], 4, -378558); d = this.md5hh(d, a, b, c, x[i + 8], 11, -2022574463); c = this.md5hh(c, d, a, b, x[i + 11], 16, 1839030562); b = this.md5hh(b, c, d, a, x[i + 14], 23, -35309556); a = this.md5hh(a, b, c, d, x[i + 1], 4, -1530992060); d = this.md5hh(d, a, b, c, x[i + 4], 11, 1272893353); c = this.md5hh(c, d, a, b, x[i + 7], 16, -155497632); b = this.md5hh(b, c, d, a, x[i + 10], 23, -1094730640); a = this.md5hh(a, b, c, d, x[i + 13], 4, 681279174); d = this.md5hh(d, a, b, c, x[i], 11, -358537222); c = this.md5hh(c, d, a, b, x[i + 3], 16, -722521979); b = this.md5hh(b, c, d, a, x[i + 6], 23, 76029189); a = this.md5hh(a, b, c, d, x[i + 9], 4, -640364487); d = this.md5hh(d, a, b, c, x[i + 12], 11, -421815835); c = this.md5hh(c, d, a, b, x[i + 15], 16, 530742520); b = this.md5hh(b, c, d, a, x[i + 2], 23, -995338651); a = this.md5ii(a, b, c, d, x[i], 6, -198630844); d = this.md5ii(d, a, b, c, x[i + 7], 10, 1126891415); c = this.md5ii(c, d, a, b, x[i + 14], 15, -1416354905); b = this.md5ii(b, c, d, a, x[i + 5], 21, -57434055); a = this.md5ii(a, b, c, d, x[i + 12], 6, 1700485571); d = this.md5ii(d, a, b, c, x[i + 3], 10, -1894986606); c = this.md5ii(c, d, a, b, x[i + 10], 15, -1051523); b = this.md5ii(b, c, d, a, x[i + 1], 21, -2054922799); a = this.md5ii(a, b, c, d, x[i + 8], 6, 1873313359); d = this.md5ii(d, a, b, c, x[i + 15], 10, -30611744); c = this.md5ii(c, d, a, b, x[i + 6], 15, -1560198380); b = this.md5ii(b, c, d, a, x[i + 13], 21, 1309151649); a = this.md5ii(a, b, c, d, x[i + 4], 6, -145523070); d = this.md5ii(d, a, b, c, x[i + 11], 10, -1120210379); c = this.md5ii(c, d, a, b, x[i + 2], 15, 718787259); b = this.md5ii(b, c, d, a, x[i + 9], 21, -343485551); a = this.safeAdd(a, olda); b = this.safeAdd(b, oldb); c = this.safeAdd(c, oldc); d = this.safeAdd(d, oldd) } return [a, b, c, d] }, binl2rstr(input) { var i; var output = ''; var length32 = input.length * 32; for (i = 0; i < length32; i += 8) { output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff) } return output }, rstr2binl(input) { var i; var output = []; output[(input.length >> 2) - 1] = undefined; for (i = 0; i < output.length; i += 1) { output[i] = 0 } var length8 = input.length * 8; for (i = 0; i < length8; i += 8) { output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32) } return output }, rstrMD5(s) { return this.binl2rstr(this.binlMD5(this.rstr2binl(s), s.length * 8)) }, rstrHMACMD5(key, data) { var i; var bkey = this.rstr2binl(key); var ipad = []; var opad = []; var hash; ipad[15] = opad[15] = undefined; if (bkey.length > 16) { bkey = this.binlMD5(bkey, key.length * 8) } for (i = 0; i < 16; i += 1) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5c5c5c5c } hash = this.binlMD5(ipad.concat(this.rstr2binl(data)), 512 + data.length * 8); return this.binl2rstr(this.binlMD5(opad.concat(hash), 512 + 128)) }, rstr2hex(input) { var hexTab = '0123456789abcdef'; var output = ''; var x; var i; for (i = 0; i < input.length; i += 1) { x = input.charCodeAt(i); output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f) } return output }, str2rstrUTF8(input) { return unescape(encodeURIComponent(input)) }, rawMD5(s) { return this.rstrMD5(this.str2rstrUTF8(s)) }, hexMD5(s) { return this.rstr2hex(this.rawMD5(s)) }, rawHMACMD5(k, d) { return this.rstrHMACMD5(this.str2rstrUTF8(k), str2rstrUTF8(d)) }, hexHMACMD5(k, d) { return this.rstr2hex(this.rawHMACMD5(k, d)) }, md5(string, key, raw) { if (!key) { if (!raw) { return this.hexMD5(string) } return this.rawMD5(string) } if (!raw) { return this.hexHMACMD5(key, string) } return this.rawHMACMD5(key, string) }, getSig(requestParam, sk, feature, mode) { var sig = null; var requestArr = []; Object.keys(requestParam).sort().forEach(function (key) { requestArr.push(key + '=' + requestParam[key]) }); if (feature == 'search') { sig = '/ws/place/v1/search?' + requestArr.join('&') + sk } if (feature == 'suggest') { sig = '/ws/place/v1/suggestion?' + requestArr.join('&') + sk } if (feature == 'reverseGeocoder') { sig = '/ws/geocoder/v1/?' + requestArr.join('&') + sk } if (feature == 'geocoder') { sig = '/ws/geocoder/v1/?' + requestArr.join('&') + sk } if (feature == 'getCityList') { sig = '/ws/district/v1/list?' + requestArr.join('&') + sk } if (feature == 'getDistrictByCityId') { sig = '/ws/district/v1/getchildren?' + requestArr.join('&') + sk } if (feature == 'calculateDistance') { sig = '/ws/distance/v1/?' + requestArr.join('&') + sk } if (feature == 'direction') { sig = '/ws/direction/v1/' + mode + '?' + requestArr.join('&') + sk } sig = this.md5(sig); return sig }, 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 }, 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 }, 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 }) }, 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 () { } }, 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 }, checkKeyword(param) { return !this.checkParamKeyEmpty(param, 'keyword') }, 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 }, buildErrorConfig(errCode, errMsg) { return { status: errCode, message: errMsg } }, 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) { 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 if (feature == 'direction') { var direction = data.result.routes; param.success(data, direction) } else { param.success(data) } }, 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 { constructor(options) { if (!options.key) { throw Error('key值不能为空') } this.key = options.key }; 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 + ")"; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'search') } } else if (rectangle && !region) { requestParam.boundary = "rectangle(" + rectangle + ")"; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'search') } } else { requestParam.boundary = "nearby(" + result.latitude + "," + result.longitude + "," + distance + "," + auto_extend + ")"; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'search') } } wx.request(Utils.buildWxRequestConfig(options, { url: URL_SEARCH, data: requestParam }, 'search')) }; Utils.locationProcess(options, locationsuccess) }; 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; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'suggest') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_SUGGESTION, data: requestParam }, "suggest")) }; Utils.locationProcess(options, locationsuccess) } else { if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'suggest') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_SUGGESTION, data: requestParam }, "suggest")) } }; 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; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'reverseGeocoder') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_GET_GEOCODER, data: requestParam }, 'reverseGeocoder')) }; Utils.locationProcess(options, locationsuccess) }; 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 } if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'geocoder') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_GET_GEOCODER, data: requestParam }, 'geocoder')) }; getCityList(options) { var that = this; options = options || {}; Utils.polyfillParam(options); var requestParam = { output: 'json', key: that.key }; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'getCityList') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_CITY_LIST, data: requestParam }, 'getCityList')) }; 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 }; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'getDistrictByCityId') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_AREA_LIST, data: requestParam }, 'getDistrictByCityId')) }; 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; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'calculateDistance') } wx.request(Utils.buildWxRequestConfig(options, { url: URL_DISTANCE, data: requestParam }, 'calculateDistance')) }; Utils.locationProcess(options, locationsuccess) } }; direction(options) { var that = this; options = options || {}; Utils.polyfillParam(options); if (Utils.checkParamKeyEmpty(options, 'to')) { return } var requestParam = { output: 'json', key: that.key }; if (typeof options.to == 'string') { requestParam.to = options.to } else { requestParam.to = options.to.latitude + ',' + options.to.longitude } var SET_URL_DIRECTION = null; options.mode = options.mode || MODE.driving; SET_URL_DIRECTION = URL_DIRECTION + options.mode; if (options.from) { options.location = options.from } if (options.mode == MODE.driving) { if (options.from_poi) { requestParam.from_poi = options.from_poi } if (options.heading) { requestParam.heading = options.heading } if (options.speed) { requestParam.speed = options.speed } if (options.accuracy) { requestParam.accuracy = options.accuracy } if (options.road_type) { requestParam.road_type = options.road_type } if (options.to_poi) { requestParam.to_poi = options.to_poi } if (options.from_track) { requestParam.from_track = options.from_track } if (options.waypoints) { requestParam.waypoints = options.waypoints } if (options.policy) { requestParam.policy = options.policy } if (options.plate_number) { requestParam.plate_number = options.plate_number } } if (options.mode == MODE.transit) { if (options.departure_time) { requestParam.departure_time = options.departure_time } if (options.policy) { requestParam.policy = options.policy } } var locationsuccess = function (result) { requestParam.from = result.latitude + ',' + result.longitude; if (options.sig) { requestParam.sig = Utils.getSig(requestParam, options.sig, 'direction', options.mode) } wx.request(Utils.buildWxRequestConfig(options, { url: SET_URL_DIRECTION, data: requestParam }, 'direction')) }; Utils.locationProcess(options, locationsuccess) } }; module.exports = QQMapWX;
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "miniprogramRoot": "miniprogram/",
3 | "cloudfunctionRoot": "cloudfunctions/",
4 | "setting": {
5 | "urlCheck": false,
6 | "es6": true,
7 | "enhance": true,
8 | "postcss": true,
9 | "minified": true,
10 | "newFeature": true,
11 | "coverView": true,
12 | "nodeModules": true,
13 | "autoAudits": false,
14 | "uglifyFileName": true,
15 | "checkInvalidKey": true,
16 | "checkSiteMap": true,
17 | "uploadWithSourceMap": true,
18 | "babelSetting": {
19 | "ignore": [],
20 | "disablePlugins": [],
21 | "outputPath": ""
22 | }
23 | },
24 | "appid": "wx63f4cbe16bc7194d",
25 | "projectname": "%E4%B8%AD%E7%A7%91%E5%A4%A7%E6%A0%A1%E5%8F%8B%E4%BC%9A",
26 | "libVersion": "2.8.3",
27 | "simulatorType": "wechat",
28 | "simulatorPluginLibVersion": {},
29 | "condition": {
30 | "search": {
31 | "current": -1,
32 | "list": []
33 | },
34 | "conversation": {
35 | "current": -1,
36 | "list": []
37 | },
38 | "plugin": {
39 | "current": -1,
40 | "list": []
41 | },
42 | "game": {
43 | "list": []
44 | },
45 | "miniprogram": {
46 | "current": 1,
47 | "list": [
48 | {
49 | "id": -1,
50 | "name": "db guide",
51 | "pathName": "pages/databaseGuide/databaseGuide",
52 | "query": ""
53 | },
54 | {
55 | "id": -1,
56 | "name": "pages/congratulation/congratulation",
57 | "pathName": "pages/congratulation/congratulation",
58 | "scene": null
59 | }
60 | ]
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------