2025/2/8第一次更新

This commit is contained in:
爱吃咸鱼小猫咪
2025-02-08 18:50:38 +08:00
commit d7af560866
26519 changed files with 5046029 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
import { withNoopInstall } from '../../utils'
import Modal from './src/modal.vue'
export const TnModal = withNoopInstall(Modal)
export default TnModal
export * from './src/modal'
export type { TnModalInstance } from './src/instance'
@@ -0,0 +1,2 @@
export * from './modal-custom'
export * from './use-modal'
@@ -0,0 +1,101 @@
import { computed, toRef, watch } from 'vue'
import { useComponentColor, useNamespace } from '../../../../hooks'
import type { CSSProperties, Ref } from 'vue'
import type { ModalBtnStyle } from '../modal'
type OperationBtnComputedClass = (type: 'cancel' | 'confirm') => string
type OperationBtnComputedStyle = (type: 'cancel' | 'confirm') => CSSProperties
export const useModalCustomStyle = (
cancelBtnStyle: Ref<ModalBtnStyle>,
confirmBtnStyle: Ref<ModalBtnStyle>
) => {
const ns = useNamespace('modal')
// 解析按钮的颜色
const [cancelBtnBgClass, cancelBtnBgStyle, updateCancelBtnBg] =
useComponentColor(toRef(cancelBtnStyle.value, 'bgColor'), 'bg')
const [cancelBtnColorClass, cancelBtnColorStyle, updateCancelBtnColor] =
useComponentColor(toRef(cancelBtnStyle.value, 'color'), 'text')
const [confirmBtnBgClass, confirmBtnBgStyle, updateConfirmBtnBg] =
useComponentColor(toRef(confirmBtnStyle.value, 'bgColor'), 'bg')
const [confirmBtnColorClass, confirmBtnColorStyle, updateConfirmBtnColor] =
useComponentColor(toRef(confirmBtnStyle.value, 'color'), 'text')
watch(
() => confirmBtnStyle,
(value) => {
updateConfirmBtnBg(value.value.bgColor)
updateConfirmBtnColor(value.value.color)
},
{
deep: true,
}
)
watch(
() => cancelBtnStyle,
(value) => {
updateCancelBtnBg(value.value.bgColor)
updateCancelBtnColor(value.value.color)
},
{
deep: true,
}
)
// 操作按钮所属类
const operationBtnClass = computed<OperationBtnComputedClass>(() => {
return (type: 'cancel' | 'confirm') => {
const cls: string[] = [
ns.e('operation-btn'),
ns.em('operation-btn', type),
]
if (type === 'cancel') {
if (cancelBtnBgClass.value) cls.push(cancelBtnBgClass.value)
if (cancelBtnColorClass.value) cls.push(cancelBtnColorClass.value)
}
if (type === 'confirm') {
if (confirmBtnBgClass.value) cls.push(confirmBtnBgClass.value)
if (confirmBtnColorClass.value) cls.push(confirmBtnColorClass.value)
}
return cls.join(' ')
}
})
// 操作按钮的样式
const operationBtnStyle = computed<OperationBtnComputedStyle>(() => {
return (type: 'cancel' | 'confirm') => {
const style: CSSProperties = {}
if (type === 'cancel') {
if (cancelBtnBgStyle.value)
style.backgroundColor = cancelBtnBgStyle.value
if (cancelBtnColorStyle.value) {
style.color = cancelBtnColorStyle.value
} else if (!cancelBtnBgClass.value && !cancelBtnColorClass.value) {
style.color = 'var(--tn-color-danger)'
}
}
if (type === 'confirm') {
if (confirmBtnBgStyle.value)
style.backgroundColor = confirmBtnBgStyle.value
if (confirmBtnColorStyle.value) {
style.color = confirmBtnColorStyle.value
} else if (!confirmBtnBgClass.value && !confirmBtnColorClass.value) {
style.color = 'var(--tn-color-primary)'
}
}
return style
}
})
return {
ns,
operationBtnClass,
operationBtnStyle,
}
}
@@ -0,0 +1,148 @@
import { ref } from 'vue'
import {
isBoolean,
isEmptyVariableInDefault,
isPromise,
} from '../../../../utils'
import type { ModalOptions } from '../modal'
export const useModal = () => {
const openModal = ref(false)
// 弹框标题
const title = ref<Required<ModalOptions>['title']>('')
// 弹框内容
const content = ref<Required<ModalOptions>['content']>('')
// 是否显示取消按钮
const showCancel = ref<Required<ModalOptions>['showCancel']>(false)
// 取消按钮的文字
const cancelText = ref<Required<ModalOptions>['cancelText']>('')
// 取消按钮的样式
const cancelStyle = ref<Required<ModalOptions>['cancelStyle']>({})
// 确认按钮的文字
const confirmText = ref<Required<ModalOptions>['confirmText']>('')
// 确认按钮的样式
const confirmStyle = ref<Required<ModalOptions>['confirmStyle']>({})
// 是否显示遮罩
const mask = ref<Required<ModalOptions>['mask']>(true)
// 是否允许点击遮罩关闭
const maskClosable = ref<Required<ModalOptions>['maskClosable']>(false)
// 点击取消按钮触发的回调函数
const cancelFunc = ref<ModalOptions['cancel']>(undefined)
// 点击确认按钮触发的回调函数
const confirmFunc = ref<ModalOptions['confirm']>(undefined)
// 打开弹窗
const showModal = (options: ModalOptions) => {
openModal.value = true
title.value = isEmptyVariableInDefault(options.title, '')
content.value = options.content
showCancel.value = isEmptyVariableInDefault(options?.showCancel, false)
cancelText.value = isEmptyVariableInDefault(options?.cancelText, '取 消')
cancelStyle.value = isEmptyVariableInDefault(options?.cancelStyle, {})
confirmText.value = isEmptyVariableInDefault(options?.confirmText, '确 认')
confirmStyle.value = isEmptyVariableInDefault(options?.confirmStyle, {})
mask.value = isEmptyVariableInDefault(options?.mask, true)
maskClosable.value = isEmptyVariableInDefault(options?.maskClosable, false)
cancelFunc.value = options?.cancel
confirmFunc.value = options?.confirm
}
// 关闭弹窗
const closeModal = () => {
openModal.value = false
}
// 点击取消按钮
const clickCancel = () => {
if (!cancelFunc.value) {
closeModal()
return
}
const func = cancelFunc.value()
const isPromiseOrBool = [isPromise(func), isBoolean(func)].includes(true)
if (!isPromiseOrBool) {
// 传递的是普通函数
closeModal()
return
}
if (isPromise(func)) {
func
.then((res) => {
if (res) closeModal()
})
.catch((err) => {
// eslint-disable-next-line no-console
console.warn(`[TnModal] some error occured: ${err}`)
})
} else if (func) {
closeModal()
}
}
// 点击确认按钮
const clickConfirm = () => {
if (!confirmFunc.value) {
closeModal()
return
}
const func = confirmFunc.value()
const isPromiseOrBool = [isPromise(func), isBoolean(func)].includes(true)
if (!isPromiseOrBool) {
// 传递的是普通函数
closeModal()
return
}
if (isPromise(func)) {
func
.then((res) => {
if (res) closeModal()
})
.catch((err) => {
// eslint-disable-next-line no-console
console.warn(`[TnModal] some error occured: ${err}`)
})
} else if (func) {
closeModal()
}
}
return {
openModal,
showModal,
title,
content,
showCancel,
cancelText,
cancelStyle,
confirmText,
confirmStyle,
mask,
maskClosable,
cancelFunc,
confirmFunc,
clickCancel,
clickConfirm,
}
}
@@ -0,0 +1,3 @@
import type Modal from './modal.vue'
export type TnModalInstance = InstanceType<typeof Modal>
+77
View File
@@ -0,0 +1,77 @@
import { buildProps } from '../../../utils'
import { ZIndex } from '../../../constants'
import type { ExtractPropTypes } from 'vue'
/**
* @description Modal配置项
*/
export interface ModalOptions {
/**
* @description 内容
*/
content: string
/**
* @description 标题
*/
title?: string
/**
* @description 是否显示取消按钮
*/
showCancel?: boolean
/**
* @description 取消按钮的文字
*/
cancelText?: string
/**
* @description 取消按钮的样式
*/
cancelStyle?: ModalBtnStyle
/**
* @description 确认按钮的文字
*/
confirmText?: string
/**
* @description 确认按钮的样式
*/
confirmStyle?: ModalBtnStyle
/**
* @description 是否显示遮罩
*/
mask?: boolean
/**
* @description 是否允许点击遮罩关闭
*/
maskClosable?: boolean
/**
* @description 点击取消按钮触发的回调函数,返回 false 或者返回 Promise 且被 reject 则取消关闭
*/
cancel?: () => (Promise<boolean> | void) | boolean
/**
* @description 点击确认按钮触发的回调函数,返回 false 或者返回 Promise 且被 reject 则取消关闭
*/
confirm?: () => (Promise<boolean> | void) | boolean
}
export interface ModalBtnStyle {
/**
* @description 按钮的背景色
*/
bgColor?: string
/**
* @description 按钮的文字颜色
*/
color?: string
}
export const modalProps = buildProps({
/**
* @description zIndex
*/
zIndex: {
type: Number,
default: ZIndex.modal,
},
})
export type ModalProps = ExtractPropTypes<typeof modalProps>
+85
View File
@@ -0,0 +1,85 @@
<script lang="ts" setup>
import TnPopup from '../../popup/src/popup.vue'
import { modalProps } from './modal'
import { useModal, useModalCustomStyle } from './composables'
defineProps(modalProps)
const {
openModal,
showModal,
title,
content,
showCancel,
cancelText,
confirmText,
mask,
maskClosable,
cancelStyle,
confirmStyle,
clickCancel,
clickConfirm,
} = useModal()
const { ns, operationBtnClass, operationBtnStyle } = useModalCustomStyle(
cancelStyle,
confirmStyle
)
defineExpose({
/**
* @description 打开模态框
*/
showModal,
})
</script>
<template>
<TnPopup
v-model="openModal"
open-direction="center"
bg-color="transparent"
radius="0"
width="80%"
:overlay="mask"
:overlay-closeable="maskClosable"
:z-index="zIndex"
>
<view :class="[ns.b()]">
<view v-if="title" class="tn-text-ellipsis-1" :class="[ns.e('title')]">
{{ title }}
</view>
<view :class="[ns.e('content')]">
<slot>
<view class="tn-gray_text" :class="[ns.em('content', 'text')]">
{{ content }}
</view>
</slot>
</view>
<view :class="[ns.e('operation')]">
<view
v-if="showCancel"
:class="[operationBtnClass('cancel')]"
:style="operationBtnStyle('cancel')"
hover-class="tn-u-btn-hover"
:hover-stay-time="300"
@tap.stop="clickCancel"
>
{{ cancelText }}
</view>
<view
:class="[operationBtnClass('confirm')]"
:style="operationBtnStyle('confirm')"
hover-class="tn-u-btn-hover"
:hover-stay-time="300"
@tap.stop="clickConfirm"
>
{{ confirmText }}
</view>
</view>
</view>
</TnPopup>
</template>
<style lang="scss" scoped>
@import '../../../theme-chalk/src/modal.scss';
</style>