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