mrr.sj.front/pages/shop/manHour/buyManHour.vue

869 lines
21 KiB
Vue

<template>
<view class="container" :class="{ popupShow: filterShow }">
<custom-navbar
title="订工时"
:showBack="true"
backgroundColor="#FFFFFF"
></custom-navbar>
<view class="flexed" :style="{top:`${statusBarHeight*2 + 88}rpx`}">
<!-- 搜索框 -->
<view class="headerBox">
<view class="search-box">
<input
type="text"
class="search-inp"
placeholder="工时名称"
placeholder-class="placeholder"
v-model="title"
@confirm="refreshList"
/>
<image
src="/static/home/search.png"
class="search-icon"
mode="aspectFit"
@click="refreshList"
>
</image>
</view>
</view>
<!-- 状态标签 -->
<!-- 一级Tab -->
<scroll-view scroll-x class="main-tab-scroll" :show-scrollbar="false">
<view class="main-tabs">
<view
v-for="(tab, idx) in tabs"
:key="tab.id"
:class="[
'main-tab',
{ active: queryData.first_class_id == tab.id },
]"
@click="getFirstlist(tab, idx)"
>
<text class="tab-text">{{ tab.title }}</text>
</view>
</view>
</scroll-view>
<!-- 二级icon分类 -->
<scroll-view scroll-x class="icon-tab-scroll" show-scrollbar="false" v-if="tabs.length > 0">
<view class="icon-tabs">
<view
v-for="(item, idx) in tabs[tabsIndex].data"
:key="item.id"
class="icon-tab"
:class="{ active: queryData.second_class_id == item.id }"
@click="getSecondlist(item)"
>
<image
:src="item.photo"
class="icon-img"
mode="aspectFill"
></image>
<text class="icon-text">{{ item.title }}</text>
</view>
</view>
</scroll-view>
<view class="filter">
<view class="filter__left">
<view class="filter__text" @click="showTimeFilter = !showTimeFilter"
>服务时间</view
>
<image
src="/static/images/icons/triangle_down.png"
class="filter-icon"
/>
</view>
<view class="filter__right">
<view class="filter__text" @click="openFilter">筛选</view>
<image
src="/static/images/icons/triangle_down.png"
class="filter-icon"
/>
</view>
</view>
<!-- 服务时间选择 -->
<view
class="filter__left__select__bj"
@click="showTimeFilter = false"
v-show="showTimeFilter"
></view>
<view class="filter__left__select" :class="{ show: showTimeFilter }">
<view
v-for="(item, index) in serviceHours"
:key="item.id"
@click="selctServiceHours(item, index)"
:class="[
`filter__left__select__item`,
{ active: serviceHoursIndex === item.id },
]"
>
<view class="filter__left__select__item__title"
>{{ item.title }}
<image
v-if="serviceHoursIndex === item.id"
src="/static/images/icons/active.png"
class="filter__left__select__item__title__icon"
mode="aspectFit"
></image>
</view>
</view>
</view>
</view>
<view class="server-list" v-if="serverlist.length">
<buy-order-card
v-for="(item, index) in serverlist"
:key="index"
:info="item"
@placeOrder="placeOrder"
></buy-order-card>
</view>
<!-- 暂无数据 -->
<noData v-else></noData>
<filterPopup
ref="filterPopup"
@change="filterChange"
:filterListSelectLists="filterListSelectLists"
@reset="resetFilter"
@sure="sureFilter"
>
<filterCard
:info="filterDetailsLists[0]"
@selectDetail="selectDetailTime"
:infoDetailList="infoDetailLists[0]"
>
<view class="time-customize" @click="openTimePopup">
{{ customizeTime ? customizeTime : "自定义" }}
</view>
</filterCard>
<filterCard
:info="filterDetailsLists[1]"
@selectDetail="selectDetailPrice"
:isSingle="true"
:infoDetailList="infoDetailLists[1]"
>
<view class="price-input">
<input
type="number"
v-model="start_price"
placeholder="最低价"
class="price-input-field"
/>
<text class="price-separator"></text>
<input
type="number"
v-model="end_price"
placeholder="最高价"
class="price-input-field"
/>
</view>
</filterCard>
<filterCard
:info="filterDetailsLists[2]"
@selectDetail="selectDetailSort"
:isSingle="true"
:infoDetailList="infoDetailLists[2]"
>
</filterCard>
</filterPopup>
<timePicker ref="timePopup" @confirmTime="confirmTime"></timePicker>
</view>
</template>
<script>
import timePicker from "components/time-picker/time-picker.vue";
import filterPopup from "../../../components/filter-popup/filter-popup.vue";
import request from "@/utils/request";
import buyOrderCard from "./components/buyOrderCard.vue";
import filterCard from "components/filterCard/filterCard.vue";
export default {
name: "buyManHour",
data() {
return {
statusBarHeight:0,
filterShow: false,
isLoad: true, //加载完成
count: 0,
customizeTime: "", // 自定义时间
showTimeFilter: false, // 服务时间选择显示状态
title: "", // 搜索标题
tabs: [],
tabsIndex: 0, // 当前选中的分类索引
queryData: {
page: 1,
limit: 10,
},
start_price: null,
end_price: null,
filterListId: null,
infoDetailLists: [], // 筛选列表选择项
filterListSelectLists: [], // 筛选列表选择状态
filterDetailsLists: [
{
id: 1,
title: "营业时间",
details: [
{
id: 1,
name: "营业中",
value: "",
},
{
id: 2,
name: "24小时营业",
value: "00:00-23:59",
},
{
id: 3,
name: "9-12时",
value: "9:00-12:00",
},
{
id: 4,
name: "12-14时",
value: "12:00-14:00",
},
{
id: 5,
name: "14-18时",
value: "14:00-18:00",
},
{
id: 6,
name: "18-24时",
value: "18:00-23:59",
},
{
id: 7,
name: "0-9时",
value: "0:00-12:00",
},
],
},
{
id: 2,
title: "价格",
details: [
{
id: 1,
name: "0-10元",
value: "0-10",
},
{
id: 2,
name: "10-30元",
value: "10-30",
},
{
id: 3,
name: "30-50元",
value: "30-50",
},
{
id: 4,
name: "50-100元",
value: "50-100",
},
{
id: 5,
name: "100-300元",
value: "100-300",
},
{
id: 6,
name: "300+",
value: "300-",
},
],
},
{
id: 3,
title: "排序",
details: [
{
id: 1,
name: "价格最低",
value: "1",
},
{
id: 2,
name: "价格最高",
value: "2",
},
{
id: 3,
name: "销量最高",
value: "3",
},
],
},
],
serviceHours: [
{
id: 1,
title: "今日可约",
},
{
id: 2,
title: "近两日可约",
},
{
id: 3,
title: "近三日可约",
},
], // 服务工时列表
serviceHoursIndex: null, // 当前选中的服务工时索引
serverlist: [],
};
},
components: {
buyOrderCard,
filterPopup,
filterCard,
timePicker,
},
async onLoad() {
// 获取状态栏高度
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight;
await this.getClass();
await this.refreshList();
//赋予当前营业中value
this.filterDetailsLists[0].details[0].value = this.getCurrentToEndOfDay();
},
onPullDownRefresh() {
this.refreshList();
},
async onReachBottom() {
console.log("onReachBottom");
if (
this.count <= this.queryData.page * this.queryData.limit ||
!this.isLoad
) {
return;
}
this.queryData.page++;
this.refreshList(false);
},
methods: {
filterChange(e) {
this.filterShow = e.show;
},
placeOrder(id) {
console.log("下单工时ID", id);
uni.navigateTo({
url: `/pages/shop/manHour/manHourDetail?id=${id}`,
});
},
getCurrentToEndOfDay() {
const now = new Date();
const hours = String(now.getHours()).padStart(2, "0");
const minutes = String(now.getMinutes()).padStart(2, "0");
return `${hours}:${minutes}-${hours}:${minutes}`;
},
openTimePopup() {
this.$refs.timePopup.openTimePopup();
},
openFilter() {
this.$refs.filterPopup.open();
},
refreshList(isRefresh = true) {
if (isRefresh) {
this.queryData.page = 1;
this.queryData.limit = 10;
}
this.queryData.title = this.title;
request
.post("/sj/workHour/list", this.queryData)
.then((res) => {
if (isRefresh) {
this.serverlist = res.data.list;
this.count = res.data.count;
} else {
this.serverlist = [...this.serverlist, ...res.data.list];
this.count = res.data.count;
}
})
.finally(() => {
this.isLoad = true;
uni.stopPullDownRefresh();
});
},
async getClass() {
await request.post("/sj/workHour/classList").then((res) => {
console.log("获取工时分类列表", res);
if (res.code == 200) {
this.tabs = res.data;
this.queryData.first_class_id = this.tabs[0].id;
// 通过 Vuex 存储分类列表到全局状态管理;
this.$store.commit("setworkHourSJClassList", res.data);
}
});
},
async selctServiceHours(item, index) {
this.serviceHoursIndex = item.id;
// this.queryData.service_hours = item.id;
await this.getDate(index);
this.queryData.page = 1; // 重置页码
this.refreshList(); // 刷新列表
this.showTimeFilter = false; // 隐藏服务时间选择
},
getDate(index) {
this.queryData.date = [];
//今天的时间
var day1 = new Date();
day1.setTime(day1.getTime());
var m1 = day1.getMonth() + 1;
if (m1 <= 9) {
m1 = "0" + m1;
}
var d1 = day1.getDate();
if (d1 <= 9) {
d1 = "0" + d1;
}
var s1 = day1.getFullYear() + "-" + m1 + "-" + d1;
//明天的时间
var day2 = new Date();
day2.setTime(day2.getTime() + 24 * 60 * 60 * 1000);
var m2 = day2.getMonth() + 1;
if (m2 <= 9) {
m2 = "0" + m2;
}
var d2 = day2.getDate();
if (d2 <= 9) {
d2 = "0" + d2;
}
var s2 = day2.getFullYear() + "-" + m2 + "-" + d2;
//后天的时间
var day3 = new Date();
day3.setTime(day3.getTime() + 24 * 60 * 60 * 1000 * 2);
var m3 = day3.getMonth() + 1;
if (m3 <= 9) {
m3 = "0" + m3;
}
var d3 = day3.getDate();
if (d3 <= 9) {
d3 = "0" + d3;
}
var s3 = day3.getFullYear() + "-" + m3 + "-" + d3;
if (index == 0) {
return (this.queryData.date = [`${s1}`]);
} else if (index == 1) {
return (this.queryData.date = [`${s1}`, `${s2}`]);
} else if (index == 2) {
return (this.queryData.date = [`${s1}`, `${s2}`, `${s3}`]);
}
},
getFirstlist(tab, index) {
this.tabsIndex = index;
let { id, ratio, title } = tab;
this.queryData.first_class_id = id;
// this.ratio = ratio;
// this.title = title;
delete this.queryData.second_class_id;
this.queryData.page = 1;
console.log("tab", this.queryData);
this.refreshList();
// this.getIconTabs();
},
getSecondlist(tab) {
let { id, ratio, title } = tab;
this.queryData.second_class_id = id;
// this.ratio = ratio;
// this.title = title;
this.queryData.page = 1;
this.refreshList();
},
//处理当前列表
handleSelectLists(detail, id) {
if (detail.length > 0) {
this.$set(this.filterListSelectLists, id, true);
} else {
this.$set(this.filterListSelectLists, id, false);
}
console.log("当前选择的筛选列表", this.filterListSelectLists);
// this.filterListId = id;
},
resetFilter() {
this.infoDetailLists = [];
this.filterListSelectLists = [];
delete this.queryData.price;
delete this.queryData.times;
delete this.queryData.sort;
this.customizeTime = "";
this.start_price = null;
this.end_price = null;
this.refreshList();
console.log("重置筛选条件");
},
sureFilter() {
if (this.customizeTime) {
if (this.queryData.times) {
this.queryData.times = `${this.queryData.times},${this.customizeTime}`;
} else {
this.queryData.times = this.customizeTime;
}
}
if (this.start_price || this.end_price) {
this.queryData.price = `${this.start_price || 0}-${
this.end_price || ""
}`;
this.$set(this.filterListSelectLists, 2, true);
} else {
this.$set(this.filterListSelectLists, 2, false);
}
this.queryData.page = 1; // 重置页码
this.refreshList(); // 刷新列表
},
selectDetailTime(detail) {
this.handleSelectLists(detail, 1);
this.$set(this.infoDetailLists, 0, detail);
// this.infoDetailLists[0] = detail;
this.queryData.times = detail.join(",");
console.log("选择的时间段", detail);
},
selectDetailPrice(detail) {
if (detail[0]) {
let priceList = detail[0].split("-");
this.start_price = priceList[0];
this.end_price = priceList[1] || null;
} else {
this.start_price = null;
this.end_price = null;
}
this.handleSelectLists(detail, 2);
this.$set(this.infoDetailLists, 1, detail);
console.log("选择的价格区间", detail);
},
selectDetailSort(detail) {
this.handleSelectLists(detail, 3);
//
this.$set(this.infoDetailLists, 2, detail);
//赋予排序方式
this.queryData.sort = detail[0];
console.log("选择的排序方式", detail);
},
// 选择服务时间
confirmTime(time) {
console.log("选择的时间", time);
this.customizeTime = time;
this.$set(this.filterListSelectLists, 1, true);
},
},
};
</script>
<style lang="scss" scoped>
.container {
width: 750rpx;
}
.popupShow {
overflow: hidden;
position: fixed;
}
.flexed {
position: sticky;
top: 88rpx;
left: 0;
z-index: 999;
.headerBox {
display: flex;
align-items: center;
gap: 30rpx;
background-color: #fff;
padding: 24rpx 30rpx;
.search-box {
// width: 750rpx;
width: 100%;
background-color: #ffffff;
border-radius: 8rpx;
box-sizing: border-box;
position: relative;
.search-inp {
// width: 700rpx;
width: 100%;
height: 68rpx;
background-color: #f4f5f7;
border-radius: 34rpx;
padding: 0 70rpx 0 82rpx;
font-size: 28rpx;
box-sizing: border-box;
}
.placeholder {
font-weight: 400;
font-size: 28rpx;
color: #cccccc;
line-height: 34rpx;
text-align: left;
font-style: normal;
}
.search-icon {
width: 34rpx;
height: 34rpx;
position: absolute;
left: 30rpx;
top: 50%;
transform: translateY(-50%);
}
}
}
.filter {
z-index: 999;
background-color: #fff;
padding: 32rpx 50rpx 0rpx 50rpx;
margin-bottom: 32rpx;
padding-bottom: 35rpx;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
align-items: center;
position: relative;
&__left {
display: flex;
flex-wrap: nowrap;
align-items: center;
}
&__right {
display: flex;
flex-wrap: nowrap;
align-items: center;
}
.filter-icon {
width: 16rpx;
height: 10rpx;
margin-left: 8rpx;
}
.filter__text {
font-weight: 400;
font-size: 26rpx;
color: #333333;
line-height: 37rpx;
text-align: left;
font-style: normal;
}
}
.filter__left__select__bj {
z-index: 987;
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: transparent;
}
.filter__left__select {
z-index: 988;
position: absolute;
background-color: #fff;
left: 0;
right: 0;
bottom: 0;
transform: translateY(0%);
opacity: 0;
transition: all 0.3s ease;
visibility: hidden;
&__item {
margin: 30rpx 30rpx 0rpx 30rpx;
padding-bottom: 30rpx;
border-bottom: 1px solid #f5f5f5;
&__title {
font-weight: 400;
font-size: 26rpx;
color: #333333;
line-height: 37rpx;
text-align: left;
font-style: normal;
margin-left: 20rpx;
display: flex;
align-items: center;
&__icon {
width: 25rpx;
height: 20rpx;
margin-left: 10rpx;
}
}
}
.filter__left__select__item.active {
.filter__left__select__item__title {
color: #FF4767;
}
}
}
.filter__left__select.show {
opacity: 1;
visibility: visible;
transform: translateY(100%);
}
}
//价格区间样式
.price-input {
display: flex;
justify-content: space-between;
align-items: center;
width: 370rpx;
height: 80rpx;
background: #f3f6f8;
border-radius: 10rpx;
.price-input-field {
width: 166rpx;
height: 80rpx;
line-height: 50rpx;
text-align: center;
border-radius: 26rpx;
font-size: 26rpx;
font-weight: 400;
color: #3d3d3d;
}
.price-separator {
height: 3rpx;
width: 38rpx;
background-color: #dddddd;
}
}
.time-customize {
width: 180rpx;
height: 80rpx;
background: #f3f6f8;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
}
.main-tab-scroll {
position: sticky;
top: calc(var(--status-bar-height) + 88rpx);
z-index: 9999;
white-space: nowrap;
background-color: #fff;
}
.icon-tab-scroll {
position: relative;
z-index: 1999;
background-color: #fff;
}
.main-tabs {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
background: #fff;
border-bottom: 1rpx solid #f5f5f5;
// padding: 0 24rpx;
padding-left: 30rpx;
padding-top: 24rpx;
padding-bottom: 20rpx;
height: 56rpx;
gap: 40rpx;
}
.main-tab {
line-height: 56rpx;
position: relative;
}
.tab-text {
font-weight: 400;
font-size: 30rpx;
color: #333333;
line-height: 42rpx;
text-align: left;
font-style: normal;
white-space: nowrap;
}
.main-tab.active .tab-text {
font-weight: 500;
}
.main-tab.active::after {
content: "";
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 32rpx;
height: 6rpx;
background: #FF4767;
border-radius: 3rpx;
}
.icon-tabs {
display: flex;
flex-flow: row nowrap;
justify-content: flex-start;
align-items: center;
background: #fff;
padding: 30rpx 0 0 30rpx;
}
.icon-tab {
width: 110rpx;
display: flex;
flex-direction: column;
align-items: center;
margin-right: 56rpx;
margin-bottom: 30rpx;
background: #fff;
}
.icon-img {
width: 96rpx;
height: 96rpx;
border-radius: 48rpx;
margin-bottom: 12rpx;
}
.icon-text {
font-size: 24rpx;
color: #3d3d3d;
}
.icon-tab.active .icon-text {
color: #FF4767;
}
.icon-tab.active .icon-img {
border: 2rpx solid #FF4767;
}
.service-list {
margin: 32rpx 24rpx;
}
</style>