diff --git a/.gitignore b/.gitignore
index c6a900e..6cfa49f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
/unpackage/
.DS_Store
+# xuchao: Playwright 验证产物(截图/控制台日志),不入库
+.playwright-mcp/
diff --git a/App.vue b/App.vue
index 0f2d17b..be65a46 100644
--- a/App.vue
+++ b/App.vue
@@ -37,7 +37,362 @@
@import "uview-ui/index.scss";
@import "./unit/font/index.css";
+ /* xuchao: Minimalist Modern 设计令牌 —— H5 全局 CSS 变量,页面样式统一用 var(--mm-*) 取值 */
+ page {
+ --mm-bg: #FAFAFA;
+ --mm-fg: #0F172A;
+ --mm-muted: #F1F5F9;
+ --mm-muted-fg: #64748B;
+ --mm-accent: #0052FF;
+ --mm-accent-2: #4D7CFF;
+ --mm-card: #FFFFFF;
+ --mm-border: #E2E8F0;
+ --mm-grad: linear-gradient(135deg, #0052FF, #4D7CFF);
+ --mm-grad-h: linear-gradient(to right, #0052FF, #4D7CFF);
+ --mm-shadow-sm: 0 2rpx 6rpx rgba(15, 23, 42, 0.06);
+ --mm-shadow-md: 0 8rpx 16rpx rgba(15, 23, 42, 0.07);
+ --mm-shadow-lg: 0 20rpx 30rpx rgba(15, 23, 42, 0.08);
+ --mm-shadow-accent: 0 8rpx 28rpx rgba(0, 82, 255, 0.25);
+ --mm-radius: 24rpx;
+
+ background: var(--mm-bg);
+ color: var(--mm-fg);
+ font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC",
+ "HarmonyOS Sans SC", "Source Han Sans SC", "Microsoft YaHei", sans-serif;
+ }
+
+ /* xuchao: 页面根容器 —— 该 H5 运行时 uni-view 默认 inline,根视图必须显式 block,
+ 否则内边距/最小高度不生效,子级会顶满屏幕 */
+ .mm-page {
+ display: block;
+ min-height: 100vh;
+ box-sizing: border-box;
+ }
+
+ /* xuchao: mm- 前缀全局工具类 —— 各页面共用,禁止页面内再写一次性渐变/阴影 */
+ /* 签名渐变背景 */
+ .mm-grad {
+ background: var(--mm-grad);
+ }
+
+ /* 渐变文字(标题关键词、价格数字) */
+ .mm-grad-text {
+ background: var(--mm-grad-h);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ }
+
+ /* 标准卡片:白底 + 描边 + 圆角 + 柔和投影 */
+ .mm-card {
+ background: var(--mm-card);
+ border: 2rpx solid var(--mm-border);
+ border-radius: var(--mm-radius);
+ box-shadow: var(--mm-shadow-md);
+ }
+
+ /* 主按钮:渐变底 + 白字 + 蓝色投影,按下有触感反馈 */
+ .mm-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 96rpx;
+ border-radius: var(--mm-radius);
+ background: var(--mm-grad);
+ color: #fff;
+ font-size: 30rpx;
+ font-weight: 500;
+ letter-spacing: 0.02em;
+ box-shadow: var(--mm-shadow-accent);
+ transition: all 0.2s ease-out;
+ }
+
+ .mm-btn:active {
+ transform: scale(0.98);
+ filter: brightness(1.1);
+ }
+
+ /* 次级按钮:描边幽灵态,用于"返回/取消"类操作 */
+ .mm-btn-ghost {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 96rpx;
+ border-radius: var(--mm-radius);
+ border: 2rpx solid var(--mm-border);
+ background: transparent;
+ color: var(--mm-fg);
+ font-size: 30rpx;
+ transition: all 0.2s ease-out;
+ }
+
+ .mm-btn-ghost:active {
+ background: var(--mm-muted);
+ }
+
+ /* 区块标签徽章:小圆点 + 宽字距文字(设计系统的 section label 形态) */
+ .mm-badge {
+ display: inline-flex;
+ align-items: center;
+ border-radius: 999rpx;
+ border: 2rpx solid rgba(0, 82, 255, 0.3);
+ background: rgba(0, 82, 255, 0.05);
+ padding: 10rpx 24rpx;
+ }
+
+ .mm-badge__dot {
+ width: 12rpx;
+ height: 12rpx;
+ border-radius: 50%;
+ background: var(--mm-accent);
+ margin-right: 12rpx;
+ animation: mm-pulse 2s ease-in-out infinite;
+ }
+
+ .mm-badge__text {
+ font-size: 22rpx;
+ letter-spacing: 0.15em;
+ color: var(--mm-accent);
+ }
+
+ /* 区块标题:左侧签名渐变竖条 + 标题文字,各页内容分区统一用它 */
+ .mm-sec-title {
+ display: flex;
+ align-items: center;
+ font-size: 32rpx;
+ font-weight: 600;
+ letter-spacing: -0.01em;
+ color: var(--mm-fg);
+ }
+
+ .mm-sec-title::before {
+ content: '';
+ width: 8rpx;
+ height: 32rpx;
+ border-radius: 4rpx;
+ background: var(--mm-grad);
+ margin-right: 16rpx;
+ }
+
+ /* xuchao: 输入占位符浅灰(设计令牌)—— 配合 placeholder-class="mm-ph" 使用 */
+ .mm-ph {
+ color: #CBD5E1;
+ }
+
+ .mm-ph::placeholder {
+ color: #CBD5E1;
+ opacity: 1;
+ }
+
+ /* 展示字体(本地 YouShe 优设标题黑),大标题与价格数字用 */
+ .mm-display {
+ font-family: "YouShe", "PingFang SC", sans-serif;
+ font-weight: 400;
+ }
+
+ /* 入场动效:上移渐显;配合 .mm-stagger 给子元素逐个延迟 */
+ .mm-fade-up {
+ animation: mm-fade-up 0.7s cubic-bezier(0.16, 1, 0.3, 1) both;
+ }
+
+ .mm-stagger>*:nth-child(1) { animation-delay: 0.05s; }
+ .mm-stagger>*:nth-child(2) { animation-delay: 0.12s; }
+ .mm-stagger>*:nth-child(3) { animation-delay: 0.19s; }
+ .mm-stagger>*:nth-child(4) { animation-delay: 0.26s; }
+ .mm-stagger>*:nth-child(5) { animation-delay: 0.33s; }
+ .mm-stagger>*:nth-child(6) { animation-delay: 0.4s; }
+ .mm-stagger>*:nth-child(7) { animation-delay: 0.47s; }
+ .mm-stagger>*:nth-child(n+8) { animation-delay: 0.54s; }
+
+ @keyframes mm-fade-up {
+ from {
+ opacity: 0;
+ transform: translateY(40rpx);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ /* 脉动圆点:徽章"进行中"指示 */
+ @keyframes mm-pulse {
+
+ 0%,
+ 100% {
+ transform: scale(1);
+ opacity: 1;
+ }
+
+ 50% {
+ transform: scale(1.3);
+ opacity: 0.7;
+ }
+ }
+
+ /* 底部安全区(iPhone X 系列全面屏) */
+ .mm-safe-bottom {
+ padding-bottom: constant(safe-area-inset-bottom);
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+
+ /* 用户偏好减少动效时,关闭所有装饰性动画 */
+ @media (prefers-reduced-motion: reduce) {
+
+ .mm-fade-up,
+ .mm-badge__dot {
+ animation: none !important;
+ }
+
+ .mm-btn,
+ .mm-btn-ghost {
+ transition: none !important;
+ }
+ }
+
/* #ifdef H5 */
+ // xuchao: 该 H5 运行时 uni-view 默认 inline(标准 uni-app 为 block),
+ // 无 display 声明的样式容器会退化为行内:内边距/外边距/高/文本对齐全部失效。
+ // 全局恢复 block,与标准 uni-app H5 行为一致。
+ uni-view,
+ uni-scroll-view {
+ display: block;
+ }
+
+ // xuchao: 该 H5 运行时还缺 scroll-view 内置滚动样式 —— 内层 .uni-scroll-view 无 overflow
+ // 声明且高度被内容撑开,所有 scroll-view 都不能滚(弹窗里滑动会穿透去滚背后页面)。
+ // 补齐:外层裁切、内层承担滚动;overscroll-behavior 防止滚到边缘后链式滚动背景页。
+ uni-scroll-view {
+ overflow: hidden;
+ }
+
+ uni-scroll-view .uni-scroll-view {
+ height: 100%;
+ overflow-x: hidden;
+ overflow-y: auto;
+ overscroll-behavior: contain;
+ -webkit-overflow-scrolling: touch;
+ }
+
+ // xuchao: 横向 scroll-view(带 scroll-x 属性)改为横向滚动、内容不换行
+ uni-scroll-view[scroll-x] .uni-scroll-view {
+ height: auto;
+ overflow-x: auto;
+ overflow-y: hidden;
+ white-space: nowrap;
+ }
+
+ // xuchao: 该 H5 运行时缺 uni-swiper 内置样式 —— 宿主元素 inline,组件内联写入的
+ // height 不生效,整个轮播塌成 0(详情页头图不显示)。按标准 uni-app H5 补齐:
+ // 宿主 block 定高裁切,wrapper 铺满,slides 绝对定位(其 inset:0 为内联样式)。
+ uni-swiper {
+ display: block;
+ position: relative;
+ width: 100%;
+ height: 150px;
+ overflow: hidden;
+ }
+
+ uni-swiper .uni-swiper-wrapper {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ }
+
+ uni-swiper .uni-swiper-slides {
+ position: absolute;
+ }
+
+ // xuchao: 该 H5 运行时缺 uni-toast 内置样式 —— 提示以文档流内联渲染(透明底黑字、
+ // 掉到页面底部视口外),等同不可见。恢复标准 uni-app H5 形态:全屏 fixed 居中 + 深色胶囊。
+ uni-toast {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ pointer-events: none;
+ }
+
+ .uni-sample-toast {
+ max-width: 70%;
+ padding: 20rpx 36rpx;
+ border-radius: 16rpx;
+ background: rgba(15, 23, 42, 0.82);
+ color: #fff;
+ font-size: 28rpx;
+ line-height: 1.5;
+ text-align: center;
+ word-break: break-all;
+ }
+
+ // xuchao: 该 H5 运行时缺少 uni-app 内置的 input 基础样式(输入框退化为浏览器默认带框小输入条),
+ // 按标准 uni-app H5 补齐:wrapper 撑满、真实 input 绝对定位铺满去边框、占位符绝对定位叠在上方。
+ uni-input,
+ uni-textarea {
+ display: block;
+ position: relative;
+ }
+
+ .uni-input-wrapper,
+ .uni-textarea-wrapper {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ }
+
+ .uni-input-input,
+ .uni-textarea-input {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ border: none;
+ outline: none;
+ background: transparent;
+ border-radius: 0;
+ font: inherit;
+ color: inherit;
+ -webkit-appearance: none;
+ appearance: none;
+ }
+
+ .uni-input-placeholder,
+ .uni-textarea-placeholder {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ pointer-events: none;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ /* xuchao: 占位符统一浅灰(设计令牌) */
+ color: #CBD5E1;
+ }
+
+ // xuchao: 模板里的原生 input/textarea 同样剥掉浏览器默认边框
+ input,
+ textarea {
+ border: none;
+ outline: none;
+ background: transparent;
+ border-radius: 0;
+ font: inherit;
+ color: inherit;
+ -webkit-appearance: none;
+ appearance: none;
+ }
+
// xuchao: 修复 uni-image 内部填充元素宽高为 0 导致图片不显示/溢出
uni-image {
display: inline-block;
@@ -60,8 +415,9 @@
// xuchao: 宽屏(>768px,框架此时把 rpx 基准锁在 375)下,把页面列居中、两侧露出底色
@media screen and (min-width: 769px) {
body {
- // xuchao: 页面级 page 背景会染到 body,需 !important 才能露出两侧底色
- background: #dfe4ea !important;
+ // xuchao: 页面级 page 背景会染到 body,需 !important 才能露出两侧底色;
+ // 底色取设计系统描边色,与 #FAFAFA 页面形成柔和层次
+ background: #E2E8F0 !important;
}
uni-page-body {
@@ -74,7 +430,7 @@
margin: 0 auto !important;
min-height: 100vh;
overflow-x: hidden;
- box-shadow: 0 0 24px rgba(31, 45, 61, 0.14);
+ box-shadow: 0 0 24px rgba(15, 23, 42, 0.14);
}
}
/* #endif */
diff --git a/back.png b/back.png
new file mode 100644
index 0000000..da91dc4
Binary files /dev/null and b/back.png differ
diff --git a/components/gmy-back-touch/gmy-back-touch.vue b/components/gmy-back-touch/gmy-back-touch.vue
new file mode 100644
index 0000000..8d1d544
--- /dev/null
+++ b/components/gmy-back-touch/gmy-back-touch.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/gmy-float-touch/gmy-float-touch.vue b/components/gmy-float-touch/gmy-float-touch.vue
index 2f91518..5e5800d 100644
--- a/components/gmy-float-touch/gmy-float-touch.vue
+++ b/components/gmy-float-touch/gmy-float-touch.vue
@@ -1,21 +1,17 @@
-
-
-
+
+
+
+
+
diff --git a/pages/index/authorization.vue b/pages/index/authorization.vue
index f8413cd..908a1b7 100644
--- a/pages/index/authorization.vue
+++ b/pages/index/authorization.vue
@@ -1,27 +1,38 @@
-
-
- 质惠游
+
+
+
+
+
+ 质惠游
+
- 开发模式:输入测试手机号直接登录
+ 开发模式:输入测试手机号直接登录
-
-
-
-
-
-
- {{tips}}
-
+
+
+
+
+
+
+
+
+
+
+ {{tips}}
+
-
+ 立即登录
-
-
- 我已阅读并同意用户服务协议
-
+
+
+ 我已阅读并同意用户服务协议
+
+
-
+
diff --git a/pages/ticket/orderdetail.vue b/pages/ticket/orderdetail.vue
index c88c36d..0dc15bc 100644
--- a/pages/ticket/orderdetail.vue
+++ b/pages/ticket/orderdetail.vue
@@ -1,192 +1,150 @@
-
-
-
- {{orderStatus}}
-
-
- ¥
- {{(obj.order.orderAmount/100).toFixed(2)}}
-
+
+
+
+
+
+ {{orderStatus}}
+
+ ¥
+ {{(obj.order.orderAmount/100).toFixed(2)}}
- {{orderTitle}}
+ {{orderTitle}}
-
- 商品信息
-
- {{ticketName}}
-
+
+
+
+ 商品信息
+
+ {{ticketName}}
-
- 票型类型
-
- 【{{getSkuType(obj.sku.typeId)}}】 {{obj.sku.skuName}}
+
+ 票型类型
+ 【{{getSkuType(obj.sku.typeId)}}】 {{obj.sku.skuName}}
-
-
- 使用日期
- {{obj.orderGoods.bookDate}}
+ 使用日期
+ {{obj.orderGoods.bookDate}} ({{obj.orderGoods.timeSlot}})
-
- 生效时间
- 出票后立即生效
+
+ 生效时间
+ 出票后立即生效
-
-
- 入园凭证
-
-
- 凭证码
-
- {{item.qrCode}}
- 复制
-
-
+
+
+
+ 入园凭证
+
+
+ 凭证码
+
+ {{item.qrCode}}
+ 复制
+
+
-
-
-
-
-
-
- 入园方式
-
- {{obj.sku.enterChangeFlag?'凭('+getTyepStr(obj.sku.enterType)+')换票入园':'无需换票'}}
-
-
-
-
- 换票时间
-
- {{obj.sku.changeStart}}~{{obj.sku.changeEnd}}
-
-
-
-
- 换票地点
- {{obj.sku.changePostion}}
-
-
-
- 入园时间
- {{obj.sku.enterStart}}~{{obj.sku.enterEnd}}
-
-
-
-
- 入园地点
- {{obj.sku.enterPostion}}
-
-
-
- 门票
-
- ¥{{(obj.orderGoods.skuPrice/100).toFixed(2)}} x {{obj.order.buyNum}}
-
-
-
- 取消政策
-
- {{obj.sku.refundType==1?'随时退':obj.sku.refundType==2?'有条件退':obj.sku.refundType==3?'不可退款':''}}
-
-
-
-
-
- 订单信息
-
-
- 出行人
- {{item.name}}
- {{item.phone}}
-
{{item.identityNo}}
-
-
-
- 联系人
- {{obj.order.orderContactName}}
-
-
- 手机号
- {{obj.order.orderContactMobile}}
-
-
- 订单编号
- {{obj.order.id}}
- 复制
+
-
- 支付时间
-
- {{obj.payment.createdTime||''}}
-
+
+ 入园方式
+ {{obj.sku.enterChangeFlag?'凭('+getTyepStr(obj.sku.enterType)+')换票入园':'无需换票'}}
+
+
+ 换票时间
+ {{obj.sku.changeStart}}~{{obj.sku.changeEnd}}
+
+
+ 换票地点
+ {{obj.sku.changePostion}}
+
+
+ 入园时间
+ {{obj.sku.enterStart}}~{{obj.sku.enterEnd}}
+
+
+ 入园地点
+ {{obj.sku.enterPostion}}
+
+
+ 门票
+ ¥{{(obj.orderGoods.skuPrice/100).toFixed(2)}} x {{obj.order.buyNum}}
+
+
+
+ 取消政策
+
+ {{obj.sku.refundType==1?'随时退':obj.sku.refundType==2?'有条件退':obj.sku.refundType==3?'不可退款':''}}
+
-
-
-
- 去支付
- 取消订单
-
- 重新购买
-
- 申请退款
+
+
+ 订单信息
+
+
+ 出行人
+ {{item.name}} {{item.phone}} {{item.identityNo}}
+
+
+
+ 联系人
+ {{obj.order.orderContactName}}
+
+
+ 手机号
+ {{obj.order.orderContactMobile}}
+
+
+ 订单编号
+ {{obj.order.id}}
+ 复制
+
+
+ 支付时间
+ {{obj.payment.createdTime||''}}
+
-
-
- 取消政策
+
+
+
+
+ 申请退款
+ 重新购买
+ 取消订单
+ 去支付
+
-
-
-
-
- 确定
-
+
+
+
+ 取消政策
+
+ 确定
-
-
-
- 请选择游客
-
- {{item.name}}
+
+
+
+ 请选择游客
+
+ {{item.name}}
-
- 确定
+ 确定
@@ -200,7 +158,11 @@
import {
getSkuType
} from '../../unit/utils.js'
+ import gmyBackTouch from "@/components/gmy-back-touch/gmy-back-touch.vue"
export default {
+ components: {
+ 'gmy-back-touch': gmyBackTouch
+ },
data() {
return {
enterTypeList: [{
@@ -228,7 +190,7 @@
label: '6'
},
{
- value: "台湾居民来往大陆通行证",
+ value: "台湾居民来往内地通行证",
label: '7'
}
],
@@ -294,6 +256,16 @@
}
return str
+ },
+ // xuchao: 待支付状态用主题蓝强调
+ isWaitPay() {
+ return this.obj && this.obj.order.orderStatus == 'WAITPAY'
+ },
+ // xuchao: 是否存在底部操作按钮(决定操作栏与占位是否渲染)
+ hasActs() {
+ if (!this.obj) return false
+ const s = this.obj.order.orderStatus
+ return s == 'WAITPAY' || s == 'HAVESEND' || s == 'COMPLETED' || s == 'BACKPAYED'
}
},
onLoad(e) {
@@ -341,7 +313,7 @@
},
refund() {
- //
+ //
this.show = true
},
sure() {
@@ -410,114 +382,313 @@
}
}
-
+
\ No newline at end of file
+
+ /* ---------- 取消政策入口 ---------- */
+ .policy {
+ display: flex;
+ align-items: center;
+ height: 96rpx;
+ position: relative;
+ }
+
+ .policy__label {
+ font-size: 28rpx;
+ font-weight: 600;
+ color: var(--mm-fg);
+ margin-right: 12rpx;
+ }
+
+ .policy__val {
+ margin-left: 12rpx;
+ font-size: 26rpx;
+ color: var(--mm-muted-fg);
+ }
+
+ .policy__arrow {
+ position: absolute;
+ right: 0;
+ }
+
+ /* ---------- 底部操作栏 ---------- */
+ .safe {
+ height: 160rpx;
+ }
+
+ .bar {
+ position: fixed;
+ left: 0;
+ right: 0;
+ margin: 0 auto;
+ width: 750rpx;
+ bottom: 0;
+ z-index: 99;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 20rpx;
+ background: var(--mm-card);
+ border-top: 2rpx solid var(--mm-border);
+ padding: 20rpx 24rpx;
+ /* xuchao: 全面屏底部安全区 */
+ padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
+ padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+ }
+
+ .bar__main {
+ height: 72rpx;
+ padding: 0 40rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999rpx;
+ color: #fff;
+ font-size: 28rpx;
+ font-weight: 600;
+ box-shadow: var(--mm-shadow-accent);
+ transition: transform 0.15s ease;
+ }
+
+ .bar__main:active {
+ transform: scale(0.96);
+ }
+
+ .bar__ghost {
+ height: 72rpx;
+ padding: 0 32rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999rpx;
+ border: 2rpx solid var(--mm-border);
+ color: var(--mm-fg);
+ font-size: 28rpx;
+ transition: background 0.15s ease;
+ }
+
+ .bar__ghost:active {
+ background: var(--mm-muted);
+ }
+
+ /* ---------- 弹层 ---------- */
+ .pp {
+ padding: 48rpx;
+ display: flex;
+ flex-direction: column;
+ }
+
+ .pp__parse {
+ margin-top: 24rpx;
+ font-size: 26rpx;
+ line-height: 1.7;
+ color: var(--mm-fg);
+ }
+
+ .pp__btn {
+ margin-top: 48rpx;
+ }
+
+ .pp__center-title {
+ text-align: center;
+ font-size: 30rpx;
+ font-weight: 600;
+ color: var(--mm-fg);
+ margin-bottom: 24rpx;
+ }
+
diff --git a/pages/ticket/orderlist.vue b/pages/ticket/orderlist.vue
index 645b744..2d86ff7 100644
--- a/pages/ticket/orderlist.vue
+++ b/pages/ticket/orderlist.vue
@@ -1,38 +1,67 @@
-
-
-
- 订单编号:{{item.id}}
- {{getText(item.orderStatus,1)}}
+
+
+
+
+
+
+ 门票订单
-
- {{item.skuName}}
-
- 使用日期:{{item.orderDate}}
- ¥{{(item.orderAmount/100).toFixed(2)}}
+
+
+
+
+
+
+ 订单编号:{{item.id}}
+ {{getText(item.orderStatus,1)}}
+
+
+ {{item.skuName}}
+
-
+
+
+
+
+ 暂无相关订单
+
+
+
-
-
\ No newline at end of file
diff --git a/pages/ticket/ordersure.vue b/pages/ticket/ordersure.vue
index ae4253d..014f12f 100644
--- a/pages/ticket/ordersure.vue
+++ b/pages/ticket/ordersure.vue
@@ -1,151 +1,137 @@
-
-
-
-
- 总价
-
- ¥{{salesPriceSum}}
+
+
+
+
+ {{skuObj.sku.skuName}}
+ 适用年龄:{{skuObj.sku.typeInfo}}
-
- 明细
-
-
+
- 立即购买
-
-
-
-
- {{skuObj.sku.skuName}}
-
- 适用年龄:{{skuObj.sku.typeInfo}}
-
-
-
- 使用日期
-
-
-
-
+ 使用日期
+
+ :class="['date', item.isSelect?'date--on':'', (!item.isEnabled&&!item.isSelect)?'date--off':'']"
+ @click="selectDate(item)">
{{getDayName(item.enableDate)}}
{{formatToMonthDay(item.enableDate)}}
- {{item.isSelect?'√':item.isEnabled?'可订':'不可订'}}
+ {{item.isSelect?'√':item.isEnabled?'可订':'不可订'}}
-
- 更多
- 日期
-
+ 更多
日期
+
-
- 适用时段
-
- {{item.name}}
- 余{{item.stock}}张
-
-
-
-
-
-
- 购买数量
-
-
-
-
-
-
-
-
- 游客信息
-
- 需要 {{value}}位 出行游客信息,用于入园身份验证
-
-
-
-
-
-
- {{item.name}}
- 新增/更换 >
-
-
-
-
- 游客{{index+1}}
-
-
-
-
-
-
- 联系手机
- {{createInfo.mobile}}
-
-
-
-
-
- 联系人信息
-
-
-
-
-
- 联系人
-
-
-
- 手机号
- {{createInfo.mobile}}
-
-
-
-
-
-
-
-
-
- 费用明细
- 景区/场馆
-
-
- 门票
- ¥{{salesPrice}}
- x{{value}}
-
-
- 总价¥{{salesPriceSum}}
+
+ 适用时段
+
+ {{item.name}}
+ 余{{item.stock}}张
-
-
- 确定
+
+
+
+
+
+
+ 购买数量
+
+
+
+
+ {{value}}
+
+
+
+
+
+
+
+
+
+
+ 游客信息
+ 需要 {{value}}位 出行游客信息,用于入园身份验证
+
+
+
+ {{item.name}}
+ 新增/更换
+
+
+
+
+
+ 游客{{index+1}}
+
+ {{item.name}}
+ {{item.identityNo}}
+
+
+
+
+ 联系手机
+ {{createInfo.mobile}}
+
+
+
+
+
+ 联系人信息
+
+ 联系人
+
+
+
+ 手机号
+ {{createInfo.mobile}}
+
+
+
+
+
+
+
+
+
+ 总价
+
+ ¥
+ {{salesPriceSum}}
+ 明细
+
+
+
+
+ 立即购买
+
+
+
+
+
+ 费用明细
+ 景区/场馆
+
+ 门票
+ ¥{{salesPrice}} x{{value}}
+
+
+ 总价
+
+ ¥
+ {{salesPriceSum}}
+
+
+ 确定
+
-
-
@@ -154,7 +140,11 @@
import pay from '@/common/pay.js'
var that = ''
+ import gmyBackTouch from "@/components/gmy-back-touch/gmy-back-touch.vue"
export default {
+ components: {
+ 'gmy-back-touch': gmyBackTouch
+ },
data() {
return {
show1: false,
@@ -167,7 +157,6 @@
whday: '',
skuObj: '',
calendarList: [],
- windowHeight: '',
mobile: '',
personList: [],
objInfo: '',
@@ -230,11 +219,11 @@
cList() {
let arr = []
-
+
console.log(this.calendarList,12312);
if (this.calendarList.length != 0) {
this.calendarList.forEach((item, index) => {
-
+
if (item.isSelect && index < 3) {
if(this.calendarList.length==1){
arr.push(this.calendarList[0])
@@ -246,7 +235,7 @@
arr.push(this.calendarList[1])
arr.push(this.calendarList[2])
}
-
+
} else if (item.isSelect && index >= 3) {
arr.push(this.calendarList[0])
arr.push(this.calendarList[1])
@@ -282,11 +271,6 @@
},
onLoad() {
that = this
- uni.getSystemInfo({
- success: function(res) {
- that.windowHeight = res.windowHeight
- }
- });
this.createInfo.mobile = uni.getStorageSync('phone')
this.createInfo.contactMobile = uni.getStorageSync('phone')
this.skuObj = uni.getStorageSync('scenicDetail')
@@ -414,8 +398,20 @@
const day = date.getDate().toString().padStart(2, '0');
return `${month}月${day}日`;
},
- valChange(e) {
- console.log('当前值为: ' + e.value)
+ // xuchao: 数量步进 —— 减到下限 1 为止,加到当前库存上限并提示
+ minusNum() {
+ if (this.value > 1) this.value--
+ },
+ plusNum() {
+ if (this.value < this.getMaxStock()) {
+ this.value++
+ } else {
+ uni.showToast({
+ icon: 'none',
+ title: '库存不足了',
+ duration: 1500
+ })
+ }
},
change(e) {
this.calendarList.forEach((item, index) => {
@@ -446,6 +442,15 @@
});
return
}
+ // xuchao: 出行人多于购买数量也拦截(如先选多人后减量),提示移除多余位
+ if (this.personList.length > this.value) {
+ uni.showToast({
+ icon: 'none',
+ title: '只需' + this.value + '位出行人,请移除多余' + (this.personList.length - this.value) + '位',
+ duration: 2000
+ });
+ return
+ }
} else {
if (this.createInfo.contactName == '') {
uni.showToast({
@@ -532,204 +537,451 @@
}
}
-
-
\ No newline at end of file
diff --git a/pages/ticket/paysuccess.vue b/pages/ticket/paysuccess.vue
index 05cde25..df73422 100644
--- a/pages/ticket/paysuccess.vue
+++ b/pages/ticket/paysuccess.vue
@@ -1,31 +1,36 @@
-
-
-
- 支付成功
+
+
+
+
+
+
+ 支付成功
+ 门票订单已提交,请留意出票通知
-
-
-
-
-
-
- 支付方式:微信支付
- 实付金额:¥{{(obj.order.orderAmount/100).toFixed(2)||0}}
+
+
+
+
+ 支付方式
+ 微信支付
+
+
+ 实付金额
+
+ ¥
+ {{(obj.order.orderAmount/100).toFixed(2)||0}}
-
-
-
-
- 查看订单
-
- 继续逛逛
-
-
+
+
+
+ 查看订单
+ 继续逛逛
+
+
@@ -33,7 +38,11 @@
-
-
diff --git a/pages/ticket/person.vue b/pages/ticket/person.vue
index e980b14..8d9fd7d 100644
--- a/pages/ticket/person.vue
+++ b/pages/ticket/person.vue
@@ -1,35 +1,40 @@
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
- 完成
+
+
+
+
+
+ 完成
+
+
\ No newline at end of file
+
+ .card {
+ padding: 12rpx 32rpx;
+ }
+
+ /* xuchao: 底部固定按钮 —— left/right 0 + margin auto 保证宽屏居中时与页面列对齐 */
+ .bar {
+ position: fixed;
+ left: 0;
+ right: 0;
+ margin: 0 auto;
+ width: 686rpx;
+ bottom: calc(32rpx + constant(safe-area-inset-bottom));
+ bottom: calc(32rpx + env(safe-area-inset-bottom));
+ z-index: 99;
+ }
+
diff --git a/pages/ticket/scenic.vue b/pages/ticket/scenic.vue
index 719e8aa..965e9bd 100644
--- a/pages/ticket/scenic.vue
+++ b/pages/ticket/scenic.vue
@@ -1,22 +1,46 @@
-
-
-
-
- {{item.name||''}}
-
- {{item1}}
+
+
+
+
+
+
+ {{item.name||''}}
+ {{item.subTypeId}}
+
- {{item.subTypeId}}
- 原售价{{(item.price/100).toFixed(0)}}元
- 会员补贴价¥{{(item.unitPrice/100).toFixed(0)}}元
+
+
+
+
+ 暂无在售门票产品
+
+
+
+
+
-
+
@@ -30,10 +54,11 @@
components: { gmyFloatTouch },
data() {
return {
- mainImg: "../../static/logo4.png",
pageAll: 2,
isLoad: true,
lookList: [],
+ // xuchao: 首次请求是否已返回,用于区分"加载中"与"真没数据"
+ firstLoaded: false,
obj: {
"name": "",
"typeId": "",
@@ -44,6 +69,11 @@
}
}
},
+ computed: {
+ showEmpty() {
+ return this.firstLoaded && this.lookList.length === 0
+ }
+ },
onLoad() {
that = this
// xuchao: 未登录则(正式)跳登录页 / (开发)静默假登录
@@ -59,8 +89,10 @@
this.isLoad = false
this.$u.api.queryTicketsPage(this.obj).then(res => {
this.isLoad = true
+ this.firstLoaded = true
this.obj.pageNum = this.obj.pageNum * 1 + 1
this.pageAll = Math.ceil(res.data.total / 10)
+ this.total = res.data.total
this.lookList = this.lookList.concat(res.data.list)
})
}
@@ -82,209 +114,143 @@
}
-
diff --git a/pages/ticket/scenicdetail.vue b/pages/ticket/scenicdetail.vue
index e49cf94..3455d53 100644
--- a/pages/ticket/scenicdetail.vue
+++ b/pages/ticket/scenicdetail.vue
@@ -1,159 +1,151 @@
-
-
-
+
+
+
+
+
+
+
+
+ {{obj.tickets.name}}
+ {{obj.shop.level}}
+
+ {{obj.tickets.remark1}}
+
+
+
+
+ 开园时间
+ {{obj.tickets.openDate}}
+
+
+
+
+ {{obj.shop.address}}
+
+
+
+
+
+
+
+
+
-
-
- {{obj.tickets.name}} {{obj.shop.level}}
- {{obj.tickets.remark1}}
-
-
- 开园时间
-
- {{obj.tickets.openDate}}
-
-
-
- {{obj.shop.address}}
-
-
-
-
-
-
-
-
-
-
- 【{{getSkuType(item.typeId)}}】{{item.skuName}}
-
- {{item.bookTimeLimit}}之前{{item.bookType?'可订当天':'可订明日'}}·
+
+
+ 门票规格
+
+
+ 【{{getSkuType(item.typeId)}}】{{item.skuName}}
+
+
+ {{item.bookTimeLimit}}之前{{item.bookType?'可订当天':'可订次日'}}
+
+ 预订须知
+
- 预订须知 >
-
-
- 原售价¥{{item.calendar.listPrice?(item.calendar.listPrice/100).toFixed(2):0}}
-
-
-
+
+ 原售价 ¥{{item.calendar.listPrice?(item.calendar.listPrice/100).toFixed(2):0}}
+
+ ¥
工会会员补贴价¥{{item.calendar.salePrice?(item.calendar.salePrice/100).toFixed(2):0}}
+ class="sku__price-num mm-display mm-grad-text">{{item.calendar.salePrice?(item.calendar.salePrice/100).toFixed(2):0}}
- 购买
+ 购买
-
- 产品介绍
+
+
+
+
+ 产品介绍
+
-
-
-
- {{skuObj.sku.skuName}}
-
-
- 预订规则
-
- 预订时间
-
- {{skuObj.sku.bookTimeLimit}}之前{{skuObj.sku.bookType?'可订当天':'可订明日'}}
-
+
+
+
+
+ {{skuObj.sku.skuName}}
+
+
+ 预订规则
+
+ 预订时间
+ {{skuObj.sku.bookTimeLimit}}之前{{skuObj.sku.bookType?'可订当天':'可订次日'}}
-
- 生效时间
- 出票后立即使用
+
+ 生效时间
+ 出票后立即使用
-
- 有效期
- 指定出行日期1天内有效
+
+ 有效期
+ 指定出行日期1天内有效
-
- 适用人群
- {{skuObj.sku.typeInfo}}
+
+ 适用人群
+ {{skuObj.sku.typeInfo}}
-
- 费用说明
-
- 费用包含
- {{skuObj.sku.contentWith}}
+
+ 费用说明
+
+ 费用包含
+ {{skuObj.sku.contentWith}}
-
- 费用不含
- {{skuObj.sku.contentWithout}}
-
-
-
-
-
-
- 使用说明
-
- 入园方式
-
- {{skuObj.sku.enterChangeFlag?'凭('+getTyepStr(skuObj.sku.enterType)+')换票入园':'无需换票'}}
-
-
-
- 换票时间
-
- {{skuObj.sku.changeStart}}~{{skuObj.sku.changeEnd}}
-
-
-
- 换票地点
- {{skuObj.sku.changePostion}}
-
-
- 入园时间
-
- {{skuObj.sku.enterStart}}~{{skuObj.sku.enterEnd}}
-
-
-
- 入园地址
- {{skuObj.sku.enterPostion}}
+
+ 费用不含
+ {{skuObj.sku.contentWithout}}
-
-
- 取消政策
-
+
+ 使用说明
+
+ 入园方式
+ {{skuObj.sku.enterChangeFlag?'凭('+getTyepStr(skuObj.sku.enterType)+')换票入园':'无需换票'}}
+
+
+ 换票时间
+ {{skuObj.sku.changeStart}}~{{skuObj.sku.changeEnd}}
+
+
+ 换票地点
+ {{skuObj.sku.changePostion}}
+
+
+ 入园时间
+ {{skuObj.sku.enterStart}}~{{skuObj.sku.enterEnd}}
+
+
+ 入园地址
+ {{skuObj.sku.enterPostion}}
+
+
+ 取消政策
+
+
-
- 其他说明
-
- 补充说明
- {{skuObj.sku.remark}}
+
+ 其他说明
+
+ 补充说明
+ {{skuObj.sku.remark}}
-
- 发票说明
- {{skuObj.sku.receiptPolicy}}
+
+ 发票说明
+ {{skuObj.sku.receiptPolicy}}
-
@@ -165,7 +157,11 @@
import {
getSkuType
} from '../../unit/utils.js'
+ import gmyBackTouch from "@/components/gmy-back-touch/gmy-back-touch.vue"
export default {
+ components: {
+ 'gmy-back-touch': gmyBackTouch
+ },
data() {
return {
show: false,
@@ -267,11 +263,20 @@
id: e
}).then(res => {
if (res) {
+ // xuchao: 头图首张放单票主图(与列表卡片一致),再拼宣传图,跳过与主图重复项
+ const mainPic = res.data.tickets.mainPic
+ if (mainPic) {
+ this.list.push({
+ image: mainPic
+ })
+ }
if (res.data.tickets.propagatePic) {
res.data.tickets.propagatePic.split(',').forEach((item, index) => {
- this.list.push({
- image: item
- })
+ if (item && item !== mainPic) {
+ this.list.push({
+ image: item
+ })
+ }
})
}
@@ -297,103 +302,292 @@
},
};
-
-
\ No newline at end of file
diff --git a/pages/ticket/select.vue b/pages/ticket/select.vue
index 1207ae3..1fa8ffb 100644
--- a/pages/ticket/select.vue
+++ b/pages/ticket/select.vue
@@ -1,27 +1,54 @@
-
- 需添加 {{value}} 个出行人
-
- 新增出行人
- +
-
-
-
- {{item.name}}
- {{item.identityNo}}
-
-
+
+
+
+
+
+
+ 需添加 {{value}} 个出行人(已选 {{selectedCount}})
-
- 完成
-
+
+
+
+
+
+
+ 新增出行人
+
+
+
+
+
+
+ {{(item.name||'').charAt(0)}}
+
+ {{item.name}}
+ {{item.identityNo}}
+
+
+
+
+
+
+
+
+
+
+
+
+ 完成
+
\ No newline at end of file
+
+ .add__text {
+ flex: 1;
+ margin-left: 20rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ color: var(--mm-accent);
+ }
+
+ .list {
+ margin-top: 24rpx;
+ display: flex;
+ flex-direction: column;
+ gap: 20rpx;
+ }
+
+ .person {
+ display: flex;
+ align-items: center;
+ padding: 28rpx 24rpx;
+ transition: transform 0.15s ease;
+ }
+
+ .person:active {
+ transform: scale(0.985);
+ }
+
+ .person__avatar {
+ flex: none;
+ width: 80rpx;
+ height: 80rpx;
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: #fff;
+ font-size: 32rpx;
+ font-weight: 600;
+ box-shadow: var(--mm-shadow-accent);
+ }
+
+ .person__info {
+ flex: 1;
+ min-width: 0;
+ margin-left: 20rpx;
+ }
+
+ .person__name {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: var(--mm-fg);
+ }
+
+ .person__id {
+ margin-top: 6rpx;
+ font-size: 22rpx;
+ letter-spacing: 0.04em;
+ color: var(--mm-muted-fg);
+ }
+
+ .person__edit {
+ flex: none;
+ padding: 0 24rpx 0 8rpx;
+ }
+
+ .person__check {
+ flex: none;
+ /* xuchao: 复选框仅作状态展示,勾选统一走整卡 toggle,数量上限才拦得住 */
+ pointer-events: none;
+ }
+
+ /* xuchao: 底部固定按钮 —— left/right 0 + margin auto 保证宽屏居中时与页面列对齐 */
+ .bar {
+ position: fixed;
+ left: 0;
+ right: 0;
+ margin: 0 auto;
+ width: 686rpx;
+ bottom: calc(32rpx + constant(safe-area-inset-bottom));
+ bottom: calc(32rpx + env(safe-area-inset-bottom));
+ z-index: 99;
+ }
+
diff --git a/static/back.png b/static/back.png
new file mode 100644
index 0000000..da91dc4
Binary files /dev/null and b/static/back.png differ
diff --git a/uni.scss b/uni.scss
index e439bfb..50d3dcb 100644
--- a/uni.scss
+++ b/uni.scss
@@ -74,4 +74,29 @@ $uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
-@import "uview-ui/theme.scss";
\ No newline at end of file
+@import "uview-ui/theme.scss";
+
+/* xuchao: Minimalist Modern 设计令牌(SCSS 变量)——全站统一色彩来源 */
+$mm-bg: #FAFAFA; // 页面底色,暖白
+$mm-fg: #0F172A; // 主文字,深石板(同时用作反色区块背景)
+$mm-muted: #F1F5F9; // 次级表面/浅填充
+$mm-muted-fg: #64748B; // 次级文字
+$mm-accent: #0052FF; // 电光蓝,唯一强调色
+$mm-accent-2: #4D7CFF; // 签名渐变终点色
+$mm-card: #FFFFFF; // 卡片表面
+$mm-border: #E2E8F0; // 描边
+
+/* xuchao: 覆盖 uView 主题变量,让内置组件(按钮/输入/弹层/日历等)换肤为新设计系统。
+ 放在 theme.scss 引入之后,Sass 变量后赋值生效。 */
+$u-main-color: $mm-fg;
+$u-content-color: #475569;
+$u-tips-color: $mm-muted-fg;
+$u-light-color: #CBD5E1;
+$u-border-color: $mm-border;
+$u-bg-color: $mm-muted;
+$u-type-primary: $mm-accent;
+$u-type-primary-light: #E8EEFF;
+$u-type-primary-disabled: #A8BEFF;
+$u-type-primary-dark: #0041CC;
+/* uni-app 默认主色同步为电光蓝 */
+$uni-color-primary: $mm-accent;
\ No newline at end of file
diff --git a/unit/font/index.css b/unit/font/index.css
index a3655df..5d63555 100644
--- a/unit/font/index.css
+++ b/unit/font/index.css
@@ -1,5 +1,7 @@
-
@font-face {
font-family: 'YouShe';
+ /* xuchao: 该文件经 App.vue @import 内联后,webpack 以"项目根目录"为基准解析 url,
+ 故 ./static/ 即根目录 static/,勿改成相对本文件的 ../../ 路径(会解析失败) */
src: url('./static/YouShe.ttf') format('truetype');
+ font-display: swap;
}
diff --git a/uview-ui/components/u-calendar/u-calendar.vue b/uview-ui/components/u-calendar/u-calendar.vue
index e544f56..19fe241 100644
--- a/uview-ui/components/u-calendar/u-calendar.vue
+++ b/uview-ui/components/u-calendar/u-calendar.vue
@@ -63,7 +63,8 @@
- 确定
+
+ 确定
@@ -187,9 +188,10 @@
default: '#999999'
},
// 选中|起始结束日期背景色
+ // xuchao: 默认色换主题蓝(原绿色与整站风格不一致)
activeBgColor: {
type: String,
- default: '#22B464'
+ default: '#0052FF'
},
// 选中|起始结束日期字体颜色
activeColor: {
@@ -199,12 +201,12 @@
// 范围内日期背景色
rangeBgColor: {
type: String,
- default: 'rgba(123,202,74,0.13)'
+ default: 'rgba(0, 82, 255, 0.08)'
},
// 范围内日期字体颜色
rangeColor: {
type: String,
- default: '#22B464'
+ default: '#0052FF'
},
// mode=range时生效,起始日期自定义文案
startText: {
@@ -246,7 +248,7 @@
return {
// 星期几,值为1-7
customStyle: {
- background: 'linear-gradient(180deg, #FF9E49 0%, #ED3B1A 100%)'
+ background: 'linear-gradient(135deg, #0052FF, #4D7CFF)'
},
weekday: 1,
weekdayArr: [],
@@ -307,7 +309,8 @@
},
getColor1(index, type) {
- let color = type == 1 ? '' : '#f00';
+ // xuchao: 未选中日期价格色由红改主题蓝
+ let color = type == 1 ? '' : '#0052FF';
let day = index + 1
let date = `${this.year}-${this.month}-${day}`
let timestamp = new Date(date.replace(/\-/g, '/')).getTime();
@@ -567,6 +570,12 @@
.u-calendar {
color: $u-content-color;
+ /* xuchao: 限高视口 85%,超出时日历内部上下滑动(小屏机型弹窗不再顶出屏幕);
+ overscroll-behavior 防止滚到边缘后链式滚动背景页 */
+ max-height: 85vh;
+ overflow-y: auto;
+ overscroll-behavior: contain;
+ -webkit-overflow-scrolling: touch;
&__header {
width: 100%;
diff --git a/uview-ui/components/u-popup/u-popup.vue b/uview-ui/components/u-popup/u-popup.vue
index 57bd3ec..0dbd90a 100644
--- a/uview-ui/components/u-popup/u-popup.vue
+++ b/uview-ui/components/u-popup/u-popup.vue
@@ -3,6 +3,8 @@
zIndex: uZindex - 1
}]" class="u-drawer" hover-stop-propagation>
+