通过微信开发者工具 商城模板 创建新小程序
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Sidebar 侧边导航
|
||||
|
||||
### 引入
|
||||
|
||||
全局引入,在miniprogram根目录下的`app.json`中配置,局部引入,在需要引入的页面或组件的`index.json`中配置。
|
||||
|
||||
```json
|
||||
// app.json 或 index.json
|
||||
"usingComponents": {
|
||||
"wr-sidebar": "path/to/components/goods-category/wr-sidebar/index",
|
||||
"wr-sidebar-item": "path/to/component/goods-category/wr-sidebar/wr-sidebar-item/index"
|
||||
}
|
||||
```
|
||||
|
||||
## 代码演示
|
||||
|
||||
### 基础用法
|
||||
|
||||
通过在`wr-sidebar`上设置`activeKey`属性来控制选中项
|
||||
|
||||
```html
|
||||
<wr-sidebar active-key="{{ activeKey }}" bind:change="onChange">
|
||||
<wr-sidebar-item title="标签名称" />
|
||||
<wr-sidebar-item title="标签名称" />
|
||||
<wr-sidebar-item title="标签名称" />
|
||||
</wr-sidebar>
|
||||
```
|
||||
|
||||
``` javascript
|
||||
Page({
|
||||
data: {
|
||||
activeKey: 0
|
||||
},
|
||||
|
||||
onChange(event) {
|
||||
wx.showToast({
|
||||
icon: 'none',
|
||||
title: `切换至第${event.detail}项`
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### 提示气泡(暂未实现)
|
||||
|
||||
设置`dot`属性后,会在右上角展示一个小红点。设置`info`属性后,会在右上角展示相应的徽标
|
||||
|
||||
```html
|
||||
<wr-sidebar active-key="{{ activeKey }}">
|
||||
<wr-sidebar-item title="标签名称" dot />
|
||||
<wr-sidebar-item title="标签名称" info="5" />
|
||||
<wr-sidebar-item title="标签名称" info="99+" />
|
||||
</wr-sidebar>
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### Sidebar Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| activeKey | 选中项的索引 | *string \| number* | `0` | - |
|
||||
|
||||
### Sidebar Event
|
||||
|
||||
| 事件名 | 说明 | 参数 |
|
||||
|------|------|------|
|
||||
| change | 切换选项时触发 | 当前选中选项的索引 |
|
||||
|
||||
### Sidebar 外部样式类
|
||||
|
||||
| 类名 | 说明 |
|
||||
|-----------|-----------|
|
||||
| custom-class | 根节点样式类 |
|
||||
|
||||
### SidebarItem Props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
|-----------|-----------|-----------|-------------|-------------|
|
||||
| title | 内容 | *string* | `''` | - |
|
||||
| disabled | 是否禁用 | | *boolean* | `false` | - |
|
||||
| dot | 是否显示右上角小红点 | *boolean* | `false` | - |
|
||||
| info | 提示消息 | *string \| number* | `''` | - |
|
||||
|
||||
### SidebarItem Event
|
||||
|
||||
| 事件名 | 说明 | 参数 |
|
||||
|------|------|------|
|
||||
| click | 点击徽章时触发 | 当前徽章的索引 |
|
||||
|
||||
### SidebarItem 外部样式类
|
||||
|
||||
| 类名 | 说明 |
|
||||
|-----------|-----------|
|
||||
| custom-class | 根节点样式类 |
|
@@ -0,0 +1,51 @@
|
||||
Component({
|
||||
relations: {
|
||||
'../../c-sidebar/index': {
|
||||
type: 'ancestor',
|
||||
linked(target) {
|
||||
this.parent = target;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
properties: {
|
||||
title: String,
|
||||
disabled: Boolean,
|
||||
},
|
||||
|
||||
data: {
|
||||
topRightRadius: false,
|
||||
bottomRightRadius: false,
|
||||
},
|
||||
|
||||
methods: {
|
||||
setActive(selected) {
|
||||
return this.setData({ selected });
|
||||
},
|
||||
onClick() {
|
||||
const { parent } = this;
|
||||
|
||||
if (!parent || this.properties.disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = parent.children.indexOf(this);
|
||||
|
||||
parent.setActive(index).then(() => {
|
||||
this.triggerEvent('click', index);
|
||||
parent.triggerEvent('change', { index });
|
||||
});
|
||||
},
|
||||
setTopRightRadius(val) {
|
||||
return this.setData({
|
||||
topRightRadius: val,
|
||||
});
|
||||
},
|
||||
setBottomRightRadius(val) {
|
||||
return this.setData({
|
||||
bottomRightRadius: val,
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
<view class="c-sidebar-item-container">
|
||||
<view
|
||||
class="c-sidebar-item {{ selected ? 'active' : '' }} {{ disabled ? 'disabled' : '' }} {{topRightRadius ? 'top-right-radius' : ''}} {{bottomRightRadius ? 'bottom-right-radius' : ''}} custom-class"
|
||||
hover-class="c-sidebar-item--hover"
|
||||
hover-stay-time="70"
|
||||
bind:tap="onClick"
|
||||
>
|
||||
<view class="c-sidebar-item__text text-overflow"> {{ title }} </view>
|
||||
</view>
|
||||
</view>
|
@@ -0,0 +1,60 @@
|
||||
.c-sidebar-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
background-color: #f5f5f5;
|
||||
color: #222427;
|
||||
padding: 20rpx 0;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.c-sidebar-item.active {
|
||||
position: relative;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.c-sidebar-item.active::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 6rpx;
|
||||
height: 48rpx;
|
||||
background-color: #fa4126;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(0, -50%);
|
||||
border-radius: 64rpx;
|
||||
}
|
||||
|
||||
.c-sidebar-item__text {
|
||||
width: 136rpx;
|
||||
height: 36rpx;
|
||||
padding: 8rpx 0;
|
||||
line-height: 36rpx;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.c-sidebar-item.active .c-sidebar-item__text {
|
||||
background-color: white;
|
||||
border-radius: 36rpx;
|
||||
color: #fa4126;
|
||||
}
|
||||
|
||||
.text-overflow {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.top-right-radius {
|
||||
border-top-right-radius: 16rpx;
|
||||
}
|
||||
|
||||
.bottom-right-radius {
|
||||
border-bottom-right-radius: 16rpx;
|
||||
}
|
||||
|
||||
.c-sidebar-item-container {
|
||||
background-color: white;
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
Component({
|
||||
relations: {
|
||||
'./c-sidebar-item/index': {
|
||||
type: 'descendant',
|
||||
linked(target) {
|
||||
this.children.push(target);
|
||||
this.setActive(this.properties.activeKey, true);
|
||||
},
|
||||
unlinked(target) {
|
||||
this.children = this.children.filter((item) => item !== target);
|
||||
this.setActive(this.properties.activeKey, true);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
activeKey: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
},
|
||||
observers: {
|
||||
activeKey(newVal) {
|
||||
this.setActive(newVal);
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.children = [];
|
||||
this.currentActive = -1;
|
||||
this.topRightRadiusItemIndexs = [];
|
||||
this.bottomRightRadiusItemIndexs = [];
|
||||
},
|
||||
|
||||
methods: {
|
||||
setActive(activeKey, isChildrenChange) {
|
||||
const {
|
||||
children,
|
||||
currentActive,
|
||||
topRightRadiusItemIndexs: preTopRightRadiusItemIndexs,
|
||||
bottomRightRadiusItemIndexs: preBottomRightRadiusItemIndexs,
|
||||
} = this;
|
||||
|
||||
if (!children.length) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
if (activeKey === currentActive && !isChildrenChange) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
this.currentActive = activeKey;
|
||||
this.topRightRadiusItemIndexs = this.getTopRightRadiusItemIndexs(
|
||||
activeKey,
|
||||
children,
|
||||
);
|
||||
this.bottomRightRadiusItemIndexs = this.getBottomRightRadiusItemIndexs(
|
||||
activeKey,
|
||||
children,
|
||||
);
|
||||
|
||||
const stack = []; // 任务列表,存放调用子组件的setActive后返回的一堆promise
|
||||
|
||||
// 将旧的选中项改为false
|
||||
if (currentActive !== activeKey && children[currentActive]) {
|
||||
stack.push(children[currentActive].setActive(false));
|
||||
}
|
||||
|
||||
// 将新的选中项改为true
|
||||
if (children[activeKey]) {
|
||||
stack.push(children[activeKey].setActive(true));
|
||||
}
|
||||
|
||||
preTopRightRadiusItemIndexs.forEach((item) => {
|
||||
stack.push(children[item].setTopRightRadius(false));
|
||||
});
|
||||
|
||||
preBottomRightRadiusItemIndexs.forEach((item) => {
|
||||
stack.push(children[item].setBottomRightRadius(false));
|
||||
});
|
||||
|
||||
this.topRightRadiusItemIndexs.forEach((item) => {
|
||||
stack.push(children[item].setTopRightRadius(true));
|
||||
});
|
||||
|
||||
this.bottomRightRadiusItemIndexs.forEach((item) => {
|
||||
stack.push(children[item].setBottomRightRadius(true));
|
||||
});
|
||||
|
||||
return Promise.all(stack);
|
||||
},
|
||||
getTopRightRadiusItemIndexs(activeKey, children) {
|
||||
const { length } = children;
|
||||
if (activeKey !== 0 && activeKey < length - 1) return [0, activeKey + 1];
|
||||
if (activeKey !== 0) return [0];
|
||||
if (activeKey < length - 1) return [activeKey + 1];
|
||||
return [];
|
||||
},
|
||||
getBottomRightRadiusItemIndexs(activeKey) {
|
||||
if (activeKey !== 0) return [activeKey - 1];
|
||||
return [];
|
||||
},
|
||||
},
|
||||
});
|
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
||||
|
@@ -0,0 +1,3 @@
|
||||
<scroll-view class="c-sidebar custom-class" scroll-y>
|
||||
<slot />
|
||||
</scroll-view>
|
@@ -0,0 +1,9 @@
|
||||
.c-sidebar {
|
||||
width: 176rpx;
|
||||
height: 100vh;
|
||||
}
|
||||
.c-sidebar::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
Component({
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
tabList: Array,
|
||||
},
|
||||
|
||||
data: {
|
||||
unfolded: false,
|
||||
boardMaxHeight: null,
|
||||
},
|
||||
attached() {
|
||||
wx.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('.c-tabbar-more')
|
||||
.boundingClientRect((rect) => {
|
||||
this.setData({ boardMaxHeight: rect.height });
|
||||
})
|
||||
.exec();
|
||||
},
|
||||
|
||||
methods: {
|
||||
changeFold() {
|
||||
this.setData({
|
||||
unfolded: !this.data.unfolded,
|
||||
});
|
||||
const { unfolded } = this.data;
|
||||
this.triggerEvent('change', { unfolded });
|
||||
},
|
||||
|
||||
onSelect(event) {
|
||||
const activeKey = event.currentTarget.dataset.index;
|
||||
this.triggerEvent('select', activeKey);
|
||||
this.changeFold();
|
||||
},
|
||||
},
|
||||
});
|
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
<view class="c-tabbar-more">
|
||||
<view class="c-tabbar-more__btn" bind:tap="changeFold">
|
||||
<view class="wr {{unfolded ? 'wr-arrow-up':'wr-arrow-down'}}"></view>
|
||||
</view>
|
||||
<view class="t-tabbar-more__boardwrapper" wx:if="{{ unfolded }}">
|
||||
<view class="t-tabbar-more__mask"></view>
|
||||
<scroll-view
|
||||
class="c-tabbar-more__board"
|
||||
style="{{ boardMaxHeight ? 'height:' + boardMaxHeight + 'px;' : '' }}"
|
||||
scroll-y
|
||||
>
|
||||
<view class="c-tabbar-more__boardinner">
|
||||
<view
|
||||
class="c-tabbar-more__item text-overflow"
|
||||
wx:for="{{ tabList }}"
|
||||
wx:key="index"
|
||||
data-index="{{ index }}"
|
||||
bind:tap="onSelect"
|
||||
>
|
||||
{{ item.name }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
@@ -0,0 +1,63 @@
|
||||
.c-tabbar-more {
|
||||
width: 100%;
|
||||
height: calc(100% - var(--tabbar-height, 100rpx));
|
||||
position: absolute;
|
||||
top: var(--tabbar-height, 100rpx);
|
||||
}
|
||||
.c-tabbar-more__btn {
|
||||
position: absolute;
|
||||
top: calc(0rpx - var(--tabbar-height, 100rpx));
|
||||
right: 0;
|
||||
width: 80rpx;
|
||||
height: var(--tabbar-height, 100rpx);
|
||||
line-height: var(--tabbar-height, 100rpx);
|
||||
background-color: var(--tabbar-background-color, white);
|
||||
box-shadow: -20rpx 0 20rpx -10rpx var(--tabbar-background-color, white);
|
||||
text-align: center;
|
||||
}
|
||||
.c-tabbar-more__btn .market {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
.t-tabbar-more__boardwrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.t-tabbar-more__mask {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.c-tabbar-more__board {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
.c-tabbar-more__boardinner {
|
||||
padding: 20rpx 0 20rpx 20rpx;
|
||||
background-color: var(--tabbar-background-color, white);
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
.c-tabbar-more__item {
|
||||
margin: 0 20rpx 20rpx 0;
|
||||
flex: 0 0 calc((100% - 60rpx) / 3);
|
||||
box-sizing: border-box;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 30rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
text-align: center;
|
||||
font-size: 22rpx;
|
||||
color: #5d5d5d;
|
||||
background-color: #eee;
|
||||
}
|
||||
.text-overflow {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
Component({
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
activeKey: {
|
||||
type: Number,
|
||||
value: 0,
|
||||
},
|
||||
tabList: {
|
||||
type: Array,
|
||||
value: [],
|
||||
},
|
||||
showMore: Boolean, // 是否需要下拉功能
|
||||
},
|
||||
observers: {
|
||||
activeKey(newVal) {
|
||||
if (this.properties.tabList && newVal) {
|
||||
this.setActive(newVal).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
data: {
|
||||
currentActive: -1,
|
||||
},
|
||||
attached() {
|
||||
this.setActive(this.properties.activeKey).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
setActive(activeKey) {
|
||||
if (
|
||||
!this.properties.tabList[activeKey] ||
|
||||
this.properties.tabList[activeKey].disabled
|
||||
) {
|
||||
return Promise.reject('数据异常或不可操作');
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
this.setData(
|
||||
{
|
||||
currentActive: activeKey,
|
||||
},
|
||||
() => resolve(),
|
||||
);
|
||||
});
|
||||
},
|
||||
onClick(event) {
|
||||
let activeKey;
|
||||
if (event.type === 'select') {
|
||||
activeKey = event.detail;
|
||||
} else {
|
||||
activeKey = event.currentTarget.dataset.index;
|
||||
}
|
||||
this.setActive(activeKey)
|
||||
.then(() => {
|
||||
const { currentActive } = this.data;
|
||||
this.triggerEvent('change', { index: currentActive });
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"c-tabbar-more": "./c-tabbar-more/index"
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
<view class="c-tabbar custom-class">
|
||||
<scroll-view
|
||||
wx:if="{{ tabList.length > 0 }}"
|
||||
class="c-tabbar__scroll"
|
||||
scroll-x="true"
|
||||
scroll-into-view="{{ 'id-' + currentActive }}"
|
||||
>
|
||||
<view
|
||||
class="c-tabbar__inner {{showMore && tabList.length > 4 ? 'c-tabbar__inner_more' : ''}}"
|
||||
>
|
||||
<view
|
||||
wx:for="{{ tabList }}"
|
||||
wx:key="index"
|
||||
id="{{ 'id-' + index }}"
|
||||
class="c-tabbar-item {{ currentActive === index ? 'active' : '' }} {{ item.disabled ? 'disabled' : '' }}"
|
||||
bind:tap="onClick"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
<view class="c-tabbar-item__text"> {{ item.name }} </view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<c-tabbar-more
|
||||
wx:if="{{ showMore && tabList.length > 4 }}"
|
||||
tabList="{{tabList}}"
|
||||
bindselect="onClick"
|
||||
/>
|
||||
<slot />
|
||||
</view>
|
@@ -0,0 +1,53 @@
|
||||
.c-tabbar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
--tabbar-height: 100rpx;
|
||||
--tabbar-fontsize: 28rpx;
|
||||
--tabbar-background-color: white;
|
||||
}
|
||||
.c-tabbar__inner {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
.c-tabbar__scroll {
|
||||
position: relative;
|
||||
}
|
||||
.c-tabbar__scroll::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: -1px;
|
||||
height: 1px;
|
||||
background-color: #eee;
|
||||
z-index: 1;
|
||||
}
|
||||
.c-tabbar__inner.c-tabbar__inner_more::after {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
flex: none;
|
||||
}
|
||||
.c-tabbar-item {
|
||||
flex: none;
|
||||
height: 100rpx;
|
||||
color: #282828;
|
||||
font-size: 28rpx;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
.c-tabbar-item.active:not(.disabled) {
|
||||
color: #0071ce;
|
||||
position: relative;
|
||||
}
|
||||
.c-tabbar-item.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
.c-tabbar-item__text {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
Component({
|
||||
externalClasses: ['custom-class'],
|
||||
|
||||
properties: {
|
||||
category: {
|
||||
type: Array,
|
||||
},
|
||||
initActive: {
|
||||
type: Array,
|
||||
value: [],
|
||||
observer(newVal, oldVal) {
|
||||
if (newVal[0] !== oldVal[0]) {
|
||||
this.setActiveKey(newVal[0], 0);
|
||||
}
|
||||
},
|
||||
},
|
||||
isSlotRight: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
value: 3,
|
||||
},
|
||||
},
|
||||
data: {
|
||||
activeKey: 0,
|
||||
subActiveKey: 0,
|
||||
},
|
||||
attached() {
|
||||
if (this.properties.initActive && this.properties.initActive.length > 0) {
|
||||
this.setData({
|
||||
activeKey: this.properties.initActive[0],
|
||||
subActiveKey: this.properties.initActive[1] || 0,
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onParentChange(event) {
|
||||
this.setActiveKey(event.detail.index, 0).then(() => {
|
||||
this.triggerEvent('change', [
|
||||
this.data.activeKey,
|
||||
this.data.subActiveKey,
|
||||
]);
|
||||
});
|
||||
},
|
||||
onChildChange(event) {
|
||||
this.setActiveKey(this.data.activeKey, event.detail.index).then(() => {
|
||||
this.triggerEvent('change', [
|
||||
this.data.activeKey,
|
||||
this.data.subActiveKey,
|
||||
]);
|
||||
});
|
||||
},
|
||||
changCategory(event) {
|
||||
const { item } = event.currentTarget.dataset;
|
||||
this.triggerEvent('changeCategory', {
|
||||
item,
|
||||
});
|
||||
},
|
||||
setActiveKey(key, subKey) {
|
||||
return new Promise((resolve) => {
|
||||
this.setData(
|
||||
{
|
||||
activeKey: key,
|
||||
subActiveKey: subKey,
|
||||
},
|
||||
() => {
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"c-tabbar": "./components/c-tabbar/index",
|
||||
"c-sidebar": "./components/c-sidebar/index",
|
||||
"c-sidebar-item": "./components/c-sidebar/c-sidebar-item/index",
|
||||
"t-image": "/components/webp-image/index"
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
<view class="goods-category custom-class">
|
||||
<c-sidebar custom-class="custom-sidebar" bindchange="onParentChange" activeKey="{{activeKey}}">
|
||||
<c-sidebar-item
|
||||
wx:for="{{ category }}"
|
||||
wx:key="index"
|
||||
title="{{ item.name }}"
|
||||
disabled="{{ item.disabled }}"
|
||||
/>
|
||||
</c-sidebar>
|
||||
<view class="goods-category__right">
|
||||
<c-tabbar
|
||||
wx:if="{{isSlotRight}}"
|
||||
activeKey="{{subActiveKey}}"
|
||||
bindchange="onChildChange"
|
||||
showMore
|
||||
>
|
||||
<slot/>
|
||||
</c-tabbar>
|
||||
<view wx:if="{{!isSlotRight}}" class="goods-category-normal">
|
||||
<view class="goods-category-normal-item" wx:if="{{category[activeKey].children && category[activeKey].children.length > 0}}">
|
||||
<block wx:for="{{category[activeKey].children}}" wx:key="index" wx:if="{{level === 3 && item.children && item.children.length > 0}}">
|
||||
<view class="flex goods-category-normal-item-title">
|
||||
{{item.name}}
|
||||
</view>
|
||||
<view class="goods-category-normal-item-container">
|
||||
<view
|
||||
class="goods-category-normal-item-container-item"
|
||||
wx:for="{{item.children}}"
|
||||
wx:for-index="subIndex"
|
||||
wx:key="subIndex"
|
||||
wx:for-item="subItem"
|
||||
bindtap="changCategory"
|
||||
data-item="{{subItem}}"
|
||||
>
|
||||
<t-image src="{{subItem.thumbnail}}" t-class="image" />
|
||||
<view class="flex goods-category-normal-item-container-item-title">
|
||||
{{subItem.name}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="goods-category-normal-item-second-container" wx:if="{{level === 2}}">
|
||||
<block wx:for="{{category[activeKey].children}}" wx:key="index">
|
||||
<view
|
||||
class="goods-category-normal-item-second-container-item"
|
||||
wx:for-key="index"
|
||||
bindtap="changCategory"
|
||||
data-item="{{item}}"
|
||||
>
|
||||
<t-image src="{{item.thumbnail}}" t-class="image" />
|
||||
<view class="flex goods-category-normal-item-container-item-title">
|
||||
{{item.name}}
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
@@ -0,0 +1,102 @@
|
||||
.goods-category {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.custom-sidebar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.goods-category__right {
|
||||
height: 100%;
|
||||
flex: auto;
|
||||
width: 0;
|
||||
position: relative;
|
||||
overflow: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.goods-category-normal {
|
||||
margin: 28rpx 34rpx 0rpx 32rpx;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-container {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
padding-top: 28rpx;
|
||||
margin-top: -24rpx;
|
||||
margin-bottom: 30rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-container-item {
|
||||
height: 196rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-top: 24rpx;
|
||||
width: 33.3%;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-container-item .image {
|
||||
width: 144rpx;
|
||||
height: 144rpx;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-container-item-title {
|
||||
justify-content: center;
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.goods-category .custom-sidebar {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.custom-sidebar {
|
||||
width: 180rpx;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.custom-sidebar::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-second-container {
|
||||
background-color: #fff;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 8rpx;
|
||||
margin-bottom: 30rpx;
|
||||
display: grid;
|
||||
grid-template-columns: 33.33% 33.33% 33.33%;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-second-container-item {
|
||||
height: 200rpx;
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-second-container-item .image {
|
||||
width: 144rpx;
|
||||
height: 144rpx;
|
||||
}
|
||||
|
||||
.goods-category-normal-item-second-container-item-title {
|
||||
justify-content: center;
|
||||
font-size: 24rpx;
|
||||
color: #222427;
|
||||
}
|
28
mini-program/pages/goods/category/index.js
Normal file
28
mini-program/pages/goods/category/index.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { getCategoryList } from '../../../services/good/fetchCategoryList';
|
||||
Page({
|
||||
data: {
|
||||
list: [],
|
||||
},
|
||||
async init() {
|
||||
try {
|
||||
const result = await getCategoryList();
|
||||
this.setData({
|
||||
list: result,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('err:', error);
|
||||
}
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.getTabBar().init();
|
||||
},
|
||||
onChange() {
|
||||
wx.navigateTo({
|
||||
url: '/pages/goods/list/index',
|
||||
});
|
||||
},
|
||||
onLoad() {
|
||||
this.init(true);
|
||||
},
|
||||
});
|
6
mini-program/pages/goods/category/index.json
Normal file
6
mini-program/pages/goods/category/index.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"navigationBarTitleText": "分类",
|
||||
"usingComponents": {
|
||||
"goods-category": "./components/goods-category/index"
|
||||
}
|
||||
}
|
8
mini-program/pages/goods/category/index.wxml
Normal file
8
mini-program/pages/goods/category/index.wxml
Normal file
@@ -0,0 +1,8 @@
|
||||
<view class="wrap">
|
||||
<goods-category
|
||||
level="{{3}}"
|
||||
custom-class="goods-category-class"
|
||||
category="{{list}}"
|
||||
bind:changeCategory="onChange"
|
||||
/>
|
||||
</view>
|
23
mini-program/pages/goods/category/index.wxss
Normal file
23
mini-program/pages/goods/category/index.wxss
Normal file
@@ -0,0 +1,23 @@
|
||||
.tabbar-position {
|
||||
position: fixed !important;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
.goods-category-class {
|
||||
background-color: #f6f6f6 !important;
|
||||
height: 100%;
|
||||
}
|
||||
.goods-category-class .goods-category-normal-item-container-item {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
page {
|
||||
min-height: none;
|
||||
padding-bottom: 0;
|
||||
}
|
Reference in New Issue
Block a user