feat(components): 新增分页、选择器和标签栏组件并优化插件页面
- 添加 pagination-plugin 组件,包含完整的分页功能和页面跳转选择 - 添加 select-plugin 组件,支持单选和多选模式的选择弹窗 - 添加 tab-bar-plugin 组件,提供底部导航栏功能 - 在 page-plugin 中集成 t-loading 组件替换原有的加载逻辑 - 移除页面中的登录状态监听逻辑和相关订阅功能 - 修改页面样式传递方式,将 style 属性改为 customStyle - 更新组件依赖配置文件,添加新的组件引用
This commit is contained in:
@@ -3,7 +3,8 @@
|
|||||||
"usingComponents": {
|
"usingComponents": {
|
||||||
"t-button": "tdesign-miniprogram/button/button",
|
"t-button": "tdesign-miniprogram/button/button",
|
||||||
"t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
|
"t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
|
||||||
"t-divider": "tdesign-miniprogram/divider/divider",
|
"t-link": "tdesign-miniprogram/link/link",
|
||||||
"t-link": "tdesign-miniprogram/link/link"
|
"t-loading": "tdesign-miniprogram/loading/loading",
|
||||||
|
"no-auth-plugin": "/pages/components/no-auth-plugin/no-auth-plugin"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { base, defaultAvatarUrl } from "@/utils/config";
|
import { base, defaultAvatarUrl } from "@/utils/config";
|
||||||
import { Subscribe } from "@/utils/subscribe";
|
import { Subscribe } from "@/utils/subscribe";
|
||||||
import { getCurrentPageRoute, getStorage, setStorage } from "@/utils/util";
|
import { setStorage } from "@/utils/util";
|
||||||
// import { IStorage } from "@/utils/storage";
|
// import { IStorage } from "@/utils/storage";
|
||||||
|
|
||||||
// const app = getApp();
|
// const app = getApp();
|
||||||
@@ -12,22 +12,22 @@ Component({
|
|||||||
isLogin: Boolean,
|
isLogin: Boolean,
|
||||||
loading: Boolean,
|
loading: Boolean,
|
||||||
isAuth: null,
|
isAuth: null,
|
||||||
style: null,
|
customStyle: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
attached() {
|
// attached() {
|
||||||
this.setData({ isLogin: getStorage("isLogin") == 1 });
|
// this.setData({ isLogin: getStorage("isLogin") == 1 });
|
||||||
|
|
||||||
console.log("attached");
|
// console.log("attached");
|
||||||
Subscribe.on("isLogin", getCurrentPageRoute(), () => {
|
// Subscribe.on("isLogin", getCurrentPageRoute(), () => {
|
||||||
this.setData({ isLogin: getStorage("isLogin") == 1 });
|
// this.setData({ isLogin: getStorage("isLogin") == 1 });
|
||||||
console.log("监听到 isLogin 变化:");
|
// console.log("监听到 isLogin 变化:");
|
||||||
});
|
// });
|
||||||
},
|
// },
|
||||||
detached() {
|
// detached() {
|
||||||
console.log("detached");
|
// console.log("detached");
|
||||||
Subscribe.off("isLogin", getCurrentPageRoute());
|
// Subscribe.off("isLogin", getCurrentPageRoute());
|
||||||
},
|
// },
|
||||||
|
|
||||||
data: {
|
data: {
|
||||||
avatarUrl: defaultAvatarUrl,
|
avatarUrl: defaultAvatarUrl,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<block wx:if="{{isLogin}}">
|
<block wx:if="{{isLogin}}">
|
||||||
<view wx:if="{{!isAuth}}" style="padding: 12px;padding-bottom: env(safe-area-inset-bottom);{{style ||''}}">
|
<view wx:if="{{isAuth}}" style="padding: 12px;padding-bottom: env(safe-area-inset-bottom);{{customStyle ||''}}">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</view>
|
</view>
|
||||||
<no-auth-plugin wx:else />
|
<no-auth-plugin wx:else />
|
||||||
</block>
|
</block>
|
||||||
<block wx:else>
|
<block wx:else>
|
||||||
<!-- <loading_plugin wx:if="{{loading}}" /> -->
|
<t-loading wx:if="{{loading}}" theme="spinner" fullscreen text="加载中..." layout="vertical" />
|
||||||
<view style="padding: 0 16px;height: 100vh;justify-content: center;display: flex;flex-direction: column;">
|
<view wx:else style="padding: 0 16px;height: 100vh;justify-content: center;display: flex;flex-direction: column;">
|
||||||
<view style="display: flex;justify-content: center;">
|
<view style="display: flex;justify-content: center;">
|
||||||
<view style="width: 80px;height: 80px;overflow: hidden;border-radius: 80px;">
|
<view style="width: 80px;height: 80px;overflow: hidden;border-radius: 80px;">
|
||||||
<image style="width: 100%;height: 100%;object-fit: cover;" src="{{avatarUrl}}" mode="cover"></image>
|
<image style="width: 100%;height: 100%;object-fit: cover;" src="{{avatarUrl}}" mode="cover" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view style="padding: 20px 0">
|
<view style="padding: 20px 0">
|
||||||
@@ -27,11 +27,12 @@
|
|||||||
<t-checkbox borderless style="padding: 0;margin: 1em 0;" value="{{isAgree}}" bind:change="changeAgreementCheck">
|
<t-checkbox borderless style="padding: 0;margin: 1em 0;" value="{{isAgree}}" bind:change="changeAgreementCheck">
|
||||||
我已阅读并同意
|
我已阅读并同意
|
||||||
</t-checkbox>
|
</t-checkbox>
|
||||||
<!-- <t-divider /> -->
|
|
||||||
<t-link theme="primary" bindtap="navAgreement" data-type="user" style="margin-bottom: 8px;">
|
<t-link theme="primary" bindtap="navAgreement" data-type="user" style="margin-bottom: 8px;">
|
||||||
《{{appletName}}平台用户服务协议》</t-link>
|
《{{appletName}}平台用户服务协议》
|
||||||
|
</t-link>
|
||||||
<t-link theme="primary" bindtap="navAgreement" data-type="privacy" style="margin-bottom: 8px;">
|
<t-link theme="primary" bindtap="navAgreement" data-type="privacy" style="margin-bottom: 8px;">
|
||||||
《{{appletName}}隐私权政策》</t-link>
|
《{{appletName}}隐私权政策》
|
||||||
|
</t-link>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"t-picker": "tdesign-miniprogram/picker/picker",
|
||||||
|
"t-picker-item": "tdesign-miniprogram/picker-item/picker-item"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { getDataSet, toNumber } from "@/utils/util";
|
||||||
|
|
||||||
|
Component({
|
||||||
|
options: { multipleSlots: true },
|
||||||
|
/**
|
||||||
|
* 组件的属性列表
|
||||||
|
*/
|
||||||
|
properties: {
|
||||||
|
curr_page: {
|
||||||
|
type: Number,
|
||||||
|
value: 1,
|
||||||
|
observer() {
|
||||||
|
this.page();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
value: 0,
|
||||||
|
observer() {
|
||||||
|
this.page();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
page_count: {
|
||||||
|
type: Number,
|
||||||
|
value: 20,
|
||||||
|
observer() {
|
||||||
|
this.page();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
pages: [] as number[],
|
||||||
|
totalPage: 0,
|
||||||
|
open: false,
|
||||||
|
pickerPages: [] as any[],
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件的方法列表
|
||||||
|
*/
|
||||||
|
methods: {
|
||||||
|
page() {
|
||||||
|
const totalPage = Math.ceil(
|
||||||
|
toNumber(this.data.total) / toNumber(this.data.page_count)
|
||||||
|
);
|
||||||
|
const showPageNum = 3;
|
||||||
|
|
||||||
|
// 计算显示的页码范围
|
||||||
|
let startPage = Math.max(
|
||||||
|
1,
|
||||||
|
toNumber(this.data.curr_page) - Math.floor(showPageNum / 2)
|
||||||
|
);
|
||||||
|
let endPage = Math.min(totalPage, startPage + showPageNum - 1);
|
||||||
|
|
||||||
|
// 调整起始页码,确保显示的页码数量不超过最大值
|
||||||
|
if (endPage - startPage + 1 < showPageNum) {
|
||||||
|
startPage = Math.max(1, endPage - showPageNum + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成页码数组
|
||||||
|
const pages = [];
|
||||||
|
for (let i = startPage; i <= endPage; i++) {
|
||||||
|
pages.push(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setData({ pages, totalPage });
|
||||||
|
},
|
||||||
|
pageChange(e: any) {
|
||||||
|
let curr_page = getDataSet(e).page;
|
||||||
|
// if (curr_page == this.data.curr_page) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
if (curr_page == "prev") {
|
||||||
|
curr_page = this.data.curr_page - 1;
|
||||||
|
} else if (curr_page == "next") {
|
||||||
|
curr_page = this.data.curr_page + 1;
|
||||||
|
}
|
||||||
|
this.triggerEvent("change", { curr_page });
|
||||||
|
},
|
||||||
|
pageSelect() {
|
||||||
|
this.setData({
|
||||||
|
open: true,
|
||||||
|
pickerPages: Array.from({ length: this.data.totalPage }, (_, i) => ({
|
||||||
|
value: i + 1,
|
||||||
|
label: `第 ${i + 1} 页`,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onConfirm(e: any) {
|
||||||
|
const curr_page = e.detail.value[0];
|
||||||
|
// if (curr_page == this.data.curr_page) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
this.triggerEvent("change", { curr_page: curr_page });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<view class="box">
|
||||||
|
<view>共{{total}}条</view>
|
||||||
|
<t-button
|
||||||
|
size="small"
|
||||||
|
disabled="{{curr_page == 1}}"
|
||||||
|
bindtap="pageChange"
|
||||||
|
data-page="prev"
|
||||||
|
icon="chevron-left"
|
||||||
|
style="padding-left: 8px;padding-right: 8px"
|
||||||
|
/>
|
||||||
|
<block wx:for="{{pages}}" wx:key="index">
|
||||||
|
<t-button
|
||||||
|
size="small"
|
||||||
|
theme="{{curr_page == item ? 'primary': ''}}"
|
||||||
|
variant="{{curr_page == item ? 'outline': ''}}"
|
||||||
|
bindtap="pageChange"
|
||||||
|
data-page="{{item}}"
|
||||||
|
>{{item}}
|
||||||
|
</t-button>
|
||||||
|
</block>
|
||||||
|
<t-button
|
||||||
|
size="small"
|
||||||
|
disabled="{{curr_page == totalPage}}"
|
||||||
|
bindtap="pageChange"
|
||||||
|
data-page="next"
|
||||||
|
icon="chevron-right"
|
||||||
|
style="padding-left: 8px;padding-right: 8px"
|
||||||
|
/>
|
||||||
|
<t-button size="small" bindtap="pageSelect" style="padding-left: 8px;padding-right: 8px">跳转
|
||||||
|
</t-button>
|
||||||
|
<t-picker
|
||||||
|
title="选择页码"
|
||||||
|
visible="{{open}}"
|
||||||
|
value="{{[curr_page]}}"
|
||||||
|
cancelBtn="取消"
|
||||||
|
confirmBtn="确认"
|
||||||
|
bind:confirm="onConfirm"
|
||||||
|
>
|
||||||
|
<t-picker-item options="{{pickerPages}}" />
|
||||||
|
</t-picker>
|
||||||
|
</view>
|
||||||
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
column-gap: 8px;
|
||||||
|
row-gap: 8px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"popup-plugin": "/pages/components/popup-plugin/popup-plugin",
|
||||||
|
"t-radio-group": "tdesign-miniprogram/radio-group/radio-group",
|
||||||
|
"t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
|
||||||
|
"t-checkbox-group": "tdesign-miniprogram/checkbox-group/checkbox-group"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
64
miniprogram/pages/components/select-plugin/select-plugin.ts
Normal file
64
miniprogram/pages/components/select-plugin/select-plugin.ts
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
Component({
|
||||||
|
options: { multipleSlots: true },
|
||||||
|
/**
|
||||||
|
* 组件的属性列表
|
||||||
|
*/
|
||||||
|
properties: {
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
value: "single",
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
value: "请选择",
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: null,
|
||||||
|
value: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
observers: {
|
||||||
|
"value,mode": function (v, m) {
|
||||||
|
if (m == "multiple") {
|
||||||
|
this.setData({ val: Array.isArray(v) ? [...v] : [] });
|
||||||
|
} else {
|
||||||
|
this.setData({ val: v });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
visible: false,
|
||||||
|
val: [] as any[] | string | number,
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件的方法列表
|
||||||
|
*/
|
||||||
|
methods: {
|
||||||
|
click() {
|
||||||
|
this.setData({ visible: true });
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.setData({ visible: false });
|
||||||
|
},
|
||||||
|
radioChange(e: any) {
|
||||||
|
this.setData({ val: e.detail.value });
|
||||||
|
},
|
||||||
|
checkboxChange(e: any) {
|
||||||
|
this.setData({ val: e.detail.value });
|
||||||
|
},
|
||||||
|
ok() {
|
||||||
|
this.setData({ visible: false });
|
||||||
|
this.triggerEvent("change", { value: this.data.val });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<view style="display: contents" bindtap="click">
|
||||||
|
<slot/>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<popup-plugin visible="{{visible}}" bind:close="close" title="{{title}}">
|
||||||
|
|
||||||
|
<view>
|
||||||
|
<t-radio-group
|
||||||
|
wx:if="{{mode == 'single'}}"
|
||||||
|
bind:change="radioChange"
|
||||||
|
allow-uncheck
|
||||||
|
value="{{val}}"
|
||||||
|
options="{{options}}"
|
||||||
|
/>
|
||||||
|
<t-checkbox-group wx:else value="{{val}}" bind:change="checkboxChange">
|
||||||
|
<t-checkbox
|
||||||
|
wx:for="{{options}}"
|
||||||
|
icon="rectangle"
|
||||||
|
wx:key="index"
|
||||||
|
value="{{item.value}}"
|
||||||
|
>{{item.label}}
|
||||||
|
</t-checkbox>
|
||||||
|
</t-checkbox-group>
|
||||||
|
</view>
|
||||||
|
<view class="footer">
|
||||||
|
<t-button size="small" theme="primary" bindtap="ok">确定</t-button>
|
||||||
|
</view>
|
||||||
|
</popup-plugin>
|
||||||
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
background: #fff;
|
||||||
|
z-index: 1;
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
Component({
|
||||||
|
options: { multipleSlots: true },
|
||||||
|
/**
|
||||||
|
* 组件的属性列表
|
||||||
|
*/
|
||||||
|
properties: {
|
||||||
|
active: {
|
||||||
|
type: String,
|
||||||
|
value: "home",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件的初始数据
|
||||||
|
*/
|
||||||
|
data: {
|
||||||
|
list: [
|
||||||
|
{ value: "home", label: "首页", icon: "home" },
|
||||||
|
{ value: "scan", label: "扫码", icon: "scan" },
|
||||||
|
{ value: "my", label: "我的", icon: "user" },
|
||||||
|
],
|
||||||
|
pages: {
|
||||||
|
index: "/pages/index/index",
|
||||||
|
scan: "/pages/processEntry/processEntry",
|
||||||
|
my: "/pages/my/my",
|
||||||
|
} as Record<string, string>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件的方法列表
|
||||||
|
*/
|
||||||
|
methods: {
|
||||||
|
onChange(e: any) {
|
||||||
|
if (e.detail.value == this.data.active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wx.reLaunch({
|
||||||
|
url: this.data.pages[e.detail.value],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<t-tab-bar
|
||||||
|
t-class="t-tab-bar"
|
||||||
|
value="{{active}}"
|
||||||
|
bindchange="onChange"
|
||||||
|
theme="normal"
|
||||||
|
fixed="{{true}}"
|
||||||
|
split="{{false}}"
|
||||||
|
>
|
||||||
|
<t-tab-bar-item wx:for="{{list}}" wx:key="value" value="{{item.value}}" icon="{{item.icon}}">
|
||||||
|
{{item.label}}
|
||||||
|
</t-tab-bar-item>
|
||||||
|
</t-tab-bar>
|
||||||
|
|
||||||
Reference in New Issue
Block a user