Initial commit
This commit is contained in:
12
.editorconfig
Normal file
12
.editorconfig
Normal file
@@ -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
|
||||
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
dist/
|
||||
deploy_versions/
|
||||
.temp/
|
||||
.rn_temp/
|
||||
node_modules/
|
||||
.DS_Store
|
||||
.idea
|
||||
/package-lock.json
|
||||
/sandun-mobile.iml
|
||||
yarn.lock
|
||||
*.iml
|
||||
10
babel.config.js
Normal file
10
babel.config.js
Normal file
@@ -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
|
||||
}]
|
||||
]
|
||||
}
|
||||
57
build.js
Normal file
57
build.js
Normal file
@@ -0,0 +1,57 @@
|
||||
// 根据不同场景生成不同配置文件
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
function copyIt(from, to) {
|
||||
fs.writeFileSync(to, fs.readFileSync(from));
|
||||
}
|
||||
|
||||
|
||||
function copyDir(from, to) {
|
||||
fs.readdir(from, (err, files) => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
if (!fs.existsSync(to)) {
|
||||
fs.mkdirSync(to);
|
||||
} else {
|
||||
files.forEach((item, index) => {
|
||||
let itemPath = path.join(from, item);
|
||||
let tempFile = fs.statSync(itemPath);
|
||||
if (tempFile.isFile()) {
|
||||
copyIt(itemPath, path.join(to, item))
|
||||
} else {
|
||||
copyDir(itemPath, path.join(to, item));
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let argv = process.argv[2] || "vast-box";
|
||||
console.log('process.argv', argv);
|
||||
|
||||
// env配置文件
|
||||
let fromEnvPath = path.join(__dirname, 'build_config', argv, '.env');
|
||||
let toEnvPath = path.join(__dirname, '.env');
|
||||
// assets目录
|
||||
let fromConstantPath = path.join(__dirname, 'build_config', argv, 'assets');
|
||||
let toConstantPath = path.join(__dirname, 'src', 'assets');
|
||||
// 小程序可配置参数文件
|
||||
let fromConfigPath = path.join(__dirname, 'build_config', argv, 'config.js');
|
||||
let toConfigPath = path.join(__dirname, 'src', 'config', 'config.js');
|
||||
// 小程序工程配置
|
||||
let fromProjectPath = path.join(__dirname, 'build_config', argv, 'project.config.json');
|
||||
let toProjectPath = path.join(__dirname, 'project.config.json');
|
||||
|
||||
let copyArr = [[fromEnvPath, toEnvPath], [fromConstantPath, toConstantPath], [fromConfigPath, toConfigPath], [fromProjectPath, toProjectPath]];
|
||||
|
||||
//拷贝文件到对应目录下
|
||||
copyArr.map((item, idx) => {
|
||||
if (idx == 1) {
|
||||
copyDir(item[0], item[1])
|
||||
} else {
|
||||
copyIt(item[0], item[1])
|
||||
}
|
||||
});
|
||||
8
config/dev.js
Normal file
8
config/dev.js
Normal file
@@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
NODE_ENV: '"development"'
|
||||
},
|
||||
defineConstants: {},
|
||||
mini: {},
|
||||
h5: {}
|
||||
};
|
||||
73
config/index.js
Normal file
73
config/index.js
Normal file
@@ -0,0 +1,73 @@
|
||||
const config = {
|
||||
projectName: 'template-taro',
|
||||
date: '2021-5-21',
|
||||
designWidth: 750,
|
||||
deviceRatio: {
|
||||
640: 2.34 / 2,
|
||||
750: 1,
|
||||
828: 1.81 / 2
|
||||
},
|
||||
sourceRoot: 'src',
|
||||
outputRoot: 'dist',
|
||||
plugins: [],
|
||||
copy: {
|
||||
patterns: [],
|
||||
options: {}
|
||||
},
|
||||
alias: {
|
||||
"@": require('path').resolve(__dirname, "../", "src"),
|
||||
},
|
||||
framework: 'react',
|
||||
mini: {
|
||||
enableExtract: true,
|
||||
optimizeMainPackage: {
|
||||
enable: true,
|
||||
},
|
||||
miniCssExtractPluginOption: {
|
||||
ignoreOrder: true,
|
||||
},
|
||||
postcss: {
|
||||
pxtransform: {
|
||||
enable: true,
|
||||
config: {}
|
||||
},
|
||||
url: {
|
||||
enable: true,
|
||||
config: {
|
||||
limit: 1024 // 设定转换尺寸上限
|
||||
}
|
||||
},
|
||||
cssModules: {
|
||||
enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
|
||||
config: {
|
||||
namingPattern: 'module', // 转换模式,取值为 global/module
|
||||
generateScopedName: '[name]__[local]___[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
h5: {
|
||||
publicPath: '/',
|
||||
staticDirectory: 'static',
|
||||
postcss: {
|
||||
autoprefixer: {
|
||||
enable: true,
|
||||
config: {}
|
||||
},
|
||||
cssModules: {
|
||||
enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
|
||||
config: {
|
||||
namingPattern: 'module', // 转换模式,取值为 global/module
|
||||
generateScopedName: '[name]__[local]___[hash:base64:5]'
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function (merge) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return merge({}, config, require('./dev'))
|
||||
}
|
||||
return merge({}, config, require('./prod'))
|
||||
};
|
||||
17
config/prod.js
Normal file
17
config/prod.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
NODE_ENV: '"production"'
|
||||
},
|
||||
defineConstants: {},
|
||||
mini: {},
|
||||
h5: {
|
||||
/**
|
||||
* 如果h5端编译后体积过大,可以使用webpack-bundle-analyzer插件对打包体积进行分析。
|
||||
* 参考代码如下:
|
||||
* webpackChain (chain) {
|
||||
* chain.plugin('analyzer')
|
||||
* .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
|
||||
* }
|
||||
*/
|
||||
}
|
||||
};
|
||||
18
global.d.ts
vendored
Normal file
18
global.d.ts
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/// <reference path="node_modules/@tarojs/plugin-platform-weapp/types/shims-weapp.d.ts" />
|
||||
|
||||
declare module '*.png';
|
||||
declare module '*.gif';
|
||||
declare module '*.jpg';
|
||||
declare module '*.jpeg';
|
||||
declare module '*.svg';
|
||||
declare module '*.css';
|
||||
declare module '*.less';
|
||||
declare module '*.scss';
|
||||
declare module '*.sass';
|
||||
declare module '*.styl';
|
||||
|
||||
declare namespace NodeJS {
|
||||
interface ProcessEnv {
|
||||
TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd'
|
||||
}
|
||||
}
|
||||
12
jsconfig.json
Normal file
12
jsconfig.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
73
package.json
Normal file
73
package.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "taro-demo",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "",
|
||||
"templateInfo": {
|
||||
"name": "default",
|
||||
"typescript": true,
|
||||
"css": "less"
|
||||
},
|
||||
"scripts": {
|
||||
"build:weapp": "taro build --type weapp",
|
||||
"build:vastbox": "node build.js vast-box && taro build --type weapp",
|
||||
"build:xihu": "node build.js xihu && taro build --type weapp",
|
||||
"build:swan": "taro build --type swan",
|
||||
"build:alipay": "taro build --type alipay",
|
||||
"build:tt": "taro build --type tt",
|
||||
"build:h5": "taro build --type h5",
|
||||
"build:rn": "taro build --type rn",
|
||||
"build:qq": "taro build --type qq",
|
||||
"build:jd": "taro build --type jd",
|
||||
"build:quickapp": "taro build --type quickapp",
|
||||
"dev:weapp": "npm run build:weapp -- --watch",
|
||||
"dev:vastbox": "node build.js vast-box && npm run build:weapp -- --watch",
|
||||
"dev:xihu": "node build.js xihu && 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",
|
||||
"dev:weapp-pro": "NODE_ENV=production taro build --type weapp --watch"
|
||||
},
|
||||
"browserslist": [
|
||||
"last 3 versions",
|
||||
"Android >= 4.1",
|
||||
"ios >= 8"
|
||||
],
|
||||
"author": "",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.7",
|
||||
"@tarojs/components": "3.3.18",
|
||||
"@tarojs/react": "3.3.18",
|
||||
"@tarojs/runtime": "3.3.18",
|
||||
"@tarojs/taro": "3.3.18",
|
||||
"dayjs": "1.10.5",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"taro-poster-render": "^2.0.5",
|
||||
"taro-ui": "3.0.0-alpha.10",
|
||||
"three-platformize": "^1.133.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.8.0",
|
||||
"@tarojs/mini-runner": "3.3.18",
|
||||
"@tarojs/webpack-runner": "3.3.18",
|
||||
"@types/webpack-env": "^1.13.6",
|
||||
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
||||
"@typescript-eslint/parser": "^4.15.1",
|
||||
"babel-preset-taro": "3.3.18",
|
||||
"dayjs": "1.10.5",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-taro": "3.3.18",
|
||||
"eslint-plugin-import": "^2.12.0",
|
||||
"eslint-plugin-react": "^7.8.2",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"stylelint": "9.3.0",
|
||||
"typescript": "^4.1.0"
|
||||
}
|
||||
}
|
||||
14
project.config.json
Normal file
14
project.config.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"miniprogramRoot": "./dist",
|
||||
"projectname": "template-taro",
|
||||
"description": "",
|
||||
"appid": "xxxxxxxx",
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"es6": false,
|
||||
"postcss": false,
|
||||
"minified": false
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"checkSiteMap": false
|
||||
}
|
||||
53
src/app.config.js
Normal file
53
src/app.config.js
Normal file
@@ -0,0 +1,53 @@
|
||||
const config = require('./config/config');
|
||||
|
||||
export default {
|
||||
pages: [
|
||||
// tab切换
|
||||
"pages/tabs/home",
|
||||
"pages/tabs/mine",
|
||||
"pages/login/index",
|
||||
"pages/common/webview",
|
||||
|
||||
// home
|
||||
"pages/home/pay",
|
||||
"pages/home/payDetail",
|
||||
"pages/home/news/index",
|
||||
"pages/home/owner/index",
|
||||
|
||||
|
||||
// mine
|
||||
"pages/mine/set/index",
|
||||
"pages/mine/set/contact",
|
||||
"pages/mine/set/agreement",
|
||||
"pages/mine/order/index",
|
||||
"pages/mine/give/index",
|
||||
"pages/mine/receive",
|
||||
|
||||
],
|
||||
subpackages: [
|
||||
{
|
||||
root: "pages_goods/",
|
||||
pages: [
|
||||
// 藏品详情
|
||||
"goods/detail",
|
||||
]
|
||||
},
|
||||
],
|
||||
plugins: {},
|
||||
window: {
|
||||
backgroundColor: "#000506",
|
||||
backgroundTextStyle: 'light',
|
||||
navigationBarBackgroundColor: '#000506',
|
||||
navigationBarTextStyle: 'white',
|
||||
backgroundColorTop: "#000506",
|
||||
backgroundColorBottom: "#000506",
|
||||
...config.app.window,
|
||||
},
|
||||
tabBar: {
|
||||
custom: true,
|
||||
list: [
|
||||
{pagePath: "pages/tabs/home", text: "首页"},
|
||||
{pagePath: "pages/tabs/mine", text: "我的"}
|
||||
]
|
||||
}
|
||||
}
|
||||
42
src/app.js
Normal file
42
src/app.js
Normal file
@@ -0,0 +1,42 @@
|
||||
import {Component} from 'react'
|
||||
import './app.less'
|
||||
import 'taro-ui/dist/style/index.scss'
|
||||
import Taro from '@tarojs/taro';
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
|
||||
|
||||
class App extends Component {
|
||||
|
||||
componentDidMount() {
|
||||
const updateManager = Taro.getUpdateManager();
|
||||
updateManager.onCheckForUpdate(res => {
|
||||
console.log(res);
|
||||
});
|
||||
updateManager.onUpdateReady(() => {
|
||||
Taro.showModal({
|
||||
title: '更新提示', content: "新版本已经准备好,是否重启应用?",
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
updateManager.applyUpdate()
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
componentDidShow() {
|
||||
}
|
||||
|
||||
componentDidHide() {
|
||||
}
|
||||
|
||||
componentDidCatchError() {
|
||||
}
|
||||
|
||||
// this.props.children 是将要会渲染的页面
|
||||
render() {
|
||||
return this.props.children
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
66
src/app.less
Normal file
66
src/app.less
Normal file
@@ -0,0 +1,66 @@
|
||||
@import './assets/less/constant.less';
|
||||
|
||||
page {
|
||||
color: white;
|
||||
background-color: @bgColor;
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
.primaryColor {
|
||||
color: @primaryColor;
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40vh;
|
||||
font-size: 24px;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-image: linear-gradient(to right, rgba(#979797, .32) 0%, rgba(#979797, .32) 50%, transparent 0%);
|
||||
background-size: 20px 1px;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.globalPadding {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.primaryBtn {
|
||||
background: @primaryColor;
|
||||
color: white;
|
||||
font-size: 30px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
height: 84px;
|
||||
}
|
||||
|
||||
.at-modal__container {
|
||||
width: calc(100vw - 88px) !important;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.at-modal__overlay {
|
||||
background: rgba(0, 0, 0, 0.8) !important;
|
||||
}
|
||||
|
||||
.wx-swiper-dot {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
background: rgba(255, 255, 255, .3) !important;
|
||||
}
|
||||
|
||||
.wx-swiper-dot-active {
|
||||
.wx-swiper-dot;
|
||||
width: 36px !important;
|
||||
border-radius: 16px !important;
|
||||
background: linear-gradient(@primaryTopColor, @primaryColor) !important;
|
||||
}
|
||||
40
src/components/CustomTabBar/index.jsx
Normal file
40
src/components/CustomTabBar/index.jsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import React from "react";
|
||||
import less from './index.module.less';
|
||||
import Taro from "@tarojs/taro";
|
||||
import Flex from "@/components/Flex";
|
||||
import config from "@/config/config";
|
||||
import GcImage from "@/components/GcImage";
|
||||
|
||||
const CustomTabBar = ({tabIdx = 1}) => {
|
||||
|
||||
///////////////////////////////////////// 逻辑方法
|
||||
|
||||
/**
|
||||
* 切换tab
|
||||
* @param idx
|
||||
*/
|
||||
const switchTab = (idx) => {
|
||||
Taro.switchTab({url: config.app.tabbar.list[idx].url}).then(res => {
|
||||
|
||||
})
|
||||
};
|
||||
|
||||
///////////////////////////////////////// 页面渲染
|
||||
|
||||
return <Flex className={less.tabbar} style={{backgroundColor: config.app.tabbar?.bgColor || "blank"}}>
|
||||
{config.app.tabbar?.list?.map((item, idx) => {
|
||||
return <Flex
|
||||
direction={'column'} itemGrow={1} className={less.tab} key={item.id}
|
||||
justify={'center'} alignItems={'center'}
|
||||
onClick={() => switchTab(idx)}
|
||||
>
|
||||
<GcImage className={less.icn} src={tabIdx == item.id ? item.selectedIcon : item.icon}/>
|
||||
<Flex
|
||||
className={less.dot} style={{color: tabIdx == item.id ? item.selectedColor : item.color}}
|
||||
>{item.title}</Flex>
|
||||
</Flex>
|
||||
})}
|
||||
</Flex>
|
||||
};
|
||||
|
||||
export default CustomTabBar;
|
||||
31
src/components/CustomTabBar/index.module.less
Normal file
31
src/components/CustomTabBar/index.module.less
Normal file
@@ -0,0 +1,31 @@
|
||||
@import 'build_config/xihu/assets/less/constant.less';
|
||||
|
||||
.tabbar {
|
||||
width: 100vw;
|
||||
color: white;
|
||||
height: calc(130px + env(safe-area-inset-bottom));
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 100;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
|
||||
.tab {
|
||||
width: 0;
|
||||
padding: 24px;
|
||||
|
||||
.icn {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.dot {
|
||||
margin-top: 4px;
|
||||
border-radius: 10px;
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
17
src/components/EmptyView/index.jsx
Normal file
17
src/components/EmptyView/index.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from "react";
|
||||
import Flex from "@/components/Flex";
|
||||
import GcImage from "@/components/GcImage";
|
||||
import less from './index.module.less';
|
||||
|
||||
const EmptyView = ({type = "def", tips = "暂无记录"}) => {
|
||||
|
||||
let icnSrc = config.page.common.emptyObj[type] || config.page.common.emptyObj.def;
|
||||
|
||||
return <Flex direction={"column"} className={less.empty} alignItems={"center"}>
|
||||
<GcImage src={icnSrc} className={less.icn} mode={'aspectFit'}/>
|
||||
<Flex>{tips}</Flex>
|
||||
</Flex>
|
||||
|
||||
};
|
||||
|
||||
export default EmptyView;
|
||||
13
src/components/EmptyView/index.module.less
Normal file
13
src/components/EmptyView/index.module.less
Normal file
@@ -0,0 +1,13 @@
|
||||
.empty {
|
||||
width: 100%;
|
||||
margin: 136px 0;
|
||||
font-size: 28px;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
|
||||
.icn {
|
||||
width: 302px;
|
||||
height: 276px;
|
||||
margin: 0 auto 46px;
|
||||
}
|
||||
|
||||
}
|
||||
50
src/components/Flex/index.jsx
Normal file
50
src/components/Flex/index.jsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from "react";
|
||||
import {View} from "@tarojs/components";
|
||||
import less from './index.module.less';
|
||||
|
||||
|
||||
const Flex = ({
|
||||
direction, wrap, justify, alignItems, itemOrder, itemSelf, itemGrow,
|
||||
className, style, children, ...restProps
|
||||
}) => {
|
||||
|
||||
const newStyle = {...style};
|
||||
|
||||
if (direction) {
|
||||
newStyle['flexDirection'] = direction;
|
||||
newStyle['WebkitFlexDirection'] = direction;
|
||||
}
|
||||
if (wrap) {
|
||||
newStyle['flexWrap'] = wrap;
|
||||
newStyle['WebkitFlexWrap'] = wrap;
|
||||
}
|
||||
if (justify) {
|
||||
newStyle['justifyContent'] = justify;
|
||||
newStyle['WebkitJustifyContent'] = justify;
|
||||
}
|
||||
if (alignItems) {
|
||||
newStyle['alignItems'] = alignItems;
|
||||
newStyle['WebkitAlignItems'] = alignItems;
|
||||
}
|
||||
if (itemSelf) {
|
||||
newStyle['alignSelf'] = itemSelf;
|
||||
newStyle['WebkitAlignSelf'] = itemSelf;
|
||||
}
|
||||
if (itemOrder) {
|
||||
newStyle['order'] = itemOrder;
|
||||
}
|
||||
if (itemGrow) {
|
||||
newStyle['flexGrow'] = itemGrow;
|
||||
newStyle['WebkitFlexGrow'] = itemGrow;
|
||||
}
|
||||
|
||||
///////////////////////////////////////// 页面渲染
|
||||
|
||||
return <View
|
||||
className={less.flex + " " + className} style={newStyle}
|
||||
{...restProps}
|
||||
>{children}</View>
|
||||
|
||||
};
|
||||
|
||||
export default Flex
|
||||
7
src/components/Flex/index.module.less
Normal file
7
src/components/Flex/index.module.less
Normal file
@@ -0,0 +1,7 @@
|
||||
.flex {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
}
|
||||
37
src/components/GcImage/index.jsx
Normal file
37
src/components/GcImage/index.jsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from "react";
|
||||
import Taro from '@tarojs/taro';
|
||||
import Common from "@/utils/Common";
|
||||
import {Image, View} from "@tarojs/components";
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
|
||||
|
||||
const GcImage = ({src, preview, empty = true, className, mode, onClick, children}) => {
|
||||
|
||||
const httpSrc = HttpUtils.getImageUrl(src);
|
||||
|
||||
///////////////////////////////////////// 逻辑方法
|
||||
|
||||
const onImgClick = (e) => {
|
||||
if (!preview) {
|
||||
onClick && onClick();
|
||||
return
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
Taro.previewImage({
|
||||
urls: [httpSrc], current: httpSrc
|
||||
})
|
||||
};
|
||||
|
||||
if (Common.isEmpty(src)) {
|
||||
return <View className={empty ? null : className}/>
|
||||
}
|
||||
|
||||
return <Image
|
||||
src={httpSrc} className={className} mode={mode || "aspectFill"}
|
||||
onClick={onImgClick}
|
||||
>{children}</Image>
|
||||
|
||||
};
|
||||
|
||||
export default GcImage;
|
||||
30
src/components/GcRichText/index.jsx
Normal file
30
src/components/GcRichText/index.jsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import React from "react";
|
||||
import Taro from '@tarojs/taro';
|
||||
import less from './index.module.less';
|
||||
import '@tarojs/taro/html.css'
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
import {View} from "@tarojs/components";
|
||||
|
||||
|
||||
Taro.options.html.transformElement = (el) => {
|
||||
|
||||
if (el.nodeName === "image") {
|
||||
const path = HttpUtils.imageUrl(el.props.src);
|
||||
el.setAttribute("src", path);
|
||||
el.setAttribute("mode", "widthFix");
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
|
||||
const GcRichText = ({html = "", className, style, ...restProps}) => {
|
||||
|
||||
///////////////////////////////////////// 逻辑方法
|
||||
|
||||
return <View className={less.rich + " " + className} style={style} {...restProps}>
|
||||
<View className="taro_html" dangerouslySetInnerHTML={{__html: html}}/>
|
||||
</View>
|
||||
};
|
||||
|
||||
export default GcRichText;
|
||||
11
src/components/GcRichText/index.module.less
Normal file
11
src/components/GcRichText/index.module.less
Normal file
@@ -0,0 +1,11 @@
|
||||
.rich {
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
|
||||
img, image {
|
||||
width: 100% !important;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
}
|
||||
20
src/components/PageContainer/index.js
Normal file
20
src/components/PageContainer/index.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from "react";
|
||||
import Flex from "@/components/Flex";
|
||||
import config from "@/config/config";
|
||||
import Common from "@/utils/Common";
|
||||
|
||||
/**
|
||||
* 页面
|
||||
* @constructor
|
||||
*/
|
||||
const PageContainer = ({bgUrlColor, children, ...restProps}) => {
|
||||
|
||||
return <Flex
|
||||
direction={'column'} style={Common.bgUrlColor(bgUrlColor || config?.page?.common?.bgUrlColor)}
|
||||
{...restProps}
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
};
|
||||
|
||||
export default PageContainer;
|
||||
21
src/config/config.js
Normal file
21
src/config/config.js
Normal file
@@ -0,0 +1,21 @@
|
||||
const home = {
|
||||
bgUrl: ''
|
||||
};
|
||||
|
||||
const http = {
|
||||
develop: {
|
||||
serverUrl: "https://vast-box-api-test.tmp.vastchain.ltd",
|
||||
imageUrl: "https://vast-box-api-test.tmp.vastchain.ltd",
|
||||
cdnUrl: "",
|
||||
},
|
||||
release: {
|
||||
serverUrl: "https://vast-box-api.app.vastchain.ltd",
|
||||
imageUrl: "https://vast-box-api.app.vastchain.ltd",
|
||||
cdnUrl: "https://vast-box-cdn.vastchain.cn",
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
http,
|
||||
home,
|
||||
};
|
||||
209
src/config/config_test.js
Normal file
209
src/config/config_test.js
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* app相关配置
|
||||
* @param terminalId 小程序id
|
||||
* @param deptId 服务商id
|
||||
* @type {{}}
|
||||
*/
|
||||
const app = {
|
||||
terminalId: "1480731682234568704",
|
||||
deptId: "101",
|
||||
appName: "西湖一号数字藏品平台",
|
||||
appLogo: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/app_logo.png",
|
||||
copyright: "元镜联盟链提供技术支持",
|
||||
|
||||
|
||||
/**
|
||||
* 窗口设置
|
||||
*/
|
||||
window: {
|
||||
backgroundColor: "#0B1426",
|
||||
navigationBarBackgroundColor: "#0B1426",
|
||||
backgroundColorTop: "#0B1426",
|
||||
backgroundColorBottom: "#0B1426",
|
||||
},
|
||||
|
||||
/**
|
||||
* tabbar配置
|
||||
*/
|
||||
tabbar: {
|
||||
bgColor: "#171A20",
|
||||
list: [
|
||||
{
|
||||
id: 1, title: "首页",
|
||||
color: "#999999", selectedColor: "white", url: "/pages/tabs/home",
|
||||
icon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/tab_index_gray.png",
|
||||
selectedIcon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/tab_index_active.png"
|
||||
},
|
||||
{
|
||||
id: 2, title: "我的",
|
||||
color: "#999999", selectedColor: "white", url: "/pages/tabs/mine",
|
||||
icon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/tab_mine_gray.png",
|
||||
selectedIcon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/tab_mine_active.png"
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 网络请求配置
|
||||
* @param serverUrl API地址
|
||||
* @param imageUrl 图片地址。如果没有,则使用serverUrl
|
||||
* @param cdnUrl cdn地址。如果没有,则使用imageUrl
|
||||
*/
|
||||
const http = {
|
||||
develop: {
|
||||
serverUrl: "https://saas-server-api-test.tmp.vastchain.ltd",
|
||||
imageUrl: "https://saas-server-api-test.tmp.vastchain.ltd",
|
||||
cdnUrl: "",
|
||||
},
|
||||
trial: {
|
||||
serverUrl: "https://saas-server-api-test.tmp.vastchain.ltd",
|
||||
imageUrl: "https://saas-server-api-test.tmp.vastchain.ltd",
|
||||
cdnUrl: "",
|
||||
},
|
||||
release: {
|
||||
serverUrl: "https://saas-server-api-test.tmp.vastchain.ltd",
|
||||
imageUrl: "https://saas-server-api-test.tmp.vastchain.ltd",
|
||||
cdnUrl: "",
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 页面相关配置
|
||||
* @type {{home: {bgurl: string}}}
|
||||
*/
|
||||
const page = {
|
||||
common: {
|
||||
bgUrlColor: 'https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/common_bg.png',
|
||||
defaultAvatar: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/avatar_default.png",
|
||||
emptyObj: {
|
||||
def: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/empty_box.png",
|
||||
mine: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/empty_box_mine.png",
|
||||
},
|
||||
arrowLeft: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/white_arrow.png",
|
||||
copyright: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/copyright.png",
|
||||
shareIcon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/share_btn.png",
|
||||
addressIcon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/order_address.png",
|
||||
},
|
||||
|
||||
/**
|
||||
* 首页配置
|
||||
*/
|
||||
home: {
|
||||
bgUrlColor: '#0B1426'
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 我的页面
|
||||
*/
|
||||
mine: {
|
||||
menu: {
|
||||
bgUrlColor: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/setting_menu_bg.png",
|
||||
data: [
|
||||
{
|
||||
id: '1', name: '领取', url: '/pages/mine/receive', login: true,
|
||||
img: 'https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/mine_receive.png'
|
||||
},
|
||||
{
|
||||
id: '2', name: '我的订单', url: "/pages/mine/order/index", login: true,
|
||||
img: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/mine_order.png"
|
||||
},
|
||||
{
|
||||
id: '3', name: '转赠列表', url: '/pages/mine/give/index', login: true,
|
||||
img: 'https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/mine_zz.png'
|
||||
},
|
||||
{
|
||||
id: '4', name: '设置', url: '/pages/mine/set/index', login: false,
|
||||
img: 'https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/mine_set.png'
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
|
||||
setting: {
|
||||
menu: [
|
||||
{
|
||||
id: 1, title: "用户协议", go: "/pages/mine/set/agreement", customStyle: {background: '#212838'},
|
||||
icon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/mine_user.png"
|
||||
},
|
||||
{
|
||||
id: 2, title: "关于我们", go: "/pages/mine/set/contact", customStyle: {background: "#212838"},
|
||||
icon: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/white_circle_question.png",
|
||||
content: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/about_us.png",
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
goods: {
|
||||
titleUrl: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/goods_detail_title.png",
|
||||
lamplightUrl: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/goods_detail_lamplight.png",
|
||||
bgUrlColor: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/goods_detail_bg.png",
|
||||
|
||||
detail: {
|
||||
author: {
|
||||
customStyle: {
|
||||
color: "#F0DCC0",
|
||||
backgroundColor: "#212838",
|
||||
}
|
||||
},
|
||||
owner: {
|
||||
customStyle: {
|
||||
backgroundColor: "#212838",
|
||||
}
|
||||
},
|
||||
cpbq: {
|
||||
titleUrl: "",
|
||||
customStyle: {
|
||||
color: "white",
|
||||
backgroundColor: "#212838",
|
||||
}
|
||||
},
|
||||
cpjs: {
|
||||
titleUrl: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/goods_introduction.png",
|
||||
customStyle: {
|
||||
color: "#F0DCC0",
|
||||
backgroundColor: "#212838",
|
||||
}
|
||||
},
|
||||
cpxj: {
|
||||
titleUrl: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/goods_detail.png",
|
||||
customStyle: {
|
||||
color: "#F0DCC0",
|
||||
backgroundColor: "#212838",
|
||||
}
|
||||
},
|
||||
gmxz: {
|
||||
titleUrl: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/goods_detail_purchase.png",
|
||||
customStyle: {
|
||||
color: "#F0DCC0",
|
||||
backgroundColor: "#212838",
|
||||
}
|
||||
}
|
||||
},
|
||||
share: {
|
||||
bg: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/share_bg.png",
|
||||
qrcode: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/share_qrcode.png",
|
||||
shadow: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/share_shadow.png",
|
||||
hashColor: "#717983",
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 领取页面
|
||||
*/
|
||||
receive: {
|
||||
bgUrlColor: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/receive_bg.png",
|
||||
receiveTitle: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/receive_digital_collection.png",
|
||||
holder: "https://static-test.tmp.vastchain.ltd/saas-front-admin/static/mini/receive_holder.png",
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
app,
|
||||
http,
|
||||
page
|
||||
};
|
||||
141
src/https/HttpUtils.js
Normal file
141
src/https/HttpUtils.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import Taro from '@tarojs/taro';
|
||||
|
||||
/**
|
||||
* 请求地址
|
||||
* @type {{}}
|
||||
*/
|
||||
const RequestUrl = {
|
||||
|
||||
// 开发版
|
||||
"develop": {
|
||||
serverUrl: "https://xxxx",
|
||||
mini: "https://xxxx",
|
||||
imageUrl: "https://xxxx",
|
||||
},
|
||||
|
||||
// 体验版
|
||||
"trial": {
|
||||
serverUrl: "https://xxxx",
|
||||
mini: "https://xxxx",
|
||||
imageUrl: "https://xxxx",
|
||||
},
|
||||
|
||||
// 正式版
|
||||
"release": {
|
||||
serverUrl: "https://xxxx",
|
||||
mini: "https://xxxx",
|
||||
imageUrl: "https://xxxx",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 获取小程序的运行环境
|
||||
*/
|
||||
const getMiniEnv = () => {
|
||||
if (!Taro.canIUse("getAccountInfoSync")) {
|
||||
return "release";
|
||||
}
|
||||
return Taro.getAccountInfoSync().miniProgram.envVersion;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取API地址
|
||||
* 正式环境时使用正式地址,其他环境使用测试地址
|
||||
*/
|
||||
const getServerUrl = () => {
|
||||
return RequestUrl[getMiniEnv()].serverUrl;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 发起网络请求
|
||||
* @param url
|
||||
* @param method
|
||||
* @param options
|
||||
*/
|
||||
const request = (url, method, options) => {
|
||||
options.header = {
|
||||
...options.header, token: Taro.getStorageSync("token"),
|
||||
};
|
||||
return Taro.request({
|
||||
url: joinUrl(url), method, ...options, success: (res => {
|
||||
if (res.data.code === 401) {
|
||||
Taro.removeStorageSync('token');
|
||||
Taro.switchTab({url: "/pages/index/index"})
|
||||
}
|
||||
})
|
||||
}).then(res => res.data)
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 加入url
|
||||
* @param path
|
||||
*/
|
||||
const joinUrl = (path) => {
|
||||
if (path?.startsWith("http")) {
|
||||
return path;
|
||||
}
|
||||
return getServerUrl() + path;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 图片地址构造
|
||||
* @param path
|
||||
* @return {string|*}
|
||||
*/
|
||||
const getImageUrl = (path) => {
|
||||
if (path?.startsWith("http")) {
|
||||
return path;
|
||||
}
|
||||
if (path?.startsWith("data:")) {
|
||||
return path;
|
||||
}
|
||||
if (path?.startsWith("mini://")) {
|
||||
return RequestUrl[getMiniEnv()].mini + path.substr(6)
|
||||
}
|
||||
return joinUrl(path);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 提示返回信息
|
||||
* @param res
|
||||
*/
|
||||
const showRespError = (res = {}) => {
|
||||
if (res.code != 200) {
|
||||
Taro.showToast({title: res.msg, icon: 'none'})
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
request,
|
||||
joinUrl,
|
||||
getImageUrl,
|
||||
showRespError,
|
||||
|
||||
/**
|
||||
* 发起get请求
|
||||
* @param url
|
||||
* @param data
|
||||
* @param options
|
||||
* @return {*}
|
||||
*/
|
||||
get: (url, data, options) => {
|
||||
return request(url, "GET", {data, ...options})
|
||||
},
|
||||
|
||||
/**
|
||||
* 发起post请求
|
||||
* @param url
|
||||
* @param data
|
||||
* @param options
|
||||
* @return {*}
|
||||
*/
|
||||
post: (url, data, options) => {
|
||||
return request(url, "POST", {data, ...options})
|
||||
},
|
||||
|
||||
}
|
||||
19
src/index.html
Normal file
19
src/index.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-touch-fullscreen" content="yes">
|
||||
<meta name="format-detection" content="telephone=no,address=no">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="white">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
|
||||
<title></title>
|
||||
<script>
|
||||
!function(x){function w(){var v,u,t,tes,s=x.document,r=s.documentElement,a=r.getBoundingClientRect().width;if(!v&&!u){var n=!!x.navigator.appVersion.match(/AppleWebKit.*Mobile.*/);v=x.devicePixelRatio;tes=x.devicePixelRatio;v=n?v:1,u=1/v}if(a>=640){r.style.fontSize="40px"}else{if(a<=320){r.style.fontSize="20px"}else{r.style.fontSize=a/320*20+"px"}}}x.addEventListener("resize",function(){w()});w()}(window);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
6
src/pages/tabs/home.config.js
Normal file
6
src/pages/tabs/home.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
navigationBarTitleText: '',
|
||||
enablePullDownRefresh: true,
|
||||
enableShareAppMessage: true,
|
||||
navigationStyle: "custom",
|
||||
}
|
||||
110
src/pages/tabs/home.js
Normal file
110
src/pages/tabs/home.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import React, {useEffect, useState} from "react";
|
||||
import Flex from "@/components/Flex";
|
||||
import {Swiper, SwiperItem} from "@tarojs/components";
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
import GcImage from "@/components/GcImage";
|
||||
import less from './home.module.less';
|
||||
import Taro, {usePullDownRefresh, useReachBottom} from '@tarojs/taro'
|
||||
import RouteGo from "@/route/RouteGo";
|
||||
import CustomTabBar from "@/components/CustomTabBar";
|
||||
import PageContainer from "@/components/PageContainer";
|
||||
|
||||
export default () => {
|
||||
|
||||
const [bannerList, setBannerList] = useState([]);
|
||||
const [pageNo, setPageNo] = useState(1);
|
||||
const [pageSize] = useState(100);
|
||||
const [lastTotal, setLastTotal] = useState(0);
|
||||
const [goodsList, setGoodsList] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
getBannerList();
|
||||
}, [1]);
|
||||
|
||||
useEffect(() => {
|
||||
getGoodsList();
|
||||
}, [pageNo]);
|
||||
|
||||
usePullDownRefresh(() => {
|
||||
getBannerList();
|
||||
|
||||
if (pageNo == 1) {
|
||||
getGoodsList();
|
||||
} else {
|
||||
setPageNo(1);
|
||||
}
|
||||
});
|
||||
|
||||
useReachBottom(() => {
|
||||
if (lastTotal >= pageSize) {
|
||||
setPageNo(pageNo + 1);
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////////////////////// 逻辑方法
|
||||
|
||||
/**
|
||||
* 轮播图
|
||||
*/
|
||||
const getBannerList = () => {
|
||||
HttpUtils.get("/customer/news_body/list").then(res => {
|
||||
if (res.code == 200) {
|
||||
let tempDates = res.rows;
|
||||
if (tempDates.length == 1) {
|
||||
tempDates = tempDates.concat(tempDates).concat(tempDates);
|
||||
} else if (tempDates.length == 2) {
|
||||
tempDates = tempDates.concat(tempDates);
|
||||
}
|
||||
setBannerList(tempDates);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
const getGoodsList = () => {
|
||||
HttpUtils.get("/customer/release/item/list", {pageSize, pageNum: pageNo}).then(res => {
|
||||
if (res.code == 200) {
|
||||
if (pageNo == 1) {
|
||||
setGoodsList(res.rows);
|
||||
} else {
|
||||
setGoodsList([...goodsList].concat(res.rows));
|
||||
}
|
||||
}
|
||||
setLastTotal(res.total);
|
||||
setLoading(false);
|
||||
Taro.stopPullDownRefresh();
|
||||
})
|
||||
};
|
||||
|
||||
///////////////////////////////////////// 页面渲染
|
||||
|
||||
if (loading) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return <PageContainer className={less.home}>
|
||||
|
||||
<Flex direction={'column'} className={less.content}>
|
||||
<Swiper
|
||||
className={less.swiper} circular nextMargin={'192rpx'} snapToEdge={true}
|
||||
indicatorDots={true} indicatorColor={'#FFFFFF'}
|
||||
autoplay={true}
|
||||
>
|
||||
{bannerList.map(item => {
|
||||
return <SwiperItem key={item.id}>
|
||||
<GcImage
|
||||
className={less.banner} alt={''} src={item.img}
|
||||
onClick={() => RouteGo.byBanner(item)}/>
|
||||
</SwiperItem>
|
||||
})}
|
||||
</Swiper>
|
||||
|
||||
</Flex>
|
||||
|
||||
<CustomTabBar tabIdx={1}/>
|
||||
|
||||
</PageContainer>
|
||||
|
||||
}
|
||||
|
||||
|
||||
25
src/pages/tabs/home.module.less
Normal file
25
src/pages/tabs/home.module.less
Normal file
@@ -0,0 +1,25 @@
|
||||
.home {
|
||||
width: 100vw;
|
||||
background-size: 101% 100%;
|
||||
background-repeat: no-repeat;
|
||||
padding-bottom: calc(130px + env(safe-area-inset-bottom));
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
|
||||
.swiper {
|
||||
height: 426px;
|
||||
|
||||
.banner {
|
||||
width: calc(100% - 56px);
|
||||
margin: 12px 0 0 56px;
|
||||
border-radius: 12px;
|
||||
height: 356px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
5
src/pages/tabs/mine.config.js
Normal file
5
src/pages/tabs/mine.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
navigationBarTitleText: '我的',
|
||||
enablePullDownRefresh: true,
|
||||
enableShareAppMessage: true,
|
||||
}
|
||||
131
src/pages/tabs/mine.js
Normal file
131
src/pages/tabs/mine.js
Normal file
@@ -0,0 +1,131 @@
|
||||
import React, {useRef, useState} from "react";
|
||||
import Flex from "@/components/Flex";
|
||||
import {Text, View} from "@tarojs/components";
|
||||
import less from "./mine.module.less";
|
||||
import Taro, {usePullDownRefresh, useShareAppMessage, useDidShow} from "@tarojs/taro";
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
import GcImage from "@/components/GcImage";
|
||||
import RouteGo from "@/route/RouteGo";
|
||||
import EmptyView from "@/components/EmptyView";
|
||||
import Common from "@/utils/Common";
|
||||
import config from "@/config/config";
|
||||
import CustomTabBar from "@/components/CustomTabBar";
|
||||
|
||||
export default () => {
|
||||
|
||||
const headRef = useRef();
|
||||
const [itemType] = useState("C");
|
||||
const [myGoods, setMyGoods] = useState([]);
|
||||
|
||||
useDidShow(() => {
|
||||
getCollectList();
|
||||
headRef?.current?.getUserInfo();
|
||||
// EventManager.order.addOrderChange("mine", getCollectList);
|
||||
// EventManager.login.addLoginChange("mine", () => {
|
||||
// headRef?.current?.getUserInfo();
|
||||
// getCollectList();
|
||||
// });
|
||||
});
|
||||
|
||||
usePullDownRefresh(() => {
|
||||
getCollectList();
|
||||
});
|
||||
|
||||
useShareAppMessage(() => {
|
||||
let shareMessage = config.page.common.shareMessage;
|
||||
return {
|
||||
...shareMessage, imageUrl: HttpUtils.imageUrl(shareMessage.imageUrl)
|
||||
};
|
||||
});
|
||||
|
||||
///////////////////////////////////////// 逻辑方法
|
||||
|
||||
/**
|
||||
* 获取自己获得的藏品
|
||||
*/
|
||||
const getCollectList = () => {
|
||||
HttpUtils.get("/customer/self/item/list", {itemType}).then(res => {
|
||||
if (res.code == 200) {
|
||||
setMyGoods(res.rows);
|
||||
}
|
||||
Taro.stopPullDownRefresh();
|
||||
})
|
||||
};
|
||||
|
||||
///////////////////////////////////////// 页面渲染
|
||||
|
||||
/**
|
||||
* 菜单
|
||||
*/
|
||||
const Menu = () => {
|
||||
return <Flex className={less.frame} style={Common.bgUrlColor(config?.page?.mine?.menu?.bgUrlColor)}>
|
||||
{config.page.mine?.menu.data?.map((item) => {
|
||||
return <Flex
|
||||
key={item.id} direction={'column'} className={less.menuItem}
|
||||
justify={'center'} alignItems={'center'}
|
||||
onClick={() => {
|
||||
if (!item.login) {
|
||||
Taro.navigateTo({url: item.url})
|
||||
} else {
|
||||
RouteGo.checkLogin().then(res => {
|
||||
Taro.navigateTo({url: item.url})
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
<GcImage src={item.img} mode={'aspectFit'}/>
|
||||
<View>{item.name}</View>
|
||||
</Flex>
|
||||
})}
|
||||
</Flex>
|
||||
};
|
||||
|
||||
/**
|
||||
* 藏品
|
||||
*/
|
||||
const renderGoods = () => {
|
||||
|
||||
return <Flex direction={"column"} className={less.collection}>
|
||||
|
||||
<Flex justify={'flex-start'} className={less.title}>
|
||||
<Flex className={less.title}>我的数字藏品 (<Text>{myGoods.length}</Text>)</Flex>
|
||||
</Flex>
|
||||
|
||||
{(myGoods.length == 0 ? <EmptyView type={'mine'} tips={'暂无藏品'}/> :
|
||||
<Flex wrap={'wrap'}>
|
||||
{myGoods.map((item) => {
|
||||
return <Flex
|
||||
key={item.id} className={less.myItem} direction={'column'}
|
||||
onClick={() => RouteGo.goodsDetail(item.objectType.id, itemType, item.id)}
|
||||
>
|
||||
|
||||
<GcImage src={item.objectType.img} className={less.picture} mode={'aspectFill'}/>
|
||||
<Flex className={less.picture_detail} direction={'column'}>
|
||||
<Text className={less.name}>{item.objectType.name}</Text>
|
||||
|
||||
<Flex className={less.tags} wrap={'wrap'}>
|
||||
{item.objectType.itemTags?.map(stringValue => {
|
||||
return <Text className={less.tagsItem}>{stringValue}</Text>
|
||||
})}
|
||||
</Flex>
|
||||
|
||||
</Flex>
|
||||
</Flex>
|
||||
})}
|
||||
</Flex>
|
||||
)}
|
||||
|
||||
</Flex>;
|
||||
};
|
||||
|
||||
return <Flex direction={'column'} className={less.mine}>
|
||||
|
||||
<Flex direction={'column'} className={less.content}>
|
||||
<Menu/>
|
||||
{renderGoods()}
|
||||
</Flex>
|
||||
|
||||
<CustomTabBar tabIdx={2}/>
|
||||
|
||||
</Flex>
|
||||
}
|
||||
153
src/pages/tabs/mine.module.less
Normal file
153
src/pages/tabs/mine.module.less
Normal file
@@ -0,0 +1,153 @@
|
||||
@import "src/assets/less/constant.less";
|
||||
|
||||
.mine {
|
||||
width: 100vw;
|
||||
padding-bottom: calc(130px + env(safe-area-inset-bottom));
|
||||
|
||||
.content {
|
||||
margin-bottom: 20px;
|
||||
|
||||
.frame {
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
flex-direction: row;
|
||||
width: calc(100% - 92px);
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
margin: 0 46px 46px;
|
||||
font-size: 24px;
|
||||
line-height: 34px;
|
||||
color: #FFFFFF;
|
||||
padding: 48px 0;
|
||||
border-radius: 24px;
|
||||
|
||||
.menuItem {
|
||||
|
||||
image {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.collection {
|
||||
width: calc(100% - 70px);
|
||||
margin: 0 35px;
|
||||
|
||||
.title {
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
margin: 0 11px;
|
||||
|
||||
text {
|
||||
color: @mineGoodsNumColor;
|
||||
}
|
||||
}
|
||||
|
||||
.lingqu {
|
||||
width: 100%;
|
||||
margin: 136px 0;
|
||||
|
||||
button {
|
||||
background: #2A49C8;
|
||||
padding: 0 36px;
|
||||
border-radius: 24px;
|
||||
color: white;
|
||||
height: 74px;
|
||||
line-height: 74px;
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
.myItem {
|
||||
width: calc((100% - 44px) / 2);
|
||||
margin: 22px 11px 0;
|
||||
position: relative;
|
||||
background: @goodsBg;
|
||||
border-radius: 46px;
|
||||
|
||||
.picture {
|
||||
width: 100%;
|
||||
height: 380px;
|
||||
border-radius: 46px;
|
||||
}
|
||||
|
||||
.picture_detail {
|
||||
margin: 0 12px 12px;
|
||||
width: calc(100% - 24px);
|
||||
border-radius: 46px;
|
||||
padding: 24px 12px;
|
||||
|
||||
.name {
|
||||
font-weight: 600;
|
||||
color: #FFFFFF;
|
||||
font-size: 32px;
|
||||
margin-bottom: 6px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tags {
|
||||
margin-top: 12px;
|
||||
|
||||
.tagsItem {
|
||||
background-color: @goodsTagBg;
|
||||
padding: 4px 12px;
|
||||
font-size: 20px;
|
||||
color: @goodsTagColor;
|
||||
border-radius: 32px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.limited_box {
|
||||
margin-top: 16px;
|
||||
|
||||
.limited {
|
||||
display: flex;
|
||||
background: #FFF72F;
|
||||
border-radius: 24px 0 0 24px;
|
||||
position: relative;
|
||||
width: 81px;
|
||||
height: 36px;
|
||||
margin-right: 71px;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
color: #000506;
|
||||
line-height: 32px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.number {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #2C55FF;
|
||||
border-radius: 24px;
|
||||
position: absolute;
|
||||
width: 86px;
|
||||
height: 36px;
|
||||
font-size: 22px;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
82
src/route/RouteGo.js
Normal file
82
src/route/RouteGo.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import Taro from "@tarojs/taro";
|
||||
import Common from "@/utils/Common";
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
|
||||
|
||||
/**
|
||||
* 藏品详情
|
||||
* @param id
|
||||
* @param itemType id类型
|
||||
* @param drawId 领取记录id
|
||||
* @param nfcCode 往领取页面
|
||||
*/
|
||||
const goodsDetail = (id, itemType, drawId = "", nfcCode = "",) => {
|
||||
let params = {id, itemType, drawId, nfcCode};
|
||||
Taro.navigateTo({
|
||||
url: "/pages_goods/goods/detail?" + Object.keys(params).map(it => `${it}=${params[it]}`).join("&"),
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 跳转到webview打开
|
||||
*/
|
||||
const goWebView = (httpUrl) => {
|
||||
httpUrl = HttpUtils.joinUrl(httpUrl);
|
||||
// 检查一下是否需要token
|
||||
if (httpUrl.indexOf("TOKEN") != -1) {
|
||||
checkLogin().then(tokenVal => {
|
||||
httpUrl = httpUrl.replace("TOKEN", tokenVal);
|
||||
Taro.navigateTo({url: "/pages/common/webview?src=" + encodeURIComponent(httpUrl)});
|
||||
});
|
||||
} else {
|
||||
Taro.navigateTo({url: "/pages/common/webview?src=" + encodeURIComponent(httpUrl)});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 检查等
|
||||
* @return {Promise<unknown>}
|
||||
*/
|
||||
const checkLogin = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let phoneVal = Taro.getStorageSync("phone");
|
||||
if (Common.isEmpty(phoneVal)) {
|
||||
Taro.navigateTo({url: "/pages/login/index"});
|
||||
reject();
|
||||
} else {
|
||||
resolve(Taro.getStorageSync("token"));
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* 返回
|
||||
*/
|
||||
const goBack = (delta = -1) => {
|
||||
Taro.navigateBack({delta})
|
||||
};
|
||||
|
||||
/**
|
||||
* 路由之间的跳转
|
||||
*/
|
||||
export default {
|
||||
goodsDetail,
|
||||
goWebView,
|
||||
checkLogin,
|
||||
goBack,
|
||||
|
||||
/**
|
||||
* 通过banner跳转
|
||||
* @param banner
|
||||
*/
|
||||
byBanner: (banner) => {
|
||||
if (!Common.isEmpty(banner.link)) {
|
||||
Taro.navigateTo({url: "/pages/common/webview?src=" + encodeURIComponent(banner.link)});
|
||||
} else {
|
||||
Taro.navigateTo({url: "/pages/home/news/index?id=" + banner.id});
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
53
src/utils/Common.js
Normal file
53
src/utils/Common.js
Normal file
@@ -0,0 +1,53 @@
|
||||
import HttpUtils from "@/https/HttpUtils";
|
||||
|
||||
/**
|
||||
* 是否为空
|
||||
* @param value
|
||||
* @return {boolean}
|
||||
*/
|
||||
const isEmpty = (value) => {
|
||||
return value === '' || value === undefined || value === null;
|
||||
};
|
||||
|
||||
/**
|
||||
* 计算平均配速
|
||||
* @param km
|
||||
* @param hour
|
||||
* @param minutes
|
||||
* @param seconds
|
||||
*/
|
||||
const getRunAvg = (km = 1, hour = 0, minutes = 0, seconds = 0) => {
|
||||
let allSeconds = hour * 60 * 60 + minutes * 60 + seconds;
|
||||
let kmSeconds = allSeconds / km;
|
||||
return (kmSeconds / 60).toFixed(0) + "'" + (kmSeconds % 60).toFixed(0) + "''";
|
||||
};
|
||||
|
||||
/**
|
||||
* 讲¥分转换为¥元
|
||||
*/
|
||||
const handlePrice = (yuan = 0) => {
|
||||
const rlt = Number(yuan).toFixed(2);
|
||||
if (!isEmpty(rlt)) {
|
||||
return rlt;
|
||||
} else {
|
||||
return '未有价格';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理urlColor
|
||||
*/
|
||||
const bgUrlColor = (val = "") => {
|
||||
if (val.startsWith("#")) {
|
||||
return {backgroundColor: val};
|
||||
}
|
||||
return {
|
||||
backgroundImage: "url('" + HttpUtils.imageUrl(val) + "')",
|
||||
backgroundRepeat: "no-repeat", backgroundSize: "100%"
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export default {
|
||||
isEmpty, getRunAvg, handlePrice, bgUrlColor
|
||||
}
|
||||
12
webpack.config.js
Normal file
12
webpack.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 不是真实的 webpack 配置,仅为兼容 webstorm 和 intellij idea 代码跳转
|
||||
* ref: https://github.com/umijs/umi/issues/1109#issuecomment-423380125
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': require('path').resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user