Browse Source

add style

master
刘嘉炜 4 years ago
parent
commit
3dc241f7f8
  1. 21
      README.md
  2. 6
      package.json
  3. 23
      src/App.vue
  4. 149
      src/components/authorize_modal/authorize_modal.vue
  5. 12
      src/js/api.js
  6. 91
      src/js/server.js
  7. 27
      src/pages.json
  8. 151
      src/pages/feedback/feedback.vue
  9. 230
      src/pages/index/index.vue
  10. 205
      src/pages/login/login.vue
  11. 94
      src/pages/message_list/message_list.vue
  12. BIN
      src/static/images/authorize.png
  13. BIN
      src/static/logo.png
  14. 16
      src/store/actions.js
  15. 54
      src/store/index.js
  16. 15
      src/store/mutations.js
  17. 89
      src/style/public.scss
  18. 338
      src/utils/util.js

21
README.md

@ -17,3 +17,24 @@ yarn build
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
### 库
```
vuex、numeral
依赖-> sass-loader/ node-sass/
```
*sass 需要cnpm装,npm安装报错*
> 原型链接:https://org.modao.cc/app/d33151880c5a6a975b9f3af1868bf3a125a8923b?simulator_type=outside_artboard&sticky
> 设计稿链接:https://lanhuapp.com/web/#/item/project/board?pid=ea91cb92-0502-40c9-a746-e68d121e26fd
### ipx 底部适配高度函数
```css
padding-bottom: 0;
padding-bottom: calc( 0 + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */
padding-bottom: calc( 0 + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */
```

6
package.json

@ -80,8 +80,12 @@
"jest": "^25.4.0",
"mini-types": "*",
"miniprogram-api-typings": "*",
"node-sass": "^5.0.0",
"numeral": "^2.0.6",
"postcss-comment": "^2.0.0",
"vue-template-compiler": "^2.6.11"
"sass-loader": "^10.1.1",
"vue-template-compiler": "^2.6.11",
"vuex": "^3.6.0"
},
"browserslist": [
"Android >= 4",

23
src/App.vue

@ -14,4 +14,27 @@
<style>
/*每个页面公共css */
page{
background-color: #f2f2f7;
}
view,scroll-view,text,picker{
box-sizing: border-box;
}
/* btn hover-class */
.hover-active{
position: relative;
overflow: hidden;
}
.hover-active::after{
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 2;
background-color: rgba(0,0,0,.1);
}
/* btn hover-class */
</style>

149
src/components/authorize_modal/authorize_modal.vue

@ -0,0 +1,149 @@
<template>
<view class="authorize-modal">
<view class="am-content">
<view class="ac-tit">微信授权</view>
<view class="ac-tip">您的信息和数据将受到保护</view>
<image class="ac-img" mode="aspectFit" src="/static/images/authorize.png"></image>
<view class="ac-btns">
<button plain class="ab-btn" hover-class="hover-active" @click="cancel">取消</button>
<button
plain
class="ab-btn"
hover-class="hover-active"
open-type="getUserInfo"
lang="zh_CN"
@getuserinfo="getUserInfo"
>授权并登录</button>
</view>
</view>
</view>
</template>
<script>
import { API } from '../../js/api';
import { servers } from '../../js/server';
import util from '../../utils/util';
import Vuex from 'vuex';
const uniLogin = util.promisify(uni.login);
export default {
methods: {
cancel(){
this.closeThis();
},
closeThis(){
this.$emit('close');
},
async getUserInfo(userRes){
if(!userRes.detail.userInfo){
this.$emit('loginFail');
this.closeThis();
return util.showNone('获取用户信息失败!请稍后重试');
}
let loginRes = await uniLogin();
if(!loginRes.code){
this.$emit('loginFail');
this.closeThis();
return util.showNone('获取登陆凭证失败!稍后重试');
}
const APPID = uni.getAccountInfoSync().miniProgram.appId;
util.showLoad();
servers.post({
url: API.wechatMiniAppLoginAndSync,
data: {
code:loginRes.code,
appid:APPID,
encryptedData:userRes.detail.encryptedData,
iv:userRes.detail.iv,
'avatar_url': userRes.detail.userInfo.avatarUrl,
...userRes.detail.userInfo,
},
isDefaultGet: false,
})
.then(res=>{
util.hideLoad();
if(res.data.code == 0){
util.showNone(res.data.message || '登陆成功!');
let _data = res.data.data;
uni.setStorageSync('token',_data.token);
uni.setStorageSync('userInfo',_data.user);
this.$emit('loginSuccess',res);
setTimeout(_=>this.closeThis(), 1200);
}else{
util.showNone(res.data.message || '后台登陆失败!');
this.$emit('loginFail');
setTimeout(_=>this.closeThis(), 1200);
}
}).catch(util.hideLoad)
// this.$store.dispatch('initStoreInfo')
// .then(store=>console.log('---',store))
}
}
}
</script>
<style scoped lang="scss">
@import "../../style/public.scss";
.authorize-modal{
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba($color: #000, $alpha: .5);
z-index: 10;
.am-content{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding-top: 60upx;
width: 626upx;
border-radius: 16upx;
background-color: #fff;
.ac-tit{
margin-bottom: 22upx;
text-align: center;
line-height: 44upx;
font-size: 32upx;
color: #181818;
}
.ac-tip{
margin-bottom: 50upx;
text-align: center;
line-height: 40upx;
font-size: 28upx;
color: #9A9A9D;
}
.ac-img{
display: block;
margin: 0 auto;
width: 488upx;
height: 416upx;
}
.ac-btns{
padding: 60upx 56upx 80upx;
@include centerFlex(space-between);
.ab-btn{
height: 88upx;
width: 240upx;
line-height: 84upx;
text-align: center;
border: 2upx solid #C9C9CB;
border-radius: 44upx;
font-size: 28upx;
color: #9a9a9d;
&+.ab-btn{
background-color: $themeColor;
border-color: $themeColor;
color: #fff;
}
}
}
}
}
</style>

12
src/js/api.js

@ -0,0 +1,12 @@
export const ORIGIN = ``; // 测试
// export const ORIGIN = ``; // 正式
export const API = {
ex: `${ORIGIN}/test/test`,
}
export default { ORIGIN, API };

91
src/js/server.js

@ -0,0 +1,91 @@
import util from '../utils/util';
// import { app as vm } from '../main';
const islog = true;
export class Server {
request(url,data,method,header,isDefaultGet,failMsg){
return new Promise(async (rs,rj)=>{
// const _store = vm.$store;
// let storeInfo = _store.state.storeInfo || null;
// if(storeInfo)data['brand_id'] = storeInfo.brand_id;
const _token = uni.getStorageSync('token') || '';
if(_token)data['token'] = _token;
if(method === 'POST'&&_token)url = url + `?token=${_token}`
uni.request({
url,
data,
method, // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
header: {...header}, // 设置请求的 header // {'custom-header': 'application/json'}
success: res=>{
if(islog)console.log('req success---->',{
link: url,
query: data,
method: method,
data: res,
})
if(isDefaultGet){
if(failMsg == '')throw Error('默认回调,失败提示不能为空 key -> failMsg');
defaultGet({
url,
data,
res,
failMsg,
resolve: rs,
reject: rj
});
return
}
rs(res);
},
fail: err=>{
if(islog)console.log('req fail---->',{
link: url,
query: data,
method: method,
data: err,
})
util.hideLoad();
if(typeof(err.errMsg) == 'string'&&(err.errMsg.indexOf('timeout')!=-1 || err.errMsg.indexOf('interrupted')!=-1 || err.errMsg.indexOf('请求超时')!=-1)){
util.showNone('网络超时!');
}else if(typeof(err.errMsg) == 'string'){
util.showNone(err.errMsg);
}else{
util.showNone('请求数据失败!请检查当前网络状态。');
}
rj(err);
},
})
})
function defaultGet({res,failMsg,resolve,reject,url,data}){
if(res.data.code == 0){
resolve(res.data.data);
}else{
util.hideLoad();
util.showNone(res.data.message || failMsg || '');
reject({url,res,data});
}
}
}
get({url,data={},header={},isDefaultGet=true,failMsg=''}){
return this.request(url,data,'GET',header,isDefaultGet,failMsg);
}
post({url,data={},header={'custom-header': 'application/json'},isDefaultGet=true,failMsg=''}){
return this.request(url,data,'POST',header,isDefaultGet,failMsg);
}
uploadFile({url,filePath,onProgressCallBack,formData={}}){
return new Promise((rs,rj)=>{
let uploadTask = wx.uploadFile({
url,filePath,formData,name:'file',success:rs,fail:rj
})
uploadTask.onProgressUpdate(res=>onProgressCallBack&&onProgressCallBack(res))
})
}
}
export const servers = new Server();
export default { servers, Server };

27
src/pages.json

@ -3,14 +3,31 @@
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app"
"navigationBarTitleText": "欧轩智能教裁助手"
}
},
{
"path": "pages/feedback/feedback",
"style": {
}
},
{
"path": "pages/message_list/message_list",
"style": {
}
},
{
"path": "pages/login/login",
"style": {
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
"navigationBarTextStyle": "white",
"navigationBarTitleText": "欧轩智能教裁助手",
"navigationBarBackgroundColor": "#009874",
"backgroundColor": "#f2f2f7"
}
}

151
src/pages/feedback/feedback.vue

@ -0,0 +1,151 @@
<template>
<view class="feedback-container">
<view class="fc-textarea">
<textarea placeholder="请输入您的反馈、建议或者发现的问题"></textarea>
</view>
<view class="fc-tit"><text>上传照片</text>(最多上传3张只支持.jpgpng 格式</view>
<view class="fc-imgs">
<view class="fi-item" v-for="i in 5" :key="i">
<image class="fi-img"></image>
<image class="fi-close"></image>
</view>
<view class="fi-item fi-add">
<view></view>
<view>上传照片</view>
</view>
</view>
<view class="fc-fixed-bar">
<view hover-class="hover-active">保存</view>
</view>
</view>
</template>
<script>
export default {
}
</script>
<style lang='scss'>
@import '~style/public.scss';
page{
background-color: #fff;
}
.feedback-container{
padding-top: 44upx;
padding-bottom: 108upx;
padding-bottom: calc( 108upx + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */
padding-bottom: calc( 108upx + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */
.fc-textarea{
padding: 20upx;
margin: 0 auto 36upx;
width: 692upx;
height: 360upx;
border-radius: 10upx;
border: 2upx solid #D8D8D8;
>textarea{
width: 100%;
height: 100%;
font-size: 28upx;
line-height: 40upx;
color: #1a1a1a;
}
}
.fc-tit{
padding: 0 30upx;
margin-bottom: 24upx;
line-height: 44upx;
font-size: 24upx;
color: #9a9a9d;
@include textHide(1);
>text{
font-size: 32upx;
color: #333;
}
}
.fc-imgs{
padding-left: 6upx;
font-size: 0;
.fi-item{
position: relative;
margin: 0 24upx 24upx;
display: inline-block;
width: 200upx;
height: 200upx;
background-color: skyblue;
border-radius: 10upx;
overflow: hidden;
&.fi-add{
padding-top: 36upx;
>view{
&:first-child{
position: relative;
margin: 0 auto 30upx;
width: 60upx;
height: 60upx;
&::before{
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 60upx;
height: 4upx;
background-color: #d8d8d8;
}
&::after{
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 60upx;
width: 4upx;
background-color: #d8d8d8;
}
}
&+view{
text-align: center;
font-size: 28upx;
color: #9a9a9d;
}
}
}
.fi-img{
width: 100%;
height: 100%;
background-color: slateblue;
}
.fi-close{
position: absolute;
right: 6upx;
top: 6upx;
width: 40upx;
height: 40upx;
background-color: red;
}
}
}
.fc-fixed-bar{
position: fixed;
width: 100%;
left: 0;
bottom: 0;
padding: 10upx 20upx;
padding-bottom: calc( 10upx + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */
padding-bottom: calc( 10upx + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */
>view{
height: 88upx;
line-height: 88upx;
text-align: center;
border-radius: 44upx;
font-size: 32upx;
background-color: $themeColor;
color: #fff;
}
}
}
</style>

230
src/pages/index/index.vue

@ -1,49 +1,215 @@
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view>
<text class="title">{{title}}</text>
<view class="index-container">
<view class="ic-header">
<!-- <button hover-class="hover-active">前往登录</button> -->
<view class="ih-store-name">
<view>广州欧轩智能场馆(共6家)</view>
<image></image>
</view>
<view class="ih-tip">本月课时</view>
<view class="ih-num">0</view>
</view>
<view class="ic-notice">
<view class="in-left">
<image></image>
<text>欧轩智能场馆商家助手上线啦</text>
</view>
<view class="in-right">
<view>99</view>
<image></image>
</view>
</view>
<view class="ic-tab-section">
<view class="its-item" v-for="e in 8" :key="e">
<image></image>
<view>我的课程</view>
</view>
</view>
<view class="ic-feedback">
<view class="if-right">
<image></image>
<text>在线反馈</text>
</view>
<image></image>
</view>
<authorize-modal v-if="false"></authorize-modal>
</view>
</template>
<script>
import authorize_modal from '../../components/authorize_modal/authorize_modal';
export default {
data() {
return {
title: 'Hello'
}
components: {
'authorize-modal': authorize_modal
},
onLoad() {
data(){
return {
}
},
methods: {
onLoad(){
}
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin: 200rpx auto 50rpx auto;
}
<style lang="scss">
@import '~style/public.scss';
.index-container{
padding-top: 24upx;
padding: 24upx;
.ic-header{
padding-top: 66upx;
margin-bottom: 24upx;
height: 364upx;
border-radius: 10upx;
background-color: $themeColor;
button{
margin: 0 auto 42upx;
padding: 0;
width: 160upx;
line-height: 40upx;
height: 40upx;
text-align: center;
border-radius: 20upx;
border: none;
font-size: 28upx;
background-color: #fff;
color: $themeColor;
}
.ih-store-name{
margin-top: 22upx;
margin-bottom: 10upx;
@include centerFlex(center);
>view{
max-width: 80%;
line-height: 50upx;
text-align: center;
font-size: 36upx;
font-weight: 500;
color: #fff;
@include textHide(1);
}
>image{
margin-left: 20upx;
width: 28upx;
height: 28upx;
background-color: skyblue;
}
}
.ih-tip{
text-align: center;
line-height: 40upx;
font-size: 28upx;
color: rgba($color: #fff, $alpha: .7);
}
.ih-num{
padding: 0 20upx;
font-size: 104upx;
text-align: center;
line-height: 146upx;
font-weight: 600;
color: #fff;
@include textHide(1);
}
}
@mixin sec{
margin-bottom: 24upx;
border-radius: 10upx;
background-color: #fff;
}
.ic-notice{
padding: 0 24upx;
height: 108upx;
@include sec;
@include centerFlex(space-between);
.in-left{
flex-shrink: 0;
flex-grow: 1;
font-size: 28upx;
color: #1a1a1a;
@include textHide(1);
>image{
vertical-align: middle;
width: 52upx;
height: 52upx;
margin-right: 10upx;
background-color: skyblue;
}
.text-area {
display: flex;
justify-content: center;
}
}
.in-right{
@include centerFlex(flex-end);
>view{
margin-right: 14upx;
width: 40upx;
height: 40upx;
border-radius: 50%;
background-color: #EA5061;
line-height: 40upx;
text-align: center;
font-size: 24upx;
color: #fff;
@include textHide(1);
}
>image{
flex-shrink: 0;
width: 28upx;
height: 28upx;
background-color: skyblue;
}
}
}
.ic-tab-section{
padding: 10upx 0;
font-size: 0;
@include sec;
.its-item{
display: inline-block;
padding: 30upx 10upx;
width: 33.33%;
height: auto;
>image{
background-color: skyblue;
margin: 0 auto 20upx;
display: block;
width: 52upx;
height: 52upx;
}
>view{
text-align: center;
height: 40upx;
line-height: 40upx;
font-size: 28upx;
color: #1a1a1a;
@include textHide(1);
}
}
}
.ic-feedback{
padding: 0 24upx;
height: 108upx;
@include sec;
@include centerFlex(space-between);
.if-right{
font-size: 28upx;
line-height: 40upx;
color: #1a1a1a;
@include textHide(1);
>image{
vertical-align: middle;
margin-right: 16upx;
width: 52upx;
height: 52upx;
background-color: skyblue;
}
}
>image{
flex-shrink: 0;
flex-grow: 0;
width: 28upx;
height: 28upx;
background-color: skyblue;
}
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>

205
src/pages/login/login.vue

@ -0,0 +1,205 @@
<template>
<view class="login-container">
<view class="lc-header">
<view class="lh-logo"></view>
<view class="lh-name">欧轩智能场馆</view>
</view>
<view class="lc-form">
<view class="lf-frame"><input placeholder="请输入品牌ID" v-model="formData.brand_id" /></view>
<view class="lf-frame"><input placeholder="请输入账号" v-model="formData.account" /></view>
<view class="lf-frame"><input placeholder="请输入密码" v-model="formData.password" password /></view>
</view>
<button
class="lf-btn"
hover-class="hover-active"
open-type="getUserInfo"
lang="zh_CN"
@getuserinfo="submitBtn"
>登录</button>
<!-- <view class="lf-tip">提示请联系管理员添加您为员工账号</view>
<view class="lf-bot-btn" @click="toWebView">成为商家</view> -->
</view>
</template>
<script>
import { API } from '../../js/api';
import { servers } from '../../js/server';
import util from '../../utils/util';
const uniGetSetting = util.promisify(uni.getSetting);
const uniLogin = util.promisify(uni.login);
const APPID = '';
export default {
data(){
return {
formData: {
brand_id: '',
account: '',
password: '',
}
}
},
methods: {
async submitBtn(userRes){
try{
util.showLoad();
if(!userRes.detail.userInfo){
util.hideLoad();
return util.showNone('获取用户信息失败!请稍后重试');
}
let loginRes = await uniLogin();
if(!loginRes.code){
util.hideLoad();
return util.showNone('获取登陆凭证失败!稍后重试');
}
let userInfo = userRes.detail || {};
console.log(userRes)
let { formData } = this;
servers.post({
url: API.WechatMiniApplogin,
data: {
appid: APPID,
code: loginRes.code,
encryptedData: userInfo.encryptedData,
// is_details: 1,
//
user_info: userInfo.userInfo,
user_raw_data: userInfo.rawData,
...userInfo.userInfo,
username: formData.account,
password: formData.password,
brand_id: formData.brand_id,
},
isDefaultGet: false,
})
.then(res=>{
util.hideLoad();
let _data = res.data || {};
if(_data.code == 0){
util.showNone(_data.message || '操作成功!');
uni.setStorageSync('token',_data.data);
setTimeout(_=>{
util.routeTo(`/pages/index/index`, 'rL');
}, 1200);
}else{
util.showNone(_data.message || '操作失败!');
}
})
.catch(util.hideLoad)
}catch(err){
util.hideLoad();
console.warn('login err', err);
}
},
toWebView(){
util.routeTo(`/pages/web_view/web_view`,'rL');
}
},
}
</script>
<style lang="scss">
@import '~style/public.scss';
page{
background-color: #fff;
}
.login-container{
padding-bottom: 0;
padding-bottom: calc( 0 + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */
padding-bottom: calc( 0 + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */
.lc-header{
position: relative;
padding-top: 70upx;
margin-bottom: 46upx;
height: 390upx;
width: 100%;
overflow: hidden;
&::before{
content: '';
display: block;
position: absolute;
left: 50%;
bottom: 0upx;
z-index: -1;
transform: translateX(-50%);
background-color: $themeColor;
width: 3000upx;
height: 3000upx;
border-radius: 50%;
}
.lh-logo{
margin: 0 auto 20upx;
width: 170upx;
height: 170upx;
border-radius: 50%;
background-color: #fff;
overflow: hidden;
>image{
width: 100%;
height: 100%;
}
}
.lh-name{
padding: 0 24upx;
text-align: center;
line-height: 50upx;
font-weight: 500;
font-size: 36upx;
color: #fff;
}
}
.lc-form{
margin-bottom: 80upx;
.lf-frame{
margin: 0 auto 24upx;
padding: 0 20upx;
width: 610upx;
height: 108upx;
border: 2upx solid #dddddd;
border-radius: 54upx;
>input{
width: 100%;
height: 100%;
text-align: center;
font-size: 32upx;
color: #333;
}
&:last-child{
margin-bottom: 0;
}
}
}
.lf-btn{
margin-bottom: 16upx;
width: 610upx;
height: 108upx;
border-radius: 54upx;
border: none;
background-color: $themeColor;
font-size: 36upx;
line-height: 108upx;
color: #fff;
}
.lf-tip{
margin-bottom: 120upx;
text-align: center;
line-height: 40upx;
text-align: center;
font-size: 28upx;
color: #9A9A9D;
}
.lf-bot-btn{
margin-bottom: 20upx;
line-height: 40upx;
text-align: center;
font-size: 28upx;
color: $themeColor;
text-decoration: underline;
}
}
</style>

94
src/pages/message_list/message_list.vue

@ -0,0 +1,94 @@
<template>
<view class="message-list">
<view class="ml-item" v-for="i in 10" :key="i">
<view class="mi-tit">
<view class="mt-name" >
<view :class="[i==5?'active':'']">欧轩智能商家助手功能更新</view>
</view>
<view class="mt-date">2020/11/23</view>
</view>
<view class="mi-desc">
<view>喜欢喜欢需和许 i 会修 hi 休闲鞋被选行啊学休闲鞋被选行啊学休闲鞋被选行啊学</view>
<image></image>
</view>
</view>
</view>
</template>
<script>
export default {
}
</script>
<style lang="scss">
@import '~style/public.scss';
page{
background-color: #fff;
}
.message-list{
padding-left: 24upx;
padding-bottom: 24upx;
padding-bottom: calc( 24upx + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */
padding-bottom: calc( 24upx + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */
.ml-item{
padding: 54upx 24upx 40upx 0;
border-bottom: 2upx solid #D8D8D8;
.mi-tit{
margin-bottom: 20upx;
@include centerFlex(space-between);
.mt-name{
position: relative;
flex-shrink: 1;
min-width: 0;
&::after{
content: '';
position: absolute;
right: -16upx;
top: 6upx;
width: 12upx;
height: 12upx;
border-radius: 50%;
background-color: #FF4444;
}
>view{
line-height: 44upx;
font-size: 32upx;
color: #333;
@include textHide(1);
&.active{
color: #9A9A9D;
}
}
}
.mt-date{
flex-shrink: 0;
flex-grow: 0;
max-width: 50%;
margin-left: 24upx;
font-size: 28upx;
color: #9a9a9d;
@include textHide(1);
}
}
.mi-desc{
@include centerFlex(space-between);
>view{
flex-grow: 1;
flex-shrink: 0;
max-width: 80%;
font-size: 24upx;
line-height: 34upx;
color: #9a9a9d;
@include textHide(1);
}
>image{
flex-shrink: 0;
width: 32upx;
height: 32upx;
background-color: skyblue;
}
}
}
}
</style>

BIN
src/static/images/authorize.png

After

Width: 488  |  Height: 416  |  Size: 14 KiB

BIN
src/static/logo.png

Before

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

16
src/store/actions.js

@ -0,0 +1,16 @@
// 异步方法
import { servers } from '../js/server';
import { API } from '../js/api';
export default {
getBrandInfo({commit, state}){
return servers.get({
url: API.calc,
data: {},
failMsg: '加载数据失败!'
})
.then(res=>{
commit('setBrandInfo',res);
return res;
})
}
}

54
src/store/index.js

@ -0,0 +1,54 @@
import Vue from 'vue';
import Vuex from 'vuex';
import mutations from './mutations';
import actions from './actions';
import device from './device';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
device
},
state: {
// #ifdef H5
APPID: uni.getAccountInfoSync().miniProgram.appId,
// #endif
brandInfo: {
brand: {}
},
permissionObj: { // 权限代号对应
'1001': '营业额',
'1002': '收款记录',
'1003': '经营分析',
'1004': '预约订单',
'1005': '会员卡订单',
'1006': '积分订单',
'1007': '员工管理',
'1008': '查询核销',
'1009': '场地管理',
'1010': '设备管理',
},
// 场地占用提交页面信息
occupyInfo: {
storeInfo: {}, // 店铺信息
dateInfo: {}, // 时间信息
typeInfo: {}, // 球场类型
venueList: [], // 选择场地列表
}
},
mutations,
actions,
getters: {
permissionArr: state=>{
let _arr = [], _obj = state.permissionObj;
for(let key in _obj){
_arr.push({
key,
name: _obj[key],
})
}
return _arr;
}
}
});

15
src/store/mutations.js

@ -0,0 +1,15 @@
// 同步方法
export default {
// 设置品牌信息
setBrandInfo(state, brandInfo){
// console.log(storeInfo,'-----')
state.brandInfo = brandInfo
},
// 场地占用信息
setOccupyInfo(state, _occupyInfo){
state.occupyInfo = _occupyInfo;
}
}

89
src/style/public.scss

@ -0,0 +1,89 @@
@charset "utf-8";
$themeColor: #009874;
/*每个页面公共css */
/* view,scroll-view,text,picker{
box-sizing: border-box;
} */
@mixin textHide($line) {
display: -webkit-box;
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
-webkit-box-orient: vertical;
-webkit-line-clamp:$line;
}
@mixin centerFlex($justtify){
display: flex;
align-items: center;
justify-content: $justtify;
}
@mixin botLine{
border-bottom: 2upx solid #e5e5e5;
}
@mixin picBgc{
background-color: #f9f9f9;
}
@mixin closeIcon($width,$height,$color) {
transform: rotateZ(45deg);
&::before{
content: '';
display: block;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
width: $width;
height: $height;
background-color: $color;
border-radius: $height;
}
&::after{
content: '';
display: block;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
width: $height;
height: $width;
background-color: $color;
border-radius: $height;
}
}
@mixin hover {
position: relative;
overflow: hidden;
&::after{
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 2;
background-color: rgba(0,0,0,.1);
}
}
@mixin arrowIcon($size,$line,$radius,$angle,$color) {
&::after{
content:'';
display: inline-block;
vertical-align: middle;
transform: rotateZ($angle);
width: $size;
height: $size;
border-right: $line solid $color;
border-bottom: $line solid $color;
border-bottom-right-radius: $radius;
}
}

338
src/utils/util.js

@ -0,0 +1,338 @@
// import {emojiMap,emojiUrl} from './emojiMap';
export const phoneReg = new RegExp(/^1(3|4|5|6|7|8|9)\d{9}$/);
export const mailReg = new RegExp(/^\w+((.\w+)|(-\w+))@[A-Za-z0-9]+((.|-)[A-Za-z0-9]+).[A-Za-z0-9]+$/);
export const specialReg = new RegExp("[^a-zA-Z0-9\_\u4e00-\u9fa5]","i");
export const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
export const formatDate = ({ date= new Date(), partition= '-' }) => {
let _date;
if(typeof (date) === 'string'&&date.indexOf('-')!=-1){
_date = new Date(date.replace(/\-/g,'/'))
}else{
_date = new Date(date)
}
const year = _date.getFullYear();
const month = formatNumber(_date.getMonth() + 1);
const day = formatNumber(_date.getDate());
if(partition == 'zh')return `${year}${month}${day}`
return [year, month, day].map(formatNumber).join(partition);
}
export const formatNumber = n => {
n = n.toString()
return n[1] ? n : '0' + n
}
// 路由跳转
export const routeTo = (url,type) => {
switch(type){
case 'nT': uni.navigateTo({url});
break
case 'rT': uni.redirectTo({url});
break
case 'rL': uni.reLaunch({url});
break
case 'sT': uni.switchTab({url});
break
default: uni.navigateBack({delta: 1})
break
}
}
function showNone(txt,duration=1500){
uni.hideToast();
uni.hideLoading();
uni.showToast({
mask: true,
title: txt,
icon: 'none',
duration,
})
}
function showLoad(title='加载中', mask=true){
uni.showLoading({
mask,
title,
})
}
function hideLoad(){
uni.hideLoading()
}
function showModal({
title='提示',
content='',
showCancel=false,
cancelText='取消',
confirmText='确定',
confirmColor='#009874',
success,
fail,
complete
}){
uni.showModal({
title,
content,
showCancel,
cancelText,
confirmColor,
confirmText,
success,
fail,
complete
})
}
function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result;
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp;
// 上次被包装函数被调用时间间隔last小于设定时间间隔wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args);
if (!timeout) context = args = null;
}
}
}
return function(...args) {
context = this;
timestamp = +new Date();
const callNow = immediate && !timeout;
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait);
if (callNow) {
result = func.apply(context, args);
context = args = null;
}
return result;
}
}
function jsonStr(data){
return encodeURIComponent(JSON.stringify(data))
}
function jsonPar(json){
return JSON.parse(decodeURIComponent(json))
}
export let promisify = api => {
return (options, ...params) => {
return new Promise((resolve, reject) => {
api(Object.assign({}, options, { success: resolve, fail: reject }), ...params);
});
}
}
function previousPageFunction({fnName,query}){
return new Promise((rs,rj)=>{
try{
if(getCurrentPages().length>1){
console.log(getCurrentPages())
getCurrentPages()[getCurrentPages().length-2]['$vm'][fnName](query);
rs('success');
}else{
console.error('当前路由栈为一,无法调取上一页数据');
rj('当前路由栈为一,无法调取上一页数据');
}
}catch(err){
console.error('调用上一页面栈方法失败!',err);
rj('调用上一页面栈方法失败!');
}
})
}
// 获取节点信息
function getNodeMes(selector,_this=null){
return new Promise(rs=>{
let query = _this ? uni.createSelectorQuery().in(_this) : uni.createSelectorQuery();
query.select(selector).boundingClientRect(res=>{
rs(res)
// this.height = uni.getSystemInfoSync().windowHeight - res.height;
}).exec()
})
}
export const convertBase64 = function(base64data){
const fsm = uni.getFileSystemManager();
const FILE_BASE_NAME = 'tmp_base64src';//临时文件名
return new Promise((resolve, reject) => {
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64data) || []; //去掉 base64 的头信息:
if (!format) {
reject(new Error('ERROR_BASE64SRC_PARSE'));
}
const filePath = `${uni.env.USER_DATA_PATH}/${FILE_BASE_NAME}.${format}`;
const buffer = bodyData&&uni.base64ToArrayBuffer(bodyData); //将 base64 数据转换为 ArrayBuffer 数据
// console.log(uni.base64ToArrayBuffer(bodyData))
fsm.writeFile({ //将 ArrayBuffer 写为本地用户路径的二进制图片文件 //图片文件路径在 uni.env.USER_DATA_PATH 中
filePath,
data: buffer,
encoding: 'binary',
success() {
// console.log(buffer)
resolve(filePath);
},
fail() {
reject(new Error('ERROR_BASE64SRC_WRITE'));
},
});
});
}
export function failAuthorizeTosetting(content='调用失败,请打开检查授权状态'){
showModal({
title:'提示',
content,
showCancel:true,
confirmText:'打开',
success:res=>{if(res.confirm)uni.openSetting()}
})
}
// 解析小程序码 scene 参数
export function getSceneQuery(scene){
const queryStr = decodeURIComponent(scene) || null;
let queryObj = queryStr.split('&').reduce((obj,el)=>{
let arr = el.split('=');
obj[`${arr[0]}`] = arr[1];
return obj;
},{}) || null;
return queryObj;
}
//获取地址栏里(URL)传递的参数
function getUrlQuery(key,url){
var _url = decodeURI(url).split('?a=1').join(''); //剪切'?a=1'安卓兼容,再获取参数
if(_url.indexOf(`${key}=`) !=-1){
return _url.split(`${key}=`)[1].split('&')[0]
}
return null
}
//获取地址字段栏信息 腾讯获取授权码时
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return (r[2]); // 编码的字符串进行解码
return null;
}
function getRandom(min, max) {
return Math.round(Math.random() * (max - min)) + min;
}
export function get_zh_day(date){
if(isSameDay(new Date().getTime(),new Date(date).getTime()))return '今天'
const Arr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
return Arr[new Date(date).getDay()] || '';
}
// 判断是否同一天
export function isSameDay(timeStampA, timeStampB) {
let dateA = new Date(timeStampA);
let dateB = new Date(timeStampB);
return (dateA.setHours(0, 0, 0, 0) == dateB.setHours(0, 0, 0, 0));
}
// 获取中文日期
export function get_zh_date(date = new Date()){
return `${new Date(date).getMonth()+1}${new Date(date).getDate()}`
}
export function substrDate(date){
if(!date)return;
return date.substr(0,10) || '-'
}
// package 貌似为保留字,作为参数时 编译报错
export function requestPayment(query = {}){
showLoad();
uni.requestPayment({
timeStamp: query.timeStamp || '',
nonceStr: query.nonceStr || '',
package: query.package || '',
signType: query.signType || '',
paySign: query.paySign || '',
success: function(res){
query.success&&query.success(res)
},
fail: function(res){
query.fail&&query.fail(res)
},
complete: function(res){
hideLoad();
query.complete&&query.complete(res)
},
})
}
function getQueryStr({url,name}){
let queryArr = (url.split('?')[1] || '').split("&") || [];
// let vars = query.split("&");
for (let i=0;i<queryArr.length;i++) {
let pair = queryArr[i].split("=");
if(pair[0] == name)return pair[1] || '';
}
return '';
}
// 小程序码参数 -> '{}'
function formatScene(sceneStr = ''){
let scene = decodeURIComponent(sceneStr);
let queryArr = scene.split('&');
return queryArr.reduce((obj,e,i)=>{
let _arr = e.split('=');
obj[_arr[0]] = _arr[1];
return obj;
},{}) || {};
}
function changeLowerCase(str){
return str.toString().toLocaleLowerCase();
}
export default {
formatTime,
formatNumber,
formatDate,
routeTo,
showNone,
showLoad,
hideLoad,
showModal,
debounce,
jsonStr,
jsonPar,
promisify,
previousPageFunction,
getNodeMes,
failAuthorizeTosetting,
getSceneQuery,
getUrlQuery,
getQueryString,
getRandom,
get_zh_day,
isSameDay,
get_zh_date,
substrDate,
requestPayment,
getQueryStr,
formatScene,
changeLowerCase
}
Loading…
Cancel
Save