master
lion 1 week ago
parent 75edcbf7f1
commit 604b262c3b

@ -1,12 +1,26 @@
<script>
import { API } from './config/index.js'
import { urlUtils } from './common/util.js'
// #ifdef H5
import wx from 'jweixin-module'
// #endif
export default {
onLaunch: function() {
console.log('App Launch')
//
// #ifdef H5
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
console.log('[App] H5 onLaunch, isWeixinBrowser =', isWeixinBrowser, ', typeof wx =', typeof wx)
// wx window
if (typeof window !== 'undefined' && typeof wx !== 'undefined') {
window.wx = wx
console.log('[App] 已将 wx 挂载到 window.wx')
} else {
console.warn('[App] 未找到 wx 对象jweixin-module 可能未正确加载')
}
//
if (process.env.NODE_ENV === 'development') {
console.log('开发环境,使用模拟登录')
@ -15,8 +29,8 @@
this.wxH5AuthLogin()
}
//
this.setupGlobalWechatShare()
// JS-SDK
this.configWechatJSSDK()
// #endif
// #ifdef MP-WEIXIN
@ -204,12 +218,99 @@
})
},
// JS-SDK
configWechatJSSDK() {
// #ifdef H5
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
console.log('[App] configWechatJSSDK 调用isWeixinBrowser =', isWeixinBrowser, ', typeof wx =', typeof wx, ', has window.wx =', typeof window !== 'undefined' && !!window.wx)
if (!isWeixinBrowser || typeof window === 'undefined' || typeof wx === 'undefined') {
console.log('[App] 非微信环境或微信JS-SDK未加载跳过配置')
return
}
// URL hash
const rawUrl = window.location.href.split('#')[0]
// encodeURIComponent
const encodedUrl = encodeURIComponent(rawUrl)
console.log('[App] 当前用于签名的 URL =', rawUrl, ',编码后 =', encodedUrl)
// wx-config JSSDK appId/timestamp/nonceStr/signature
uni.request({
url: `${API.WECHAT_JSSDK_CONFIG}?url=${encodedUrl}`,
method: 'GET',
success: (res) => {
console.log('[App] WECHAT_JSSDK_CONFIG 响应:', res.data)
if (!res.data) {
console.warn('[App] WECHAT_JSSDK_CONFIG 返回为空')
return
}
if (res.data.errcode !== 0 || !res.data.data) {
console.warn('[App] 获取微信 JSSDK 配置失败errcode =', res.data.errcode, 'errmsg =', res.data.errmsg)
return
}
//
const cfg = res.data.data
this.initWechatJSSDK(cfg)
},
fail: (err) => {
console.error('[App] 调用 WECHAT_JSSDK_CONFIG 接口失败:', err)
}
})
// #endif
},
// JS-SDK
initWechatJSSDK(config) {
// #ifdef H5
if (typeof wx === 'undefined') {
console.error('微信 JS-SDK 未加载')
return
}
wx.config({
debug: false, // false
appId: config.appId,
timestamp: config.timestamp,
nonceStr: config.nonceStr,
signature: config.signature,
jsApiList: [
'getLocation', //
'onMenuShareTimeline', //
'onMenuShareAppMessage', //
'onMenuShareQQ', // QQ
'onMenuShareWeibo' //
]
})
wx.ready(() => {
console.log('微信 JS-SDK 配置成功')
//
this.setupGlobalWechatShare()
})
wx.error((res) => {
console.error('微信 JS-SDK 配置失败:', res)
uni.showToast({
title: '微信功能配置失败',
icon: 'none'
})
})
// #endif
},
//
setupGlobalWechatShare() {
// #ifdef H5
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
if (!isWeixinBrowser || typeof window === 'undefined' || !window.wx) {
console.log('非微信环境或微信JS-SDK未加载跳过分享配置')
if (!isWeixinBrowser || typeof window === 'undefined') {
console.log('非微信环境,跳过分享配置')
return
}
// 使 window.wx 使 wx
const wxObj = window.wx || wx
if (!wxObj) {
console.log('微信JS-SDK未加载跳过分享配置')
return
}
@ -240,11 +341,12 @@
safeShareUrl = shareConfig.link
}
window.wx.ready(() => {
// 使 ready
const setupShare = () => {
console.log('微信JS-SDK准备就绪配置全局分享')
//
window.wx.onMenuShareTimeline({
wxObj.onMenuShareTimeline({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
@ -259,7 +361,7 @@
})
//
window.wx.onMenuShareAppMessage({
wxObj.onMenuShareAppMessage({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
@ -276,7 +378,7 @@
})
// QQ
window.wx.onMenuShareQQ({
wxObj.onMenuShareQQ({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
@ -291,7 +393,7 @@
})
//
window.wx.onMenuShareWeibo({
wxObj.onMenuShareWeibo({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
@ -306,11 +408,21 @@
})
console.log('全局微信分享配置完成')
})
}
// wx ready ready
if (wxObj.ready) {
wxObj.ready(setupShare)
} else {
// wx ready
setupShare()
}
window.wx.error((res) => {
if (wxObj.error) {
wxObj.error((res) => {
console.error('微信JS-SDK配置失败:', res)
})
}
// #endif
}
}

@ -6,6 +6,7 @@ const IS_PROD = process.env.NODE_ENV === 'production';
// API接口地址
export const API = {
WECHAT_JSSDK_CONFIG: `${BASE_URL}/api/customer/wechat/jssdk-config`,
LOGIN: `${BASE_URL}/api/customer/login-by-code`,
WX_LOGIN: `${BASE_URL}/api/customer/login-by-wechat-code`,
STATISTICS: `${BASE_URL}/api/customer/reservation/statistics`,
@ -32,4 +33,7 @@ export const API = {
GET_DIRECTION_ENUM: `${BASE_URL}/api/customer/reservation/get-direction-enum`,
SHIP_UPDATE: `${BASE_URL}/api/customer/ship/update`,
GET_INVOICE: `${BASE_URL}/api/customer/reservation/get-invoice`,
GET_DAILY_RESERVATION_DEADLINE: `${BASE_URL}/api/customer/setting/get-daily-reservation-deadline`,
GET_GEOFENCE_BY_DIRECTION: `${BASE_URL}/api/customer/geofence/get-by-direction`,
}

6
node_modules/.package-lock.json generated vendored

@ -4,6 +4,12 @@
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/jweixin-module": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz",
"integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w==",
"license": "ISC"
},
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",

7
package-lock.json generated

@ -9,10 +9,17 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"jweixin-module": "^1.6.0",
"moment": "^2.30.1",
"psd.js": "^3.9.1"
}
},
"node_modules/jweixin-module": {
"version": "1.6.0",
"resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz",
"integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w==",
"license": "ISC"
},
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",

@ -17,6 +17,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"jweixin-module": "^1.6.0",
"moment": "^2.30.1",
"psd.js": "^3.9.1"
}

@ -245,6 +245,7 @@ export default {
canvasHeight: 0,
hasDrawn: false,
hasSigned: false,
originalSignature: '', //
isEdit: false,
shipTypeEnum: {}, //
tonnageClassEnum: {}, //
@ -279,11 +280,17 @@ export default {
return;
}
if (options && options.edit === '1' && options.ship) {
// id
if (options && options.edit === '1') {
this.isEdit = true;
if (options.id) {
// id
this.fetchShipDetailForEdit(options.id);
} else if (options.ship) {
// URL ship
try {
const ship = JSON.parse(decodeURIComponent(options.ship));
console.log("填充数据:",ship.fee_type)
this.isEdit = true;
console.log('填充数据(兼容旧参数 ship):', ship.fee_type);
//
this.form.id = ship.id || '';
this.form.owner = ship.owner_name || '';
@ -307,8 +314,10 @@ export default {
this.originalPage1Img = this.page1Img;
this.originalPage2Img = this.page2Img;
this.originalPage3Img = this.page3Img;
//
} catch (e) {}
} catch (e) {
console.error('解析 ship 参数失败:', e);
}
}
}
});
@ -317,6 +326,82 @@ export default {
// #endif
},
methods: {
// id
async fetchShipDetailForEdit(id) {
const token = uni.getStorageSync('token');
if (!token) {
uni.showToast({ title: '请先登录', icon: 'none' });
return;
}
if (!id) {
uni.showToast({ title: '无效的船舶ID', icon: 'none' });
return;
}
uni.showLoading({ title: '加载中...' });
try {
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.SHIP_DETAIL}/${id}`,
method: 'GET',
data: { token },
success: resolve,
fail: reject
});
});
uni.hideLoading();
if (res.data && res.data.errcode === 0 && res.data.data) {
const ship = res.data.data;
console.log('编辑模式-详情数据:', ship);
this.isEdit = true;
//
this.form.id = ship.id || id;
this.form.owner = ship.owner_name || '';
this.form.idCard = ship.id_card || '';
this.form.phone = ship.phone || '';
this.form.shipNo = ship.ship_number || '';
this.form.ton = ship.total_tonnage || '';
this.form.length = ship.total_length || '';
this.form.width = ship.total_width || '';
this.form.depth = ship.molded_depth || '';
this.form.tonLevel = ship.tonnage_class || '';
this.form.shipType = (ship.ship_type || '').toString();
this.form.feeType = ship.fee_type || 1; //
// 簿 fileId
this.form.page1FileId = ship.picture1 || '';
this.form.page2FileId = ship.picture2 || '';
this.form.page3FileId = ship.picture3 || '';
// 使 picture*_file.url退
const p1Url = ship.picture1_file && ship.picture1_file.url ? ship.picture1_file.url : this.getFileUrl(ship.picture1);
const p2Url = ship.picture2_file && ship.picture2_file.url ? ship.picture2_file.url : this.getFileUrl(ship.picture2);
const p3Url = ship.picture3_file && ship.picture3_file.url ? ship.picture3_file.url : this.getFileUrl(ship.picture3);
this.page1Img = p1Url;
this.page2Img = p2Url;
this.page3Img = p3Url;
this.originalPage1Img = p1Url;
this.originalPage2Img = p2Url;
this.originalPage3Img = p3Url;
// signature
//
if (ship.signature) {
this.signImg = ship.signature;
this.originalSignature = ship.signature;
this.hasSigned = true;
}
} else {
uni.showToast({ title: (res.data && res.data.errmsg) || '获取船舶详情失败', icon: 'none' });
}
} catch (error) {
uni.hideLoading();
console.error('获取船舶详情异常:', error);
uni.showToast({ title: error.message || '网络错误', icon: 'none' });
}
},
async fetchShipPropertyEnum() {
const token = uni.getStorageSync('token');
if (!token) {
@ -520,7 +605,16 @@ export default {
try {
uni.showLoading({ title: '处理中...' });
const signBase64 = await this.getSignBase64();
//
// - hasDrawn false使 signature
// - base64
let signValue = '';
if (this.isEdit && this.originalSignature && !this.hasDrawn) {
signValue = this.originalSignature;
} else {
signValue = await this.getSignBase64();
}
const token = uni.getStorageSync('token');
if (!token) {
uni.hideLoading();
@ -545,7 +639,7 @@ export default {
picture1: this.form.page1FileId,
picture2: this.form.page2FileId,
picture3: this.form.page3FileId,
signature: signBase64
signature: signValue
};
//
@ -579,8 +673,24 @@ export default {
uni.navigateBack();
}, 800);
} else {
console.log(res.data)
uni.showToast({ title: res.data.data || '提交失败', icon: 'none' });
console.log('提交失败返回:', res.data);
const resp = res.data || {};
const detail = resp.data || {};
let msg = '';
//
// { signature: [''] }
if (detail && typeof detail === 'object') {
if (Array.isArray(detail.signature) && detail.signature.length) {
msg = `签名:${detail.signature.join('')}`;
}
}
if (!msg) {
msg = resp.errmsg || '提交失败';
}
uni.showToast({ title: msg, icon: 'none' });
}
} catch (error) {
uni.hideLoading();
@ -1094,7 +1204,7 @@ export default {
}
.sign-img {
width: 100%;
height: 100%;
height: 460rpx;
object-fit: contain;
border-radius: 16rpx;
}

@ -24,15 +24,15 @@
<view class="section-title">船检簿</view>
<view class="section-row">
<text>第一页</text>
<image :src="getFileUrl(ship.picture1)" style="width:80px;height:80px;" mode="aspectFill" />
<image :src="ship.picture1_file ? ship.picture1_file.url : ''" style="width:80px;height:80px;" mode="aspectFill" />
</view>
<view class="section-row">
<text>第二页</text>
<image :src="getFileUrl(ship.picture2)" style="width:80px;height:80px;" mode="aspectFill" />
<image :src="ship.picture2_file ? ship.picture2_file.url : ''" style="width:80px;height:80px;" mode="aspectFill" />
</view>
<view class="section-row">
<text>第三页</text>
<image :src="getFileUrl(ship.picture3)" style="width:80px;height:80px;" mode="aspectFill" />
<image :src="ship.picture3_file ? ship.picture3_file.url : ''" style="width:80px;height:80px;" mode="aspectFill" />
</view>
</view>
<view v-if="ship" class="ship-section">
@ -43,7 +43,7 @@
</view>
<view class="section-row">
<text>签名图片</text>
<image :src="'data:image/png;base64,' + ship.signature" style="width:120px;height:60px;" mode="aspectFit" />
<image :src="ship.signature" style="width:120px;height:60px;" mode="aspectFit" />
</view>
</view>
</view>
@ -65,7 +65,10 @@ export default {
ship: null,
id: null,
shipTypeEnum: [],
isWeixinBrowser: false
isWeixinBrowser: false,
picture1_file: {},
picture2_file: {},
picture3_file: {},
}
},
onLoad(options) {
@ -161,10 +164,10 @@ export default {
return `${API.BASE_URL}/api/customer/upload-file/preview?id=${fileId}`;
},
onEdit() {
if (!this.ship) return;
const shipStr = encodeURIComponent(JSON.stringify(this.ship));
if (!this.ship || !this.ship.id) return;
// id
uni.navigateTo({
url: `/pages/index/ship_add?edit=1&ship=${shipStr}`
url: `/pages/index/ship_add?edit=1&id=${this.ship.id}`
});
},
onDelete() {

@ -116,9 +116,13 @@ export default {
return '';
},
goEdit(item) {
const itemStr = encodeURIComponent(JSON.stringify(item));
if (!item || !item.id) {
uni.showToast({ title: '无效的船舶信息', icon: 'none' });
return;
}
// id ship_add
uni.navigateTo({
url: `/pages/index/ship_add?edit=1&ship=${itemStr}`
url: `/pages/index/ship_add?edit=1&id=${item.id}`
});
},
onDelete(item) {

@ -60,11 +60,13 @@
<button
class="direction-btn"
:class="{ active: gateDate === 'today' }"
:disabled="isDateDisabled"
@click="setGateDate('today')"
>今天</button>
<button
class="direction-btn"
:class="{ active: gateDate === 'tomorrow' }"
:class="{ active: gateDate === 'tomorrow', 'tomorrow-default': gateDate === 'tomorrow' && isDateDisabled }"
:disabled="isDateDisabled"
@click="setGateDate('tomorrow')"
>明天</button>
</view>
@ -89,6 +91,9 @@
<script>
import NavBar from '@/components/NavBar.vue'
import { API } from '@/config/index.js'
// #ifdef H5
import wx from 'jweixin-module'
// #endif
export default {
name: 'ReservationPage',
components: { NavBar },
@ -109,6 +114,10 @@ export default {
shipTypeEnum: [],
agreeNotice: false,
gateDate: 'today', // ""
deadlineTime: '', // "18:00"
isDateDisabled: false, //
userLocation: null, // {latitude, longitude}
isInGeofence: null, // nulltruefalse
}
},
onLoad() {
@ -122,10 +131,365 @@ export default {
this.fetchShipList();
});
});
//
uni.showModal({
title: '提示',
content: '预约前需要先获取您的位置信息',
showCancel: true,
confirmText: '确定',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
this.getUserLocation();
} else {
//
uni.showToast({
title: '未获取位置信息,可能无法完成预约',
icon: 'none'
});
}
}
});
this.fetchDailyReservationDeadline();
},
methods: {
//
getUserLocation() {
// #ifdef H5
if (this.isWeixinBrowser) {
// H5
console.log('微信 H5 环境');
this.getWeixinLocation();
} else {
// H5
console.log('普通 H5 环境');
this.getBrowserLocation();
}
// #endif
// #ifdef MP-WEIXIN
//
console.log('微信小程序环境');
this.getMiniProgramLocation();
// #endif
},
// H5
getWeixinLocation() {
// #ifdef H5
console.log('[WeixinLocation] 调用 getWeixinLocation');
const inWeixin = /MicroMessenger/i.test(navigator.userAgent);
console.log('[WeixinLocation] 是否微信环境 isWeixinBrowser =', this.isWeixinBrowser, 'UA检测 =', inWeixin ? '是' : '否');
// 使 window.wx App.vue 使 wx
const hasWindowWx = (typeof window !== 'undefined' && !!window.wx);
const hasModuleWx = (typeof wx !== 'undefined');
console.log('[WeixinLocation] has window.wx =', hasWindowWx, ', has module wx =', hasModuleWx);
const wxObj = hasWindowWx ? window.wx : (hasModuleWx ? wx : null);
console.log('[WeixinLocation] wxObj =', wxObj);
if (!wxObj) {
console.error('微信 JS-SDK 未加载');
uni.showModal({
title: '提示',
content: '微信 JS-SDK 未加载,请刷新页面重试',
showCancel: false
});
return;
}
console.log('[WeixinLocation] wxObj.version =', wxObj.version, 'typeof wxObj.config =', typeof wxObj.config, 'typeof wxObj.ready =', typeof wxObj.ready, 'typeof wxObj.getLocation =', typeof wxObj.getLocation);
if (typeof wxObj.config !== 'function') {
console.warn('[WeixinLocation] wx.config 未定义说明微信JS-SDK可能还没有正确初始化wx.ready 可能不会触发,请确认后端是否已下发 JSSDK 配置并在 App.vue 中调用 initWechatJSSDK');
}
if (typeof wxObj.getLocation !== 'function') {
console.warn('[WeixinLocation] wx.getLocation 不是函数,说明当前 JSSDK 可能未加载完整或未包含该接口');
}
if (typeof wxObj.error === 'function') {
wxObj.error((err) => {
console.error('[WeixinLocation] wx.error 回调触发JSSDK 配置或调用出错:', err);
});
} else {
console.warn('[WeixinLocation] wx.error 不存在,无法捕获 JSSDK 配置错误');
}
// 5 ready
let readyCalled = false;
setTimeout(() => {
if (!readyCalled) {
console.warn('[WeixinLocation] 5 秒内 wx.ready 未回调,可能是 wx.config 未正确执行或签名错误');
}
}, 5000);
// 使 JS-SDK
wxObj.ready(() => {
readyCalled = true;
console.log('[WeixinLocation] wx.ready 回调触发,开始调用 wx.getLocation');
wxObj.getLocation({
type: 'gcj02', // uni.openLocation
success: (res) => {
console.log('[WeixinLocation] wx.getLocation success 原始返回值:', res);
this.userLocation = {
latitude: res.latitude,
longitude: res.longitude,
speed: res.speed,
accuracy: res.accuracy
};
console.log('[WeixinLocation] 已保存 userLocation =', this.userLocation);
},
fail: (err) => {
console.error('[WeixinLocation] wx.getLocation fail:', err);
uni.showModal({
title: '提示',
content: '获取位置失败,请允许访问位置信息',
showCancel: false
});
}
});
});
// #endif
},
// H5
getBrowserLocation() {
// #ifdef H5
if (typeof navigator === 'undefined' || !navigator.geolocation) {
uni.showModal({
title: '提示',
content: '您的浏览器不支持地理位置功能',
showCancel: false
});
return;
}
navigator.geolocation.getCurrentPosition(
(position) => {
this.userLocation = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
accuracy: position.coords.accuracy,
altitude: position.coords.altitude,
altitudeAccuracy: position.coords.altitudeAccuracy,
heading: position.coords.heading,
speed: position.coords.speed
};
console.log('浏览器获取位置成功:', this.userLocation);
},
(error) => {
console.error('浏览器获取位置失败:', error);
let errorMsg = '获取位置失败';
switch(error.code) {
case error.PERMISSION_DENIED:
errorMsg = '用户拒绝了位置请求';
break;
case error.POSITION_UNAVAILABLE:
errorMsg = '位置信息不可用';
break;
case error.TIMEOUT:
errorMsg = '获取位置超时';
break;
}
uni.showModal({
title: '提示',
content: errorMsg + ',请允许访问位置信息',
showCancel: false
});
},
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
}
);
// #endif
},
//
getMiniProgramLocation() {
// #ifdef MP-WEIXIN
uni.getLocation({
type: 'gcj02',
success: (res) => {
this.userLocation = {
latitude: res.latitude,
longitude: res.longitude,
speed: res.speed,
accuracy: res.accuracy
};
console.log('小程序获取位置成功:', this.userLocation);
},
fail: (err) => {
console.error('小程序获取位置失败:', err);
uni.showModal({
title: '提示',
content: '获取位置失败,请在设置中允许位置权限',
showCancel: false
});
}
});
// #endif
},
setDirection(dir) {
this.direction = dir
this.direction = dir;
//
this.isInGeofence = null;
//
if (dir) {
this.fetchGeofenceByDirection();
}
},
async fetchGeofenceByDirection() {
const token = uni.getStorageSync('token');
if (!token || !this.direction) return;
try {
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.GET_GEOFENCE_BY_DIRECTION}?token=${token}&direction=${this.direction}`,
method: 'GET',
success: resolve,
fail: reject
});
});
if (res.data && res.data.errcode === 0) {
const geofenceData = res.data.data;
console.log(geofenceData);
//
if (!geofenceData || !Array.isArray(geofenceData) || geofenceData.length === 0) {
this.isInGeofence = true; //
return;
}
//
this.checkLocationInGeofence(geofenceData);
}
} catch (e) {
//
}
},
//
checkLocationInGeofence(geofenceData) {
//
if (!this.userLocation || !this.userLocation.latitude || !this.userLocation.longitude) {
console.warn('用户位置信息不存在,无法进行范围判断');
return;
}
const userLat = parseFloat(this.userLocation.latitude);
const userLng = parseFloat(this.userLocation.longitude);
// coordinates
for (let i = 0; i < geofenceData.length; i++) {
const item = geofenceData[i];
if (item && item.coordinates && Array.isArray(item.coordinates) && item.coordinates.length > 0) {
//
if (this.isPointInPolygon(userLng, userLat, item.coordinates)) {
// true
this.isInGeofence = true;
console.log('用户位置在围栏范围内');
return;
}
}
}
// false
this.isInGeofence = false;
uni.showModal({
title: '提示',
content: '您的当前位置不在闸站可预约范围内',
showCancel: false
});
},
// 使线
isPointInPolygon(lng, lat, coordinates) {
if (!coordinates || coordinates.length < 3) {
return false;
}
//
const polygon = coordinates.map(coord => {
if (Array.isArray(coord) && coord.length >= 2) {
return [
parseFloat(coord[0]),
parseFloat(coord[1])
];
}
return null;
}).filter(coord => coord !== null);
if (polygon.length < 3) {
return false;
}
let inside = false;
const x = lng;
const y = lat;
// 线线
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
const xi = polygon[i][0];
const yi = polygon[i][1];
const xj = polygon[j][0];
const yj = polygon[j][1];
// 线
const intersect = ((yi > y) !== (yj > y)) &&
(x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) {
inside = !inside;
}
}
return inside;
},
async fetchDailyReservationDeadline() {
const token = uni.getStorageSync('token');
if (!token) return;
try {
const res = await new Promise((resolve, reject) => {
uni.request({
url: `${API.GET_DAILY_RESERVATION_DEADLINE}?token=${token}`,
method: 'GET',
success: resolve,
fail: reject
});
});
if (res.data && res.data.errcode === 0) {
const deadlineData = res.data.data;
if (deadlineData && deadlineData.deadline_time) {
this.deadlineTime = deadlineData.deadline_time;
this.checkDeadlineAndSetDate();
}
}
} catch (e) {
//
}
},
checkDeadlineAndSetDate() {
if (!this.deadlineTime) return;
const now = new Date();
const currentHour = now.getHours();
const currentMinute = now.getMinutes();
// "18:00"
const [deadlineHour, deadlineMinute] = this.deadlineTime.split(':').map(Number);
//
const currentTimeMinutes = currentHour * 60 + currentMinute;
const deadlineTimeMinutes = deadlineHour * 60 + deadlineMinute;
//
if (currentTimeMinutes >= deadlineTimeMinutes) {
this.gateDate = 'tomorrow';
} else {
//
this.gateDate = 'today';
}
//
this.isDateDisabled = true;
},
async fetchShipList() {
const token = uni.getStorageSync('token');
@ -183,10 +547,7 @@ export default {
label,
value: res.data.data[label]
}));
//
if (this.directionEnum.length && !this.direction) {
this.direction = this.directionEnum[0].value;
}
//
}
} catch (e) {}
},
@ -226,6 +587,15 @@ export default {
uni.showToast({ title: '请先阅读并同意预约须知', icon: 'none' });
return;
}
if (!this.direction) {
uni.showToast({ title: '请先选择航行方向', icon: 'none' });
return;
}
//
if (this.isInGeofence === false) {
uni.showToast({ title: '您的当前位置不在闸站可预约范围内', icon: 'none' });
return;
}
const token = uni.getStorageSync('token');
if (!token) {
uni.showToast({ title: '请先登录', icon: 'none' });
@ -249,16 +619,25 @@ export default {
gateDateStr = tomorrow.toISOString().slice(0, 10);
}
uni.showLoading({ title: '提交中...' });
uni.request({
url: `${API.RESERVATION_CREATE}`,
method: 'POST',
data: {
//
const requestData = {
token,
ship_id: this.currentShip.id,
direction: directionValue,
passage_date: gateDateStr
},
};
//
if (this.userLocation && this.userLocation.latitude && this.userLocation.longitude) {
requestData.latitude = this.userLocation.latitude;
requestData.longitude = this.userLocation.longitude;
}
uni.showLoading({ title: '提交中...' });
uni.request({
url: `${API.RESERVATION_CREATE}`,
method: 'POST',
data: requestData,
success: (res) => {
uni.hideLoading();
if (res.data && res.data.errcode === 0) {
@ -267,8 +646,34 @@ export default {
uni.switchTab({ url: '/pages/order/index' });
}, 800);
} else {
uni.hideLoading();
uni.showToast({ title: res.data.errmsg || '预约失败', icon: 'none' });
//
// res.data.data = { latitude: [''], longitude: [''] }
const resp = res.data || {};
const detail = resp.data || {};
let msg = '';
if (detail && typeof detail === 'object') {
const parts = [];
if (Array.isArray(detail.latitude) && detail.latitude.length) {
parts.push(`纬度:${detail.latitude.join('')}`);
}
if (Array.isArray(detail.longitude) && detail.longitude.length) {
parts.push(`经度:${detail.longitude.join('')}`);
}
if (parts.length) {
msg = parts.join('');
}
}
if (!msg) {
msg = resp.errmsg || '预约失败';
}
uni.showModal({
title: '提示',
content: msg,
showCancel: false
});
}
},
fail: () => {
@ -281,6 +686,10 @@ export default {
this.agreeNotice = !this.agreeNotice;
},
setGateDate(val) {
//
if (this.isDateDisabled) {
return;
}
this.gateDate = val;
},
}
@ -421,6 +830,14 @@ export default {
background: #217aff;
color: #fff;
}
.direction-btn:disabled {
opacity: 0.6;
pointer-events: none;
}
.direction-btn.tomorrow-default {
background: linear-gradient(90deg, rgb(255, 185, 128) 0%, rgb(255, 201, 154) 100%) !important;
color: #fff;
}
.notice-row {
margin: 24px 16px 0 16px;
}

@ -1,2 +1,2 @@
<!DOCTYPE html><html lang=zh-CN><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>胥口闸站购票</title><script>var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/h5/static/index.883130ca.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/h5/static/js/chunk-vendors.b0f646d7.js></script><script src=/h5/static/js/index.8a37751e.js></script></body></html>
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')</script><link rel=stylesheet href=/h5/static/index.883130ca.css></head><body><noscript><strong>Please enable JavaScript to continue.</strong></noscript><div id=app></div><script src=/h5/static/js/chunk-vendors.f93c9f80.js></script><script src=/h5/static/js/index.c970d746.js></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save