Browse Source

initial commit

master
BJ-HPC3\13478 19 hours ago
commit
c7a55d14da
  1. 12
      .editorconfig
  2. 2
      .env.development
  3. 1
      .env.production
  4. 1
      .env.test
  5. 7
      .eslintrc
  6. 8
      .gitignore
  7. 78
      README.md
  8. 12
      babel.config.js
  9. 16
      config/dev.js
  10. 89
      config/index.js
  11. 37
      config/prod.js
  12. BIN
      docs/image-20250708103317051.png
  13. BIN
      docs/image-20250708103453330.png
  14. BIN
      docs/image-20250708104053513.png
  15. BIN
      docs/image-20250708104244826.png
  16. 93
      package.json
  17. 15
      project.config.json
  18. 56
      src/app.config.js
  19. 15
      src/app.js
  20. 3
      src/app.less
  21. 1
      src/assets/icons/ali.svg
  22. 1
      src/assets/icons/bank.svg
  23. BIN
      src/assets/icons/dataset-active.png
  24. BIN
      src/assets/icons/dataset.png
  25. BIN
      src/assets/icons/home-active.png
  26. BIN
      src/assets/icons/home.png
  27. 1
      src/assets/icons/kefu.svg
  28. BIN
      src/assets/icons/logo.png
  29. BIN
      src/assets/icons/mine-active.png
  30. BIN
      src/assets/icons/mine.png
  31. 1
      src/assets/icons/setting.svg
  32. 1
      src/assets/icons/wx.svg
  33. BIN
      src/assets/images/banner.png
  34. 71
      src/components/FormImage/index.jsx
  35. 15
      src/components/FormImage/index.module.less
  36. 7
      src/components/FormLabel/index.jsx
  37. 96
      src/hooks/useRequestList/index.ts
  38. 50
      src/hooks/useRequestSubmit/index.ts
  39. 17
      src/index.html
  40. 111
      src/pages/dataset/components/DataList/index.jsx
  41. 12
      src/pages/dataset/components/DataList/index.module.less
  42. 15
      src/pages/dataset/constants.js
  43. 4
      src/pages/dataset/index.config.js
  44. 25
      src/pages/dataset/index.jsx
  45. 16
      src/pages/dataset/index.module.less
  46. 42
      src/pages/feeconfirm/components/Alipay/index.jsx
  47. 3
      src/pages/feeconfirm/components/Alipay/index.module.less
  48. 41
      src/pages/feeconfirm/components/BankPay/index.jsx
  49. 2
      src/pages/feeconfirm/components/BankPay/index.module.less
  50. 179
      src/pages/feeconfirm/components/FormBar/index.jsx
  51. 71
      src/pages/feeconfirm/components/FormBar/index.module.less
  52. 42
      src/pages/feeconfirm/components/Wxpay/index.jsx
  53. 2
      src/pages/feeconfirm/components/Wxpay/index.module.less
  54. 4
      src/pages/feeconfirm/index.config.js
  55. 25
      src/pages/feeconfirm/index.jsx
  56. 10
      src/pages/feeconfirm/index.module.less
  57. 4
      src/pages/feedback/index.config.js
  58. 45
      src/pages/feedback/index.jsx
  59. 28
      src/pages/feedback/index.module.less
  60. 93
      src/pages/forget/components/FormBar/index.jsx
  61. 46
      src/pages/forget/components/FormBar/index.module.less
  62. 33
      src/pages/forget/components/HeaderBar/index.jsx
  63. 42
      src/pages/forget/components/HeaderBar/index.module.less
  64. 4
      src/pages/forget/index.config.js
  65. 34
      src/pages/forget/index.jsx
  66. 51
      src/pages/forget/index.module.less
  67. 40
      src/pages/funds/components/Balance/Alipay/index.jsx
  68. 3
      src/pages/funds/components/Balance/Alipay/index.module.less
  69. 38
      src/pages/funds/components/Balance/BankPay/index.jsx
  70. 2
      src/pages/funds/components/Balance/BankPay/index.module.less
  71. 39
      src/pages/funds/components/Balance/Wxpay/index.jsx
  72. 2
      src/pages/funds/components/Balance/Wxpay/index.module.less
  73. 123
      src/pages/funds/components/Balance/index.jsx
  74. 98
      src/pages/funds/components/Balance/index.module.less
  75. 38
      src/pages/funds/components/DataList/index.jsx
  76. 44
      src/pages/funds/components/DataList/index.module.less
  77. 4
      src/pages/funds/index.config.js
  78. 77
      src/pages/funds/index.jsx
  79. 11
      src/pages/funds/index.module.less
  80. 29
      src/pages/index/components/Banner/index.jsx
  81. 5
      src/pages/index/components/Banner/index.module.less
  82. 33
      src/pages/index/components/Header/index.jsx
  83. 20
      src/pages/index/components/Header/index.module.less
  84. 53
      src/pages/index/components/MyShop/index.jsx
  85. 70
      src/pages/index/components/MyShop/index.module.less
  86. 30
      src/pages/index/components/TodoList/index.jsx
  87. 30
      src/pages/index/components/TodoList/index.module.less
  88. 30
      src/pages/index/components/Toolbar/index.jsx
  89. 29
      src/pages/index/components/Toolbar/index.module.less
  90. 4
      src/pages/index/index.config.js
  91. 58
      src/pages/index/index.jsx
  92. 7
      src/pages/index/index.module.less
  93. 88
      src/pages/invite/components/FormBar/index.jsx
  94. 80
      src/pages/invite/components/FormBar/index.module.less
  95. 4
      src/pages/invite/index.config.js
  96. 31
      src/pages/invite/index.jsx
  97. 9
      src/pages/invite/index.module.less
  98. 41
      src/pages/login/components/FormBar/index.jsx
  99. 38
      src/pages/login/components/FormBar/index.module.less
  100. 34
      src/pages/login/components/HeaderBar/index.jsx

12
.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

2
.env.development

@ -0,0 +1,2 @@
# 配置文档参考 https://taro-docs.jd.com/docs/next/env-mode-config
# TARO_APP_ID="开发环境下的小程序 AppID"

1
.env.production

@ -0,0 +1 @@
# TARO_APP_ID="生产环境下的小程序 AppID"

1
.env.test

@ -0,0 +1 @@
# TARO_APP_ID="测试环境下的小程序 AppID"

7
.eslintrc

@ -0,0 +1,7 @@
{
"extends": ["taro/react"],
"rules": {
"react/jsx-uses-react": "off",
"react/react-in-jsx-scope": "off"
}
}

8
.gitignore

@ -0,0 +1,8 @@
dist/
deploy_versions/
.temp/
.rn_temp/
node_modules/
.DS_Store
.swc
*.local

78
README.md

@ -0,0 +1,78 @@
# jf_202506
#### 介绍
202506小程序交付
#### 软件架构
taro react
### 依赖工具
+ **开发框架**:[tarojs@4.1.2](https://docs.taro.zone/docs/)
+ **基础架构**:[react@18.0](https://reactjs.org/)
+ **ui框架**:[antd-mobile@5.39](https://mobile.ant.design/zh)
### 项目启动
1. node > ver.18
2. 安装yarn@1.22.19,执行`yarn install`
3. 执行`npm run dev:h5`,本地启动
4. 执行`npm run build:h5`,打包编译
### 项目部署
1. 本地构建
```bash
// 1. git 操作拉取项目,此处省略...
// 2. 进入到项目根目录
yarn install
// 3. 编译构建
npm run build:h5
```
2. 登录宝塔平台
3. 网站/HTML项目 下 添加HTML项目
![image-20250708103317051](.\docs\image-20250708103317051.png)
4. 修改nginx配置文件
![image-20250708103453330](.\docs\image-20250708103453330.png)
```nginx
location ^~/api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection '';
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400s;
send_timeout 86400s;
client_max_body_size 50m;
# 这里改成 [对应的域名 + /api]
proxy_pass https://he.lehuonianhua.com/api;
}
```
5. 上传生产包
![image-20250708104053513](.\docs\image-20250708104053513.png)
6. 重启nginx
![image-20250708104244826](.\docs\image-20250708104244826.png)
## 讨论
联系人:jinech 13478707150@163.com

12
babel.config.js

@ -0,0 +1,12 @@
// babel-preset-taro 更多选项和默认值:
// https://docs.taro.zone/docs/next/babel-config
module.exports = {
presets: [
['taro', {
framework: 'react',
ts: false,
compiler: 'vite',
useBuiltIns: process.env.TARO_ENV === 'h5' ? 'usage' : false
}]
]
}

16
config/dev.js

@ -0,0 +1,16 @@
export default {
mini: {},
h5: {
devServer: {
proxy: {
'/api/Open': {
target: 'https://he.lehuonianhua.com',
changeOrigin: true,
},
}
}
}
}

89
config/index.js

@ -0,0 +1,89 @@
import { defineConfig } from '@tarojs/cli'
import devConfig from './dev'
import prodConfig from './prod'
// https://taro-docs.jd.com/docs/next/config#defineconfig-辅助函数
export default defineConfig(async (merge, { command, mode }) => {
const baseConfig = {
projectName: 'jf_20250608',
date: '2025-6-8',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
375: 2,
828: 1.81 / 2
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: [],
defineConstants: {
},
copy: {
patterns: [
],
options: {
}
},
framework: 'react',
compiler: 'vite',
mini: {
postcss: {
pxtransform: {
enable: true,
config: {
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
},
},
h5: {
publicPath: '/',
staticDirectory: 'static',
miniCssExtractPluginOption: {
ignoreOrder: true,
filename: 'css/[name].[hash].css',
chunkFilename: 'css/[name].[chunkhash].css'
},
postcss: {
autoprefixer: {
enable: true,
config: {}
},
cssModules: {
enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
},
rn: {
appName: 'taroDemo',
postcss: {
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
}
}
}
}
process.env.BROWSERSLIST_ENV = process.env.NODE_ENV
if (process.env.NODE_ENV === 'development') {
// 本地开发构建配置(不混淆压缩)
return merge({}, baseConfig, devConfig)
}
// 生产构建配置(默认开启压缩混淆等)
return merge({}, baseConfig, prodConfig)
})

37
config/prod.js

@ -0,0 +1,37 @@
export default {
mini: {},
h5: {
// publicPath: '/ryc/',
// staticDirectory: './ryc/static'
// 确保产物为 es5
// legacy: true,
/**
* WebpackChain 插件配置
* @docs https://github.com/neutrinojs/webpack-chain
*/
// webpackChain (chain) {
// /**
// * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。
// * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer
// */
// chain.plugin('analyzer')
// .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
// /**
// * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。
// * @docs https://github.com/chrisvfritz/prerender-spa-plugin
// */
// const path = require('path')
// const Prerender = require('prerender-spa-plugin')
// const staticDir = path.join(__dirname, '..', 'dist')
// chain
// .plugin('prerender')
// .use(new Prerender({
// staticDir,
// routes: [ '/pages/index/index' ],
// postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') })
// }))
// }
}
}

BIN
docs/image-20250708103317051.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
docs/image-20250708103453330.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
docs/image-20250708104053513.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
docs/image-20250708104244826.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

93
package.json

@ -0,0 +1,93 @@
{
"name": "jf_20250608",
"version": "1.0.0",
"private": true,
"description": "",
"templateInfo": {
"name": "default",
"typescript": false,
"css": "Less",
"framework": "React"
},
"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:harmony-hybrid": "taro build --type harmony-hybrid",
"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:harmony-hybrid": "npm run build:harmony-hybrid -- --watch"
},
"browserslist": {
"development": [
"defaults and fully supports es6-module",
"maintained node versions"
],
"production": [
"last 3 versions",
"Android >= 4.1",
"ios >= 8"
]
},
"author": "",
"dependencies": {
"@babel/runtime": "^7.24.4",
"@tarojs/components": "4.1.2",
"@tarojs/helper": "4.1.2",
"@tarojs/plugin-framework-react": "4.1.2",
"@tarojs/plugin-platform-alipay": "4.1.2",
"@tarojs/plugin-platform-h5": "4.1.2",
"@tarojs/plugin-platform-harmony-hybrid": "4.1.2",
"@tarojs/plugin-platform-jd": "4.1.2",
"@tarojs/plugin-platform-qq": "4.1.2",
"@tarojs/plugin-platform-swan": "4.1.2",
"@tarojs/plugin-platform-tt": "4.1.2",
"@tarojs/plugin-platform-weapp": "4.1.2",
"@tarojs/react": "4.1.2",
"@tarojs/runtime": "4.1.2",
"@tarojs/shared": "4.1.2",
"@tarojs/taro": "4.1.2",
"ahooks": "^3.8.5",
"antd-mobile": "^5.39.0",
"axios": "^1.10.0",
"classnames": "^2.5.1",
"lodash": "^4.17.21",
"md5": "^2.3.0",
"qrcode.react": "^4.2.0",
"react": "^18.0.0",
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@babel/core": "^7.24.4",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/plugin-transform-class-properties": "7.25.9",
"@babel/preset-react": "^7.24.1",
"@tarojs/cli": "4.1.2",
"@tarojs/vite-runner": "4.1.2",
"@types/react": "^18.0.0",
"@vitejs/plugin-react": "^4.3.0",
"babel-preset-taro": "4.1.2",
"eslint": "^8.57.0",
"eslint-config-taro": "4.1.2",
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.4.0",
"less": "^4.2.0",
"postcss": "^8.4.38",
"react-refresh": "^0.14.0",
"stylelint": "^16.4.0",
"terser": "^5.30.4",
"vite": "^4.2.0"
}
}

15
project.config.json

@ -0,0 +1,15 @@
{
"miniprogramRoot": "./dist",
"projectname": "jf_20250608",
"description": "",
"appid": "touristappid",
"setting": {
"urlCheck": true,
"es6": false,
"enhance": false,
"compileHotReLoad": false,
"postcss": false,
"minified": false
},
"compileType": "miniprogram"
}

56
src/app.config.js

@ -0,0 +1,56 @@
export default defineAppConfig({
pages: [
'pages/index/index',
'pages/dataset/index',
'pages/mine/index',
'pages/login/index',
'pages/forget/index',
'pages/payforget/index',
'pages/register/index',
'pages/shopinfo/index',
'pages/team/index',
'pages/invite/index',
'pages/paymentmethod/index',
'pages/funds/index',
'pages/safe/index',
'pages/feedback/index',
'pages/myfeedback/index',
'pages/notice/index',
'pages/notice-detail/index',
'pages/viplevelup/index',
'pages/sitemessage/index',
'pages/payconfirm/index',
'pages/feeconfirm/index',
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
},
tabBar: {
color: '#7A7E83',
selectedColor: '#007AFF',
backgroundColor: '#FAFAFA',
list: [
{
pagePath: 'pages/index/index',
text: '首页',
iconPath: 'assets/icons/home.png',
selectedIconPath: 'assets/icons/home-active.png'
},
{
pagePath: 'pages/dataset/index',
text: '数据优化',
iconPath: 'assets/icons/dataset.png',
selectedIconPath: 'assets/icons/dataset-active.png'
},
{
pagePath: 'pages/mine/index',
text: '我的',
iconPath: 'assets/icons/mine.png',
selectedIconPath: 'assets/icons/mine-active.png'
}
]
}
})

15
src/app.js

@ -0,0 +1,15 @@
import { useLaunch } from '@tarojs/taro';
import './app.less';
function App({ children }) {
useLaunch(() => {
console.log('App launched.')
});
// children 是将要会渲染的页面
return children;
}
export default App;

3
src/app.less

@ -0,0 +1,3 @@
:root {
--color-primary: #007AFF;
}

1
src/assets/icons/ali.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749868910629" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5348" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M230.771014 576.556522c-12.614493 9.646377-25.228986 23.744928-28.93913 42.295652-5.194203 24.486957-0.742029 55.652174 22.26087 80.13913 28.93913 28.93913 72.718841 37.101449 92.011594 38.585508 51.2 3.710145 106.110145-22.26087 147.663768-50.457971 16.324638-11.130435 43.77971-34.133333 70.492754-69.750725-59.362319-30.423188-133.565217-64.556522-212.22029-61.588406-41.553623 1.484058-70.492754 9.646377-91.269566 20.776812zM983.188406 712.347826c25.971014-61.588406 40.811594-129.113043 40.811594-200.347826 0-281.971014-230.028986-512-512-512S0 230.028986 0 512s230.028986 512 512 512c170.666667 0 321.298551-83.849275 414.794203-212.22029C838.492754 768.742029 693.797101 696.023188 604.011594 652.985507c-42.295652 48.973913-105.368116 97.205797-176.602898 117.982609-44.521739 13.356522-85.333333 18.550725-126.886957 9.646377-42.295652-8.904348-72.718841-28.197101-90.527536-47.489855-8.904348-10.388406-19.292754-22.26087-27.455073-37.843479 0.742029 0.742029 0.742029 2.226087 0.742029 2.968116 0 0-4.452174-7.42029-7.420289-19.292753-1.484058-5.936232-2.968116-11.872464-3.710145-17.808696-0.742029-4.452174-0.742029-8.904348 0-12.614493-0.742029-7.42029 0-15.582609 1.484058-23.744927 4.452174-20.776812 12.614493-43.77971 35.617391-65.298551 48.973913-48.231884 115.014493-50.457971 149.147826-50.457971 50.457971 0.742029 138.017391 22.26087 212.22029 48.973913 20.776812-43.77971 34.133333-89.785507 42.295652-121.692754H304.973913v-33.391304h158.052174v-66.782609H272.324638v-34.133333h190.701449v-66.782609c0-8.904348 2.226087-16.324638 16.324638-16.324637h74.944927v83.107246h207.026087v33.391304H554.295652v66.782609H719.768116S702.701449 494.933333 651.501449 586.202899c115.014493 40.811594 277.518841 104.626087 331.686957 126.144927z m0 0" fill="#06B4FD" p-id="5349"></path></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

1
src/assets/icons/bank.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749869158287" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9284" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M512 512m-430.08 0a430.08 430.08 0 1 0 860.16 0 430.08 430.08 0 1 0-860.16 0Z" fill="#257AE7" p-id="9285"></path><path d="M682.67008 726.82496h-333.4144A62.54592 62.54592 0 0 1 286.72 664.28928V451.96288a62.54592 62.54592 0 0 1 62.53568-62.54592h333.4144a62.54592 62.54592 0 0 1 62.54592 62.54592v212.3264a62.54592 62.54592 0 0 1-62.54592 62.53568z" fill="#FFFFFF" p-id="9286"></path><path d="M606.1568 644.29056l-248.58624-77.9264a62.53568 62.53568 0 0 1-40.98048-78.3872l42.97728-136.91904a62.53568 62.53568 0 0 1 78.37696-40.98048l248.56576 77.95712a62.53568 62.53568 0 0 1 40.97024 78.37696l-42.91584 136.9088a62.57664 62.57664 0 0 1-78.40768 40.97024z" fill="#FFFFFF" p-id="9287"></path><path d="M692.57216 390.51264a63.72352 63.72352 0 0 0-11.78624-1.09568H351.09888c-1.2288 0-2.42688 0.0512-3.62496 0.1024l-30.30016 96.65536a64.4096 64.4096 0 0 0 42.17856 80.72192l245.02272 76.83072a64.4096 64.4096 0 0 0 80.72192-42.16832l41.82016-133.38624a64.4096 64.4096 0 0 0-34.34496-77.66016z" fill="#E2EEF9" p-id="9288"></path><path d="M618.50624 635.82208a30.80192 30.80192 0 1 0 61.61408 0 30.80192 30.80192 0 0 0-61.61408 0z" fill="#328DEC" p-id="9289"></path><path d="M286.72 466.1248h458.496v42.5984H286.72z" fill="#3895EE" p-id="9290"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/assets/icons/dataset-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/assets/icons/dataset.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/assets/icons/home-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/assets/icons/home.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

1
src/assets/icons/kefu.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749559662762" class="icon" viewBox="0 0 1051 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8838" xmlns:xlink="http://www.w3.org/1999/xlink" width="131.375" height="128"><path d="M55.351351 553.402811v110.924108a83.027027 83.027027 0 0 0 166.054054 0v-110.924108a83.027027 83.027027 0 0 0-166.054054 0z m763.101406 211.552865A137.852541 137.852541 0 0 1 774.918919 664.326919v-110.924108A138.378378 138.378378 0 0 1 912.328649 415.135135C898.131027 214.071351 730.499459 55.351351 525.837838 55.351351 321.148541 55.351351 153.544649 214.071351 139.347027 415.135135A138.461405 138.461405 0 0 1 276.756757 553.402811v110.924108a138.378378 138.378378 0 0 1-276.756757 0v-110.924108a138.378378 138.378378 0 0 1 83.303784-126.865297C91.883243 189.523027 286.72 0 525.837838 0s433.954595 189.523027 442.534054 426.537514A138.461405 138.461405 0 0 1 1051.675676 553.402811v110.924108a138.378378 138.378378 0 0 1-184.790487 130.269405 470.763243 470.763243 0 0 1-188.858811 121.21946A96.809514 96.809514 0 0 1 580.912432 1010.162162h-82.528864c-53.690811 0-97.113946-43.174054-97.113946-96.864865 0-53.607784 43.284757-96.864865 97.141621-96.864865h82.473514c34.954378 0 65.536 18.265946 82.639567 45.803244a415.273514 415.273514 0 0 0 154.900757-97.28zM830.27027 553.402811v110.924108a83.027027 83.027027 0 0 0 166.054054 0v-110.924108a83.027027 83.027027 0 0 0-166.054054 0zM498.438919 954.810811h82.473513c23.302919 0 41.79027-18.487351 41.790271-41.513514 0-23.053838-18.570378-41.513514-41.790271-41.513513h-82.473513c-23.302919 0-41.79027 18.487351-41.79027 41.513513 0 23.053838 18.570378 41.513514 41.79027 41.513514z" fill="#515151" p-id="8839"></path></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
src/assets/icons/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
src/assets/icons/mine-active.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
src/assets/icons/mine.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

1
src/assets/icons/setting.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749559586556" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7488" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M924.8 625.7l-65.5-56c3.1-19 4.7-38.4 4.7-57.8s-1.6-38.8-4.7-57.8l65.5-56c10.1-8.6 13.8-22.6 9.3-35.2l-0.9-2.6c-18.1-50.5-44.9-96.9-79.7-137.9l-1.8-2.1c-8.6-10.1-22.5-13.9-35.1-9.5l-81.3 28.9c-30-24.6-63.5-44-99.7-57.6l-15.7-85c-2.4-13.1-12.7-23.3-25.8-25.7l-2.7-0.5c-52.1-9.4-106.9-9.4-159 0l-2.7 0.5c-13.1 2.4-23.4 12.6-25.8 25.7l-15.8 85.4c-35.9 13.6-69.2 32.9-99 57.4l-81.9-29.1c-12.5-4.4-26.5-0.7-35.1 9.5l-1.8 2.1c-34.8 41.1-61.6 87.5-79.7 137.9l-0.9 2.6c-4.5 12.5-0.8 26.5 9.3 35.2l66.3 56.6c-3.1 18.8-4.6 38-4.6 57.1 0 19.2 1.5 38.4 4.6 57.1L99 625.5c-10.1 8.6-13.8 22.6-9.3 35.2l0.9 2.6c18.1 50.4 44.9 96.9 79.7 137.9l1.8 2.1c8.6 10.1 22.5 13.9 35.1 9.5l81.9-29.1c29.8 24.5 63.1 43.9 99 57.4l15.8 85.4c2.4 13.1 12.7 23.3 25.8 25.7l2.7 0.5c26.1 4.7 52.8 7.1 79.5 7.1 26.7 0 53.5-2.4 79.5-7.1l2.7-0.5c13.1-2.4 23.4-12.6 25.8-25.7l15.7-85c36.2-13.6 69.7-32.9 99.7-57.6l81.3 28.9c12.5 4.4 26.5 0.7 35.1-9.5l1.8-2.1c34.8-41.1 61.6-87.5 79.7-137.9l0.9-2.6c4.5-12.3 0.8-26.3-9.3-35zM788.3 465.9c2.5 15.1 3.8 30.6 3.8 46.1s-1.3 31-3.8 46.1l-6.6 40.1 74.7 63.9c-11.3 26.1-25.6 50.7-42.6 73.6L721 702.8l-31.4 25.8c-23.9 19.6-50.5 35-79.3 45.8l-38.1 14.3-17.9 97c-28.1 3.2-56.8 3.2-85 0l-17.9-97.2-37.8-14.5c-28.5-10.8-55-26.2-78.7-45.7l-31.4-25.9-93.4 33.2c-17-22.9-31.2-47.6-42.6-73.6l75.5-64.5-6.5-40c-2.4-14.9-3.7-30.3-3.7-45.5 0-15.3 1.2-30.6 3.7-45.5l6.5-40-75.5-64.5c11.3-26.1 25.6-50.7 42.6-73.6l93.4 33.2 31.4-25.9c23.7-19.5 50.2-34.9 78.7-45.7l37.9-14.3 17.9-97.2c28.1-3.2 56.8-3.2 85 0l17.9 97 38.1 14.3c28.7 10.8 55.4 26.2 79.3 45.8l31.4 25.8 92.8-32.9c17 22.9 31.2 47.6 42.6 73.6L781.8 426l6.5 39.9z" p-id="7489" fill="#515151"></path><path d="M512 326c-97.2 0-176 78.8-176 176s78.8 176 176 176 176-78.8 176-176-78.8-176-176-176z m79.2 255.2C570 602.3 541.9 614 512 614c-29.9 0-58-11.7-79.2-32.8C411.7 560 400 531.9 400 502c0-29.9 11.7-58 32.8-79.2C454 401.6 482.1 390 512 390c29.9 0 58 11.6 79.2 32.8C612.3 444 624 472.1 624 502c0 29.9-11.7 58-32.8 79.2z" p-id="7490" fill="#515151"></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

1
src/assets/icons/wx.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749868898823" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4353" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><path d="M337.387283 341.82659c-17.757225 0-35.514451 11.83815-35.514451 29.595375s17.757225 29.595376 35.514451 29.595376 29.595376-11.83815 29.595376-29.595376c0-18.49711-11.83815-29.595376-29.595376-29.595375zM577.849711 513.479769c-11.83815 0-22.936416 12.578035-22.936416 23.6763 0 12.578035 11.83815 23.676301 22.936416 23.676301 17.757225 0 29.595376-11.83815 29.595376-23.676301s-11.83815-23.676301-29.595376-23.6763zM501.641618 401.017341c17.757225 0 29.595376-12.578035 29.595376-29.595376 0-17.757225-11.83815-29.595376-29.595376-29.595375s-35.514451 11.83815-35.51445 29.595375 17.757225 29.595376 35.51445 29.595376zM706.589595 513.479769c-11.83815 0-22.936416 12.578035-22.936416 23.6763 0 12.578035 11.83815 23.676301 22.936416 23.676301 17.757225 0 29.595376-11.83815 29.595376-23.676301s-11.83815-23.676301-29.595376-23.6763z" fill="#28C445" p-id="4354"></path><path d="M510.520231 2.959538C228.624277 2.959538 0 231.583815 0 513.479769s228.624277 510.520231 510.520231 510.520231 510.520231-228.624277 510.520231-510.520231-228.624277-510.520231-510.520231-510.520231zM413.595376 644.439306c-29.595376 0-53.271676-5.919075-81.387284-12.578034l-81.387283 41.433526 22.936416-71.768786c-58.450867-41.433526-93.965318-95.445087-93.965317-159.815029 0-113.202312 105.803468-201.988439 233.803468-201.98844 114.682081 0 216.046243 71.028902 236.023121 166.473989-7.398844-0.739884-14.797688-1.479769-22.196532-1.479769-110.982659 1.479769-198.289017 85.086705-198.289017 188.67052 0 17.017341 2.959538 33.294798 7.398844 49.572255-7.398844 0.739884-15.537572 1.479769-22.936416 1.479768z m346.265896 82.867052l17.757225 59.190752-63.630058-35.514451c-22.936416 5.919075-46.612717 11.83815-70.289017 11.83815-111.722543 0-199.768786-76.947977-199.768786-172.393063-0.739884-94.705202 87.306358-171.653179 198.289017-171.65318 105.803468 0 199.028902 77.687861 199.028902 172.393064 0 53.271676-34.774566 100.624277-81.387283 136.138728z" fill="#28C445" p-id="4355"></path></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
src/assets/images/banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

71
src/components/FormImage/index.jsx

@ -0,0 +1,71 @@
import cls from 'classnames';
import styles from './index.module.less';
import { Image, ImageViewer } from 'antd-mobile';
import { CameraOutline } from 'antd-mobile-icons';
import { View } from '@tarojs/components';
import { uploadImage64Action } from '../../request/actions';
import Taro from '@tarojs/taro';
import React, { useState } from 'react';
const FormImage = ({ value, className, onChange, readonly, ...props }) => {
const prefix = cls(styles.img, className);
const [visible, updateVisible] = useState(false);
const handleClick = () => {
// TODO
if (readonly || value) {
updateVisible(true);
return;
}
const input = document.createElement('input');
input.type = 'file';
input.accept = 'image/*';
input.onchange = (event) => {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = async () => {
const imageBase64 = reader.result;
const res = await uploadImage64Action({ imageBase64 });
onChange(res?.logo);
};
reader.readAsDataURL(file); // Base64
}
};
input.click();
};
if (!value) {
if (readonly) {
return (
<Image src={value} className={prefix} fit='fill' {...props} />
);
}
return (
<View className={styles.empty} onClick={handleClick} {...props}>
<CameraOutline />
</View>
);
}
return (
<React.Fragment>
<Image src={value} className={prefix} fit='fill' onClick={handleClick} {...props} />
<ImageViewer
classNames={{
mask: 'customize-mask',
body: 'customize-body',
}}
image={value}
visible={visible}
onClose={() => {
updateVisible(false)
}}
/>
</React.Fragment>
);
};
export default FormImage;

15
src/components/FormImage/index.module.less

@ -0,0 +1,15 @@
.img {
width: 72px;
height: 72px;
}
.empty {
width: 72px;
height: 72px;
border-radius: 6px;
background-color: #f4f5f7;
display: flex;
justify-content: center;
align-items: center;
}

7
src/components/FormLabel/index.jsx

@ -0,0 +1,7 @@
const FormLabel = ({ value, render, ...props }) => {
return <span {...props} >{render ? render(value) : value}</span>;
};
export default FormLabel;

96
src/hooks/useRequestList/index.ts

@ -0,0 +1,96 @@
import { useEffect, useRef, useState } from 'react';
import { AxiosRequestConfig } from 'axios';
import { Toast } from 'antd-mobile';
type Request<T, U> = (params: T, options?: any) => Promise<U>;
interface UseRequestListProps<P, R> {
action: Request<P, R>;
immediate?: boolean;
onOk?: () => void | boolean;
initFilterParams?: Partial<P>;
showMsg?: boolean;
options?: AxiosRequestConfig;
loop?: boolean;
interval?: number;
onLoop?: (data: any) => boolean;
};
function useRequestList<P, R>({
action,
immediate = true,
onOk,
initFilterParams,
showMsg = false,
options = {},
loop = false,
interval = 2000,
onLoop
}: UseRequestListProps<P, R>) {
const [loading, updateLoading] = useState(false);
const filterParamsRef = useRef(initFilterParams);
const [data, updateData] = useState<R>();
const timer = useRef<any>(null);
const abortLoop = () => {
if (timer.current) {
clearInterval(timer.current);
timer.current = null;
}
};
const getDataTask = async (params: P, loading = true) => {
try {
loading && updateLoading(true);
const filterParams = filterParamsRef.current;
const queryParams = { ...filterParams, ...params };
const res = await action(queryParams, options);
filterParamsRef.current = queryParams;
updateData(res);
if (loop && onLoop?.(res)) {
timer.current = setTimeout(() => {
getDataTask(queryParams, loading);
}, interval);
}
else {
loading && updateLoading(false);
onOk?.();
return res;
}
}
catch (err) {
abortLoop();
showMsg && Toast.show({
icon: 'error',
content: `${err}`
});
}
finally {
loading && !loop && updateLoading(false);
}
};
useEffect(() => {
return abortLoop;
}, []);
useEffect(() => {
if (!immediate) {
return;
}
getDataTask({} as P);
}, []);
return {
getDataTask,
loading,
data,
filterParams: filterParamsRef.current,
abortLoop
};
}
export default useRequestList;

50
src/hooks/useRequestSubmit/index.ts

@ -0,0 +1,50 @@
/*
* @Author: WIN-J7OL7MK489U\EDY 13478707150@163.com
* @Date: 2023-06-28 16:45:43
* @LastEditors: BJ-HPC3\13478 13478707150@163.com
* @LastEditTime: 2025-02-21 17:15:40
* @FilePath: \jsure_zdbg_web_react\src\hooks\useRequest\index.ts
* @Description:
*/
import { useState } from 'react';
import type { Request } from '@/request/utils';
interface UseRequestListProps<P, R> {
action?: Request<P, R>;
onOk?: () => void;
};
function useRequestSubmit<P, R>({
action,
onOk,
}: UseRequestListProps<P, R>) {
const [loading, updateLoading] = useState(false);
const [data, updateData] = useState<R>(null);
const actionTask = async (params: P, loading = true) => {
try {
loading && updateLoading(true);
const res = await action(params);
updateData(res);
onOk?.();
return res;
}
catch (err) {
console.log('[request submit err]: ', err);
return Promise.reject(err);
}
finally {
loading && updateLoading(false);
}
};
return {
actionTask,
loading,
data
};
}
export default useRequestSubmit;

17
src/index.html

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<meta name="format-detection" content="telephone=no,address=no">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
<title>jf_20250608</title>
<script><%= htmlWebpackPlugin.options.script %></script>
</head>
<body>
<div id="app"></div>
</body>
</html>

111
src/pages/dataset/components/DataList/index.jsx

@ -0,0 +1,111 @@
import React, { useEffect, useState } from 'react';
import { PullToRefresh, List, Empty, Button, Modal, Toast } from 'antd-mobile';
import { View, Text, ScrollView } from '@tarojs/components';
import { getOrderListLoopAction, orderConfirmAction } from '../../../../request/actions';
import { OrderStatusEnum } from '../../constants';
import Taro, { useDidShow } from '@tarojs/taro';
import styles from './index.module.less';
const fetchDataRecursively = async (times, params, datasource) => {
if (times <= 0 || (datasource && datasource?.length < 10)) {
return [];
}
const lastOrderId = datasource?.[datasource?.length - 1]?.orderId;
const result = await getOrderListLoopAction({ ...params, lastOrderId });
const nextResults = await fetchDataRecursively(times - 1, params, result?.dataList);
return [...result?.dataList, ...nextResults];
};
const DataList = ({ orderStatus }) => {
const [data, setData] = useState([]);
const initData = async () => {
const dataSource = await fetchDataRecursively(1, { orderStatus });
setData(dataSource);
};
const handleScrollToLower = async () => {
const lastLogId = data?.[data?.length - 1]?.orderId;
const result = await getOrderListLoopAction({ lastLogId });
const newDataSource = result?.dataList;
setData([...data, ...newDataSource]);
};
const handleJump = item => {
//
if (orderStatus === OrderStatusEnum.waittingForPay.value) {
Taro.navigateTo({
url: `/pages/payconfirm/index?orderId=${item.orderId}`
});
}
//
if (orderStatus === OrderStatusEnum.waittingForConfirm.value) {
// Modal.confirm({
// title: '?',
// onConfirm: async () => {
// try {
// const orderId = item.orderId;
// await orderConfirmAction({ orderId });
// initData();
// Toast.show({
// icon: 'success',
// content: ''
// });
// }
// catch (err) {
// console.log('err: ', err);
// }
// }
// })
Taro.navigateTo({
url: `/pages/feeconfirm/index?orderId=${item.orderId}`
});
}
};
useDidShow(initData);
useEffect(() => {
initData();
}, [orderStatus]);
return (
<PullToRefresh
onRefresh={initData}
>
{data.length > 0 ? (
<ScrollView
scrollY
onScrollToLower={handleScrollToLower}
lowerThreshold={50}
>
<List className={styles.list}>
{data.map((item, index) => (
<List.Item key={index} onClick={() => handleJump(item)} arrowIcon={false}>
<View className={styles.row}>
<Text>订单编号: {item.orderId}</Text>
<Text>订单日期: {item.orderDate || '-'}</Text>
</View>
<View className={styles.row}>
<Text>订单金额: {item.orderPrice}</Text>
</View>
{orderStatus !== OrderStatusEnum.done.value && (
<Button className={styles.btn}>{item.buttonText}</Button>
)}
</List.Item>
))}
</List>
</ScrollView>
) : (
<Empty
style={{ padding: '64px 0' }}
description='暂无数据'
/>
)}
</PullToRefresh >
)
};
export default DataList;

12
src/pages/dataset/components/DataList/index.module.less

@ -0,0 +1,12 @@
.row {
display: flex;
justify-content: space-between;
font-size: 28px;
line-height: 2;
}
.btn {
width: 100%;
}
.list {
height: calc(100vh - 92px - 120px);
}

15
src/pages/dataset/constants.js

@ -0,0 +1,15 @@
export const OrderStatusEnum = {
waittingForPay: {
label: '待付款',
value: '0'
},
waittingForConfirm: {
label: '待确认',
value: '1'
},
done: {
label: '已完成',
value: '9'
}
};

4
src/pages/dataset/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '数据优化',
usingComponents: {},
})

25
src/pages/dataset/index.jsx

@ -0,0 +1,25 @@
import { View } from '@tarojs/components';
import { Tabs } from 'antd-mobile';
import DataList from './components/DataList';
import { OrderStatusEnum } from './constants';
import styles from './index.module.less';
export default function Dataset() {
return (
<View className={styles.container}>
<Tabs className={styles.tabs} defaultActiveKey={OrderStatusEnum.waittingForPay.value}>
<Tabs.Tab title='待支付' key={OrderStatusEnum.waittingForPay.value}>
<DataList orderStatus={OrderStatusEnum.waittingForPay.value} />
</Tabs.Tab>
<Tabs.Tab title='待确认' key={OrderStatusEnum.waittingForConfirm.value}>
<DataList orderStatus={OrderStatusEnum.waittingForConfirm.value} />
</Tabs.Tab>
<Tabs.Tab title='已完成' key={OrderStatusEnum.done.value}>
<DataList orderStatus={OrderStatusEnum.done.value} />
</Tabs.Tab>
</Tabs>
</View>
)
}

16
src/pages/dataset/index.module.less

@ -0,0 +1,16 @@
.container {
position: relative;
.tabs {
height: 82px;
position: sticky;
top: 0;
z-index: 9;
background-color: #fff;
}
:global {
.adm-list-body {
border-top: unset;
}
}
}

42
src/pages/feeconfirm/components/Alipay/index.jsx

@ -0,0 +1,42 @@
import { View } from '@tarojs/components';
import { Form } from 'antd-mobile';
import FormLabel from '/components/FormLabel';
import FormImage from '/components/FormImage';
import styles from './index.module.less';
export default function Alipay({ namePrefix }) {
return (
<View className={styles.container}>
<Form.Item
name={`${namePrefix}-alipay`}
label='支付宝账号'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
<Form.Item
name={`${namePrefix}-alipayName`}
label='支付宝姓名'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
{/* <Form.Item
name={`${namePrefix}-alipayImage`}
label='收款码'
childElementPosition='right'
>
<FormImage readonly width={72} height={72} />
</Form.Item> */}
{/* <Form.Item
name='password'
label='支付密码'
rules={[{ required: true, message: '请输入支付密码' }]}
>
<Input type='password' placeholder='请输入支付密码' />
</Form.Item> */}
</View >
)
}

3
src/pages/feeconfirm/components/Alipay/index.module.less

@ -0,0 +1,3 @@
.container {
}

41
src/pages/feeconfirm/components/BankPay/index.jsx

@ -0,0 +1,41 @@
import { View } from '@tarojs/components';
import { Form } from 'antd-mobile';
import FormLabel from '/components/FormLabel';
import styles from './index.module.less';
export default function BankPay({ namePrefix }) {
return (
<View className={styles.container}>
<Form.Item
name={`${namePrefix}-payeeBank`}
label='开户行'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
<Form.Item
name={`${namePrefix}-payeeAccount`}
label='银行卡号'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
<Form.Item
name={`${namePrefix}-payeeName`}
label='开户人'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
{/* <Form.Item
name='password'
label='支付密码'
rules={[{ required: true, message: '请输入支付密码' }]}
>
<Input type='password' placeholder='请输入支付密码' />
</Form.Item> */}
</View >
)
}

2
src/pages/feeconfirm/components/BankPay/index.module.less

@ -0,0 +1,2 @@
.container {
}

179
src/pages/feeconfirm/components/FormBar/index.jsx

@ -0,0 +1,179 @@
import { View } from '@tarojs/components';
import { Button, CapsuleTabs, Form, Modal, Toast } from 'antd-mobile';
import FormImage from '/components/FormImage';
import FormLabel from '/components/FormLabel';
import React, { useEffect, useMemo, useState } from 'react';
import { getOrderInfoAction } from '/request/actions';
import { getUrlParam } from '/utils';
import Taro from '@tarojs/taro';
// import Alipay from '../Alipay';
// import Wxpay from '../Wxpay';
// import BankPay from '../BankPay';
// import aliSrc from '/assets/icons/ali.svg';
// import wxSrc from '/assets/icons/wx.svg';
// import bankSrc from '/assets/icons/bank.svg';
import { orderConfirmAction } from '../../../../request/actions';
import styles from './index.module.less';
// const TabItem = ({ src, text }) => (
// <View className={styles['tabitem']}>
// <img src={src} />
// {text}
// </View>
// );
export default function FormBar() {
const [form] = Form.useForm();
// const [showFee, updateShowFee] = useState(false);
useEffect(() => {
getOrderInfoAction({
orderId: getUrlParam('orderId')
}).then(res => {
const orderShopInfo = res.orderShopInfo || {};
const feeShopInfo = res.feeShopInfo || {};
const _orderShopInfo = Object.keys(orderShopInfo).reduce((res, key) => {
return {
...res,
[`pay-${key}`]: orderShopInfo[key]
}
}, {});
const _feeShopInfo = Object.keys(orderShopInfo).reduce((res, key) => {
return {
...res,
[`fee-${key}`]: feeShopInfo[key]
}
}, {});
form.setFieldsValue({
...res,
..._orderShopInfo,
..._feeShopInfo
});
// updateShowFee(res.feePrice || res.feeImage || res.feeShopInfo)
});
}, []);
const handleSubmit = () => {
Modal.confirm({
title: '是否确认收款?',
onConfirm: async () => {
try {
const orderId = getUrlParam('orderId');
await orderConfirmAction({ orderId });
Toast.show({
icon: 'success',
content: '已成功确认收款信息'
});
Taro.navigateTo({
url: '/pages/dataset/index'
});
}
catch (err) {
console.log('err: ', err);
}
}
})
};
// const way = Form.useWatch('way', form);
// const feeway = Form.useWatch('feeway', form);
// const detailRenderer = useMemo(() => {
// return {
// alipay: <Alipay namePrefix='pay' />,
// wx: <Wxpay namePrefix='pay' />,
// bank: <BankPay namePrefix='pay' />
// }[way];
// }, [way]);
// const feeDetailRenderer = useMemo(() => {
// return {
// alipay: <Alipay namePrefix='fee' />,
// wx: <Wxpay namePrefix='fee' />,
// bank: <BankPay namePrefix='fee' />
// }[feeway];
// }, [feeway]);
const payImage = Form.useWatch('payImage', form);
const feeImage = Form.useWatch('feeImage', form);
return (
<View className={styles.container}>
<Form form={form} className={styles.form} layout='horizontal' >
<View className={styles.title}>
收款信息
</View>
<Form.Item name='orderId' label='订单编号' childElementPosition='right'>
<FormLabel />
</Form.Item>
<Form.Item name='orderDate' label='订单日期' childElementPosition='right'>
<FormLabel />
</Form.Item>
<Form.Item name='orderPrice' label='订单金额' childElementPosition='right'>
<FormLabel render={val => `${val || 0}`} />
</Form.Item>
<Form.Item name='feePrice' label='服务费金额' childElementPosition='right'>
<FormLabel render={val => `${val || 0}`} />
</Form.Item>
<Form.Item name='payUserTelephone' label='付款账号' childElementPosition='right'>
<FormLabel />
</Form.Item>
<Form.Item style={!payImage ? { display: 'none' } : {}} name='payImage' label='付款凭证' childElementPosition='right'>
<FormImage readonly />
</Form.Item>
<Form.Item style={!feeImage ? { display: 'none' } : {}} name='feeImage' label='服务费凭证' childElementPosition='right'>
<FormImage readonly />
</Form.Item>
{/* <Form.Item
name='way'
label='提现方式'
valuePropName='activeKey'
initialValue='alipay'
childElementPosition='right'
>
<CapsuleTabs style={{ padding: 0 }}>
<CapsuleTabs.Tab title={<TabItem text='支付宝' src={aliSrc} />} key='alipay' />
<CapsuleTabs.Tab title={<TabItem text='微信' src={wxSrc} />} key='wx' />
<CapsuleTabs.Tab title={<TabItem text='银行卡' src={bankSrc} />} key='bank' />
</CapsuleTabs>
</Form.Item>
{detailRenderer}
{showFee && (
<React.Fragment>
<View className={styles.title}>
服务费收款信息
</View>
<Form.Item name='feePrice' label='服务费' childElementPosition='right'>
<FormLabel render={val => `${val || 0}`} />
</Form.Item>
<Form.Item name='feeImage' label='服务费付款凭证' childElementPosition='right'>
<FormImage readonly />
</Form.Item>
<Form.Item
name='feeway'
label='提现方式'
valuePropName='activeKey'
initialValue='alipay'
childElementPosition='right'
>
<CapsuleTabs style={{ padding: 0 }}>
<CapsuleTabs.Tab title={<TabItem text='支付宝' src={aliSrc} />} key='alipay' />
<CapsuleTabs.Tab title={<TabItem text='微信' src={wxSrc} />} key='wx' />
<CapsuleTabs.Tab title={<TabItem text='银行卡' src={bankSrc} />} key='bank' />
</CapsuleTabs>
</Form.Item>
{feeDetailRenderer}
</React.Fragment>
)} */}
</Form >
<Button color='primary' shape='rounded' className={styles.submit} onClick={handleSubmit}>
确认收款
</Button>
</View>
)
}

71
src/pages/feeconfirm/components/FormBar/index.module.less

@ -0,0 +1,71 @@
.container {
background-color: #fff;
border-radius: 18px;
padding: 32px 32px 48px 32px;
.tabitem {
font-size: 24px;
display: flex;
align-items: center;
img {
width: 28px;
margin-right: 8px;
}
}
.btn {
width: 100%;
margin-top: 24px;
}
.title {
font-size: 28px;
font-weight: 600;
margin: 24px 0;
}
.margin {
margin-top: 32px;
}
.submit {
width: 100%;
margin-top: 72px;
}
:global {
.adm-capsule-tabs-header {
padding: 0;
}
.adm-list-item-content-prefix {
width: 168px;
}
.adm-capsule-tabs-tab {
padding: 8px;
border-radius: 6px;
border: 1px solid transparent;
transition: all .2s ease-in-out;
}
.adm-capsule-tabs-tab-active {
color: var(--color-primary);
background-color: #f0f9ff;
border-color: var(--color-primary);
}
.adm-list-body {
border-top: unset;
}
.adm-list-item {
padding-left: 0;
}
.adm-list-item-content {
border-top: unset;
}
}
}

42
src/pages/feeconfirm/components/Wxpay/index.jsx

@ -0,0 +1,42 @@
import { View } from '@tarojs/components';
import { Form } from 'antd-mobile';
import FormLabel from '/components/FormLabel';
import FormImage from '/components/FormImage';
import styles from './index.module.less';
export default function Wxpay({ namePrefix }) {
return (
<View className={styles.container}>
<Form.Item
name={`${namePrefix}-weixin`}
label='微信账号'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
<Form.Item
name={`${namePrefix}-weixinName`}
label='微信姓名'
childElementPosition='right'
>
<FormLabel />
</Form.Item>
{/* <Form.Item
name={`${namePrefix}-weixinImage`}
label='收款码'
childElementPosition='right'
>
<FormImage readonly width={72} height={72} />
</Form.Item> */}
{/* <Form.Item
name='password'
label='支付密码'
rules={[{ required: true, message: '请输入支付密码' }]}
>
<Input type='password' placeholder='请输入支付密码' />
</Form.Item> */}
</View >
)
}

2
src/pages/feeconfirm/components/Wxpay/index.module.less

@ -0,0 +1,2 @@
.container {
}

4
src/pages/feeconfirm/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '确认收款',
usingComponents: {},
})

25
src/pages/feeconfirm/index.jsx

@ -0,0 +1,25 @@
import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import FormBar from './components/FormBar';
import { NavBar } from 'antd-mobile';
import styles from './index.module.less';
export default function ShopInfo() {
const handleBack = () => {
Taro.navigateTo({
url: '/pages/dataset/index'
});
};
return (
<View className={styles.container}>
<NavBar onBack={handleBack} style={{ padding: 0 }}>确认收款</NavBar>
<View className={styles.wrapper}>
<FormBar />
</View>
</View>
)
}

10
src/pages/feeconfirm/index.module.less

@ -0,0 +1,10 @@
.container {
background: linear-gradient(180deg, #d7ebfa, #f5f5f5 30vh);
height: 100%;
overflow-y: auto;
.wrapper {
box-sizing: border-box;
padding: 42px;
}
}

4
src/pages/feedback/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '反馈',
usingComponents: {},
})

45
src/pages/feedback/index.jsx

@ -0,0 +1,45 @@
import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { Button, Form, NavBar, TextArea } from 'antd-mobile';
import { feedbackAction } from '../../request/actions';
import styles from './index.module.less';
export default function Feedback() {
const [form] = Form.useForm();
const handleBack = () => {
Taro.navigateTo({
url: '/pages/mine/index'
});
};
const handleVery = async () => {
try {
const values = await form.validateFields();
console.log('values: ', values);
await feedbackAction(values);
handleBack();
}
catch (err) {
console.log('err: ', err);
}
};
return (
<View className={styles.container}>
<NavBar onBack={handleBack} style={{ padding: 0 }}>
反馈
</NavBar>
<Form form={form} className={styles.form} layout='horizontal'>
<Form.Item name='contents' rules={[{ required: true, message: '请填写反馈内容' }]}>
<TextArea placeholder='请输入反馈' autoFocus autoSize={{ minRows: 12 }} />
</Form.Item>
<Button color='primary' shape='rounded' className={styles.submit} onClick={handleVery}>
提交
</Button>
</Form >
</View>
);
}

28
src/pages/feedback/index.module.less

@ -0,0 +1,28 @@
.container {
background: linear-gradient(180deg, #d7ebfa, #f5f5f5 30vh);
height: 100%;
.form {
background-color: #fff;
border-radius: 18px;
padding: 32px 32px 48px 32px;
width: 620px;
margin: 0 auto;
margin-top: 72px;
:global {
.adm-list-body {
border-top: unset;
}
.adm-list-item {
padding-left: 0;
}
}
.submit {
width: 100%;
margin-top: 72px;
}
}
}

93
src/pages/forget/components/FormBar/index.jsx

@ -0,0 +1,93 @@
import { View } from '@tarojs/components';
import { Button, Form, Input, Toast } from 'antd-mobile';
import { useState } from 'react';
import Taro from '@tarojs/taro';
import { editPasswordAction } from '../../../../request/actions';
import styles from './index.module.less';
export default function FormBar() {
const [form] = Form.useForm();
const [countdown, setCountdown] = useState(60);
const [isCounting, setIsCounting] = useState(false);
const sendVerificationCode = () => {
if (isCounting) {
return;
}
setIsCounting(true);
// Simulate sending verification code
console.log('Sending verification code...');
const interval = setInterval(() => {
setCountdown(prev => {
if (prev <= 1) {
clearInterval(interval);
setIsCounting(false);
return 60; // Reset countdown
}
return prev - 1;
});
}, 1000);
};
const handleReset = async () => {
try {
const values = await form.validateFields();
await editPasswordAction(values);
Toast.show({
icon: 'success',
content: '密码修改成功'
});
Taro.navigateBack();
}
catch (err) {
console.log('err: ', err);
}
};
return (
<View className={styles.container}>
<Form form={form} className={styles.form}>
<Form.Item
name='newPassword'
label='新密码'
rules={[
{ required: true, message: '请输入密码' },
{ whitespace: true, message: '请输入有效的密码' }
]}
>
<Input placeholder='请输入密码' />
</Form.Item>
<Form.Item
name='repassword'
label='确认密码'
rules={[
{ required: true, message: '请确认密码' },
{ whitespace: true, message: '请输入有效的密码' }
]}
>
<Input type='password' placeholder='请确认密码' />
</Form.Item>
{/* <Form.Item
name='veryCode'
label='验证码'
rules={[{ required: true, message: '请输入新密码' }]}
extra={
<View className={styles.extra} onClick={sendVerificationCode}>
<a>{isCounting ? `${countdown}秒后重新获取)` : '发送验证码'}</a>
</View>
}
>
<Input
placeholder='请输入验证码'
style={{ '--text-align': 'left' }}
clearable
/>
</Form.Item> */}
</Form >
<Button color='primary' className={styles.submit} onClick={handleReset}>确认修改</Button>
</View >
)
}

46
src/pages/forget/components/FormBar/index.module.less

@ -0,0 +1,46 @@
.container {
background-color: #fff;
border-radius: 18px;
margin-top: 72px;
padding: 32px;
.form {
:global {
.adm-list-body {
border-top: unset;
}
.adm-list-item {
padding-left: 0;
}
}
.extra {
color: #007AFF;
position: relative;
font-size: 24px;
top: 24px;
}
}
.bar {
display: flex;
justify-content: center;
padding: 24px 72px;
.btn {
font-size: 24px;
flex: 1;
text-align: center;
&:first-child {
border-right: 1px solid #eee;
}
}
}
.submit {
width: 100%;
margin-top: 72px;
}
}

33
src/pages/forget/components/HeaderBar/index.jsx

@ -0,0 +1,33 @@
import { View } from '@tarojs/components';
import { useLoad } from '@tarojs/taro';
import logoSrc from '/assets/icons/logo.png';
import styles from './index.module.less';
export default function HeaderBar() {
useLoad(() => {
console.log('Page loaded.')
});
return (
<View className={styles.container}>
<View className={styles.row}>
<View className={styles.title}>
Hi Weaith
</View>
<View className={styles.subtitle}>
欢迎您来到融易诚
</View>
</View>
<View className={styles.row2}>
<View className={styles.item}>
<img src={logoSrc} className={styles.logo} alt='logo' />
<View className={styles.title}>
融易诚
</View>
</View>
</View>
</View>
)
}

42
src/pages/forget/components/HeaderBar/index.module.less

@ -0,0 +1,42 @@
.container {
.row {
.title {
font-weight: normal;
overflow-wrap: normal;
font-size: 42px;
color: rgb(48, 49, 51);
}
.subtitle {
font-weight: normal;
overflow-wrap: normal;
font-size: 32px;
color: rgb(48, 49, 51);
}
}
.row2 {
display: flex;
justify-content: flex-end;
.item {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 42px;
.title {
font-weight: normal;
overflow-wrap: normal;
font-size: 32px;
color: rgb(48, 49, 51);
text-align: center;
}
.logo {
width: 120px;
}
}
}
}

4
src/pages/forget/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '忘记密码',
usingComponents: {},
})

34
src/pages/forget/index.jsx

@ -0,0 +1,34 @@
import { View } from '@tarojs/components';
import Taro, { useLoad } from '@tarojs/taro';
import HeaderBar from './components/HeaderBar';
import FormBar from './components/FormBar';
import { NavBar } from 'antd-mobile';
import styles from './index.module.less';
export default function Forget() {
const query = Taro.getCurrentInstance()?.router?.params;
useLoad(() => {
console.log('Page loaded.')
});
const handleBack = () => {
Taro.navigateBack();
};
return (
<View className={styles.container}>
{query?.hasBack && (
<NavBar onBack={handleBack} style={{ padding: 0 }}>
忘记密码
</NavBar>
)}
<View className={styles.wrapper}>
<HeaderBar />
<FormBar />
</View>
</View>
);
}

51
src/pages/forget/index.module.less

@ -0,0 +1,51 @@
.container {
background: linear-gradient(180deg, #d7ebfa, #f5f5f5 30vh);
height: 100%;
}
.wrapper {
box-sizing: border-box;
padding: 120px 42px;
.row {
.title {
font-weight: normal;
overflow-wrap: normal;
font-size: 42px;
color: rgb(48, 49, 51);
}
.subtitle {
font-weight: normal;
overflow-wrap: normal;
font-size: 32px;
color: rgb(48, 49, 51);
}
}
.row2 {
display: flex;
justify-content: flex-end;
.item {
display: flex;
flex-direction: column;
align-items: center;
margin-right: 42px;
.title {
font-weight: normal;
overflow-wrap: normal;
font-size: 32px;
color: rgb(48, 49, 51);
text-align: center;
}
.logo {
width: 120px;
}
}
}
}

40
src/pages/funds/components/Balance/Alipay/index.jsx

@ -0,0 +1,40 @@
import { View } from '@tarojs/components';
import { Form } from 'antd-mobile';
import FormLabel from '/components/FormLabel';
import FormImage from '/components/FormImage';
import styles from './index.module.less';
export default function Alipay() {
return (
<View className={styles.container}>
<Form.Item
name='alipay'
label='支付宝账号'
>
<FormLabel />
</Form.Item>
<Form.Item
name='alipayName'
label='支付宝姓名'
>
<FormLabel />
</Form.Item>
<Form.Item
name='alipayImage'
label='收款码'
rules={[{ required: true, message: '请选择请码' }]}
>
<FormImage readonly width={72} height={72} />
</Form.Item>
{/* <Form.Item
name='password'
label='支付密码'
rules={[{ required: true, message: '请输入支付密码' }]}
>
<Input type='password' placeholder='请输入支付密码' />
</Form.Item> */}
</View >
)
}

3
src/pages/funds/components/Balance/Alipay/index.module.less

@ -0,0 +1,3 @@
.container {
}

38
src/pages/funds/components/Balance/BankPay/index.jsx

@ -0,0 +1,38 @@
import { View } from '@tarojs/components';
import { Form } from 'antd-mobile';
import FormLabel from '/components/FormLabel';
import styles from './index.module.less';
export default function BankPay() {
return (
<View className={styles.container}>
<Form.Item
name='payeeBank'
label='开户行'
>
<FormLabel />
</Form.Item>
<Form.Item
name='payeeAccount'
label='银行卡号'
>
<FormLabel />
</Form.Item>
<Form.Item
name='payeeName'
label='开户人'
>
<FormLabel />
</Form.Item>
{/* <Form.Item
name='password'
label='支付密码'
rules={[{ required: true, message: '请输入支付密码' }]}
>
<Input type='password' placeholder='请输入支付密码' />
</Form.Item> */}
</View >
)
}

2
src/pages/funds/components/Balance/BankPay/index.module.less

@ -0,0 +1,2 @@
.container {
}

39
src/pages/funds/components/Balance/Wxpay/index.jsx

@ -0,0 +1,39 @@
import { View } from '@tarojs/components';
import { Form } from 'antd-mobile';
import FormLabel from '/components/FormLabel';
import FormImage from '/components/FormImage';
import styles from './index.module.less';
export default function Wxpay() {
return (
<View className={styles.container}>
<Form.Item
name='weixin'
label='微信账号'
>
<FormLabel />
</Form.Item>
<Form.Item
name='weixinName'
label='微信姓名'
>
<FormLabel />
</Form.Item>
<Form.Item
name='weixinImage'
label='收款码'
>
<FormImage readonly width={72} height={72} />
</Form.Item>
{/* <Form.Item
name='password'
label='支付密码'
rules={[{ required: true, message: '请输入支付密码' }]}
>
<Input type='password' placeholder='请输入支付密码' />
</Form.Item> */}
</View >
)
}

2
src/pages/funds/components/Balance/Wxpay/index.module.less

@ -0,0 +1,2 @@
.container {
}

123
src/pages/funds/components/Balance/index.jsx

@ -0,0 +1,123 @@
import { useState } from 'react';
import cls from 'classnames';
import { View } from '@tarojs/components';
import { Button, Form, Input, Popup, Toast } from 'antd-mobile';
// import Alipay from './Alipay';
// import Wxpay from './Wxpay';
// import BankPay from './BankPay';
// import aliSrc from '/assets/icons/ali.svg';
// import wxSrc from '/assets/icons/wx.svg';
// import bankSrc from '/assets/icons/bank.svg';
import FormLabel from '/components/FormLabel';
import { getShopInfoAction, userWithdrawalAction } from '../../../../request/actions';
import styles from './index.module.less';
// const TabItem = ({ src, text }) => (
// <View className={styles['tabitem']}>
// <img src={src} />
// {text}
// </View>
// );
const Balance = ({ balanceData, className, onAfterClose }) => {
const prefix = cls(styles.container, className);
const [visible, setVisible] = useState(false);
const [form] = Form.useForm();
const onShow = () => {
setVisible(true);
//
getShopInfoAction().then(res => {
form.setFieldsValue(res);
});
};
const onClose = () => {
setVisible(false);
onAfterClose();
setTimeout(() => {
form.resetFields();
}, 200);
};
const handleWithdrawal = async () => {
try {
const values = await form.validateFields();
const cash = values.cash;
await userWithdrawalAction({ cash });
Toast.show({
content: '您已提现成功'
});
onClose();
}
catch (err) {
console.log('err: ', err);
}
};
// const way = Form.useWatch('way', form);
// const detailRenderer = useMemo(() => {
// return {
// alipay: <Alipay />,
// wx: <Wxpay />,
// bank: <BankPay />
// }[way];
// }, [way]);
const balance = balanceData?.balance || '0.00';
return (
<View className={prefix}>
<View className={styles.title}>账户余额</View>
<View className={styles.subtitle}>{balance}</View>
<Button color='primary' className={styles.btn} onClick={onShow}>提现</Button>
<Popup
visible={visible}
onMaskClick={onClose}
bodyClassName={styles['popup-wrapper']}
>
<Form form={form} className={styles.popup} layout='horizontal'>
<View className={styles.balance}>
<FormLabel value={balance} render={val => `当前可用提现余额¥${val}`} />
</View>
<Form.Item
name='cash'
label='提现金额'
// extra={`${balance}`}
rules={[{ required: true, message: '请输入提现金额' }]}
>
<Input className={styles.cash} type='number' min={0} max={9999999999} placeholder='请输入提现金额' />
</Form.Item>
{/* <Form.Item
name='way'
label='提现方式'
valuePropName='activeKey'
initialValue='alipay'
>
<CapsuleTabs style={{ padding: 0 }}>
<CapsuleTabs.Tab title={<TabItem text='支付宝' src={aliSrc} />} key='alipay' />
<CapsuleTabs.Tab title={<TabItem text='微信' src={wxSrc} />} key='wx' />
<CapsuleTabs.Tab title={<TabItem text='银行卡' src={bankSrc} />} key='bank' />
</CapsuleTabs>
</Form.Item>
{detailRenderer} */}
<Button
className={styles.btn}
color='primary'
shape='rounded'
onClick={handleWithdrawal}
>
确认提现
</Button>
</Form>
</Popup>
</View>
)
};
export default Balance;

98
src/pages/funds/components/Balance/index.module.less

@ -0,0 +1,98 @@
.container {
background-color: #fff;
border-radius: 18px;
padding: 32px;
display: flex;
flex-direction: column;
align-items: center;
.title {
font-size: 28px;
font-weight: 600;
margin-bottom: 24px;
}
.subtitle {
font-size: 42px;
font-weight: 600;
margin-bottom: 24px;
color: var(--color-primary);
}
.btn {
width: 380px;
}
}
.popup-wrapper {
height: 480px;
}
.balance {
display: flex;
justify-content: center;
margin: 48px 0 24px;
}
.popup {
padding: 24px;
.tabitem {
font-size: 24px;
display: flex;
align-items: center;
img {
width: 28px;
margin-right: 8px;
}
}
.btn {
width: 100%;
margin-top: 24px;
}
:global {
.adm-capsule-tabs-header {
padding: 0;
}
.adm-capsule-tabs-tab {
padding: 8px 20px;
border-radius: 6px;
border: 1px solid transparent;
transition: all .2s ease-in-out;
}
.adm-capsule-tabs-tab-active {
color: var(--color-primary);
background-color: #f0f9ff;
border-color: var(--color-primary);
}
.adm-list-item {
padding: 32px 0;
}
.adm-form-item-label {
font-size: 28px;
position: relative;
top: 12px;
}
.adm-input-element {
font-size: 42px;
}
}
}
:global {
.adm-list-default .adm-list-body {
border-top: unset;
}
.adm-list-item-content {
border-top: unset;
}
}

38
src/pages/funds/components/DataList/index.jsx

@ -0,0 +1,38 @@
import React from 'react';
import { List, Empty, Tag } from 'antd-mobile';
import { Text, View } from '@tarojs/components';
import cls from 'classnames';
import styles from './index.module.less';
const DataList = ({ dataSource = [], className }) => {
const prefix = cls(styles.container, className);
return (
<View className={prefix}>
<View className={styles.title}>交易记录</View>
{dataSource.length > 0 ? (
<List>
{dataSource.map((item, index) => (
<List.Item key={index}>
<View className={styles.row}>
<View className={styles.left}>
<Tag className={styles.status} color={item.isIn ? 'primary' : 'warning'}>{item.isIn ? '入账' : '出账'}</Tag>
{item.cash}
</View>
<Text className={styles.tag} color='default'>{item.remark}</Text>
</View>
</List.Item>
))}
</List>
) : (
<Empty
style={{ padding: '64px 0' }}
description='暂无数据'
/>
)}
</View>
)
};
export default DataList;

44
src/pages/funds/components/DataList/index.module.less

@ -0,0 +1,44 @@
.container {
background-color: #fff;
border-radius: 18px;
padding: 32px;
margin-top: 24px;
.title {
font-size: 28px;
font-weight: 600;
margin-bottom: 24px;
}
.row {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex;
align-items: center;
font-size: 24px;
.status {
margin-right: 12px;
}
}
.tag {
font-size: 24px;
}
&:not(:last-child) {
border-bottom: 1px solid #eee;
}
}
:global {
.adm-list-default .adm-list-body {
border: unset;
}
}
}

4
src/pages/funds/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '资产管理',
usingComponents: {},
})

77
src/pages/funds/index.jsx

@ -0,0 +1,77 @@
import { useState } from 'react';
import { View, ScrollView } from '@tarojs/components';
import Taro, { useLoad } from '@tarojs/taro';
import { NavBar, PullToRefresh } from 'antd-mobile';
import DataList from './components/DataList';
import Balance from './components/Balance';
import { myBalanceAction, userWalletLogListLoopAction } from '../../request/actions';
import useRequestList from '../../hooks/useRequestList';
import styles from './index.module.less';
const fetchDataRecursively = async (times, datasource) => {
if (times <= 0 || (datasource && datasource?.length < 10)) {
return [];
}
const lastLogId = datasource?.[datasource?.length - 1]?.logId;
const result = await userWalletLogListLoopAction({ lastLogId });
const nextResults = await fetchDataRecursively(times - 1, result?.dataList);
return [...result?.dataList, ...nextResults];
};
export default function Funds() {
const [data, setData] = useState([]);
//
const { data: balanceData, getDataTask: getBananceData } = useRequestList({
immediate: false,
showMsg: false,
action: myBalanceAction
});
const handleInitData = async () => {
getBananceData();
const dataSource = await fetchDataRecursively(2);
setData(dataSource);
};
useLoad(() => {
handleInitData();
});
const handleBack = () => {
Taro.navigateTo({
url: '/pages/mine/index'
});
};
const handleScrollToLower = async () => {
const lastLogId = data?.[data?.length - 1]?.logId;
const result = await userWalletLogListLoopAction({ lastLogId });
const newDataSource = result?.dataList;
setData([...data, ...newDataSource]);
};
return (
<View className={styles.container}>
<NavBar onBack={handleBack} style={{ padding: 0 }}>
资金管理
</NavBar>
<PullToRefresh
onRefresh={handleInitData}
>
<ScrollView
scrollY
onScrollToLower={handleScrollToLower}
lowerThreshold={50}
>
<View className={styles.wrapper}>
<Balance balanceData={balanceData} onAfterClose={handleInitData} />
<DataList className={styles.list} dataSource={data} />
</View>
</ScrollView>
</PullToRefresh>
</View>
)
}

11
src/pages/funds/index.module.less

@ -0,0 +1,11 @@
.container {
background: linear-gradient(180deg, #d7ebfa, #f5f5f5 30vh);
height: 100%;
.wrapper {
box-sizing: border-box;
padding: 42px;
height: calc(100vh - 82px);
}
}

29
src/pages/index/components/Banner/index.jsx

@ -0,0 +1,29 @@
import { View, Swiper, SwiperItem, Image } from '@tarojs/components';
import styles from './index.module.less';
export default function Banner({
swiperList = []
}) {
if (swiperList.length === 0) {
return <View className={styles.container} style={{ background: '#eee' }}></View>
}
return (
<Swiper
className={styles.container}
indicatorColor='#999'
indicatorActiveColor='#007AFF'
circular
indicatorDots
autoplay
>
{swiperList.map((bannerSrc, index) => (
<SwiperItem key={index}>
<Image style={{ width: '100%' }} src={bannerSrc} mode='aspectFit' />
</SwiperItem>
))}
</Swiper>
)
}

5
src/pages/index/components/Banner/index.module.less

@ -0,0 +1,5 @@
.container {
margin-top: 36px;
height: 328px;
}

33
src/pages/index/components/Header/index.jsx

@ -0,0 +1,33 @@
import { View } from '@tarojs/components';
import { NoticeBar } from 'antd-mobile';
import Taro from '@tarojs/taro';
import logoSrc from '/assets/icons/logo.png';
import styles from './index.module.less';
export default function Header({
noticeTitle
}) {
return (
<View className={styles.header}>
<View className={styles.left}>
<img src={logoSrc} className={styles.logo} alt='logo' />
<View className={styles.title}>
融易诚
</View>
</View>
{noticeTitle && (
<NoticeBar
content={noticeTitle}
color='alert'
style={{ width: 206, height: 32, padding: '0 8px', color: 'red', background: '#f5f5f5' }}
shape='rounded'
bordered={false}
onClick={() => Taro.navigateTo({ url: '/pages/notice/index' })}
/>
)}
</View>
);
}

20
src/pages/index/components/Header/index.module.less

@ -0,0 +1,20 @@
.header {
display: flex;
justify-content: space-between;
.left {
display: flex;
align-items: center;
.logo {
width: 68px;
margin-right: 12px;
}
.title {
font-size: 28px;
font-weight: 500;
color: #333;
}
}
}

53
src/pages/index/components/MyShop/index.jsx

@ -0,0 +1,53 @@
import { ExclamationCircleFill } from 'antd-mobile-icons'
import { View } from '@tarojs/components';
import { Button } from 'antd-mobile';
import Taro from '@tarojs/taro';
import logoSrc from '/assets/icons/logo.png';
import styles from './index.module.less';
const MyShop = () => {
const handleVery = () => {
Taro.navigateTo({
url: '/pages/shopinfo/index'
});
};
return (
<View className={styles.container}>
<View className={styles.title}>
<img src={logoSrc} className={styles.logo} alt='logo' />
<View className={styles.title}>
我的小店
</View>
</View>
<View className={styles.card}>
<View className={styles.title}>
完成考试 帮您开启成功之路
</View>
<View className={styles.info}>
<View className={styles.left}>
<ExclamationCircleFill className={styles.icon} />
<View>
<View className={styles.title}>店铺认证</View>
<View className={styles.subtitle}>请完成店铺认证以开启完整功能</View>
</View>
</View>
<Button
className={styles.btn}
color='primary'
shape='rounded'
size='small'
onClick={handleVery}
>
立即认证
</Button>
</View>
</View>
</View>
);
};
export default MyShop;

70
src/pages/index/components/MyShop/index.module.less

@ -0,0 +1,70 @@
.container {
background: linear-gradient(180deg, #1677ff, #fff 30vh);
padding: 24px;
border-radius: 12px;
margin-top: 32px;
.title {
display: flex;
align-items: center;
.logo {
width: 98px;
margin-right: 12px;
}
.title {
font-size: 28px;
font-weight: 500;
color: #fff;
}
}
.card {
padding: 18px 24px;
border-radius: 12px;
background-color: #fff;
margin-top: 18px;
.title {
font-size: 28px;
font-weight: 500;
color: #333;
}
.info {
margin-top: 18px;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex;
align-items: center;
.icon {
color: rgb(255, 0, 0);
font-size: 42px;
margin-right: 18px;
}
.title {
font-size: 24px;
color: #333;
font-weight: bolder;
}
.subtitle {
font-size: 22px;
color: #999;
margin-top: 4px;
}
}
.btn {
font-size: 24px;
padding: 0px 18px;
height: 48px;
}
}
}
}

30
src/pages/index/components/TodoList/index.jsx

@ -0,0 +1,30 @@
import { View, Text } from '@tarojs/components';
import { List } from 'antd-mobile';
import { FileOutline } from 'antd-mobile-icons';
import styles from './index.module.less';
const TodoList = () => {
return (
<View className={styles.container}>
<View className={styles.title}>
<Text className={styles.text}>今日任务</Text>
</View>
<List className={styles.list}>
<List.Item prefix={<FileOutline />} onClick={() => { }}>
1完成店铺认证
</List.Item>
<List.Item prefix={<FileOutline />} onClick={() => { }}>
2完成信用优化
</List.Item>
<List.Item prefix={<FileOutline />} onClick={() => { }}>
3完成店铺认证
</List.Item>
</List>
</View>
);
};
export default TodoList;

30
src/pages/index/components/TodoList/index.module.less

@ -0,0 +1,30 @@
.container {
padding: 24px;
border-radius: 12px;
background-color: #fff;
margin-top: 24px;
.title {
.text {
font-size: 28px;
font-weight: 500;
color: #333;
padding: 12px 0;
border-bottom: 4px solid #007AFF;
}
}
.list {
margin-top: 18px;
>* {
font-size: 28px !important;
}
:global {
.adm-list-item {
// padding-left: unset;
}
}
}
}

30
src/pages/index/components/Toolbar/index.jsx

@ -0,0 +1,30 @@
import { ExclamationCircleFill } from 'antd-mobile-icons'
import { View, Text } from '@tarojs/components';
import styles from './index.module.less';
import { Button } from 'antd-mobile';
import { AddCircleOutline, TeamFill, RedoOutline } from 'antd-mobile-icons';
import Taro from '@tarojs/taro';
const Toolbar = () => {
return (
<View className={styles.container}>
<View className={styles.card} onClick={() => Taro.navigateTo({ url: '/pages/dataset/index' })}>
<AddCircleOutline className={styles.icon} style={{ color: '#007AFF' }} />
<View>数据优化</View>
</View>
<View className={styles.card} onClick={() => Taro.navigateTo({ url: '/pages/team/index' })}>
<TeamFill className={styles.icon} style={{ color: 'rgb(114, 46, 209)' }} />
<View>团队矩阵</View>
</View>
<View className={styles.card} onClick={() => Taro.navigateTo({ url: '/pages/invite/index' })}>
<RedoOutline className={styles.icon} style={{ color: 'rgb(82, 196, 26)' }} />
<View>邀请商户</View>
</View>
</View>
);
};
export default Toolbar;

29
src/pages/index/components/Toolbar/index.module.less

@ -0,0 +1,29 @@
.container {
padding: 8px 24px;
border-radius: 12px;
background-color: #fff;
margin-top: 24px;
display: flex;
justify-content: space-around;
.card {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 12px;
transition: all .2s ease-in-out;
&:active {
background-color: #fafafa;
border-radius: 12px;
}
.icon {
font-size: 48px;
margin-bottom: 12px;
}
}
}

4
src/pages/index/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '首页',
usingComponents: {},
})

58
src/pages/index/index.jsx

@ -0,0 +1,58 @@
import { View } from '@tarojs/components';
import Header from './components/Header';
import Banner from './components/Banner';
import MyShop from './components/MyShop';
import Toolbar from './components/Toolbar';
import Taro from '@tarojs/taro';
import TodoList from './components/TodoList';
import useRequestList from '../../hooks/useRequestList';
import { getIndexPageAction } from '../../request/actions';
import { useEffect } from 'react';
import { Modal } from 'antd-mobile';
import styles from './index.module.less';
export default function Index() {
const { data } = useRequestList({
action: getIndexPageAction
});
useEffect(() => {
if (!data) {
return;
}
if (data?.systemMessage && data?.systemMessage?.messageId !== localStorage.getItem('messageId')) {
let handler = null;
handler = Modal.show({
title: '有新的站内新,点击查看详情',
showCloseButton: false,
actions: [
{
key: 'view',
text: '查看站内信',
},
],
onAction: action => {
if (action.key === 'view') {
Taro.navigateTo({
url: '/pages/sitemessage/index'
});
localStorage.setItem('messageId', data.systemMessage?.messageId);
handler.close();
}
}
});
}
}, [data]);
return (
<View className={styles.container}>
<Header {...data} />
<Banner {...data} />
<MyShop {...data} />
<Toolbar {...data} />
<TodoList {...data} />
</View>
)
}

7
src/pages/index/index.module.less

@ -0,0 +1,7 @@
.container {
background: linear-gradient(180deg, #d7ebfa, #f5f5f5 30vh);
height: 100%;
box-sizing: border-box;
padding: 24px 24px;
}

88
src/pages/invite/components/FormBar/index.jsx

@ -0,0 +1,88 @@
import { View } from '@tarojs/components';
import { Button, Divider, Form } from 'antd-mobile';
import { useEffect, useRef } from 'react';
import { QRCodeCanvas } from 'qrcode.react';
import { CopyToClipboard } from 'react-copy-to-clipboard';
import { useLocalStorageState } from 'ahooks';
import styles from './index.module.less';
const FormUser = ({ value }) => (
<View className={styles.user}>
<View className={styles.logo}>
1
</View>
<View className={styles.phone}>
{value}
</View>
</View>
);
const FormCopyText = ({ value }) => (
<View className={styles.copy}>
<View className={styles.text}>{value}</View>
<CopyToClipboard text={value}><a>复制</a></CopyToClipboard>
</View>
);
const QRCode = ({ value }) => {
const ref = useRef();
const handleDownload = () => {
const canvas = ref.current;
if (canvas) {
const imageURL = canvas.toDataURL('image/png'); //
const link = document.createElement('a');
link.href = imageURL;
link.download = '邀请码.png';
link.click();
}
};
return (
<View className={styles.qrcode}>
<QRCodeCanvas value={value} ref={ref} />
<Button className={styles.btn} color='primary' shape='default' onClick={handleDownload}>
下载
</Button>
</View>
);
};
export default function FormBar() {
const [form] = Form.useForm();
const [storage] = useLocalStorageState('userInfo');
useEffect(() => {
const origin = window.location.origin;
const invite_code = storage?.shareCode;
const invite_url = `${origin}/#/pages/register/index?shareCode=${invite_code}`;
form.setFieldsValue({
user_info: storage?.telephone,
qrcode: invite_url,
invite_code,
invite_url
});
}, []);
return (
<View className={styles.container}>
<Form form={form} className={styles.form} layout='vertical'>
<Form.Item name='user_info'>
<FormUser />
</Form.Item>
<Form.Item name='qrcode' style={{ display: 'flex', justifyContent: 'center' }}>
<QRCode />
</Form.Item>
<Divider />
<Form.Item name='invite_code' label='我的邀请码'>
<FormCopyText />
</Form.Item>
<Form.Item name='invite_url' label='邀请链接'>
<FormCopyText />
</Form.Item>
</Form >
</View>
)
}

80
src/pages/invite/components/FormBar/index.module.less

@ -0,0 +1,80 @@
.container {
background-color: #fff;
border-radius: 18px;
margin-top: 72px;
padding: 32px 32px 48px 32px;
.form {
:global {
.adm-list-body {
border-top: unset;
}
.adm-list-item {
padding-left: 0;
}
.adm-list-item-content {
border: unset;
}
}
.user {
display: flex;
align-items: center;
.logo {
width: 72px;
height: 72px;
border-radius: 50%;
background-color: pink;
font-size: 42px;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
margin-right: 18px;
}
.phone {
font-weight: 700;
font-size: 32px;
margin-bottom: 4px;
}
}
.qrcode {
display: flex;
flex-direction: column;
align-items: center;
.btn {
width: 100%;
margin-top: 24px;
}
}
.copy {
display: flex;
background-color: #f8f8f8;
padding: 12px;
border-radius: 2px;
font-size: 24px;
.text {
flex: 1;
word-break: break-all;
margin-right: 24px;
}
a {
flex-basis: 72px;
}
}
}
.submit {
width: 100%;
margin-top: 72px;
}
}

4
src/pages/invite/index.config.js

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '店铺信息',
usingComponents: {},
})

31
src/pages/invite/index.jsx

@ -0,0 +1,31 @@
import { View } from '@tarojs/components';
import Taro, { useLoad } from '@tarojs/taro';
import FormBar from './components/FormBar';
import { NavBar } from 'antd-mobile';
import styles from './index.module.less';
export default function Invite() {
useLoad(() => {
console.log('Page loaded.')
});
const handleBack = () => {
Taro.navigateTo({
url: '/pages/index/index'
});
};
return (
<View className={styles.container}>
<NavBar onBack={handleBack} style={{ padding: 0 }}>
邀请商户
</NavBar>
<View className={styles.wrapper}>
<FormBar />
</View>
</View>
);
}

9
src/pages/invite/index.module.less

@ -0,0 +1,9 @@
.container {
background: linear-gradient(180deg, #d7ebfa, #f5f5f5 30vh);
height: 100%;
.wrapper {
box-sizing: border-box;
padding: 42px;
}
}

41
src/pages/login/components/FormBar/index.jsx

@ -0,0 +1,41 @@
import { View } from '@tarojs/components';
import { Button, Form, Input } from 'antd-mobile';
import Taro from '@tarojs/taro';
import { loginAction } from '../../../../request/actions';
import { useLocalStorageState } from 'ahooks';
import styles from './index.module.less';
export default function FormBar() {
const [form] = Form.useForm();
const [, updateStorage] = useLocalStorageState('userInfo', {defaultValue: null});
const handleLogin = async () => {
try {
const values = await form.validateFields();
const data = await loginAction(values);
updateStorage(data);
Taro.navigateTo({ url: '/pages/index/index' });
}
catch (err) {
console.log('err: ', err);
}
};
return (
<View className={styles.container}>
<Form form={form} className={styles.form}>
<Form.Item name='telephone' label='账号' rules={[{ required: true, message: '请输入手机号或电子邮箱' }]}>
<Input placeholder='请输入手机号或电子邮箱' />
</Form.Item>
<Form.Item name='password' label='密码' rules={[{ required: true, message: '请输入密码' }]}>
<Input type='password' placeholder='请输入密码' />
</Form.Item>
</Form>
<Button color='primary' className={styles.submit} onClick={handleLogin}>登录</Button>
<View className={styles.bar}>
<View className={styles.btn} onClick={() => Taro.navigateTo({ url: '/pages/register/index' })}>注册</View>
</View>
</View>
)
}

38
src/pages/login/components/FormBar/index.module.less

@ -0,0 +1,38 @@
.container {
background-color: #fff;
border-radius: 18px;
margin-top: 72px;
padding: 32px 32px 0 32px;
.form {
:global {
.adm-list-body {
border-top: unset;
}
.adm-list-item {
padding-left: 0;
}
}
}
.bar {
display: flex;
justify-content: space-around;
padding: 24px 72px;
.btn {
font-size: 24px;
flex: 1;
text-align: center;
&:first-child {
border-right: 1px solid #eee;
}
}
}
.submit {
width: 100%;
margin-top: 72px;
}
}

34
src/pages/login/components/HeaderBar/index.jsx

@ -0,0 +1,34 @@
import { View } from '@tarojs/components';
import { useLoad } from '@tarojs/taro';
import logoSrc from '/assets/icons/logo.png';
import styles from './index.module.less';
export default function HeaderBar() {
useLoad(() => {
console.log('Page loaded.')
});
return (
<View className={styles.container}>
<View className={styles.row}>
<View className={styles.title}>
Hi Weaith
</View>
<View className={styles.subtitle}>
欢迎您来到融易诚
</View>
</View>
<View className={styles.row2}>
<View className={styles.item}>
<img src={logoSrc} className={styles.logo} alt='logo' />
<View className={styles.title}>
融易诚
</View>
</View>
</View>
</View>
)
}

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

Loading…
Cancel
Save