Files
2026-09-24 16:25:22 +08:00

373 lines
9.4 KiB
Plaintext

<template>
<view v-if="showAlert" @click="onclickbar" class="xAlert" :style="_styleMap.bgStyle">
<!--
@slot 左边图标插槽
-->
<slot name="left">
<view class="xAlertLeft">
<x-icon :font-size="props.iconSize" :color="(_styleMap.textStyle.get('color')! as string)"
:dark-color="(_styleMap.textStyle.get('color')! as string)" :name="_iconName"></x-icon>
</view>
</slot>
<view class="xAlertContent">
<text :style="_styleMap.textStyle">
<!--
@slot 默认插槽内容
-->
<slot></slot>
</text>
</view>
<view @click="closeAlert" v-if="_showClose" class="xAlertRight">
<x-icon :font-size="props.iconSize" :color="(_styleMap.textStyle.get('color')! as string)"
:dark-color="(_styleMap.textStyle.get('color')! as string)" :name="props.closeIcon"></x-icon>
</view>
</view>
</template>
<script lang="ts" setup>
import { computed, ref, onMounted } from "vue"
import { xDate } from "../../core/util/xDate.uts"
import { checkIsCssUnit, getUnit, fillArrayCssValue, fillArrayCssValueByround, fillArrayCssValueBycolor } from "../../core/util/xCoreUtil.uts"
import { getDefaultColor, getDefaultColorObj, getThinColorObj } from "../../core/util/xCoreColorUtil.uts"
import { xConfig } from "../../config/xConfig.uts"
type styleMapType = {
textStyle: Map<string, any>,
bgStyle: Map<string, any>
}
type xAlertStatusType = "primary"|"warn"|"success"|"error"|"info"
/**
* @name 警告 xAlert
* @page /pages/index/alert
* @category 展示组件
* @description 样式丰富常用警告提醒
* @constant 平台兼容
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
| --- | --- | --- | --- | --- | --- | --- | --- |
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
*/
defineOptions({ name: "xAlert" })
defineSlots<{
left(): any
default(): any
}>()
const emits = defineEmits([
/**
* 关闭时触发
*/
"close",
/**
* 组件被点击时触发
*/
"click"
])
export type xAlertPropsType = {
/**
* 类型
* warn:警告
* success:成功
* error:错误
* info:信息
* primary:正常主题
*/
status: xAlertStatusType,
/**
* 警告图标,不填写取status默认图标
* 填写以填写为准
*/
icon: string,
/**
* 警告图标大小
*/
iconSize: string,
/**
* 关闭图标
*/
closeIcon: string,
/**
* 显示还是隐藏关闭按钮
*/
showClose: boolean,
/**
* 文字大小
*/
fontSize: string,
/**
* 主题色,如果不填写以status为准
*/
color: string,
/**
* 文字颜色,如果不填写以status为准
*/
fontColor: string,
/**
* 暗黑主题颜色,如果不填写自动计算
*/
darkColor: string,
/**
* 暗黑文字颜色,如果不填写自动计算
*/
fontDarkColor: string,
/**
* 它是建立在你没有提供color时才有效。
* 如果提供了color是以你color为背景最终色。
* thin浅色模式,
* normal标准背景色
*/
skin: string,
/**
* 圆角
* 数组数字时
* [全部]
* [顶左,顶右,底右,底左]
* [顶左,底右]
* [顶左,顶右,底右]
* 空数组时取全局值
*/
round: string[],
/**
* 边线
* 数组数字时
* 数组数字时
* [全部]
* [左,上,右,下]
* [左右,上下]
* [左,上,右]
* 空数组时取全局值
*/
border: string[],
/**
* 边框颜色
* 格式同border边线。
* 空数组时取全局值
*/
borderColor: string[],
/**
* 如果不填写,自动计算
*/
darkBorderColor: string[],
/**
* 边线类型,默认solid,可以为none
*/
borderStyle: string,
/**
* 间隙[x]全部,[x,x]左右,上下,[x,x,x]左上右,[x,x,x,x]左上右下
* 空数组时取全局值
*/
margin: string[],
/**
* 内间隙[x]全部,[x,x]左右,上下,[x,x,x]左上右,[x,x,x,x]左上右下
* 空数组时取全局值
*/
padding: string[],
/**
* 自定义高度,可以是数字,单位或者百分比,auto
*/
height: string,
/**
* 宽,单位合法即可数字,字符串带单位,百分比,auto
*/
width: string
}
const props = withDefaults(defineProps<xAlertPropsType>(), {
status: "primary",
icon: "",
iconSize: "20",
closeIcon: "close-line",
showClose: true,
fontSize: "15",
color: "",
fontColor: "",
darkColor: "",
fontDarkColor: "",
skin: "thin",
round:():string[] => [] as string[],
border: ():string[] => [] as string[],
borderColor: ():string[] => [] as string[],
darkBorderColor: ():string[] => [] as string[],
borderStyle: 'solid',
margin: ():string[] => ['16', '0', '16', '16'] as string[],
padding: ():string[] => ['16', '12'] as string[],
height: "auto",
width: "auto"
})
// 响应式数据
const showAlert = ref(true)
// 计算属性
const _color = computed((): string => {
let tcolor = props.color;
if (tcolor == '') {
tcolor = props.status;
}
if (xConfig.dark == 'dark' && props.darkColor != '') {
tcolor = props.darkColor
}
let color = getDefaultColor(tcolor)
return color;
})
const _fontColor = computed((): string => {
let tcolor = props.fontColor;
if (xConfig.dark == 'dark' && props.fontDarkColor != '') {
tcolor = props.fontDarkColor
}
return tcolor;
})
const _isDark = computed((): boolean => xConfig.dark == 'dark')
const _showClose = computed((): boolean => props.showClose)
const _fontSize = computed((): string => {
let fontSize = checkIsCssUnit(props.fontSize, xConfig.unit);
if (xConfig.fontScale == 1) return fontSize;
let sizeNumber = parseInt(fontSize)
if (isNaN(sizeNumber)) {
sizeNumber = 16
}
return (sizeNumber * xConfig.fontScale).toString() + getUnit(fontSize)
})
const _margin = computed((): string => {
if (props.margin.length == 0) {
let par = fillArrayCssValue(xConfig.sheetMargin)
if (par.length == 0) return "0px 0px 0px 0px";
return par.join(" ")
}
let ar: string[] = fillArrayCssValue(props.margin as string[])
if (ar.length == 0) return "0px 0px 0px 0px";
return ar.join(" ")
})
const _padding = computed((): string => {
if (props.padding.length == 0) {
let par = fillArrayCssValue(xConfig.sheetMargin)
if (par.length == 0) return "0px 0px 0px 0px";
return par.join(" ")
}
let ar: string[] = fillArrayCssValue(props.padding as string[])
if (ar.length == 0) return "0px 0px 0px 0px";
return ar.join(" ")
})
const _round = computed((): string => {
if (props.round.length == 0) {
let par = fillArrayCssValueByround(xConfig.sheetRadius)
if (par.length == 0) return "0px 0px 0px 0px";
return par.join(" ")
}
let ar: string[] = fillArrayCssValueByround(props.round as string[])
if (ar.length == 0) return "0px 0px 0px 0px";
return ar.join(" ")
})
const _border = computed((): string => {
let ar: string[] = fillArrayCssValue(props.border as string[])
if (ar.length == 0) return "0px 0px 0px 0px";
return ar.join(" ")
})
const _borderColor = computed((): string => {
let bordercolor = props.borderColor as string[];
if (xConfig.dark == 'dark') {
bordercolor = props.darkBorderColor.length == 0 ? xConfig.sheetDarkBorderColor : props.darkBorderColor
}
let ar: string[] = fillArrayCssValueBycolor(bordercolor as string[])
if (ar.length == 0) return "transparent transparent transparent transparent";
return ar.join(" ")
})
const _iconName = computed((): string => {
const iconsmap = new Map<string, string>([
['warn', 'alert-line'],
['success', 'check-double-line'],
['error', 'close-circle-line'],
['info', 'information-2-line'],
['primary', 'notification-line'],
])
let dicon = iconsmap.get(props.status)
return props.icon == '' ? (dicon == null ? '' : dicon!) : props.icon
})
const _styleMap = computed((): styleMapType => {
let bgStylemap = new Map<string, any>()
let textStylemap = new Map<string, any>()
let colorObj = getDefaultColorObj(_color.value, _color.value)
if (props.skin == 'thin') {
colorObj = getThinColorObj(_color.value, _color.value, _isDark.value)
}
let defaultObj: UTSJSONObject = colorObj.getJSON("default")!
bgStylemap.set("backgroundColor", defaultObj.getString("background")!)
bgStylemap.set("margin", _margin.value)
bgStylemap.set("padding", _padding.value)
bgStylemap.set("border-radius", _round.value)
bgStylemap.set("border-width", _border.value)
bgStylemap.set("height", checkIsCssUnit(props.height, xConfig.unit))
bgStylemap.set("width", checkIsCssUnit(props.width, xConfig.unit))
bgStylemap.set("border-style", props.borderStyle)
if (props.borderColor.length > 0) {
bgStylemap.set("border-color", _borderColor.value)
} else {
bgStylemap.set("border-color", getDefaultColor(_color.value))
}
if (_fontColor.value == '') {
textStylemap.set("color", defaultObj.getString("fontColor")!)
} else {
textStylemap.set("color", _fontColor.value)
}
textStylemap.set("font-size", _fontSize.value)
return {
bgStyle: bgStylemap,
textStyle: textStylemap
} as styleMapType;
})
// 方法
function closeAlert(): void {
emits('close')
showAlert.value = false
}
function onclickbar(): void {
emits('click')
}
</script>
<style>
.xAlert {
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
}
.xAlertContent {
flex: 1;
}
.xAlertLeft {
margin-right: 8rpx;
}
.xAlertLeft {
flex-shrink: 0;
padding-right: 6px;
}
.xAlertRight {
flex-shrink: 0;
padding-left: 20px;
}
</style>