├── .gitignore ├── README.md ├── cloudfunctionTemplate └── cloud.json ├── cloudfunctions ├── cloud │ ├── comm │ │ ├── biz_util.js │ │ ├── config.js │ │ └── router.js │ ├── config.json │ ├── controller │ │ ├── album_controller.js │ │ ├── base_controller.js │ │ ├── check_controller.js │ │ ├── info_controller.js │ │ ├── my_controller.js │ │ ├── passport_controller.js │ │ └── user_controller.js │ ├── framework │ │ ├── client │ │ │ └── controller.js │ │ ├── cloud │ │ │ ├── cloud_base.js │ │ │ └── cloud_util.js │ │ ├── database │ │ │ ├── db_util.js │ │ │ └── model.js │ │ ├── handler │ │ │ ├── app_code.js │ │ │ ├── app_error.js │ │ │ └── application.js │ │ ├── lib │ │ │ ├── mini_lib.js │ │ │ └── official_account_lib.js │ │ ├── utils │ │ │ ├── constant.js │ │ │ ├── str_util.js │ │ │ ├── time_util.js │ │ │ └── util.js │ │ └── validate │ │ │ ├── content_check.js │ │ │ └── data_check.js │ ├── index.js │ ├── model │ │ ├── album_model.js │ │ ├── base_model.js │ │ ├── info_model.js │ │ ├── setup_model.js │ │ └── user_model.js │ ├── package-lock.json │ ├── package.json │ └── service │ │ ├── album_service.js │ │ ├── base_service.js │ │ ├── info_service.js │ │ ├── passport_service.js │ │ └── user_service.js └── package-lock.json ├── miniprogram ├── app.js ├── app.json ├── app.wxss ├── biz │ ├── album_biz.js │ ├── base_biz.js │ ├── foot_biz.js │ ├── info_biz.js │ ├── passport_biz.js │ ├── reg_biz.js │ ├── search_biz.js │ └── user_biz.js ├── cmpts │ ├── lib │ │ └── wxa-plugin-canvas │ │ │ ├── index │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ └── index.wxss │ │ │ └── poster │ │ │ ├── index.js │ │ │ ├── index.json │ │ │ ├── index.wxml │ │ │ ├── index.wxss │ │ │ └── poster.js │ └── public │ │ ├── img │ │ ├── img_upload_cmpt.js │ │ ├── img_upload_cmpt.json │ │ ├── img_upload_cmpt.wxml │ │ └── img_upload_cmpt.wxss │ │ └── list │ │ ├── comm_list_cmpt.js │ │ ├── comm_list_cmpt.json │ │ ├── comm_list_cmpt.wxml │ │ ├── comm_list_cmpt.wxss │ │ ├── simple_list_cmpt.js │ │ ├── simple_list_cmpt.json │ │ ├── simple_list_cmpt.wxml │ │ └── simple_list_cmpt.wxss ├── helper │ ├── biz_helper.js │ ├── cache_helper.js │ ├── cloud_helper.js │ ├── comm.js │ ├── content_check_helper.js │ ├── helper.js │ ├── page_helper.js │ ├── setting.js │ └── validate.js ├── images │ ├── group │ │ ├── logo0.png │ │ ├── logo1.png │ │ ├── logo2.png │ │ └── logo3.png │ ├── main.jpg │ └── tabbar │ │ ├── home.png │ │ ├── home_cur.png │ │ ├── info.png │ │ ├── info_cur.png │ │ ├── meet.png │ │ ├── meet_cur.png │ │ ├── my.png │ │ ├── my_cur.png │ │ ├── user.png │ │ └── user_cur.png ├── lib │ └── we-cropper │ │ ├── we-cropper.js │ │ └── we-cropper.wxml ├── pages │ ├── about │ │ ├── about.js │ │ ├── about.json │ │ ├── about.wxml │ │ ├── about.wxss │ │ ├── hint.js │ │ ├── hint.json │ │ ├── hint.wxml │ │ └── hint.wxss │ ├── album │ │ ├── album_add.js │ │ ├── album_add.json │ │ ├── album_add.wxml │ │ ├── album_add.wxss │ │ ├── album_detail.js │ │ ├── album_detail.json │ │ ├── album_detail.wxml │ │ ├── album_detail.wxss │ │ ├── album_edit.js │ │ ├── album_edit.json │ │ ├── album_edit.wxml │ │ ├── album_edit.wxss │ │ ├── album_form_tpl.wxml │ │ ├── album_index.js │ │ ├── album_index.json │ │ ├── album_index.wxml │ │ └── album_index.wxss │ ├── info │ │ ├── info_add.js │ │ ├── info_add.json │ │ ├── info_add.wxml │ │ ├── info_add.wxss │ │ ├── info_detail.js │ │ ├── info_detail.json │ │ ├── info_detail.wxml │ │ ├── info_detail.wxss │ │ ├── info_edit.js │ │ ├── info_edit.json │ │ ├── info_edit.wxml │ │ ├── info_edit.wxss │ │ ├── info_form_tpl.wxml │ │ ├── info_index.js │ │ ├── info_index.json │ │ ├── info_index.wxml │ │ └── info_index.wxss │ ├── my │ │ ├── ad │ │ │ ├── my_ad.js │ │ │ ├── my_ad.json │ │ │ ├── my_ad.wxml │ │ │ └── my_ad.wxss │ │ ├── album │ │ │ ├── my_album.js │ │ │ ├── my_album.json │ │ │ ├── my_album.wxml │ │ │ └── my_album.wxss │ │ ├── base │ │ │ ├── my_avatar.js │ │ │ ├── my_avatar.json │ │ │ ├── my_avatar.wxml │ │ │ ├── my_avatar.wxss │ │ │ ├── my_base.js │ │ │ ├── my_base.json │ │ │ ├── my_base.wxml │ │ │ └── my_base.wxss │ │ ├── foot │ │ │ ├── my_foot.js │ │ │ ├── my_foot.json │ │ │ ├── my_foot.wxml │ │ │ └── my_foot.wxss │ │ ├── index │ │ │ ├── my_index.js │ │ │ ├── my_index.json │ │ │ ├── my_index.wxml │ │ │ └── my_index.wxss │ │ ├── info │ │ │ ├── my_info.js │ │ │ ├── my_info.json │ │ │ ├── my_info.wxml │ │ │ └── my_info.wxss │ │ └── reload │ │ │ ├── my_reload.js │ │ │ ├── my_reload.json │ │ │ ├── my_reload.wxml │ │ │ └── my_reload.wxss │ ├── reg │ │ ├── reg.wxss │ │ ├── reg_step1.js │ │ ├── reg_step1.json │ │ ├── reg_step1.wxml │ │ ├── reg_step1.wxss │ │ ├── reg_step2.js │ │ ├── reg_step2.json │ │ ├── reg_step2.wxml │ │ ├── reg_step2.wxss │ │ ├── reg_step3.js │ │ ├── reg_step3.json │ │ ├── reg_step3.wxml │ │ └── reg_step3.wxss │ ├── search │ │ ├── search.js │ │ ├── search.json │ │ ├── search.wxml │ │ └── search.wxss │ └── user │ │ ├── user_detail.js │ │ ├── user_detail.json │ │ ├── user_detail.wxml │ │ ├── user_detail.wxss │ │ ├── user_index.js │ │ ├── user_index.json │ │ ├── user_index.wxml │ │ └── user_index.wxss ├── sitemap.json ├── style │ ├── comm │ │ ├── animation.wxss │ │ ├── avatar.wxss │ │ ├── background.wxss │ │ ├── bar.wxss │ │ ├── base.wxss │ │ ├── border.wxss │ │ ├── button.wxss │ │ ├── comm.wxss │ │ ├── form.wxss │ │ ├── icon.wxss │ │ ├── image.wxss │ │ ├── layout.wxss │ │ ├── list.wxss │ │ ├── load.wxss │ │ ├── modal.wxss │ │ ├── nav.wxss │ │ ├── shadow.wxss │ │ ├── tag.wxss │ │ └── text.wxss │ ├── project │ │ ├── admin.wxss │ │ ├── article_list.wxss │ │ ├── detail.wxss │ │ ├── project.wxss │ │ └── user_list.wxss │ └── skin.wxss └── tpls │ ├── biz │ └── user_card_tpl.wxml │ └── public │ ├── list_load_tpl.wxml │ └── top_tpl.wxml ├── project.config.json └── 同学录小程序说明.docx /.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 | - 在这里,你会看到最完整的校友名录,一键找到你想找的TA! 2 | 3 | - 在这里,你可以了解最新的校友活动,点击报名就可参加心仪的活动! 4 | 5 | - 在这里,你能掌握最全的学院资讯,足不出户掌握一手消息! 6 | 7 | - 在这里,你可以收到校友专享的招聘信息,为你职业发展添砖加瓦! 8 | 9 | - 在这里,你会发现校友互助平台,帮助你对接需求和资源! 10 | 11 | # 技术使用 12 | 项目使用微信小程序平台进行开发。 使用腾讯云开发技术,免费资源配额, 无需域名和服务器即可搭建。 小程序本身的即用即走,适合小工具的使用场景,也适合程序的开发。 13 | ![image](https://user-images.githubusercontent.com/89532109/130811555-d532c37f-acf4-45ea-921d-9c488e589855.png) 14 | -------------------------------------------------------------------------------- /cloudfunctionTemplate/cloud.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "测试", 4 | "value": { 5 | "router": "test/test" 6 | } 7 | } 8 | ] -------------------------------------------------------------------------------- /cloudfunctions/cloud/comm/biz_util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 业务相关公用 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-10-24 19:20:00 5 | */ 6 | const TYPE = { 7 | //类型 0=用户,1=互助,2=活动 3=相册 4=资讯 5=接龙 99=系统 8 | USER: 0, 9 | INFO: 1, 10 | MEET: 2, 11 | ALBUM: 3, 12 | NEWS: 4, 13 | GROUP: 5, 14 | SYS: 99 15 | } 16 | 17 | function getTypeDesc(type) { 18 | switch (type) { 19 | //类型 0=用户,1=互助,2=活动 3=相册 4=资讯 5=接龙 99=系统 20 | case TYPE.USER: 21 | return '用户'; 22 | case TYPE.INFO: 23 | return '互助'; 24 | case TYPE.MEET: 25 | return '活动'; 26 | case TYPE.ALBUM: 27 | return '相册'; 28 | case TYPE.NEWS: 29 | return '资讯'; 30 | case TYPE.GROUP: 31 | return '接龙'; 32 | case TYPE.SYS: 33 | return '系统'; 34 | } 35 | } 36 | module.exports = { 37 | TYPE, 38 | getTypeDesc 39 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/comm/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | CLOUD_ID: 'xxxx', //云环境ID 3 | 4 | TEST_MODE: true, // 测试模式 涉及小程序码生成路径, 用以下 TEST_TOKEN_ID openid.. 5 | 6 | TEST_TOKEN_ID: 'oTthr5P34HTx5iYLtATaGjNlIxZw', 7 | 8 | USER_MINI_QRCODE_DIR: 'client/mini_qrcode/', // 用户小程序码目录 9 | 10 | CHECK_CONTENT: true, //图片文字是否校验 11 | 12 | MINI_STATE: 'formal' //跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版 13 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/comm/router.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 路由配置文件 3 | * User: CC 4 | * Date: 2020-10-14 07:00:00 5 | */ 6 | 7 | module.exports = { 8 | 9 | 10 | 11 | 'info/list': 'InfoController@getInfoList', 12 | 'info/my_list': 'InfoController@getMyInfoList', 13 | 'info/insert': 'InfoController@insertInfo', 14 | 'info/my_detail': 'InfoController@getMyInfoDetail', 15 | 'info/edit': 'InfoController@editInfo', 16 | 'info/del': 'InfoController@delInfo', 17 | 'info/like': 'InfoController@likeInfo', 18 | 'info/view': 'InfoController@viewInfo', 19 | 'info/update_pic': 'InfoController@updateInfoPic', 20 | 21 | 22 | 'album/list': 'AlbumController@getAlbumList', 23 | 'album/my_list': 'AlbumController@getMyAlbumList', 24 | 'album/insert': 'AlbumController@insertAlbum', 25 | 'album/my_detail': 'AlbumController@getMyAlbumDetail', 26 | 'album/edit': 'AlbumController@editAlbum', 27 | 'album/del': 'AlbumController@delAlbum', 28 | 'album/like': 'AlbumController@likeAlbum', 29 | 'album/view': 'AlbumController@viewAlbum', 30 | 'album/update_pic': 'AlbumController@updateAlbumPic', 31 | 32 | 33 | 34 | 'user/list': 'UserController@getUserList', 35 | 'user/detail': 'UserController@getUser', 36 | 'user/view': 'UserController@viewUser', //用户单页面查看 37 | 'user/my_detail': 'UserController@getMyDetail', 38 | 39 | 'my/invite': 'MyController@getMyInviteList', //我邀请的人 40 | 'my/info': 'MyController@getMyInfoList', //我发布的互助 41 | 'my/album': 'MyController@getMyAlbumList', //我发布的相册 42 | 43 | 44 | 'passport/phone': 'PassportController@getPhone', 45 | 'passport/unionid': 'PassportController@getUnionId', 46 | 'passport/reg': 'PassportController@register', 47 | 'passport/modify': 'PassportController@modifyBase', 48 | 'passport/login': 'PassportController@login', 49 | 'passport/check_family': 'PassportController@checkFamily', 50 | 'passport/update_pic': 'PassportController@updatePic', 51 | 52 | 'check/img': 'CheckController@checkImg', 53 | 54 | 'test/test': 'TestController@test', 55 | 56 | 57 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "permissions": { 3 | "openapi": ["wxacode.getUnlimited", "security.imgSecCheck", "security.msgSecCheck","serviceMarket.invokeService"] 4 | } 5 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/controller/base_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 基本业务控制器 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | const timeUtil = require('../framework/utils/time_util.js'); 9 | const Controller = require('../framework/client/controller.js'); 10 | const dataCheck = require('../framework/validate/data_check.js'); 11 | 12 | class BaseController extends Controller { 13 | 14 | constructor(miniOpenId, request, router, token) { 15 | super(miniOpenId, request, router, token); 16 | 17 | // 云函数入口文件 18 | 19 | //this._cloud = cloudUtil.getCloud(); 20 | //this._log = this._cloud.logger(); 21 | /* 22 | this._db = this._cloud.database(); 23 | this._dbCmd = this._db.command; 24 | this._dbAggr = this._dbCmd.aggregate;*/ 25 | 26 | // 微信上下文 OPENID, APPID,UNIONID,CLIENTIP, CLIENTIPV6 27 | //this._wxContext = this._cloud.getWXContext(); 28 | this._userId = miniOpenId; 29 | 30 | // 当前时间戳 31 | this._timestamp = timeUtil.time(); 32 | 33 | 34 | } 35 | 36 | /** 37 | * 数据校验 38 | * @param {*} rules 39 | */ 40 | validateData(rules = {}) { 41 | let input = this._request; 42 | return dataCheck.check(input, rules); 43 | } 44 | } 45 | 46 | module.exports = BaseController; -------------------------------------------------------------------------------- /cloudfunctions/cloud/controller/check_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 内容检测控制器 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-10-14 07:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | const BaseController = require('./base_controller.js'); 9 | const contentCheck = require('../framework/validate/content_check.js'); 10 | 11 | class CheckController extends BaseController { 12 | 13 | /** 14 | * 图片校验 15 | */ 16 | async checkImg() { 17 | 18 | // 数据校验 19 | let rules = { 20 | img: 'name=img', 21 | mine: 'required|default=jpg', 22 | }; 23 | 24 | // 取得数据 25 | let input = this.validateData(rules); 26 | 27 | return await contentCheck.checkImg(input.img, 'jpg'); 28 | 29 | } 30 | 31 | } 32 | 33 | module.exports = CheckController; -------------------------------------------------------------------------------- /cloudfunctions/cloud/controller/passport_controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: passport模块控制器 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-10 19:52:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | const BaseController = require('./base_controller.js'); 9 | const PassportService = require('../service/passport_service.js'); 10 | const contentCheck = require('../framework/validate/content_check.js'); 11 | 12 | class PassportController extends BaseController { 13 | 14 | /** 15 | * 获取UnionID 16 | */ 17 | async getUnionId() { 18 | 19 | // 数据校验 20 | let rules = { 21 | cloudID: 'required|string|min:1|max:200|name=cloudID', 22 | }; 23 | 24 | // 取得数据 25 | let input = this.validateData(rules); 26 | 27 | let service = new PassportService(); 28 | return await service.getUnionId(input.cloudID); 29 | } 30 | 31 | /** 32 | * 获取手机号码 33 | */ 34 | async getPhone() { 35 | 36 | // 数据校验 37 | let rules = { 38 | cloudID: 'required|string|min:1|max:200|name=cloudID', 39 | }; 40 | 41 | // 取得数据 42 | let input = this.validateData(rules); 43 | 44 | let service = new PassportService(); 45 | return await service.getPhone(input.cloudID); 46 | } 47 | 48 | /** 49 | * 注册 50 | * @param {*} formData=表单填写数据,wechatData微信授权数据,phone授权的手机数据 51 | */ 52 | async register() { 53 | // 数据校验 54 | let rules = { 55 | phone: 'required|string', 56 | formData: 'required|object', 57 | inviteData: 'required|object', 58 | wechatData: 'required|object', 59 | }; 60 | 61 | // 取得数据 62 | let input = this.validateData(rules); 63 | 64 | // 内容审核 65 | await contentCheck.checkTextMulti(input.formData); 66 | 67 | let service = new PassportService(); 68 | return await service.register(this._userId, input); 69 | } 70 | 71 | /** 72 | * 修改用户资料 73 | * @param {*} formData=表单填写数据 74 | */ 75 | async modifyBase() { 76 | // 数据校验 77 | let rules = { 78 | formData: 'required|object', 79 | }; 80 | 81 | // 取得数据 82 | let input = this.validateData(rules); 83 | 84 | // 内容审核 85 | await contentCheck.checkTextMulti(input.formData); 86 | 87 | let service = new PassportService(); 88 | return await service.modifyBase(this._userId, input); 89 | } 90 | 91 | /** 92 | * 登录 93 | */ 94 | async login() { 95 | // 数据校验 96 | let rules = {}; 97 | 98 | // 取得数据 99 | let input = this.validateData(rules); 100 | 101 | let service = new PassportService(); 102 | return await service.login(this._userId); 103 | } 104 | 105 | /** 106 | * 修改用户头像 107 | */ 108 | async updatePic() { 109 | // 数据校验 110 | let rules = { 111 | fileID: 'required|string', 112 | }; 113 | 114 | // 取得数据 115 | let input = this.validateData(rules); 116 | 117 | let service = new PassportService(); 118 | return await service.updatePic(this._userId, input.fileID); 119 | } 120 | 121 | } 122 | 123 | module.exports = PassportController; -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/client/controller.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 基础控制器 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | class Controller { 8 | 9 | constructor(miniOpenId, request, router, token) { 10 | this._miniOpenId = miniOpenId; 11 | this._request = request; 12 | this._router = router; 13 | this._token = token; 14 | } 15 | } 16 | 17 | module.exports = Controller; -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/cloud/cloud_base.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 云初始化实例 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | const config = require('../../comm/config.js'); 9 | 10 | /** 11 | * 获得云实例 12 | */ 13 | function getCloud() { 14 | const cloud = require('wx-server-sdk'); 15 | cloud.init({ 16 | env: config.CLOUD_ID 17 | }); 18 | return cloud; 19 | } 20 | 21 | module.exports = { 22 | getCloud 23 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/cloud/cloud_util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 云基本操作模块 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | const cloudBase = require('./cloud_base.js'); 8 | 9 | /** 10 | * 高级日志记录错误 11 | * @param {*} method 12 | * @param {*} err 13 | */ 14 | function log(method, err, level = 'error') { 15 | const cloud = cloudBase.getCloud(); 16 | const log = cloud.logger(); 17 | log.error({ 18 | method: method, 19 | errCode: err.code, 20 | errMsg: err.message, 21 | errStack: err.stack 22 | }); 23 | } 24 | /** 25 | * 根据临时文件地址取得网络地址 26 | * @param {*} fileID 27 | * @returns {String} 28 | */ 29 | async function getTempFileURLOne(fileID) { 30 | if (!fileID) return ''; 31 | 32 | const cloud = cloudBase.getCloud(); 33 | let result = await cloud.getTempFileURL({ 34 | fileList: [fileID], 35 | }) 36 | if (result && result.fileList && result.fileList[0] && result.fileList[0].tempFileURL) 37 | return result.fileList[0].tempFileURL; 38 | return ''; 39 | } 40 | 41 | /** 42 | * 根据临时文件地址取得网络地址 43 | * 用云文件 ID 换取真实链接,公有读的文件获取的链接不会过期,私有的文件获取的链接十分钟有效期。一次最多取 50 44 | * @param {*} fileList 45 | * @param {*} isValid 是否只取本次获取的合法的 46 | * @returns {Array} 对象数组 [{cloudId:, url:}] 47 | */ 48 | async function getTempFileURL(tempFileList, isValid = false) { 49 | if (!tempFileList || tempFileList.length == 0) return []; 50 | 51 | const cloud = cloudBase.getCloud(); 52 | let result = await cloud.getTempFileURL({ 53 | fileList: tempFileList, 54 | }) 55 | console.log(result); 56 | 57 | let list = result.fileList; 58 | let outList = []; 59 | for (let i = 0; i < list.length; i++) { 60 | let pic = {}; 61 | if (list[i].status == 0) { 62 | //获取到地址的 63 | pic.url = list[i].tempFileURL; 64 | pic.cloudId = list[i].fileID; 65 | outList.push(pic) 66 | } else { 67 | //未获取到地址的(已经转换过的) 68 | if (!isValid) { 69 | pic.url = list[i].fileID; // fileID为URL, tempFileURL为空 70 | pic.cloudId = list[i].fileID; 71 | outList.push(pic) 72 | } 73 | } 74 | } 75 | console.log(outList); 76 | return outList; 77 | } 78 | 79 | /** 80 | * 用后面的文件数组替换前面的,并删除已经不存在的FileID 81 | * @param {*} oldFiles 82 | * 格式 下同 83 | * [{ 84 | cloudId: xxxxx 85 | url: yyyyyy 86 | * },....] 87 | * @param {*} newFiles 88 | * @returns {Array} 对象数组 [{cloudId:, url:}] 89 | */ 90 | async function handlerCloudFiles(oldFiles, newFiles) { 91 | const cloud = cloudBase.getCloud(); 92 | for (let i = 0; i < oldFiles.length; i++) { 93 | let isDel = true; 94 | for (let j = 0; j < newFiles.length; j++) { 95 | if (oldFiles[i].url == newFiles[j].url) { 96 | // 从旧文件数组里 找到 新组 还存在的文件, 保存cloudID 97 | newFiles[j].cloudId = oldFiles[i].cloudId; 98 | isDel = false; 99 | break; 100 | } 101 | } 102 | // 新组里不存在,直接删除 103 | if (isDel && oldFiles[i].cloudId) { 104 | 105 | let result = await cloud.deleteFile({ 106 | fileList: [oldFiles[i].cloudId], 107 | }); 108 | console.log(result); 109 | } 110 | 111 | } 112 | 113 | return newFiles; 114 | } 115 | 116 | /** 117 | * 删除文件 118 | * @param {*} list 文件数组cloudid 119 | */ 120 | async function deleteFiles(list = []) { 121 | const cloud = cloudBase.getCloud(); 122 | if (!Array.isArray(list) || list.length == 0) return; 123 | await cloud.deleteFile({ 124 | fileList: list, 125 | }); 126 | } 127 | 128 | module.exports = { 129 | log, 130 | getTempFileURL, 131 | getTempFileURLOne, 132 | deleteFiles, 133 | handlerCloudFiles 134 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/handler/app_code.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 错误代码定义 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | module.exports = { 8 | SUCC: 200, 9 | SVR: 500, //服务器错误 10 | LOGIC: 1600, //逻辑错误 11 | DATA: 1301, // 数据校验错误 12 | HEADER: 1302, // header 校验错误 13 | NOT_USER: 1303, // 用户不存在 14 | USER_EXCEPTION: 1304, // 用户异常 15 | MUST_LOGIN: 1305, //需要登录 16 | USER_CHECK: 1306, //用户审核中 17 | 18 | ADMIN_ERROR: 2001 //管理员错误 19 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/handler/app_error.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 应用异常处理类 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | 9 | const appCode = require('./app_code.js'); 10 | 11 | class AppError extends Error { 12 | constructor(message, code = appCode.LOGIC) { 13 | super(message); 14 | this.name = 'AppError'; 15 | this.code = code; 16 | } 17 | } 18 | 19 | module.exports = AppError; -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/lib/mini_lib.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 小程序封装类库 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-06 14:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | const cloudBase = require('../cloud/cloud_base.js'); 8 | const cloudUtil = require('../cloud/cloud_util.js'); 9 | 10 | async function sendOnceTempMsg(body) { 11 | console.log('sendOnceTempMsg', body); 12 | let cloud = cloudBase.getCloud(); 13 | try { 14 | await cloud.openapi.subscribeMessage.send(body); 15 | } catch (err) { 16 | cloudUtil.log('sendOnceTempMsg', err); 17 | } 18 | } 19 | module.exports = { 20 | sendOnceTempMsg 21 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/lib/official_account_lib.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 公众号封装类库 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-06 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | const request = require('request'); 9 | 10 | /** 11 | * 获取公众号access_token 12 | */ 13 | async function getOfficialAccountAccessToken() { 14 | let appid = 'wx63eb61409e1a25f5'; 15 | let secret = '1c3ae7d1af911085b84355bd5e27ab13'; 16 | let token_url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + appid + '&' + 'secret=' + secret; 17 | const rp = options => 18 | new Promise((resolve, reject) => { 19 | request(options, (error, response, body) => { 20 | if (error) { 21 | reject(error); 22 | } 23 | resolve(response); 24 | }); 25 | }); 26 | const result = await rp({ 27 | url: token_url, 28 | method: 'GET' 29 | }); 30 | return (typeof result.body === 'object') ? result.body : JSON.parse(result.body);; 31 | } 32 | 33 | 34 | /** 35 | * 发送公众号模板消息 36 | */ 37 | async function sendTemp() { 38 | try { 39 | const cloud = cloudUtil.getCloud(); 40 | const result = await cloud.openapi.uniformMessage.send({ 41 | touser: 'oYyk-5Q4WyAc0DWnqt2x89kfR_y0', 42 | mpTemplateMsg: { 43 | appid: 'wx63eb61409e1a25f5', 44 | url: 'http://weixin.qq.com/download', 45 | miniprogram: { 46 | appid: 'wxac22c5d07761ba60', 47 | path: 'info/info_index' 48 | }, 49 | data: { 50 | first: { 51 | value: '恭喜你购买成功!', 52 | color: '#173177' 53 | }, 54 | keyword1: { 55 | value: '巧克力', 56 | color: '#173177' 57 | }, 58 | keyword2: { 59 | value: '39.8元', 60 | color: '#173177' 61 | }, 62 | 63 | remark: { 64 | value: '欢迎再次购买!', 65 | color: '#173177' 66 | } 67 | }, 68 | templateId: '4-OLRJmUxTyCSZJH1IJHn6DPFvz6f2nDjS0XSL4UwJM' 69 | }, 70 | }); 71 | console.log(result) 72 | } catch (err) { 73 | console.log(err) 74 | } 75 | } 76 | 77 | module.exports = { 78 | getOfficialAccountAccessToken, 79 | sendTemp //发送模板消息 80 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/utils/constant.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 通用常量定义 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | module.exports = { 8 | 9 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/utils/str_util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 字符相关操作函数 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | 9 | /** 10 | * 生成一个特定范围内的随机数 11 | */ 12 | const genRandomNum = (min, max) => (Math.random() * (max - min + 1) | 0) + min; 13 | 14 | /** 15 | * 生成一个随机的数字字母字符串 16 | */ 17 | const genRandomString = len => { 18 | const text = 'abcdefghijklmnopqrstuvwxyz0123456789'; 19 | const rdmIndex = text => Math.random() * text.length | 0; 20 | let rdmString = ''; 21 | for (; rdmString.length < len; rdmString += text.charAt(rdmIndex(text))); 22 | return rdmString; 23 | } 24 | 25 | 26 | /** 27 | * 把字符串格式化为数组 28 | * @param {*} str 29 | * @param {*} sp 30 | */ 31 | function str2Arr(str, sp) { 32 | if (str && Array.isArray(str)) return str; 33 | 34 | if (sp == undefined) sp = ','; 35 | 36 | str = str.replace(/,/g, ","); 37 | let arr = str.split(','); 38 | for (let i = 0; i < arr.length; i++) { 39 | arr[i] = arr[i].trim(); 40 | 41 | if (isNumber(arr[i])) { 42 | arr[i] = Number(arr[i]); 43 | } 44 | 45 | } 46 | return arr; 47 | } 48 | 49 | /** 50 | * 校验只要是数字(包含正负整数,0以及正负浮点数)就返回true 51 | * @param {*} val 52 | */ 53 | function isNumber(val) { 54 | var reg = /^[0-9]+.?[0-9]*$/; 55 | if (reg.test(val)) { 56 | return true; 57 | } else { 58 | return false; 59 | } 60 | } 61 | 62 | /** 63 | * 提取对象数组的某个属性数组 64 | * @param {*} arr 65 | * @param {*} key 66 | */ 67 | function getArrByKey(arr, key) { 68 | if (!Array.isArray(arr)) return; 69 | return arr.map((item) => { 70 | return item[key] 71 | }); 72 | } 73 | 74 | /** 75 | * 文本内容格式化处理 76 | * @param {*} content 77 | * @param {*} len 截取长度 -1不截取 78 | */ 79 | function fmtText(content, len = -1) { 80 | let str = content.replace(/[\r\n]/g, ""); //去掉回车换行 81 | if (len > 0) { 82 | str = str.substr(0, len); 83 | } 84 | return str.trim(); 85 | } 86 | 87 | module.exports = { 88 | str2Arr, 89 | isNumber, 90 | getArrByKey, 91 | genRandomString, // 随机字符串 92 | genRandomNum, // 随机数字 93 | fmtText, // 文本内容格式化处理 94 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/utils/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 通用工具函数 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | /** 9 | * 判断变量,参数,对象属性是否定义 10 | * @param {*} val 11 | */ 12 | function isDefined(val) { 13 | // == 不能判断是否为null 14 | if (val === undefined) 15 | return false; 16 | else 17 | return true; 18 | } 19 | 20 | /** 21 | * 休眠时间,配合await使用 22 | * @param {*} time 毫秒 23 | */ 24 | function sleep(time) { 25 | return new Promise((resolve) => setTimeout(resolve, time)); 26 | }; 27 | 28 | module.exports = { 29 | isDefined, //判断变量,参数,对象属性是否定义 30 | sleep 31 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/framework/validate/content_check.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 内容审核 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | const AppError = require('../handler/app_error.js'); 9 | const cloudBase = require('../cloud/cloud_base.js'); 10 | const config = require('../../comm/config.js'); 11 | 12 | /** 13 | * 校验图片信息 14 | * @param {*} 图片流buffer 15 | */ 16 | async function checkImg(imgData, mine) { 17 | if (!config.CHECK_CONTENT) return; 18 | 19 | let cloud = cloudBase.getCloud(); 20 | try { 21 | const result = await cloud.openapi.security.imgSecCheck({ 22 | media: { 23 | contentType: 'image/' + mine, 24 | value: Buffer.from(imgData, 'base64') // 这里必须要将小程序端传过来的进行Buffer转化,否则就会报错,接口异常 25 | } 26 | 27 | }) 28 | console.log('imgcheck', result); 29 | if (!result || result.errCode !== 0) { 30 | throw new AppError('图片内容不合适,请修改'); 31 | } 32 | 33 | } catch (err) { 34 | console.log('imgcheck ex', err); 35 | throw new AppError('图片内容不合适,请修改'); 36 | } 37 | 38 | } 39 | 40 | /** 41 | * 把输入数据里的文本数据提交内容审核 42 | * @param {*} input 43 | */ 44 | async function checkTextMulti(input) { 45 | if (!config.CHECK_CONTENT) return; 46 | 47 | let txt = ''; 48 | for (let k in input) { 49 | if (typeof (input[k]) === 'string') 50 | txt += input[k]; 51 | } 52 | await checkText(txt); 53 | } 54 | 55 | /** 56 | * 校验文字信息 57 | * @param {*} 58 | */ 59 | async function checkText(txt) { 60 | if (!config.CHECK_CONTENT) return; 61 | 62 | if (!txt) return; 63 | 64 | let cloud = cloudBase.getCloud(); 65 | try { 66 | const result = await cloud.openapi.security.msgSecCheck({ 67 | content: txt 68 | 69 | }) 70 | // console.log('checkText', result); 71 | if (!result || result.errCode !== 0) { 72 | throw new AppError('文字内容不合适,请修改'); 73 | } 74 | 75 | } catch (err) { 76 | console.log('checkText ex', err); 77 | throw new AppError('文字内容不合适,请修改'); 78 | } 79 | 80 | } 81 | 82 | module.exports = { 83 | checkImg, 84 | checkTextMulti, 85 | checkText 86 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/index.js: -------------------------------------------------------------------------------- 1 | const application = require('./framework/handler/application.js'); 2 | 3 | // 云函数入口函数 4 | exports.main = async (event, context) => { 5 | return await application.app(event, context); 6 | } -------------------------------------------------------------------------------- /cloudfunctions/cloud/model/album_model.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 相册实体 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-10-24 19:20:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | 9 | const BaseModel = require('./base_model.js'); 10 | 11 | class AlbumModel extends BaseModel { 12 | 13 | } 14 | 15 | // 集合名 16 | AlbumModel.CL = "t_album"; 17 | 18 | AlbumModel.DB_STRUCTURE = { 19 | ALBUM_ID: 'string|true', 20 | ALBUM_USER_ID: 'string|true', 21 | 22 | ALBUM_TITLE: 'string|true|comment=标题', 23 | ALBUM_CONTENT: 'string|true|comment=内容', 24 | ALBUM_DESC: 'string|false|comment=描述', 25 | ALBUM_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=正常 7=结束 8=停用 9=删除', 26 | ALBUM_TYPE: 'string|true|default=其他|comment=类型 同学时光,校园追忆,校友今夕,活动聚会,个人风采,其他', 27 | ALBUM_ORDER: 'int|true|default=9999', 28 | 29 | ALBUM_VIEW_CNT: 'int|true|default=0|comment=访问次数', 30 | ALBUM_FAV_CNT: 'int|true|default=0|comment=收藏人数', 31 | ALBUM_COMMENT_CNT: 'int|true|default=0|comment=评论数', 32 | ALBUM_LIKE_CNT: 'int|true|default=0|comment=点赞数', 33 | 34 | 35 | ALBUM_PIC: 'array|false|default=[]|comment=附加图片 对象数组[{cloudId,url}]', 36 | 37 | ALBUM_ADD_TIME: 'int|true', 38 | ALBUM_EDIT_TIME: 'int|true', 39 | ALBUM_ADD_IP: 'string|false', 40 | ALBUM_EDIT_IP: 'string|false', 41 | }; 42 | 43 | // 字段前缀 44 | AlbumModel.FIELD_PREFIX = "ALBUM_"; 45 | 46 | AlbumModel.STATUS = { 47 | //0=待审核 1=正常 7=结束 8=停用 9=删除 48 | UNUSE: 0, 49 | COMM: 1, 50 | OVER: 7, 51 | PEDDING: 8, 52 | DEL: 9 53 | }; 54 | 55 | AlbumModel.STATUS_DESC = { 56 | //0=待审核 1=正常 7=结束 8=停用 9=删除 57 | UNUSE: '待审核', 58 | COMM: '正常', 59 | OVER: '结束', 60 | PEDDING: '停用', 61 | DEL: '删除' 62 | }; 63 | 64 | 65 | module.exports = AlbumModel; -------------------------------------------------------------------------------- /cloudfunctions/cloud/model/base_model.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 实体基类 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 19:20:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | 9 | const Model = require('../framework/database/model.js'); 10 | 11 | class BaseModel extends Model{ 12 | } 13 | 14 | module.exports = BaseModel; -------------------------------------------------------------------------------- /cloudfunctions/cloud/model/info_model.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 互助实体 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-10-14 19:20:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | 9 | const BaseModel = require('./base_model.js'); 10 | 11 | class InfoModel extends BaseModel { 12 | 13 | } 14 | 15 | // 集合名 16 | InfoModel.CL = "t_info"; 17 | 18 | InfoModel.DB_STRUCTURE = { 19 | INFO_ID: 'string|true', 20 | INFO_USER_ID: 'string|true', 21 | 22 | INFO_TITLE: 'string|true|comment=标题', 23 | INFO_DESC: 'string|false|comment=描述', 24 | INFO_CONTENT: 'string|true|comment=内容', 25 | INFO_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=正常 7=过期 8=停用 9=删除', 26 | INFO_TYPE: 'string|true|default=其他|comment=类型 资源合作,活动聚会,创业合作,招聘猎头,求职,企业推介,供应采购,商务合作,服务咨询,其他', 27 | INFO_ORDER: 'int|true|default=9999', 28 | 29 | INFO_VIEW_CNT: 'int|true|default=0|comment=访问次数', 30 | INFO_FAV_CNT: 'int|true|default=0|comment=收藏人数', 31 | INFO_COMMENT_CNT: 'int|true|default=0|comment=评论数', 32 | INFO_LIKE_CNT: 'int|true|default=0|comment=点赞数', 33 | 34 | INFO_EXPIRE_TIME: 'int|true|default=0|comment=过期时间 0=永不过期', 35 | 36 | INFO_REGION_PROVINCE: 'string|false|comment=区域(省)', 37 | INFO_REGION_CITY: 'string|false|comment=区域(市)', 38 | INFO_REGION_COUNTY: 'string|false|comment=区域(区)', 39 | 40 | INFO_PIC: 'array|false|default=[]|comment=附加图片 对象数组[{cloudId,url}]', 41 | 42 | INFO_ADD_TIME: 'int|true', 43 | INFO_EDIT_TIME: 'int|true', 44 | INFO_ADD_IP: 'string|false', 45 | INFO_EDIT_IP: 'string|false', 46 | }; 47 | 48 | // 字段前缀 49 | InfoModel.FIELD_PREFIX = "INFO_"; 50 | 51 | InfoModel.STATUS = { 52 | //0=待审核 1=正常 8=停用 9=删除 53 | UNUSE: 0, 54 | COMM: 1, 55 | PEDDING: 8, 56 | DEL: 9 57 | }; 58 | 59 | InfoModel.STATUS_DESC = { 60 | //0=待审核 1=正常 8=停用 9=删除 61 | UNUSE: '待审核', 62 | COMM: '正常', 63 | PEDDING: '停用', 64 | DEL: '删除' 65 | }; 66 | 67 | 68 | module.exports = InfoModel; -------------------------------------------------------------------------------- /cloudfunctions/cloud/model/setup_model.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 系统设置实体 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-05 19:20:00 5 | * Version : CCMiniCloud Framework Ver 2.0.1 ALL RIGHTS RESERVED BY 明章科技 6 | */ 7 | 8 | 9 | const BaseModel = require('./base_model.js'); 10 | 11 | class SetupModel extends BaseModel { 12 | 13 | } 14 | 15 | // 集合名 16 | SetupModel.CL = "t_setup"; 17 | 18 | SetupModel.DB_STRUCTURE = { 19 | SETUP_ID: 'string|true', 20 | 21 | SETUP_TITLE: 'string|false|comment=网站名称', 22 | SETUP_ABOUT: 'string|false|comment=关于我们', 23 | 24 | SETUP_LOGO: 'object|false|default={}|comment=网站底图 对象{cloudId,url}', 25 | 26 | SETUP_AD_PIC: 'array|false|default=[]|comment=海报底图 对象数组[{cloudId,url}]', 27 | 28 | SETUP_REG_CHECK : 'int|true|default=0|comment=注册是否审核 0/1', 29 | 30 | SETUP_ADD_TIME: 'int|true', 31 | SETUP_EDIT_TIME: 'int|true', 32 | SETUP_ADD_IP: 'string|false', 33 | SETUP_EDIT_IP: 'string|false', 34 | }; 35 | 36 | // 字段前缀 37 | SetupModel.FIELD_PREFIX = "SETUP_"; 38 | 39 | 40 | 41 | 42 | 43 | 44 | module.exports = SetupModel; -------------------------------------------------------------------------------- /cloudfunctions/cloud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cloud", 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 | "date-utils": "^1.2.21", 13 | "wx-server-sdk": "~2.1.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /cloudfunctions/cloud/service/base_service.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 业务基类 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-09-05 04:00:00 5 | */ 6 | 7 | const AppError = require('../framework/handler/app_error.js'); 8 | const appCode = require('../framework/handler/app_code.js'); 9 | const timeUtil = require('../framework/utils/time_util.js'); 10 | const UserModel = require('../model/user_model.js'); 11 | 12 | class BaseService { 13 | constructor() { 14 | // 当前时间戳 15 | this._timestamp = timeUtil.time(); 16 | } 17 | 18 | /** 19 | * 抛出异常 20 | * @param {*} msg 21 | * @param {*} code 22 | */ 23 | AppError(msg, code = appCode.LOGIC) { 24 | throw new AppError(msg, code); 25 | } 26 | 27 | /** 28 | * 与用户表联表查询 默认用户表参数 29 | * @param {*} localField 30 | */ 31 | getJoinUserParams(localField = '_openid') { 32 | return { 33 | from: 't_user', 34 | localField: localField, 35 | foreignField: 'USER_MINI_OPENID', 36 | as: 'USER_DETAIL', 37 | }; 38 | } 39 | 40 | /** 41 | * 与用户表联表查询 默认用户表输出字段 42 | */ 43 | getJoinUserFields() { 44 | return 'USER_DETAIL.USER_ITEM,USER_DETAIL.USER_NAME,USER_DETAIL.USER_PIC,USER_DETAIL.USER_MINI_OPENID,USER_DETAIL.USER_SEX'; 45 | } 46 | 47 | /** 48 | * 与用户表联表查询 默认用户表输出字段 for ADMIN 49 | */ 50 | getJoinUserFieldsAdmin() { 51 | return 'USER_DETAIL.USER_ITEM,USER_DETAIL.USER_NAME,USER_DETAIL.USER_MINI_OPENID,USER_DETAIL.USER_SEX'; 52 | } 53 | 54 | 55 | /** 56 | * 单独用户表 默认输出字段 57 | */ 58 | getUserFields() { 59 | return 'USER_NAME,USER_PIC,USER_SEX,USER_MINI_OPENID,USER_ITEM'; 60 | } 61 | 62 | /** 63 | * 获取当前授权用户信息 64 | * @param {*} openid 65 | */ 66 | async getUserMyBase(userId, fields = this.getUserFields()) { 67 | let where = { 68 | USER_MINI_OPENID: userId 69 | } 70 | return await UserModel.getOne(where, fields); 71 | } 72 | 73 | /** 74 | * 获取某个用户信息 75 | * @param {*} openid 76 | */ 77 | async getUserOne(userId, fields = this.getUserFields()) { 78 | let where = { 79 | USER_MINI_OPENID: userId 80 | } 81 | return await UserModel.getOne(where, fields); 82 | } 83 | } 84 | 85 | module.exports = BaseService; -------------------------------------------------------------------------------- /cloudfunctions/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "lockfileVersion": 1 3 | } 4 | -------------------------------------------------------------------------------- /miniprogram/app.js: -------------------------------------------------------------------------------- 1 | const PassportBiz = require('./biz/passport_biz.js'); 2 | 3 | App({ 4 | onLaunch: function (options) { 5 | 6 | if (!wx.cloud) { 7 | console.error('请使用 2.2.3 或以上的基础库以使用云能力') 8 | } else { 9 | wx.cloud.init({ 10 | // env 参数说明: 11 | // env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源 12 | // 此处请填入环境 ID, 环境 ID 可打开云控制台查看 13 | // 如不填则使用默认环境(第一个创建的环境) 14 | // env: 'my-env-id', 15 | traceUser: true, 16 | }) 17 | } 18 | 19 | this.globalData = {} 20 | }, 21 | /* 22 | onShow: function (options) { 23 | // 启动,或者从后台进入前台 24 | //GroupBiz.initGroupShareTicket(options); 25 | }, 26 | onHide: function () { 27 | // 小程序从前台进入后台 28 | //GroupBiz.clearGroupShareTicket(); 29 | }*/ 30 | }) -------------------------------------------------------------------------------- /miniprogram/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | 4 | "pages/my/index/my_index", 5 | "pages/reg/reg_step1", 6 | "pages/reg/reg_step2", 7 | "pages/reg/reg_step3", 8 | "pages/my/base/my_base", 9 | "pages/my/reload/my_reload", 10 | "pages/my/base/my_avatar", 11 | "pages/info/info_index", 12 | "pages/info/info_add", 13 | "pages/info/info_detail", 14 | 15 | "pages/info/info_edit", 16 | "pages/search/search", 17 | "pages/user/user_index", 18 | "pages/user/user_detail", 19 | 20 | "pages/album/album_index", 21 | "pages/album/album_add", 22 | "pages/album/album_edit", 23 | "pages/album/album_detail", 24 | 25 | 26 | "pages/my/info/my_info", 27 | "pages/my/album/my_album", 28 | "pages/my/foot/my_foot", 29 | "pages/my/ad/my_ad", 30 | 31 | "pages/about/about", 32 | "pages/about/hint" 33 | ], 34 | "window": { 35 | "backgroundColor": "#f1f1f1", 36 | "backgroundTextStyle": "light", 37 | "navigationBarBackgroundColor": "#1cbbb4", 38 | "navigationBarTitleText": "CC校友录", 39 | "navigationBarTextStyle": "white" 40 | }, 41 | "tabBar": { 42 | "backgroundColor": "#fefefe", 43 | "color": "#ccc", 44 | "selectedColor": "#1cbbb4", 45 | "list": [ 46 | 47 | { 48 | "pagePath": "pages/user/user_index", 49 | "text": "找校友", 50 | "iconPath": "/images/tabbar/user.png", 51 | "selectedIconPath": "/images/tabbar/user_cur.png" 52 | }, 53 | { 54 | "pagePath": "pages/info/info_index", 55 | "text": "校友互助", 56 | "iconPath": "/images/tabbar/info.png", 57 | "selectedIconPath": "/images/tabbar/info_cur.png" 58 | }, 59 | { 60 | "pagePath": "pages/album/album_index", 61 | "text": "校友相册", 62 | "iconPath": "/images/tabbar/meet.png", 63 | "selectedIconPath": "/images/tabbar/meet_cur.png" 64 | }, 65 | { 66 | "pagePath": "pages/my/index/my_index", 67 | "text": "个人中心", 68 | "iconPath": "/images/tabbar/my.png", 69 | "selectedIconPath": "/images/tabbar/my_cur.png" 70 | } 71 | ] 72 | }, 73 | "sitemapLocation": "sitemap.json" 74 | } -------------------------------------------------------------------------------- /miniprogram/app.wxss: -------------------------------------------------------------------------------- 1 | @import "style/comm/comm.wxss"; 2 | @import "style/project/project.wxss"; 3 | 4 | @import "style/skin.wxss"; 5 | 6 | -------------------------------------------------------------------------------- /miniprogram/biz/album_biz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 相册模块业务逻辑 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const BaseBiz = require('./base_biz.js'); 8 | const cloudHelper = require('../helper/cloud_helper.js'); 9 | const helper = require('../helper/helper.js'); 10 | const setting = require('../helper/setting.js'); 11 | 12 | class AlbumBiz extends BaseBiz { 13 | 14 | 15 | /** 16 | * 表单初始化相关数据 17 | */ 18 | static initFormData(id = '') { 19 | 20 | return { 21 | id, 22 | 23 | // 分类 24 | typeOptions: AlbumBiz.TYPE_OPTIONS, 25 | 26 | 27 | 28 | // 图片数据 29 | imgMax: setting.ALBUM_MAX_PIC, 30 | imgList: [], 31 | 32 | // 表单数据 33 | formTypeIndex: 0, 34 | formTitle: '', 35 | formContent: '', 36 | } 37 | 38 | } 39 | 40 | /** 41 | * 图片上传 42 | * @param {string} albumId 43 | * @param {Array} imgList 图片数组 44 | */ 45 | static async updateAlbumPic(albumId, imgList) { 46 | 47 | // 图片上传到云空间 48 | imgList = await cloudHelper.transTempPics(imgList, setting.ALBUM_PIC_DIR, albumId); 49 | 50 | // 更新本记录的图片信息 51 | let params = { 52 | albumId: albumId, 53 | imgList: imgList 54 | } 55 | 56 | try { 57 | // 更新数据 从promise 里直接同步返回 58 | let res = await cloudHelper.callCloudSumbit('album/update_pic', params); 59 | return res.data.urls; 60 | } catch (e) {} 61 | } 62 | 63 | /** 64 | * 搜索菜单设置 65 | */ 66 | static getSearchMenu() { 67 | 68 | let sortItem1 = [{ 69 | label: '综合排序', 70 | type: '', 71 | value: 0 72 | }]; 73 | 74 | // 分类 75 | let sortItem2 = [{ 76 | label: '所有分类', 77 | type: '', 78 | value: 0 79 | }]; 80 | for (let k in AlbumBiz.TYPE_OPTIONS){ 81 | sortItem2.push( 82 | { 83 | label: AlbumBiz.TYPE_OPTIONS[k], 84 | type: 'type', 85 | value: AlbumBiz.TYPE_OPTIONS[k], 86 | } 87 | ) 88 | } 89 | 90 | let sortItems = [sortItem2]; 91 | let sortMenus = [{ 92 | label: '最新', 93 | type: 'sort', 94 | value: 'new' 95 | }, 96 | { 97 | label: '最热', 98 | type: 'sort', 99 | value: 'view' 100 | }, 101 | { 102 | label: '全部', 103 | type: '', 104 | value: '' 105 | } 106 | ] 107 | 108 | return { 109 | sortItems, 110 | sortMenus 111 | } 112 | 113 | } 114 | } 115 | /** 116 | * 分类 117 | */ 118 | AlbumBiz.TYPE_OPTIONS = "同学时光,校园追忆,校友今夕,活动聚会,个人风采,其他".split(','); 119 | 120 | //表单校验 121 | AlbumBiz.CHECK_FORM = { 122 | title: 'formTitle|required|string|min:5|max:50|name=相册标题', 123 | type: 'formType|required|string|min:2|max:10|name=相册分类', 124 | content: 'formContent|required|string|min:10|max:500|name=简要描述' 125 | }; 126 | 127 | module.exports = AlbumBiz; -------------------------------------------------------------------------------- /miniprogram/biz/base_biz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 基础模块业务逻辑 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | class BaseBiz { 8 | 9 | } 10 | 11 | module.exports = BaseBiz; -------------------------------------------------------------------------------- /miniprogram/biz/foot_biz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 足迹模块业务逻辑 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const BaseBiz = require('./base_biz.js'); 8 | const cacheHelper = require('../helper/cache_helper.js'); 9 | const helper = require('../helper/helper.js'); 10 | const bizHelper = require('../helper/biz_helper.js'); 11 | const CACHE_FOOT = 'CACHE_FOOT'; 12 | 13 | class FootBiz extends BaseBiz { 14 | 15 | static getFootList() { 16 | let foot = cacheHelper.get(CACHE_FOOT); 17 | if (foot) { 18 | for (let i = 0; i < foot.length; i++) { 19 | foot[i].time = helper.timestamp2Time(foot[i].time); 20 | 21 | switch (foot[i].type) { 22 | case bizHelper.TYPE.USER: 23 | foot[i].typeDesc = '同学'; 24 | foot[i].color = 'red'; 25 | break; 26 | case bizHelper.TYPE.INFO: 27 | foot[i].typeDesc = '互助'; 28 | foot[i].color = 'blue'; 29 | break; 30 | case bizHelper.TYPE.MEET: 31 | foot[i].typeDesc = '活动'; 32 | foot[i].color = 'green'; 33 | break; 34 | case bizHelper.TYPE.ALBUM: 35 | foot[i].typeDesc = '相册'; 36 | foot[i].color = 'yellow'; 37 | break; 38 | case bizHelper.TYPE.NEWS: 39 | foot[i].typeDesc = '资讯'; 40 | foot[i].color = 'pink'; 41 | break; 42 | } 43 | } 44 | } 45 | 46 | return foot; 47 | } 48 | 49 | /**添加足迹缓存 50 | * 51 | * @param {*} key 键 52 | * @param {*} val 值 53 | * 格式 key:{ 54 | * oid: 55 | * type:类型 56 | * title:标题 57 | * time:加入时间 58 | * } 59 | * @param {*} size 最大个数 60 | * @param {*} expire 过期时间 61 | */ 62 | static addFoot(oid, type, title, size = 60, expire = 86400 * 365 * 3) { 63 | if (!oid || !title) return []; 64 | 65 | let foot = cacheHelper.get(CACHE_FOOT, []); 66 | 67 | //查询是否存在 并删除 68 | for (let k in foot) { 69 | if (oid == foot[k].oid && type == foot[k].type) 70 | foot.splice(k, 1); 71 | } 72 | 73 | // 加到头部 74 | let val = { 75 | oid, 76 | type, 77 | title, 78 | time: helper.time() 79 | } 80 | foot.unshift(val); 81 | 82 | // 判断个数, 多的删除 83 | if (foot.length > size) 84 | foot.splice(foot.length - 1, 1); 85 | 86 | // 存缓存 87 | cacheHelper.set(CACHE_FOOT, foot, expire); 88 | 89 | return foot; 90 | } 91 | } 92 | 93 | module.exports = FootBiz; -------------------------------------------------------------------------------- /miniprogram/biz/info_biz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 资讯模块业务逻辑 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const BaseBiz = require('./base_biz.js'); 8 | const cloudHelper = require('../helper/cloud_helper.js'); 9 | const helper = require('../helper/helper.js'); 10 | const setting = require('../helper/setting.js'); 11 | 12 | class InfoBiz extends BaseBiz { 13 | 14 | 15 | /** 16 | * 表单初始化相关数据 17 | */ 18 | static initFormData(id = '') { 19 | 20 | return { 21 | id, 22 | 23 | // 分类 24 | typeOptions: InfoBiz.TYPE_OPTIONS, 25 | 26 | // 有效期 27 | expireStart: helper.time('Y-M-D'), 28 | expireEnd: helper.time('Y-M-D', setting.INFO_MAX_EXPIRE), 29 | 30 | // 图片数据 31 | imgMax: setting.INFO_MAX_PIC, 32 | imgList: [], 33 | 34 | 35 | // 表单数据 36 | formTypeIndex: 0, 37 | formTitle: '', 38 | formContent: '', 39 | formExpireTime: helper.time('Y-M-D'), 40 | formRegion: setting.INFO_DEFAULT_REGION 41 | } 42 | 43 | } 44 | 45 | /** 46 | * 图片上传 47 | * @param {string} infoId 48 | * @param {Array} imgList 图片数组 49 | */ 50 | static async updateInfoPic(infoId, imgList) { 51 | 52 | // 图片上传到云空间 53 | imgList = await cloudHelper.transTempPics(imgList, setting.INFO_PIC_DIR, infoId); 54 | 55 | // 更新本记录的图片信息 56 | let params = { 57 | infoId: infoId, 58 | imgList: imgList 59 | } 60 | 61 | try { 62 | // 更新数据 从promise 里直接同步返回 63 | let res = await cloudHelper.callCloudSumbit('info/update_pic', params); 64 | return res.data.urls; 65 | } catch (e) {} 66 | } 67 | 68 | /** 69 | * 搜索菜单设置 70 | */ 71 | static getSearchMenu() { 72 | 73 | let sortItem1 = [{ 74 | label: '综合排序', 75 | type: '', 76 | value: 0 77 | }]; 78 | 79 | // 分类 80 | let sortItem2 = [{ 81 | label: '所有分类', 82 | type: '', 83 | value: 0 84 | }]; 85 | for (let k in InfoBiz.TYPE_OPTIONS){ 86 | sortItem2.push( 87 | { 88 | label: InfoBiz.TYPE_OPTIONS[k], 89 | type: 'type', 90 | value: InfoBiz.TYPE_OPTIONS[k], 91 | } 92 | ) 93 | } 94 | 95 | let sortItems = [sortItem2]; 96 | let sortMenus = [{ 97 | label: '最新', 98 | type: 'sort', 99 | value: 'new' 100 | }, 101 | { 102 | label: '最热', 103 | type: 'sort', 104 | value: 'view' 105 | }, 106 | { 107 | label: '全部', 108 | type: '', 109 | value: '' 110 | } 111 | ] 112 | 113 | return { 114 | sortItems, 115 | sortMenus 116 | } 117 | 118 | } 119 | } 120 | /** 121 | * 分类 122 | */ 123 | InfoBiz.TYPE_OPTIONS = "资源合作,活动聚会,创业合作,招聘猎头,求职,企业推介,供应采购,商务合作,服务咨询,其他".split(','); 124 | 125 | //表单校验 126 | InfoBiz.CHECK_FORM = { 127 | title: 'formTitle|required|string|min:5|max:50|name=互助标题', 128 | type: 'formType|required|string|min:2|max:10|name=互助分类', 129 | expireTime: 'formExpireTime|required|date|name=有效期', 130 | region: 'formRegion|required|array|len:3|name=有效区域', 131 | content: 'formContent|required|string|min:10|max:50000|name=详细描述' 132 | }; 133 | 134 | module.exports = InfoBiz; -------------------------------------------------------------------------------- /miniprogram/biz/reg_biz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 注册模块业务逻辑 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const BaseBiz = require('./base_biz.js'); 8 | const cacheHelper = require('../helper/cache_helper.js'); 9 | const cloudHelper = require('../helper/cloud_helper.js'); 10 | const helper = require('../helper/helper.js'); 11 | const validate = require('../helper/validate.js'); 12 | const pageHelper = require('../helper/page_helper.js'); 13 | 14 | /** 15 | * 16 | */ 17 | class RegBiz extends BaseBiz { 18 | /** 19 | * 判断第一步是否完成 20 | */ 21 | static isStep1() { 22 | let cache = cacheHelper.get(RegBiz.CACHE_REG); 23 | if (!cache || !cache['phone']) 24 | return false; 25 | else 26 | return true; 27 | } 28 | 29 | /** 30 | * 判断第2步是否完成 31 | */ 32 | static isStep2() { 33 | let cache = cacheHelper.get(RegBiz.CACHE_REG); 34 | if (!cache || !cache['user']) 35 | return false; 36 | else 37 | return true; 38 | } 39 | 40 | static clearRegCache() { 41 | cacheHelper.remove(RegBiz.CACHE_REG); 42 | } 43 | 44 | /** 45 | * 保存已授权或者填写的信息 phone=电话 user=微信资料 form=填写的表单 invite=邀请信息 46 | * @param {*} key 47 | * @param {*} val 48 | */ 49 | static setRegCache(key, val) { 50 | let cache = cacheHelper.get(RegBiz.CACHE_REG); 51 | if (!cache) cache = {}; 52 | cache[key] = val; 53 | cacheHelper.set(RegBiz.CACHE_REG, cache, 3600 * 30); 54 | } 55 | 56 | /** 57 | * 获取授权或者填写的信息 58 | * @param {*} key 59 | */ 60 | static getRegCache(key) { 61 | let cache = cacheHelper.get(RegBiz.CACHE_REG); 62 | if (cache && cache[key]) return cache[key]; 63 | return null; 64 | } 65 | 66 | /** 67 | * 邀请判断 68 | * @param {*} options 69 | */ 70 | static async checkInvite(options) { 71 | 72 | // 判断参数 73 | let code = options.code; 74 | 75 | if (options && options.scene) { 76 | code = options.scene; 77 | } 78 | if (!validate.isCheckId(code, 15, 20)) return; 79 | 80 | RegBiz.setRegCache('invite', { 81 | code 82 | }); 83 | } 84 | 85 | /** 86 | * 注册第二步 87 | * @param {*} e 88 | */ 89 | static async registerStep2(e) { 90 | if (e.detail.errMsg == "getUserInfo:ok") { 91 | let userInfo = e.detail.userInfo; 92 | if (!helper.isDefined(userInfo) || !userInfo) 93 | wx.showToast({ 94 | title: '授权失败,请重新授权', 95 | icon: 'none', 96 | duration: 4000 97 | }); 98 | else { 99 | 100 | // 存储 用户信息 101 | RegBiz.setRegCache('user', userInfo); 102 | wx.navigateTo({ 103 | url: 'reg_step3', 104 | }) 105 | } 106 | } else 107 | wx.showToast({ 108 | title: '授权失败,请重新授权', 109 | icon: 'none' 110 | }); 111 | } 112 | 113 | /** 114 | * 注册第一步 115 | * @param {*} e 116 | */ 117 | static async registerStep1(e) { 118 | if (e.detail.errMsg == "getPhoneNumber:ok") { 119 | let cloudID = e.detail.cloudID; 120 | let params = { 121 | cloudID 122 | }; 123 | let opt = { 124 | title: '验证中' 125 | }; 126 | let phone = await cloudHelper.callCloudData('passport/phone', params, opt); 127 | if (!phone || phone.length < 11) 128 | wx.showToast({ 129 | title: '手机号码获取失败,请重新绑定手机号码', 130 | icon: 'none', 131 | duration: 4000 132 | }); 133 | else { 134 | // 存储 手机号码 135 | RegBiz.setRegCache('phone', phone); 136 | // 判断是否手机授权 137 | 138 | wx.navigateTo({ 139 | url: 'reg_step2', 140 | }) 141 | } 142 | } else 143 | wx.showToast({ 144 | title: '手机号码获取失败,请重启绑定手机号码', 145 | icon: 'none' 146 | }); 147 | 148 | } 149 | } 150 | RegBiz.CACHE_REG = 'CACHE_REG_INFO'; 151 | 152 | module.exports = RegBiz; -------------------------------------------------------------------------------- /miniprogram/biz/search_biz.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 搜索模块业务逻辑 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const BaseBiz = require('./base_biz.js'); 8 | const cacheHelper = require('../helper/cache_helper.js'); 9 | 10 | /** 11 | * 12 | */ 13 | class SearchBiz extends BaseBiz { 14 | 15 | static clearHistory(key){ 16 | cacheHelper.remove(key); 17 | } 18 | 19 | static getHistory(key) 20 | { 21 | return cacheHelper.get(key, []); 22 | 23 | } 24 | 25 | /**添加关键字缓存 26 | * 27 | * @param {*} key 28 | * @param {*} val 29 | * @param {*} size 个数 30 | * @param {*} expire 过期时间 31 | */ 32 | static addHistory(key, val, size = 20, expire = 86400 * 30) { 33 | if (!val || val.length == 0) return []; 34 | 35 | let his = cacheHelper.get(key, []); 36 | 37 | //查询是否存在 并删除 38 | let pos = his.indexOf(val); 39 | if (pos > -1) his.splice(pos, 1); 40 | 41 | // 加到头部 42 | his.unshift(val); 43 | 44 | // 判断个数, 多的删除 45 | if (his.length > size) 46 | his.splice(his.length - 1, 1); 47 | 48 | // 存缓存 49 | cacheHelper.set(key, his, expire); 50 | 51 | return his; 52 | } 53 | 54 | } 55 | 56 | module.exports = SearchBiz; -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/index/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true 3 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/index/index.wxss: -------------------------------------------------------------------------------- 1 | .canvas { 2 | width: 750rpx; 3 | height: 750rpx; 4 | } 5 | .canvas.pro { 6 | position: absolute; 7 | bottom: 0; 8 | left: 0; 9 | transform: translate3d(-9999rpx, 0, 0); 10 | } 11 | .canvas.debug { 12 | position: absolute; 13 | bottom: 0; 14 | left: 0; 15 | border: 1rpx solid #ccc; 16 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/poster/index.js: -------------------------------------------------------------------------------- 1 | Component({ 2 | properties: { 3 | config: { 4 | type: Object, 5 | value: {}, 6 | }, 7 | preload: { // 是否预下载图片资源 8 | type: Boolean, 9 | value: false, 10 | }, 11 | hideLoading: { // 是否隐藏loading 12 | type: Boolean, 13 | value: false, 14 | } 15 | }, 16 | ready() { 17 | if (this.data.preload) { 18 | const poster = this.selectComponent('#poster'); 19 | this.downloadStatus = 'doing'; 20 | poster.downloadResource(this.data.config).then(() => { 21 | this.downloadStatus = 'success'; 22 | this.trigger('downloadSuccess'); 23 | }).catch((e) => { 24 | this.downloadStatus = 'fail'; 25 | this.trigger('downloadFail', e); 26 | }); 27 | } 28 | }, 29 | methods: { 30 | trigger(event, data) { 31 | if (this.listener && typeof this.listener[event] === 'function') { 32 | this.listener[event](data); 33 | } 34 | }, 35 | once(event, fun) { 36 | if (typeof this.listener === 'undefined') { 37 | this.listener = {}; 38 | } 39 | this.listener[event] = fun; 40 | }, 41 | downloadResource(reset) { 42 | return new Promise((resolve, reject) => { 43 | if (reset) { 44 | this.downloadStatus = null; 45 | } 46 | const poster = this.selectComponent('#poster'); 47 | if (this.downloadStatus && this.downloadStatus !== 'fail') { 48 | if (this.downloadStatus === 'success') { 49 | resolve(); 50 | } else { 51 | this.once('downloadSuccess', () => resolve()); 52 | this.once('downloadFail', (e) => reject(e)); 53 | } 54 | } else { 55 | poster.downloadResource(this.data.config) 56 | .then(() => { 57 | this.downloadStatus = 'success'; 58 | resolve(); 59 | }) 60 | .catch((e) => reject(e)); 61 | } 62 | }) 63 | }, 64 | onCreate(reset = false) { 65 | !this.data.hideLoading && wx.showLoading({ mask: true, title: '生成中' }); 66 | return this.downloadResource(typeof reset === 'boolean' && reset).then(() => { 67 | !this.data.hideLoading && wx.hideLoading(); 68 | const poster = this.selectComponent('#poster'); 69 | poster.create(this.data.config); 70 | }) 71 | .catch((err) => { 72 | !this.data.hideLoading && wx.hideLoading(); 73 | wx.showToast({ icon: 'none', title: err.errMsg || '生成失败' }); 74 | console.error(err); 75 | this.triggerEvent('fail', err); 76 | }) 77 | }, 78 | onCreateSuccess(e) { 79 | const { detail } = e; 80 | this.triggerEvent('success', detail); 81 | }, 82 | onCreateFail(err) { 83 | console.error(err); 84 | this.triggerEvent('fail', err); 85 | } 86 | } 87 | }) -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/poster/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": { 4 | "we-canvas": "../index/index" 5 | } 6 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/poster/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/poster/index.wxss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/cmpts/lib/wxa-plugin-canvas/poster/index.wxss -------------------------------------------------------------------------------- /miniprogram/cmpts/lib/wxa-plugin-canvas/poster/poster.js: -------------------------------------------------------------------------------- 1 | const defaultOptions = { 2 | selector: '#poster' 3 | }; 4 | 5 | function Poster(options = {}, that) { 6 | options = { 7 | ...defaultOptions, 8 | ...options, 9 | }; 10 | 11 | const pages = getCurrentPages(); 12 | let ctx = pages[pages.length - 1]; 13 | if (that) ctx = that 14 | const poster = ctx.selectComponent(options.selector); 15 | delete options.selector; 16 | 17 | return poster; 18 | }; 19 | 20 | Poster.create = (reset = false, that) => { 21 | const poster = Poster({}, that); 22 | if (!poster) { 23 | console.error('请设置组件的id="poster"!!!'); 24 | } else { 25 | return Poster({}, that).onCreate(reset); 26 | } 27 | } 28 | 29 | export default Poster; 30 | -------------------------------------------------------------------------------- /miniprogram/cmpts/public/img/img_upload_cmpt.js: -------------------------------------------------------------------------------- 1 | const pageHelper = require('../../../helper/page_helper.js'); 2 | const cloudHelper = require('../../../helper/cloud_helper.js'); 3 | const contentCheckHelper = require('../../../helper/content_check_helper.js'); 4 | const setting = require('../../../helper/setting.js'); 5 | 6 | Component({ 7 | /** 8 | * 组件的属性列表 9 | */ 10 | properties: { 11 | imgList: { 12 | type: Array, 13 | value: [] 14 | 15 | }, 16 | imgMax: { 17 | type: Number, 18 | value: 4, 19 | }, 20 | title: { 21 | type: String, 22 | value: '图片上传', 23 | }, 24 | isCheck:{ //是否做图片内容校验 25 | type: Boolean, 26 | value: true, 27 | }, 28 | imgUploadSize:{ //图片最大大小 29 | type: Number, 30 | value: setting.IMG_UPLOAD_SIZE, 31 | } 32 | }, 33 | 34 | /** 35 | * 组件的初始数据 36 | */ 37 | data: { 38 | //imgList:[] 39 | }, 40 | 41 | 42 | /** 43 | * 生命周期方法 44 | */ 45 | lifetimes: { 46 | attached: function () { 47 | 48 | }, 49 | 50 | ready: function () { 51 | 52 | }, 53 | detached: function () { 54 | // 在组件实例被从页面节点树移除时执行 55 | }, 56 | }, 57 | 58 | /** 59 | * 组件的方法列表 60 | */ 61 | methods: { 62 | /** 63 | * 选择上传图片 64 | */ 65 | bindChooseImgTap: function (e) { 66 | wx.chooseImage({ 67 | count: this.data.imgMax - this.data.imgList.length, //默认9 68 | sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有 69 | sourceType: ['album', 'camera'], //从相册选择 70 | success: async (res) => { 71 | wx.showLoading({ 72 | title: '图片校验中', 73 | mask: true 74 | }); 75 | 76 | for (let k = 0; k < res.tempFiles.length; k++) { 77 | let size = res.tempFiles[k].size; 78 | let path = res.tempFiles[k].path; 79 | console.log('size=' + size + ',path=' + path) 80 | if (!contentCheckHelper.imgTypeCheck(path)) { 81 | wx.hideLoading(); 82 | return pageHelper.showNoneToast('只能上传png、jpg、jpep格式', 3000); 83 | } 84 | 85 | let imageMaxSize = 1024 * 1000 * this.data.imgUploadSize; 86 | if (!contentCheckHelper.imgSizeCheck(size, imageMaxSize)) { 87 | wx.hideLoading(); 88 | return pageHelper.showNoneToast('单张图片大小不能超过 ' + this.data.imgUploadSize + 'M', 3000); 89 | } 90 | 91 | 92 | // 读取文件流,云校验 93 | //let imgData = wx.getFileSystemManager().readFileSync(path, 'base64'); 94 | 95 | //console.log('imgData size=' + imgData.length); 96 | 97 | if (this.data.isCheck){ 98 | let check = await contentCheckHelper.imgCheck(path); 99 | if (!check) { 100 | wx.hideLoading(); 101 | return pageHelper.showNoneToast('存在不合适的图片, 已屏蔽', 3000); 102 | } 103 | } 104 | 105 | 106 | this.setData({ 107 | imgList: this.data.imgList.concat(path) 108 | }); 109 | this.triggerEvent('myImgUploadEvent', this.data.imgList); 110 | 111 | } 112 | 113 | wx.hideLoading(); 114 | } 115 | }); 116 | }, 117 | 118 | bindPreviewImgTap: function (e) { 119 | wx.previewImage({ 120 | urls: this.data.imgList, 121 | current: e.currentTarget.dataset.url 122 | }); 123 | }, 124 | 125 | /** 126 | * 删除图片 127 | */ 128 | catchDelImgTap: function (e) { 129 | let that = this; 130 | let callback = function () { 131 | that.data.imgList.splice(e.currentTarget.dataset.index, 1); 132 | that.setData({ 133 | imgList: that.data.imgList 134 | }); 135 | that.triggerEvent('myImgUploadEvent', that.data.imgList); 136 | } 137 | pageHelper.showConfirm('确定要删除该图片吗?', callback); 138 | }, 139 | 140 | } 141 | }) -------------------------------------------------------------------------------- /miniprogram/cmpts/public/img/img_upload_cmpt.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/public/img/img_upload_cmpt.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{title}} (每张大小不超过{{imgUploadSize}}M) 4 | 5 | 6 | {{imgList.length}}/{{imgMax}} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /miniprogram/cmpts/public/img/img_upload_cmpt.wxss: -------------------------------------------------------------------------------- 1 | @import "../../../style/comm/comm.wxss"; 2 | @import "../../../style/project/project.wxss"; 3 | 4 | @import "../../../style/skin.wxss"; 5 | 6 | -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/comm_list_cmpt.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/comm_list_cmpt.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{ index==sortIndex && item.items[sortItemIndex] ? item.items[sortItemIndex].label: item.items[0].label}} 20 | 21 | 22 | 23 | 24 | 25 | 26 | {{item.label}} 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {{its.label}} 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/comm_list_cmpt.wxss: -------------------------------------------------------------------------------- 1 | @import "../../../style/comm/comm.wxss"; 2 | @import "../../../style/project/project.wxss"; 3 | 4 | @import "../../../style/skin.wxss"; 5 | 6 | 7 | 8 | 9 | /*sort*/ 10 | .tabs { 11 | display: flex; 12 | font-size: 28rpx; 13 | color: #aaa; 14 | height: 80rpx; 15 | line-height: 80rpx; 16 | } 17 | 18 | .tabs .tab { 19 | flex-grow: 1; 20 | text-align: center; 21 | position: relative; 22 | } 23 | 24 | .tabs .cur{ 25 | font-weight:bold; 26 | } 27 | 28 | .tabs .tab-menu.cur:after{ 29 | content: " "; 30 | position: absolute; 31 | left: 0; 32 | bottom: 0rpx; 33 | width: 100%; 34 | height: 4rpx; 35 | background-color: #0E9489; 36 | } 37 | 38 | .tabs .icon { 39 | color: #000; 40 | } 41 | 42 | 43 | .sort { 44 | position: absolute; 45 | top: 178rpx; 46 | bottom: 0; 47 | width: 100%; 48 | background-color: rgba(188, 188, 188, 0.3); 49 | z-index: 999; 50 | } 51 | 52 | .sort .sort-item { 53 | border-top: 1px solid #eee; 54 | height: 80rpx; 55 | line-height: 80rpx; 56 | padding-left: 50rpx; 57 | background-color: #fff; 58 | } 59 | 60 | 61 | /**头部*/ 62 | .top_bar { 63 | width: 100%; 64 | } 65 | 66 | .top_bar_scroll { 67 | position: fixed; 68 | top: 0rpx; 69 | left: 0; 70 | z-index: 99; 71 | background: #fff; 72 | 73 | z-index: 999; 74 | } 75 | 76 | 77 | .box-list { 78 | display: flex; 79 | flex-direction: column; 80 | height: 100vh; 81 | overflow: hidden; 82 | } 83 | 84 | .box-list-scroll { 85 | flex: 1; 86 | height: 1px; 87 | } 88 | 89 | 90 | .top-button{ 91 | position: fixed; 92 | bottom: 50rpx; 93 | right: 30rpx; 94 | opacity: .8 ; 95 | } 96 | 97 | .list-scroll-view{ 98 | display: inline-block; 99 | padding: 0 10rpx; 100 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/simple_list_cmpt.js: -------------------------------------------------------------------------------- 1 | const cloudHelper = require('../../../helper/cloud_helper.js'); 2 | const bizHelper = require('../../../helper/biz_helper.js'); 3 | const pageHelper = require('../../../helper/page_helper.js'); 4 | const helper = require('../../../helper/helper.js'); 5 | const PassportBiz = require('../../../biz/passport_biz.js'); 6 | 7 | Component({ 8 | options: { 9 | //pureDataPattern: /^_dataList/, // 指定所有 _ 开头的数据字段为纯数据字段 10 | multipleSlots: true // 在组件定义时的选项中启用多slot支持 11 | }, 12 | 13 | /** 14 | * 组件的属性列表 15 | */ 16 | properties: { 17 | router: { // 业务路由 18 | type: String, 19 | value: '' 20 | }, 21 | _params: { //路由的附加参数 22 | type: Object, 23 | value: {} 24 | }, 25 | _dataList: { 26 | type: Object, 27 | value: null 28 | }, 29 | type: { 30 | type: String, //业务类型 info,user,well 31 | value: '' 32 | }, 33 | 34 | whereEx: { 35 | type: Object, // 附加查询条件 36 | value: null, 37 | }, 38 | 39 | topBottom: { 40 | type: String, // 回顶部按钮的位置 41 | value: '50' 42 | }, 43 | 44 | isCache: { 45 | type: Boolean, //是否cache 46 | value: true 47 | }, 48 | skin: { 49 | type: String, // 皮肤 50 | value: '' 51 | }, 52 | isLoad: { 53 | type: Boolean, //数据加载中 54 | value: false 55 | }, 56 | dataNoHint: { 57 | type: String, //无数据提示 58 | value: '暂无数据' 59 | }, 60 | }, 61 | 62 | /** 63 | * 组件的初始数据 64 | */ 65 | data: { 66 | refresherTriggered: false, //下拉刷新是否完成 67 | 68 | topNum: 0, //回顶部 69 | topShow: false, 70 | }, 71 | 72 | lifetimes: { 73 | created: function () { 74 | // 组件实例化,但节点树还未导入,因此这时不能用setData 75 | }, 76 | attached: function () { 77 | // 在组件实例进入页面节点树时执行 78 | // 节点树完成,可以用setData渲染节点,但无法操作节点 79 | }, 80 | ready: async function () { 81 | PassportBiz.initPage(this); 82 | 83 | // 组件布局完成,这时可以获取节点信息,也可以操作节点 84 | await this._getList(1); 85 | }, 86 | move: function () { 87 | // 组件实例被移动到树的另一个位置 88 | }, 89 | detached: function () { 90 | // 在组件实例被从页面节点树移除时执行 91 | }, 92 | }, 93 | 94 | pageLifetimes: { 95 | async show() { 96 | // 页面被展示 97 | if (!this.data.isCache || !bizHelper.isCacheList(this.data.type)) 98 | await this._getList(1); 99 | }, 100 | hide() { 101 | // 页面被隐藏 102 | }, 103 | resize(size) { 104 | // 页面尺寸变化 105 | } 106 | }, 107 | 108 | /** 109 | * 组件的方法列表 110 | */ 111 | methods: { 112 | reload: async function () { 113 | await this._getList(1); 114 | }, 115 | // 数据列表 116 | _getList: async function (page) { 117 | 118 | let params = { 119 | page: page, 120 | ...this.data._params 121 | }; 122 | if (this.data.whereEx) params.whereEx = this.data.whereEx; 123 | 124 | if (page == 1 && !this.data._dataList) { 125 | this.triggerEvent('myCommListEvent', { 126 | dataList: null //第一页面且没有数据提示加载中 127 | }); 128 | } 129 | 130 | 131 | let opt = {}; 132 | //if (this.data._dataList && this.data._dataList.list && this.data._dataList.list.length > 0) 133 | opt.title = 'bar'; 134 | await cloudHelper.dataList(this, '_dataList', this.data.router, params, opt); 135 | 136 | this.triggerEvent('myCommListEvent', { //TODO 考虑改为双向数据绑定model 137 | dataList: this.data._dataList 138 | }); 139 | 140 | if (this.data.isCache) 141 | bizHelper.setCacheList(this.data.type); 142 | }, 143 | 144 | bindReachBottom: async function () { 145 | // 上拉触底 146 | this.setData({ 147 | isLoad: true 148 | }); 149 | await this._getList(this.data._dataList.page + 1); 150 | this.setData({ 151 | isLoad: false 152 | }); 153 | }, 154 | 155 | } 156 | }) -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/simple_list_cmpt.json: -------------------------------------------------------------------------------- 1 | { 2 | "component": true, 3 | "usingComponents": {} 4 | } -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/simple_list_cmpt.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 点击查看更多... 6 | 7 | 10 | 11 | 13 | 14 | {{dataNoHint}} 15 | 16 | -------------------------------------------------------------------------------- /miniprogram/cmpts/public/list/simple_list_cmpt.wxss: -------------------------------------------------------------------------------- 1 | @import "../../../style/comm/comm.wxss"; 2 | @import "../../../style/project/project.wxss"; 3 | 4 | @import "../../../style/skin.wxss"; 5 | 6 | 7 | 8 | /**头部*/ 9 | .top_bar { 10 | width: 100%; 11 | } 12 | 13 | .top_bar_scroll { 14 | position: fixed; 15 | top: 0rpx; 16 | left: 0; 17 | z-index: 99; 18 | background: #fff; 19 | 20 | z-index: 999; 21 | } 22 | 23 | 24 | .box-list { 25 | display: flex; 26 | flex-direction: column; 27 | flex: 1; 28 | overflow: hidden; 29 | } 30 | 31 | .box-list-scroll { 32 | flex: 1; 33 | height: 1px; 34 | } 35 | 36 | 37 | .top-button{ 38 | position: fixed; 39 | bottom: 50rpx; 40 | right: 30rpx; 41 | opacity: .8 ; 42 | } 43 | 44 | .list-scroll-view{ 45 | display: inline-block; 46 | padding: 0 10rpx; 47 | } -------------------------------------------------------------------------------- /miniprogram/helper/biz_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 业务通用 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const cacheHelper = require('./cache_helper.js'); 8 | const setting = require('./setting.js'); 9 | 10 | const TYPE = { 11 | //类型 0=用户,1=互助,2=活动 3=相册 4=资讯 5=接龙 12 | USER: 0, 13 | INFO: 1, 14 | MEET: 2, 15 | ALBUM: 3, 16 | NEWS: 4, 17 | GROUP: 5 18 | } 19 | 20 | 21 | 22 | function getSkin(skin) { 23 | for (let k in SKIN) { 24 | if (SKIN[k].def == skin) 25 | return SKIN[k]; 26 | } 27 | } 28 | 29 | function getType(type) { 30 | let ret = 0; 31 | switch (type) { 32 | case 'user': 33 | ret = 0; 34 | break; 35 | case 'info': 36 | ret = 1; 37 | break; 38 | case 'meet': 39 | ret = 2; 40 | break; 41 | case 'album': 42 | ret = 3; 43 | break; 44 | case 'news': 45 | ret = 4; 46 | break; 47 | } 48 | return ret; 49 | } 50 | 51 | function isCacheList(key) { 52 | key = key.toUpperCase(); 53 | if (setting.CACHE_IS_LIST) 54 | return cacheHelper.get(key + '_LIST'); 55 | else 56 | return false; 57 | } 58 | 59 | function removeCacheList(key) { 60 | key = key.toUpperCase(); 61 | if (setting.CACHE_IS_LIST) 62 | cacheHelper.remove(key + '_LIST'); 63 | } 64 | 65 | function setCacheList(key, time = setting.CACHE_LIST_TIME) { 66 | key = key.toUpperCase(); 67 | if (setting.CACHE_IS_LIST) 68 | cacheHelper.set(key + '_LIST', 'TRUE', time); 69 | } 70 | 71 | 72 | module.exports = { 73 | isCacheList, 74 | removeCacheList, 75 | setCacheList, 76 | TYPE, 77 | getType, 78 | getSkin 79 | } -------------------------------------------------------------------------------- /miniprogram/helper/cache_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 微信缓存二次封装,有设置时效性的封装 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const TIME_SUFFIX = "_deadtime" 8 | 9 | /** 10 | * 设置 11 | * k 键key 12 | * v 值value 13 | * t 秒 14 | */ 15 | function set(k, v, t = 86400 * 30) { 16 | if (!k) return null; 17 | 18 | wx.setStorageSync(k, v); 19 | let seconds = parseInt(t); 20 | if (seconds > 0) { 21 | let newtime = Date.parse(new Date()); 22 | newtime = newtime / 1000 + seconds; 23 | wx.setStorageSync(k + TIME_SUFFIX, newtime + ""); 24 | } else { 25 | wx.removeStorageSync(k + TIME_SUFFIX); 26 | } 27 | } 28 | 29 | 30 | /** 31 | * 获取 32 | * k 键key 33 | * def 默认值 34 | */ 35 | function get(k, def = null) { 36 | if (!k) return null; 37 | 38 | let deadtime = parseInt(wx.getStorageSync(k + TIME_SUFFIX)); 39 | 40 | if (deadtime) { 41 | if (parseInt(deadtime) < Date.parse(new Date()) / 1000) { 42 | wx.removeStorageSync(k); 43 | wx.removeStorageSync(k + TIME_SUFFIX); 44 | return def; 45 | } 46 | } 47 | 48 | let res = wx.getStorageSync(k); 49 | if (res) { 50 | return res; 51 | } else { 52 | return def; 53 | } 54 | } 55 | 56 | /** 57 | * 删除 58 | */ 59 | function remove(k) { 60 | if (!k) return null; 61 | 62 | wx.removeStorageSync(k); 63 | wx.removeStorageSync(k + TIME_SUFFIX); 64 | } 65 | 66 | /** 67 | * 清除所有key 68 | */ 69 | function clear() { 70 | wx.clearStorageSync(); 71 | } 72 | 73 | module.exports = { 74 | set, 75 | get, 76 | remove, 77 | clear 78 | } -------------------------------------------------------------------------------- /miniprogram/helper/comm.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: 通用常量 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | module.exports = { 8 | CACHE_TOKEN: 'CACHE_TOKEN', // 登录 9 | CACHE_ADMIN: 'ADMIN_TOKEN', // 管理员登录 10 | } -------------------------------------------------------------------------------- /miniprogram/helper/content_check_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Notes: UGC内容校验 3 | * Ver : CCMiniCloud Framework 2.0.1 ALL RIGHTS RESERVED BY www.code942.com 4 | * Date: 2020-11-14 07:48:00 5 | */ 6 | 7 | const cloudHelper = require('../helper/cloud_helper.js'); 8 | const setting = require('../helper/setting.js'); 9 | 10 | /** 11 | * 图片类型校验 12 | * @param {*} fileName 13 | * @param {*} type 14 | */ 15 | function imgTypeCheck(path, type = ['jpg', 'jpeg', 'png']) { 16 | let fmt = path.split(".")[(path.split(".")).length - 1]; 17 | if (type.indexOf(fmt) > -1) 18 | return true; 19 | else 20 | return false; 21 | } 22 | 23 | /** 24 | * 图片大小校验 25 | * @param {*} size 26 | * @param {*} maxSize 27 | */ 28 | function imgSizeCheck(size, maxSize) { 29 | return size < maxSize; 30 | } 31 | 32 | async function imgCheckCloud(path, opt) { 33 | 34 | 35 | /* 36 | let result = await cloudHelper.callCloudSumbit('check/img', params, opt).then(res => { 37 | return true; 38 | }).catch(err => { 39 | return false; 40 | }); 41 | */ 42 | 43 | let result = await wx.cloud.callFunction({ 44 | name: 'cloud', 45 | data: { 46 | router: 'check/img', 47 | token : '', 48 | params:{img: wx.cloud.CDN( { 49 | type: 'filePath', 50 | filePath: path, 51 | }) 52 | } 53 | }, 54 | success: function (res) { 55 | console.log(res) 56 | console.log('scc') 57 | return true; 58 | }, 59 | fail: function (res) { 60 | console.log(res) 61 | return false; 62 | }, 63 | complete: function (res) { 64 | 65 | } 66 | }); 67 | return result; 68 | } 69 | 70 | /** 71 | * 图像校验 72 | * @param {*} imgData 73 | */ 74 | async function imgCheck(imgData) { 75 | if (!setting.CHECK_CONTENT) return true; 76 | 77 | let result = await wx.serviceMarket.invokeService({ 78 | service: 'wxee446d7507c68b11', 79 | api: 'imgSecCheck', 80 | data: { 81 | "Action": "ImageModeration", 82 | "Scenes": ["PORN", "POLITICS", "TERRORISM"], 83 | "ImageUrl": new wx.serviceMarket.CDN({ 84 | type: 'filePath', 85 | filePath: imgData, 86 | }), 87 | "ImageBase64": '', 88 | "Config": "", 89 | "Extra": "" 90 | }, 91 | }).then(res => { 92 | if (res && res.data && res.data.Response && 93 | res.data.Response.PornResult && res.data.Response.PornResult.Suggestion === 'PASS' && 94 | res.data.Response.PoliticsResult && res.data.Response.PoliticsResult.Suggestion === 'PASS' && 95 | res.data.Response.TerrorismResult && res.data.Response.TerrorismResult.Suggestion === 'PASS') 96 | return true; 97 | else 98 | return false; 99 | }).catch(err => { 100 | console.log(err); 101 | return false; 102 | }); 103 | 104 | return result; 105 | } 106 | 107 | 108 | module.exports = { 109 | imgCheck, 110 | imgCheckCloud, 111 | imgTypeCheck, 112 | imgSizeCheck 113 | } -------------------------------------------------------------------------------- /miniprogram/helper/setting.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | CLOUD_ID: 'xxx', // 云环境ID 3 | 4 | CHECK_CONTENT: true, //图片文字是否校验 5 | 6 | 7 | TEST_MODE: false, 8 | 9 | SKIN: 'skin1', //皮肤 10 | 11 | TEST_USER_ID: 'oYyk-5Q4WyAc0DWnqt2x89kfR_y0', 12 | TEST_TOKEN: { 13 | id: 'aa133ce55f4048a400124d2b38b64f60', 14 | name: '刘敏', 15 | pic: '', 16 | status: 1, 17 | type: 1 18 | }, 19 | 20 | VER: 'CC校友录Free', 21 | 22 | IMG_UPLOAD_SIZE: 2, //图片上传大小M兆 23 | 24 | IS_OPEN_COMMENT: true, //是否开启评论 25 | 26 | PASSPORT_TOKEN_EXPIRE: 86400, //登录有效时间 秒 27 | 28 | ADMIN_TOKEN_EXPIRE: 3600 * 2, //管理员过期时间2小时有效 秒 29 | 30 | CACHE_IS_LIST: true, //列表是否缓存 31 | CACHE_LIST_TIME: 60 * 30, //列表缓存时间秒 32 | 33 | CHAT_IS_WATCH: true, // 开启聊天观察者监控 34 | 35 | TABBAR_IS_GUEST: true, //是否开启tabbar可游客访问 36 | 37 | 38 | USER_PIC_DIR: 'client/user/pic/', //用户头像图片目录 39 | 40 | AD_PIC_DIR: 'client/ad/pic/', //海报底图图片目录 41 | AD_MAX_PIC: 8, //海报底图上限 42 | 43 | SCHOOL_PIC_DIR: 'client/school/pic/', //校园底图 44 | 45 | INFO_PIC_DIR: 'client/info/pic/', //互助图片目录 46 | INFO_MAX_EXPIRE: 86400 * 60, //互助有效期 秒 47 | INFO_DEFAULT_REGION: ['广东省', '广州市', '越秀区'], //默认区域 48 | INFO_MAX_PIC: 8, //互助图片上限 49 | 50 | MEET_PIC_DIR: 'client/info/pic/', //活动图片目录 51 | MEET_DEFAULT_REGION: ['广东省', '广州市', '越秀区'], //默认区域 52 | MEET_MAX_PIC: 8, //活动图片上限 53 | 54 | ALBUM_PIC_DIR: 'client/album/pic/', //活动图片目录 55 | ALBUM_MAX_PIC: 8, //活动图片上限 56 | 57 | NEWS_PIC_DIR: 'client/news/pic/', //资讯图片目录 58 | NEWS_MAX_PIC: 8, //资讯图片上限 59 | 60 | HOME_CACHE_TIME: 60 * 5, //秒 61 | 62 | CACHE_SETUP: 3600 * 10, //系统全局配置缓存时间 秒 63 | 64 | } -------------------------------------------------------------------------------- /miniprogram/images/group/logo0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/group/logo0.png -------------------------------------------------------------------------------- /miniprogram/images/group/logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/group/logo1.png -------------------------------------------------------------------------------- /miniprogram/images/group/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/group/logo2.png -------------------------------------------------------------------------------- /miniprogram/images/group/logo3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/group/logo3.png -------------------------------------------------------------------------------- /miniprogram/images/main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/main.jpg -------------------------------------------------------------------------------- /miniprogram/images/tabbar/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/home.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/home_cur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/home_cur.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/info.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/info_cur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/info_cur.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/meet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/meet.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/meet_cur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/meet_cur.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/my.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/my.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/my_cur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/my_cur.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/user.png -------------------------------------------------------------------------------- /miniprogram/images/tabbar/user_cur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yixuandouyin/tjuclassmate/c9472addef33404bbd78af571e54faf1ab4333aa/miniprogram/images/tabbar/user_cur.png -------------------------------------------------------------------------------- /miniprogram/lib/we-cropper/we-cropper.wxml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /miniprogram/pages/about/about.js: -------------------------------------------------------------------------------- 1 | const cloudHelper = require('../../helper/cloud_helper.js'); 2 | const helper = require('../../helper/helper.js'); 3 | const bizHelper = require('../../helper/biz_helper.js'); 4 | const pageHelper = require('../../helper/page_helper.js'); 5 | const PassportBiz = require('../../biz/passport_biz.js'); 6 | 7 | Page({ 8 | 9 | /** 10 | * 页面的初始数据 11 | */ 12 | data: { 13 | isLoad: false 14 | }, 15 | 16 | /** 17 | * 生命周期函数--监听页面加载 18 | */ 19 | onLoad: function (options) { 20 | PassportBiz.initPage(this); 21 | 22 | }, 23 | 24 | /** 25 | * 生命周期函数--监听页面初次渲染完成 26 | */ 27 | onReady: function () { 28 | 29 | }, 30 | 31 | /** 32 | * 生命周期函数--监听页面显示 33 | */ 34 | onShow: function () { 35 | 36 | }, 37 | 38 | /** 39 | * 生命周期函数--监听页面隐藏 40 | */ 41 | onHide: function () { 42 | 43 | }, 44 | 45 | /** 46 | * 生命周期函数--监听页面卸载 47 | */ 48 | onUnload: function () { 49 | 50 | }, 51 | 52 | /** 53 | * 页面相关事件处理函数--监听用户下拉动作 54 | */ 55 | onPullDownRefresh: function () { 56 | this._loadDetail(); 57 | wx.stopPullDownRefresh(); 58 | }, 59 | 60 | 61 | /** 62 | * 用户点击右上角分享 63 | */ 64 | onShareAppMessage: function () { 65 | 66 | }, 67 | 68 | url: function (e) { 69 | pageHelper.url(e, this); 70 | } 71 | }) -------------------------------------------------------------------------------- /miniprogram/pages/about/about.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | 4 | }, 5 | "enablePullDownRefresh": true, 6 | "navigationBarTitleText": "关于我们" 7 | } -------------------------------------------------------------------------------- /miniprogram/pages/about/about.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 关于CC校友录Free版 5 | 6 | CC校友录小程序 是一个采用微信小程序和腾讯云开发技术构建的高效校友录解决方案。 7 | 8 | 使用腾讯云开发技术,免费资源配额,无需域名和服务器即可搭建. 9 | 10 | 小程序在微信里打开,无须下载app,也无须再访问传统的PC站点,随时随地可以和互动. 11 | 12 | 13 | 14 | 15 | 作者主页: http://www.code942.com 16 | 作者微信: cclinux0730 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 关于我们 27 | | 28 | 29 | 30 | Copyright © {{setup.SETUP_TITLE}} 版权所有 31 | {{setup.ver}} 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /miniprogram/pages/about/about.wxss: -------------------------------------------------------------------------------- 1 | .main-about{ 2 | padding:40rpx; 3 | height:100vh; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: flex-start; 7 | } 8 | 9 | .main-about .main-content{ 10 | width:100%; 11 | flex: 1; 12 | } 13 | 14 | .main-about .content{ 15 | width:100%; 16 | background-color: #fff; 17 | padding:50rpx; 18 | border-radius: 20rpx; 19 | margin-top:15rpx; 20 | } 21 | 22 | .main-about .content .title{ 23 | width:100%; 24 | text-align: center; 25 | font-size:36rpx; 26 | line-height: 1.8; 27 | margin-bottom: 30rpx; 28 | } 29 | 30 | .main-about .content .txt{ 31 | color:#666; 32 | margin-bottom: 30rpx; 33 | font-size:28rpx; 34 | line-height: 1.6; 35 | } 36 | 37 | .main-about .content.content-err{ 38 | padding-top:120rpx; 39 | padding-bottom:120rpx; 40 | } 41 | 42 | .main-about .content .err-icon{ 43 | text-align: center; 44 | font-size: 150rpx; 45 | } 46 | 47 | .main-about .content .err-info{ 48 | text-align: center; 49 | font-size: 30rpx; 50 | color:#666; 51 | } 52 | 53 | .main-about .content .err-apply{ 54 | display: flex; 55 | justify-content: center; 56 | align-items: center; 57 | margin-top:60rpx; 58 | } 59 | 60 | .main-about .comm-list{ 61 | width:100%; 62 | } 63 | -------------------------------------------------------------------------------- /miniprogram/pages/about/hint.js: -------------------------------------------------------------------------------- 1 | const pageHelper = require('../../helper/page_helper.js'); 2 | const PassportBiz = require('../../biz/passport_biz.js'); 3 | 4 | Page({ 5 | 6 | /** 7 | * 页面的初始数据 8 | */ 9 | data: { 10 | type: 0, //0-需要注册提示 1=用户异常提示 2=认证中提示 9=自定义错误 11 | msg: '' 12 | }, 13 | 14 | /** 15 | * 生命周期函数--监听页面加载 16 | */ 17 | onLoad: function (options) { 18 | PassportBiz.initPage(this); 19 | PassportBiz.setSetup(this); 20 | 21 | let type = 9; 22 | let msg = (options && options.msg) ? decodeURIComponent(options.msg) : ''; 23 | 24 | if (options && options.type) type = options.type; 25 | 26 | this.setData({ 27 | type, 28 | msg 29 | }); 30 | }, 31 | 32 | /** 33 | * 生命周期函数--监听页面初次渲染完成 34 | */ 35 | onReady: function () { 36 | 37 | }, 38 | 39 | /** 40 | * 生命周期函数--监听页面显示 41 | */ 42 | onShow: function () { 43 | 44 | }, 45 | 46 | /** 47 | * 生命周期函数--监听页面隐藏 48 | */ 49 | onHide: function () { 50 | 51 | }, 52 | 53 | /** 54 | * 生命周期函数--监听页面卸载 55 | */ 56 | onUnload: function () { 57 | 58 | }, 59 | 60 | url: function (e) { 61 | pageHelper.url(e, this); 62 | } 63 | 64 | }) -------------------------------------------------------------------------------- /miniprogram/pages/about/hint.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | 4 | }, 5 | "navigationBarTitleText": "温馨提示" 6 | } -------------------------------------------------------------------------------- /miniprogram/pages/about/hint.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 抱歉!该操作仅限校友 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 抱歉!用户状态异常,请联系客服 15 | 16 | 17 | 18 | 19 | 正在用户审核,暂无法使用本功能 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | {{msg}} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 首页 40 | | 41 | 关于我们 42 | | 43 | 44 | 45 | Copyright © {{setup.SETUP_TITLE}} 版权所有 46 | CC校友录提供技术支持 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /miniprogram/pages/about/hint.wxss: -------------------------------------------------------------------------------- 1 | @import 'about.wxss' -------------------------------------------------------------------------------- /miniprogram/pages/album/album_add.js: -------------------------------------------------------------------------------- 1 | const cloudHelper = require('../../helper/cloud_helper.js'); 2 | const helper = require('../../helper/helper.js'); 3 | const validate = require('../../helper/validate.js'); 4 | var AlbumBiz = require('../../biz/album_biz.js'); 5 | const setting = require('../../helper/setting.js'); 6 | const pageHelper = require('../../helper/page_helper.js'); 7 | const bizHelper = require('../../helper/biz_helper.js'); 8 | const PassportBiz = require('../../biz/passport_biz.js'); 9 | 10 | Page({ 11 | 12 | /** 13 | * 页面的初始数据 14 | */ 15 | data: { 16 | 17 | 18 | }, 19 | 20 | /** 21 | * 生命周期函数--监听页面加载 22 | */ 23 | onLoad: async function (options) { 24 | PassportBiz.initPage(this); 25 | 26 | if (!await PassportBiz.loginMustRegWin(this)) return; 27 | 28 | this.setData(AlbumBiz.initFormData()); // 初始化表单数据 29 | }, 30 | 31 | /** 32 | * 生命周期函数--监听页面初次渲染完成 33 | */ 34 | onReady: function () { 35 | 36 | }, 37 | 38 | /** 39 | * 生命周期函数--监听页面显示 40 | */ 41 | onShow: function () { 42 | 43 | }, 44 | 45 | /** 46 | * 生命周期函数--监听页面隐藏 47 | */ 48 | onHide: function () { 49 | 50 | }, 51 | 52 | /** 53 | * 生命周期函数--监听页面卸载 54 | */ 55 | onUnload: function () { 56 | 57 | }, 58 | 59 | 60 | model: function (e) { 61 | pageHelper.model(this, e); 62 | }, 63 | 64 | /** 65 | * 数据提交 66 | */ 67 | bindFormSubmit: async function () { 68 | 69 | let data = this.data; 70 | data.formType = AlbumBiz.TYPE_OPTIONS[data.formTypeIndex]; 71 | 72 | // 数据校验 73 | data = validate.check(data, AlbumBiz.CHECK_FORM, this); 74 | if (!data) return; 75 | 76 | try { 77 | // 图片 提交处理 78 | let imgList = this.data.imgList; 79 | if (imgList.length == 0) 80 | { 81 | pageHelper.showModal('至少需要上传一张图片'); 82 | return; 83 | } 84 | 85 | // 先创建,再上传 86 | let result = await cloudHelper.callCloudSumbit('album/insert', data); 87 | 88 | wx.showLoading({ 89 | title: '提交中...', 90 | mask: true 91 | }); 92 | 93 | let albumId = result.data.id; 94 | await AlbumBiz.updateAlbumPic(albumId, imgList); 95 | 96 | 97 | let callback = async function () { 98 | bizHelper.removeCacheList('album'); 99 | wx.switchTab({ 100 | url: "album_index" 101 | }); 102 | } 103 | pageHelper.showSuccToast('发布成功', 2000, callback); 104 | 105 | } catch (err) { 106 | console.log(err); 107 | } 108 | 109 | }, 110 | 111 | 112 | bindMyImgUploadListener: function (e) { 113 | this.setData({ 114 | imgList: e.detail 115 | }); 116 | } 117 | 118 | }) -------------------------------------------------------------------------------- /miniprogram/pages/album/album_add.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": { 3 | "cmpt-img-upload": "../../cmpts/public/img/img_upload_cmpt" 4 | }, 5 | "enablePullDownRefresh":false, 6 | "navigationBarTitleText": "创建相册" 7 | } -------------------------------------------------------------------------------- /miniprogram/pages/album/album_add.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |