chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,420 @@
@import '@/uni_modules/lime-style/index.scss';
/* #ifdef uniVersion >= 4.75 */
$use-css-var: true;
/* #endif */
$button: #{$prefix}-button;
$button-gap: create-var(button-gap, 4px);
$button-border-width: create-var(button-border-width, 0.71px);
$button-border-radius: create-var(button-border-radius, $border-radius-sm);
$button-solid-text-color: create-var(button-solid-text-color, white);
$button-disabled-opacity: create-var(button-disabled-opacity, 0.6);
$button-default-type-map:(
solid-color: create-var(button-default-solid-text-color, white),
color: create-var(button-default-color, $gray-14),
hover-color: create-var(button-default-hover-color, rgba(0,0,0,1)),
light: create-var(button-default-light-color, $gray-2),
light-hover: create-var(button-default-light-hover-color, $gray-3),
border-color: create-var(button-default-border-color, $gray-5)
);
$button-primary-type-map:(
solid-color: create-var(button-primary-solid-text-color, white),
color: create-var(button-primary-color, $primary-color),
hover-color: create-var(button-primary-hover-color, $primary-color-7),
light: create-var(button-primary-light-color, $primary-color-1),
light-hover: create-var(button-primary-light-hover-color, $primary-color-2),
border-color: create-var(button-primary-border-color, $primary-color)
);
$button-danger-type-map:(
solid-color: create-var(button-dangert-solid-text-color, white),
color: create-var(button-danger-color, $error-color),
hover-color: create-var(button-danger-hover-color, $error-color-7),
light: create-var(button-danger-light-color, $error-color-1),
light-hover: create-var(button-danger-light-hover-color, $error-color-3),
border-color: create-var(button-danger-border-color, $error-color)
);
$button-warning-type-map:(
solid-color: create-var(button-warning-solid-text-color, white),
color: create-var(button-warning-color, $warning-color),
hover-color: create-var(button-warning-hover-color, $warning-color-7),
light: create-var(button-warning-light-color, $warning-color-1),
light-hover: create-var(button-warning-light-hover-color, $warning-color-2),
border-color: create-var(button-warning-border-color, $warning-color)
);
$button-success-type-map:(
solid-color: create-var(button-success-solid-text-color, white),
color: create-var(button-success-color, $success-color),
hover-color: create-var(button-success-hover-color, $success-color-7),
light: create-var(button-success-light-color, $success-color-1),
light-hover: create-var(button-success-light-hover-color, $success-color-2),
border-color: create-var(button-success-border-color, $success-color)
);
$button-info-type-map:(
solid-color: create-var(button-info-solid-text-color, white),
color: create-var(button-info-color, $info-color),
hover-color: create-var(button-info-hover-color, $info-color-7),
light: create-var(button-info-light-color, $info-color-2),
light-hover: create-var(button-info-light-hover-color, $info-color-3),
border-color: create-var(button-info-border-color, $info-color)
);
$button-type-map:(
default: $button-default-type-map,
primary: $button-primary-type-map,
danger: $button-danger-type-map,
warning: $button-warning-type-map,
success: $button-success-type-map,
info: $button-info-type-map,
);
$button-icon-size-map:(
mini: create-var(button-icon-size, 32rpx),
small: create-var(button-icon-size, 36rpx),
medium: create-var(button-icon-size, 36rpx),
large: create-var(button-icon-size, 48rpx),
);
$button-font-size-map:(
mini: create-var(button-font-size, $font-size-sm),
small: create-var(button-font-size, $font-size),
medium: create-var(button-font-size, $font-size-md),
large: create-var(button-font-size, $font-size-md),
);
// $button-padding-map:(
// mini: create-var(button-padding, 0 $spacer-xs),
// small: create-var(button-padding,0 $spacer-sm),
// medium: create-var(button-padding, 0 $spacer),
// large: create-var(button-padding, 0 $spacer-md),
// );
$button-padding-x-map:(
mini: create-var(button-padding-x, $spacer-xs),
small: create-var(button-padding-x, $spacer-sm),
medium: create-var(button-padding-x, $spacer),
large: create-var(button-padding-x, $spacer-md),
);
$button-padding-y-map:(
mini: create-var(button-padding-y, 0),
small: create-var(button-padding-y, 0),
medium: create-var(button-padding-y, 0),
large: create-var(button-padding-y, 0),
);
$button-height-map:(
mini: create-var(button-mini-height, 56rpx),
small: create-var(button-small-height, 64rpx),
medium: create-var(button-medium-height, 80rpx),
large: create-var(button-large-height, 96rpx),
);
@mixin button-size($size) {
$iconSize: map-get($button-icon-size-map, $size);
$fontSize: map-get($button-font-size-map, $size);
// $padding: map-get($button-padding-map, $size);
$paddingX: map-get($button-padding-x-map, $size);
$paddingY: map-get($button-padding-y-map, $size);
$height: map-get($button-height-map, $size);
.#{$button}--#{$size} {
// padding: $padding;
@include padding($paddingY $paddingX);
height: $height;
/* #ifndef UNI-APP-X */
font-size: $fontSize;
--l-loading-size: #{$iconSize};
/* #endif */
/* #ifdef UNI-APP-X */
.#{$button} {
&__content {
font-size: $fontSize;
// line-height: 1;
}
// &__icon {
// font-size: $iconSize;
// }
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
&__loading {
--l-loading-size: #{$iconSize};
font-size: $iconSize;
}
/* #endif */
}
/* #endif */
&.#{$button} {
&--square,&--circle {
width: $height;
padding-left: 0;
padding-right: 0;
}
}
}
}
@mixin button-type($type) {
$type-map: map-get($button-type-map, $type);
$color: map-get($type-map, color);
$solid-color: map-get($type-map, solid-color);
$hoverColor: map-get($type-map, hover-color);
$borderColor: map-get($type-map, border-color);
$lightColor: map-get($type-map, light);
$lightHoverColor: map-get($type-map, light-hover);
.#{$button}--hover {
&.#{$button}--#{$type} {
background-color: $lightColor;
&.#{$button}--solid {
background-color: $hoverColor;
}
&.#{$button}--light {
background-color: $lightHoverColor;
}
}
}
.#{$button}--#{$type} {
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
color: $color;
&:not(.#{$button}--solid) {
--l-loading-color: #{$color};
}
/* #endif */
.#{$button} {
/* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
&__content {
color: $color;
}
/* #endif */
}
&.#{$button}--solid {
background-color: $color;
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
color: $solid-color;
--l-loading-color: #{$solid-color};
&:after {
border-color: transparent;
}
/* #endif */
/* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
// border-style: solid;
.#{$button} {
&__content {
color: $solid-color;
}
&__icon {
color: $solid-color;
}
&__loading {
// color: $button-solid-text-color;
}
}
/* #endif*/
}
/* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
&.#{$button}--outline {
border-color: $borderColor;
}
&.#{$button}--dashed {
border-color: $borderColor;
}
/* #endif */
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
&.#{$button}--outline {
&:after {
border-color: $borderColor;
}
}
&.#{$button}--dashed {
&:after {
border-color: $borderColor;
}
}
/* #endif */
&.#{$button}--light {
background-color: $lightColor;
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
&:after {
border-color: transparent;
}
/* #endif */
}
&.#{$button}--ghost {
background-color: transparent;
/* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
border-color: $borderColor;
/* #endif */
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
&:after {
border-color: $borderColor;
}
/* #endif */
}
}
}
@include button-size(mini);
@include button-size(small);
@include button-size(medium);
@include button-size(large);
@include button-type(default);
@include button-type(primary);
@include button-type(danger);
@include button-type(info);
@include button-type(warning);
@include button-type(success);
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY || MP-WEIXIN */
#{$button} {
&[data-block]{
width:100%;
display: flex;
margin-right: 0!important;
.#{$button} {
display: flex;
width: 100%;
}
}
}
/* #endif */
.#{$button} {
opacity: 1; // uniapp x IOS必须存在
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
display: inline-flex;
white-space: nowrap;
font-family: PingFang SC, Microsoft YaHei, Arial Regular;
vertical-align: top;
-webkit-appearance: none;
margin: 0;
background-color: transparent;
/* #endif */
position: relative;
align-items: center;
justify-content: center;
flex-direction: row;
// css var 不支持过渡?
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
transition-duration: 200ms;
/* #endif */
// background-color ios 无法恢复
transition-property:opacity,border-color,width,height;
// border-radius: $button-border-radius;
@include border-radius($button-border-radius);
&__button {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
border: none;
background-color: transparent;
}
// border-width: $button-border-width;
// border-color: transparent;
//,&--loading
&.#{$button}--disabled {
opacity: $button-disabled-opacity;
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
cursor: no-drop;
/* #endif */
}
&--block {
/* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
// border-style: solid;
/* #endif*/
width: 100%;
align-self: auto
}
// &--solid {
// /* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
// color: $button-solid-text-color;
// --l-loading-color: #{$button-solid-text-color};
// /* #endif*/
// /* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
// // border-style: solid;
// .#{$button} {
// &__content {
// color: $button-solid-text-color;
// }
// &__icon {
// color: $button-solid-text-color;
// }
// &__loading {
// // color: $button-solid-text-color;
// }
// }
// /* #endif*/
// }
/* #ifdef APP-ANDROID || APP-IOS || APP-HARMONY */
&--outline {
border-style: solid;
border-width: $button-border-width;
}
&--dashed {
border-style: dashed;
border-width: $button-border-width;
}
/* #endif*/
&__loading,&__icon{
align-self: center;
}
&--round,&--circle {
border-radius: 999px;
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY */
--l-button-border-radius: 999px
/* #endif*/
}
/* #ifdef UNI-APP-X */
.gap {
margin-left: $button-gap;
}
/* #endif*/
/* #ifndef APP-ANDROID || APP-IOS || APP-HARMONY || MP-WEIXIN */
&::after {
border-radius: calc($button-border-radius * 2);
border-color: var(--l-button-border-color);
}
&--text {
&::after {
border: 0;
}
}
view+&__content:not(:empty),
l-button+&__content:not(:empty),
l-icon+&__content:not(:empty),
&__loading+&__content:not(:empty),
&__icon+&__content:not(:empty) {
margin-left: $button-gap;
}
/* #endif*/
}

View File

@@ -0,0 +1,315 @@
<template>
<!-- #ifdef APP-ANDROID || APP-IOS || APP-HARMONY -->
<view class="l-button"
ref="rootRef"
:class="classes"
:hover-class="disabled || loading || color != null ? '': hoverClass ?? 'l-button--hover'"
:style="[styles, lStyle]"
:hover-start-time="hoverStartTime"
:hover-stay-time="hoverStayTime"
:data-disabled="disabled||loading"
@tap.stop="handleTap" >
<l-loading class="l-button__loading" :color="loadingColor" v-if="loading"></l-loading>
<l-icon class="l-button__icon" :size="innerIconSize" :color="loadingColor" v-if="icon" :name="icon"></l-icon>
<text class="l-button__content" :class="gapClass" ref="buttonTextRef" :style="[contentStyle]">
<slot>{{content}}</slot>
</text>
<button
class="l-button__button"
hover-class="none"
v-if="formType != null || openType != null"
@agreeprivacyauthorization="agreeprivacyauthorization"
:disabled="disabled || loading"
:form-type="disabled || loading ? '' : formType"
:open-type="disabled || loading ? '' : openType" >
</button>
</view>
<!-- #endif -->
<!-- #ifndef APP-ANDROID || APP-IOS || APP-HARMONY -->
<button class="l-button l-class"
:id="lId"
:style="[styles, lStyle]"
:class="[
'l-button--' + size,
'l-button--' + type,
'l-button--' + shape,
'l-button--' + computedVariant,
{
'l-button--ghost': ghost,
'l-button--block': block,
'l-button--disabled': disabled,
'l-button--loading': loading,
}
]"
:form-type="disabled || loading ? '' : formType"
:open-type="disabled || loading ? '' : openType"
:hover-stop-propagation="hoverStopPropagation"
:hover-start-time="hoverStartTime"
:hover-stay-time="hoverStayTime" :lang="lang"
:session-from="sessionFrom"
:hover-class="hoverClasses"
:send-message-title="sendMessageTitle"
:send-message-path="sendMessagePath"
:send-message-img="sendMessageImg"
:app-parameter="appParameter"
:show-message-card="showMessageCard"
@tap.stop="handleTap"
@getuserinfo="getuserinfo"
@contact="contact"
@getphonenumber="getphonenumber"
@error="error"
@opensetting="opensetting"
@launchapp="launchapp"
@chooseavatar="chooseavatar"
@agreeprivacyauthorization="agreeprivacyauthorization"
:aria-label="ariaLabel"
:data-disabled="disabled||loading">
<view class="l-button__loading" v-if="loading">
<l-loading inheritColor></l-loading>
</view>
<l-icon class="l-button__icon" v-if="icon" :name="icon"></l-icon>
<view class="l-button__content" v-if="content || $slots.default" :style="[contentStyle]" :class="[gapClass]">
<slot>{{content}}</slot>
</view>
</button>
<!-- #endif -->
</template>
<script lang="uts" setup>
/**
* Button 按钮组件
* @description 提供丰富的按钮样式和交互功能,支持多种形态和平台特性
* <br> 插件类型LButtonComponentPublicInstance
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-button
*
* @property {string} ariaLabel 无障碍标签(用于屏幕阅读器)
* @property {boolean} block 块级布局(占满父容器宽度)
* @property {boolean} disabled 禁用状态
* @property {boolean} ghost 幽灵模式(透明背景+边框)
* @property {string} icon 左侧图标名称/路径
* @property {string} iconSize 图标尺寸支持CSS单位
* @property {boolean} loading 加载状态(显示加载动画)
* @property {UTSJSONObject} loadingProps 加载动画配置
* @property {'rectangle' | 'square' | 'round' | 'circle'} shape 按钮形状
* @value rectangle 长方形(默认)
* @value square 正方形
* @value round 圆角矩形
* @value circle 圆形
* @property {SizeEnum} size 按钮尺寸
* @value mini 小号
* @value small 小号
* @value medium 中号(默认)
* @value large 大号
* @property {string} suffix 右侧附加内容(图标/文本)
* @property {'default' | 'primary' | 'danger' | 'warning' | 'success' | 'info'} type 色彩类型
* @value default
* @value primary
* @value danger
* @value warning
* @value success
* @value info
* @property {'solid' | 'outline' | 'text' | 'light' | 'dashed'} variant 样式变体
* @value solid
* @value outline
* @value text
* @value light
* @value dashed
* @property {string} radius 自定义圆角覆盖shape设置
* @property {string} fontSize 文字字号支持CSS单位
* @property {string} textColor 文字颜色支持CSS颜色值
* @property {string} color 主色(背景/边框色)
*
* @platform 微信小程序
* @property {string} formType 表单类型submit/reset
* @property {string} openType 开放能力contact/share等
* @property {string} lang 用户信息语言zh_CN/zh_TW/en
* @property {string} sessionFrom 会话来源contact模式有效
* @property {string} sendMessageTitle 消息卡片标题contact模式有效
* @property {string} sendMessagePath 消息跳转路径contact模式有效
* @property {string} sendMessageImg 消息卡片图片contact模式有效
* @property {string} appParameter APP启动参数launchApp模式
* @property {boolean} showMessageCard 显示消息卡片提示
*
* @property {string} hoverClass 点击态样式类默认button-hover
* @property {boolean} hoverStopPropagation 阻止祖先点击态
* @property {number} hoverStartTime 点击态延迟默认20ms
* @property {number} hoverStayTime 点击态保留时间默认70ms
* @event {Function} click 点击事件(禁用状态下不触发)
* @event {Function} getuserinfo 用户信息授权回调
* @event {Function} contact 客服会话回调
* @event {Function} agreeprivacyauthorization
* @event {Function} chooseavatar
* @event {Function} getphonenumber
* @event {Function} error
* @event {Function} opensetting
* @event {Function} launchapp
*/
import { ButtonProps } from './type'
// #ifdef APP
import { getCssVariableColor } from './utils'
// #endif
defineOptions({
behaviors: ['wx://form-field-button']
})
const emit = defineEmits(['click','agreeprivacyauthorization', 'chooseavatar', 'getuserinfo','contact', 'getphonenumber', 'error', 'opensetting', 'launchapp'])
const props = withDefaults(defineProps<ButtonProps>(), {
block: false,
disabled: false,
ghost: false,
loading: false,
shape: 'rectangle',
size: 'medium',
type: 'default',
// hoverClass: '',
hoverStopPropagation: false,
hoverStartTime: 20,
hoverStayTime: 70,
lang: 'en',
sessionFrom: '',
sendMessageTitle: '',
sendMessagePath: '',
sendMessageImg: '',
appParameter: '',
showMessageCard: false
// variant: 'solid'
})
const instance = getCurrentInstance()
// const rootRef = ref<UniElement|null>(null)
const buttonTextRef = ref<UniTextElement|null>(null)
const hasContent = computed(():boolean => {
return props.content != null || instance?.proxy?.$slots?.['default'] != null
})
const variant = computed(():string => props.variant ?? (props.color != null ? 'solid' : (props.type == 'default' ? 'outline': 'solid')))
const classes = computed(():Map<string, any>=>{
const cls = new Map<string, any>()
const name = 'l-button'
cls.set(`${name}--${props.size}`, true)
cls.set(`${name}--${props.type}`, true)
cls.set(`${name}--${variant.value}`, true)
cls.set(`${name}--${props.shape}`, true)
cls.set(`${name}--disabled`, props.disabled)
cls.set(`${name}--loading`, props.loading)
cls.set(`${name}--ghost`, props.ghost)
cls.set(`${name}--block`, props.block)
return cls
})
const styles = computed(():Map<string, any>=>{
const style = new Map<string, any>()
// #ifndef APP
if(props.gap) {
style.set('--l-button-gap', props.gap)
}
// #endif
if(props.radius != null) {
style.set('border-radius', props.radius!)
}
if(props.color != null) {
if(variant.value == 'solid') {
style.set('background', props.color!)
} else if(['outline', 'dashed'].includes(variant.value)) {
// #ifdef APP
style.set('border-color', props.color!)
// #endif
// #ifndef APP
style.set('--l-button-default-border-color', props.color!)
style.set('--l-button-border-color', props.color!)
// #endif
}
}
return style
})
const sizes = new Map<string, string>([
// #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
['mini', '16px'],
['small', '18px'],
['medium', '18px'],
['large', '24px'],
// #endif
])
const innerIconSize = computed(():string|null=> {
return props.iconSize ?? props.fontSize ?? sizes.get(props.size)
})
const colors = new Map<string, string>([
// #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
// ['default', 'rgba(0,0,0,0.88)'],
// ['primary', '#3283ff'],
// ['danger', '#FF4D4F'],
// ['warning', '#ffb400'],
// ['success', '#34c471'],
// ['info', '#3283ff'],
// #endif
])
const loadingColor = computed(():string|null => {
// #ifdef APP
console.log(`111props.textColor ?? (variant.value == 'solid' ? 'white' : getCssVariableColor(buttonTextRef.value)) ?? ''`, props.textColor ?? (variant.value == 'solid' ? 'white' : getCssVariableColor(buttonTextRef.value)) ?? '')
return props.textColor ?? (variant.value == 'solid' ? 'white' : getCssVariableColor(buttonTextRef.value)) ?? ''//colors.get(props.type))
// #endif
// #ifndef APP
return props.textColor ?? (variant.value == 'solid' ? 'white' : colors.get(props.type))
// #endif
})
const gapClass = computed((): string => {
return props.loading || props.icon != null ? 'gap' : ''
})
const contentStyle = computed(():Map<string, any> => {
const style = new Map<string, any>()
if(props.gap != null && (props.loading || props.icon != null)) {
style.set('margin-left', props.gap!)
}
if(props.textColor != null || props.color != null && variant.value != 'solid') {
style.set('color', (props.textColor ?? props.color)!)
}
if(props.fontSize != null) {
style.set('font-size', props.fontSize!)
}
return style
})
// #ifndef APP
const hoverClasses = computed(():string => {
return props.disabled || props.loading ? '' : (props.hoverClass || `l-button--hover`)
})
const computedVariant = computed(():string => props.variant ?? (props.color ? 'solid' : (props.type == 'default' ? 'outline': 'solid')))
// #endif
const getuserinfo = (e: UniEvent) => {
emit('getuserinfo', e);
}
const contact = (e: UniEvent) => {
emit('contact', e);
}
const getphonenumber = (e: UniEvent) => {
emit('getphonenumber', e);
}
const error = (e: UniEvent) => {
emit('error', e);
}
const opensetting = (e: UniEvent) => {
emit('opensetting', e);
}
const launchapp = (e: UniEvent) => {
emit('launchapp', e);
}
const chooseavatar = (e: UniEvent) => {
emit('chooseavatar', e);
}
const agreeprivacyauthorization = (e: UniEvent) => {
emit('agreeprivacyauthorization', e);
}
const handleTap = (e: UniPointerEvent)=>{
if (props.disabled || props.loading) return;
emit('click', e);
}
</script>
<style lang="scss">
@import './index-u';
</style>

View File

@@ -0,0 +1,217 @@
<template>
<button class="l-button l-class"
:id="lId"
:style="[styles, lStyle]"
:class="[
'l-button--' + size,
'l-button--' + type,
'l-button--' + shape,
'l-button--' + computedVariant,
{
'l-button--ghost': ghost,
'l-button--block': block,
'l-button--disabled': disabled,
'l-button--loading': loading,
}
]"
:form-type="disabled || loading ? '' : formType"
:open-type="disabled || loading ? '' : openType"
:hover-stop-propagation="hoverStopPropagation"
:hover-start-time="hoverStartTime"
:hover-stay-time="hoverStayTime" :lang="lang"
:session-from="sessionFrom"
:hover-class="hoverClasses"
:send-message-title="sendMessageTitle"
:send-message-path="sendMessagePath"
:send-message-img="sendMessageImg"
:app-parameter="appParameter"
:show-message-card="showMessageCard"
@tap.stop="handleTap"
@getuserinfo="getuserinfo"
@contact="contact"
@getphonenumber="getphonenumber"
@error="error"
@opensetting="opensetting"
@launchapp="launchapp"
@chooseavatar="chooseavatar"
@agreeprivacyauthorization="agreeprivacyauthorization"
:aria-label="ariaLabel"
:data-disabled="disabled||loading">
<view class="l-button__loading" v-if="loading">
<l-loading inheritColor></l-loading>
</view>
<l-icon class="l-button__icon" v-if="icon" :name="icon"></l-icon>
<view class="l-button__content" v-if="content || $slots.default">
<slot>{{content}}</slot>
</view>
</button>
</template>
<script lang="ts">
// @ts-nocheck
/**
* Button 按钮组件
* @description 提供丰富的按钮样式和交互功能,支持多种形态和平台特性
* <br> 插件类型LButtonComponentPublicInstance
* @tutorial https://ext.dcloud.net.cn/plugin?name=lime-button
*
* @property {string} ariaLabel 无障碍标签(用于屏幕阅读器)
* @property {boolean} block 块级布局(占满父容器宽度)
* @property {boolean} disabled 禁用状态
* @property {boolean} ghost 幽灵模式(透明背景+边框)
* @property {string} icon 左侧图标名称/路径
* @property {string} iconSize 图标尺寸支持CSS单位
* @property {boolean} loading 加载状态(显示加载动画)
* @property {UTSJSONObject} loadingProps 加载动画配置
* @property {'rectangle' | 'square' | 'round' | 'circle'} shape 按钮形状
* @value rectangle 长方形(默认)
* @value square 正方形
* @value round 圆角矩形
* @value circle 圆形
* @property {SizeEnum} size 按钮尺寸
* @value small 小号
* @value medium 中号(默认)
* @value large 大号
* @property {string} suffix 右侧附加内容(图标/文本)
* @property {'default' | 'primary' | 'danger' | 'warning' | 'success' | 'info'} type 色彩类型
* @value default
* @value primary
* @value danger
* @value warning
* @value success
* @value info
* @property {'solid' | 'outline' | 'text' | 'light' | 'dashed'} variant 样式变体
* @value solid
* @value outline
* @value text
* @value light
* @value dashed
* @property {string} radius 自定义圆角覆盖shape设置
* @property {string} fontSize 文字字号支持CSS单位
* @property {string} textColor 文字颜色支持CSS颜色值
* @property {string} color 主色(背景/边框色)
*
* @platform 微信小程序
* @property {string} formType 表单类型submit/reset
* @property {string} openType 开放能力contact/share等
* @property {string} lang 用户信息语言zh_CN/zh_TW/en
* @property {string} sessionFrom 会话来源contact模式有效
* @property {string} sendMessageTitle 消息卡片标题contact模式有效
* @property {string} sendMessagePath 消息跳转路径contact模式有效
* @property {string} sendMessageImg 消息卡片图片contact模式有效
* @property {string} appParameter APP启动参数launchApp模式
* @property {boolean} showMessageCard 显示消息卡片提示
*
* @property {string} hoverClass 点击态样式类默认button-hover
* @property {boolean} hoverStopPropagation 阻止祖先点击态
* @property {number} hoverStartTime 点击态延迟默认20ms
* @property {number} hoverStayTime 点击态保留时间默认70ms
* @event {Function} click 点击事件(禁用状态下不触发)
* @event {Function} getuserinfo 用户信息授权回调
* @event {Function} contact 客服会话回调
* @event {Function} agreeprivacyauthorization
* @event {Function} chooseavatar
* @event {Function} getphonenumber
* @event {Function} error
* @event {Function} opensetting
* @event {Function} launchapp
*/
import { computed, defineComponent } from '@/uni_modules/lime-shared/vue';
import ButtonProps from './props'
const name = 'l-button'
export default defineComponent({
name,
options: {
addGlobalClass: true,
virtualHost: true
},
behaviors: ['wx://form-field-button'],
externalClasses: ['l-class',`l-class-icon`, `l-class-loading`],
props: ButtonProps,
emits: ['click','agreeprivacyauthorization', 'chooseavatar', 'getuserinfo','contact', 'getphonenumber', 'error', 'opensetting', 'launchapp'],
setup(props, { emit }) {
const computedVariant = computed(():string => props.variant || (props.color ? 'solid' : (props.type == 'default' ? 'outline': 'solid')))
const classes = computed(() => {
return {
[`${name}--${props.size}`]: true,
[`${name}--${props.type}`]: true,
[`${name}--${props.shape}`]: true,
[`${name}--${computedVariant .value}`]: true,
// [`${name}--color`]: props.color,
[`${name}--ghost`]: props.ghost,
[`${name}--block`]: props.block,
[`${name}--disabled`]: props.disabled,
[`${name}--loading`]: props.loading,
}
})
const hoverClasses = computed(() => {
return props.disabled || props.loading ? '' : (props.hoverClass || `l-button--hover`)
})
const styles = computed(()=>{
const style:Record<string, any> = {}
if(props.gap) {
style['--l-button-gap'] = props.gap
}
if(props.color){
if(['outline'].includes(props.variant) ){
style['--l-button-border-color'] = props.color
style['color'] = props.color
} else {
style['--l-button-border-color'] = props.color
style['background'] = props.color
style['color'] = 'white'
}
}
return style
})
const getuserinfo = (e) => {
emit('getuserinfo', e);
}
const contact = (e) => {
emit('contact', e);
}
const getphonenumber = (e) => {
emit('getphonenumber', e);
}
const error = (e) => {
emit('error', e);
}
const opensetting = (e) => {
emit('opensetting', e);
}
const launchapp = (e) => {
emit('launchapp', e);
}
const chooseavatar = (e) => {
emit('chooseavatar', e);
}
const agreeprivacyauthorization = (e) => {
emit('agreeprivacyauthorization', e);
}
const handleTap = (e)=>{
if (props.disabled || props.loading) return;
emit('click', e);
}
return {
classes,
hoverClasses,
styles,
computedVariant,
agreeprivacyauthorization,
chooseavatar,
getuserinfo,
launchapp,
opensetting,
error,
getphonenumber,
contact,
handleTap
}
}
})
</script>
<style lang="scss">
@import './index-u';
</style>

View File

@@ -0,0 +1,152 @@
export const ariaProps = {
ariaHidden: Boolean,
ariaRole: String,
ariaLabel: String,
ariaLabelledby: String,
ariaDescribedby: String,
ariaBusy: Boolean,
lStyle: String
}
export default {
...ariaProps,
// lClass:String,
lId: String,
type: {
type: String,
default: 'default',
validator(val : string) : boolean {
return ['default', 'primary', 'danger', 'success', 'warning'].includes(val);
},
},
variant: {
type: String,
default: null,
validator(val : string) : boolean {
return ['solid', 'outline', 'dashed','text', 'light'].includes(val);
},
},
disabled: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
size: {
type: String,
default: 'medium',
validator(val : string) : boolean {
if (val == '') return true;
return ['mini', 'small', 'medium', 'large'].includes(val);
},
},
shape: {
type: String,
default: 'rectangle',
validator(val : string) : boolean {
return ['rectangle', 'square', 'round', 'circle'].includes(val);
},
},
icon: {
type: String
},
iconSize: {
type: String
},
block: {
type: Boolean,
default: false
},
ghost: {
type: Boolean,
default: false
},
content: {
type: String,
default: null
},
color: {
type: String,
default: null
},
radius: {
type: String,
default: null
},
fontSize: {
type: String,
default: null
},
textColor: {
type: String,
default: null
},
formType: {
type: String,
default: null
},
openType: {
type: String,
default: null
},
/** 指定按钮按下去的样式类,按钮不为加载或禁用状态时有效。当 `hover-class="none"` 时,没有点击态效果 */
hoverClass: {
type: String,
default: '',
},
/** 指定是否阻止本节点的祖先节点出现点击态 */
hoverStopPropagation: {
type: Boolean,
default: false,
},
/** 按住后多久出现点击态,单位毫秒 */
hoverStartTime: {
type: Number,
default: 20,
},
/** 手指松开后点击态保留时间,单位毫秒 */
hoverStayTime: {
type: Number,
default: 70,
},
/** 指定返回用户信息的语言zh_CN 简体中文zh_TW 繁体中文en 英文。。<br />具体释义:<br />`en` 英文;<br />`zh_CN` 简体中文;<br />`zh_TW` 繁体中文。<br />[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) */
lang: {
type: String,
default: 'en',
},
/** 会话来源open-type="contact"时有效 */
sessionFrom: {
type: String,
default: '',
},
/** 会话内消息卡片标题open-type="contact"时有效 */
sendMessageTitle: {
type: String,
default: '',
},
/** 会话内消息卡片点击跳转小程序路径open-type="contact"时有效 */
sendMessagePath: {
type: String,
default: '',
},
/** 会话内消息卡片图片open-type="contact"时有效 */
sendMessageImg: {
type: String,
default: '',
},
/** 打开 APP 时,向 APP 传递的参数open-type=launchApp时有效 */
appParameter: {
type: String,
default: '',
},
/** 是否显示会话内消息卡片,设置此参数为 true用户进入客服会话会在右下角显示"可能要发送的小程序"提示用户点击后可以快速发送小程序消息open-type="contact"时有效 */
showMessageCard: {
type: Boolean,
default: false,
},
gap: {
type: String
}
}

View File

@@ -0,0 +1,84 @@
// @ts-nocheck
export type SizeEnum = 'small' | 'medium' | 'large';
export interface ButtonProps {
ariaLabel?: string;
lId ?: string;
content ?: string
/**
* 是否为块级元素
*/
block : boolean;
/**
* 禁用状态
*/
disabled : boolean;
/**
* 是否为幽灵按钮(镂空按钮)
*/
ghost : boolean;
/**
* 按钮内部图标,可完全自定义
*/
icon ?: string;
iconSize ?: string;
/**
* 是否显示为加载状态
*/
loading : boolean;
/**
* 透传加载组件全部属性
*/
loadingProps ?: UTSJSONObject//LoadingProps;
/**
* 按钮形状:长方形、正方形、圆角长方形、圆形
*/
shape : 'rectangle' | 'square' | 'round' | 'circle';
/**
* 组件尺寸
*/
size : SizeEnum;
/**
* 右侧内容,可用于定义右侧图标
*/
suffix ?: string;
/**
* 组件风格,依次为品牌色、危险色、
*/
type : 'default' | 'primary' | 'danger' | 'warning' | 'success' | 'info';
/**
* 按钮形式,基础、线框、文字、高亮、虚线
*/
variant ?: 'solid' | 'outline' | 'text' | 'light' | 'dashed';
radius ?: string
fontSize ?: string;
textColor ?: string;
color ?: string;
lStyle?: string;
gap?: string;
formType ?: string
openType ?: string
/** 指定按钮按下去的样式类,按钮不为加载或禁用状态时有效。当 `hover-class="none"` 时,没有点击态效果 */
hoverClass ?: string
/** 指定是否阻止本节点的祖先节点出现点击态 */
hoverStopPropagation : boolean
/** 按住后多久出现点击态,单位毫秒 */
hoverStartTime : number
/** 手指松开后点击态保留时间,单位毫秒 */
hoverStayTime : number
/** 指定返回用户信息的语言zh_CN 简体中文zh_TW 繁体中文en 英文。。<br />具体释义:<br />`en` 英文;<br />`zh_CN` 简体中文;<br />`zh_TW` 繁体中文。<br />[小程序官方文档](https://developers.weixin.qq.com/miniprogram/dev/component/button.html) */
lang :string
/** 会话来源open-type="contact"时有效 */
sessionFrom : string,
/** 会话内消息卡片标题open-type="contact"时有效 */
sendMessageTitle : string,
/** 会话内消息卡片点击跳转小程序路径open-type="contact"时有效 */
sendMessagePath : string,
/** 会话内消息卡片图片open-type="contact"时有效 */
sendMessageImg : string,
/** 打开 APP 时,向 APP 传递的参数open-type=launchApp时有效 */
appParameter : string,
/** 是否显示会话内消息卡片,设置此参数为 true用户进入客服会话会在右下角显示"可能要发送的小程序"提示用户点击后可以快速发送小程序消息open-type="contact"时有效 */
showMessageCard : boolean,
}

View File

@@ -0,0 +1,39 @@
/**
* 简单检查是否是有效的颜色值
* @param {string} value
* @returns {boolean}
*/
function isValidColor(value : string | null) {
if (value == null) return false;
// 常见颜色格式检查
return (
// 颜色关键字red, blue 等)
/^[a-z]+$/i.test(value!) ||
// 十六进制(#fff, #ffffff
/^#([0-9a-f]{3}){1,2}$/i.test(value!) ||
// rgb/rgba
/^rgba?\([\s\d.,%]+\)$/.test(value!) ||
// hsl/hsla
/^hsla?\([\s\d.,%]+\)$/.test(value!)
);
}
export function getCssVariableColor(element : UniTextElement | null) : string | null {
if (element == null) return null
let value = element!.style.getPropertyValue('color').trim();
// 如果没有找到变量值,直接返回 null
if (value == '') return null;
if(value.startsWith('var(')) {
const innerVar = value.match(/var\(([^,)]+)(?:,\s*(.*))?\)/);
if(innerVar == null) return null
const [, , innerFallback] = innerVar!;
return innerFallback
} else {
return value
}
}