init
This commit is contained in:
commit
369aecfb32
160
.eslintrc.js
Normal file
160
.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
.gitignore
vendored
Normal file
15
.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
.husky/commit-msg
Normal file
4
.husky/commit-msg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx --no-install commitlint --edit ""
|
4
.husky/pre-commit
Normal file
4
.husky/pre-commit
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
. "$(dirname "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
npx lint-staged
|
4
.husky/prepare-commit-msg
Normal file
4
.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
.npmrc
Normal file
9
.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
.prettierignore
Normal file
3
.prettierignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
miniprogram_npm
|
||||||
|
package.json
|
||||||
|
project.config.json
|
49
.prettierrc.yml
Normal file
49
.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
|
34
.vscode/settings.json
vendored
Normal file
34
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
|
"eslint.enable": true,
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.tslint": true,
|
||||||
|
"source.fixAll.eslint": true
|
||||||
|
},
|
||||||
|
"[javascript]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||||
|
},
|
||||||
|
"[json]": {
|
||||||
|
"editor.defaultFormatter": "vscode.json-language-features"
|
||||||
|
},
|
||||||
|
"[wxss]": {
|
||||||
|
"editor.defaultFormatter": "HookyQR.beautify"
|
||||||
|
},
|
||||||
|
"wxmlConfig.onSaveFormat": true,
|
||||||
|
"wxmlConfig.format": {
|
||||||
|
"brace_style": "collapse",
|
||||||
|
"indent_inner_html": true,
|
||||||
|
"indent_scripts": "keep",
|
||||||
|
"indent_size": 2,
|
||||||
|
"indent_char": " ",
|
||||||
|
"unformatted": "['wxs']",
|
||||||
|
"disable_automatic_closing_labels": false,
|
||||||
|
"preserve_newlines": true,
|
||||||
|
"wrap_attributes": "force-expand-multiline",
|
||||||
|
"wrap_attributes_count": 4,
|
||||||
|
"wrap_attributes_indent_size": 2
|
||||||
|
},
|
||||||
|
"editor.tabSize": 2
|
||||||
|
}
|
9
LICENSE
Normal file
9
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
README.md
Normal file
138
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)。
|
BIN
__MACOSX/components/._.DS_Store
Normal file
BIN
__MACOSX/components/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/model/._.DS_Store
Normal file
BIN
__MACOSX/model/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/pages/._.DS_Store
Normal file
BIN
__MACOSX/pages/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/pages/coupon/._.DS_Store
Normal file
BIN
__MACOSX/pages/coupon/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/pages/goods/._.DS_Store
Normal file
BIN
__MACOSX/pages/goods/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/pages/order/._.DS_Store
Normal file
BIN
__MACOSX/pages/order/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/pages/usercenter/._.DS_Store
Normal file
BIN
__MACOSX/pages/usercenter/._.DS_Store
Normal file
Binary file not shown.
BIN
__MACOSX/services/._.DS_Store
Normal file
BIN
__MACOSX/services/._.DS_Store
Normal file
Binary file not shown.
8
app.js
Normal file
8
app.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import updateManager from './common/updateManager';
|
||||||
|
|
||||||
|
App({
|
||||||
|
onLaunch: function () {},
|
||||||
|
onShow: function () {
|
||||||
|
updateManager();
|
||||||
|
},
|
||||||
|
});
|
73
app.json
Normal file
73
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
app.wxss
Normal file
3
app.wxss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@import 'style/iconfont.wxss';
|
||||||
|
|
||||||
|
@import 'style/theme.wxss';
|
1
commitlint.config.js
Normal file
1
commitlint.config.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
module.exports = { extends: ['@commitlint/config-conventional'] };
|
29
common/updateManager.js
Normal file
29
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
components/filter-popup/index.js
Normal file
36
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
components/filter-popup/index.json
Normal file
6
components/filter-popup/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"t-popup": "tdesign-miniprogram/popup/popup"
|
||||||
|
}
|
||||||
|
}
|
18
components/filter-popup/index.wxml
Normal file
18
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
components/filter-popup/index.wxss
Normal file
39
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
components/filter/index.js
Normal file
84
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
components/filter/index.json
Normal file
6
components/filter/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||||
|
}
|
||||||
|
}
|
37
components/filter/index.wxml
Normal file
37
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
components/filter/index.wxss
Normal file
50
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
components/goods-card/index.js
Normal file
141
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
components/goods-card/index.json
Normal file
8
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
components/goods-card/index.wxml
Normal file
63
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
components/goods-card/index.wxss
Normal file
133
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
components/goods-list/index.js
Normal file
62
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
components/goods-list/index.json
Normal file
6
components/goods-list/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"goods-card": "/components/goods-card/index"
|
||||||
|
}
|
||||||
|
}
|
16
components/goods-list/index.wxml
Normal file
16
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
components/goods-list/index.wxss
Normal file
7
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
components/load-more/index.js
Normal file
54
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
components/load-more/index.json
Normal file
7
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
components/load-more/index.wxml
Normal file
31
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
components/load-more/index.wxss
Normal file
35
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
components/loading-content/index.js
Normal file
23
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
components/loading-content/index.json
Normal file
6
components/loading-content/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"t-loading": "tdesign-miniprogram/loading/loading"
|
||||||
|
}
|
||||||
|
}
|
11
components/loading-content/index.wxml
Normal file
11
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
components/loading-content/index.wxss
Normal file
23
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
components/price/index.js
Normal file
71
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
components/price/index.json
Normal file
4
components/price/index.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
21
components/price/index.wxml
Normal file
21
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
components/price/index.wxss
Normal file
66
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
components/swipeout/index.js
Normal file
79
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
components/swipeout/index.json
Normal file
4
components/swipeout/index.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {}
|
||||||
|
}
|
174
components/swipeout/index.wxml
Normal file
174
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
components/swipeout/index.wxss
Normal file
18
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
components/webp-image/index.js
Normal file
86
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
components/webp-image/index.json
Normal file
6
components/webp-image/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"t-image": "tdesign-miniprogram/image/image"
|
||||||
|
}
|
||||||
|
}
|
14
components/webp-image/index.wxml
Normal file
14
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
components/webp-image/index.wxss
Normal file
0
components/webp-image/index.wxss
Normal file
140
components/webp-image/utils.wxs
Normal file
140
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
config/eslintCheck.js
Normal file
91
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
config/index.js
Normal file
20437
config/index.js
Normal file
File diff suppressed because it is too large
Load Diff
22
custom-tab-bar/data.js
Normal file
22
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
custom-tab-bar/index.js
Normal file
29
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
custom-tab-bar/index.json
Normal file
8
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
custom-tab-bar/index.wxml
Normal file
18
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
custom-tab-bar/index.wxss
Normal file
9
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
jsconfig.json
Normal file
5
jsconfig.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "."
|
||||||
|
}
|
||||||
|
}
|
34
mock.md
Normal file
34
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
model/activities.js
Normal file
7
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
model/activity.js
Normal file
18
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
model/address.js
Normal file
31
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
model/cart.js
Normal file
324
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
model/category.js
Normal file
206
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
model/comments.js
Normal file
338
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
model/comments/queryDetail.js
Normal file
50
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
model/coupon.js
Normal file
39
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
model/detailsComments.js
Normal file
30
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
model/good.js
Normal file
1916
model/good.js
Normal file
File diff suppressed because it is too large
Load Diff
7
model/goods.js
Normal file
7
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
model/order/applyService.js
Normal file
295
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
model/order/orderConfirm.js
Normal file
147
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
model/order/orderDetail.js
Normal file
1212
model/order/orderDetail.js
Normal file
File diff suppressed because it is too large
Load Diff
1054
model/order/orderList.js
Normal file
1054
model/order/orderList.js
Normal file
File diff suppressed because it is too large
Load Diff
21
model/promotion.js
Normal file
21
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
model/search.js
Normal file
60
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
model/submitComment.js
Normal file
58
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
model/swiper.js
Normal file
39
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
model/usercenter.js
Normal file
52
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
package.json
Normal file
45
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
pages/cart/components/cart-bar/index.js
Normal file
59
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
pages/cart/components/cart-bar/index.json
Normal file
7
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
pages/cart/components/cart-bar/index.wxml
Normal file
31
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
pages/cart/components/cart-bar/index.wxss
Normal file
80
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
pages/cart/components/cart-empty/index.js
Normal file
23
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
pages/cart/components/cart-empty/index.json
Normal file
6
pages/cart/components/cart-empty/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"t-image": "/components/webp-image/index"
|
||||||
|
}
|
||||||
|
}
|
6
pages/cart/components/cart-empty/index.wxml
Normal file
6
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
pages/cart/components/cart-empty/index.wxss
Normal file
33
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
pages/cart/components/cart-group/index.js
Normal file
166
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' });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user