通过微信开发者工具 商城模板 创建新小程序
This commit is contained in:
parent
ada464a8cc
commit
c21ff901d5
160
mini-program/.eslintrc.js
Normal file
160
mini-program/.eslintrc.js
Normal file
@ -0,0 +1,160 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
commonjs: true,
|
||||
es6: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
// ECMAScript modules 模式
|
||||
sourceType: 'module',
|
||||
},
|
||||
extends: ['plugin:prettier/recommended', 'prettier'],
|
||||
globals: {
|
||||
wx: true,
|
||||
App: true,
|
||||
Page: true,
|
||||
Component: true,
|
||||
getApp: true,
|
||||
getCurrentPages: true,
|
||||
Behavior: true,
|
||||
global: true,
|
||||
__wxConfig: true,
|
||||
},
|
||||
ignorePatterns: ['*.wxs'],
|
||||
rules: {
|
||||
'prettier/prettier': 'warn',
|
||||
'no-undef': 'off',
|
||||
camelcase: ['error', { ignoreDestructuring: true }],
|
||||
'class-name-casing': 'off',
|
||||
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
||||
'no-debugger': 'error',
|
||||
'no-unused-expressions': [
|
||||
'error',
|
||||
{ allowShortCircuit: true, allowTernary: true },
|
||||
],
|
||||
'no-empty-interface': 'off',
|
||||
'no-use-before-define': ['error', { functions: false }],
|
||||
'no-useless-constructor': 'error',
|
||||
'prefer-const': 'error',
|
||||
'prefer-destructuring': [
|
||||
'error',
|
||||
{
|
||||
AssignmentExpression: {
|
||||
array: false,
|
||||
object: false,
|
||||
},
|
||||
VariableDeclarator: {
|
||||
array: false,
|
||||
object: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
enforceForRenamedProperties: false,
|
||||
},
|
||||
],
|
||||
'no-const-assign': 'error',
|
||||
'no-new-object': 'error',
|
||||
'no-prototype-builtins': 'error',
|
||||
'no-array-constructor': 'error',
|
||||
'array-callback-return': 'warn',
|
||||
'prefer-template': 'error',
|
||||
'no-useless-escape': 'error',
|
||||
'wrap-iife': ['error', 'outside'],
|
||||
'space-before-function-paren': [
|
||||
'warn',
|
||||
{
|
||||
anonymous: 'always',
|
||||
named: 'never',
|
||||
asyncArrow: 'always',
|
||||
},
|
||||
],
|
||||
'no-param-reassign': [
|
||||
'warn',
|
||||
{
|
||||
props: true,
|
||||
ignorePropertyModificationsFor: [
|
||||
'acc', // for reduce accumulators
|
||||
'accumulator', // for reduce accumulators
|
||||
'e', // for e.returnvalue
|
||||
'ctx', // for Koa routing
|
||||
'req', // for Express requests
|
||||
'request', // for Express requests
|
||||
'res', // for Express responses
|
||||
'response', // for Express responses
|
||||
'$scope', // for Angular 1 scopes
|
||||
'staticContext', // for ReactRouter context
|
||||
'state', // for Vuex
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-confusing-arrow': 'warn',
|
||||
'no-dupe-class-members': 'error',
|
||||
'no-iterator': 'warn',
|
||||
'dot-notation': 'warn',
|
||||
'one-var': ['warn', 'never'],
|
||||
'no-multi-assign': 'error',
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
args: 'after-used',
|
||||
ignoreRestSiblings: true,
|
||||
argsIgnorePattern: '^_.+',
|
||||
varsIgnorePattern: '^_.+',
|
||||
},
|
||||
],
|
||||
eqeqeq: ['warn', 'always'],
|
||||
'no-case-declarations': 'error',
|
||||
'no-nested-ternary': 'warn',
|
||||
'no-unneeded-ternary': 'warn',
|
||||
'no-mixed-operators': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
['%', '**'],
|
||||
['%', '+'],
|
||||
['%', '-'],
|
||||
['%', '*'],
|
||||
['%', '/'],
|
||||
['&', '|', '<<', '>>', '>>>'],
|
||||
['==', '!=', '===', '!=='],
|
||||
['&&', '||'],
|
||||
],
|
||||
allowSamePrecedence: false,
|
||||
},
|
||||
],
|
||||
'no-else-return': [
|
||||
'warn',
|
||||
{
|
||||
allowElseIf: false,
|
||||
},
|
||||
],
|
||||
'no-new-wrappers': 'warn',
|
||||
indent: [
|
||||
'warn',
|
||||
2,
|
||||
{
|
||||
SwitchCase: 1,
|
||||
VariableDeclarator: 1,
|
||||
outerIIFEBody: 1,
|
||||
FunctionDeclaration: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
FunctionExpression: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
CallExpression: {
|
||||
arguments: 1,
|
||||
},
|
||||
ArrayExpression: 1,
|
||||
ObjectExpression: 1,
|
||||
ImportDeclaration: 1,
|
||||
flatTernaryExpressions: false,
|
||||
ignoreComments: false,
|
||||
},
|
||||
],
|
||||
'linebreak-style': ['warn', 'unix'],
|
||||
},
|
||||
};
|
15
mini-program/.gitignore
vendored
Normal file
15
mini-program/.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
node_modules/
|
||||
yarn-error.log
|
||||
miniprogram/
|
||||
miniprogram_npm/
|
||||
miniprogram_dist/
|
||||
.DS_Store
|
||||
$node_modules/
|
||||
.history/
|
||||
**/dist
|
||||
components/**/*.lock
|
||||
components/**/package-lock.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
project.private.config.json
|
||||
.eslintcache
|
4
mini-program/.husky/commit-msg
Normal file
4
mini-program/.husky/commit-msg
Normal file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx --no-install commitlint --edit ""
|
4
mini-program/.husky/pre-commit
Normal file
4
mini-program/.husky/pre-commit
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
4
mini-program/.husky/prepare-commit-msg
Normal file
4
mini-program/.husky/prepare-commit-msg
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
exec < /dev/tty && npx git-cz --hook || true
|
9
mini-program/.npmrc
Normal file
9
mini-program/.npmrc
Normal file
@ -0,0 +1,9 @@
|
||||
# 去除注释可以使用代理进行安装
|
||||
# proxy=http://127.0.0.1:1080
|
||||
# https_proxy=http://127.0.0.1:1080
|
||||
|
||||
# 去除注释可以使用淘宝源
|
||||
# registry=https://registry.npm.taobao.org
|
||||
|
||||
# 去除注释可以使用腾讯源
|
||||
#registry=http://mirrors.tencent.com/npm/
|
3
mini-program/.prettierignore
Normal file
3
mini-program/.prettierignore
Normal file
@ -0,0 +1,3 @@
|
||||
miniprogram_npm
|
||||
package.json
|
||||
project.config.json
|
49
mini-program/.prettierrc.yml
Normal file
49
mini-program/.prettierrc.yml
Normal file
@ -0,0 +1,49 @@
|
||||
# 一行最多 100 字符
|
||||
printWidth: 120
|
||||
# 使用 2 个空格缩进
|
||||
tabWidth: 2
|
||||
# 不使用缩进符,而使用空格
|
||||
useTabs: false
|
||||
# 行尾需要分号
|
||||
semi: true
|
||||
# 使用单引号
|
||||
singleQuote: true
|
||||
# 对象的 key 仅在必要时用引号
|
||||
quoteProps: as-needed
|
||||
# jsx 不使用单引号,而使用双引号
|
||||
jsxSingleQuote: false
|
||||
# 末尾需要逗号
|
||||
trailingComma: all
|
||||
# 大括号内的首尾需要空格
|
||||
bracketSpacing: true
|
||||
# jsx 标签的反尖括号需要换行
|
||||
jsxBracketSameLine: false
|
||||
# 箭头函数,只有一个参数的时候,不需要括号
|
||||
arrowParens: always
|
||||
# 每个文件格式化的范围是文件的全部内容
|
||||
rangeStart: 0
|
||||
# 不需要写文件开头的 @prettier
|
||||
requirePragma: false
|
||||
# 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false
|
||||
# 使用默认的折行标准
|
||||
proseWrap: preserve
|
||||
# 根据显示样式决定 html 要不要折行
|
||||
htmlWhitespaceSensitivity: css
|
||||
# 换行符使用 lf
|
||||
endOfLine: lf
|
||||
# 后缀文件名特有规则
|
||||
overrides:
|
||||
- files: '*.{wxss,less}'
|
||||
options:
|
||||
parser: less
|
||||
- files: '*.json,.*rc'
|
||||
options:
|
||||
parser: json
|
||||
- files: '*.{wxml,html}'
|
||||
options:
|
||||
parser: html
|
||||
htmlWhitespaceSensitivity: strict
|
||||
- files: '*.wxs'
|
||||
options:
|
||||
parser: babel
|
9
mini-program/LICENSE
Normal file
9
mini-program/LICENSE
Normal file
@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-present TDesign
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
138
mini-program/README.md
Normal file
138
mini-program/README.md
Normal file
@ -0,0 +1,138 @@
|
||||
<p align="center">
|
||||
<a href="https://tdesign.tencent.com/" target="_blank">
|
||||
<img alt="TDesign Logo" width="200" src="https://tdesign.gtimg.com/site/TDesign.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://img.shields.io/github/stars/Tencent/tdesign-miniprogram-starter-retail">
|
||||
<img src="https://img.shields.io/github/stars/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/Tencent/tdesign-miniprogram-starter-retail/issues">
|
||||
<img src="https://img.shields.io/github/issues/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/Tencent/tdesign-miniprogram-starter-retail/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/tdesign-miniprogram">
|
||||
<img src="https://img.shields.io/npm/v/tdesign-miniprogram.svg?sanitize=true" alt="Version">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/tdesign-miniprogram">
|
||||
<img src="https://img.shields.io/npm/dw/tdesign-miniprogram" alt="Downloads">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# TDesign 零售行业模版示例小程序
|
||||
|
||||
TDesign 零售模版示例小程序采用 [TDesign 企业级设计体系小程序解决方案](https://tdesign.tencent.com/miniprogram/overview) 进行搭建,依赖 [TDesign 微信小程序组件库](https://github.com/Tencent/tdesign-miniprogram),涵盖完整的基本零售场景需求。
|
||||
|
||||
## :high_brightness: 预览
|
||||
|
||||
<p>请使用微信扫描以下二维码:</p>
|
||||
|
||||
<img src="https://we-retail-static-1300977798.cos.ap-guangzhou.myqcloud.com/retail-mp/common/qrcode.jpeg" width = "200" height = "200" alt="模版小程序二维码" align=center />
|
||||
|
||||
## :pushpin: 项目介绍
|
||||
|
||||
### 1. 业务介绍
|
||||
|
||||
零售行业模版小程序是个经典的单店版电商小程序,涵盖了电商的黄金链路流程,从商品->购物车->结算->订单等。小程序总共包含 28 个完整的页面,涵盖首页,商品详情页,个人中心,售后流程等基础页面。采用 mock 数据进行展示,提供了完整的零售商品展示、交易与售后流程。页面详情:
|
||||
|
||||
<img src="https://cdn-we-retail.ym.tencent.com/tsr/tdesign-starter-readmeV1.png" width = "650" height = "900" alt="模版小程序页面详情" align=center />
|
||||
|
||||
|
||||
|
||||
主要页面截图如下:
|
||||
|
||||
<p align="center">
|
||||
<img alt="example-home" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/home.png" />
|
||||
<img alt="example-sort" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v2/sort.png" />
|
||||
<img alt="example-cart" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/cart.png" />
|
||||
<img alt="example-user-center" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/user-center.png" />
|
||||
<img alt="example-goods-detail" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/goods-detail.png" />
|
||||
<img alt="example-pay" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/pay.png" />
|
||||
<img alt="example-order" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/order.png" />
|
||||
<img alt="example-order-detail" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v2/order.png" />
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
### 2. 项目构成
|
||||
|
||||
零售行业模版小程序采用基础的 JavaScript + WXSS + ESLint 进行构建,降低了使用门槛。
|
||||
|
||||
项目目录结构如下:
|
||||
|
||||
```
|
||||
|-- tdesign-miniprogram-starter
|
||||
|-- README.md
|
||||
|-- app.js
|
||||
|-- app.json
|
||||
|-- app.wxss
|
||||
|-- components // 公共组件库
|
||||
|-- config // 基础配置
|
||||
|-- custom-tab-bar // 自定义 tabbar
|
||||
|-- model // mock 数据
|
||||
|-- pages
|
||||
| |-- cart // 购物车相关页面
|
||||
| |-- coupon // 优惠券相关页面
|
||||
| |-- goods // 商品相关页面
|
||||
| |-- home // 首页
|
||||
| |-- order // 订单售后相关页面
|
||||
| |-- promotion-detail // 营销活动页面
|
||||
| |-- usercenter // 个人中心及收货地址相关页面
|
||||
|-- services // 请求接口
|
||||
|-- style // 公共样式与iconfont
|
||||
|-- utils // 工具库
|
||||
```
|
||||
|
||||
### 3. 数据模拟
|
||||
|
||||
零售小程序采用真实的接口数据,模拟后端返回逻辑,在小程序展示完整的购物场景与购物体验逻辑。
|
||||
|
||||
### 4. 添加新页面
|
||||
|
||||
1. 在 `pages `目录下创建对应的页面文件夹
|
||||
2. 在 `app.json` 文件中的 ` "pages"` 数组中加上页面路径
|
||||
3. [可选] 在 `project.config.json` 文件的 `"miniprogram-list"` 下添加页面配置
|
||||
|
||||
## :hammer: 构建运行
|
||||
|
||||
1. `npm install`
|
||||
2. 小程序开发工具中引入工程
|
||||
3. 构建 npm
|
||||
|
||||
## :art: 代码风格控制
|
||||
|
||||
`eslint` `prettier`
|
||||
|
||||
## :iphone: 基础库版本
|
||||
|
||||
最低基础库版本`^2.6.5`
|
||||
|
||||
## :dart: 反馈&合作
|
||||
|
||||
本开源项目是由[腾讯云Mall团队](https://ym.qq.com/)核心贡献。项目也在[github](https://github.com/Tencent/tdesign-miniprogram-starter-retail)上做了开源,有任何问题或者建议都欢迎在issue上留言反馈, 或者加入TD小程序开发者群进行反馈:star2::star2::star2:
|
||||
|
||||
<img src="https://cdn.qa.ym.qq.com/officical-site/assets/logo.png?auto=format&fit=max&w=384" width = "100" height = "30" alt="模版小程序页面详情" align=center />
|
||||
|
||||
[云Mall](https://ym.qq.com/)是基于微信小程序的电商SaaS产品,致力于提供全面、可靠的小程序商城经营服务,助力商家成功。支持标准化和定开类型商家入驻。
|
||||
|
||||
企业微信群
|
||||
TDesign 团队会及时在企业微信大群中同步发布版本、问题修复信息,也会有一些关于组件库建设的讨论,欢迎微信或企业微信扫码入群交流:
|
||||
|
||||
<img src="https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/site/doc/TDesign%20IM.png" width = "200" height = "200" alt="模版小程序页面详情" align=center />
|
||||
|
||||
|
||||
邮件联系:tdesign@tencent.com
|
||||
|
||||
## :link: TDesign 其他技术栈实现
|
||||
|
||||
- 移动端 小程序 实现:[mobile-miniprogram](https://github.com/Tencent/tdesign-miniprogram)
|
||||
- 桌面端 Vue 2 实现:[web-vue](https://github.com/Tencent/tdesign-vue)
|
||||
- 桌面端 Vue 3 实现:[web-vue-next](https://github.com/Tencent/tdesign-vue-next)
|
||||
- 桌面端 React 实现:[web-react](https://github.com/Tencent/tdesign-react)
|
||||
|
||||
## :page_with_curl: 开源协议
|
||||
|
||||
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-miniprogram-starter-retail/LICENSE)。
|
8
mini-program/app.js
Normal file
8
mini-program/app.js
Normal file
@ -0,0 +1,8 @@
|
||||
import updateManager from './common/updateManager';
|
||||
|
||||
App({
|
||||
onLaunch: function () {},
|
||||
onShow: function () {
|
||||
updateManager();
|
||||
},
|
||||
});
|
73
mini-program/app.json
Normal file
73
mini-program/app.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/home/home",
|
||||
"pages/usercenter/index",
|
||||
"pages/usercenter/person-info/index",
|
||||
"pages/usercenter/address/list/index",
|
||||
"pages/usercenter/address/edit/index",
|
||||
"pages/goods/list/index",
|
||||
"pages/goods/details/index",
|
||||
"pages/goods/category/index",
|
||||
"pages/goods/search/index",
|
||||
"pages/goods/result/index",
|
||||
"pages/cart/index",
|
||||
"pages/order/order-confirm/index",
|
||||
"pages/order/receipt/index",
|
||||
"pages/order/pay-result/index",
|
||||
"pages/order/order-list/index",
|
||||
"pages/order/order-detail/index",
|
||||
"pages/goods/comments/index",
|
||||
"pages/order/apply-service/index",
|
||||
"pages/order/after-service-list/index",
|
||||
"pages/order/after-service-detail/index",
|
||||
"pages/goods/comments/create/index",
|
||||
"pages/coupon/coupon-list/index",
|
||||
"pages/coupon/coupon-detail/index",
|
||||
"pages/coupon/coupon-activity-goods/index",
|
||||
"pages/promotion-detail/index",
|
||||
"pages/order/fill-tracking-no/index",
|
||||
"pages/order/delivery-detail/index",
|
||||
"pages/order/invoice/index",
|
||||
"pages/usercenter/name-edit/index"
|
||||
],
|
||||
"tabBar": {
|
||||
"custom": true,
|
||||
"color": "#666666",
|
||||
"selectedColor": "#FF5F15",
|
||||
"backgroundColor": "#ffffff",
|
||||
"borderStyle": "black",
|
||||
"list": [
|
||||
{
|
||||
"pagePath": "pages/home/home",
|
||||
"text": "首页"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/goods/category/index",
|
||||
"text": "分类"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/cart/index",
|
||||
"text": "购物车"
|
||||
},
|
||||
{
|
||||
"pagePath": "pages/usercenter/index",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
"requiredPrivateInfos": ["chooseAddress"],
|
||||
"lazyCodeLoading": "requiredComponents",
|
||||
"usingComponents": {},
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"navigationBarTitleText": "Weixin",
|
||||
"navigationBarTextStyle": "black"
|
||||
},
|
||||
"sitemapLocation": "sitemap.json",
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "你的位置信息将用于小程序位置接口的效果展示"
|
||||
}
|
||||
}
|
||||
}
|
3
mini-program/app.wxss
Normal file
3
mini-program/app.wxss
Normal file
@ -0,0 +1,3 @@
|
||||
@import 'style/iconfont.wxss';
|
||||
|
||||
@import 'style/theme.wxss';
|
1
mini-program/commitlint.config.js
Normal file
1
mini-program/commitlint.config.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
29
mini-program/common/updateManager.js
Normal file
29
mini-program/common/updateManager.js
Normal file
@ -0,0 +1,29 @@
|
||||
export default () => {
|
||||
if (!wx.canIUse('getUpdateManager')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateManager = wx.getUpdateManager();
|
||||
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
// 请求完新版本信息的回调
|
||||
console.log('版本信息', res);
|
||||
});
|
||||
|
||||
updateManager.onUpdateReady(function () {
|
||||
wx.showModal({
|
||||
title: '更新提示',
|
||||
content: '新版本已经准备好,是否重启应用?',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
updateManager.onUpdateFailed(function () {
|
||||
// 新版本下载失败
|
||||
});
|
||||
};
|
36
mini-program/components/filter-popup/index.js
Normal file
36
mini-program/components/filter-popup/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
|
||||
properties: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
observer(show) {
|
||||
this.setData({ visible: show });
|
||||
},
|
||||
},
|
||||
closeBtn: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
data: { visible: false },
|
||||
|
||||
methods: {
|
||||
reset() {
|
||||
this.triggerEvent('reset');
|
||||
},
|
||||
confirm() {
|
||||
this.triggerEvent('confirm');
|
||||
},
|
||||
close() {
|
||||
this.triggerEvent('showFilterPopupClose');
|
||||
|
||||
this.setData({ visible: false });
|
||||
},
|
||||
},
|
||||
});
|
6
mini-program/components/filter-popup/index.json
Normal file
6
mini-program/components/filter-popup/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-popup": "tdesign-miniprogram/popup/popup"
|
||||
}
|
||||
}
|
18
mini-program/components/filter-popup/index.wxml
Normal file
18
mini-program/components/filter-popup/index.wxml
Normal file
@ -0,0 +1,18 @@
|
||||
<t-popup
|
||||
visible="{{visible}}"
|
||||
placement="right"
|
||||
bind:visible-change="close"
|
||||
data-index="5"
|
||||
close-btn="{{closeBtn}}"
|
||||
>
|
||||
<view class="content">
|
||||
<slot name="filterSlot" />
|
||||
<view class="filter-btns-wrap">
|
||||
<view class="filter-btn btn-reset" bind:tap="reset">重置</view>
|
||||
<view class="filter-btn btn-confirm" bind:tap="confirm" data-index="5">
|
||||
确定
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</t-popup>
|
||||
|
39
mini-program/components/filter-popup/index.wxss
Normal file
39
mini-program/components/filter-popup/index.wxss
Normal file
@ -0,0 +1,39 @@
|
||||
.content .filter-btns-wrap {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
border-radius: 10rpx 0 0 10rpx;
|
||||
padding: 16rpx 32rpx;
|
||||
border-top: 1rpx solid #e5e5e5;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.filter-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.btn-reset {
|
||||
color: #fa4126;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
position: relative;
|
||||
border: 1rpx solid #fa4126;
|
||||
border-radius: 84rpx 0 0 84rpx;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
border-radius: 0 84rpx 84rpx 0;
|
||||
border: 1rpx solid #fa4126;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
color: #fff;
|
||||
background: #fa4126;
|
||||
}
|
84
mini-program/components/filter/index.js
Normal file
84
mini-program/components/filter/index.js
Normal file
@ -0,0 +1,84 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
|
||||
properties: {
|
||||
overall: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
observer(overall) {
|
||||
this.setData({
|
||||
overall,
|
||||
});
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
observer(layout) {
|
||||
this.setData({
|
||||
layout,
|
||||
});
|
||||
},
|
||||
},
|
||||
sorts: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer(sorts) {
|
||||
this.setData({
|
||||
sorts,
|
||||
});
|
||||
},
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: '#FA550F',
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
layout: 1,
|
||||
overall: 1,
|
||||
sorts: '',
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChangeShowAction() {
|
||||
const { layout } = this.data;
|
||||
const nextLayout = layout === 1 ? 0 : 1;
|
||||
this.triggerEvent('change', { ...this.properties, layout: nextLayout });
|
||||
},
|
||||
|
||||
handlePriseSort() {
|
||||
const { sorts } = this.data;
|
||||
this.triggerEvent('change', {
|
||||
...this.properties,
|
||||
overall: 0,
|
||||
sorts: sorts === 'desc' ? 'asc' : 'desc',
|
||||
});
|
||||
},
|
||||
|
||||
open() {
|
||||
this.triggerEvent('showFilterPopup', {
|
||||
show: true,
|
||||
});
|
||||
},
|
||||
|
||||
onOverallAction() {
|
||||
const { overall } = this.data;
|
||||
const nextOverall = overall === 1 ? 0 : 1;
|
||||
const nextData = {
|
||||
sorts: '',
|
||||
prices: [],
|
||||
};
|
||||
this.triggerEvent('change', {
|
||||
...this.properties,
|
||||
...nextData,
|
||||
overall: nextOverall,
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
6
mini-program/components/filter/index.json
Normal file
6
mini-program/components/filter/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
37
mini-program/components/filter/index.wxml
Normal file
37
mini-program/components/filter/index.wxml
Normal file
@ -0,0 +1,37 @@
|
||||
<!-- 过滤组件 -->
|
||||
<view class="wr-class filter-wrap">
|
||||
<view class="filter-left-content">
|
||||
<view class="filter-item {{overall === 1 ? 'filter-active-item' : ''}}" bindtap="onOverallAction">
|
||||
综合
|
||||
</view>
|
||||
<view class="filter-item" bind:tap="handlePriseSort">
|
||||
<text style="color: {{sorts !== '' ? color : '' }}">价格</text>
|
||||
<view class="filter-price">
|
||||
<t-icon
|
||||
prefix="wr"
|
||||
name="arrow_drop_up"
|
||||
size="18rpx"
|
||||
style="color:{{sorts === 'asc' ? color : '#bbb'}}"
|
||||
/>
|
||||
<t-icon
|
||||
prefix="wr"
|
||||
name="arrow_drop_down"
|
||||
size="18rpx"
|
||||
style="color:{{sorts === 'desc' ? color : '#bbb'}}"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="filter-item {{prices.length ? 'filter-active-item' : ''}}" bindtap="open" data-index="5">
|
||||
筛选
|
||||
<t-icon
|
||||
name="filter"
|
||||
prefix="wr"
|
||||
color="#333"
|
||||
size="32rpx"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 筛选弹框 -->
|
||||
<slot name="filterPopup" />
|
||||
|
50
mini-program/components/filter/index.wxss
Normal file
50
mini-program/components/filter/index.wxss
Normal file
@ -0,0 +1,50 @@
|
||||
.filter-wrap {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.filter-right-content {
|
||||
height: 100%;
|
||||
flex-basis: 100rpx;
|
||||
text-align: center;
|
||||
line-height: 88rpx;
|
||||
}
|
||||
|
||||
.filter-left-content {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-grow: 2;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.filter-left-content .filter-item {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 26rpx;
|
||||
line-height: 36rpx;
|
||||
font-weight: 400;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
}
|
||||
|
||||
.filter-left-content .filter-item .filter-price {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 6rpx;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.filter-left-content .filter-item .wr-filter {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.filter-left-content .filter-active-item {
|
||||
color: #fa550f;
|
||||
}
|
141
mini-program/components/goods-card/index.js
Normal file
141
mini-program/components/goods-card/index.js
Normal file
@ -0,0 +1,141 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
},
|
||||
|
||||
properties: {
|
||||
id: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer(id) {
|
||||
this.genIndependentID(id);
|
||||
if (this.properties.thresholds?.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
observer(data) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
let isValidityLinePrice = true;
|
||||
if (data.originPrice && data.price && data.originPrice < data.price) {
|
||||
isValidityLinePrice = false;
|
||||
}
|
||||
this.setData({ goods: data, isValidityLinePrice });
|
||||
},
|
||||
},
|
||||
currency: {
|
||||
type: String,
|
||||
value: '¥',
|
||||
},
|
||||
|
||||
thresholds: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer(thresholds) {
|
||||
if (thresholds && thresholds.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
} else {
|
||||
this.clearIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
independentID: '',
|
||||
goods: { id: '' },
|
||||
isValidityLinePrice: false,
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.init();
|
||||
},
|
||||
detached() {
|
||||
this.clear();
|
||||
},
|
||||
},
|
||||
|
||||
pageLifeTimes: {},
|
||||
|
||||
methods: {
|
||||
clickHandle() {
|
||||
this.triggerEvent('click', { goods: this.data.goods });
|
||||
},
|
||||
|
||||
clickThumbHandle() {
|
||||
this.triggerEvent('thumb', { goods: this.data.goods });
|
||||
},
|
||||
|
||||
addCartHandle(e) {
|
||||
const { id } = e.currentTarget;
|
||||
const { id: cardID } = e.currentTarget.dataset;
|
||||
this.triggerEvent('add-cart', {
|
||||
...e.detail,
|
||||
id,
|
||||
cardID,
|
||||
goods: this.data.goods,
|
||||
});
|
||||
},
|
||||
|
||||
genIndependentID(id) {
|
||||
let independentID;
|
||||
if (id) {
|
||||
independentID = id;
|
||||
} else {
|
||||
independentID = `goods-card-${~~(Math.random() * 10 ** 8)}`;
|
||||
}
|
||||
this.setData({ independentID });
|
||||
},
|
||||
|
||||
init() {
|
||||
const { thresholds, id } = this.properties;
|
||||
this.genIndependentID(id);
|
||||
if (thresholds && thresholds.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.clearIntersectionObserverHandle();
|
||||
},
|
||||
|
||||
intersectionObserverContext: null,
|
||||
|
||||
createIntersectionObserverHandle() {
|
||||
if (this.intersectionObserverContext || !this.data.independentID) {
|
||||
return;
|
||||
}
|
||||
this.intersectionObserverContext = this.createIntersectionObserver({
|
||||
thresholds: this.properties.thresholds,
|
||||
}).relativeToViewport();
|
||||
|
||||
this.intersectionObserverContext.observe(
|
||||
`#${this.data.independentID}`,
|
||||
(res) => {
|
||||
this.intersectionObserverCB(res);
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
intersectionObserverCB() {
|
||||
this.triggerEvent('ob', {
|
||||
goods: this.data.goods,
|
||||
context: this.intersectionObserverContext,
|
||||
});
|
||||
},
|
||||
|
||||
clearIntersectionObserverHandle() {
|
||||
if (this.intersectionObserverContext) {
|
||||
try {
|
||||
this.intersectionObserverContext.disconnect();
|
||||
} catch (e) {}
|
||||
this.intersectionObserverContext = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
8
mini-program/components/goods-card/index.json
Normal file
8
mini-program/components/goods-card/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"price": "/components/price/index",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-image": "/components/webp-image/index"
|
||||
}
|
||||
}
|
63
mini-program/components/goods-card/index.wxml
Normal file
63
mini-program/components/goods-card/index.wxml
Normal file
@ -0,0 +1,63 @@
|
||||
<view
|
||||
id="{{independentID}}"
|
||||
class="goods-card"
|
||||
bind:tap="clickHandle"
|
||||
data-goods="{{ goods }}"
|
||||
>
|
||||
<view class="goods-card__main">
|
||||
<view class="goods-card__thumb" bind:tap="clickThumbHandle">
|
||||
<t-image
|
||||
wx:if="{{ !!goods.thumb }}"
|
||||
t-class="goods-card__img"
|
||||
src="{{ goods.thumb }}"
|
||||
mode="aspectFill"
|
||||
lazy-load
|
||||
/>
|
||||
</view>
|
||||
<view class="goods-card__body">
|
||||
<view class="goods-card__upper">
|
||||
<view wx:if="{{ goods.title }}" class="goods-card__title">
|
||||
{{ goods.title }}
|
||||
</view>
|
||||
<view wx:if="{{ goods.tags && !!goods.tags.length }}" class="goods-card__tags">
|
||||
<view
|
||||
wx:for="{{ goods.tags }}"
|
||||
wx:key="index"
|
||||
wx:for-item="tag"
|
||||
class="goods-card__tag"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
{{tag}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-card__down">
|
||||
<price
|
||||
wx:if="{{ goods.price }}"
|
||||
wr-class="spec-for-price"
|
||||
symbol-class="spec-for-symbol"
|
||||
symbol="{{currency}}"
|
||||
price="{{goods.price}}"
|
||||
/>
|
||||
<price
|
||||
wx:if="{{ goods.originPrice && isValidityLinePrice }}"
|
||||
wr-class="goods-card__origin-price"
|
||||
symbol="{{currency}}"
|
||||
price="{{goods.originPrice}}"
|
||||
type="delthrough"
|
||||
/>
|
||||
<t-icon
|
||||
class="goods-card__add-cart"
|
||||
prefix="wr"
|
||||
name="cartAdd"
|
||||
id="{{independentID}}-cart"
|
||||
data-id="{{independentID}}"
|
||||
catchtap="addCartHandle"
|
||||
size="48rpx"
|
||||
color="#FA550F"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
133
mini-program/components/goods-card/index.wxss
Normal file
133
mini-program/components/goods-card/index.wxss
Normal file
@ -0,0 +1,133 @@
|
||||
.goods-card {
|
||||
box-sizing: border-box;
|
||||
font-size: 24rpx;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.goods-card__main {
|
||||
position: relative;
|
||||
display: flex;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
width: 342rpx;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 16rpx;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.goods-card__thumb {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: 340rpx;
|
||||
height: 340rpx;
|
||||
}
|
||||
|
||||
.goods-card__thumb:empty {
|
||||
display: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.goods-card__img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods-card__body {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
background: #fff;
|
||||
border-radius: 0 0 16rpx 16rpx;
|
||||
padding: 16rpx 24rpx 18rpx;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.goods-card__upper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.goods-card__title {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
display: -webkit-box;
|
||||
height: 72rpx;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.goods-card__tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: 8rpx 0 0 0;
|
||||
}
|
||||
|
||||
.goods-card__tag {
|
||||
color: #fa4126;
|
||||
background: transparent;
|
||||
font-size: 20rpx;
|
||||
border: 1rpx solid #fa4126;
|
||||
padding: 0 8rpx;
|
||||
border-radius: 16rpx;
|
||||
line-height: 30rpx;
|
||||
margin: 0 8rpx 8rpx 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
word-break: keep-all;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.goods-card__down {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: baseline;
|
||||
line-height: 32rpx;
|
||||
margin: 8rpx 0 0 0;
|
||||
}
|
||||
|
||||
.goods-card__origin-price {
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
order: 2;
|
||||
color: #bbbbbb;
|
||||
font-size: 24rpx;
|
||||
margin: 0 0 0 8rpx;
|
||||
}
|
||||
|
||||
.goods-card__add-cart {
|
||||
order: 3;
|
||||
margin: auto 0 0 auto;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.spec-for-price {
|
||||
font-size: 36rpx;
|
||||
white-space: nowrap;
|
||||
font-weight: 700;
|
||||
order: 1;
|
||||
color: #fa4126;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.spec-for-symbol {
|
||||
font-size: 24rpx;
|
||||
}
|
62
mini-program/components/goods-list/index.js
Normal file
62
mini-program/components/goods-list/index.js
Normal file
@ -0,0 +1,62 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
properties: {
|
||||
goodsList: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer: (id) => {
|
||||
this.genIndependentID(id);
|
||||
},
|
||||
},
|
||||
thresholds: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
independentID: '',
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClickGoods(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
this.triggerEvent('click', { ...e.detail, index });
|
||||
},
|
||||
|
||||
onAddCart(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
this.triggerEvent('addcart', { ...e.detail, index });
|
||||
},
|
||||
|
||||
onClickGoodsThumb(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
this.triggerEvent('thumb', { ...e.detail, index });
|
||||
},
|
||||
|
||||
init() {
|
||||
this.genIndependentID(this.id || '');
|
||||
},
|
||||
|
||||
genIndependentID(id) {
|
||||
if (id) {
|
||||
this.setData({ independentID: id });
|
||||
} else {
|
||||
this.setData({
|
||||
independentID: `goods-list-${~~(Math.random() * 10 ** 8)}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
6
mini-program/components/goods-list/index.json
Normal file
6
mini-program/components/goods-list/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"goods-card": "/components/goods-card/index"
|
||||
}
|
||||
}
|
16
mini-program/components/goods-list/index.wxml
Normal file
16
mini-program/components/goods-list/index.wxml
Normal file
@ -0,0 +1,16 @@
|
||||
<view class="goods-list-wrap wr-class" id="{{independentID}}">
|
||||
<block wx:for="{{goodsList}}" wx:for-item="item" wx:key="index">
|
||||
<goods-card
|
||||
id="{{independentID}}-gd-{{index}}"
|
||||
data="{{item}}"
|
||||
currency="{{item.currency || '¥'}}"
|
||||
thresholds="{{thresholds}}"
|
||||
class="goods-card-inside"
|
||||
data-index="{{index}}"
|
||||
bind:thumb="onClickGoodsThumb"
|
||||
bind:click="onClickGoods"
|
||||
bind:add-cart="onAddCart"
|
||||
/>
|
||||
</block>
|
||||
</view>
|
||||
|
7
mini-program/components/goods-list/index.wxss
Normal file
7
mini-program/components/goods-list/index.wxss
Normal file
@ -0,0 +1,7 @@
|
||||
.goods-list-wrap {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: space-between;
|
||||
padding: 0;
|
||||
background: #fff;
|
||||
}
|
54
mini-program/components/load-more/index.js
Normal file
54
mini-program/components/load-more/index.js
Normal file
@ -0,0 +1,54 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class', 'wr-class--no-more'],
|
||||
|
||||
options: { multipleSlots: true },
|
||||
|
||||
properties: {
|
||||
status: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
value: '加载中...',
|
||||
},
|
||||
noMoreText: {
|
||||
type: String,
|
||||
value: '没有更多了',
|
||||
},
|
||||
failedText: {
|
||||
type: String,
|
||||
value: '加载失败,点击重试',
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: '#BBBBBB',
|
||||
},
|
||||
failedColor: {
|
||||
type: String,
|
||||
value: '#FA550F',
|
||||
},
|
||||
size: {
|
||||
type: null,
|
||||
value: '40rpx',
|
||||
},
|
||||
loadingBackgroundColor: {
|
||||
type: String,
|
||||
value: '#F5F5F5',
|
||||
},
|
||||
listIsEmpty: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 点击处理 */
|
||||
tapHandle() {
|
||||
// 失败重试
|
||||
if (this.data.status === 3) {
|
||||
this.triggerEvent('retry');
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
7
mini-program/components/load-more/index.json
Normal file
7
mini-program/components/load-more/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||
"t-divider": "tdesign-miniprogram/divider/divider"
|
||||
}
|
||||
}
|
31
mini-program/components/load-more/index.wxml
Normal file
31
mini-program/components/load-more/index.wxml
Normal file
@ -0,0 +1,31 @@
|
||||
<view
|
||||
class="load-more wr-class"
|
||||
style="{{listIsEmpty && (status === 0 || status === 2) ? 'display: none' : '' }}"
|
||||
bindtap="tapHandle"
|
||||
>
|
||||
<!-- 加载中 -->
|
||||
|
||||
<t-loading
|
||||
t-class="t-class-loading"
|
||||
t-class-text="t-class-loading-text"
|
||||
t-class-indicator="t-class-indicator"
|
||||
loading="{{status === 1}}"
|
||||
text="加载中..."
|
||||
theme="circular"
|
||||
size="40rpx"
|
||||
/>
|
||||
|
||||
<!-- 已全部加载 -->
|
||||
<t-divider wx:if="{{status === 2}}" t-class="t-class-divider" t-class-content="t-class-divider-content">
|
||||
<text slot="content">{{noMoreText}}</text>
|
||||
</t-divider>
|
||||
|
||||
<!-- 加载失败 -->
|
||||
<view class="load-more__error" wx:if="{{status===3}}">
|
||||
加载失败
|
||||
<text class="load-more__refresh-btn" bind:tap="tapHandle">刷新</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支持通过slot传入页面/列表的空态,load-more来控制空态的显示状态 -->
|
||||
<slot wx:if="{{listIsEmpty && (status === 0 || status === 2)}}" name="empty" />
|
35
mini-program/components/load-more/index.wxss
Normal file
35
mini-program/components/load-more/index.wxss
Normal file
@ -0,0 +1,35 @@
|
||||
.load-more {
|
||||
font-size: 24rpx;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.load-more .t-class-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
--td-loading-color: #fa4126;
|
||||
}
|
||||
|
||||
.load-more .t-class-loading-text {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.t-class-divider-content {
|
||||
margin: 0 10rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
.load-more .t-class-indicator {
|
||||
color: #b9b9b9 !important;
|
||||
}
|
||||
|
||||
.load-more__error {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.load-more__refresh-btn {
|
||||
margin-left: 16rpx;
|
||||
color: #fa4126;
|
||||
}
|
23
mini-program/components/loading-content/index.js
Normal file
23
mini-program/components/loading-content/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
properties: {
|
||||
position: {
|
||||
type: String,
|
||||
value: 'static',
|
||||
},
|
||||
noMask: Boolean,
|
||||
type: {
|
||||
type: String,
|
||||
value: 'circular',
|
||||
},
|
||||
vertical: Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
value: '50rpx',
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
value: 'rgba(0, 0, 0, .6)',
|
||||
},
|
||||
},
|
||||
});
|
6
mini-program/components/loading-content/index.json
Normal file
6
mini-program/components/loading-content/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-loading": "tdesign-miniprogram/loading/loading"
|
||||
}
|
||||
}
|
11
mini-program/components/loading-content/index.wxml
Normal file
11
mini-program/components/loading-content/index.wxml
Normal file
@ -0,0 +1,11 @@
|
||||
<view class="t-class loading-content {{position}}" style="{{(position === 'static' || noMask) ? 'visibility: hidden;' : ''}} background-color: {{backgroundColor}}">
|
||||
<t-loading
|
||||
t-class="loading"
|
||||
theme="{{type}}"
|
||||
layout="{{vertical}}"
|
||||
size="{{size}}"
|
||||
>
|
||||
<slot/>
|
||||
</t-loading>
|
||||
</view>
|
||||
|
23
mini-program/components/loading-content/index.wxss
Normal file
23
mini-program/components/loading-content/index.wxss
Normal file
@ -0,0 +1,23 @@
|
||||
.loading-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
position: relative;
|
||||
}
|
||||
.loading-content.absolute {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.loading-content.fixed {
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.loading-content .loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
visibility: visible;
|
||||
}
|
71
mini-program/components/price/index.js
Normal file
71
mini-program/components/price/index.js
Normal file
@ -0,0 +1,71 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class', 'symbol-class', 'decimal-class'],
|
||||
useStore: [],
|
||||
properties: {
|
||||
priceUnit: {
|
||||
type: String,
|
||||
value: 'fen',
|
||||
}, // 价格单位,分 | 元, fen,yuan
|
||||
price: {
|
||||
type: null,
|
||||
value: '',
|
||||
observer(price) {
|
||||
this.format(price);
|
||||
},
|
||||
}, // 价格, 以分为单位
|
||||
type: {
|
||||
type: String,
|
||||
value: '', //
|
||||
}, // main 粗体, lighter 细体, mini 黑色, del 中划线, delthrough 中划线,包括货币符号
|
||||
symbol: {
|
||||
type: String,
|
||||
value: '¥', // '¥',
|
||||
}, // 货币符号,默认是人民币符号¥
|
||||
fill: Boolean, // 是否自动补齐两位小数
|
||||
decimalSmaller: Boolean, // 小数字号小一点
|
||||
lineThroughWidth: {
|
||||
type: null,
|
||||
value: '0.12em',
|
||||
}, // 划线价线条高度
|
||||
},
|
||||
|
||||
data: {
|
||||
pArr: [],
|
||||
},
|
||||
|
||||
methods: {
|
||||
format(price) {
|
||||
price = parseFloat(`${price}`);
|
||||
const pArr = [];
|
||||
if (!isNaN(price)) {
|
||||
const isMinus = price < 0;
|
||||
if (isMinus) {
|
||||
price = -price;
|
||||
}
|
||||
if (this.properties.priceUnit === 'yuan') {
|
||||
const priceSplit = price.toString().split('.');
|
||||
pArr[0] = priceSplit[0];
|
||||
pArr[1] = !priceSplit[1]
|
||||
? '00'
|
||||
: priceSplit[1].length === 1
|
||||
? `${priceSplit[1]}0`
|
||||
: priceSplit[1];
|
||||
} else {
|
||||
price = Math.round(price * 10 ** 8) / 10 ** 8; // 恢复精度丢失
|
||||
price = Math.ceil(price); // 向上取整
|
||||
pArr[0] = price >= 100 ? `${price}`.slice(0, -2) : '0';
|
||||
pArr[1] = `${price + 100}`.slice(-2);
|
||||
}
|
||||
if (!this.properties.fill) {
|
||||
// 如果 fill 为 false, 不显示小数末尾的0
|
||||
if (pArr[1] === '00') pArr[1] = '';
|
||||
else if (pArr[1][1] === '0') pArr[1] = pArr[1][0];
|
||||
}
|
||||
if (isMinus) {
|
||||
pArr[0] = `-${pArr[0]}`;
|
||||
}
|
||||
}
|
||||
this.setData({ pArr });
|
||||
},
|
||||
},
|
||||
});
|
4
mini-program/components/price/index.json
Normal file
4
mini-program/components/price/index.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
21
mini-program/components/price/index.wxml
Normal file
21
mini-program/components/price/index.wxml
Normal file
@ -0,0 +1,21 @@
|
||||
<wxs module="utils">
|
||||
var REGEXP = getRegExp('^\d+(\.\d+)?$');
|
||||
function addUnit(value) {
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
return REGEXP.test('' + value) ? value + 'rpx' : value;
|
||||
}
|
||||
module.exports = {
|
||||
addUnit: addUnit
|
||||
};
|
||||
</wxs>
|
||||
<view class="price {{type}} wr-class">
|
||||
<view wx:if="{{type === 'delthrough'}}" class="line" style="height:{{utils.addUnit(lineThroughWidth)}};" />
|
||||
<view class="symbol symbol-class">{{symbol}}</view>
|
||||
<view class="pprice">
|
||||
<view class="integer inline">{{pArr[0]}}</view>
|
||||
<view wx:if="{{pArr[1]}}" class="decimal inline {{decimalSmaller ? 'smaller' : ''}} decimal-class">.{{pArr[1]}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
66
mini-program/components/price/index.wxss
Normal file
66
mini-program/components/price/index.wxss
Normal file
@ -0,0 +1,66 @@
|
||||
:host {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
font-weight: inherit;
|
||||
}
|
||||
.inline {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.price {
|
||||
display: inline;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.lighter {
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.mini {
|
||||
font-size: 24rpx;
|
||||
color: #5d5d5d;
|
||||
font-weight: 400;
|
||||
}
|
||||
.del .pprice {
|
||||
font-size: 32rpx;
|
||||
color: #9b9b9b;
|
||||
text-decoration: line-through;
|
||||
font-weight: 400;
|
||||
}
|
||||
.delthrough {
|
||||
position: relative;
|
||||
}
|
||||
.delthrough .line {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
margin: 0;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
display: inline;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.pprice {
|
||||
display: inline;
|
||||
margin: 0 0 0 4rpx;
|
||||
}
|
||||
.integer {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.decimal {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.decimal.smaller {
|
||||
font-size: 0.8em;
|
||||
vertical-align: baseline;
|
||||
}
|
79
mini-program/components/swipeout/index.js
Normal file
79
mini-program/components/swipeout/index.js
Normal file
@ -0,0 +1,79 @@
|
||||
let ARRAY = [];
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
properties: {
|
||||
disabled: Boolean,
|
||||
leftWidth: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
rightWidth: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
asyncClose: Boolean,
|
||||
},
|
||||
attached() {
|
||||
ARRAY.push(this);
|
||||
},
|
||||
|
||||
detached() {
|
||||
ARRAY = ARRAY.filter((item) => item !== this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Component initial data
|
||||
*/
|
||||
data: {
|
||||
wrapperStyle: '',
|
||||
asyncClose: false,
|
||||
closed: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* Component methods
|
||||
*/
|
||||
methods: {
|
||||
open(position) {
|
||||
this.setData({ closed: false });
|
||||
this.triggerEvent('close', {
|
||||
position,
|
||||
instance: this,
|
||||
});
|
||||
},
|
||||
|
||||
close() {
|
||||
this.setData({ closed: true });
|
||||
},
|
||||
|
||||
closeOther() {
|
||||
ARRAY.filter((item) => item !== this).forEach((item) => item.close());
|
||||
},
|
||||
|
||||
noop() {
|
||||
return;
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
const { key: position = 'outside' } = event.currentTarget.dataset;
|
||||
this.triggerEvent('click', position);
|
||||
|
||||
if (this.data.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.data.asyncClose) {
|
||||
this.triggerEvent('close', {
|
||||
position,
|
||||
instance: this,
|
||||
});
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
4
mini-program/components/swipeout/index.json
Normal file
4
mini-program/components/swipeout/index.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
174
mini-program/components/swipeout/index.wxml
Normal file
174
mini-program/components/swipeout/index.wxml
Normal file
@ -0,0 +1,174 @@
|
||||
<wxs module="swipe">
|
||||
var THRESHOLD = 0.3;
|
||||
var MIN_DISTANCE = 10;
|
||||
var owner;
|
||||
var state;
|
||||
|
||||
var getState = function(ownerInstance) {
|
||||
owner = ownerInstance;
|
||||
state = owner.getState();
|
||||
state.leftWidth = state.leftWidth || 0;
|
||||
state.rightWidth = state.rightWidth || 0;
|
||||
state.offset = state.offset || 0;
|
||||
state.startOffset = state.startOffset || 0;
|
||||
};
|
||||
|
||||
var initRightWidth = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.rightWidth = newVal;
|
||||
if (state.offset < 0) {
|
||||
swipeMove(-state.rightWidth);
|
||||
}
|
||||
};
|
||||
|
||||
var initLeftWidth = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.leftWidth = newVal;
|
||||
if (state.offset > 0) {
|
||||
swipeMove(state.leftWidth);
|
||||
}
|
||||
}
|
||||
|
||||
var resetTouchStatus = function() {
|
||||
state.direction = '';
|
||||
state.deltaX = 0;
|
||||
state.deltaY = 0;
|
||||
state.offsetX = 0;
|
||||
state.offsetY = 0;
|
||||
};
|
||||
|
||||
var touchMove = function(event) {
|
||||
var touchPoint = event.touches[0];
|
||||
state.deltaX = touchPoint.clientX - state.startX;
|
||||
state.deltaY = touchPoint.clientY - state.startY;
|
||||
state.offsetX = Math.abs(state.deltaX);
|
||||
state.offsetY = Math.abs(state.deltaY);
|
||||
state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
|
||||
};
|
||||
|
||||
var getDirection = function(x, y) {
|
||||
if (x > y && x > MIN_DISTANCE) {
|
||||
return 'horizontal';
|
||||
}
|
||||
if (y > x && y > MIN_DISTANCE) {
|
||||
return 'vertical';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
var range = function(num, min, max) {
|
||||
return Math.min(Math.max(num, min), max);
|
||||
};
|
||||
|
||||
var swipeMove = function(_offset = 0) {
|
||||
state.offset = range(
|
||||
_offset,
|
||||
-state.rightWidth,
|
||||
+state.leftWidth,
|
||||
);
|
||||
|
||||
var transform = 'translate3d(' + state.offset + 'px, 0, 0)';
|
||||
var transition = state.dragging
|
||||
? 'none'
|
||||
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
|
||||
owner.selectComponent('#wrapper').setStyle({
|
||||
'-webkit-transform': transform,
|
||||
'-webkit-transition': transition,
|
||||
'transform': transform,
|
||||
'transition': transition
|
||||
});
|
||||
};
|
||||
|
||||
var close = function() {
|
||||
swipeMove(0);
|
||||
};
|
||||
|
||||
var onCloseChange = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
if (newVal === oldVal) return;
|
||||
if (newVal) {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
var touchStart = function(event) {
|
||||
resetTouchStatus();
|
||||
state.startOffset = state.offset;
|
||||
var touchPoint = event.touches[0];
|
||||
state.startX = touchPoint.clientX;
|
||||
state.startY = touchPoint.clientY;
|
||||
owner.callMethod('closeOther');
|
||||
};
|
||||
|
||||
var startDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
touchStart(event);
|
||||
};
|
||||
|
||||
var onDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
touchMove(event);
|
||||
if (state.direction !== 'horizontal') {
|
||||
return;
|
||||
}
|
||||
state.dragging = true;
|
||||
swipeMove(state.startOffset + state.deltaX);
|
||||
};
|
||||
|
||||
var open = function(position) {
|
||||
var _offset = position === 'left' ? +state.leftWidth : -state.rightWidth;
|
||||
owner.callMethod('open', { position: position });
|
||||
swipeMove(_offset);
|
||||
};
|
||||
|
||||
var endDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.dragging = false;
|
||||
// 左/右侧有可滑动区域,且当前不是已open状态,且滑动幅度超过阈值时open左/右侧(滚动到该侧的最边上)
|
||||
if (+state.rightWidth > 0 && -state.startOffset < +state.rightWidth && -state.offset > +state.rightWidth * THRESHOLD) {
|
||||
open('right');
|
||||
} else if (+state.leftWidth > 0 && state.startOffset < +state.leftWidth && state.offset > +state.leftWidth * THRESHOLD) {
|
||||
open('left');
|
||||
} else {
|
||||
// 仅在有发生侧滑的情况下自动关闭(由js控制是否异步关闭)
|
||||
if (state.startOffset !== state.offset) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initLeftWidth: initLeftWidth,
|
||||
initRightWidth: initRightWidth,
|
||||
startDrag: startDrag,
|
||||
onDrag: onDrag,
|
||||
endDrag: endDrag,
|
||||
onCloseChange: onCloseChange
|
||||
};
|
||||
</wxs>
|
||||
|
||||
<view
|
||||
class="wr-class wr-swipeout"
|
||||
data-key="cell"
|
||||
capture-bind:tap="onClick"
|
||||
bindtouchstart="{{disabled || swipe.startDrag}}"
|
||||
capture-bind:touchmove="{{disabled || swipe.onDrag}}"
|
||||
bindtouchend="{{disabled || swipe.endDrag}}"
|
||||
bindtouchcancel="{{disabled || swipe.endDrag}}"
|
||||
closed="{{closed}}"
|
||||
change:closed="{{swipe.onCloseChange}}"
|
||||
leftWidth="{{leftWidth}}"
|
||||
rightWidth="{{rightWidth}}"
|
||||
change:leftWidth="{{swipe.initLeftWidth}}"
|
||||
change:rightWidth="{{swipe.initRightWidth}}"
|
||||
>
|
||||
<view id="wrapper">
|
||||
<view wx:if="{{ leftWidth }}" class="wr-swipeout__left" data-key="left" catch:tap="onClick">
|
||||
<slot name="left" />
|
||||
</view>
|
||||
<slot />
|
||||
<view wx:if="{{ rightWidth }}" class="wr-swipeout__right" data-key="right" catch:tap="onClick">
|
||||
<slot name="right" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
18
mini-program/components/swipeout/index.wxss
Normal file
18
mini-program/components/swipeout/index.wxss
Normal file
@ -0,0 +1,18 @@
|
||||
.wr-swipeout {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-swipeout__left,
|
||||
.wr-swipeout__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.wr-swipeout__left {
|
||||
left: 0;
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
.wr-swipeout__right {
|
||||
right: 0;
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
86
mini-program/components/webp-image/index.js
Normal file
86
mini-program/components/webp-image/index.js
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* @Author: rileycai
|
||||
* @Date: 2022-03-14 14:21:26
|
||||
* @LastEditTime: 2022-03-14 15:23:04
|
||||
* @LastEditors: rileycai
|
||||
* @Description: webp-image组件对t-image包裹了一层,主要实现图片裁剪、webp压缩功能
|
||||
* @FilePath: /tdesign-miniprogram-starter/components/webp-image/index.js
|
||||
*/
|
||||
const systemInfo = wx.getSystemInfoSync();
|
||||
Component({
|
||||
externalClasses: ['t-class', 't-class-load'],
|
||||
properties: {
|
||||
loadFailed: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
loading: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
value: 'aspectFill',
|
||||
},
|
||||
webp: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
lazyLoad: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
showMenuByLongpress: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
thumbHeight: 375,
|
||||
thumbWidth: 375,
|
||||
systemInfo,
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
const { mode } = this.properties;
|
||||
// 获取容器的真实宽高,设置图片的裁剪宽度
|
||||
this.getRect('.J-image').then((res) => {
|
||||
if (res) {
|
||||
const { width, height } = res;
|
||||
this.setData(
|
||||
mode === 'heightFix'
|
||||
? {
|
||||
thumbHeight: this.px2rpx(height) || 375,
|
||||
}
|
||||
: {
|
||||
thumbWidth: this.px2rpx(width) || 375,
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
px2rpx(px) {
|
||||
return (750 / (systemInfo.screenWidth || 375)) * px;
|
||||
},
|
||||
getRect(selector) {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.selectorQuery) {
|
||||
this.selectorQuery = this.createSelectorQuery();
|
||||
}
|
||||
this.selectorQuery.select(selector).boundingClientRect(resolve).exec();
|
||||
});
|
||||
},
|
||||
onLoad(e) {
|
||||
this.triggerEvent('load', e.detail);
|
||||
},
|
||||
onError(e) {
|
||||
this.triggerEvent('error', e.detail);
|
||||
},
|
||||
},
|
||||
});
|
6
mini-program/components/webp-image/index.json
Normal file
6
mini-program/components/webp-image/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-image": "tdesign-miniprogram/image/image"
|
||||
}
|
||||
}
|
14
mini-program/components/webp-image/index.wxml
Normal file
14
mini-program/components/webp-image/index.wxml
Normal file
@ -0,0 +1,14 @@
|
||||
<wxs src="./utils.wxs" module="Utils" />
|
||||
<t-image
|
||||
t-class="J-image"
|
||||
src="{{Utils.getSrc({src, thumbWidth: thumbWidth || 0, thumbHeight: thumbHeight || 0, systemInfo, webp, mode})}}"
|
||||
t-class="t-class"
|
||||
t-class-load="t-class-load"
|
||||
mode="{{ mode }}"
|
||||
lazy="{{ lazyLoad }}"
|
||||
show-menu-by-longpress="{{showMenuByLongpress}}"
|
||||
error="{{loadFailed}}"
|
||||
loading="{{loading}}"
|
||||
binderror="onError"
|
||||
bindload="onLoad"
|
||||
/>
|
0
mini-program/components/webp-image/index.wxss
Normal file
0
mini-program/components/webp-image/index.wxss
Normal file
140
mini-program/components/webp-image/utils.wxs
Normal file
140
mini-program/components/webp-image/utils.wxs
Normal file
@ -0,0 +1,140 @@
|
||||
var isString = function (value) {
|
||||
return typeof value === 'string';
|
||||
};
|
||||
|
||||
var isNumber = function (value) {
|
||||
return typeof value === 'number';
|
||||
};
|
||||
|
||||
var getFileExt = function (src) {
|
||||
var fileUrl = src.split('?')[0];
|
||||
var splitUlr = fileUrl.split('/');
|
||||
var filepath = splitUlr[splitUlr.length - 1];
|
||||
return filepath.split('.')[1] || 'jpg';
|
||||
};
|
||||
|
||||
function isUrl(url) {
|
||||
// NOCC:ToolNameCheck(非敏感词)
|
||||
var urlReg = getRegExp(
|
||||
'/[(http(s)?)://(www.)?a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/',
|
||||
'ig',
|
||||
);
|
||||
|
||||
return urlReg.test(url);
|
||||
}
|
||||
|
||||
function rpx2px(rpx, screenWidth) {
|
||||
// px / systemWidth = rpx / 750
|
||||
var result = (rpx * (screenWidth || 375)) / 750;
|
||||
|
||||
return Math.round(result);
|
||||
}
|
||||
|
||||
function imageMogr(url, options) {
|
||||
if (!isString(url) || !url) return '';
|
||||
|
||||
if (
|
||||
url.indexOf('qlogo.cn') !== -1 ||
|
||||
url.indexOf('wxfile://') === 0 ||
|
||||
url.indexOf('http://tmp/wx') === 0 ||
|
||||
url.indexOf('imageMogr2') !== -1
|
||||
) {
|
||||
//qlogo.cn域名或者本地图片不做转换
|
||||
return url;
|
||||
} //强制转https
|
||||
|
||||
if (url.indexOf('http://') === 0) {
|
||||
url = url.replace('http://', 'https://');
|
||||
} else if (url.indexOf('//') === 0) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
|
||||
if (!options) return url;
|
||||
|
||||
var width = Math.ceil(options.width),
|
||||
height = Math.ceil(options.height),
|
||||
format = options.format,
|
||||
_optionsQuality = options.quality,
|
||||
quality = _optionsQuality === undefined ? 70 : _optionsQuality,
|
||||
_optionsStrip = options.strip,
|
||||
strip = _optionsStrip === undefined ? true : _optionsStrip,
|
||||
crop = options.crop;
|
||||
var isValidWidth = isNumber(width) && width > 0;
|
||||
var isValidHeight = isNumber(height) && height > 0;
|
||||
var imageMogrStr = '';
|
||||
var size = '';
|
||||
|
||||
if (isValidWidth && isValidHeight) {
|
||||
size = ''.concat(width, 'x').concat(height);
|
||||
} else if (isValidWidth) {
|
||||
size = ''.concat(width, 'x');
|
||||
} else if (isValidHeight) {
|
||||
size = 'x'.concat(height);
|
||||
}
|
||||
|
||||
if (size) {
|
||||
//缩放或者裁剪
|
||||
imageMogrStr += '/'.concat(crop ? 'crop' : 'thumbnail', '/').concat(size);
|
||||
|
||||
if (crop) {
|
||||
//裁剪目前需求只有以图片中心为基准
|
||||
imageMogrStr += '/gravity/center';
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumber(quality)) {
|
||||
//质量变换
|
||||
imageMogrStr += '/quality/'.concat(quality);
|
||||
}
|
||||
|
||||
if (strip) {
|
||||
//去除元信息
|
||||
imageMogrStr += '/strip';
|
||||
}
|
||||
|
||||
var ext = getFileExt(url);
|
||||
|
||||
// gif 图片不做格式转换,否则会损坏动图
|
||||
if (ext === 'gif') {
|
||||
imageMogrStr += '/cgif/1';
|
||||
} else if (format) {
|
||||
//格式转换
|
||||
imageMogrStr += '/format/'.concat(format);
|
||||
}
|
||||
|
||||
if (format === 'jpg' || (!format && (ext === 'jpg' || ext === 'jpeg'))) {
|
||||
//渐进式 jpg 加载
|
||||
imageMogrStr += '/interlace/1';
|
||||
}
|
||||
if (!imageMogrStr) return url;
|
||||
return ''
|
||||
.concat(url)
|
||||
.concat(url.indexOf('?') !== -1 ? '&' : '?', 'imageMogr2')
|
||||
.concat(imageMogrStr);
|
||||
}
|
||||
function getSrc(options) {
|
||||
if (!options.src) return '';
|
||||
|
||||
if (options.thumbWidth || options.thumbHeight) {
|
||||
return imageMogr(options.src, {
|
||||
width:
|
||||
options.mode !== 'heightFix'
|
||||
? rpx2px(options.thumbWidth, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
: null,
|
||||
height:
|
||||
options.mode !== 'widthFix'
|
||||
? rpx2px(options.thumbHeight, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
: null,
|
||||
format: options.webp ? 'webp' : null,
|
||||
});
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
imageMogr: imageMogr,
|
||||
getSrc: getSrc,
|
||||
};
|
91
mini-program/config/eslintCheck.js
Normal file
91
mini-program/config/eslintCheck.js
Normal file
@ -0,0 +1,91 @@
|
||||
/* eslint-disable prefer-template */
|
||||
/**
|
||||
* 工程代码pre-commit 检查工具
|
||||
* @date 2019.9.4
|
||||
* @author 310227663@qq.com
|
||||
*/
|
||||
const { exec } = require('child_process');
|
||||
const chalk = require('chalk');
|
||||
const { CLIEngine } = require('eslint');
|
||||
const cli = new CLIEngine({});
|
||||
const { log } = console;
|
||||
|
||||
function getErrorLevel(number) {
|
||||
switch (number) {
|
||||
case 2:
|
||||
return 'error';
|
||||
case 1:
|
||||
return 'warn';
|
||||
default:
|
||||
}
|
||||
return 'undefined';
|
||||
}
|
||||
let pass = 0;
|
||||
exec(
|
||||
'git diff --cached --name-only --diff-filter=ACM | grep -Ei "\\.ts$|\\.js$"',
|
||||
(error, stdout) => {
|
||||
if (stdout.length) {
|
||||
const array = stdout.split('\n');
|
||||
array.pop();
|
||||
const { results } = cli.executeOnFiles(array);
|
||||
let errorCount = 0;
|
||||
let warningCount = 0;
|
||||
results.forEach((result) => {
|
||||
errorCount += result.errorCount;
|
||||
warningCount += result.warningCount;
|
||||
if (result.messages.length > 0) {
|
||||
log('\n');
|
||||
log(result.filePath);
|
||||
result.messages.forEach((obj) => {
|
||||
const level = getErrorLevel(obj.severity);
|
||||
if (level === 'warn')
|
||||
log(
|
||||
' ' +
|
||||
obj.line +
|
||||
':' +
|
||||
obj.column +
|
||||
'\t ' +
|
||||
chalk.yellow(level) +
|
||||
' \0 ' +
|
||||
obj.message +
|
||||
'\t\t' +
|
||||
chalk.grey(obj.ruleId) +
|
||||
'',
|
||||
);
|
||||
if (level === 'error')
|
||||
log(
|
||||
' ' +
|
||||
obj.line +
|
||||
':' +
|
||||
obj.column +
|
||||
'\t ' +
|
||||
chalk.red.bold(level) +
|
||||
' \0 ' +
|
||||
obj.message +
|
||||
'\t\t ' +
|
||||
chalk.grey(obj.ruleId) +
|
||||
'',
|
||||
);
|
||||
if (level === 'error') pass = 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
if (warningCount > 0 || errorCount > 0) {
|
||||
log(
|
||||
'\n' +
|
||||
chalk.bgRed.bold(errorCount + warningCount + ' problems') +
|
||||
' (' +
|
||||
chalk.red.bold(errorCount) +
|
||||
' errors, ' +
|
||||
chalk.yellow(warningCount) +
|
||||
' warnings) \0',
|
||||
);
|
||||
}
|
||||
!pass && log(chalk.green.bold('~~ Done: 代码检验通过,提交成功 ~~'));
|
||||
process.exit(pass);
|
||||
}
|
||||
if (error !== null) {
|
||||
log(`exec error: ${error}`);
|
||||
}
|
||||
},
|
||||
);
|
20437
mini-program/config/index.js
Normal file
20437
mini-program/config/index.js
Normal file
File diff suppressed because it is too large
Load Diff
22
mini-program/custom-tab-bar/data.js
Normal file
22
mini-program/custom-tab-bar/data.js
Normal file
@ -0,0 +1,22 @@
|
||||
export default [
|
||||
{
|
||||
icon: 'home',
|
||||
text: '首页',
|
||||
url: 'pages/home/home',
|
||||
},
|
||||
{
|
||||
icon: 'sort',
|
||||
text: '分类',
|
||||
url: 'pages/goods/category/index',
|
||||
},
|
||||
{
|
||||
icon: 'cart',
|
||||
text: '购物车',
|
||||
url: 'pages/cart/index',
|
||||
},
|
||||
{
|
||||
icon: 'person',
|
||||
text: '个人中心',
|
||||
url: 'pages/usercenter/index',
|
||||
},
|
||||
];
|
29
mini-program/custom-tab-bar/index.js
Normal file
29
mini-program/custom-tab-bar/index.js
Normal file
@ -0,0 +1,29 @@
|
||||
import TabMenu from './data';
|
||||
Component({
|
||||
data: {
|
||||
active: 0,
|
||||
list: TabMenu,
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange(event) {
|
||||
this.setData({ active: event.detail.value });
|
||||
wx.switchTab({
|
||||
url: this.data.list[event.detail.value].url.startsWith('/')
|
||||
? this.data.list[event.detail.value].url
|
||||
: `/${this.data.list[event.detail.value].url}`,
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
const page = getCurrentPages().pop();
|
||||
const route = page ? page.route.split('?')[0] : '';
|
||||
const active = this.data.list.findIndex(
|
||||
(item) =>
|
||||
(item.url.startsWith('/') ? item.url.substr(1) : item.url) ===
|
||||
`${route}`,
|
||||
);
|
||||
this.setData({ active });
|
||||
},
|
||||
},
|
||||
});
|
8
mini-program/custom-tab-bar/index.json
Normal file
8
mini-program/custom-tab-bar/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-tab-bar": "tdesign-miniprogram/tab-bar/tab-bar",
|
||||
"t-tab-bar-item": "tdesign-miniprogram/tab-bar-item/tab-bar-item",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
18
mini-program/custom-tab-bar/index.wxml
Normal file
18
mini-program/custom-tab-bar/index.wxml
Normal file
@ -0,0 +1,18 @@
|
||||
<t-tab-bar
|
||||
value="{{active}}"
|
||||
bindchange="onChange"
|
||||
split="{{false}}"
|
||||
>
|
||||
<t-tab-bar-item
|
||||
wx:for="{{list}}"
|
||||
wx:for-item="item"
|
||||
wx:for-index="index"
|
||||
wx:key="index"
|
||||
>
|
||||
<view class="custom-tab-bar-wrapper">
|
||||
<t-icon prefix="wr" name="{{item.icon}}" size="48rpx" />
|
||||
<view class="text">{{ item.text }}</view>
|
||||
</view>
|
||||
</t-tab-bar-item>
|
||||
</t-tab-bar>
|
||||
|
9
mini-program/custom-tab-bar/index.wxss
Normal file
9
mini-program/custom-tab-bar/index.wxss
Normal file
@ -0,0 +1,9 @@
|
||||
.custom-tab-bar-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-tab-bar-wrapper .text {
|
||||
font-size: 20rpx;
|
||||
}
|
5
mini-program/jsconfig.json
Normal file
5
mini-program/jsconfig.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
34
mini-program/mock.md
Normal file
34
mini-program/mock.md
Normal file
@ -0,0 +1,34 @@
|
||||
## 模拟与数据
|
||||
|
||||
model 用于放置模拟后端数据返回的逻辑;假若接入真实后端接口,则本文件夹可改造为数据层适配。
|
||||
services 用于请求逻辑,根据 config.useMock 配置可控制返回 mock 数据或是真实接口数据
|
||||
|
||||
### 1 模拟策略
|
||||
|
||||
1)只依靠 ID 规律进行关联
|
||||
大部分情况下推荐使用本方案,ID 为`1`的商品固定会关联 ID 为`1`的优惠券或者[ID 对 10 的模运算结果为 1](https://www.runoob.com/try/try.php?filename=tryjs_oper_mod)的优惠券(看需要 1 个还是多个了)。
|
||||
|
||||
> 为保持关系稳定,模运算统一使用`10`为除数,`ID`为被除数;即`1%10`、`2%10`。
|
||||
|
||||
2)建立额外关联关系查询
|
||||
在无法使用简单数学关系维持关系的情况下,可以采用单独提供关系数据的方式进行关联(目前也没想到什么场景是数学关系稳定不了的了,先假定有,定下规范做法)。如数据 A 与数据 B 之间需要一个关联 AB,则需要提供`A数据mock`、`B数据mock`、以及`A查B与B反查A`共 4 个 mock 源。
|
||||
|
||||
### 2 使用数据
|
||||
|
||||
使用数据源时应该在 services 文件夹中按照业务新建自己 fetch 函数导出,fetch 函数以 Promise 形式返回组合调用 model 逻辑得到的数据。
|
||||
|
||||
> 不允许直接在业务中调用、使用 model 数据。
|
||||
|
||||
## 接入真实 API 后
|
||||
|
||||
接入真实 API 后 model 文件夹逻辑可以反转层级,作为数据适配层继续为项目服务。举例说明:
|
||||
|
||||
1. 在没有接入 API 时(useMock 为 true)
|
||||
1.1 业务调用 services 进行 fetch
|
||||
1.2 fetch 逻辑调用 model 文件夹中对应的数据源,构造、返回业务需要的结构
|
||||
|
||||
2. 在接入 API 后(useMock 为 false)
|
||||
2.1 业务调用 services 进行 fetch
|
||||
2.2 fetch 逻辑调用接口得到真实后端数据
|
||||
2.3 比对 model 文件夹中数据 mock 数据结构 export 一个数据结构转换函数,输入真实后端数据,输出与 mock 数据结构一致的新数据,返回给 fetch
|
||||
2.4 fetch 函数 返回 转换后的 数据结构,业务层无需进行更改
|
7
mini-program/model/activities.js
Normal file
7
mini-program/model/activities.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { getActivity } from './activity';
|
||||
|
||||
export function getActivityList(baseID = 0, length = 10) {
|
||||
return new Array(length).fill(0).map((_, idx) => getActivity(idx + baseID));
|
||||
}
|
||||
|
||||
export const activityList = getActivityList();
|
18
mini-program/model/activity.js
Normal file
18
mini-program/model/activity.js
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @param {string|number} key 唯一值
|
||||
*/
|
||||
export function getActivity(key) {
|
||||
return {
|
||||
promotionId: `${key}`,
|
||||
title: `满减满折回归${key}`,
|
||||
description: null,
|
||||
promotionCode: 'MERCHANT',
|
||||
promotionSubCode: key % 2 === 0 ? 'MYJ' : 'MYG',
|
||||
tag: '满减',
|
||||
timeType: 1,
|
||||
startTime: '1588737710000',
|
||||
endTime: '1601467070000',
|
||||
teasingStartTime: null,
|
||||
activityLadder: [{ label: '满100元减99.9元' }],
|
||||
};
|
||||
}
|
31
mini-program/model/address.js
Normal file
31
mini-program/model/address.js
Normal file
@ -0,0 +1,31 @@
|
||||
/** 地址 */
|
||||
export function genAddress(id) {
|
||||
return {
|
||||
saasId: '88888888',
|
||||
uid: `8888888820550${id}`,
|
||||
authToken: null,
|
||||
id: `${id}`,
|
||||
addressId: `${id}`,
|
||||
phone: '17612345678',
|
||||
name: `测试用户${id}`,
|
||||
countryName: '中国',
|
||||
countryCode: 'chn',
|
||||
provinceName: '甘肃省',
|
||||
provinceCode: '620000',
|
||||
cityName: '甘南藏族自治州',
|
||||
cityCode: '623000',
|
||||
districtName: '碌曲县',
|
||||
districtCode: '623026',
|
||||
detailAddress: `松日鼎盛大厦${id}层${id}号`,
|
||||
isDefault: `${id}` === '0' ? 1 : 0,
|
||||
addressTag: id === 0 ? '' : '公司',
|
||||
latitude: '34.59103',
|
||||
longitude: '102.48699',
|
||||
storeId: null,
|
||||
};
|
||||
}
|
||||
|
||||
/** 地址列表 */
|
||||
export function genAddressList(len = 10) {
|
||||
return new Array(len).fill(0).map((_, idx) => genAddress(idx));
|
||||
}
|
324
mini-program/model/cart.js
Normal file
324
mini-program/model/cart.js
Normal file
@ -0,0 +1,324 @@
|
||||
import { mockIp, mockReqId } from '../utils/mock';
|
||||
|
||||
export function genCartGroupData() {
|
||||
const resp = {
|
||||
data: {
|
||||
isNotEmpty: true,
|
||||
storeGoods: [
|
||||
{
|
||||
storeId: '1000',
|
||||
storeName: '云Mall深圳旗舰店',
|
||||
storeStatus: 1,
|
||||
totalDiscountSalePrice: '9990',
|
||||
promotionGoodsList: [
|
||||
{
|
||||
title: '满减满折回归',
|
||||
promotionCode: 'MERCHANT',
|
||||
promotionSubCode: 'MYJ',
|
||||
promotionId: '159174555838121985',
|
||||
tagText: ['满100元减99.9元'],
|
||||
promotionStatus: 3,
|
||||
tag: '满减',
|
||||
description: '满100元减99.9元,已减99.9元',
|
||||
doorSillRemain: null,
|
||||
isNeedAddOnShop: 0,
|
||||
goodsPromotionList: [
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '12',
|
||||
skuId: '135691622',
|
||||
isSelected: 1,
|
||||
thumb:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/dz-3a.png',
|
||||
title:
|
||||
'腾讯极光盒子4智能网络电视机顶盒6K千兆网络机顶盒4K高分辨率',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/dz-3a.png',
|
||||
quantity: 1,
|
||||
stockStatus: true,
|
||||
stockQuantity: 3,
|
||||
price: '9900',
|
||||
originPrice: '16900',
|
||||
tagPrice: null,
|
||||
titlePrefixTags: [{ text: '新品' }, { text: '火爆' }],
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '经典白',
|
||||
},
|
||||
{
|
||||
specTitle: '类型',
|
||||
specValue: '经典套装',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-06-29T07:55:40.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '18',
|
||||
skuId: '135681631',
|
||||
isSelected: 1,
|
||||
thumb:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-09a.png',
|
||||
title:
|
||||
'白色短袖连衣裙荷叶边裙摆宽松韩版休闲纯白清爽优雅连衣裙',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-09a.png',
|
||||
quantity: 1,
|
||||
stockStatus: true,
|
||||
stockQuantity: 177,
|
||||
price: '29800',
|
||||
originPrice: '40000',
|
||||
tagPrice: null,
|
||||
titlePrefixTags: null,
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '米色荷叶边',
|
||||
},
|
||||
{
|
||||
specTitle: '尺码',
|
||||
specValue: 'M',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-06-29T07:55:27.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '13',
|
||||
skuId: '135698362',
|
||||
isSelected: 1,
|
||||
thumb:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/muy-3a.png',
|
||||
title:
|
||||
'带帽午休毯虎年款多功能加厚加大加绒简约多功能午休毯连帽披肩',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/muy-3a.png',
|
||||
quantity: 13,
|
||||
stockStatus: true,
|
||||
stockQuantity: 9,
|
||||
price: '29900',
|
||||
originPrice: '0',
|
||||
tagPrice: null,
|
||||
titlePrefixTags: [{ text: '火爆' }],
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '浅灰色',
|
||||
},
|
||||
{
|
||||
specTitle: '尺码',
|
||||
specValue: 'M',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-06-29T07:54:43.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '7',
|
||||
skuId: '135681625',
|
||||
isSelected: 1,
|
||||
thumb:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/gh-2b.png',
|
||||
title:
|
||||
'不锈钢刀叉勺套装家用西餐餐具ins简约耐用不锈钢金色银色可选',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/gh-2b.png',
|
||||
quantity: 1,
|
||||
stockStatus: true,
|
||||
stockQuantity: 0,
|
||||
price: '29900',
|
||||
originPrice: '29900',
|
||||
tagPrice: null,
|
||||
titlePrefixTags: null,
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '奶黄色',
|
||||
},
|
||||
{
|
||||
specTitle: '数量',
|
||||
specValue: '六件套',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-06-29T07:55:00.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
],
|
||||
lastJoinTime: '2020-06-29T07:55:40.000+0000',
|
||||
},
|
||||
{
|
||||
title: null,
|
||||
promotionCode: 'EMPTY_PROMOTION',
|
||||
promotionSubCode: null,
|
||||
promotionId: null,
|
||||
tagText: null,
|
||||
promotionStatus: null,
|
||||
tag: null,
|
||||
description: null,
|
||||
doorSillRemain: null,
|
||||
isNeedAddOnShop: 0,
|
||||
goodsPromotionList: [
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '11',
|
||||
skuId: '135691629',
|
||||
isSelected: 0,
|
||||
thumb:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-17a.png',
|
||||
title: '运动连帽拉链卫衣休闲开衫长袖多色运动细绒面料运动上衣',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-17a.png',
|
||||
quantity: 1,
|
||||
stockStatus: false,
|
||||
stockQuantity: 0,
|
||||
price: '25900',
|
||||
originPrice: '39900',
|
||||
tagPrice: null,
|
||||
tagText: null,
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '军绿色',
|
||||
},
|
||||
{
|
||||
specTitle: '尺码',
|
||||
specValue: 'S',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-04-24T06:26:48.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '5',
|
||||
skuId: '135691635',
|
||||
isSelected: 0,
|
||||
thumb:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/dz-2a.png',
|
||||
title:
|
||||
'迷你便携高颜值蓝牙无线耳机立体声只能触控式操作简约立体声耳机',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/dz-2a.png',
|
||||
quantity: 1,
|
||||
stockStatus: true,
|
||||
stockQuantity: 96,
|
||||
price: '29000',
|
||||
originPrice: '29900',
|
||||
tagPrice: null,
|
||||
tagText: null,
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '黑色',
|
||||
},
|
||||
{
|
||||
specTitle: '类型',
|
||||
specValue: '简约款',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-06-29T07:55:17.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
],
|
||||
lastJoinTime: null,
|
||||
},
|
||||
],
|
||||
lastJoinTime: '2020-06-29T07:55:40.000+0000',
|
||||
postageFreePromotionVo: {
|
||||
title: null,
|
||||
promotionCode: null,
|
||||
promotionSubCode: null,
|
||||
promotionId: null,
|
||||
tagText: null,
|
||||
promotionStatus: null,
|
||||
tag: null,
|
||||
description: null,
|
||||
doorSillRemain: null,
|
||||
isNeedAddOnShop: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
invalidGoodItems: [
|
||||
{
|
||||
uid: '88888888205468',
|
||||
saasId: '88888888',
|
||||
storeId: '1000',
|
||||
spuId: '1',
|
||||
skuId: '135691631',
|
||||
isSelected: 1,
|
||||
thumb: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
title: '纯色纯棉休闲圆领短袖T恤纯白亲肤厚柔软细腻面料纯白短袖套头T恤',
|
||||
primaryImage:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
quantity: 8,
|
||||
stockStatus: true,
|
||||
stockQuantity: 177,
|
||||
price: '26900',
|
||||
originPrice: '31900',
|
||||
tagPrice: null,
|
||||
tagText: null,
|
||||
roomId: null,
|
||||
specInfo: [
|
||||
{
|
||||
specTitle: '颜色',
|
||||
specValue: '白色',
|
||||
},
|
||||
{
|
||||
specTitle: '尺码',
|
||||
specValue: 'S',
|
||||
},
|
||||
],
|
||||
joinCartTime: '2020-04-28T04:03:59.000+0000',
|
||||
available: 1,
|
||||
putOnSale: 1,
|
||||
etitle: null,
|
||||
},
|
||||
],
|
||||
isAllSelected: false,
|
||||
selectedGoodsCount: 16,
|
||||
totalAmount: '179997',
|
||||
totalDiscountAmount: '110000',
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 269,
|
||||
success: true,
|
||||
};
|
||||
return resp;
|
||||
}
|
206
mini-program/model/category.js
Normal file
206
mini-program/model/category.js
Normal file
@ -0,0 +1,206 @@
|
||||
export function getCategoryList() {
|
||||
return [
|
||||
{
|
||||
groupId: '24948',
|
||||
name: '女装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249481',
|
||||
name: '女装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '卫衣',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-1.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '毛呢外套',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-2.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '雪纺衫',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-3.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '羽绒服',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-4.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '毛衣',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-5.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '棉衣',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-6.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '西装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-7.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '马甲',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-8.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '连衣裙',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-9.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '半身裙',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-10.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '裤子',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-11.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupId: '24948',
|
||||
name: '男装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249481',
|
||||
name: '男装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '卫衣',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-1.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '裤子',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-11.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '西装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-7.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '羽绒服',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-4.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '马甲',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-8.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupId: '24948',
|
||||
name: '儿童装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249481',
|
||||
name: '儿童装',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '马甲',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-8.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '裤子',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-11.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '连衣裙',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/classify/img-9.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '其他',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/muy-3b.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupId: '24948',
|
||||
name: '美妆',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249481',
|
||||
name: '美妆',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/category/category-default.png',
|
||||
children: [
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '唇釉',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/mz-20a1.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '美妆蛋',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/mz-11a1.png',
|
||||
},
|
||||
{
|
||||
groupId: '249480',
|
||||
name: '眼影',
|
||||
thumbnail:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/mz-12b.png',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
338
mini-program/model/comments.js
Normal file
338
mini-program/model/comments.js
Normal file
@ -0,0 +1,338 @@
|
||||
/**
|
||||
* * @param {number} spuId
|
||||
* @param {number} pageNum
|
||||
* @param {number} pageSize
|
||||
* @param {number} commentsLevel
|
||||
* @param {boolean} hasImage
|
||||
*/
|
||||
export function getGoodsAllComments(params) {
|
||||
const { hasImage } = params.queryParameter;
|
||||
if (hasImage) {
|
||||
return {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
totalCount: '1',
|
||||
pageList: [
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '0',
|
||||
specInfo: '',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentResources: [
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
type: 'image',
|
||||
},
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/comment-video.mp4',
|
||||
type: 'video',
|
||||
coverSrc:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
},
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/comment-video.mp4',
|
||||
type: 'video',
|
||||
coverSrc:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
},
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/comment-video.mp4',
|
||||
type: 'video',
|
||||
coverSrc:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
},
|
||||
],
|
||||
commentScore: 4,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1591953561000',
|
||||
isAutoComment: false,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '0',
|
||||
specInfo: '',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentResources: [
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
type: 'image',
|
||||
},
|
||||
],
|
||||
commentScore: 4,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1591953561000',
|
||||
isAutoComment: false,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '0',
|
||||
specInfo: '',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentResources: [
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
type: 'image',
|
||||
},
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/comment-video.mp4',
|
||||
type: 'video',
|
||||
coverSrc:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
},
|
||||
],
|
||||
commentScore: 4,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1591953561000',
|
||||
isAutoComment: false,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '0',
|
||||
specInfo: '',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentResources: [
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
type: 'image',
|
||||
},
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/comment-video.mp4',
|
||||
type: 'video',
|
||||
coverSrc:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
},
|
||||
{
|
||||
src: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/comment-video.mp4',
|
||||
type: 'video',
|
||||
coverSrc:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
},
|
||||
],
|
||||
commentScore: 4,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1591953561000',
|
||||
isAutoComment: false,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
totalCount: '47',
|
||||
pageList: [
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: '很不错',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 1,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592224320000',
|
||||
isAutoComment: false,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697693',
|
||||
specInfo: '很适合',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 1,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592224320000',
|
||||
isAutoComment: false,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: 'NICE',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592218074000',
|
||||
isAutoComment: true,
|
||||
sellerReply:
|
||||
'亲,你好,我们会联系商家和厂商给您一个满意的答复请一定妥善保管好发票',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '0',
|
||||
specInfo: '',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592218074000',
|
||||
isAutoComment: false,
|
||||
goodsDetailInfo: '颜色:纯净白 尺码:S码',
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: '测试dr超长:dr专用超长;bwtgg01:fff',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592217607000',
|
||||
isAutoComment: false,
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697693',
|
||||
specInfo: '测试dr超长:超长测试超长测试1;bwtgg01:bbb',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 4,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592217607000',
|
||||
isAutoComment: false,
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: '测试dr超长:dr专用超长;bwtgg01:fff',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592205599000',
|
||||
isAutoComment: false,
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: '测试dr超长:dr专用超长;bwtgg01:fff',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1592188822000',
|
||||
isAutoComment: false,
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: '测试dr超长:dr专用超长;bwtgg01:fff',
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881055835',
|
||||
userName: 'Max',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1593792002000',
|
||||
isAutoComment: true,
|
||||
},
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: '1697694',
|
||||
specInfo: '测试dr超长:dr专用超长;bwtgg01:fff',
|
||||
commentContent: '',
|
||||
commentImageUrls: null,
|
||||
commentScore: 5,
|
||||
uid: '88881055835',
|
||||
userName: 'Max',
|
||||
userHeadUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/avatar/avatar1.png',
|
||||
isAnonymity: false,
|
||||
commentTime: '1593792001000',
|
||||
isAutoComment: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function getGoodsCommentsCount() {
|
||||
return {
|
||||
commentCount: '47',
|
||||
badCount: '0',
|
||||
middleCount: '2',
|
||||
goodCount: '45',
|
||||
hasImageCount: '1',
|
||||
goodRate: 95.7,
|
||||
uidCount: '0',
|
||||
};
|
||||
}
|
50
mini-program/model/comments/queryDetail.js
Normal file
50
mini-program/model/comments/queryDetail.js
Normal file
@ -0,0 +1,50 @@
|
||||
const queryDetail = {
|
||||
commentInfos: [
|
||||
{
|
||||
id: '647984992708380600',
|
||||
uid: '',
|
||||
userName: 'Dean Cheng',
|
||||
userHeadUrl:
|
||||
'https://bizmid-material-qa-1302115263.cos.ap-guangzhou.myqcloud.com/comment/default_head.png',
|
||||
commentId: '1937712',
|
||||
commentIdName: '小鹿商品',
|
||||
commentIdImageUrl:
|
||||
'https://bizmid-material-qa-1302115263.file.myqcloud.com/persist/4bf2ded7-1759-4821-919c-cc4960e14120/1078823925183295617/100000114727/material/1/cdbeb389be64427b8c165627895ff0bc-1610425563793-%E5%A4%B4%E5%83%8F.png',
|
||||
commentStage: 1,
|
||||
commentCheckStatus: 2,
|
||||
commentIdType: 1,
|
||||
content: '',
|
||||
commentInfo: {
|
||||
score: null,
|
||||
content: '',
|
||||
medias: [],
|
||||
commentTime: '1617872404000',
|
||||
},
|
||||
isAgainComment: 0,
|
||||
commentHasAgainComment: 0,
|
||||
isAnonymous: 0,
|
||||
replyList: [],
|
||||
specification: '颜色:白色 ',
|
||||
specificationJson: '{"颜色":"白色"}',
|
||||
commentExtendId: '1937713',
|
||||
commentTime: '1617872404000',
|
||||
score: 0,
|
||||
goodsScore: null,
|
||||
freightScore: null,
|
||||
serviceScore: null,
|
||||
medias: [],
|
||||
againCommentList: null,
|
||||
},
|
||||
],
|
||||
logisticsScore: null,
|
||||
serviceScore: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} skuId
|
||||
* @param {string} spuId
|
||||
* @param {string} orderNo
|
||||
*/
|
||||
export function queryCommentDetail() {
|
||||
return queryDetail;
|
||||
}
|
39
mini-program/model/coupon.js
Normal file
39
mini-program/model/coupon.js
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 优惠券
|
||||
*
|
||||
* @typedef {'default'|'useless'|'disabled'} CouponCardStatus
|
||||
* @typedef {'discount'|'price'} CouponCardType
|
||||
*
|
||||
* @param {number} [id]
|
||||
* @param {CouponCardStatus} [status]
|
||||
* @param {CouponCardType} [type]
|
||||
*/
|
||||
export function getCoupon(id = 0, status = 'default', type = (id % 2) + 1) {
|
||||
return {
|
||||
/** key */
|
||||
key: `${id}`,
|
||||
/** 优惠券状态 */
|
||||
status,
|
||||
/** 优惠券类型 */
|
||||
type,
|
||||
/** 折扣或者满减值 */
|
||||
value: type === 2 ? 5.5 : 1800,
|
||||
/** 标签 */
|
||||
tag: '',
|
||||
/** 描述 */
|
||||
desc: parseInt(id) > 0 ? `满${parseInt(id) * 100}元可用` : '无门槛使用',
|
||||
/** 订单底价,满n元 */
|
||||
base: 10000 * (parseInt(id) || 0),
|
||||
/** 标题 */
|
||||
title: type === 2 ? `生鲜折扣券 - ${id}` : `生鲜满减券 - ${id}`,
|
||||
/** 有效时间限制 */
|
||||
timeLimit: '2019.11.18-2023.12.18',
|
||||
/** 货币符号 */
|
||||
currency: '¥',
|
||||
};
|
||||
}
|
||||
|
||||
/** 优惠券列表 */
|
||||
export function getCouponList(status = 'default', length = 10) {
|
||||
return new Array(length).fill(0).map((_, idx) => getCoupon(idx, status));
|
||||
}
|
30
mini-program/model/detailsComments.js
Normal file
30
mini-program/model/detailsComments.js
Normal file
@ -0,0 +1,30 @@
|
||||
export function getGoodsDetailsComments() {
|
||||
return {
|
||||
homePageComments: [
|
||||
{
|
||||
spuId: '1722045',
|
||||
skuId: null,
|
||||
specInfo: null,
|
||||
commentContent:
|
||||
'收到货了,第一时间试了一下,很漂亮特别喜欢,大爱大爱,颜色也很好看。棒棒!',
|
||||
commentScore: 4,
|
||||
uid: '88881048075',
|
||||
userName: 'Dean',
|
||||
userHeadUrl:
|
||||
'https://wx.qlogo.cn/mmopen/vi_32/5mKrvn3ibyDNaDZSZics3aoKlz1cv0icqn4EruVm6gKjsK0xvZZhC2hkUkRWGxlIzOEc4600JkzKn9icOLE6zjgsxw/132',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function getGoodsDetailsCommentsCount() {
|
||||
return {
|
||||
commentCount: '47',
|
||||
badCount: '0',
|
||||
middleCount: '2',
|
||||
goodCount: '45',
|
||||
hasImageCount: '1',
|
||||
goodRate: 95.7,
|
||||
uidCount: '0',
|
||||
};
|
||||
}
|
1916
mini-program/model/good.js
Normal file
1916
mini-program/model/good.js
Normal file
File diff suppressed because it is too large
Load Diff
7
mini-program/model/goods.js
Normal file
7
mini-program/model/goods.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { genGood } from './good';
|
||||
|
||||
export function getGoodsList(baseID = 0, length = 10) {
|
||||
return new Array(length).fill(0).map((_, idx) => genGood(idx + baseID));
|
||||
}
|
||||
|
||||
export const goodsList = getGoodsList();
|
295
mini-program/model/order/applyService.js
Normal file
295
mini-program/model/order/applyService.js
Normal file
@ -0,0 +1,295 @@
|
||||
import { mockIp, mockReqId } from '../../utils/mock';
|
||||
|
||||
const orderResps = [
|
||||
{
|
||||
data: {
|
||||
saasId: '88888888',
|
||||
uid: '88888888205468',
|
||||
storeId: '1000',
|
||||
skuId: '135691625',
|
||||
numOfSku: 1,
|
||||
numOfSkuAvailable: 1,
|
||||
refundableAmount: '26900',
|
||||
refundableDiscountAmount: '0',
|
||||
shippingFeeIncluded: '0',
|
||||
paidAmountEach: '26900',
|
||||
boughtQuantity: 1,
|
||||
orderNo: '132222623132329291',
|
||||
goodsInfo: {
|
||||
goodsName:
|
||||
'迷你便携高颜值蓝牙无线耳机立体声只能触控式操作简约立体声耳机',
|
||||
skuImage: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/dz-2a.png',
|
||||
specInfo: [
|
||||
{
|
||||
specId: '50456',
|
||||
specTitle: '颜色',
|
||||
specValue: '黑色',
|
||||
},
|
||||
{
|
||||
specId: '50459',
|
||||
specTitle: '尺码',
|
||||
specValue: '简约款',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 36,
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
data: {
|
||||
saasId: '88888888',
|
||||
uid: '88888888205468',
|
||||
storeId: '1000',
|
||||
skuId: '135676631',
|
||||
numOfSku: 1,
|
||||
numOfSkuAvailable: 1,
|
||||
refundableAmount: '26900',
|
||||
refundableDiscountAmount: '0',
|
||||
shippingFeeIncluded: '0',
|
||||
paidAmountEach: '26900',
|
||||
boughtQuantity: 1,
|
||||
orderNo: '132222623132329291',
|
||||
goodsInfo: {
|
||||
goodsName: '白色短袖连衣裙荷叶边裙摆宽松韩版休闲纯白清爽优雅连衣裙',
|
||||
skuImage: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-09a.png',
|
||||
specInfo: [
|
||||
{
|
||||
specId: '50456',
|
||||
specTitle: '颜色',
|
||||
specValue: '米色荷叶边',
|
||||
},
|
||||
{
|
||||
specId: '50459',
|
||||
specTitle: '尺码',
|
||||
specValue: 'S',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 36,
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
data: {
|
||||
saasId: '88888888',
|
||||
uid: '88888888205468',
|
||||
storeId: '1000',
|
||||
skuId: '135691622',
|
||||
numOfSku: 1,
|
||||
numOfSkuAvailable: 1,
|
||||
refundableAmount: '26900',
|
||||
refundableDiscountAmount: '0',
|
||||
shippingFeeIncluded: '0',
|
||||
paidAmountEach: '26900',
|
||||
boughtQuantity: 1,
|
||||
orderNo: '132222623132329291',
|
||||
goodsInfo: {
|
||||
goodsName: '腾讯极光盒子4智能网络电视机顶盒6K千兆网络机顶盒4K高分辨率',
|
||||
skuImage: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/dz-3a.png',
|
||||
specInfo: [
|
||||
{
|
||||
specId: '50456',
|
||||
specTitle: '颜色',
|
||||
specValue: '经典白',
|
||||
},
|
||||
{
|
||||
specId: '50459',
|
||||
specTitle: '类型',
|
||||
specValue: '经典套装',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 36,
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
data: {
|
||||
saasId: '88888888',
|
||||
uid: '88888888205468',
|
||||
storeId: '1000',
|
||||
skuId: '135676629',
|
||||
numOfSku: 1,
|
||||
numOfSkuAvailable: 1,
|
||||
refundableAmount: '26900',
|
||||
refundableDiscountAmount: '0',
|
||||
shippingFeeIncluded: '0',
|
||||
paidAmountEach: '26900',
|
||||
boughtQuantity: 1,
|
||||
orderNo: '132222623132329291',
|
||||
goodsInfo: {
|
||||
goodsName: '带帽午休毯虎年款多功能加厚加大加绒简约多功能午休毯连帽披肩',
|
||||
skuImage: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/muy-3a.png',
|
||||
specInfo: [
|
||||
{
|
||||
specId: '50456',
|
||||
specTitle: '颜色',
|
||||
specValue: '浅灰色',
|
||||
},
|
||||
{
|
||||
specId: '50459',
|
||||
specTitle: '尺码',
|
||||
specValue: 'S',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 36,
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
data: {
|
||||
saasId: '88888888',
|
||||
uid: '88888888205468',
|
||||
storeId: '1000',
|
||||
skuId: '135686631',
|
||||
numOfSku: 1,
|
||||
numOfSkuAvailable: 1,
|
||||
refundableAmount: '26900',
|
||||
refundableDiscountAmount: '0',
|
||||
shippingFeeIncluded: '0',
|
||||
paidAmountEach: '26900',
|
||||
boughtQuantity: 1,
|
||||
orderNo: '132222623132329291',
|
||||
goodsInfo: {
|
||||
goodsName: '运动连帽拉链卫衣休闲开衫长袖多色运动细绒面料运动上衣',
|
||||
skuImage: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-17a.png',
|
||||
specInfo: [
|
||||
{
|
||||
specId: '50456',
|
||||
specTitle: '颜色',
|
||||
specValue: '军绿色',
|
||||
},
|
||||
{
|
||||
specId: '50459',
|
||||
specTitle: '尺码',
|
||||
specValue: 'XS',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 36,
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
data: {
|
||||
saasId: '88888888',
|
||||
uid: '88888888205468',
|
||||
storeId: '1000',
|
||||
skuId: '19384938948343',
|
||||
numOfSku: 1,
|
||||
numOfSkuAvailable: 1,
|
||||
refundableAmount: '26900',
|
||||
refundableDiscountAmount: '0',
|
||||
shippingFeeIncluded: '0',
|
||||
paidAmountEach: '26900',
|
||||
boughtQuantity: 1,
|
||||
orderNo: '130169571554503755',
|
||||
goodsInfo: {
|
||||
goodsName:
|
||||
'纯色纯棉休闲圆领短袖T恤纯白亲肤厚柔软细腻面料纯白短袖套头T恤',
|
||||
skuImage: 'https://cdn-we-retail.ym.tencent.com/tsr/goods/nz-08b.png',
|
||||
specInfo: [
|
||||
{
|
||||
specId: '50456',
|
||||
specTitle: '颜色',
|
||||
specValue: '军绿色',
|
||||
},
|
||||
{
|
||||
specId: '50459',
|
||||
specTitle: '尺码',
|
||||
specValue: 'XS',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 36,
|
||||
success: true,
|
||||
},
|
||||
];
|
||||
|
||||
export function genRightsPreview(params) {
|
||||
const { orderNo, skuId } = params;
|
||||
const resp = orderResps.find(
|
||||
(r) => r.data.orderNo === orderNo && r.data.skuId === skuId,
|
||||
);
|
||||
return resp;
|
||||
}
|
||||
|
||||
export function genApplyReasonList(params) {
|
||||
const resp = {
|
||||
data: {
|
||||
saasId: '70000001',
|
||||
rightsReasonList: [
|
||||
{ id: '1', desc: '实际商品与描述不符' },
|
||||
{ id: '2', desc: '质量问题' },
|
||||
{ id: '3', desc: '少件/漏发' },
|
||||
{ id: '4', desc: '包装/商品/污迹/裂痕/变形' },
|
||||
{ id: '5', desc: '发货太慢' },
|
||||
{ id: '6', desc: '物流配送太慢' },
|
||||
{ id: '7', desc: '商家发错货' },
|
||||
{ id: '8', desc: '不喜欢' },
|
||||
],
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 6,
|
||||
success: true,
|
||||
};
|
||||
// 未收货对应的原因列表
|
||||
if (params.rightsReasonType === 'REFUND_MONEY') {
|
||||
resp.data.rightsReasonList = [
|
||||
{ id: '9', desc: '空包裹' },
|
||||
{ id: '10', desc: '快递/物流一直未送到' },
|
||||
{ id: '11', desc: '货物破损已拒签' },
|
||||
{ id: '12', desc: '不喜欢' },
|
||||
];
|
||||
}
|
||||
return resp;
|
||||
}
|
||||
|
||||
export function applyService() {
|
||||
const resp = {
|
||||
data: {
|
||||
rightsNo: '123123423',
|
||||
saasId: '70000001',
|
||||
uid: '700000011070005',
|
||||
storeId: '542',
|
||||
result: null,
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 269,
|
||||
success: true,
|
||||
};
|
||||
return resp;
|
||||
}
|
147
mini-program/model/order/orderConfirm.js
Normal file
147
mini-program/model/order/orderConfirm.js
Normal file
@ -0,0 +1,147 @@
|
||||
import { mockIp, mockReqId } from '../../utils/mock';
|
||||
|
||||
export const transformGoodsDataToConfirmData = (goodsDataList) => {
|
||||
const list = [];
|
||||
|
||||
goodsDataList.forEach((goodsData) => {
|
||||
list.push({
|
||||
storeId: goodsData.storeId,
|
||||
spuId: goodsData.spuId,
|
||||
skuId: goodsData.skuId,
|
||||
goodsName: goodsData.title,
|
||||
image: goodsData.primaryImage,
|
||||
reminderStock: 119,
|
||||
quantity: goodsData.quantity,
|
||||
payPrice: goodsData.price,
|
||||
totalSkuPrice: goodsData.price,
|
||||
discountSettlePrice: goodsData.price,
|
||||
realSettlePrice: goodsData.price,
|
||||
settlePrice: goodsData.price,
|
||||
oriPrice: goodsData.originPrice,
|
||||
tagPrice: null,
|
||||
tagText: null,
|
||||
skuSpecLst: goodsData.specInfo,
|
||||
promotionIds: null,
|
||||
weight: 0.0,
|
||||
unit: 'KG',
|
||||
volume: null,
|
||||
masterGoodsType: 0,
|
||||
viceGoodsType: 0,
|
||||
roomId: goodsData.roomId,
|
||||
egoodsName: null,
|
||||
});
|
||||
});
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
/** 生成结算数据 */
|
||||
export function genSettleDetail(params) {
|
||||
const { userAddressReq, couponList, goodsRequestList } = params;
|
||||
|
||||
const resp = {
|
||||
data: {
|
||||
settleType: 0,
|
||||
userAddress: null,
|
||||
totalGoodsCount: 3,
|
||||
packageCount: 1,
|
||||
totalAmount: '289997',
|
||||
totalPayAmount: '',
|
||||
totalDiscountAmount: '110000',
|
||||
totalPromotionAmount: '1100',
|
||||
totalCouponAmount: '0',
|
||||
totalSalePrice: '289997',
|
||||
totalGoodsAmount: '289997',
|
||||
totalDeliveryFee: '0',
|
||||
invoiceRequest: null,
|
||||
skuImages: null,
|
||||
deliveryFeeList: null,
|
||||
storeGoodsList: [
|
||||
{
|
||||
storeId: '1000',
|
||||
storeName: '云Mall深圳旗舰店',
|
||||
remark: null,
|
||||
goodsCount: 1,
|
||||
deliveryFee: '0',
|
||||
deliveryWords: null,
|
||||
storeTotalAmount: '0',
|
||||
storeTotalPayAmount: '179997',
|
||||
storeTotalDiscountAmount: '110000',
|
||||
storeTotalCouponAmount: '0',
|
||||
skuDetailVos: [],
|
||||
couponList: [
|
||||
{
|
||||
couponId: 11,
|
||||
storeId: '1000',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
inValidGoodsList: null,
|
||||
outOfStockGoodsList: null,
|
||||
limitGoodsList: null,
|
||||
abnormalDeliveryGoodsList: null,
|
||||
invoiceSupport: 1,
|
||||
},
|
||||
code: 'Success',
|
||||
msg: null,
|
||||
requestId: mockReqId(),
|
||||
clientIp: mockIp(),
|
||||
rt: 244,
|
||||
success: true,
|
||||
};
|
||||
|
||||
const list = transformGoodsDataToConfirmData(goodsRequestList);
|
||||
|
||||
// 获取购物车传递的商品数据
|
||||
resp.data.storeGoodsList[0].skuDetailVos = list;
|
||||
|
||||
// 判断是否携带优惠券数据
|
||||
const discountPrice = [];
|
||||
|
||||
if (couponList && couponList.length > 0) {
|
||||
couponList.forEach((coupon) => {
|
||||
if (coupon.status === 'default') {
|
||||
discountPrice.push({
|
||||
type: coupon.type,
|
||||
value: coupon.value,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 模拟计算场景
|
||||
|
||||
// 计算总价
|
||||
const totalPrice = list.reduce((pre, cur) => {
|
||||
return pre + cur.quantity * Number(cur.settlePrice);
|
||||
}, 0);
|
||||
|
||||
// 计算折扣
|
||||
const totalDiscountPrice =
|
||||
discountPrice.length > 0
|
||||
? discountPrice.reduce((pre, cur) => {
|
||||
if (cur.type === 1) {
|
||||
return pre + cur.value;
|
||||
}
|
||||
if (cur.type === 2) {
|
||||
return pre + (Number(totalPrice) * cur.value) / 10;
|
||||
}
|
||||
|
||||
return pre + cur;
|
||||
}, 0)
|
||||
: 0;
|
||||
|
||||
resp.data.totalSalePrice = totalPrice;
|
||||
|
||||
resp.data.totalCouponAmount = totalDiscountPrice;
|
||||
|
||||
resp.data.totalPayAmount =
|
||||
totalPrice - totalDiscountPrice - Number(resp.data.totalPromotionAmount);
|
||||
|
||||
if (userAddressReq) {
|
||||
resp.data.settleType = 1;
|
||||
resp.data.userAddress = userAddressReq;
|
||||
}
|
||||
return resp;
|
||||
}
|
1212
mini-program/model/order/orderDetail.js
Normal file
1212
mini-program/model/order/orderDetail.js
Normal file
File diff suppressed because it is too large
Load Diff
1054
mini-program/model/order/orderList.js
Normal file
1054
mini-program/model/order/orderList.js
Normal file
File diff suppressed because it is too large
Load Diff
21
mini-program/model/promotion.js
Normal file
21
mini-program/model/promotion.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { getGoodsList } from './goods';
|
||||
|
||||
export function getPromotion(baseID = 0, length = 10) {
|
||||
return {
|
||||
list: getGoodsList(baseID, length).map((item) => {
|
||||
return {
|
||||
spuId: item.spuId,
|
||||
thumb: item.primaryImage,
|
||||
title: item.title,
|
||||
price: item.minSalePrice,
|
||||
originPrice: item.maxLinePrice,
|
||||
tags: item.spuTagList.map((tag) => ({ title: tag.title })),
|
||||
};
|
||||
}),
|
||||
banner:
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/promotion/banner-promotion.png',
|
||||
time: 1000 * 60 * 60 * 20,
|
||||
showBannerDesc: true,
|
||||
statusTag: 'running',
|
||||
};
|
||||
}
|
60
mini-program/model/search.js
Normal file
60
mini-program/model/search.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { getGoodsList } from './goods';
|
||||
|
||||
/**
|
||||
* @param {number} sort
|
||||
* @param {number} pageNum
|
||||
* @param {number} pageSize
|
||||
* @param {number} minPrice
|
||||
* @param {number} maxPrice
|
||||
* @param {string} keyword
|
||||
*/
|
||||
|
||||
export function getSearchHistory() {
|
||||
return {
|
||||
historyWords: [
|
||||
'鸡',
|
||||
'电脑',
|
||||
'iPhone12',
|
||||
'车载手机支架',
|
||||
'自然堂',
|
||||
'小米10',
|
||||
'原浆古井贡酒',
|
||||
'欧米伽',
|
||||
'华为',
|
||||
'针织半身裙',
|
||||
'氢跑鞋',
|
||||
'三盒处理器',
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function getSearchPopular() {
|
||||
return {
|
||||
popularWords: [
|
||||
'鸡',
|
||||
'电脑',
|
||||
'iPhone12',
|
||||
'车载手机支架',
|
||||
'自然堂',
|
||||
'小米10',
|
||||
'原浆古井贡酒',
|
||||
'欧米伽',
|
||||
'华为',
|
||||
'针织半身裙',
|
||||
'氢跑鞋',
|
||||
'三盒处理器',
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function getSearchResult() {
|
||||
return {
|
||||
saasId: null,
|
||||
storeId: null,
|
||||
pageNum: 1,
|
||||
pageSize: 30,
|
||||
totalCount: 1,
|
||||
spuList: getGoodsList(7),
|
||||
algId: 0,
|
||||
};
|
||||
}
|
58
mini-program/model/submitComment.js
Normal file
58
mini-program/model/submitComment.js
Normal file
@ -0,0 +1,58 @@
|
||||
export function getGoods() {
|
||||
return {
|
||||
goods: [
|
||||
{
|
||||
squid: '1',
|
||||
checkItems: [
|
||||
{
|
||||
name: '匿名评价',
|
||||
value: 'anonymous',
|
||||
checked: false,
|
||||
},
|
||||
],
|
||||
detail: {
|
||||
image:
|
||||
'https://wx.qlogo.cn/mmopen/vi_32/51VSMNuy1CyHiaAhAjLJ00kMZVqqnCqXeZduCLXHUBr52zFHRGxwL7kGia3fHj8GSNzFcqFDInQmRGM1eWjtQgqA/132',
|
||||
title: '',
|
||||
},
|
||||
goodComment: {
|
||||
/** 商品评价 */
|
||||
rate: 0,
|
||||
/** 评价内容 */
|
||||
label: '123',
|
||||
/** 上传图片 */
|
||||
images: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
squid: '2',
|
||||
checkItems: [
|
||||
{
|
||||
name: '匿名评价',
|
||||
value: 'anonymous',
|
||||
checked: false,
|
||||
},
|
||||
],
|
||||
detail: {
|
||||
image:
|
||||
'https://wx.qlogo.cn/mmopen/vi_32/51VSMNuy1CyHiaAhAjLJ00kMZVqqnCqXeZduCLXHUBr52zFHRGxwL7kGia3fHj8GSNzFcqFDInQmRGM1eWjtQgqA/132',
|
||||
title: '评价内容 山姆智利进口',
|
||||
},
|
||||
goodComment: {
|
||||
/** 商品评价 */
|
||||
rate: 0,
|
||||
/** 评价内容 */
|
||||
label: '山姆智利进口',
|
||||
/** 上传图片 */
|
||||
images: [],
|
||||
},
|
||||
},
|
||||
],
|
||||
storeComment: {
|
||||
/** 物流评价 */
|
||||
logisticsRate: 0,
|
||||
/** 服务评价 */
|
||||
servicesRate: 0,
|
||||
},
|
||||
};
|
||||
}
|
39
mini-program/model/swiper.js
Normal file
39
mini-program/model/swiper.js
Normal file
@ -0,0 +1,39 @@
|
||||
// const images = [
|
||||
// {
|
||||
// img: 'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner1.png',
|
||||
// text: '1',
|
||||
// },
|
||||
// {
|
||||
// img: 'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner2.png',
|
||||
// text: '2',
|
||||
// },
|
||||
// {
|
||||
// img: 'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner3.png',
|
||||
// text: '3',
|
||||
// },
|
||||
// {
|
||||
// img: 'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner4.png',
|
||||
// text: '4',
|
||||
// },
|
||||
// {
|
||||
// img: 'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner5.png',
|
||||
// text: '5',
|
||||
// },
|
||||
// {
|
||||
// img: 'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner6.png',
|
||||
// text: '6',
|
||||
// },
|
||||
// ];
|
||||
|
||||
const images = [
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner1.png',
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner2.png',
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner3.png',
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner4.png',
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner5.png',
|
||||
'https://cdn-we-retail.ym.tencent.com/tsr/home/v2/banner6.png',
|
||||
];
|
||||
|
||||
export function genSwiperImageList() {
|
||||
return images;
|
||||
}
|
52
mini-program/model/usercenter.js
Normal file
52
mini-program/model/usercenter.js
Normal file
@ -0,0 +1,52 @@
|
||||
const userInfo = {
|
||||
avatarUrl:
|
||||
'https://we-retail-static-1300977798.cos.ap-guangzhou.myqcloud.com/retail-ui/components-exp/avatar/avatar-1.jpg',
|
||||
nickName: 'TDesign 🌟',
|
||||
phoneNumber: '13438358888',
|
||||
gender: 2,
|
||||
};
|
||||
const countsData = [
|
||||
{
|
||||
num: 2,
|
||||
name: '积分',
|
||||
type: 'point',
|
||||
},
|
||||
{
|
||||
num: 10,
|
||||
name: '优惠券',
|
||||
type: 'coupon',
|
||||
},
|
||||
];
|
||||
|
||||
const orderTagInfos = [
|
||||
{
|
||||
orderNum: 1,
|
||||
tabType: 5,
|
||||
},
|
||||
{
|
||||
orderNum: 1,
|
||||
tabType: 10,
|
||||
},
|
||||
{
|
||||
orderNum: 1,
|
||||
tabType: 40,
|
||||
},
|
||||
{
|
||||
orderNum: 0,
|
||||
tabType: 0,
|
||||
},
|
||||
];
|
||||
|
||||
const customerServiceInfo = {
|
||||
servicePhone: '4006336868',
|
||||
serviceTimeDuration: '每周三至周五 9:00-12:00 13:00-15:00',
|
||||
};
|
||||
|
||||
export const genSimpleUserInfo = () => ({ ...userInfo });
|
||||
|
||||
export const genUsercenter = () => ({
|
||||
userInfo,
|
||||
countsData,
|
||||
orderTagInfos,
|
||||
customerServiceInfo,
|
||||
});
|
45
mini-program/package.json
Normal file
45
mini-program/package.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "supermarket-pages",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "app.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "eslint --cache --fix --ext .js",
|
||||
"check": "node config/eslintCheck.js",
|
||||
"prepare": "husky install",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js, ts}": "eslint --cache --fix",
|
||||
"*.{js,ts,wxml,html,json,css,less}": [
|
||||
"prettier --write"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"dayjs": "^1.9.3",
|
||||
"tdesign-miniprogram": "^1.0.0",
|
||||
"tslib": "^1.11.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.4.2",
|
||||
"@commitlint/config-conventional": "^17.4.2",
|
||||
"commitizen": "^4.3.0",
|
||||
"conventional-changelog-cli": "^2.2.2",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-prettier": "^6.10.0",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-prettier": "^3.1.2",
|
||||
"husky": "^8.0.3",
|
||||
"lint-staged": "^10.0.8",
|
||||
"prettier": "^2.1.2"
|
||||
}
|
||||
}
|
59
mini-program/pages/cart/components/cart-bar/index.js
Normal file
59
mini-program/pages/cart/components/cart-bar/index.js
Normal file
@ -0,0 +1,59 @@
|
||||
Component({
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
},
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
isAllSelected: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
totalAmount: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
},
|
||||
totalGoodsNum: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
observer(num) {
|
||||
const isDisabled = num == 0;
|
||||
setTimeout(() => {
|
||||
this.setData({
|
||||
isDisabled,
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
totalDiscountAmount: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
bottomHeight: {
|
||||
type: Number,
|
||||
value: 100,
|
||||
},
|
||||
fixed: Boolean,
|
||||
},
|
||||
data: {
|
||||
isDisabled: false,
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleSelectAll() {
|
||||
const { isAllSelected } = this.data;
|
||||
this.setData({
|
||||
isAllSelected: !isAllSelected,
|
||||
});
|
||||
this.triggerEvent('handleSelectAll', {
|
||||
isAllSelected: isAllSelected,
|
||||
});
|
||||
},
|
||||
|
||||
handleToSettle() {
|
||||
if (this.data.isDisabled) return;
|
||||
this.triggerEvent('handleToSettle');
|
||||
},
|
||||
},
|
||||
});
|
7
mini-program/pages/cart/components/cart-bar/index.json
Normal file
7
mini-program/pages/cart/components/cart-bar/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"price": "/components/price/index",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
31
mini-program/pages/cart/components/cart-bar/index.wxml
Normal file
31
mini-program/pages/cart/components/cart-bar/index.wxml
Normal file
@ -0,0 +1,31 @@
|
||||
<view class="cart-bar__placeholder" wx:if="{{fixed}}" />
|
||||
<view class="cart-bar {{fixed ? 'cart-bar--fixed' : ''}} flex flex-v-center" style="bottom: {{fixed ? 'calc(' + bottomHeight + 'rpx + env(safe-area-inset-bottom))' : ''}};">
|
||||
<t-icon
|
||||
size="40rpx"
|
||||
color="{{isAllSelected ? '#FA4126' : '#BBBBBB'}}"
|
||||
name="{{isAllSelected ? 'check-circle-filled' : 'circle'}}"
|
||||
class="cart-bar__check"
|
||||
catchtap="handleSelectAll"
|
||||
/>
|
||||
<text>全选</text>
|
||||
<view class="cart-bar__total flex1">
|
||||
<view>
|
||||
<text class="cart-bar__total--bold text-padding-right">总计</text>
|
||||
<price
|
||||
price="{{totalAmount || '0'}}"
|
||||
fill="{{false}}"
|
||||
decimalSmaller
|
||||
class="cart-bar__total--bold cart-bar__total--price"
|
||||
/>
|
||||
<text class="cart-bar__total--normal">(不含运费)</text>
|
||||
</view>
|
||||
<view wx:if="{{totalDiscountAmount}}">
|
||||
<text class="cart-bar__total--normal text-padding-right">已优惠</text>
|
||||
<price class="cart-bar__total--normal" price="{{totalDiscountAmount || '0'}}" fill="{{false}}" />
|
||||
</view>
|
||||
</view>
|
||||
<view catchtap="handleToSettle" class="{{!isDisabled ? '' : 'disabled-btn'}} account-btn" hover-class="{{!isDisabled ? '' : 'hover-btn'}}">
|
||||
去结算({{totalGoodsNum}})
|
||||
</view>
|
||||
</view>
|
||||
|
80
mini-program/pages/cart/components/cart-bar/index.wxss
Normal file
80
mini-program/pages/cart/components/cart-bar/index.wxss
Normal file
@ -0,0 +1,80 @@
|
||||
.cart-bar__placeholder {
|
||||
height: 100rpx;
|
||||
}
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
.flex-v-center {
|
||||
align-items: center;
|
||||
}
|
||||
.flex1 {
|
||||
flex: 1;
|
||||
}
|
||||
.algin-bottom {
|
||||
text-align: end;
|
||||
}
|
||||
.cart-bar--fixed {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.cart-bar {
|
||||
height: 112rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1rpx solid #e5e5e5;
|
||||
padding: 16rpx 32rpx;
|
||||
box-sizing: border-box;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cart-bar .cart-bar__check {
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.cart-bar .cart-bar__total {
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.cart-bar .account-btn {
|
||||
width: 192rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background-color: #fa4126;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
line-height: 80rpx;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
}
|
||||
.cart-bar .disabled-btn {
|
||||
background-color: #cccccc !important;
|
||||
}
|
||||
.cart-bar .hover-btn {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.cart-bar__total .cart-bar__total--bold {
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cart-bar__total .cart-bar__total--normal {
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.cart-bar__total .cart-bar__total--price {
|
||||
color: #fa4126;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.text-padding-right {
|
||||
padding-right: 4rpx;
|
||||
}
|
23
mini-program/pages/cart/components/cart-empty/index.js
Normal file
23
mini-program/pages/cart/components/cart-empty/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
Component({
|
||||
properties: {
|
||||
imgUrl: {
|
||||
type: String,
|
||||
value:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/template/empty-cart.png',
|
||||
},
|
||||
tip: {
|
||||
type: String,
|
||||
value: '购物车是空的',
|
||||
},
|
||||
btnText: {
|
||||
type: String,
|
||||
value: '去首页',
|
||||
},
|
||||
},
|
||||
data: {},
|
||||
methods: {
|
||||
handleClick() {
|
||||
this.triggerEvent('handleClick');
|
||||
},
|
||||
},
|
||||
});
|
6
mini-program/pages/cart/components/cart-empty/index.json
Normal file
6
mini-program/pages/cart/components/cart-empty/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-image": "/components/webp-image/index"
|
||||
}
|
||||
}
|
6
mini-program/pages/cart/components/cart-empty/index.wxml
Normal file
6
mini-program/pages/cart/components/cart-empty/index.wxml
Normal file
@ -0,0 +1,6 @@
|
||||
<view class="cart-empty">
|
||||
<t-image t-class="cart-img" src="{{imgUrl}}" />
|
||||
<view class="tip">{{tip}}</view>
|
||||
<view class="btn" bind:tap="handleClick">{{btnText}}</view>
|
||||
</view>
|
||||
|
33
mini-program/pages/cart/components/cart-empty/index.wxss
Normal file
33
mini-program/pages/cart/components/cart-empty/index.wxss
Normal file
@ -0,0 +1,33 @@
|
||||
.cart-empty {
|
||||
padding: 64rpx 0rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
height: calc(100vh - 100rpx);
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.cart-empty .cart-img {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.cart-empty .tip {
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
color: #999;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.cart-empty .btn {
|
||||
width: 240rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 36rpx;
|
||||
text-align: center;
|
||||
line-height: 72rpx;
|
||||
border: 2rpx solid #fa4126;
|
||||
color: #fa4126;
|
||||
background-color: transparent;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
}
|
166
mini-program/pages/cart/components/cart-group/index.js
Normal file
166
mini-program/pages/cart/components/cart-group/index.js
Normal file
@ -0,0 +1,166 @@
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
|
||||
const shortageImg =
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/cart/shortage.png';
|
||||
|
||||
Component({
|
||||
isSpecsTap: false, // 标记本次点击事件是否因为点击specs触发(由于底层goods-card组件没有catch specs点击事件,只能在此处加状态来避免点击specs时触发跳转商品详情)
|
||||
externalClasses: ['wr-class'],
|
||||
properties: {
|
||||
storeGoods: {
|
||||
type: Array,
|
||||
observer(storeGoods) {
|
||||
for (const store of storeGoods) {
|
||||
for (const activity of store.promotionGoodsList) {
|
||||
for (const goods of activity.goodsPromotionList) {
|
||||
goods.specs = goods.specInfo.map((item) => item.specValue); // 目前仅展示商品已选规格的值
|
||||
}
|
||||
}
|
||||
for (const goods of store.shortageGoodsList) {
|
||||
goods.specs = goods.specInfo.map((item) => item.specValue); // 目前仅展示商品已选规格的值
|
||||
}
|
||||
}
|
||||
|
||||
this.setData({ _storeGoods: storeGoods });
|
||||
},
|
||||
},
|
||||
invalidGoodItems: {
|
||||
type: Array,
|
||||
observer(invalidGoodItems) {
|
||||
invalidGoodItems.forEach((goods) => {
|
||||
goods.specs = goods.specInfo.map((item) => item.specValue); // 目前仅展示商品已选规格的值
|
||||
});
|
||||
this.setData({ _invalidGoodItems: invalidGoodItems });
|
||||
},
|
||||
},
|
||||
thumbWidth: { type: null },
|
||||
thumbHeight: { type: null },
|
||||
},
|
||||
|
||||
data: {
|
||||
shortageImg,
|
||||
isShowSpecs: false,
|
||||
currentGoods: {},
|
||||
isShowToggle: false,
|
||||
_storeGoods: [],
|
||||
_invalidGoodItems: [],
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 删除商品
|
||||
deleteGoods(e) {
|
||||
const { goods } = e.currentTarget.dataset;
|
||||
this.triggerEvent('delete', { goods });
|
||||
},
|
||||
|
||||
// 清空失效商品
|
||||
clearInvalidGoods() {
|
||||
this.triggerEvent('clearinvalidgoods');
|
||||
},
|
||||
|
||||
// 选中商品
|
||||
selectGoods(e) {
|
||||
const { goods } = e.currentTarget.dataset;
|
||||
this.triggerEvent('selectgoods', {
|
||||
goods,
|
||||
isSelected: !goods.isSelected,
|
||||
});
|
||||
},
|
||||
|
||||
changeQuantity(num, goods) {
|
||||
this.triggerEvent('changequantity', {
|
||||
goods,
|
||||
quantity: num,
|
||||
});
|
||||
},
|
||||
changeStepper(e) {
|
||||
const { value } = e.detail;
|
||||
const { goods } = e.currentTarget.dataset;
|
||||
let num = value;
|
||||
if (value > goods.stack) {
|
||||
num = goods.stack;
|
||||
}
|
||||
this.changeQuantity(num, goods);
|
||||
},
|
||||
|
||||
input(e) {
|
||||
const { value } = e.detail;
|
||||
const { goods } = e.currentTarget.dataset;
|
||||
const num = value;
|
||||
this.changeQuantity(num, goods);
|
||||
},
|
||||
|
||||
overlimit(e) {
|
||||
const text =
|
||||
e.detail.type === 'minus'
|
||||
? '该商品数量不能减少了哦'
|
||||
: '同一商品最多购买999件';
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: text,
|
||||
});
|
||||
},
|
||||
|
||||
// 去凑单/再逛逛
|
||||
gotoBuyMore(e) {
|
||||
const { promotion, storeId = '' } = e.currentTarget.dataset;
|
||||
this.triggerEvent('gocollect', { promotion, storeId });
|
||||
},
|
||||
|
||||
// 选中门店
|
||||
selectStore(e) {
|
||||
const { storeIndex } = e.currentTarget.dataset;
|
||||
const store = this.data.storeGoods[storeIndex];
|
||||
const isSelected = !store.isSelected;
|
||||
if (store.storeStockShortage && isSelected) {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '部分商品库存不足',
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.triggerEvent('selectstore', {
|
||||
store,
|
||||
isSelected,
|
||||
});
|
||||
},
|
||||
|
||||
// 展开/收起切换
|
||||
showToggle() {
|
||||
this.setData({
|
||||
isShowToggle: !this.data.isShowToggle,
|
||||
});
|
||||
},
|
||||
|
||||
// 展示规格popup
|
||||
specsTap(e) {
|
||||
this.isSpecsTap = true;
|
||||
const { goods } = e.currentTarget.dataset;
|
||||
this.setData({
|
||||
isShowSpecs: true,
|
||||
currentGoods: goods,
|
||||
});
|
||||
},
|
||||
|
||||
hideSpecsPopup() {
|
||||
this.setData({
|
||||
isShowSpecs: false,
|
||||
});
|
||||
},
|
||||
|
||||
goGoodsDetail(e) {
|
||||
if (this.isSpecsTap) {
|
||||
this.isSpecsTap = false;
|
||||
return;
|
||||
}
|
||||
const { goods } = e.currentTarget.dataset;
|
||||
this.triggerEvent('goodsclick', { goods });
|
||||
},
|
||||
|
||||
gotoCoupons() {
|
||||
wx.navigateTo({ url: '/pages/coupon/coupon-list/index' });
|
||||
},
|
||||
},
|
||||
});
|
11
mini-program/pages/cart/components/cart-group/index.json
Normal file
11
mini-program/pages/cart/components/cart-group/index.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-stepper": "tdesign-miniprogram/stepper/stepper",
|
||||
"swipeout": "/components/swipeout/index",
|
||||
"goods-card": "../../components/goods-card/index",
|
||||
"specs-popup": "../../components/specs-popup/index"
|
||||
}
|
||||
}
|
152
mini-program/pages/cart/components/cart-group/index.wxml
Normal file
152
mini-program/pages/cart/components/cart-group/index.wxml
Normal file
@ -0,0 +1,152 @@
|
||||
<wxs src="./index.wxs" module="handlePromotion" />
|
||||
<wxs src="./utils.wxs" module="utils" />
|
||||
|
||||
<view class="cart-group">
|
||||
<view class="goods-wrap" wx:for="{{_storeGoods}}" wx:for-item="store" wx:for-index="si" wx:key="storeId">
|
||||
<view class="cart-store">
|
||||
<t-icon
|
||||
size="40rpx"
|
||||
color="{{store.isSelected ? '#FA4126' : '#BBBBBB'}}"
|
||||
name="{{store.isSelected ? 'check-circle-filled' : 'circle'}}"
|
||||
class="cart-store__check"
|
||||
bindtap="selectStore"
|
||||
data-store-index="{{si}}"
|
||||
/>
|
||||
<view class="cart-store__content">
|
||||
<view class="store-title">
|
||||
<t-icon prefix="wr" size="40rpx" color="#333333" name="store" />
|
||||
<view class="store-name">{{store.storeName}}</view>
|
||||
</view>
|
||||
<view class="get-coupon" catch:tap="gotoCoupons">优惠券</view>
|
||||
</view>
|
||||
</view>
|
||||
<block wx:for="{{store.promotionGoodsList}}" wx:for-item="promotion" wx:for-index="promoindex" wx:key="promoindex">
|
||||
<view
|
||||
class="promotion-wrap"
|
||||
wx:if="{{handlePromotion.hasPromotion(promotion.promotionCode)}}"
|
||||
bindtap="gotoBuyMore"
|
||||
data-promotion="{{promotion}}"
|
||||
data-store-id="{{store.storeId}}"
|
||||
>
|
||||
<view class="promotion-title">
|
||||
<view class="promotion-icon">{{promotion.tag}}</view>
|
||||
<view class="promotion-text">{{promotion.description}}</view>
|
||||
</view>
|
||||
<view class="promotion-action action-btn" hover-class="action-btn--active">
|
||||
<view class="promotion-action-label"> {{promotion.isNeedAddOnShop == 1 ? '去凑单' : '再逛逛'}} </view>
|
||||
<t-icon name="chevron-right" size="32rpx" color="#BBBBBB" />
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="goods-item"
|
||||
wx:for="{{promotion.goodsPromotionList}}"
|
||||
wx:for-item="goods"
|
||||
wx:for-index="gi"
|
||||
wx:key="extKey"
|
||||
>
|
||||
<swipeout right-width="{{ 72 }}">
|
||||
<view class="goods-item-info">
|
||||
<view class="check-wrap" catchtap="selectGoods" data-goods="{{goods}}">
|
||||
<t-icon
|
||||
size="40rpx"
|
||||
color="{{goods.isSelected ? '#FA4126' : '#BBBBBB'}}"
|
||||
name="{{goods.isSelected ? 'check-circle-filled' : 'circle'}}"
|
||||
class="check"
|
||||
/>
|
||||
</view>
|
||||
<view class="goods-sku-info">
|
||||
<goods-card
|
||||
layout="horizontal-wrap"
|
||||
thumb-width="{{thumbWidth}}"
|
||||
thumb-height="{{thumbHeight}}"
|
||||
centered="{{true}}"
|
||||
data="{{goods}}"
|
||||
data-goods="{{goods}}"
|
||||
catchspecs="specsTap"
|
||||
catchclick="goGoodsDetail"
|
||||
>
|
||||
<view slot="thumb-cover" class="stock-mask" wx:if="{{goods.shortageStock || goods.stockQuantity <= 3}}">
|
||||
仅剩{{goods.stockQuantity}}件
|
||||
</view>
|
||||
<view slot="append-body" class="goods-stepper">
|
||||
<view class="stepper-tip" wx:if="{{goods.shortageStock}}">库存不足</view>
|
||||
<t-stepper
|
||||
classname="stepper-info"
|
||||
value="{{goods.quantity}}"
|
||||
min="{{1}}"
|
||||
max="{{999}}"
|
||||
data-goods="{{goods}}"
|
||||
data-gi="{{gi}}"
|
||||
data-si="{{si}}"
|
||||
catchchange="changeStepper"
|
||||
catchblur="input"
|
||||
catchoverlimit="overlimit"
|
||||
theme="filled"
|
||||
/>
|
||||
</view>
|
||||
</goods-card>
|
||||
</view>
|
||||
</view>
|
||||
<view slot="right" class="swiper-right-del" bindtap="deleteGoods" data-goods="{{goods}}"> 删除 </view>
|
||||
</swipeout>
|
||||
</view>
|
||||
<view
|
||||
class="promotion-line-wrap"
|
||||
wx:if="{{handlePromotion.hasPromotion(promotion.promotionCode) && promoindex != (store.promotionGoodsList.length - 2)}}"
|
||||
>
|
||||
<view class="promotion-line" />
|
||||
</view>
|
||||
</block>
|
||||
<block wx:if="{{store.shortageGoodsList.length>0}}">
|
||||
<view
|
||||
class="goods-item"
|
||||
wx:for="{{store.shortageGoodsList}}"
|
||||
wx:for-item="goods"
|
||||
wx:for-index="gi"
|
||||
wx:key="extKey"
|
||||
>
|
||||
<swipeout right-width="{{ 72 }}">
|
||||
<view class="goods-item-info">
|
||||
<view class="check-wrap">
|
||||
<view class="unCheck-icon" />
|
||||
</view>
|
||||
<view class="goods-sku-info">
|
||||
<goods-card
|
||||
layout="horizontal-wrap"
|
||||
thumb-width="{{thumbWidth}}"
|
||||
thumb-height="{{thumbHeight}}"
|
||||
centered="{{true}}"
|
||||
data="{{goods}}"
|
||||
data-goods="{{goods}}"
|
||||
catchspecs="specsTap"
|
||||
catchclick="goGoodsDetail"
|
||||
>
|
||||
<view slot="thumb-cover" class="no-storage-mask" wx:if="{{goods.stockQuantity <=0}}">
|
||||
<view class="no-storage-content">无货</view>
|
||||
</view>
|
||||
</goods-card>
|
||||
</view>
|
||||
</view>
|
||||
<view slot="right" class="swiper-right-del" bindtap="deleteGoods" data-goods="{{goods}}"> 删除 </view>
|
||||
</swipeout>
|
||||
</view>
|
||||
<view
|
||||
class="promotion-line-wrap"
|
||||
wx:if="{{handlePromotion.hasPromotion(promotion.promotionCode) && promoindex != (store.promotionGoodsList.length - 2)}}"
|
||||
>
|
||||
<view class="promotion-line" />
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<specs-popup
|
||||
show="{{isShowSpecs}}"
|
||||
title="{{currentGoods.title || ''}}"
|
||||
price="{{currentGoods.price || ''}}"
|
||||
thumb="{{utils.imgCut(currentGoods.thumb, 180, 180)}}"
|
||||
specs="{{currentGoods.specs || []}}"
|
||||
zIndex="{{999}}"
|
||||
bindclose="hideSpecsPopup"
|
||||
/>
|
||||
|
||||
<t-toast id="t-toast" />
|
5
mini-program/pages/cart/components/cart-group/index.wxs
Normal file
5
mini-program/pages/cart/components/cart-group/index.wxs
Normal file
@ -0,0 +1,5 @@
|
||||
var hasPromotion = function (code) {
|
||||
return code && code !== 'EMPTY_PROMOTION';
|
||||
};
|
||||
|
||||
module.exports.hasPromotion = hasPromotion;
|
335
mini-program/pages/cart/components/cart-group/index.wxss
Normal file
335
mini-program/pages/cart/components/cart-group/index.wxss
Normal file
@ -0,0 +1,335 @@
|
||||
.cart-group {
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
.cart-group .goods-wrap {
|
||||
margin-top: 40rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cart-group .goods-wrap:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
.cart-group .cart-store {
|
||||
height: 96rpx;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0rpx 24rpx 0rpx 36rpx;
|
||||
}
|
||||
.cart-group .cart-store .cart-store__check {
|
||||
padding: 28rpx 32rpx 28rpx 0rpx;
|
||||
}
|
||||
.cart-group .cart-store__content {
|
||||
box-sizing: border-box;
|
||||
flex: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.cart-group .cart-store__content .store-title {
|
||||
flex: auto;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
color: #333333;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: bold;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cart-group .cart-store__content .store-title .wr-store {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.cart-group .cart-store__content .store-title .store-name {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
.cart-group .cart-store__content .get-coupon {
|
||||
width: 112rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #ffecf9;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: #fa4126;
|
||||
}
|
||||
|
||||
.cart-group .promotion-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0rpx 24rpx 32rpx 36rpx;
|
||||
background-color: #ffffff;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
color: #222427;
|
||||
}
|
||||
.cart-group .promotion-wrap .promotion-title {
|
||||
font-weight: bold;
|
||||
flex: auto;
|
||||
overflow: hidden;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.cart-group .promotion-wrap .promotion-title .promotion-icon {
|
||||
flex: none;
|
||||
font-weight: normal;
|
||||
display: inline-block;
|
||||
padding: 0 8rpx;
|
||||
color: #ffffff;
|
||||
background: #fa4126;
|
||||
font-size: 20rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
margin-right: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
.cart-group .promotion-wrap .promotion-title .promotion-text {
|
||||
flex: auto;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cart-group .promotion-wrap .promotion-action {
|
||||
flex: none;
|
||||
color: #333333;
|
||||
}
|
||||
.cart-group .promotion-line-wrap {
|
||||
background-color: #fff;
|
||||
height: 2rpx;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.cart-group .promotion-line-wrap .promotion-line {
|
||||
width: 684rpx;
|
||||
height: 2rpx;
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.cart-group .goods-item-info {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.cart-group .goods-item-info .check-wrap {
|
||||
margin-top: 56rpx;
|
||||
padding: 20rpx 28rpx 20rpx 36rpx;
|
||||
}
|
||||
|
||||
.cart-group .goods-item-info .check-wrap .unCheck-icon {
|
||||
box-sizing: border-box;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
border-radius: 20rpx;
|
||||
background: #f5f5f5;
|
||||
border: 2rpx solid #bbbbbb;
|
||||
}
|
||||
|
||||
.cart-group .goods-item-info .goods-sku-info {
|
||||
padding: 0rpx 32rpx 40rpx 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.cart-group .goods-item-info .goods-sku-info .stock-mask {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
bottom: 0rpx;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
height: 40rpx;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
.cart-group .goods-item-info .goods-sku-info .goods-stepper {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 8rpx;
|
||||
}
|
||||
.cart-group .goods-item-info .goods-sku-info .goods-stepper .stepper-tip {
|
||||
position: absolute;
|
||||
top: -36rpx;
|
||||
right: 0;
|
||||
height: 28rpx;
|
||||
color: #ff2525;
|
||||
font-size: 20rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
|
||||
.cart-group .shortage-line {
|
||||
width: 662rpx;
|
||||
height: 2rpx;
|
||||
background-color: #e6e6e6;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.cart-group .shortage-goods-wrap {
|
||||
background-color: #fff;
|
||||
}
|
||||
.cart-group .shortage-goods-wrap .shortage-tip-title {
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
padding-left: 28rpx;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
.stepper-info {
|
||||
margin-left: auto;
|
||||
}
|
||||
.invalid-goods-wrap {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
.invalid-goods-wrap .invalid-head {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 20rpx;
|
||||
font-size: 24rpx;
|
||||
border-bottom: 2rpx solid #f6f6f6;
|
||||
}
|
||||
.invalid-goods-wrap .invalid-head .invalid-title {
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.invalid-goods-wrap .invalid-head .invalid-clear {
|
||||
color: #fa4126;
|
||||
}
|
||||
.invalid-goods-wrap .toggle {
|
||||
display: flex;
|
||||
height: 80rpx;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
color: #fa4126;
|
||||
}
|
||||
.invalid-goods-wrap .toggle .m-r-6 {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
.invalid-goods-wrap .toggle .top-icon {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10rpx solid transparent;
|
||||
border-right: 10rpx solid transparent;
|
||||
border-bottom: 10rpx solid #fa4126;
|
||||
}
|
||||
.invalid-goods-wrap .toggle .down-icon {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 10rpx solid transparent;
|
||||
border-right: 10rpx solid transparent;
|
||||
border-top: 10rpx solid #fa4126;
|
||||
}
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.action-btn .action-btn-arrow {
|
||||
font-size: 20rpx;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
.action-btn--active {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.swiper-right-del {
|
||||
height: calc(100% - 40rpx);
|
||||
width: 144rpx;
|
||||
background-color: #fa4126;
|
||||
font-size: 28rpx;
|
||||
color: white;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.goods-stepper .stepper {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
height: auto;
|
||||
width: 168rpx;
|
||||
overflow: visible;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__minus,
|
||||
.goods-stepper .stepper .stepper__plus {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__minus--hover,
|
||||
.goods-stepper .stepper .stepper__plus--hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__minus .wr-icon,
|
||||
.goods-stepper .stepper .stepper__plus .wr-icon {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__minus {
|
||||
position: relative;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__minus::after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
content: ' ';
|
||||
left: -20rpx;
|
||||
right: -5rpx;
|
||||
top: -20rpx;
|
||||
bottom: -20rpx;
|
||||
background-color: transparent;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__plus {
|
||||
position: relative;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__plus::after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
content: ' ';
|
||||
left: -5rpx;
|
||||
right: -20rpx;
|
||||
top: -20rpx;
|
||||
bottom: -20rpx;
|
||||
background-color: transparent;
|
||||
}
|
||||
.goods-stepper .stepper .stepper__input {
|
||||
width: 72rpx;
|
||||
height: 44rpx;
|
||||
background-color: #f5f5f5;
|
||||
font-size: 24rpx;
|
||||
color: #222427;
|
||||
font-weight: 600;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
min-height: 40rpx;
|
||||
margin: 0 4rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.goods-sku-info .no-storage-mask {
|
||||
position: absolute;
|
||||
color: #fff;
|
||||
bottom: 0rpx;
|
||||
left: 0rpx;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
height: 192rpx;
|
||||
width: 192rpx;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.no-storage-mask .no-storage-content {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
border-radius: 64rpx;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
text-align: center;
|
||||
line-height: 128rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
20
mini-program/pages/cart/components/cart-group/utils.wxs
Normal file
20
mini-program/pages/cart/components/cart-group/utils.wxs
Normal file
@ -0,0 +1,20 @@
|
||||
module.exports.slice = function(arr) {
|
||||
return arr.slice(0, 2);
|
||||
};
|
||||
module.exports.imgCut = function(url, width, height) {
|
||||
if (url && (url.slice(0, 5) === 'http:' || url.slice(0, 6) === 'https:' || url.slice(0, 2) === '//')) {
|
||||
var argsStr = 'imageMogr2/thumbnail/!' + width + 'x' + height + 'r';
|
||||
if (url.indexOf('?') > -1) {
|
||||
url = url + '&' + argsStr;
|
||||
} else {
|
||||
url = url + '?' + argsStr;
|
||||
}
|
||||
if (url.slice(0, 5) === 'http:') {
|
||||
url = 'https://' + url.slice(5)
|
||||
}
|
||||
if (url.slice(0, 2) === '//') {
|
||||
url = 'https:' + url
|
||||
}
|
||||
}
|
||||
return url;
|
||||
};
|
243
mini-program/pages/cart/components/goods-card/index.js
Normal file
243
mini-program/pages/cart/components/goods-card/index.js
Normal file
@ -0,0 +1,243 @@
|
||||
Component({
|
||||
options: {
|
||||
multipleSlots: true, // 在组件定义时的选项中启用多slot支持
|
||||
addGlobalClass: true,
|
||||
},
|
||||
intersectionObserverContext: null,
|
||||
|
||||
externalClasses: [
|
||||
'card-class',
|
||||
'title-class',
|
||||
'desc-class',
|
||||
'num-class',
|
||||
'thumb-class',
|
||||
'specs-class',
|
||||
'price-class',
|
||||
'origin-price-class',
|
||||
'price-prefix-class',
|
||||
],
|
||||
|
||||
properties: {
|
||||
hidden: {
|
||||
// 设置为null代表不做类型转换
|
||||
type: null,
|
||||
value: false,
|
||||
observer(hidden) {
|
||||
// null就是代表没有设置,没有设置的话不setData,防止祖先组件触发的setHidden操作被覆盖
|
||||
if (hidden !== null) {
|
||||
this.setHidden(!!hidden);
|
||||
}
|
||||
},
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
// `goods-card-88888888`
|
||||
// 不能在这里写生成逻辑,如果在这里写,那么假设有多个goods-list时,他们将共享这个值
|
||||
value: '',
|
||||
observer: (id) => {
|
||||
this.genIndependentID(id);
|
||||
if (this.properties.thresholds?.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
},
|
||||
data: {
|
||||
type: Object,
|
||||
observer(goods) {
|
||||
// 有ID的商品才渲染
|
||||
if (!goods) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** 划线价是否有效 */
|
||||
let isValidityLinePrice = true;
|
||||
// 判断一次划线价格是否合理
|
||||
if (
|
||||
goods.originPrice &&
|
||||
goods.price &&
|
||||
goods.originPrice < goods.price
|
||||
) {
|
||||
isValidityLinePrice = false;
|
||||
}
|
||||
|
||||
// 敲定换行数量默认值
|
||||
if (goods.lineClamp === undefined || goods.lineClamp <= 0) {
|
||||
// tag数组长度 大于0 且 可见
|
||||
// 指定换行为1行
|
||||
if ((goods.tags?.length || 0) > 0 && !goods.hideKey?.tags) {
|
||||
goods.lineClamp = 1;
|
||||
} else {
|
||||
goods.lineClamp = 2;
|
||||
}
|
||||
}
|
||||
|
||||
this.setData({ goods, isValidityLinePrice });
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
value: 'horizontal',
|
||||
},
|
||||
thumbMode: {
|
||||
type: String,
|
||||
value: 'aspectFill',
|
||||
},
|
||||
priceFill: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
currency: {
|
||||
type: String,
|
||||
value: '¥',
|
||||
},
|
||||
lazyLoad: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
centered: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
pricePrefix: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
/** 元素可见监控阈值, 数组长度大于0就创建 */
|
||||
thresholds: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer(current) {
|
||||
if (current && current.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
} else {
|
||||
this.clearIntersectionObserverHandle();
|
||||
}
|
||||
},
|
||||
},
|
||||
specsIconClassPrefix: {
|
||||
type: String,
|
||||
value: 'wr',
|
||||
},
|
||||
specsIcon: {
|
||||
type: String,
|
||||
value: 'expand_more',
|
||||
},
|
||||
addCartIconClassPrefix: {
|
||||
type: String,
|
||||
value: 'wr',
|
||||
},
|
||||
addCartIcon: {
|
||||
type: String,
|
||||
value: 'cart',
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
hiddenInData: false,
|
||||
independentID: '',
|
||||
goods: { id: '' },
|
||||
/** 保证划线价格不小于原价,否则不渲染划线价 */
|
||||
isValidityLinePrice: false,
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready() {
|
||||
this.init();
|
||||
},
|
||||
detached() {
|
||||
this.clear();
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
clickHandle() {
|
||||
this.triggerEvent('click', { goods: this.data.goods });
|
||||
},
|
||||
clickThumbHandle() {
|
||||
this.triggerEvent('thumb', { goods: this.data.goods });
|
||||
},
|
||||
clickSpecsHandle() {
|
||||
this.triggerEvent('specs', { goods: this.data.goods });
|
||||
},
|
||||
clickTagHandle(evt) {
|
||||
const { index } = evt.currentTarget.dataset;
|
||||
this.triggerEvent('tag', { goods: this.data.goods, index });
|
||||
},
|
||||
// 加入购物车
|
||||
addCartHandle(e) {
|
||||
const { id } = e.currentTarget;
|
||||
const { id: cardID } = e.currentTarget.dataset;
|
||||
this.triggerEvent('add-cart', {
|
||||
...e.detail,
|
||||
id,
|
||||
cardID,
|
||||
goods: this.data.goods,
|
||||
});
|
||||
},
|
||||
genIndependentID(id, cb) {
|
||||
let independentID;
|
||||
if (id) {
|
||||
independentID = id;
|
||||
} else {
|
||||
independentID = `goods-card-${~~(Math.random() * 10 ** 8)}`;
|
||||
}
|
||||
this.setData({ independentID }, cb);
|
||||
},
|
||||
|
||||
init() {
|
||||
const { thresholds, id, hidden } = this.properties;
|
||||
if (hidden !== null) {
|
||||
this.setHidden(!!hidden);
|
||||
}
|
||||
|
||||
this.genIndependentID(id || '', () => {
|
||||
if (thresholds && thresholds.length) {
|
||||
this.createIntersectionObserverHandle();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clear() {
|
||||
this.clearIntersectionObserverHandle();
|
||||
},
|
||||
|
||||
setHidden(hidden) {
|
||||
this.setData({ hiddenInData: !!hidden });
|
||||
},
|
||||
|
||||
createIntersectionObserverHandle() {
|
||||
if (this.intersectionObserverContext || !this.data.independentID) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.intersectionObserverContext = wx
|
||||
.createIntersectionObserver(this, {
|
||||
thresholds: this.properties.thresholds,
|
||||
})
|
||||
.relativeToViewport();
|
||||
|
||||
this.intersectionObserverContext.observe(
|
||||
`#${this.data.independentID}`,
|
||||
(res) => {
|
||||
this.intersectionObserverCB(res);
|
||||
},
|
||||
);
|
||||
},
|
||||
intersectionObserverCB(ob) {
|
||||
this.triggerEvent('ob', {
|
||||
goods: this.data.goods,
|
||||
context: this.intersectionObserverContext,
|
||||
ob,
|
||||
});
|
||||
},
|
||||
clearIntersectionObserverHandle() {
|
||||
if (this.intersectionObserverContext) {
|
||||
try {
|
||||
this.intersectionObserverContext.disconnect();
|
||||
} catch (e) {}
|
||||
|
||||
this.intersectionObserverContext = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
9
mini-program/pages/cart/components/goods-card/index.json
Normal file
9
mini-program/pages/cart/components/goods-card/index.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"price": "/components/price/index",
|
||||
"t-tag": "tdesign-miniprogram/tag/tag",
|
||||
"t-image": "/components/webp-image/index",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
75
mini-program/pages/cart/components/goods-card/index.wxml
Normal file
75
mini-program/pages/cart/components/goods-card/index.wxml
Normal file
@ -0,0 +1,75 @@
|
||||
<view
|
||||
id="{{independentID}}"
|
||||
class="wr-goods-card card-class {{ layout }} {{ centered ? 'center' : ''}}"
|
||||
bind:tap="clickHandle"
|
||||
data-goods="{{ goods }}"
|
||||
hidden="{{hiddenInData}}"
|
||||
>
|
||||
<view class="wr-goods-card__main">
|
||||
<view class="wr-goods-card__thumb thumb-class" bind:tap="clickThumbHandle">
|
||||
<!-- data-src 是方便加购动画读取图片用的 -->
|
||||
<t-image
|
||||
t-class="wr-goods-card__thumb-com"
|
||||
wx:if="{{ !!goods.thumb && !goods.hideKey.thumb }}"
|
||||
src="{{ goods.thumb }}"
|
||||
mode="{{ thumbMode }}"
|
||||
lazy-load="{{ lazyLoad }}"
|
||||
/>
|
||||
<slot name="thumb-cover" />
|
||||
</view>
|
||||
<view class="wr-goods-card__body">
|
||||
<view class="wr-goods-card__long_content">
|
||||
<view wx:if="{{ goods.title && !goods.hideKey.title }}" class="wr-goods-card__title title-class" style="-webkit-line-clamp: {{ goods.lineClamp }};">
|
||||
<slot name="before-title" />
|
||||
{{ goods.title }}
|
||||
</view>
|
||||
<slot name="after-title" />
|
||||
<view wx:if="{{ goods.desc && !goods.hideKey.desc }}" class="wr-goods-card__desc desc-class">{{ goods.desc }}</view>
|
||||
<slot name="after-desc" />
|
||||
<view wx:if="{{ goods.specs && goods.specs.length > 0 && !goods.hideKey.specs }}" class="wr-goods-card__specs__desc specs-class" bind:tap="clickSpecsHandle">
|
||||
<view class="wr-goods-card__specs__desc-text">{{ goods.specs }}</view>
|
||||
<t-icon name="chevron-down" size="32rpx" color="#999999" />
|
||||
</view>
|
||||
<view class="goods_tips" wx:if="{{goods.stockQuantity !== 0 && goods.quantity >= goods.stockQuantity}}">库存不足</view>
|
||||
</view>
|
||||
<view class="wr-goods-card__short_content">
|
||||
<block wx:if="{{goods.stockQuantity !== 0}}">
|
||||
<view wx:if="{{ pricePrefix }}" class="wr-goods-card__price__prefix price-prefix-class">{{ pricePrefix }}</view>
|
||||
<slot name="price-prefix" />
|
||||
<view wx:if="{{ goods.price && !goods.hideKey.price }}" class="wr-goods-card__price">
|
||||
<price
|
||||
wr-class="price-class"
|
||||
symbol="{{currency}}"
|
||||
price="{{goods.price}}"
|
||||
fill="{{priceFill}}"
|
||||
decimalSmaller
|
||||
/>
|
||||
</view>
|
||||
<view wx:if="{{ goods.originPrice && !goods.hideKey.originPrice && isValidityLinePrice }}" class="wr-goods-card__origin-price">
|
||||
<price
|
||||
wr-class="origin-price-class"
|
||||
symbol="{{currency}}"
|
||||
price="{{goods.originPrice}}"
|
||||
fill="{{priceFill}}"
|
||||
/>
|
||||
</view>
|
||||
<slot name="origin-price" />
|
||||
<view wx:if="{{goods.num && !goods.hideKey.num}}" class="wr-goods-card__num num-class">
|
||||
<text class="wr-goods-card__num__prefix">x </text>
|
||||
{{ goods.num }}
|
||||
</view>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<view class="no_storage">
|
||||
<view>请重新选择商品规格</view>
|
||||
<view class="no_storage__right">重选</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<slot name="append-body" />
|
||||
</view>
|
||||
<slot name="footer" />
|
||||
</view>
|
||||
<slot name="append-card" />
|
||||
</view>
|
||||
|
260
mini-program/pages/cart/components/goods-card/index.wxss
Normal file
260
mini-program/pages/cart/components/goods-card/index.wxss
Normal file
@ -0,0 +1,260 @@
|
||||
.wr-goods-card {
|
||||
box-sizing: border-box;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
/* */
|
||||
.wr-goods-card__main {
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.wr-goods-card.center .wr-goods-card__main {
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.wr-goods-card__thumb {
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
}
|
||||
|
||||
.wr-goods-card__thumb-com {
|
||||
width: 192rpx;
|
||||
height: 192rpx;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-goods-card__thumb:empty {
|
||||
display: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.wr-goods-card__body {
|
||||
display: flex;
|
||||
margin: 0 0 0 20rpx;
|
||||
flex-direction: row;
|
||||
flex: 1 1 auto;
|
||||
min-height: 192rpx;
|
||||
}
|
||||
|
||||
.wr-goods-card__long_content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.wr-goods-card__long_content .goods_tips {
|
||||
width: 100%;
|
||||
margin-top: 16rpx;
|
||||
text-align: right;
|
||||
color: #fa4126;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.wr-goods-card__title {
|
||||
flex-shrink: 0;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
line-height: 40rpx;
|
||||
font-weight: 400;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
}
|
||||
.wr-goods-card__title__prefix-tags {
|
||||
display: inline-flex;
|
||||
}
|
||||
.wr-goods-card__title__prefix-tags .prefix-tag {
|
||||
margin: 0 8rpx 0 0;
|
||||
}
|
||||
.wr-goods-card__desc {
|
||||
font-size: 24rpx;
|
||||
color: #f5f5f5;
|
||||
line-height: 40rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-goods-card__specs__desc,
|
||||
.wr-goods-card__specs__text {
|
||||
font-size: 24rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
color: #999999;
|
||||
margin: 8rpx 0;
|
||||
}
|
||||
.wr-goods-card__specs__desc {
|
||||
display: flex;
|
||||
align-self: flex-start;
|
||||
flex-direction: row;
|
||||
background: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
padding: 4rpx 8rpx;
|
||||
}
|
||||
.wr-goods-card__specs__desc-text {
|
||||
height: 100%;
|
||||
max-width: 380rpx;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
.wr-goods-card__specs__desc-icon {
|
||||
line-height: inherit;
|
||||
margin-left: 8rpx;
|
||||
font-size: 24rpx;
|
||||
color: #bbb;
|
||||
}
|
||||
.wr-goods-card__specs__text {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
}
|
||||
.wr-goods-card__tags {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: 16rpx 0 0 0;
|
||||
}
|
||||
.wr-goods-card__tag {
|
||||
color: #fa550f;
|
||||
background: transparent;
|
||||
font-size: 20rpx;
|
||||
border: 1rpx solid #fa550f;
|
||||
padding: 0 8rpx;
|
||||
height: 30rpx;
|
||||
line-height: 30rpx;
|
||||
margin: 0 8rpx 8rpx 0;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
word-break: keep-all;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.wr-goods-card__short_content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-end;
|
||||
margin: 0 0 0 46rpx;
|
||||
}
|
||||
.wr-goods-card__price__prefix {
|
||||
order: 0;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
}
|
||||
.wr-goods-card__price {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
order: 1;
|
||||
color: #fa4126;
|
||||
font-size: 36rpx;
|
||||
margin: 0;
|
||||
line-height: 48rpx;
|
||||
}
|
||||
.wr-goods-card__origin-price {
|
||||
white-space: nowrap;
|
||||
font-weight: normal;
|
||||
order: 2;
|
||||
color: #aaaaaa;
|
||||
font-size: 24rpx;
|
||||
margin: 0;
|
||||
}
|
||||
.wr-goods-card__num {
|
||||
white-space: nowrap;
|
||||
order: 4;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin: 20rpx 0 0 auto;
|
||||
}
|
||||
.wr-goods-card__num__prefix {
|
||||
color: inherit;
|
||||
}
|
||||
.wr-goods-card__add-cart {
|
||||
order: 3;
|
||||
margin: auto 0 0 auto;
|
||||
}
|
||||
.wr-goods-card.horizontal-wrap .wr-goods-card__thumb {
|
||||
width: 192rpx;
|
||||
height: 192rpx;
|
||||
border-radius: 8rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-goods-card.horizontal-wrap .wr-goods-card__body {
|
||||
flex-direction: column;
|
||||
}
|
||||
.wr-goods-card.horizontal-wrap .wr-goods-card__short_content {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin: 16rpx 0 0 0;
|
||||
}
|
||||
|
||||
.wr-goods-card.horizontal-wrap .wr-goods-card__num {
|
||||
margin: 0 0 0 auto;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__main {
|
||||
padding: 0 0 22rpx 0;
|
||||
flex-direction: column;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__thumb {
|
||||
width: 340rpx;
|
||||
height: 340rpx;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__body {
|
||||
margin: 20rpx 20rpx 0 20rpx;
|
||||
flex-direction: column;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__long_content {
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__title {
|
||||
line-height: 36rpx;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__short_content {
|
||||
margin: 20rpx 0 0 0;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__price {
|
||||
order: 2;
|
||||
color: #fa4126;
|
||||
margin: 20rpx 0 0 0;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__origin-price {
|
||||
order: 1;
|
||||
}
|
||||
.wr-goods-card.vertical .wr-goods-card__add-cart {
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
right: 20rpx;
|
||||
}
|
||||
|
||||
.wr-goods-card__short_content .no_storage {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40rpx;
|
||||
color: #333;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.no_storage .no_storage__right {
|
||||
width: 80rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 2rpx solid #fa4126;
|
||||
line-height: 40rpx;
|
||||
text-align: center;
|
||||
color: #fa4126;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user