Browse Source

add api

dev
刘嘉炜 3 weeks ago
parent
commit
91790d34ec
  1. 2
      src/pages/index/index.vue
  2. 4
      src/subpackage/groupon/api/index.js
  3. 52
      src/subpackage/groupon/components/search_bar.vue
  4. 28
      src/subpackage/groupon/components/ticket_item.vue
  5. 29
      src/subpackage/groupon/pages/list.vue
  6. 152
      src/subpackage/groupon/pages/stadiums.vue
  7. 3
      src/utils/index.js

2
src/pages/index/index.vue

@ -6,8 +6,6 @@ import { routeTo } from "@/utils/polish";
import { stadiumFind } from "@/api";
onLoad(() => {
console.log('deepClone', deepClone({ a: 1, b: { c: 2 } }));
console.log('accAdd', accAdd(0.1, 0.2));
// stadiumFind({ data: { brand_id: 63 }, loading: '...' })
// .then(res=>{
// console.log('stadiumFind', res);

4
src/subpackage/groupon/api/index.js

@ -4,5 +4,9 @@ export const venueTypes = params => server.post({ url: '/stadium/venue/types', .
export const bookDate = params => server.post({ url: '/stadium/book/date', ...params }); // 可预订场馆列表
export const bookList = params => server.post({ url: '/stadium/book/list', ...params }); // 可预订场馆,矩阵图 时间+场馆
export const userCertificates = params => server.post({ url: '/douyinMiniapp/202506/postv1-api-trade-v2-fulfillment-query_user_certificates', ...params }); // 抖音团购券列表
export const countCity = params => server.post({ url: '/stadium/count/city', ...params }); // A主页-选择门店-城市列表
export const stadiumFind = params => server.post({ url: '/stadium/find', ...params }); // 门店列表

52
src/subpackage/groupon/components/search_bar.vue

@ -1,24 +1,64 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app';
import { reactive, ref } from "vue";
onLoad(() => {
import { reactive, ref, computed } from "vue";
const props = defineProps({
cityLs: {
type: Array,
default: () => []
},
city: {
type: String,
default: ''
},
iptkey: {
type: String,
default: ''
}
});
const emits = defineEmits(['update:city', 'update:iptkey', 'input:confirm']);
const cityVal = computed({
get() {
return props.city;
},
set(val) {
emits('update:city', val);
}
});
const iptVal = computed({
get() {
return props.value;
},
set(val) {
emits('update:iptkey', val);
}
});
function pickerChange(e){
const idx = e.detail.value;
cityVal.value = props.cityLs[idx]?.city ?? '';
}
function confirmBtn(e){
const val = e.detail.value;
emits('input:confirm', val);
}
</script>
<template>
<view class="search-bar">
<view class="sb-frame">
<picker class="sf-picker" mode="time">
<picker class="sf-picker" mode="selector" :range="cityLs" range-key="city" @change="pickerChange">
<view class="sf-select">
<view class="ss-val">广州市</view>
<view class="ss-val">{{ cityVal ?? '-' }}</view>
<text class="ss-icon">&#xe695;</text>
</view>
</picker>
<view class="sf-ipt">
<text class="si-icon">&#xe6b9;</text>
<input class="si-ipt" placeholder="搜索门店" />
<input class="si-ipt" placeholder="搜索门店" v-model="iptVal" @confirm="confirmBtn" />
</view>
</view>
</view>

28
src/subpackage/groupon/components/ticket_item.vue

@ -1,14 +1,36 @@
<script setup>
import { reactive, ref } from "vue";
import { reactive, ref, computed } from "vue";
const emits = defineEmits([ 'click:use' ]);
const props = defineProps({
ticketName: {
type: String,
default: ''
},
startTimeStamp: {
type: Number,
default: 0
},
endTimeStamp: {
type: Number,
default: 0
}
});
const startTime = computed(() => {
return props.startTimeStamp ? new Date(props.startTimeStamp * 1000).toLocaleDateString() : '';
});
const endTime = computed(() => {
return props.endTimeStamp ? new Date(props.endTimeStamp * 1000).toLocaleDateString() : '';
});
</script>
<template>
<view class="ticket-item">
<view class="ti-left">
<view class="tl-tit">订场100元代金券欧轩运动生活</view>
<view class="tl-time">有效时间2025.03.03至2026.03.03</view>
<view class="tl-tit">{{ ticketName ?? '' }}</view>
<view class="tl-time" v-if="endTime">有效时间{{ startTime }}{{ endTime }}</view>
</view>
<view class="ti-btn" @click="emits('click:use')">立即使用</view>
</view>

29
src/subpackage/groupon/pages/list.vue

@ -2,13 +2,28 @@
import { onLoad } from '@dcloudio/uni-app';
import { reactive, ref } from "vue";
import ticketItem from "../components/ticket_item.vue";
import { routeTo } from '@/utils/polish';
import { routeTo, showModal } from '@/utils/polish';
import { userCertificates } from "../api";
const ticketLs = ref([]);
onLoad(() => {
userCertificates({
data: {
debug: 1,
appid: tt.getEnvInfoSync()?.microapp?.appId ?? '',
data: JSON.stringify({
"account_id": "7419147144797358116",
"open_id": "-",
})
}
})
.then(res => {
console.log('票券列表--->', res);
if(res?.data?.data?.total === 0)return showModal({ content: '暂无票券' });
ticketLs.value = res.data?.data?.orders || [];
});
});
function ticketClick(){
console.log(1224)
routeTo('/subpackage/groupon/pages/stadiums');
}
@ -16,8 +31,12 @@ function ticketClick(){
<template>
<view class="groupon-list">
<view class="gl-item" v-for="i in 3" :key="i">
<ticket-item @click:use="ticketClick"></ticket-item>
<view class="gl-item" v-for="(e, i) in ticketLs" :key="i">
<ticket-item
:ticketName="e?.certificates?.[0]?.sku_info?.title ?? ''"
:startTimeStamp="e?.certificates?.[0]?.start_time ?? 0"
:endTimeStamp="e?.certificates?.[0]?.expire_time ?? 0"
@click:use="ticketClick"></ticket-item>
</view>
</view>
</template>

152
src/subpackage/groupon/pages/stadiums.vue

@ -1,37 +1,161 @@
<script setup>
import { onLoad } from '@dcloudio/uni-app';
import { reactive, ref } from "vue";
import { reactive, ref, watch } from "vue";
import searchBar from "../components/search_bar.vue";
onLoad(() => {
import { countCity, stadiumFind } from "../api";
import { routeTo, showModal } from '@/utils/polish';
import { debounce } from '@/utils';
const cityLs = ref([]);
const cityName = ref(''); //
const stadiumKey = ref(''); //
const stadiumLs = ref([]);
const appid = tt.getEnvInfoSync()?.microapp?.appId ?? '';
watch(cityName, val=>{
stadiumLs.value = [];
stadiumFind({
data: {
appid: appid,
city: val ?? '',
key: stadiumKey.value ?? '',
},
})
.then(sRes=> {
if(val !== cityName.value) return; //
let _ls = sRes?.data?.list || [];
if(!_ls?.length) return showModal({ content: '暂无门店' });
stadiumLs.value = _ls;
})
});
onLoad(opts => {
countCity({
data: { brand_id: opts?.brand_id ?? '' }
})
.then(res=>{
console.log('城市列表--->', res);
return cityLs.value = res.data?.list || [];
})
.then(cityLs => {
if(!cityLs?.length) return showModal({ content: '暂无城市' });
if(opts?.appid)appid = opts?.appid;
cityName.value = cityLs[0]?.city ?? '';
})
});
function updateStadiumLs({
appid = '',
city = '',
key = '',
}){
return stadiumFind({
data: { appid, city, key, },
})
.then(stadiumRes => {
let _ls = stadiumRes?.data?.list || [];
if(!_ls?.length) return showModal({ content: '暂无门店' });
stadiumLs.value = _ls;
})
}
function getBusinessTime(stadiumInfo){ //
let _businessTime = stadiumInfo?.business_times || [];
let _str = ''
if(_businessTime?.length){
_businessTime.forEach(el =>{
let _wStr = '', _tStr = '';
if(el?.weeks?.length){
_wStr = el.weeks.join('、') || '';
}
if(el?.stimes?.length){
el.stimes.forEach((sRes, sIdx) =>{
_tStr += `${sRes.start || ''}-${sRes.end || ''}`;
_tStr += sIdx === el.stimes.length -1 ? ';' : ','
})
}
_str += `${_wStr || ''} ${_tStr || ''}`;
})
}
return _str || '-';
}
function phoneCall(phone) {
if(!phone) return showModal({ content: '暂无联系电话' });
uni.makePhoneCall({ phoneNumber: phone,
success: () => {
console.log('拨打电话成功');
},
fail: (err) => {
showModal({ content: err?.errMsg || '拨打电话失败' });
console.error('拨打电话失败', err);
}
});
}
function openMap(res){
uni.openLocation({
latitude: +(res?.lat || 0),
longitude: +(res?.lng || 0),
name: res?.name || '',
address: res?.address || '',
success: () => {
console.log('打开地图成功');
},
fail: (err) => {
showModal({ content: err?.errMsg || '打开地图失败' });
console.error('打开地图失败', err);
}
});
}
function searchKeyConfrim(val){
stadiumLs.value = [];
stadiumFind({
data: {
appid: appid,
city: cityName.value,
key: val,
},
})
.then(stadiumRes => {
let _ls = stadiumRes?.data?.list || [];
stadiumLs.value = _ls;
})
}
</script>
<template>
<view class="stadium-select">
<search-bar></search-bar>
<view class="ss-search">
<search-bar
:cityLs="cityLs"
v-model:city="cityName"
v-model:iptkey="stadiumKey"
@input:confirm="searchKeyConfrim"
></search-bar>
</view>
<view class="stadium-ls">
<view class="sl-item" v-for="i in 3" :key="i">
<view class="sl-item" v-for="(e, i) in stadiumLs" :key="i">
<view class="si-info">
<view class="si-top">
<view class="st-logo"></view>
<view class="st-name">MJ体育(天空篮球从云店)</view>
<image class="st-logo" mode="aspectFit" :src="e.logo"></image>
<view class="st-name">{{ e?.name || '-' }}</view>
</view>
<view class="si-line">
<view class="sl-icon">&#xe60f;</view>
<view class="sl-txt">周一周日09:05-12:0014:30-24周二周四周五...</view>
<view class="sl-txt">{{ getBusinessTime(e) }}</view>
</view>
<view class="si-line">
<view class="sl-icon">&#xe600;</view>
<view class="sl-txt">白云区从云路822号城市像素6楼电梯5楼走到6楼</view>
<view class="sl-txt">{{ e.address || '-' }}</view>
</view>
</view>
<view class="si-right">
<view class="sr-txt">去核销</view>
<view class="sr-icons">
<view class="si-item">&#xe605;</view>
<view class="si-item">&#xe672;</view>
<view class="si-item" @click="phoneCall(e.contact_mobile)">&#xe605;</view>
<view class="si-item" @click="openMap(e)">&#xe672;</view>
</view>
</view>
</view>
@ -41,6 +165,11 @@ onLoad(() => {
<style lang="scss" scoped>
.stadium-select{
.ss-search{
position: sticky;
left: 0;
top: 0;
}
.stadium-ls{
padding: 24upx;
@include isPd(24upx);
@ -64,7 +193,6 @@ onLoad(() => {
margin-right: 20upx;
width: 36upx;
height: 36upx;
background: skyblue;
}
.st-name{
flex-grow: 1;

3
src/utils/index.js

@ -58,8 +58,9 @@ export function debounce(func, wait, immediate) {
}
}
}
return function(...args) {
return function(...params) {
context = this;
args = params;
timestamp = +new Date();
const callNow = immediate && !timeout;
// 如果延时不存在,重新设定延时

Loading…
Cancel
Save