generated from weChat/xcx_temp
Initial commit
This commit is contained in:
commit
1afbd62391
160
.eslintrc.js
Normal file
160
.eslintrc.js
Normal file
@ -0,0 +1,160 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
commonjs: true,
|
||||
es6: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020,
|
||||
// ECMAScript modules 模式
|
||||
sourceType: 'module',
|
||||
},
|
||||
extends: ['plugin:prettier/recommended', 'prettier'],
|
||||
globals: {
|
||||
wx: true,
|
||||
App: true,
|
||||
Page: true,
|
||||
Component: true,
|
||||
getApp: true,
|
||||
getCurrentPages: true,
|
||||
Behavior: true,
|
||||
global: true,
|
||||
__wxConfig: true,
|
||||
},
|
||||
ignorePatterns: ['*.wxs'],
|
||||
rules: {
|
||||
'prettier/prettier': 'warn',
|
||||
'no-undef': 'off',
|
||||
camelcase: ['error', { ignoreDestructuring: true }],
|
||||
'class-name-casing': 'off',
|
||||
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
||||
'no-debugger': 'error',
|
||||
'no-unused-expressions': [
|
||||
'error',
|
||||
{ allowShortCircuit: true, allowTernary: true },
|
||||
],
|
||||
'no-empty-interface': 'off',
|
||||
'no-use-before-define': ['error', { functions: false }],
|
||||
'no-useless-constructor': 'error',
|
||||
'prefer-const': 'error',
|
||||
'prefer-destructuring': [
|
||||
'error',
|
||||
{
|
||||
AssignmentExpression: {
|
||||
array: false,
|
||||
object: false,
|
||||
},
|
||||
VariableDeclarator: {
|
||||
array: false,
|
||||
object: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
enforceForRenamedProperties: false,
|
||||
},
|
||||
],
|
||||
'no-const-assign': 'error',
|
||||
'no-new-object': 'error',
|
||||
'no-prototype-builtins': 'error',
|
||||
'no-array-constructor': 'error',
|
||||
'array-callback-return': 'warn',
|
||||
'prefer-template': 'error',
|
||||
'no-useless-escape': 'error',
|
||||
'wrap-iife': ['error', 'outside'],
|
||||
'space-before-function-paren': [
|
||||
'warn',
|
||||
{
|
||||
anonymous: 'always',
|
||||
named: 'never',
|
||||
asyncArrow: 'always',
|
||||
},
|
||||
],
|
||||
'no-param-reassign': [
|
||||
'warn',
|
||||
{
|
||||
props: true,
|
||||
ignorePropertyModificationsFor: [
|
||||
'acc', // for reduce accumulators
|
||||
'accumulator', // for reduce accumulators
|
||||
'e', // for e.returnvalue
|
||||
'ctx', // for Koa routing
|
||||
'req', // for Express requests
|
||||
'request', // for Express requests
|
||||
'res', // for Express responses
|
||||
'response', // for Express responses
|
||||
'$scope', // for Angular 1 scopes
|
||||
'staticContext', // for ReactRouter context
|
||||
'state', // for Vuex
|
||||
],
|
||||
},
|
||||
],
|
||||
'no-confusing-arrow': 'warn',
|
||||
'no-dupe-class-members': 'error',
|
||||
'no-iterator': 'warn',
|
||||
'dot-notation': 'warn',
|
||||
'one-var': ['warn', 'never'],
|
||||
'no-multi-assign': 'error',
|
||||
'no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
args: 'after-used',
|
||||
ignoreRestSiblings: true,
|
||||
argsIgnorePattern: '^_.+',
|
||||
varsIgnorePattern: '^_.+',
|
||||
},
|
||||
],
|
||||
eqeqeq: ['warn', 'always'],
|
||||
'no-case-declarations': 'error',
|
||||
'no-nested-ternary': 'warn',
|
||||
'no-unneeded-ternary': 'warn',
|
||||
'no-mixed-operators': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
['%', '**'],
|
||||
['%', '+'],
|
||||
['%', '-'],
|
||||
['%', '*'],
|
||||
['%', '/'],
|
||||
['&', '|', '<<', '>>', '>>>'],
|
||||
['==', '!=', '===', '!=='],
|
||||
['&&', '||'],
|
||||
],
|
||||
allowSamePrecedence: false,
|
||||
},
|
||||
],
|
||||
'no-else-return': [
|
||||
'warn',
|
||||
{
|
||||
allowElseIf: false,
|
||||
},
|
||||
],
|
||||
'no-new-wrappers': 'warn',
|
||||
indent: [
|
||||
'warn',
|
||||
2,
|
||||
{
|
||||
SwitchCase: 1,
|
||||
VariableDeclarator: 1,
|
||||
outerIIFEBody: 1,
|
||||
FunctionDeclaration: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
FunctionExpression: {
|
||||
parameters: 1,
|
||||
body: 1,
|
||||
},
|
||||
CallExpression: {
|
||||
arguments: 1,
|
||||
},
|
||||
ArrayExpression: 1,
|
||||
ObjectExpression: 1,
|
||||
ImportDeclaration: 1,
|
||||
flatTernaryExpressions: false,
|
||||
ignoreComments: false,
|
||||
},
|
||||
],
|
||||
'linebreak-style': ['warn', 'unix'],
|
||||
},
|
||||
};
|
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
node_modules/
|
||||
yarn-error.log
|
||||
miniprogram/
|
||||
miniprogram_npm/
|
||||
miniprogram_dist/
|
||||
.DS_Store
|
||||
$node_modules/
|
||||
.history/
|
||||
**/dist
|
||||
components/**/*.lock
|
||||
components/**/package-lock.json
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
project.private.config.json
|
||||
.eslintcache
|
9
.npmrc
Normal file
9
.npmrc
Normal file
@ -0,0 +1,9 @@
|
||||
# 去除注释可以使用代理进行安装
|
||||
# proxy=http://127.0.0.1:1080
|
||||
# https_proxy=http://127.0.0.1:1080
|
||||
|
||||
# 去除注释可以使用淘宝源
|
||||
# registry=https://registry.npm.taobao.org
|
||||
|
||||
# 去除注释可以使用腾讯源
|
||||
#registry=http://mirrors.tencent.com/npm/
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@ -0,0 +1,3 @@
|
||||
miniprogram_npm
|
||||
package.json
|
||||
project.config.json
|
49
.prettierrc.yml
Normal file
49
.prettierrc.yml
Normal file
@ -0,0 +1,49 @@
|
||||
# 一行最多 100 字符
|
||||
printWidth: 120
|
||||
# 使用 2 个空格缩进
|
||||
tabWidth: 2
|
||||
# 不使用缩进符,而使用空格
|
||||
useTabs: false
|
||||
# 行尾需要分号
|
||||
semi: true
|
||||
# 使用单引号
|
||||
singleQuote: true
|
||||
# 对象的 key 仅在必要时用引号
|
||||
quoteProps: as-needed
|
||||
# jsx 不使用单引号,而使用双引号
|
||||
jsxSingleQuote: false
|
||||
# 末尾需要逗号
|
||||
trailingComma: all
|
||||
# 大括号内的首尾需要空格
|
||||
bracketSpacing: true
|
||||
# jsx 标签的反尖括号需要换行
|
||||
jsxBracketSameLine: false
|
||||
# 箭头函数,只有一个参数的时候,不需要括号
|
||||
arrowParens: always
|
||||
# 每个文件格式化的范围是文件的全部内容
|
||||
rangeStart: 0
|
||||
# 不需要写文件开头的 @prettier
|
||||
requirePragma: false
|
||||
# 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false
|
||||
# 使用默认的折行标准
|
||||
proseWrap: preserve
|
||||
# 根据显示样式决定 html 要不要折行
|
||||
htmlWhitespaceSensitivity: css
|
||||
# 换行符使用 lf
|
||||
endOfLine: lf
|
||||
# 后缀文件名特有规则
|
||||
overrides:
|
||||
- files: '*.{wxss,less}'
|
||||
options:
|
||||
parser: less
|
||||
- files: '*.json,.*rc'
|
||||
options:
|
||||
parser: json
|
||||
- files: '*.{wxml,html}'
|
||||
options:
|
||||
parser: html
|
||||
htmlWhitespaceSensitivity: strict
|
||||
- files: '*.wxs'
|
||||
options:
|
||||
parser: babel
|
40
.vscode/settings.json
vendored
Normal file
40
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"eslint.enable": true,
|
||||
"editor.formatOnSave": false,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.tslint": true,
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": false,
|
||||
"editor.defaultFormatter": "HookyQR.beautify"
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
},
|
||||
"[wxss]": {
|
||||
"editor.defaultFormatter": "HookyQR.beautify"
|
||||
},
|
||||
"wxmlConfig.onSaveFormat": true,
|
||||
"wxmlConfig.format": {
|
||||
"brace_style": "collapse",
|
||||
"indent_inner_html": true,
|
||||
"indent_scripts": "keep",
|
||||
"indent_size": 2,
|
||||
"indent_char": " ",
|
||||
"unformatted": "['wxs']",
|
||||
"disable_automatic_closing_labels": false,
|
||||
"preserve_newlines": true,
|
||||
"wrap_attributes": "force-expand-multiline",
|
||||
"wrap_attributes_count": 4,
|
||||
"wrap_attributes_indent_size": 2
|
||||
},
|
||||
"editor.tabSize": 2,
|
||||
"[wxml]": {
|
||||
"editor.defaultFormatter": "wechat.miniprogram.wxml-language-features"
|
||||
},
|
||||
"[css]": {
|
||||
"editor.defaultFormatter": "HookyQR.beautify"
|
||||
}
|
||||
}
|
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021-present TDesign
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
138
README.md
Normal file
138
README.md
Normal file
@ -0,0 +1,138 @@
|
||||
<p align="center">
|
||||
<a href="https://tdesign.tencent.com/" target="_blank">
|
||||
<img alt="TDesign Logo" width="200" src="https://tdesign.gtimg.com/site/TDesign.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://img.shields.io/github/stars/Tencent/tdesign-miniprogram-starter-retail">
|
||||
<img src="https://img.shields.io/github/stars/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/Tencent/tdesign-miniprogram-starter-retail/issues">
|
||||
<img src="https://img.shields.io/github/issues/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://github.com/Tencent/tdesign-miniprogram-starter-retail/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/Tencent/tdesign-miniprogram-starter-retail" alt="License">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/tdesign-miniprogram">
|
||||
<img src="https://img.shields.io/npm/v/tdesign-miniprogram.svg?sanitize=true" alt="Version">
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/package/tdesign-miniprogram">
|
||||
<img src="https://img.shields.io/npm/dw/tdesign-miniprogram" alt="Downloads">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
# TDesign 零售行业模版示例小程序
|
||||
|
||||
TDesign 零售模版示例小程序采用 [TDesign 企业级设计体系小程序解决方案](https://tdesign.tencent.com/miniprogram/overview) 进行搭建,依赖 [TDesign 微信小程序组件库](https://github.com/Tencent/tdesign-miniprogram),涵盖完整的基本零售场景需求。
|
||||
|
||||
## :high_brightness: 预览
|
||||
|
||||
<p>请使用微信扫描以下二维码:</p>
|
||||
|
||||
<img src="https://we-retail-static-1300977798.cos.ap-guangzhou.myqcloud.com/retail-mp/common/qrcode.jpeg" width = "200" height = "200" alt="模版小程序二维码" align=center />
|
||||
|
||||
## :pushpin: 项目介绍
|
||||
|
||||
### 1. 业务介绍
|
||||
|
||||
零售行业模版小程序是个经典的单店版电商小程序,涵盖了电商的黄金链路流程,从商品->购物车->结算->订单等。小程序总共包含 28 个完整的页面,涵盖首页,商品详情页,个人中心,售后流程等基础页面。采用 mock 数据进行展示,提供了完整的零售商品展示、交易与售后流程。页面详情:
|
||||
|
||||
<img src="https://cdn-we-retail.ym.tencent.com/tsr/tdesign-starter-readmeV1.png" width = "650" height = "900" alt="模版小程序页面详情" align=center />
|
||||
|
||||
|
||||
|
||||
主要页面截图如下:
|
||||
|
||||
<p align="center">
|
||||
<img alt="example-home" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/home.png" />
|
||||
<img alt="example-sort" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v2/sort.png" />
|
||||
<img alt="example-cart" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/cart.png" />
|
||||
<img alt="example-user-center" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/user-center.png" />
|
||||
<img alt="example-goods-detail" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/goods-detail.png" />
|
||||
<img alt="example-pay" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/pay.png" />
|
||||
<img alt="example-order" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v1/order.png" />
|
||||
<img alt="example-order-detail" width="200" src="https://cdn-we-retail.ym.tencent.com/tsr/example/v2/order.png" />
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
### 2. 项目构成
|
||||
|
||||
零售行业模版小程序采用基础的 JavaScript + WXSS + ESLint 进行构建,降低了使用门槛。
|
||||
|
||||
项目目录结构如下:
|
||||
|
||||
```
|
||||
|-- tdesign-miniprogram-starter
|
||||
|-- README.md
|
||||
|-- app.js
|
||||
|-- app.json
|
||||
|-- app.wxss
|
||||
|-- components // 公共组件库
|
||||
|-- config // 基础配置
|
||||
|-- custom-tab-bar // 自定义 tabbar
|
||||
|-- model // mock 数据
|
||||
|-- pages
|
||||
| |-- cart // 购物车相关页面
|
||||
| |-- coupon // 优惠券相关页面
|
||||
| |-- goods // 商品相关页面
|
||||
| |-- home // 首页
|
||||
| |-- order // 订单售后相关页面
|
||||
| |-- promotion-detail // 营销活动页面
|
||||
| |-- usercenter // 个人中心及收货地址相关页面
|
||||
|-- services // 请求接口
|
||||
|-- style // 公共样式与iconfont
|
||||
|-- utils // 工具库
|
||||
```
|
||||
|
||||
### 3. 数据模拟
|
||||
|
||||
零售小程序采用真实的接口数据,模拟后端返回逻辑,在小程序展示完整的购物场景与购物体验逻辑。
|
||||
|
||||
### 4. 添加新页面
|
||||
|
||||
1. 在 `pages `目录下创建对应的页面文件夹
|
||||
2. 在 `app.json` 文件中的 ` "pages"` 数组中加上页面路径
|
||||
3. [可选] 在 `project.config.json` 文件的 `"miniprogram-list"` 下添加页面配置
|
||||
|
||||
## :hammer: 构建运行
|
||||
|
||||
1. `npm install`
|
||||
2. 小程序开发工具中引入工程
|
||||
3. 构建 npm
|
||||
|
||||
## :art: 代码风格控制
|
||||
|
||||
`eslint` `prettier`
|
||||
|
||||
## :iphone: 基础库版本
|
||||
|
||||
最低基础库版本`^2.6.5`
|
||||
|
||||
## :dart: 反馈&合作
|
||||
|
||||
本开源项目是由[腾讯云Mall团队](https://ym.qq.com/)核心贡献。项目也在[github](https://github.com/Tencent/tdesign-miniprogram-starter-retail)上做了开源,有任何问题或者建议都欢迎在issue上留言反馈, 或者加入TD小程序开发者群进行反馈:star2::star2::star2:
|
||||
|
||||
<img src="https://cdn.qa.ym.qq.com/officical-site/assets/logo.png?auto=format&fit=max&w=384" width = "100" height = "30" alt="模版小程序页面详情" align=center />
|
||||
|
||||
[云Mall](https://ym.qq.com/)是基于微信小程序的电商SaaS产品,致力于提供全面、可靠的小程序商城经营服务,助力商家成功。支持标准化和定开类型商家入驻。
|
||||
|
||||
企业微信群
|
||||
TDesign 团队会及时在企业微信大群中同步发布版本、问题修复信息,也会有一些关于组件库建设的讨论,欢迎微信或企业微信扫码入群交流:
|
||||
|
||||
<img src="https://oteam-tdesign-1258344706.cos.ap-guangzhou.myqcloud.com/site/doc/TDesign%20IM.png" width = "200" height = "200" alt="模版小程序页面详情" align=center />
|
||||
|
||||
|
||||
邮件联系:tdesign@tencent.com
|
||||
|
||||
## :link: TDesign 其他技术栈实现
|
||||
|
||||
- 移动端 小程序 实现:[mobile-miniprogram](https://github.com/Tencent/tdesign-miniprogram)
|
||||
- 桌面端 Vue 2 实现:[web-vue](https://github.com/Tencent/tdesign-vue)
|
||||
- 桌面端 Vue 3 实现:[web-vue-next](https://github.com/Tencent/tdesign-vue-next)
|
||||
- 桌面端 React 实现:[web-react](https://github.com/Tencent/tdesign-react)
|
||||
|
||||
## :page_with_curl: 开源协议
|
||||
|
||||
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-miniprogram-starter-retail/LICENSE)。
|
12
app.js
Normal file
12
app.js
Normal file
@ -0,0 +1,12 @@
|
||||
import updateManager from './common/updateManager';
|
||||
|
||||
// export const ServerBasePath = 'http://localhost:8888/api/';
|
||||
// export const ServerBasePath = 'http://192.168.1.102:8888/api/';
|
||||
export const ServerBasePath = 'http://emo-api.aerwen.net/api/';
|
||||
|
||||
App({
|
||||
onLaunch: function () {},
|
||||
onShow: function () {
|
||||
updateManager();
|
||||
},
|
||||
});
|
51
app.json
Normal file
51
app.json
Normal file
@ -0,0 +1,51 @@
|
||||
{
|
||||
"pages": [
|
||||
"pages/home/home",
|
||||
"pages/home/search/index",
|
||||
"pages/login/login",
|
||||
"pages/login/authorize-avatar-name/index",
|
||||
"pages/login/phone-register/index",
|
||||
"pages/login/agree-link/index",
|
||||
"pages/usercenter/index",
|
||||
"pages/usercenter/goods-collect/index",
|
||||
"pages/usercenter/goods-history/index",
|
||||
"pages/usercenter/person-info/index",
|
||||
"pages/usercenter/set/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/usercenter/index",
|
||||
"text": "我的"
|
||||
}
|
||||
]
|
||||
},
|
||||
"requiredPrivateInfos": ["chooseAddress"],
|
||||
"lazyCodeLoading": "requiredComponents",
|
||||
"usingComponents": {},
|
||||
"window": {
|
||||
"backgroundTextStyle": "light",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"navigationBarTitleText": "Weixin",
|
||||
"navigationBarTextStyle": "black"
|
||||
},
|
||||
"sitemapLocation": "sitemap.json",
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "你的位置信息将用于小程序位置接口的效果展示"
|
||||
}
|
||||
},
|
||||
"resolveAlias": {
|
||||
"~/*": "/*"
|
||||
}
|
||||
}
|
2
app.wxss
Normal file
2
app.wxss
Normal file
@ -0,0 +1,2 @@
|
||||
@import 'style/iconfont.wxss';
|
||||
@import 'style/theme.wxss';
|
1
commitlint.config.js
Normal file
1
commitlint.config.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
29
common/updateManager.js
Normal file
29
common/updateManager.js
Normal file
@ -0,0 +1,29 @@
|
||||
export default () => {
|
||||
if (!wx.canIUse('getUpdateManager')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateManager = wx.getUpdateManager();
|
||||
|
||||
updateManager.onCheckForUpdate(function (res) {
|
||||
// 请求完新版本信息的回调
|
||||
console.log('版本信息', res);
|
||||
});
|
||||
|
||||
updateManager.onUpdateReady(function () {
|
||||
wx.showModal({
|
||||
title: '更新提示',
|
||||
content: '新版本已经准备好,是否重启应用?',
|
||||
success(res) {
|
||||
if (res.confirm) {
|
||||
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
|
||||
updateManager.applyUpdate();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
updateManager.onUpdateFailed(function () {
|
||||
// 新版本下载失败
|
||||
});
|
||||
};
|
54
components/load-more/index.js
Normal file
54
components/load-more/index.js
Normal file
@ -0,0 +1,54 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class', 'wr-class--no-more'],
|
||||
|
||||
options: { multipleSlots: true },
|
||||
|
||||
properties: {
|
||||
status: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
value: '加载中...',
|
||||
},
|
||||
noMoreText: {
|
||||
type: String,
|
||||
value: '没有更多了',
|
||||
},
|
||||
failedText: {
|
||||
type: String,
|
||||
value: '加载失败,点击重试',
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: '#BBBBBB',
|
||||
},
|
||||
failedColor: {
|
||||
type: String,
|
||||
value: '#FA550F',
|
||||
},
|
||||
size: {
|
||||
type: null,
|
||||
value: '40rpx',
|
||||
},
|
||||
loadingBackgroundColor: {
|
||||
type: String,
|
||||
value: '#F5F5F5',
|
||||
},
|
||||
listIsEmpty: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 点击处理 */
|
||||
tapHandle() {
|
||||
// 失败重试
|
||||
if (this.data.status === 3) {
|
||||
this.triggerEvent('retry');
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
7
components/load-more/index.json
Normal file
7
components/load-more/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||
"t-divider": "tdesign-miniprogram/divider/divider"
|
||||
}
|
||||
}
|
31
components/load-more/index.wxml
Normal file
31
components/load-more/index.wxml
Normal file
@ -0,0 +1,31 @@
|
||||
<view
|
||||
class="load-more wr-class"
|
||||
style="{{listIsEmpty && (status === 0 || status === 2) ? 'display: none' : '' }}"
|
||||
bindtap="tapHandle"
|
||||
>
|
||||
<!-- 加载中 -->
|
||||
|
||||
<t-loading
|
||||
t-class="t-class-loading"
|
||||
t-class-text="t-class-loading-text"
|
||||
t-class-indicator="t-class-indicator"
|
||||
loading="{{status === 1}}"
|
||||
text="加载中..."
|
||||
theme="circular"
|
||||
size="40rpx"
|
||||
/>
|
||||
|
||||
<!-- 已全部加载 -->
|
||||
<t-divider wx:if="{{status === 2}}" t-class="t-class-divider" t-class-content="t-class-divider-content">
|
||||
<text slot="content">{{noMoreText}}</text>
|
||||
</t-divider>
|
||||
|
||||
<!-- 加载失败 -->
|
||||
<view class="load-more__error" wx:if="{{status===3}}">
|
||||
加载失败
|
||||
<text class="load-more__refresh-btn" bind:tap="tapHandle">刷新</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 支持通过slot传入页面/列表的空态,load-more来控制空态的显示状态 -->
|
||||
<slot wx:if="{{listIsEmpty && (status === 0 || status === 2)}}" name="empty" />
|
35
components/load-more/index.wxss
Normal file
35
components/load-more/index.wxss
Normal file
@ -0,0 +1,35 @@
|
||||
.load-more {
|
||||
font-size: 24rpx;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.load-more .t-class-loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
--td-loading-color: #fa4126;
|
||||
}
|
||||
|
||||
.load-more .t-class-loading-text {
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.t-class-divider-content {
|
||||
margin: 0 10rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
.load-more .t-class-indicator {
|
||||
color: #b9b9b9 !important;
|
||||
}
|
||||
|
||||
.load-more__error {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.load-more__refresh-btn {
|
||||
margin-left: 16rpx;
|
||||
color: #fa4126;
|
||||
}
|
23
components/loading-content/index.js
Normal file
23
components/loading-content/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
properties: {
|
||||
position: {
|
||||
type: String,
|
||||
value: 'static',
|
||||
},
|
||||
noMask: Boolean,
|
||||
type: {
|
||||
type: String,
|
||||
value: 'circular',
|
||||
},
|
||||
vertical: Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
value: '50rpx',
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
value: 'rgba(0, 0, 0, .6)',
|
||||
},
|
||||
},
|
||||
});
|
6
components/loading-content/index.json
Normal file
6
components/loading-content/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-loading": "tdesign-miniprogram/loading/loading"
|
||||
}
|
||||
}
|
11
components/loading-content/index.wxml
Normal file
11
components/loading-content/index.wxml
Normal file
@ -0,0 +1,11 @@
|
||||
<view class="t-class loading-content {{position}}" style="{{(position === 'static' || noMask) ? 'visibility: hidden;' : ''}} background-color: {{backgroundColor}}">
|
||||
<t-loading
|
||||
t-class="loading"
|
||||
theme="{{type}}"
|
||||
layout="{{vertical}}"
|
||||
size="{{size}}"
|
||||
>
|
||||
<slot/>
|
||||
</t-loading>
|
||||
</view>
|
||||
|
23
components/loading-content/index.wxss
Normal file
23
components/loading-content/index.wxss
Normal file
@ -0,0 +1,23 @@
|
||||
.loading-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
position: relative;
|
||||
}
|
||||
.loading-content.absolute {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.loading-content.fixed {
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.loading-content .loading {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
visibility: visible;
|
||||
}
|
71
components/price/index.js
Normal file
71
components/price/index.js
Normal file
@ -0,0 +1,71 @@
|
||||
Component({
|
||||
externalClasses: ['wr-class', 'symbol-class', 'decimal-class'],
|
||||
useStore: [],
|
||||
properties: {
|
||||
priceUnit: {
|
||||
type: String,
|
||||
value: 'fen',
|
||||
}, // 价格单位,分 | 元, fen,yuan
|
||||
price: {
|
||||
type: null,
|
||||
value: '',
|
||||
observer(price) {
|
||||
this.format(price);
|
||||
},
|
||||
}, // 价格, 以分为单位
|
||||
type: {
|
||||
type: String,
|
||||
value: '', //
|
||||
}, // main 粗体, lighter 细体, mini 黑色, del 中划线, delthrough 中划线,包括货币符号
|
||||
symbol: {
|
||||
type: String,
|
||||
value: '¥', // '¥',
|
||||
}, // 货币符号,默认是人民币符号¥
|
||||
fill: Boolean, // 是否自动补齐两位小数
|
||||
decimalSmaller: Boolean, // 小数字号小一点
|
||||
lineThroughWidth: {
|
||||
type: null,
|
||||
value: '0.12em',
|
||||
}, // 划线价线条高度
|
||||
},
|
||||
|
||||
data: {
|
||||
pArr: [],
|
||||
},
|
||||
|
||||
methods: {
|
||||
format(price) {
|
||||
price = parseFloat(`${price}`);
|
||||
const pArr = [];
|
||||
if (!isNaN(price)) {
|
||||
const isMinus = price < 0;
|
||||
if (isMinus) {
|
||||
price = -price;
|
||||
}
|
||||
if (this.properties.priceUnit === 'yuan') {
|
||||
const priceSplit = price.toString().split('.');
|
||||
pArr[0] = priceSplit[0];
|
||||
pArr[1] = !priceSplit[1]
|
||||
? '00'
|
||||
: priceSplit[1].length === 1
|
||||
? `${priceSplit[1]}0`
|
||||
: priceSplit[1];
|
||||
} else {
|
||||
price = Math.round(price * 10 ** 8) / 10 ** 8; // 恢复精度丢失
|
||||
price = Math.ceil(price); // 向上取整
|
||||
pArr[0] = price >= 100 ? `${price}`.slice(0, -2) : '0';
|
||||
pArr[1] = `${price + 100}`.slice(-2);
|
||||
}
|
||||
if (!this.properties.fill) {
|
||||
// 如果 fill 为 false, 不显示小数末尾的0
|
||||
if (pArr[1] === '00') pArr[1] = '';
|
||||
else if (pArr[1][1] === '0') pArr[1] = pArr[1][0];
|
||||
}
|
||||
if (isMinus) {
|
||||
pArr[0] = `-${pArr[0]}`;
|
||||
}
|
||||
}
|
||||
this.setData({ pArr });
|
||||
},
|
||||
},
|
||||
});
|
4
components/price/index.json
Normal file
4
components/price/index.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
21
components/price/index.wxml
Normal file
21
components/price/index.wxml
Normal file
@ -0,0 +1,21 @@
|
||||
<wxs module="utils">
|
||||
var REGEXP = getRegExp('^\d+(\.\d+)?$');
|
||||
function addUnit(value) {
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
return REGEXP.test('' + value) ? value + 'rpx' : value;
|
||||
}
|
||||
module.exports = {
|
||||
addUnit: addUnit
|
||||
};
|
||||
</wxs>
|
||||
<view class="price {{type}} wr-class">
|
||||
<view wx:if="{{type === 'delthrough'}}" class="line" style="height:{{utils.addUnit(lineThroughWidth)}};" />
|
||||
<view class="symbol symbol-class">{{symbol}}</view>
|
||||
<view class="pprice">
|
||||
<view class="integer inline">{{pArr[0]}}</view>
|
||||
<view wx:if="{{pArr[1]}}" class="decimal inline {{decimalSmaller ? 'smaller' : ''}} decimal-class">.{{pArr[1]}}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
66
components/price/index.wxss
Normal file
66
components/price/index.wxss
Normal file
@ -0,0 +1,66 @@
|
||||
:host {
|
||||
display: inline-block;
|
||||
display: inline-block;
|
||||
font-weight: inherit;
|
||||
}
|
||||
.inline {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.price {
|
||||
display: inline;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.lighter {
|
||||
font-weight: 400;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.mini {
|
||||
font-size: 24rpx;
|
||||
color: #5d5d5d;
|
||||
font-weight: 400;
|
||||
}
|
||||
.del .pprice {
|
||||
font-size: 32rpx;
|
||||
color: #9b9b9b;
|
||||
text-decoration: line-through;
|
||||
font-weight: 400;
|
||||
}
|
||||
.delthrough {
|
||||
position: relative;
|
||||
}
|
||||
.delthrough .line {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
transform: translateY(-50%);
|
||||
margin: 0;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
.symbol {
|
||||
display: inline;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.pprice {
|
||||
display: inline;
|
||||
margin: 0 0 0 4rpx;
|
||||
}
|
||||
.integer {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.decimal {
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.decimal.smaller {
|
||||
font-size: 0.8em;
|
||||
vertical-align: baseline;
|
||||
}
|
79
components/swipeout/index.js
Normal file
79
components/swipeout/index.js
Normal file
@ -0,0 +1,79 @@
|
||||
let ARRAY = [];
|
||||
Component({
|
||||
externalClasses: ['wr-class'],
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
properties: {
|
||||
disabled: Boolean,
|
||||
leftWidth: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
rightWidth: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
asyncClose: Boolean,
|
||||
},
|
||||
attached() {
|
||||
ARRAY.push(this);
|
||||
},
|
||||
|
||||
detached() {
|
||||
ARRAY = ARRAY.filter((item) => item !== this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Component initial data
|
||||
*/
|
||||
data: {
|
||||
wrapperStyle: '',
|
||||
asyncClose: false,
|
||||
closed: true,
|
||||
},
|
||||
|
||||
/**
|
||||
* Component methods
|
||||
*/
|
||||
methods: {
|
||||
open(position) {
|
||||
this.setData({ closed: false });
|
||||
this.triggerEvent('close', {
|
||||
position,
|
||||
instance: this,
|
||||
});
|
||||
},
|
||||
|
||||
close() {
|
||||
this.setData({ closed: true });
|
||||
},
|
||||
|
||||
closeOther() {
|
||||
ARRAY.filter((item) => item !== this).forEach((item) => item.close());
|
||||
},
|
||||
|
||||
noop() {
|
||||
return;
|
||||
},
|
||||
|
||||
onClick(event) {
|
||||
const { key: position = 'outside' } = event.currentTarget.dataset;
|
||||
this.triggerEvent('click', position);
|
||||
|
||||
if (this.data.closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.data.asyncClose) {
|
||||
this.triggerEvent('close', {
|
||||
position,
|
||||
instance: this,
|
||||
});
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
4
components/swipeout/index.json
Normal file
4
components/swipeout/index.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
174
components/swipeout/index.wxml
Normal file
174
components/swipeout/index.wxml
Normal file
@ -0,0 +1,174 @@
|
||||
<wxs module="swipe">
|
||||
var THRESHOLD = 0.3;
|
||||
var MIN_DISTANCE = 10;
|
||||
var owner;
|
||||
var state;
|
||||
|
||||
var getState = function(ownerInstance) {
|
||||
owner = ownerInstance;
|
||||
state = owner.getState();
|
||||
state.leftWidth = state.leftWidth || 0;
|
||||
state.rightWidth = state.rightWidth || 0;
|
||||
state.offset = state.offset || 0;
|
||||
state.startOffset = state.startOffset || 0;
|
||||
};
|
||||
|
||||
var initRightWidth = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.rightWidth = newVal;
|
||||
if (state.offset < 0) {
|
||||
swipeMove(-state.rightWidth);
|
||||
}
|
||||
};
|
||||
|
||||
var initLeftWidth = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.leftWidth = newVal;
|
||||
if (state.offset > 0) {
|
||||
swipeMove(state.leftWidth);
|
||||
}
|
||||
}
|
||||
|
||||
var resetTouchStatus = function() {
|
||||
state.direction = '';
|
||||
state.deltaX = 0;
|
||||
state.deltaY = 0;
|
||||
state.offsetX = 0;
|
||||
state.offsetY = 0;
|
||||
};
|
||||
|
||||
var touchMove = function(event) {
|
||||
var touchPoint = event.touches[0];
|
||||
state.deltaX = touchPoint.clientX - state.startX;
|
||||
state.deltaY = touchPoint.clientY - state.startY;
|
||||
state.offsetX = Math.abs(state.deltaX);
|
||||
state.offsetY = Math.abs(state.deltaY);
|
||||
state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
|
||||
};
|
||||
|
||||
var getDirection = function(x, y) {
|
||||
if (x > y && x > MIN_DISTANCE) {
|
||||
return 'horizontal';
|
||||
}
|
||||
if (y > x && y > MIN_DISTANCE) {
|
||||
return 'vertical';
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
var range = function(num, min, max) {
|
||||
return Math.min(Math.max(num, min), max);
|
||||
};
|
||||
|
||||
var swipeMove = function(_offset = 0) {
|
||||
state.offset = range(
|
||||
_offset,
|
||||
-state.rightWidth,
|
||||
+state.leftWidth,
|
||||
);
|
||||
|
||||
var transform = 'translate3d(' + state.offset + 'px, 0, 0)';
|
||||
var transition = state.dragging
|
||||
? 'none'
|
||||
: 'transform .6s cubic-bezier(0.18, 0.89, 0.32, 1)';
|
||||
owner.selectComponent('#wrapper').setStyle({
|
||||
'-webkit-transform': transform,
|
||||
'-webkit-transition': transition,
|
||||
'transform': transform,
|
||||
'transition': transition
|
||||
});
|
||||
};
|
||||
|
||||
var close = function() {
|
||||
swipeMove(0);
|
||||
};
|
||||
|
||||
var onCloseChange = function(newVal, oldVal, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
if (newVal === oldVal) return;
|
||||
if (newVal) {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
var touchStart = function(event) {
|
||||
resetTouchStatus();
|
||||
state.startOffset = state.offset;
|
||||
var touchPoint = event.touches[0];
|
||||
state.startX = touchPoint.clientX;
|
||||
state.startY = touchPoint.clientY;
|
||||
owner.callMethod('closeOther');
|
||||
};
|
||||
|
||||
var startDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
touchStart(event);
|
||||
};
|
||||
|
||||
var onDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
touchMove(event);
|
||||
if (state.direction !== 'horizontal') {
|
||||
return;
|
||||
}
|
||||
state.dragging = true;
|
||||
swipeMove(state.startOffset + state.deltaX);
|
||||
};
|
||||
|
||||
var open = function(position) {
|
||||
var _offset = position === 'left' ? +state.leftWidth : -state.rightWidth;
|
||||
owner.callMethod('open', { position: position });
|
||||
swipeMove(_offset);
|
||||
};
|
||||
|
||||
var endDrag = function(event, ownerInstance) {
|
||||
getState(ownerInstance);
|
||||
state.dragging = false;
|
||||
// 左/右侧有可滑动区域,且当前不是已open状态,且滑动幅度超过阈值时open左/右侧(滚动到该侧的最边上)
|
||||
if (+state.rightWidth > 0 && -state.startOffset < +state.rightWidth && -state.offset > +state.rightWidth * THRESHOLD) {
|
||||
open('right');
|
||||
} else if (+state.leftWidth > 0 && state.startOffset < +state.leftWidth && state.offset > +state.leftWidth * THRESHOLD) {
|
||||
open('left');
|
||||
} else {
|
||||
// 仅在有发生侧滑的情况下自动关闭(由js控制是否异步关闭)
|
||||
if (state.startOffset !== state.offset) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initLeftWidth: initLeftWidth,
|
||||
initRightWidth: initRightWidth,
|
||||
startDrag: startDrag,
|
||||
onDrag: onDrag,
|
||||
endDrag: endDrag,
|
||||
onCloseChange: onCloseChange
|
||||
};
|
||||
</wxs>
|
||||
|
||||
<view
|
||||
class="wr-class wr-swipeout"
|
||||
data-key="cell"
|
||||
capture-bind:tap="onClick"
|
||||
bindtouchstart="{{disabled || swipe.startDrag}}"
|
||||
capture-bind:touchmove="{{disabled || swipe.onDrag}}"
|
||||
bindtouchend="{{disabled || swipe.endDrag}}"
|
||||
bindtouchcancel="{{disabled || swipe.endDrag}}"
|
||||
closed="{{closed}}"
|
||||
change:closed="{{swipe.onCloseChange}}"
|
||||
leftWidth="{{leftWidth}}"
|
||||
rightWidth="{{rightWidth}}"
|
||||
change:leftWidth="{{swipe.initLeftWidth}}"
|
||||
change:rightWidth="{{swipe.initRightWidth}}"
|
||||
>
|
||||
<view id="wrapper">
|
||||
<view wx:if="{{ leftWidth }}" class="wr-swipeout__left" data-key="left" catch:tap="onClick">
|
||||
<slot name="left" />
|
||||
</view>
|
||||
<slot />
|
||||
<view wx:if="{{ rightWidth }}" class="wr-swipeout__right" data-key="right" catch:tap="onClick">
|
||||
<slot name="right" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
18
components/swipeout/index.wxss
Normal file
18
components/swipeout/index.wxss
Normal file
@ -0,0 +1,18 @@
|
||||
.wr-swipeout {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.wr-swipeout__left,
|
||||
.wr-swipeout__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
.wr-swipeout__left {
|
||||
left: 0;
|
||||
transform: translate3d(-100%, 0, 0);
|
||||
}
|
||||
.wr-swipeout__right {
|
||||
right: 0;
|
||||
transform: translate3d(100%, 0, 0);
|
||||
}
|
113
components/upload/index.js
Normal file
113
components/upload/index.js
Normal file
@ -0,0 +1,113 @@
|
||||
// components/upload/index.js
|
||||
import { ServerBasePath } from '~/services/_utils/request'
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
mediaType: {
|
||||
type: Array,
|
||||
value: ['image'],
|
||||
},
|
||||
max: {
|
||||
type: Number,
|
||||
value: 1,
|
||||
},
|
||||
lable: {
|
||||
type: String,
|
||||
value: "",
|
||||
},
|
||||
fileList: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
fileList: []
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
// 子组件中触发自定义事件并传递数据
|
||||
// triggerEventToParent() {
|
||||
// const dataToPass = this.data.fileList; // 获取要传递的值
|
||||
// this.triggerEvent('customEvent', dataToPass); // 触发自定义事件,并传递值
|
||||
// },
|
||||
|
||||
|
||||
|
||||
|
||||
handleAdd(e) {
|
||||
|
||||
const {
|
||||
fileList
|
||||
} = this.data;
|
||||
const {
|
||||
files
|
||||
} = e.detail;
|
||||
|
||||
// 方法1:选择完所有图片之后,统一上传,因此选择完就直接展示
|
||||
// this.setData({
|
||||
// fileList: [...fileList, ...files], // 此时设置了 fileList 之后才会展示选择的图片
|
||||
// });
|
||||
|
||||
// 方法2:每次选择图片都上传,展示每次上传图片的进度
|
||||
files.forEach(file => this.onUpload(file))
|
||||
},
|
||||
onUpload(file) {
|
||||
const {
|
||||
fileList
|
||||
} = this.data;
|
||||
|
||||
this.setData({
|
||||
fileList: [...fileList, {
|
||||
...file,
|
||||
status: 'loading'
|
||||
}],
|
||||
});
|
||||
const {
|
||||
length
|
||||
} = fileList;
|
||||
|
||||
const task = wx.uploadFile({
|
||||
url: ServerBasePath + '/Common/UploadFile', // 仅为示例,非真实的接口地址
|
||||
filePath: file.url,
|
||||
name: 'file',
|
||||
formData: {
|
||||
fileDir: 'Shops'
|
||||
},
|
||||
success: (res) => {
|
||||
this.setData({
|
||||
[`fileList[${length}].url`]: JSON.parse(res.data).data.url,
|
||||
[`fileList[${length}].status`]: 'done',
|
||||
});
|
||||
// this.triggerEventToParent()
|
||||
},
|
||||
});
|
||||
task.onProgressUpdate((res) => {
|
||||
this.setData({
|
||||
[`fileList[${length}].percent`]: res.progress,
|
||||
});
|
||||
});
|
||||
},
|
||||
handleRemove(e) {
|
||||
const {
|
||||
index
|
||||
} = e.detail;
|
||||
const {
|
||||
fileList
|
||||
} = this.data;
|
||||
|
||||
fileList.splice(index, 1);
|
||||
this.setData({
|
||||
fileList,
|
||||
});
|
||||
},
|
||||
}
|
||||
})
|
6
components/upload/index.json
Normal file
6
components/upload/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-upload": "tdesign-miniprogram/upload/upload"
|
||||
}
|
||||
}
|
12
components/upload/index.wxml
Normal file
12
components/upload/index.wxml
Normal file
@ -0,0 +1,12 @@
|
||||
<!-- 上传组件 -->
|
||||
<view class="wrapper">
|
||||
<view class="wrapper-title">{{lable}}</view>
|
||||
<t-upload
|
||||
mediaType="{{mediaType}}"
|
||||
max="{{max}}"
|
||||
files="{{fileList}}"
|
||||
bind:add="handleAdd"
|
||||
bind:remove="handleRemove"
|
||||
>
|
||||
</t-upload>
|
||||
</view>
|
19
components/upload/index.wxss
Normal file
19
components/upload/index.wxss
Normal file
@ -0,0 +1,19 @@
|
||||
/* components/upload/index.wxss */
|
||||
.wrapper{
|
||||
padding: 50rpx 30rpx;
|
||||
border-bottom: 1px solid #f3f3f3;
|
||||
}
|
||||
|
||||
.wrapper-title{
|
||||
font-size: 32rpx;
|
||||
margin-left: 5rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.sub-btn-pos-box{
|
||||
width: 100%;
|
||||
padding: 50rpx 0 100rpx 0;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
background-color: white;
|
||||
}
|
86
components/webp-image/index.js
Normal file
86
components/webp-image/index.js
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* @Author: rileycai
|
||||
* @Date: 2022-03-14 14:21:26
|
||||
* @LastEditTime: 2022-03-14 15:23:04
|
||||
* @LastEditors: rileycai
|
||||
* @Description: webp-image组件对t-image包裹了一层,主要实现图片裁剪、webp压缩功能
|
||||
* @FilePath: /tdesign-miniprogram-starter/components/webp-image/index.js
|
||||
*/
|
||||
const systemInfo = wx.getSystemInfoSync();
|
||||
Component({
|
||||
externalClasses: ['t-class', 't-class-load'],
|
||||
properties: {
|
||||
loadFailed: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
loading: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
},
|
||||
src: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
value: 'aspectFill',
|
||||
},
|
||||
webp: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
lazyLoad: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
showMenuByLongpress: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
thumbHeight: 375,
|
||||
thumbWidth: 375,
|
||||
systemInfo,
|
||||
},
|
||||
lifetimes: {
|
||||
ready() {
|
||||
const { mode } = this.properties;
|
||||
// 获取容器的真实宽高,设置图片的裁剪宽度
|
||||
this.getRect('.J-image').then((res) => {
|
||||
if (res) {
|
||||
const { width, height } = res;
|
||||
this.setData(
|
||||
mode === 'heightFix'
|
||||
? {
|
||||
thumbHeight: this.px2rpx(height) || 375,
|
||||
}
|
||||
: {
|
||||
thumbWidth: this.px2rpx(width) || 375,
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
px2rpx(px) {
|
||||
return (750 / (systemInfo.screenWidth || 375)) * px;
|
||||
},
|
||||
getRect(selector) {
|
||||
return new Promise((resolve) => {
|
||||
if (!this.selectorQuery) {
|
||||
this.selectorQuery = this.createSelectorQuery();
|
||||
}
|
||||
this.selectorQuery.select(selector).boundingClientRect(resolve).exec();
|
||||
});
|
||||
},
|
||||
onLoad(e) {
|
||||
this.triggerEvent('load', e.detail);
|
||||
},
|
||||
onError(e) {
|
||||
this.triggerEvent('error', e.detail);
|
||||
},
|
||||
},
|
||||
});
|
6
components/webp-image/index.json
Normal file
6
components/webp-image/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-image": "tdesign-miniprogram/image/image"
|
||||
}
|
||||
}
|
14
components/webp-image/index.wxml
Normal file
14
components/webp-image/index.wxml
Normal file
@ -0,0 +1,14 @@
|
||||
<wxs src="./utils.wxs" module="Utils" />
|
||||
<t-image
|
||||
t-class="J-image"
|
||||
src="{{Utils.getSrc({src, thumbWidth: thumbWidth || 0, thumbHeight: thumbHeight || 0, systemInfo, webp, mode})}}"
|
||||
t-class="t-class"
|
||||
t-class-load="t-class-load"
|
||||
mode="{{ mode }}"
|
||||
lazy="{{ lazyLoad }}"
|
||||
show-menu-by-longpress="{{showMenuByLongpress}}"
|
||||
error="{{loadFailed}}"
|
||||
loading="{{loading}}"
|
||||
binderror="onError"
|
||||
bindload="onLoad"
|
||||
/>
|
0
components/webp-image/index.wxss
Normal file
0
components/webp-image/index.wxss
Normal file
140
components/webp-image/utils.wxs
Normal file
140
components/webp-image/utils.wxs
Normal file
@ -0,0 +1,140 @@
|
||||
var isString = function (value) {
|
||||
return typeof value === 'string';
|
||||
};
|
||||
|
||||
var isNumber = function (value) {
|
||||
return typeof value === 'number';
|
||||
};
|
||||
|
||||
var getFileExt = function (src) {
|
||||
var fileUrl = src.split('?')[0];
|
||||
var splitUlr = fileUrl.split('/');
|
||||
var filepath = splitUlr[splitUlr.length - 1];
|
||||
return filepath.split('.')[1] || 'jpg';
|
||||
};
|
||||
|
||||
function isUrl(url) {
|
||||
// NOCC:ToolNameCheck(非敏感词)
|
||||
var urlReg = getRegExp(
|
||||
'/[(http(s)?)://(www.)?a-zA-Z0-9@:%._+~#=]{2,256}.[a-z]{2,6}\b([-a-zA-Z0-9@:%_+.~#?&//=]*)/',
|
||||
'ig',
|
||||
);
|
||||
|
||||
return urlReg.test(url);
|
||||
}
|
||||
|
||||
function rpx2px(rpx, screenWidth) {
|
||||
// px / systemWidth = rpx / 750
|
||||
var result = (rpx * (screenWidth || 375)) / 750;
|
||||
|
||||
return Math.round(result);
|
||||
}
|
||||
|
||||
function imageMogr(url, options) {
|
||||
if (!isString(url) || !url) return '';
|
||||
|
||||
if (
|
||||
url.indexOf('qlogo.cn') !== -1 ||
|
||||
url.indexOf('wxfile://') === 0 ||
|
||||
url.indexOf('http://tmp/wx') === 0 ||
|
||||
url.indexOf('imageMogr2') !== -1
|
||||
) {
|
||||
//qlogo.cn域名或者本地图片不做转换
|
||||
return url;
|
||||
} //强制转https
|
||||
|
||||
if (url.indexOf('http://') === 0) {
|
||||
url = url.replace('http://', 'https://');
|
||||
} else if (url.indexOf('//') === 0) {
|
||||
url = 'https:' + url;
|
||||
}
|
||||
|
||||
if (!options) return url;
|
||||
|
||||
var width = Math.ceil(options.width),
|
||||
height = Math.ceil(options.height),
|
||||
format = options.format,
|
||||
_optionsQuality = options.quality,
|
||||
quality = _optionsQuality === undefined ? 70 : _optionsQuality,
|
||||
_optionsStrip = options.strip,
|
||||
strip = _optionsStrip === undefined ? true : _optionsStrip,
|
||||
crop = options.crop;
|
||||
var isValidWidth = isNumber(width) && width > 0;
|
||||
var isValidHeight = isNumber(height) && height > 0;
|
||||
var imageMogrStr = '';
|
||||
var size = '';
|
||||
|
||||
if (isValidWidth && isValidHeight) {
|
||||
size = ''.concat(width, 'x').concat(height);
|
||||
} else if (isValidWidth) {
|
||||
size = ''.concat(width, 'x');
|
||||
} else if (isValidHeight) {
|
||||
size = 'x'.concat(height);
|
||||
}
|
||||
|
||||
if (size) {
|
||||
//缩放或者裁剪
|
||||
imageMogrStr += '/'.concat(crop ? 'crop' : 'thumbnail', '/').concat(size);
|
||||
|
||||
if (crop) {
|
||||
//裁剪目前需求只有以图片中心为基准
|
||||
imageMogrStr += '/gravity/center';
|
||||
}
|
||||
}
|
||||
|
||||
if (isNumber(quality)) {
|
||||
//质量变换
|
||||
imageMogrStr += '/quality/'.concat(quality);
|
||||
}
|
||||
|
||||
if (strip) {
|
||||
//去除元信息
|
||||
imageMogrStr += '/strip';
|
||||
}
|
||||
|
||||
var ext = getFileExt(url);
|
||||
|
||||
// gif 图片不做格式转换,否则会损坏动图
|
||||
if (ext === 'gif') {
|
||||
imageMogrStr += '/cgif/1';
|
||||
} else if (format) {
|
||||
//格式转换
|
||||
imageMogrStr += '/format/'.concat(format);
|
||||
}
|
||||
|
||||
if (format === 'jpg' || (!format && (ext === 'jpg' || ext === 'jpeg'))) {
|
||||
//渐进式 jpg 加载
|
||||
imageMogrStr += '/interlace/1';
|
||||
}
|
||||
if (!imageMogrStr) return url;
|
||||
return ''
|
||||
.concat(url)
|
||||
.concat(url.indexOf('?') !== -1 ? '&' : '?', 'imageMogr2')
|
||||
.concat(imageMogrStr);
|
||||
}
|
||||
function getSrc(options) {
|
||||
if (!options.src) return '';
|
||||
|
||||
if (options.thumbWidth || options.thumbHeight) {
|
||||
return imageMogr(options.src, {
|
||||
width:
|
||||
options.mode !== 'heightFix'
|
||||
? rpx2px(options.thumbWidth, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
: null,
|
||||
height:
|
||||
options.mode !== 'widthFix'
|
||||
? rpx2px(options.thumbHeight, options.systemInfo.screenWidth) *
|
||||
options.systemInfo.pixelRatio
|
||||
: null,
|
||||
format: options.webp ? 'webp' : null,
|
||||
});
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
imageMogr: imageMogr,
|
||||
getSrc: getSrc,
|
||||
};
|
91
config/eslintCheck.js
Normal file
91
config/eslintCheck.js
Normal file
@ -0,0 +1,91 @@
|
||||
/* eslint-disable prefer-template */
|
||||
/**
|
||||
* 工程代码pre-commit 检查工具
|
||||
* @date 2019.9.4
|
||||
* @author 310227663@qq.com
|
||||
*/
|
||||
const { exec } = require('child_process');
|
||||
const chalk = require('chalk');
|
||||
const { CLIEngine } = require('eslint');
|
||||
const cli = new CLIEngine({});
|
||||
const { log } = console;
|
||||
|
||||
function getErrorLevel(number) {
|
||||
switch (number) {
|
||||
case 2:
|
||||
return 'error';
|
||||
case 1:
|
||||
return 'warn';
|
||||
default:
|
||||
}
|
||||
return 'undefined';
|
||||
}
|
||||
let pass = 0;
|
||||
exec(
|
||||
'git diff --cached --name-only --diff-filter=ACM | grep -Ei "\\.ts$|\\.js$"',
|
||||
(error, stdout) => {
|
||||
if (stdout.length) {
|
||||
const array = stdout.split('\n');
|
||||
array.pop();
|
||||
const { results } = cli.executeOnFiles(array);
|
||||
let errorCount = 0;
|
||||
let warningCount = 0;
|
||||
results.forEach((result) => {
|
||||
errorCount += result.errorCount;
|
||||
warningCount += result.warningCount;
|
||||
if (result.messages.length > 0) {
|
||||
log('\n');
|
||||
log(result.filePath);
|
||||
result.messages.forEach((obj) => {
|
||||
const level = getErrorLevel(obj.severity);
|
||||
if (level === 'warn')
|
||||
log(
|
||||
' ' +
|
||||
obj.line +
|
||||
':' +
|
||||
obj.column +
|
||||
'\t ' +
|
||||
chalk.yellow(level) +
|
||||
' \0 ' +
|
||||
obj.message +
|
||||
'\t\t' +
|
||||
chalk.grey(obj.ruleId) +
|
||||
'',
|
||||
);
|
||||
if (level === 'error')
|
||||
log(
|
||||
' ' +
|
||||
obj.line +
|
||||
':' +
|
||||
obj.column +
|
||||
'\t ' +
|
||||
chalk.red.bold(level) +
|
||||
' \0 ' +
|
||||
obj.message +
|
||||
'\t\t ' +
|
||||
chalk.grey(obj.ruleId) +
|
||||
'',
|
||||
);
|
||||
if (level === 'error') pass = 1;
|
||||
});
|
||||
}
|
||||
});
|
||||
if (warningCount > 0 || errorCount > 0) {
|
||||
log(
|
||||
'\n' +
|
||||
chalk.bgRed.bold(errorCount + warningCount + ' problems') +
|
||||
' (' +
|
||||
chalk.red.bold(errorCount) +
|
||||
' errors, ' +
|
||||
chalk.yellow(warningCount) +
|
||||
' warnings) \0',
|
||||
);
|
||||
}
|
||||
!pass && log(chalk.green.bold('~~ Done: 代码检验通过,提交成功 ~~'));
|
||||
process.exit(pass);
|
||||
}
|
||||
if (error !== null) {
|
||||
log(`exec error: ${error}`);
|
||||
}
|
||||
},
|
||||
);
|
20437
config/index.js
Normal file
20437
config/index.js
Normal file
File diff suppressed because it is too large
Load Diff
12
custom-tab-bar/data.js
Normal file
12
custom-tab-bar/data.js
Normal file
@ -0,0 +1,12 @@
|
||||
export default [
|
||||
{
|
||||
icon: 'home',
|
||||
text: '首页',
|
||||
url: 'pages/home/home',
|
||||
},
|
||||
{
|
||||
icon: 'person',
|
||||
text: '个人中心',
|
||||
url: 'pages/usercenter/index',
|
||||
},
|
||||
];
|
29
custom-tab-bar/index.js
Normal file
29
custom-tab-bar/index.js
Normal file
@ -0,0 +1,29 @@
|
||||
import TabMenu from './data';
|
||||
Component({
|
||||
data: {
|
||||
active: 0,
|
||||
list: TabMenu,
|
||||
},
|
||||
|
||||
methods: {
|
||||
onChange(event) {
|
||||
this.setData({ active: event.detail.value });
|
||||
wx.switchTab({
|
||||
url: this.data.list[event.detail.value].url.startsWith('/')
|
||||
? this.data.list[event.detail.value].url
|
||||
: `/${this.data.list[event.detail.value].url}`,
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
const page = getCurrentPages().pop();
|
||||
const route = page ? page.route.split('?')[0] : '';
|
||||
const active = this.data.list.findIndex(
|
||||
(item) =>
|
||||
(item.url.startsWith('/') ? item.url.substr(1) : item.url) ===
|
||||
`${route}`,
|
||||
);
|
||||
this.setData({ active });
|
||||
},
|
||||
},
|
||||
});
|
8
custom-tab-bar/index.json
Normal file
8
custom-tab-bar/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-tab-bar": "tdesign-miniprogram/tab-bar/tab-bar",
|
||||
"t-tab-bar-item": "tdesign-miniprogram/tab-bar-item/tab-bar-item",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
18
custom-tab-bar/index.wxml
Normal file
18
custom-tab-bar/index.wxml
Normal file
@ -0,0 +1,18 @@
|
||||
<t-tab-bar
|
||||
value="{{active}}"
|
||||
bindchange="onChange"
|
||||
split="{{false}}"
|
||||
>
|
||||
<t-tab-bar-item
|
||||
wx:for="{{list}}"
|
||||
wx:for-item="item"
|
||||
wx:for-index="index"
|
||||
wx:key="index"
|
||||
>
|
||||
<view class="custom-tab-bar-wrapper">
|
||||
<t-icon prefix="wr" name="{{item.icon}}" size="48rpx" />
|
||||
<view class="text">{{ item.text }}</view>
|
||||
</view>
|
||||
</t-tab-bar-item>
|
||||
</t-tab-bar>
|
||||
|
9
custom-tab-bar/index.wxss
Normal file
9
custom-tab-bar/index.wxss
Normal file
@ -0,0 +1,9 @@
|
||||
.custom-tab-bar-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-tab-bar-wrapper .text {
|
||||
font-size: 20rpx;
|
||||
}
|
5
jsconfig.json
Normal file
5
jsconfig.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
}
|
||||
}
|
34
mock.md
Normal file
34
mock.md
Normal file
@ -0,0 +1,34 @@
|
||||
## 模拟与数据
|
||||
|
||||
model 用于放置模拟后端数据返回的逻辑;假若接入真实后端接口,则本文件夹可改造为数据层适配。
|
||||
services 用于请求逻辑,根据 config.useMock 配置可控制返回 mock 数据或是真实接口数据
|
||||
|
||||
### 1 模拟策略
|
||||
|
||||
1)只依靠 ID 规律进行关联
|
||||
大部分情况下推荐使用本方案,ID 为`1`的商品固定会关联 ID 为`1`的优惠券或者[ID 对 10 的模运算结果为 1](https://www.runoob.com/try/try.php?filename=tryjs_oper_mod)的优惠券(看需要 1 个还是多个了)。
|
||||
|
||||
> 为保持关系稳定,模运算统一使用`10`为除数,`ID`为被除数;即`1%10`、`2%10`。
|
||||
|
||||
2)建立额外关联关系查询
|
||||
在无法使用简单数学关系维持关系的情况下,可以采用单独提供关系数据的方式进行关联(目前也没想到什么场景是数学关系稳定不了的了,先假定有,定下规范做法)。如数据 A 与数据 B 之间需要一个关联 AB,则需要提供`A数据mock`、`B数据mock`、以及`A查B与B反查A`共 4 个 mock 源。
|
||||
|
||||
### 2 使用数据
|
||||
|
||||
使用数据源时应该在 services 文件夹中按照业务新建自己 fetch 函数导出,fetch 函数以 Promise 形式返回组合调用 model 逻辑得到的数据。
|
||||
|
||||
> 不允许直接在业务中调用、使用 model 数据。
|
||||
|
||||
## 接入真实 API 后
|
||||
|
||||
接入真实 API 后 model 文件夹逻辑可以反转层级,作为数据适配层继续为项目服务。举例说明:
|
||||
|
||||
1. 在没有接入 API 时(useMock 为 true)
|
||||
1.1 业务调用 services 进行 fetch
|
||||
1.2 fetch 逻辑调用 model 文件夹中对应的数据源,构造、返回业务需要的结构
|
||||
|
||||
2. 在接入 API 后(useMock 为 false)
|
||||
2.1 业务调用 services 进行 fetch
|
||||
2.2 fetch 逻辑调用接口得到真实后端数据
|
||||
2.3 比对 model 文件夹中数据 mock 数据结构 export 一个数据结构转换函数,输入真实后端数据,输出与 mock 数据结构一致的新数据,返回给 fetch
|
||||
2.4 fetch 函数 返回 转换后的 数据结构,业务层无需进行更改
|
46
package.json
Normal file
46
package.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"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": {
|
||||
"@vant/weapp": "^1.10.19",
|
||||
"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"
|
||||
}
|
||||
}
|
159
pages/home/home.js
Normal file
159
pages/home/home.js
Normal file
@ -0,0 +1,159 @@
|
||||
import {
|
||||
getbannerList
|
||||
} from '~/services/home/getbannerList';
|
||||
import {
|
||||
getNoticeList
|
||||
} from '~/services/home/getNoticeList';
|
||||
import {
|
||||
getSearchRecList
|
||||
} from '~/services/home/getSearchRecList';
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
imgSrcs: [],
|
||||
tabList: [{
|
||||
text: "精选推荐",
|
||||
key: 0,
|
||||
categoryGuid: 1,
|
||||
}],
|
||||
hotCategoryList: [],
|
||||
noticeList: [],
|
||||
popularWords: [],
|
||||
pageLoading: false,
|
||||
current: 0,
|
||||
autoplay: true,
|
||||
duration: '500',
|
||||
interval: 5000,
|
||||
navigation: {
|
||||
type: 'dots',
|
||||
},
|
||||
swiperImageProps: {
|
||||
mode: 'scaleToFill',
|
||||
},
|
||||
categoryGuid: 0,
|
||||
loadMoreStatus: 0
|
||||
},
|
||||
|
||||
page: {
|
||||
size: 20,
|
||||
num: 1,
|
||||
},
|
||||
privateData: {
|
||||
tabIndex: 0,
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.getTabBar().init();
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
// 划到底部触发
|
||||
onReachBottom() {
|
||||
this.getEmocticonLastData()
|
||||
},
|
||||
|
||||
onPullDownRefresh() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
init() {
|
||||
this.loadHomePage();
|
||||
},
|
||||
|
||||
loadHomePage() {
|
||||
wx.stopPullDownRefresh();
|
||||
|
||||
this.setData({
|
||||
pageLoading: true,
|
||||
});
|
||||
|
||||
this.getBanner()
|
||||
this.getRec()
|
||||
// this.getNotice()
|
||||
},
|
||||
|
||||
|
||||
getBanner() {
|
||||
// 获取轮播图列表
|
||||
getbannerList().then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.setData({
|
||||
imgSrcs: res.data.map((v) => v.bannerImg),
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getRec() {
|
||||
// 获取搜索推荐
|
||||
getSearchRecList().then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.setData({
|
||||
popularWords: res.data,
|
||||
pageLoading: false
|
||||
});
|
||||
} else {}
|
||||
});
|
||||
},
|
||||
|
||||
// 获取列表
|
||||
getEmocticonLastData() {
|
||||
const params = {
|
||||
pageSize: this.page.size,
|
||||
pageNum: this.page.num,
|
||||
isLastUpdate: true
|
||||
};
|
||||
this.setData({
|
||||
loadMoreStatus: 1,
|
||||
});
|
||||
// 获取最近更新表情包列表
|
||||
getEmoticonDataList(params).then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.page.num++;
|
||||
|
||||
this.setData({
|
||||
lastUpdatedList: this.data.lastUpdatedList.concat(res.data.result),
|
||||
loadMoreStatus: 0
|
||||
});
|
||||
|
||||
} else {}
|
||||
});
|
||||
},
|
||||
|
||||
getNotice() {
|
||||
// 获取公告列表
|
||||
getNoticeList().then((res) => {
|
||||
if (res.code == 200) {
|
||||
const _noticeData = res.data.map((v) => {
|
||||
return {
|
||||
...v,
|
||||
visible: true
|
||||
};
|
||||
});
|
||||
this.setData({
|
||||
noticeList: _noticeData,
|
||||
pageLoading: false
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 点击搜索推荐
|
||||
handleRecTap(e) {
|
||||
const {
|
||||
dataset
|
||||
} = e.currentTarget;
|
||||
const _searchValue = dataset?.value;
|
||||
if (_searchValue) {
|
||||
wx.navigateTo({
|
||||
url: `/pages/emoticon/result/index?searchValue=${_searchValue}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
});
|
20
pages/home/home.json
Normal file
20
pages/home/home.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"navigationBarTitleText": "小程序模板",
|
||||
"onReachBottomDistance": 10,
|
||||
"navigationBarBackgroundColor": "#ffffff",
|
||||
"backgroundTextStyle": "light",
|
||||
"enablePullDownRefresh": true,
|
||||
"usingComponents": {
|
||||
"t-search": "tdesign-miniprogram/search/search",
|
||||
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||
"t-swiper": "tdesign-miniprogram/swiper/swiper",
|
||||
"t-swiper-nav": "tdesign-miniprogram/swiper-nav/swiper-nav",
|
||||
"t-image": "/components/webp-image/index",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"t-tabs": "tdesign-miniprogram/tabs/tabs",
|
||||
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
|
||||
"load-more": "/components/load-more/index",
|
||||
"t-notice-bar": "tdesign-miniprogram/notice-bar/notice-bar"
|
||||
}
|
||||
}
|
46
pages/home/home.wxml
Normal file
46
pages/home/home.wxml
Normal file
@ -0,0 +1,46 @@
|
||||
<view style="text-align: center; color: #b9b9b9" wx:if="{{pageLoading}}">
|
||||
<t-loading theme="circular" size="40rpx" text="加载中..." inherit-color />
|
||||
</view>
|
||||
|
||||
<view class="home-page-header">
|
||||
<!-- 公告 -->
|
||||
<!-- <view class="notice-container ">
|
||||
<view wx:for="{{noticeList}}">
|
||||
<t-notice-bar class="notice-bar" visible="{{item.visible}}" prefixIcon="null" marquee="{{marquee}}" content="{{item.noticeContent}}">
|
||||
<view slot="prefix-icon" class="notice-title">
|
||||
<t-icon class="notice-icon" name="error-circle-filled"></t-icon>
|
||||
<view>
|
||||
{{item.noticeTitle}}
|
||||
</view>
|
||||
</view>
|
||||
</t-notice-bar>
|
||||
</view>
|
||||
</view> -->
|
||||
<!-- 轮播图 -->
|
||||
<view class="swiper-wrap">
|
||||
<t-swiper wx:if="{{imgSrcs.length > 0}}" current="{{current}}" autoplay="{{autoplay}}" duration="{{duration}}" interval="{{interval}}" navigation="{{navigation}}" imageProps="{{swiperImageProps}}" list="{{imgSrcs}}" />
|
||||
<!-- bind:click="navToActivityDetail" -->
|
||||
</view>
|
||||
<!-- 搜索框 -->
|
||||
<view class="search" bind:tap="navToSearchPage">
|
||||
<t-search t-class-input="t-search__input" t-class-input-container="t-search__input-container" placeholder="搜索关键词" leftIcon="" disabled>
|
||||
<t-icon slot="left-icon" prefix="wr" name="search" size="40rpx" color="#bbb" />
|
||||
</t-search>
|
||||
<!-- 热门搜索 -->
|
||||
<view class="popular-wrap">
|
||||
<view class="search-content" wx:if="{{popularWords.length > 0}}">
|
||||
<view class="search-item" hover-class="hover-history-item" wx:for="{{popularWords}}" data-value="{{item.title}}" bind:tap="handleRecTap" data-index="{{index}}" wx:key="*this">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else class="search-item">
|
||||
暂无数据
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="home-page-container">
|
||||
|
||||
</view>
|
||||
<t-toast id="t-toast" />
|
165
pages/home/home.wxss
Normal file
165
pages/home/home.wxss
Normal file
@ -0,0 +1,165 @@
|
||||
page {
|
||||
box-sizing: border-box;
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) + 96rpx);
|
||||
}
|
||||
|
||||
.t-tabs.t-tabs--top .t-tabs__scroll {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.home-page-header {
|
||||
background: linear-gradient(#fff, #f5f5f5);
|
||||
}
|
||||
|
||||
.home-page-container {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.home-page-container,
|
||||
.home-page-header {
|
||||
display: block;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.home-page-header .t-search__input-container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 32rpx !important;
|
||||
height: 64rpx !important;
|
||||
}
|
||||
|
||||
.home-page-header .t-search__input {
|
||||
font-size: 28rpx !important;
|
||||
color: rgb(116, 116, 116) !important;
|
||||
}
|
||||
|
||||
.home-page-header .swiper-wrap {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.home-page-header .t-image__swiper {
|
||||
width: 100%;
|
||||
height: 300rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.home-page-container .t-tabs {
|
||||
background: #f5f5f5 !important;
|
||||
}
|
||||
|
||||
.home-page-container .t-tabs .t-tabs-nav {
|
||||
background-color: transparent;
|
||||
line-height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.home-page-container .t-tabs .t-tabs-scroll {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
/* 半个字 */
|
||||
.home-page-container .tab.order-nav .order-nav-item.scroll-width {
|
||||
min-width: 165rpx;
|
||||
}
|
||||
|
||||
.home-page-container .tab .order-nav-item.active {
|
||||
color: #fa550f !important;
|
||||
}
|
||||
|
||||
.home-page-container .tab .bottom-line {
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.home-page-container .tab .order-nav-item.active .bottom-line {
|
||||
background-color: #fa550f !important;
|
||||
}
|
||||
|
||||
.home-page-container .tabs-external__item {
|
||||
/* color: #666 !important; */
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.home-page-container .tabs-external__active {
|
||||
color: #333333 !important;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.home-page-container .tabs-external__track {
|
||||
/* background-color: #fa4126 !important; */
|
||||
height: 6rpx !important;
|
||||
border-radius: 4rpx !important;
|
||||
width: 48rpx !important;
|
||||
}
|
||||
|
||||
.t-tabs.t-tabs--top .t-tabs__item,
|
||||
.t-tabs.t-tabs--bottom .t-tabs__item {
|
||||
height: 86rpx !important;
|
||||
}
|
||||
|
||||
.home-page-container .goods-list-container {
|
||||
background: #f5f5f5 !important;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.home-page-tabs {
|
||||
--td-tab-nav-bg-color: transparent;
|
||||
--td-tab-border-color: transparent;
|
||||
--td-tab-item-color: #666;
|
||||
--td-tab-track-color: red;
|
||||
}
|
||||
|
||||
.notice-container {
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.notice-bar {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.notice-bar .t-notice-bar__content {
|
||||
color: #666 !important;
|
||||
}
|
||||
|
||||
.notice-title {
|
||||
font-size: 28rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.notice-icon {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
|
||||
.popular-wrap {
|
||||
padding-top: 15rpx;
|
||||
padding-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.search-content {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.search-item {
|
||||
color: #333333;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: normal;
|
||||
margin-right: 24rpx;
|
||||
/* margin-bottom: 24rpx; */
|
||||
background: white;
|
||||
border-radius: 38rpx;
|
||||
padding: 15rpx 24rpx;
|
||||
}
|
||||
|
||||
.hover-history-item {
|
||||
position: relative;
|
||||
top: 3rpx;
|
||||
left: 3rpx;
|
||||
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1) inset;
|
||||
}
|
8
pages/home/readme
Normal file
8
pages/home/readme
Normal file
@ -0,0 +1,8 @@
|
||||
首页功能设定
|
||||
1. loading入场
|
||||
2. 下拉刷新
|
||||
3. 搜索栏
|
||||
4. 分类切换
|
||||
5. 商品列表
|
||||
6. 规格弹层
|
||||
7. 加载更多
|
175
pages/home/search/index.js
Normal file
175
pages/home/search/index.js
Normal file
@ -0,0 +1,175 @@
|
||||
import {
|
||||
getHistorySearchList
|
||||
} from '~/services/home/getHistorySearchList';
|
||||
import {
|
||||
getSearchRecList
|
||||
} from '~/services/home/getSearchRecList';
|
||||
import {
|
||||
getHotSearchList
|
||||
} from '~/services/home/getHotSearchList';
|
||||
import {
|
||||
addHistorySearch
|
||||
} from '~/services/home/addHistorySearch';
|
||||
import {
|
||||
deleteHistorySearch
|
||||
} from '~/services/home/deleteHistorySearch';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
historyWords: [],
|
||||
popularWords: [],
|
||||
searchValue: '',
|
||||
dialog: {
|
||||
showCancelButton: true,
|
||||
message: '',
|
||||
},
|
||||
dialogShow: false,
|
||||
},
|
||||
|
||||
deleteType: 0,
|
||||
deleteIndex: '',
|
||||
|
||||
onShow() {
|
||||
// this.queryHistory();
|
||||
this.queryPopular();
|
||||
},
|
||||
|
||||
async queryHistory() {
|
||||
try {
|
||||
getHistorySearchList().then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.setData({
|
||||
historyWords: res.data,
|
||||
});
|
||||
} else {
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
|
||||
async queryPopular() {
|
||||
try {
|
||||
getSearchRecList().then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.setData({
|
||||
popularWords: res.data,
|
||||
});
|
||||
} else {
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
|
||||
confirm() {
|
||||
const {
|
||||
historyWords
|
||||
} = this.data;
|
||||
const {
|
||||
deleteType,
|
||||
deleteIndex
|
||||
} = this;
|
||||
if (deleteType === 0) {
|
||||
const deleteWord = historyWords[deleteIndex];
|
||||
historyWords.splice(deleteIndex, 1);
|
||||
this.setData({
|
||||
historyWords,
|
||||
dialogShow: false,
|
||||
});
|
||||
deleteHistorySearch(deleteWord.historySearchId);
|
||||
} else {
|
||||
this.setData({
|
||||
historyWords: [],
|
||||
dialogShow: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
close() {
|
||||
this.setData({
|
||||
dialogShow: false,
|
||||
});
|
||||
},
|
||||
|
||||
handleClearHistory() {
|
||||
const {
|
||||
dialog
|
||||
} = this.data;
|
||||
this.deleteType = 1;
|
||||
this.setData({
|
||||
dialog: {
|
||||
...dialog,
|
||||
message: '确认删除所有历史记录',
|
||||
},
|
||||
dialogShow: true,
|
||||
});
|
||||
},
|
||||
|
||||
deleteCurr(e) {
|
||||
const {
|
||||
index
|
||||
} = e.currentTarget.dataset;
|
||||
const {
|
||||
dialog
|
||||
} = this.data;
|
||||
this.deleteIndex = index;
|
||||
this.setData({
|
||||
dialog: {
|
||||
...dialog,
|
||||
message: '确认删除当前历史记录',
|
||||
deleteType: 0,
|
||||
},
|
||||
dialogShow: true,
|
||||
});
|
||||
},
|
||||
|
||||
// 点击历史记录跳转
|
||||
handleHistoryTap(e) {
|
||||
const {
|
||||
historyWords
|
||||
} = this.data;
|
||||
const {
|
||||
dataset
|
||||
} = e.currentTarget;
|
||||
const _searchValue = historyWords[dataset.index || 0].historySearchContent || '';
|
||||
if (_searchValue) {
|
||||
wx.navigateTo({
|
||||
url: `/pages/emoticon/result/index?searchValue=${_searchValue}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// 点击搜索推荐
|
||||
handleRecTap(e) {
|
||||
const {
|
||||
dataset
|
||||
} = e.currentTarget;
|
||||
const _searchValue = dataset?.value;
|
||||
if (_searchValue) {
|
||||
wx.navigateTo({
|
||||
url: `/pages/emoticon/result/index?searchValue=${_searchValue}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// TODO:提交搜索
|
||||
handleSubmit(e) {
|
||||
const {
|
||||
value
|
||||
} = e.detail;
|
||||
if (value?.length === 0 || value == undefined) return;
|
||||
const data = {
|
||||
HistorySearchContent: value,
|
||||
};
|
||||
addHistorySearch(data).then((res) => {
|
||||
this.queryHistory();
|
||||
});
|
||||
wx.navigateTo({
|
||||
url: `/pages/emoticon/result/index?searchValue=${value}`,
|
||||
});
|
||||
},
|
||||
});
|
8
pages/home/search/index.json
Normal file
8
pages/home/search/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"navigationBarTitleText": "搜索",
|
||||
"usingComponents": {
|
||||
"t-search": "tdesign-miniprogram/search/search",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-dialog": "tdesign-miniprogram/dialog/dialog"
|
||||
}
|
||||
}
|
50
pages/home/search/index.wxml
Normal file
50
pages/home/search/index.wxml
Normal file
@ -0,0 +1,50 @@
|
||||
<view class="search-page">
|
||||
<t-search t-class-input-container="t-class__input-container" t-class-input="t-search__input" value="{{searchValue}}" leftIcon="" placeholder="搜索你想要的表情/获取码" bind:submit="handleSubmit" focus>
|
||||
<t-icon slot="left-icon" prefix="wr" name="search" size="40rpx" color="#bbb" />
|
||||
</t-search>
|
||||
<view class="search-wrap">
|
||||
<!-- <view class="history-wrap">
|
||||
<view class="search-header">
|
||||
<text class="search-title">历史搜索</text>
|
||||
<text class="search-clear" bind:tap="handleClearHistory">清除</text>
|
||||
</view>
|
||||
<view class="search-content" wx:if="{{historyWords.length > 0}}">
|
||||
<view class="search-item" hover-class="hover-history-item" wx:for="{{historyWords}}" bind:tap="handleHistoryTap" bindlongpress="deleteCurr" data-index="{{index}}" wx:key="*this">
|
||||
{{item.historySearchContent}}
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else class="search-item">
|
||||
暂无数据
|
||||
</view>
|
||||
</view> -->
|
||||
<view class="popular-wrap">
|
||||
<view class="search-header">
|
||||
<text class="search-title">搜索推荐</text>
|
||||
</view>
|
||||
<view class="search-content" wx:if="{{popularWords.length > 0}}">
|
||||
<view class="search-item" hover-class="hover-history-item" wx:for="{{popularWords}}" data-value="{{item.title}}" bind:tap="handleRecTap" data-index="{{index}}" wx:key="*this">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else class="search-item">
|
||||
暂无数据
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="popular-wrap">
|
||||
<view class="search-header">
|
||||
<text class="search-title">热门搜索</text>
|
||||
</view>
|
||||
<view class="search-content">
|
||||
<view wx:if="{{popularWords.length > 0}}">
|
||||
<view class="search-item" hover-class="hover-history-item" wx:for="{{popularWords}}" bind:tap="handleHistoryTap" data-index="{{index}}" wx:key="*this">
|
||||
{{item.searchTerm}}
|
||||
</view>
|
||||
</view>
|
||||
<view wx:else class="search-item">
|
||||
暂无数据
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<t-dialog visible="{{dialogShow}}" content="{{dialog.message}}" bindconfirm="confirm" bind:close="close" confirm-btn="确定" cancel-btn="{{dialog.showCancelButton ? '取消' : null}}" t-class-confirm="dialog__button-confirm" t-class-cancel="dialog__button-cancel" />
|
||||
</view>
|
79
pages/home/search/index.wxss
Normal file
79
pages/home/search/index.wxss
Normal file
@ -0,0 +1,79 @@
|
||||
.search-page {
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.search-page .t-class__input-container {
|
||||
height: 64rpx !important;
|
||||
border-radius: 32rpx !important;
|
||||
}
|
||||
|
||||
.search-page .t-search__input {
|
||||
font-size: 28rpx !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.search-page .search-wrap {
|
||||
margin-top: 44rpx;
|
||||
}
|
||||
|
||||
.search-page .history-wrap {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.search-page .search-header {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-page .search-title {
|
||||
font-size: 30rpx;
|
||||
font-family: PingFangSC-Semibold, PingFang SC;
|
||||
font-weight: 600;
|
||||
color: rgba(51, 51, 51, 1);
|
||||
line-height: 42rpx;
|
||||
}
|
||||
|
||||
.search-page .search-clear {
|
||||
font-size: 24rpx;
|
||||
font-family: PingFang SC;
|
||||
line-height: 32rpx;
|
||||
color: #999999;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.search-page .search-content {
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.search-page .search-item {
|
||||
color: #333333;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: normal;
|
||||
margin-right: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
background: #f5f5f5;
|
||||
border-radius: 38rpx;
|
||||
padding: 12rpx 24rpx;
|
||||
}
|
||||
|
||||
.search-page .hover-history-item {
|
||||
position: relative;
|
||||
top: 3rpx;
|
||||
left: 3rpx;
|
||||
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.1) inset;
|
||||
}
|
||||
|
||||
.add-notes__confirm {
|
||||
color: #fa4126 !important;
|
||||
}
|
70
pages/login/agree-link/index.js
Normal file
70
pages/login/agree-link/index.js
Normal file
@ -0,0 +1,70 @@
|
||||
import {
|
||||
getPlatformSpecDetails
|
||||
} from '~/services/login/getPlatformSpecDetails';
|
||||
|
||||
Page({
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
detailsData: {}
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
getPlatformSpecDetails({
|
||||
PlatformSpecGuid: options.guid
|
||||
}).then(res => {
|
||||
this.setData({
|
||||
detailsData: res.data
|
||||
})
|
||||
wx.setNavigationBarTitle({
|
||||
title: this.data.detailsData.platformSpecTitle
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
})
|
5
pages/login/agree-link/index.json
Normal file
5
pages/login/agree-link/index.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
},
|
||||
"navigationBarTitleText": ""
|
||||
}
|
3
pages/login/agree-link/index.wxml
Normal file
3
pages/login/agree-link/index.wxml
Normal file
@ -0,0 +1,3 @@
|
||||
<view style="width: 90%; margin: 40rpx auto; padding-bottom: 200rpx;">
|
||||
<rich-text nodes="{{detailsData.platformSpecContent}}"></rich-text>
|
||||
</view>
|
0
pages/login/agree-link/index.wxss
Normal file
0
pages/login/agree-link/index.wxss
Normal file
107
pages/login/authorize-avatar-name/index.js
Normal file
107
pages/login/authorize-avatar-name/index.js
Normal file
@ -0,0 +1,107 @@
|
||||
// pages/login/authorize-avatar-name/index.js
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
image: "https://cdn-we-retail.ym.tencent.com/miniapp/usercenter/icon-user-center-avatar@2x.png",
|
||||
},
|
||||
|
||||
login() {
|
||||
var that = this;
|
||||
// 基础库要在2.27.1以下才可以使用
|
||||
wx.getUserProfile({
|
||||
//获取用户信息。页面产生点击事件(例如 button 上 bindtap 的回调中)后才可调用,每次请求都会弹出授权窗口,用户同意后返回 userInfo,用于替换 wx.getUserInfo
|
||||
lang: 'zh_CN',
|
||||
desc: '用于在后台更好的识别您的身份', //声明获取用户个人信息后的用途
|
||||
success(user) {
|
||||
//接口调用成功的回调函数
|
||||
const data = {
|
||||
encryptedData: user.encryptedData,
|
||||
iv: user.iv,
|
||||
// signature: user.signature,
|
||||
// rawData: user.rawData,
|
||||
userInfo: user.userInfo,
|
||||
};
|
||||
|
||||
// app.request({
|
||||
// url: `login`,
|
||||
// method: 'POST',
|
||||
// data: data,
|
||||
// success: async function (res) {
|
||||
// // wx.setStorageSync('userInfo', res);
|
||||
// app.put('userInfo', res, 86400);
|
||||
// const userInfo = app.get('userInfo');
|
||||
|
||||
// // 如果第一次登录就注册一个客户账号
|
||||
|
||||
|
||||
// },
|
||||
// });
|
||||
},
|
||||
fail() {
|
||||
wx.switchTab({
|
||||
url: '/pages/home/home',
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
7
pages/login/authorize-avatar-name/index.json
Normal file
7
pages/login/authorize-avatar-name/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"t-avatar": "tdesign-miniprogram/avatar/avatar",
|
||||
"van-button": "@vant/weapp/button/index"
|
||||
},
|
||||
"navigationBarTitleText": "授权登录"
|
||||
}
|
25
pages/login/authorize-avatar-name/index.wxml
Normal file
25
pages/login/authorize-avatar-name/index.wxml
Normal file
@ -0,0 +1,25 @@
|
||||
<!-- 授权头像昵称登录页 -->
|
||||
<view class="mainContainer">
|
||||
|
||||
<!-- 头部头像盒子 -->
|
||||
<view class="top-avatar-box">
|
||||
<view class="avatar-img-box">
|
||||
<image class="avatar-img" src="{{image}}"></image>
|
||||
</view>
|
||||
<view class="avatar-line"></view>
|
||||
</view>
|
||||
|
||||
<!-- 权限文字盒子 -->
|
||||
<view class="authorize-content-box">
|
||||
<view class="authorize-content-title">申请获取以下权限</view>
|
||||
<view class="authorize-content-text">获得你的公开信息(昵称、头像等)</view>
|
||||
</view>
|
||||
|
||||
<!-- 授权按钮盒子 -->
|
||||
<view class="authorize-btn-box">
|
||||
<van-button type="primary" round block bind:tap="login">授权登录</van-button>
|
||||
<view class="authorize-btn"></view>
|
||||
<van-button round block>暂不登录</van-button>
|
||||
</view>
|
||||
|
||||
</view>
|
61
pages/login/authorize-avatar-name/index.wxss
Normal file
61
pages/login/authorize-avatar-name/index.wxss
Normal file
@ -0,0 +1,61 @@
|
||||
/* pages/login/authorize-avatar-name/index.wxss */
|
||||
|
||||
.mainContainer {
|
||||
width: 85%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* 头部头像盒子 */
|
||||
.top-avatar-box {
|
||||
margin-top: 50rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar-img-box {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
padding: 5rpx;
|
||||
box-shadow: 0 0 15rpx 5rpx #e8e8e8;
|
||||
}
|
||||
|
||||
.avatar-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.avatar-line {
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: #e3e3e3;
|
||||
margin-top: 50rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 权限文字盒子 */
|
||||
.authorize-content-box {
|
||||
margin: 80rpx 0;
|
||||
}
|
||||
|
||||
.authorize-content-title {
|
||||
font-size: 35rpx;
|
||||
margin-bottom:40rpx;
|
||||
color: #585858;
|
||||
}
|
||||
|
||||
.authorize-content-text{
|
||||
font-size:30rpx;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
|
||||
/* 授权按钮盒子 */
|
||||
.authorize-btn{
|
||||
margin-bottom: 25rpx;
|
||||
}
|
||||
|
148
pages/login/login.js
Normal file
148
pages/login/login.js
Normal file
@ -0,0 +1,148 @@
|
||||
// pages/login/login.js
|
||||
import Toast from '~/miniprogram_npm/@vant/weapp/toast/toast';
|
||||
import {
|
||||
login
|
||||
} from '~/services/login/login';
|
||||
import {
|
||||
getOpenId
|
||||
} from '~/services/login/getOpenId';
|
||||
import {
|
||||
getPlatformSpecList
|
||||
} from '~/services/login/getPlatformSpecList';
|
||||
|
||||
Page({
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
back: true,
|
||||
bg_image: "",
|
||||
checked: true,
|
||||
code: "",
|
||||
agree_Link: {}
|
||||
},
|
||||
|
||||
// 获取手机号
|
||||
getPhoneNumber(e) {
|
||||
console.log(e,'adsasdasdasd');
|
||||
let that = this
|
||||
if (that.data.checked == false) {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '请勾选同意按钮',
|
||||
duration: 2000,
|
||||
icon: '',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.detail.code) {
|
||||
let phoneCode = e.detail.code
|
||||
let openId = wx.getStorageSync('openId')
|
||||
|
||||
let data = {
|
||||
CustomerXcxOpenid: openId,
|
||||
Code: phoneCode
|
||||
}
|
||||
|
||||
// 登录请求
|
||||
login(data).then((res) => {
|
||||
if (res.data != null) {
|
||||
that.setData({
|
||||
back: false
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {}
|
||||
},
|
||||
|
||||
// 跳转到手机号登录
|
||||
gotoPhoneRegister() {
|
||||
wx.navigateTo({
|
||||
url: `/pages/login/phone-register/index`,
|
||||
});
|
||||
},
|
||||
|
||||
// 选择是否已同意
|
||||
onChangeChecked() {
|
||||
this.setData({
|
||||
checked: !this.data.checked
|
||||
})
|
||||
},
|
||||
|
||||
//协议点击
|
||||
agreeLink(data) {
|
||||
wx.navigateTo({
|
||||
url: '/pages/login/agree-link/index?guid=' + data.currentTarget.dataset.guid
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad() {
|
||||
let that = this
|
||||
// 获取OpenId的code
|
||||
wx.login({
|
||||
success(res) {
|
||||
that.setData({
|
||||
code: res.code
|
||||
})
|
||||
getOpenId({
|
||||
code: res.code
|
||||
}).then((res) => {
|
||||
wx.setStorageSync('openId', res.data)
|
||||
})
|
||||
},
|
||||
});
|
||||
// 获取平台资质与规范列表
|
||||
getPlatformSpecList().then(res => {
|
||||
this.setData({
|
||||
agree_Link: res.data
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
let that = this
|
||||
if (that.data.back == true) {
|
||||
wx.reLaunch({
|
||||
url: '/pages/home/home'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {},
|
||||
});
|
7
pages/login/login.json
Normal file
7
pages/login/login.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"van-button": "@vant/weapp/button/index",
|
||||
"van-checkbox": "@vant/weapp/checkbox/index"
|
||||
},
|
||||
"navigationBarTitleText": "授权登录"
|
||||
}
|
29
pages/login/login.wxml
Normal file
29
pages/login/login.wxml
Normal file
@ -0,0 +1,29 @@
|
||||
<!-- 登录页 -->
|
||||
|
||||
<!-- 背景图盒子 -->
|
||||
<view class="bg-box">
|
||||
<image class="bg-box-img" src="http://mall.api.aerwen.net/Uploads/uploads/20231029/E47DAEBE34756E17.jpg" />
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 登录盒子 -->
|
||||
<view class="login-pos-box">
|
||||
<view class="login-container-box">
|
||||
<view class="login-box">
|
||||
<view class="login-btn-box">
|
||||
<van-button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber" icon="wechat" type="primary" size="large" custom-style="font-size: 31rpx;font-weight: bold;" round block>微信一键登录</van-button>
|
||||
<!-- <view class="mb-30"></view>
|
||||
<van-button icon="phone" color="#eff0f1" size="large" custom-style="font-size: 31rpx;color: #999999;font-weight: bold;" round block bind:click="gotoPhoneRegister">手机号登录/注册</van-button> -->
|
||||
</view>
|
||||
|
||||
<!-- <view class="agree-box">
|
||||
<van-checkbox icon-size="35rpx" value="{{ checked }}" checked-color="#fc2e2a" bind:change="onChangeChecked"></van-checkbox>
|
||||
<view class="agree-text">
|
||||
我已阅读并同意
|
||||
<span class="agree-link" wx:for="{{agree_Link}}" bindtap='agreeLink' data-Guid='{{item.platformSpecGuid}}'>《{{item.platformSpecTitle}}》</span>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
61
pages/login/login.wxss
Normal file
61
pages/login/login.wxss
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
/* 背景图盒子 */
|
||||
.bg-box{
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
overflow: hidden;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.bg-box-img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* 登录盒子 */
|
||||
.login-pos-box{
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.login-container-box{
|
||||
width: 90%;
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
height: 220rpx;
|
||||
background-color: white;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.login-box{
|
||||
padding: 50rpx 40rpx;
|
||||
}
|
||||
|
||||
.phone-btn{
|
||||
color: black !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.agree-box{
|
||||
margin-top: 50rpx;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.agree-text{
|
||||
font-size: 25rpx;
|
||||
color: #555555;
|
||||
margin-top: -3rpx;
|
||||
}
|
||||
|
||||
.agree-link{
|
||||
font-size: 26rpx;
|
||||
color: red;
|
||||
}
|
115
pages/login/phone-register/index.js
Normal file
115
pages/login/phone-register/index.js
Normal file
@ -0,0 +1,115 @@
|
||||
// pages/login/phone-register/index.js
|
||||
import {
|
||||
sendPhoneCode
|
||||
} from '~/services/login/phone-register';
|
||||
|
||||
Page({
|
||||
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
logoImg: "https://tool.aerwen.net/prod-api/Open/20230602/8969EAF2294B1FF4.png",
|
||||
phoneNumber: "", //手机号
|
||||
phoneError: false, // 手机号验证
|
||||
verifyCode: "", //验证码
|
||||
},
|
||||
|
||||
|
||||
/** 发送验证码 */
|
||||
send() {
|
||||
if (!this.data.phoneNumber) {
|
||||
wx.showToast({
|
||||
icon: 'error',
|
||||
title: '请输入手机号',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const isPhoneNumber = /^[1][3,4,5,7,8,9][0-9]{9}$/.test(this.data.phoneNumber);
|
||||
if(!isPhoneNumber){
|
||||
wx.showToast({
|
||||
icon: 'error',
|
||||
title: '手机号格式不正确',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let data = {
|
||||
PhoneNumber: this.data.phoneNumber,
|
||||
}
|
||||
sendPhoneCode(data)
|
||||
},
|
||||
|
||||
|
||||
/** 手机号验证 */
|
||||
onPhoneInput(e) {
|
||||
const {
|
||||
phoneError
|
||||
} = this.data;
|
||||
const isPhoneNumber = /^[1][3,4,5,7,8,9][0-9]{9}$/.test(e.detail.value);
|
||||
if (phoneError === isPhoneNumber) {
|
||||
this.setData({
|
||||
phoneError: !isPhoneNumber,
|
||||
phoneNumber: e.detail.value,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面上拉触底事件的处理函数
|
||||
*/
|
||||
onReachBottom() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
7
pages/login/phone-register/index.json
Normal file
7
pages/login/phone-register/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"t-input": "tdesign-miniprogram/input/input",
|
||||
"van-button": "@vant/weapp/button/index"
|
||||
},
|
||||
"navigationBarTitleText": ""
|
||||
}
|
50
pages/login/phone-register/index.wxml
Normal file
50
pages/login/phone-register/index.wxml
Normal file
@ -0,0 +1,50 @@
|
||||
<!-- 手机号登录页 -->
|
||||
|
||||
<view class="phone-register-pos-box">
|
||||
|
||||
<!-- Logo盒子 -->
|
||||
<view class="logo-box">
|
||||
<view class="logo-img-box">
|
||||
<image class="logo-img" src="{{logoImg}}" mode="heightFix" />
|
||||
</view>
|
||||
<view class="logo-title">阿尔文电商</view>
|
||||
<view class="logo-text">一家有感情的电商模板</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 表单 -->
|
||||
<view class="register-form">
|
||||
<view class="register-form-box">
|
||||
<!-- 手机号 -->
|
||||
<t-input
|
||||
value="{{phoneNumber}}"
|
||||
placeholder="请输入手机号"
|
||||
borderless="{{true}}"
|
||||
style="border-radius: 100rpx; background-color: #f3f4f6;margin-bottom: 50rpx;height: 50rpx;"
|
||||
tips="{{phoneError ? '手机号输入不正确' : ''}}"
|
||||
bindchange="onPhoneInput"
|
||||
/>
|
||||
|
||||
<!-- 验证码 -->
|
||||
<t-input
|
||||
placeholder="请输入验证码"
|
||||
value="{{verifyCode}}"
|
||||
borderless="{{true}}"
|
||||
style="border-radius: 100rpx; background-color: #f3f4f6; height: 50rpx;"
|
||||
>
|
||||
<view slot="suffix" style="display: flex; align-items: center">
|
||||
<view class="suffix--line"></view>
|
||||
<van-button size="small" round type="info" bind:click="send">发送验证码</van-button>
|
||||
</view>
|
||||
</t-input>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-btn">
|
||||
<van-button type="info" size="large" round block>登录/注册</van-button>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
43
pages/login/phone-register/index.wxss
Normal file
43
pages/login/phone-register/index.wxss
Normal file
@ -0,0 +1,43 @@
|
||||
/* 手机号登录页Css */
|
||||
|
||||
/* Logo盒子 */
|
||||
.logo-box{
|
||||
margin-top: 50rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo-img{
|
||||
width: 230rpx;
|
||||
height: 230rpx;
|
||||
}
|
||||
|
||||
.logo-title{
|
||||
font-size: 40rpx;
|
||||
letter-spacing: 4rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo-text{
|
||||
font-size: 28rpx;
|
||||
margin-top: 20rpx;
|
||||
color: #999999;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
|
||||
/* 表单 */
|
||||
.register-form{
|
||||
margin-top: 100rpx;
|
||||
}
|
||||
.register-form-box{
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.submit-btn{
|
||||
margin-top: 50rpx;
|
||||
}
|
124
pages/usercenter/components/t-location/index.js
Normal file
124
pages/usercenter/components/t-location/index.js
Normal file
@ -0,0 +1,124 @@
|
||||
import { getPermission } from '../../../../utils/getPermission';
|
||||
import { phoneRegCheck } from '../../../../utils/util';
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
import { addressParse } from '../../../../utils/addressParse';
|
||||
import { resolveAddress, rejectAddress } from '../../address/list/util';
|
||||
|
||||
Component({
|
||||
externalClasses: ['t-class'],
|
||||
properties: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
navigateUrl: {
|
||||
type: String,
|
||||
},
|
||||
navigateEvent: {
|
||||
type: String,
|
||||
},
|
||||
isCustomStyle: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
isDisabledBtn: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
isOrderSure: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getWxLocation() {
|
||||
if (this.properties.isDisabledBtn) return;
|
||||
getPermission({ code: 'scope.address', name: '通讯地址' }).then(() => {
|
||||
wx.chooseAddress({
|
||||
success: async (options) => {
|
||||
const { provinceName, cityName, countyName, detailInfo, userName, telNumber } = options;
|
||||
|
||||
if (!phoneRegCheck(telNumber)) {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '请填写正确的手机号',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const target = {
|
||||
name: userName,
|
||||
phone: telNumber,
|
||||
countryName: '中国',
|
||||
countryCode: 'chn',
|
||||
detailAddress: detailInfo,
|
||||
provinceName: provinceName,
|
||||
cityName: cityName,
|
||||
districtName: countyName,
|
||||
isDefault: false,
|
||||
isOrderSure: this.properties.isOrderSure,
|
||||
};
|
||||
|
||||
try {
|
||||
const { provinceCode, cityCode, districtCode } = await addressParse(provinceName, cityName, countyName);
|
||||
|
||||
const params = Object.assign(target, {
|
||||
provinceCode,
|
||||
cityCode,
|
||||
districtCode,
|
||||
});
|
||||
if (this.properties.isOrderSure) {
|
||||
this.onHandleSubmit(params);
|
||||
} else if (this.properties.navigateUrl != '') {
|
||||
const { navigateEvent } = this.properties;
|
||||
this.triggerEvent('navigate');
|
||||
wx.navigateTo({
|
||||
url: this.properties.navigateUrl,
|
||||
success: function (res) {
|
||||
res.eventChannel.emit(navigateEvent, params);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.triggerEvent('change', params);
|
||||
}
|
||||
} catch (error) {
|
||||
wx.showToast({ title: '地址解析出错,请稍后再试', icon: 'none' });
|
||||
}
|
||||
},
|
||||
fail(err) {
|
||||
console.warn('未选择微信收货地址', err);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
async queryAddress(addressId) {
|
||||
try {
|
||||
const { data } = await apis.userInfo.queryAddress({ addressId });
|
||||
return data.userAddressVO;
|
||||
} catch (err) {
|
||||
console.error('查询地址错误', err);
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
||||
findPage(pageRouteUrl) {
|
||||
const currentRoutes = getCurrentPages().map((v) => v.route);
|
||||
return currentRoutes.indexOf(pageRouteUrl);
|
||||
},
|
||||
|
||||
async onHandleSubmit(params) {
|
||||
try {
|
||||
const orderPageDeltaNum = this.findPage('pages/order/order-confirm/index');
|
||||
if (orderPageDeltaNum > -1) {
|
||||
wx.navigateBack({ delta: 1 });
|
||||
resolveAddress(params);
|
||||
return;
|
||||
}
|
||||
} catch (err) {
|
||||
rejectAddress(params);
|
||||
console.error(err);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
8
pages/usercenter/components/t-location/index.json
Normal file
8
pages/usercenter/components/t-location/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-cell": "tdesign-miniprogram/cell/cell",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast"
|
||||
}
|
||||
}
|
16
pages/usercenter/components/t-location/index.wxml
Normal file
16
pages/usercenter/components/t-location/index.wxml
Normal file
@ -0,0 +1,16 @@
|
||||
<view class="wx-address t-class" bind:tap="getWxLocation">
|
||||
<block wx:if="{{isCustomStyle}}">
|
||||
<view class="wx-address-custom">
|
||||
<t-icon prefix="wr" t-class="weixin" color="#0ABF5B" name="wechat" size="48rpx" />
|
||||
<text>{{title}}</text>
|
||||
</view>
|
||||
<slot />
|
||||
</block>
|
||||
<block wx:else>
|
||||
<t-cell title="{{title}}" title-class="cell__title" wr-class="cell" border="{{false}}">
|
||||
<t-icon t-class="weixin" slot="icon" color="#0ABF5B" name="logo-windows" size="48rpx" />
|
||||
<t-icon slot="right-icon" name="chevron-right" class="custom-icon" color="#bbb" />
|
||||
</t-cell>
|
||||
</block>
|
||||
</view>
|
||||
<t-toast id="t-toast" />
|
19
pages/usercenter/components/t-location/index.wxss
Normal file
19
pages/usercenter/components/t-location/index.wxss
Normal file
@ -0,0 +1,19 @@
|
||||
.wx-address .weixin {
|
||||
display: inline-block;
|
||||
font-size: 48rpx !important;
|
||||
margin-right: 20rpx;
|
||||
font-weight: normal;
|
||||
}
|
||||
.wx-address .cell {
|
||||
padding: 32rpx 30rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
.wx-address .cell__title {
|
||||
font-size: 30rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.wx-address-custom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
}
|
73
pages/usercenter/components/ui-select-picker/index.js
Normal file
73
pages/usercenter/components/ui-select-picker/index.js
Normal file
@ -0,0 +1,73 @@
|
||||
Component({
|
||||
properties: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
observer(show) {
|
||||
if (!show) return;
|
||||
this.updateDivisions();
|
||||
},
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
value: '',
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer() {
|
||||
if (!this.data.show) return;
|
||||
this.updateDivisions();
|
||||
},
|
||||
},
|
||||
pickerOptions: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer() {
|
||||
if (!this.data.show) return;
|
||||
this.updateDivisions();
|
||||
},
|
||||
},
|
||||
headerVisible: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
pickerValue: [],
|
||||
},
|
||||
methods: {
|
||||
updateDivisions() {
|
||||
const { pickerOptions, value } = this.data;
|
||||
const index = (pickerOptions || []).findIndex(
|
||||
(item) => item.code === value,
|
||||
);
|
||||
|
||||
setTimeout(() => {
|
||||
this.setData({ pickerValue: index >= 0 ? [index] : [0] });
|
||||
}, 0);
|
||||
},
|
||||
|
||||
getAreaByIndex(indexes) {
|
||||
const { pickerOptions } = this.data;
|
||||
return pickerOptions[indexes.toString()];
|
||||
},
|
||||
|
||||
onChange(e) {
|
||||
const currentValue = e.detail.value;
|
||||
const target = this.getAreaByIndex(currentValue);
|
||||
if (target === null) return;
|
||||
|
||||
this.setData({ pickerValue: currentValue });
|
||||
this.triggerEvent('change', { value: target.code, target: target });
|
||||
},
|
||||
|
||||
onConfirm() {
|
||||
const target = this.getAreaByIndex(this.data.pickerValue);
|
||||
this.triggerEvent('confirm', { value: target?.code, target });
|
||||
},
|
||||
|
||||
onClose() {
|
||||
this.triggerEvent('close');
|
||||
},
|
||||
},
|
||||
});
|
6
pages/usercenter/components/ui-select-picker/index.json
Normal file
6
pages/usercenter/components/ui-select-picker/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-popup": "tdesign-miniprogram/popup/popup"
|
||||
}
|
||||
}
|
21
pages/usercenter/components/ui-select-picker/index.wxml
Normal file
21
pages/usercenter/components/ui-select-picker/index.wxml
Normal file
@ -0,0 +1,21 @@
|
||||
<t-popup visible="{{show}}" placement="bottom">
|
||||
<view class="city-picker-box" slot="content">
|
||||
<view wx:if="{{headerVisible}}" class="city-picker-header city-picker-more">
|
||||
<view class="btn" hover-class="btn__active" catch:tap="onClose">取消</view>
|
||||
<view wx:if="{{title}}" class="title">{{title}}</view>
|
||||
<view class="btn primary" hover-class="btn__active" catch:tap="onConfirm">确定</view>
|
||||
</view>
|
||||
<view wx:else class="city-picker-header">
|
||||
<view wx:if="{{title}}" class="title">{{title}}</view>
|
||||
</view>
|
||||
<picker-view class="picker" indicator-class="picker-center-row" value="{{pickerValue}}" bind:change="onChange">
|
||||
<picker-view-column class="picker-column">
|
||||
<view wx:for="{{ pickerOptions }}" wx:key="code">{{ item.name }}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<view class="city-picker-footer" wx:if="{{!headerVisible}}">
|
||||
<view class="btn" hover-class="btn__active" catch:tap="onClose">取消</view>
|
||||
<view class="btn primary" hover-class="btn__active" catch:tap="onConfirm">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</t-popup>
|
102
pages/usercenter/components/ui-select-picker/index.wxss
Normal file
102
pages/usercenter/components/ui-select-picker/index.wxss
Normal file
@ -0,0 +1,102 @@
|
||||
.city-picker-container {
|
||||
opacity: 0;
|
||||
position: fixed;
|
||||
top: 100vh;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100vh;
|
||||
z-index: 100;
|
||||
}
|
||||
.city-picker-container.show {
|
||||
top: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
.city-picker-container.show .city-picker-box {
|
||||
bottom: 0;
|
||||
}
|
||||
.city-picker-shadow {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.65);
|
||||
}
|
||||
.city-picker-header {
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.city-picker-more {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.city-picker-footer {
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.city-picker-footer .btn {
|
||||
width: 330rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
color: #666666;
|
||||
font-size: 32rpx;
|
||||
position: relative;
|
||||
}
|
||||
.city-picker-footer .btn__active {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.city-picker-footer .btn::after {
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: -50%;
|
||||
right: -50%;
|
||||
top: -50%;
|
||||
bottom: -50%;
|
||||
transform: scale(0.5);
|
||||
border: 1rpx solid #999999;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
.city-picker-footer .btn.primary {
|
||||
color: #fa550f;
|
||||
}
|
||||
.city-picker-footer .btn.primary::after {
|
||||
border-color: #fa550f;
|
||||
}
|
||||
.picker-column:not(:first-child) {
|
||||
margin-left: 40rpx;
|
||||
}
|
||||
.city-picker-box {
|
||||
position: absolute;
|
||||
bottom: -100%;
|
||||
transition: 0.3s bottom ease-in-out;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background-color: #fff;
|
||||
padding: 0 30rpx;
|
||||
color: #333333;
|
||||
font-size: 34rpx;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
}
|
||||
.show .city-picker-shadow {
|
||||
display: block;
|
||||
}
|
||||
.picker {
|
||||
height: 300rpx;
|
||||
margin: 50rpx 0;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
}
|
||||
/* 似乎小程序picker-view的bug,indicator-class仅height生效,其他诸如line-height、text-align等放到父class中设置 */
|
||||
.picker-center-row {
|
||||
height: 88rpx;
|
||||
}
|
38
pages/usercenter/components/user-center-card/index.js
Normal file
38
pages/usercenter/components/user-center-card/index.js
Normal file
@ -0,0 +1,38 @@
|
||||
const AuthStepType = {
|
||||
ONE: 1,
|
||||
TWO: 2,
|
||||
THREE: 3,
|
||||
};
|
||||
|
||||
Component({
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
},
|
||||
properties: {
|
||||
currAuthStep: {
|
||||
type: Number,
|
||||
value: AuthStepType.ONE,
|
||||
},
|
||||
userInfo: {
|
||||
type: Object,
|
||||
value: {},
|
||||
},
|
||||
isNeedGetUserInfo: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
defaultAvatarUrl:
|
||||
'https://cdn-we-retail.ym.tencent.com/miniapp/usercenter/icon-user-center-avatar@2x.png',
|
||||
AuthStepType,
|
||||
},
|
||||
methods: {
|
||||
gotoUserEditPage() {
|
||||
this.triggerEvent('gotoUserEditPage');
|
||||
},
|
||||
gotoLogin(){
|
||||
wx.navigateTo({ url: '/pages/login/login' });
|
||||
}
|
||||
},
|
||||
});
|
7
pages/usercenter/components/user-center-card/index.json
Normal file
7
pages/usercenter/components/user-center-card/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-avatar": "tdesign-miniprogram/avatar/avatar"
|
||||
}
|
||||
}
|
40
pages/usercenter/components/user-center-card/index.wxml
Normal file
40
pages/usercenter/components/user-center-card/index.wxml
Normal file
@ -0,0 +1,40 @@
|
||||
<wxs module="phoneReg">
|
||||
var toHide = function (array) { var mphone = array.substring(0, 3) + '****' + array.substring(7); return mphone; }
|
||||
module.exports.toHide = toHide;
|
||||
</wxs>
|
||||
<view class="user-center-card">
|
||||
<!-- 未登录的情况 -->
|
||||
<block wx:if="{{currAuthStep === AuthStepType.ONE}}">
|
||||
<view class="user-center-card__header" bind:tap="gotoLogin">
|
||||
<t-avatar image="{{userInfo.avatarUrl || defaultAvatarUrl}}" class="user-center-card__header__avatar" />
|
||||
<view class="user-center-card__header__name">{{'请登录'}}</view>
|
||||
</view>
|
||||
</block>
|
||||
<!-- 已登录但未授权用户信息情况 -->
|
||||
<block wx:if="{{currAuthStep === AuthStepType.TWO}}">
|
||||
<view class="user-center-card__header">
|
||||
<t-avatar image="{{userInfo.avatarUrl || defaultAvatarUrl}}" class="user-center-card__header__avatar" />
|
||||
<view class="user-center-card__heade__text__box">
|
||||
<view class="user-center-card__header__name">{{userInfo.nickName || '微信用户'}}</view>
|
||||
<view class="user-center-card__header__phone">{{phoneReg.toHide(userInfo.phoneNumber || '')}}</view>
|
||||
</view>
|
||||
<!-- 需要授权用户信息,通过slot添加弹窗 -->
|
||||
<view class="user-center-card__header__transparent" wx:if="{{isNeedGetUserInfo}}">
|
||||
<slot name="getUserInfo" />
|
||||
</view>
|
||||
<!-- 不需要授权用户信息,仍然触发gotoUserEditPage事件 -->
|
||||
<view class="user-center-card__header__transparent" bind:tap="gotoUserEditPage" wx:else></view>
|
||||
</view>
|
||||
</block>
|
||||
<!-- 已登录且已经授权用户信息的情况 -->
|
||||
<block wx:if="{{currAuthStep === AuthStepType.THREE}}">
|
||||
<view class="user-center-card__header" bind:tap="gotoUserEditPage">
|
||||
<t-avatar t-class="avatar" mode="aspectFill" class="user-center-card__header__avatar" image="{{userInfo.avatarUrl || defaultAvatarUrl}}" />
|
||||
<view class="user-center-card__header__name">{{userInfo.nickName || '微信用户'}}</view>
|
||||
<view class="user-center-card__heade__text__box">
|
||||
<view class="user-center-card__header__name">{{userInfo.nickName || '微信用户'}}</view>
|
||||
<view class="user-center-card__header__phone">{{phoneReg.toHide(userInfo.phoneNumber || '')}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
58
pages/usercenter/components/user-center-card/index.wxss
Normal file
58
pages/usercenter/components/user-center-card/index.wxss
Normal file
@ -0,0 +1,58 @@
|
||||
.user-center-card {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 480rpx;
|
||||
/* 个人信息背景图 */
|
||||
background-image: url('https://cdn-we-retail.ym.tencent.com/miniapp/template/user-center-bg-v1.png');
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
padding: 0 35rpx;
|
||||
}
|
||||
.user-center-card__header {
|
||||
margin-top: 192rpx;
|
||||
margin-bottom: 48rpx;
|
||||
height: 96rpx;
|
||||
line-height: 48rpx;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
color: #333;
|
||||
position: relative;
|
||||
}
|
||||
.user-center-card__header__avatar {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 48rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-center-card__heade__text__box{
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.user-center-card__header__name {
|
||||
font-size: 36rpx;
|
||||
line-height: 48rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
.user-center-card__header__phone {
|
||||
font-size: 30rpx;
|
||||
margin-right: 16rpx;
|
||||
margin-top: 5rpx;
|
||||
}
|
||||
|
||||
.user-center-card__header__transparent {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-color: transparent;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.user-center-card__icon {
|
||||
line-height: 96rpx;
|
||||
}
|
113
pages/usercenter/goods-collect/index.js
Normal file
113
pages/usercenter/goods-collect/index.js
Normal file
@ -0,0 +1,113 @@
|
||||
import {
|
||||
getGoodsCollectionList
|
||||
} from '~/services/usercenter/goods-collect/getGoodsCollectionList';
|
||||
|
||||
|
||||
Page({
|
||||
page: {
|
||||
size: 10,
|
||||
num: 1,
|
||||
},
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
list: [],
|
||||
goodsListLoadStatus: 0
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
this.init()
|
||||
},
|
||||
|
||||
// 获取售后订单列表
|
||||
init(reset = false) {
|
||||
const params = {
|
||||
pageSize: this.page.size,
|
||||
pageNum: this.page.num,
|
||||
};
|
||||
this.setData({
|
||||
goodsListLoadStatus: 1,
|
||||
});
|
||||
return getGoodsCollectionList(params)
|
||||
.then((res) => {
|
||||
this.page.num++;
|
||||
|
||||
if (res && res.data && res.data.result) {
|
||||
this.setData({
|
||||
list: this.data.list.concat(res.data.result),
|
||||
goodsListLoadStatus: 0,
|
||||
});
|
||||
}
|
||||
|
||||
}).catch((err) => {
|
||||
this.setData({
|
||||
goodsListLoadStatus: 3,
|
||||
});
|
||||
return Promise.reject(err);
|
||||
});
|
||||
},
|
||||
|
||||
gotoGoodsDetail(e) {
|
||||
const {
|
||||
index
|
||||
} = e.detail;
|
||||
const {
|
||||
spuId
|
||||
} = this.data.list[index];
|
||||
wx.navigateTo({
|
||||
url: `/pages/goods/details/index?spuId=${spuId}`,
|
||||
});
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.goodsListLoadStatus === 0) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
8
pages/usercenter/goods-collect/index.json
Normal file
8
pages/usercenter/goods-collect/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"navigationBarTitleText": "我的收藏",
|
||||
"usingComponents": {
|
||||
"t-empty": "tdesign-miniprogram/empty/empty",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"load-more": "/components/load-more/index"
|
||||
}
|
||||
}
|
9
pages/usercenter/goods-collect/index.wxml
Normal file
9
pages/usercenter/goods-collect/index.wxml
Normal file
@ -0,0 +1,9 @@
|
||||
<!--pages/usercenter/goods-collect/index.wxml-->
|
||||
<view wx:key="index" class="section">
|
||||
<view class="goods-category-crad">
|
||||
<view class="empty-wrap" wx:if="{{list.length === 0}}">
|
||||
<t-empty t-class="empty-tips" size="240rpx" description="暂无收藏商品" />
|
||||
</view>
|
||||
<!-- 列表 -->
|
||||
</view>
|
||||
</view>
|
1
pages/usercenter/goods-collect/index.wxss
Normal file
1
pages/usercenter/goods-collect/index.wxss
Normal file
@ -0,0 +1 @@
|
||||
/* pages/usercenter/goods-collect/index.wxss */
|
119
pages/usercenter/goods-history/index.js
Normal file
119
pages/usercenter/goods-history/index.js
Normal file
@ -0,0 +1,119 @@
|
||||
import {
|
||||
getGoodsBrowsingHistoryList
|
||||
} from '~/services/usercenter/goods-history/getGoodsBrowsingHistoryList';
|
||||
|
||||
|
||||
Page({
|
||||
page: {
|
||||
size: 10,
|
||||
num: 1,
|
||||
},
|
||||
/**
|
||||
* 页面的初始数据
|
||||
*/
|
||||
data: {
|
||||
list: [],
|
||||
goodsListLoadStatus: 0
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面加载
|
||||
*/
|
||||
onLoad(options) {
|
||||
this.init()
|
||||
},
|
||||
|
||||
onReTry() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
// 获取商品浏览记录列表
|
||||
async init(reset = false) {
|
||||
const params = {
|
||||
pageSize: this.page.size,
|
||||
pageNum: this.page.num,
|
||||
};
|
||||
this.setData({
|
||||
goodsListLoadStatus: 1,
|
||||
});
|
||||
return getGoodsBrowsingHistoryList(params)
|
||||
.then((res) => {
|
||||
this.page.num++;
|
||||
|
||||
if (res && res.data && res.data.result) {
|
||||
this.setData({
|
||||
list: this.data.list.concat(res.data.result),
|
||||
goodsListLoadStatus: 0,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
this.setData({
|
||||
goodsListLoadStatus: 3,
|
||||
});
|
||||
return Promise.reject(err);
|
||||
});
|
||||
},
|
||||
|
||||
gotoGoodsDetail(e) {
|
||||
const {
|
||||
index
|
||||
} = e.detail;
|
||||
const {
|
||||
spuId
|
||||
} = this.data.list[index];
|
||||
wx.navigateTo({
|
||||
url: `/pages/goods/details/index?spuId=${spuId}`,
|
||||
});
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.goodsListLoadStatus === 0) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面初次渲染完成
|
||||
*/
|
||||
onReady() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面显示
|
||||
*/
|
||||
onShow() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面隐藏
|
||||
*/
|
||||
onHide() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 生命周期函数--监听页面卸载
|
||||
*/
|
||||
onUnload() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 页面相关事件处理函数--监听用户下拉动作
|
||||
*/
|
||||
onPullDownRefresh() {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 用户点击右上角分享
|
||||
*/
|
||||
onShareAppMessage() {
|
||||
|
||||
}
|
||||
})
|
8
pages/usercenter/goods-history/index.json
Normal file
8
pages/usercenter/goods-history/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"navigationBarTitleText": "我的浏览记录",
|
||||
"usingComponents": {
|
||||
"t-empty": "tdesign-miniprogram/empty/empty",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"load-more": "/components/load-more/index"
|
||||
}
|
||||
}
|
10
pages/usercenter/goods-history/index.wxml
Normal file
10
pages/usercenter/goods-history/index.wxml
Normal file
@ -0,0 +1,10 @@
|
||||
<!--pages/usercenter/goods-collect/index.wxml-->
|
||||
<view wx:key="index" class="section">
|
||||
<view class="goods-category-crad">
|
||||
<view class="empty-wrap" wx:if="{{list.length === 0}}">
|
||||
<t-empty t-class="empty-tips" size="240rpx" description="暂无浏览记录" />
|
||||
</view>
|
||||
<!-- 列表 -->
|
||||
<load-more list-is-empty="{{!list.length}}" status="{{goodsListLoadStatus}}" bind:retry="onReTry" />
|
||||
</view>
|
||||
</view>
|
1
pages/usercenter/goods-history/index.wxss
Normal file
1
pages/usercenter/goods-history/index.wxss
Normal file
@ -0,0 +1 @@
|
||||
/* pages/usercenter/goods-history/index.wxss */
|
195
pages/usercenter/index.js
Normal file
195
pages/usercenter/index.js
Normal file
@ -0,0 +1,195 @@
|
||||
import {
|
||||
fetchUserCenter
|
||||
} from '~/services/usercenter/fetchUsercenter';
|
||||
import {
|
||||
getCustomerServiceList
|
||||
} from '~/services/usercenter/getCustomerServiceList';
|
||||
import {
|
||||
getOpenId
|
||||
} from '~/services/login/getOpenId';
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
|
||||
const menuData = [
|
||||
[
|
||||
{
|
||||
title: '设置',
|
||||
tit: '',
|
||||
url: '',
|
||||
type: 'set',
|
||||
},
|
||||
],
|
||||
[
|
||||
// {
|
||||
// title: '帮助中心',
|
||||
// tit: '',
|
||||
// url: '',
|
||||
// type: 'help-center',
|
||||
// },
|
||||
{
|
||||
title: '联系客服',
|
||||
tit: '',
|
||||
url: '',
|
||||
type: 'service',
|
||||
icon: 'service',
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
const getDefaultData = () => ({
|
||||
showMakePhone: false,
|
||||
userInfo: {
|
||||
avatarUrl: '',
|
||||
nickName: '正在登录...',
|
||||
phoneNumber: '',
|
||||
},
|
||||
collectData: {
|
||||
collectCount: 0,
|
||||
historyCount: 0,
|
||||
},
|
||||
menuData,
|
||||
customerServiceInfo: {},
|
||||
currAuthStep: 1,
|
||||
showKefu: true,
|
||||
CustomerService: {},
|
||||
});
|
||||
|
||||
Page({
|
||||
data: getDefaultData(),
|
||||
|
||||
onLoad() {
|
||||
this.onGetCustomerServiceList();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.getTabBar().init();
|
||||
this.init();
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.init();
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetUseriInfoHandle();
|
||||
},
|
||||
|
||||
/** 获取客户信息 */
|
||||
fetUseriInfoHandle() {
|
||||
fetchUserCenter().then(
|
||||
({
|
||||
userInfo,
|
||||
collectData,
|
||||
}) => {
|
||||
this.setData({
|
||||
userInfo,
|
||||
collectData,
|
||||
currAuthStep: 2,
|
||||
});
|
||||
wx.stopPullDownRefresh();
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
onClickCell({
|
||||
currentTarget
|
||||
}) {
|
||||
const {
|
||||
type
|
||||
} = currentTarget.dataset;
|
||||
|
||||
switch (type) {
|
||||
case 'service': {
|
||||
this.openMakePhone();
|
||||
break;
|
||||
}
|
||||
case 'set': {
|
||||
wx.navigateTo({
|
||||
url: '/pages/usercenter/set/index'
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '未知跳转',
|
||||
icon: '',
|
||||
duration: 1000,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
jumpAllOrder() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/order/order-list/index'
|
||||
});
|
||||
},
|
||||
|
||||
jumpCollect() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/usercenter/goods-collect/index'
|
||||
});
|
||||
},
|
||||
|
||||
jumpHistory() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/usercenter/goods-history/index'
|
||||
});
|
||||
},
|
||||
|
||||
openMakePhone() {
|
||||
this.setData({
|
||||
showMakePhone: true
|
||||
});
|
||||
},
|
||||
|
||||
closeMakePhone() {
|
||||
this.setData({
|
||||
showMakePhone: false
|
||||
});
|
||||
},
|
||||
|
||||
call() {
|
||||
wx.makePhoneCall({
|
||||
phoneNumber: this.data.customerServiceInfo.servicePhone,
|
||||
});
|
||||
},
|
||||
|
||||
getOpenIdFun() {
|
||||
wx.login({
|
||||
success(res) {
|
||||
getOpenId({
|
||||
code: res.code
|
||||
}).then((res) => {
|
||||
wx.setStorageSync('openId', res.data)
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
gotoUserEditPage() {
|
||||
const {
|
||||
currAuthStep
|
||||
} = this.data;
|
||||
if (currAuthStep === 2) {
|
||||
wx.navigateTo({
|
||||
url: '/pages/usercenter/person-info/index'
|
||||
});
|
||||
} else {
|
||||
// this.fetUseriInfoHandle();
|
||||
}
|
||||
},
|
||||
|
||||
// 获取客服列表
|
||||
onGetCustomerServiceList() {
|
||||
getCustomerServiceList().then((res) => {
|
||||
if (res.code == 200) {
|
||||
this.setData({
|
||||
CustomerService: res.data[0]
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
13
pages/usercenter/index.json
Normal file
13
pages/usercenter/index.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"navigationBarTitleText": "个人中心",
|
||||
"navigationStyle": "custom",
|
||||
"usingComponents": {
|
||||
"t-popup": "tdesign-miniprogram/popup/popup",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-cell-group": "tdesign-miniprogram/cell-group/cell-group",
|
||||
"t-cell": "tdesign-miniprogram/cell/cell",
|
||||
"t-user-center-card": "./components/user-center-card/index",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast"
|
||||
},
|
||||
"enablePullDownRefresh": true
|
||||
}
|
44
pages/usercenter/index.wxml
Normal file
44
pages/usercenter/index.wxml
Normal file
@ -0,0 +1,44 @@
|
||||
<t-user-center-card userInfo="{{userInfo}}" isPhoneHide="{{true}}" name-class="custom-name-class" phone-class="custom-phone-class" avatar-class="customer-avatar-class" currAuthStep="{{currAuthStep}}" bind:gotoUserEditPage="gotoUserEditPage" />
|
||||
|
||||
|
||||
<view class="content-wrapper">
|
||||
<!-- 收藏和足迹 -->
|
||||
<view class="order-history-box">
|
||||
<view class="order-history-content-box" bind:tap="jumpCollect">
|
||||
<view class="order-history-content-num">{{collectData.collectCount}}</view>
|
||||
<view class="order-history-content-text">收藏</view>
|
||||
</view>
|
||||
<view class="order-history-content-line"></view>
|
||||
<view class="order-history-content-box" bind:tap="jumpHistory">
|
||||
<view class="order-history-content-num">{{collectData.historyCount}}</view>
|
||||
<view class="order-history-content-text">浏览记录</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <button type="primary" bind:tap="getOpenIdFun">获取OpenID</button> -->
|
||||
|
||||
<view wx:for="{{menuData}}" wx:key="item" class="cell-box">
|
||||
<t-cell-group>
|
||||
<t-cell wx:for="{{item}}" wx:for-item="xitem" wx:for-index="xindex" wx:key="xindex" title="{{xitem.title}}" arrow="{{!xitem.icon}}" note="{{xitem.tit}}" data-type="{{xitem.type}}" bordered="{{false}}" bind:click="onClickCell" t-class="t-cell-padding" t-class-note="order-group-note" t-class-left="order-group__left">
|
||||
<t-icon name="{{xitem.icon}}" size="48rpx" slot="note" />
|
||||
</t-cell>
|
||||
</t-cell-group>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{CustomerService}}">
|
||||
<view class="footer__version" style="margin-top: 50rpx;">客服电话 {{CustomerService.customerServicePhone}}</view>
|
||||
<view class="footer__version">工作时间 {{CustomerService.workingHoursBeginTime}}-{{CustomerService.workingHoursEndTime}}</view>
|
||||
</view>
|
||||
<t-popup visible="{{showMakePhone}}" placement="bottom" bind:visible-change="closeMakePhone" data-index="2">
|
||||
<view class="popup-content">
|
||||
<view class="customer-service-img" wx:if="{{CustomerService.customerServiceImg}}">
|
||||
<image src="{{CustomerService.customerServiceImg}}" mode="widthFix" />
|
||||
</view>
|
||||
<!-- <view class="popup-title border-bottom-1px" wx:if="{{customerServiceInfo.serviceTimeDuration}}">
|
||||
服务时间: {{customerServiceInfo.serviceTimeDuration}}
|
||||
</view>
|
||||
<view class="popup-phone {{showKefu ? 'border-bottom-1px' : ''}}" bind:tap="call">电话客服</view>
|
||||
<button class="popup-phone border-bottom-1px online" open-type="contact" wx:if="{{showKefu}}">在线客服</button> -->
|
||||
<view class="popup-close" bind:tap="closeMakePhone">取消</view>
|
||||
</view>
|
||||
</t-popup>
|
||||
<t-toast id="t-toast" />
|
188
pages/usercenter/index.wxss
Normal file
188
pages/usercenter/index.wxss
Normal file
@ -0,0 +1,188 @@
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
margin-top: 340rpx;
|
||||
position: relative;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
height: 500rpx;
|
||||
}
|
||||
|
||||
.order-group-wrapper {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.order-group-note {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.cell-box {
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.icon-color {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.cell-class {
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.order-content {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
|
||||
.order-item {
|
||||
flex: 1;
|
||||
height: 180rpx;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.order-content-box {
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.order-content-t {
|
||||
margin-top: 10rpx;
|
||||
font-size: 24rpx;
|
||||
color: #333;
|
||||
letter-spacing: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
background: #f5f5f5;
|
||||
margin-bottom: env(safe-area-inset-bottom);
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
}
|
||||
|
||||
.popup-content .popup-title {
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
height: 112rpx;
|
||||
text-align: center;
|
||||
line-height: 112rpx;
|
||||
border-radius: 16rpx 16rpx 0 0;
|
||||
}
|
||||
|
||||
.border-bottom-1px {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.border-bottom-1px::after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
content: '';
|
||||
box-sizing: border-box;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
transform: scale(0.5);
|
||||
transform-origin: left top;
|
||||
border-bottom: 2rpx solid #e5e5e5;
|
||||
}
|
||||
|
||||
.popup-content .popup-phone,
|
||||
.popup-content .popup-close {
|
||||
background: #fff;
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
font-size: 30rpx;
|
||||
font-family: PingFangSC-Regular, PingFang SC;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-content .popup-phone.online {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.popup-content .popup-phone.online::after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
.popup-content .popup-close {
|
||||
color: #333;
|
||||
border: 0;
|
||||
/* margin-top: 16rpx; */
|
||||
}
|
||||
|
||||
.customer-service-img,
|
||||
.customer-service-img>image {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.my-order {
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.footer__version {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
margin-bottom: 4rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
|
||||
.cell-box .order-group__left {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.cell-box .t-cell-padding {
|
||||
padding: 24rpx 18rpx 24rpx 32rpx;
|
||||
}
|
||||
|
||||
.order-history-box {
|
||||
width: 90%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin: 30rpx auto;
|
||||
}
|
||||
|
||||
.order-history-content-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.order-history-content-num {
|
||||
font-size: 35rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.order-history-content-line {
|
||||
/* width: 1rpx; */
|
||||
height: 80rpx;
|
||||
border: 1px solid black;
|
||||
display: flex;
|
||||
align-self: center;
|
||||
}
|
19
pages/usercenter/name-edit/index.js
Normal file
19
pages/usercenter/name-edit/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
Page({
|
||||
data: {
|
||||
nameValue: '',
|
||||
},
|
||||
onLoad(options) {
|
||||
const { name } = options;
|
||||
this.setData({
|
||||
nameValue: name,
|
||||
});
|
||||
},
|
||||
onSubmit() {
|
||||
wx.navigateBack({ backRefresh: true });
|
||||
},
|
||||
clearContent() {
|
||||
this.setData({
|
||||
nameValue: '',
|
||||
});
|
||||
},
|
||||
});
|
8
pages/usercenter/name-edit/index.json
Normal file
8
pages/usercenter/name-edit/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"navigationBarTitleText": "昵称",
|
||||
"usingComponents": {
|
||||
"t-input": "tdesign-miniprogram/input/input",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-button": "tdesign-miniprogram/button/button"
|
||||
}
|
||||
}
|
14
pages/usercenter/name-edit/index.wxml
Normal file
14
pages/usercenter/name-edit/index.wxml
Normal file
@ -0,0 +1,14 @@
|
||||
<view class="name-edit">
|
||||
<t-input
|
||||
borderless
|
||||
model:value="{{nameValue}}"
|
||||
placeholder="请输入文字"
|
||||
label="昵称"
|
||||
clearable
|
||||
bind:clear="clearContent"
|
||||
/>
|
||||
<view class="name-edit__input--desc"> 最多可输入15个字 </view>
|
||||
<view class="name-edit__wrapper">
|
||||
<t-button block shape="round" disabled="{{!nameValue}}" bind:tap="onSubmit">保存</t-button>
|
||||
</view>
|
||||
</view>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user