437c1c5a by simon

基础工程

0 parents
Showing 75 changed files with 2189 additions and 0 deletions
root = true;
[*]
# indent_style = tab
indent_style = space
# indent_size = 4
indent_size = 2
tab_width = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
# [*.{json,yml,wxml,html}]
# indent_style = tab
# indent_size = 4
# tab_width = 2
[README.md]
trim_trailing_whitespace = ignore
.idea
.DS_Store
dist
tmp
node_modules
_old
config.custom.js
src/assets/images/filetype.png
src/assets/images/filetype@2x.png
.gitignore
.editorconfig
.eslintrc
.idea
node_modules/
npm-debug.log
CHANGELOG.md
test
examples
gulpfile.js
.travis.yml
appveyor.yml
.DS_Store
dist
tmp
_old
config.custom.js
src/assets/images/filetype.png
src/assets/images/filetype@2x.png
sudo: false
language: node_js
node_js:
- "6"
- "7"
- "8"
- "stable"
before_script:
- npm install -g gulp@next
MIT License
Copyright (c) 2017 Jeff Ma
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## 介绍
mp-gulp-framework 是一个专门为开发微信小程序打造的前端开发工作流,基于Gulp 4 开发,旨在通过工作流的方式解决微信小程序开发过程中写前端代码的痛点。
借鉴于:[https://github.com/Jeff2Ma/WeApp-Workflow](https://github.com/Jeff2Ma/WeApp-Workflow)
在此基础上作修改。
## 功能
### SCSS 实时编译为 WXSS
使用Sass 预处理器,让写CSS 更加顺畅。`.scss`文件会实时编译为微信小程序支持的`.wxss`文件。
### WXSS(CSS) 中px 单位转小程序单位rpx
以官方推荐的iPhone 6 为标准设计格式,开发中直接写`px` 即可自动转换为`rpx`
其中屏幕铺满为750px。
```css
// Input: src/pages/index/index.scss
.index__header {
font-size: 14px;
margin-top: 20PX; /* 如果为大写的`PX`单位则不会转换 */
}
// Output: dist/pages/index/index.wxss
.index__header {
font-size: 28rpx;
margin-top: 20PX; /* 如果为大写的`PX`单位则不会转换 */
}
```
### 图片压缩
实时压缩图片并采用增量方式防止被重复压缩。
### 自动上传图片到CDN 并更新路径为https 绝对路径
小程序不支持相对路径的图片引用,仅支持带`https`协议头的绝对路径。本工作流可以将WXML 以及WXSS 文件中引用的相对路径图片上传到云存储CDN 或通过FTP/SFTP 协议上传到个人服务器空间。目前支持腾讯云,七牛云。
```html
// Input: src/pages/index/index.wxml
<image src="%ASSETS_IMG%/t.png"></image>
// Output: dist/pages/index/index.wxml
<image src="https://cdn.devework.com/weapp/devework/t.png"></image>
```
### Font 文件转为base64 编码
小程序不支持相对路径的字体文件,本工作流可将CSS 中引用到的Font 文件转码为base64 并替换原路径。
```
// Input: src/pages/index/index.scss
@font-face {
font-family: 'fontello';
src: url("assets/fonts/fontello.ttf") format('truetype');
}
// Output: dist/pages/index/index.wxss
@font-face {
font-family: 'fontello';
src: url(data:application/font-sfnt;charset=utf-8;base64,AAEAAAAPAIAA....FsASNsQIARAAA) format("truetype");
}
```
### 全自动构建雪碧图及生成相应CSS
本功能由[postcss-lazysprite](https://github.com/Jeff2Ma/postcss-lazysprite) 插件驱动。开发中准备好图片后仅仅写一句类似`@lazysprite "xxxx"`的代码,即可全自动构建雪碧图及生成相应CSS。
```css
// Input: src/app.scss
@lazysprite "filetype";
// Output: dist/app.wxss
.icon-filetype-doc {
background-image: url(../sprites/filetype.png);
background-position: 0 0;
width: 80px;
height: 80px;
}
.icon-filetype-pdf {
background-image: url(../sprites/filetype.png);
background-position: -90px 0;
width: 80px;
height: 80px;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-device-pixel-ratio:2) {
.icon-filetype-doc {
background-image: url(../sprites/filetype@2x.png);
background-position: 0 0;
background-size: 170px 170px;
}
.icon-filetype-pdf {
background-image: url(../sprites/filetype@2x.png);
background-position: -90px 0;
background-size: 170px 170px;
}
}
```
## 项目结构
```
.
├── config.custom.js // gulp自定义配置,会覆盖config.js
├── config.js // gulp 配置文件
├── gulpfile.js
├── package.json
├── src // 开发目录
│   ├── app.js
│   ├── app.json
│   ├── app.scss
│   ├── assets // 开发相关的静态文件原始资源
│  │   ├── fonts //字体文件
│  │   ├── images // 图片文件,可被上传到CDN
│  │   ├── scss // 一般放置SCSS 的minxins 等被import 的SCSS 文件
│  │   └── sprites // 生成雪碧图小图的目录
│   ├── image // 小程序专用的图片资源(如tabbar icon)目录
│   ├── pages
│   └── utils
├── tmp // 通过src 目录编译后生成的缓存目录
└── dist // 通过src 目录编译后生成的文件目录,也是小程序开发的项目目录
```
# Notes:
# - Minimal appveyor.yml file is an empty file. All sections are optional.
# - Indent each level of configuration with 2 spaces. Do not use tabs!
# - All section names are case-sensitive.
# - Section names should be unique on each level.
#---------------------------------#
# general configuration #
#---------------------------------#
# branches to build
#branches:
# # whitelist
# only:
# - master
# - test
# Do not build on tags (GitHub and BitBucket)
skip_tags: true
# Do not build feature branch with open Pull Requests
skip_branch_with_pr: true
# Build worker image (VM template)
image: Visual Studio 2015
environment:
matrix:
- nodejs_version: 4.7.0
# scripts that run after cloning repository
install:
# to run script as a PowerShell command prepend it with ps:
- ps: Install-Product node $env:nodejs_version
# batch commands start from cmd:
- npm cache clean
- npm i
- npm install -g gulp@next
# to run your custom scripts instead of automatic tests
test_script:
# Output useful info for debugging.
- node --version && npm --version
- npm i
- pwd
- gulp test
# Don't actually build.
build: off
matrix:
fast_finish: true
cache:
# local npm modules
- C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache
- node_modules -> package.json
/**
* ------------------------------------------------------------------
* 配置文件
*
* 建议复制一份并重命名为 config.custom.js ,即可在config.custom.js 上根据需求进行配置
* ------------------------------------------------------------------
*
*/
module.exports = {
"enabledQcloud": false, //是否开启腾讯云COS 上传功能
// 腾讯云COS 上传功能配置表
"qcloud": {
"appid": "1111111",
"secretId": "xxx",
"secretKey": "xxxxx",
"bucket": "xxxx",
"region": "sh",
"prefix": "what-ever/you-want",
"overWrite": true,
"headers": {
"Cache-Control": "max-age=5184000"
}
},
// 静态资源CDN 域名,配合CDN 功能实用,线上请确保在mp管理端已经注册域名
"assetsCDN": "https://res.jianhui.org/"
};
/**
* ------------------------------------------------------------------
* gulpfile 文件
* ------------------------------------------------------------------
*/
var path = require('path');
var gulp = require('gulp');
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var imagemin = require('gulp-imagemin');
var sftp = require('gulp-sftp');
var del = require('del');
var replace = require('gulp-replace');
var postcss = require('gulp-postcss');
var qcloudUpload = require('gulp-qcloud-upload');
var gulpif = require('gulp-if');
var gutil = require('gulp-util');
var newer = require('gulp-newer');
var cache = require('gulp-cached');
var debug = require('gulp-debug');
var pxtorpx = require('postcss-px2rpx');
// var base64 = require('postcss-font-base64');
// var lazysprite = require('postcss-lazysprite');
var argv = require('yargs').argv;
var config = null;
// 获取用户配置
try {
config = require('./config.custom.js');
} catch (e) {
try {
config = require('./config.js');
} catch (e) {
log(gutil.colors.red('丢失配置文件(config.js/config.custom.js)'));
}
}
// 相关路径配置
var paths = {
src: {
baseDir: 'src',
imgDir: 'src/image',
spriteDir: 'src/assets/sprites',
scssDir: 'src/assets/scss',
imgFiles: 'src/image/**/*',
scssFiles: 'src/**/*.scss',
baseFiles: ['src/**/*.{png,js,json,wxml,wxss,wxs,ts,woff2}', '!src/assets/**/*', '!src/image/**/*'],
assetsDir: 'src/assets',
assetsImgFiles: 'src/assets/images/**/*.{png,jpg,jpeg,svg,gif}',
wxmlFiles: ['src/**/*.wxml'],
jsFiles: 'src/**/*.js'
},
dist: {
baseDir: 'dist',
imgDir: 'dist/image',
wxssFiles: 'dist/**/*.wxss',
},
tmp: {
baseDir: 'tmp',
imgDir: 'tmp/assets/images',
imgFiles: 'tmp/assets/images/**/*.{png,jpg,jpeg,svg,gif}'
}
};
// 雪碧图的配置
var lazyspriteConfig = {
imagePath: paths.src.spriteDir,
stylesheetInput: paths.src.scssDir,
stylesheetRelative: paths.src.assetsDir,
spritePath: paths.src.assetsDir + '/images',
smartUpdate: false,
cssSeparator: '-',
outputExtralCSS: true,
nameSpace: 'icon-'
};
// Log for output msg.
function log() {
var data = Array.prototype.slice.call(arguments);
gutil.log.apply(false, data);
}
// 压缩图片
function imageMin() {
// return gulp.src(paths.src.imgFiles, {si≤nce: gulp.lastRun(imageMin)})
return gulp.src(paths.src.imgFiles)
.pipe(newer(paths.dist.imgDir))
.pipe(imagemin({
progressive: true,
svgoPlugins: [{
removeViewBox: false
}]
}))
.pipe(gulp.dest(paths.dist.imgDir));
}
// assets 文件夹下的图片处理
function assetsImgMin() {
return gulp.src(paths.src.assetsImgFiles)
.pipe(newer(paths.tmp.imgDir))
.pipe(imagemin({
progressive: true,
svgoPlugins: [{
removeViewBox: false
}]
}))
.pipe(gulp.dest(paths.tmp.imgDir))
}
// Sass 编译
function sassCompile() {
var res = config.assetsCDN + config.qcloud.prefix + '/';
// 缩放比例 1为750
var pxtorpxOpts = {
times: 1
};
return gulp.src(paths.src.scssFiles)
.pipe(sass({
errLogToConsole: true,
outputStyle: 'expanded'
})
.on('error', sass.logError))
.pipe(gulpif(Boolean(argv.debug), debug({
title: '`sassCompile` Debug:'
})))
// .pipe(postcss([lazysprite(lazyspriteConfig), pxtorpx(pxtorpxOpts), base64()]))
.pipe(postcss([pxtorpx(pxtorpxOpts)]))
.pipe(rename({
'extname': '.wxss'
}))
.pipe(replace('.scss', '.wxss'))
.pipe(replace('%ASSETS_IMG%/', res))
.pipe(replace('src/assets/images', res)) // 雪碧图CSS RUL 中的图片路径
.pipe(gulp.dest(paths.dist.baseDir))
}
// 复制基础文件
function copyBasicFiles() {
return gulp.src(paths.src.baseFiles, {})
.pipe(gulp.dest(paths.dist.baseDir));
}
// 复制 WXML
function copyWXML() {
return gulp.src(paths.src.wxmlFiles, {})
.pipe(gulp.dest(paths.dist.baseDir));
}
// 重写WXML 中 image 标签中的图片路径
function wxmlImgRewrite() {
var res = config.assetsCDN + config.qcloud.prefix + '/';
// console.log(res);
return gulp.src(paths.src.wxmlFiles)
.pipe(replace('%ASSETS_IMG%/', res))
.pipe(gulp.dest(paths.dist.baseDir))
}
// clean 任务, dist 目录
function cleanDist() {
return del(paths.dist.baseDir);
}
// clean tmp 目录
function cleanTmp() {
return del(paths.tmp.baseDir);
}
// 腾讯云上传任务
function qcloudCDN(cb) {
if (config.enabledQcloud) {
// return gulp.src(paths.src.assetsImgFiles, {since: gulp.lastRun(qcloudCDN)})
return gulp.src(paths.tmp.imgFiles)
.pipe(cache('qcloudCache'))
.pipe(qcloudUpload({
appid: config.qcloud.appid,
secretId: config.qcloud.secretId,
secretKey: config.qcloud.secretKey,
bucket: config.qcloud.bucket,
region: config.qcloud.region,
prefix: config.qcloud.prefix,
overWrite: config.qcloud.overWrite,
headers: config.qcloud.headers
}));
}
cb();
}
var watchHandler = function (type, file) {
var extname = path.extname(file);
// SCSS 文件
if (extname === '.scss') {
if (type === 'removed') {
var tmp = file.replace('src/', 'dist/').replace(extname, '.wxss');
del([tmp]);
} else {
sassCompile();
}
}
// 图片文件
else if (extname === '.png' || extname === '.jpg' || extname === '.jpeg' || extname === '.svg' || extname === '.gif') {
if (type === 'removed') {
if (file.indexOf('assets') > -1) {
del([file.replace('src/', 'tmp/')]);
} else {
del([file.replace('src/', 'dist/')]);
}
} else {
imageMin();
assetsImgMin();
qcloudCDN();
wxmlImgRewrite();
}
}
// wxml
else if (extname === '.wxml') {
if (type === 'removed') {
var tmp = file.replace('src/', 'dist/')
del([tmp]);
} else {
copyWXML();
wxmlImgRewrite();
}
}
// 其余文件
else {
if (type === 'removed') {
var tmp = file.replace('src/', 'dist/');
del([tmp]);
} else {
copyBasicFiles();
// copyWXML();
// wxmlImgRewrite();
}
}
};
//监听文件
function watch(cb) {
var watcher = gulp.watch([
paths.src.baseDir,
paths.tmp.imgDir
], {
ignored: /[\/\\]\./
});
watcher
.on('change', function (file) {
log(gutil.colors.yellow(file) + ' is changed');
watchHandler('changed', file);
})
.on('add', function (file) {
log(gutil.colors.yellow(file) + ' is added');
watchHandler('add', file);
})
.on('unlink', function (file) {
log(gutil.colors.yellow(file) + ' is deleted');
watchHandler('removed', file);
});
cb();
}
//注册默认任务
gulp.task('default', gulp.series(
cleanTmp,
copyBasicFiles,
gulp.parallel(
sassCompile,
imageMin,
copyWXML
),
wxmlImgRewrite,
assetsImgMin,
qcloudCDN,
watch
));
//注册测试任务
gulp.task('test', gulp.series(
cleanTmp,
copyBasicFiles,
gulp.parallel(
sassCompile,
imageMin,
copyWXML
),
wxmlImgRewrite,
assetsImgMin,
qcloudCDN
));
// 删除任务
gulp.task('clean', gulp.parallel(
cleanTmp,
cleanDist
));
This diff could not be displayed because it is too large.
{
"name": "mp-gulp-frame-work",
"version": "0.0.5",
"description": "A workflow for better weapp developing.",
"main": "index.js",
"scripts": {
"test": "gulp test",
"dev": "gulp"
},
"repository": {
"type": "git",
"url": "http://admin@www.simonfungc.com:10086/r/mp/mp-gulp-framework.git"
},
"keywords": [
"gulp",
"gulpjs",
"workflow",
"weapp",
"wexin",
"wechat",
"css",
"wxml",
"wxss"
],
"author": "SimonFungc",
"license": "MIT",
"bugs": {
"url": "https://www.simonfungc.com/"
},
"homepage": "https://www.simonfungc.com/",
"devDependencies": {
"del": "^4.0.0",
"gulp": "^4.0.0",
"gulp-cached": "^1.1.1",
"gulp-debug": "^4.0.0",
"gulp-if": "^2.0.2",
"gulp-imagemin": "^5.0.0",
"gulp-newer": "^1.3.0",
"gulp-postcss": "^8.0.0",
"gulp-qcloud-upload": "^2.2.0",
"gulp-rename": "^1.2.2",
"gulp-replace": "^1.0.0",
"gulp-sass": "^4.0.0",
"gulp-sftp": "^0.1.5",
"gulp-util": "^3.0.8",
"postcss-font-base64": "^1.0.4",
"postcss-lazysprite": "^2.0.0",
"postcss-px2rpx": "0.0.4",
"yargs": "^13.1.0"
}
}
{
"client": "./dist",
"svr": "./server",
"setting": {
"urlCheck": false,
"es6": true,
"postcss": true,
"minified": true,
"newFeature": true
},
"appid": "wxc57ed87f2569f701",
"projectname": "gulp-example",
"condition": {}
}
//app.js
let fetchApi = require('./http/fetch-api.js');
let api = require('./http/api');
let config = require('./config');
let router = require('./router/index');
let store = require('./utils/stroage');
require('./http/mock-data');
App({
get: fetchApi.fetch,
post: (params) => {
params.method = 'post';
return fetchApi.fetch(params);
},
api: api,
config: config,
router: router,
store: store,
onLaunch: function () {},
globalData: {
indexInfo: null,
userInfo: null
}
})
{
"pages": [
"pages/authorize/authorize",
"pages/index/index",
"pages/example/example",
"pages/more/more"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "mp-gulp-framework",
"navigationBarTextStyle": "black"
},
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#CF4646",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "image/tabbar/home_D.png",
"selectedIconPath": "image/tabbar/home.png",
"text": "介绍"
},
{
"pagePath": "pages/more/more",
"iconPath": "image/tabbar/set_D.png",
"selectedIconPath": "image/tabbar/set.png",
"text": "更多"
}
]
}
}
/**
* ------------------------------------------------------------------
* app.scss 入口文件
*
* ------------------------------------------------------------------
*
*/
// 支持文件
@import "assets/scss/support";
// 原子类
@import "assets/scss/utils";
// 图标
// @import 'styles/iconfont.wxss';
// 雪碧图
// @lazysprite "filetype";
.test {
background-image: url(%ASSETS_IMG%/qr-r.jpg);
}
.app {
height: 100%;
justify-content: space-between;
// text-align: center;
box-sizing: border-box;
font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif, FZY3JW-GB1-0;
}
.app__width {
width: 750px;
}
.app__width {
width: 750px;
}
.app__inner {
margin: 20px;
}
.app__title {
font-size: $fontSize;
line-height: $fontSize + 4px;
font-weight: bold;
padding-bottom: 10px;
margin-bottom: 20px;
border-bottom: .5px solid #EEEEEE;
}
.app__desc {
font-size: $fontSizeSmaller;
line-height: $fontSizeSmaller +2px;
margin-bottom: 20px;
color: $colorGray;
}
.app__bgc {
position: fixed;
background-color: #ffffff;
width: 100%;
height: 100%;
}
.app__bg {
position: absolute;
width: 100%;
height: 100%;
}
.app__top-shadow {
position: fixed;
width: 750px;
height: 1px;
box-shadow: 0px 4px 0.9px 0.1px rgba(6, 0, 1, 0.07);
background-color: #ffffff;
}
.app__content {
position: relative;
}
// web font icon
@font-face {
font-family: "iconfont";
src:url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAOsAAsAAAAAB6gAAANdAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqDDIJmATYCJAMMCwgABCAFhG0HORuvBsgOJUHBwIABAAlgPHyN/f7c3UVEk0mi+3QSQxJNJCoexUrxUhhKIyT4UsKbL89+kizTNWb3wyt7UkR96ayA4xev1q04fZzIa32ey/Gt5wc26luWy5iT9qKFAcYBBbQ3RgEFWiAJesPYlRdxn0C9YccRqxl5ZcBCYSwLxJFS3gwsUk6lpj7UCtUle4t4Yqo2XaeXAHj0vx//QUhYkFRlxtq1w/Q2kPRz+iOmhipDoM51Gx7PD3aIjBlAITZLgxuoMDODUq8YTerLqxUhjRU3GgFfqeqrzT88kiCqGbWNYAJlEz+nbQmJP1h91rUZVMPcGeAZM51XhqohJw97O/vO23paqy3T6coNhsqQ1esr3nVWF19mTZ3YnOwtWwPk5bvMfvYCQV11V+xUzZx02tPO6H02TtP0y4dn5a7M9ravfPvs/poNl43TTmVrW87O66dcKzd3myo2Tjo5rW07l6+fcXXd3KmUDdBKXH240GtvAAw49qfa2BeatkTevUsumTJX5pzRRVy781FXe+YP15YALi0+kkDHQRm8OLz2sP/U1NGjIPxKdyVpafxHpKWvbajtddvnaxmZHLP0XGY1d2wvLarJWrd3LMD6Q1DiSPHusrPgvOxtlAKDyt7bk32nH3emP+npcwo2dKU/Vj040Jn2+HTvAU5VFtOf5vZDf683NVrpbEvIO7N3IX421A40MRbmdVIPQGXQhMi7/+o3vjanTBtt4/7Vygr4/p/GIHW7aqBWorXqz7QVQMVYCK4xXLnISlup57Ntpvcth3Ju8j8aod2b/tauu8+FWl0xkhpDyGqNEIWZQZUG86hWawH1pmUebtBBQolShynjAKHVFSTNPpG1ekUU5jWqdPuGaq1Bod56OJ7ZYCyUdKqEmjFqgy3dUNkqCozlwXRQX4Lk7VyzlNT4XAWSNMo4DA4IyuYzkYCkMTZoOuQhGDOQkUQeZoDHEMeJUC2JKtSKAxQYq2MCA5myFwW0ijygrZAgzTCkDdSiG6TUSiRg3MEYnft8CUSuHaeZVNNTka6ASDSUo0PBAgS1IDKNQquea3lGo4NcCAxjQAyJiAdlgFkIhyOC1OWzVJBWWABFj5RajECzH9PWGDC/mX++Q1DPGJsjRY6i5hgx1hSNwhTxatwNAAAAAA==') format('woff2'),
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconrefresh:before {
content: "\e874";
}
.iconempty:before {
content: "\e6a6";
}
.drop-down-item :last-child {
border-bottom: none;
}
/**
* ------------------------------------------------------------------
* Sass Minxins
*
* 参考收集:
* https://github.com/twbs/bootstrap-sass/tree/master/assets/stylesheets/bootstrap/mixins
* ------------------------------------------------------------------
*
*/
// 文字截取
@mixin text-overflow() {
overflow: hidden;
white-space: normal;
text-overflow: ellipsis;
word-break: break-all;
word-wrap: normal;
}
@mixin word-break() {
word-break: break-all;
word-wrap: break-word;
white-space: normal;
}
// No wrap
@mixin no-wrap() {
word-break: normal;
word-wrap: normal;
white-space: nowrap;
}
// 清除浮动
@mixin clearfix() {
&:before,
&:after {
content: " "; // 1
display: table; // 2
}
&:after {
clear: both;
}
}
// Single side border-radius
@mixin border-top-radius($radius) {
border-top-right-radius: $radius;
border-top-left-radius: $radius;
}
@mixin border-right-radius($radius) {
border-bottom-right-radius: $radius;
border-top-right-radius: $radius;
}
@mixin border-bottom-radius($radius) {
border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius;
}
@mixin border-left-radius($radius) {
border-bottom-left-radius: $radius;
border-top-left-radius: $radius;
}
// Center-align a block level element
@mixin center-block() {
display: block;
margin-left: auto;
margin-right: auto;
}
// CSS image replacement
// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
@mixin hide-text() {
font-size: 0;
line-height: 0;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
/**
* ------------------------------------------------------------------
* 支持文件
* 需要引用的地方均需要加上这个支持文件
*
* ------------------------------------------------------------------
*
*/
@import "mixins";
@import "var";
/**
* ------------------------------------------------------------------
* 原子类
*
* ------------------------------------------------------------------
*
*/
@import "support";
// Margin
.u-mt-smaller {
margin-top: $marginTopSmaller;
}
.u-mt-small {
margin-top: $marginTopSmall;
}
.u-mt-medium {
margin-top: $marginTopMedium;
}
.u-mt-large {
margin-top: $marginTopLarge;
}
.u-mt-larger {
margin-top: $marginTopLarger;
}
.u-mb-smaller {
margin-bottom: $marginTopSmaller;
}
.u-mb-small {
margin-bottom: $marginTopSmall;
}
.u-mb-medium {
margin-bottom: $marginTopMedium;
}
.u-mb-large {
margin-bottom: $marginTopLarge;
}
.u-mb-larger {
margin-bottom: $marginTopLarger;
}
// Padding
.u-pt-smaller {
padding-top: $paddingTopSmaller;
}
.u-pt-small {
padding-top: $paddingTopSmall;
}
.u-pt-medium {
padding-top: $paddingTopMedium;
}
.u-pt-large {
padding-top: $paddingTopLarge;
}
.u-pt-larger {
padding-top: $paddingTopLarger;
}
.u-pb-smaller {
padding-bottom: $paddingTopSmaller;
}
.u-pb-small {
padding-bottom: $paddingTopSmall;
}
.u-pb-medium {
padding-bottom: $paddingTopMedium;
}
.u-pb-large {
padding-bottom: $paddingTopLarge;
}
.u-pb-larger {
padding-bottom: $paddingTopLarger;
}
// 布局方位
.u-ta-c {
text-align: center !important;
}
.u-ta-l {
text-align: left !important;
}
.u-ta-r {
text-align: right !important;
}
.u-fl-l {
float: left;
}
.u-fl-n {
float: none;
}
.u-fl-r {
float: right;
}
.u-d-b {
display: block;
}
.u-d-i {
display: inline !important;
}
.u-d-ib {
display: inline-block !important;
}
.u-d-n {
display: none !important;
}
.u-d-t {
display: table;
table-layout: fixed;
}
.u-d-tc {
display: table-cell;
}
.u-va-b {
vertical-align: bottom;
}
.u-va-m {
vertical-align: middle;
}
.u-va-t {
vertical-align: top;
}
// clearfix
.u-clearfix {
@include clearfix;
}
// 虚拟格式
.u-cur-d {
cursor: default;
}
.u-cur-p {
cursor: pointer;
}
// flex
.u-flex {
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.u-flex-item {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
}
// 小程序中模拟ul、li
.u-ul {
padding-left: 30px;
text-align: left;
display: block;
}
.u-li {
position: relative;
font-size: $fontSizeSmall;
line-height: $fontSizeSmall + 4px;
margin-bottom: $marginTopSmall;
&:before {
position: absolute;
content: " ";
top: 14px;
left: -20px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: $colorBlack;
}
}
/**
* ------------------------------------------------------------------
* Sass 变量
*
* ------------------------------------------------------------------
*
*/
// Margin
$marginTopSmaller: 20px;
$marginTopSmall: 30px;
$marginTopMedium: 40px;
$marginTopLarge: 60px;
$marginTopLarger: 80px;
// Padding
$paddingTopSmaller: 20px;
$paddingTopSmall: 30px;
$paddingTopMedium: 40px;
$paddingTopLarge: 60px;
$paddingTopLarger: 80px;
// Color
$colorBlue: #20A0FF;
$colorGreen: #13CE66;
$colorGray: #475669;
$colorBlack: #000;
$colorRed: #FF4949;
$colorYellow: #F7BA2A;
$color: #787878;
$colorLink: #1D8CE0;
$backGroundColor: #fff;
// Font
$fontSize: 32px;
$fontSizeSmall: 28px;
$fontSizeSmaller: 24px;
$fontSizeLarge: 36px;
$fontSizeLarger: 44px;
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
},
bottomVisible: {
type: Boolean,
value: false
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {}
}
})
// 底线
.bottom-tips {
position: relative;
padding: 40px 0;
width: 100%;
text-align: center;
color: #666666;
.line {
border-bottom: dashed 1px #cccccc;
width: 80%;
position: absolute;
top: 50%;
left: 0;
right: 0;
margin: 0 auto;
}
.tips-wrap {
position: relative;
font-size: 28px;
.tips {
padding: 0 20px;
background-color: #ffffff;
}
}
}
<view class="bottom-tips" wx:if="{{bottomVisible}}">
<view class="line"></view>
<view class="tips-wrap">
<text class="tips">我是有底线的</text>
</view>
</view>
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {}
}
})
<view class="demo-item">demo-item</view>
Component({
options: {
styleIsolation: 'apply-shared' // 接受外部样式
},
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
},
emptyVisible: {
type: Boolean,
value: false
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod() {}
}
})
//用的fixed 请确保 内容为空
.empty-tips {
position: fixed;
text-align: center;
color: #666666;
font-size: 32px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
top:35%;
.iconfont{
font-size: 100px;
}
.tips {
padding: 20px;
}
}
<view class="empty-tips" wx:if="{{emptyVisible}}">
<view class="tips">
<span class="iconfont iconempty"></span>
<view class="tips">这里空空如也~</view>
</view>
</view>
let ENV_CONFIG = require('./env/index');
const APPID = ''
/** ====每次发布版本记得修改此环境配置==== */
const ENV = 'Dev';
const NET_CONFIG = ENV_CONFIG[ENV];
const MOCKAPI = ENV_CONFIG.mockApi;
module.exports = {
APPID,
ENV,
NET_CONFIG,
MOCKAPI
}
module.exports = {
mockApi: 'http://mock.simonfungc.com',
Dev: {
baseApi: 'https://dev-api.xxx.com'
},
Test: {
baseApi: 'https://test-api.xxx.com'
},
Slave: {
baseApi: 'https://slave-api.xxx.com'
},
Prod: {
baseApi: 'https://api.xxx.com'
}
}
module.exports = {
index: '/xxx/index', // Index 接口
decrypt: '/xxx/decrypt', // 解析用户信息
}
let config = require('./../config');
let Store = require('./../utils/stroage');
const reason = '服务异常,请稍后重试';
// 检查并获取sessionid sid:是否需要验证sessionId
function checkSessionId(sid) {
return new Promise((resolve, reject) => {
if (!sid) {
resolve();
return;
}
let sessionId = Store.getItem('sessionId');
if (sessionId) {
resolve(sessionId);
} else {
// 身份失效
//登陆失效的回调
// Store.clear("sessionId");
// wx.reLaunch({
// // url: '/pages/authorize/authorize'
// url: '/pages/login/login',
// })
}
});
}
const fetch = function ({
loading = false,
toast = true,
sid = true,
mode,
isMock,
url,
data,
method
}) {
// 自定义参数
// const clientInfo = {
// user_id: 1
// }
// 日志埋点不需要出现loading
if (loading && mode != 'log') wx.showLoading();
// if (loading && mode != 'log') Util.showLoading();
// 新建promise对象
let promise = new Promise((resolve, reject) => {
/**
* isMock设置单个接口Mock开启
* mode:目前针对不同业务的接口进行处理,log标识本地埋点上传
*/
let baseUrl = config.NET_CONFIG.baseApi;
if (isMock && mode != 'log') {
baseUrl = config.MOCKAPI; //环境配置
}
checkSessionId().then((result) => {
if (sid) {
url += "?sessionId=" + Store.getItem("sessionId")
}
// console.log("url:", url);
wx.request({
url: baseUrl + url, //请求地址
data: data, //自定义参数
method: method || 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
// header: {}, // 设置请求的 header的默认参数,根据项目需求添加
// header: {
// 'clientInfo': JSON.stringify(clientInfo),
// 'Server-Token':'xxx'
// },
success: function (result) {
// 日志上传不需要处理结果
if (mode == 'log') return;
let res = result.data;
// 登陆失效拦截,根据项目需要添加自己的配置
if (res.code == 404) {
// wx.showToast({
// title: '当前登陆失效,请重新登陆',
// icon: 'none',
// mask: true,
// success: () => {
// return;
// }
// })
//登陆失效的回调
Store.clear("sessionId");
wx.reLaunch({
url: '/pages/authorize/authorize'
})
}
// 内部统一的成功code拦截码
if (res.code === 200) {
if (loading) {
wx.hideLoading();
}
// resolve(res);
// 直接返回content
resolve(res.content);
} else {
// 有些特殊状况不需要toast 需要弹窗
if (toast) {
wx.showToast({
title: res.errMsg || errMsg,
icon: 'none'
})
} else {
wx.hideLoading();
}
// 返回错误信息
reject(res);
}
},
fail: function (e = {
CODE: -1,
msg: errMsg,
errMsg
}) {
let msg = e.errMsg;
if (e.errMsg == 'request:fail timeout') {
msg = '服务请求超时,请稍后重试'
}
wx.showToast({
title: msg,
icon: 'none'
});
reject(e)
},
complete: function () {
// complete
}
})
})
});
return promise;
}
module.exports = {
fetch
}
// https://github.com/webx32/WxMock
let Mock = require('../utils/mockSdk.js');
let config = require('../config')
let env = config.MOCKAPI;
Mock.mock(env + '/eatClassifyService', {
data: {
resultCode: 0,
content: function () {
return Mock.Random.ip();
}
}
});
let app = getApp();
Page({
data: {
barHeight: app.globalData.barHeight,
navbarData: {
showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
title: '微信授权' //导航栏 中间的标题
},
loginData: null,
authorized: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
parentMemberCode: "",
},
onLoad(options) {},
onReady() {
app.store.clear("sessionId");
let _this = this;
wx.login({
success: function (res) {
_this.data.loginData = res;
}
});
},
bindGetUserInfo(e) {
wx.showLoading();
this.getUserInfo(e.detail);
},
getUserInfo(e) {
let _this = this;
app.globalData.userInfo = e.userInfo;
// console.log("loginData:",_this.data.loginData);
app.post({
url: app.api.register,
sid: false,
data: {
encryptedData: e.encryptedData,
iv: e.iv,
code: _this.data.loginData.code,
parentMemberCode: _this.data.parentMemberCode,
}
}).then((res2) => {
app.store.setItem('sessionId', res2.sessionId);
_this.setData({
authorized: true
})
_this.toIndex();
}).catch((err) => {
console.log("@authorize || err:", err);
})
},
toIndex() {
console.log("@authorize || toIndex ");
setTimeout(() => {
app.router.push({
path: "index",
query: {},
openType: "redirect"
})
wx.hideLoading();
}, 2000);
}
})
{
"usingComponents": {
"navbar": "../../component/navbar/index"
},
"navigationStyle": "custom"
}
@import '../../assets/scss/mixins';
.page {
position: relative;
overflow: hidden;
.bgc {
// background-color: transparent;
// background-color: black;
background-color: #fafafc;
}
.main {
position: relative;
.top-space {
height: 60px;
}
.login {
position: relative;
width: 650px;
margin: 0 auto;
text-align: center;
&-logo {
width: 140px;
height: 140px;
}
&-name {
margin-top: 32px;
font-size: 32px;
color: #333333;
}
&-line {
margin-top: 70px;
width: 650px;
height: 2px;
background-color: #eaeaec;
}
&-title {
margin-top: 40px;
font-size: 32px;
text-align: left;
color: #333333;
}
&-tips {
margin-top: 28px;
font-size: 26px;
text-align: left;
color: #666666;
}
&-btn {
margin-top: 102px;
width: 650px;
height: 90px;
line-height: 90px;
border-radius: 8px;
background-color: #00c200;
font-size: 32px;
color: #ffffff;
}
}
}
}
<navbar navbar-data='{{navbarData}}'></navbar>
<view style='height: {{barHeight}}px'></view>
<view class="page-authorize page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="login">
<image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
<view class="login-name">美赞臣</view>
<view class="login-line"></view>
<view class="login-title">完整体验小程序功能,需要您的微信授权哦</view>
<view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
<button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
确认授权
</button>
</view>
</view>
</view>
let app = getApp();
Page({
data: {
barHeight: app.globalData.barHeight,
navbarData: {
showCapsule: 0, //是否显示左上角图标 1表示显示 0表示不显示
title: '微信授权' //导航栏 中间的标题
},
loginData: null,
authorized: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
parentMemberCode: "",
},
onLoad(options) {},
onReady() {
app.store.clear("sessionId");
let _this = this;
wx.login({
success: function (res) {
_this.data.loginData = res;
}
});
},
bindGetUserInfo(e) {
wx.showLoading();
this.getUserInfo(e.detail);
},
getUserInfo(e) {
let _this = this;
app.globalData.userInfo = e.userInfo;
// console.log("loginData:",_this.data.loginData);
app.post({
url: app.api.register,
sid: false,
data: {
encryptedData: e.encryptedData,
iv: e.iv,
code: _this.data.loginData.code,
parentMemberCode: _this.data.parentMemberCode,
}
}).then((res2) => {
app.store.setItem('sessionId', res2.sessionId);
_this.setData({
authorized: true
})
_this.toIndex();
}).catch((err) => {
console.log("@authorize || err:", err);
})
},
toIndex() {
console.log("@authorize || toIndex ");
setTimeout(() => {
app.router.push({
path: "index",
query: {},
openType: "redirect"
})
wx.hideLoading();
}, 2000);
}
})
{
"navigationStyle": "custom"
}
@import '../../assets/scss/mixins';
.page {
position: relative;
overflow: hidden;
.bgc {
// background-color: transparent;
// background-color: black;
background-color: #fafafc;
}
.main {
position: relative;
.top-space {
height: 60px;
}
.login {
position: relative;
width: 650px;
margin: 0 auto;
text-align: center;
&-logo {
width: 140px;
height: 140px;
}
&-name {
margin-top: 32px;
font-size: 32px;
color: #333333;
}
&-line {
margin-top: 70px;
width: 650px;
height: 2px;
background-color: #eaeaec;
}
&-title {
margin-top: 40px;
font-size: 32px;
text-align: left;
color: #333333;
}
&-tips {
margin-top: 28px;
font-size: 26px;
text-align: left;
color: #666666;
}
&-btn {
margin-top: 102px;
width: 650px;
height: 90px;
line-height: 90px;
border-radius: 8px;
background-color: #00c200;
font-size: 32px;
color: #ffffff;
}
}
}
}
<view class="page-authorize page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="login">
<image class="login-logo" src="../../image/logo.png" mode="aspectFit" />
<view class="login-name">小程序</view>
<view class="login-line"></view>
<view class="login-title">完整体验小程序功能,需要您的微信授权哦</view>
<view class="login-tips">· 获取您的公开信息(昵称、头像等)</view>
<button type="default" class="login-btn" wx:if="{{!authorized}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">
确认授权
</button>
</view>
</view>
</view>
let app = getApp();
Page({
data: {},
onLoad(options) {}
})
{
"navigationBarTitleText": "more"
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="content"></view>
</view>
</view>
let app = getApp();
let Router = app.router;
let Store = app.store;
// import Notify from './../../ui/vant-weapp/notify/notify';
Page({
data: {},
onLoad: function (options = {}) {},
// 页面跳转
navHandler() {
// 默认navigateTo,可选 redirect reLaunch back,参照小程序跳转
// 配置在tabBar的页面不能用navigateTo,要用reLaunch
let openType = "reLaunch";
Router.push({
path: 'more',
query: {
id: 1
},
duration: 500,
openType
})
},
// 请求数据
reqHandler() {
// 是否使用本地模拟数据
let isMock = true;
app.post({
isMock,
url: '/eatClassifyService',
data: {}
}).then((res) => {
console.log("res:", res);
}).catch((err) => {
console.log("err:", err);
})
},
// 储存数据到本地
storeHandler() {
Store.setItem("id", 2);
},
// 使用有赞UI组件
showNotify() {
// Notify("vant notify提示");
}
})
{
"navigationBarTitleText": "example",
"usingComponents": {
"demo-item": "../../component/demo-item/demo-item"
}
}
<view class="page-example">
<button bindtap="navHandler">页面跳转</button>
<button bindtap="reqHandler">数据请求</button>
<button bindtap="storeHandler">储存数据到本地</button>
<button bindtap="showNotify">有赞提示</button>
<demo-item></demo-item>
</view>
<!-- <van-notify id="van-notify" /> -->
let app = getApp();
Page({
data: {},
onLoad(options) {}
})
{
"navigationBarTitleText": "index"
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="content"></view>
</view>
</view>
let app = getApp();
Page({
data: {},
onLoad(options) {}
})
{
"navigationBarTitleText": "demo"
}
@import '../../assets/scss/mixins';
@import '../../assets/scss/utils';
.page {
.bgc {}
.bg {}
.main {
.top-space {
height: 0px;
}
.content {
position: relative;
}
}
}
<view class="page">
<view class="app__bgc bgc"></view>
<view class="app__bg bg"></view>
<!-- <view class="app__top-shadow"></view> -->
<view class="app__content main">
<view class="top-space"></view>
<view class="content"></view>
</view>
</view>
let app = getApp();
Page({
data: {
isShow: false, // 控制组件显示隐藏
url: ''
},
onLoad: function (options = {}) {
let url = options.url;
if (url) {
this.setData({
url: url,
isShow: true
})
} else {
wx.showToast({
title: '未找到页面地址',
title: 'none',
});
}
}
})
{
"navigationBarTitleText": "webview"
}
<view class="loading-wrap">
<view class="loading">
<view class="icon"></view>
<view class="text">加载中...</view>
</view>
</view>
<web-view wx:if="{{isShow}}" src="{{url}}" bindload="loadSucc"/>
const routerPath = {
index: '/pages/index/index', // 首页
register: '/pages/register/register', // 注册
authorize: '/pages/authorize/authorize', // 授权
example: '/pages/example/example',
more: '/pages/more/more',
}
function parse(data) {
let tempArr = [];
for (let key in data) {
tempArr.push(key + '=' + encodeURIComponent(data[key]));
}
return tempArr.join('&');
}
function push(path, option = {}) {
if (typeof path == 'string') {
option.path = path; //兼容无参数路径
} else {
option = path;
}
// console.log("option:", option);
// 配置key值找到对应path
let url = routerPath[option.path] || routerPath['index'];
// console.log("url:", url);
// 读取传入的配置参数
let {
query = {}, openType = 'navigate', duration = 0
} = option;
// json 转换为 字符串拼接参数
let params = parse(query)
// console.log("params:", params);
if (params) {
url = url + '?' + params;
}
// 是否需要延时跳转
duration ? setTimeout(() => {
to(openType, url);
}, duration) : to(openType, url);
}
function to(openType, url) {
let obj = {
url
};
if (openType == 'redirect') {
wx.redirectTo(obj);
} else if (openType == 'reLaunch') {
wx.reLaunch(obj);
} else if (openType == 'switchTab') {
wx.switchTab(obj);
} else if (openType == 'back') {
wx.navigateBack({
delta: 1
});
} else {
wx.navigateTo(obj);
}
}
module.exports = {
parse,
push,
to
}
This diff could not be displayed because it is too large.
var __request = wx.request;
var Mock = require("./mock.js");
// console.log('Mock', Mock)
Object.defineProperty(wx, "request", { writable: true }); wx.request = function (config) { if (typeof Mock._mocked[config.url] == "undefined") { __request(config); return } var resTemplate = Mock._mocked[config.url].template; var response = Mock.mock(resTemplate); if (typeof config.success == "function") { config.success(response) } if (typeof config.complete == "function") { config.complete(response) } }; module.exports = Mock;
function setItem(key, value, module_name) {
if (module_name) {
let module_name_info = getItem(module_name) || {};
module_name_info[key] = value;
try {
wx.setStorageSync(module_name, module_name_info);
} catch (e) {
wx.setStorage({
key: module_name,
data: module_name_info
})
}
} else {
try {
wx.setStorageSync(key, value);
} catch (e) {
wx.setStorage({
key: key,
data: value
})
}
}
}
function getItem(key, module_name) {
if (module_name) {
let val = getItem(module_name);
if (val) return val[key];
return '';
}
return wx.getStorageSync(key)
}
function clear(name) {
name ? wx.removeStorageSync(name) : wx.clearStorageSync()
}
module.exports = {
setItem,
getItem,
clear
}
// 手机正则
const REGEXPS = {
"mobile": /^1\d{10}$/
}
// 验证手机
function checkMobile(str) {
return REGEXPS.mobile.test(str);
}
function formatTime(date) {
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
function formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
}
/**
* 获取屏幕剩余高度
* useHeight 单位是rpx
* 默认返回单位是rpx 可通过unit参数改为 px
*/
function getLastScreenHeight(useHeight = 0, unit = 'rpx') {
let sysInfo = wx.getSystemInfoSync();
let clientHeight = sysInfo.windowHeight;
// 获取可使用窗口高度
let clientWidth = sysInfo.windowWidth;
// 算出比例
let ratio = 750 / clientWidth;
// 算出屏幕高度(单位rpx)
let height = clientHeight * ratio;
// 计算剩余高度
let lastHeight = height - useHeight;
// 可转换成px
if (unit == 'px') {
lastHeight = lastHeight / 750 * clientWidth
}
return lastHeight;
}
module.exports = {
formatTime: formatTime,
checkMobile: checkMobile,
getLastScreenHeight: getLastScreenHeight
}