Browse Source

Merge branch 'dev' of https://gitea.anxinyun.cn/gao.zhiyuan/Highways4Good into dev

release_0.0.1
巴林闲侠 3 years ago
parent
commit
9a0536d920
  1. 12
      weapp/.editorconfig
  2. 3
      weapp/.eslintrc.js
  3. 6
      weapp/.gitignore
  4. 0
      weapp/README.md
  5. 10
      weapp/babel.config.js
  6. 9
      weapp/config/dev.js
  7. 93
      weapp/config/index.js
  8. 18
      weapp/config/prod.js
  9. 14
      weapp/jsconfig.json
  10. 15645
      weapp/package-lock.json
  11. 69
      weapp/package.json
  12. 46
      weapp/project.config.json
  13. 7
      weapp/project.private.config.json
  14. 54
      weapp/src/actions/auth.js
  15. 12
      weapp/src/actions/business.js
  16. 41
      weapp/src/actions/fetcher.js
  17. 49
      weapp/src/app.config.js
  18. 52
      weapp/src/app.jsx
  19. 256
      weapp/src/app.scss
  20. 39
      weapp/src/components/calenda/index.js
  21. 11
      weapp/src/components/calenda/index.scss
  22. 24
      weapp/src/components/chart/chart.jsx
  23. 90
      weapp/src/components/datePicker/filterPicker.jsx
  24. 6
      weapp/src/components/datePicker/filterPicker.scss
  25. 126
      weapp/src/components/datePicker/format.js
  26. 188
      weapp/src/components/datePicker/index.jsx
  27. 47
      weapp/src/components/datePicker/index.scss
  28. 870
      weapp/src/components/dropdown/index.jsx
  29. 348
      weapp/src/components/dropdown/index.scss
  30. 250
      weapp/src/components/ec-canvas/ec-canvas.js
  31. 4
      weapp/src/components/ec-canvas/ec-canvas.json
  32. 4
      weapp/src/components/ec-canvas/ec-canvas.wxml
  33. 4
      weapp/src/components/ec-canvas/ec-canvas.wxss
  34. 18
      weapp/src/components/ec-canvas/echarts.js
  35. 121
      weapp/src/components/ec-canvas/wx-canvas.js
  36. 29
      weapp/src/components/echartForWx/common.js
  37. 28
      weapp/src/components/echartForWx/common.scss
  38. 26
      weapp/src/components/index.js
  39. 27
      weapp/src/components/infoCard/infoCard.jsx
  40. 41
      weapp/src/components/infoCard/infoCard.scss
  41. 90
      weapp/src/components/list-view/index.jsx
  42. 5
      weapp/src/components/list-view/index.scss
  43. 18
      weapp/src/components/loading-page/index.jsx
  44. 4
      weapp/src/components/loading-page/index.scss
  45. 29
      weapp/src/components/no-data/noData.jsx
  46. 16
      weapp/src/components/no-data/noData.scss
  47. BIN
      weapp/src/components/result-page/assets/empty.png
  48. 42
      weapp/src/components/result-page/index.jsx
  49. 28
      weapp/src/components/result-page/index.scss
  50. 212
      weapp/src/components/searchBar/index.jsx
  51. 14
      weapp/src/components/searchBar/index.scss
  52. 38
      weapp/src/components/tabs/tabs.jsx
  53. 87
      weapp/src/components/tabs/tabs.scss
  54. 1
      weapp/src/components/vant-weapp/button/index.d.ts
  55. 58
      weapp/src/components/vant-weapp/button/index.js
  56. 7
      weapp/src/components/vant-weapp/button/index.json
  57. 53
      weapp/src/components/vant-weapp/button/index.wxml
  58. 39
      weapp/src/components/vant-weapp/button/index.wxs
  59. 1
      weapp/src/components/vant-weapp/button/index.wxss
  60. 1
      weapp/src/components/vant-weapp/cell-group/index.d.ts
  61. 10
      weapp/src/components/vant-weapp/cell-group/index.js
  62. 3
      weapp/src/components/vant-weapp/cell-group/index.json
  63. 9
      weapp/src/components/vant-weapp/cell-group/index.wxml
  64. 1
      weapp/src/components/vant-weapp/cell-group/index.wxss
  65. 1
      weapp/src/components/vant-weapp/cell/index.d.ts
  66. 38
      weapp/src/components/vant-weapp/cell/index.js
  67. 6
      weapp/src/components/vant-weapp/cell/index.json
  68. 46
      weapp/src/components/vant-weapp/cell/index.wxml
  69. 17
      weapp/src/components/vant-weapp/cell/index.wxs
  70. 1
      weapp/src/components/vant-weapp/cell/index.wxss
  71. 1
      weapp/src/components/vant-weapp/col/index.d.ts
  72. 9
      weapp/src/components/vant-weapp/col/index.js
  73. 3
      weapp/src/components/vant-weapp/col/index.json
  74. 9
      weapp/src/components/vant-weapp/col/index.wxml
  75. 18
      weapp/src/components/vant-weapp/col/index.wxs
  76. 1
      weapp/src/components/vant-weapp/col/index.wxss
  77. 7
      weapp/src/components/vant-weapp/common/color.d.ts
  78. 7
      weapp/src/components/vant-weapp/common/color.js
  79. 8
      weapp/src/components/vant-weapp/common/component.d.ts
  80. 45
      weapp/src/components/vant-weapp/common/component.js
  81. 1
      weapp/src/components/vant-weapp/common/index.wxss
  82. 21
      weapp/src/components/vant-weapp/common/relation.d.ts
  83. 64
      weapp/src/components/vant-weapp/common/relation.js
  84. 1
      weapp/src/components/vant-weapp/common/style/clearfix.wxss
  85. 1
      weapp/src/components/vant-weapp/common/style/ellipsis.wxss
  86. 1
      weapp/src/components/vant-weapp/common/style/hairline.wxss
  87. 0
      weapp/src/components/vant-weapp/common/style/mixins/clearfix.wxss
  88. 0
      weapp/src/components/vant-weapp/common/style/mixins/ellipsis.wxss
  89. 0
      weapp/src/components/vant-weapp/common/style/mixins/hairline.wxss
  90. 0
      weapp/src/components/vant-weapp/common/style/theme.wxss
  91. 0
      weapp/src/components/vant-weapp/common/style/var.wxss
  92. 30
      weapp/src/components/vant-weapp/common/utils.d.ts
  93. 89
      weapp/src/components/vant-weapp/common/utils.js
  94. 11
      weapp/src/components/vant-weapp/common/validator.d.ts
  95. 30
      weapp/src/components/vant-weapp/common/validator.js
  96. 6
      weapp/src/components/vant-weapp/common/version.d.ts
  97. 45
      weapp/src/components/vant-weapp/common/version.js
  98. 1
      weapp/src/components/vant-weapp/divider/index.d.ts
  99. 12
      weapp/src/components/vant-weapp/divider/index.js
  100. 4
      weapp/src/components/vant-weapp/divider/index.json

12
weapp/.editorconfig

@ -0,0 +1,12 @@
# 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

3
weapp/.eslintrc.js

@ -0,0 +1,3 @@
module.exports = {
'extends': ['taro/react']
}

6
weapp/.gitignore

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

0
weapp/README.md

10
weapp/babel.config.js

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

9
weapp/config/dev.js

@ -0,0 +1,9 @@
module.exports = {
env: {
NODE_ENV: '"development"'
},
defineConstants: {
},
mini: {},
h5: {}
}

93
weapp/config/index.js

@ -0,0 +1,93 @@
import path from 'path';
const config = {
projectName: 'fs-wxapp-taro3',
date: '2020-12-7',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: [],
defineConstants: {
},
alias: {
'@/components': path.resolve(__dirname, '..', 'src/components'),
'@/actions': path.resolve(__dirname, '..', 'src/actions'),
'@/utils': path.resolve(__dirname, '..', 'src/utils'),
'@/hooks': path.resolve(__dirname, '..', 'src/hooks'),
'@/services': path.resolve(__dirname, '..', 'src/services'),
'@/constants': path.resolve(__dirname, '..', 'src/constants'),
},
copy: {
patterns: [
{ from: 'src/components/vant-weapp/wxs', to: 'dist/components/vant-weapp/wxs' },
{ from: 'src/components/vant-weapp/common/style', to: 'dist/components/vant-weapp/common/style' },
{ from: 'src/components/vant-weapp/common/index.wxss', to: 'dist/components/vant-weapp/common/index.wxss' },
{ from: 'src/components/vant-weapp/button/index.wxs', to: 'dist/components/vant-weapp/button/index.wxs' },
{ from: 'src/components/vant-weapp/icon/index.wxs', to: 'dist/components/vant-weapp/icon/index.wxs' },
{ from: 'src/components/vant-weapp/loading/index.wxs', to: 'dist/components/vant-weapp/loading/index.wxs' },
{ from: 'src/components/vant-weapp/popup/index.wxs', to: 'dist/components/vant-weapp/popup/index.wxs' },
{ from: 'src/components/vant-weapp/cell/index.wxs', to: 'dist/components/vant-weapp/cell/index.wxs' },
{ from: 'src/components/vant-weapp/dropdown-menu/index.wxs', to: 'dist/components/vant-weapp/dropdown-menu/index.wxs' },
{ from: 'src/components/vant-weapp/transition/index.wxs', to: 'dist/components/vant-weapp/transition/index.wxs' },
{ from: 'src/components/vant-weapp/tag/index.wxs', to: 'dist/components/vant-weapp/tag/index.wxs' },
{ from: 'src/components/vant-weapp/row/index.wxs', to: 'dist/components/vant-weapp/row/index.wxs' },
{ from: 'src/components/vant-weapp/col/index.wxs', to: 'dist/components/vant-weapp/col/index.wxs' },
],
options: {
}
},
framework: 'react',
mini: {
postcss: {
pxtransform: {
enable: true,
config: {
selectorBlackList: [/van-/]
}
},
url: {
enable: true,
config: {
limit: 1024 // 设定转换尺寸上限
}
},
cssModules: {
enable: false, // 默认为 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: 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'))
}

18
weapp/config/prod.js

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

14
weapp/jsconfig.json

@ -0,0 +1,14 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"baseUrl": ".",
"paths": {
"@/components/*": ["./src/components/*"],
"@/actions/*": ["./src/actions/*"],
"@/utils/*": ["./src/utils/*"],
"@/hooks/*": ["./src/hooks/*"],
"@/services/*": ["./src/services/*"],
"@constants/*": ["./src/constants/*"],
}
}
}

15645
weapp/package-lock.json

File diff suppressed because it is too large

69
weapp/package.json

@ -0,0 +1,69 @@
{
"name": "fs-wxapp-taro3",
"version": "1.0.0",
"private": true,
"description": "飞尚小程序taro3模板",
"templateInfo": {
"name": "redux",
"typescript": false,
"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",
"start": "npm run build:weapp -- --watch",
"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"
},
"browserslist": [
"last 3 versions",
"Android >= 4.1",
"ios >= 8"
],
"author": "",
"license": "MIT",
"dependencies": {
"@antv/f2-canvas": "^1.0.5",
"@antv/wx-f2": "^1.1.4",
"@babel/runtime": "^7.7.7",
"@tarojs/components": "3.1.4",
"@tarojs/react": "3.1.4",
"@tarojs/runtime": "3.1.4",
"@tarojs/taro": "3.1.4",
"dayjs": "^1.9.8",
"deepmerge": "^4.0.0",
"react": "^16.10.0",
"react-dom": "^16.10.0",
"swr": "^0.5.4",
"taro-ui": "^3.0.0-alpha.10"
},
"devDependencies": {
"@babel/core": "^7.8.0",
"@tarojs/mini-runner": "3.1.4",
"@tarojs/webpack-runner": "3.1.4",
"@types/react": "^16.0.0",
"@types/webpack-env": "^1.16.0",
"babel-preset-taro": "3.1.4",
"blueimp-md5": "^2.12.0",
"eslint": "^7.22.0",
"eslint-config-taro": "3.1.4",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-react": "^7.23.1",
"eslint-plugin-react-hooks": "^4.2.0",
"stylelint": "^13.12.0"
}
}

46
weapp/project.config.json

@ -0,0 +1,46 @@
{
"miniprogramRoot": "dist/",
"projectname": "四好公路",
"description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"appid": "wx3c0c46dcf49a85be",
"setting": {
"urlCheck": false,
"es6": false,
"postcss": false,
"minified": false,
"coverView": true,
"lazyloadPlaceholderEnable": false,
"preloadBackgroundData": false,
"autoAudits": false,
"uglifyFileName": false,
"uploadWithSourceMap": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmManually": false,
"packNpmRelationList": [],
"minifyWXSS": true,
"useStaticServer": true,
"showES6CompileOption": false,
"checkInvalidKey": true,
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"disableUseStrict": false,
"useCompilerPlugins": false,
"minifyWXML": true
},
"compileType": "miniprogram",
"libVersion": "2.25.1",
"srcMiniprogramRoot": "dist/",
"packOptions": {
"ignore": [],
"include": []
},
"condition": {},
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

7
weapp/project.private.config.json

@ -0,0 +1,7 @@
{
"projectname": "%E5%9B%9B%E5%A5%BD%E5%85%AC%E8%B7%AF",
"setting": {
"compileHotReLoad": true
},
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html"
}

54
weapp/src/actions/auth.js

@ -0,0 +1,54 @@
import Taro from '@tarojs/taro';
import request from '../services/request';
function dealError(error) {
Taro.showToast({
title: error,
icon: 'none',
duration: 1500
});
throw new Error(error);
}
export const login = (url, data) => {
return request.post(url, data, { hideErrorToast: true }).then(res => {
if (res.statusCode == 200) {
//let obj = {};
// res.cookies.map(t=>{
// const fsiota = t.split(';').find(v=> v.includes('fsiota')).split('=');
// obj[fsiota[0]] = fsiota[1];
// })
// console.log(obj);
// Taro.setStorageSync("cookie", {
// fsiota: obj.fsiota,
// sig: obj['fsiota.sig']
// })
Taro.setStorageSync('token', res.data.token)
Taro.setStorageSync('userInfo', res.data);
return res.data;
} else {
dealError(res.data.message || '请求出错');
}
}, err => {
dealError(err.message || '请求出错');
});
};
export const logout = (url, data) => {
return request.post(url, data).then(res => {
if (res.statusCode == 200 || res.statusCode == 204) {
Taro.clearStorage();
return res.data;
} else {
throw new Error(res.data.message || '登出失败');
}
}).catch(err => {
throw new Error(err.message || '请求出错');
});
};

12
weapp/src/actions/business.js

@ -0,0 +1,12 @@
import useSWR, { useSWRInfinite } from 'swr';
import {
getIndustryUrl,
} from '@/services/api';
import { fetcher, useCommonSwr } from './fetcher';
//获取行业列表
export const useIndustry = () => {
const url = getIndustryUrl();
return useCommonSwr(url);
}

41
weapp/src/actions/fetcher.js

@ -0,0 +1,41 @@
import request from '@/services/request';
import useSWR, { useSWRInfinite } from 'swr';
export const PAGE_SIZE = 10;
//swr 返回获取数据函数
export const fetcher = ({ url, data }, cb) => {
return async function () {
const res = await request.get(url, data);
const payload = cb ? cb(res.data) : res.data;
if (res.statusCode === 200 || res.statusCode === 204) {
return payload;
} else {
//向外抛出错误
throw new Error(res.data.message || '请求出错');
}
}
}
//分页获取数据
export const pageFetcher = async (url) => {
const res = await request.get(url);
const payload = res.data;
if (res.statusCode === 200 || res.statusCode === 204) {
if(payload && payload.rows){
return payload.rows
}
return payload;
} else {
//向外抛出错误
throw new Error(res.data.message || '请求出错');
}
}
export const useCommonSwr = (url) => {
const { data, error } = useSWR(url, fetcher({ url }));
return {
data: data,
isLoading: !error && !data,
error: error
}
}

49
weapp/src/app.config.js

@ -0,0 +1,49 @@
export default {
pages: [
'pages/home/index',
'pages/user/index',
'pages/auth/login/login'
],
permission: {
"scope.userLocation": {
"desc": '需要获取您的地理位置'
}
},
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: "#2C66F3",
navigationBarTitleText: '智慧交通',
backgroundColor: "#f2f2f2",
},
tabBar: {
color: '#B2B2B2',
selectedColor: '#0080EE',
list: [
{
'pagePath': 'pages/home/index',
'iconPath': 'static/img/tabbar/shouye.png',
'selectedIconPath': 'static/img/tabbar/shouye-active.png',
'text': '首页'
},
{
'pagePath': 'pages/user/index',
'iconPath': 'static/img/tabbar/wode.png',
'selectedIconPath': 'static/img/tabbar/wode-active.png',
'text': '我的'
},
]
},
usingComponents: {
'chart-wx': 'components/wx-chart/chart',
"van-icon": "components/vant-weapp/icon/index",
"van-dropdown-menu": "components/vant-weapp/dropdown-menu/index",
"van-dropdown-item": "components/vant-weapp/dropdown-item/index",
"van-tag": "components/vant-weapp/tag/index",
"van-button": "components/vant-weapp/button/index",
"van-row": "components/vant-weapp/row/index",
"van-col": "components/vant-weapp/col/index",
"van-transition": "components/vant-weapp/transition/index",
"ec-canvas": "components/ec-canvas/ec-canvas"
}
}

52
weapp/src/app.jsx

@ -0,0 +1,52 @@
import React, { Component } from 'react';
import Taro from '@tarojs/taro';
import { SWRConfig } from 'swr';
import 'taro-ui/dist/style/index.scss';
//import appUpdate from './utils/appUpdate';
import './app.scss';
class App extends Component {
componentDidMount() {
const userInfo = Taro.getStorageSync('userInfo') || null;
const token = Taro.getStorageSync('token') || null;
if (!userInfo || !token) {
Taro.showModal({
title: '提示',
content: '未获取用户信息,请重新登录',
showCancel: false,
success: (res) => {
if (res.confirm) {
Taro.reLaunch({
url: '/pages/auth/login/login'
});
}
}
});
}
}
componentDidShow() { }
componentDidHide() { }
componentDidCatchError() { }
// App render()
//
render() {
return (
<SWRConfig
value={{
suspense: false,
dedupingInterval: 2000
}}
>
{this.props.children}
</SWRConfig>
)
}
}
export default App

256
weapp/src/app.scss

@ -0,0 +1,256 @@
//$color-brand: #2579C7 !default;
@import 'src/styles/theme';
/* 引入 Taro UI 默认样式 */
@import "~taro-ui/dist/style/index.scss";
//全局默认字体, 蚂蚁金服
page,view,button{
font-family: "Monospaced Number", "Chinese Quote", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
/* 修改 taro ui样式 */
// .at-list::after {
// border-bottom-width: 0;
// }
/* 弹性布局 */
.flex{
display: flex;
justify-content: center;
align-items: center;
}
.flex-start{
justify-content: flex-start;
}
.flex-col{
flex-direction: column;
}
.flex-between{
justify-content: space-between;
}
/* 自定义png图标颜色 */
$icon-size: 50px;
.color-icon{
display: inline-block;
width: $icon-size;
height: $icon-size;
overflow: hidden;
.img{
display: block;
position: relative;
left: -$icon-size;
border-right: $icon-size solid transparent;
filter: drop-shadow($icon-size 0 0 $color-brand);
}
}
/* 字体省略号 */
.text---{
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
.break-all{
word-break: break-all
}
/* 字体大小 */
.fs6{font-size: 6px}.fs8{font-size: 8px}.fs10{font-size:10px;}.fs11{font-size:11px;}.fs12{font-size:12px;}.fs13{font-size:13px;}.fs14{font-size:14px;}.fs15{font-size:15px;}.fs16{font-size:16px;}.fs18{font-size:18px;}.fs20{font-size:20px;}.fs24{font-size:24px;}.fs28{font-size:28px;}.fs30{font-size:30px;}.fs32{font-size:32px;}.fs36{font-size:36px;}.fs40{font-size:40px;}.fs48{font-size:48px;}.fs50{font-size:50px;}.fs60{font-size:60px;}
.fw-400{
font-weight: 400;
}
.fw-500{
font-weight: 500;
}
.fw-600{
font-weight: 600;
}
.fw-700{
font-weight: 700;
}
/* 字体颜色 */
.c-111{
color: #111;
}
.c-222{
color: #222;
}
.c-333{
color: #333;
}
.c-444{
color: #444;
}
.c-555{
color: #555;
}
.c-666{
color: #666;
}
.c-777{
color: #777;
}
.c-888{
color: #888;
}
.c-999{
color: #999;
}
.c-aaa{
color: #aaa;
}
.c-ccc{
color: #ccc;
}
.c-fff{
color: #fff;
}
.c-b2{
color: #b2b2b2;
}
.c-f00{
color: #f00;
}
.c-m{
color: #2F54FF;
}
.c-m-bg{
background-color: #2F54FF;
}
.t-center{
text-align: center;
}
button::after{
border: none;
}
//背景色
.bc-e00{
background-color: #e00;
}
/* 边距 */
.pr10{
padding-right: 10px;
}
.pt5{
padding-top: 5px;
}
.pb30{
padding-bottom: 30px;
}
.ptr120{
padding-top: 120rpx;
}
.ptr160{
padding-top: 160rpx;
}
.pb10{
padding-bottom: 10px;
}
.pl5{
padding-left: 5px;
}
.pl10{
padding-left: 10px;
}
.pl20{
padding-left: 20px;
}
.pl30{
padding-left: 30px;
}
.p-lr30{
padding-left: 30px;
padding-right: 30px;
}
.mt7{
margin-top: 7px;
}
.mt8{
margin-top: 8px;
}
.mt10{
margin-top: 10px;
}
.mt20{
margin-top: 20px;
}
.mt30{
margin-top: 30px;
}
.mt40{
margin-top: 40px;
}
.mt60{
margin-top: 60px;
}
.mt100{
margin-top: 200px;
}
.mt200{
margin-top: 200px;
}
.mt300{
margin-top: 300px;
}
.mb8{
margin-bottom: 8px;
}
.mb6{
margin-bottom: 6px;
}
.mb10{
margin-bottom: 10px;
}
.mb20{
margin-bottom: 20px;
}
.mb30{
margin-bottom: 30px;
}
.mb50{
margin-bottom: 50px;
}
.ml10{
margin-left: 10px;
}
.ml20{
margin-left: 20px;
}
.ml30{
margin-left: 30px;
}
.ml40{
margin-left: 40px;
}
.ml50{
margin-left: 50px;
}
.ml60{
margin-left: 60px;
}
//伪类阴影 父元素需设置z-index和position: relative;
.shadow{
position: relative;
&::before{
content:'';
position: absolute;
bottom: -20px;
left: 50%;
transform: translateX(-50%);
width:90%;
height:68px;
background:rgba(0,0,0,0.06);
border-radius:9px;
filter:blur(15px);
z-index: -2;
}
}
.loadmore{
background: #F7F7FA;
}

39
weapp/src/components/calenda/index.js

@ -0,0 +1,39 @@
import React, { Component } from 'react';
import { View, } from '@tarojs/components';
import { AtCalendar } from 'taro-ui';
import './index.scss';
class MyCalenda extends Component {
constructor(props) {
super(props);
this.state = {
//date: null,
};
}
selectDate(e) {
this.props.onSelectDate(e.value);
}
render() {
const { date } = this.props;
return (
<View>
<View>
<View className='fw-bold'>时间筛选</View>
<View className='time'>
<View className='w-200'>{date && date.start ? date.start : '起始时间'}</View>
<View>|</View>
<View className='w-200'>{date && date.end ? date.end : '结束时间'}</View>
</View>
</View>
<AtCalendar currentDate={date && date.start && date.end ? { start: date.start.replace(/-/g, '/'), end: date.end.replace(/-/g, '/') } : Date.now()} onSelectDate={this.selectDate.bind(this)} isMultiSelect />
</View>
);
}
}
export default MyCalenda;

11
weapp/src/components/calenda/index.scss

@ -0,0 +1,11 @@
.w-200{
width: 200rpx
}
.fw-bold{
font-weight: bold
}
.time{
display: flex;
justify-content: space-around;
text-align: center;
}

24
weapp/src/components/chart/chart.jsx

@ -0,0 +1,24 @@
import React, { Component } from 'react';
import { View } from '@tarojs/components';
class Chart extends Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount() {
}
render() {
return (
<View>
<chart-wx chartData={this.props.chartData} simpleChart={this.props.simpleChart}></chart-wx>
</View>
);
}
}
export default Chart;

90
weapp/src/components/datePicker/filterPicker.jsx

@ -0,0 +1,90 @@
/*
* create by Xumeng 2020/12/31
* 时间日期筛选框包装
*/
import React, { Component } from 'react'
import { View } from '@tarojs/components';
import { AtFloatLayout, AtList, AtListItem } from "taro-ui";
import 'dayjs/locale/zh-cn'
import DatePicker from './index'
import './filterPicker.scss'
export default class FilterPicker extends Component {
constructor() {
super(...arguments)
this.state = {
isOpened: false,
chevronDown: true,
showValue: ''
}
}
componentWillMount() {
}
componentDidMount() {
}
componentWillUnmount() {}
componentDidShow() {}
componentDidHide() {}
handleInitial = () => {
}
handleConfirm = () => {
}
handleCancel = () => {
}
handleClose = () => {
this.setState({
isOpened : false,
chevronDown: true
})
}
handleOpen = () => {
this.setState({
isOpened : true,
chevronDown: false
})
}
render() {
const { isOpened, chevronDown, showValue } = this.state
const { dateTime = [{ mode: 'year', unit: '年' },{ mode: 'month', unit: '月' },{ mode: 'day', unit: '日' }] , mode, formatShow, value} = this.props
return (
<View>
{/* <View className='picker-cell' onClick={this.handleOpen}>
<View className='label'>{showValue}</View>
{chevronDown ? <View className='at-icon at-icon-chevron-down' /> : <View className='at-icon at-icon-chevron-up' />}
</View> */}
<AtList hasBorder={false}>
<AtListItem title='请选择日期区间' extraText={showValue} onClick={this.handleOpen} />
</AtList>
<AtFloatLayout isOpened={isOpened} onClose={this.handleClose}>
<DatePicker
dateTime={dateTime}
onInitial={this.handleInitial}
onConfirm={this.handleConfirm}
onCancel={this.handleCancel}
mode={mode || 'format'}
formatShow={formatShow ||'YYYY-MM-DD'}
value={value || [0, 0, 0]}
/>
</AtFloatLayout>
</View>
)
}
}

6
weapp/src/components/datePicker/filterPicker.scss

@ -0,0 +1,6 @@
.picker-cell{
min-width: 210px;
height: 44px;
display: flex;
align-items: center;
}

126
weapp/src/components/datePicker/format.js

@ -0,0 +1,126 @@
// 输出的结果包含item为显示的可选项,value为默认显示值
// res为返回的结果,time为返回的默认时间
// 整个代码流程为:
// 1.如果指定了offset,则根据offset属性将time做偏移作为time(为了实现当前8:30,需要默认选择9点这样的需求)
// 2.如果指定了selected,则根据第一步的结果寻找大于或者等于time的可选时间点作为新的time,
// 如果无法匹配到合适的selected(findIndex返回-1),则设定time为下个周期的开始时间
// 如果同时指定了selectedDefault,则设定time为selected的selectedDefault对应的值
// 3.根据mode来区分开年/日---月/时/分/秒---range,对三种mode分别进行单独的处理
const format = (dateTime, dayjs) => {
// res为返回的结果,time为返回的默认时间
let res = { value: [], item: [] },
time = dayjs.clone()
// 注释掉这里是因为这里判断fields的同时只做了增加到下一个时间点的操作,完全可以用fields和offset搭配实现select下一个时间点
// dateTime
// .filter((key) => key.fields > 1)
// .map((item) => {
// time = time.add(item.fields, item.mode)
// })
// offset: 设定time偏移量(常用于设定下一小时或者下一天等)
dateTime
.filter((key) => key.offset)
.map((item) => {
time = time.add(item.offset, item.mode)
})
// selected: 可指定当前模式下只选择有效范围内的哪几个元素,例如24小时内,只选择8点、12点、16点
// 寻找大于或者等于time的最近的可选择时间点
dateTime
.filter((key) => key.selected)
.map((item) => {
const { selected, mode, selectedDefault } = item
const index = selected.findIndex((value) => value >= time.get(mode))
if (index === -1) {
// 如果未找到可选时间点,就设定time为下个周期(如第二天)的开始时间
time = time.add(getInverval(mode) - time.get(mode), mode)
} else {
// 如果找到可选时间点,就设定time为这个时间点
time = time.set(mode, selected[index])
}
// 如果设定了selectedDefault,则将time设定为default对应的时间点
if (selectedDefault !== undefined) {
time = time.set(mode, selected[selectedDefault])
}
})
// 此处针对offset、selected和selectedDefault属性处理完成
dateTime.map((item) => {
const { mode, selected, selectedDefault, unit = '', fields = 1 } = item
// 此处区分年、天有别于其他周期在于年和天都不是标准周期(每个月不同天,年一直在增长)
if (['month', 'hour', 'minute', 'second'].includes(mode)) {
// 设定显示的可选项
// [...Array(getInverval('hour')).keys()]获取24个小时的数字的数组:[0,1,...,23]
res.item.push(
[...Array(getInverval(mode)).keys()]
// 按照fields来平均分割这些数字
.filter((i) => i % fields === 0)
// 如果设置了selected属性,只返回特定的数字
.filter((i) => {
if (selected) return selected.includes(i)
else return true
})
// 在所有的数字后面添加单位(unit);由于月份为0-11,需要转换为1-12
.map((i) => (mode === 'month' ? i + 1 : i) + unit)
)
// 根据time的值和selected的匹配来设定默认值为数组中第几个,当未指定selected或者定位到下个周期时,设定index为-1
const index = selected && selected.findIndex((value) => value === time.get(mode))
// 设定显示的默认选择项
res.value.push(selected ? (index < 0 ? 0 : index) : ~~(time.get(mode) / fields))
} else if (['year', 'day'].includes(mode)) {
// 根据
res.item.push(timeFormat(item, dayjs))
// 寻找time和dayjs时间点的差值作为默认选择值
res.value.push(selectedDefault || time.startOf(mode).diff(dayjs.startOf(mode), mode))
} else {
return
}
})
return res
}
// 对于年和日,获取显示的可选项
const timeFormat = (time, dayjs) => {
const { mode, duration = 30, unit = '', humanity = false } = time,
res = []
for (let i = 0; i < duration; i++) {
let timeItem
// 利用dayjs[convertDay(mode)]来动态实现dayjs.date()或dayjs.year()的方法,用computedTime来实现可选择项的生成
const computedTime = dayjs.add(i, mode)
if (humanity && mode === 'day') {
timeItem = `${computedTime.month() + 1}${computedTime.date()}`
if (i < 3) {
// 今天明天后天这三天明确显示出来
timeItem = (i === 0 ? '' : timeItem + ' ') + convertDate(i)
} else {
// 在日期后添加星期几,更人性化
timeItem += ` ${convertWeek(computedTime.day())}`
}
} else {
timeItem = computedTime.get(convertDay(mode)) + unit
}
res.push(timeItem)
}
return res
}
const convertWeek = (item) => {
return { 0: '周日', 1: '周一', 2: '周二', 3: '周三', 4: '周四', 5: '周五', 6: '周六' }[item]
}
const convertDate = (item) => {
return { 0: '今天', 1: '明天', 2: '后天' }[item]
}
// dayjs的get分为day of week和date of month,故需要将day转换为date使用
const convertDay = (item) => {
return { day: 'date' }[item] || item
}
const getInverval = (item) => {
return { hour: 24, minute: 60, second: 60, month: 12 }[item]
}
export default format

188
weapp/src/components/datePicker/index.jsx

@ -0,0 +1,188 @@
/*
* create by Xumeng 2020/12/31
* 时间日期选择器通用组件
*/
import React, { Component } from 'react'
import { View, PickerView, PickerViewColumn, Button } from '@tarojs/components';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import customParseFormat from 'dayjs/plugin/customParseFormat'
import format from './format'
import './index.scss'
dayjs.extend(customParseFormat)
export default class Index extends Component {
constructor() {
super(...arguments)
this.state = {
itemHeight: `height: 40px;`,
value: [],
source: [],
markMultiDateTime: false,
isOpened: false,
chevronDown: true,
showValue: this.props.paickerText ? this.props.paickerText : '请选择'
}
}
componentWillMount() {
const { dateTime, start, value: _value } = this.props
let markMultiDateTime = false
if (dateTime && Array.isArray(dateTime)) {
dateTime.map((dateTimeItem) => {
//
if (Array.isArray(dateTimeItem)) {
markMultiDateTime = true
//
const source = dateTimeItem && format(dateTimeItem, dayjs(start))
// sourceitemsourceitemvalue
this.setState((state) => ({
...state,
source: [...state.source, source],
value: [...state.value, source.value],
}))
// this.setState((state) => ({ ...state, value: [...state.value, source.value] }))
}
})
if (!markMultiDateTime) {
const source = dateTime && format(dateTime, dayjs(start))
this.setState((state) => ({
...state,
source: [...state.source, source],
value: [...state.value, source.value],
}))
// this.setState((state) => ({ ...state, source: [...state.source, source] }))
// this.setState((state) => ({ ...state, value: [...state.value, source.value] }))
}
this.setState((state) => ({ ...state, markMultiDateTime }))
}
_value && this.setState((state) => ({ ...state, ...{ value: markMultiDateTime ? _value : [_value] } }))
}
componentDidMount() {
this.onInitial()
}
componentWillUnmount() {}
componentDidShow() {}
componentDidHide() {}
onChange = (e, index) => {
console.log(e.detail.value)
const _value = [...this.state.value]
_value[index] = e.detail.value
this.setState({ value: _value })
}
onInitial = () => {
const { value, markMultiDateTime } = this.state
const { onInitial, mode, formatShow } = this.props
// (mode)
onInitial && onInitial(this.getDayjs(mode), markMultiDateTime ? value : value[0])
}
onConfirm = () => {
const { value, markMultiDateTime } = this.state
const { onConfirm, mode, formatShow } = this.props;
const newValue = this.getDayjs(mode);
let formatNewValue = '';
if(formatShow && mode == 'format'){
if(Array.isArray(newValue)){
formatNewValue = newValue.map(v=> dayjs(v).format(formatShow)).join(' - ');
}else{
formatNewValue = dayjs(newValue).format(formatShow);
}
this.setState({
showValue: formatNewValue
})
}
onConfirm && onConfirm(formatNewValue, markMultiDateTime ? value : value[0])
}
//
getDayjs = (mode = 'unix') => {
let { source, value, markMultiDateTime } = this.state
const { dateTime } = this.props
const res = []
// dateTimesource
for (let i = 0; i < source.length; i++) {
let time = '',
token = ''
// source[i].item.length
for (let j = 0; j < source[i].item.length; j++) {
// source[i].item[j],value[i][j]
const select = source[i].item[j][value[i][j]]
// ''
time += (select === '今天' ? dayjs().format('M月D日') : select) + '-'
// ijj
const item = markMultiDateTime ? dateTime[i][j] : dateTime[j]
token += (item.format || this.getToken(item.mode)) + '-'
}
res.push(dayjs(time, token)[mode]())
}
return markMultiDateTime ? res : res[0]
}
onCancel = () => {
const { onCancel } = this.props
onCancel && onCancel()
}
//
getToken = (mode) => {
return {
year: 'YYYY年',
month: 'M月',
day: 'D日',
hour: 'H时',
minute: 'm分',
second: 's秒',
}[mode]
}
render() {
const { source, value, itemHeight } = this.state;
//console.log(source)
//const { dateTime = [] } = this.props
return (
<View
className='date-picker-page'
//style={{ width: dateTime.reduce((acc, val) => acc.concat(val), []).length < 4 ? '80%' : '100%' }}
>
<View className='section'>
{source.map((element, index) => (
<PickerView
key={'element' + index}
indicator-style={itemHeight}
value={value[index]}
onChange={(e) => this.onChange(e, index)}
// 使acc.concat
>
{element.item.map((item, elementIndex) => (
<PickerViewColumn key={elementIndex}>
{item.map((time) => (
<View key={time}>{time}</View>
))}
</PickerViewColumn>
))}
</PickerView>
))}
</View>
<View className='handle'>
<Button className='cancel' type='default' size='default' onClick={this.onCancel}>
取消
</Button>
<Button className='confirm' type='primary' size='default' onClick={this.onConfirm}>
确定
</Button>
</View>
</View>
)
}
}

47
weapp/src/components/datePicker/index.scss

@ -0,0 +1,47 @@
.date-picker-page{
width: 100%;
flex-direction: column;
align-items: center;
display: flex;
.section {
display: flex;
width: 100%;
justify-content: center;
align-items: center;
picker-view {
width: 100%;
height: 240Px;
picker-view-column {
text-align: center;
font-size: 26px;
view {
//height: 100Px;
line-height: 40Px;
}
}
}
}
.handle {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
height: 100px;
button {
height: 70px;
line-height: 70px;
font-size: 32px;
padding: 0 80px;
margin: 0 20px;
}
.confirm {
background-color: #07C160;
}
.cancel {
background-color: #F2F2F2;
color: #1AAD19;
}
}
}

870
weapp/src/components/dropdown/index.jsx

@ -0,0 +1,870 @@
import React,{ Component } from 'react'
import Taro from '@tarojs/taro'
import { View, Text, Block, ScrollView } from '@tarojs/components';
import { DatePicker } from '@/components';
import PropTypes from 'prop-types';
import './index.scss'
export default class FilterDropdown extends Component {
state = {
subData: [], //
menu: [], //
showPage: -1, ///
pageState: [], //
activeMenuArr: [], //UI
shadowActiveMenuArr: [], //
defaultActive: [],
triangleDeg: [], //
isShowMask: false, ///
maskVisibility: false, ///
//
firstScrollInto: 0,
secondScrollInto: 0,
componentTop: 0,//top
isReadNewSelect: false,
filterData: null,
defaultSelected: null
}
componentWillMount() {
this.setState({
filterData: this.props.filterData,
}, () => {
this.initMenu(); //filterData
})
// if (this.props.defaultSelected.length == 0) {
// return;
// }
// this.setState({
// defaultActive: JSON.parse(JSON.stringify(this.props.defaultSelected)),
// activeMenuArr: JSON.parse(JSON.stringify(this.props.defaultSelected)),
// shadowActiveMenuArr: JSON.parse(JSON.stringify(this.props.defaultSelected))
// }, () => {
// })
}
componentDidMount() {
}
componentWillUnmount() { }
componentDidShow() { }
componentDidHide() { }
// componentDidUpdate(prevProps,prevState) {
// if (prevProps.filterData !== this.state.filterData) {
// // this.initData();
// this.setState({
// filterData: prevProps.filterData,
// }, () => {
// this.initMenu(); //filterData
// })
// }
// if (prevProps.defaultSelected !== this.state.defaultSelected) {
// this.setState({
// defaultSelected: prevProps.defaultSelected,
// }, () => {
// // this.initData();
// if (prevProps.defaultSelected.length == 0) {
// return;
// }
// this.setState({
// defaultActive: JSON.parse(JSON.stringify(prevProps.defaultSelected)),
// activeMenuArr: JSON.parse(JSON.stringify(prevProps.defaultSelected)),
// shadowActiveMenuArr: JSON.parse(JSON.stringify(prevProps.defaultSelected))
// }, () => {
// if (this.props.updateMenuName) {
// this.setMenuName();
// }
// })
// })
// }
// }
initMenu = () => {
let tmpMenuActiveArr = [];
let tmpMenu = [];
let { filterData, triangleDeg, pageState, activeMenuArr } = this.state;
const { defaultSelected } = this.props;
let newFilterData = filterData.map(item=>{
tmpMenu.push({
name: item.name || item?.submenu[0]?.name,
type: item.type
});
//-ui
tmpMenuActiveArr.push(this.processActive(item));
triangleDeg.push(0);
pageState.push(false);
//
let tmpitem = this.processSubMenu(item);
return tmpitem;
})
//
tmpMenuActiveArr = defaultSelected?.length > 0 ? defaultSelected : activeMenuArr.length > 0 ? activeMenuArr : tmpMenuActiveArr;
//console.log(tmpMenuActiveArr)
this.setState({
menu: tmpMenu,
triangleDeg,
pageState,
filterData: newFilterData,
//
subData: newFilterData,
activeMenuArr: JSON.parse(JSON.stringify(tmpMenuActiveArr)),
shadowActiveMenuArr: JSON.parse(JSON.stringify(tmpMenuActiveArr)),
}, () => {
if (this.props.updateMenuName) {
this.setMenuName();
}
})
}
setMenuName = () => {
const { activeMenuArr, subData } = this.state;
let menu = this.state.menu
activeMenuArr.map((item,i)=>{
if (Array.isArray(item) && typeof (item[0]) !== 'object') {
let tmpsub = false;
if (item.length > 0 && item[0] != null) {
tmpsub = subData[i].submenu[item[0]];
if (item.length > 1 && item[1] != null) {
tmpsub = tmpsub.submenu[item[1]];
if (item.length > 2 && item[2] != null) {
tmpsub = tmpsub.submenu[item[2]];
}
}
} else {
tmpsub = false;
}
if (tmpsub) {
menu[i].name = tmpsub.name
}
}
})
this.setState({
menu
})
}
//
showMoreSub = (index) => {
let subData = this.subData
subData[this.state.showPage].submenu[this.state.activeMenuArr[this.state.showPage][0]].submenu[index].showAllSub = true;
this.setState({
subData
}, () => {
this.forceUpdate();
})
}
//
selectHierarchyMenu = (page_index, level1_index, level2_index, level3_index) => {
let activeMenuArr = this.state.activeMenuArr
//
if (level1_index != null && level2_index == null && level3_index == null && this.state.shadowActiveMenuArr[page_index][0] ==
level1_index) {
activeMenuArr.splice(page_index, 1, JSON.parse(JSON.stringify(this.state.shadowActiveMenuArr[page_index])));
this.setState({
activeMenuArr
})
} else {
activeMenuArr[page_index].splice(0, 1, level1_index);
this.setState({
activeMenuArr
}, () => {
activeMenuArr = this.state.activeMenuArr;
if (level2_index != null || activeMenuArr[page_index].length >= 2) {
activeMenuArr[page_index].splice(1, 1, level2_index)
} else {
activeMenuArr[page_index].splice(1, 1)
}
if (level3_index != null || activeMenuArr[page_index].length >= 3) {
activeMenuArr[page_index].splice(2, 1, level3_index)
} else {
activeMenuArr[page_index].splice(2, 1)
}
this.setState({
activeMenuArr
})
})
}
this.setState({
activeMenuArr
}, () => {
console.log(this.state.activeMenuArr)
//
if (level3_index != null || level2_index != null || (level1_index != null && this.state.subData[page_index].submenu[level1_index].submenu.length == 0)
) {
let sub = this.state.subData[page_index].submenu[level1_index].submenu[level2_index];
if (this.props.updateMenuName) {
var menu = this.state.menu
menu[page_index].name = (level3_index != null && sub.submenu[level3_index].name) || (level2_index != null && sub.name) || this.state.subData[page_index].submenu[level1_index].name;
this.setState({
menu
})
}
var shadowActiveMenuArr = this.state.shadowActiveMenuArr
shadowActiveMenuArr[page_index] = this.state.activeMenuArr[page_index];
this.setState({
shadowActiveMenuArr: shadowActiveMenuArr
}, () => {
console.log(this.state.shadowActiveMenuArr)
this.togglePage(this.state.showPage);
})
}
})
}
//
setFilterData = (page_index) => {
var shadowActiveMenuArr = this.state.shadowActiveMenuArr
shadowActiveMenuArr[page_index] = JSON.parse(JSON.stringify(this.state.activeMenuArr[page_index]));
this.setState({
shadowActiveMenuArr
}, () => {
this.togglePage(this.state.showPage);
})
}
//ui
resetFilterData = (page_index) => {
let tmpArr = [];
let level = this.state.shadowActiveMenuArr[page_index].length;
while (level > 0) {
tmpArr.push([]);
let box = this.state.subData[page_index].submenu[level - 1].submenu;
for (let i = 0; i < box.length; i++) {
let subData = this.state.subData
subData[page_index].submenu[level - 1].submenu[i].selected = false;
this.setState({
subData
})
}
level--;
}
var activeMenuArr = this.state.activeMenuArr
activeMenuArr[page_index] = JSON.parse(JSON.stringify(tmpArr));
this.setState({
activeMenuArr
}, () => {
this.forceUpdate();
})
}
//label-UI
selectFilterLabel = (page_index, box_index, label_index) => {
let find_index = this.state.activeMenuArr[page_index][box_index].indexOf(label_index);
let activeMenuArr, subData
activeMenuArr = this.state.activeMenuArr
subData = this.state.subData
if (find_index > -1) {
activeMenuArr[page_index][box_index].splice(find_index, 1);
subData[page_index].submenu[box_index].submenu[label_index].selected = false;
this.setState({
activeMenuArr,
subData
}, () => {
this.forceUpdate();
})
} else {
activeMenuArr[page_index][box_index].push(label_index);
subData[page_index].submenu[box_index].submenu[label_index].selected = true;
this.setState({
activeMenuArr,
subData
}, () => {
this.forceUpdate();
})
}
}
//label-UI
selectRadioLabel = (page_index, box_index, label_index) => {
let activeIndex = this.state.activeMenuArr[page_index][box_index][0];
let activeMenuArr, subData
activeMenuArr = this.state.activeMenuArr
subData = this.state.subData
if (activeIndex == label_index) {
subData[page_index].submenu[box_index].submenu[activeIndex].selected = false;
activeMenuArr[page_index][box_index][0] = null;
this.setState({
activeMenuArr,
subData
}, () => {
this.forceUpdate();
})
} else {
if (activeIndex != null && activeIndex < this.state.subData[page_index].submenu[box_index].submenu.length) {
subData[page_index].submenu[box_index].submenu[activeIndex].selected = false;
}
subData[page_index].submenu[box_index].submenu[label_index].selected = true;
activeMenuArr[page_index][box_index][0] = label_index;
this.setState({
activeMenuArr,
subData
}, () => {
this.forceUpdate();
})
}
}
//
togglePage = (index) => {
if (index == this.state.showPage) {
this.hidePageLayer(true);
this.hideMask();
this.setState({
showPage: -1
})
} else {
if (this.state.showPage > -1) {
this.hidePageLayer(false);
}
this.showPageLayer(index);
this.showMask();
}
}
//hide
hideMask = () => {
this.setState({
isShowMask: false
}, () => {
setTimeout(() => {
this.setState({
maskVisibility: false
})
}, 200);
})
}
//show
showMask = () => {
this.setState({
maskVisibility: true
}, () => {
Taro.nextTick(() => {
setTimeout(() => {
this.setState({
isShowMask: true
})
}, 0);
})
})
}
//hide
hidePageLayer = (isAnimation) => {
let { triangleDeg, showPage, pageState } = this.state;
triangleDeg[showPage] = 0;
if (isAnimation) {
setTimeout(() => {
pageState.splice(showPage, 1, false);
this.setState({
pageState,
triangleDeg,
firstScrollInto: null,
secondScrollInto: null
})
}, 200);
this.confirm();
} else {
pageState.splice(showPage, 1, false)
this.setState({
pageState,
triangleDeg,
firstScrollInto: null,
secondScrollInto: null
})
}
// this.setState({
// triangleDeg,
// firstScrollInto: null,
// secondScrollInto: null
// }, () => {
// let tmpIndex = this.state.showPage;
// let pageState = this.state.pageState
// if (isAnimation) {
// setTimeout(() => {
// pageState.splice(tmpIndex, 1, false);
// this.setState({
// pageState
// })
// }, 200);
// this.confirm();
// } else {
// pageState.splice(tmpIndex, 1, false)
// this.setState({
// pageState
// })
// }
// })
}
confirm = () => {
let index = JSON.parse(JSON.stringify(this.state.shadowActiveMenuArr));
let value = JSON.parse(JSON.stringify(this.state.shadowActiveMenuArr));
//
const { menu } = this.state;
index.forEach((item, i) => {
if (typeof (item[0]) == 'object') {
//
item.forEach((s, j) => {
if (s != null) {
s.sort((val1, val2) => {
return val1 - val2;
});
item[j] = s;
s.forEach((v, k) => {
value[i][j][k] = (v == null || v >= this.state.subData[i].submenu[j].submenu.length) ? null : this.state.subData[i].submenu[j].submenu[v].value;
if (this.state.subData[i].type == 'radio' && value[i][j][k] == null) {
value[i][j] = [];
index[i][j] = [];
}
});
}
});
} else {
if(menu[i].type != 'date'){
let submenu = this.state.subData[i].submenu[item[0]];
value[i][0] = submenu.value;
if (value[i].length >= 2 && item[1] != null) {
if (submenu.submenu.length > 0) {
submenu = submenu.submenu[item[1]];
value[i][1] = submenu.hasOwnProperty('value') ? submenu.value : null;
} else {
value[i][1] = null
}
if (value[i].length >= 3 && item[2] != null) {
if (submenu.submenu.length > 0) {
submenu = submenu.submenu[item[2]];
value[i][2] = submenu.hasOwnProperty('value') ? submenu.value : null;
} else {
value[i][2] = null;
}
}
}
}
}
index[i] = item;
});
//
this.props.confirm({
index: index,
value: value
})
}
//show
showPageLayer = (index) => {
let pageState, showPage, triangleDeg
this.processPage(index);
pageState = this.state.pageState
pageState.splice(index, 1, true);
this.setState({
pageState
}, () => {
Taro.nextTick(() => {
setTimeout(() => {
showPage = index;
this.setState({
showPage
})
}, 0);
})
triangleDeg = this.state.triangleDeg
triangleDeg[index] = 180;
this.setState({
triangleDeg
})
})
}
reloadActiveMenuArr = () => {
let filterData, activeMenuArr, shadowActiveMenuArr, subData
for (let i = 0; i < this.state.filterData.length; i++) {
let tmpitem = this.state.filterData[i];
let tmpArr = this.processActive(tmpitem);
tmpitem = this.processSubMenu(tmpitem);
if (this.state.activeMenuArr[i].length != tmpArr.length) {
filterData = this.state.filterData
activeMenuArr = this.state.activeMenuArr
shadowActiveMenuArr = this.state.shadowActiveMenuArr
filterData[i] = tmpitem;
activeMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)));
shadowActiveMenuArr.splice(i, 1, JSON.parse(JSON.stringify(tmpArr)));
this.setState({
filterData,
activeMenuArr,
shadowActiveMenuArr
})
}
}
subData = this.state.subData
subData = this.state.filterData;
this.setState({
subData
}, () => {
this.forceUpdate();
})
}
processPage = (index) => {
let activeMenuArr, subData, firstScrollInto, secondScrollInto
//check UI,UI
this.reloadActiveMenuArr();
//UI
activeMenuArr = this.state.activeMenuArr;
console.log(activeMenuArr,index)
activeMenuArr.splice(index, 1, JSON.parse(JSON.stringify(this.state.shadowActiveMenuArr[index])));
this.setState({
activeMenuArr
}, () => {
if (this.state.menu[index].type == 'filter') {
//
let level = this.state.shadowActiveMenuArr[index].length;
for (let i = 0; i < level; i++) {
let box = this.state.subData[index].submenu[i].submenu;
for (let j = 0; j < box.length; j++) {
subData = this.state.subData
if (this.state.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
subData[index].submenu[i].submenu[j].selected = true;
} else {
subData[index].submenu[i].submenu[j].selected = false;
}
this.setState({
subData
})
}
}
} else if (this.state.menu[index].type == 'hierarchy') {
Taro.nextTick(() => {
setTimeout(() => {
//
firstScrollInto = this.state.firstScrollInto
secondScrollInto = this.state.secondScrollInto
firstScrollInto = parseInt(this.state.activeMenuArr[index][0]);
secondScrollInto = parseInt(this.state.activeMenuArr[index][1]);
this.setState({
firstScrollInto,
secondScrollInto
})
}, 0);
})
} else if (this.state.menu[index].type == 'radio') {
//
let level = this.state.shadowActiveMenuArr[index].length;
for (let i = 0; i < level; i++) {
let box = this.state.subData[index].submenu[i].submenu;
for (let j = 0; j < box.length; j++) {
subData = this.state.subData
if (this.state.shadowActiveMenuArr[index][i].indexOf(j) > -1) {
subData[index].submenu[i].submenu[j].selected = true;
} else {
subData[index].submenu[i].submenu[j].selected = false;
}
this.setState({
subData
})
}
}
}
})
}
processActive = (tmpitem) => {
let tmpArr = []
if (tmpitem.type == 'hierarchy' && tmpitem.hasOwnProperty('submenu') && tmpitem.submenu.length > 0) {
let level = this.getMaxFloor(tmpitem.submenu);
while (level > 0) {
tmpArr.push(0);
level--;
}
} else if (tmpitem.type == 'filter') {
let level = tmpitem.submenu.length;
while (level > 0) {
tmpArr.push([]);
level--;
}
} else if (tmpitem.type == 'radio') {
let level = tmpitem.submenu.length;
while (level > 0) {
tmpArr.push([]);
level--;
}
}
return tmpArr;
}
processSubMenu = (menu) => {
if (menu.hasOwnProperty('submenu') && menu.submenu.length > 0) {
for (let i = 0; i < menu.submenu.length; i++) {
menu.submenu[i] = this.processSubMenu(menu.submenu[i]);
}
} else {
menu.submenu = [];
}
return menu;
}
//
getMaxFloor = (treeData) => {
let max = 0
function each(data, floor) {
data.forEach(e => {
max = floor > max ? floor : max;
if (e.hasOwnProperty('submenu') && e.submenu.length > 0) {
each(e.submenu, floor + 1)
}
})
}
each(treeData, 1)
return max;
}
handleInitial = (value, index) => {
// console.log('initial value: ', value, ', selected index: ', index)
}
handleConfirm = (page_index, value, index) => {
console.log(page_index,'confirm value: ', value, ', selected index: ', index)
let { shadowActiveMenuArr, menu } = this.state;
shadowActiveMenuArr[page_index] = [value,index]
this.setState({
shadowActiveMenuArr
}, () => {
this.togglePage(this.state.showPage);
})
}
handleCancel = (page_index) => {
console.log('cancel action')
let { shadowActiveMenuArr } = this.state;
shadowActiveMenuArr[page_index] = []
this.setState({
shadowActiveMenuArr
}, () => {
this.togglePage(this.state.showPage);
})
}
render() {
const { menu, subData, showPage, pageState, activeMenuArr, triangleDeg, isShowMask, maskVisibility, firstScrollInto, secondScrollInto, shadowActiveMenuArr } = this.state;
//console.log(shadowActiveMenuArr)
return (
<View className='index'>
<View className='HMfilterDropdown' catchtouchmove>
<View className='nav'>
{
menu.map((item, index) => {
return (<Block key={index}>
<View className={'first-menu' + (showPage == index ? ' on' : '')} onClick={this.togglePage.bind(this, index)}>
<Text className='name'>{item.name}</Text>
<Text className='iconfont triangle' style={'transform:rotate(' + triangleDeg[index] + 'deg);'}></Text>
</View>
</Block>)
})
}
</View>
<View className={'mask' + (isShowMask ? ' show' : '') + (maskVisibility != true ? ' hide' : '')} onClick={this.togglePage.bind(this, showPage)}></View>
{
subData.map((page, page_index) => {
return (<Block key={page_index}>
<View className={'sub-menu-class' + (showPage == page_index ? ' show' : '') + (pageState[page_index] != true ? ' hide' : '')}>
{
(page.type == 'hierarchy' && page.submenu.length > 0) ? (
<Block>
<ScrollView
className={'sub-menu-list' + (activeMenuArr[page_index].length > 1 ? ' first' : ' alone')}
scrollY
scrollIntoView={'first_id' + firstScrollInto}
>
{
page.submenu.map((sub, index) => {
return (
<Block key={index}>
<View className={'sub-menu' + (activeMenuArr[page_index][0] == index ? ' on' : '')} id={'first_id' + index} onTap={this.selectHierarchyMenu.bind(this, page_index, index, null, null)}>
<View className='menu-name'>
<Text>{sub.name}</Text>
<Text className='iconfont selected'></Text>
</View>
</View>
</Block>)
})
}
</ScrollView>
<Block>
{
page.submenu.map((sub, index) => {
return (<Block key={index}>
{
(activeMenuArr[page_index][0] == index && sub.submenu.length > 0) ? (
<ScrollView
className='sub-menu-list not-first'
scrollY
scrollIntoView={'second_id' + secondScrollInto}
>
{
sub.submenu.map((sub_second, second_index) => {
return (<Block key='second_index'>
<View className={'sub-menu' + (activeMenuArr[page_index][1] == second_index ? ' on' : '')} id={'second_id' + second_index}>
<View className='menu-name' onTap={this.selectHierarchyMenu.bind(this, page_index, activeMenuArr[page_index][0], second_index, null)}>
<Text>{sub_second.name}</Text>
<Text className='iconfont selected'></Text>
</View>
{
(sub_second.submenu && sub.submenu.length > 0 && sub_second.submenu.length > 0) ? (
<View className='more-sub-menu'>
{
sub_second.submenu.map((sub2, sub2_index) => {
return (<Block key='sub2_index'>
{
(sub_second.showAllSub || (sub2_index < 8)) ? (
<Text
className={(activeMenuArr[page_index][1] == second_index && activeMenuArr[page_index][2] == sub2_index) ? 'on' : ''}
onTap={this.selectHierarchyMenu.bind(this, page_index, activeMenuArr[page_index][0], second_index, sub2_index)}
>{sub2.name}
</Text>
) : null
}
{
(sub_second.showAllSub != true && sub2_index == 8 && sub_second.submenu.length > 9) ? (
<Text onTap={this.showMoreSub.bind(this, second_index)}>更多<Text className='iconfont triangle'></Text></Text>
) : null
}
</Block>)
})
}
</View>
) : null
}
</View>
</Block>
)
})
}
</ScrollView>
) : null
}
</Block>)
})
}
</Block>
</Block>
) : null
}
{
(page.type == 'filter') ? (
<Block>
<View className='filter'>
<ScrollView className='menu-box' scrollY >
{
page.submenu.map((box, box_index) => {
return (<View className='box' key={box_index}>
<View className='title'>{box.name}</View>
<View className='labels'>
{
box.submenu.map((label, label_index) => {
return (<View
key={label_index}
onTap={this.selectFilterLabel.bind(this, page_index, box_index, label_index)}
className={label.selected ? 'on' : ''}
>{label.name}
</View>)
})
}
</View>
</View>)
})
}
</ScrollView>
<View className='btn-box'>
<View className='reset' onTap={this.resetFilterData.bind(this, page_index)}>重置</View>
<View className='submit' onTap={this.setFilterData.bind(this, page_index)}>确定</View>
</View>
</View>
</Block>
) : null
}
{
(page.type == 'radio') ? (
<Block>
<View className='filter'>
<ScrollView className='menu-box' scrollY >
{
page.submenu.map((box, box_index) => {
return (<View className='box' key={box_index}>
<View className='title'>{box.name}</View>
<View className='labels'>
{
box.submenu.map((label, label_index) => {
return (<View key={label_index} onTap={this.selectRadioLabel.bind(this, page_index, box_index, label_index)}
className={label.selected ? 'on' : ''}
>{label.name}</View>)
})
}
</View>
</View>)
})
}
</ScrollView>
<View className='btn-box'>
<View className='reset' onTap={this.resetFilterData.bind(this, page_index)}>重置</View>
<View className='submit' onTap={this.setFilterData.bind(this, page_index)}>确定</View>
</View>
</View>
</Block>
) : null
}
{
(page.type == 'date') ? (
<Block>
<View className='filter'>
<DatePicker
dateTime={page.dateTime}
onInitial={this.handleInitial}
onConfirm={this.handleConfirm.bind(this,page_index)}
onCancel={this.handleCancel.bind(this,page_index)}
mode='format'
formatShow='YYYY-MM-DD'
value={[0,0,0]}
start={946656000000}
/>
</View>
</Block>
) : null
}
</View>
</Block>)
})
}
</View>
</View >
)
}
}
FilterDropdown.propTypes = {
filterData: PropTypes.array,
defaultSelected: PropTypes.array,
updateMenuName: PropTypes.bool,
dataFormat: PropTypes.string,
}
FilterDropdown.defaultProps = {
filterData: [],
defaultSelected: [],
updateMenuName: true,
dataFormat: 'Array',
}

348
weapp/src/components/dropdown/index.scss

@ -0,0 +1,348 @@
@import 'src/styles/theme';
.HMfilterDropdown {
flex-shrink: 0;
width: 100%;
height: 88px;
position: fixed;
z-index: 997;
flex-wrap: nowrap;
display: flex;
flex-direction: row;
top: var(--window-top);
left: 0;
// view {
// display: flex;
// flex-wrap: nowrap;
// }
}
.region {
flex: 1;
height: 44px;
}
.nav {
display: flex;
flex-wrap: nowrap;
width: 100%;
height: 88px;
border-bottom: solid 1rpx #eee;
z-index: 12;
background-color: #ffffff;
flex-direction: row;
.first-menu {
display: flex;
flex-wrap: nowrap;
width: 100%;
font-size: 26px;
color: #757575;
flex-direction: row;
align-items: center;
justify-content: center;
transition: color .2s linear;
.name {
height: 40px;
text-align: center;
text-overflow: clip;
overflow: hidden;
}
.iconfont {
width: 26px;
height: 26px;
align-items: center;
justify-content: center;
transition: transform .2s linear, color .2s linear;
}
&.on {
color: $primary-color;
.iconfont {
color: $primary-color;
}
}
}
}
.sub-menu-class {
display: flex;
flex-wrap: nowrap;
width: 100%;
position: absolute;
left: 0;
transform: translate3d(0, - 100%, 0);
max-height: 690px;
background-color: #ffffff;
z-index: 11;
box-shadow: 0 10px 10px rgba(0, 0, 0, .1);
overflow: hidden;
flex-direction: row;
transition: transform .15s linear;
&.hide {
display: none;
}
&.show {
transform: translate3d(0, calc(89px), 0);
}
}
.sub-menu-list {
width: 100%;
height: 690px;
flex-direction: column;
view {
display: flex;
flex-wrap: nowrap;
}
.sub-menu {
min-height: 88px;
font-size: 26px;
flex-direction: column;
padding-right: 30px;
>.menu-name {
height: 88px;
flex-direction: row;
align-items: center;
justify-content: space-between;
>.iconfont {
display: none;
font-size: 36px;
color: $primary-color;
}
}
}
&.first {
flex-shrink: 0;
width: 236rpx;
background-color: #f0f0f0;
.sub-menu {
padding-left: 30px;
&.on {
background-color: #fff;
}
}
}
&.alone {
max-height: 690px;
min-height: 340px;
height: auto;
.sub-menu {
min-height: calc(88px - 1rpx);
margin-left: 30px;
border-bottom: solid 1rpx #e5e5e5;
&.on {
color: $primary-color;
>.menu-name {
>.iconfont {
display: block;
}
}
}
}
}
&.not-first {
.sub-menu {
min-height: calc(88px - 1rpx);
margin-left: 30px;
border-bottom: solid 1rpx #e5e5e5;
>.menu-name {
height: calc(88px - 1rpx);
>.iconfont {
display: none;
font-size: 36px;
color: $primary-color;
}
}
&.on {
color: $primary-color;
>.menu-name {
>.iconfont {
display: block;
}
}
}
.more-sub-menu {
flex-direction: row;
flex-wrap: wrap;
padding-bottom: 18px;
>text {
height: 60px;
border-radius: 6px;
background-color: #f5f5f5;
color: #9b9b9b;
margin-bottom: 12px;
margin-right: 12px;
text-align: center;
line-height: 60px;
border: solid #f5f5f5 1rpx;
flex: 0 0 calc(33.33% - 12px);
overflow: hidden;
font-size: 24px;
&:nth-child(3n) {
margin-right: 0;
}
&.on {
border-color: #f6c8ac;
color: $primary-color;
}
.iconfont {
color: #9b9b9b;
}
}
}
}
}
}
.filter {
width: 100%;
height: 690px;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
.menu-box {
width: 698rpx;
height: calc(690px - 150px);
flex-shrink: 1;
view {
display: flex;
flex-wrap: nowrap;
}
.box {
width: 100%;
margin-top: 32px;
flex-direction: column;
.title {
width: 100%;
font-size: 26px;
color: #888;
}
.labels {
flex-direction: row;
flex-wrap: wrap;
.on {
border-color: $primary-color;
background-color: $primary-color;
color: #fff;
}
>view {
width: 148rpx;
height: 60px;
border: solid 1rpx #adadad;
border-radius: 4px;
margin-right: 30px;
margin-top: 16px;
font-size: 24px;
flex-direction: row;
justify-content: center;
align-items: center;
&:nth-child(4n) {
margin-right: 0;
}
}
}
}
}
.btn-box {
flex-shrink: 0;
width: 698rpx;
height: 150px;
flex-direction: row !important;
align-items: center;
justify-content: space-between;
display: flex;
flex-wrap: nowrap;
>view {
display: flex;
flex-wrap: nowrap;
width: 320rpx;
height: 80px;
border-radius: 80px;
border: solid 1rpx $primary-color;
align-items: center;
justify-content: center;
}
.reset {
color: $primary-color;
}
.submit {
color: #fff;
background-color: $primary-color;
}
}
}
.mask {
z-index: 10;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0);
transition: background-color .15s linear;
&.show {
background-color: rgba(0, 0, 0, 0.5);
}
&.hide {
display: none;
}
}
/* 字体图标 */
@font-face {
font-family: "HM-FD-font";
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAALAAAsAAAAABpQAAAJzAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgp4gQIBNgIkAwwLCAAEIAWEbQc5G8sFERWMIbIfCbbzqA4hp7InSBibVsYGb4J42o82b3e/nJlHMw/NHbGOlwKJRCRpwzPtpAECCOZubdqxjYpQLMlVg+70/08edrgQOtx2ukpVyApZn+dyehPoQObHo3O85rYx9vOjXoBxQIHugW2yIkqIW2QXcScu4jwE8CSWbKSmrqUHFwOaJoCsLM5P4haSGIxRcRHshrUGucLCVcfqI3AZfV/+USguKCwNmtsxVztDxU/n55C+3W0Z4QQpEOTNFqCBbMCAjDUWB9CIwWk87aa70cYgqLkyd3dEmm+18R8eKATEBrV7A5CulBT8dKiWOYZk412XNcDdKSEKSGODnyKIDl+dmVt9/Dx4pu/xyeutkMlHISGPTsPCnoTNP9nOT6wTtDdlO6dPr47efvj942lkYuQzrhMKEjq9N6y98P3340gmlJ/RStUD6F31CAEEPtUW94/7rf+7XgaAz57X0ZHXAGsFFwVgw38yALuMb0IBbVyNamFYEw4oKMDTj3AHRQP5Pt4dci9VwSVkRNQh5r7CLskZadhsWHhRDBsXczk8ZYk3ewnCxmQeQKa3BOHvA8XXO2j+vqRhf7CE+sPmn4anvoL29JLa4qqaUQkmoK+QG2osCckq7txi2leK86aIPyJ3eQZ8xytXYmyQ51jQndJAxIJlqiGSLsOqImiZCjTiZCJt6Lq26U2OoXqwUo0hRaAE0K5AziANy/uLVeXzWyjVqyjcoeupjxDr5MMDn8MDkLG9Aenu5ZrOSSoghAUsRmogkkahSoWAtnlUARnCkY3It0Iu7mWhdmd9Z/19BwBP6GidEi0G56opckXTGZVSPxgAAAA=');
}
.iconfont {
font-family: "HM-FD-font" !important;
font-size: 26px;
font-style: normal;
color: #757575;
&.triangle {
&:before {
content: "\e65a";
}
}
&.selected {
&:before {
content: "\e607";
}
}
}

250
weapp/src/components/ec-canvas/ec-canvas.js

@ -0,0 +1,250 @@
import WxCanvas from './wx-canvas';
import * as echarts from './echarts';
let ctx;
function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data: {
isUseNewCanvas: false
},
ready: function () {
// Disable prograssive because drawImage doesn't support DOM as parameter
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
}
else if (typeof option.series === 'object') {
option.series.progressive = 0;
}
}
});
if (!this.data.ec) {
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
return;
}
if (!this.data.ec.lazyLoad) {
this.init();
}
},
methods: {
init: function (callback) {
const version = wx.getSystemInfoSync().SDKVersion
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
const forceUseOldCanvas = this.data.forceUseOldCanvas;
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
this.setData({ isUseNewCanvas });
if (forceUseOldCanvas && canUseNewCanvas) {
console.warn('开发者强制使用旧canvas,建议关闭');
}
if (isUseNewCanvas) {
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 可以使用 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = compareVersion(version, '1.9.91') >= 0
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。'
+ '参见:https://github.com/ecomfe/echarts-for-weixin'
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
return;
} else {
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0:原来的方式初始化
ctx = wx.createCanvasContext(this.data.canvasId, this);
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
const canvasDpr = 1
var query = wx.createSelectorQuery().in(this);
query.select('.ec-canvas').boundingClientRect(res => {
if (typeof callback === 'function') {
this.chart = callback(canvas, res.width, res.height, canvasDpr);
}
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
}
else {
this.triggerEvent('init', {
canvas: canvas,
width: res.width,
height: res.height,
canvasDpr: canvasDpr // 增加了dpr,可方便外面echarts.init
});
}
}).exec();
},
initByNewWay(callback) {
// version >= 2.9.0:使用新的方式初始化
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
this.canvasNode = canvasNode
const canvasDpr = wx.getSystemInfoSync().pixelRatio
const canvasWidth = res[0].width
const canvasHeight = res[0].height
const ctx = canvasNode.getContext('2d')
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
echarts.setCanvasCreator(() => {
return canvas
})
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
})
},
canvasToTempFilePath(opt) {
if (this.data.isUseNewCanvas) {
// 新版
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
opt.canvas = canvasNode
wx.canvasToTempFilePath(opt)
})
} else {
// 旧的
if (!opt.canvasId) {
opt.canvasId = this.data.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y
});
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'start');
}
},
touchMove(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'change');
}
},
touchEnd(e) {
if (this.chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.chart.getZr().handler;
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y
});
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'end');
}
}
}
});
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}

4
weapp/src/components/ec-canvas/ec-canvas.json

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

4
weapp/src/components/ec-canvas/ec-canvas.wxml

@ -0,0 +1,4 @@
<!-- 新的:接口对其了H5 -->
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
<!-- 旧的 -->
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>

4
weapp/src/components/ec-canvas/ec-canvas.wxss

@ -0,0 +1,4 @@
.ec-canvas {
width: 100%;
height: 100%;
}

18
weapp/src/components/ec-canvas/echarts.js

File diff suppressed because one or more lines are too long

121
weapp/src/components/ec-canvas/wx-canvas.js

@ -0,0 +1,121 @@
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
this.isNew = isNew
if (isNew) {
this.canvasNode = canvasNode;
}
else {
this._initStyle(ctx);
}
// this._initCanvas(zrender, ctx);
this._initEvent();
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx;
}
}
// canvasToTempFilePath(opt) {
// if (!opt.canvasId) {
// opt.canvasId = this.canvasId;
// }
// return wx.canvasToTempFilePath(opt, this);
// }
setChart(chart) {
this.chart = chart;
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = function () {
return ctx;
};
zrender.util.$override('measureText', function (text, font) {
ctx.font = font || '12px sans-serif';
return ctx.measureText(text);
});
}
_initStyle(ctx) {
var styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
styles.forEach(style => {
Object.defineProperty(ctx, style, {
set: value => {
if (style !== 'fillStyle' && style !== 'strokeStyle'
|| value !== 'none' && value !== null
) {
ctx['set' + style.charAt(0).toUpperCase() + style.slice(1)](value);
}
}
});
});
ctx.createRadialGradient = () => {
return ctx.createCircularGradient(arguments);
};
}
_initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown'
}, {
wxName: 'touchMove',
ecName: 'mousemove'
}, {
wxName: 'touchEnd',
ecName: 'mouseup'
}, {
wxName: 'touchEnd',
ecName: 'click'
}];
eventNames.forEach(name => {
this.event[name.wxName] = e => {
const touch = e.touches[0];
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y
});
};
});
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
get width() {
if (this.canvasNode)
return this.canvasNode.width
return 0
}
get height() {
if (this.canvasNode)
return this.canvasNode.height
return 0
}
}

29
weapp/src/components/echartForWx/common.js

@ -0,0 +1,29 @@
import React, { useState, useEffect } from 'react';
import { View, CoverView } from '@tarojs/components';
import * as echarts from "../ec-canvas/echarts";
import './common.scss'
const Common = ({ ...props }) => {
const { option } = props;
const ec = {
onInit: function (canvas, width, height, dpr) {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr
});
canvas.setChart(chart);
chart.setOption(option);
return chart;
}
}
return (
<View style={{ width: '100%', height: '100%' }}>
<ec-canvas ec={ec} force-use-old-canvas='true'></ec-canvas>
</View>
);
}
export default Common;

28
weapp/src/components/echartForWx/common.scss

@ -0,0 +1,28 @@
.tooltipContainer {
z-index: 1000;
background-color: rgba(0, 0, 0, 0.4);
position: absolute;
top: 30rpx;
color: white;
font-size: 20rpx;
border-radius: 6rpx;
.tooltip {
display: flex;
padding: 6rpx 16rpx;
justify-content: flex-start;
&:first-child {
padding-top: 10rpx;
}
&:last-child {
padding-bottom: 10rpx;
}
.color {
margin-right: 8rpx;
display: inline-block;
height: 22rpx;
width: 22rpx;
border-radius: 50%;
background-color: black;
}
}
}

26
weapp/src/components/index.js

@ -0,0 +1,26 @@
import Chart from './chart/chart';
import DatePicker from './datePicker/index';
import FilterPicker from './datePicker/filterPicker';
import ListView from './list-view/index';
import ListVirtual from './virtual-list/index';
import NoData from './no-data/noData';
import ResultPage from './result-page/index';
import LoadingPage from './loading-page/index';
import SearchBar from './searchBar/index';
import Tabs from './tabs/tabs';
import FilterDropdown from './dropdown/index';
export {
Chart,
DatePicker,
FilterPicker,
//Card,
ListView,
ListVirtual,
NoData,
ResultPage,
LoadingPage,
SearchBar,
Tabs,
FilterDropdown,
}

27
weapp/src/components/infoCard/infoCard.jsx

@ -0,0 +1,27 @@
import React, { useState } from 'react';
import { AtIcon } from "taro-ui";
import { View } from '@tarojs/components';
import './infoCard.scss';
function Card({ title, children, onClick }) {
const [showChildren, setShow] = useState(true)
function onTitleClick() {
setShow(!showChildren)
}
function onCardClick(e) {
if (onClick) {
onClick(e)
}
}
return (
<View className='info-card info-card-shadow' onClick={onCardClick}>
{title ? <View className='title' onClick={onTitleClick}>
<View className='text'>{title}</View>
<AtIcon value={showChildren ? 'chevron-down' : 'chevron-up'} size='16' color='#999'></AtIcon>
</View> : null}
{showChildren ? <View>{children}</View> : null}
</View>
);
}
export default Card;

41
weapp/src/components/infoCard/infoCard.scss

@ -0,0 +1,41 @@
.info-card {
padding: 40rpx;
background: #fff;
margin-bottom: 30px;
border-radius: 20px;
box-shadow: 0 4px 15px 0 rgba($color: #000000, $alpha: 0.06);
.title{
display: flex;
font-weight: 500;
padding-right: 10px;
padding-bottom: 20px;
.text{
padding-right: 10px;
}
}
.row {
font-size: 26px;
display: flex;
margin: 10px 0;
.color {
display: inline;
color: #2F54FF;
}
}
}
.info-card-shadow{
position: relative;
&::before{
content:'';
position: absolute;
bottom: -20px;
left: 50%;
transform: translateX(-50%);
width:90%;
height:68px;
background:rgba(0,0,0,0.06);
border-radius:9px;
filter:blur(15px);
z-index: -2;
}
}

90
weapp/src/components/list-view/index.jsx

@ -0,0 +1,90 @@
/*
* create by Xumeng 2020/12/29
* 默认无限滚动列表组件
*/
import React from 'react';
import Taro,{ useReachBottom,usePullDownRefresh } from '@tarojs/taro';
import { View, Text } from '@tarojs/components';
import { ResultPage, LoadingPage, NoData } from '@/components';
import { AtDivider, AtActivityIndicator, AtFab } from 'taro-ui';
import './index.scss';
const ListView = ({...props}) => {
const {
//swr hoosk return
data,
isLoadingInitialData,
isLoadingMore,
isEmpty,
isReachingEnd,
isRefreshing,
isValidating,
error,
size,
mutate,
setSize,
// item render function
row,
//
isScrollToTop,
ReachingEndText //
} = props;
console.log(data,isLoadingInitialData,size,isLoadingMore,isValidating,isReachingEnd)
//
usePullDownRefresh(() => {
//
Taro.showNavigationBarLoading()
//
setTimeout(function()
{
// complete
setSize(1)
mutate()
//
Taro.hideNavigationBarLoading() //
Taro.stopPullDownRefresh() //
}, 1000);
})
useReachBottom(()=>{
console.log('我要更新了')
if(!isReachingEnd && !isLoadingMore){
setSize(size + 1)
}
})
const scrollToTop = () => {
Taro.pageScrollTo({
scrollTop: 0,
duration: 300
})
}
if(error) {
return <ResultPage isError />
}
if(isLoadingInitialData) {
return <LoadingPage text='加载中...' />
}
if(isEmpty){
return <NoData />
}
return (
<View >
{data.map(row)}
{ isLoadingMore && <AtDivider fontColor='#2d8cf0' lineColor='#2d8cf0' >
<AtActivityIndicator content='加载中...'></AtActivityIndicator>
</AtDivider>}
{ isReachingEnd && <AtDivider content={ReachingEndText ? ReachingEndText : '我是有底线的'} fontColor='#2d8cf0' lineColor='#2d8cf0' />}
{
isScrollToTop &&
<View className='list-view-atfab' onClick={scrollToTop}>
<AtFab size='small'>
<Text className='at-fab__icon at-icon at-icon-menu'></Text>
</AtFab>
</View>
}
</View>
);
}
export default ListView;

5
weapp/src/components/list-view/index.scss

@ -0,0 +1,5 @@
.list-view-atfab{
position: fixed;
bottom: 50px;
right: 30px;
}

18
weapp/src/components/loading-page/index.jsx

@ -0,0 +1,18 @@
import React, { Component } from 'react';
import { View } from '@tarojs/components';
import { AtActivityIndicator } from 'taro-ui'
import './index.scss'
class LoadingPage extends Component {
render() {
const { text, pageStyle} = this.props;
return (
<View style={pageStyle ? pageStyle : ''} className='page-loading'>
<AtActivityIndicator mode='center' content={text || ''}></AtActivityIndicator>
</View>
)
}
}
export default LoadingPage;

4
weapp/src/components/loading-page/index.scss

@ -0,0 +1,4 @@
.page-loading {
height: 100vh;
position: relative;
}

29
weapp/src/components/no-data/noData.jsx

@ -0,0 +1,29 @@
import React, { Component } from 'react';
import { View,Image } from '@tarojs/components';
import './noData.scss';
import img from '../../static/img/no-data.png';
class NoData extends Component {
constructor(props) {
super(props);
this.state = {
};
}
externalClasses= ['out-class']
render() {
const {top} = this.props;
return (
<View className='out-class' style={`margin-top: ${top}`}>
<View className='no-data-box'>
<Image className='img' src={img}></Image>
<View className='text'>暂无数据</View>
</View>
</View>
);
}
}
export default NoData;

16
weapp/src/components/no-data/noData.scss

@ -0,0 +1,16 @@
.no-data-box{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.img{
width: 200px;
height: 150px;
}
.text{
margin-top: 20px;
text-align: center;
font-size: 28px;
color: #999;
}
}

BIN
weapp/src/components/result-page/assets/empty.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

42
weapp/src/components/result-page/index.jsx

@ -0,0 +1,42 @@
import React, { Component } from 'react';
import { View } from '@tarojs/components';
import './index.scss'
class Page extends Component {
render() {
const { isError, launchError, launchEmpty, isEmpty, emptyText, fetchInit } = this.props;
const showError = isError; // isErrorUI
const showErrorText = showError && !launchError; // ErrorText
const showRenderError = showError && launchError; // renderError
const showEmpty = !isError && isEmpty; // isErrorUI
const showEmptyText = showEmpty && !launchEmpty; // emptyText
const showRenderEmpty = showEmpty && launchEmpty; // renderEmpty
return (
<View>
{showErrorText && (
<View className='errorPage'>
<View className='marginBottom30'>网络似乎开小差了~</View>
{
fetchInit && <View className='button' onClick={fetchInit}>
重新加载
</View>
}
</View>
)}
{/* custom error page */}
{showRenderError ? this.props.renderError : ''}
{/* default blank page */}
{showEmptyText && (
<View className='noContentTips'>
{emptyText}
</View>
)}
{/* custom blank page */}
{showRenderEmpty ? this.props.renderEmpty : ''}
</View>
)}
}
export default Page;

28
weapp/src/components/result-page/index.scss

@ -0,0 +1,28 @@
.errorPage {
text-align: center;
padding: 40px;
font-size: 30px;
.button {
border-radius: 10px;
margin-top: 10px;
display: inline-block;
border: 1px solid cornflowerblue;
color: cornflowerblue;
padding: 10px;
}
}
.noContentTips {
display: flex;
padding: 100px 20px 20px;
text-align: center;
flex-direction: column;
.emptyBanner {
width: 250px;
height: 170px;
display: inline-block;
margin: 0 auto 20px;
}
}
.marginBottom30 {
margin-bottom: 30px;
}

212
weapp/src/components/searchBar/index.jsx

@ -0,0 +1,212 @@
/*
* create by Xumeng 2020/01/07
* 通用搜索栏组件可选筛选抽屉 filterOptions 暂支持 select 日期时间日历
* filterOptions = [
{
field: 'name',
type: 'SELECT',
label: '业务类型',
list: [{id: 1, name: '张三'},{ id:2, name: '李四'}],
},
{
field: 'createDate',
type: 'DATE',
label: '申请日期',
},
{
field: 'applyTime',
type: 'TIME',
label: '申请时间',
},
{
field: 'endTime',
type: 'CALENDAR',
label: '结束时间',
},
]
*/
import React, { useState } from 'react';
import { View, Picker, Button } from '@tarojs/components';
import { AtButton, AtSearchBar, AtDrawer, AtList, AtListItem, AtCalendar, AtModal, AtModalContent, AtModalAction } from 'taro-ui';
import { useVisible } from '@/hooks/useCommon';
import './index.scss';
const SearchBar = ({...props}) => {
const { btnName, filterOptions, onFilterSubmit, onSearch } = props;
const [value, setValue] = useState('');
const [filterValues, setFilterValues] = useState({});
const { visible, show, close } = useVisible();
const { visible: calendarVisble, show: calendarShow, close: calendarClose } = useVisible();
const [calendarFiled, setCalendarFiled] = useState('');
const [calendarSelectedDate, setCalendarSelectedDate] = useState('');
const handerChange = (e) => {
setValue(e)
}
const handerActionClick = () => {
onSearch && onSearch(value)
}
const handerShowFilter = () => {
show();
}
const handerHideFilter = () => {
close();
}
const handlerShowCalendar = (filed) => {
calendarShow();
setCalendarFiled(filed)
}
//filter
const handerReSet = () => {
setFilterValues({})
}
//filter
const handerSubmit = () => {
close();
onFilterSubmit && onFilterSubmit(filterValues);
}
//
const handerTimeChange = (e,filed) => {
setFilterValues({...filterValues, [filed]: e.detail.value})
}
//
const handerDateChange = (e,filed) => {
setFilterValues({...filterValues, [filed]: e.detail.value})
}
//
const handerSelectChange = (e,filed,list) => {
setFilterValues({...filterValues, [filed]: list[e.detail.value]})
}
//
const handeSelectDate = (selectDate) => {
console.log(selectDate)
setCalendarSelectedDate(selectDate)
}
const handleModalConfirm = () => {
setFilterValues({...filterValues, [calendarFiled]: calendarSelectedDate?.value})
calendarClose()
}
//filteritem
const renderFields = () => {
const fieldItemList = [];
if (filterOptions && filterOptions.length > 0) {
filterOptions.forEach((item, index) => {
const { label, field, type, list } = item;
switch (type) {
case 'TIME':
const TIME = (
<View className='search-drawer-item' key={`${field}-${index}`}>
<Picker mode='time' onChange={(e) => handerTimeChange(e,field)}>
<AtList hasBorder={false}>
<AtListItem title={label || '请选择时间'} extraText={filterValues[field] || ''} />
</AtList>
</Picker>
</View>
);
fieldItemList.push(TIME);
break;
case 'DATE':
const DATE = (
<View className='search-drawer-item' key={`${field}-${index}`}>
<Picker mode='date' onChange={(e) => handerDateChange(e,field)}>
<AtList hasBorder={false}>
<AtListItem title={label || '请选择日期'} extraText={filterValues[field] || ''} />
</AtList>
</Picker>
</View>
);
fieldItemList.push(DATE);
break;
case 'SELECT':
const SELECT = (
<View className='search-drawer-item' key={`${field}-${index}`}>
<Picker mode='selector' range={Array.isArray(list) && list.map(s => s.name)} onChange={(e) =>handerSelectChange(e,field,list)}>
<AtList hasBorder={false}>
<AtListItem
title={label || '请选择'}
extraText={filterValues[field] && filterValues[field].name || ''}
/>
</AtList>
</Picker>
</View>
);
fieldItemList.push(SELECT);
break;
case 'CALENDAR':
const CALENDAR = (
<View className='search-drawer-item' key={`${field}-${index}`}>
<AtList hasBorder={false}>
<AtListItem title={label || '请选择日期区间'} extraText={filterValues[field] && `${filterValues[field]?.start} - ${filterValues[field]?.end}` || ''} onClick={()=> handlerShowCalendar(field)} />
</AtList>
</View>
);
fieldItemList.push(CALENDAR);
break;
default:
break;
}
});
}
return fieldItemList;
}
return (
<View className='search-bar'>
{
filterOptions && Array.isArray(filterOptions) ?
<View className='at-row at-row__align--center'>
<View className='at-col at-col-11'>
<AtSearchBar
actionName={btnName || '搜索'}
value={value}
onChange={handerChange}
onActionClick={handerActionClick}
/>
</View>
<View className='at-col at-col-1'>
<View className='at-icon at-icon-list search-filter' onClick={handerShowFilter}></View>
</View>
</View> :
<AtSearchBar
actionName={btnName || '搜索'}
value={value}
onChange={handerChange}
onActionClick={handerActionClick}
/>
}
<AtDrawer
show={visible}
onClose={handerHideFilter}
right
mask
width='70%'
>
{renderFields()}
<View className='search-drawer-item-btn'>
<View className='at-row at-row__justify--around'>
<View className='at-col at-col-5'>
<AtButton type='primary' size='small' onClick={handerReSet}>重置</AtButton>
</View>
<View className='at-col at-col-5'>
<AtButton type='primary' size='small' onClick={handerSubmit}>确定</AtButton>
</View>
</View>
</View>
</AtDrawer>
<AtModal
isOpened={calendarVisble}
onClose={()=> {calendarClose()}}
>
<AtModalContent>
<AtCalendar isMultiSelect onSelectDate={handeSelectDate} currentDate={filterValues[calendarFiled] || Date.now()} />
</AtModalContent>
<AtModalAction > <Button onClick={()=> {calendarClose()}}>取消</Button> <Button onClick={handleModalConfirm}>确定</Button> </AtModalAction>
</AtModal>
</View>
);
}
export default SearchBar;

14
weapp/src/components/searchBar/index.scss

@ -0,0 +1,14 @@
@import 'src/styles/theme';
.search-bar {
.search-filter {
font-size: 48px;
color: $primary-color;
}
.search-drawer-item-btn {
margin-top: 20px;
}
// .search-drawer-item {
// margin: 5px 10px;
// }
}

38
weapp/src/components/tabs/tabs.jsx

@ -0,0 +1,38 @@
import React, { Component } from 'react';
import { CoverView } from '@tarojs/components';
import './tabs.scss';
class Tabs extends Component {
constructor(props) {
super(props);
this.state = {
activeIdx:props.current || 0
};
}
onCellClick(val,idx){
this.setState({
activeIdx: idx
})
this.props.onChange(val,idx)
}
render() {
const {list=[], padding} = this.props;
const {activeIdx} = this.state;
const cell = list.length===2?'cell half':'cell'
return (
<CoverView className='tabs-box' style={`padding: ${padding}`}>
<CoverView className='bg'></CoverView>
<CoverView className='tabs-row' style={`${list.length===2?'justify-content: space-between':''}`}>
{list.map((val,idx)=>{
return <CoverView className={`${cell} ${activeIdx ===idx?'active':''}`} key={val.id} onClick={this.onCellClick.bind(this,val,idx)}>{val.title}</CoverView>
})}
</CoverView>
</CoverView>
);
}
}
export default Tabs;

87
weapp/src/components/tabs/tabs.scss

@ -0,0 +1,87 @@
.tabs-box{
position: fixed;
top: 0;
left: 0;
width: 100%;
box-sizing: border-box;
z-index: 99;
.bg{
position: absolute;
bottom: 50%;
left: 0;
width: 100%;
height: 100%;
background-color: #f7f7f7;
z-index: -1;
}
}
.tabs-row{
position: relative;
display: flex;
// justify-content: space-between;
align-items: center;
height: 80px;
width: 684px;
margin: 0 auto;
box-sizing: border-box;
background-color:transparen;
font-size: 28px;
border-radius: 40px;
// box-shadow:0px 10px 10px 4px rgba(0,0,0,0.06);
border: 1px solid #00000006;
background-color: #fff;
overflow-x: scroll;
overflow-y: hidden;
z-index: 99;
// .bg{
// position: absolute;
// top: 50%;
// transform: translateY(-50%);
// bottom: 0px;
// width: 100%;
// height: 64px;
// background-color: #fff;
// // box-shadow:0px 10px 10px 10px rgba(0,0,0,0.06);
// z-index: -1;
// }
.cell{
// border-radius: 36px;
color: #B2B2B2;
// padding: 0px 50px;
height: 80px;
line-height: 80px;
width: 228px;
text-align: center;
flex-shrink: 0;
background-color: #fff;
}
.active{
background-color: #2F54FF;
color: #fff;
box-sizing: content-box;
font-size: 30px;
border-radius: 40px;
}
.half{
width: 342px;
}
}
//伪类阴影 父元素需设置z-index和position: relative;
// .shadow{
// position: relative;
// &::before{
// content:'';
// position: absolute;
// bottom: -20px;
// left: 50%;
// transform: translateX(-50%);
// width:90%;
// height:68px;
// background:rgba(0,0,0,0.06);
// border-radius:9px;
// filter:blur(15px);
// z-index: -2;
// }
// }

1
weapp/src/components/vant-weapp/button/index.d.ts

@ -0,0 +1 @@
export {};

58
weapp/src/components/vant-weapp/button/index.js

@ -0,0 +1,58 @@
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
import { canIUseFormFieldButton } from '../common/version';
const mixins = [button, openType];
if (canIUseFormFieldButton()) {
mixins.push('wx://form-field-button');
}
VantComponent({
mixins,
classes: ['hover-class', 'loading-class'],
data: {
baseStyle: '',
},
props: {
formType: String,
icon: String,
classPrefix: {
type: String,
value: 'van-icon',
},
plain: Boolean,
block: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
loadingText: String,
customStyle: String,
loadingType: {
type: String,
value: 'circular',
},
type: {
type: String,
value: 'default',
},
dataset: null,
size: {
type: String,
value: 'normal',
},
loadingSize: {
type: String,
value: '20px',
},
color: String,
},
methods: {
onClick() {
if (!this.data.loading) {
this.$emit('click');
}
},
noop() {},
},
});

7
weapp/src/components/vant-weapp/button/index.json

@ -0,0 +1,7 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index",
"van-loading": "../loading/index"
}
}

53
weapp/src/components/vant-weapp/button/index.wxml

@ -0,0 +1,53 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<button
id="{{ id }}"
data-detail="{{ dataset }}"
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'van-hairline--surround' : '' }}"
hover-class="van-button--active hover-class"
lang="{{ lang }}"
form-type="{{ formType }}"
style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
open-type="{{ disabled ? '' : openType }}"
business-id="{{ businessId }}"
session-from="{{ sessionFrom }}"
send-message-title="{{ sendMessageTitle }}"
send-message-path="{{ sendMessagePath }}"
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
app-parameter="{{ appParameter }}"
aria-label="{{ ariaLabel }}"
bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
bindgetuserinfo="bindGetUserInfo"
bindcontact="bindContact"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindlaunchapp="bindLaunchApp"
bindopensetting="bindOpenSetting"
>
<block wx:if="{{ loading }}">
<van-loading
custom-class="loading-class"
size="{{ loadingSize }}"
type="{{ loadingType }}"
color="{{ computed.loadingColor({ type, color, plain }) }}"
/>
<view wx:if="{{ loadingText }}" class="van-button__loading-text">
{{ loadingText }}
</view>
</block>
<block wx:else>
<van-icon
wx:if="{{ icon }}"
size="1.2em"
name="{{ icon }}"
class-prefix="{{ classPrefix }}"
class="van-button__icon"
custom-style="line-height: inherit;"
/>
<view class="van-button__text">
<slot />
</view>
</block>
</button>

39
weapp/src/components/vant-weapp/button/index.wxs

@ -0,0 +1,39 @@
/* eslint-disable */
var style = require('../wxs/style.wxs');
function rootStyle(data) {
if (!data.color) {
return data.customStyle;
}
var properties = {
color: data.plain ? data.color : '#fff',
background: data.plain ? null : data.color,
};
// hide border when color is linear-gradient
if (data.color.indexOf('gradient') !== -1) {
properties.border = 0;
} else {
properties['border-color'] = data.color;
}
return style([properties, data.customStyle]);
}
function loadingColor(data) {
if (data.plain) {
return data.color ? data.color : '#c9c9c9';
}
if (data.type === 'default') {
return '#c9c9c9';
}
return '#fff';
}
module.exports = {
rootStyle: rootStyle,
loadingColor: loadingColor,
};

1
weapp/src/components/vant-weapp/button/index.wxss

@ -0,0 +1 @@
@import '../common/index.wxss';.van-button{position:relative;display:-webkit-inline-flex;display:inline-flex;-webkit-align-items:center;align-items:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;padding:0;text-align:center;vertical-align:middle;-webkit-appearance:none;-webkit-text-size-adjust:100%;height:44px;height:var(--button-default-height,44px);line-height:20px;line-height:var(--button-line-height,20px);font-size:16px;font-size:var(--button-default-font-size,16px);transition:opacity .2s;transition:opacity var(--animation-duration-fast,.2s);border-radius:2px;border-radius:var(--button-border-radius,2px)}.van-button:before{position:absolute;top:50%;left:50%;width:100%;height:100%;border:inherit;border-radius:inherit;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);opacity:0;content:" ";background-color:#000;background-color:var(--black,#000);border-color:#000;border-color:var(--black,#000)}.van-button:after{border-width:0}.van-button--active:before{opacity:.15}.van-button--unclickable:after{display:none}.van-button--default{color:#323233;color:var(--button-default-color,#323233);background:#fff;background:var(--button-default-background-color,#fff);border:1px solid #ebedf0;border:var(--button-border-width,1px) solid var(--button-default-border-color,#ebedf0)}.van-button--primary{color:#fff;color:var(--button-primary-color,#fff);background:#07c160;background:var(--button-primary-background-color,#07c160);border:1px solid #07c160;border:var(--button-border-width,1px) solid var(--button-primary-border-color,#07c160)}.van-button--info{color:#fff;color:var(--button-info-color,#fff);background:#1989fa;background:var(--button-info-background-color,#1989fa);border:1px solid #1989fa;border:var(--button-border-width,1px) solid var(--button-info-border-color,#1989fa)}.van-button--danger{color:#fff;color:var(--button-danger-color,#fff);background:#ee0a24;background:var(--button-danger-background-color,#ee0a24);border:1px solid #ee0a24;border:var(--button-border-width,1px) solid var(--button-danger-border-color,#ee0a24)}.van-button--warning{color:#fff;color:var(--button-warning-color,#fff);background:#ff976a;background:var(--button-warning-background-color,#ff976a);border:1px solid #ff976a;border:var(--button-border-width,1px) solid var(--button-warning-border-color,#ff976a)}.van-button--plain{background:#fff;background:var(--button-plain-background-color,#fff)}.van-button--plain.van-button--primary{color:#07c160;color:var(--button-primary-background-color,#07c160)}.van-button--plain.van-button--info{color:#1989fa;color:var(--button-info-background-color,#1989fa)}.van-button--plain.van-button--danger{color:#ee0a24;color:var(--button-danger-background-color,#ee0a24)}.van-button--plain.van-button--warning{color:#ff976a;color:var(--button-warning-background-color,#ff976a)}.van-button--large{width:100%;height:50px;height:var(--button-large-height,50px)}.van-button--normal{padding:0 15px;font-size:14px;font-size:var(--button-normal-font-size,14px)}.van-button--small{min-width:60px;min-width:var(--button-small-min-width,60px);height:30px;height:var(--button-small-height,30px);padding:0 8px;padding:0 var(--padding-xs,8px);font-size:12px;font-size:var(--button-small-font-size,12px)}.van-button--mini{display:inline-block;min-width:50px;min-width:var(--button-mini-min-width,50px);height:22px;height:var(--button-mini-height,22px);font-size:10px;font-size:var(--button-mini-font-size,10px)}.van-button--mini+.van-button--mini{margin-left:5px}.van-button--block{display:-webkit-flex;display:flex;width:100%}.van-button--round{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--square{border-radius:0}.van-button--disabled{opacity:.5;opacity:var(--button-disabled-opacity,.5)}.van-button__text{display:inline}.van-button__icon+.van-button__text:not(:empty),.van-button__loading-text{margin-left:4px}.van-button__icon{min-width:1em;line-height:inherit!important;vertical-align:top}.van-button--hairline{padding-top:1px;border-width:0}.van-button--hairline:after{border-color:inherit;border-width:1px;border-radius:4px;border-radius:calc(var(--button-border-radius, 2px)*2)}.van-button--hairline.van-button--round:after{border-radius:999px;border-radius:var(--button-round-border-radius,999px)}.van-button--hairline.van-button--square:after{border-radius:0}

1
weapp/src/components/vant-weapp/cell-group/index.d.ts

@ -0,0 +1 @@
export {};

10
weapp/src/components/vant-weapp/cell-group/index.js

@ -0,0 +1,10 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
border: {
type: Boolean,
value: true,
},
},
});

3
weapp/src/components/vant-weapp/cell-group/index.json

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

9
weapp/src/components/vant-weapp/cell-group/index.wxml

@ -0,0 +1,9 @@
<view
wx:if="{{ title }}"
class="van-cell-group__title"
>
{{ title }}
</view>
<view class="custom-class van-cell-group {{ border ? 'van-hairline--top-bottom' : '' }}">
<slot />
</view>

1
weapp/src/components/vant-weapp/cell-group/index.wxss

@ -0,0 +1 @@
@import '../common/index.wxss';.van-cell-group__title{padding:16px 16px 8px;padding:var(--cell-group-title-padding,16px 16px 8px);font-size:14px;font-size:var(--cell-group-title-font-size,14px);line-height:16px;line-height:var(--cell-group-title-line-height,16px);color:#969799;color:var(--cell-group-title-color,#969799)}

1
weapp/src/components/vant-weapp/cell/index.d.ts

@ -0,0 +1 @@
export {};

38
weapp/src/components/vant-weapp/cell/index.js

@ -0,0 +1,38 @@
import { link } from '../mixins/link';
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'title-class',
'label-class',
'value-class',
'right-icon-class',
'hover-class',
],
mixins: [link],
props: {
title: null,
value: null,
icon: String,
size: String,
label: String,
center: Boolean,
isLink: Boolean,
required: Boolean,
clickable: Boolean,
titleWidth: String,
customStyle: String,
arrowDirection: String,
useLabelSlot: Boolean,
border: {
type: Boolean,
value: true,
},
titleStyle: String,
},
methods: {
onClick(event) {
this.$emit('click', event.detail);
this.jumpLink();
},
},
});

6
weapp/src/components/vant-weapp/cell/index.json

@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"van-icon": "../icon/index"
}
}

46
weapp/src/components/vant-weapp/cell/index.wxml

@ -0,0 +1,46 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable }]) }}"
hover-class="van-cell--hover hover-class"
hover-stay-time="70"
style="{{ customStyle }}"
bind:tap="onClick"
>
<van-icon
wx:if="{{ icon }}"
name="{{ icon }}"
class="van-cell__left-icon-wrap"
custom-class="van-cell__left-icon"
/>
<slot wx:else name="icon" />
<view
style="{{ computed.titleStyle({ titleWidth, titleStyle }) }}"
class="van-cell__title title-class"
>
<block wx:if="{{ title }}">{{ title }}</block>
<slot wx:else name="title" />
<view wx:if="{{ label || useLabelSlot }}" class="van-cell__label label-class">
<slot wx:if="{{ useLabelSlot }}" name="label" />
<block wx:elif="{{ label }}">{{ label }}</block>
</view>
</view>
<view class="van-cell__value value-class">
<block wx:if="{{ value || value === 0 }}">{{ value }}</block>
<slot wx:else />
</view>
<van-icon
wx:if="{{ isLink }}"
name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
class="van-cell__right-icon-wrap right-icon-class"
custom-class="van-cell__right-icon"
/>
<slot wx:else name="right-icon" />
<slot name="extra" />
</view>

17
weapp/src/components/vant-weapp/cell/index.wxs

@ -0,0 +1,17 @@
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function titleStyle(data) {
return style([
{
'max-width': addUnit(data.titleWidth),
'min-width': addUnit(data.titleWidth),
},
data.titleStyle,
]);
}
module.exports = {
titleStyle: titleStyle,
};

1
weapp/src/components/vant-weapp/cell/index.wxss

@ -0,0 +1 @@
@import '../common/index.wxss';.van-cell{position:relative;display:-webkit-flex;display:flex;box-sizing:border-box;width:100%;padding:10px 16px;padding:var(--cell-vertical-padding,10px) var(--cell-horizontal-padding,16px);font-size:14px;font-size:var(--cell-font-size,14px);line-height:24px;line-height:var(--cell-line-height,24px);color:#323233;color:var(--cell-text-color,#323233);background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;right:16px;bottom:0;left:16px;border-bottom:1px solid #ebedf0;-webkit-transform:scaleY(.5);transform:scaleY(.5)}.van-cell--borderless:after{display:none}.van-cell-group{background-color:#fff;background-color:var(--cell-background-color,#fff)}.van-cell__label{margin-top:3px;margin-top:var(--cell-label-margin-top,3px);font-size:12px;font-size:var(--cell-label-font-size,12px);line-height:18px;line-height:var(--cell-label-line-height,18px);color:#969799;color:var(--cell-label-color,#969799)}.van-cell__value{overflow:hidden;text-align:right;vertical-align:middle;color:#969799;color:var(--cell-value-color,#969799)}.van-cell__title,.van-cell__value{-webkit-flex:1;flex:1}.van-cell__title:empty,.van-cell__value:empty{display:none}.van-cell__left-icon-wrap,.van-cell__right-icon-wrap{display:-webkit-flex;display:flex;-webkit-align-items:center;align-items:center;height:24px;height:var(--cell-line-height,24px);font-size:16px;font-size:var(--cell-icon-size,16px)}.van-cell__left-icon-wrap{margin-right:4px;margin-right:var(--padding-base,4px)}.van-cell__right-icon-wrap{margin-left:4px;margin-left:var(--padding-base,4px);color:#969799;color:var(--cell-right-icon-color,#969799)}.van-cell__left-icon{vertical-align:middle}.van-cell__left-icon,.van-cell__right-icon{line-height:24px;line-height:var(--cell-line-height,24px)}.van-cell--clickable.van-cell--hover{background-color:#f2f3f5;background-color:var(--cell-active-color,#f2f3f5)}.van-cell--required{overflow:visible}.van-cell--required:before{position:absolute;content:"*";left:8px;left:var(--padding-xs,8px);font-size:14px;font-size:var(--cell-font-size,14px);color:#ee0a24;color:var(--cell-required-color,#ee0a24)}.van-cell--center{-webkit-align-items:center;align-items:center}.van-cell--large{padding-top:12px;padding-top:var(--cell-large-vertical-padding,12px);padding-bottom:12px;padding-bottom:var(--cell-large-vertical-padding,12px)}.van-cell--large .van-cell__title{font-size:16px;font-size:var(--cell-large-title-font-size,16px)}.van-cell--large .van-cell__value{font-size:16px;font-size:var(--cell-large-value-font-size,16px)}.van-cell--large .van-cell__label{font-size:14px;font-size:var(--cell-large-label-font-size,14px)}

1
weapp/src/components/vant-weapp/col/index.d.ts

@ -0,0 +1 @@
export {};

9
weapp/src/components/vant-weapp/col/index.js

@ -0,0 +1,9 @@
import { useParent } from '../common/relation';
import { VantComponent } from '../common/component';
VantComponent({
relation: useParent('row'),
props: {
span: Number,
offset: Number,
},
});

3
weapp/src/components/vant-weapp/col/index.json

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

9
weapp/src/components/vant-weapp/col/index.wxml

@ -0,0 +1,9 @@
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="./index.wxs" module="computed" />
<view
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'van-col--offset-' + offset : '' }}"
style="{{ computed.rootStyle({ gutter }) }}"
>
<slot />
</view>

18
weapp/src/components/vant-weapp/col/index.wxs

@ -0,0 +1,18 @@
/* eslint-disable */
var style = require('../wxs/style.wxs');
var addUnit = require('../wxs/add-unit.wxs');
function rootStyle(data) {
if (!data.gutter) {
return '';
}
return style({
'padding-right': addUnit(data.gutter / 2),
'padding-left': addUnit(data.gutter / 2),
});
}
module.exports = {
rootStyle: rootStyle,
};

1
weapp/src/components/vant-weapp/col/index.wxss

@ -0,0 +1 @@
@import '../common/index.wxss';.van-col{float:left;box-sizing:border-box}.van-col--1{width:4.16666667%}.van-col--offset-1{margin-left:4.16666667%}.van-col--2{width:8.33333333%}.van-col--offset-2{margin-left:8.33333333%}.van-col--3{width:12.5%}.van-col--offset-3{margin-left:12.5%}.van-col--4{width:16.66666667%}.van-col--offset-4{margin-left:16.66666667%}.van-col--5{width:20.83333333%}.van-col--offset-5{margin-left:20.83333333%}.van-col--6{width:25%}.van-col--offset-6{margin-left:25%}.van-col--7{width:29.16666667%}.van-col--offset-7{margin-left:29.16666667%}.van-col--8{width:33.33333333%}.van-col--offset-8{margin-left:33.33333333%}.van-col--9{width:37.5%}.van-col--offset-9{margin-left:37.5%}.van-col--10{width:41.66666667%}.van-col--offset-10{margin-left:41.66666667%}.van-col--11{width:45.83333333%}.van-col--offset-11{margin-left:45.83333333%}.van-col--12{width:50%}.van-col--offset-12{margin-left:50%}.van-col--13{width:54.16666667%}.van-col--offset-13{margin-left:54.16666667%}.van-col--14{width:58.33333333%}.van-col--offset-14{margin-left:58.33333333%}.van-col--15{width:62.5%}.van-col--offset-15{margin-left:62.5%}.van-col--16{width:66.66666667%}.van-col--offset-16{margin-left:66.66666667%}.van-col--17{width:70.83333333%}.van-col--offset-17{margin-left:70.83333333%}.van-col--18{width:75%}.van-col--offset-18{margin-left:75%}.van-col--19{width:79.16666667%}.van-col--offset-19{margin-left:79.16666667%}.van-col--20{width:83.33333333%}.van-col--offset-20{margin-left:83.33333333%}.van-col--21{width:87.5%}.van-col--offset-21{margin-left:87.5%}.van-col--22{width:91.66666667%}.van-col--offset-22{margin-left:91.66666667%}.van-col--23{width:95.83333333%}.van-col--offset-23{margin-left:95.83333333%}.van-col--24{width:100%}.van-col--offset-24{margin-left:100%}

7
weapp/src/components/vant-weapp/common/color.d.ts

@ -0,0 +1,7 @@
export declare const RED = "#ee0a24";
export declare const BLUE = "#1989fa";
export declare const WHITE = "#fff";
export declare const GREEN = "#07c160";
export declare const ORANGE = "#ff976a";
export declare const GRAY = "#323233";
export declare const GRAY_DARK = "#969799";

7
weapp/src/components/vant-weapp/common/color.js

@ -0,0 +1,7 @@
export const RED = '#ee0a24';
export const BLUE = '#1989fa';
export const WHITE = '#fff';
export const GREEN = '#07c160';
export const ORANGE = '#ff976a';
export const GRAY = '#323233';
export const GRAY_DARK = '#969799';

8
weapp/src/components/vant-weapp/common/component.d.ts

@ -0,0 +1,8 @@
/// <reference types="miniprogram-api-typings" />
import { VantComponentOptions } from '../definitions/index';
declare function VantComponent<
Data extends WechatMiniprogram.Component.DataOption,
Props extends WechatMiniprogram.Component.PropertyOption,
Methods extends WechatMiniprogram.Component.MethodOption
>(vantOptions: VantComponentOptions<Data, Props, Methods>): void;
export { VantComponent };

45
weapp/src/components/vant-weapp/common/component.js

@ -0,0 +1,45 @@
import { basic } from '../mixins/basic';
function mapKeys(source, target, map) {
Object.keys(map).forEach((key) => {
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function VantComponent(vantOptions) {
const options = {};
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
mixins: 'behaviors',
methods: 'methods',
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
destroyed: 'detached',
classes: 'externalClasses',
});
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
// add default behaviors
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// add relations
const { relation } = vantOptions;
if (relation) {
options.relations = relation.relations;
options.behaviors.push(relation.mixin);
}
// map field to form-field behavior
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
options.options = {
multipleSlots: true,
addGlobalClass: true,
};
Component(options);
}
export { VantComponent };

1
weapp/src/components/vant-weapp/common/index.wxss

@ -0,0 +1 @@
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}.van-clearfix:after{display:table;clear:both;content:""}.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #ebedf0;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}

21
weapp/src/components/vant-weapp/common/relation.d.ts

@ -0,0 +1,21 @@
/// <reference types="miniprogram-api-typings" />
declare type TrivialInstance = WechatMiniprogram.Component.TrivialInstance;
export declare function useParent(
name: string,
onEffect?: (this: TrivialInstance) => void
): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export declare function useChildren(
name: string,
onEffect?: (this: TrivialInstance, target: TrivialInstance) => void
): {
relations: {
[x: string]: WechatMiniprogram.Component.RelationOption;
};
mixin: string;
};
export {};

64
weapp/src/components/vant-weapp/common/relation.js

@ -0,0 +1,64 @@
export function useParent(name, onEffect) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'ancestor',
linked() {
onEffect && onEffect.call(this);
},
linkChanged() {
onEffect && onEffect.call(this);
},
unlinked() {
onEffect && onEffect.call(this);
},
},
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'parent', {
get: () => this.getRelationNodes(path)[0],
});
Object.defineProperty(this, 'index', {
// @ts-ignore
get: () => {
var _a, _b;
return (_b =
(_a = this.parent) === null || _a === void 0
? void 0
: _a.children) === null || _b === void 0
? void 0
: _b.indexOf(this);
},
});
},
}),
};
}
export function useChildren(name, onEffect) {
const path = `../${name}/index`;
return {
relations: {
[path]: {
type: 'descendant',
linked(target) {
onEffect && onEffect.call(this, target);
},
linkChanged(target) {
onEffect && onEffect.call(this, target);
},
unlinked(target) {
onEffect && onEffect.call(this, target);
},
},
},
mixin: Behavior({
created() {
Object.defineProperty(this, 'children', {
get: () => this.getRelationNodes(path) || [],
});
},
}),
};
}

1
weapp/src/components/vant-weapp/common/style/clearfix.wxss

@ -0,0 +1 @@
.van-clearfix:after{display:table;clear:both;content:""}

1
weapp/src/components/vant-weapp/common/style/ellipsis.wxss

@ -0,0 +1 @@
.van-ellipsis{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.van-multi-ellipsis--l2{-webkit-line-clamp:2}.van-multi-ellipsis--l2,.van-multi-ellipsis--l3{display:-webkit-box;overflow:hidden;text-overflow:ellipsis;-webkit-box-orient:vertical}.van-multi-ellipsis--l3{-webkit-line-clamp:3}

1
weapp/src/components/vant-weapp/common/style/hairline.wxss

@ -0,0 +1 @@
.van-hairline,.van-hairline--bottom,.van-hairline--left,.van-hairline--right,.van-hairline--surround,.van-hairline--top,.van-hairline--top-bottom{position:relative}.van-hairline--bottom:after,.van-hairline--left:after,.van-hairline--right:after,.van-hairline--surround:after,.van-hairline--top-bottom:after,.van-hairline--top:after,.van-hairline:after{position:absolute;box-sizing:border-box;-webkit-transform-origin:center;transform-origin:center;content:" ";pointer-events:none;top:-50%;right:-50%;bottom:-50%;left:-50%;border:0 solid #ebedf0;-webkit-transform:scale(.5);transform:scale(.5)}.van-hairline--top:after{border-top-width:1px}.van-hairline--left:after{border-left-width:1px}.van-hairline--right:after{border-right-width:1px}.van-hairline--bottom:after{border-bottom-width:1px}.van-hairline--top-bottom:after{border-width:1px 0}.van-hairline--surround:after{border-width:1px}

0
weapp/src/components/vant-weapp/common/style/mixins/clearfix.wxss

0
weapp/src/components/vant-weapp/common/style/mixins/ellipsis.wxss

0
weapp/src/components/vant-weapp/common/style/mixins/hairline.wxss

0
weapp/src/components/vant-weapp/common/style/theme.wxss

0
weapp/src/components/vant-weapp/common/style/var.wxss

30
weapp/src/components/vant-weapp/common/utils.d.ts

@ -0,0 +1,30 @@
/// <reference types="miniprogram-api-typings" />
export declare function range(num: number, min: number, max: number): number;
export declare function nextTick(cb: (...args: any[]) => void): void;
export declare function getSystemInfoSync(): WechatMiniprogram.GetSystemInfoSyncResult;
export declare function addUnit(value?: string | number): string | undefined;
export declare function requestAnimationFrame(
cb: () => void
): number | WechatMiniprogram.NodesRef;
export declare function pickExclude(obj: unknown, keys: string[]): {};
export declare function getRect(
context: WechatMiniprogram.Component.TrivialInstance,
selector: string
): Promise<WechatMiniprogram.BoundingClientRectCallbackResult>;
export declare function getAllRect(
context: WechatMiniprogram.Component.TrivialInstance,
selector: string
): Promise<WechatMiniprogram.BoundingClientRectCallbackResult[]>;
export declare function groupSetData(
context: WechatMiniprogram.Component.TrivialInstance,
cb: () => void
): void;
export declare function toPromise(
promiseLike: Promise<unknown> | unknown
): Promise<unknown>;
export declare function getCurrentPage<T>(): T &
WechatMiniprogram.OptionalInterface<WechatMiniprogram.Page.ILifetime> &
WechatMiniprogram.Page.InstanceProperties &
WechatMiniprogram.Page.InstanceMethods<Record<string, any>> &
WechatMiniprogram.Page.Data<Record<string, any>> &
Record<string, any>;

89
weapp/src/components/vant-weapp/common/utils.js

@ -0,0 +1,89 @@
import { isDef, isNumber, isPlainObject, isPromise } from './validator';
import { canIUseGroupSetData, canIUseNextTick } from './version';
export function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
export function nextTick(cb) {
if (canIUseNextTick()) {
wx.nextTick(cb);
} else {
setTimeout(() => {
cb();
}, 1000 / 30);
}
}
let systemInfo;
export function getSystemInfoSync() {
if (systemInfo == null) {
systemInfo = wx.getSystemInfoSync();
}
return systemInfo;
}
export function addUnit(value) {
if (!isDef(value)) {
return undefined;
}
value = String(value);
return isNumber(value) ? `${value}px` : value;
}
export function requestAnimationFrame(cb) {
const systemInfo = getSystemInfoSync();
if (systemInfo.platform === 'devtools') {
return setTimeout(() => {
cb();
}, 1000 / 30);
}
return wx
.createSelectorQuery()
.selectViewport()
.boundingClientRect()
.exec(() => {
cb();
});
}
export function pickExclude(obj, keys) {
if (!isPlainObject(obj)) {
return {};
}
return Object.keys(obj).reduce((prev, key) => {
if (!keys.includes(key)) {
prev[key] = obj[key];
}
return prev;
}, {});
}
export function getRect(context, selector) {
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(context)
.select(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
});
}
export function getAllRect(context, selector) {
return new Promise((resolve) => {
wx.createSelectorQuery()
.in(context)
.selectAll(selector)
.boundingClientRect()
.exec((rect = []) => resolve(rect[0]));
});
}
export function groupSetData(context, cb) {
if (canIUseGroupSetData()) {
context.groupSetData(cb);
} else {
cb();
}
}
export function toPromise(promiseLike) {
if (isPromise(promiseLike)) {
return promiseLike;
}
return Promise.resolve(promiseLike);
}
export function getCurrentPage() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}

11
weapp/src/components/vant-weapp/common/validator.d.ts

@ -0,0 +1,11 @@
export declare function isFunction(val: unknown): val is Function;
export declare function isPlainObject(
val: unknown
): val is Record<string, unknown>;
export declare function isPromise<T = unknown>(val: unknown): val is Promise<T>;
export declare function isDef(value: unknown): boolean;
export declare function isObj(x: unknown): x is Record<string, unknown>;
export declare function isNumber(value: string): boolean;
export declare function isBoolean(value: unknown): value is boolean;
export declare function isImageUrl(url: string): boolean;
export declare function isVideoUrl(url: string): boolean;

30
weapp/src/components/vant-weapp/common/validator.js

@ -0,0 +1,30 @@
export function isFunction(val) {
return typeof val === 'function';
}
export function isPlainObject(val) {
return val !== null && typeof val === 'object' && !Array.isArray(val);
}
export function isPromise(val) {
return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch);
}
export function isDef(value) {
return value !== undefined && value !== null;
}
export function isObj(x) {
const type = typeof x;
return x !== null && (type === 'object' || type === 'function');
}
export function isNumber(value) {
return /^\d+(\.\d+)?$/.test(value);
}
export function isBoolean(value) {
return typeof value === 'boolean';
}
const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i;
const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i;
export function isImageUrl(url) {
return IMAGE_REGEXP.test(url);
}
export function isVideoUrl(url) {
return VIDEO_REGEXP.test(url);
}

6
weapp/src/components/vant-weapp/common/version.d.ts

@ -0,0 +1,6 @@
export declare function canIUseModel(): boolean;
export declare function canIUseFormFieldButton(): boolean;
export declare function canIUseAnimate(): boolean;
export declare function canIUseGroupSetData(): boolean;
export declare function canIUseNextTick(): boolean;
export declare function canIUseCanvas2d(): boolean;

45
weapp/src/components/vant-weapp/common/version.js

@ -0,0 +1,45 @@
import { getSystemInfoSync } from './utils';
function compareVersion(v1, v2) {
v1 = v1.split('.');
v2 = v2.split('.');
const len = Math.max(v1.length, v2.length);
while (v1.length < len) {
v1.push('0');
}
while (v2.length < len) {
v2.push('0');
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10);
const num2 = parseInt(v2[i], 10);
if (num1 > num2) {
return 1;
}
if (num1 < num2) {
return -1;
}
}
return 0;
}
function gte(version) {
const system = getSystemInfoSync();
return compareVersion(system.SDKVersion, version) >= 0;
}
export function canIUseModel() {
return gte('2.9.3');
}
export function canIUseFormFieldButton() {
return gte('2.10.3');
}
export function canIUseAnimate() {
return gte('2.9.0');
}
export function canIUseGroupSetData() {
return gte('2.4.0');
}
export function canIUseNextTick() {
return wx.canIUse('nextTick');
}
export function canIUseCanvas2d() {
return gte('2.9.0');
}

1
weapp/src/components/vant-weapp/divider/index.d.ts

@ -0,0 +1 @@
export {};

12
weapp/src/components/vant-weapp/divider/index.js

@ -0,0 +1,12 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
dashed: Boolean,
hairline: Boolean,
contentPosition: String,
fontSize: String,
borderColor: String,
textColor: String,
customStyle: String,
},
});

4
weapp/src/components/vant-weapp/divider/index.json

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save