feat: taro

This commit is contained in:
NICE CODE BY DEV 2022-05-25 12:31:42 +08:00
parent 671157aee5
commit e3ce650ef8
39 changed files with 14103 additions and 32 deletions

16
.editorconfig Normal file
View File

@ -0,0 +1,16 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
quote_type = single
[*.js, *.jsx, *.ts, *.tsx]
quote_type = single
[*.md]
trim_trailing_whitespace = false

4
.eslintrc.js Normal file
View File

@ -0,0 +1,4 @@
module.exports = {
extends: [],
rules: {},
};

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
dist/
deploy_versions/
.temp/
.rn_temp/
node_modules/
.DS_Store

46
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,46 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": [
"javascript",
"react",
"typescript",
"typescriptreact",
"vue"
],
"editor.formatOnSave": true,
"[typescriptreact]": {
"editor.defaultFormatter": null
},
"[javascript]": {
"editor.defaultFormatter": null
},
"[typescript]": {
"editor.defaultFormatter": null
},
"[javascriptreact]": {
"editor.defaultFormatter": null
},
"[vue]": {
"editor.defaultFormatter": null
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[md]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}

View File

@ -1,34 +1,7 @@
## 目前已有脚手架列表
# YOUR_PROJECT_NAME
| 名称 | 说明 | 技术栈 |
| ------- | --------------------------- | --------------------- |
| nextJs | 基于 React 的服务端渲染方案 | nextJs + axios + antd |
| ReactJs | 基于 React 的业务型脚手架 | umiJs + axios + antd |
| TaroJs | 基于 React 的多端适配方案 | TaroJs 全家桶 |
| Vue | 基于 Vue 的业务型脚手架 | vueJs 全家桶 |
| Gulp | 基于 Gulp 的清凉型脚手架 | -- |
## 项目介绍
## 技术栈
## 快速上手
### 1. 安装相关依赖
```js
// 推荐
yarn global add @nicecode/cli
// or
// npm install @nicecode/cli -g
```
### 2. 运行命令
```js
// 查看脚手架版本号,是否安装成功
nice - V
```
### 3. 创建项目
```js
nice create ${项目名称}
```
- Taro
- scss

14
babel.config.js Normal file
View File

@ -0,0 +1,14 @@
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
sourceMap: false,
presets: [
[
'taro',
{
framework: 'react',
ts: true,
},
],
],
};

10
config/dev.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
env: {
NODE_ENV: '"test"',
BASE_URL: '""', // 小程序使用,直接请求
BASE_API: '"/api"', // h5使用代理请求
},
defineConstants: {},
mini: {},
h5: {},
};

86
config/index.js Normal file
View File

@ -0,0 +1,86 @@
const path = require('path');
const config = {
projectName: 'taro-template',
date: '2020-9-23',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2,
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: [],
defineConstants: {},
copy: {
patterns: [],
options: {},
},
framework: 'react',
alias: {
'@': path.resolve(__dirname, '..', 'src'),
},
mini: {
postcss: {
pxtransform: {
enable: true,
config: {},
},
url: {
enable: true,
config: {
limit: 1024, // 设定转换尺寸上限
},
},
cssModules: {
enable: true, // 默认为 false如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
},
},
h5: {
publicPath: '/',
staticDirectory: 'static',
postcss: {
autoprefixer: {
enable: true,
config: {},
},
cssModules: {
enable: true, // 默认为 false如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]',
},
},
},
esnextModules: ['taro-ui'],
devServer: {
proxy: {
'/api': {
target: 'http://mock.uniubi.com',
pathRewrite: {
'^/api': '',
},
},
},
},
},
};
module.exports = function (merge) {
if (process.env.NODE_ENV === 'dev') {
return merge({}, config, require('./dev'));
} else if (process.env.NODE_ENV === 'test') {
return merge({}, config, require('./test'));
} else if (process.env.NODE_ENV === 'release') {
return merge({}, config, require('./release'));
} else if (process.env.NODE_ENV === 'pre') {
return merge({}, config, require('./pre'));
}
return merge({}, config, require('./prod'));
};

10
config/pre.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
env: {
NODE_ENV: '"pre"',
BASE_URL: '""', // 小程序使用,直接请求
BASE_API: '"/api"', // h5使用代理请求
},
defineConstants: {},
mini: {},
h5: {},
};

19
config/prod.js Normal file
View File

@ -0,0 +1,19 @@
module.exports = {
env: {
NODE_ENV: '"production"',
BASE_URL: '""', // 小程序使用,直接请求
BASE_API: '"/api"', // h5使用代理请求
},
defineConstants: {},
mini: {},
h5: {
/**
* 如果h5端编译后体积过大可以使用webpack-bundle-analyzer插件对打包体积进行分析
* 参考代码如下
* webpackChain (chain) {
* chain.plugin('analyzer')
* .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
* }
*/
},
};

10
config/release.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
env: {
NODE_ENV: '"release"',
BASE_URL: '""', // 小程序使用,直接请求
BASE_API: '"/api"', // h5使用代理请求
},
defineConstants: {},
mini: {},
h5: {},
};

10
config/test.js Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
env: {
NODE_ENV: '"test"',
BASE_URL: '""', // 小程序使用,直接请求
BASE_API: '"/api"', // h5使用代理请求
},
defineConstants: {},
mini: {},
h5: {},
};

27
global.d.ts vendored Normal file
View File

@ -0,0 +1,27 @@
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'
| 'jd';
[key: string]: any;
};
};

103
package.json Normal file
View File

@ -0,0 +1,103 @@
{
"name": "taro-template",
"version": "1.0.0",
"private": true,
"description": "Taro 项目模版",
"templateInfo": {
"name": "default",
"typescript": true,
"css": "sass"
},
"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:jd": "taro build --type jd",
"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:jd": "npm run build:jd -- --watch",
"dev:quickapp": "npm run build:quickapp -- --watch",
"build:test": "cross-env NODE_ENV=test taro build --type h5",
"build:release": "cross-env NODE_ENV=release taro build --type h5",
"build:pre": "cross-env NODE_ENV=pre taro build --type h5",
"build:production": "cross-env NODE_ENV=production taro build --type h5",
"build:weapp:test": "cross-env NODE_ENV=test taro build --type weapp",
"build:weapp:release": "cross-env NODE_ENV=release taro build --type weapp",
"build:weapp:pre": "cross-env NODE_ENV=pre taro build --type weapp",
"build:weapp:production": "cross-env NODE_ENV=production taro build --type weapp",
"lint": "eslint 'src/**/*.{js,jsx,tsx,ts}'",
"lint:fix": "eslint 'src/**/*.{js,jsx,tsx,ts}' --fix",
"prettier": "prettier --write 'src/**/*.{less,scss,css,md,json}'"
},
"browserslist": [
"last 3 versions",
"Android >= 4.1",
"ios >= 8"
],
"author": "Json",
"dependencies": {
"@babel/runtime": "^7.7.7",
"@tarojs/components": "3.0.21",
"@tarojs/helper": "^3.0.21",
"@tarojs/react": "3.0.21",
"@tarojs/runtime": "3.0.21",
"@tarojs/taro": "3.0.21",
"classnames": "^2.2.6",
"react": "^16.10.0",
"react-dom": "^16.10.0",
"taro-ui": "3.0.0-alpha.3"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/helper-compilation-targets": "^7.12.5",
"@babel/helper-create-class-features-plugin": "^7.12.1",
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-decorators": "^7.12.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-json-strings": "^7.8.3",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-syntax-numeric-separator": "^7.10.4",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
"@babel/plugin-transform-typescript": "^7.12.1",
"@babel/preset-env": "^7.12.11",
"@tarojs/mini-runner": "3.0.21",
"@tarojs/plugin-sass": "^2.2.10",
"@tarojs/webpack-runner": "3.0.21",
"@types/react": "^16.0.0",
"@types/webpack-env": "^1.13.6",
"babel-plugin-transform-jsx-stylesheet": "^1.0.0",
"babel-preset-taro": "3.0.21",
"cross-env": "^7.0.2",
"end-type-to-front-type": "^1.2.1",
"eslint": "^7.32.0",
"husky": "^7.0.2",
"lint-staged": "^11.1.2",
"prettier": "^2.3.2",
"stylelint": "9.3.0",
"typescript": "^4.4.2",
"yorkie": "^2.0.0"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,tsx,ts}": [
"npm run lint:fix",
"git add ."
],
"*.{less,scss,css,md,json}": [
"npm run prettier",
"git add ."
]
}
}

13
project.config.json Normal file
View File

@ -0,0 +1,13 @@
{
"miniprogramRoot": "./dist",
"projectname": "taro-template",
"description": "Trao 项目模版",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}

9
src/app.config.ts Normal file
View File

@ -0,0 +1,9 @@
export default {
pages: ['pages/index/index'],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black',
},
};

13
src/app.ts Normal file
View File

@ -0,0 +1,13 @@
import { Component } from 'react';
import './styles/custom-variables.scss';
import './styles/reset.scss';
import './styles/index.scss';
class App extends Component {
// this.props.children 是将要会渲染的页面
render() {
return this.props.children;
}
}
export default App;

View File

@ -0,0 +1 @@
{}

1
src/assets/data/enums.ts Normal file
View File

@ -0,0 +1 @@
export const DEMO_MAP = new Map([[1, 'demo 1']]);

View File

@ -0,0 +1,8 @@
import React from 'react';
import { View } from '@tarojs/components';
const Demo: Taro.FC = () => {
return <View>demo</View>;
};
export default Demo;

19
src/index.html Normal file
View File

@ -0,0 +1,19 @@
<!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>

26
src/interface/base.ts Normal file
View File

@ -0,0 +1,26 @@
export interface BaseProps {
className?: string;
style?: React.CSSProperties;
children?: React.ReactNode;
}
export interface Pagination {
total: number;
size: number;
index: number;
length: number;
beginIndex: number;
endIndex: number;
}
export interface BaseResponse {
code: string;
msg: string;
memo: string;
data: any;
pagination?: Pagination;
result: number;
success: boolean;
requestId: string;
linkTime: number;
}

View File

@ -0,0 +1,3 @@
export default {
navigationBarTitleText: '首页',
};

View File

@ -0,0 +1,4 @@
.container {
width: 400px;
margin: 0 auto;
}

25
src/pages/index/index.tsx Normal file
View File

@ -0,0 +1,25 @@
import React from 'react';
import { View, Text } from '@tarojs/components';
import { AtButton } from 'taro-ui';
import Demo from '@/components/Demo';
import styles from './index.module.scss';
import { chooseImage } from '@/utils';
const Index: Taro.FC = () => {
const upload = async () => {
const res = await chooseImage();
console.log(res);
};
return (
<View className={styles.container}>
<Text>Hello world!</Text>
<Demo />
<AtButton type="primary" onClick={upload}>
AtButton
</AtButton>
</View>
);
};
export default Index;

View File

@ -0,0 +1,8 @@
@import './var.scss';
$color-brand: $S3;
$color-success: $F-green;
$color-error: $F-red;
/* 引入 Taro UI 默认样式 */
@import '~taro-ui/dist/style/index.scss';

2
src/styles/index.scss Normal file
View File

@ -0,0 +1,2 @@
@import './custom-variables.scss';
@import './var.scss';

441
src/styles/reset.scss Normal file
View File

@ -0,0 +1,441 @@
@import './var.scss';
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin: 0;
padding: 0;
border: 0;
font: inherit;
font-family: 'PingFang SC', 'Heiti SC', 'Microsoft YaHei', Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
vertical-align: baseline;
box-sizing: border-box;
}
html,
body {
min-height: 100vh;
height: auto;
}
/* make sure to set some focus styles for accessibility */
:focus {
outline: 0;
}
/* HTML5 display-role reset for older browsers */
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
display: block;
}
body {
line-height: 1;
}
ol,
ul {
list-style: none;
}
blockquote,
q {
quotes: none;
}
blockquote:before,
blockquote:after,
q:before,
q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input[type='search']::-webkit-search-cancel-button,
input[type='search']::-webkit-search-decoration,
input[type='search']::-webkit-search-results-button,
input[type='search']::-webkit-search-results-decoration {
-webkit-appearance: none;
-moz-appearance: none;
}
input[type='search'] {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
textarea {
overflow: auto;
vertical-align: top;
resize: vertical;
}
/**
* Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
max-width: 100%;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/**
* 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a {
text-decoration: none;
}
a:focus {
outline: none;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/**
* 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improve image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/**
* Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/**
* Correct margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct color not being inherited in IE 6/7/8/9.
* 2. Correct text not wrapping in Firefox 3.
* 3. Correct alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
}
/**
* 1. Correct font size not being inherited in all browsers.
* 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improve appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
}
/**
* Address Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
* 4. Remove inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to content-box in IE 8/9.
* 2. Remove excess padding in IE 8/9.
* 3. Remove excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type='checkbox'],
input[type='radio'] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type='search'] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type='search']::-webkit-search-cancel-button,
input[type='search']::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 6/7/8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
html,
button,
input,
select,
textarea {
color: #222;
}
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
img {
vertical-align: middle;
}
fieldset {
border: 0;
margin: 0;
padding: 0;
}
textarea {
resize: vertical;
}

93
src/styles/var.scss Normal file
View File

@ -0,0 +1,93 @@
/* UI 规范 */
/* 颜色 */
$S1: #002952;
$S2: #106ecc;
$S3: #148aff;
$S4: #5cadff;
$S5: #85c2ff;
$S6: #cce6ff;
$M1: #0e1114;
$M2: #33383d;
$M3: #565e66;
$M4: #83898f;
$M5: #bfc3c7;
$M6: #e6e8eb;
$M7: #f0f2f5;
$M8: #fafbfc;
$M9: #ffffff;
$M10: #000000;
$D1: #fac105;
$D2: #ffab24;
$D3: #ff6952;
$D4: #ff3c73;
$D5: #ee62d5;
$D6: #8475ff;
$D7: #4f73ff;
$D8: #2e9cff;
$D9: #0cc0c9;
$D10: #0cc991;
$D11: #83d615;
$D1-1: #fef8e5;
$D2-1: #fff6e9;
$D3-1: #fff0ed;
$D4-1: #ffebf1;
$D5-1: #fdeffa;
$D6-1: #f2f1ff;
$D7-1: #edf1ff;
$D8-1: #eaf5ff;
$D9-1: #e6f8f9;
$D10-1: #e6f9f3;
$D11-1: #f2fae7;
$F-blue: #29b8ff;
$F-green: #46cf84;
$F-yellow: #ffa42e;
$F-red: #ff475a;
/* 字体 */
$Fs-1: 12px;
$Fs-2: 14px;
$Fs-3: 16px;
$Fs-4: 18px;
$Fs-5: 20px;
$Fs-6: 22px;
$Fs-7: 24px;
$Fs-8: 28px;
$Fs-9: 32px;
/* 行高 */
$Lh-1: 20px;
$Lh-2: 22px;
$Lh-3: 24px;
$Lh-4: 26px;
$Lh-5: 28px;
$Lh-6: 30px;
$Lh-7: 32px;
$Lh-8: 36px;
$Lh-9: 42px;
/* 间距 */
$Sp-1: 2px;
$Sp-2: 4px;
$Sp-3: 8px;
$Sp-4: 10px;
$Sp-5: 12px;
$Sp-6: 16px;
$Sp-7: 20px;
$Sp-8: 24px;
$Sp-9: 30px;
$Sp-10: 32px;
$Sp-11: 40px;
/* 阴影 */
$Sh-1: 0 0 8px 0 rgba(0, 0, 0, 0.05);
$Sh-2: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
$Sh-3: 0 0 12px 0 rgba(0, 0, 0, 0.1);
$Sh-4: -4px 0 20px 0 rgba(0, 0, 0, 0.1);
$Sh-5: 0 2px 20px 0 rgba(0, 0, 0, 0.3);
/* 圆角 */
$Ra-1: 2px;
$Ra-2: 3px;
$Ra-3: 6px;
$Ra-4: 10px;
/* $Ra-5: (元素高的一半) / 50% */

26
src/utils/cache.ts Normal file
View File

@ -0,0 +1,26 @@
/**
*
*/
import Taro from '@tarojs/taro';
export enum CacheKey {
Key = 'key',
}
export class Cache {
static get(key: CacheKey) {
return Taro.getStorageSync(key);
}
static set(key: CacheKey, data: any, isSync = false) {
if (isSync) {
Taro.setStorage({ key, data });
} else {
Taro.setStorageSync(key, data);
}
}
static remove(key: CacheKey) {
Taro.removeStorageSync(key);
}
}

16
src/utils/common.ts Normal file
View File

@ -0,0 +1,16 @@
import Taro from '@tarojs/taro';
/**
*
* @param path
* @returns
*/
export const initVoice = (path: string) => {
let voiceContext: Taro.InnerAudioContext = {} as any;
voiceContext = Taro.createInnerAudioContext();
voiceContext.src = path;
voiceContext.onEnded(() => {
voiceContext.destroy();
});
return voiceContext;
};

34
src/utils/event.ts Normal file
View File

@ -0,0 +1,34 @@
import { useState, useEffect } from 'react';
import { Events } from '@tarojs/taro';
const globalEvent = new Events();
// 通知事件key
export enum EventsKey {
Demo = 'demo',
}
// 监听和关闭事件的hooks
export const useEvents = (
key: EventsKey,
listener: (info?: any) => void,
isUse = true,
) => {
// 监听事件实例;
const [eventInstance, setEventInstance] = useState<any>();
useEffect(() => {
if (isUse) {
const event = globalEvent.on(key, listener);
setEventInstance(event);
}
return () => {
eventInstance && globalEvent.off(key);
};
}, []);
};
// 通知方法
export const triggerEvent = (key: EventsKey, info?: any) => {
globalEvent.trigger(key, info);
};

122
src/utils/file.ts Normal file
View File

@ -0,0 +1,122 @@
import { Toast } from '@/utils/toast';
import Taro from '@tarojs/taro';
import { Loading } from './loading';
/**
*
* @param option http://taro-docs.jd.com/taro/docs/apis/media/image/chooseImage/
* @returns Promise<any>
*/
export const chooseImage = (option?: Taro.chooseImage.Option): Promise<any> => {
const { count = 1, sourceType = ['album', 'camera'], ...rest } = option || {};
return new Promise((resolve, reject) => {
Taro.chooseImage({
count,
sourceType,
...rest,
sizeType: ['compressed'],
success: (res) => {
resolve(res);
},
fail: (e) => {
reject(e);
},
});
});
};
/**
*
* @param option https://taro-docs.jd.com/taro/docs/apis/network/upload/uploadFile
* @returns Promise<any>
*/
export const uploadFile = (option: Taro.uploadFile.Option): Promise<any> => {
Loading.show();
return new Promise((resolve, reject) => {
Taro.uploadFile({
...option,
success(res) {
if (res.statusCode === 200 && res.data) {
const data = JSON.parse(res.data);
resolve(data.success ? data.data : false);
} else {
resolve(true);
}
},
fail(e) {
Toast.info('上传失败');
reject(e);
},
complete() {
Loading.hide();
},
});
});
};
/**
* OSS
* @param superKey superKey
* @returns
*/
export const getSignature = async (superKey: string) => {
try {
const params = { superKey };
// TODO: 根据业务修改获取 signature 方法
// const res = await fn(params);
const res: any = { ...params, success: true };
if (res.success) {
return res.data;
}
} catch (err) {
console.log(err);
}
};
/**
* OSS
* @param tempFile
* @param superKey OSS superKey
* @returns OSS
*/
export const uploadOSS = async (
tempFile: Taro.chooseImage.ImageFile | Taro.chooseMessageFile.ChooseFile,
superKey: string,
) => {
// 获取上传oss参数
const oss = await getSignature(superKey);
if (oss) {
// 无法获取图片名称,采用时间戳作为文件名
const fileName = (tempFile as any)?.name
// BUG
? `${+new Date()}`
: `${+new Date()}`;
const key = `${superKey}/${fileName}`;
const { dir, policy, accessId: OSSAccessKeyId, signature, host } = oss;
try {
// 上传至 oss
const res = await uploadFile({
url: host,
name: fileName,
filePath: tempFile.path,
formData: {
dir,
policy,
OSSAccessKeyId,
signature,
key,
success_action_status: '200',
},
});
if (res) {
// 返回文件地址
return `${host}/${key}`;
} else {
Toast.info('上传失败');
}
} catch (e) {
console.log('e', e);
}
}
};

6
src/utils/index.ts Normal file
View File

@ -0,0 +1,6 @@
export { initVoice } from './common';
export { Cache, CacheKey } from './cache';
export { Toast } from './toast';
export { useEvents, EventsKey } from './event';
export { chooseImage, uploadFile } from './file';
export { Loading } from './loading';

16
src/utils/loading.ts Normal file
View File

@ -0,0 +1,16 @@
import Taro from '@tarojs/taro';
export class Loading {
static show(option?: Partial<Taro.showLoading.Option>) {
const { title = 'loading...', mask = true, ...rest } = option || {};
Taro.showLoading({
title,
mask,
...rest,
});
}
static hide() {
Taro.hideLoading();
}
}

50
src/utils/request.ts Normal file
View File

@ -0,0 +1,50 @@
import Taro from '@tarojs/taro';
import { BaseResponse } from '@/interface/base';
import CodeMsg from '@/assets/data/code.json';
export const DEFAULT_TIP_MESSAGE = '请求失败,请刷新重试';
/**
*
* @param {Object} data
*/
export function handleError(data) {
const message = CodeMsg[data.code] || data.msg || DEFAULT_TIP_MESSAGE;
Taro.atMessage({
message,
type: 'error',
});
}
const request = (options) => {
return new Promise<BaseResponse>((resolve, reject) => {
Taro.request({
timeout: 5000,
mode: 'cors',
success(res) {
const { data } = res;
if (!data.success) {
handleError(data);
}
resolve(data);
},
fail(err) {
Taro.atMessage({ message: DEFAULT_TIP_MESSAGE, type: 'error' });
reject(err);
// for debug
console.log(err);
},
...options,
header: {
'content-type': 'application/json', // 默认值
token: Taro.getStorageSync('token'),
...options.header,
},
url: `${process.env.BASE_URL || ''}${process.env.BASE_API || ''}${
options.url || ''
}`,
});
});
};
export default request;

85
src/utils/toast.ts Normal file
View File

@ -0,0 +1,85 @@
import Taro from '@tarojs/taro';
const DEFAULT_TOAST_TIME = 3000;
// 文档
// showToast http://taro-docs.jd.com/taro/docs/apis/ui/interaction/showToast/
// showModal: http://taro-docs.jd.com/taro/docs/apis/ui/interaction/showModal/
export class Toast {
static info(msg: string, option?: Taro.showToast.Option) {
const {
title,
icon,
duration = DEFAULT_TOAST_TIME,
...rest
} = option || {};
Taro.showToast({
icon: 'none',
title: msg,
duration,
...rest,
});
}
static success(msg: string, option?: Taro.showToast.Option) {
const {
title,
icon,
duration = DEFAULT_TOAST_TIME,
...rest
} = option || {};
Taro.showToast({
title: msg,
icon: 'success',
duration,
...rest,
});
}
static alert({
title = '提示',
showCancel,
success,
fail,
...rest
}: Taro.showModal.Option) {
Taro.showModal({
title,
showCancel: false,
success: (res) => {
if (res.confirm) {
success && success(res);
}
},
...rest,
});
}
static confirm({
confirmText = '确定',
cancelText = '取消',
success,
fail,
showCancel,
confirmColor = '#16953C',
...rest
}: Taro.showModal.Option) {
Taro.showModal({
confirmText,
cancelText,
showCancel: true,
confirmColor,
success: (res) => {
if (res.confirm) {
success && success(res);
} else if (res.cancel) {
fail && fail(res);
}
},
...rest,
});
}
}
// export default Toast;

29
tsconfig.json Normal file
View File

@ -0,0 +1,29 @@
{
"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": ".",
"paths": {
"@/*": ["./src/*"]
},
"rootDir": ".",
"jsx": "react",
"jsxFactory": "React.createElement",
"allowJs": true,
"resolveJsonModule": true,
"typeRoots": ["node_modules/@types", "global.d.ts"]
},
"exclude": ["node_modules", "dist"],
"compileOnSave": false
}

12687
yarn.lock Normal file

File diff suppressed because it is too large Load Diff