diff --git a/ejsRender.config.js b/ejsRender.config.js index 1244aa8..23310fc 100644 --- a/ejsRender.config.js +++ b/ejsRender.config.js @@ -3,6 +3,7 @@ const path = require('path'); const ROOT = path.join(__dirname, './'); const ejsData = { + appType: 'miniapp', targets: ['web'], miniappType: 'runtime', mpa: false, @@ -30,5 +31,6 @@ module.exports = { { target: path.join(ROOT, 'scaffolds/app-ts/'), name: 'app-ts', data: ejsData, preview: previewData }, { target: path.join(ROOT, 'scaffolds/app-midway-faas/'), name: 'app-midway-faas', data: ejsData, preview: previewData }, { target: path.join(ROOT, 'scaffolds/app-midway-faas/'), name: 'app-midway-ssr', data: ejsData, preview: previewData }, + { target: path.join(ROOT, 'scaffolds/app-shop/'), name: 'app-shop', data: ejsData, preview: previewData }, ], }; diff --git a/scaffolds/app-shop/.vscode/extensions.json b/scaffolds/app-shop/.vscode/extensions.json new file mode 100644 index 0000000..08ecef5 --- /dev/null +++ b/scaffolds/app-shop/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["iceworks-team.iceworks"] +} diff --git a/scaffolds/app-shop/README.md b/scaffolds/app-shop/README.md new file mode 100644 index 0000000..8d9945a --- /dev/null +++ b/scaffolds/app-shop/README.md @@ -0,0 +1,15 @@ +# rax-materials-basic-app + +## Getting Started + +### `npm run start` + +Runs the app in development mode. + +Open [http://localhost:3333](http://localhost:3333) to view it in the browser. + +The page will reload if you make edits. + +### `npm run build` + +Builds the app for production to the `build` folder. diff --git a/scaffolds/app-shop/_eslintignore b/scaffolds/app-shop/_eslintignore new file mode 100644 index 0000000..357fc60 --- /dev/null +++ b/scaffolds/app-shop/_eslintignore @@ -0,0 +1,8 @@ +node_modules/ +lib/ +dist/ +build/ +coverage/ +demo/ +es/ +.rax/ diff --git a/scaffolds/app-shop/_eslintrc.js b/scaffolds/app-shop/_eslintrc.js new file mode 100644 index 0000000..2d4f838 --- /dev/null +++ b/scaffolds/app-shop/_eslintrc.js @@ -0,0 +1,8 @@ +const { getESLintConfig } = require('@iceworks/spec'); + +// https://www.npmjs.com/package/@iceworks/spec +module.exports = getESLintConfig('rax-ts', { + rules: { + 'react/no-array-index-key': 'off', + }, +}); diff --git a/scaffolds/app-shop/_gitignore b/scaffolds/app-shop/_gitignore new file mode 100644 index 0000000..2faedd3 --- /dev/null +++ b/scaffolds/app-shop/_gitignore @@ -0,0 +1,18 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +*~ +*.swp +*.log + +.DS_Store +.idea/ +.temp/ + +build/ +dist/ +lib/ +coverage/ +node_modules/ +.rax/ + +template.yml \ No newline at end of file diff --git a/scaffolds/app-shop/_prettierignore b/scaffolds/app-shop/_prettierignore new file mode 100644 index 0000000..357fc60 --- /dev/null +++ b/scaffolds/app-shop/_prettierignore @@ -0,0 +1,8 @@ +node_modules/ +lib/ +dist/ +build/ +coverage/ +demo/ +es/ +.rax/ diff --git a/scaffolds/app-shop/_prettierrc.js b/scaffolds/app-shop/_prettierrc.js new file mode 100644 index 0000000..23c8ce5 --- /dev/null +++ b/scaffolds/app-shop/_prettierrc.js @@ -0,0 +1,3 @@ +const { getPrettierConfig } = require('@iceworks/spec'); + +module.exports = getPrettierConfig('rax'); diff --git a/scaffolds/app-shop/_stylelintignore b/scaffolds/app-shop/_stylelintignore new file mode 100644 index 0000000..357fc60 --- /dev/null +++ b/scaffolds/app-shop/_stylelintignore @@ -0,0 +1,8 @@ +node_modules/ +lib/ +dist/ +build/ +coverage/ +demo/ +es/ +.rax/ diff --git a/scaffolds/app-shop/_stylelintrc.js b/scaffolds/app-shop/_stylelintrc.js new file mode 100644 index 0000000..2805e39 --- /dev/null +++ b/scaffolds/app-shop/_stylelintrc.js @@ -0,0 +1,3 @@ +const { getStylelintConfig } = require('@iceworks/spec'); + +module.exports = getStylelintConfig('rax'); diff --git a/scaffolds/app-shop/build.json.ejs b/scaffolds/app-shop/build.json.ejs new file mode 100644 index 0000000..eafa413 --- /dev/null +++ b/scaffolds/app-shop/build.json.ejs @@ -0,0 +1,14 @@ +{<%_ if ( appType === 'web-mpa' ) { -%> + "targets": [ + "web" + ], + "web": { + "mpa": true + } +<%_ } else { %> + "targets": [ + "web", + "miniapp", + "wechat-miniprogram" + ] +<%_ } %>} diff --git a/scaffolds/app-shop/mini.project.json b/scaffolds/app-shop/mini.project.json new file mode 100644 index 0000000..8b8860f --- /dev/null +++ b/scaffolds/app-shop/mini.project.json @@ -0,0 +1,6 @@ +{ + "miniprogramRoot": "build/miniapp", + "scripts": { + "beforeUpload": "npm run build" + } +} diff --git a/scaffolds/app-shop/package.json b/scaffolds/app-shop/package.json new file mode 100644 index 0000000..d3c8c0d --- /dev/null +++ b/scaffolds/app-shop/package.json @@ -0,0 +1,50 @@ +{ + "name": "@rax-materials/scaffolds-app-shop", + "author": "rax", + "description": "Rax 无线跨端商城应用工程,使用 TypeScript。", + "version": "0.2.0", + "scripts": { + "start": "rax-app start", + "build": "rax-app build", + "eslint": "eslint --ext .js,.jsx,.tsx,.ts ./", + "stylelint": "stylelint \"**/*.{css,scss,less}\"", + "prettier": "prettier **/* --write", + "lint": "npm run eslint && npm run stylelint" + }, + "scaffoldConfig": { + "supportAppType": [ + "web-mpa", + "miniapp" + ], + "title": "Rax App Pro - Shop", + "category": "Industry", + "screenshot": "https://img.alicdn.com/imgextra/i2/O1CN01LtylNw1gobofXxEdL_!!6000000004189-2-tps-558-998.png", + "name": "Rax App Pro - Shop" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@uni/element": "^1.0.6", + "@uni/env": "^1.0.7", + "@uni/system-info": "^1.0.5", + "lodash.throttle": "^4.1.1", + "rax": "^1.1.0", + "rax-document": "^0.1.0", + "rax-image": "^2.0.0", + "rax-link": "^1.0.1", + "rax-recyclerview": "^1.3.6", + "rax-scrollview": "^3.6.1", + "rax-slider": "^3.1.2", + "rax-text": "^2.0.0", + "rax-view": "^2.0.0" + }, + "devDependencies": { + "rax-app": "^3.0.0", + "@iceworks/spec": "^1.0.0", + "@types/rax": "^1.0.0", + "eslint": "^6.8.0", + "prettier": "^2.1.2", + "stylelint": "^13.7.2" + } +} diff --git a/scaffolds/app-shop/public/icons/cart.png b/scaffolds/app-shop/public/icons/cart.png new file mode 100644 index 0000000..29b14fb Binary files /dev/null and b/scaffolds/app-shop/public/icons/cart.png differ diff --git a/scaffolds/app-shop/public/icons/cart_active.png b/scaffolds/app-shop/public/icons/cart_active.png new file mode 100644 index 0000000..6a115b7 Binary files /dev/null and b/scaffolds/app-shop/public/icons/cart_active.png differ diff --git a/scaffolds/app-shop/public/icons/home.png b/scaffolds/app-shop/public/icons/home.png new file mode 100644 index 0000000..0c63a2c Binary files /dev/null and b/scaffolds/app-shop/public/icons/home.png differ diff --git a/scaffolds/app-shop/public/icons/home_active.png b/scaffolds/app-shop/public/icons/home_active.png new file mode 100644 index 0000000..96ecc89 Binary files /dev/null and b/scaffolds/app-shop/public/icons/home_active.png differ diff --git a/scaffolds/app-shop/public/icons/mine.png b/scaffolds/app-shop/public/icons/mine.png new file mode 100644 index 0000000..2f2e15b Binary files /dev/null and b/scaffolds/app-shop/public/icons/mine.png differ diff --git a/scaffolds/app-shop/public/icons/mine_active.png b/scaffolds/app-shop/public/icons/mine_active.png new file mode 100644 index 0000000..e6bb9bb Binary files /dev/null and b/scaffolds/app-shop/public/icons/mine_active.png differ diff --git a/scaffolds/app-shop/src/app.json b/scaffolds/app-shop/src/app.json new file mode 100644 index 0000000..177c312 --- /dev/null +++ b/scaffolds/app-shop/src/app.json @@ -0,0 +1,45 @@ +{ + "routes": [{ + "path": "/", + "source": "pages/Home/index" + },{ + "path": "/cart", + "source": "pages/Cart/index" + }, + { + "path": "/mine", + "source": "pages/Mine/index" + }, + { + "path": "/detail", + "source": "pages/Detail/index" + } + ], + "window": { + "title": "手机淘宝" + }, + "tabBar": { + "textColor": "#999", + "selectedColor": "#666", + "backgroundColor": "#f8f8f8", + "items": [{ + "pageName": "/", + "text": "首页", + "icon": "./icons/home.png", + "activeIcon": "./icons/home_active.png" + }, + { + "pageName": "/cart", + "text": "购物车", + "icon": "./icons/cart.png", + "activeIcon": "./icons/cart_active.png" + }, + { + "pageName": "/mine", + "text": "我的淘宝", + "icon": "./icons/mine.png", + "activeIcon": "./icons/mine_active.png" + } + ] + } +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/app.ts b/scaffolds/app-shop/src/app.ts new file mode 100644 index 0000000..27231bf --- /dev/null +++ b/scaffolds/app-shop/src/app.ts @@ -0,0 +1,5 @@ +// MPA 模式下该文件无效 +import { runApp, IAppConfig } from 'rax-app'; + +const appConfig: IAppConfig = {}; +runApp(appConfig); diff --git a/scaffolds/app-shop/src/components/GoGtop/index.module.css b/scaffolds/app-shop/src/components/GoGtop/index.module.css new file mode 100644 index 0000000..39246f1 --- /dev/null +++ b/scaffolds/app-shop/src/components/GoGtop/index.module.css @@ -0,0 +1,24 @@ +.container { + position: fixed; + right: 20rpx; + bottom: 140rpx; + z-index: 1000; + color: #bbb; + background-color: #fff; + border: 2rpx solid #ccc; + text-align: center; + border-radius: 50%; + width: 88rpx; + height: 88rpx; +} + +.image { + margin: 3rpx auto; + width: 44rpx; + height: 44rpx; +} + +.text { + line-height: 24rpx; + font-size: 24rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/components/GoGtop/index.tsx b/scaffolds/app-shop/src/components/GoGtop/index.tsx new file mode 100644 index 0000000..a48dd70 --- /dev/null +++ b/scaffolds/app-shop/src/components/GoGtop/index.tsx @@ -0,0 +1,17 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './index.module.css'; + +function GoTop(props) { + return ( + + + 顶部 + + ); +} + +export default GoTop; diff --git a/scaffolds/app-shop/src/components/ItemList/Card.module.css b/scaffolds/app-shop/src/components/ItemList/Card.module.css new file mode 100644 index 0000000..2a2fc08 --- /dev/null +++ b/scaffolds/app-shop/src/components/ItemList/Card.module.css @@ -0,0 +1,33 @@ +.container { + margin: 18rpx 9rpx 0; + background: #fff; + width: 342rpx; +} + +.image { + width: 342rpx; + height: 342rpx; +} + +.name { + padding: 20rpx; + font-size: 26rpx; + color: #333; +} + +.info { + padding: 0 20rpx 20rpx; + flex-direction: row; + align-items: baseline; +} + +.price { + color: #f50; + font-size: 28rpx; +} + +.extra { + margin-left: 18rpx; + color: #999; + font-size: 22rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/components/ItemList/Card.tsx b/scaffolds/app-shop/src/components/ItemList/Card.tsx new file mode 100644 index 0000000..22aa2c2 --- /dev/null +++ b/scaffolds/app-shop/src/components/ItemList/Card.tsx @@ -0,0 +1,32 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; +import Link from '@/components/Link'; + +import styles from './Card.module.css'; + +interface IProps { + image: string; + name: string; + price: string; + extra: string; +} + +function Card(props: IProps) { + const { image, name, price, extra } = props; + return ( + + + + {name} + + ¥ {price} + {extra} + + + + ); +} + +export default Card; diff --git a/scaffolds/app-shop/src/components/ItemList/data.json b/scaffolds/app-shop/src/components/ItemList/data.json new file mode 100644 index 0000000..8b36f67 --- /dev/null +++ b/scaffolds/app-shop/src/components/ItemList/data.json @@ -0,0 +1,62 @@ +[ + { + "recExc": "21人已购买", + "price": "20", + "picUrl": "https://img.alicdn.com/bao/uploaded/i1/683495160/O1CN013Xsm0l1nzKJZiST6h_!!683495160-0-lubanu-s.jpg", + "title": "TransArt 变形玩具金刚 滑板猩猩 队长 TA 猛兽侠BW系列野兽战争" + }, + { + "recExc": "275人已购买", + "price": "9.99", + "picUrl": "https://img.alicdn.com/bao/uploaded/i4/718056489/O1CN01qwETEb1xo0cze4wXs_!!0-item_pic.jpg", + "title": "羽毛球钥匙扣挂件创意个性可爱汽车锁匙链圈环男士女款书包包挂饰" + }, + { + "recExc": "45人已购买", + "price": "76", + "picUrl": "https://img.alicdn.com/bao/uploaded/i1/3060442778/O1CN01gUOOPF1WOMwElCF8B_!!0-item_pic.jpg", + "title": "马克杯陶瓷日式带盖过滤办公室大容量定制logo茶水分离杯子泡茶杯" + }, + { + "recExc": "72人已购买", + "price": "98", + "picUrl": "https://img.alicdn.com/bao/uploaded/i1/4082440896/O1CN01uSxhka1IUPVoMfxej_!!4082440896.jpg", + "title": "「官方直营」育胶乐园 AMAZING EXIA MG惊异能天使GK改件 YJL" + }, + { + "recExc": "278人已购买", + "price": "1,690", + "picUrl": "https://img.alicdn.com/bao/uploaded/i4/2208902963218/O1CN01ME1x6K1ZdtEZoh4mu_!!2208902963218.jpg", + "title": "西藏那曲冬虫夏草旗舰店干虫草正品4根/克40根10克礼盒装天然干货" + }, + { + "recExc": "66人已购买", + "price": "68", + "picUrl": "https://img.alicdn.com/bao/uploaded/i1/3011877565/O1CN012BGE9b25koqoUPZGy_!!0-item_pic.jpg", + "title": "优比熊汽车窗帘遮阳挡板防晒隔热磁吸轨道侧窗遮光磁铁卡通遮阳帘" + }, + { + "recExc": "1人已购买", + "price": "388", + "picUrl": "https://img.alicdn.com/bao/uploaded/i2/76787924/O1CN01BM8uDj28PF2uRyCTo_!!76787924-0-lubanu-s.jpg", + "title": "现货 吉模神金牛 合金圣衣斗士神话EX2.0 EX神金牛座 阿鲁迪巴" + }, + { + "recExc": "197人已购买", + "price": "98", + "picUrl": "https://img.alicdn.com/bao/uploaded/i4/2206853744565/O1CN01o9Gnem1jaoefuTmvj_!!0-item_pic.jpg", + "title": "中国红瓷器姓氏马克杯陶瓷茶杯办公室泡茶家用咖啡杯带盖礼品礼物" + }, + { + "recExc": "186人已购买", + "price": "263", + "picUrl": "https://img.alicdn.com/bao/uploaded/i1/2206561920712/O1CN01JgyEP41H88ftIDoKu_!!0-item_pic.jpg", + "title": "福建建阳蓝麒麟建盏杯茶杯纯手工男主人杯单杯女茶碗高端茶盏建窑" + }, + { + "recExc": "103人已购买", + "price": "28.9", + "picUrl": "https://img.alicdn.com/bao/uploaded/i1/6000000004494/O1CN01Sigvvm1j4IcFnhbKd_!!6000000004494-0-picassoopen.jpg", + "title": "生龙迷你型佬米酒桂花味500g冲调米酒儿童宝宝婴儿米零食饮料" + } +] diff --git a/scaffolds/app-shop/src/components/ItemList/index.module.css b/scaffolds/app-shop/src/components/ItemList/index.module.css new file mode 100644 index 0000000..62f4e55 --- /dev/null +++ b/scaffolds/app-shop/src/components/ItemList/index.module.css @@ -0,0 +1,19 @@ +.container { + padding: 0 15rpx; + background-color: #f4f4f4; +} + +.header { + padding: 24rpx 0; +} + +.headerImage { + margin: 0 auto; + width: 322rpx; + height: 38rpx; +} + +.list { + flex-direction: row; + flex-wrap: wrap; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/components/ItemList/index.tsx b/scaffolds/app-shop/src/components/ItemList/index.tsx new file mode 100644 index 0000000..02c83af --- /dev/null +++ b/scaffolds/app-shop/src/components/ItemList/index.tsx @@ -0,0 +1,45 @@ +import { createElement, useEffect, forwardRef, useImperativeHandle, useState } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; +import Card from './Card'; + +// mock data +import data from './data.json'; + +import styles from './index.module.css'; + +const maxItems = 300; + +export interface IRefObject { + loadItems: () => void; +} + +function ItemList(props, ref) { + const [list, setList] = useState>([]); + + function loadItems() { + if (list.length >= maxItems) return; + setList(list.concat(data)); + } + + useImperativeHandle(ref, () => ({ loadItems })); + + useEffect(() => { + loadItems(); + }, []); + + return ( + + + + + + {list.map((item, index) => { + return ; + })} + + + ); +} + +export default forwardRef(ItemList); diff --git a/scaffolds/app-shop/src/components/Link/index.tsx.ejs b/scaffolds/app-shop/src/components/Link/index.tsx.ejs new file mode 100644 index 0000000..8f9a553 --- /dev/null +++ b/scaffolds/app-shop/src/components/Link/index.tsx.ejs @@ -0,0 +1,31 @@ +<%_ if ( appType === 'web-mpa' ) { -%> +import { createElement } from 'rax'; + +function Link(props) { + return ( + + {props.children} + + ); +} + +export default Link; +<%_ } else { %> +import { createElement } from 'rax'; +import { withRouter } from 'rax-app'; +import View from 'rax-view'; + +function Link(props) { + const handleClick = () => { + props.history.push(props.href === '/home' ? '/' : props.href); + }; + + return ( + + {props.children} + + ); +} + +export default withRouter(Link); +<%_ } %> diff --git a/scaffolds/app-shop/src/global.css b/scaffolds/app-shop/src/global.css new file mode 100644 index 0000000..ec8d9c3 --- /dev/null +++ b/scaffolds/app-shop/src/global.css @@ -0,0 +1,19 @@ +body { + margin: 0; +} + +a { + text-decoration: none; +} + +a:visited { + text-decoration: none; +} + +a:hover { + text-decoration: none; +} + +a:active { + text-decoration: none; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Cart/components/Header/index.module.css b/scaffolds/app-shop/src/pages/Cart/components/Header/index.module.css new file mode 100644 index 0000000..89e6d95 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/components/Header/index.module.css @@ -0,0 +1,20 @@ +.container { + position: relative; + width: 750rpx; + flex-direction: row; + justify-content: space-between; + align-items: center; + padding: 40rpx 24rpx 20rpx; + background-image: linear-gradient(-90deg, #ff5000 0%, #ff8400 100%); +} + +.title { + font-size: 40rpx; + font-weight: bold; + color: #fff; +} + +.extra { + font-size: 30rpx; + color: #fff; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Cart/components/Header/index.tsx b/scaffolds/app-shop/src/pages/Cart/components/Header/index.tsx new file mode 100644 index 0000000..6904d1b --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/components/Header/index.tsx @@ -0,0 +1,16 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; + +import styles from './index.module.css'; + +function Header() { + return ( + + 购物车 + 管理 + + ); +} + +export default Header; diff --git a/scaffolds/app-shop/src/pages/Cart/components/Item/Card.module.css b/scaffolds/app-shop/src/pages/Cart/components/Item/Card.module.css new file mode 100644 index 0000000..b531b4a --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/components/Item/Card.module.css @@ -0,0 +1,36 @@ +.container { + flex-direction: row; + justify-content: space-between; +} + +.image { + width: 180rpx; + height: 180rpx; +} + +.info { + width: 440rpx; + height: 180rpx; + justify-content: space-between; +} + +.name { + font-size: 28rpx; + color: #333; +} + +.price { + flex-direction: row; + justify-content: space-between; +} + +.priceText { + font-size: 28rpx; + color: #f50; +} + +.countText { + margin-right: 14rpx; + color: #666; + font-size: 24rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Cart/components/Item/Card.tsx b/scaffolds/app-shop/src/pages/Cart/components/Item/Card.tsx new file mode 100644 index 0000000..6db66a5 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/components/Item/Card.tsx @@ -0,0 +1,23 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Card.module.css'; + +function Card() { + return ( + + + + 手机淘宝 - 随时随地,想淘就淘。手机淘宝 - 随时随地,想淘就淘。手机淘宝 - 随时随地,想淘就淘。 + + ¥520 + x1 + + + + ); +} + +export default Card; diff --git a/scaffolds/app-shop/src/pages/Cart/components/Item/index.module.css b/scaffolds/app-shop/src/pages/Cart/components/Item/index.module.css new file mode 100644 index 0000000..0b57ba1 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/components/Item/index.module.css @@ -0,0 +1,27 @@ +.container { + position: relative; +} + +.header { + position: absolute; + top: 0; + left: 0; + width: 750rpx; + height: 250rpx; + background-image: linear-gradient(-90deg, #ff5000 0%, #ff8400 100%); +} + +.title { + padding: 0rpx 24rpx 0rpx 24rpx; + color: #fff; + font-size: 24rpx; +} + +.content { + margin: 80rpx 24rpx 40rpx; + padding: 24rpx; + position: relative; + border-radius: 24rpx; + background: #fff; + z-index: 1; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Cart/components/Item/index.tsx b/scaffolds/app-shop/src/pages/Cart/components/Item/index.tsx new file mode 100644 index 0000000..1d225d7 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/components/Item/index.tsx @@ -0,0 +1,21 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Card from './Card'; + +import styles from './index.module.css'; + +function Item() { + return ( + + + 共1件宝贝 + + + + + + ); +} + +export default Item; diff --git a/scaffolds/app-shop/src/pages/Cart/index.module.css b/scaffolds/app-shop/src/pages/Cart/index.module.css new file mode 100644 index 0000000..febd26e --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/index.module.css @@ -0,0 +1,9 @@ +.container { + align-items: center; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #f4f4f4; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Cart/index.tsx b/scaffolds/app-shop/src/pages/Cart/index.tsx new file mode 100644 index 0000000..635999f --- /dev/null +++ b/scaffolds/app-shop/src/pages/Cart/index.tsx @@ -0,0 +1,24 @@ +import { createElement, useRef } from 'rax'; +import View from 'rax-view'; +import RecyclerView from 'rax-recyclerview'; +import ItemList, { IRefObject } from '@/components/ItemList'; +import Header from './components/Header'; +import Item from './components/Item'; + +import styles from './index.module.css'; + +function Cart() { + const itemListRef = useRef(null); + + return ( + + { itemListRef.current?.loadItems(); }} > +
+ + + + + ); +} + +export default Cart; diff --git a/scaffolds/app-shop/src/pages/Detail/components/Banner/data.json b/scaffolds/app-shop/src/pages/Detail/components/Banner/data.json new file mode 100644 index 0000000..a5d5f95 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Banner/data.json @@ -0,0 +1,7 @@ +[ + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png" +] diff --git a/scaffolds/app-shop/src/pages/Detail/components/Banner/index.module.css b/scaffolds/app-shop/src/pages/Detail/components/Banner/index.module.css new file mode 100644 index 0000000..a6ebde0 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Banner/index.module.css @@ -0,0 +1,24 @@ +.container { + position: relative; +} + +.image { + width: 750rpx; + height: 750rpx; +} + +.pagination { + position: absolute; + right: 20rpx; + bottom: 32rpx; + height: 40rpx; + border-radius: 40rpx; + line-height: 40rpx; + padding: 0 20rpx; + background: rgba(0, 0, 0, 0.3); +} + +.paginationText { + color: #fff; + font-size: 20rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/Banner/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/Banner/index.tsx new file mode 100644 index 0000000..a50ed0e --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Banner/index.tsx @@ -0,0 +1,44 @@ +import { createElement, useState } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; +import Slider from 'rax-slider'; + +// mock data +import data from './data.json'; + +import styles from './index.module.css'; + +function Banner() { + const [index, setIndex] = useState(1); + + function handleChange(e) { + setIndex(Number(e.index) + 1); + } + + return ( + + + {data.map((item) => { + return ( + + + + ); + })} + + + {index}/{data.length} + + + ); +} + +export default Banner; diff --git a/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Coupon.module.css b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Coupon.module.css new file mode 100644 index 0000000..32438aa --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Coupon.module.css @@ -0,0 +1,32 @@ +.container { + margin-top: 12rpx; + flex-direction: row; + justify-content: space-between; +} + +.coupon { + flex-direction: row; +} + +.couponText { + margin-right: 48rpx; + padding: 2rpx 8rpx; + font-size: 26rpx; + line-height: 32rpx; + color: #ff5000; + background-color: #ffede8; +} + +.button { + flex-direction: row; +} + +.buttonText { + font-size: 26rpx; + color: #ff5000; +} + +.buttonIcon { + width: 28rpx; + height: 28rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Coupon.tsx b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Coupon.tsx new file mode 100644 index 0000000..45ac033 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Coupon.tsx @@ -0,0 +1,23 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Coupon.module.css'; + +function Coupon() { + return ( + + + 淘金币可抵8.94元 + 店铺券满355减25 + + + 领券 + + + + ); +} + +export default Coupon; diff --git a/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Price.module.css b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Price.module.css new file mode 100644 index 0000000..f6404ce --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Price.module.css @@ -0,0 +1,28 @@ +.container { + flex-direction: row; + align-items: center; +} + +.price { + flex-direction: row; + align-items: baseline; +} + +.priceText { + color: #ff5000; +} + +.newPrice { + background: #ff5000; + margin-left: 20rpx; + padding: 0 18rpx; + border-radius: 24rpx; + height: 48rpx; + flex-direction: row; + align-items: center; +} + +.newPriceText { + color: #fff; + font-weight: bold; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Price.tsx b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Price.tsx new file mode 100644 index 0000000..2fc50a3 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/Price.tsx @@ -0,0 +1,23 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; + +import styles from './Price.module.css'; + +function Price() { + return ( + + + + 999 + + + 券后 + + 699 + + + ); +} + +export default Price; diff --git a/scaffolds/app-shop/src/pages/Detail/components/BaseCard/index.module.css b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/index.module.css new file mode 100644 index 0000000..de0efd9 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/index.module.css @@ -0,0 +1,12 @@ +.container { + margin: 18rpx 18rpx 0; + padding: 24rpx; + background: #fff; + border-radius: 24rpx; +} + +.title { + margin-top: 24rpx; + color: #111; + font-size: 32rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/BaseCard/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/index.tsx new file mode 100644 index 0000000..d1916a0 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/BaseCard/index.tsx @@ -0,0 +1,19 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Price from './Price'; +import Coupon from './Coupon'; + +import styles from './index.module.css'; + +function BaseCard() { + return ( + + + + 手机淘宝 随时随地,想淘就淘。手机淘宝 随时随地,想淘就淘。 + + ); +} + +export default BaseCard; diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/AskAll.module.css b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/AskAll.module.css new file mode 100644 index 0000000..d656fe2 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/AskAll.module.css @@ -0,0 +1,33 @@ +.container { + margin-top: 36rpx; + padding-top: 36rpx; + border-top: 2rpx solid #f4f4f4; +} + +.item { + margin-top: 20rpx; + flex-direction: row; + justify-content: space-between; + align-items: center; +} + +.question { + flex-direction: row; + align-items: center; +} + +.icon { + margin-right: 10rpx; + width: 26rpx; + height: 26rpx; +} + +.questionText { + color: #162b36; + font-size: 28rpx; +} + +.answer { + color: #999; + font-size: 28rpx; +} diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/AskAll.tsx b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/AskAll.tsx new file mode 100644 index 0000000..ef650b1 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/AskAll.tsx @@ -0,0 +1,31 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; +import Title from './Title'; + +// mock data +import data from './data.json'; + +import styles from './AskAll.module.css'; + +function AskAll() { + return ( + + + {data.questions.map(((question) => { + return ( + <View className={styles.item}> + <View className={styles.question}> + <Image className={styles.icon} source={{ uri: 'https://gw.alicdn.com/tfs/TB1lneilZLJ8KJjy0FnXXcFDpXa-36-36.png' }} /> + <Text className={styles.questionText}>{question.question}</Text> + </View> + <Text className={styles.answer}>{question.answerCount}个回答</Text> + </View> + ); + }))} + </View> + ); +} + +export default AskAll; diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Comment.module.css b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Comment.module.css new file mode 100644 index 0000000..53768f6 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Comment.module.css @@ -0,0 +1,48 @@ +.tags { + margin-top: 28rpx; + flex-direction: row; +} + +.tag { + display: inline-block; + border-radius: 26rpx; + padding: 8rpx 20rpx; + margin-right: 20rpx; + color: #111; + background: #ffecea; + font-size: 28rpx; +} + +.comment { + margin-top: 28rpx; +} + +.info { + flex-direction: row; + justify-content: start; +} + +.avatar { + margin-right: 14rpx; + width: 68rpx; + height: 68rpx; + border-radius: 34rpx; +} + +.name { + color: #111; + font-size: 28rpx; + line-height: 34rpx; +} + +.time { + color: #999; + font-size: 24rpx; + line-height: 36rpx; +} + +.commentText { + margin-top: 22rpx; + font-size: 28rpx; + color: #111; +} diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Comment.tsx b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Comment.tsx new file mode 100644 index 0000000..e920688 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Comment.tsx @@ -0,0 +1,43 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; +import Title from './Title'; + +// mock data +import data from './data.json'; + +import styles from './Comment.module.css'; + +function Comment() { + return ( + <View> + <Title name="宝贝评价(78)" /> + <View className={styles.tags}> + {data.tags.map((tag) => { + return ( + <Text className={styles.tag} key={tag}>{tag}</Text> + ); + })} + </View> + <View> + {data.comments.map((comment) => { + return ( + <View key={comment.comment} className={styles.comment}> + <View className={styles.info} > + <Image className={styles.avatar} source={{ uri: comment.avatar }} /> + <View> + <Text className={styles.name}>{comment.name}</Text> + <Text className={styles.time}>{comment.timeString}</Text> + </View> + </View> + <Text className={styles.commentText}>{comment.comment}</Text> + </View> + ); + })} + </View> + </View> + ); +} + +export default Comment; diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Photos.module.css b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Photos.module.css new file mode 100644 index 0000000..c02040c --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Photos.module.css @@ -0,0 +1,18 @@ +.container { + margin-top: 28rpx; + padding-top: 36rpx; + border-top: 2rpx solid #f4f4f4; +} + +.wrap { + flex-direction: row; + width: 690rpx; + overflow: hidden; + margin-top: 24rpx; +} + +.image { + width: 166rpx; + height: 166rpx; + margin-right: 2rpx; +} diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Photos.tsx b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Photos.tsx new file mode 100644 index 0000000..138c0aa --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Photos.tsx @@ -0,0 +1,26 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; +import Title from './Title'; + +// mock data +import data from './data.json'; + +import styles from './Photos.module.css'; + +function Photos() { + return ( + <View className={styles.container}> + <Title name="买家秀(60)" /> + <View className={styles.wrap}> + {data.photos.map((photo, index) => { + return ( + <Image key={index} className={styles.image} source={{ uri: photo }} /> + ); + })} + </View> + </View> + ); +} + +export default Photos; diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Title.module.css b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Title.module.css new file mode 100644 index 0000000..e428b49 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Title.module.css @@ -0,0 +1,27 @@ +.title { + flex-direction: row; + justify-content: space-between; + align-items: center; +} + +.titleText { + font-size: 32rpx; + line-height: 38rpx; + font-weight: bold; + color: #111; +} + +.extra { + flex-direction: row; + align-items: center; +} + +.extraText { + font-size: 26rpx; + color: #ff5000; +} + +.icon { + width: 26rpx; + height: 26rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Title.tsx b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Title.tsx new file mode 100644 index 0000000..57f93a4 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/Title.tsx @@ -0,0 +1,24 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Title.module.css'; + +interface IProps { + name: string; +} + +function Title(props: IProps) { + return ( + <View className={styles.title}> + <Text className={styles.titleText}>{props.name}</Text> + <View className={styles.extra}> + <Text className={styles.extraText}>查看全部</Text> + <Image className={styles.icon} source={{ uri: 'https://gw.alicdn.com/imgextra/i2/O1CN01Lnk0v51qhPkpLfTww_!!6000000005527-2-tps-64-64.png' }} /> + </View> + </View> + ); +} + +export default Title; diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/data.json b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/data.json new file mode 100644 index 0000000..38645e6 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/data.json @@ -0,0 +1,27 @@ +{ + "tags": ["安装非常容易(2)"], + "comments": [{ + "avatar": "https://gw.alicdn.com/tps/i3/TB1yeWeIFXXXXX5XFXXuAZJYXXX-210-210.png_50x50.jpg", + "name": "手**宝", + "timeString": "4天前", + "comment": "质量很好,颜值不错" + }, { + "avatar": "https://gw.alicdn.com/tps/i3/TB1yeWeIFXXXXX5XFXXuAZJYXXX-210-210.png_50x50.jpg", + "name": "手**宝", + "timeString": "1个月前", + "comment": "这个颜色搭配比较好看,安装也非常容易" + }], + "photos": [ + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png", + "https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png" + ], + "questions": [{ + "question": "请问亲们,质量如何?牢固吗?", + "answerCount": 3 + }, { + "question": "好用吗?会不会容易晃", + "answerCount": 6 + }] +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/index.module.css b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/index.module.css new file mode 100644 index 0000000..6546ede --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/index.module.css @@ -0,0 +1,6 @@ +.container { + margin: 18rpx 18rpx 0; + padding: 24rpx; + background: #fff; + border-radius: 24rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/index.tsx new file mode 100644 index 0000000..caa67e7 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/CommunityCard/index.tsx @@ -0,0 +1,19 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Comment from './Comment'; +import Photos from './Photos'; +import AskAll from './AskAll'; + +import styles from './index.module.css'; + +function CommunityCard() { + return ( + <View className={styles.container}> + <Comment /> + <Photos /> + <AskAll /> + </View> + ); +} + +export default CommunityCard; diff --git a/scaffolds/app-shop/src/pages/Detail/components/Description/Title.module.css b/scaffolds/app-shop/src/pages/Detail/components/Description/Title.module.css new file mode 100644 index 0000000..83e09ea --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Description/Title.module.css @@ -0,0 +1,28 @@ +.container { + padding: 16rpx 0; + align-items: center; +} + +.wrap { + position: relative; + width: 320rpx; + align-items: center; +} + +.line { + position: absolute; + top: 18rpx; + left: 0; + width: 320rpx; + height: 2px; + background: #999; +} + +.text { + position: relative; + width: 120rpx; + text-align: center; + background: #f2f2f2; + font-size: 24rpx; + color: #999; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/Description/Title.tsx b/scaffolds/app-shop/src/pages/Detail/components/Description/Title.tsx new file mode 100644 index 0000000..20a56d8 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Description/Title.tsx @@ -0,0 +1,18 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; + +import styles from './Title.module.css'; + +function Title() { + return ( + <View className={styles.container}> + <View className={styles.wrap}> + <View className={styles.line} /> + <Text className={styles.text}>详情</Text> + </View> + </View> + ); +} + +export default Title; diff --git a/scaffolds/app-shop/src/pages/Detail/components/Description/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/Description/index.tsx new file mode 100644 index 0000000..59d69ec --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Description/index.tsx @@ -0,0 +1,16 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; +import Title from './Title'; + +function Description() { + return ( + <View> + <Title /> + <Image style={{ width: '750rpx', height: '750rpx' }} source={{ uri: 'https://gw.alicdn.com/imgextra/i4/O1CN011APjrP1bPLtgGLU6n_!!6000000003457-2-tps-1152-1152.png' }} /> + <Image style={{ width: '750rpx', height: '640rpx' }} source={{ uri: 'https://gw.alicdn.com/tfs/TB1d0h2qVYqK1RjSZLeXXbXppXa-1125-960.png?getAvatar=avatar_640x0q80_.webp' }} /> + </View> + ); +} + +export default Description; diff --git a/scaffolds/app-shop/src/pages/Detail/components/Header/index.module.css b/scaffolds/app-shop/src/pages/Detail/components/Header/index.module.css new file mode 100644 index 0000000..f69cbc1 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Header/index.module.css @@ -0,0 +1,22 @@ +.container { + position: fixed; + z-index: 999; + width: 750rpx; + flex-direction: row; + justify-content: space-between; +} + +.button { + margin: 18rpx; + background: rgba(0, 0, 0, 0.4); + width: 68rpx; + height: 68rpx; + border-radius: 68rpx; + align-items: center; + justify-content: center; +} + +.icon { + width: 40rpx; + height: 40rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/Header/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/Header/index.tsx new file mode 100644 index 0000000..2d31c0c --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/Header/index.tsx @@ -0,0 +1,25 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; +import Link from '@/components/Link'; + +import styles from './index.module.css'; + +function Header() { + return ( + <View className={styles.container}> + <View className={styles.button}> + <Link href="/home"> + <Image className={styles.icon} source={{ uri: 'https://img.alicdn.com/imgextra/i2/O1CN01U8ASos1gbKKc32hmM_!!6000000004160-2-tps-64-64.png' }} /> + </Link> + </View> + <View className={styles.button}> + <Link href="/cart"> + <Image className={styles.icon} source={{ uri: 'https://img.alicdn.com/imgextra/i1/O1CN01lDjcPl1nAUQktdY1O_!!6000000005049-2-tps-64-64.png' }} /> + </Link> + </View> + </View> + ); +} + +export default Header; diff --git a/scaffolds/app-shop/src/pages/Detail/components/SkuCard/Item.module.css b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/Item.module.css new file mode 100644 index 0000000..21b30cd --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/Item.module.css @@ -0,0 +1,38 @@ +.container { + padding: 24rpx 0; + flex-direction: row; + justify-content: space-between; + align-items: center; +} + +.row { + flex-direction: row; +} + +.label { + color: #999; + font-size: 28rpx; + margin-right: 38rpx; +} + +.split { + color: #eee; + font-size: 28rpx; + margin: 0 20rpx; +} + +.content { + max-width: 544rpx; + font-size: 28rpx; + color: #111; +} + +.extra { + color: #999; + font-size: 28rpx; +} + +.icon { + width: 26rpx; + height: 26rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/SkuCard/Item.tsx b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/Item.tsx new file mode 100644 index 0000000..115c85e --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/Item.tsx @@ -0,0 +1,39 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Item.module.css'; + +interface IProps { + label: string; + content: string[]; + extra?: string; +} + +function Item(props: IProps) { + const { label, content, extra } = props; + + + return ( + <View className={styles.container}> + <View className={styles.row}> + <Text className={styles.label}>{label}</Text> + {content.map((item, index) => { + return ( + <View key={item} className={styles.row}> + <Text x-if={index} className={styles.split}>|</Text> + <Text className={styles.content} numberOfLines={1}>{item}</Text> + </View> + ); + })} + </View> + <View > + <Text x-if={extra} className={styles.extra}>{extra}</Text> + <Image x-else className={styles.icon} source={{ uri: 'https://img.alicdn.com/imgextra/i2/O1CN01pVMVOn22TvTd3CMcA_!!6000000007122-2-tps-64-64.png' }} /> + </View> + </View> + ); +} + +export default Item; diff --git a/scaffolds/app-shop/src/pages/Detail/components/SkuCard/index.module.css b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/index.module.css new file mode 100644 index 0000000..1b14327 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/index.module.css @@ -0,0 +1,6 @@ +.container { + margin: 18rpx 18rpx 0; + padding: 24rpx; + background: #fff; + border-radius: 24rpx; +} diff --git a/scaffolds/app-shop/src/pages/Detail/components/SkuCard/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/index.tsx new file mode 100644 index 0000000..670c997 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/SkuCard/index.tsx @@ -0,0 +1,18 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Item from './Item'; + +import styles from './index.module.css'; + +function SkuCard() { + return ( + <View className={styles.container}> + <Item label="选择" content={['颜色分类']} /> + <Item label="发货" content={['北京', '快递:快递包邮']} extra="月销4" /> + <Item label="保障" content={['付款后48小时内发货 · 订单险 · 7天无理由 · 运费险']} /> + <Item label="参数" content={['适用年龄 颜色分类']} /> + </View> + ); +} + +export default SkuCard; diff --git a/scaffolds/app-shop/src/pages/Detail/components/StoreCard/index.module.css b/scaffolds/app-shop/src/pages/Detail/components/StoreCard/index.module.css new file mode 100644 index 0000000..38a213c --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/StoreCard/index.module.css @@ -0,0 +1,59 @@ +.container { + margin: 18rpx 18rpx 0; + padding: 24rpx; + background: #fff; + border-radius: 24rpx; +} + +.wrap { + flex-direction: row; + align-items: center; + justify-content: center; +} + +.shop { + flex: 1; + margin-left: 28rpx; +} + +.name { + color: #333; + font-size: 34rpx; + font-weight: bold; + +} + +.level { + margin-top: 14rpx; + width: 132rpx; + height: 24rpx; +} + +.avatar { + border-radius: 48rpx; + width: 96rpx; + height: 96rpx; +} + +.description { + flex-direction: row; +} + +.label { + font-size: 20rpx; +} + +.rank { + margin-left: 6rpx; + font-size: 20rpx; + color: #ff5000; +} + +.button { + margin-left: 20rpx; + border-radius: 26rpx; + border: 2rpx solid #ff5000; + padding: 8rpx 24rpx; + font-size: 28rpx; + color: #ff5000; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/components/StoreCard/index.tsx b/scaffolds/app-shop/src/pages/Detail/components/StoreCard/index.tsx new file mode 100644 index 0000000..cf7e1dc --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/components/StoreCard/index.tsx @@ -0,0 +1,40 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './index.module.css'; + +function StoreCard() { + return ( + <View className={styles.container}> + <View className={styles.wrap}> + <Image className={styles.avatar} source={{ uri: 'https://gw.alicdn.com/tps/i3/TB1yeWeIFXXXXX5XFXXuAZJYXXX-210-210.png_50x50.jpg' }} /> + <View className={styles.shop}> + <Text className={styles.name}>手机淘宝</Text> + <Image className={styles.level} source={{ uri: 'https://gw.alicdn.com/tfs/TB1Gez8ir_I8KJjy1XaXXbsxpXa-132-24.png' }} /> + </View> + <View > + <View className={styles.description}> + <Text className={styles.label}>宝贝描述 5.0</Text> + <Text className={styles.rank}>高</Text> + </View> + <View className={styles.description}> + <Text className={styles.label}>卖家服务 5.0</Text> + <Text className={styles.rank}>高</Text> + </View> + <View className={styles.description}> + <Text className={styles.label}>物流服务 5.0</Text> + <Text className={styles.rank}>高</Text> + </View> + </View> + </View> + <View className={styles.wrap} style={{ margin: '24rpx 0' }}> + <Text className={styles.button}>进店逛逛</Text> + <Text className={styles.button}>全部宝贝</Text> + </View> + </View> + ); +} + +export default StoreCard; diff --git a/scaffolds/app-shop/src/pages/Detail/index.module.css b/scaffolds/app-shop/src/pages/Detail/index.module.css new file mode 100644 index 0000000..a316ddc --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/index.module.css @@ -0,0 +1,4 @@ +.container { + background: #f2f2f2; + padding-bottom: 108rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Detail/index.tsx b/scaffolds/app-shop/src/pages/Detail/index.tsx new file mode 100644 index 0000000..c1cc301 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Detail/index.tsx @@ -0,0 +1,28 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; + +import Header from './components/Header'; +import Banner from './components/Banner'; +import BaseCard from './components/BaseCard'; +import SkuCard from './components/SkuCard'; +import CommunityCard from './components/CommunityCard'; +import StoreCard from './components/StoreCard'; +import Description from './components/Description'; + +import styles from './index.module.css'; + +function Detail() { + return ( + <View className={styles.container}> + <Header /> + <Banner /> + <BaseCard /> + <SkuCard /> + <CommunityCard /> + <StoreCard /> + <Description /> + </View> + ); +} + +export default Detail; diff --git a/scaffolds/app-shop/src/pages/Home/components/Banner/data.json b/scaffolds/app-shop/src/pages/Home/components/Banner/data.json new file mode 100644 index 0000000..2ed262f --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/Banner/data.json @@ -0,0 +1,5 @@ +[ + "https://gw.alicdn.com/imgextra/i4/O1CN01K5H7u71wbMCn9Mgjh_!!6000000006326-2-tps-1125-352.png", + "https://gw.alicdn.com/imgextra/i4/O1CN01nqP1AP1OBWw0zQ2qn_!!6000000001667-2-tps-1125-352.png", + "https://gw.alicdn.com/imgextra/i2/O1CN01HWcosl1tk6va5G8yJ_!!6000000005939-2-tps-1125-352.png" +] diff --git a/scaffolds/app-shop/src/pages/Home/components/Banner/index.module.css b/scaffolds/app-shop/src/pages/Home/components/Banner/index.module.css new file mode 100644 index 0000000..d5436d4 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/Banner/index.module.css @@ -0,0 +1,5 @@ +.image { + width: 750rpx; + height: 240rpx; +} + diff --git a/scaffolds/app-shop/src/pages/Home/components/Banner/index.tsx b/scaffolds/app-shop/src/pages/Home/components/Banner/index.tsx new file mode 100644 index 0000000..5d214e1 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/Banner/index.tsx @@ -0,0 +1,47 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; +import Slider from 'rax-slider'; +import Link from '@/components/Link'; + +// mock data +import data from './data.json'; + +import styles from './index.module.css'; + +function Banner() { + return ( + <View> + <Slider + className="slider" + width={750} + height={240} + autoPlay + loop + showsPagination + paginationStyle={{ + position: 'absolute', + width: 750, + height: 40, + bottom: 20, + left: 0, + itemColor: 'rgba(255, 255, 255, 0.5)', + itemSelectedColor: 'rgb(255, 80, 0)', + itemSize: 16, + }} + > + {data.map((item) => { + return ( + <View key={item} className="itemWrap"> + <Link href={'/detail'}> + <Image className={styles.image} source={{ uri: item }} /> + </Link> + </View> + ); + })} + </Slider> + </View> + ); +} + +export default Banner; diff --git a/scaffolds/app-shop/src/pages/Home/components/Header/index.module.css b/scaffolds/app-shop/src/pages/Home/components/Header/index.module.css new file mode 100644 index 0000000..98e6494 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/Header/index.module.css @@ -0,0 +1,38 @@ +.header { + position: sticky; + width: 750rpx; + height: 74rpx; + padding: 12rpx 18rpx; + flex-direction: row; + justify-content: center; + align-items: center; + background-color: #ff8429; +} + +.logo { + width: 54rpx; + height: 40rpx; +} + +.searcher { + margin-left: 10rpx; + flex: 1; + height: 50rpx; + background-color: #ff4e22; + color: #f0e0dc; + border-radius: 8rpx; + flex-direction: row; + justify-content: center; + align-items: center; +} + +.searcherIcon { + width: 32rpx; + height: 32rpx; +} + +.searcherText { + margin-left: 10rpx; + line-height: 50rpx; + font-size: 26rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/components/Header/index.tsx b/scaffolds/app-shop/src/pages/Home/components/Header/index.tsx new file mode 100644 index 0000000..e2cde2a --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/Header/index.tsx @@ -0,0 +1,20 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; +import Text from 'rax-text'; + +import styles from './index.module.css'; + +function Header() { + return ( + <View className={styles.header}> + <Image className={styles.logo} source={{ uri: 'https://img.alicdn.com/imgextra/i2/O1CN01l2ZYVg1EL0ylPHIJH_!!6000000000334-2-tps-63-48.png' }} /> + <View className={styles.searcher}> + <Image className={styles.searcherIcon} source={{ uri: 'https://img.alicdn.com/imgextra/i4/O1CN01QW41YX1aiIf7nyqGi_!!6000000003363-2-tps-200-200.png' }} /> + <Text className={styles.searcherText} >寻找宝贝店铺</Text> + </View> + </View> + ); +} + +export default Header; diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/Card.module.css b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/Card.module.css new file mode 100644 index 0000000..78aad2b --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/Card.module.css @@ -0,0 +1,29 @@ +.container { + position: relative; + width: 50%; +} + +.title { + margin-top: 20rpx; + width: 357rpx; + height: 40rpx; +} + +.items { + flex-direction: row; +} + +.item { + margin: 20rpx 0 0 34rpx; +} + +.tag { + font-size: 26rpx; + line-height: 32rpx; + font-weight: 700; +} + +.image { + width: 124rpx; + height: 124rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/Card.tsx b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/Card.tsx new file mode 100644 index 0000000..0b6c8f1 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/Card.tsx @@ -0,0 +1,39 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Card.module.css'; + +interface IProps { + index: number; + titleImage: string; + items: Array<{ + tag?: { + text: string; + color: string; + }; + image: string; + }>; +} + +function Card(props: IProps) { + const { index, titleImage, items } = props; + return ( + <View className={styles.container} style={index % 2 !== 0 ? { borderLeft: '1px solid #f2f2f2' } : {}}> + <Image className={styles.title} source={{ uri: titleImage }} /> + <View className={styles.items}> + {items.map((item) => { + return ( + <View key={item.image} className={styles.item}> + <Text x-if={item.tag} className={styles.tag} style={{ color: item.tag?.color }}>{item.tag?.text}</Text> + <Image className={styles.image} source={{ uri: item.image }} /> + </View> + ); + })} + </View> + </View> + ); +} + +export default Card; diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/News.module.css b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/News.module.css new file mode 100644 index 0000000..00d82ff --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/News.module.css @@ -0,0 +1,31 @@ +.container { + border-top: 2rpx solid #f2f2f2; + position: relative; + height: 80rpx; + flex-direction: row; + align-items: center; +} + +.brand { + margin: 0 24rpx; + font-size: 32rpx; + color: #3e3e3e; + font-weight: 600; +} + +.tag { + padding: 0 12rpx; + line-height: 40rpx; + font-size: 26rpx; + color: #e86217; + background-color: #feefec; + border-radius: 8rpx; +} + +.title { + margin-left: 10px; + max-width: 344rpx; + font-size: 26rpx; + color: #313131; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/News.tsx b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/News.tsx new file mode 100644 index 0000000..ba130e9 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/News.tsx @@ -0,0 +1,23 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; + +import styles from './News.module.css'; + +function News() { + return ( + <View className={styles.container}> + <Text className={styles.brand}> + 淘宝头条 + </Text> + <Text className={styles.tag}> + 评测 + </Text> + <Text className={styles.title} numberOfLines={1}> + 实测:五款最强防霾滤芯安利给你 + </Text> + </View> + ); +} + +export default News; diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/data.json b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/data.json new file mode 100644 index 0000000..eaccad3 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/data.json @@ -0,0 +1,100 @@ +[ + { + "titleImage": "https://gw.alicdn.com/tfs/TB11.K2mq61gK0jSZFlXXXDKFXa-525-60.png?getAvatar=1_360x360q90_.webp", + "items": [ + { + "tag": { + "text": "品牌折扣", + "color": "#fe4e50" + }, + "image": "https://img.alicdn.com/tps/O1CN01hjD05x1DBZAiylKuT_!!178-2-lubanu.png_125x125q90_.webp" + }, + { + "tag": { + "text": "划算好货", + "color": "#ff7518" + }, + "image": "https://img.alicdn.com/tps/O1CN0140SG9u1xSU9HKPM2K_!!0-juitemmedia.jpg_125x125q90_.webp" + } + ] + }, + { + "titleImage": "https://gw.alicdn.com/tfs/TB1MfTtQrrpK1RjSZTEXXcWAVXa-525-60.png?getAvatar=1_360x360q90_.webp", + "items": [ + { + "tag": { + "text": "好物传送门", + "color": "#ff507d" + }, + "image": "https://gw.alicdn.com/imgextra/i3/117/O1CN01rIvTiI1CjcweVVOUY_!!117-2-lubanu.png_125x125q90_.webp" + }, + { + "image": "https://gw.alicdn.com/imgextra/i3/13/O1CN016ZFbmU1BxzjHpTXkD_!!13-0-lubanu.jpg_180x180q90_.webp" + } + ] + }, + { + "titleImage": "https://gw.alicdn.com/imgextra/i2/O1CN01AeZ5mk1IhEf54f1Ce_!!6000000000924-2-tps-512-63.png", + "items": [ + { + "tag": { + "text": "限时半价", + "color": "#fa2a59" + }, + "image": "https://gw.alicdn.com/imgextra/i2/2/TB2m7tdwf5TBuNjSspmXXaDRVXa_!!2-2-luban.png_125x125q90_.webp" + }, + { + "tag": { + "text": "9.9包邮", + "color": "#ff4c09" + }, + "image": "https://img.alicdn.com/tps/O1CN01FIpNiW1dBjLTfoIY2_!!6000000003698-0-yinhe.jpg_125x125q90_.webp" + } + ] + }, + { + "titleImage": "https://gw.alicdn.com/tfs/TB1Cbq1mrj1gK0jSZFuXXcrHpXa-525-60.png?getAvatar=1_360x360q90_.webp", + "items": [ + { + "tag": { + "text": "全民口碑推荐", + "color": "#50bdff" + }, + "image": "https://gw.alicdn.com/imgextra/i1/142/O1CN01X7HlmC1Cv4qfUnwxD_!!142-2-lubanu.png_125x125q90_.webp" + }, + { + "image": "https://gw.alicdn.com/imgextra/i2/44/O1CN01BfHIWX1CCBzZeHzQc_!!44-0-lubanu.jpg_180x180q90_.webp" + } + ] + }, + { + "titleImage": "https://gw.alicdn.com/tfs/TB1lfyQmpY7gK0jSZKzXXaikpXa-525-60.png?getAvatar=1_360x360q90_.webp", + "items": [ + { + "tag": { + "text": "挖深藏的店", + "color": "#f9a500" + }, + "image": "https://gw.alicdn.com/imgextra/i4/159/O1CN01hjIr8a1D2rds9SPtB_!!159-2-lubanu.png_125x125q90_.webp" + }, + { + "image": "https://gw.alicdn.com/imgextra/i4/23/O1CN01qKCpqs1C2ZmWlfHra_!!23-0-lubanu.jpg_180x180q90_.webp" + } + ] + }, + { + "titleImage": "https://gw.alicdn.com/tfs/TB1jkazoAL0gK0jSZFAXXcA9pXa-525-60.png?getAvatar=1_360x360q90_.webp", + "items": [ + { + "tag": { + "text": "粉丝都爱看", + "color": "#ff611d" + }, + "image": "https://gw.alicdn.com/imgextra/i2/173/TB2LZERnpOWBuNjy0FiXXXFxVXa_!!173-2-luban.png_125x125q90_.webp" + }, + { + "image": "https://gw.alicdn.com/imgextra/i1/124/TB2ZxuTd5MnBKNjSZFCXXX0KFXa_!!124-0-luban.jpg_180x180q90_.webp" + } + ] + } +] diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/index.module.css b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/index.module.css new file mode 100644 index 0000000..85b447b --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/index.module.css @@ -0,0 +1,13 @@ +.container { + position: relative; + margin: 20rpx 18rpx 0; + border-radius: 12rpx; + background-color: #fff; + width: 714rpx; +} + +.items { + flex-direction: row; + flex-wrap: wrap; + margin-bottom: 20rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/components/ItemWrap/index.tsx b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/index.tsx new file mode 100644 index 0000000..74bca3c --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/ItemWrap/index.tsx @@ -0,0 +1,24 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Card from './Card'; +import News from './News'; + +// mock data +import data from './data.json'; + +import styles from './index.module.css'; + +function ItemWrap() { + return ( + <View className={styles.container}> + <View className={styles.items}> + {data.map((item, index) => { + return <Card key={`card${index}`} titleImage={item.titleImage} items={item.items} index={index} />; + })} + </View> + <News /> + </View> + ); +} + +export default ItemWrap; diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/Nav.module.css b/scaffolds/app-shop/src/pages/Home/components/NavList/Nav.module.css new file mode 100644 index 0000000..7ec644e --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/Nav.module.css @@ -0,0 +1,22 @@ +.nav { + flex-direction: column; + -webkit-box-align: center; + align-items: center; + height: 134rpx; + width: 122rpx; + margin-top: 6rpx; + margin-left: 23rpx; +} + +.image { + width: 122rpx; + height: 96rpx; +} + +.text { + text-align: center; + margin-top: 8rpx; + line-height: 30rpx; + font-size: 22rpx; + color: #666; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/Nav.tsx b/scaffolds/app-shop/src/pages/Home/components/NavList/Nav.tsx new file mode 100644 index 0000000..24a8c40 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/Nav.tsx @@ -0,0 +1,23 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Nav.module.css'; + +interface IProps { + image: string; + text: string; +} + +function Nav(props: IProps) { + const { image, text } = props; + return ( + <View className={styles.nav}> + <Image className={styles.image} source={{ uri: image }} /> + <Text className={styles.text}>{text}</Text> + </View> + ); +} + +export default Nav; diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/Scrollbar.module.css b/scaffolds/app-shop/src/pages/Home/components/NavList/Scrollbar.module.css new file mode 100644 index 0000000..c5138ed --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/Scrollbar.module.css @@ -0,0 +1,20 @@ +.container { + text-align: center; + padding: 28rpx 0 18rpx; +} + +.scrollbar { + position: relative; + margin: 0 auto; + width: 100rpx; + height: 6rpx; + border-radius: 6rpx; + background-color: #d4d8de; + overflow: hidden; +} + +.drag { + position: relative; + background-color: #ff6d2a; + height: 6rpx; +} diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/Scrollbar.tsx b/scaffolds/app-shop/src/pages/Home/components/NavList/Scrollbar.tsx new file mode 100644 index 0000000..8d7ad1a --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/Scrollbar.tsx @@ -0,0 +1,52 @@ +import { createElement, useEffect, forwardRef, useImperativeHandle, useState } from 'rax'; +import View from 'rax-view'; +import { getInfoSync } from '@uni/system-info'; +import { getBoundingClientRect } from '@uni/element'; +import type { ScrollEvent } from 'rax-scrollview'; +import styles from './Scrollbar.module.css'; + +interface IProps { + target: string; +} +export interface IRefObject { + handleTargetScroll: (e: ScrollEvent) => void; +} + +function Scrollbar(props, ref) { + const { target } = props; + + const [dragWidth, setDragWidth] = useState(0); + const [dragTX, setDragTX] = useState(0); + + useImperativeHandle(ref, () => ({ + handleTargetScroll: (e) => { + setDragTX(e.nativeEvent.contentOffset?.x / e.nativeEvent.contentSize?.width * 100); + }, + })); + + useEffect(() => { + setTimeout(() => { + // 兼容异步渲染的小程序 + const { screenWidth } = getInfoSync(); + getBoundingClientRect(target).then((ret) => { + setDragWidth(screenWidth / ret[0].width); + }); + }, 0); + }, []); + + return ( + <View className={styles.container}> + <View className={styles.scrollbar}> + <View + className={styles.drag} + style={{ + width: `${Math.round(dragWidth * 100)}%`, + transform: `translateX(${dragTX}rpx)`, + }} + /> + </View> + </View> + ); +} + +export default forwardRef<IRefObject, IProps>(Scrollbar); diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/data.json b/scaffolds/app-shop/src/pages/Home/components/NavList/data.json new file mode 100644 index 0000000..752c7d0 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/data.json @@ -0,0 +1,74 @@ +[ + { + "icon": "https://gw.alicdn.com/tfs/TB1OIxTcLc3T1VjSZLeXXbZsVXa-183-144.png?getAvatar=1", + "text": "天猫新品" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1llI3f4n1gK0jSZKPXXXvUXXa-183-144.png?getAvatar=1", + "text": "充值中心" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1LvIxVAvoK1RjSZFDXXXY3pXa-183-144.png?getAvatar=1", + "text": "今日爆款" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1O_AyVwHqK1RjSZFPXXcwapXa-183-144.png?getAvatar=1", + "text": "机票酒店" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB19uWKXkCy2eVjSZPfXXbdgpXa-183-144.png?getAvatar=1", + "text": "天猫国际" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB19yZJVBLoK1RjSZFuXXXn0XXa-183-144.png?getAvatar=1", + "text": "金币庄园" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1DaMyVpzqK1RjSZFoXXbfcXXa-185-144.png?getAvatar=1", + "text": "饿了么" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB16ZYDk4n1gK0jSZKPXXXvUXXa-183-144.png?getAvatar=1", + "text": "阿里拍卖" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1FucwVwHqK1RjSZFgXXa7JXXa-183-144.png?getAvatar=1", + "text": "天猫超市" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB19dcwVyrpK1RjSZFhXXXSdXXa-183-144.png?getAvatar=1", + "text": "淘宝吃货" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1nBktVxTpK1RjSZR0XXbEwXXa-183-144.png?getAvatar=1", + "text": "分类" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1CoEwVrvpK1RjSZFqXXcXUVXa-185-144.png?getAvatar=1", + "text": "闲鱼" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1fcOKXkCy2eVjSZSyXXXukVXa-183-144.png?getAvatar=1", + "text": "天猫美食" + }, + { + "icon": "https://img.alicdn.com/tfs/TB1FyEazAY2gK0jSZFgXXc5OFXa-183-144.png?getAvatar=1", + "text": "会员中心" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1tikBVAPoK1RjSZKbXXX1IXXa-183-144.png?getAvatar=1", + "text": "阿里健康" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1xcTYxFT7gK0jSZFpXXaTkpXa-183-144.png?getAvatar=1", + "text": "造点新货" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1h1MnVCrqK1RjSZK9XXXyypXa-183-144.png?getAvatar=1", + "text": "口碑生活" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB11tFkr7L0gK0jSZFxXXXWHVXa-183-144.png?getAvatar=1", + "text": "土货鲜食" + } +] diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/index.module.css b/scaffolds/app-shop/src/pages/Home/components/NavList/index.module.css new file mode 100644 index 0000000..7e1e0ba --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/index.module.css @@ -0,0 +1,17 @@ +.navList { + margin-top: -5rpx; + background-color: #fff; + width: 750rpx; + max-height: 360rpx; +} + +.wrap { + max-height: 305rpx; +} + +.list { + max-height: 305rpx; + overflow-x: auto; + flex-direction: row; + padding-right: 23rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/components/NavList/index.tsx b/scaffolds/app-shop/src/pages/Home/components/NavList/index.tsx new file mode 100644 index 0000000..36617be --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/components/NavList/index.tsx @@ -0,0 +1,47 @@ +import { createElement, useRef } from 'rax'; +import View from 'rax-view'; +import ScrollView from 'rax-scrollview'; +import throttle from 'lodash.throttle'; +import { isWeChatMiniProgram } from '@uni/env'; +import Nav from './Nav'; +import Scrollbar, { IRefObject } from './Scrollbar'; + +// mock data +import data from './data.json'; + +import styles from './index.module.css'; + +function NavList() { + const scrollbarRef = useRef<IRefObject>(null); + return ( + <View className={styles.navList}> + <ScrollView + className={styles.wrap} + horizontal + showsHorizontalScrollIndicator={false} + showsVerticalScrollIndicator={false} + onScroll={throttle((e) => { scrollbarRef.current?.handleTargetScroll(e); }, isWeChatMiniProgram ? 160 : 0)} + > + <View className={styles.list} id="navList"> + {data.map((item, index) => { + if (index % 2 === 0) { + const nextItem = data[index + 1]; + return ( + <View key={`item${item.text}`}> + <Nav image={item.icon} text={item.text} /> + <View style={{ marginTop: '24rpx' }}> + <Nav image={nextItem.icon} text={nextItem.text} /> + </View> + </View> + ); + } + return null; + })} + </View> + </ScrollView> + <Scrollbar ref={scrollbarRef} target="#navList" /> + </View> + ); +} + +export default NavList; diff --git a/scaffolds/app-shop/src/pages/Home/index.module.css b/scaffolds/app-shop/src/pages/Home/index.module.css new file mode 100644 index 0000000..febd26e --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/index.module.css @@ -0,0 +1,9 @@ +.container { + align-items: center; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #f4f4f4; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Home/index.tsx b/scaffolds/app-shop/src/pages/Home/index.tsx new file mode 100644 index 0000000..df564d8 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Home/index.tsx @@ -0,0 +1,44 @@ +import { createElement, useState, useRef } from 'rax'; +import View from 'rax-view'; +import RecyclerView from 'rax-recyclerview'; +import GoTop from '@/components/GoGtop'; +import ItemList, { IRefObject } from '@/components/ItemList'; +import Header from './components/Header'; +import Banner from './components/Banner'; +import NavList from './components/NavList'; +import ItemWrap from './components/ItemWrap'; + +import styles from './index.module.css'; + +export default function Home() { + const [showGoTop, setShowGoTop] = useState(false); + + const itemListRef = useRef<IRefObject>(null); + const recyclerViewRef = useRef<any>(null); + + const handlerScroll = (e) => { + const { contentOffset } = e.nativeEvent; + if (contentOffset.y >= 500) { + setShowGoTop(true); + } else { + setShowGoTop(false); + } + }; + + return ( + <View className={styles.container}> + <Header /> + <RecyclerView + ref={recyclerViewRef} + onScroll={handlerScroll} + onEndReached={() => { itemListRef.current?.loadItems(); }} + > + <Banner /> + <NavList /> + <ItemWrap /> + <ItemList ref={itemListRef} /> + <GoTop x-if={showGoTop} onClick={() => { recyclerViewRef.current?.scrollTo({ y: 0 }); }} /> + </RecyclerView> + </View> + ); +} diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/Avatar.module.css b/scaffolds/app-shop/src/pages/Mine/components/Header/Avatar.module.css new file mode 100644 index 0000000..3bd47d5 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/Avatar.module.css @@ -0,0 +1,27 @@ +.container { + position: relative; + margin: 56rpx 0 0 36rpx; + width: 98rpx; + height: 98rpx; +} + +.avatar { + width: 98rpx; + height: 98rpx; + border-radius: 50rpx; + border: 2rpx solid #fff; + overflow: hidden; +} + +.crown { + position: absolute; + top: -15rpx; + right: -5rpx; + width: 36rpx; + height: 36rpx; +} + +.user { + width: 98rpx; + height: 98rpx; +} diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/Avatar.tsx b/scaffolds/app-shop/src/pages/Mine/components/Header/Avatar.tsx new file mode 100644 index 0000000..03302c6 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/Avatar.tsx @@ -0,0 +1,18 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Image from 'rax-image'; + +import styles from './Avatar.module.css'; + +function Avatar() { + return ( + <View className={styles.container}> + <Image className={styles.crown} source={{ uri: 'https://gw.alicdn.com/tfs/TB103uFg49YBuNjy0FfXXXIsVXa-60-60.png?getAvatar=avatar_40x40q90_.webp' }} /> + <View className={styles.avatar}> + <Image className={styles.user} source={{ uri: 'https://gw.alicdn.com/tps/i3/TB1yeWeIFXXXXX5XFXXuAZJYXXX-210-210.png_50x50.jpg' }} /> + </View> + </View> + ); +} + +export default Avatar; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/Base.module.css b/scaffolds/app-shop/src/pages/Mine/components/Header/Base.module.css new file mode 100644 index 0000000..c343599 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/Base.module.css @@ -0,0 +1,26 @@ +.container { + margin-top: 20rpx; + flex-direction: row; + justify-content: space-between; +} + +.left { + flex-direction: row; +} + +.name { + margin: 50rpx 0 0 24rpx; + color: #fff; + font-size: 40rpx; +} + +.right { + margin-top: 50rpx; + flex-direction: row; +} + +.icon { + margin-right: 40rpx; + width: 40rpx; + height: 40rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/Base.tsx b/scaffolds/app-shop/src/pages/Mine/components/Header/Base.tsx new file mode 100644 index 0000000..d7d0558 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/Base.tsx @@ -0,0 +1,24 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; +import Avatar from './Avatar'; + +import styles from './Base.module.css'; + +function Base() { + return ( + <View className={styles.container}> + <View className={styles.left}> + <Avatar /> + <Text className={styles.name}>Hello World</Text> + </View> + <View className={styles.right}> + <Image className={styles.icon} source={{ uri: 'https://gw.alicdn.com/tfs/TB1tcovekL0gK0jSZFxXXXWHVXa-54-54.png_48x48q90_.webp' }} /> + <Image className={styles.icon} source={{ uri: 'https://gw.alicdn.com/tfs/TB1dbweXwHqK1RjSZFgXXa7JXXa-57-54.png_48x48q90_.webp' }} /> + </View> + </View > + ); +} + +export default Base; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/Favorite.module.css b/scaffolds/app-shop/src/pages/Mine/components/Header/Favorite.module.css new file mode 100644 index 0000000..bd1d735 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/Favorite.module.css @@ -0,0 +1,20 @@ +.container { + margin-top: 32rpx; + flex-direction: row; +} + +.card { + text-align: center; + width: 180rpx; +} + +.count { + font-size: 28rpx; + color: #fff; +} + +.label { + margin-top: 10rpx; + font-size: 24rpx; + color: #fff; +} diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/Favorite.tsx b/scaffolds/app-shop/src/pages/Mine/components/Header/Favorite.tsx new file mode 100644 index 0000000..66366b9 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/Favorite.tsx @@ -0,0 +1,30 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; + +import styles from './Favorite.module.css'; + +function Favorite() { + return ( + <View className={styles.container}> + <View className={styles.card}> + <Text className={styles.count}>123</Text> + <Text className={styles.label}>收藏夹</Text> + </View> + <View className={styles.card}> + <Text className={styles.count}>123</Text> + <Text className={styles.label}>关注店铺</Text> + </View> + <View className={styles.card}> + <Text className={styles.count}>123</Text> + <Text className={styles.label}>足迹</Text> + </View> + <View className={styles.card}> + <Text className={styles.count}>123</Text> + <Text className={styles.label}>红包卡券</Text> + </View> + </View> + ); +} + +export default Favorite; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/index.module.css b/scaffolds/app-shop/src/pages/Mine/components/Header/index.module.css new file mode 100644 index 0000000..4cf9b2c --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/index.module.css @@ -0,0 +1,7 @@ +.container { + position: relative; + width: 750rpx; + height: 340rpx; + background-color: #ff5000; + background-image: linear-gradient(to right, #fd9126, #ff5000); +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Header/index.tsx b/scaffolds/app-shop/src/pages/Mine/components/Header/index.tsx new file mode 100644 index 0000000..78da1dc --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Header/index.tsx @@ -0,0 +1,17 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Base from './Base'; +import Favorite from './Favorite'; + +import styles from './index.module.css'; + +function Header() { + return ( + <View className={styles.container}> + <Base /> + <Favorite /> + </View> + ); +} + +export default Header; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Order/Card.module.css b/scaffolds/app-shop/src/pages/Mine/components/Order/Card.module.css new file mode 100644 index 0000000..993c5f4 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Order/Card.module.css @@ -0,0 +1,36 @@ +.container { + position: relative; + width: 140rpx; + height: 152rpx; + align-items: center; + justify-content: center; +} + + +.count { + position: absolute; + top: 20rpx; + right: 24rpx; + padding: 0 8rpx; + height: 32rpx; + line-height: 30rpx; + border-radius: 20rpx; + border: 2rpx solid #f50; + background: #fff; +} + +.countNumber { + color: #f50; + font-size: 22rpx; +} + +.icon { + width: 58rpx; + height: 58rpx; +} + +.title { + margin-top: 12rpx; + font-size: 24rpx; + color: #666; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Order/Card.tsx b/scaffolds/app-shop/src/pages/Mine/components/Order/Card.tsx new file mode 100644 index 0000000..4bb8f01 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Order/Card.tsx @@ -0,0 +1,28 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Card.module.css'; + +interface IProps { + title: string; + icon: string; + count: number; +} + +function Card(props: IProps) { + const { title, icon, count } = props; + + return ( + <View className={styles.container}> + <View x-if={count} className={styles.count} > + <Text className={styles.countNumber}>{count}</Text> + </View> + <Image className={styles.icon} source={{ uri: icon }} /> + <Text className={styles.title} >{title}</Text> + </View> + ); +} + +export default Card; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Order/Header.module.css b/scaffolds/app-shop/src/pages/Mine/components/Order/Header.module.css new file mode 100644 index 0000000..fa11cdc --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Order/Header.module.css @@ -0,0 +1,30 @@ +.container { + height: 76rpx; + flex-direction: row; + align-items: center; + justify-content: space-between; + border-bottom: 2rpx solid #eeeee7; +} + +.title { + margin-left: 23rpx; + color: #333; + font-weight: bold; + font-size: 28rpx; +} + +.extra { + margin-right: 23rpx; + flex-direction: row; + align-items: center; +} + +.extraText { + color: #999; + font-size: 24rpx; +} + +.arrow { + width: 28rpx; + height: 28rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Order/Header.tsx b/scaffolds/app-shop/src/pages/Mine/components/Order/Header.tsx new file mode 100644 index 0000000..169301a --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Order/Header.tsx @@ -0,0 +1,20 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Header.module.css'; + +function Header() { + return ( + <View className={styles.container}> + <Text className={styles.title}>我的订单</Text> + <View className={styles.extra}> + <Text className={styles.extraText}>查看全部订单</Text> + <Image className={styles.arrow} source={{ uri: 'https://img.alicdn.com/imgextra/i3/O1CN014Rz7lW1LDPimYq8rD_!!6000000001265-2-tps-200-200.png' }} /> + </View> + </View> + ); +} + +export default Header; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Order/index.module.css b/scaffolds/app-shop/src/pages/Mine/components/Order/index.module.css new file mode 100644 index 0000000..773461f --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Order/index.module.css @@ -0,0 +1,9 @@ +.container { + margin: 20rpx 24rpx; + width: 702rpx; + background: #fff; +} + +.body { + flex-direction: row; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Order/index.tsx b/scaffolds/app-shop/src/pages/Mine/components/Order/index.tsx new file mode 100644 index 0000000..e31c188 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Order/index.tsx @@ -0,0 +1,23 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Header from './Header'; +import Card from './Card'; + +import styles from './index.module.css'; + +function Order() { + return ( + <View className={styles.container}> + <Header /> + <View className={styles.body}> + <Card count={0} title="待付款" icon="https://gw.alicdn.com/tfs/TB135Ipp.H1gK0jSZSyXXXtlpXa-87-87.png_60x60q90_.webp" /> + <Card count={3} title="待发货" icon="https://gw.alicdn.com/tfs/TB1DdAqp.Y1gK0jSZFMXXaWcVXa-87-87.png_60x60q90_.webp" /> + <Card count={1} title="待收货" icon="https://gw.alicdn.com/tfs/TB1b3zgmMmTBuNjy1XbXXaMrVXa-87-87.png_60x60q90_.webp" /> + <Card count={7} title="评价" icon="https://gw.alicdn.com/tfs/TB1fOKqm_tYBeNjy1XdXXXXyVXa-87-87.png_60x60q90_.webp" /> + <Card count={0} title="退款/售后" icon="https://gw.alicdn.com/tfs/TB1fMzgmMmTBuNjy1XbXXaMrVXa-87-87.png_60x60q90_.webp" /> + </View> + </View> + ); +} + +export default Order; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/Card.module.css b/scaffolds/app-shop/src/pages/Mine/components/Tools/Card.module.css new file mode 100644 index 0000000..adbffb8 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/Card.module.css @@ -0,0 +1,18 @@ +.container { + position: relative; + width: 172rpx; + height: 160rpx; + align-items: center; + justify-content: center; +} + +.icon { + width: 58rpx; + height: 58rpx; +} + +.name { + margin-top: 12rpx; + font-size: 24rpx; + color: #666; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/Card.tsx b/scaffolds/app-shop/src/pages/Mine/components/Tools/Card.tsx new file mode 100644 index 0000000..4651eda --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/Card.tsx @@ -0,0 +1,24 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Card.module.css'; + +interface IProps { + name: string; + icon: string; +} + +function Card(props: IProps) { + const { name, icon } = props; + + return ( + <View className={styles.container}> + <Image className={styles.icon} source={{ uri: icon }} /> + <Text className={styles.name} >{name}</Text> + </View> + ); +} + +export default Card; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/Header.module.css b/scaffolds/app-shop/src/pages/Mine/components/Tools/Header.module.css new file mode 100644 index 0000000..fa11cdc --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/Header.module.css @@ -0,0 +1,30 @@ +.container { + height: 76rpx; + flex-direction: row; + align-items: center; + justify-content: space-between; + border-bottom: 2rpx solid #eeeee7; +} + +.title { + margin-left: 23rpx; + color: #333; + font-weight: bold; + font-size: 28rpx; +} + +.extra { + margin-right: 23rpx; + flex-direction: row; + align-items: center; +} + +.extraText { + color: #999; + font-size: 24rpx; +} + +.arrow { + width: 28rpx; + height: 28rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/Header.tsx b/scaffolds/app-shop/src/pages/Mine/components/Tools/Header.tsx new file mode 100644 index 0000000..ea131e0 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/Header.tsx @@ -0,0 +1,20 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Text from 'rax-text'; +import Image from 'rax-image'; + +import styles from './Header.module.css'; + +function Header() { + return ( + <View className={styles.container}> + <Text className={styles.title}>必备工具</Text> + <View className={styles.extra}> + <Text className={styles.extraText}>查看全部工具</Text> + <Image className={styles.arrow} source={{ uri: 'https://img.alicdn.com/imgextra/i3/O1CN014Rz7lW1LDPimYq8rD_!!6000000001265-2-tps-200-200.png' }} /> + </View> + </View> + ); +} + +export default Header; diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/data.json b/scaffolds/app-shop/src/pages/Mine/components/Tools/data.json new file mode 100644 index 0000000..fa5f8da --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/data.json @@ -0,0 +1,33 @@ +[{ + "icon": "https://gw.alicdn.com/tfs/TB1Jcbkj4D1gK0jSZFsXXbldVXa-96-96.png_70x70q90_.webp", + "name": "每日返现" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1zT0hkkT2gK0jSZPcXXcKkpXa-96-96.png_70x70q90_.webp", + "name": "领劵中心" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB14QMupYj1gK0jSZFuXXcrHpXa-96-96.png_70x70q90_.webp", + "name": "闲置换钱" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1csUri13tHKVjSZSgXXX4QFXa-96-96.png_70x70q90_.webp", + "name": "客服小蜜" + }, + { + "icon": "https://gw.alicdn.com/tps/TB1rhCFPXXXXXa1XVXXXXXXXXXX-96-96.png_70x70q90_.webp", + "name": "花呗" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1S6oYmQL0gK0jSZFxXXXWHVXa-96-96.png_70x70q90_.webp", + "name": "我的快递" + }, + { + "icon": "https://gw.alicdn.com/tps/TB1RN1QPXXXXXaqXFXXXXXXXXXX-96-96.png_70x70q90_.webp", + "name": "我的评价" + }, + { + "icon": "https://gw.alicdn.com/tfs/TB1q0T8mpOWBuNjy0FiXXXFxVXa-96-96.png_70x70q90_.webp", + "name": "主体皮肤" + } +] \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/index.module.css b/scaffolds/app-shop/src/pages/Mine/components/Tools/index.module.css new file mode 100644 index 0000000..aadae2c --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/index.module.css @@ -0,0 +1,11 @@ +.container { + margin: 20rpx 24rpx; + width: 702rpx; + background: #fff; +} + +.body { + flex-direction: row; + flex-wrap: wrap; + width: 702rpx; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/components/Tools/index.tsx b/scaffolds/app-shop/src/pages/Mine/components/Tools/index.tsx new file mode 100644 index 0000000..85034b1 --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/components/Tools/index.tsx @@ -0,0 +1,24 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Header from './Header'; +import Card from './Card'; + +// mock data +import data from './data.json'; + +import styles from './index.module.css'; + +function Tools() { + return ( + <View className={styles.container}> + <Header /> + <View className={styles.body}> + {data.map((item) => { + return <Card key={item.name} name={item.name} icon={item.icon} />; + })} + </View> + </View> + ); +} + +export default Tools; diff --git a/scaffolds/app-shop/src/pages/Mine/index.module.css b/scaffolds/app-shop/src/pages/Mine/index.module.css new file mode 100644 index 0000000..febd26e --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/index.module.css @@ -0,0 +1,9 @@ +.container { + align-items: center; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #f4f4f4; +} \ No newline at end of file diff --git a/scaffolds/app-shop/src/pages/Mine/index.tsx b/scaffolds/app-shop/src/pages/Mine/index.tsx new file mode 100644 index 0000000..fd5679b --- /dev/null +++ b/scaffolds/app-shop/src/pages/Mine/index.tsx @@ -0,0 +1,19 @@ +import { createElement } from 'rax'; +import View from 'rax-view'; +import Header from './components/Header'; +import Order from './components/Order'; +import Tools from './components/Tools'; + +import styles from './index.module.css'; + +function Mine() { + return ( + <View className={styles.container}> + <Header /> + <Order /> + <Tools /> + </View> + ); +} + +export default Mine; diff --git a/scaffolds/app-shop/src/typings.d.ts b/scaffolds/app-shop/src/typings.d.ts new file mode 100644 index 0000000..3d673e2 --- /dev/null +++ b/scaffolds/app-shop/src/typings.d.ts @@ -0,0 +1,4 @@ +declare module '*.module.css' { + const classes: { [key: string]: string }; + export default classes; +} diff --git a/scaffolds/app-shop/tsconfig.json b/scaffolds/app-shop/tsconfig.json new file mode 100644 index 0000000..a4bc8d6 --- /dev/null +++ b/scaffolds/app-shop/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compileOnSave": false, + "buildOnSave": false, + "compilerOptions": { + "resolveJsonModule": true, + "baseUrl": ".", + "outDir": "build", + "module": "esnext", + "target": "es6", + "jsx": "preserve", + "jsxFactory": "createElement", + "moduleResolution": "node", + "allowSyntheticDefaultImports": true, + "lib": ["es6", "dom"], + "sourceMap": true, + "allowJs": true, + "rootDir": "./", + "forceConsistentCasingInFileNames": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": false, + "importHelpers": true, + "strictNullChecks": true, + "suppressImplicitAnyIndexErrors": true, + "noUnusedLocals": true, + "skipLibCheck": true, + "types": ["node", "jest"], + "paths": { + "@/*": ["./src/*"], + "rax-app": [".rax/index.ts"] + } + }, + "include": ["src", ".rax"], + "exclude": ["node_modules", "build", "public"] +} \ No newline at end of file diff --git a/scripts/checkPackagePublished.ts b/scripts/checkPackagePublished.ts index 2c80bd6..347921c 100644 --- a/scripts/checkPackagePublished.ts +++ b/scripts/checkPackagePublished.ts @@ -6,7 +6,7 @@ export default function checkPackagePublished() { const publishedPackages: string[] = getPublishedPackages(); const timeout = 10000; - const maxDetectTimes = 18; // wait 3 minutes + const maxDetectTimes = 30; // wait 5 minutes return Promise.all( publishedPackages.map((publishedPackage) => { return new Promise((resolve, retject) => { diff --git a/scripts/ejsRender/copy.ts b/scripts/ejsRender/copy.ts new file mode 100644 index 0000000..60952c6 --- /dev/null +++ b/scripts/ejsRender/copy.ts @@ -0,0 +1,16 @@ +import * as fs from 'fs-extra'; +import * as path from 'path'; + +const ignores = ['node_modules/']; + +export default function copy(from: string, to: string) { + const reg = new RegExp(ignores.map((ignore) => path.join(from, ignore)).join('|')); + fs.copySync(from, to, { + filter: (src: string) => { + if (reg.test(src)) { + return false; + } + return true; + }, + }); +} diff --git a/scripts/ejsRender/generate.ts b/scripts/ejsRender/generate.ts index 1a81f23..c8896f9 100644 --- a/scripts/ejsRender/generate.ts +++ b/scripts/ejsRender/generate.ts @@ -1,8 +1,8 @@ /* eslint-disable no-await-in-loop */ // render a scaffold ejs template to temp dir -import * as fs from 'fs-extra'; import * as path from 'path'; import { formatScaffoldToProject } from '@iceworks/generate-project'; +import copy from './copy'; import { IConfig, IScaffold } from './interface'; import * as config from '../../ejsRender.config'; @@ -12,14 +12,14 @@ export default async function (scaffoldConfig: IScaffold) { const tempTarget = path.join(tmpDir, '.temp', name); - fs.copySync(target, tempTarget); + copy(target, tempTarget); try { console.log(`Generating ${name} project...`); await formatScaffoldToProject(tempTarget, '', data); // Why copy twice? Because the target project may contain the node_modules. - fs.copySync(tempTarget, path.join(tmpDir, name)); + copy(tempTarget, path.join(tmpDir, name)); } catch (e) { console.log(`Format scaffold '${target}' error:`, e); } diff --git a/scripts/ejsRender/prePublish.ts b/scripts/ejsRender/prePublish.ts index fce5433..9f35284 100644 --- a/scripts/ejsRender/prePublish.ts +++ b/scripts/ejsRender/prePublish.ts @@ -3,6 +3,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; import { spawnSync } from 'child_process'; import { IConfig } from './interface'; +import copy from './copy'; import * as config from '../../ejsRender.config'; const BUILD_DIR = 'build'; @@ -57,12 +58,12 @@ export default function (directory: string) { cwd: targetDir, }, ); - fs.copySync(path.join(targetDir, BUILD_DIR), path.join(directory, BUILD_DIR)); + copy(path.join(targetDir, BUILD_DIR), path.join(directory, BUILD_DIR)); // Use web result as scaffold home page const webResult = path.join(directory, BUILD_DIR, 'web'); if (fs.existsSync(webResult)) { - fs.copySync(webResult, path.join(directory, BUILD_DIR)); + copy(webResult, path.join(directory, BUILD_DIR)); } } } diff --git a/scripts/ejsRender/watch.ts b/scripts/ejsRender/watch.ts index 3403ecd..296d331 100644 --- a/scripts/ejsRender/watch.ts +++ b/scripts/ejsRender/watch.ts @@ -2,6 +2,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; import * as chokidar from 'chokidar'; +import copy from './copy'; import generate from './generate'; import { IConfig } from './interface'; import * as config from '../../ejsRender.config'; @@ -16,7 +17,7 @@ chokidar.watch(path.join(__dirname, '../../scaffolds/'), { ignoreInitial: true } generate(scaffoldConfig); } else { // do copy - fs.copySync(file, path.join(tmpDir, scaffoldConfig.name, file.replace(scaffoldConfig.target, ''))); + copy(file, path.join(tmpDir, scaffoldConfig.name, file.replace(scaffoldConfig.target, ''))); } } });