Commit c04b6053 authored by 罗超's avatar 罗超

机票模块修改

parent 24124116
...@@ -15,6 +15,45 @@ ...@@ -15,6 +15,45 @@
flex-wrap: nowrap; flex-wrap: nowrap;
align-items: center; align-items: center;
} }
.q-mr-md{
margin-right: 32rpx;
}
.q-ml-md{
margin-left: 32rpx;
}
.q-mt-md{
margin-top: 32rpx;
}
.q-mb-md{
margin-bottom: 32rpx;
}
.q-mr-sm{
margin-right: 16rpx;
}
.q-ml-sm{
margin-left: 16rpx;
}
.q-mt-sm{
margin-top: 16rpx;
}
.q-mb-sm{
margin-bottom: 16rpx;
}
.flex-grid{
margin-left: -16rpx;
margin-bottom: -16rpx;
}
.flex-wrap{
flex-wrap: wrap;
}
.col-t-b{
width: calc(50% - 16rpx);
margin: 0 0 16rpx 16rpx
}
.col-f-b{
width: calc(25% - 16rpx);
margin: 0 0 16rpx 16rpx
}
.row-ajc-w{ .row-ajc-w{
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
...@@ -33,6 +72,25 @@ ...@@ -33,6 +72,25 @@
align-items: center; align-items: center;
justify-content: end; justify-content: end;
} }
.text-center{
text-align: center;
}
.text-input{
background: #F1F2F4;
/* height: 60rpx; */
border-radius: 12rpx;
padding: 12rpx;
font-size: 28rpx;
color: #111111;
}
.text-input:focus,
.text-input:active{
background-color: #111111;
color:#F1F2F4;
}
.text-input::placeholder{
font-size: 24rpx;
}
.row-sb-n{ .row-sb-n{
display: flex; display: flex;
align-items: center; align-items: center;
...@@ -59,6 +117,9 @@ ...@@ -59,6 +117,9 @@
.items-center{ .items-center{
align-items: center; align-items: center;
} }
.justify-center{
justify-content: center;
}
.flex1,.col{ .flex1,.col{
flex: 1; flex: 1;
} }
......
@font-face { @font-face {
font-family: "tffont"; /* Project id 4816119 */ font-family: "tffont"; /* Project id 4816119 */
src: url('//at.alicdn.com/t/c/font_4816119_ut3uqptmt1.woff2?t=1737444391856') format('woff2'), src: url('//at.alicdn.com/t/c/font_4816119_vhne921vx0o.woff2?t=1739518077462') format('woff2'),
url('//at.alicdn.com/t/c/font_4816119_ut3uqptmt1.woff?t=1737444391856') format('woff'), url('//at.alicdn.com/t/c/font_4816119_vhne921vx0o.woff?t=1739518077462') format('woff'),
url('//at.alicdn.com/t/c/font_4816119_ut3uqptmt1.ttf?t=1737444391856') format('truetype'); url('//at.alicdn.com/t/c/font_4816119_vhne921vx0o.ttf?t=1739518077462') format('truetype');
} }
.tffont { .tffont {
...@@ -13,6 +13,46 @@ ...@@ -13,6 +13,46 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.tffont-arrowleft:before {
content: "\e610";
}
.tffont-arrow_right:before {
content: "\e616";
}
.tffont-arrow_down:before {
content: "\e687";
}
.tffont-wangfan1:before {
content: "\e613";
}
.tffont-home_1:before {
content: "\e665";
}
.tffont-Home:before {
content: "\e64e";
}
.tffont-arrow-down:before {
content: "\e674";
}
.tffont-dingwei:before {
content: "\e6a2";
}
.tffont-ditu-xian:before {
content: "\e631";
}
.tffont-change1:before {
content: "\e66a";
}
.tffont-shouye:before { .tffont-shouye:before {
content: "\e634"; content: "\e634";
} }
......
...@@ -718,6 +718,27 @@ ...@@ -718,6 +718,27 @@
"style": { "style": {
"navigationStyle": "custom" "navigationStyle": "custom"
} }
},
{
"path" : "airIndex",
"style" :
{
"navigationStyle": "custom"
}
},
{
"path" : "airCity",
"style" :
{
"navigationBarTitleText" : "特价城市集合"
}
},
{
"path" : "ticketList/ticketList",
"style" :
{
"navigationStyle" : "custom"
}
} }
] ]
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</view> </view>
<view class="height-line1"></view> <view class="height-line1"></view>
</view> </view>
<view class="column" style="display: none;"> <view class="column">
<view class="AirplanePassengerAddEditingC-text row-sb-n fz30"> <view class="AirplanePassengerAddEditingC-text row-sb-n fz30">
<text class="flexS AirplanePassengerAddEditingC-textL">联系电话</text> <text class="flexS AirplanePassengerAddEditingC-textL">联系电话</text>
<view class="flexG"> <view class="flexG">
...@@ -158,8 +158,8 @@ ...@@ -158,8 +158,8 @@
</view> </view>
<view class="showAddEditing-buttom fz32 fontBold textCenter row-sb-n"> <view class="showAddEditing-buttom fz32 fontBold textCenter row-sb-n">
<view class="border1 colorDEBF7B borderDEBF7B" @click="showAddEditingPreviwe=false">返回修改</view> <view class="border1 colorDEBF7B borderDEBF7B" @click="showAddEditingPreviwe=false">返回修改</view>
<view v-if="!loading" class="border1 borderDEBF7B" @click="submit">确认{{editorIndex||editorIndex==0?'编辑':'添加'}}</view> <view class="border1 borderDEBF7B" @click="submit">确认{{editorIndex||editorIndex==0?'编辑':'添加'}}</view>
<view v-else class="border1 bgF5">确认{{editorIndex||editorIndex==0?'编辑':'添加'}}</view> <!-- <view v-else class="border1 bgF5">确认{{editorIndex||editorIndex==0?'编辑':'添加'}}</view> -->
</view> </view>
</view> </view>
</u-popup> </u-popup>
...@@ -325,10 +325,15 @@ ...@@ -325,10 +325,15 @@
this.addMsg.PassportExpiry = e.fulldate this.addMsg.PassportExpiry = e.fulldate
}, },
submit(){ submit(){
console.log('enter....')
if(this.loading) return
this.loading = true
this.addMsg.Id = Math.floor(Math.random()*(100-1)+1) this.addMsg.Id = Math.floor(Math.random()*(100-1)+1)
if(!this.editorIndex){ if(!this.editorIndex){
this.GuestList.push(this.addMsg) this.GuestList.push(this.addMsg)
} }
this.loading=false
console.log('enter....',this.GuestList,this.editorIndex,this.addMsg)
if(this.GuestList.length>0){ if(this.GuestList.length>0){
uni.setStorageSync("GuestList",this.GuestList) uni.setStorageSync("GuestList",this.GuestList)
uni.navigateBack({ uni.navigateBack({
......
This diff is collapsed.
This diff is collapsed.
<template>
<view style="height: 100vh; z-index:2; width:100vw;position: fixed;left: 0;top: 0;background-color: rgba(0, 0, 0, 0.6);">
<view style="z-index: 2; background-color: #FFF;padding-bottom:36rpx;position: absolute;top: 0;left: 0;right: 0;border-radius: 0 0 16rpx 16rpx;">
<view style="padding:24rpx;font-size: 40rpx;font-weight: bold;color: #121212;" class="text-center">
重新选择
</view>
<view class="air-tools">
<view class="row items-center" style="padding: 18rpx;padding-bottom: 10rpx;">
<text class="normal-label">出发地</text>
<text class="col text-center"></text>
<text class="normal-label">目的地</text>
</view>
<view class="row items-center toolsContainer"
style="padding:0 18rpx; padding-bottom: 18rpx;">
<text class="cities-name left-name" @click="showCityHandler(0)" :style="{transform: `translateX(${leftPos}px)`,transition: 'transform 0.5s ease'}">{{chosenResult[0].Name}}</text>
<view class="col exchange row items-center justify-center" @click="swapLocations">
<u-icon name="change1" custom-prefix="tffont" color="#B99846" size="66" :style="{transform: `rotate(${rotateNum}deg)`,transition: 'transform 0.5s ease'}"></u-icon>
</view>
<text class="cities-name right-name" @click="showCityHandler(1)" :style="{transform: `translateX(${rightPos}px)`,transition: 'transform 0.5s ease'}">{{chosenResult[1].Name}}</text>
</view>
<view @click="setCitiesHandler" class="text-center cities-name q-mt-md" style="background-color: #B99846;border-radius: 10rpx;height: 90rpx; line-height: 90rpx;color:#EEF1F4">确 认</view>
<u-popup mode="bottom" border-radius="20" :popup="false" v-model="citiesVisible" :maskCloseAble="true" length="auto" :safeAreaInsetBottom="true" @close="popupClose" :z-index="9999">
<city-list :city-type="currentCityObj.type" :city-value="currentCityObj.ID" @change="setCityHandler"></city-list>
</u-popup>
</view>
<view style="height: 100%;width: 100%;" @click="closed"></view>
</view>
</view>
</template>
<script>
import CityList from './CityList.vue';
export default {
components:{CityList},
props:{
value:{
type:Array
}
},
data(){
return {
chosenResult:[
{
type:0,
ID:0,
Name:'全部低价城市'
},
{
type:1,
ID:0,
Name:'全部低价城市'
}
],
currentCityObj:{
type:0,
ID:0
},
leftPos: 0,
rightPos: 0,
leftStyle:{
transform: `translateX(0px)`,
transition: 'transform 0.5s ease',
},
rightStyle:{
transform: `translateX(0px)`,
transition: 'transform 0.5s ease',
},
scrollTop:0,
containerWidth:336,
leftWidth:0,
rightWidth:0,
rotateNum:0,
citiesVisible:false,
}
},
watch: {
value: {
deep: true,
immediate: true,
handler: function(newVal, oldVal) {
if(this.value){
this.chosenResult = this.value
}
},
},
},
created() {
if(this.value){
this.chosenResult = this.value
}
},
mounted() {
//this.getContainerWidth()
},
methods:{
swapLocations() {
this.leftPos = this.leftPos === 0 ? (this.containerWidth-(this.chosenResult[0].Name.length*16)) : 0;
this.rightPos = this.rightPos === 0 ? -(this.containerWidth-(this.chosenResult[1].Name.length*16)) : 0;
this.chosenResult[0].type = this.leftPos === 0 ? 0 : 1
this.chosenResult[1].type = this.rightPos === 0 ? 1 : 0
this.rotateNum += 180
},
popupClose(){
this.citiesVisible = false
},
showCityHandler(i){
console.log(this.chosenResult[i])
this.currentCityObj = this.chosenResult[i]
this.citiesVisible = true
},
setCityHandler(val){
const i = this.chosenResult.findIndex((x)=>x.type==this.currentCityObj.type)
this.chosenResult[i] = {...this.currentCityObj,...val}
this.citiesVisible = false
},
setCitiesHandler(){
const result = JSON.parse(JSON.stringify(this.chosenResult))
result.sort((a, b) => {
return a.type - b.type;
});
this.$emit('change',result)
},
closed(){
this.$emit('closed')
}
}
}
</script>
<style>
@import url('../../../../asset/css/flex.css');
.air-tools {
padding:0 36rpx;
}
.air-tools .cities-name {
font-weight: bold;
font-size: 32rpx;
color: #080A09;
}
.air-tools .normal-label {
font-size: 24rpx;
color: #9999A6;
}
.air-tools .exchange {
background-image: url('https://viitto-1301420277.cos.ap-chengdu.myqcloud.com/Test/Upload/Goods/1696990221000_663.png');
background-repeat: no-repeat;
background-position: center center;
background-size: 38rpx auto;
/* 这里设置背景图片的宽度和高度 */
height: 30px;
}
</style>
\ No newline at end of file
<template>
<view style="padding: 36rpx;">
<view class="cities-name text-center">选择{{cityType==0?'出发地':'目的地'}}</view>
<view style="padding: 36rpx 0;">
<input type="text" class="text-input" v-model="keywords" placeholder="填写城市名称快速筛选" placeholder-style="font-size:12px" />
</view>
<template v-if="!loading">
<view class="cities-name" style="font-size: 28rpx;">{{ keywords==''?'热门城市':'搜索结果' }}</view>
<template v-if="showAddress && showAddress.length>0">
<scroll-view scroll-y="true" style="height: 55vh;">
<div class="row q-mt-md">
<view class="col city-item big q-mr-sm" v-if="keywords==''" :class="{'active':currentValue==0}" @click="setCurrentCity(0)">
<u-icon name="ditu-xian" custom-prefix="tffont" size="66" v-if="showAddress.length>2"></u-icon>
<view style="font-size: 28rpx;font-weight: 600;">全部低价城市</view>
</view>
<view class="col row flex-grid flex-wrap">
<template v-for="(x,i) in showAddress">
<view class="city-item " v-if="i<4" :key="i" @click="setCurrentCity(x.ID)" :class="{'active':currentValue==x.ID,'col-t-b':keywords=='','col-f-b':keywords!=''}">{{x.Name}}</view>
</template>
</view>
</div>
<div class="row flex-grid flex-wrap q-mt-sm">
<template v-for="(x,i) in showAddress">
<view class="city-item col-f-b" v-if="i>3" :key="i" @click="setCurrentCity(x.ID)" :class="{'active':currentValue==x.ID}">{{x.Name}}</view>
</template>
</div>
</scroll-view>
<view class="text-center q-mt-md" @click="setHandler" style="background-color: #B99846;border-radius: 10rpx;height: 90rpx; line-height: 90rpx;color:#EEF1F4">确认选择</view>
</template>
<view style="margin-top:10vh" class="text-center" v-else>
<u-empty mode="data"></u-empty>
</view>
</template>
<view style="margin-top:20vh" class="text-center" v-else>
<u-loading mode="circle" size="60"></u-loading>
<view class="normal-label text-center q-mt-sm">正在加载城市信息</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
addressList:[],
orgList:[],
keywords:'',
currentValue:0,
loading:false,
currentObj:{}
}
},
props:{
cityType:{
type:Number,
default:0
},
cityValue:{
type:Number,
default:0
}
},
created() {
this.getDataAddressList()
this.currentValue = this.cityValue
},
computed:{
showAddress(){
return this.addressList.filter((x)=>x.Name.indexOf(this.keywords)!=-1)
}
},
watch: {
cityType: {
deep: true,
immediate: true,
handler: function(newVal, oldVal) {
this.formatArray()
},
},
cityValue: {
deep: true,
immediate: true,
handler: function(newVal, oldVal) {
this.currentValue = this.cityValue,
this.mappingCityInfoHandler(this.cityValue)
},
}
},
methods: {
getDataAddressList(){
this.loading=true
const params = {
StartDate: '',
EndDate: '',
ArriveCityId: '0',
DepartCityId: '0',
AirLineID:'',
TicketType:2,//1单程 2往返
}
this.apipost("AirTicket_get_GetTicketCity",params,(res) => {
if(res.resultCode==1){
this.orgList = res.data
this.formatArray()
}
this.loading=false
},(e)=>{
this.loading=false
});
},
formatArray(){
if(!this.orgList || this.orgList.length==0) return
if(this.cityType==0) this.addressList = this.orgList
else{
let temp =[]
this.orgList.forEach(x=>{
const arr = x.CityList.map((y)=> ({ID:y.ID,Name:y.Name}))
temp = temp.concat(arr)
})
this.addressList = temp.filter((x,i)=>temp.findIndex(t=>t.ID===x.ID) === i)
}
},
setCurrentCity (id) {
this.currentValue = id
this.mappingCityInfoHandler(id)
},
mappingCityInfoHandler(id){
if(id==0){
this.currentObj = {
ID:id,
Name:'全部低价城市'
}
} else {
const i = this.showAddress.findIndex(x=>x.ID===id)
if(i>=0){
this.currentObj = {
ID:id,
Name:this.showAddress[i].Name
}
}
}
},
setHandler(){
this.$emit('change',this.currentObj)
}
}
}
</script>
<style>
.city-item{
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
font-weight: 400;
color: #000;
background-color: #f1f2f1;
text-align: center;
border-radius: 16rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: clip;
}
.city-item.active{
font-size: 30rpx;
font-weight: bold;
color: #f1f2f1;
background-color: #000;
}
.city-item.big{
height: auto;
line-height: auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: #B99846;
line-height: 1;
}
</style>
//节假日信息 //节假日信息
const day=[ const day =[
{
"year": 2025,
"month": 1,
"festival": [
{"name": "元旦", "day": 1},
{"name": "班", "day": 2},
{"name": "班", "day": 26},
{"name": "除夕", "day": 28},
{"name": "春节", "day": 29},
{"name": "休", "day": 30},
{"name": "休", "day": 31}
]
},
{ {
year:2022, "year": 2025,
month:1, "month": 2,
festival:[ "festival": [
{name:'元旦',day:1}, {"name": "休", "day": 1},
{name:'除夕',day:31}, {"name": "休", "day": 2},
{"name": "休", "day": 3},
] {"name": "休", "day": 4},
{"name": "班", "day": 8},
{"name": "元宵", "day": 12}
]
}, },
{ {
year:2022, "year": 2025,
month:2, "month": 3,
festival:[ "festival": [
{name:'春节',day:1}, {"name": "妇女节", "day": 8}
{name:'元宵',day:15}, ]
{name:'情人节',day:14}
]
}, },
{
"year": 2025,
"month": 4,
"festival": [
{"name": "清明节", "day": 4},
{"name": "班", "day": 27},
]
},
{
"year": 2025,
"month": 5,
"festival": [
{"name": "劳动节", "day": 1},
{"name": "休", "day": 2},
{"name": "休", "day": 3},
{"name": "休", "day": 4},
{"name": "休", "day": 5},
{"name": "端午", "day": 31}
]
},
{ {
year:2022, "year": 2025,
month:3, "month": 6,
festival:[ "festival": [
{name:'妇女节',day:8}, {"name": "儿童节", "day": 1},
] {"name": "休", "day": 2}
]
}, },
{ {
year:2022, "year": 2025,
month:4, "month": 8,
festival:[ "festival": [
{name:'清明',day:4}, {"name": "七夕", "day": 29},
] ]
}, },
{ {
year:2022, "year": 2025,
month:5, "month": 9,
festival:[ "festival": [
{name:'劳动节',day:1}, {"name": "班", "day": 28},
{name:'青年节',day:4}, ]
{name:'母亲节',day:10}, },
] {
}, "year": 2025,
{ "month": 10,
year:2021, "festival": [
month:6, {"name": "国庆", "day": 1},
festival:[ {"name": "休", "day": 2},
{name:'儿童节',day:1}, {"name": "休", "day": 3},
{name:'父亲节',day:21}, {"name": "休", "day": 4},
{name:'端午',day:14}, {"name": "休", "day": 5},
] {"name": "中秋", "day": 6},
}, {"name": "休", "day": 7},
{ {"name": "休", "day": 8},
year:2021, {"name": "班", "day": 11},
month:7, {"name": "重阳", "day": 29}
festival:[ ]
{name:'建党节',day:1} }
] ]
},
{
year:2021,
month:8,
festival:[
{name:'建军节',day:1},
{name:'七夕',day:14},
{name:'中元节',day:22},
]
},
{
year:2021,
month:9,
festival:[
{name:'教师节',day:10},
{name:'中秋',day:21}
]
},
{
year:2021,
month:10,
festival:[
{name:'国庆',day:1},
{name:'重阳',day:14}
]
},
{
year:2021,
month:11,
festival:[
{name:'感恩节',day:26}
]
},
{
year:2021,
month:12,
festival:[
{name:'平安夜',day:24},
{name:'圣诞节',day:25}
]
}
]
export default day export default day
\ No newline at end of file
<template>
<view class="calendar-container">
<view class="week-header">
<view v-for="(day, index) in weekDays" :key="index" class="week-day">{{ day }}</view>
</view>
<scroll-view scroll-y class="col" style="width:100%;height: 1px;">
<view v-for="(month, monthIndex) in calendarData" :key="monthIndex" class="month-container">
<view class="month-title">{{ month.year }}{{ month.month }}</view>
<view class="days-grid">
<view
v-for="(dayOffset, index) in month.firstDayOffset"
:key="`offset-${index}`"
class="day-placeholder"
></view>
<view
v-for="(day, dayIndex) in month.days"
:key="dayIndex"
class="day-item"
:class="[
{ 'selected': isSelected(monthIndex, dayIndex) },
{ 'disabled': isDisabled(monthIndex, dayIndex) },
{ 'festival': isFestivalDay(month, day) }
]"
@tap="handleDaySelect(monthIndex, dayIndex)"
>
<view class="day-number">{{ day }}</view>
<view v-if="calendarFestivals[`${month.year}${month.month}${day}`]" class="day-status">{{calendarFestivals[`${month.year}${month.month}${day}`]}}</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import festivals from "./day.js";
export default {
props: {
defaultDate: {
type: String,
default: ""
}
},
data() {
return {
weekDays: ['日', '一', '二', '三', '四', '五', '六'],
calendarData: [],
selectedDate: [],
screenWidth: 375,
calendarFestivals:{}
};
},
computed: {
// 计算当前日期信息
currentDate() {
const date = new Date();
return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate()
};
}
},
mounted() {
this.initializeCalendar();
},
methods: {
initializeCalendar() {
this.getScreenWidth();
this.generateCalendarData();
this.setInitialSelection();
this.applyFestivalData()
},
getScreenWidth() {
uni.getSystemInfo({
success: (res) => {
this.screenWidth = res.windowWidth;
}
});
},
generateCalendarData() {
let year = this.currentDate.year;
let month = this.currentDate.month;
this.calendarData = Array.from({ length: 6 }, (_, index) => {
const monthData = this.createMonthData(year, month + index);
return monthData;
});
},
createMonthData(year, month) {
// 处理月份超过 12 的情况
const actualMonth = month > 12 ? month % 12 : month;
return {
// 如果月份超过 12,年份加 1
year: month > 12 ? year + 1 : year,
// 实际月份
month: actualMonth,
// 该月的天数数组
days: Array.from({ length: new Date(year, actualMonth, 0).getDate() }, (_, index) => index + 1),
// 该月第一天是星期几
firstDayOffset: new Date(`${year}/${actualMonth}/1`).getDay()
};
},
applyFestivalData(monthData) {
this.calendarFestivals = festivals.reduce((acc, { year, month, festival }) => {
const subResult = festival.map(({ name, day }) => {
const key = `${year}${month}${day}`;
return { [key]: name };
});
return {...acc,...Object.assign({},...subResult) };
}, {})
},
setInitialSelection() {
if (this.defaultDate) {
const [year, month, day] = this.defaultDate.split('-');
const monthIndex = this.calendarData.findIndex(m =>
m.year == year && m.month == month
);
if (monthIndex !== -1) {
this.selectedDate = [monthIndex, parseInt(day) - 1];
}
}
},
isSelected(monthIndex, dayIndex) {
return this.selectedDate[0] === monthIndex &&
this.selectedDate[1] === dayIndex;
},
isDisabled(monthIndex, dayIndex) {
if (monthIndex === 0) {
return dayIndex + 1 < this.currentDate.day;
}
return false;
},
isFestivalDay(month, day) {
return typeof day === 'string';
},
formatDayDisplay(day) {
return typeof day === 'string' ? day : day + 1;
},
handleDaySelect(monthIndex, dayIndex) {
if (this.isDisabled(monthIndex, dayIndex)) return;
this.selectedDate = [monthIndex, dayIndex];
this.$emit('selected', this.getSelectedDateString());
},
getSelectedDateString() {
const monthData = this.calendarData[this.selectedDate[0]];
const dayNumber = this.selectedDate[1] + 1;
return `${monthData.year}-${String(monthData.month).padStart(2,'0')}-${String(dayNumber).padStart(2,'0')}`;
}
}
};
</script>
<style>
.calendar-container {
height: 100%;
display: flex;
flex-direction: column;
}
.week-header {
display: flex;
justify-content: space-around;
padding: 10px 0;
background: #f8f8f8;
border-radius: 16rpx;
}
.week-day {
width: 14.28%;
text-align: center;
font-size: 14px;
color: #333;
}
.month-container {
padding: 15px 10px;
}
.month-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
padding-left: 10px;
}
.days-grid {
display: flex;
flex-wrap: wrap;
}
.day-item, .day-placeholder {
width: 14.28%;
min-height: 50px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 5px 0;
}
.day-item {
position: relative;
font-size: 14px;
color: #333;
background: #fff;
}
.day-placeholder {
visibility: hidden;
}
.day-item.selected {
background: #DEBF7B;
color: #fff;
border-radius: 4px;
}
.day-item.disabled {
color: #ccc;
}
.day-item.festival {
color: #d32f2f;
font-size: 12px;
}
.day-status {
font-size: 10px;
color: #d32f2f;
position: absolute;
bottom: 2px;
}
</style>
\ No newline at end of file
<template>
<view style="padding:36rpx;height: 80vh;padding-bottom: 0;" class="column">
<view class="col column" style="width:100%;height: 1px;">
<view class="cities-name text-center full-width">选择出发日期</view>
<view class="q-mt-md q-mb-md full-width">
<u-tabs :list="chosenTypes" :show-bar="false" :is-scroll="false" :current="dateRangeValue.type" :active-color='mainColor' @change="changeTypeHandler"></u-tabs>
</view>
<view class="col full-width" v-if="dateRangeValue.type==0">
<view class="cities-name" style="font-size: 28rpx;">出发时间</view>
<div class="row flex-grid flex-wrap q-mt-md">
<view class="date-item col-f-b" v-for="(x,i) in fuzzyTypeList" @click="setFuzzyTypeHandle(x)" :key="i" :class="{'active':dateRangeValue.fuzzy.fuzzyType==x.Id}">{{x.Name}}</view>
</div>
<view class="cities-name" style="font-size: 28rpx;margin-top: 72rpx;">周几出发</view>
<div class="row items-center q-mt-md">
<view class="date-item col q-mr-sm" v-for="(x,i) in weeks" :key="i" @click="setWeekHandler(i)" :class="{'active':dateRangeValue.fuzzy.weeks.indexOf(i)!=-1}">{{x}}</view>
</div>
<view class="row items-center" style="margin-top: 72rpx;">
<view class="col">
<text class="cities-name" style="font-size: 28rpx;margin-top: 72rpx;">出行天数</text>
<text class="q-ml-md cities-name" style="font-size: 28rpx;">({{ dateRangeValue.fuzzy.dayRange.join(' - ') }}) 天</text>
</view>
<view class="">
<u-switch v-model="dateRangeValue.fuzzy.dayRangStatus" :active-color="mainColor" :size="30"></u-switch>
</view>
</view>
<view class="q-mt-md" v-show="dateRangeValue.fuzzy.dayRangStatus">
<llt-slider-range :model-value="dateRangeValue.fuzzy.dayRange" @change="handleDayRangChange" :blockSize="24" :active-color="mainColor" :min="1" :max="15" />
</view>
</view>
<view class="col" style="height: 1px;" v-else>
<date-sign :default-date="dateRangeValue.startDate" @selected="handleSelectedDate"></date-sign>
</view>
</view>
<view class="text-center q-mt-md" @click="setValueHandler" style="background-color: #B99846;border-radius: 10rpx;height: 90rpx; line-height: 90rpx;color:#EEF1F4">确认选择</view>
</view>
</template>
<script>
import DateSign from '../sign/sign.vue';
export default {
data(){
return {
dateRangeValue:{
type:0,
startDate:'',
fuzzy:{
fuzzyType:0,
fuzzyTypeName:'',
weeks:[],
dayRangStatus:false,
dayRange:[4,10]
}
},
mainColor:'',
chosenTypes:[
{name:'模糊日期'},
{name:'精确日期'}
],
fuzzyTypeList:[
{Id:-1,Name:'未来一个月'},
{Id:-2,Name:'未来三个月'}
],
weeks:['一','二','三','四','五','六','日']
}
},
components:{DateSign},
props:{
value:{
type:Object,
default:null
}
},
created() {
this.mainColor = this.$uiConfig.mainColor;
this.fillMonthType()
if(this.value){
this.dateRangeValue = this.value
}
console.log(this.value)
},
watch:{
value: {
deep: true,
immediate: true,
handler: function(newVal, oldVal) {
if(this.value){
this.dateRangeValue = this.value
}else{
this.dateRangeValue = {
type:0,
range:['',''],
fuzzy:{
fuzzyType:0,
fuzzyTypeName:'',
weeks:[],
dayRangStatus:false,
dayRange:[4,10]
}
}
}
},
},
},
methods:{
changeTypeHandler(index){
this.dateRangeValue.type = index
},
fillMonthType(){
let date = new Date()
for (var i = 0; i < 4; i++) {
date.setMonth(date.getMonth() + (i==0?0:1));
const month = date.getMonth()+1
this.fuzzyTypeList.push({
Id:i+1,
Name:`${month}月`
})
}
},
setWeekHandler(i){
const t = this.dateRangeValue.fuzzy.weeks.indexOf(i)
if(t==-1) this.dateRangeValue.fuzzy.weeks.push(i)
else this.dateRangeValue.fuzzy.weeks.splice(t,1)
},
handleDayRangChange(val){
this.dateRangeValue.fuzzy.dayRange = val
},
setValueHandler(){
this.resolveDateFormatHandle()
this.$emit('change',this.dateRangeValue)
},
setFuzzyTypeHandle(item){
this.dateRangeValue.fuzzy.fuzzyType=item.Id
this.dateRangeValue.fuzzy.fuzzyTypeName=item.Name
},
handleSelectedDate(val){
this.dateRangeValue.startDate = val
},
resolveDateFormatHandle(){
console.log(this.dateRangeValue.fuzzy)
if(this.dateRangeValue.type==1){
if(this.dateRangeValue.startDate==''){
this.dateRangeValue.formatStartDate='任意时间出发'
}else{
this.dateRangeValue.formatStartDate=`${this.dateRangeValue.startDate} ${this.$utils.getWeekName(this.dateRangeValue.startDate)}`
}
}else{
let val = ''
if(this.dateRangeValue.fuzzy.fuzzyType!=0){
val = this.dateRangeValue.fuzzy.fuzzyTypeName
}
if(this.dateRangeValue.fuzzy.weeks && this.dateRangeValue.fuzzy.weeks.length>0){
const w = this.weeks.filter((x,i)=>this.dateRangeValue.fuzzy.weeks.indexOf(i)!=-1).map((x,i)=>{
return `周${x}`
})
val += (val==''?'':' | ')+w.join(',')
}
if(this.dateRangeValue.fuzzy.dayRangStatus){
val += (val==''?'':' | ')+this.dateRangeValue.fuzzy.dayRange.join('-')+'天'
}
this.dateRangeValue.formatStartDate = val==''?'任意时间出发':val
}
}
}
}
</script>
<style>
.full-width{
width: 100%;
}
.date-item{
height: 80rpx;
line-height: 80rpx;
font-size: 28rpx;
font-weight: 400;
color: #000;
background-color: #f1f2f1;
text-align: center;
border-radius: 16rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: clip;
}
.date-item.active{
font-size: 30rpx;
/* font-weight: bold; */
color: #f1f2f1;
background-color: #000;
}
</style>
\ No newline at end of file
<template>
<view style="height: 100vh;" class="column">
<view class="nav-box row items-center" :style="{paddingTop:barHeight+'px',height:(barHeight+44)+'px'}">
<view class="home-btn row items-center" @click="goBackHandle">
<u-icon name="arrowleft" custom-prefix="tffont" color="#111" size="34"
style="font-weight: bolder;"></u-icon>
</view>
<view class="home-btn row items-center" @click="goHomeHandle">
<u-icon name="home_1" custom-prefix="tffont" color="#111" size="38"
style="font-weight: bolder;"></u-icon>
</view>
<view class="title row items-center justify-center">
<text>{{chosenResult[0].Name}}</text>
<view style="margin:0 20rpx">
<u-icon name="wangfan1" custom-prefix="tffont" color="#00000066" size="36"></u-icon>
</view>
<text>{{chosenResult[1].Name}}</text>
<u-icon class="q-ml-sm" name='arrow_down' custom-prefix="tffont" color="#00000066" size="32"></u-icon>
</view>
</view>
<view class="column items-center justify-center q-mb-md" v-if="loadingLow">
<u-loading mode="circle" size="40"></u-loading>
<view class="normal-label text-center q-mt-sm">正在加载信息</view>
</view>
<view style="margin:10vh 0" class="text-center" v-else-if="lowData.length==0">
<u-empty mode="data"></u-empty>
</view>
<template v-else>
<view class="time-list row" style="padding:0 12rpx;">
<scroll-view scroll-x class="col" style="padding:12rpx 0;">
<view class="row items-center">
<view class="time-item" @click="setCurrentDateHandle"
:class="{'active':currentDate==x.FlightDate}" v-for="(x,i) in lowHeadData" :key="i">
<view class="">{{x.FlightDate.split('-').splice(1,2).join('-')}}</view>
<view style="margin: 10rpx 0;">{{x.WeekDayStr}}</view>
<view class="">¥{{x.B2BPrice}}</view>
</view>
</view>
</scroll-view>
<view class="time-item" style="box-shadow: -1 0 10px #00000066;">
<u-icon class="q-ml-sm" name='arrow_down' custom-prefix="tffont" color="#00000066" size="32"></u-icon>
</view>
</view>
</template>
</view>
</template>
<script>
export default {
data() {
return {
barHeight: 0,
currentDate: '',
lowData: [],
lowHeadData: [],
dateRangeValue: {
type: 0,
startDate: '',
fuzzy: {
fuzzyType: 0,
fuzzyTypeName: '',
weeks: [],
dayRangStatus: false,
dayRange: [4, 10]
},
formatStartDate: '任意时间出发'
},
chosenResult: [{
type: 0,
ID: 0,
Name: '全部城市'
},
{
type: 1,
ID: 0,
Name: '全部城市'
}
],
loadingLow: false,
parementers: {
StartDate: '',
EndDate: '',
DepartCityId: 0,
ArriveCityId: 0,
AirLineID: 0,
groupId: 2,
TicketType: 2,
StartPlayDay: 0,
EndPlayDay: 0,
WeekDay: ''
}
}
},
created() {
if (uni.getStorageSync('scf')) {
const s = uni.getStorageSync('scf')
this.dateRangeValue = s.dateRange
this.chosenResult = s.cities
}
this.chosenResult.sort((a, b) => {
return a.type - b.type;
});
this.getTopLowTicketHandle()
},
mounted() {
let that = this
uni.getSystemInfo({
success(r) {
that.barHeight = r.statusBarHeight
},
});
},
methods: {
resolveParameterHanle() {
this.resetParameterHandle()
this.parementers.DepartCityId = this.chosenResult[0].ID
this.parementers.ArriveCityId = this.chosenResult[1].ID
if (this.dateRangeValue.type == 1) {
//this.parementers.StartDate = this.dateRangeValue.startDate
this.currentDate = this.formatDateHandle(start)
//this.parementers.EndDate = this.dateRangeValue.startDate
} else {
const d = this.resolveDateByFuzzyHandle(this.dateRangeValue.fuzzy.fuzzyType)
this.parementers.StartDate = d[0]
this.parementers.EndDate = d[1]
// if (this.dateRangeValue.fuzzy.weeks.length > 0) {
// const weeks = [2, 3, 4, 5, 6, 7, 1]
// this.parementers.WeekDay = weeks.filter((x, i) => this.dateRangeValue.fuzzy.weeks.indexOf(i) != -1)
// .join(',')
// }
// if (this.dateRangeValue.fuzzy.dayRangStatus) {
// this.parementers.StartPlayDay = this.dateRangeValue.fuzzy.dayRange[0]
// this.parementers.EndPlayDay = this.dateRangeValue.fuzzy.dayRange[1]
// }
}
},
resetParameterHandle() {
this.currentDate = ''
this.parementers = {
StartDate: '',
EndDate: '',
DepartCityId: 0,
ArriveCityId: 0,
AirLineID: 0,
groupId: 2,
TicketType: 2,
StartPlayDay: 0,
EndPlayDay: 0,
WeekDay: ''
}
},
resolveDateByFuzzyHandle(t) {
if (t == 0) return ['', '']
let start = new Date();
let end = new Date()
if (t == -1) {
start.setTime(start.getTime() + 3600 * 1000 * 24 * 1);
end.setMonth(end.getMonth() + 1);
} else if (t == -2) {
start.setTime(start.getTime() + 3600 * 1000 * 24 * 1);
end.setMonth(end.getMonth() + 3)
} else {
const currentDate = new Date()
currentDate.setMonth(currentDate.getMonth() + t);
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
start = new Date(year, month, 1);
end = new Date(year, month + 1, 0);
}
this.currentDate = this.formatDateHandle(start)
return ['', ''] //[this.formatDateHandle(start), this.formatDateHandle(end)]
},
formatDateHandle(date) {
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2,'0')}-${String(date.getDate()).padStart(2,'0')}`
},
getTopLowTicketHandle() {
this.resolveParameterHanle()
this.lowData = []
this.loadingLow = true
this.apipost('AirTicket_get_GetTopTicketProduct', this.parementers, (r) => {
if (r.resultCode == 1) {
this.lowData = this.formatLowData(r.data)
}
this.loadingLow = false
}, (e) => {
this.loadingLow = false
})
},
formatLowData(d) {
if (!d || d.length == 0) return []
const list = d[0].TicketProductList
list.sort((a, b) => {
return new Date(a.FlightDate) - new Date(b.FlightDate);
})
this.lowHeadData =this.foramtHeaderListHandle(list)
return list
},
setCurrentDateHandle(date) {
this.currentDate = date
},
foramtHeaderListHandle(d){
const result = d.reduce((acc, item) => {
const groupValue = item.FlightDate;
const currentPrice = item.B2BPrice;
if (!acc[groupValue]) {
acc[groupValue] = {
FlightDate: groupValue,
B2BPrice: currentPrice,
WeekDayStr: item.WeekDayStr
};
} else {
acc[groupValue].B2BPrice = Math.min(acc[groupValue].B2BPrice, currentPrice);
}
return acc;
}, {});
const finalResult = Object.values(result);
return finalResult
},
formatDateString(d) {
const date = new Date(d)
const weeks = ['日', '一', '二', '三', '四', '五', '六']
return `${String(date.getMonth()+1).padStart(2,'0')}.${String(date.getDate()).padStart(2,'0')}${weeks[date.getDay()]}` //周${weeks[date.getDay()]}
},
goBackHandle() {
uni.navigateBack(-1)
},
goHomeHandle() {
uni.redirectTo({
url: '/pages/index/index'
})
}
}
}
</script>
<style>
@import url('../../../asset/css/flex.css');
.nav-box {
height: 44px;
/* 这里的44px是示例高度,可根据实际设计调整 */
line-height: 44px;
background-color: #FFF;
color: #fff;
width: 100vw;
padding-left: 30rpx;
background-color: #d4b465;
}
.nav-box .home-btn {
width: 60rpx;
height: 60rpx;
border-radius: 60rpx;
/* border:2rpx solid #ccc; */
display: flex;
align-items: center;
justify-content: center;
}
.nav-box .title {
font-weight: bold;
font-size: 32rpx;
color: #080A09;
text-align: center;
width: calc(100vw - 140px);
}
.time-list {
background: linear-gradient(0, #eacf8d, #d4b465);
width: 100%;
}
.time-list .time-item {
padding: 22rpx 33rpx;
font-size: 24rpx;
color: #111;
line-height: 1;
text-align: center;
border-radius: 16rpx;
position: relative;
min-width: 148rpx;
}
.time-list .time-item::after {
position: absolute;
display: block;
right: 0;
width: 1px;
height: 60%;
top: 20%;
content: ' ';
background-color: #FFFFFF33;
}
.time-list .time-item.active {
background-color: #e7d9b2;
font-weight: bold;
margin-left: -1px;
}
.time-list .time-item.active::after,
.time-list .time-item:last-child::after {
display: none;
}
/* .nav-box .home-btn:active{
background-color: #ccc;
} */
</style>
\ No newline at end of file
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
<!--同行绑定--> <!--同行绑定-->
<view class="login-page"> <view class="login-page">
<view class="logo-head"> <view class="logo-head">
<image src="https://viitto-1301420277.cos.ap-chengdu.myqcloud.com/Test/Upload/Goods/1695262844000_280.png" mode="widthFix"></image> <image src="https://viitto-1301420277.cos.ap-chengdu.myqcloud.com/Upload/Goods/638749517916150559.jpg" mode="heightFix"></image>
<view class="logo-text">旅小友</view> <!-- <view class="logo-text">旅小友</view> -->
</view> </view>
<view class="login-form"> <view class="login-form">
<view class="login-title">同行登录</view> <view class="login-title">同行登录</view>
...@@ -147,7 +147,7 @@ ...@@ -147,7 +147,7 @@
} }
.login-page .logo-head image { .login-page .logo-head image {
width: 50px; /* width: 50px; */
height: 50px; height: 50px;
margin-right: 10px; margin-right: 10px;
} }
......
...@@ -52,8 +52,18 @@ ...@@ -52,8 +52,18 @@
<view class="jz_LineTitleLText" v-else>返100/人</view> <view class="jz_LineTitleLText" v-else>返100/人</view>
</view> </view>
<view class="col"> <view class="col">
<text>同业价:</text>
<text class="jz_renmin">¥</text><text class="jz_B2bPrice">{{ discountPrice }}</text> <text class="jz_renmin">¥</text><text class="jz_B2bPrice">{{ discountPrice }}</text>
<text style="color: #999999; font-size: 28rpx; font-weight: 400">/人起</text> <text style="color: #999999; font-size: 28rpx; font-weight: 400">/人起</text>
<view class="" v-if="stepNumber==0&&dataList.currentPriceInfo.teamType==0">
<text style="font-size: 13px;color:#111">
直客价:<text style="font-size: 20rpx;">¥</text>{{ currentPrice.b2CPrice}}
</text>
</view>
<text style="font-size: 13px;color:#111;margin-left: 10px;" v-else>
直客价:<text style="font-size: 20rpx;">¥</text>{{ currentPrice.b2CPrice}}
</text>
</view> </view>
<view v-if="stepNumber==0&&dataList.currentPriceInfo.teamType==0" class="row items-center jz_LineDetaCZ" style="border-radius: 4px;overflow: hidden;font-size: 12px;" > <view v-if="stepNumber==0&&dataList.currentPriceInfo.teamType==0" class="row items-center jz_LineDetaCZ" style="border-radius: 4px;overflow: hidden;font-size: 12px;" >
......
...@@ -24,9 +24,9 @@ export default { ...@@ -24,9 +24,9 @@ export default {
Vue.prototype.host = "https://wx.weibaoge.cn/web/index.php?_mall_id=1285" Vue.prototype.host = "https://wx.weibaoge.cn/web/index.php?_mall_id=1285"
// Vue.prototype.host2 = "http://192.168.5.46:8300" // Vue.prototype.host2 = "http://192.168.5.46:8300"
// Vue.prototype.host3 = "http://192.168.5.46" Vue.prototype.host3 = "http://192.168.5.46:8501"
Vue.prototype.host2 = "https://erpmallapi.oytour.com" Vue.prototype.host2 = "https://erpmallapi.oytour.com"
Vue.prototype.host3 = "https://reborn.oytour.com" //Vue.prototype.host3 = "https://reborn.oytour.com"
Vue.prototype.request = function(param, success, failed) { Vue.prototype.request = function(param, success, failed) {
//网络请求 //网络请求
......
...@@ -17,6 +17,12 @@ function SystemInfo() {//获取屏幕宽高 ...@@ -17,6 +17,12 @@ function SystemInfo() {//获取屏幕宽高
}) })
return SystemInfo return SystemInfo
} }
function getWeekName(date) {
const weeks = ['周日','周一','周二','周三','周四','周五','周六']
const currentDate = new Date(date)
const i = currentDate.getDay()
return weeks[i]
}
function getRect(selector) {//获取元素的信息 function getRect(selector) {//获取元素的信息
return new Promise((resolve) => { return new Promise((resolve) => {
let view = uni.createSelectorQuery().select(selector); let view = uni.createSelectorQuery().select(selector);
...@@ -157,4 +163,5 @@ export default { ...@@ -157,4 +163,5 @@ export default {
SubscribeMsgAli, SubscribeMsgAli,
// #endif // #endif
VersionUpdate, VersionUpdate,
getWeekName
} }
\ No newline at end of file
## 1.0.6(2025-01-08)
更新文档
## 1.0.5(2024-12-26)
优化显示
## 1.0.4(2024-12-26)
优化显示
## 1.0.3(2024-12-25)
- 更新依赖
## 1.0.2(2024-12-25)
- 优化滑块相近时tip显示
## 1.0.1(2024-12-25)
- 优化逻辑
## 1.0.0(2024-12-25)
新增:
- 双滑块范围选择器基础功能
- 支持设置最小值(min)和最大值(max)
- 支持自定义步长(step)设置
- 支持禁用状态(disabled)
- 自定义样式功能:
- 滑动条背景色(backgroundColor)
- 选中范围颜色(activeColor)
- 滑块大小(blockSize)
- 滑块颜色(blockColor)
- 值格式化功能(format)
- 支持移动端触摸操作
- v-model双向绑定支持
let timer; let
flag
/**
* 节流原理:在一定时间内,只能触发一次
*
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
function throttle(func, wait = 500, immediate = true) {
if (immediate) {
if (!flag) {
flag = true
// 如果是立即执行,则在wait毫秒内开始时执行
typeof func === 'function' && func()
timer = setTimeout(() => {
flag = false
}, wait)
}
} else if (!flag) {
flag = true
// 如果是非立即执行,则在wait毫秒内的结束处执行
timer = setTimeout(() => {
flag = false
typeof func === 'function' && func()
}, wait)
}
}
export default throttle
{
"id": "llt-slider-range",
"displayName": "slider range双滑块范围选择器",
"version": "1.0.6",
"description": "一个功能强大的双滑块范围选择器组件,可用于价格区间、数值范围等场景的选择。支持自定义样式、步长设置,具有良好的移动端适配性和交互体验。",
"keywords": [
"slider",
"range",
"slider-range",
"区间滑块"
],
"repository": "",
"engines": {
"HBuilderX": "^3.8.6"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"type": "component-vue"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "n",
"app-uvue": "n",
"app-harmony": "u"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "y",
"Edge": "y",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "y",
"百度": "y",
"字节跳动": "y",
"QQ": "y",
"钉钉": "y",
"快手": "y",
"飞书": "y",
"京东": "y"
},
"快应用": {
"华为": "y",
"联盟": "y"
},
"Vue": {
"vue2": "y",
"vue3": "y"
}
}
}
}
}
# SliderRange 双滑块范围选择器
> 一个轻量级但功能强大的双滑块范围选择器组件,完美适配移动端和PC端,为您的项目提供直观的范围选择体验。
## 🌟 特性
- ✨ 灵活的范围设置 - 支持自定义最大最小值
- 📏 精确的步长控制 - 可设置数值变化的最小单位
- 🎨 丰富的样式定制 - 支持自定义滑块、轨道样式
- 📱 完美的跨端适配 - 支持H5/App/小程序多端使用
- 🔄 双向绑定支持 - 支持v-model语法
- 🎯 刻度线显示 - 直观的数值参考
- ⌨️ 键盘操作支持 - 提升无障碍体验
- 🚫 禁用状态 - 支持只读模式
## 📦 安装
### 下载使用
`llt-slider-range` 组件复制到你的项目中即可。
## 🚀 快速开始
### H5/App使用示例
```vue
<template>
<llt-slider-range v-model="rangeValue" />
</template>
<script>
export default {
data() {
return {
rangeValue: [30, 50] // 设置初始范围值
}
}
}
</script>
```
### 微信小程序使用示例
```vue
<template>
<llt-slider-range
:model-value="rangeValue"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
rangeValue: [30, 50]
}
},
methods: {
handleChange(val) {
this.rangeValue = val
}
}
}
</script>
```
## 📝 API文档
### Props 属性
| 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| modelValue/v-model | Array | [0, 100] | 当前选中的范围值 |
| min | Number | 0 | 最小可选值 |
| max | Number | 100 | 最大可选值 |
| step | Number | 1 | 步长,必须大于0 |
| disabled | Boolean | false | 是否禁用 |
| backgroundColor | String | '#F6F6F6' | 滑动条背景色 |
| activeColor | String | '#4DB8F6' | 选中范围的颜色 |
| blockSize | Number | 48 | 滑块大小(rpx) |
| blockColor | String | '#fff' | 滑块颜色 |
| format | Function | val => val | 数值格式化函数 |
### Events 事件
| 事件名 | 说明 | 回调参数 |
|--------|------|----------|
| update:modelValue | 值更新时触发 | (value: number[]) |
| change | 值变化时触发 | (value: number[]) |
## 💡 高级用法
### 价格范围选择器
```vue
<template>
<llt-slider-range
v-model="priceRange"
:min="0"
:max="10000"
:step="100"
:format="formatPrice"
active-color="#FF6B6B"
/>
</template>
<script>
export default {
data() {
return {
priceRange: [1000, 5000]
}
},
methods: {
formatPrice(val) {
return `¥${val}`
}
}
}
</script>
```
### 温度选择器
```vue
<template>
<llt-slider-range
v-model="tempRange"
:min="-20"
:max="40"
:format="val => `${val}°C`"
active-color="#2196F3"
/>
</template>
```
## ⚠️ 注意事项
1. 确保传入的范围值在 min 和 max 之间
2. step 值必须为正数
3. 移动端使用时建议适当增大 blockSize 以提升触控体验
4. 小程序端需使用 model-value + change 事件方式实现双向绑定
5. 建议在父容器设置合适的宽度,以获得最佳显示效果
## 🔗 相关链接
- [GitHub 仓库](https://github.com/llt3677/slider-range)
- [插件市场](https://ext.dcloud.net.cn/plugin?id=21575)
- [问题反馈](https://github.com/llt3677/slider-range/issues)
## 📄 License
[MIT](https://opensource.org/licenses/MIT)
---
如果这个组件对你有帮助,欢迎 star ⭐️ 支持一下!
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment