智能柜补货
This commit is contained in:
1 parent
587858fc74
commit
eb57fc50b0
10 files changed
+1148
-812
No files matched your search
@@ -335,6 +335,20 @@
|
||||
"navigationBarTitleText": "智能柜列表",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "replenishment",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商品补货",
|
||||
"disableScroll": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "putaway",
|
||||
"style": {
|
||||
"navigationBarTitleText": "商品上架",
|
||||
"disableScroll": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+14
-32
@@ -1,68 +1,50 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<view class="bg-white rounded-16rpx mx-2 my-40rpx animate-both">
|
||||
<view class="bg-white rounded-20rpx my-20rpx font-bold">
|
||||
<z-tabs
|
||||
:list="[
|
||||
{ name: '浙政钉支付', value: 1 },
|
||||
{ name: '支付宝支付', value: 2, disabled: true },
|
||||
]"
|
||||
bar-width="300"
|
||||
bar-height="0"
|
||||
bar-width="150"
|
||||
:active-style="{
|
||||
width: '300rpx',
|
||||
height: '70rpx',
|
||||
backgroundColor: '#0779FDdd',
|
||||
color: '#ffffff',
|
||||
textAlign: 'center',
|
||||
lineHeight: '70rpx',
|
||||
fontWeight: 'light',
|
||||
fontSize: '30rpx',
|
||||
borderRadius: '10rpx',
|
||||
marginTop: '10rpx',
|
||||
}"
|
||||
:inactive-style="{
|
||||
width: '300rpx',
|
||||
height: '70rpx',
|
||||
color: '#000000',
|
||||
textAlign: 'center',
|
||||
lineHeight: '70rpx',
|
||||
fontWeight: 'light',
|
||||
fontSize: '30rpx',
|
||||
borderRadius: '10rpx',
|
||||
marginTop: '10rpx',
|
||||
}"
|
||||
@change="payMethodTabChange"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<tm-sheet v-if="!state.isUseDoor && state.isUseDoorTip" borderWidth="2" margin="40" padding="10" color="#0094FF22">
|
||||
<tm-sheet v-if="!state.isUseDoor && state.isUseDoorTip" borderWidth="2" :margin="[0, 20]" padding="10" color="#0094FF22">
|
||||
<view class="flex items-center justify-between pl-4">
|
||||
<tm-text font-size="30 " color="#0779FD">{{ state.isUseDoorTip }}</tm-text>
|
||||
<tm-button size="m" @click="goRecharge">去充值</tm-button>
|
||||
<tm-button size="s" @click="goRecharge">去充值</tm-button>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
|
||||
<tm-sheet>
|
||||
<tm-sheet margin="0">
|
||||
<tm-text font-size="30">购买须知:</tm-text>
|
||||
<view class="flex items-center px-10rpx py-20rpx">
|
||||
<image class="w-60rpx h-60rpx mr-3" src="@/static/page/印章.svg" />
|
||||
<view class="flex items-center p-10rpx">
|
||||
<image class="w-50rpx h-50rpx mr-3" src="@/static/page/印章.svg" />
|
||||
<view>
|
||||
<view class="second-text-26">第一步</view>
|
||||
<tm-text font-size="30">购买需钱包余额大于100元</tm-text>
|
||||
<tm-text font-size="28">购买需钱包余额大于100元</tm-text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center px-10rpx py-20rpx">
|
||||
<image class="w-60rpx h-60rpx mr-3" src="@/static/page/开门.svg" />
|
||||
<view class="flex items-center p-10rpx">
|
||||
<image class="w-50rpx h-50rpx mr-3" src="@/static/page/开门.svg" />
|
||||
<view>
|
||||
<view class="second-text-26">第二步</view>
|
||||
<tm-text font-size="30">开门之后选取商品并关门</tm-text>
|
||||
<tm-text font-size="28">开门之后选取商品并关门</tm-text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex items-center px-10rpx py-20rpx">
|
||||
<image class="w-60rpx h-60rpx mr-3" src="@/static/page/支付.svg" />
|
||||
<view class="flex items-center p-10rpx">
|
||||
<image class="w-50rpx h-50rpx mr-3" src="@/static/page/支付.svg" />
|
||||
<view>
|
||||
<view class="second-text-26">第三步</view>
|
||||
<tm-text font-size="30">关门后自动结算</tm-text>
|
||||
<tm-text font-size="28">关门后自动结算</tm-text>
|
||||
</view>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
>
|
||||
<view class="h-30rpx" />
|
||||
<tm-collapse :multiple="false">
|
||||
<tm-collapse-item
|
||||
v-for="(item, index) in new Array(3).fill({})"
|
||||
:key="index"
|
||||
left-icon="settings-line"
|
||||
:name="index"
|
||||
title="柜子123"
|
||||
>
|
||||
<tm-text class="line-10">地址:123</tm-text>
|
||||
<view class="card flex justify-around items-center">
|
||||
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8">
|
||||
<image class="w-60 h-60" src="@/static/page/开门.svg" />
|
||||
<text>货柜详情</text>
|
||||
</view>
|
||||
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="replenishment">
|
||||
<image class="w-60 h-60" src="@/static/page/开门.svg" />
|
||||
<text>货柜补货</text>
|
||||
</view>
|
||||
<view class="flex-col items-center p-2 rounded-1 active:bg-#E8E8E8" @click="openPutaway">
|
||||
<image class="w-60 h-60" src="@/static/page/开门.svg" />
|
||||
<text>商品上架</text>
|
||||
</view>
|
||||
</view>
|
||||
</tm-collapse-item>
|
||||
</tm-collapse>
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { router } from "@/sheep"
|
||||
|
||||
// 商品补货
|
||||
const replenishment = () => {
|
||||
router.jump("/pages/cabinet/replenishment", {}, 1)
|
||||
}
|
||||
|
||||
// 商品上架
|
||||
const openPutaway = () => {
|
||||
router.jump("/pages/cabinet/putaway", {}, 1)
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
>
|
||||
<template #top>
|
||||
<view class="h-30rpx" />
|
||||
<tm-tabs
|
||||
item-width="50%"
|
||||
gap="0"
|
||||
line-full
|
||||
line-height="4rpx"
|
||||
round="10"
|
||||
active-title-color=""
|
||||
:list="['门1', '门2']"
|
||||
@change="doorTabsChange"
|
||||
/>
|
||||
<view class="h-10rpx" />
|
||||
</template>
|
||||
|
||||
<view class="w-full w-full">
|
||||
<view v-for="(item, index) in new Array(6).fill(new Array(10)).map((item) => item.fill({}))" :key="index">
|
||||
<tm-text class="text-center mt-4">第 {{ index + 1 }} 层</tm-text>
|
||||
<view class="flex flex-wrap">
|
||||
<view v-for="(v, i) in item" :key="i" class="w-1/4 h-200 p-1">
|
||||
<view class="card w-full h-full p-2 flex items-center justify-center active:bg-#e8e8e8!" @click="doPutaway">
|
||||
<image class="w-half h-half" src="@/static/page/加号.svg" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="h-30rpx" />
|
||||
</z-paging>
|
||||
|
||||
<tm-drawer
|
||||
title="选择商品"
|
||||
:showClose="true"
|
||||
:showFooter="true"
|
||||
size="90%"
|
||||
placement="bottom"
|
||||
v-model:show="state.showDrawer"
|
||||
zIndex="999"
|
||||
>
|
||||
<tm-tabs
|
||||
item-width="50%"
|
||||
gap="0"
|
||||
line-full
|
||||
line-height="4rpx"
|
||||
round="10"
|
||||
active-title-color=""
|
||||
:list="['平台商品', '我的商品']"
|
||||
@change="goodsTabsChange"
|
||||
/>
|
||||
<view class="h-30rpx" />
|
||||
|
||||
<tm-checkbox-group v-model="state.checkboxValue" direction="column">
|
||||
<view
|
||||
v-for="(item, index) in listview"
|
||||
:key="index"
|
||||
class="w-full h-100rpx flex items-center p-2 border-1 border-solid border-b-coolGray"
|
||||
:class="[state.checkboxValue.includes(item.id) ? 'bg-#e8e8e8' : '']"
|
||||
>
|
||||
<tm-checkbox class="w-full h-full" :value="item.id">
|
||||
<template v-slot:label="checked">
|
||||
<tm-text>{{ 11111 }}</tm-text>
|
||||
</template>
|
||||
</tm-checkbox>
|
||||
</view>
|
||||
</tm-checkbox-group>
|
||||
|
||||
<view class="h-30rpx" />
|
||||
|
||||
<template #footer>
|
||||
<view class="px-20rpx flex justify-between">
|
||||
<tm-button skin="thin" block>取消</tm-button>
|
||||
|
||||
<tm-button block>上架</tm-button>
|
||||
</view>
|
||||
</template>
|
||||
</tm-drawer>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue"
|
||||
|
||||
const state = reactive<any>({
|
||||
curDoorTabIndex: 0,
|
||||
curGoodsTabIndex: 0,
|
||||
showDrawer: false,
|
||||
checkboxValue: [],
|
||||
})
|
||||
|
||||
const listview = ref<any>([
|
||||
{ text: "科技创新引领制造业高质量发展", id: 1 },
|
||||
{ text: "明确提出“建立保持制造业合理比重投入机制”。", id: 2 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 3 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 4 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 5 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 6 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 7 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 8 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 9 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 10 },
|
||||
])
|
||||
|
||||
const doorTabsChange = (index: number) => {
|
||||
state.curDoorTabIndex = index
|
||||
}
|
||||
|
||||
const goodsTabsChange = (index: number) => {
|
||||
state.curGoodsTabIndex = index
|
||||
}
|
||||
|
||||
// 上架
|
||||
const doPutaway = () => {
|
||||
state.curGoodsTabIndex = 0
|
||||
state.showDrawer = true
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<crud-layout bg="/static/page/blue-bg.png">
|
||||
<z-paging
|
||||
ref="pageRef"
|
||||
height="100%"
|
||||
:fixed="false"
|
||||
safe-area-inset-bottom
|
||||
:loading-more-enabled="true"
|
||||
:show-scrollbar="false"
|
||||
:auto-clean-list-when-reload="false"
|
||||
:auto-scroll-to-top-when-reload="false"
|
||||
>
|
||||
<template #top>
|
||||
<view class="bg-white rounded-20rpx my-20rpx font-bold">
|
||||
<z-tabs
|
||||
:list="[
|
||||
{ name: '门1', value: 1 },
|
||||
{ name: '门2', value: 2 },
|
||||
]"
|
||||
bar-width="150"
|
||||
:active-style="{
|
||||
fontSize: '30rpx',
|
||||
}"
|
||||
:inactive-style="{
|
||||
fontSize: '30rpx',
|
||||
}"
|
||||
@change="doorTabsChange"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<tm-sheet v-for="(item, index) in listview" :key="index" :margin="[0, 20]">
|
||||
<view class="flex">
|
||||
<image class="w-120rpx h-120rpx" />
|
||||
<view class="ml-2 flex-1 flex-col">
|
||||
<tm-text font-size="32">更改圆角</tm-text>
|
||||
<view class="flex justify-between my-1">
|
||||
<tm-text font-size="26">规格:</tm-text>
|
||||
<tm-text font-size="26">规格:</tm-text>
|
||||
</view>
|
||||
<view class="flex justify-end items-center">
|
||||
<tm-text font-size="30">库存:</tm-text>
|
||||
<tm-stepper width="200" v-model="item.stock" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</tm-sheet>
|
||||
</z-paging>
|
||||
|
||||
<template #main-bottom>
|
||||
<view class="m-30rpx flex justify-between">
|
||||
<tm-button block @click="openDoor" :disabled="!state.isUseDoor">一键补满</tm-button>
|
||||
|
||||
<tm-button block @click="openDoor" :disabled="!state.isUseDoor">开 门</tm-button>
|
||||
|
||||
<tm-button block @click="save" :disabled="!state.isUseDoor">保 存</tm-button>
|
||||
</view>
|
||||
</template>
|
||||
</crud-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from "vue"
|
||||
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
|
||||
|
||||
const listview = ref<any>([
|
||||
{ text: "科技创新引领制造业高质量发展", id: 1 },
|
||||
{ text: "明确提出“建立保持制造业合理比重投入机制”。", id: 2 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 3 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 4 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 5 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 6 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 7 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 8 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 9 },
|
||||
{ text: "改造提升传统产业,培育壮大新兴产业,布局建设未来产业,完善现代化产业体系", id: 10 },
|
||||
])
|
||||
|
||||
const state = reactive({
|
||||
curDoorTabIndex: 0,
|
||||
})
|
||||
|
||||
// 柜门tab切换
|
||||
const doorTabsChange = (e: number) => {
|
||||
state.curDoorTabIndex = e
|
||||
}
|
||||
</script>
|
||||
@@ -76,6 +76,7 @@ const state = reactive<{
|
||||
// { text: "外来人员就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/foreign-list" },
|
||||
// { text: "跨单位就餐", icon: "/static/icon/service_1.png", router: "/pages/apply/stride-list" },
|
||||
{ text: "人脸管理", icon: "/static/icon/service_5.png", router: "/pages/human-face/list" },
|
||||
{ text: "智能柜列表", icon: "/static/icon/service_5.png", router: "/pages/cabinet/cabinetList" },
|
||||
// { text: "意见反馈", icon: "/static/icon/service_5.png", router: "/pages/integrated/feedback/index" },
|
||||
],
|
||||
appInfo: "",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1744875639609" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2836" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M512 0c-285.257143 0-512 226.742857-512 512s226.742857 512 512 512 512-226.742857 512-512-226.742857-512-512-512z m0 950.857143c-241.371429 0-438.857143-197.485714-438.857143-438.857143s197.485714-438.857143 438.857143-438.857143 438.857143 197.485714 438.857143 438.857143-197.485714 438.857143-438.857143 438.857143z" fill="#707070" p-id="2837"></path><path d="M731.428571 475.428571h-182.857142v-182.857142c0-21.942857-14.628571-36.571429-36.571429-36.571429s-36.571429 14.628571-36.571429 36.571429v182.857142h-182.857142c-21.942857 0-36.571429 14.628571-36.571429 36.571429s14.628571 36.571429 36.571429 36.571429h182.857142v182.857142c0 21.942857 14.628571 36.571429 36.571429 36.571429s36.571429-14.628571 36.571429-36.571429v-182.857142h182.857142c21.942857 0 36.571429-14.628571 36.571429-36.571429s-14.628571-36.571429-36.571429-36.571429z" fill="#707070" p-id="2838"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,8 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch, PropType } from 'vue'
|
||||
import { arrayNumberValid, arrayNumberValidByStyleMP, covetUniNumber, arrayNumberValidByStyleBorderColor, linearValid, getUnit } from "../../libs/tool";
|
||||
import { getDefaultColor, getDefaultColorObj, getOutlineColorObj, getTextColorObj, getThinColorObj } from "../../libs/colors";
|
||||
import { useTmConfig } from "../../libs/config";
|
||||
import { ref, computed, onMounted, watch } from "vue"
|
||||
import {
|
||||
arrayNumberValid,
|
||||
arrayNumberValidByStyleMP,
|
||||
covetUniNumber,
|
||||
arrayNumberValidByStyleBorderColor,
|
||||
linearValid,
|
||||
getUnit,
|
||||
} from "../../libs/tool"
|
||||
import { getDefaultColor, getDefaultColorObj, getOutlineColorObj, getTextColorObj, getThinColorObj } from "../../libs/colors"
|
||||
import { useTmConfig } from "../../libs/config"
|
||||
/**
|
||||
* @displayName 角标
|
||||
* @exportName tm-badge
|
||||
@@ -13,210 +20,204 @@ import { useTmConfig } from "../../libs/config";
|
||||
| --- | --- | --- | --- |
|
||||
| ☑️| ☑️ | ☑️ | ☑️ | ☑️ | 1.0.0 |
|
||||
*/
|
||||
defineOptions({ name: 'TmBadge' });
|
||||
defineOptions({ name: "TmBadge" })
|
||||
const { config } = useTmConfig()
|
||||
|
||||
const attrs = defineProps({
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: "20"
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: "error"
|
||||
},
|
||||
fontColor: {
|
||||
type: String,
|
||||
default: "white"
|
||||
},
|
||||
maxCount: {
|
||||
type: [String, Number],
|
||||
default: 99
|
||||
},
|
||||
/**
|
||||
* 如果是boolean就显示角标小红点
|
||||
* 如果是string显示文本标签
|
||||
* 如果是数字显示数字并启用maxCount
|
||||
*/
|
||||
label: {
|
||||
type: [String, Number,Boolean],
|
||||
default: ""
|
||||
},
|
||||
position: {
|
||||
type: String as PropType<"right" | "left" | "bottomLeft" | "bottomRight" | 'top' | 'bottom'>,
|
||||
default: "right"
|
||||
},
|
||||
offset: {
|
||||
type: Array as PropType<number[]>,
|
||||
default: (): number[] => [0, 0] as number[],
|
||||
validator(val: number[]): boolean {
|
||||
if (val.length == 0 || val.length == 2) return true
|
||||
console.error("x:必须是长度为2的数字数组参数或者空数组")
|
||||
return false
|
||||
}
|
||||
}
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: "20",
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: "error",
|
||||
},
|
||||
fontColor: {
|
||||
type: String,
|
||||
default: "white",
|
||||
},
|
||||
maxCount: {
|
||||
type: [String, Number],
|
||||
default: 99,
|
||||
},
|
||||
/**
|
||||
* 如果是boolean就显示角标小红点
|
||||
* 如果是string显示文本标签
|
||||
* 如果是数字显示数字并启用maxCount
|
||||
*/
|
||||
label: {
|
||||
type: [String, Number, Boolean],
|
||||
default: "",
|
||||
},
|
||||
// "right" | "left" | "bottomLeft" | "bottomRight" | "top" | "bottom"
|
||||
position: {
|
||||
type: String,
|
||||
default: "right",
|
||||
},
|
||||
// number[]
|
||||
offset: {
|
||||
type: Array,
|
||||
default: (): number[] => [0, 0] as number[],
|
||||
validator(val: number[]): boolean {
|
||||
if (val.length == 0 || val.length == 2) return true
|
||||
console.error("x:必须是长度为2的数字数组参数或者空数组")
|
||||
return false
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
const _offset = computed(() => attrs.offset)
|
||||
const _isDot = computed(() => {
|
||||
if(typeof attrs.label === 'boolean') return attrs.label
|
||||
return false;
|
||||
if (typeof attrs.label === "boolean") return attrs.label
|
||||
return false
|
||||
})
|
||||
|
||||
const _cStyles = computed(() => {
|
||||
let trs = ''
|
||||
if (attrs.position == 'right') {
|
||||
trs = 'translate(50%, -50%)'
|
||||
} else if (attrs.position == 'left') {
|
||||
trs = 'translate(-50%, -50%)'
|
||||
} else if (attrs.position == 'bottomLeft') {
|
||||
trs = 'translate(-50%, 50%)'
|
||||
} else if (attrs.position == 'bottomRight') {
|
||||
trs = 'translate(50%, 50%)'
|
||||
} else if (attrs.position == 'top') {
|
||||
trs = 'translate(0%, -50%)'
|
||||
} else if (attrs.position == 'bottom') {
|
||||
trs = 'translate(0%, 50%)'
|
||||
}
|
||||
let trs = ""
|
||||
if (attrs.position == "right") {
|
||||
trs = "translate(50%, -50%)"
|
||||
} else if (attrs.position == "left") {
|
||||
trs = "translate(-50%, -50%)"
|
||||
} else if (attrs.position == "bottomLeft") {
|
||||
trs = "translate(-50%, 50%)"
|
||||
} else if (attrs.position == "bottomRight") {
|
||||
trs = "translate(50%, 50%)"
|
||||
} else if (attrs.position == "top") {
|
||||
trs = "translate(0%, -50%)"
|
||||
} else if (attrs.position == "bottom") {
|
||||
trs = "translate(0%, 50%)"
|
||||
}
|
||||
|
||||
let top = ''
|
||||
let bottom = ''
|
||||
let left = ''
|
||||
let right = ''
|
||||
let top = ""
|
||||
let bottom = ""
|
||||
let left = ""
|
||||
let right = ""
|
||||
|
||||
if (attrs.position == 'top') {
|
||||
top = '0px'
|
||||
left = 'auto'
|
||||
right = 'auto'
|
||||
} else if (attrs.position == 'bottom') {
|
||||
bottom = '0px'
|
||||
left = 'auto'
|
||||
right = 'auto'
|
||||
} else if (attrs.position == 'right') {
|
||||
top = _offset.value[1].toString() + 'px'
|
||||
right = _offset.value[0].toString() + 'px'
|
||||
} else if (attrs.position == 'left') {
|
||||
top = '0px'
|
||||
left = '0px'
|
||||
} else if (attrs.position == 'bottomLeft') {
|
||||
bottom = '0px'
|
||||
left = '0px'
|
||||
} else if (attrs.position == 'bottomRight') {
|
||||
bottom = '0px'
|
||||
right = '0px'
|
||||
}
|
||||
if (attrs.position == "top") {
|
||||
top = "0px"
|
||||
left = "auto"
|
||||
right = "auto"
|
||||
} else if (attrs.position == "bottom") {
|
||||
bottom = "0px"
|
||||
left = "auto"
|
||||
right = "auto"
|
||||
} else if (attrs.position == "right") {
|
||||
top = _offset.value[1].toString() + "px"
|
||||
right = _offset.value[0].toString() + "px"
|
||||
} else if (attrs.position == "left") {
|
||||
top = "0px"
|
||||
left = "0px"
|
||||
} else if (attrs.position == "bottomLeft") {
|
||||
bottom = "0px"
|
||||
left = "0px"
|
||||
} else if (attrs.position == "bottomRight") {
|
||||
bottom = "0px"
|
||||
right = "0px"
|
||||
}
|
||||
|
||||
let dotMapCs:{[key:string]:any} = {}
|
||||
dotMapCs['background'] = getDefaultColor(attrs.bgColor)
|
||||
dotMapCs['left'] = left
|
||||
dotMapCs['right'] = right
|
||||
dotMapCs['top'] = top
|
||||
dotMapCs['bottom'] = bottom
|
||||
dotMapCs['transform'] = trs
|
||||
let dotMapCs: { [key: string]: any } = {}
|
||||
dotMapCs["background"] = getDefaultColor(attrs.bgColor)
|
||||
dotMapCs["left"] = left
|
||||
dotMapCs["right"] = right
|
||||
dotMapCs["top"] = top
|
||||
dotMapCs["bottom"] = bottom
|
||||
dotMapCs["transform"] = trs
|
||||
|
||||
let labelMapCs:{[key:string]:any} = {}
|
||||
labelMapCs['background'] = getDefaultColor(attrs.bgColor)
|
||||
labelMapCs['left'] = left
|
||||
labelMapCs['right'] = right
|
||||
labelMapCs['top'] = top
|
||||
labelMapCs['bottom'] = bottom
|
||||
labelMapCs['transform'] = trs
|
||||
labelMapCs['visibility'] = _label.value == "" ? "hidden" : "visible"
|
||||
|
||||
return [dotMapCs, labelMapCs]
|
||||
let labelMapCs: { [key: string]: any } = {}
|
||||
labelMapCs["background"] = getDefaultColor(attrs.bgColor)
|
||||
labelMapCs["left"] = left
|
||||
labelMapCs["right"] = right
|
||||
labelMapCs["top"] = top
|
||||
labelMapCs["bottom"] = bottom
|
||||
labelMapCs["transform"] = trs
|
||||
labelMapCs["visibility"] = _label.value == "" ? "hidden" : "visible"
|
||||
|
||||
return [dotMapCs, labelMapCs]
|
||||
})
|
||||
|
||||
const _fontColor = computed(() => getDefaultColor(attrs.fontColor))
|
||||
const _fontSize = computed(() => covetUniNumber(attrs.fontSize, config.unit))
|
||||
const _label = computed((): string => {
|
||||
if(typeof attrs.label === 'boolean') return ''
|
||||
if(typeof attrs.label === 'string') return attrs.label
|
||||
let count = attrs.label
|
||||
let maxCount = typeof attrs.maxCount == "number" ? attrs.maxCount : parseInt(attrs.maxCount)
|
||||
if (count > 0 && count <= maxCount) return count.toString();
|
||||
if (count <= 0) return ""
|
||||
return maxCount.toString() + "+"
|
||||
if (typeof attrs.label === "boolean") return ""
|
||||
if (typeof attrs.label === "string") return attrs.label
|
||||
let count = attrs.label
|
||||
let maxCount = typeof attrs.maxCount == "number" ? attrs.maxCount : parseInt(attrs.maxCount)
|
||||
if (count > 0 && count <= maxCount) return count.toString()
|
||||
if (count <= 0) return ""
|
||||
return maxCount.toString() + "+"
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
options: {
|
||||
styleIsolation: "apply-shared",
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
};
|
||||
options: {
|
||||
styleIsolation: "apply-shared",
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view class="tmBadge">
|
||||
<view class="tmBadgeWrap">
|
||||
<text :style='_cStyles[0]' class="tmBadge-dot" :class="[_isDot ? 'noneShow' : 'nonex']"></text>
|
||||
<view id="tmBadge-countAndLabel" class="tmBadge-countAndLabel" :class="[_isDot ? 'nonex' : 'noneShow']"
|
||||
:style='_cStyles[1]'>
|
||||
<text class="tmBadge-countAndLabelText" :style='{ color: _fontColor, fontSize: _fontSize }'>{{ _label}}</text>
|
||||
</view>
|
||||
<!--
|
||||
<view class="tmBadge">
|
||||
<view class="tmBadgeWrap">
|
||||
<text :style="_cStyles[0]" class="tmBadge-dot" :class="[_isDot ? 'noneShow' : 'nonex']"></text>
|
||||
<view id="tmBadge-countAndLabel" class="tmBadge-countAndLabel" :class="[_isDot ? 'nonex' : 'noneShow']" :style="_cStyles[1]">
|
||||
<text class="tmBadge-countAndLabelText" :style="{ color: _fontColor, fontSize: _fontSize }">{{ _label }}</text>
|
||||
</view>
|
||||
<!--
|
||||
@slot 默认内容插槽
|
||||
-->
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.tmBadge {
|
||||
overflow: visible;
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
|
||||
overflow: visible;
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tmBadge-countAndLabel {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
border-radius: 100px;
|
||||
min-width: 0px;
|
||||
padding: 0rpx 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
border-radius: 100px;
|
||||
min-width: 0px;
|
||||
padding: 0rpx 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tmBadge-countAndLabelText {
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tmBadge-dot {
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 18px;
|
||||
z-index: 3;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 18px;
|
||||
z-index: 3;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.noneShow {
|
||||
opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.nonex {
|
||||
opacity: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.tmBadgeWrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: visible;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -1,8 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onBeforeUnmount, watch, PropType, getCurrentInstance, ComponentInstance, onUpdated, nextTick, VueElement, inject, watchEffect } from 'vue';
|
||||
import { arrayNumberValid, arrayNumberValidByStyleMP, covetUniNumber, arrayNumberValidByStyleBorderColor, linearValid, getUnit, getUid } from "../../libs/tool";
|
||||
import { getDefaultColor, getDefaultColorObj, getOutlineColorObj, getTextColorObj, getThinColorObj, isBlackAndWhite, setBgColorLightByDark } from "../../libs/colors";
|
||||
import { useTmConfig } from "../../libs/config";
|
||||
import {
|
||||
ref,
|
||||
computed,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
watch,
|
||||
getCurrentInstance,
|
||||
onUpdated,
|
||||
nextTick,
|
||||
VueElement,
|
||||
inject,
|
||||
watchEffect,
|
||||
} from "vue"
|
||||
import {
|
||||
arrayNumberValid,
|
||||
arrayNumberValidByStyleMP,
|
||||
covetUniNumber,
|
||||
arrayNumberValidByStyleBorderColor,
|
||||
linearValid,
|
||||
getUnit,
|
||||
getUid,
|
||||
} from "../../libs/tool"
|
||||
import {
|
||||
getDefaultColor,
|
||||
getDefaultColorObj,
|
||||
getOutlineColorObj,
|
||||
getTextColorObj,
|
||||
getThinColorObj,
|
||||
isBlackAndWhite,
|
||||
setBgColorLightByDark,
|
||||
} from "../../libs/colors"
|
||||
import { useTmConfig } from "../../libs/config"
|
||||
|
||||
/**
|
||||
* @displayName 步进器
|
||||
@@ -14,150 +42,150 @@ import { useTmConfig } from "../../libs/config";
|
||||
| --- | --- | --- | --- |
|
||||
| ☑️| ☑️ | ☑️ | ☑️ | ☑️ | 1.0.0 |
|
||||
*/
|
||||
defineOptions({ name: 'TmNavbar' });
|
||||
defineOptions({ name: "TmNavbar" })
|
||||
const { config } = useTmConfig()
|
||||
const props = defineProps({
|
||||
/**
|
||||
* 当前值,可v-model
|
||||
*/
|
||||
modelValue: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 最大值
|
||||
*/
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
/**
|
||||
* 组件宽
|
||||
*/
|
||||
width: {
|
||||
type: String,
|
||||
default: "auto"
|
||||
},
|
||||
/**
|
||||
* 最小值
|
||||
*/
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 是否禁用
|
||||
*/
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 步进值
|
||||
*/
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
/**
|
||||
* 如果进步值是小数位需要设置此值
|
||||
*/
|
||||
decimalLen: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 按钮的颜色
|
||||
*/
|
||||
btnColor: {
|
||||
type: String,
|
||||
default: "info"
|
||||
},
|
||||
/**
|
||||
* 按钮的暗黑颜色
|
||||
* 空值读取全局的Input暗黑背景色
|
||||
*/
|
||||
darkBtnColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 输入框的背景色
|
||||
*/
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: "info"
|
||||
},
|
||||
/**
|
||||
* 输入框的暗黑背景色
|
||||
* 空值读取全局的Input暗黑背景色
|
||||
*/
|
||||
darkBgColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 按钮的宽
|
||||
*/
|
||||
btnWidth: {
|
||||
type: String,
|
||||
default: "64"
|
||||
},
|
||||
/**
|
||||
* 输入框及按钮的高
|
||||
*/
|
||||
height: {
|
||||
type: String,
|
||||
default: "64"
|
||||
},
|
||||
/**
|
||||
* 按钮的圆角。
|
||||
*/
|
||||
round: {
|
||||
type: String,
|
||||
default: "8"
|
||||
},
|
||||
/**
|
||||
* 是否按钮与输入框独立开来
|
||||
* 不和输入框粘一起。
|
||||
*/
|
||||
splitBtn: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 按钮文本颜色,暗黑时取白色
|
||||
*/
|
||||
btnFontColor: {
|
||||
type: String,
|
||||
default: "#333333"
|
||||
},
|
||||
/**
|
||||
* 文本颜色,暗黑时取白色
|
||||
*/
|
||||
fontColor: {
|
||||
type: String,
|
||||
default: "#333333"
|
||||
},
|
||||
/**
|
||||
* 文本文字大小
|
||||
*/
|
||||
fontSize: {
|
||||
type: String,
|
||||
default: "28"
|
||||
},
|
||||
/**
|
||||
* 当前值,可v-model
|
||||
*/
|
||||
modelValue: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
/**
|
||||
* 最大值
|
||||
*/
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
/**
|
||||
* 组件宽
|
||||
*/
|
||||
width: {
|
||||
type: String,
|
||||
default: "auto",
|
||||
},
|
||||
/**
|
||||
* 最小值
|
||||
*/
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
/**
|
||||
* 是否禁用
|
||||
*/
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 步进值
|
||||
*/
|
||||
step: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
/**
|
||||
* 如果进步值是小数位需要设置此值
|
||||
*/
|
||||
decimalLen: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
/**
|
||||
* 按钮的颜色
|
||||
*/
|
||||
btnColor: {
|
||||
type: String,
|
||||
default: "info",
|
||||
},
|
||||
/**
|
||||
* 按钮的暗黑颜色
|
||||
* 空值读取全局的Input暗黑背景色
|
||||
*/
|
||||
darkBtnColor: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 输入框的背景色
|
||||
*/
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: "info",
|
||||
},
|
||||
/**
|
||||
* 输入框的暗黑背景色
|
||||
* 空值读取全局的Input暗黑背景色
|
||||
*/
|
||||
darkBgColor: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 按钮的宽
|
||||
*/
|
||||
btnWidth: {
|
||||
type: String,
|
||||
default: "64",
|
||||
},
|
||||
/**
|
||||
* 输入框及按钮的高
|
||||
*/
|
||||
height: {
|
||||
type: String,
|
||||
default: "64",
|
||||
},
|
||||
/**
|
||||
* 按钮的圆角。
|
||||
*/
|
||||
round: {
|
||||
type: String,
|
||||
default: "8",
|
||||
},
|
||||
/**
|
||||
* 是否按钮与输入框独立开来
|
||||
* 不和输入框粘一起。
|
||||
*/
|
||||
splitBtn: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 按钮文本颜色,暗黑时取白色
|
||||
*/
|
||||
btnFontColor: {
|
||||
type: String,
|
||||
default: "#333333",
|
||||
},
|
||||
/**
|
||||
* 文本颜色,暗黑时取白色
|
||||
*/
|
||||
fontColor: {
|
||||
type: String,
|
||||
default: "#333333",
|
||||
},
|
||||
/**
|
||||
* 文本文字大小
|
||||
*/
|
||||
fontSize: {
|
||||
type: String,
|
||||
default: "28",
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
/**
|
||||
* 输入值或者点击按钮时触发
|
||||
* @param {number} str - 当前的值。
|
||||
*/
|
||||
'change',
|
||||
/**
|
||||
* 等同vmodel
|
||||
*/
|
||||
'update:modelValue'
|
||||
/**
|
||||
* 输入值或者点击按钮时触发
|
||||
* @param {number} str - 当前的值。
|
||||
*/
|
||||
"change",
|
||||
/**
|
||||
* 等同vmodel
|
||||
*/
|
||||
"update:modelValue",
|
||||
])
|
||||
|
||||
const _value = ref(0)
|
||||
@@ -166,19 +194,19 @@ const addDomDisabeld = ref(false)
|
||||
const surDomDisabeld = ref(false)
|
||||
|
||||
const _round = computed((): string => {
|
||||
return covetUniNumber(props.round, config.unit)
|
||||
return covetUniNumber(props.round, config.unit)
|
||||
})
|
||||
|
||||
const _width = computed((): string => covetUniNumber(props.width, config.unit))
|
||||
|
||||
const _fontSize = computed((): string => {
|
||||
let fontSize = covetUniNumber(props.fontSize, config.unit);
|
||||
if (config.fontSizeScale == 1) return fontSize;
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 14
|
||||
}
|
||||
return (sizeNumber * config.fontSizeScale).toString() + getUnit(fontSize)
|
||||
let fontSize = covetUniNumber(props.fontSize, config.unit)
|
||||
if (config.fontSizeScale == 1) return fontSize
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 14
|
||||
}
|
||||
return (sizeNumber * config.fontSizeScale).toString() + getUnit(fontSize)
|
||||
})
|
||||
|
||||
const _unFontSize = computed((): string => props.fontSize)
|
||||
@@ -186,8 +214,8 @@ const _unFontSize = computed((): string => props.fontSize)
|
||||
const _btnFontColor = computed((): string => getDefaultColor(props.btnFontColor))
|
||||
|
||||
const _fontColor = computed((): string => {
|
||||
if (config.mode == 'dark') return '#ffffff'
|
||||
return getDefaultColor(props.fontColor)
|
||||
if (config.mode == "dark") return "#ffffff"
|
||||
return getDefaultColor(props.fontColor)
|
||||
})
|
||||
|
||||
const _height = computed((): string => covetUniNumber(props.height, config.unit))
|
||||
@@ -197,27 +225,27 @@ const _btnWidth = computed((): string => covetUniNumber(props.btnWidth, config.u
|
||||
const _splitBtn = computed((): boolean => props.splitBtn)
|
||||
|
||||
const _btnColor = computed((): string => {
|
||||
let color = getDefaultColor(props.btnColor)
|
||||
if (config.mode == 'dark') {
|
||||
if (props.darkBtnColor == "") {
|
||||
color = config.inputDarkColor
|
||||
} else {
|
||||
color = getDefaultColor(props.darkBtnColor)
|
||||
}
|
||||
}
|
||||
return color
|
||||
let color = getDefaultColor(props.btnColor)
|
||||
if (config.mode == "dark") {
|
||||
if (props.darkBtnColor == "") {
|
||||
color = config.inputDarkColor
|
||||
} else {
|
||||
color = getDefaultColor(props.darkBtnColor)
|
||||
}
|
||||
}
|
||||
return color
|
||||
})
|
||||
|
||||
const _bgColor = computed((): string => {
|
||||
let color = getDefaultColor(props.bgColor)
|
||||
if (config.mode == 'dark') {
|
||||
if (props.darkBgColor == "") {
|
||||
color = config.inputDarkColor
|
||||
} else {
|
||||
color = getDefaultColor(props.darkBgColor)
|
||||
}
|
||||
}
|
||||
return color
|
||||
let color = getDefaultColor(props.bgColor)
|
||||
if (config.mode == "dark") {
|
||||
if (props.darkBgColor == "") {
|
||||
color = config.inputDarkColor
|
||||
} else {
|
||||
color = getDefaultColor(props.darkBgColor)
|
||||
}
|
||||
}
|
||||
return color
|
||||
})
|
||||
|
||||
const _max = computed((): number => props.max)
|
||||
@@ -225,137 +253,163 @@ const _min = computed((): number => props.min)
|
||||
const _step = computed((): number => props.step)
|
||||
const _disabled = computed((): boolean => props.disabled)
|
||||
|
||||
watch(() => props.modelValue, (newval: number) => {
|
||||
if (newval == _value.value) return;
|
||||
setValue(newval, false)
|
||||
})
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newval: number) => {
|
||||
if (newval == _value.value) return
|
||||
setValue(newval, false)
|
||||
},
|
||||
)
|
||||
|
||||
onMounted(() => {
|
||||
setValue(props.modelValue, false)
|
||||
setValue(props.modelValue, false)
|
||||
})
|
||||
|
||||
const isInRange = (value: number): boolean => {
|
||||
return value >= _min.value && value <= _max.value;
|
||||
return value >= _min.value && value <= _max.value
|
||||
}
|
||||
|
||||
const clampValue = (value: number): number => {
|
||||
return Math.min(Math.max(value, _min.value), _max.value);
|
||||
return Math.min(Math.max(value, _min.value), _max.value)
|
||||
}
|
||||
|
||||
const getDecimalPlaces = (): number => {
|
||||
return props.decimalLen;
|
||||
return props.decimalLen
|
||||
}
|
||||
|
||||
/**
|
||||
* 加
|
||||
*/
|
||||
const handleIncrement = () => {
|
||||
const newValue = Math.min(_value.value + _step.value, props.max);
|
||||
let val = clampValue(parseFloat(newValue.toFixed(props.decimalLen)));
|
||||
setValue(val, true)
|
||||
const newValue = Math.min(_value.value + _step.value, props.max)
|
||||
let val = clampValue(parseFloat(newValue.toFixed(props.decimalLen)))
|
||||
setValue(val, true)
|
||||
}
|
||||
|
||||
/**减 */
|
||||
const handleDecrement = () => {
|
||||
const newValue = Math.max(_value.value - _step.value, props.min);
|
||||
let val = clampValue(parseFloat(newValue.toFixed(props.decimalLen)));
|
||||
setValue(val, true)
|
||||
const newValue = Math.max(_value.value - _step.value, props.min)
|
||||
let val = clampValue(parseFloat(newValue.toFixed(props.decimalLen)))
|
||||
setValue(val, true)
|
||||
}
|
||||
|
||||
const handleInputChange = (event: any) => {
|
||||
_input_value.value = event.detail.value
|
||||
_input_value.value = event.detail.value
|
||||
}
|
||||
|
||||
const inputBlur = () => {
|
||||
const inputValue = parseFloat(_input_value.value);
|
||||
if (!isNaN(inputValue)) {
|
||||
let val = clampValue(inputValue);
|
||||
setValue(val, true)
|
||||
} else {
|
||||
setValue(parseFloat(_min.value.toFixed(props.decimalLen)), true)
|
||||
}
|
||||
const inputValue = parseFloat(_input_value.value)
|
||||
if (!isNaN(inputValue)) {
|
||||
let val = clampValue(inputValue)
|
||||
setValue(val, true)
|
||||
} else {
|
||||
setValue(parseFloat(_min.value.toFixed(props.decimalLen)), true)
|
||||
}
|
||||
}
|
||||
|
||||
const setValue = (value: number, isEmit: boolean) => {
|
||||
const clampedValue = clampValue(value);
|
||||
_value.value = clampedValue;
|
||||
_input_value.value = _value.value.toString();
|
||||
addDomDisabeld.value = _value.value >= props.max
|
||||
surDomDisabeld.value = _value.value <= props.min
|
||||
const clampedValue = clampValue(value)
|
||||
_value.value = clampedValue
|
||||
_input_value.value = _value.value.toString()
|
||||
addDomDisabeld.value = _value.value >= props.max
|
||||
surDomDisabeld.value = _value.value <= props.min
|
||||
|
||||
if (isEmit) {
|
||||
/**
|
||||
* 等同v-model
|
||||
*/
|
||||
emit("update:modelValue", clampedValue)
|
||||
/**
|
||||
* 输入值或者点击按钮时触发
|
||||
* @param {number} 当前的值。
|
||||
*/
|
||||
emit("change", clampedValue)
|
||||
}
|
||||
if (isEmit) {
|
||||
/**
|
||||
* 等同v-model
|
||||
*/
|
||||
emit("update:modelValue", clampedValue)
|
||||
/**
|
||||
* 输入值或者点击按钮时触发
|
||||
* @param {number} 当前的值。
|
||||
*/
|
||||
emit("change", clampedValue)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
options: {
|
||||
styleIsolation: "apply-shared",
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
};
|
||||
options: {
|
||||
styleIsolation: "apply-shared",
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view class="xStepper" :style="{ width: _width, borderRadius: _round }">
|
||||
<view :hover-start-time="20" :hover-stay-time="150" :hover-class="addDomDisabeld ? '' : 'xStepperHoverbtn'"
|
||||
@click="handleDecrement" class="xStepperBtn"
|
||||
:style="{ backgroundColor: _btnColor, height: _height, width: _btnWidth, opacity: surDomDisabeld ? 0.6 : 1, borderRadius: _splitBtn ? '50px' : '0rpx' }">
|
||||
<tm-icon _style="pointer-events: none" :color="_btnFontColor" :size="_unFontSize"
|
||||
name="subtract-line"></tm-icon>
|
||||
</view>
|
||||
<view class="xStepper" :style="{ width: _width, borderRadius: _round }">
|
||||
<view
|
||||
:hover-start-time="20"
|
||||
:hover-stay-time="150"
|
||||
:hover-class="addDomDisabeld ? '' : 'xStepperHoverbtn'"
|
||||
@click="handleDecrement"
|
||||
class="xStepperBtn"
|
||||
:style="{
|
||||
backgroundColor: _btnColor,
|
||||
height: _height,
|
||||
width: _btnWidth,
|
||||
opacity: surDomDisabeld ? 0.6 : 1,
|
||||
borderRadius: _splitBtn ? '50px' : '0rpx',
|
||||
}"
|
||||
>
|
||||
<tm-icon _style="pointer-events: none" :color="_btnFontColor" :size="_unFontSize" name="subtract-line"></tm-icon>
|
||||
</view>
|
||||
|
||||
<input @blur="inputBlur" @input="handleInputChange" :value="_input_value" class="xStepperInput"
|
||||
:style="{ backgroundColor: _splitBtn ? 'transparent' : _btnColor, height: _height, color: _fontColor, fontSize: _fontSize }"
|
||||
:type="decimalLen > 0 ? 'digit' : 'number'" />
|
||||
<view :hover-start-time="20" :hover-stay-time="150" :hover-class="addDomDisabeld ? '' : 'xStepperHoverbtn'"
|
||||
@click="handleIncrement" class="xStepperBtn"
|
||||
:style="{ backgroundColor: _btnColor, height: _height, width: _btnWidth, borderRadius: _splitBtn ? '50px' : '0rpx' }">
|
||||
<tm-icon :_style="` opacity: ${addDomDisabeld} ? 0.6 : 1,'pointerEvents': 'none'`" :color="_btnFontColor"
|
||||
:size="_unFontSize" name="add-line"></tm-icon>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<input
|
||||
@blur="inputBlur"
|
||||
@input="handleInputChange"
|
||||
:value="_input_value"
|
||||
class="xStepperInput"
|
||||
:style="{ backgroundColor: _splitBtn ? 'transparent' : _btnColor, height: _height, color: _fontColor, fontSize: _fontSize }"
|
||||
:type="decimalLen > 0 ? 'digit' : 'number'"
|
||||
/>
|
||||
<view
|
||||
:hover-start-time="20"
|
||||
:hover-stay-time="150"
|
||||
:hover-class="addDomDisabeld ? '' : 'xStepperHoverbtn'"
|
||||
@click="handleIncrement"
|
||||
class="xStepperBtn"
|
||||
:style="{ backgroundColor: _btnColor, height: _height, width: _btnWidth, borderRadius: _splitBtn ? '50px' : '0rpx' }"
|
||||
>
|
||||
<tm-icon
|
||||
:_style="` opacity: ${addDomDisabeld} ? 0.6 : 1,'pointerEvents': 'none'`"
|
||||
:color="_btnFontColor"
|
||||
:size="_unFontSize"
|
||||
name="add-line"
|
||||
></tm-icon>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<style scoped>
|
||||
.xStepperBtnBtn {
|
||||
pointer-events: none;
|
||||
flex-shrink: 0;
|
||||
pointer-events: none;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.xStepperHoverbtn {
|
||||
opacity: 0.8;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.xStepper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.xStepperInput {
|
||||
flex: 1;
|
||||
margin: 0 1px;
|
||||
padding: 0 5px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
min-width: 20px;
|
||||
flex: 1;
|
||||
margin: 0 1px;
|
||||
padding: 0 5px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
.xStepperBtn {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch, PropType, provide, nextTick } from 'vue';
|
||||
import { useTmConfig } from "../../libs/config";
|
||||
import { tmDate, type tmDateTypeTime, createDate } from '../../libs/tmDate';
|
||||
import { covetUniNumber, getUnit } from '../../libs/tool';
|
||||
import { getDefaultColor } from '../../libs/colors';
|
||||
import { ref, computed, onMounted, watch, provide, nextTick } from "vue"
|
||||
import { useTmConfig } from "../../libs/config"
|
||||
import { tmDate, type tmDateTypeTime, createDate } from "../../libs/tmDate"
|
||||
import { covetUniNumber, getUnit } from "../../libs/tool"
|
||||
import { getDefaultColor } from "../../libs/colors"
|
||||
|
||||
/**
|
||||
* @displayName 标签导航
|
||||
@@ -15,221 +15,219 @@ import { getDefaultColor } from '../../libs/colors';
|
||||
| --- | --- | --- | --- |
|
||||
| ☑️| ☑️ | ☑️ | ☑️ | ☑️ | 1.0.0 |
|
||||
*/
|
||||
defineOptions({ name: 'TmTabs' });
|
||||
defineOptions({ name: "TmTabs" })
|
||||
const { config } = useTmConfig()
|
||||
const emit = defineEmits([
|
||||
/** 变化时触发 */
|
||||
"change",
|
||||
/** 同步vmodel */
|
||||
"update:modelValue"
|
||||
/** 变化时触发 */
|
||||
"change",
|
||||
/** 同步vmodel */
|
||||
"update:modelValue",
|
||||
])
|
||||
const props = defineProps(
|
||||
{
|
||||
/**
|
||||
* 圆角
|
||||
*/
|
||||
round: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 宽
|
||||
*/
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: "auto"
|
||||
},
|
||||
/**
|
||||
* 高是必填,不可为auto。
|
||||
*/
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: "88"
|
||||
},
|
||||
/**
|
||||
* 排版模式
|
||||
* around:居中并且均分[数据多时会造成无法滚动]
|
||||
* between:均分在整个宽上(如想相项目宽一样,你可以设置属性width比如你有3个可以设置为33%)[数据多时会造成无法滚动]
|
||||
* start:左对齐[数据多时可滚动]
|
||||
* end:右对齐[数据多时可滚动]
|
||||
* center:中间对齐[数据多时会造成无法滚动]
|
||||
*/
|
||||
mode: {
|
||||
type: String as PropType<"around" | "between" | "start" | "end" | "center">,
|
||||
default: "start"
|
||||
},
|
||||
/**
|
||||
* 背景
|
||||
*/
|
||||
color: {
|
||||
type: String,
|
||||
default: "white"
|
||||
},
|
||||
/**
|
||||
* 暗黑时的背景,如果不填写读取sheetDark
|
||||
*/
|
||||
darkColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 文本激活时的颜色 ,空值默认取全局主题色
|
||||
*/
|
||||
activeTitleColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 文本默认颜色
|
||||
*/
|
||||
titleColor: {
|
||||
type: String,
|
||||
default: "#888888"
|
||||
},
|
||||
/**
|
||||
* 文本默认的暗黑颜色,如果不填写取白色。
|
||||
*/
|
||||
darkTitleColor: {
|
||||
type: String,
|
||||
default: "#cacaca"
|
||||
},
|
||||
/**
|
||||
* 底部线条激活时的颜色,空值默认取全局主题色
|
||||
*/
|
||||
lineColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
lineHeight: {
|
||||
type: String,
|
||||
default: "3px"
|
||||
},
|
||||
/**
|
||||
* 底部的线条是与项目等宽还是固定默认的小宽度。
|
||||
*/
|
||||
lineFull: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 是否显示底部的线条
|
||||
*/
|
||||
showLine: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* id值,如果数据没有提供id属性,这里的id就是索引
|
||||
* 等同v-model
|
||||
*/
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 标题字号
|
||||
*/
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: "30"
|
||||
},
|
||||
/**
|
||||
* 激活时的标题字号
|
||||
*/
|
||||
activeFontSize: {
|
||||
type: [String, Number],
|
||||
default: "32"
|
||||
},
|
||||
/**
|
||||
* 项目宽度,默认是auto,即自动根据标题内容自动撑开宽度。
|
||||
* 如果你想均分(适合不超过一行),比如你有5个标签,那么你就可以设置为"20%"
|
||||
*/
|
||||
itemWidth: {
|
||||
type: [String, Number],
|
||||
default: "auto"
|
||||
},
|
||||
/**
|
||||
* 标题的padding是左右的间隙。
|
||||
*/
|
||||
titlePadding: {
|
||||
type: [String, Number],
|
||||
default: "12px"
|
||||
},
|
||||
/**
|
||||
* 选中当前项是,移动的差值个数。比如你要让选中的居中,你一屏内
|
||||
* 刚好显示5个,你就设置为2,如果你一屏显示3个,就设置为1,就是你一屏内
|
||||
* 里面要显示的是单数,才好控制选中的始终是在中间位置 。
|
||||
*/
|
||||
moveCount: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
/**
|
||||
* 项目之间的间隙.如果你设定了itemwidth一般会有富余宽,两边自然有间隙,此时你应该设置为0以免造成不居中的假象.
|
||||
*/
|
||||
gap: {
|
||||
type: [String, Number],
|
||||
default: 20
|
||||
},
|
||||
/**
|
||||
* 数据数组,可以混合类型可以是单类型
|
||||
* 数据格式比较灵活.
|
||||
* 如果数据是对象且出现了dot:true该项数组右上角出现角标红点
|
||||
* 如果dot:非boolean比如:dot:32会出现数字角标或者文本角标.如果为false或者空值为隐藏
|
||||
*/
|
||||
list: {
|
||||
type: [Array<Record<string, any> | string>],
|
||||
default: () => [],
|
||||
require: true
|
||||
},
|
||||
/**
|
||||
* 当你的list为对象时可用
|
||||
* 如果数据是string会直接取数据本身
|
||||
*/
|
||||
rangKey: {
|
||||
type: String,
|
||||
default: "title"
|
||||
},
|
||||
/**
|
||||
* id标识,用来vmodel双向绑定选中的值,
|
||||
* 如果你的list中不存在或者没有id标识
|
||||
* 那么取数组循环的索引值
|
||||
* */
|
||||
rangId: {
|
||||
type: String,
|
||||
default: "id"
|
||||
},
|
||||
/**
|
||||
* 读取角标的标识字段,默认是dot
|
||||
* */
|
||||
rangDot: {
|
||||
type: String,
|
||||
default: "dot"
|
||||
},
|
||||
/**
|
||||
* 角标的背景,默认是等同激活的标题颜色
|
||||
* 如果填写使用本值,文字颜色始终是白的.
|
||||
*/
|
||||
dotBgColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 默认的自定项目的style样式,可以用来完全覆盖默认的样式.
|
||||
*/
|
||||
customItemStyle: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* 默认的激活自定项目的style样式,可以用来完全覆盖默认的样式.
|
||||
*/
|
||||
activeItemStyle: {
|
||||
type: String,
|
||||
default: ""
|
||||
}
|
||||
}
|
||||
)
|
||||
const props = defineProps({
|
||||
/**
|
||||
* 圆角
|
||||
*/
|
||||
round: {
|
||||
type: [String, Number],
|
||||
default: 0,
|
||||
},
|
||||
/**
|
||||
* 宽
|
||||
*/
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: "auto",
|
||||
},
|
||||
/**
|
||||
* 高是必填,不可为auto。
|
||||
*/
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: "88",
|
||||
},
|
||||
/**
|
||||
* 排版模式
|
||||
* around:居中并且均分[数据多时会造成无法滚动]
|
||||
* between:均分在整个宽上(如想相项目宽一样,你可以设置属性width比如你有3个可以设置为33%)[数据多时会造成无法滚动]
|
||||
* start:左对齐[数据多时可滚动]
|
||||
* end:右对齐[数据多时可滚动]
|
||||
* center:中间对齐[数据多时会造成无法滚动]
|
||||
*/
|
||||
mode: {
|
||||
type: String,
|
||||
default: "start",
|
||||
},
|
||||
/**
|
||||
* 背景
|
||||
*/
|
||||
color: {
|
||||
type: String,
|
||||
default: "white",
|
||||
},
|
||||
/**
|
||||
* 暗黑时的背景,如果不填写读取sheetDark
|
||||
*/
|
||||
darkColor: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 文本激活时的颜色 ,空值默认取全局主题色
|
||||
*/
|
||||
activeTitleColor: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 文本默认颜色
|
||||
*/
|
||||
titleColor: {
|
||||
type: String,
|
||||
default: "#888888",
|
||||
},
|
||||
/**
|
||||
* 文本默认的暗黑颜色,如果不填写取白色。
|
||||
*/
|
||||
darkTitleColor: {
|
||||
type: String,
|
||||
default: "#cacaca",
|
||||
},
|
||||
/**
|
||||
* 底部线条激活时的颜色,空值默认取全局主题色
|
||||
*/
|
||||
lineColor: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
lineHeight: {
|
||||
type: String,
|
||||
default: "3px",
|
||||
},
|
||||
/**
|
||||
* 底部的线条是与项目等宽还是固定默认的小宽度。
|
||||
*/
|
||||
lineFull: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* 是否显示底部的线条
|
||||
*/
|
||||
showLine: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
/**
|
||||
* id值,如果数据没有提供id属性,这里的id就是索引
|
||||
* 等同v-model
|
||||
*/
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: 0,
|
||||
},
|
||||
/**
|
||||
* 标题字号
|
||||
*/
|
||||
fontSize: {
|
||||
type: [String, Number],
|
||||
default: "30",
|
||||
},
|
||||
/**
|
||||
* 激活时的标题字号
|
||||
*/
|
||||
activeFontSize: {
|
||||
type: [String, Number],
|
||||
default: "32",
|
||||
},
|
||||
/**
|
||||
* 项目宽度,默认是auto,即自动根据标题内容自动撑开宽度。
|
||||
* 如果你想均分(适合不超过一行),比如你有5个标签,那么你就可以设置为"20%"
|
||||
*/
|
||||
itemWidth: {
|
||||
type: [String, Number],
|
||||
default: "auto",
|
||||
},
|
||||
/**
|
||||
* 标题的padding是左右的间隙。
|
||||
*/
|
||||
titlePadding: {
|
||||
type: [String, Number],
|
||||
default: "12px",
|
||||
},
|
||||
/**
|
||||
* 选中当前项是,移动的差值个数。比如你要让选中的居中,你一屏内
|
||||
* 刚好显示5个,你就设置为2,如果你一屏显示3个,就设置为1,就是你一屏内
|
||||
* 里面要显示的是单数,才好控制选中的始终是在中间位置 。
|
||||
*/
|
||||
moveCount: {
|
||||
type: Number,
|
||||
default: 2,
|
||||
},
|
||||
/**
|
||||
* 项目之间的间隙.如果你设定了itemwidth一般会有富余宽,两边自然有间隙,此时你应该设置为0以免造成不居中的假象.
|
||||
*/
|
||||
gap: {
|
||||
type: [String, Number],
|
||||
default: 20,
|
||||
},
|
||||
/**
|
||||
* 数据数组,可以混合类型可以是单类型
|
||||
* 数据格式比较灵活.
|
||||
* 如果数据是对象且出现了dot:true该项数组右上角出现角标红点
|
||||
* 如果dot:非boolean比如:dot:32会出现数字角标或者文本角标.如果为false或者空值为隐藏
|
||||
*/
|
||||
list: {
|
||||
type: [Array<Record<string, any> | string>],
|
||||
default: () => [],
|
||||
require: true,
|
||||
},
|
||||
/**
|
||||
* 当你的list为对象时可用
|
||||
* 如果数据是string会直接取数据本身
|
||||
*/
|
||||
rangKey: {
|
||||
type: String,
|
||||
default: "title",
|
||||
},
|
||||
/**
|
||||
* id标识,用来vmodel双向绑定选中的值,
|
||||
* 如果你的list中不存在或者没有id标识
|
||||
* 那么取数组循环的索引值
|
||||
* */
|
||||
rangId: {
|
||||
type: String,
|
||||
default: "id",
|
||||
},
|
||||
/**
|
||||
* 读取角标的标识字段,默认是dot
|
||||
* */
|
||||
rangDot: {
|
||||
type: String,
|
||||
default: "dot",
|
||||
},
|
||||
/**
|
||||
* 角标的背景,默认是等同激活的标题颜色
|
||||
* 如果填写使用本值,文字颜色始终是白的.
|
||||
*/
|
||||
dotBgColor: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 默认的自定项目的style样式,可以用来完全覆盖默认的样式.
|
||||
*/
|
||||
customItemStyle: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
/**
|
||||
* 默认的激活自定项目的style样式,可以用来完全覆盖默认的样式.
|
||||
*/
|
||||
activeItemStyle: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
})
|
||||
const _showLine = computed(() => props.showLine)
|
||||
|
||||
const _lineFull = computed(() => props.lineFull)
|
||||
@@ -237,13 +235,13 @@ const _customItemStyle = computed(() => props.customItemStyle)
|
||||
const _activeItemStyle = computed(() => props.activeItemStyle)
|
||||
|
||||
const _fontSize = computed(() => {
|
||||
let fontSize = covetUniNumber(props.fontSize, config.unit);
|
||||
if (config.fontSizeScale == 1) return fontSize;
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 30
|
||||
}
|
||||
return (sizeNumber * config.fontSizeScale).toString() + getUnit(fontSize)
|
||||
let fontSize = covetUniNumber(props.fontSize, config.unit)
|
||||
if (config.fontSizeScale == 1) return fontSize
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 30
|
||||
}
|
||||
return (sizeNumber * config.fontSizeScale).toString() + getUnit(fontSize)
|
||||
})
|
||||
|
||||
const _itemWidth = computed(() => covetUniNumber(props.itemWidth, config.unit))
|
||||
@@ -251,14 +249,14 @@ const _itemWidth = computed(() => covetUniNumber(props.itemWidth, config.unit))
|
||||
const _round = computed(() => covetUniNumber(props.round, config.unit))
|
||||
|
||||
const _activeFontSize = computed(() => {
|
||||
// covetUniNumber(props.activeFontSize, config.unit)
|
||||
let fontSize = covetUniNumber(props.activeFontSize, config.unit);
|
||||
if (config.fontSizeScale == 1) return fontSize;
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 32
|
||||
}
|
||||
return (sizeNumber * config.fontSizeScale).toString() + getUnit(fontSize)
|
||||
// covetUniNumber(props.activeFontSize, config.unit)
|
||||
let fontSize = covetUniNumber(props.activeFontSize, config.unit)
|
||||
if (config.fontSizeScale == 1) return fontSize
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 32
|
||||
}
|
||||
return (sizeNumber * config.fontSizeScale).toString() + getUnit(fontSize)
|
||||
})
|
||||
|
||||
const _lineHeight = computed(() => covetUniNumber(props.lineHeight, config.unit))
|
||||
@@ -268,199 +266,213 @@ const _height = computed(() => covetUniNumber(props.height, config.unit))
|
||||
const _width = computed(() => covetUniNumber(props.width, config.unit))
|
||||
|
||||
const _color = computed(() => {
|
||||
if (config.mode == 'dark') {
|
||||
if (props.darkColor != '') {
|
||||
return getDefaultColor(props.darkColor)
|
||||
} else {
|
||||
return getDefaultColor(config.sheetDarkColor)
|
||||
}
|
||||
}
|
||||
return getDefaultColor(props.color)
|
||||
if (config.mode == "dark") {
|
||||
if (props.darkColor != "") {
|
||||
return getDefaultColor(props.darkColor)
|
||||
} else {
|
||||
return getDefaultColor(config.sheetDarkColor)
|
||||
}
|
||||
}
|
||||
return getDefaultColor(props.color)
|
||||
})
|
||||
|
||||
const _activeTitleColor = computed(() => {
|
||||
if (props.activeTitleColor == "") return getDefaultColor(config.color);
|
||||
return getDefaultColor(props.activeTitleColor)
|
||||
if (props.activeTitleColor == "") return getDefaultColor(config.color)
|
||||
return getDefaultColor(props.activeTitleColor)
|
||||
})
|
||||
const _dotBgColor = computed(() => {
|
||||
if (props.dotBgColor == "") return _activeTitleColor.value
|
||||
return props.dotBgColor
|
||||
if (props.dotBgColor == "") return _activeTitleColor.value
|
||||
return props.dotBgColor
|
||||
})
|
||||
|
||||
const _titleColor = computed(() => {
|
||||
if (config.mode == 'dark') {
|
||||
if (props.darkTitleColor != '') {
|
||||
return getDefaultColor(props.darkTitleColor)
|
||||
} else {
|
||||
return "#ffffff"
|
||||
}
|
||||
}
|
||||
return getDefaultColor(props.titleColor)
|
||||
if (config.mode == "dark") {
|
||||
if (props.darkTitleColor != "") {
|
||||
return getDefaultColor(props.darkTitleColor)
|
||||
} else {
|
||||
return "#ffffff"
|
||||
}
|
||||
}
|
||||
return getDefaultColor(props.titleColor)
|
||||
})
|
||||
|
||||
const _lineColor = computed(() => {
|
||||
if (props.lineColor == "") return _activeTitleColor.value;
|
||||
return getDefaultColor(props.lineColor)
|
||||
if (props.lineColor == "") return _activeTitleColor.value
|
||||
return getDefaultColor(props.lineColor)
|
||||
})
|
||||
|
||||
const activeName = ref(props.modelValue)
|
||||
const moveName = ref(props.modelValue)
|
||||
const _list = computed(() => props.list)
|
||||
const _listIds = computed(() => {
|
||||
let ids: Array<string | number> = _list.value.map((item, index) => {
|
||||
if (typeof item === 'string') return index
|
||||
let id = typeof item[props.rangId] == 'undefined' ? index : item[props.rangId]
|
||||
return id;
|
||||
})
|
||||
return ids;
|
||||
let ids: Array<string | number> = _list.value.map((item, index) => {
|
||||
if (typeof item === "string") return index
|
||||
let id = typeof item[props.rangId] == "undefined" ? index : item[props.rangId]
|
||||
return id
|
||||
})
|
||||
return ids
|
||||
})
|
||||
const _mode = computed(() => {
|
||||
if (props.mode == 'around') return "space-around"
|
||||
if (props.mode == 'between') return "space-between"
|
||||
if (props.mode == 'center') return "center"
|
||||
if (props.mode == 'end') return "flex-end"
|
||||
return 'flex-start'
|
||||
if (props.mode == "around") return "space-around"
|
||||
if (props.mode == "between") return "space-between"
|
||||
if (props.mode == "center") return "center"
|
||||
if (props.mode == "end") return "flex-end"
|
||||
return "flex-start"
|
||||
})
|
||||
provide('tmTabsActiveName', computed((): string | number => activeName.value))
|
||||
provide(
|
||||
"tmTabsActiveName",
|
||||
computed((): string | number => activeName.value),
|
||||
)
|
||||
|
||||
watch(() => props.modelValue, (newValue: string | number) => {
|
||||
if (newValue == activeName.value) return;
|
||||
toggleActivate(newValue)
|
||||
})
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue: string | number) => {
|
||||
if (newValue == activeName.value) return
|
||||
toggleActivate(newValue)
|
||||
},
|
||||
)
|
||||
const getValue = (item: Record<string, any> | string): string => {
|
||||
if (typeof item === 'string') return item;
|
||||
let value = item[props.rangKey] || ""
|
||||
return value;
|
||||
if (typeof item === "string") return item
|
||||
let value = item[props.rangKey] || ""
|
||||
return value
|
||||
}
|
||||
const getDot = (item: Record<string, any> | string): boolean | string | number => {
|
||||
if (typeof item === 'string') return false;
|
||||
let value = typeof item[props.rangDot] == 'undefined' ? false : item[props.rangDot]
|
||||
return value;
|
||||
if (typeof item === "string") return false
|
||||
let value = typeof item[props.rangDot] == "undefined" ? false : item[props.rangDot]
|
||||
return value
|
||||
}
|
||||
/**
|
||||
* 切换选中
|
||||
*/
|
||||
const toggleActivate = (name: string | number, isEmits = false) => {
|
||||
activeName.value = name
|
||||
if (isEmits) {
|
||||
emit('update:modelValue', name)
|
||||
emit('change', name)
|
||||
}
|
||||
changMovename(name)
|
||||
activeName.value = name
|
||||
if (isEmits) {
|
||||
emit("update:modelValue", name)
|
||||
emit("change", name)
|
||||
}
|
||||
changMovename(name)
|
||||
}
|
||||
const changMovename = (name: string | number) => {
|
||||
let index = _listIds.value.findIndex(el => el == name)
|
||||
if (index == -1) return;
|
||||
index = index - props.moveCount
|
||||
index = Math.max(0, index)
|
||||
moveName.value = ''
|
||||
let index = _listIds.value.findIndex((el) => el == name)
|
||||
if (index == -1) return
|
||||
index = index - props.moveCount
|
||||
index = Math.max(0, index)
|
||||
moveName.value = ""
|
||||
|
||||
nextTick(() => {
|
||||
moveName.value = _listIds.value[index];
|
||||
})
|
||||
nextTick(() => {
|
||||
moveName.value = _listIds.value[index]
|
||||
})
|
||||
}
|
||||
const tabsOnclick = (item: string | Record<string, any>, index: number) => {
|
||||
let name = _listIds.value[index];
|
||||
if (name == activeName.value) return;
|
||||
toggleActivate(name, true)
|
||||
let name = _listIds.value[index]
|
||||
if (name == activeName.value) return
|
||||
toggleActivate(name, true)
|
||||
}
|
||||
|
||||
defineExpose({ toggleActivate })
|
||||
|
||||
</script>
|
||||
<script lang="ts">
|
||||
export default {
|
||||
options: {
|
||||
styleIsolation: "apply-shared",
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true
|
||||
}
|
||||
options: {
|
||||
styleIsolation: "apply-shared",
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
multipleSlots: true,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<view class="tmTabs" :style="{
|
||||
backgroundColor: _color,
|
||||
'border-radius': _round,
|
||||
height: _height,
|
||||
width: _width
|
||||
}
|
||||
">
|
||||
<scroll-view :show-scrollbar="false" enable-flex :scroll-into-view="'tabs_' + moveName" class="tmTabsWrapBox"
|
||||
:scroll-x="true">
|
||||
<view class="tmTabsWrap" :style="{ justifyContent: _mode }">
|
||||
<view @click="tabsOnclick(item, index)" class="tmTabsItem" :id="'tabs_' + _listIds[index]"
|
||||
v-for="(item, index) in _list" :key="index" :style="[
|
||||
{
|
||||
color: activeName == _listIds[index] ? _activeTitleColor : _titleColor,
|
||||
fontSize: activeName == _listIds[index] ? _activeFontSize : _fontSize,
|
||||
fontWeight: activeName == _listIds[index] ? 'bold' : 'normal',
|
||||
width: _itemWidth,
|
||||
padding: `0px ${_gap}`
|
||||
},
|
||||
activeName == _listIds[index] ? _activeItemStyle : _customItemStyle
|
||||
]">
|
||||
<tm-badge :bg-color="_dotBgColor" :label="getDot(item)">
|
||||
{{ getValue(item) }}
|
||||
</tm-badge>
|
||||
<view v-if="_showLine" class="tmTabsItemLiner" :style="{
|
||||
width: activeName == _listIds[index] ? (_lineFull ? '100%' : '36%') : '0%',
|
||||
height: _lineHeight,
|
||||
maxWidth: !_lineFull ? '36px' : 'auto',
|
||||
backgroundColor: activeName == _listIds[index] ? _lineColor : 'transparent'
|
||||
}"></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="tmTabs"
|
||||
:style="{
|
||||
backgroundColor: _color,
|
||||
'border-radius': _round,
|
||||
height: _height,
|
||||
width: _width,
|
||||
}"
|
||||
>
|
||||
<scroll-view :show-scrollbar="false" enable-flex :scroll-into-view="'tabs_' + moveName" class="tmTabsWrapBox" :scroll-x="true">
|
||||
<view class="tmTabsWrap" :style="{ justifyContent: _mode }">
|
||||
<view
|
||||
@click="tabsOnclick(item, index)"
|
||||
class="tmTabsItem"
|
||||
:id="'tabs_' + _listIds[index]"
|
||||
v-for="(item, index) in _list"
|
||||
:key="index"
|
||||
:style="[
|
||||
{
|
||||
color: activeName == _listIds[index] ? _activeTitleColor : _titleColor,
|
||||
fontSize: activeName == _listIds[index] ? _activeFontSize : _fontSize,
|
||||
fontWeight: activeName == _listIds[index] ? 'bold' : 'normal',
|
||||
width: _itemWidth,
|
||||
padding: `0px ${_gap}`,
|
||||
},
|
||||
activeName == _listIds[index] ? _activeItemStyle : _customItemStyle,
|
||||
]"
|
||||
>
|
||||
<tm-badge :bg-color="_dotBgColor" :label="getDot(item)">
|
||||
{{ getValue(item) }}
|
||||
</tm-badge>
|
||||
<view
|
||||
v-if="_showLine"
|
||||
class="tmTabsItemLiner"
|
||||
:style="{
|
||||
width: activeName == _listIds[index] ? (_lineFull ? '100%' : '36%') : '0%',
|
||||
height: _lineHeight,
|
||||
maxWidth: !_lineFull ? '36px' : 'auto',
|
||||
backgroundColor: activeName == _listIds[index] ? _lineColor : 'transparent',
|
||||
}"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
<style lang="css">
|
||||
.tmTabsItem {
|
||||
/* padding: 0 20rpx; */
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
/* padding: 0 20rpx; */
|
||||
height: 100%;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tmTabsItemLiner {
|
||||
/* height: 2px; */
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 0px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
|
||||
/* height: 2px; */
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 0px;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.tmTabs {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tmTabsWrapBox {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.tmTabsWrap {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
min-width: 100%;
|
||||
/* justify-content: flex-start; */
|
||||
align-items: center;
|
||||
/* width: auto; */
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
min-width: 100%;
|
||||
/* justify-content: flex-start; */
|
||||
align-items: center;
|
||||
/* width: auto; */
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
Reference in new issue
Block a user