版本发布
This commit is contained in:
64
uni_modules/cool-ui/components/cl-page/back-top.uvue
Normal file
64
uni_modules/cool-ui/components/cl-page/back-top.uvue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<view class="back-top-wrapper" :style="{ bottom }">
|
||||
<view
|
||||
class="back-top"
|
||||
:class="{
|
||||
'is-show': visible
|
||||
}"
|
||||
>
|
||||
<cl-icon name="skip-up-line" color="white" :size="50"></cl-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import { usePage } from "@/cool";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-page-back-top"
|
||||
});
|
||||
|
||||
const page = usePage();
|
||||
const { screenHeight } = uni.getWindowInfo();
|
||||
|
||||
// 是否显示回到顶部按钮
|
||||
const visible = ref(false);
|
||||
|
||||
// 底部距离
|
||||
const bottom = computed(() => {
|
||||
let h = 20;
|
||||
|
||||
if (page.hasCustomTabBar()) {
|
||||
h += page.getTabBarHeight();
|
||||
}
|
||||
|
||||
return h + "px";
|
||||
});
|
||||
|
||||
// 监听页面滚动
|
||||
page.onPageScroll((top) => {
|
||||
// 控制是否显示回到顶部按钮
|
||||
visible.value = top > screenHeight - 100;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.back-top {
|
||||
@apply flex flex-row items-center justify-center bg-primary-500 rounded-full;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
transition-property: transform;
|
||||
transition-duration: 0.3s;
|
||||
transform: translateX(160rpx);
|
||||
|
||||
&.is-show {
|
||||
transform: translateX(-20px);
|
||||
}
|
||||
|
||||
&-wrapper {
|
||||
@apply fixed z-50 overflow-visible;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
95
uni_modules/cool-ui/components/cl-page/cl-page.uvue
Normal file
95
uni_modules/cool-ui/components/cl-page/cl-page.uvue
Normal file
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<!-- #ifdef APP -->
|
||||
<scroll-view
|
||||
:style="{ flex: 1 }"
|
||||
:scroll-top="scrollViewTop"
|
||||
:scroll-with-animation="true"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<back-top v-if="backTop" @tap="scrollToTop"></back-top>
|
||||
<theme></theme>
|
||||
<ui></ui>
|
||||
<slot></slot>
|
||||
</scroll-view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifndef APP -->
|
||||
<back-top v-if="backTop" @tap="scrollToTop"></back-top>
|
||||
<theme></theme>
|
||||
<ui></ui>
|
||||
<slot></slot>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { router, usePage } from "@/cool";
|
||||
import BackTop from "./back-top.uvue";
|
||||
import Theme from "./theme.uvue";
|
||||
import Ui from "./ui.uvue";
|
||||
import { locale, t } from "@/locale";
|
||||
import { config } from "@/config";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-page"
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
// 是否显示回到顶部按钮
|
||||
backTop: {
|
||||
type: Boolean,
|
||||
default: config.backTop
|
||||
}
|
||||
});
|
||||
|
||||
const page = usePage();
|
||||
|
||||
// scroll-view 滚动位置
|
||||
const scrollViewTop = ref(0);
|
||||
|
||||
// view 滚动事件
|
||||
function onScroll(e: UniScrollEvent) {
|
||||
page.triggerScroll(e.detail.scrollTop);
|
||||
}
|
||||
|
||||
// 回到顶部
|
||||
function scrollToTop() {
|
||||
// #ifdef H5
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
duration: 300
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifdef APP
|
||||
scrollViewTop.value = 0 + Math.random() / 1000;
|
||||
// #endif
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 标题多语言
|
||||
// #ifdef H5 || APP
|
||||
watch(
|
||||
computed(() => locale.value),
|
||||
() => {
|
||||
const style = router.route()?.style;
|
||||
|
||||
if (style != null) {
|
||||
if (style.navigationBarTitleText != null) {
|
||||
uni.setNavigationBarTitle({
|
||||
title: t((style.navigationBarTitleText as string).replaceAll("%", ""))
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
// #endif
|
||||
});
|
||||
</script>
|
||||
6
uni_modules/cool-ui/components/cl-page/props.ts
Normal file
6
uni_modules/cool-ui/components/cl-page/props.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { ClConfirmAction, ClConfirmOptions, ClToastOptions } from "../../types";
|
||||
import type { UiInstance } from "../../hooks";
|
||||
|
||||
export type ClPageUiProps = {
|
||||
className?: string;
|
||||
};
|
||||
46
uni_modules/cool-ui/components/cl-page/theme.uvue
Normal file
46
uni_modules/cool-ui/components/cl-page/theme.uvue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<cl-float-view :size="40" :left="20" :bottom="20" :gap="20" v-if="config.showDarkButton">
|
||||
<view class="theme-set" @tap="toggleTheme()">
|
||||
<view class="theme-set__inner" :class="{ 'is-dark': isDark }">
|
||||
<view class="theme-set__icon" v-for="item in list" :key="item">
|
||||
<cl-icon :name="item" color="white" :size="36"></cl-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</cl-float-view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { config } from "@/config";
|
||||
import { isDark, toggleTheme } from "@/cool";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-page-theme"
|
||||
});
|
||||
|
||||
const list = ["moon-fill", "sun-fill"];
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.theme-set {
|
||||
@apply flex flex-col items-center justify-center rounded-full h-full w-full;
|
||||
@apply bg-primary-500;
|
||||
|
||||
&__inner {
|
||||
@apply flex flex-col;
|
||||
transform: translateY(20px);
|
||||
transition-property: transform;
|
||||
transition-duration: 300ms;
|
||||
|
||||
&.is-dark {
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
@apply flex items-center justify-center;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
68
uni_modules/cool-ui/components/cl-page/ui.uvue
Normal file
68
uni_modules/cool-ui/components/cl-page/ui.uvue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<cl-confirm ref="confirmRef"></cl-confirm>
|
||||
<cl-confirm ref="tipsRef"></cl-confirm>
|
||||
<cl-toast ref="toastRef"></cl-toast>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import type { ClConfirmAction, ClConfirmOptions, ClToastOptions } from "../../types";
|
||||
import { createUi, type UiInstance } from "../../hooks";
|
||||
import { t } from "@/locale";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-page-ui"
|
||||
});
|
||||
|
||||
// 确认弹窗实例
|
||||
const confirmRef = ref<ClConfirmComponentPublicInstance | null>(null);
|
||||
|
||||
// 提示弹窗实例
|
||||
const tipsRef = ref<ClConfirmComponentPublicInstance | null>(null);
|
||||
|
||||
// 提示弹窗实例
|
||||
const toastRef = ref<ClToastComponentPublicInstance | null>(null);
|
||||
|
||||
/**
|
||||
* 显示确认弹窗
|
||||
* @param options ClConfirmOptions 弹窗配置项
|
||||
*/
|
||||
function showConfirm(options: ClConfirmOptions) {
|
||||
if (confirmRef.value != null) {
|
||||
confirmRef.value!.open(options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示提示弹窗
|
||||
* @param message 提示消息
|
||||
* @param callback 回调函数
|
||||
*/
|
||||
function showTips(message: string, callback: (action: ClConfirmAction) => void) {
|
||||
if (tipsRef.value != null) {
|
||||
tipsRef.value!.open({
|
||||
title: t("提示"),
|
||||
message,
|
||||
callback,
|
||||
showCancel: false
|
||||
} as ClConfirmOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示提示弹窗
|
||||
* @param options ClToastOptions 弹窗配置项
|
||||
*/
|
||||
function showToast(options: ClToastOptions) {
|
||||
if (toastRef.value != null) {
|
||||
toastRef.value!.open(options);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册当前页面的 UiInstance 实例
|
||||
createUi({
|
||||
showConfirm,
|
||||
showTips,
|
||||
showToast
|
||||
} as UiInstance);
|
||||
</script>
|
||||
Reference in New Issue
Block a user