feat: 我的预约,专家预约界面编写以及接口对接
parent
0816b72919
commit
23f18c9dd3
|
|
@ -2,14 +2,6 @@
|
|||
|
||||
六维志愿小程序
|
||||
|
||||
## 平台兼容性
|
||||
|
||||
| H5 | IOS | 安卓 | 微信小程序 | 字节小程序 | 快手小程序 | 支付宝小程序 | 钉钉小程序 | 百度小程序 |
|
||||
| --- | --- | ---- | ---------- | ---------- | ---------- | ------------ | ---------- | ---------- |
|
||||
| √ | √ | √ | √ | √ | √ | √ | √ | √ |
|
||||
|
||||
注意每种 `UI框架` 支持的平台有所不同,详情请看各 `UI框架` 的官网,也可以看 `unibest` 文档。
|
||||
|
||||
## ⚙️ 环境
|
||||
|
||||
- node>=18
|
||||
|
|
|
|||
|
|
@ -330,55 +330,102 @@ const getPosition = (index: number, list = cloneList.value): [number, number] =>
|
|||
}
|
||||
|
||||
// 初始化
|
||||
const initList = (list: ItemType[] = [], changeheight: boolean = false) => {
|
||||
const newList = deepCopy(list)
|
||||
showList.value = newList.map((item, index) => {
|
||||
const [x, y] = getPosition(index)
|
||||
let data = {
|
||||
...item,
|
||||
x,
|
||||
y,
|
||||
dropId: index + 1,
|
||||
}
|
||||
let key = 'slot' + Math.random() + index
|
||||
// 如果x轴和y轴没变,那么不用更新key来刷新状态
|
||||
if (x === item?.x && y === item?.y) {
|
||||
if (activeIndex.value !== index) {
|
||||
// 非当前点击的下标和目标下标的下标不需要生成新的key
|
||||
key = item.key
|
||||
const initList = (list: ItemType[] = [], changeheight: boolean = false): Promise<void> => {
|
||||
return new Promise((resolve) => {
|
||||
const newList = deepCopy(list)
|
||||
// 给每个item添加一x,y和key
|
||||
showList.value = newList.map((item, index) => {
|
||||
const [x, y] = getPosition(index)
|
||||
let data = {
|
||||
...item,
|
||||
x,
|
||||
y,
|
||||
dropId: index + 1,
|
||||
}
|
||||
}
|
||||
data.key = key
|
||||
return data
|
||||
})
|
||||
cloneList.value = deepCopy(showList.value)
|
||||
nextTick(() => {
|
||||
showArea.value = true
|
||||
})
|
||||
if (changeheight && props.itemHeight === 'auto') {
|
||||
const query = uni.createSelectorQuery().in(instance.proxy)
|
||||
query
|
||||
.selectAll('.slotContent')
|
||||
.boundingClientRect((data) => {
|
||||
let domList = JSON.parse(JSON.stringify(data))
|
||||
let max = 0
|
||||
let _viewMaxHeight = 0
|
||||
for (let i = 0; i < domList.length; i++) {
|
||||
let height = domList[i].height
|
||||
if (isList.value) {
|
||||
cloneList.value[i].height = height
|
||||
}
|
||||
_viewMaxHeight += height
|
||||
if (height > max) {
|
||||
max = height
|
||||
}
|
||||
let key = 'slot' + Math.random() + index
|
||||
// 如果x轴和y轴没变,那么不用更新key来刷新状态
|
||||
if (x === item?.x && y === item?.y) {
|
||||
if (activeIndex.value !== index) {
|
||||
// 非当前点击的下标和目标下标的下标不需要生成新的key
|
||||
key = item.key
|
||||
}
|
||||
viewMaxHeight.value = _viewMaxHeight // 内容区域总高度
|
||||
itemMaxHeight.value = max + 'px'
|
||||
initList(cloneList.value)
|
||||
})
|
||||
.exec()
|
||||
}
|
||||
}
|
||||
// 判断拖动位置的元素是那个
|
||||
data.key = key
|
||||
return data
|
||||
})
|
||||
cloneList.value = deepCopy(showList.value)
|
||||
nextTick(() => {
|
||||
showArea.value = true
|
||||
})
|
||||
|
||||
if (changeheight && props.itemHeight === 'auto') {
|
||||
// 获取到最高的item
|
||||
setTimeout(async () => {
|
||||
// #ifdef APP-NVUE
|
||||
showArea.value = false
|
||||
|
||||
const calculateHeights = async () => {
|
||||
let max = 0
|
||||
let viewMaxHeightVal = 0
|
||||
|
||||
const promises = slotContent.value.map((content, index) => {
|
||||
return new Promise<void>((resolve) => {
|
||||
dom.getComponentRect(content, (res: any) => {
|
||||
let size = res.size
|
||||
if (isList.value) {
|
||||
cloneList.value[index].height = size.height
|
||||
}
|
||||
viewMaxHeightVal += size.height
|
||||
if (size.height > max) {
|
||||
max = size.height
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await Promise.all(promises)
|
||||
viewMaxHeight.value = viewMaxHeightVal
|
||||
itemMaxHeight.value = max + 'px'
|
||||
nextTick(() => {
|
||||
initList(cloneList.value).then(resolve)
|
||||
})
|
||||
}
|
||||
|
||||
await calculateHeights()
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
const query = uni.createSelectorQuery().in(instance.proxy)
|
||||
query
|
||||
.selectAll('.slotContent')
|
||||
.boundingClientRect((data) => {
|
||||
let domList = JSON.parse(JSON.stringify(data))
|
||||
let max = 0
|
||||
let viewMaxHeightVal = 0
|
||||
|
||||
for (let i = 0; i < domList.length; i++) {
|
||||
let height = domList[i].height
|
||||
if (isList.value) {
|
||||
cloneList.value[i].height = height
|
||||
}
|
||||
viewMaxHeightVal += height
|
||||
if (height > max) {
|
||||
max = height
|
||||
}
|
||||
}
|
||||
viewMaxHeight.value = viewMaxHeightVal // 内容区域总高度
|
||||
itemMaxHeight.value = max + 'px'
|
||||
initList(cloneList.value).then(resolve)
|
||||
})
|
||||
.exec()
|
||||
// #endif
|
||||
}, 0)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 方法
|
||||
|
|
|
|||
|
|
@ -100,21 +100,23 @@ const handleMove = (index) => {
|
|||
myDrop.value.handleLongpress(index)
|
||||
}
|
||||
|
||||
const handleDelete = (index) => {
|
||||
const handleDelete = async (index) => {
|
||||
// 如果新增或者删除了数据,请调用此函数
|
||||
wishList.value.splice(index, 1)
|
||||
myDrop.value.initList(wishList.value)
|
||||
await myDrop.value.initList(wishList.value)
|
||||
}
|
||||
|
||||
const handleUpdateHeight = () => {
|
||||
const handleUpdateHeight = async () => {
|
||||
// 调用 DragSort 组件的重新计算高度方法
|
||||
myDrop.value?.initList(wishList.value, true)
|
||||
await myDrop.value?.initList(wishList.value, true)
|
||||
}
|
||||
|
||||
const handleDeleteMajor = async (index, majorIndex) => {
|
||||
wishList.value[index].vItems.splice(majorIndex, 1)
|
||||
userStore.sortWishMajorList({ list: wishList.value[index].vItems, uIndex: index })
|
||||
myDrop.value?.initList(wishList.value, true)
|
||||
myDrop.value?.initList(wishList.value, true).then(() => {
|
||||
myDrop.value?.initList(wishList.value, true)
|
||||
})
|
||||
}
|
||||
|
||||
const handleSave = () => {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -7,12 +7,12 @@
|
|||
</route>
|
||||
|
||||
<template>
|
||||
<scroll-view scroll-y class="pb-safe bg-[#f8f8f8]">
|
||||
<view class="item-wrapper" v-for="(item, index) in wishList" :key="index">
|
||||
<scroll-view scroll-y class="pb-safe bg-[#f8f8f8] h-screen">
|
||||
<view class="item-wrapper" v-for="(item, index) in list" :key="index">
|
||||
<view class="flex gap-[24rpx] wish-border justify-between p-[32rpx] rounded-[8rpx]">
|
||||
<view class="flex flex-col gap-[14rpx]">
|
||||
<text class="text-[#303030] text-[32rpx] font-semibold">
|
||||
{{ item.tableName }}
|
||||
{{ item.title }}
|
||||
</text>
|
||||
<text class="text-[22rpx] text-[#303030]">{{ item.createTime || '时间消失了' }}</text>
|
||||
</view>
|
||||
|
|
@ -25,17 +25,17 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { deleteWishList, getWishList } from '@/service/index/api'
|
||||
import { deleteWishList, getMyBusReports } from '@/service/index/api'
|
||||
import { useUserStore } from '@/store'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const wishList = ref([])
|
||||
const list = ref([])
|
||||
|
||||
onLoad(() => {
|
||||
getWishList().then((res) => {
|
||||
getMyBusReports({ CustomId: userStore.userInfo?.estimatedAchievement.wxId }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
wishList.value = res.result as any[]
|
||||
list.value = (res.result as { customReports: any[] }).customReports
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -43,7 +43,7 @@ onLoad(() => {
|
|||
const handleDelete = (item, index) => {
|
||||
deleteWishList({ id: item.vId }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
wishList.value.splice(index, 1)
|
||||
list.value.splice(index, 1)
|
||||
uni.showToast({ title: '删除成功' })
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
"path": "pages/expert/index/index",
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "测评师"
|
||||
"navigationBarTitleText": "专家"
|
||||
},
|
||||
"needLogin": true
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,18 +1,138 @@
|
|||
<route lang="json5" type="page">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '测评师',
|
||||
navigationBarTitleText: '专家',
|
||||
},
|
||||
needLogin: true,
|
||||
}
|
||||
</route>
|
||||
<template>
|
||||
<view class="">
|
||||
<text>庄家</text>
|
||||
<view class="h-screen flex flex-col bg-[#F9F9F9]">
|
||||
<view class="flex-1 m-[32rpx] rounded-t-[32rpx] gap-[30rpx] flex flex-col">
|
||||
<view
|
||||
class="flex items-start gap-[24rpx] pl-[24rpx] pr-[38rpx] pt-[24rpx] pb-[12rpx] bg-[#fff]"
|
||||
v-for="(item, index) in list"
|
||||
:key="item.id"
|
||||
>
|
||||
<view class="flex flex-col gap-[24rpx]">
|
||||
<image :src="item.pic" mode="aspectFit" class="w-[112rpx] h-[112rpx] rounded-full" />
|
||||
<button
|
||||
:class="`appointment-btn ${item.isAppointment ? 'bg-[#1580ff]!' : ''}`"
|
||||
@click="handleAppointment(item, index)"
|
||||
>
|
||||
<text v-if="!item.isAppointment">预约</text>
|
||||
<view class="i-carbon-checkmark text-[#fff] font-semibold" v-else></view>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="flex flex-col">
|
||||
<text class="text-[36rpx] font-semibold text-[#333]">{{ item.name }}</text>
|
||||
|
||||
<view class="flex gap-[8rpx] mt-[14rpx]">
|
||||
<view
|
||||
v-for="(major, majorIndex) in item.majorTags.slice(0, 3)"
|
||||
:key="majorIndex"
|
||||
class="bg-[#f8f8f8] rounded-[4rpx] px-[16rpx] py-[4rpx] text-[#999] text-[20rpx]"
|
||||
>
|
||||
{{ major }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="text-[22rpx] text-[#999] mt-[16rpx]">{{ item.summary }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<TabBar :current-page="1"></TabBar>
|
||||
<FabButton :initial-x="0" :initial-y="100" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import TabBar from '@/components/bar/TabBar.vue'
|
||||
import FabButton from '@/components/fab/FabButton.vue'
|
||||
import {
|
||||
addSpecial,
|
||||
deleteMyAppointment,
|
||||
getBusSpecialListGroup,
|
||||
getMySpecialList,
|
||||
} from '@/service/index/api'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
const list = ref<any[]>([])
|
||||
const userStore = useUserStore()
|
||||
const show = ref(true)
|
||||
|
||||
onLoad(() => {
|
||||
getMySpecialList({
|
||||
openId: userStore.userInfo?.estimatedAchievement.wxId.toString(),
|
||||
}).then((_res) => {
|
||||
if (_res.code === 200) {
|
||||
let _mySpecialList = _res.result as any[]
|
||||
getBusSpecialListGroup().then((res) => {
|
||||
if (res.code === 200) {
|
||||
list.value = res.result as any[]
|
||||
list.value = list.value.map((item) => {
|
||||
let _mySpecial = _mySpecialList.find((_item) => _item.sId === item.id)
|
||||
return {
|
||||
...item,
|
||||
isAppointment: !!_mySpecial,
|
||||
appointId: _mySpecial?.id,
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const handleAppointment = (
|
||||
item: { id: number; isAppointment: boolean; appointId: number },
|
||||
index: number,
|
||||
) => {
|
||||
if (item.isAppointment) {
|
||||
deleteMyAppointment({ id: item.appointId }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
list.value[index].isAppointment = !item.isAppointment
|
||||
}
|
||||
})
|
||||
} else {
|
||||
addSpecial({
|
||||
sId: item.id,
|
||||
openId: userStore.userInfo?.estimatedAchievement.wxId.toString(),
|
||||
appointmentTime: '2025-07-31',
|
||||
isDelete: item.isAppointment,
|
||||
}).then((res) => {
|
||||
if (res.code === 200) {
|
||||
list.value[index].isAppointment = !item.isAppointment
|
||||
uni.showToast({
|
||||
title: item.isAppointment ? '预约成功' : '取消预约成功',
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.message,
|
||||
icon: 'none',
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.appointment-btn {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
border-radius: 70rpx;
|
||||
border: 2rpx solid #1580ff;
|
||||
line-height: 1;
|
||||
font-size: 24rpx;
|
||||
color: #1580ff;
|
||||
width: 96rpx;
|
||||
height: 44rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -384,3 +384,28 @@ export const saveBusScaleAnswer = (params: {
|
|||
}) => {
|
||||
return http.post('/api/busScale/CustomBusScale/v2', params)
|
||||
}
|
||||
|
||||
export const getBusSpecialListGroup = (params?: { Code: number }) => {
|
||||
return http.get('/api/busSpecialistGroup/list', params)
|
||||
}
|
||||
|
||||
export const addSpecial = (params: {
|
||||
openId: string
|
||||
sId: number
|
||||
appointmentTime: string
|
||||
isDelete?: boolean
|
||||
}) => {
|
||||
return http.post('/api/specialistReservation/add', params)
|
||||
}
|
||||
|
||||
export const getMySpecialList = (params: { openId: string }) => {
|
||||
return http.get('/api/specialistReservation/reservation', params)
|
||||
}
|
||||
|
||||
export const getMyBusReports = (params: { CustomId: number }) => {
|
||||
return http.get('/api/busScale/GetBusCustomReports', params)
|
||||
}
|
||||
|
||||
export const deleteMyAppointment = (params: { id: number }) => {
|
||||
return http.post('/api/specialistReservation/delete', params)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue