Commit 868f5381 by 姜雷

建立页面

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"],
"rules": {
"no-unused-vars": ["error", { "varsIgnorePattern": "Taro" }],
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".tsx"] }]
},
"parser": "babel-eslint",
"plugins": ["typescript"]
}
dist/
.temp/
.rn_temp/
node_modules/
.DS_Store
module.exports = {
env: {
NODE_ENV: '"development"'
},
defineConstants: {
},
weapp: {},
h5: {}
}
const config = {
projectName: 'wx-school-app',
date: '2019-2-20',
designWidth: 750,
deviceRatio: {
'640': 2.34 / 2,
'750': 1,
'828': 1.81 / 2
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: {
babel: {
sourceMap: true,
presets: [
['env', {
modules: false
}]
],
plugins: [
'transform-decorators-legacy',
'transform-class-properties',
'transform-object-rest-spread'
]
}
},
defineConstants: {
},
copy: {
patterns: [
],
options: {
}
},
weapp: {
module: {
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',
module: {
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: {
},
weapp: {},
h5: {}
}
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";
{
"name": "wx-school-app",
"version": "1.0.0",
"private": true,
"description": "",
"scripts": {
"build:weapp": "npx taro build --type weapp",
"build:swan": "npx taro build --type swan",
"build:alipay": "npx taro build --type alipay",
"build:tt": "npx taro build --type tt",
"build:h5": "npx taro build --type h5",
"build:rn": "npx taro build --type rn",
"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"
},
"author": "",
"license": "MIT",
"dependencies": {
"@tarojs/async-await": "1.2.13",
"@tarojs/components": "1.2.13",
"@tarojs/redux": "1.2.13",
"@tarojs/redux-h5": "1.2.13",
"@tarojs/router": "1.2.13",
"@tarojs/taro": "1.2.13",
"@tarojs/taro-alipay": "1.2.13",
"@tarojs/taro-h5": "1.2.13",
"@tarojs/taro-swan": "1.2.13",
"@tarojs/taro-tt": "1.2.13",
"@tarojs/taro-weapp": "1.2.13",
"nervjs": "^1.3.9",
"nerv-devtools": "^1.3.9",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@types/react": "^16.4.8",
"@types/webpack-env": "^1.13.6",
"@tarojs/plugin-babel": "1.2.13",
"@tarojs/plugin-csso": "1.2.13",
"@tarojs/plugin-sass": "1.2.13",
"@tarojs/plugin-uglifyjs": "1.2.13",
"@tarojs/webpack-runner": "1.2.13",
"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-preset-env": "^1.6.1",
"babel-eslint": "^8.2.3",
"eslint": "^4.19.1",
"eslint-config-taro": "1.2.13",
"eslint-plugin-react": "^7.8.2",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-taro": "1.2.13",
"eslint-plugin-typescript": "^0.12.0",
"typescript": "^3.0.1"
}
}
{
"miniprogramRoot": "./dist",
"projectname": "wx-school-app",
"description": "",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}
.taro_router,
.taro_page {
width: 100%;
height: 100%;
}
import '@tarojs/async-await';
import Taro, { Component, Config } from '@tarojs/taro';
import { Provider } from '@tarojs/redux';
import Index from './pages/index';
import configStore from './store';
import './app.scss';
// 如果需要在 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/index/index',
'pages/Login/Login',
'pages/CheckTelephone/CheckTelephone',
'pages/Register/Register',
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black',
},
};
componentDidMount() {}
componentDidShow() {}
componentDidHide() {}
componentCatchError() {}
componentDidCatchError() {}
// 在 App 类中的 render() 函数没有实际作用
// 请勿修改此函数
render() {
return (
<Provider store={store}>
<Index />
</Provider>
);
}
}
Taro.render(<App />, document.getElementById('app'));
export const ADD = 'ADD'
export const MINUS = 'MINUS'
type globalData = {
APP_ID: string;
};
const globalData = {
APP_ID: '',
};
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>
.checkTelephone {
width: 100%;
height: 100%;
overflow: hidden;
background: url('../../images/login/bg@2x.png') center;
background-size: cover;
}
.loginBox {
width: 634px;
height: 538px;
margin: 180px auto 0;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 8px;
padding: 50px 40px 0;
line-height: 88px;
.loginBox-input {
box-sizing: border-box;
background-color: #fff;
width: 100%;
height: 88px;
padding: 0 20px;
font-size: 30px;
margin-bottom: 50px;
border-radius: 8px;
color: #ff9000;
}
.loginBox-input::-webkit-input-placeholder {
/* WebKit browsers */
color: #d9a842;
}
.loginBox-button {
font-size: 28px;
width: 100%;
height: 88px;
background-color: #ff9000;
color: #fff;
border: none;
outline: none;
border-radius: 8px;
}
.loginBox-button.big {
font-size: 34px;
}
.loginBox-button.fetching {
background-color: #ccc;
}
.loginBox-vcodeBox {
display: flex;
}
.vcodeBox-input-wrap {
flex: 1;
margin-right: 20px;
}
.vcodeBox-button-wrap {
text-align: center;
width: 200px;
height: 88px;
}
.countDownText {
color: #ff9000;
font-size: 30px;
}
}
.imgVcodeBox-wrap {
.imgVcodeBox-content {
width: 380px;
height: 332px;
}
.imgVcodeBox {
display: flex;
margin-bottom: 60px;
justify-content: space-between;
}
.imgVcodeBox-item {
width: 180px;
height: 88px;
background-color: #ffebcc;
border-radius: 8px;
}
.loginBox-input {
background-color: #ffebcc;
color: #d9a842;
}
}
import { ComponentClass } from 'react';
import Taro, { Component } from '@tarojs/taro';
import { View, Text, Button, Input } from '@tarojs/components';
import './CheckTelephone.scss';
type PageOwnProps = {};
type PageState = {
count: number;
timer: null;
fetching: boolean;
tel: string;
code: string;
sending: boolean;
vcode: string;
imgCode: string;
imgVcode: string;
dialogVisible: boolean;
};
interface CheckTelephone {
state: PageState;
}
class CheckTelephone extends Component {
constructor(props) {
super(props);
this.state = {
timer: null,
fetching: false,
tel: '',
code: '',
count: 60,
sending: false,
vcode: '',
imgCode: '',
imgVcode: '',
dialogVisible: false,
};
}
fetchImageVcode = () => {
console.log('in fetchImageVcode');
};
registerUser = () => {
Taro.navigateTo({
url: '/pages/Register/Register',
});
};
render() {
const { sending, count } = this.state;
return (
<View className='checkTelephone'>
<View className='loginBox'>
<Input
className='loginBox-input'
type='text'
placeholder='输入您的手机号'
/>
<View className='loginBox-vcodeBox'>
<View className='vcodeBox-input-wrap'>
<Input
className='loginBox-input'
type='text'
placeholder='请输入短信验证码'
/>
</View>
<View className='vcodeBox-button-wrap'>
{sending && <Text className='countDownText'>{{ count }}s</Text>}
<Button
v-else
className='loginBox-button'
onClick={this.fetchImageVcode}>
获取验证码
</Button>
</View>
</View>
<Button className='loginBox-button big' onClick={this.registerUser}>
登 录
</Button>
{/* // <ks-Dialog
// class="imgVcodeBox-wrap"
// :visible.sync="dialogVisible"
// top="180px"
// >
// <View class="imgVcodeBox-content">
// <View class="imgVcodeBox">
// <View class="imgVcodeBox-item">
// <input
// class="loginBox-input"
// type="text"
// v-model="imgCode"
// maxlength="6"
// />
// </View>
// <CodeView class="imgVcodeBox-item" :value="imgVcode"></CodeView>
// </View>
// <button v-if="fetching" class="loginBox-button big fetching">
// 确认
// </button>
// <button v-else class="loginBox-button big" @click="fetchVcode">
// 确认
// </button>
// </View>
// </ks-Dialog> */}
</View>
</View>
);
}
}
export default CheckTelephone as ComponentClass<PageOwnProps, PageState>;
.loadingBox {
margin: 50px auto;
padding: 50px;
}
import { ComponentClass } from 'react';
import Taro, { Component, Config } from '@tarojs/taro';
import { View, Button, Text } from '@tarojs/components';
import { connect } from '@tarojs/redux';
import './Login.scss';
type PageStateProps = {
APP_ID: string;
};
type PageOwnProps = {};
type PageState = {
loadingText: string;
};
type IProps = PageStateProps & PageOwnProps;
interface Login {
props: IProps;
state: PageState;
}
@connect(({ constants }) => ({
APP_ID: constants.APP_ID,
}))
class Login extends Component {
config: Config = {
navigationBarTitleText: '登录',
};
constructor(props) {
super(props);
this.state = {
loadingText: '载入中...',
};
}
componentWillMount() {
const { code } = this.$router.params;
if (code) {
this.setState({
loadingText: '微信授权中...',
});
setTimeout(() => {
console.log('跳转注册页');
Taro.navigateTo({
url: '/pages/CheckTelephone/CheckTelephone',
});
}, 3000);
} else {
console.log('跳转微信授权接口');
const { APP_ID } = this.props;
console.log(APP_ID);
let rUrl = encodeURIComponent(window.location.href.split('#')[0]);
// window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APP_ID}&redirect_uri=${rUrl}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`;
}
}
render() {
const { loadingText } = this.state;
return <View className='loadingBox'>{loadingText}</View>;
}
}
export default Login as ComponentClass<PageOwnProps, PageState>;
.loginBox.registerBox {
height: auto;
padding-bottom: 50px;
.loginBox-input-select {
box-sizing: border-box;
position: relative;
background-color: #fff;
width: 100%;
height: 88px;
padding: 0 20px;
font-size: 30px;
margin-bottom: 50px;
border-radius: 8px;
color: #d9a842;
.hasName {
color: #ff9000;
}
}
.loginBox-input-selectArrow {
position: absolute;
width: 30px;
height: 30px;
right: 20px;
top: 50%;
transform: translateY(-15px);
}
.popup-title {
height: 50px;
line-height: 50px;
display: flex;
justify-content: space-between;
.popup-btn {
padding: 0 30px;
}
}
.sexBox {
display: flex;
flex-direction: row;
color: #d9a842;
}
.choose-item {
display: inline-block;
align-items: center;
font-size: 30px;
margin-right: 50px;
.choose-name {
padding: 0 5px;
}
.choose-icon {
display: inline-block;
width: 25px;
height: 25px;
border: 1px solid #666;
border-radius: 50%;
vertical-align: middle;
position: relative;
}
.radioZT {
display: none;
}
.choose-icon.checked {
border-color: #ee7d1f;
}
.choose-icon.checked::after {
content: '';
display: block;
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #ee7d1f;
transform: scale(0.5);
}
}
.weui-cells_checkbox .weui-icon-checked:before,
.choose-item.checked {
color: #ee7d1f;
}
}
import { ComponentClass } from 'react';
import Taro, { Component } from '@tarojs/taro';
import {
View,
Text,
Button,
Input,
RadioGroup,
Radio,
Label,
} from '@tarojs/components';
import '../CheckTelephone/CheckTelephone.scss';
import './Register.scss';
type PageOwnProps = {};
type PageState = {
name: string;
pwd: string;
sex: string;
};
interface Register {
state: PageState;
}
class Register extends Component {
constructor(props) {
super(props);
this.state = {
name: '',
pwd: '',
sex: '',
};
}
showCampusSelector = () => {};
setSex = ({ detail: { value } }) => {
this.setState({
sex: value,
});
};
updateName = () => {};
getRegister = () => {
console.log('跳转首页');
};
render() {
const { name, sex } = this.state;
return (
<View className='checkTelephone'>
<View className='loginBox registerBox'>
<View
className='loginBox-input-select'
onClick={this.showCampusSelector}>
{/* <template v-if="userInfo.campusId">
<Text className="hasName">{{userInfo.campusName}}</Text>
</template>
<template v-else>
<Text>请输入您所在的校区</Text>
<View className="loginBox-input-selectArrow">
<img
src="../../../images/login/right-Arr@2x.png"
alt
/>
</View>
</template> */}
</View>
<Input
className='loginBox-input'
value={name}
onInput={this.updateName}
placeholder='输入您的姓名'
maxLength={20}
/>
<Input
className='loginBox-input'
password
placeholder='输入您的密码'
maxLength={20}
/>
<RadioGroup className='loginBox-input sexBox' onChange={this.setSex}>
<Label className={`choose-item ${sex == 'Male' ? 'checked' : ''}`}>
<Radio value='Male'></Radio>
</Label>
<Label
className={`choose-item ${sex == 'Female' ? 'checked' : ''}`}>
<Radio value='Female'></Radio>
</Label>
</RadioGroup>
{/* <View :className="{'choose-item': true, checked: checkMale }">
<Text className="choose-name">男</Text>
<Text :className="{'choose-icon': true, checked: checkMale }"></Text>
<Input
name="sex"
value="Male"
type="radio"
className="radioZT"
v-model="sex"
/>
</View> */}
{/* <View :className="{'choose-item': true, checked: checkFemale}">
<Text className="choose-name">女</Text>
<Text :className="{'choose-icon': true, checked: checkFemale}"></Text>
<Input
name="sex"
value="Female"
type="radio"
className="radioZT"
v-model="sex"
/>
</View> */}
<Button className='loginBox-button big' onClick={this.getRegister}>
注册
</Button>
</View>
</View>
);
}
}
export default Register as ComponentClass<PageOwnProps, PageState>;
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.scss';
// #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;
}
class Index extends Component {
/**
* 指定config的类型声明为: Taro.Config
*
* 由于 typescript 对于 object 类型推导只能推出 Key 的基本类型
* 对于像 navigationBarTextStyle: 'black' 这样的推导出的类型是 string
* 提示和声明 navigationBarTextStyle: 'black' | 'white' 类型冲突, 需要显示声明类型
*/
config: Config = {
navigationBarTitleText: '首页',
};
componentWillReceiveProps(nextProps: IProps) {
console.log(this.props, nextProps);
}
componentWillUnmount() {}
componentDidShow() {}
componentDidHide() {}
navToLogin() {
Taro.navigateTo({
url: '/pages/Login/Login',
});
}
render() {
return (
<View className='index'>
<View>
<Text>{this.props.counter.num}</Text>
</View>
<View>
<Text>Hello, World</Text>
</View>
<Button className='dec_btn' onClick={this.navToLogin}>
登录
</Button>
</View>
);
}
}
// #region 导出注意
//
// 经过上面的声明后需要将导出的 Taro.Component 子类修改为子类本身的 props 属性
// 这样在使用这个子类时 Ts 才不会提示缺少 JSX 类型参数错误
//
// #endregion
export default Index as ComponentClass<PageOwnProps, PageState>;
type INITIAL_STATE = {
APP_ID: string;
};
const INITIAL_STATE = {
APP_ID: 'wxf5912b79bba23663',
};
export default function counter(state = INITIAL_STATE) {
return state;
}
import { ADD, MINUS } from '../constants/counter'
const INITIAL_STATE = {
num: 0
}
export default function counter (state = INITIAL_STATE, action) {
switch (action.type) {
case ADD:
return {
...state,
num: state.num + 1
}
case MINUS:
return {
...state,
num: state.num - 1
}
default:
return state
}
}
import { combineReducers } from 'redux';
import constants from './constants';
import counter from './counter';
export default combineReducers({
constants,
counter,
});
interface StoreState {
login: boolean;
token: string;
id: string;
campusId: string;
name: string;
headPic: string;
}
const INITIAL_STATE = {
login: false,
token: '',
id: '',
campusId: '',
name: '',
headPic: '',
};
export default function userinfo(state: StoreState = INITIAL_STATE) {
return state;
}
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') {
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
}
import { combineReducers } from 'redux';
import constants from './rootReducers/constants';
import userinfo from './rootReducers/userinfo';
export default combineReducers({
constants,
userinfo,
});
type INITIAL_STATE = {
APP_ID: string;
};
const INITIAL_STATE = {
APP_ID: 'wxf5912b79bba23663',
};
export default function counter(state = INITIAL_STATE) {
return state;
}
interface StoreState {
login: boolean;
token: string;
id: string;
campusId: string;
name: string;
headPic: string;
}
const INITIAL_STATE = {
login: false,
token: '',
id: '',
campusId: '',
name: '',
headPic: '',
};
export default function userinfo(state: StoreState = INITIAL_STATE) {
return state;
}
{
"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,
"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