mirror of
https://gitee.com/xiangheng/x_admin.git
synced 2025-10-24 00:23:10 +08:00
增加app模板和代码生成
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
@import "./../common/abstracts/_mixin.scss";
|
||||
@import "./../common/abstracts/variable.scss";
|
||||
|
||||
.wot-theme-dark {
|
||||
@include b(input-number) {
|
||||
@include e(action) {
|
||||
color: $-dark-color;
|
||||
@include when(disabled) {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(input) {
|
||||
color: $-dark-color;
|
||||
}
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-input-number__input {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
.wd-input-number__sub,
|
||||
.wd-input-number__add {
|
||||
color: $-dark-color-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include b(input-number) {
|
||||
display: inline-block;
|
||||
user-select: none;
|
||||
line-height: 1.15;
|
||||
|
||||
@include e(action) {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: $-input-number-btn-width;
|
||||
height: $-input-number-height;
|
||||
vertical-align: middle;
|
||||
color: $-input-number-icon-color;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
box-sizing: border-box;
|
||||
|
||||
// 左右加减号的边框
|
||||
&::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: calc(200% - 2px);
|
||||
height: calc(200% - 2px);
|
||||
left: 0;
|
||||
top: 0;
|
||||
border: 1px solid $-input-number-border-color;
|
||||
border-top-left-radius: calc($-input-number-radius * 2);
|
||||
border-bottom-left-radius: calc($-input-number-radius * 2);
|
||||
transform: scale(0.5);
|
||||
transform-origin: left top;
|
||||
}
|
||||
&:last-child::after {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-right-radius: calc($-input-number-radius * 2);
|
||||
border-bottom-right-radius: calc($-input-number-radius * 2);
|
||||
}
|
||||
@include when(disabled) {
|
||||
color: $-input-number-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
@include e(inner) {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
@include e(input) {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: $-input-number-input-width;
|
||||
height: $-input-number-height;
|
||||
padding: 0 2px;
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
text-align: center;
|
||||
color: $-input-number-color;
|
||||
font-size: $-input-number-fs;
|
||||
-webkit-appearance: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
@include e(input-border) {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: calc(200% - 2px);
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-top: 1px solid $-input-number-border-color;
|
||||
border-bottom: 1px solid $-input-number-border-color;
|
||||
transform: scaleY(0.5);
|
||||
transform-origin: left top;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@include edeep(action-icon) {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
font-size: $-input-number-icon-size;
|
||||
width: $-input-number-icon-size;
|
||||
height: $-input-number-icon-size;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@include when(disabled) {
|
||||
.wd-input-number__input {
|
||||
color: $-input-number-disabled-color;
|
||||
z-index: inherit;
|
||||
}
|
||||
.wd-input-number__sub,
|
||||
.wd-input-number__add {
|
||||
color: $-input-number-disabled-color;
|
||||
}
|
||||
}
|
||||
@include when(without-input) {
|
||||
.wd-input-number__action:last-child::after {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-03-15 20:40:34
|
||||
* @LastEditTime: 2024-03-18 14:58:47
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-input-number\types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import { baseProps, makeBooleanProp, makeNumberProp, makeNumericProp, makeRequiredProp, makeStringProp, numericProp } from '../common/props'
|
||||
|
||||
export const inputNumberProps = {
|
||||
...baseProps,
|
||||
/**
|
||||
* 绑定值
|
||||
*/
|
||||
modelValue: makeRequiredProp(numericProp),
|
||||
/**
|
||||
* 最小值
|
||||
*/
|
||||
min: makeNumberProp(1),
|
||||
/**
|
||||
* 最大值
|
||||
*/
|
||||
max: makeNumberProp(Number.MAX_SAFE_INTEGER),
|
||||
/**
|
||||
* 步进值
|
||||
*/
|
||||
step: makeNumberProp(1),
|
||||
/**
|
||||
* 是否严格按照步进值递增或递减
|
||||
*/
|
||||
stepStrictly: makeBooleanProp(false),
|
||||
/**
|
||||
* 数值精度
|
||||
*/
|
||||
precision: makeNumberProp(0),
|
||||
/**
|
||||
* 是否禁用
|
||||
*/
|
||||
disabled: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否禁用输入框
|
||||
*/
|
||||
disableInput: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否禁用减号按钮
|
||||
*/
|
||||
disableMinus: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否禁用加号按钮
|
||||
*/
|
||||
disablePlus: makeBooleanProp(false),
|
||||
/**
|
||||
* 是否不显示输入框
|
||||
*/
|
||||
withoutInput: makeBooleanProp(false),
|
||||
/**
|
||||
* 输入框宽度
|
||||
*/
|
||||
inputWidth: makeNumericProp(36),
|
||||
/**
|
||||
* 是否允许为空
|
||||
*/
|
||||
allowNull: makeBooleanProp(false),
|
||||
/**
|
||||
* 输入框占位符
|
||||
*/
|
||||
placeholder: makeStringProp('')
|
||||
}
|
@@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<view :class="`wd-input-number ${customClass} ${disabled ? 'is-disabled' : ''} ${withoutInput ? 'is-without-input' : ''}`" :style="customStyle">
|
||||
<view :class="`wd-input-number__action ${minDisabled || disableMinus ? 'is-disabled' : ''}`" @click="sub">
|
||||
<wd-icon name="decrease" custom-class="wd-input-number__action-icon"></wd-icon>
|
||||
</view>
|
||||
<view v-if="!withoutInput" class="wd-input-number__inner" @click.stop="">
|
||||
<input
|
||||
class="wd-input-number__input"
|
||||
:style="`${inputWidth ? 'width: ' + inputWidth : ''}`"
|
||||
type="digit"
|
||||
:disabled="disabled || disableInput"
|
||||
v-model="inputValue"
|
||||
:placeholder="placeholder"
|
||||
@input="handleInput"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
<view class="wd-input-number__input-border"></view>
|
||||
</view>
|
||||
<view :class="`wd-input-number__action ${maxDisabled || disablePlus ? 'is-disabled' : ''}`" @click="add">
|
||||
<wd-icon name="add" custom-class="wd-input-number__action-icon"></wd-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'wd-input-number',
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { debounce, isDef, isEqual } from '../common/util'
|
||||
import { inputNumberProps } from './types'
|
||||
|
||||
const props = defineProps(inputNumberProps)
|
||||
const emit = defineEmits(['focus', 'blur', 'change', 'update:modelValue'])
|
||||
|
||||
const minDisabled = ref<boolean>(false)
|
||||
const maxDisabled = ref<boolean>(false)
|
||||
const inputValue = ref<string | number>('') // 输入框的值
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
inputValue.value = newValue
|
||||
splitDisabled(newValue)
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
[() => props.max, () => props.min],
|
||||
() => {
|
||||
updateBoundary()
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.disabled,
|
||||
(newValue) => {
|
||||
minDisabled.value = newValue
|
||||
maxDisabled.value = newValue
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
)
|
||||
|
||||
function updateBoundary() {
|
||||
debounce(() => {
|
||||
const value = formatValue(inputValue.value)
|
||||
if (!isEqual(inputValue.value, value)) {
|
||||
setValue(value)
|
||||
}
|
||||
splitDisabled(value)
|
||||
}, 30)()
|
||||
}
|
||||
|
||||
function splitDisabled(value: number | string) {
|
||||
const { disabled, min, max, step } = props
|
||||
minDisabled.value = disabled || Number(value) <= min || changeStep(value, -step) < min
|
||||
maxDisabled.value = disabled || Number(value) >= max || changeStep(value, step) > max
|
||||
}
|
||||
|
||||
function toPrecision(value: number) {
|
||||
return Number(parseFloat(`${Math.round(value * Math.pow(10, props.precision)) / Math.pow(10, props.precision)}`).toFixed(props.precision))
|
||||
}
|
||||
|
||||
function getPrecision(value?: number) {
|
||||
if (value === undefined) return 0
|
||||
const valueString = value.toString()
|
||||
const dotPosition = valueString.indexOf('.')
|
||||
let precision = 0
|
||||
if (dotPosition !== -1) {
|
||||
precision = valueString.length - dotPosition - 1
|
||||
}
|
||||
return precision
|
||||
}
|
||||
|
||||
function toStrictlyStep(value: number | string) {
|
||||
const stepPrecision = getPrecision(props.step)
|
||||
const precisionFactory = Math.pow(10, stepPrecision)
|
||||
return (Math.round(Number(value) / props.step) * precisionFactory * props.step) / precisionFactory
|
||||
}
|
||||
|
||||
function setValue(value: string | number, change: boolean = true) {
|
||||
if (props.allowNull && (!isDef(value) || value === '')) {
|
||||
dispatchChangeEvent(value, change)
|
||||
return
|
||||
}
|
||||
|
||||
if (props.stepStrictly) {
|
||||
value = toStrictlyStep(value)
|
||||
}
|
||||
if ((value || value === 0) && props.precision !== undefined) {
|
||||
value = toPrecision(Number(value))
|
||||
}
|
||||
if (Number(value) > props.max) value = toPrecision(props.max)
|
||||
if (Number(value) < props.min) value = toPrecision(props.min)
|
||||
|
||||
dispatchChangeEvent(value, change)
|
||||
}
|
||||
|
||||
function changeStep(val: string | number, step: number) {
|
||||
val = Number(val)
|
||||
|
||||
if (isNaN(val)) {
|
||||
return props.min
|
||||
}
|
||||
|
||||
const precisionFactory = Math.pow(10, props.precision)
|
||||
return toPrecision((val * precisionFactory + step * precisionFactory) / precisionFactory)
|
||||
}
|
||||
|
||||
function sub() {
|
||||
if (minDisabled.value || props.disableMinus) return
|
||||
|
||||
const newValue = changeStep(inputValue.value, -props.step)
|
||||
dispatchChangeEvent(newValue)
|
||||
}
|
||||
|
||||
function add() {
|
||||
if (maxDisabled.value || props.disablePlus) return
|
||||
|
||||
const newValue = changeStep(inputValue.value, props.step)
|
||||
dispatchChangeEvent(newValue)
|
||||
}
|
||||
|
||||
function handleInput(event: any) {
|
||||
const value = event.detail.value || ''
|
||||
dispatchChangeEvent(value)
|
||||
}
|
||||
|
||||
function handleFocus(event: any) {
|
||||
emit('focus', event.detail)
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
const value = formatValue(inputValue.value)
|
||||
if (!isEqual(inputValue.value, value)) {
|
||||
setValue(value)
|
||||
}
|
||||
emit('blur', {
|
||||
value
|
||||
})
|
||||
}
|
||||
|
||||
function dispatchChangeEvent(value: string | number, change: boolean = true) {
|
||||
if (isEqual(inputValue.value, value)) {
|
||||
return
|
||||
}
|
||||
inputValue.value = value
|
||||
change && emit('update:modelValue', inputValue.value)
|
||||
change && emit('change', { value })
|
||||
}
|
||||
|
||||
function formatValue(value: string | number) {
|
||||
if (props.allowNull && (!isDef(value) || value === '')) {
|
||||
return ''
|
||||
}
|
||||
|
||||
value = Number(value)
|
||||
|
||||
if (isNaN(value)) {
|
||||
value = props.min
|
||||
}
|
||||
|
||||
if (props.stepStrictly) {
|
||||
value = toStrictlyStep(value)
|
||||
}
|
||||
|
||||
if (props.precision !== undefined) {
|
||||
value = value.toFixed(props.precision)
|
||||
}
|
||||
|
||||
return Number(value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './index.scss';
|
||||
</style>
|
Reference in New Issue
Block a user