Compare commits
12
Commits
dev-tamako
...
dev-yzy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49851d4a57 | ||
|
|
df4229bf2f | ||
|
|
43d87b40f7 | ||
|
|
660f6921de | ||
|
|
86101e01d1 | ||
|
|
1f2a2ad6bd | ||
|
|
b91a9271a7 | ||
|
|
ec635b9ae6 | ||
|
|
6f96a69900 | ||
|
|
58d8d74158 | ||
|
|
96b3414d22 | ||
|
|
cd8ca7dcc4 |
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { IAppAPIParam } from "./core/Api";
|
||||
import { IAppAPIParam, IAnyData } from "./core/Api";
|
||||
import { IAppStorageParam, Storage, IStorageData } from "./core/Storage";
|
||||
import { Logger, LevelLogLabel, LifeCycleLogLabel } from "./core/Logger";
|
||||
|
||||
|
||||
App<IAppAPIParam & IAppStorageParam>({
|
||||
App<IAppAPIParam & IAppStorageParam & IAnyData>({
|
||||
|
||||
/**
|
||||
* API 模块需要的全局数据
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
|
||||
/**
|
||||
* 数据层键值设置
|
||||
*/
|
||||
interface IDataParamSettingItem {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
type: any;
|
||||
|
||||
/**
|
||||
* 键值是否可以获取
|
||||
*/
|
||||
isGet: boolean;
|
||||
|
||||
/**
|
||||
* 键值是否可以设置
|
||||
*/
|
||||
isSet: boolean;
|
||||
|
||||
/**
|
||||
* 是否仅为异步获取
|
||||
*/
|
||||
isGetAsync?: boolean;
|
||||
|
||||
/**
|
||||
* 是否仅为异步设置
|
||||
*/
|
||||
isSetAsync?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据层参数类型
|
||||
*/
|
||||
interface IDataParamSetting {
|
||||
[x: string]: IDataParamSettingItem
|
||||
}
|
||||
|
||||
type IGet<T> = () => T;
|
||||
type IGetAsync<T> = () => Promise<T>;
|
||||
type ISet<T> = (data: T) => INone;
|
||||
type ISetAsync<T> = (data: T) => Promise<INone>;
|
||||
|
||||
type INone = undefined | void | unknown;
|
||||
|
||||
/**
|
||||
* 注册表结构
|
||||
*/
|
||||
type IRegistryItem<S extends IDataParamSettingItem> = {
|
||||
|
||||
/**
|
||||
* 获取方法
|
||||
*/
|
||||
get: S["isGetAsync"] extends true ? INone : S["isGet"] extends true ? IGet<S["type"]> : INone;
|
||||
|
||||
/**
|
||||
* 异步获取方法
|
||||
*/
|
||||
getAsync: S["isGet"] extends true ? IGetAsync<S["type"]> : INone;
|
||||
|
||||
/**
|
||||
* 设置方法
|
||||
*/
|
||||
set: S["isSetAsync"] extends true ? INone : S["isSet"] extends true ? ISet<S["type"]> : INone;
|
||||
|
||||
/**
|
||||
* 异步设置方法
|
||||
*/
|
||||
setAsync: S["isSet"] extends true ? ISetAsync<S["type"]> : INone;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册表参数类型
|
||||
*/
|
||||
type IRegistry<D extends IDataParamSetting> = {
|
||||
[P in keyof D]: IRegistryItem<D[P]>;
|
||||
}
|
||||
|
||||
type IRegistryPartial<D extends IDataParamSetting> = {
|
||||
[P in keyof D]?: Partial<IRegistryItem<D[P]>>;
|
||||
}
|
||||
|
||||
|
||||
type IAutoSelect<IF extends boolean, A, B> = IF extends true ? A : B;
|
||||
|
||||
/**
|
||||
* Core 数据层架构
|
||||
*
|
||||
* 使用示例:
|
||||
* ```typescript
|
||||
* class TestData extends Data<{
|
||||
* test: {
|
||||
* type: number,
|
||||
* isGet: true,
|
||||
* isSet: true,
|
||||
* isGetAsync: true
|
||||
* }
|
||||
* }> {
|
||||
* public onLoad() {
|
||||
* let dataObject = {key: 1}
|
||||
* this.getter("test", () => 1);
|
||||
* this.registerKeyFromObject("test", "key", dataObject);
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class Data<D extends IDataParamSetting> {
|
||||
|
||||
/**
|
||||
* getter setter 注册表
|
||||
*/
|
||||
private registryList: IRegistryPartial<D> = {};
|
||||
|
||||
/**
|
||||
* 加载函数
|
||||
*/
|
||||
public onLoad(): any {};
|
||||
|
||||
/**
|
||||
* 注册一个 Setter 到键值上
|
||||
* @param key 注册的键值
|
||||
* @param setter 注册的 Setter
|
||||
* @param isAsync 是否为异步函数
|
||||
*/
|
||||
protected setter<KEY extends keyof D> (key: KEY, setter: IRegistryItem<D[KEY]>["set"]): this
|
||||
protected setter<KEY extends keyof D> (key: KEY, setter: IRegistryItem<D[KEY]>["setAsync"], isAsync: true): this
|
||||
protected setter<
|
||||
KEY extends keyof D,
|
||||
ASYNC extends boolean
|
||||
> (
|
||||
key: KEY,
|
||||
setter: IAutoSelect<ASYNC, IRegistryItem<D[KEY]>["setAsync"], IRegistryItem<D[KEY]>["set"]>,
|
||||
isAsync?: ASYNC
|
||||
): this {
|
||||
|
||||
// 如果此键值不存在,新建
|
||||
if (!this.registryList[key]) this.registryList[key] = {};
|
||||
|
||||
// 设置异步 setter
|
||||
if (isAsync) this.registryList[key]!.setAsync = setter as IRegistryItem<D[KEY]>["setAsync"];
|
||||
|
||||
// 设置同步 setter
|
||||
else this.registryList[key]!.set = setter as IRegistryItem<D[KEY]>["set"];
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个 Getter 到键值上
|
||||
* @param key 注册的键值
|
||||
* @param getter 注册的 Getter
|
||||
* @param isAsync 是否为异步函数
|
||||
*/
|
||||
protected getter<KEY extends keyof D> (key: KEY, getter: IRegistryItem<D[KEY]>["get"]): this
|
||||
protected getter<KEY extends keyof D> (key: KEY, getter: IRegistryItem<D[KEY]>["getAsync"], isAsync: true): this
|
||||
protected getter<
|
||||
KEY extends keyof D,
|
||||
ASYNC extends boolean
|
||||
> (
|
||||
key: KEY,
|
||||
getter: IAutoSelect<ASYNC, IRegistryItem<D[KEY]>["getAsync"], IRegistryItem<D[KEY]>["get"]>,
|
||||
isAsync?: ASYNC
|
||||
): this {
|
||||
|
||||
// 如果此键值不存在,新建
|
||||
if (!this.registryList[key]) this.registryList[key] = {};
|
||||
|
||||
// 设置异步 getter
|
||||
if (isAsync) this.registryList[key]!.getAsync = getter as IRegistryItem<D[KEY]>["getAsync"];
|
||||
|
||||
// 设置同步 getter
|
||||
else this.registryList[key]!.get = getter as IRegistryItem<D[KEY]>["get"];
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象的键值关联到 Data 层中
|
||||
* @param key Data 层键值
|
||||
* @param keyFromObject 对象源键值
|
||||
* @param object 关联对象
|
||||
*/
|
||||
protected registerKeyFromObject<
|
||||
KEY extends keyof D,
|
||||
F extends keyof O,
|
||||
O extends {[K in F]: D[KEY]["type"]}
|
||||
> (key: KEY, keyFromObject: F, object: O) {
|
||||
|
||||
// 注册同步获取
|
||||
this.getter(key, () => {
|
||||
return object[keyFromObject]
|
||||
});
|
||||
|
||||
// 注册同步设置
|
||||
this.setter(key, (data: any) => {
|
||||
object[keyFromObject] = data
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出数据对象
|
||||
* @returns 数据对象
|
||||
*/
|
||||
public export(): IRegistry<D> {
|
||||
this.autoFillFunction();
|
||||
return this.registryList as IRegistry<D>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动填充缺失的异步函数
|
||||
* 在注册表中搜索全部的同步函数
|
||||
* 并自动填充对应的异步函数
|
||||
* 此函数会在 export 前静默执行
|
||||
*/
|
||||
protected autoFillFunction(): void {
|
||||
|
||||
// 填充函数
|
||||
const fillFunction = <KEY extends keyof D>(key: KEY): void => {
|
||||
|
||||
const item = this.registryList[key] as IRegistryItem<D[KEY]>;
|
||||
if (!item) return;
|
||||
|
||||
// 检验 getter
|
||||
if (item.get && !item.getAsync) {
|
||||
item.getAsync = this.syncFn2AsyncFn(item.get as IGet<D[KEY]["type"]>);
|
||||
}
|
||||
|
||||
// 检验 setter
|
||||
if (item.set && !item.setAsync) {
|
||||
item.setAsync = this.syncFn2AsyncFn(item.set as ISet<D[KEY]["type"]>);
|
||||
}
|
||||
}
|
||||
|
||||
// 在注册表中查找
|
||||
for (const key in this.registryList) fillFunction(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将同步函数转换为异步函数
|
||||
* @param fn 同步函数
|
||||
*/
|
||||
protected syncFn2AsyncFn<D, H extends (IGet<D> | ISet<D>)> (fn: H):
|
||||
IAutoSelect<H extends IGet<D> ? true : false, IGetAsync<D>, ISetAsync<D>> {
|
||||
const asyncFn = async (...param: [D]) => {
|
||||
return fn(...param);
|
||||
};
|
||||
return asyncFn as any;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,35 @@
|
||||
import { Modular, Manager } from "../../core/Module";
|
||||
|
||||
class Mask<M extends Manager> extends Modular<M> {
|
||||
/**
|
||||
* 蒙版事件
|
||||
*/
|
||||
type IMaskEvent = {
|
||||
|
||||
/**
|
||||
* 蒙版显示事件
|
||||
*/
|
||||
show: void;
|
||||
|
||||
/**
|
||||
* 蒙版隐藏事件
|
||||
*/
|
||||
hide: void;
|
||||
|
||||
/**
|
||||
* 蒙版状态改变事件
|
||||
*/
|
||||
change: boolean;
|
||||
|
||||
/**
|
||||
* 蒙版点击事件
|
||||
*/
|
||||
click: void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 蒙版 Modular
|
||||
*/
|
||||
class Mask<M extends Manager> extends Modular<M, {}, IMaskEvent> {
|
||||
|
||||
/**
|
||||
* 动画运行时间
|
||||
@@ -25,22 +54,41 @@ class Mask<M extends Manager> extends Modular<M> {
|
||||
isShow: false
|
||||
};
|
||||
|
||||
/**
|
||||
* 当点击时是否自动关闭蒙版
|
||||
*/
|
||||
public autoCloseOnClick: boolean = true;
|
||||
|
||||
/**
|
||||
* 消失动画计时器
|
||||
*/
|
||||
private disappearTimer?: number;
|
||||
|
||||
public override onLoad() {
|
||||
this.setFunc(this.handleClickMask, "handleClickMask");
|
||||
this.on("show", this.showMask);
|
||||
this.on("hide", this.hideMask);
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示蒙版
|
||||
*/
|
||||
public showMask() {
|
||||
private showMask = () => {
|
||||
|
||||
this.disappearTimer && clearTimeout(this.disappearTimer);
|
||||
|
||||
this.setData({
|
||||
isShow: true,
|
||||
isDisplay: true
|
||||
});
|
||||
|
||||
this.emit("change", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏蒙版
|
||||
*/
|
||||
public hideMask() {
|
||||
private hideMask = () => {
|
||||
this.setData({
|
||||
isShow: false
|
||||
});
|
||||
@@ -50,15 +98,16 @@ class Mask<M extends Manager> extends Modular<M> {
|
||||
isDisplay: false
|
||||
});
|
||||
}, Mask.animateTime);
|
||||
}
|
||||
|
||||
public override onLoad() {
|
||||
this.setFunc(this.handleClickMask, "handleClickMask");
|
||||
// Do something
|
||||
}
|
||||
|
||||
this.emit("change", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理蒙版点击事件
|
||||
*/
|
||||
private handleClickMask() {
|
||||
this.hideMask();
|
||||
if (this.autoCloseOnClick) this.emit("hide", void 0);
|
||||
this.emit("click", void 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
@import "../../app.scss";
|
||||
|
||||
view.popups {
|
||||
position: fixed;
|
||||
width: 75%;
|
||||
height: 75%;
|
||||
margin:auto;
|
||||
left:0;
|
||||
right:0;
|
||||
top:0;
|
||||
bottom:0;
|
||||
background-color: $theme-color-light-layout;
|
||||
border-radius: 15px;
|
||||
z-index: 2;
|
||||
}
|
||||
view.popups.block {
|
||||
display: block;
|
||||
}
|
||||
view.popups.none {
|
||||
display: none;
|
||||
}
|
||||
|
||||
view.popups.show {
|
||||
animation-duration: 0.5s;
|
||||
animation-name: show;
|
||||
}
|
||||
|
||||
view.popups.hide {
|
||||
animation-duration: 0.5s;
|
||||
animation-name: hide;
|
||||
}
|
||||
|
||||
@keyframes show{
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide{
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Modular, Manager } from "../../core/Module";
|
||||
|
||||
class Popups<M extends Manager> extends Modular<M> {
|
||||
|
||||
/**
|
||||
* 动画运行时间
|
||||
*/
|
||||
public static readonly animateTime: number = 100;
|
||||
|
||||
public data? = {
|
||||
|
||||
/**
|
||||
* 弹出层是否显示
|
||||
*/
|
||||
display:false,
|
||||
|
||||
/**
|
||||
* 弹出层动画
|
||||
*/
|
||||
isShow:false
|
||||
};
|
||||
|
||||
disappearTimer: number | undefined;
|
||||
|
||||
/**
|
||||
* 显示弹出层
|
||||
*/
|
||||
public showPopups() {
|
||||
this.setData({
|
||||
isShow:true,
|
||||
display:true
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏弹出层
|
||||
*/
|
||||
public hidePopups() {
|
||||
this.setData({
|
||||
isShow:false
|
||||
});
|
||||
|
||||
this.disappearTimer = setTimeout(() => {
|
||||
this.setData({
|
||||
display: false
|
||||
});
|
||||
}, Popups.animateTime);
|
||||
|
||||
}
|
||||
|
||||
public override onLoad() {
|
||||
// Do something
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { Popups };
|
||||
export default Popups;
|
||||
@@ -2,6 +2,7 @@
|
||||
@import "./MainFunction.scss";
|
||||
@import "./FunctionList.scss";
|
||||
@import "../../modular/Mask/Mask.scss";
|
||||
@import "../../modular/Popups/Popups.scss";
|
||||
|
||||
view.container{
|
||||
padding-top: 50rpx;
|
||||
|
||||
@@ -3,6 +3,7 @@ import { UserCard } from "./UserCard";
|
||||
import { MainFunction } from "./MainFunction";
|
||||
import { FunctionList } from "./FunctionList";
|
||||
import { Mask } from "../../modular/Mask/Mask";
|
||||
import {Popups} from "../../modular/Popups/Popups"
|
||||
|
||||
(async () => {
|
||||
|
||||
@@ -12,8 +13,10 @@ import { Mask } from "../../modular/Mask/Mask";
|
||||
// 添加蒙版 Modular
|
||||
const mask = manager.addModule(Mask, "mask");
|
||||
|
||||
const popups = manager.addModule(Popups,"popups")
|
||||
|
||||
// 添加 UserCard Modular
|
||||
manager.addModule(UserCard, "userCard", { mask });
|
||||
manager.addModule(UserCard, "userCard", { mask, popups });
|
||||
|
||||
// 添加 MainFunction Modular
|
||||
manager.addModule(MainFunction, "mainFunction");
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
<view class="mask {{ mask$isShow ? 'show' : 'hide' }} {{ mask$isDisplay ? 'block' : 'none' }}"
|
||||
bindtap="mask$handleClickMask"></view>
|
||||
|
||||
<!-- 弹出层 -->
|
||||
<view class="popups" style="display:{{popups$isShow ? 'block' : 'none'}}"></view>
|
||||
|
||||
<!-- 顶部的阴影 -->
|
||||
<view class="top-shadow"></view>
|
||||
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import Popups from "modular/Popups/Popups";
|
||||
import { Modular, Manager } from "../../core/Module";
|
||||
import { Mask } from "../../modular/Mask/Mask";
|
||||
|
||||
type IUserCardDependent<M extends Manager> = {
|
||||
mask: Mask<M>
|
||||
popups: Popups<M>
|
||||
}
|
||||
|
||||
class UserCard<M extends Manager> extends Modular<M, IUserCardDependent<M>> {
|
||||
type IUserCardEvent = {
|
||||
|
||||
/**
|
||||
* 主题更换按钮点击事件
|
||||
*/
|
||||
clickChangeTheme: void;
|
||||
}
|
||||
|
||||
class UserCard<M extends Manager> extends Modular<M, IUserCardDependent<M>, IUserCardEvent> {
|
||||
|
||||
public override onLoad() {
|
||||
this.setFunc(this.handleChangeTheme, "changeTheme")
|
||||
@@ -15,7 +25,9 @@ class UserCard<M extends Manager> extends Modular<M, IUserCardDependent<M>> {
|
||||
* 处理主题更换
|
||||
*/
|
||||
private handleChangeTheme() {
|
||||
this.depends?.mask.showMask();
|
||||
this.depends?.popups.showPopups();
|
||||
this.depends?.mask.emit("show", void 0);
|
||||
this.emit("clickChangeTheme", void 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"setting": {},
|
||||
"condition": {
|
||||
"plugin": {
|
||||
"list": []
|
||||
@@ -16,6 +17,12 @@
|
||||
"pathName": "pages/Account/Account",
|
||||
"query": "",
|
||||
"scene": null
|
||||
},
|
||||
{
|
||||
"name": "pages/Account/Account",
|
||||
"pathName": "pages/Account/Account",
|
||||
"query": "",
|
||||
"scene": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user