From 5c74c7ccc069eb6395e34a864ad3056e0f9d9b09 Mon Sep 17 00:00:00 2001 From: xiaogg Date: Mon, 13 Apr 2026 16:13:23 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E5=AE=8C=E5=96=84?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AMapNavIOSSDK.bundle/ic_fuel@3x.png | Bin 1279 -> 1202 bytes .../AMapNavIOSSDK.bundle/ic_mileage@3x.png | Bin 0 -> 844 bytes .../AMapNavIOSSDK.bundle/ic_person@3x.png | Bin 0 -> 792 bytes .../AMapNavIOSSDK.bundle/ic_phone@3x.png | Bin 0 -> 909 bytes .../AMapNavIOSSDK.bundle/ic_price@3x.png | Bin 0 -> 1256 bytes .../AMapNavIOSSDK.bundle/ic_time@3x.png | Bin 0 -> 1167 bytes .../AMapNavIOSSDK.bundle/ic_toll@3x.png | Bin 0 -> 864 bytes .../Classes/Class/AAddHPopView.h | 30 + .../Classes/Class/AAddHPopView.m | 359 ++++++++++ .../Class/ACustomNaviDriveController.h | 16 + .../Class/ACustomNaviDriveController.m | 22 + .../Classes/Class/ARoutePlaneController.h | 4 +- .../Classes/Class/ARoutePlaneController.m | 108 ++- .../Classes/Class/ASearchAddressController.m | 45 +- .../Class/AStationDetailPopupController.h | 16 + .../Class/AStationDetailPopupController.m | 227 +++++- .../AMapNavIOSSDK/Classes/Model/ASiteModel.h | 5 + .../Classes/Tools/AMapNavCommonUtil.h | 4 + .../Classes/Tools/AMapNavCommonUtil.m | 9 + .../Classes/Tools/UIColor+ANavMap.h | 20 + .../Classes/Tools/UIColor+ANavMap.m | 53 ++ .../AMapNavIOSSDK/Classes/Tools/UIFont+HP.h | 36 + .../AMapNavIOSSDK/Classes/Tools/UIFont+HP.m | 45 ++ .../Classes/View/ABottomBarView.m | 3 +- .../Classes/View/AStationDetailPopupView.h | 70 ++ .../Classes/View/AStationDetailPopupView.m | 655 ++++++++++++++++++ 26 files changed, 1673 insertions(+), 54 deletions(-) create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_mileage@3x.png create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_person@3x.png create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_phone@3x.png create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_price@3x.png create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_time@3x.png create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_toll@3x.png create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AAddHPopView.h create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AAddHPopView.m create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.h create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.m create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.h create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.m create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.h create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.m create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.h create mode 100644 ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.m diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_fuel@3x.png b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_fuel@3x.png index a928c03fb80efaf4e3ab97f9459d84cd03599259..f7f1357762914b6c5f21da8112e6a4220347932d 100644 GIT binary patch delta 1088 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 diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_mileage@3x.png b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_mileage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8cbce62ed02a9b6c48c96cf34f1f46a05f7e2a GIT binary patch literal 844 zcmV-S1GD^zP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR917@z|H1ONa40RR917ytkO0OB=utpET5wn;=mR7ef&RnJRQQ562pol!?i z!pIu3NYTQ6P>5w&6#WV9+f<7-;X*0Qor{)|xoT0+A0Vx2)v8T7)+Qvvh$2dx(SD$W zOf$~B(>DX}-FM%6Mz-$4)Z z*G?aSR>v^7V-C5cpH955bOojIIph{|4t{;03#Mfh{n^iWk^dHsnXps0E7d-MT!PoQ zI~o&sLyTRH;wY!Lh~gR=QfH#ExPa(hk}_y$dlMzouazgB(}-o_4g7ZTbCyfK+E0?~ zBx4B^Pu3jfpPY&36wsA=Zv6~Pb{kg7WPtT{RlK(pYpI7vNKrg#iOfUM!B7joRiEMt zY}aN~rBqN=)8zzk*=Q+B)I}cS{c~}F|Pwg$WWCF?9aszWKEF| zblQ0P+K>dx6#$O1Q3a&EUjgH94bdX0d3e=*;S^Uuv|EJ&mFngNYB?%-Hu_Llz?~w+ zei91EG;bupS=UPVfWVf$UC|VdRS+jP9b|1F6WpC?5D#{Xx6T68HL;6#xzr zWNA#^55{%@pK$4l;THHva}8?Z0>*$=_?wHOJt-@5lDZr>l%VR3ndLvH!qE75EL1 WpVS<+h10+Q0000+$t8#Zw;k{$A$}PT^CbP4b-M{_wW9{brwDd;5 zR>v877CYv>Z@gQsG1v0klePn|niBdL-kkWwc)`DL_m{1*{?$!4KZ;y^eV*lo1#`B- zJ(Xo!R1?>pPt1GiF4Ea$lw|cb;BK{&9sA7-u3yA2z3@((@nX^ox0>52W^%29z72OJ z8~8k*@f%KvXm~BPqg(Em5ci^Ll>>`kTs^+ce}RVT(<#Q!&Fu;rQao?yG-@y|{>J($ zEc=Ue#yy73>W%G&h6|k;cB`Ady1mA~<%m*F!%Ds8IifFHR`1#WiF5Kz@qP81il%Xd zFVWLZ_}Dq&Tdc|C^8&M{Hz}U{Fr7_IcEZ(Uf6;>VBAx=ZE@E%PGG{LA^LT#7``}W! zCkCHwCQr_0zvr=R_U^xv-hS0TdEc~P;f9&s2QRBHwcUK`!-6lr&#h=-O*kyDWbzs9 z%)8fbg#P0bSL^tBxhl+fn!PF`{}U^H=G=x(Q<2Jl8Jkyb*&%UiY)Yn+MKKDLwKkHT%Z2Bh|S{ zuUX{yA2~Bw-ru`uP2##g#s+13&*|Q}aVuZP-o{3$a#KpnqX?nR`_}%BzR16^lvg-k zO~97_(CeM|ZHt0gIN3D*TyA9vYJPsfLbra+V&8YM`AY-syeITb{eS5p=O3ozyQdcZ TyftetC{=p8`njxgN@xNAI1W}r literal 0 HcmV?d00001 diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_phone@3x.png b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_phone@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..27d3f812bb128601981a16d10f2d5175a9195b17 GIT binary patch literal 909 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 literal 0 HcmV?d00001 diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_toll@3x.png b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Assets/AMapNavIOSSDK.bundle/ic_toll@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3b184a6cd2ad243e8f4e34599f886c8711f0cba3 GIT binary patch literal 864 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjjKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDq2jf$5Z|i(`lf z@7qvckB~r-f9GoR=cp~8<#NO|p!=3ffWqSoEUH^IIu?itZONDzs3&uo?Y2w87A=u0 z3qre_GDNp%2wXY9BUMTYhmy<5a&z+NMum3w`}Pb>%wa;v?6mCUxkr*&f{Xz?qp{ zDcUh@Qb&J-M`M6)U0_Dd@lM-hiGK^;`mT8T$5qYbMU70f0^zA@kHYj9ax zp_(tufJfNY<;tOA`_CEc>(@UsvR3`U%4C0ePtDEGn!e5bsm$j-2zN|zJwID=p|Qs` zQ{&mSOt*a-jF`L~UQD7QI$C zD0-YD86J?>XZb9~_TZenNa-W7!RxzUUiaS+W6WPO`_Np$g+_0RJ&pt&RW#c7r^nTG^0i8V_t(b5(=A0c+eOcR zYgW`)<=F6C@J5{S-;CgyhTLbm)IF|+YH!M$ysb^+yk?SV!_G6hB`(?Adrk{ + +NS_ASSUME_NONNULL_BEGIN + +/** + * 气泡弹框视图 + * + * 用法: + * AAddHPopView *pop = [[AAddHPopView alloc] init]; + * [pop showInView:self.view sourceView:addHbtn]; + * + * - 点击气泡外部自动消失 + * - 箭头在右下角45度,指向 sourceView 中心 + */ +@interface AAddHPopView : UIView + +/// 展示气泡,sourceView 为箭头指向的锚定按钮(坐标系属于 view) +- (void)showInView:(UIView *)view sourceView:(UIView *)sourceView; + +/// 手动消失(点击空白处会自动调用) +- (void)dismiss; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AAddHPopView.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AAddHPopView.m new file mode 100644 index 0000000..a624e11 --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AAddHPopView.m @@ -0,0 +1,359 @@ +// +// AAddHPopView.m +// AMapNavIOSSDK +// + +#import "AAddHPopView.h" +#import +#import "UIColor+ANavMap.h" + +// ─── 尺寸常量 ──────────────────────────────────────────────────────────────── +static const CGFloat kBubbleWidth = 200.f; // 气泡宽度 +static const CGFloat kHeaderHeight = 50.f; // 顶部绿色标题区高度 +static const CGFloat kOptionHeight = 60.f; // 每行选项高度 +static const CGFloat kArrowWidth = 50.f; // 箭头底边宽(aw = ah*2 使左右45度对称) +static const CGFloat kArrowHeight = 15.f; // 箭头高度 +static const CGFloat kBubbleRadius = 15.f; // 气泡圆角半径 +static const CGFloat kBubbleGap = 5.f; // 气泡底部与 sourceView 顶部间距 +static const CGFloat kScreenPadding = 15.f; // 气泡距屏幕边缘最小距离 + + +// ─── 自定义气泡容器:自绘白色气泡 + 底部箭头 ───────────────────────────────── +@interface _ABubbleContainerView : UIView +/// 箭头中心 X(相对于本 view 坐标系),用于 showInView 精确定位 +@property (nonatomic, assign) CGFloat arrowCenterX; +@end + +@implementation _ABubbleContainerView + +- (instancetype)init { + self = [super init]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + _arrowCenterX = kBubbleWidth / 2.f; + } + return self; +} + +- (void)setArrowCenterX:(CGFloat)arrowCenterX { + _arrowCenterX = arrowCenterX; + [self setNeedsDisplay]; +} + +- (void)drawRect:(CGRect)rect { + CGFloat bw = kBubbleWidth; // 160 + CGFloat bh = kHeaderHeight + kOptionHeight * 2.f; // 150 + CGFloat r = kBubbleRadius; // 10 + CGFloat aw = kArrowWidth; // 16 箭头底边宽 + CGFloat ah = kArrowHeight; // 10 箭头高度 + + // 箭头在底部偏右:指向右下45度 + // 箭头底边: 从 (arrowX-aw/2, bh) 到 (arrowX, bh) + // 箭头尖端: (arrowX + ah, bh + ah) — 相对于底边中心向右下45度 + CGFloat arrowX = bw - 15.f; // 箭头底边右端 X(偏右下) + CGFloat arrowTipX = arrowX + ah; // 箭头尖端 X(向右偏移ah = 45度) + CGFloat arrowTipY = bh + ah; // 箭头尖端 Y(向下偏移ah = 45度) + + UIBezierPath *path = [UIBezierPath bezierPath]; + + // ── 顶部左圆角 → 顶部右圆角 ── + [path moveToPoint:CGPointMake(r, 0)]; + [path addLineToPoint:CGPointMake(bw - r, 0)]; + [path addArcWithCenter:CGPointMake(bw - r, r) radius:r + startAngle:-M_PI_2 endAngle:0 clockwise:YES]; + + // ── 右边 → 右下圆角 ── + [path addLineToPoint:CGPointMake(bw, bh - r)]; + [path addArcWithCenter:CGPointMake(bw - r, bh - r) radius:r + startAngle:0 endAngle:M_PI_2 clockwise:YES]; + + // ── 底边 → 箭头底边右端 ── + [path addLineToPoint:CGPointMake(arrowX, bh)]; + // 箭头斜边(45度向右下到尖端) + [path addLineToPoint:CGPointMake(arrowTipX, arrowTipY)]; + // 箭头底边左端(垂直向上) + [path addLineToPoint:CGPointMake(arrowX - ah, bh)]; + + // ── 左下圆角 ── + [path addArcWithCenter:CGPointMake(r, bh - r) radius:r + startAngle:M_PI_2 endAngle:M_PI clockwise:YES]; + + // ── 左边 → 左上圆角 ── + [path addLineToPoint:CGPointMake(0, r)]; + [path addArcWithCenter:CGPointMake(r, r) radius:r + startAngle:M_PI endAngle:-M_PI_2 clockwise:YES]; + [path closePath]; + + // ── 阴影 + 白色填充 ── + CGContextRef ctx = UIGraphicsGetCurrentContext(); + CGContextSaveGState(ctx); + CGContextSetShadowWithColor(ctx, CGSizeMake(0, 3), 10.f, + [[UIColor blackColor] colorWithAlphaComponent:0.15f].CGColor); + [[UIColor whiteColor] setFill]; + [path fill]; + CGContextRestoreGState(ctx); + [[UIColor whiteColor] setFill]; + [path fill]; + + // 保存箭头尖端坐标用于定位 + _arrowTipX = arrowTipX; + _arrowTipY = arrowTipY; +} + +// 供外部访问的箭头尖端坐标 +static CGFloat _arrowTipX = 0; +static CGFloat _arrowTipY = 0; + +@end + + +// ─── AAddHPopView ──────────────────────────────────────────────────────────── + +@interface AAddHPopView () + +@property (nonatomic, strong) _ABubbleContainerView *bubbleContainer; +@property (nonatomic, strong) UIView *headerView; +@property (nonatomic, strong) UILabel *titleLabel; +@property (nonatomic, strong) UIView *separatorLine1; +@property (nonatomic, strong) UILabel *option1Label; +@property (nonatomic, strong) UIView *separatorLine2; +@property (nonatomic, strong) UILabel *option2Label; + +@end + +@implementation AAddHPopView + +#pragma mark - Init + +- (instancetype)init { + return [self initWithFrame:CGRectZero]; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self p_setupUI]; + } + return self; +} + +#pragma mark - Setup UI + +- (void)p_setupUI { + self.backgroundColor = [UIColor clearColor]; + + // ── 点击空白处(self)消失 ── + UITapGestureRecognizer *bgTap = [[UITapGestureRecognizer alloc] initWithTarget:self + action:@selector(dismiss)]; + bgTap.cancelsTouchesInView = NO; + [self addGestureRecognizer:bgTap]; + + // ── 气泡容器 ── + [self addSubview:self.bubbleContainer]; + + // ── header(绿色标题区,仅裁剪上两角) ── + [self.bubbleContainer addSubview:self.headerView]; + [self.headerView addSubview:self.titleLabel]; + + // ── 分隔线 1 ── + [self.bubbleContainer addSubview:self.separatorLine1]; + + // ── 选项 1 ── + [self.bubbleContainer addSubview:self.option1Label]; + + // ── 分隔线 2 ── + [self.bubbleContainer addSubview:self.separatorLine2]; + + // ── 选项 2 ── + [self.bubbleContainer addSubview:self.option2Label]; + + // ── 阻止气泡内点击冒泡到 bgTap ── + UITapGestureRecognizer *bubbleTap = [[UITapGestureRecognizer alloc] initWithTarget:self + action:@selector(p_bubbleTapped)]; + [self.bubbleContainer addGestureRecognizer:bubbleTap]; + + // ── Masonry 内部约束(基于 bubbleContainer) ── + // 子视图宽度统一约束到 kBubbleWidth(160),气泡主体实际宽度 + [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.left.equalTo(self.bubbleContainer); + make.width.mas_equalTo(kBubbleWidth); + make.height.mas_equalTo(kHeaderHeight); + }]; + + [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self.headerView); + }]; + + [self.separatorLine1 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.headerView.mas_bottom); + make.left.mas_equalTo(@0); + make.width.mas_equalTo(kBubbleWidth); + make.height.mas_equalTo(0.5); + }]; + + [self.option1Label mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.separatorLine1.mas_bottom); + make.left.mas_equalTo(@0); + make.width.mas_equalTo(kBubbleWidth); + make.height.mas_equalTo(kOptionHeight); + }]; + + [self.separatorLine2 mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.option1Label.mas_bottom); + make.left.mas_equalTo(@0); + make.width.mas_equalTo(kBubbleWidth); + make.height.mas_equalTo(0.5); + }]; + + [self.option2Label mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.separatorLine2.mas_bottom); + make.left.mas_equalTo(@0); + make.width.mas_equalTo(kBubbleWidth); + make.height.mas_equalTo(kOptionHeight); + }]; +} + +#pragma mark - Show / Dismiss + +- (void)showInView:(UIView *)view sourceView:(UIView *)sourceView { + self.frame = view.bounds; + [view addSubview:self]; + + // ── 计算 sourceView 在 view 坐标系中的 frame ── + CGRect srcFrame = [sourceView convertRect:sourceView.bounds toView:view]; + + // ── 容器尺寸 ── + CGFloat containerW = kBubbleWidth; // 160 + CGFloat containerH = kHeaderHeight + kOptionHeight * 2.f; // 150 + CGFloat ah = kArrowHeight; // 16 箭头高度 + + // ── 箭头尖端坐标(相对于 bubbleContainer 左下角为原点)── + // 与 drawRect 中一致:arrowX = bw - 35, arrowTipX = arrowX + ah + CGFloat arrowX_inContainer = containerW - 25.f; // 箭头底边右端 X + CGFloat arrowTipX_inContainer = arrowX_inContainer + ah; // 箭头尖端 X(右下45度) + CGFloat arrowTipY_inContainer = containerH + ah; // 箭头尖端 Y + + // ── 位置计算:气泡在按钮左上方,箭头尖端指向按钮中心 ── + CGFloat srcCenterX = CGRectGetMidX(srcFrame); + CGFloat srcCenterY = CGRectGetMidY(srcFrame); + + // 箭头尖端应指向按钮中心 + CGFloat containerX = srcCenterX - arrowTipX_inContainer; + containerX = MAX(kScreenPadding, MIN(containerX, view.bounds.size.width - containerW - kScreenPadding)); + + // 气泡顶部位置 + CGFloat containerY = srcCenterY - arrowTipY_inContainer; + containerY = MAX(kScreenPadding, containerY); + + self.bubbleContainer.bounds = CGRectMake(0, 0, containerW, containerH + ah); + + // 锚点设置在箭头尖端位置(相对于容器),实现箭头精准指向 + self.bubbleContainer.layer.anchorPoint = CGPointMake(arrowTipX_inContainer / containerW, + arrowTipY_inContainer / (containerH + ah)); + self.bubbleContainer.center = CGPointMake(srcCenterX - 25, srcCenterY - 20); + + // ── 入场动画 ── + self.alpha = 0.f; + self.bubbleContainer.transform = CGAffineTransformMakeScale(0.85f, 0.85f); + + [UIView animateWithDuration:0.25f + delay:0.f + usingSpringWithDamping:0.72f + initialSpringVelocity:0.3f + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + self.alpha = 1.f; + self.bubbleContainer.transform = CGAffineTransformIdentity; + } completion:nil]; +} + +- (void)dismiss { + [UIView animateWithDuration:0.18f + delay:0.f + options:UIViewAnimationOptionCurveEaseIn + animations:^{ + self.alpha = 0.f; + self.bubbleContainer.transform = CGAffineTransformMakeScale(0.85f, 0.85f); + } completion:^(BOOL finished) { + [self removeFromSuperview]; + }]; +} + +#pragma mark - Private Actions + +- (void)p_bubbleTapped { + // 阻止冒泡,气泡内点击不消失 +} + +#pragma mark - Lazy Load + +- (_ABubbleContainerView *)bubbleContainer { + if (!_bubbleContainer) { + _bubbleContainer = [[_ABubbleContainerView alloc] init]; + } + return _bubbleContainer; +} + +- (UIView *)headerView { + if (!_headerView) { + _headerView = [[UIView alloc] init]; + _headerView.backgroundColor = [UIColor hp_colorWithRGBHex:0x1BA855]; + if (@available(iOS 11.0, *)) { + _headerView.layer.cornerRadius = kBubbleRadius; + _headerView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner; + _headerView.clipsToBounds = YES; + } + } + return _headerView; +} + +- (UILabel *)titleLabel { + if (!_titleLabel) { + _titleLabel = [[UILabel alloc] init]; + _titleLabel.text = @"加氢规划模式"; + _titleLabel.textColor = [UIColor whiteColor]; + _titleLabel.font = [UIFont boldSystemFontOfSize:15.f]; + _titleLabel.textAlignment = NSTextAlignmentCenter; + } + return _titleLabel; +} + +- (UIView *)separatorLine1 { + if (!_separatorLine1) { + _separatorLine1 = [[UIView alloc] init]; + _separatorLine1.backgroundColor = [UIColor colorWithWhite:0.88f alpha:1.f]; + } + return _separatorLine1; +} + +- (UILabel *)option1Label { + if (!_option1Label) { + _option1Label = [[UILabel alloc] init]; + _option1Label.text = @"送货规划模式"; + _option1Label.textColor = [UIColor hp_colorWithRGBHex:0xC9CDD4]; + _option1Label.font = [UIFont boldSystemFontOfSize:14.f]; + _option1Label.textAlignment = NSTextAlignmentCenter; + } + return _option1Label; +} + +- (UIView *)separatorLine2 { + if (!_separatorLine2) { + _separatorLine2 = [[UIView alloc] init]; + _separatorLine2.backgroundColor = [UIColor colorWithWhite:0.88f alpha:1.f]; + } + return _separatorLine2; +} + +- (UILabel *)option2Label { + if (!_option2Label) { + _option2Label = [[UILabel alloc] init]; + _option2Label.text = @"成本计算模式"; + _option2Label.textColor = [UIColor hp_colorWithRGBHex:0xC9CDD4]; + _option2Label.font = [UIFont boldSystemFontOfSize:14.f]; + _option2Label.textAlignment = NSTextAlignmentCenter; + } + return _option2Label; +} + +@end diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.h new file mode 100644 index 0000000..88d203a --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.h @@ -0,0 +1,16 @@ +// +// ACustomNaviDriveController.h +// AMapNavIOSSDK +// +// Created by admin on 2026/4/11. +// + +#import "ABaseViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ACustomNaviDriveController : ABaseViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.m new file mode 100644 index 0000000..ab414ea --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ACustomNaviDriveController.m @@ -0,0 +1,22 @@ +// +// ACustomNaviDriveController.m +// AMapNavIOSSDK +// +// Created by admin on 2026/4/11. +// + +#import "ACustomNaviDriveController.h" + +@interface ACustomNaviDriveController () + +@end + +@implementation ACustomNaviDriveController + +- (void)viewDidLoad { + [super viewDidLoad]; + // Do any additional setup after loading the view. +} + + +@end diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.h index 3a34308..e4dfb8f 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.h +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.h @@ -21,8 +21,8 @@ NS_ASSUME_NONNULL_BEGIN -@interface ARoutePlaneController : ABaseViewController - +@interface ARoutePlaneController : ABaseViewController +@property (nonatomic , strong) AMapNaviDriveView * driveView; @end NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.m index dde4cf1..564a930 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.m +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ARoutePlaneController.m @@ -18,7 +18,7 @@ #import "AMapPrivacyUtility.h" -#import "AStationDetailPopupController.h" +#import "AStationDetailPopupView.h" #define kRouteIndicatorViewHeight 64.f @@ -26,8 +26,9 @@ #import "AMapNavHttpUtil.h" #import "ACustomStepView.h" #import "ABottomBarView.h" +#import "AAddHPopView.h" -@interface ARoutePlaneController () +@interface ARoutePlaneController () @property (nonatomic, strong) UITextField *textField; /// 底部搜索+规划路线栏 @@ -65,11 +66,14 @@ @property (nonatomic , strong)ACustomStepView * stepView; /// 当前弹出的站点详情弹框 -@property (nonatomic , strong)AStationDetailPopupController * stationDetailPopup; +@property (nonatomic , strong)AStationDetailPopupView * stationDetailPopup; @property (nonatomic, strong) ANavPointModel *pointModel; //当前选的目的点 @property (nonatomic, strong) ATripCalcDataModel * tjdPathInfoModel;//途经点信息 @property (nonatomic, strong) CLLocationManager * locationManager; + +/// 加氢规划按钮(用于气泡弹框定位) +@property (nonatomic, weak) UIButton *addHBtn; @end @implementation ARoutePlaneController @@ -156,6 +160,8 @@ -(void)requestRoutePathWithParms:(NSDictionary*)dic completeHandle:(void(^)(ATripCalcDataModel * tjd))blk { + ///清除上一次数据影响 + self.tjdPathInfoModel = nil; NSString * token = [[NSUserDefaults standardUserDefaults]valueForKey:@"flutter.token"]; NSString * carNo = [[NSUserDefaults standardUserDefaults]valueForKey:@"flutter.plateNumber"]; @@ -279,7 +285,7 @@ [bottomBar mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self.view); - make.bottom.equalTo(self.view); + make.bottom.equalTo(self.view).offset(-AMP_TabbarHeight - 10); }]; // ── 兼容旧逻辑:保留 startTf / dstTf 属性(隐藏,不再显示) ── @@ -319,25 +325,55 @@ [stepView addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:nil]; self.stepView = stepView; + stepView.hidden = YES; ///当前位置按钮 UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom]; - [btn setImage:[AMapNavCommonUtil imageWithName3x:@"my_location_icon"] forState:UIControlStateNormal]; - btn.backgroundColor = [UIColor lightGrayColor]; + [btn setBackgroundImage:[AMapNavCommonUtil imageWithName3x:@"my_location_icon"] forState:UIControlStateNormal]; + + btn.backgroundColor = [UIColor whiteColor]; btn.titleLabel.font = [UIFont systemFontOfSize:14]; - btn.layer.cornerRadius = 20; + btn.layer.cornerRadius = 22; [btn addTarget:self action:@selector(updateUserLocalAction) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; [btn mas_makeConstraints:^(MASConstraintMaker *make) { make.right.equalTo(self.view).offset(-10); - make.width.height.equalTo(@40); - make.bottom.equalTo(bottomBar.mas_top).offset(-85); + make.width.height.equalTo(@44); + make.bottom.equalTo(bottomBar.mas_top).offset(-105); }]; + ///加氢规划按钮 + UIButton *addHbtn = [UIButton buttonWithType:UIButtonTypeCustom]; + addHbtn.backgroundColor = [UIColor hp_colorWithRGBHex:0x017137]; + addHbtn.titleLabel.numberOfLines = 2; + + [addHbtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + [addHbtn setTitle:@"加氢规划" forState:UIControlStateNormal]; + + addHbtn.titleLabel.font = [UIFont boldSystemFontOfSize:11]; + addHbtn.titleEdgeInsets = UIEdgeInsetsMake(0, 3, 0, 3); + + addHbtn.layer.cornerRadius = 22; + [addHbtn addTarget:self action:@selector(addHbtnAction:) forControlEvents:UIControlEventTouchUpInside]; + [self.view addSubview:addHbtn]; + [addHbtn mas_makeConstraints:^(MASConstraintMaker *make) { + make.right.equalTo(self.view).offset(-10); + make.width.height.equalTo(@44); + make.bottom.equalTo(btn.mas_top).offset(-25); + }]; + self.addHBtn = addHbtn; + } +- (void)addHbtnAction:(UIButton *)sender { + // 显示加氢规划模式气泡弹窗,箭头指向按钮 + AAddHPopView *popView = [[AAddHPopView alloc] init]; + [popView showInView:self.view sourceView:sender]; +} + + - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"value"]) { self.mapView.zoomLevel = [change[NSKeyValueChangeNewKey] doubleValue]; @@ -363,6 +399,7 @@ self.mapView.userTrackingMode = MAUserTrackingModeFollowWithHeading; self.mapView.desiredAccuracy = kCLLocationAccuracyNearestTenMeters; // 定位精度 _mapView.showsScale= YES; + _mapView.showsCompass = NO; _mapView.logoCenter = CGPointMake(CGRectGetWidth(self.view.bounds)-55, 450); self.mapView.zoomLevel = 11; @@ -508,7 +545,7 @@ 0, 0, 0); - strategy = AMapNaviDrivingStrategyMultipleDefault;//使用默认策略 + strategy = AMapNaviDrivingStrategyMultipleDefault;//使用默认策略,DRIVING_MULTIPLE_ROUTES_DEFAULT id delegate = [AMapNaviDriveManager sharedInstance].delegate; if (!delegate) { @@ -780,7 +817,8 @@ [config setNeedCalculateRouteWhenPresent:NO];//不在算路 [config setMultipleRouteNaviMode:NO];//直接单线路径导航 // [config setNeedDestoryDriveManagerInstanceWhenDismiss:NO]; - + [config setShowDrivingStrategyPreferenceView:NO]; + [self.compositeManager presentRoutePlanViewControllerWithOptions:config]; } @@ -797,6 +835,8 @@ // [config setMultipleRouteNaviMode:NO];//直接单线路径导航 // [config setNeedDestoryDriveManagerInstanceWhenDismiss:NO]; +// [config setShowDrivingStrategyPreferenceView:NO]; + [self.compositeManager presentRoutePlanViewControllerWithOptions:config]; } @@ -995,9 +1035,12 @@ [self updateUIWithData:aoi textField:self.dstTf]; + ///地图选点加氢站,直接弹出开始导航弹窗(显示时间、费用、里程、路费等),不用再回填名称 + //详情弹框 + [self willRequestTJDInfo]; // 同步更新底部栏目的地文字 - self.bottomBarView.destinationText = aoi.name; +// self.bottomBarView.destinationText = aoi.name; } } @@ -1056,6 +1099,7 @@ AMapPOI *_dstPoi = self.dstPoi ? self.dstPoi : self.defaultDstPoi; if (!_dstPoi) { + [AMapNavCommonUtil showMsg:@"请先选择目的地"]; return; } @@ -1066,9 +1110,19 @@ navPoint.stationID = _dstPoi.uid; self.pointModel = navPoint; + if (self.stationDetailPopup) { + [self.stationDetailPopup resetUI]; + } + ///有_stationID 请求接口;无:不走接口,直接调整高德规划路线; if (!navPoint.stationID) { - [self gd_calPathWithNoStationId:navPoint]; +// [self gd_calPathWithNoStationId:navPoint]; + ANavPointModel * model = [ANavPointModel new]; + model.name = navPoint.name; + model.address = navPoint.address; + + [self showDstInfoPop:model]; + return; }else { __weak typeof(self) weakSelf = self; @@ -1084,7 +1138,7 @@ // --- 弹出站点详情弹框 --- if (!self.stationDetailPopup) { - AStationDetailPopupController *popup = [[AStationDetailPopupController alloc] init]; + AStationDetailPopupView *popup = [[AStationDetailPopupView alloc] init]; popup.delegate = self; self.stationDetailPopup = popup; } @@ -1100,14 +1154,26 @@ self.stationDetailPopup.driveDistance = [NSString stringWithFormat:@"%.1f" , self.tjdPathInfoModel.pathDto.distance / 1000.0] ; ///油费 self.stationDetailPopup.tollFee = self.tjdPathInfoModel.pathDto.tolls; + + ///新增字段信息 + self.stationDetailPopup.contactName = self.tjdPathInfoModel.destinationSite.liaisonName; + self.stationDetailPopup.contactPhone = self.tjdPathInfoModel.destinationSite.liaisonPhone; + self.stationDetailPopup.businessHours = [NSString stringWithFormat:@"%@-%@" , [AMapNavCommonUtil stringValueFromStr:self.tjdPathInfoModel.destinationSite.startBusiness] , [AMapNavCommonUtil stringValueFromStr:self.tjdPathInfoModel.destinationSite.endBusiness]]; + self.stationDetailPopup.hydrogenPrice = [AMapNavCommonUtil stringValueFromStr:self.tjdPathInfoModel.destinationSite.hydrogenPrice]; - [self.stationDetailPopup presentInViewController:self]; + [self.stationDetailPopup showInView:self.view]; +// [self addChildViewController:self.stationDetailPopup]; +// +// CGRect rect = CGRectMake(CGRectGetMinX(self.view.frame), CGRectGetMinY(self.view.frame), CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - (AMP_TabbarHeight + 20) * 2); +// self.stationDetailPopup.view.frame = rect; +// +// [self.view addSubview:self.stationDetailPopup.view]; } -#pragma mark - AStationDetailPopupDelegate +#pragma mark - AStationDetailPopupViewDelegate -- (void)stationDetailPopupDidTapStartNavi:(AStationDetailPopupController *)popup { +- (void)stationDetailPopupViewDidTapStartNavi:(AStationDetailPopupView *)popup { self.stationDetailPopup = nil; ///点击开始导航: ///1、有途经点,计算路线,然后再直接导航 @@ -1126,7 +1192,7 @@ } } -- (void)stationDetailPopupDidTapClose:(AStationDetailPopupController *)popup { +- (void)stationDetailPopupViewDidTapClose:(AStationDetailPopupView *)popup { self.stationDetailPopup = nil; } @@ -1140,6 +1206,9 @@ } - (void)bottomBarViewDidTapSearchField:(ABottomBarView *)barView { + ///清除上一次数据影响 + self.tjdPathInfoModel = nil; + // 弹出地址搜索页,选中后更新目的地输入框 ASearchAddressController *vc = [[ASearchAddressController alloc] init]; UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; @@ -1160,7 +1229,8 @@ -(void)updateUIWithData: (AMapPOI*)poi textField: (UITextField*)tf { BOOL isStart = tf.tag == 100; - tf.text = poi.name; + ///不显示内容 +// tf.text = poi.name; if (isStart) { self.startPoi = poi; diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ASearchAddressController.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ASearchAddressController.m index c0ce3a8..ef28b82 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ASearchAddressController.m +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/ASearchAddressController.m @@ -18,10 +18,12 @@ @property (nonatomic , strong) UIBarButtonItem *rightItem; @property (nonatomic ,strong)UIButton * backBtn; -@property (nonatomic , strong) NSArray *dataArr; +@property (nonatomic , strong) NSMutableArray *dataArr; @property (nonatomic, strong) UITextField *inputAddressTf; @property (nonatomic, strong) AMapSearchAPI *search; +@property (nonatomic,assign)NSInteger currPage; + @end @implementation ASearchAddressController @@ -30,6 +32,9 @@ [super viewDidLoad]; // Do any additional setup after loading the view. self.title = @"选择地点"; + self.currPage = 1; + _dataArr = [NSMutableArray array]; + [self initSubview]; @@ -80,7 +85,8 @@ btn.layer.borderWidth = 1; btn.layer.cornerRadius = 5; btn.titleLabel.font = [UIFont systemFontOfSize:12]; - + btn.hidden = YES; + [btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [btn addTarget:self action:@selector(searchBtnAction) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; @@ -134,6 +140,14 @@ // [self.navigationController popViewControllerAnimated:YES]; } +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { + if (indexPath.row == self.dataArr.count - 1 && (self.dataArr.count % 20 == 0)) { + self.currPage = self.currPage + 1; + [self requestAddressWithAddress:self.inputAddressTf.text atPage:self.currPage]; + } + +} + #pragma mark - - (UITableView *)tableView { if (!_tableView) { @@ -189,6 +203,7 @@ // request.types = @"高等院校"; // request.requireExtension = YES; request.offset =20; + request.page = 1; /* 搜索SDK 3.2.0 中新增加的功能,只搜索本城市的POI。*/ request.cityLimit = YES; @@ -199,6 +214,27 @@ } +-(void)requestAddressWithAddress:(NSString *)addr atPage:(NSInteger)page { + AMapPOIKeywordsSearchRequest *request = [[AMapPOIKeywordsSearchRequest alloc] init]; + + request.keywords = addr; + + AMapNavSDKManager * sdk = [AMapNavSDKManager sharedManager]; + request.city = sdk.localCity; + + +// request.types = @"高等院校"; +// request.requireExtension = YES; + request.offset =20; + request.page = page; + + /* 搜索SDK 3.2.0 中新增加的功能,只搜索本城市的POI。*/ + request.cityLimit = YES; +// request.requireSubPOIs = YES; + + + [self.search AMapPOIKeywordsSearch:request]; +} #pragma mark - /* POI 搜索回调. */ @@ -212,7 +248,8 @@ //解析response获取POI信息,具体解析见 Demo - self.dataArr = [NSArray arrayWithArray:pois]; + [self.dataArr addObjectsFromArray:pois]; + [self.tableView reloadData]; } @@ -221,6 +258,8 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; + [self.dataArr removeAllObjects]; + self.currPage = 1; [self startSearchWithAddress:textField.text]; diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.h index ce2a216..9cd5358 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.h +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.h @@ -39,6 +39,19 @@ NS_ASSUME_NONNULL_BEGIN /// 过路费,如 @"30元";若 nil 则隐藏 @property (nonatomic, copy, nullable) NSString *tollFee; +/// 营业时间,如 @"00:00-24:00";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *businessHours; + +/// 站点联系人,如 @"陈凯";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *contactName; + +/// 联系方式,如 @"18019187371";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *contactPhone; + +/// 加氢价格,如 @"32元/L";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *hydrogenPrice; + + @property (nonatomic, weak, nullable) id delegate; /// 以半透明蒙层方式弹出在目标控制器上 @@ -50,6 +63,9 @@ NS_ASSUME_NONNULL_BEGIN /// 关闭弹框,动画结束后执行 completion(用于关闭后再 present 其他页面) - (void)dismissWithCompletion:(nullable void(^)(void))completion; + +-(void)resetUI; + @end NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.m index 9ba560a..6cfe370 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.m +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Class/AStationDetailPopupController.m @@ -57,6 +57,21 @@ static inline UIColor *AStationThemeGreen(void) { /// 卡片 bottom constraint(动画用) @property (nonatomic, strong) MASConstraint *cardBottomConstraint; +// ── 营业时间 ── +@property (nonatomic, strong) UILabel *businessHoursLabel; + +// ── 站点联系人 ── +@property (nonatomic, strong) UIImageView *contactPersonIconView; +@property (nonatomic, strong) UILabel *contactPersonLabel; + +// ── 加氢价格 ── +@property (nonatomic, strong) UIImageView *priceIconView; +@property (nonatomic, strong) UILabel *priceLabel; + +// ── 联系方式 ── +@property (nonatomic, strong) UIImageView *phoneIconView; +@property (nonatomic, strong) UILabel *phoneLabel; + @end @implementation AStationDetailPopupController @@ -121,6 +136,26 @@ static inline UIColor *AStationThemeGreen(void) { if (self.isViewLoaded) [self _updateUI]; } +- (void)setBusinessHours:(NSString *)businessHours { + _businessHours = [businessHours copy]; + if (self.isViewLoaded) [self _updateUI]; +} + +- (void)setContactName:(NSString *)contactName { + _contactName = [contactName copy]; + if (self.isViewLoaded) [self _updateUI]; +} + +- (void)setContactPhone:(NSString *)contactPhone { + _contactPhone = [contactPhone copy]; + if (self.isViewLoaded) [self _updateUI]; +} + +- (void)setHydrogenPrice:(NSString *)hydrogenPrice { + _hydrogenPrice = [hydrogenPrice copy]; + if (self.isViewLoaded) [self _updateUI]; +} + #pragma mark - Build UI /** @@ -168,10 +203,13 @@ static inline UIColor *AStationThemeGreen(void) { [card addSubview:closeBtn]; self.closeButton = closeBtn; + UIColor * headTextColor = [UIColor hp_colorWithRGBHex:0x1D2129]; + UIFont * headTextFont = [UIFont hp_pingFangMedium:14]; + // ── 站点名称 ── UILabel *nameLabel = [[UILabel alloc] init]; - nameLabel.font = [UIFont boldSystemFontOfSize:18]; - nameLabel.textColor = [UIColor colorWithWhite:0.1 alpha:1]; + nameLabel.font = [UIFont hp_pingFangMedium:18]; + nameLabel.textColor = headTextColor; nameLabel.numberOfLines = 2; // nameLabel.adjustsFontSizeToFitWidth = YES; nameLabel.minimumScaleFactor = 0.8; @@ -180,8 +218,8 @@ static inline UIColor *AStationThemeGreen(void) { // ── 预计加氢费用(名称右侧,间距20pt) ── UILabel *costLabel = [[UILabel alloc] init]; - costLabel.font = [UIFont systemFontOfSize:14]; - costLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1]; + costLabel.font = headTextFont; + costLabel.textColor = headTextColor; costLabel.numberOfLines = 1; costLabel.textAlignment = NSTextAlignmentLeft; // [costLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; @@ -189,10 +227,18 @@ static inline UIColor *AStationThemeGreen(void) { [card addSubview:costLabel]; self.costLabel = costLabel; + // ── 营业时间(站点名称下方,4pt间距,浅灰色小字) ── + UILabel *bizHoursLabel = [[UILabel alloc] init]; + bizHoursLabel.font = [UIFont hp_pingFangRegular:14]; + bizHoursLabel.textColor = [UIColor hp_colorWithRGBHex:0x1D2129]; + bizHoursLabel.numberOfLines = 1; + [card addSubview:bizHoursLabel]; + self.businessHoursLabel = bizHoursLabel; + // ── 地址 ── UILabel *addrLabel = [[UILabel alloc] init]; - addrLabel.font = [UIFont systemFontOfSize:13]; - addrLabel.textColor = [UIColor colorWithWhite:0.5 alpha:1]; + addrLabel.font = [UIFont hp_pingFangRegular:14]; + addrLabel.textColor = [UIColor hp_colorWithRGBHex:0x86909C]; addrLabel.numberOfLines = 2; [card addSubview:addrLabel]; self.addressLabel = addrLabel; @@ -212,45 +258,84 @@ static inline UIColor *AStationThemeGreen(void) { // ── 预计时间图标 ── UIImageView *timeIcon = [[UIImageView alloc] init]; timeIcon.contentMode = UIViewContentModeScaleAspectFit; - timeIcon.image = [AMapNavCommonUtil imageWithName3x:@"pre_time_icon"]; + timeIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_time"]; [card addSubview:timeIcon]; self.timeIconView = timeIcon; // ── 预计时间文字 ── UILabel *timeLabel = [[UILabel alloc] init]; - timeLabel.font = [UIFont systemFontOfSize:14]; - timeLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1]; + timeLabel.font = headTextFont; + timeLabel.textColor = headTextColor; [card addSubview:timeLabel]; self.timeLabel = timeLabel; // ── 行驶里程图标 ── UIImageView *distIcon = [[UIImageView alloc] init]; distIcon.contentMode = UIViewContentModeScaleAspectFit; - distIcon.image = [AMapNavCommonUtil imageWithName3x:@"pre_distance_icon"]; + distIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_mileage"]; [card addSubview:distIcon]; self.distanceIconView = distIcon; // ── 行驶里程文字 ── UILabel *distLabel = [[UILabel alloc] init]; - distLabel.font = [UIFont systemFontOfSize:14]; - distLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1]; + distLabel.font = headTextFont; + distLabel.textColor = headTextColor; [card addSubview:distLabel]; self.distanceLabel = distLabel; // ── 过路费图标 ── UIImageView *tollIcon = [[UIImageView alloc] init]; tollIcon.contentMode = UIViewContentModeScaleAspectFit; - tollIcon.image = [AMapNavCommonUtil imageWithName3x:@"pre_cost_icon"]; + tollIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_toll"]; [card addSubview:tollIcon]; self.tollIconView = tollIcon; // ── 过路费文字 ── UILabel *tollLabel = [[UILabel alloc] init]; - tollLabel.font = [UIFont systemFontOfSize:14]; - tollLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1]; + tollLabel.font = headTextFont; + tollLabel.textColor = headTextColor; [card addSubview:tollLabel]; self.tollLabel = tollLabel; + // ── 站点联系人图标 & 文字 ── + UIImageView *personIcon = [[UIImageView alloc] init]; + personIcon.contentMode = UIViewContentModeScaleAspectFit; + personIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_person"]; + [card addSubview:personIcon]; + self.contactPersonIconView = personIcon; + + UILabel *personLabel = [[UILabel alloc] init]; + personLabel.font = headTextFont; + personLabel.textColor = headTextColor; + [card addSubview:personLabel]; + self.contactPersonLabel = personLabel; + + // ── 加氢价格图标 & 文字 ── + UIImageView *priceIcon = [[UIImageView alloc] init]; + priceIcon.contentMode = UIViewContentModeScaleAspectFit; + priceIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_price"]; + [card addSubview:priceIcon]; + self.priceIconView = priceIcon; + + UILabel *priceLabel = [[UILabel alloc] init]; + priceLabel.font = headTextFont; + priceLabel.textColor = headTextColor; + [card addSubview:priceLabel]; + self.priceLabel = priceLabel; + + // ── 联系方式图标 & 文字 ── + UIImageView *phoneIcon = [[UIImageView alloc] init]; + phoneIcon.contentMode = UIViewContentModeScaleAspectFit; + phoneIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_phone"]; + [card addSubview:phoneIcon]; + self.phoneIconView = phoneIcon; + + UILabel *phoneLabel = [[UILabel alloc] init]; + phoneLabel.font = headTextFont; + phoneLabel.textColor = headTextColor; + [card addSubview:phoneLabel]; + self.phoneLabel = phoneLabel; + // ── 开始导航按钮 ── UIButton *naviBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [naviBtn setTitle:@"开始导航" forState:UIControlStateNormal]; @@ -301,24 +386,34 @@ static inline UIColor *AStationThemeGreen(void) { make.right.equalTo(self.closeButton.mas_left).offset(-12); }]; - // ── 地址(名称下方,6pt间距) ── - [self.addressLabel mas_makeConstraints:^(MASConstraintMaker *make) { + // ── 营业时间(站点名称下方,6pt间距) ── + [self.businessHoursLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.stationNameLabel.mas_bottom).offset(10); make.left.equalTo(card).offset(16); make.right.equalTo(card).offset(-16); }]; + // ── 地址(营业时间下方,6pt间距) ── + [self.addressLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.businessHoursLabel.mas_bottom).offset(10); + make.left.equalTo(card).offset(16); + make.right.equalTo(card).offset(-16); + }]; + self.separator.hidden = YES; + // ── 分割线(地址下方,12pt间距) ── [self.separator mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.addressLabel.mas_bottom).offset(15); + make.top.equalTo(self.addressLabel.mas_bottom).offset(10); make.left.equalTo(card).offset(16); make.right.equalTo(card).offset(-16); make.height.mas_equalTo(0.5); }]; + CGFloat _offset_y = 18; + // ── 预计时间行(分割线下方,14pt) ── [self.timeIconView mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.separator.mas_bottom).offset(15); + make.top.equalTo(self.separator.mas_bottom).offset(12); make.left.equalTo(card).offset(16); make.width.height.mas_equalTo(iconSize); }]; @@ -333,7 +428,7 @@ static inline UIColor *AStationThemeGreen(void) { ///cost [self.costIconView mas_makeConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.timeIconView); - make.left.equalTo(self.timeLabel.mas_right).offset(30); + make.left.equalTo(self.timeLabel.mas_right).offset(40); make.width.height.mas_equalTo(iconSize); }]; @@ -346,7 +441,7 @@ static inline UIColor *AStationThemeGreen(void) { // ── 行驶里程 + 过路费行(时间行下方,12pt) ── [self.distanceIconView mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.timeIconView.mas_bottom).offset(15); + make.top.equalTo(self.timeIconView.mas_bottom).offset(_offset_y); make.left.equalTo(card).offset(16); make.width.height.mas_equalTo(iconSize); }]; @@ -372,9 +467,49 @@ static inline UIColor *AStationThemeGreen(void) { make.height.mas_equalTo(24); }]; - // ── 开始导航按钮(里程行下方18pt,距卡片底部30pt) ── + // ── 站点联系人行(过路费行下方,14pt) ── + [self.contactPersonIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.distanceIconView.mas_bottom).offset(_offset_y); + make.left.equalTo(card).offset(16); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.contactPersonLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contactPersonIconView); + make.left.equalTo(self.contactPersonIconView.mas_right).offset(6); + make.height.mas_equalTo(24); + }]; + + // ── 加氢价格(与站点联系人同行,右侧对齐 costIconView) ── + [self.priceIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contactPersonIconView); + make.left.equalTo(self.costIconView.mas_left); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contactPersonIconView); + make.left.equalTo(self.priceIconView.mas_right).offset(6); + make.right.lessThanOrEqualTo(card).offset(-10); + make.height.mas_equalTo(24); + }]; + + // ── 联系方式行(站点联系人行下方,12pt) ── + [self.phoneIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contactPersonIconView.mas_bottom).offset(_offset_y); + make.left.equalTo(card).offset(16); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.phoneLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.phoneIconView); + make.left.equalTo(self.phoneIconView.mas_right).offset(6); + make.height.mas_equalTo(24); + }]; + + // ── 开始导航按钮(联系方式行下方18pt,距卡片底部 safeArea) ── [self.startNaviButton mas_makeConstraints:^(MASConstraintMaker *make) { - make.top.equalTo(self.distanceIconView.mas_bottom).offset(50); + make.top.equalTo(self.phoneIconView.mas_bottom).offset(40); make.left.equalTo(card).offset(16); make.right.equalTo(card).offset(-16); make.height.mas_equalTo(48); @@ -386,29 +521,63 @@ static inline UIColor *AStationThemeGreen(void) { - (void)_updateUI { self.stationNameLabel.text = (self.pointModel.name.length > 0) - ? self.pointModel.name : @"--"; + ? self.pointModel.name : @"-"; + + // ── 营业时间 ── + self.businessHoursLabel.text = (self.businessHours.length > 0) + ? [NSString stringWithFormat:@"营业时间:%@", self.businessHours] + : @"营业时间:-"; self.costLabel.text = (self.estimatedCost.length > 0) ? [NSString stringWithFormat:@"预计加氢费用:%@元", self.estimatedCost] - : @"预计加氢费用:--元"; + : @"预计加氢费用:-"; self.addressLabel.text = (self.pointModel.address.length > 0) - ? self.pointModel.address : @"--"; + ? self.pointModel.address : @"-"; // ── 预计时间(始终显示,无值显示"-- 分钟") ── self.timeLabel.text = (self.estimatedTime.length > 0) ? [NSString stringWithFormat:@"预计时间:%@分钟", self.estimatedTime] - : @"预计时间:--分钟"; + : @"预计时间:-"; // ── 行驶里程(始终显示,无值显示"-- 公里") ── self.distanceLabel.text = (self.driveDistance.length > 0) ? [NSString stringWithFormat:@"行驶里程:%@公里", self.driveDistance] - : @"行驶里程:--公里"; + : @"行驶里程:-"; // ── 过路费(始终显示,无值显示"-- 元") ── self.tollLabel.text = (self.tollFee.length > 0) ? [NSString stringWithFormat:@"过路费:%@元", self.tollFee] - : @"过路费:--元"; + : @"过路费:-"; + + // ── 站点联系人(有值显示值,无值显示 -) ── + self.contactPersonLabel.text = (self.contactName.length > 0) + ? [NSString stringWithFormat:@"站联系人:%@", self.contactName] + : @"站联系人:-"; + + // ── 加氢价格(有值显示值,无值显示 -) ── + self.priceLabel.text = (self.hydrogenPrice.length > 0) + ? [NSString stringWithFormat:@"加氢价格:%@/L", self.hydrogenPrice] + : @"加氢价格:-"; + + // ── 联系方式(有值显示值,无值显示 -) ── + self.phoneLabel.text = (self.contactPhone.length > 0) + ? [NSString stringWithFormat:@"联系方式:%@", self.contactPhone] + : @"联系方式:-"; +} + +// 重置 UI 状态 +-(void)resetUI { + self.stationNameLabel.text = @"-"; + self.businessHoursLabel.text = @"营业时间:-"; + self.costLabel.text = @"预计加氢费用:-"; + self.addressLabel.text = @"地址:-"; + self.timeLabel.text = @"预计时间:-"; + self.distanceLabel.text = @"行驶里程:-"; + self.tollLabel.text = @"过路费:-"; + self.contactPersonLabel.text = @"站联系人:-"; + self.priceLabel.text = @"加氢价格:-"; + self.phoneLabel.text = @"联系方式:-"; } #pragma mark - Animation diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Model/ASiteModel.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Model/ASiteModel.h index 942ec0f..8be5fb0 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Model/ASiteModel.h +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Model/ASiteModel.h @@ -59,6 +59,11 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, nullable) NSString *latitude; @property (nonatomic, copy, nullable) NSString *distance; +///新增弹框参数4.13 +@property (nonatomic, copy, nullable) NSString *hydrogenPrice; +@property (nonatomic, copy, nullable) NSString *liaisonName; +@property (nonatomic, copy, nullable) NSString *liaisonPhone; + @end NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.h index e1f7894..6b70d32 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.h +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.h @@ -7,6 +7,8 @@ #import #import +#import "UIColor+ANavMap.h" +#import "UIFont+HP.h" NS_ASSUME_NONNULL_BEGIN @@ -34,6 +36,8 @@ BOOL stringIsEmpty(NSString *str); /// 判断字符串是否非空 BOOL stringIsNotEmpty(NSString *str); ++(NSString *)stringValueFromStr:(NSString *)str; + @end NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.m index 2d34da4..54243db 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.m +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/AMapNavCommonUtil.m @@ -117,6 +117,15 @@ BOOL stringIsNotEmpty (NSString *str) return ! stringIsEmpty(str); } +/// 字符串转数值 ++(NSString *)stringValueFromStr:(NSString *)str { + if (stringIsEmpty(str)) { + return @""; + } + return str; +} + + #pragma mark - 获取图片 +(UIImage *)imageWithName:(NSString *)name { diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.h new file mode 100644 index 0000000..d7b50e5 --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.h @@ -0,0 +1,20 @@ +// +// UIColor+ANavMap.h +// AMapNavIOSSDK +// +// Created by admin on 2026/4/11. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface UIColor (ANavMap) ++ (UIColor *)hp_colorWithRGBHex:(UInt32)hex; ++ (UIColor *)hp_colorWithRGBHex:(UInt32)hex alpha:(CGFloat)alpha; + +//格式:AHEX ++ (UIColor *)hp_colorWithRGBAHEX:(UInt32)hex; +@end + +NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.m new file mode 100644 index 0000000..099e436 --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIColor+ANavMap.m @@ -0,0 +1,53 @@ +// +// UIColor+ANavMap.m +// AMapNavIOSSDK +// +// Created by admin on 2026/4/11. +// + +#import "UIColor+ANavMap.h" + +@implementation UIColor (ANavMap) + + +//格式:HEX ++ (UIColor *)hp_colorWithRGBHex:(UInt32)hex +{ + CGFloat r = (hex >> 16) & 0xFF; + CGFloat g = (hex >> 8) & 0xFF; + CGFloat b = (hex) & 0xFF; + CGFloat a = 1.0f; + return [UIColor colorWithRed:r / 255.0f + green:g / 255.0f + blue:b / 255.0f + alpha:a]; +} + ++ (UIColor *)hp_colorWithRGBHex:(UInt32)hex alpha:(CGFloat)alpha +{ + CGFloat r = (hex >> 16) & 0xFF; + CGFloat g = (hex >> 8) & 0xFF; + CGFloat b = (hex) & 0xFF; + CGFloat a = alpha; + return [UIColor colorWithRed:r / 255.0f + green:g / 255.0f + blue:b / 255.0f + alpha:a]; +} + + +//格式:AHEX ++ (UIColor *)hp_colorWithRGBAHEX:(UInt32)hex +{ + CGFloat r = (hex >> 24) & 0xFF; + CGFloat g = (hex >> 16) & 0xFF; + CGFloat b = (hex >> 8) & 0xFF; + CGFloat a = (hex) & 0xFF; + return [UIColor colorWithRed:r / 255.0f + green:g / 255.0f + blue:b / 255.0f + alpha:a / 255.0f]; +} + + +@end diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.h new file mode 100644 index 0000000..50d7c0d --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.h @@ -0,0 +1,36 @@ +// +// UIFont+HP.h +// Hippo +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * UIFont 快捷分类 + * 统一使用 PingFang SC 字族,覆盖 Light / Regular / Medium / Semibold 四个字重。 + * + * 使用示例: + * label.font = [UIFont hp_pingFangLight:14]; + * label.font = [UIFont hp_pingFangRegular:16]; + * label.font = [UIFont hp_pingFangMedium:15]; + * label.font = [UIFont hp_pingFangSemibold:18]; + */ +@interface UIFont (HP) + +#pragma mark - PingFang SC Light(细体) ++ (UIFont *)hp_pingFangLight:(CGFloat)size; + +#pragma mark - PingFang SC Regular(常规) ++ (UIFont *)hp_pingFangRegular:(CGFloat)size; + +#pragma mark - PingFang SC Medium(中等) ++ (UIFont *)hp_pingFangMedium:(CGFloat)size; + +#pragma mark - PingFang SC Semibold(半粗) ++ (UIFont *)hp_pingFangSemibold:(CGFloat)size; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.m new file mode 100644 index 0000000..b1458cc --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/Tools/UIFont+HP.m @@ -0,0 +1,45 @@ +// +// UIFont+HP.m +// Hippo +// + +#import "UIFont+HP.h" + +// PingFang SC 字族名称常量 +static NSString * const kHPFontPingFangLight = @"PingFangSC-Light"; +static NSString * const kHPFontPingFangRegular = @"PingFangSC-Regular"; +static NSString * const kHPFontPingFangMedium = @"PingFangSC-Medium"; +static NSString * const kHPFontPingFangSemibold = @"PingFangSC-Semibold"; + +@implementation UIFont (HP) + +#pragma mark - PingFang SC Light(细体) + ++ (UIFont *)hp_pingFangLight:(CGFloat)size { + UIFont *font = [UIFont fontWithName:kHPFontPingFangLight size:size]; + // 若系统不支持该字体,回退到系统字体对应字重 + return font ?: [UIFont systemFontOfSize:size weight:UIFontWeightLight]; +} + +#pragma mark - PingFang SC Regular(常规) + ++ (UIFont *)hp_pingFangRegular:(CGFloat)size { + UIFont *font = [UIFont fontWithName:kHPFontPingFangRegular size:size]; + return font ?: [UIFont systemFontOfSize:size weight:UIFontWeightRegular]; +} + +#pragma mark - PingFang SC Medium(中等) + ++ (UIFont *)hp_pingFangMedium:(CGFloat)size { + UIFont *font = [UIFont fontWithName:kHPFontPingFangMedium size:size]; + return font ?: [UIFont systemFontOfSize:size weight:UIFontWeightMedium]; +} + +#pragma mark - PingFang SC Semibold(半粗) + ++ (UIFont *)hp_pingFangSemibold:(CGFloat)size { + UIFont *font = [UIFont fontWithName:kHPFontPingFangSemibold size:size]; + return font ?: [UIFont systemFontOfSize:size weight:UIFontWeightSemibold]; +} + +@end diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/ABottomBarView.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/ABottomBarView.m index 047e079..728f4fa 100644 --- a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/ABottomBarView.m +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/ABottomBarView.m @@ -163,6 +163,7 @@ static inline UIColor *ABottomBarThemeGreen(void) { self.calRouteButton = btn; CGFloat off_y = AMP_TabbarHeight; + off_y = 0; #ifdef kAMapSDKDebugFlag off_y = 0; #endif @@ -172,7 +173,7 @@ static inline UIColor *ABottomBarThemeGreen(void) { make.left.equalTo(card).offset(16); make.right.equalTo(card).offset(-16); make.height.mas_equalTo(48); - make.bottom.equalTo(card).offset(-40 - off_y); + make.bottom.equalTo(card).offset(-40); }]; } diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.h b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.h new file mode 100644 index 0000000..81d55e7 --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.h @@ -0,0 +1,70 @@ +// +// AStationDetailPopupView.h +// AMapNavIOSSDK +// +// Created by admin on 2026/3/22. +// + +#import +#import "ANavPointModel.h" +#import "AMapNavSDKHeader.h" + +NS_ASSUME_NONNULL_BEGIN + +@class AStationDetailPopupView; + +@protocol AStationDetailPopupViewDelegate + +@optional +/// 点击"开始导航" +- (void)stationDetailPopupViewDidTapStartNavi:(AStationDetailPopupView *)popup; +/// 点击关闭 +- (void)stationDetailPopupViewDidTapClose:(AStationDetailPopupView *)popup; + +@end + +@interface AStationDetailPopupView : UIView + +@property (nonatomic, strong, nullable) ANavPointModel *pointModel; + +/// 预计加氢费用(元),可由外部传入;若 nil 则隐藏 +@property (nonatomic, copy, nullable) NSString *estimatedCost; + +/// 预计时间,如 @"15分钟";若 nil 则隐藏 +@property (nonatomic, copy, nullable) NSString *estimatedTime; + +/// 行驶里程,如 @"23.5公里";若 nil 则隐藏 +@property (nonatomic, copy, nullable) NSString *driveDistance; + +/// 过路费,如 @"30元";若 nil 则隐藏 +@property (nonatomic, copy, nullable) NSString *tollFee; + +/// 营业时间,如 @"00:00-24:00";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *businessHours; + +/// 站点联系人,如 @"陈凯";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *contactName; + +/// 联系方式,如 @"18019187371";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *contactPhone; + +/// 加氢价格,如 @"32元/L";有值显示,无值显示 - +@property (nonatomic, copy, nullable) NSString *hydrogenPrice; + +@property (nonatomic, weak, nullable) id delegate; + +/// 显示弹框动画 +- (void)showInView:(UIView *)parentView; + +/// 隐藏弹框动画 +- (void)hideWithCompletion:(nullable void(^)(void))completion; + +/// 隐藏弹框动画(无 completion) +- (void)hide; + +/// 重置 UI 状态 +- (void)resetUI; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.m b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.m new file mode 100644 index 0000000..8d4ca8c --- /dev/null +++ b/ln_jq_app/ios/AMapNavIOSSDK/AMapNavIOSSDK/Classes/View/AStationDetailPopupView.m @@ -0,0 +1,655 @@ +// +// AStationDetailPopupView.m +// AMapNavIOSSDK +// +// Created by admin on 2026/3/22. +// + +#import "AStationDetailPopupView.h" +#import "AMapNavCommonUtil.h" +#import + +// 主题绿色(开始导航按钮背景) +static inline UIColor *AStationThemeGreen(void) { + return [UIColor colorWithRed:0x1A/255.0 green:0x7C/255.0 blue:0x43/255.0 alpha:1.0]; +} + +@interface AStationDetailPopupView () + +/// 背景蒙层 +@property (nonatomic, strong) UIControl *maskControl; + +/// 弹框卡片容器 +@property (nonatomic, strong) UIView *cardView; + +/// 站点名称 +@property (nonatomic, strong) UILabel *stationNameLabel; + +/// 预计加氢费用(名称右侧) +@property (nonatomic, strong) UIImageView *costIconView; +@property (nonatomic, strong) UILabel *costLabel; + +/// 地址 +@property (nonatomic, strong) UILabel *addressLabel; + +/// 分割线 +@property (nonatomic, strong) UIView *separator; + +/// 预计时间行 +@property (nonatomic, strong) UIImageView *timeIconView; +@property (nonatomic, strong) UILabel *timeLabel; + +/// 行驶里程 +@property (nonatomic, strong) UIImageView *distanceIconView; +@property (nonatomic, strong) UILabel *distanceLabel; + +/// 过路费 +@property (nonatomic, strong) UIImageView *tollIconView; +@property (nonatomic, strong) UILabel *tollLabel; + +/// 关闭按钮 +@property (nonatomic, strong) UIButton *closeButton; + +/// 开始导航按钮 +@property (nonatomic, strong) UIButton *startNaviButton; + +// ── 营业时间 ── +@property (nonatomic, strong) UILabel *businessHoursLabel; + +// ── 站点联系人 ── +@property (nonatomic, strong) UIImageView *contactPersonIconView; +@property (nonatomic, strong) UILabel *contactPersonLabel; + +// ── 加氢价格 ── +@property (nonatomic, strong) UIImageView *priceIconView; +@property (nonatomic, strong) UILabel *priceLabel; + +// ── 联系方式 ── +@property (nonatomic, strong) UIImageView *phoneIconView; +@property (nonatomic, strong) UILabel *phoneLabel; + +/// 卡片 bottom constraint(动画用) +@property (nonatomic, strong) MASConstraint *cardBottomConstraint; + +@end + +@implementation AStationDetailPopupView + +#pragma mark - Init + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + self.backgroundColor = [UIColor clearColor]; + [self _buildUI]; + [self _setupMasonryConstraints]; + [self _updateUI]; + } + return self; +} + +#pragma mark - Public + +- (void)showInView:(UIView *)parentView { + self.alpha = 0; + self.maskControl.alpha = 0; + [parentView addSubview:self]; + [self mas_remakeConstraints:^(MASConstraintMaker *make) { +// make.edges.equalTo(parentView); + make.top.left.right.equalTo(parentView); + make.bottom.equalTo(parentView).offset((-AMP_TabbarSafeBottomMargin - 35)); + }]; + [self _playShowAnimation]; +} + +- (void)hide { + [self hideWithCompletion:nil]; +} + +- (void)hideWithCompletion:(void(^)(void))completion { + [self _playDismissAnimationWithCompletion:^{ + [self removeFromSuperview]; + if (completion) { + completion(); + } + }]; +} + +#pragma mark - Setter Override(弹出前赋值 或 弹出后动态更新) + +- (void)setPointModel:(ANavPointModel *)pointModel { + _pointModel = pointModel; + [self _updateUI]; +} + +- (void)setEstimatedCost:(NSString *)estimatedCost { + _estimatedCost = [estimatedCost copy]; + [self _updateUI]; +} + +- (void)setEstimatedTime:(NSString *)estimatedTime { + _estimatedTime = [estimatedTime copy]; + [self _updateUI]; +} + +- (void)setDriveDistance:(NSString *)driveDistance { + _driveDistance = [driveDistance copy]; + [self _updateUI]; +} + +- (void)setTollFee:(NSString *)tollFee { + _tollFee = [tollFee copy]; + [self _updateUI]; +} + +- (void)setBusinessHours:(NSString *)businessHours { + _businessHours = [businessHours copy]; + [self _updateUI]; +} + +- (void)setContactName:(NSString *)contactName { + _contactName = [contactName copy]; + [self _updateUI]; +} + +- (void)setContactPhone:(NSString *)contactPhone { + _contactPhone = [contactPhone copy]; + [self _updateUI]; +} + +- (void)setHydrogenPrice:(NSString *)hydrogenPrice { + _hydrogenPrice = [hydrogenPrice copy]; + [self _updateUI]; +} + +#pragma mark - Build UI + +/** + 卡片结构: + ┌──────────────────────────────────── [✕] ┐ + │ 站点名称(加粗) 预计加氢费用:--元 │ ← 同行,间距20pt + │ 地址(灰色小字,多行) │ + │ ──────────────────────────────────────── │ + │ [icon] 预计时间:-- 分钟 │ + │ [icon] 行驶里程:-- 公里 [icon] 过路费:-- 元 │ + │ ╔════════════════════════════════════╗ │ + │ ║ 开始导航 ║ │ + │ ╚════════════════════════════════════╝ │ + │ (距底部30pt) │ + └─────────────────────────────────────────┘ +*/ +- (void)_buildUI { + // ── 蒙层 ── + UIControl *mask = [[UIControl alloc] init]; + mask.backgroundColor = [UIColor colorWithWhite:0 alpha:0.35]; + [mask addTarget:self action:@selector(_onMaskTapped) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:mask]; + self.maskControl = mask; + + // ── 卡片 ── + UIView *card = [[UIView alloc] init]; + card.backgroundColor = [UIColor whiteColor]; + card.layer.cornerRadius = 16; + card.layer.masksToBounds = NO; + card.layer.shadowColor = [UIColor blackColor].CGColor; + card.layer.shadowOpacity = 0.15; + card.layer.shadowRadius = 12; + card.layer.shadowOffset = CGSizeMake(0, -4); + [self addSubview:card]; + self.cardView = card; + + // ── 关闭按钮 ── + UIButton *closeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [closeBtn setImage:[AMapNavCommonUtil imageWithName:@"icon_close"] forState:UIControlStateNormal]; + [closeBtn setTitleColor:[UIColor colorWithWhite:0.5 alpha:1] forState:UIControlStateNormal]; + closeBtn.titleLabel.font = [UIFont systemFontOfSize:16]; + [closeBtn addTarget:self action:@selector(_onCloseTapped) forControlEvents:UIControlEventTouchUpInside]; + [card addSubview:closeBtn]; + self.closeButton = closeBtn; + + UIColor *headTextColor = [UIColor hp_colorWithRGBHex:0x1D2129]; + UIFont *headTextFont = [UIFont hp_pingFangMedium:14]; + + // ── 站点名称 ── + UILabel *nameLabel = [[UILabel alloc] init]; + nameLabel.font = [UIFont hp_pingFangMedium:18]; + nameLabel.textColor = headTextColor; + nameLabel.numberOfLines = 2; + nameLabel.minimumScaleFactor = 0.8; + [card addSubview:nameLabel]; + self.stationNameLabel = nameLabel; + + // ── 预计加氢费用(名称右侧,间距20pt) ── + UILabel *costLabel = [[UILabel alloc] init]; + costLabel.font = headTextFont; + costLabel.textColor = headTextColor; + costLabel.numberOfLines = 1; + costLabel.textAlignment = NSTextAlignmentLeft; + [card addSubview:costLabel]; + self.costLabel = costLabel; + + // ── 营业时间(站点名称下方,4pt间距,浅灰色小字) ── + UILabel *bizHoursLabel = [[UILabel alloc] init]; + bizHoursLabel.font = [UIFont hp_pingFangRegular:14]; + bizHoursLabel.textColor = [UIColor hp_colorWithRGBHex:0x1D2129]; + bizHoursLabel.numberOfLines = 1; + [card addSubview:bizHoursLabel]; + self.businessHoursLabel = bizHoursLabel; + + // ── 地址 ── + UILabel *addrLabel = [[UILabel alloc] init]; + addrLabel.font = [UIFont hp_pingFangRegular:14]; + addrLabel.textColor = [UIColor hp_colorWithRGBHex:0x86909C]; + addrLabel.numberOfLines = 2; + [card addSubview:addrLabel]; + self.addressLabel = addrLabel; + + UIImageView *costIcon = [[UIImageView alloc] init]; + costIcon.contentMode = UIViewContentModeScaleAspectFit; + costIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_fuel"]; + [card addSubview:costIcon]; + self.costIconView = costIcon; + + // ── 分割线 ── + UIView *sep = [[UIView alloc] init]; + sep.backgroundColor = [UIColor colorWithWhite:0.88 alpha:1]; + [card addSubview:sep]; + self.separator = sep; + + // ── 预计时间图标 ── + UIImageView *timeIcon = [[UIImageView alloc] init]; + timeIcon.contentMode = UIViewContentModeScaleAspectFit; + timeIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_time"]; + [card addSubview:timeIcon]; + self.timeIconView = timeIcon; + + // ── 预计时间文字 ── + UILabel *timeLabel = [[UILabel alloc] init]; + timeLabel.font = headTextFont; + timeLabel.textColor = headTextColor; + [card addSubview:timeLabel]; + self.timeLabel = timeLabel; + + // ── 行驶里程图标 ── + UIImageView *distIcon = [[UIImageView alloc] init]; + distIcon.contentMode = UIViewContentModeScaleAspectFit; + distIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_mileage"]; + [card addSubview:distIcon]; + self.distanceIconView = distIcon; + + // ── 行驶里程文字 ── + UILabel *distLabel = [[UILabel alloc] init]; + distLabel.font = headTextFont; + distLabel.textColor = headTextColor; + [card addSubview:distLabel]; + self.distanceLabel = distLabel; + + // ── 过路费图标 ── + UIImageView *tollIcon = [[UIImageView alloc] init]; + tollIcon.contentMode = UIViewContentModeScaleAspectFit; + tollIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_toll"]; + [card addSubview:tollIcon]; + self.tollIconView = tollIcon; + + // ── 过路费文字 ── + UILabel *tollLabel = [[UILabel alloc] init]; + tollLabel.font = headTextFont; + tollLabel.textColor = headTextColor; + [card addSubview:tollLabel]; + self.tollLabel = tollLabel; + + // ── 站点联系人图标 & 文字 ── + UIImageView *personIcon = [[UIImageView alloc] init]; + personIcon.contentMode = UIViewContentModeScaleAspectFit; + personIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_person"]; + [card addSubview:personIcon]; + self.contactPersonIconView = personIcon; + + UILabel *personLabel = [[UILabel alloc] init]; + personLabel.font = headTextFont; + personLabel.textColor = headTextColor; + [card addSubview:personLabel]; + self.contactPersonLabel = personLabel; + + // ── 加氢价格图标 & 文字 ── + UIImageView *priceIcon = [[UIImageView alloc] init]; + priceIcon.contentMode = UIViewContentModeScaleAspectFit; + priceIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_price"]; + [card addSubview:priceIcon]; + self.priceIconView = priceIcon; + + UILabel *priceLabel = [[UILabel alloc] init]; + priceLabel.font = headTextFont; + priceLabel.textColor = headTextColor; + [card addSubview:priceLabel]; + self.priceLabel = priceLabel; + + // ── 联系方式图标 & 文字 ── + UIImageView *phoneIcon = [[UIImageView alloc] init]; + phoneIcon.contentMode = UIViewContentModeScaleAspectFit; + phoneIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_phone"]; + [card addSubview:phoneIcon]; + self.phoneIconView = phoneIcon; + + UILabel *phoneLabel = [[UILabel alloc] init]; + phoneLabel.font = headTextFont; + phoneLabel.textColor = headTextColor; + [card addSubview:phoneLabel]; + self.phoneLabel = phoneLabel; + + // ── 开始导航按钮 ── + UIButton *naviBtn = [UIButton buttonWithType:UIButtonTypeCustom]; + [naviBtn setTitle:@"开始导航" forState:UIControlStateNormal]; + [naviBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; + naviBtn.titleLabel.font = [UIFont boldSystemFontOfSize:17]; + naviBtn.backgroundColor = AStationThemeGreen(); + naviBtn.layer.cornerRadius = 24; + [naviBtn addTarget:self action:@selector(_onStartNaviTapped) forControlEvents:UIControlEventTouchUpInside]; + [card addSubview:naviBtn]; + self.startNaviButton = naviBtn; +} + +#pragma mark - Masonry Constraints + +- (void)_setupMasonryConstraints { + UIView *card = self.cardView; + CGFloat iconSize = 16; + + // ── 蒙层:铺满父视图 ── + [self.maskControl mas_makeConstraints:^(MASConstraintMaker *make) { + make.edges.equalTo(self); + }]; + + // ── 卡片:左右各16 ── + [card mas_makeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(0); + make.right.equalTo(self).offset(-0); + make.bottom.equalTo(self).offset(-0); + }]; + + // ── 关闭按钮:右上角 ── + [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(card).offset(8); + make.right.equalTo(card).offset(-15); + make.width.height.mas_equalTo(40); + }]; + + // ── 站点名称 ── + [self.stationNameLabel setContentHuggingPriority:UILayoutPriorityDefaultLow + forAxis:UILayoutConstraintAxisHorizontal]; + [self.stationNameLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(card).offset(25); + make.left.equalTo(card).offset(16); + make.right.equalTo(self.closeButton.mas_left).offset(-12); + }]; + + // ── 营业时间(站点名称下方,10pt间距) ── + [self.businessHoursLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.stationNameLabel.mas_bottom).offset(10); + make.left.equalTo(card).offset(16); + make.right.equalTo(card).offset(-16); + }]; + + // ── 地址(营业时间下方,10pt间距) ── + [self.addressLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.businessHoursLabel.mas_bottom).offset(10); + make.left.equalTo(card).offset(16); + make.right.equalTo(card).offset(-16); + }]; + self.separator.hidden = YES; + + // ── 分割线(地址下方,10pt间距) ── + [self.separator mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.addressLabel.mas_bottom).offset(10); + make.left.equalTo(card).offset(16); + make.right.equalTo(card).offset(-16); + make.height.mas_equalTo(0.5); + }]; + + CGFloat _offset_y = 18; + + // ── 预计时间行(分割线下方,12pt) ── + [self.timeIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.separator.mas_bottom).offset(12); + make.left.equalTo(card).offset(16); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.timeIconView); + make.left.equalTo(self.timeIconView.mas_right).offset(6); + make.height.mas_equalTo(24); + }]; + + /// cost + [self.costIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.timeIconView); + make.left.equalTo(self.timeLabel.mas_right).offset(40); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.costLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.costIconView); + make.left.equalTo(self.costIconView.mas_right).offset(6); + make.right.lessThanOrEqualTo(card).offset(-10); + }]; + + // ── 行驶里程 + 过路费行(时间行下方,12pt) ── + [self.distanceIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.timeIconView.mas_bottom).offset(_offset_y); + make.left.equalTo(card).offset(16); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.distanceLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.distanceIconView); + make.left.equalTo(self.distanceIconView.mas_right).offset(6); + make.width.mas_lessThanOrEqualTo(130); + make.height.mas_equalTo(24); + }]; + + [self.tollIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.distanceIconView); + make.left.equalTo(self.costIconView.mas_left); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.tollLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.distanceIconView); + make.left.equalTo(self.tollIconView.mas_right).offset(6); + make.height.mas_equalTo(24); + }]; + + // ── 站点联系人行(过路费行下方,14pt) ── + [self.contactPersonIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.distanceIconView.mas_bottom).offset(_offset_y); + make.left.equalTo(card).offset(16); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.contactPersonLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contactPersonIconView); + make.left.equalTo(self.contactPersonIconView.mas_right).offset(6); +// make.height.mas_equalTo(24); + make.width.lessThanOrEqualTo(self).multipliedBy(0.4); + }]; + + // ── 加氢价格(与站点联系人同行,右侧对齐 costIconView) ── + [self.priceIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contactPersonIconView); + make.left.equalTo(self.costIconView.mas_left); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.contactPersonIconView); + make.left.equalTo(self.priceIconView.mas_right).offset(6); + make.right.lessThanOrEqualTo(card).offset(-10); + make.height.mas_equalTo(24); + }]; + + // ── 联系方式行(站点联系人行下方,12pt) ── + [self.phoneIconView mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.contactPersonIconView.mas_bottom).offset(_offset_y); + make.left.equalTo(card).offset(16); + make.width.height.mas_equalTo(iconSize); + }]; + + [self.phoneLabel mas_makeConstraints:^(MASConstraintMaker *make) { + make.centerY.equalTo(self.phoneIconView); + make.left.equalTo(self.phoneIconView.mas_right).offset(6); + make.height.mas_equalTo(24); + }]; + + // ── 开始导航按钮(联系方式行下方18pt,距卡片底部 safeArea) ── + [self.startNaviButton mas_makeConstraints:^(MASConstraintMaker *make) { + make.top.equalTo(self.phoneIconView.mas_bottom).offset(40); + make.left.equalTo(card).offset(16); + make.right.equalTo(card).offset(-16); + make.height.mas_equalTo(48); + make.bottom.equalTo(card).offset(-AMP_TabbarSafeBottomMargin); + }]; +} + +#pragma mark - Data Update + +- (void)_updateUI { + self.stationNameLabel.text = (self.pointModel.name.length > 0) + ? self.pointModel.name : @"-"; + + // ── 营业时间 ── + self.businessHoursLabel.text = (self.businessHours.length > 0) + ? [NSString stringWithFormat:@"营业时间:%@", self.businessHours] + : @"营业时间:-"; + + self.costLabel.text = (self.estimatedCost.length > 0) + ? [NSString stringWithFormat:@"预计加氢费用:%@元", self.estimatedCost] + : @"预计加氢费用:-"; + + self.addressLabel.text = (self.pointModel.address.length > 0) + ? self.pointModel.address : @"-"; + + // ── 预计时间(始终显示,无值显示"-- 分钟") ── + self.timeLabel.text = (self.estimatedTime.length > 0) + ? [NSString stringWithFormat:@"预计时间:%@分钟", self.estimatedTime] + : @"预计时间:-"; + + // ── 行驶里程(始终显示,无值显示"-- 公里") ── + self.distanceLabel.text = (self.driveDistance.length > 0) + ? [NSString stringWithFormat:@"行驶里程:%@公里", self.driveDistance] + : @"行驶里程:-"; + + // ── 过路费(始终显示,无值显示"-- 元") ── + self.tollLabel.text = (self.tollFee.length > 0) + ? [NSString stringWithFormat:@"过路费:%@元", self.tollFee] + : @"过路费:-"; + + // ── 站点联系人(有值显示值,无值显示 -) ── + self.contactPersonLabel.text = (self.contactName.length > 0) + ? [NSString stringWithFormat:@"站联系人:%@", self.contactName] + : @"站联系人:-"; + + // ── 加氢价格(有值显示值,无值显示 -) ── + self.priceLabel.text = (self.hydrogenPrice.length > 0) + ? [NSString stringWithFormat:@"加氢价格:%@/L", self.hydrogenPrice] + : @"加氢价格:-"; + + // ── 联系方式(有值显示值,无值显示 -) ── + self.phoneLabel.text = (self.contactPhone.length > 0) + ? [NSString stringWithFormat:@"联系方式:%@", self.contactPhone] + : @"联系方式:-"; +} + +// 重置 UI 状态 +- (void)resetUI { + self.stationNameLabel.text = @"-"; + self.businessHoursLabel.text = @"营业时间:-"; + self.costLabel.text = @"预计加氢费用:-"; + self.addressLabel.text = @"地址:-"; + self.timeLabel.text = @"预计时间:-"; + self.distanceLabel.text = @"行驶里程:-"; + self.tollLabel.text = @"过路费:-"; + self.contactPersonLabel.text = @"站联系人:-"; + self.priceLabel.text = @"加氢价格:-"; + self.phoneLabel.text = @"联系方式:-"; +} + +#pragma mark - Animation + +/** + 弹入动画 +*/ +- (void)_playShowAnimation { + // 初始状态:卡片在屏幕下方(完全隐藏在屏幕外) + [self.cardView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(0); + make.right.equalTo(self).offset(-0); + make.top.equalTo(self.mas_bottom).offset(0); + }]; + + [self layoutIfNeeded]; + + // 目标状态:卡片正常显示 + [self.cardView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(0); + make.right.equalTo(self).offset(-0); + make.bottom.equalTo(self).offset(-AMP_TabbarSafeBottomMargin); + }]; + + [UIView animateWithDuration:0.36 + delay:0 + usingSpringWithDamping:0.82 + initialSpringVelocity:0.5 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + self.alpha = 1; + self.maskControl.alpha = 1; + [self layoutIfNeeded]; + } completion:nil]; +} + +- (void)_playDismissAnimationWithCompletion:(void(^)(void))completion { + [self.cardView mas_remakeConstraints:^(MASConstraintMaker *make) { + make.left.equalTo(self).offset(0); + make.right.equalTo(self).offset(-0); + make.top.equalTo(self.mas_bottom).offset(20); + }]; + + [UIView animateWithDuration:0.25 + delay:0 + options:UIViewAnimationOptionCurveEaseIn + animations:^{ + self.maskControl.alpha = 0; + [self layoutIfNeeded]; + } completion:^(BOOL finished) { + if (completion) completion(); + }]; +} + +#pragma mark - Actions + +- (void)_onMaskTapped { + if ([self.delegate respondsToSelector:@selector(stationDetailPopupViewDidTapClose:)]) { + [self.delegate stationDetailPopupViewDidTapClose:self]; + } + [self hide]; +} + +- (void)_onCloseTapped { + if ([self.delegate respondsToSelector:@selector(stationDetailPopupViewDidTapClose:)]) { + [self.delegate stationDetailPopupViewDidTapClose:self]; + } + [self hide]; +} + +- (void)_onStartNaviTapped { + __weak typeof(self) weakSelf = self; + [self hideWithCompletion:^{ + __strong typeof(weakSelf) strongSelf = weakSelf; + if ([strongSelf.delegate respondsToSelector:@selector(stationDetailPopupViewDidTapStartNavi:)]) { + [strongSelf.delegate stationDetailPopupViewDidTapStartNavi:strongSelf]; + } + }]; +} + +@end