Commit f2e2ba70 by celery

Initial commit

parents
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
{
"extends": [
"taro",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"rules": {
"import/prefer-default-export": 0,
"@typescript-eslint/no-var-requires": 0,
"import/no-commonjs": 0,
"no-unused-vars": [
"error",
{
"varsIgnorePattern": "Taro"
}
],
"react/jsx-filename-extension": [
1,
{
"extensions": [
".js",
".jsx",
".tsx"
]
}
],
"@typescript-eslint/no-unused-vars": [
"error",
{
"varsIgnorePattern": "Taro"
}
],
"@typescript-eslint/member-delimiter-style": [
"error",
{
"multiline": {
"delimiter": "none",
"requireLast": false
},
"singleline": {
"delimiter": "semi",
"requireLast": false
}
}
],
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/no-empty-function": [
"warn"
]
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"useJSXTextNode": true,
"project": "./tsconfig.json"
}
}
\ No newline at end of file
dist/
deploy_versions/
.temp/
.rn_temp/
node_modules/
.DS_Store
module.exports = {
env: {
NODE_ENV: '"development"'
},
defineConstants: {
},
mini: {},
h5: {}
}
const path = require('path')
const config = {
alias: {
'@components': path.resolve(__dirname, '..', 'src/components'),
'@utils': path.resolve(__dirname, '..', 'src/utils'),
'@assets': path.resolve(__dirname, '..', 'src/assets')
},
projectName: 'meeting',
date: '2020-5-19',
designWidth: 750,
deviceRatio: {
'640': 2.34 / 2,
'750': 1,
'828': 1.81 / 2
},
sourceRoot: 'src',
outputRoot: `dist/${process.env.TARO_ENV}`,
babel: {
sourceMap: true,
presets: [
['env', {
modules: false
}]
],
plugins: [
'transform-decorators-legacy',
'transform-class-properties',
'transform-object-rest-spread',
['transform-runtime', {
helpers: false,
polyfill: false,
regenerator: true,
moduleName: 'babel-runtime'
}
]
]
},
defineConstants: {
},
mini: {
postcss: {
autoprefixer: {
enable: true,
config: {
browsers: [
'last 3 versions',
'Android >= 4.1',
'ios >= 8'
]
}
},
pxtransform: {
enable: true,
config: {
}
},
url: {
enable: true,
config: {
limit: 10240 // 设定转换尺寸上限
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
},
h5: {
publicPath: '/',
staticDirectory: 'static',
esnextModules: ["taro-ui"],
postcss: {
autoprefixer: {
enable: true,
config: {
browsers: [
'last 3 versions',
'Android >= 4.1',
'ios >= 8'
]
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
}
}
module.exports = function (merge) {
if (process.env.NODE_ENV === 'development') {
return merge({}, config, require('./dev'))
}
return merge({}, config, require('./prod'))
}
module.exports = {
env: {
NODE_ENV: '"production"'
},
defineConstants: {
},
mini: {},
h5: {
/**
* 如果h5端编译后体积过大,可以使用webpack-bundle-analyzer插件对打包体积进行分析。
* 参考代码如下:
* webpackChain (chain) {
* chain.plugin('analyzer')
* .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
* }
*/
}
}
declare module "*.png";
declare module "*.gif";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.svg";
declare module "*.css";
declare module "*.less";
declare module "*.scss";
declare module "*.sass";
declare module "*.styl";
// @ts-ignore
declare const process: {
env: {
TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq';
[key: string]: any;
}
}
{
"name": "meeting",
"version": "1.0.0",
"private": true,
"description": "meeting",
"templateInfo": {
"name": "redux",
"typescript": true,
"css": "less"
},
"scripts": {
"build:weapp": "taro build --type weapp",
"build:swan": "taro build --type swan",
"build:alipay": "taro build --type alipay",
"build:tt": "taro build --type tt",
"build:h5": "taro build --type h5",
"build:rn": "taro build --type rn",
"build:qq": "taro build --type qq",
"build:quickapp": "taro build --type quickapp",
"dev:weapp": "npm run build:weapp -- --watch",
"dev:swan": "npm run build:swan -- --watch",
"dev:alipay": "npm run build:alipay -- --watch",
"dev:tt": "npm run build:tt -- --watch",
"dev:h5": "npm run build:h5 -- --watch",
"dev:rn": "npm run build:rn -- --watch",
"dev:qq": "npm run build:qq -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch"
},
"author": "",
"license": "MIT",
"dependencies": {
"@tarojs/components": "2.2.5",
"@tarojs/components-qa": "2.2.5",
"@tarojs/redux": "2.2.5",
"@tarojs/redux-h5": "2.2.5",
"@tarojs/router": "2.2.5",
"@tarojs/taro": "2.2.5",
"@tarojs/taro-alipay": "2.2.5",
"@tarojs/taro-h5": "2.2.5",
"@tarojs/taro-qq": "2.2.5",
"@tarojs/taro-quickapp": "2.2.5",
"@tarojs/taro-swan": "2.2.5",
"@tarojs/taro-tt": "2.2.5",
"@tarojs/taro-weapp": "2.2.5",
"babel-runtime": "^6.26.0",
"nerv-devtools": "^1.5.5",
"nervjs": "^1.5.5",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
"regenerator-runtime": "0.11.1",
"taro-ui": "^2.3.4"
},
"devDependencies": {
"@types/react": "^16.4.8",
"@types/webpack-env": "^1.13.6",
"@tarojs/mini-runner": "2.2.5",
"@tarojs/webpack-runner": "2.2.5",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-jsx-stylesheet": "^0.6.5",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1",
"babel-eslint": "^8.2.3",
"eslint": "^5.16.0",
"eslint-config-taro": "2.2.5",
"eslint-plugin-react": "^7.8.2",
"eslint-plugin-react-hooks": "^1.6.1",
"eslint-plugin-import": "^2.12.0",
"stylelint": "9.3.0",
"stylelint-config-taro-rn": "2.2.5",
"stylelint-taro-rn": "2.2.5",
"eslint-plugin-taro": "2.2.5",
"@typescript-eslint/eslint-plugin": "^2.13.0",
"@typescript-eslint/parser": "^2.13.0",
"typescript": "^3.0.1"
}
}
{
"miniprogramRoot": "dist/",
"projectname": "meeting",
"description": "meeting",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram",
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {}
}
\ No newline at end of file
import {
ADD,
MINUS
} from '../constants/counter'
export const add = () => {
return {
type: ADD
}
}
export const minus = () => {
return {
type: MINUS
}
}
// 异步的action
export function asyncAdd () {
return dispatch => {
setTimeout(() => {
dispatch(add())
}, 2000)
}
}
.container {
box-sizing: border-box;
background-color: #f4f4f4;
}
/* #ifdef weapp */
view, image, text, navigator {
box-sizing: border-box;
padding: 0;
margin: 0;
}
view, text {
// font-family: PingFangSC-Light, helvetica, 'Heiti SC';
font-size: 29px;
color: #333;
}
/* #endif */
/* #ifdef h5 */
div, img, span, navigator {
box-sizing: border-box;
padding: 0;
margin: 0;
}
div, span {
// font-family: PingFangSC-Light, helvetica, 'Heiti SC';
font-size: 29px;
color: #333;
}
/* #endif */
\ No newline at end of file
import Taro, { Component, Config } from '@tarojs/taro'
import { Provider } from '@tarojs/redux'
import 'taro-ui/dist/style/index.scss'
import Index from './pages/index'
import configStore from './store'
import './app.less'
// 如果需要在 h5 环境中开启 React Devtools
// 取消以下注释:
// if (process.env.NODE_ENV !== 'production' && process.env.TARO_ENV === 'h5') {
// require('nerv-devtools')
// }
const store = configStore()
class App extends Component {
/**
* 指定config的类型声明为: Taro.Config
*
* 由于 typescript 对于 object 类型推导只能推出 Key 的基本类型
* 对于像 navigationBarTextStyle: 'black' 这样的推导出的类型是 string
* 提示和声明 navigationBarTextStyle: 'black' | 'white' 类型冲突, 需要显示声明类型
*/
config: Config = {
pages: [
'pages/login/login',
'pages/index/index'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
}
}
// 在 App 类中的 render() 函数没有实际作用
// 请勿修改此函数
render () {
return (
<Provider store={store}>
<Index />
</Provider>
)
}
}
Taro.render(<App />, document.getElementById('app'))
export const baseUrl = 'https://gateway-beta.mingwork.com'
export const thirdUrl = "https://third-authentication-beta.mingwork.com";
\ No newline at end of file
export const ADD = 'ADD'
export const MINUS = 'MINUS'
const globalData = {}
export function set (key, val) {
globalData[key] = val
}
export function get (key) {
return globalData[key]
}
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="format-detection" content="telephone=no,address=no">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
<title></title>
<script>
!function(x){function w(){var v,u,t,tes,s=x.document,r=s.documentElement,a=r.getBoundingClientRect().width;if(!v&&!u){var n=!!x.navigator.appVersion.match(/AppleWebKit.*Mobile.*/);v=x.devicePixelRatio;tes=x.devicePixelRatio;v=n?v:1,u=1/v}if(a>=640){r.style.fontSize="40px"}else{if(a<=320){r.style.fontSize="20px"}else{r.style.fontSize=a/320*20+"px"}}}x.addEventListener("resize",function(){w()});w()}(window);
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
.index {
flex-direction: column;
width: 100%;
}
import { ComponentClass } from 'react'
import Taro, { Component, Config } from '@tarojs/taro'
import { View, Button, Text } from '@tarojs/components'
import { connect } from '@tarojs/redux'
import { add, minus, asyncAdd } from '../../actions/counter'
import './index.less'
// #region 书写注意
//
// 目前 typescript 版本还无法在装饰器模式下将 Props 注入到 Taro.Component 中的 props 属性
// 需要显示声明 connect 的参数类型并通过 interface 的方式指定 Taro.Component 子类的 props
// 这样才能完成类型检查和 IDE 的自动提示
// 使用函数模式则无此限制
// ref: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20796
//
// #endregion
type PageStateProps = {
counter: {
num: number
}
}
type PageDispatchProps = {
add: () => void
dec: () => void
asyncAdd: () => any
}
type PageOwnProps = {}
type PageState = {}
type IProps = PageStateProps & PageDispatchProps & PageOwnProps
interface Index {
props: IProps
}
@connect(({ counter }) => ({
counter
}), (dispatch) => ({
add () {
dispatch(add())
},
dec () {
dispatch(minus())
},
asyncAdd () {
dispatch(asyncAdd())
}
})
)
class Index extends Component {
/**
* 指定config的类型声明为: Taro.Config
*
* 由于 typescript 对于 object 类型推导只能推出 Key 的基本类型
* 对于像 navigationBarTextStyle: 'black' 这样的推导出的类型是 string
* 提示和声明 navigationBarTextStyle: 'black' | 'white' 类型冲突, 需要显示声明类型
*/
componentWillReceiveProps (nextProps) {
console.log(this.props, nextProps)
}
componentWillUnmount () { }
config: Config = {
navigationBarTitleText: '首页'
}
componentDidShow () { }
componentDidHide () { }
render () {
return (
<View className='index'>
<Button className='add_btn' onClick={this.props.add}>+</Button>
<Button className='dec_btn' onClick={this.props.dec}>-</Button>
<Button className='dec_btn' onClick={this.props.asyncAdd}>async</Button>
<View><Text>{this.props.counter.num}</Text></View>
<View><Text>Hello, World test 23dasdasd</Text></View>
</View>
)
}
}
// #region 导出注意
//
// 经过上面的声明后需要将导出的 Taro.Component 子类修改为子类本身的 props 属性
// 这样在使用这个子类时 Ts 才不会提示缺少 JSX 类型参数错误
//
// #endregion
export default Index as ComponentClass<PageOwnProps, PageState>
.login-box {
width: 100%;
height: auto;
overflow: hidden;
padding: 0 40px;
margin-top: 200px;
background: #fff;
}
.wx-login-btn {
margin: 60px 0 40px 0;
height: 96px;
line-height: 96px;
font-size: 30px;
border-radius: 6px;
width: 90%;
color: #fff;
right: 0;
display: flex;
justify-content: center;
align-items: center;
position: flex;
bottom: 0;
left: 0;
padding: 0;
margin-left: 5%;
text-align: center;
/* padding-left: -5px; */
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
border-top-right-radius: 50px;
border-bottom-right-radius: 50px;
letter-spacing: 3px;
}
.account-login-btn {
width: 90%;
margin: 0 auto;
color: #fff;
font-size: 30px;
height: 96px;
line-height: 96px;
right: 0;
display: flex;
justify-content: center;
align-items: center;
position: flex;
bottom: 0;
left: 0;
border-radius: 0;
padding: 0;
margin-left: 5%;
text-align: center;
/* padding-left: -5px; */
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
border-top-right-radius: 50px;
border-bottom-right-radius: 50px;
letter-spacing: 3px;
background-image: linear-gradient(to right, #9a9ba1 0%, #9a9ba1 100%);
}
import Taro , { Component } from '@tarojs/taro';
import { View , Button} from '@tarojs/components';
import { showErrorToast } from '@utils/toast';
import { set as setGlobalData } from '../../global_data';
import * as user from '../../services/user'
import './index.less';
class Login extends Component {
state = {}
config = {
navigationBarTitleText: '登录'
}
accountLogin = () => {
Taro.navigateTo({
url: "/pages/auth/accountLogin/accountLogin"
});
}
wxLogin = (e) => {
console.log('e', e);
if (e.detail.userInfo == undefined) {
setGlobalData('hasLogin', false)
showErrorToast('微信登录失败');
return;
}
user.checkLogin().catch(() => {
user.loginByWeixin({encryptedData: e.detail.encryptedData, iv: e.detail.iv}).then(() => {
setGlobalData('hasLogin', true)
Taro.navigateTo({
url: "/pages/index/index"
});
}).catch(() => {
setGlobalData('hasLogin', false)
showErrorToast('微信登录失败');
});
});
}
render() {
return (
<View className='container'>
<View className='login-box'>
<Button type='primary' openType='getUserInfo' className='wx-login-btn' onGetUserInfo={this.wxLogin}>微信直接登录</Button>
<Button type='primary' className='account-login-btn' onClick={this.accountLogin}>账号登录</Button>
</View>
</View>
);
}
}
export default Login;
import { ADD, MINUS } from '../constants/counter'
const INITIAL_STATE = {
num: 0
}
export default function counter (state = INITIAL_STATE, action) {
switch (action.type) {
case ADD:
console.log('add')
return {
...state,
num: state.num + 1
}
case MINUS:
return {
...state,
num: state.num - 1
}
default:
return state
}
}
import { combineReducers } from 'redux'
import counter from './counter'
export default combineReducers({
counter
})
import Taro from '@tarojs/taro'
import { baseUrl } from '../config'
import { logError } from '../utils/error'
export default {
baseOptions(params, method = 'GET') {
const { url, data } = params
let contentType = 'application/json'
contentType = params.contentType || contentType
type OptionType = {
url: string
data?: object | string
method?: any
header: object
// mode: string,
success: any
error: any
xhrFields: object
}
const option: OptionType = {
// 调用第三方的api把路径写全
url: url.indexOf('http') !== -1 ? url : baseUrl + url,
data: data,
method: method,
header: {
'content-type': contentType,
Authorization: Taro.getStorageSync('access-token')
},
// mode: 'cors',
xhrFields: { withCredentials: true },
success(res) {
console.log('res', res)
if (res.statusCode === '404') {
return logError('api', '请求资源不存在')
} else if (res.statusCode === '500') {
return logError('api', '服务端出现了问题')
} else if (res.statusCode === '401') {
Taro.clearStorage()
Taro.navigateTo({
url: '/pages/login/login'
})
return logError('api', '请先登录')
} else if (res.statusCode === '200') {
return res.data
}
},
error(e) {
logError('api', '请求接口出现问题', e)
}
}
// eslint-disable-next-line
return Taro.request(option)
},
get(url: string, data?: object) {
const option = { url, data }
return this.baseOptions(option)
},
postForm: function (url: string, data: object) {
const params = { url, data: Object.keys(data).map(key => `${key}=${data[key]}`).join('&'), contentType: 'application/x-www-form-urlencoded;charset=utf-8' }
return this.baseOptions(params, 'POST')
},
post: function (url: string, data?: object, contentType?: string) {
const params = { url, data, contentType }
return this.baseOptions(params, 'POST')
},
put(url: string, data?: object) {
const option = { url, data }
return this.baseOptions(option, 'PUT')
},
delete(url: string, data?: object) {
const option = { url, data }
return this.baseOptions(option, 'DELETE')
}
}
// function postForm(url, data, options) {
// const opts = {
// ...options,
// method: 'POST',
// cache: 'no-cache',
// headers: {
// 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
// },
// body: Object.keys(data).map(key => `${key}=${data[key]}`).join('&')
// };
// return xFetch(url, opts);
// }
import Taro from '@tarojs/taro';
import api from './api';
/**
* Promise封装wx.checkSession
*/
function checkSession() {
return new Promise(function(resolve, reject) {
Taro.checkSession({
success: function() {
resolve(true);
},
fail: function() {
reject(false);
}
})
});
}
/**
* Promise封装wx.login
*/
function login() {
return new Promise(function(resolve, reject) {
Taro.login({
success: function(res) {
if (res.code) {
resolve(res);
} else {
reject(res);
}
},
fail: function(err) {
reject(err);
}
});
});
}
/**
* 调用微信登录
*/
export function loginByWeixin(data) {
return new Promise(function(resolve, reject) {
return login().then((res) => {
console.log(res)
//登录远程服务器
Taro.setStorageSync('access-token', 'Basic bWVldGluZy13ZWI6bWVldGluZy13ZWI=')
api.postForm('/admin/skipAuth/getUserInfoByWeChatCode', {
code: res.code,
...data
}).then(loginRes => {
//存储用户信息
console.log(loginRes)
Taro.setStorageSync('userInfo', loginRes.userInfo);
Taro.setStorageSync('access-token', 'Bearer ' + loginRes.token);
resolve(loginRes);
}).catch(err => {
reject(err);
})
}).catch((err) => {
reject(err);
})
});
}
/**
* 判断用户是否登录
*/
export function checkLogin() {
return new Promise(function(resolve, reject) {
if (Taro.getStorageSync('userInfo') && Taro.getStorageSync('access-token')) {
checkSession().then(() => {
resolve(true);
}).catch(() => {
reject(false);
});
} else {
reject(false);
}
});
}
import { createStore, applyMiddleware, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from '../reducers'
const composeEnhancers =
typeof window === 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
}) : compose
const middlewares = [
thunkMiddleware
]
if (process.env.NODE_ENV === 'development' && process.env.TARO_ENV !== 'quickapp') {
middlewares.push(require('redux-logger').createLogger())
}
const enhancer = composeEnhancers(
applyMiddleware(...middlewares),
// other store enhancers if any
)
export default function configStore () {
const store = createStore(rootReducer, enhancer)
return store
}
export const formatNumber = (n: number | string): string => {
n = n.toString()
return n[1] ? n : '0' + n
}
// new Date() 转化为‘2020-05-21 14:00:00’
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(':')
}
import { formatTime } from './common'
/**
*
* @param {string} name 错误名字
* @param {string} action 错误动作描述
* @param {string} info 错误信息,通常是 fail 返回的
*/
// eslint-disable-next-line
export const logError = (name: string, action: string, info?: string | object ) => {
if (!info) {
info = 'empty'
}
const time = formatTime(new Date())
if (typeof info === 'object') {
info = JSON.stringify(info)
}
console.error(time, name, action, info)
}
import Taro from '@tarojs/taro';
export function showErrorToast(msg) {
Taro.showToast({
title: msg,
image: 'assets/images/icon_error.png'
})
}
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"removeComments": false,
"preserveConstEnums": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"noImplicitAny": false,
"allowSyntheticDefaultImports": true,
"outDir": "lib",
"noUnusedLocals": true,
"noUnusedParameters": true,
"strictNullChecks": true,
"sourceMap": true,
"baseUrl": ".",
"rootDir": ".",
"jsx": "preserve",
"jsxFactory": "Taro.createElement",
"allowJs": true,
"resolveJsonModule": true,
"typeRoots": [
"node_modules/@types"
]
},
"exclude": [
"node_modules",
"dist"
],
"compileOnSave": false
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment