project init

This commit is contained in:
zhl 2019-02-14 13:21:52 +08:00
commit 5fe9f2bb20
39 changed files with 2309 additions and 0 deletions

9
.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
/.env
/.idea/
/.wepycache/
.wepycache
**/node_modules
**/.DS_Store
/config/config.js
/config/group_config.js
/config/plugin_config.js
/config/bot_config.js
/public
/logs
/build
/dist
/lib
rev-manifest.json
/yarn.lock
/nohup.out
/package-lock.json
/dist.tar.gz
/config/apiclient_cert.p12

3
.prettierrc Normal file
View File

@ -0,0 +1,3 @@
{
"singleQuote": true
}

4
.wepyignore Normal file
View File

@ -0,0 +1,4 @@
node_modules
dist
.DS_Store
*.wpy___jb_tmp___

39
package.json Normal file
View File

@ -0,0 +1,39 @@
{
"name": "game",
"version": "0.0.2",
"description": "A WePY project",
"main": "dist/app.js",
"scripts": {
"dev": "wepy build --watch",
"build": "cross-env NODE_ENV=production wepy build --no-cache",
"dev:web": "wepy build --output web",
"clean": "find ./dist -maxdepth 1 -not -name 'project.config.json' -not -name 'dist' | xargs rm -rf",
"test": "echo \"Error: no test specified\" && exit 1"
},
"wepy": {
"module-a": false,
"./src/components/list": "./src/components/wepy-list.wpy"
},
"author": "zhl <zhl010101@gmail.com>",
"license": "MIT",
"dependencies": {
"redux": "^3.7.2",
"redux-actions": "^2.2.1",
"redux-promise": "^0.5.3",
"wepy": "^1.7.2",
"wepy-async-function": "^1.4.4",
"wepy-com-toast": "^1.0.2",
"wepy-redux": "^1.5.3"
},
"devDependencies": {
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-export-extensions": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.6.1",
"cross-env": "^5.1.3",
"less": "^3.8.1",
"wepy-compiler-babel": "^1.5.3",
"wepy-compiler-less": "^1.3.14"
}
}

13
project.config.json Normal file
View File

@ -0,0 +1,13 @@
{
"description": "A WePY project",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram",
"appid": "touristappid",
"projectname": "game",
"miniprogramRoot": "./dist"
}

69
src/app.wpy Normal file
View File

@ -0,0 +1,69 @@
<style lang="less">
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
}
</style>
<script>
import wepy from 'wepy'
import 'wepy-async-function'
export default class extends wepy.app {
config = {
pages: [
'pages/index',
'pages/game',
'pages/login'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
}
}
globalData = {
userInfo: null
}
constructor () {
super()
this.use('requestfix')
}
onLaunch() {
}
getUserInfo() {
return this.globalData.userInfo
}
checkClientLogin() {
return !this.globalData.userInfo;
}
updateGlobalData(name, obj) {
// 校验: globalData
if (!this.globalData) return;
// 校验: 操作字段
if (typeof name !== 'string' || name === '') return {};
// 取已有信息
const info = this.globalData[name] || {};
// 更新缓存
if (obj) {
// Object合并第一层
this.globalData[name] = Object.assign({}, info, obj);
} else if (!this.isUndefined(obj)) {
// 其他非undefined数据直接覆盖
this.globalData[name] = obj;
}
this.$apply && this.$apply();
console.info(`[${obj ? 'UPDATE' : 'GET'} GlobalData ${name}]:`, this.globalData[name]);
return this.globalData[name];
}
}
</script>

5
src/common/global.js Normal file
View File

@ -0,0 +1,5 @@
export default {
apiBase: 'https://pay-test.kingsome.cn',
hostBase: 'https://pay.kingsome.cn',
version: '1.0.1'
}

4
src/common/images.js Normal file
View File

@ -0,0 +1,4 @@
export default {
info_img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAABGdBTUEAALGPC/xhBQAAABh0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjMxN4N3hgAAA/BJREFUeF7tmiGPFEEUhE8gNkFwCQKCIARBFoFAkJxAIJFIJBKJRJ5DnkQikfwEJPIkEolE4nZ5ncwl5NjjZntLdE19m7xcsjfdefVVTW/3ZI6O+EAAAhCAAAQgAAEIQAACEIAABCAAgRAC2+12XfXiojabzUmI9FyZZfZx1WmZ/b3+/vOp739WndU/7uZSWqjyMvZ11a9dxl/+rq77Xd+9XyiKPFll6Ic5xu8Iwpc8WgtTXOa/7TH/YkyN/7gwJDly2m/5tJwfkoFtzfEyh9qClJZxnw5yfhpc85wvCEuGlPJuNXfTNzMk6wxyC1HZzvUzjZ17GacCp2y0Y99cZ+dc154POOmP7/XQ3f+OIyGnAadUtZ37nDt7j2tOnfTH99qOgHuYe+2lHAUNI1Wmfb3W2RkXTKeJlSGC7JbL21cz/J1zCScA1yjV3ft5jsNXXVPjv7VnCq764/ueHgid94SgzP9R4x7EQ3QHUCYe77sSTHc+7wW4m/93/21P0J7r/281mO76N0vSjZZLBCoA6zL6XXtPoJ0UpreA2ptCvBZGWiAAAQhAAAIQgAAEIAABCIxBoOdJnnLMGBSCu1Ca2TNXMPoxpPeYphwzBoXgLpRm9swVjH4M6T2mKceMQSG4C6WZPXMFox9Deo9pyjFjUAjuQmlmz1zB6MeQ3mOacswYFIK7UJrZM1cw+jGk95imHDMGheAulGb2zBWMfgzpPaYpx4xBIbgLpZk9cwWjH0N6j2nKMWNQCO5CaWbPXMHofaX3GH3VGF8KwZ0TgGDzm3QCQABkGQhH6Slf5n5N5EkgvGsCQABkGQhH6Slf5j4/AQTAk0B416wABECWgXCUnvJl7rMHIACeBMK7ZgUgALIMhKP0lC9znz0AAfAkEN41KwABkGUgHKWnfJn77AEIgCeB8K5ZAQiALAPhKD3ly9xnD0AAPAmEd80KQABkGQhH6Slf5j57AALgSSC8a1YAAiDLQDhKT/ky99kDEABPAuFdswIQAFkGwlF6ype5zx6AAHgSCO+aFYAAyDIQjtJTvsx99gAEwJNAeNesAARAloFwlJ7yZe6zByAAngTCu2YFIACyDISj9JQvc589AAHwJBDeNSsAAZBlIBylp3yZ++wBCIAngfCuWQEIgCwD4SiRDwFDAnX7P1eVoXxaLvNPVAVNQwJl/jNVGcqn5TL/qaqgaUigzH+iKkP5tFzmP1YVNA0JlPmPVGUon5bL/IeqgqYhgTL/vqoM5dNymX9PVdA0JFDm31GVoXxaLvNvqwqahgTK/FuqMpRPy2X+TVVB05BAmb9SlaF8Wi7zb6gKmhCAAAQgAAEIQAACEIAABLwJ/AEEKPggcS30pwAAAABJRU5ErkJggg==',
accept_img: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjhEODI0MDNENjg0MTFFOEE1OTU4MDIxQjI4REYwRjgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjhEODI0MDRENjg0MTFFOEE1OTU4MDIxQjI4REYwRjgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCOEQ4MjQwMUQ2ODQxMUU4QTU5NTgwMjFCMjhERjBGOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCOEQ4MjQwMkQ2ODQxMUU4QTU5NTgwMjFCMjhERjBGOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pjl/41gAAAIcSURBVHja7N1BVsMwEATRKM/3v/KwZJMFxJatUf9aQwCpetQOBo+qeiGXtyUgAAgAAoAAIAAIAAKAACAACAACgAAgAAgAAoAAIAAIgF04LMFS/PUGzWECgACh6f/vxxIABAABthn/lx4DrgL6bfynzx8mQN7mX/JaBNAB0Dz9p15TB+i/8ac6gQmwz+Z/9bUIsLdwRYC89OsANt5VgM0nAAgg/TqAjTcBbD4BQADp1wFsvAlg8wmAJ4+A2//wQfrXmQC1wQLXTpuvBO6d+rHaBMBim3+nANU8cds+VeNYfOFO3/cetPFfrdG7yeKVzfc+ACZcNr8bpaekf/0OsNx97878+yZA94RGPj9PBwg7868+Ap5MTV24ELFPzzyaL9bZTlCJqd/xCCip1wGc+eEClPQ//z7A6p2gpD7jCCip1wGc+eEClPTndQBnvgkAAjjzpwowXuvft48bOsBwmdUz9Y4ATBHAsdBwrUwAHWCa2TpBgwlpAugAWcZLvwmAiR1AJ2g2AU0AHUAikn9WE0AHeCwZJfUmAIIFGNJvAiCsA+zUCbaYYCaADiBRyf3FBNABlk1WSb0JgGABhu/FBEBYB1ipE0T89tIE0AFce6em3wRAu/8PMLMTRN7FbALoAG0Z0m8CIFyAIf0mAIKuAiTYBAABQAAQAAQAAUAAEAAEAAFAABAABAABQAAQAAQAAUAAEAAEAAFAAPzyI8AAliJQGcH8J6wAAAAASUVORK5CYII=',
}

View File

@ -0,0 +1,34 @@
<!--游戏cell-->
<style lang="less">
@import "../style/game-cell.wxss";
</style>
<template>
<view class="game-cell" @tap="gameTap({{item.url}})">
<view class="game-icon">
<image src="{{item.image}}" mode="aspectFit"></image>
</view>
<view class="content-view">
<view class="title">{{item.title}}</view>
<view class="content">{{item.content}}</view>
</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class gameCell extends wepy.component {
props = {
item: {
type: Object,
defalut: null
}
}
data = {
}
methods = {
gameTap (url, e) {
this.$emit('gameCellTap', url)
}
}
}
</script>

View File

@ -0,0 +1,66 @@
<style lang="less">
.zan-dialog__mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 10;
background: rgba(0, 0, 0, 0.7);
display: none;
}
.zan-dialog__container {
position: fixed;
bottom: 0;
width: 750rpx;
background: white;
transform: translateY(100%);
z-index: 11;
}
.zan-dialog--show .zan-dialog__mask {
display: block;
}
</style>
<template>
<view class="zan-dialog {{ showDialog ? 'zan-dialog--show' : '' }}">
<view class="zan-dialog__mask" bindtap="toggleDialog" />
<view animation="{{animationData}}" class="zan-dialog__container">
<view style="padding: 100px 0; text-align: center;">{{content}}</view>
</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class zanDialog extends wepy.component {
props = {}
data = {
showDialog: false,
content: '',
animationData: {}
}
methods = {
toggleDialog({ content = '' }, event) {
console.log('showZanDialogs', content)
this.content = content
this.showDialog = !this.showDialog
let animation = wepy.createAnimation({
duration: 400,
timingFunction: 'ease'
})
this.animation = animation
wx.createSelectorQuery()
.select('.zan-dialog__container')
.boundingClientRect((rect) => {
this.showDialog
? animation.translateY().step()
: animation.translateY(rect.height).step()
this.animationData = animation.export()
this.$apply()
}).exec()
}
}
}
</script>

View File

@ -0,0 +1,107 @@
<style lang="less">
.zan-loadmore {
position: relative;
width: 65%;
margin: 21px auto;
line-height: 20px;
font-size: 14px;
text-align: center;
vertical-align: middle;
}
.zan-loading {
width:20px;
height:20px;
display: inline-block;
vertical-align: middle;
animation: weuiLoading 1s steps(12, end) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iciIgd2lkdGg9JzEyMHB4JyBoZWlnaHQ9JzEyMHB4JyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICAgIDxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIiBmaWxsPSJub25lIiBjbGFzcz0iYmsiPjwvcmVjdD4KICAgIDxyZWN0IHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjRTlFOUU5JwogICAgICAgICAgdHJhbnNmb3JtPSdyb3RhdGUoMCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+CiAgICA8L3JlY3Q+CiAgICA8cmVjdCB4PSc0Ni41JyB5PSc0MCcgd2lkdGg9JzcnIGhlaWdodD0nMjAnIHJ4PSc1JyByeT0nNScgZmlsbD0nIzk4OTY5NycKICAgICAgICAgIHRyYW5zZm9ybT0ncm90YXRlKDMwIDUwIDUwKSB0cmFuc2xhdGUoMCAtMzApJz4KICAgICAgICAgICAgICAgICByZXBlYXRDb3VudD0naW5kZWZpbml0ZScvPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyM5Qjk5OUEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSg2MCA1MCA1MCkgdHJhbnNsYXRlKDAgLTMwKSc+CiAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9J2luZGVmaW5pdGUnLz4KICAgIDwvcmVjdD4KICAgIDxyZWN0IHg9JzQ2LjUnIHk9JzQwJyB3aWR0aD0nNycgaGVpZ2h0PScyMCcgcng9JzUnIHJ5PSc1JyBmaWxsPScjQTNBMUEyJwogICAgICAgICAgdHJhbnNmb3JtPSdyb3RhdGUoOTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNBQkE5QUEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxMjAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNCMkIyQjInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxNTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNCQUI4QjknCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgxODAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNDMkMwQzEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyMTAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNDQkNCQ0InCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyNDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNEMkQyRDInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgyNzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNEQURBREEnCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgzMDAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0PgogICAgPHJlY3QgeD0nNDYuNScgeT0nNDAnIHdpZHRoPSc3JyBoZWlnaHQ9JzIwJyByeD0nNScgcnk9JzUnIGZpbGw9JyNFMkUyRTInCiAgICAgICAgICB0cmFuc2Zvcm09J3JvdGF0ZSgzMzAgNTAgNTApIHRyYW5zbGF0ZSgwIC0zMCknPgogICAgPC9yZWN0Pgo8L3N2Zz4=) no-repeat;
-webkit-background-size: 100%;
background-size: 100%;
}
.zan-loadmore .zan-loading {
margin-right: 4px;
}
.zan-loadmore__tips {
display: inline-block;
vertical-align: middle;
height: 20px;
line-height: 20px;
}
.zan-loadmore--nodata,
.zan-loadmore--nomore {
border-top: 1rpx solid #e5e5e5;
color: #999;
}
.zan-loadmore--nodata {
margin-top: 120px;
}
.zan-loadmore--nodata .zan-loadmore__tips {
position: relative;
top: -11px;
background: #f9f9f9;
padding: 0 6px;
}
.zan-loadmore--nomore .zan-loadmore__tips {
position: relative;
top: -11px;
background: #f9f9f9;
padding: 0 6px;
}
.zan-loadmore__dot {
position: absolute;
left: 50%;
top: 10px;
margin-left: -2px;
margin-top: -2px;
content: " ";
width: 4px;
height: 4px;
border-radius: 50%;
background-color: #E5E5E5;
display: inline-block;
vertical-align: middle;
}
</style>
<template>
<block wx:if="{{nomore}}">
<view class="zan-loadmore zan-loadmore--nomore">
<view class="zan-loadmore__tips">{{ nomore_str || '无更多数据' }}</view>
</view>
</block>
<block wx:elif="{{nodata}}">
<view class="zan-loadmore zan-loadmore--nodata">
<view class="zan-loadmore__tips">{{ nodata_str || '暂无数据' }}</view>
</view>
</block>
<block wx:elif="{{loading}}">
<view class="zan-loadmore">
<view class="zan-loading"></view>
<view class="zan-loadmore__tips">加载中...</view>
</view>
</block>
</template>
<script>
import wepy from 'wepy'
export default class zanLoadmore extends wepy.component {
props = {
loading: Boolean,
nodata: {type: Boolean, default: false},
nomore: {type: Boolean, default: false},
nodata_str: String,
nomore_str: String
}
methods = {
}
}
</script>

View File

@ -0,0 +1,141 @@
<style lang="less">
.zan-quantity {
color: #666;
}
.zan-quantity view {
display: inline-block;
line-height: 20px;
padding: 5px 0;
text-align: center;
min-width: 40px;
box-sizing: border-box;
vertical-align: middle;
font-size: 12px;
border: 1rpx solid #999;
}
.zan-quantity .zan-quantity__minus {
border-right: none;
border-radius: 2px 0 0 2px;
}
.zan-quantity .zan-quantity__text {
border: 1rpx solid #999;
display: inline-block;
text-align: center;
vertical-align: middle;
height: 30px;
width: 40px;
font-size: 12px;
line-height: 30px;
}
.zan-quantity .zan-quantity__plus {
border-left: none;
border-radius: 0 2px 2px 0;
}
.zan-quantity .zan-quantity--disabled {
background: #f8f8f8;
color: #bbb;
border-color: #e8e8e8;
}
.zan-quantity--small view {
min-width: 36px;
line-height: 18px;
}
.zan-quantity--small .zan-quantity__text {
width: 36px;
line-height: 28px;
height: 28px;
}
</style>
<template>
<view class="zan-quantity {{ size === 'small' ? 'zan-quantity--small' : '' }}">
<view class="zan-quantity__minus {{ quantity <= min ? 'zan-quantity--disabled' : '' }}" data-component-id="{{ componentId }}" data-quantity="{{ quantity }}" data-disabled="{{ quantity <= min }}" bindtap="handleZanQuantityMinus">-</view>
<input class="zan-quantity__text {{ min >= max ? 'zan-quantity--disabled' : '' }}" type="number" data-component-id="{{ componentId }}" data-min="{{ min }}" data-max="{{ max }}" value="{{ quantity }}" disabled="{{ min >= max }}" bindblur="handleZanQuantityBlur"></input>
<view class="zan-quantity__plus {{ quantity >= max ? 'zan-quantity--disabled' : '' }}" data-component-id="{{ componentId }}" data-quantity="{{ quantity }}" data-disabled="{{ quantity >= max }}" bindtap="handleZanQuantityPlus">+</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class zanQuantity extends wepy.component {
props = {
quantity: {
type: Number,
default: 0
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 0
},
size: String,
componentId: String
}
data = {}
methods = {
handleZanQuantityMinus(e) {
this.handle(e, -1)
},
handleZanQuantityPlus(e) {
this.handle(e, +1)
},
handleZanQuantityBlur(e) {
let dataset = e.currentTarget.dataset
let componentId = dataset.componentId
let max = +dataset.max
let min = +dataset.min
let value = e.detail.value
if (!value) {
setTimeout(() => {
this.callback(componentId, min)
}, 16)
this.callback(componentId, value)
return '' + value
}
value = +value
if (value > max) {
value = max
} else if (value < min) {
value = min
}
this.callback(componentId, value)
return '' + value
}
}
handle(e, num) {
let dataset = e.currentTarget.dataset
let componentId = dataset.componentId
let disabled = dataset.disabled
let quantity = +dataset.quantity
if (disabled) return null
this.callback(componentId, quantity + num)
}
callback(componentId, quantity) {
quantity = +quantity
let e = { componentId, quantity }
console.info('[zan:quantity:change]', e)
this.$emit('zanQuantityChange', e)
}
}
</script>

View File

@ -0,0 +1,268 @@
<style lang="less">
.zan-steps--steps.zan-steps--5 .zan-steps__step {
width: 25%;
}
.zan-steps--steps.zan-steps--4 .zan-steps__step {
width: 33%;
}
.zan-steps--steps.zan-steps--3 .zan-steps__step {
width: 50%;
}
.zan-steps--steps .zan-steps__step {
position: relative;
float: left;
padding-bottom: 25px;
color: #b1b1b1;
}
.zan-steps--steps .zan-steps__title {
transform: translateX(-50%);
font-size: 10px;
text-align: center;
}
.zan-steps--steps .zan-steps__icons {
position: absolute;
top: 30px;
left: -10px;
padding: 0 8px;
background-color: #fff;
z-index: 10;
}
.zan-steps--steps .zan-steps__circle {
display: block;
position: relative;
width: 5px;
height: 5px;
background-color: #e5e5e5;
border-radius: 50%;
}
.zan-steps--steps .zan-steps__line {
position: absolute;
left: 0px;
top: 32px;
width: 100%;
height: 1px;
background-color: #e5e5e5;
}
/* 已完成的steps */
.zan-steps--steps .zan-steps__step--done {
color: #333;
}
.zan-steps--steps .zan-steps__step--done .zan-steps__line {
background-color: #06bf04;
}
.zan-steps--steps .zan-steps__step--done .zan-steps__circle {
width: 5px;
height: 5px;
background-color: #09bb07;
}
/* 正在进行中的steps */
.zan-steps--steps .zan-steps__step--cur .zan-steps__icons {
top: 25px;
left: -14px;
}
.zan-steps--steps .zan-steps__step--cur .zan-steps__circle {
width: 13px;
height: 13px;
background-image: url("https://b.yzcdn.cn/v2/image/wap/success_small@2x.png");
background-size: 13px 13px;
}
.zan-steps--steps .zan-steps__step--cur .zan-steps__line {
background-color: #e5e5e5;
}
/* 各种不同位置的 */
.zan-steps--steps .zan-steps__step--first-child .zan-steps__title {
margin-left: 0;
transform: none;
text-align: left;
}
.zan-steps--steps .zan-steps__step--first-child .zan-steps__icons {
left: -7px;
}
.zan-steps--steps .zan-steps__step--last-child {
position: absolute;
right: 0;
top: 0;
text-align: right;
}
.zan-steps--steps .zan-steps__step--last-child .zan-steps__title {
transform: none;
text-align: right;
}
.zan-steps--steps .zan-steps__step--last-child .zan-steps__icons {
left: auto;
right: -6px;
}
.zan-steps--steps .zan-steps__step--last-child .zan-steps__line {
display: none;
}
/* 有描述的step */
.zan-steps--steps .zan-steps__step--db-title {
min-height: 29px;
}
.zan-steps--steps .zan-steps__step--db-title .zan-steps__line {
top: 45px;
}
.zan-steps--steps .zan-steps__step--db-title .zan-steps__icons {
top: 43px;
}
.zan-steps--steps .zan-steps__step--db-title.zan-steps__step--cur .zan-steps__icons {
top: 39px;
}
.zan-steps--vsteps {
color: #999;
font-size: 14px;
}
.zan-steps--vsteps .zan-steps__step {
position: relative;
padding: 15px 0;
}
.zan-steps--vsteps .zan-steps__step--done {
color: #44BB00;
}
.zan-steps--vsteps .zan-steps__line {
position: absolute;
top: 0;
bottom: 0;
left: 7px;
width: 1px;
background-color: #e5e5e5;
}
.zan-steps--vsteps .zan-steps__title {
display: inline-block;
line-height: 20px;
padding-left: 27px;
}
.zan-steps--vsteps .zan-steps__title--desc {
padding-left: 3px;
}
.zan-steps--vsteps .zan-steps__icons {
position: absolute;
left: 7px;
top: 50%;
transform: translate(-50%, -50%);
z-index: 2;
padding: 3px 0;
background-color: #fff;
}
.zan-steps--vsteps .zan-steps__circle {
width: 5px;
height: 5px;
background-color: #cacaca;
border-radius: 10px;
}
.zan-steps--vsteps .zan-steps__step--done .zan-steps__circle {
width: 5px;
height: 5px;
background-color: #09bb07;
}
.zan-steps--vsteps .zan-steps__step--cur .zan-steps__circle {
width: 13px;
height: 13px;
background: transparent url("https://b.yzcdn.cn/v2/image/wap/success_small@2x.png");
background-size: 13px 13px;
border-radius: 0;
}
.zan-steps--vsteps .zan-steps__icon--active {
width: 13px;
height: 13px;
}
.zan-steps--vsteps .zan-steps__step--first-child .zan-steps__title::before {
content: '';
position: absolute;
top: 0;
bottom: 50%;
left: 7px;
width: 1px;
background-color: #fff;
z-index: 1;
}
.zan-steps--vsteps .zan-steps__step--last-child .zan-steps__title::after {
content: '';
position: absolute;
top: 50%;
bottom: 0%;
left: 7px;
width: 1px;
background-color: #fff;
z-index: 1;
}
.zan-steps {
position: relative;
}
</style>
<template>
<view class="zan-steps zan-steps--{{ type == 'vertical' ? 'vsteps' : 'steps' }} zan-steps--{{ steps.length }} {{ className }}">
<view wx:for="{{ steps }}" wx:for-item="step" wx:key="unique" wx:for-index="index" class="zan-steps__step {{ hasDesc ? 'zan-steps__step--db-title' : '' }} {{ index == 0 ? 'zan-steps__step--first-child' : '' }} {{ index == steps.length - 1 ? 'zan-steps__step--last-child' : '' }} {{ step.done ? 'zan-steps__step--done' : '' }} {{ step.current ? 'zan-steps__step--cur' : '' }}">
<view class="zan-steps__title">{{ step.text }}</view>
<view wx:if="{{ hasDesc && step.desc }}" class="zan-steps__title zan-steps__title--desc">{{ step.desc }}</view>
<view class="zan-steps__icons">
<view class="zan-steps__circle"></view>
</view>
<view class="zan-steps__line"></view>
</view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class zanSteps extends wepy.component {
props = {
steps: Object,
type: String,
hasDesc: Boolean,
className: String
}
data = {}
methods = {}
}
</script>

View File

@ -0,0 +1,122 @@
<style lang="less">
.zan-switch {
position: relative;
display: inline-block;
width: 52px;
height: 32px;
vertical-align: middle;
box-sizing: border-box;
border-radius: 16px;
background: #44DB5E;
border: 1px solid #44DB5E;
}
.zan-switch__circle {
position: absolute;
top: 0;
left: 0;
width: 30px;
height: 30px;
display: inline-block;
background: #fff;
border-radius: 15px;
box-sizing: border-box;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1), 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
transition: transform 0.35s cubic-bezier(0.45, 1, 0.4, 1);
z-index: 2;
}
.zan-switch__bg {
position: absolute;
top: -1px;
left: -1px;
width: 52px;
height: 32px;
background: #fff;
border-radius: 26px;
display: inline-block;
border: 1px solid #e5e5e5;
box-sizing: border-box;
transition: transform 0.35s cubic-bezier(0.45, 1, 0.4, 1);
transform: scale(0);
transform-origin: 36px 16px;
}
.zan-switch--on .zan-switch__circle {
transform: translateX(20px);
}
.zan-switch--off .zan-switch__bg {
transform: scale(1);
}
.zan-swtich--disabled {
opacity: 0.4;
}
.zan-switch__loading {
position: absolute;
left: 7px;
top: 7px;
width: 16px;
height: 16px;
background: url(https://img.yzcdn.cn/public_files/2017/02/24/9acec77d91106cd15b8107c4633d9155.png) no-repeat;
background-size: 16px 16px;
animation: zan-switch-loading 0.8s infinite linear;
}
@keyframes zan-switch-loading {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
</style>
<template>
<view class="zan-switch zan-switch--{{ checked ? 'on' : 'off' }} {{ disabled ? 'zan-swtich--disabled' : '' }}" data-checked="{{ checked }}" data-loading="{{ loading }}" data-disabled="{{ disabled }}" data-component-id="{{ componentId }}" @tap="handleZanSwitchChange">
<view class="zan-switch__circle">
<view hidden="{{ !loading }}" class="zan-switch__loading"></view>
</view>
<view class="zan-switch__bg"></view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class zanSwitch extends wepy.component {
props = {
checked: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
componentId: {
type: String,
default: ''
}
}
data = {}
methods = {
handleZanSwitchChange(e) {
let dataset = e.currentTarget.dataset
let { loading, disabled, componentId } = dataset
let checked = !dataset.checked
if (loading || disabled) return
console.info('[zan:switch:change]', { checked, componentId })
this.$emit('zanSwitchChange', { componentId, checked })
}
}
}
</script>

View File

@ -0,0 +1,95 @@
<style lang="less">
.zan-tab {
height: 45px;
}
.zan-tab__bd {
width: 750rpx;
display: flex;
flex-direction: row;
border-bottom: 1rpx solid #e5e5e5;
background: #fff;
}
.zan-tab__bd--fixed {
position: fixed;
top: 0;
z-index: 2;
}
.zan-tab__item {
flex: 1;
display: inline-block;
text-align: center;
box-sizing: border-box;
}
.zan-tab__title {
font-size: 14px;
display: inline-block;
color: #666;
height: 44px;
line-height: 44px;
box-sizing: border-box;
margin: 0 10px;
word-break: keep-all;
}
.zan-tab__item--selected{
pointer-events: none;
}
.zan-tab__item--selected .zan-tab__title {
color: #0DAB3C;
border-bottom: 2px solid #0DAB3C;
}
.zan-tab__bd--scroll {
display: block;
white-space: nowrap;
}
.zan-tab__bd--scroll .zan-tab__item {
min-width: 80px;
}
.zan-tab__bd--scroll .zan-tab__text {
margin: 0 20px;
}
</style>
<template>
<view class="zan-tab">
<block wx:if="{{tab.scroll}}">
<scroll-view class="zan-tab__bd zan-tab__bd--scroll {{ fixed ? 'zan-tab__bd--fixed' : '' }}" scroll-x="true" style="height: {{ tab.height ? tab.height + 'px' : 'auto' }}">
<view wx:for="{{tab.list}}" wx:key="id" class="zan-tab__item {{tab.selectedId == item.id ? 'zan-tab__item--selected' : ''}}" data-component-id="{{componentId}}" data-item-id="{{item.id}}" @tap="handleZanTabChange">
<view class="zan-tab__title">{{item.title}}</view>
</view>
</scroll-view>
</block>
<block wx:else>
<view class="zan-tab__bd {{fixed ? 'zan-tab__bd--fixed' : ''}}">
<view wx:for="{{tab.list}}" wx:key="id" class="zan-tab__item {{tab.selectedId == item.id ? 'zan-tab__item--selected' : ''}}" data-component-id="{{componentId}}" data-item-id="{{item.id}}" @tap="handleZanTabChange">
<view class="zan-tab__title">{{item.title}}</view>
</view>
</view>
</block>
</view>
</template>
<script>
import wepy from 'wepy'
export default class zanTab extends wepy.component {
props = {
tab: Object,
componentId: String
}
data = {
showDialog: false
}
methods = {
handleZanTabChange(e) {
let { componentId, itemId: selectedId } = e.currentTarget.dataset
console.info('[zan:tab:change]', { componentId, selectedId })
this.$emit('zanTabChange', { componentId, selectedId })
}
}
}
</script>

View File

@ -0,0 +1,61 @@
<style lang="less">
.zan-toast {
position: fixed;
top: 35%;
left: 20%;
transform: translateZ(0) translateY(-100%);
background: rgba(0, 0, 0, 0.7);
color: #fff;
font-size: 14px;
width: 60%;
line-height: 1.5em;
margin: 0 auto;
box-sizing: border-box;
padding: 10px;
text-align: center;
border-radius: 4px;
z-index: 100;
}
</style>
<template>
<view class="zan-toast" wx:if="{{ toast.show }}" @tap="clearZanToast">
{{ toast.title }}</view>
</template>
<script>
import wepy from 'wepy'
export default class zanToast extends wepy.component {
props = {}
data = {
toast: {}
}
methods = {
showZanToast({title, timeout, cb}) {
var toast = this.toast || {}
clearTimeout(toast.timer)
// 弹层设置~
this.toast = {
show: true,
title
}
this.$apply()
var timer = setTimeout(() => {
this.methods.clearZanToast.call(this)
typeof cb === 'function' && cb()
}, timeout || 3000)
this.toast.timer = timer
this.$apply()
},
clearZanToast() {
var toast = this.toast || {}
clearTimeout(toast.timer)
this.toast.show = false
this.$apply()
}
}
}
</script>

View File

@ -0,0 +1,88 @@
<style lang="less">
.zan-toptips {
display: block;
position: fixed;
transform: translateY(-100%);
width: 100%;
/* 至少有一行的高度,保证第一次动画显示正常 */
min-height: 32px;
top: 0;
line-height: 2.3;
font-size: 14px;
text-align: center;
color: #FFF;
background-color: #E64340;
z-index: 110;
}
</style>
<template>
<view animation="{{animationData}}" class="zan-toptips"> {{ topTips.content }} </view>
</template>
<script>
import wepy from 'wepy'
export default class zanToptips extends wepy.component {
props = {}
data = {
topTips: {},
animationData: {}
}
methods = {
showZanTopTips({ content = '', options = {} }, event) {
console.log('showZanTopTips', content, options)
let topTips = this.topTips || {}
// 如果已经有一个计时器在了,就清理掉先
if (topTips.timer) {
clearTimeout(topTips.timer)
topTips.timer = undefined
}
if (typeof options === 'number') {
options = {
duration: options
}
}
// options参数默认参数扩展
options = Object.assign({
duration: 3000
}, options)
// 原生动画
let animation = wepy.createAnimation({
duration: 400,
timingFunction: 'ease'
})
this.animation = animation
const toggle = () => {
wx.createSelectorQuery()
.select('.zan-toptips')
.boundingClientRect((rect) => {
this.topTips.show
? animation.translateY().step()
: animation.translateY(-rect.height).step()
this.animationData = animation.export()
this.$apply()
}).exec()
}
// 设置定时器定时关闭topTips
let timer = setTimeout(() => {
this.topTips.show = false
this.topTips.timer = undefined
toggle()
}, options.duration)
// 展示出topTips
this.topTips = {
show: true,
content,
timer
}
toggle()
}
}
}
</script>

21
src/index.template.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="telephone=no" name="format-detection">
<title>转 WEB DEMO</title>
<style>
html, body, #app {height: 100%;}
</style>
</head>
<body>
<div id="app">
<router-view></router-view>
<script src="./index.js"></script>
</div>
</body>
</html>

156
src/mixins/base.js Normal file
View File

@ -0,0 +1,156 @@
import wepy from 'wepy'
export default class baseMixin extends wepy.mixin {
/**
* [公共方法]
* @param {[type]} item [description]
* @return {Boolean} [description]
*/
noop() {
return null;
}
hasOwn(obj, type) {
return Object.prototype.hasOwnProperty.call(obj, type);
}
/**
* [isXXX 基础方法]
* @param {[type]} item [description]
* @return {Boolean} [description]
*/
isUndefined(item) {
return typeof item === 'undefined';
}
isDefined(item) {
return !this.isUndefined(item);
}
isString(item) {
return typeof item === 'string';
}
isNumber(item) {
return typeof item === 'number';
}
isArray(item) {
return Object.prototype.toString.apply(item) === '[object Array]';
}
isObject(item) {
return typeof item === 'object' && !this.isArray(item);
}
isFunction(item) {
return typeof item === 'function';
}
/**
* [getXXX 增强方法]
* @param {[type]} item [description]
* @return {Boolean} [description]
*/
getString(item, defaultStr) {
if (this.isString(item)) return item.trim();
if (this.isNumber(item)) return `${item}`.trim();
return defaultStr || '';
}
getNumber(item, defaultNum) {
var matches = this.getString(item).match(/\d+/);
return this.isNumber(matches && +matches[0]) ? +matches[0] : defaultNum;
}
getArray(item, defaultArr) {
return this.isArray(item) ? item : (defaultArr || []);
}
getObject(item, defaultObj) {
return this.isObject(item) ? item : (defaultObj || {});
}
getFunction(item) {
return this.isFunction(item) ? item : noop;
}
/**
* [JSON方法]
* @param {[type]} item [description]
* @return {Boolean} [description]
*/
$json(item) {
let str = {type: Object.prototype.toString.call(item)}
try {
str = JSON.stringify(item)
} catch (e) {
str.error = e && e.stack || ''
}
return this.isString(str) ? str : this.$json(str)
}
$parse(item) {
let obj = {type: Object.prototype.toString.call(item)}
try {
obj = JSON.parse(item)
} catch (e) {
obj.error = e && e.stack || ''
}
return this.isObject(obj) ? obj : this.$parse(obj)
}
/**
* [功能方法]
* @param {[type]} item [description]
* @return {Boolean} [description]
*/
isPhone(str) {
return /^1\d{10}$/.test(str)
}
$alert(item = '标题', item2) {
const param = this.isObject(item) ? Object.assign({
// 首参数为obj
title: 'title', content: 'content'
}, item) : this.isString(item) ? this.isString(item2) ? {
// 俩参数均为字符串
title: item, content: item2
} : {
// 只有首参为字符串
title: '', content: item
} : {
// 尝试转换字符串
title: item.toString ? item.toString() : '参数异常'
}
wx.showModal(Object.assign({
showCancel: false
}, param))
}
$info(str) {
console.log('INFO:: %s', str)
}
$error(str) {
console.log('ERROR:: %s', str)
}
$trimStart(str, char) {
let r2 = new RegExp('^' + char + '+')
return str.replace(r2, '')
}
$remove(array, func) {
return array.filter(func)
}
generateShareID () {
let d = new Date().getTime()
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now()
}
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (d + Math.random() * 16) % 16 | 0
d = Math.floor(d / 16)
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
})
}
$formatMoney(money) {
return (money/100).toFixed(2)
}
$randomNum(minNum,maxNum){
return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10);
}
$getRandomColor() {
let rgb = []
for (let i = 0; i < 3; ++i) {
let color = Math.floor(Math.random() * 256).toString(16)
color = color.length == 1 ? '0' + color : color
rgb.push(color)
}
return '#' + rgb.join('')
}
}

25
src/mixins/tips.js Normal file
View File

@ -0,0 +1,25 @@
import wepy from 'wepy'
export default class testMixin extends wepy.mixin {
showToast (title, duration) {
if (!duration) {
duration = 15000
}
wepy.showToast({
title: title,
icon: 'loading',
duration: duration
})
}
showLoading() {
wepy.showToast({
title: '加载中',
icon: 'loading',
duration: 3000
})
}
hideToast () {
wepy.hideToast()
}
}

26
src/pages/game.wpy Normal file
View File

@ -0,0 +1,26 @@
<style lang="less">
</style>
<template>
<view class="container">
<web-view src="{{link}}"></web-view>
</view>
</template>
<script>
import wepy from 'wepy'
export default class GameWebPage extends wepy.page {
components = {};
data = {
link: ''
};
methods = {};
onLoad(params) {
this.link = decodeURIComponent(params.link);
console.log(this.link);
this.$apply();
}
}
</script>

109
src/pages/index.wpy Normal file
View File

@ -0,0 +1,109 @@
<style lang="less">
@import "../style/index.wxss";
</style>
<template>
<view class="container">
<view class="top-view">
<view class="userinfo">
<image class="userinfo-avatar" src="{{avatar}}"/>
<view class="userinfo-nickname">{{ nickname }}</view>
</view>
</view>
<repeat for="{{records}}" item="item" >
<recordCell :item="item" @gameCellTap.user="gameTap"/>
</repeat>
<zanLoadmore :loading.sync="loading" :nodata.sync="noData" :nomore.sync="noMore" nodata_str="暂无数据"></zanLoadmore>
<toast/>
</view>
</template>
<script>
import wepy from 'wepy';
import Toast from 'wepy-com-toast';
import base from '../mixins/base';
import tips from '../mixins/tips';
import recordCell from '../components/game-cell';
import zanLoadmore from '../components/zan-loadmore';
export default class Index extends wepy.page {
mixins = [base, tips];
config = {
navigationBarTitleText: '游戏大厅',
enablePullDownRefresh: true
};
components = {
toast: Toast,
recordCell: recordCell,
zanLoadmore: zanLoadmore
};
data = {
nickname: '加载中',
avatar: '',
records: [],
all_count: 0,
current: 0,
loading: false,
noData: true,
noMore: false
};
methods = {
gameTap(url, e) {
wepy.navigateTo({
url: '/pages/game?link=' + url
})
},
};
onPullDownRefresh() {
this.initPageParam();
this.getRecords();
}
onReachBottom() {
if (this.current < this.all_count) {
this.loading = true;
this.$apply();
let self = this;
setTimeout(() => {
self.getRecords();
}, 200);
}
}
async onLoad(options) {
if (this.$parent.checkClientLogin()) {
wepy.navigateTo({
url: '/pages/login'
})
}
this.getRecords();
}
onShow() {
let userInfo = this.$parent.getUserInfo();
console.log(userInfo);
if (userInfo) {
this.nickname = userInfo.nickName;
this.avatar = userInfo.avatarUrl;
}
}
initPageParam() {
this.all_count = 999;
this.current = 0;
this.records = [];
}
async getRecords() {
let records = [{
title: '超级玛丽(日版)',
content: '《超级马里奥兄弟》又名《超级玛丽兄弟》是任天堂于1985年出品的著名横版过关游戏作为1983年游...',
image: 'http://pub.hoh8.cn/files/game/fc/7002058/icon.jpg',
url: 'http://192.168.100.84:7456/',
id: '001'
}];
this.records = records;
}
}
</script>

59
src/pages/login.wpy Normal file
View File

@ -0,0 +1,59 @@
<style lang="less">
.zan-btns {
width: 95%;
}
</style>
<template>
<view class="container">
<view class='zan-font-14 zan-c-gray-dark' style='text-align:center;margin-top:50rpx;margin-bottom:50rpx;'>
允许微信授权后,才可以使用</view>
<view class="zan-btns">
<button open-type='getUserInfo' bindgetuserinfo="bindGetUserInfo" class="zan-btn zan-btn--primary">授权登录</button>
<!--<button bindtap='navigateBack' class="zan-btn">返回首页</button>-->
</view>
</view>
<zanToast />
</template>
<script>
import wepy from 'wepy'
import zanToast from '../components/zan-toast'
export default class Login extends wepy.page {
config = {
navigationBarTitleText: 'test'
}
components = {
zanToast: zanToast
}
data = {
backType: 'index'
}
computed = {
now () {
return +new Date()
}
}
methods = {
bindGetUserInfo: function(e) {
let self = this
if (e.detail.userInfo) {
console.log(e.detail.userInfo)
self.$parent.updateGlobalData('userInfo', e.detail.userInfo);
wepy.navigateBack({
delta: 1
})
} else {
this.$invoke('zanToast', 'showZanToast', { title: '很遗憾,您拒绝了微信授权, 无法使用该小程序', timeout: 2000 })
}
}
}
onLoad() {
console.log('login onLoad');
}
}
</script>

42
src/style/game-cell.wxss Normal file
View File

@ -0,0 +1,42 @@
.game-cell {
display: flex;
flex-flow: row nowrap;
padding: 20rpx;
width: 660rpx;
border-bottom: 1px solid #eee;
}
.game-cell .game-icon {
width: 130px;
float: left;
position: relative;
overflow: hidden;
background-size: cover;
margin-left: -15px;
padding: 2px;
}
.game-cell .game-icon image {
width: 100%;
height: 100%;
max-width: 100%;
max-height: 100%;
}
.content-view {
display: flex;
flex-flow: column nowrap;
margin-left: 5px;
}
.content-view .title {
font-size: 16px;
}
.content-view .content {
font-size: 14px;
}
.game-cell::after {
position: absolute;
left: 15px;
right: 0;
bottom: 0;
border-top: 1rpx solid #e5e5e5;
background: #e5e5e5;
content: ' ';
}

35
src/style/index.wxss Normal file
View File

@ -0,0 +1,35 @@
.userinfo {
display: flex;
align-items: center;
margin: 10px;
}
.userinfo-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
}
.userinfo-nickname {
color: #aaa;
font-size: 60 rpx;
margin-left: 8px;
}
.zan-btns {
width: 700 rpx;
margin-top: 60 rpx;
}
.top-view {
border-bottom: 1 rpx solid #eee;
box-shadow: 15 rpx 0 15px 0 rgba(0, 0, 0, 0.2);
background-color: #fff;
z-index: 2;
width: 100%;
}
.zan-loadmore--nodata {
margin-top: 60px;
}

View File

@ -0,0 +1,24 @@
.zan-badge {
position: relative;
}
.zan-badge__count {
position: absolute;
top: -8px;
right: 0px;
height: 1.6em;
min-width: 1.6em;
line-height: 1.6;
padding: 0 .4em;
font-size: 10px;
font-family: tahoma;
border-radius: .8em;
background: #FF4444;
color: #fff;
text-align: center;
white-space: nowrap;
transform: translateX(50%);
transform-origin: -10% center;
z-index: 10;
box-shadow: 0 0 0 1px #fff;
box-sizing: border-box;
}

142
src/style/zanui/btn.wxss Normal file
View File

@ -0,0 +1,142 @@
.zan-btn {
position: relative;
color: #333;
background-color: #fff;
margin-bottom: 10px;
padding-left: 15px;
padding-right: 15px;
border-radius: 2px;
border: 1rpx solid #e5e5e5;
font-size: 16px;
line-height: 45px;
height: 45px;
box-sizing: border-box;
text-decoration: none;
text-align: center;
vertical-align: middle;
}
.zan-btn::after {
display: none;
}
.zan-btns {
margin: 15px;
}
/* type */
.zan-btn--primary {
color: #fff;
background-color: #4b0;
border-color: #0a0;
}
.zan-btn--warn {
color: #fff;
background-color: #f85;
border-color: #f85;
}
.zan-btn--danger {
color: #fff;
background-color: #f44;
border-color: #e33;
}
/* size */
.zan-btn--small {
display: inline-block;
height: 30px;
line-height: 30px;
font-size: 12px;
margin-right: 5px;
margin-bottom: 0;
}
.zan-btn--mini {
display: inline-block;
line-height: 21px;
height: 22px;
font-size: 10px;
margin-right: 5px;
margin-bottom: 0;
padding-left: 5px;
padding-right: 5px;
}
.zan-btn--large {
border-radius: 0;
margin-bottom: 0;
border: none;
line-height: 50px;
height: 50px;
}
/* plain */
.zan-btn--plain.zan-btn {
background-color: transparent;
}
.zan-btn--plain.zan-btn--primary {
color: #06BF04;
}
.zan-btn--plain.zan-btn--warn {
color: #FF6600;
}
.zan-btn--plain.zan-btn--danger {
color: #FF4444;
}
/* 重写button组件的button-hover样式 */
.button-hover {
opacity: 0.9;
}
/* loading */
.zan-btn--loading {
color: transparent;
opacity: 1;
}
.zan-btn--loading::before {
position: absolute;
left: 50%;
top: 50%;
content: ' ';
width: 16px;
height: 16px;
margin-left: -8px;
margin-top: -8px;
border: 3px solid #e5e5e5;
border-color: #666 #e5e5e5 #e5e5e5 #e5e5e5;
border-radius: 8px;
box-sizing: border-box;
animation: btn-spin 0.6s linear;
animation-iteration-count: infinite;
}
.zan-btn--primary.zan-btn--loading::before,
.zan-btn--warn.zan-btn--loading::before,
.zan-btn--danger.zan-btn--loading::before {
border-color: #fff rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1);
}
@keyframes btn-spin {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
/* disabled */
.zan-btn.zan-btn--disabled {
/* 防止样式被 button[disabled] 的规则覆盖所以使用了important */
color: #999 ! important;
background: #f8f8f8 ! important;
border-color: #e5e5e5 ! important;
cursor: not-allowed ! important;
opacity: 1 ! important;
}
/* :last-child */
.zan-btn--last-child,
.zan-btn:last-child {
margin-bottom: 0;
margin-right: 0;
}

53
src/style/zanui/card.wxss Normal file
View File

@ -0,0 +1,53 @@
.zan-card {
margin-left: 0px;
width: auto;
padding: 5px 15px;
overflow: hidden;
position: relative;
font-size: 14px;
}
.zan-card__thumb {
width: 90px;
height: 90px;
float: left;
position: relative;
margin-left: auto;
margin-right: auto;
overflow: hidden;
background-size: cover;
}
.zan-card__img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}
.zan-card__detail {
margin-left: 100px;
width: auto;
position: relative;
}
.zan-card__detail-row {
overflow: hidden;
line-height: 20px;
min-height: 20px;
margin-bottom: 3px;
}
.zan-card__right-col {
float: right;
}
.zan-card__left-col {
margin-right: 80px;
}

53
src/style/zanui/cell.wxss Normal file
View File

@ -0,0 +1,53 @@
.zan-cell {
position: relative;
padding: 12px 15px;
display: flex;
align-items: center;
line-height: 1.4;
font-size: 14px;
}
.zan-cell::after {
position: absolute;
left: 15px;
right: 0;
bottom: 0;
border-top: 1rpx solid #e5e5e5;
background: #e5e5e5;
content: ' ';
}
.zan-cell__bd {
flex: 1;
}
.zan-cell__ft {
position: relative;
text-align: right;
color: #666;
}
.zan-cell--last-child::after,
.zan-cell:last-child::after {
display: none;
}
.zan-cell--access .zan-cell__ft {
padding-right: 13px;
}
.zan-cell--access .zan-cell__ft::after {
position: absolute;
top: 50%;
right: 2px;
content: " ";
display: inline-block;
height: 6px;
width: 6px;
border-width: 2px 2px 0 0;
border-color: #c8c8c8;
border-style: solid;
transform: translateY(-50%) matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
}
.zan-cell--switch {
padding-top: 6px;
padding-bottom: 6px;
}

View File

@ -0,0 +1,27 @@
.zan-c-red {
color: #f44 !important;
}
.zan-c-gray {
color: #c9c9c9 !important;
}
.zan-c-gray-dark {
color: #999 !important;
}
.zan-c-gray-darker {
color: #666 !important;
}
.zan-c-black {
color: #333 !important;
}
.zan-c-blue {
color: #3283fa !important;
}
.zan-c-green {
color: #44BB00 !important;
}

38
src/style/zanui/form.wxss Normal file
View File

@ -0,0 +1,38 @@
.zan-form {
background-color: #fff;
border-top: 1rpx solid #e5e5e5;
border-bottom: 1rpx solid #e5e5e5;
}
.zan-form__item {
line-height: 26px;
}
.zan-form__title {
float: left;
width: 80px;
font-size: 14px;
}
.zan-form__title--top {
align-self: flex-start;
}
.zan-form__input, .zan-form__textarea {
min-height: 26px;
}
.zan-form__input input {
min-height: 26px;
}
.zan-form__textarea {
display: -webkit-flex;
display: flex;
align-items: center;
}
.zan-form__textarea textarea {
width: auto;
flex: 1;
}

101
src/style/zanui/helper.wxss Normal file
View File

@ -0,0 +1,101 @@
.zan-pull-left {
float: left;
}
.zan-pull-right {
float: right;
}
.zan-center {
text-align: center;
}
.zan-right {
text-align: right;
}
.zan-text-deleted {
text-decoration: line-through;
}
.zan-font-8 {
font-size: 8px;
}
.zan-font-10 {
font-size: 10px;
}
.zan-font-12 {
font-size: 12px;
}
.zan-font-14 {
font-size: 14px;
}
.zan-font-16 {
font-size: 16px;
}
.zan-font-18 {
font-size: 18px;
}
.zan-font-20 {
font-size: 20px;
}
.zan-font-22 {
font-size: 22px;
}
.zan-font-24 {
font-size: 22px;
}
.zan-font-30 {
font-size: 30px;
}
.zan-font-bold {
font-weight: bold;
}
.zan-arrow {
position: absolute;
right: 15px;
top: 50%;
display: inline-block;
height: 6px;
width: 6px;
border-width: 2px 2px 0 0;
border-color: #c8c8c8;
border-style: solid;
transform: translateY(-50%) matrix(0.71, 0.71, -0.71, 0.71, 0, 0);
}
.zan-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
word-wrap: normal;
}
.zan-ellipsis--l2 {
max-height: 40px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.zan-ellipsis--l3 {
max-height: 60px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
.zan-clearfix {
zoom: 1;
}
.zan-clearfix::after {
content: '';
display: table;
clear: both;
}

66
src/style/zanui/icon.wxss Normal file
View File

@ -0,0 +1,66 @@
/* DO NOT EDIT! Generated by fount */
@font-face {
font-family: 'zuiicon';
src: url('https://b.yzcdn.cn/zui/font/zuiicon-b37948cf5d.eot');
src: url('https://b.yzcdn.cn/zui/font/zuiicon-b37948cf5d.eot?#iefix') format('embedded-opentype'),
url('https://b.yzcdn.cn/zui/font/zuiicon-b37948cf5d.woff2') format('woff2'),
url('https://b.yzcdn.cn/zui/font/zuiicon-b37948cf5d.woff') format('woff'),
url('https://b.yzcdn.cn/zui/font/zuiicon-b37948cf5d.ttf') format('truetype')
}
.zan-icon {
display: inline-block;
}
.zan-icon::before {
font-family: "zuiicon" !important;
font-style: normal;
font-weight: normal;
speak: none;
display: inline-block;
text-decoration: inherit;
width: 1em;
text-align: center;
/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;
/* fix buttons height, for twitter bootstrap */
line-height: 1em;
/* Animation center compensation - margins should be symmetric */
/* remove if not needed */
/* margin-left: .2em; */
/* you can be more comfortable with increased icons size */
/* font-size: 120%; */
/* Font smoothing. That was taken from TWBS */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* Uncomment for 3D effect */
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
/* DO NOT EDIT! Generated by fount */
.zan-icon-album:before { content: '\e800'; } /* '' */
.zan-icon-arrow:before { content: '\e801'; } /* '' */
.zan-icon-camera:before { content: '\e802'; } /* '' */
.zan-icon-certificate:before { content: '\e803'; } /* '' */
.zan-icon-check:before { content: '\e804'; } /* '' */
.zan-icon-checked:before { content: '\e805'; } /* '' */
.zan-icon-close:before { content: '\e806'; } /* '' */
.zan-icon-gift:before { content: '\e807'; } /* '' */
.zan-icon-home:before { content: '\e808'; } /* '' */
.zan-icon-location:before { content: '\e809'; } /* '' */
.zan-icon-message:before { content: '\e80a'; } /* '' */
.zan-icon-send:before { content: '\e80b'; } /* '' */
.zan-icon-shopping-cart:before { content: '\e80c'; } /* '' */
.zan-icon-sign:before { content: '\e80d'; } /* '' */
.zan-icon-store:before { content: '\e80e'; } /* '' */
.zan-icon-topay:before { content: '\e80f'; } /* '' */
.zan-icon-tosend:before { content: '\e810'; } /* '' */

View File

@ -0,0 +1,10 @@
@import "badge.wxss";
@import "btn.wxss";
@import "card.wxss";
@import "cell.wxss";
@import "color.wxss";
@import "form.wxss";
@import "helper.wxss";
@import "icon.wxss";
@import "label.wxss";
@import "panel.wxss";

View File

@ -0,0 +1,34 @@
.zan-label {
display: inline-block;
font-size: 12px;
height: 28px;
line-height: 28px;
color: #333;
border: 1rpx solid #999;
padding: 0px 10px;
border-radius: 2px;
margin-right: 10px;
box-sizing: border-box;
vertical-align: middle;
text-align: center;
}
.zan-label--primary {
color: #fff;
background: #f44;
border: 1rpx solid #f44;
}
.zan-label--disabled {
color: #cacaca;
background: #eee;
border: 1rpx solid #e5e5e5;
}
.zan-label--small {
font-size: 11px;
height: 16px;
line-height: 16px;
padding: 0px 3px;
}
.zan-label--plain.zan-label--primary {
color: #f44;
background: #fff;
}

View File

@ -0,0 +1,19 @@
.zan-panel {
background: #fff;
border-top: 1rpx solid #e5e5e5;
border-bottom: 1rpx solid #e5e5e5;
margin-top: 10px;
overflow: hidden;
}
.zan-panel-title {
font-size: 24rpx;
line-height: 1;
color: #999;
padding: 20px 15px 0 15px;
}
.zan-panel--without-margin-top {
margin-top: 0;
}

43
src/utils/http.js Normal file
View File

@ -0,0 +1,43 @@
import wepy from 'wepy'
import g from '../common/global'
const get = (url, data, header) => {
header = header || {}
header['accept-version'] = g.version
return Ajax(url, 'GET', data, header)
};
const post = (url, data, header) => {
header = header || {}
header['Content-Type'] = 'application/x-www-form-urlencoded'
header['accept-version'] = g.version
return Ajax(url, 'POST', data, header)
}
const Ajax = (url, method, data, header) => {
url = g.apiBase + url
header = header || {}
return new Promise((resolve, reject) => {
wepy.request({
url: url,
data: data,
method: method,
header: header
}).then(res => {
console.log(res)
if (res.errcode === 0) {
resolve(res)
} else {
reject(res)
}
}, error => {
reject(error)
})
})
}
export default {
get,
post
}

74
wepy.config.js Normal file
View File

@ -0,0 +1,74 @@
const path = require('path');
var prod = process.env.NODE_ENV === 'production';
module.exports = {
wpyExt: '.wpy',
eslint: false,
cliLogs: !prod,
build: {
web: {
htmlTemplate: path.join('src', 'index.template.html'),
htmlOutput: path.join('web', 'index.html'),
jsOutput: path.join('web', 'index.js')
}
},
resolve: {
alias: {
counter: path.join(__dirname, 'src/components/counter'),
'@': path.join(__dirname, 'src')
},
aliasFields: ['wepy', 'weapp'],
modules: ['node_modules']
},
compilers: {
less: {
compress: prod
},
/*sass: {
outputStyle: 'compressed'
},*/
babel: {
sourceMap: true,
presets: [
'env'
],
plugins: [
'transform-class-properties',
'transform-decorators-legacy',
'transform-object-rest-spread',
'transform-export-extensions',
]
}
},
plugins: {
},
appConfig: {
noPromiseAPI: ['createSelectorQuery']
}
}
if (prod) {
// 压缩sass
// module.exports.compilers['sass'] = {outputStyle: 'compressed'}
// 压缩js
module.exports.plugins = {
uglifyjs: {
filter: /\.js$/,
config: {
}
},
imagemin: {
filter: /\.(jpg|png|jpeg)$/,
config: {
jpg: {
quality: 80
},
png: {
quality: 80
}
}
}
}
}