Переглянути джерело

Merge branch 'master' into zhangtao

zhangtao 1 тиждень тому
батько
коміт
af4363bd74
29 змінених файлів з 2461 додано та 143 видалено
  1. 4 0
      async-component.d.ts
  2. 1008 3
      src/api/api.type.d.ts
  3. 10 1
      src/api/apiDefinitions.ts
  4. 112 0
      src/api/globals.d.ts
  5. 2 0
      src/auto-imports.d.ts
  6. 3 3
      src/config/index.ts
  7. 17 0
      src/pages.json
  8. 2 2
      src/pages/index/index.vue
  9. 103 64
      src/subPack-attractions/attractionsDetail/attractionsDetail.vue
  10. 466 0
      src/subPack-attractions/attractionsOrderDetail/attractionsOrderDetail.vue
  11. 30 0
      src/subPack-attractions/attractionsOrderDetail/orderDetail-data.ts
  12. 110 0
      src/subPack-attractions/attractionsOrderPay/attractionsOrderPay.vue
  13. 228 29
      src/subPack-attractions/attractionsReservation/attractionsReservation.vue
  14. 24 0
      src/subPack-attractions/attractionsReservation/reservation-data.ts
  15. 76 28
      src/subPack-attractions/commonTab/components/homeList.vue
  16. 63 2
      src/subPack-attractions/commonTab/components/orderList.vue
  17. 5 2
      src/subPack-attractions/commonTab/index.vue
  18. 1 0
      src/subPack-attractions/commonTab/order-data.ts
  19. 1 1
      src/subPack-attractions/components/DatePicker.vue
  20. 50 0
      src/subPack-attractions/components/orderDetailStatus.vue
  21. 29 5
      src/subPack-charge/chargeVoucher/chargeVoucher.vue
  22. 0 1
      src/subPack-charge/index/index.vue
  23. 85 0
      src/subPack-smqjh/components/attractions-orderList/attractions-orderList.vue
  24. 1 1
      src/subPack-smqjh/components/videoRights-orderList/videoRights-orderList.vue
  25. 5 0
      src/subPack-smqjh/order/components/OrderRenderer.vue
  26. 1 0
      src/subPack-smqjh/order/order-data.ts
  27. 1 1
      src/subPack-videoRights/commonTab/components/order.vue
  28. 2 0
      src/uni-pages.d.ts
  29. 22 0
      src/utils/index.ts

+ 4 - 0
async-component.d.ts

@@ -34,3 +34,7 @@ declare module '@/subPack-smqjh/components/djk-order/index.vue?async' {
   const component: typeof import('@/subPack-smqjh/components/djk-order/index.vue')
   export = component
 }
+declare module '@/subPack-smqjh/components/attractions-orderList/attractions-orderList.vue?async' {
+  const component: typeof import('@/subPack-smqjh/components/attractions-orderList/attractions-orderList.vue')
+  export = component
+}

+ 1008 - 3
src/api/api.type.d.ts

@@ -772,9 +772,9 @@ namespace Api {
 
   }
   interface OmsOrderOilVO {
-  /**
-   * 小桔订单号
-   */
+    /**
+     * 小桔订单号
+     */
     xjOrderId?: string
     /**
      * 门店ID
@@ -3040,6 +3040,1011 @@ namespace Api {
     welfareGoodList?: PmsDjkGoods[]
     [property: string]: any
   }
+  /**
+   * 返回数据对象
+   *
+   * DataAppProductDetailVo
+   */
+  export interface DataAppProductDetailVo {
+    list?: AppProductDetailVo[]
+    total?: number
+    [property: string]: any
+  }
+  export interface AppProductDetailVo {
+    /**
+     * 预订详细说明
+     */
+    chargeInclude?: string
+    /**
+     * 地区ID
+     */
+    cityId?: string
+    /**
+     * 景点所在地
+     */
+    cityName?: string
+    /**
+     * 产品介绍,富文本
+     */
+    content?: string
+    /**
+     * 创建时间
+     */
+    createTime?: string
+    /**
+     * 标志图
+     */
+    img?: string
+    /**
+     * 相关主图,多个图片以逗号分隔
+     */
+    imgs?: string
+    /**
+     * 重要提示
+     */
+    importantNote?: string
+    /**
+     * 退改申请类型 0不支持 1支持
+     */
+    isChangeask?: number
+    /**
+     * 是否需要人工确认,0自动确认,1人工确认
+     */
+    isConfirm?: number
+    /**
+     * 1在线支付(预付),0酒店前台现付
+     */
+    isOnlinepay?: number
+    /**
+     * 客人资料要求,1 要求输入每个客人资料,0 只需要输入一个客人资料
+     */
+    isSingle?: number
+    /**
+     * 市场价
+     */
+    marketPrice?: number
+    /**
+     * 最大预定数 0不限制
+     */
+    maxNum?: number
+    /**
+     * 预订详细说明
+     */
+    orderDesc?: string
+    /**
+     * 预订说明
+     */
+    orderPolicy?: string
+    /**
+     * 价格结束时间
+     */
+    priceEndDate?: string
+    /**
+     * 价格开始时间
+     */
+    priceStartDate?: string
+    /**
+     * 产品名称
+     */
+    productName?: string
+    /**
+     * 产品ID
+     */
+    productNo?: number
+    /**
+     * 产品简称
+     */
+    productShortName?: string
+    /**
+     * 限购规则
+     */
+    purchaseLimit?: PurchaseLimitVo
+    /**
+     * 退款说明
+     */
+    refundNote?: string
+    /**
+     * 退款规则列表
+     */
+    refundRules?: RefundRuleVo[]
+    /**
+     * 零售价
+     */
+    salePrice?: number
+    /**
+     * 结算价
+     */
+    settlementPrice?: number
+    /**
+     * 最早游玩日期
+     */
+    startDate?: string
+    /**
+     * 几点之前预定
+     */
+    startTime?: string
+    /**
+     * 产品状态 0在线 1下线
+     */
+    state?: number
+    /**
+     * 已销售数量
+     */
+    ticketCount?: number
+    /**
+     * 更新时间
+     */
+    updateTime?: string
+    /**
+     * 使用说明
+     */
+    userNote?: string
+    /**
+     * 有效期限制具体天数或日期
+     */
+    validityCon?: string
+    /**
+     * 有效期限制,0:游客选定的游玩日期当天有效 1:游客预订日期延后几天有效 2:游客预订日期截止到指定日期有效 3:游客选定日期延后几天有效 4:游客选定日期截止到指定日期有效
+     * 5:指定日期xxx到xxx内有效
+     */
+    validityType?: number
+    /**
+     * 景点地址
+     */
+    viewAddress?: string
+    /**
+     * 景点编号
+     */
+    viewId?: string
+    /**
+     * 纬度
+     */
+    viewLatitude?: string
+    /**
+     * 经度
+     */
+    viewLongitude?: string
+    /**
+     * 景点名称
+     */
+    viewName?: string
+    [property: string]: any
+  }
+
+  /**
+   * 限购规则
+   *
+   * PurchaseLimitVo
+   */
+  export interface PurchaseLimitVo {
+    /**
+     * 证件每天限制
+     */
+    limitCardDay?: number
+    /**
+     * 证件商品限制
+     */
+    limitCardGoods?: number
+    /**
+     * 证件数量限制
+     */
+    limitCardNum?: number
+    /**
+     * 手机每天限制
+     */
+    limitPhoneDay?: number
+    /**
+     * 手机商品限制
+     */
+    limitPhoneGoods?: number
+    /**
+     * 手机数量限制
+     */
+    limitPhoneNum?: number
+    /**
+     * 限制时间类型
+     */
+    limitTimeType?: number
+    /**
+     * 预定限制类型,下单数量校验类型
+     */
+    limitType?: number
+    [property: string]: any
+  }
+
+  /**
+   * 退款规则
+   *
+   * RefundRuleVo
+   */
+  export interface RefundRuleVo {
+    /**
+     * 是否支持订单完成后做强制退改 0不支持 1支持
+     */
+    agreeForcetg?: number
+    /**
+     * 分销商可退款规则
+     */
+    cancelMoneyCodex?: string
+    /**
+     * 有效退款日期,0当天,正数前x天,负数后x天
+     */
+    days?: number
+    /**
+     * 有效退款时间,申请退款需要在这个时间之前
+     */
+    hours?: number
+    /**
+     * 供应商退回规则
+     */
+    returnMoneyCodex?: string
+    [property: string]: any
+  }
+  /**
+   * 返回数据对象
+   *
+   * ProductPriceResponseVo
+   */
+  export interface ProductPriceResponseVo {
+    /**
+     * 产品ID
+     */
+    infoId?: number
+    /**
+     * 是否是多规格 0否 1是
+     */
+    isSpec?: number
+    /**
+     * 线路产品价格
+     */
+    linePrices?: LinePriceVo[]
+    /**
+     * 门票多规格价格
+     */
+    muskuPrices?: MuskuPriceVo[]
+    /**
+     * 抢购产品价格
+     */
+    snapupPrices?: SnapupPriceVo[]
+    /**
+     * 多规格商品价格
+     */
+    specProdPrices?: SpecProdPriceVo[]
+    /**
+     * 多规格信息
+     */
+    specs?: SpecVo[]
+    /**
+     * 门票产品价格
+     */
+    ticketPrices?: TicketPriceVo[]
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductPriceResponseVo.LinePriceVo
+   *
+   * LinePriceVo
+   */
+  export interface LinePriceVo {
+    /**
+     * 日期
+     */
+    date?: string
+    /**
+     * 最小团队人数
+     */
+    minTeamNum?: number
+    /**
+     * 价格明细列表
+     */
+    priceDetails?: PriceDetailVo[]
+    /**
+     * 剩余数量
+     */
+    remainNum?: number
+    /**
+     * 单房差价
+     */
+    singleRoomPrice?: number
+    /**
+     * 提前预订天数
+     */
+    startDay?: number
+    /**
+     * 起订数量
+     */
+    startNum?: number
+    /**
+     * 总数量
+     */
+    totalNum?: number
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductPriceResponseVo.PriceDetailVo
+   *
+   * PriceDetailVo
+   */
+  export interface PriceDetailVo {
+    /**
+     * 市场价
+     */
+    marketPrice?: number
+    /**
+     * 价格ID
+     */
+    priceId?: number
+    /**
+     * 价格名称
+     */
+    priceName?: string
+    /**
+     * 销售价
+     */
+    salePrice?: number
+    /**
+     * 结算价
+     */
+    settlementPrice?: number
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductPriceResponseVo.MuskuPriceVo
+   *
+   * MuskuPriceVo
+   */
+  export interface MuskuPriceVo {
+    /**
+     * 日期
+     */
+    date?: string
+    /**
+     * 剩余数量
+     */
+    num?: number
+    /**
+     * 价格明细列表
+     */
+    priceDetails?: PriceDetailVo[]
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductPriceResponseVo.SnapupPriceVo
+   *
+   * SnapupPriceVo
+   */
+  export interface SnapupPriceVo {
+    /**
+     * 总数量
+     */
+    allNum?: number
+    /**
+     * 市场价
+     */
+    marketPrice?: number
+    /**
+     * 剩余数量
+     */
+    num?: number
+    /**
+     * 销售价
+     */
+    salePrice?: number
+    /**
+     * 结算价
+     */
+    settlementPrice?: number
+    /**
+     * 规格ID
+     */
+    specId?: string
+    /**
+     * 规格名称
+     */
+    specName?: string
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductPriceResponseVo.SpecProdPriceVo
+   *
+   * SpecProdPriceVo
+   */
+  export interface SpecProdPriceVo {
+    /**
+     * 市场价
+     */
+    marketPrice?: number
+    /**
+     * 剩余数量
+     */
+    num?: number
+    /**
+     * 销售价
+     */
+    salePrice?: number
+    /**
+     * 结算价
+     */
+    settlementPrice?: number
+    /**
+     * 规格ID
+     */
+    specId?: string
+    /**
+     * 规格名称
+     */
+    specName?: string
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductDetailResponseVo.SpecVo
+   *
+   * SpecVo
+   */
+  export interface SpecVo {
+    /**
+     * 规格名称
+     */
+    specName?: string
+    /**
+     * 规格值列表
+     */
+    specValues?: { [key: string]: any }[]
+    [property: string]: any
+  }
+
+  /**
+   * com.smqjh.pms.model.vo.scenery.ProductPriceResponseVo.TicketPriceVo
+   *
+   * TicketPriceVo
+   */
+  export interface TicketPriceVo {
+    /**
+     * 日期
+     */
+    date?: string
+    /**
+     * 市场价
+     */
+    marketPrice?: number
+    /**
+     * 剩余数量
+     */
+    num?: number
+    /**
+     * 销售价
+     */
+    salePrice?: number
+    /**
+     * 时段列表
+     */
+    seats?: SeatVo[]
+    /**
+     * 结算价
+     */
+    settlementPrice?: number
+    /**
+     * 票余量状态:充足/紧张/售罄
+     */
+    ticketAvailability?: string
+    [property: string]: any
+  }
+
+  export interface CreateOrderRequest {
+    /**
+     * 结束游玩日期,格式yyyy-MM-dd
+     */
+    endTravelDate?: string
+    /**
+     * 联系人地址
+     */
+    linkAddress?: string
+    /**
+     * 联系人证件号
+     */
+    linkCreditNo?: string
+    /**
+     * 联系人证件类型
+     */
+    linkCreditType?: number
+    /**
+     * 联系人邮件
+     */
+    linkEmail?: string
+    /**
+     * 联系人姓名
+     */
+    linkMan?: string
+    /**
+     * 联系人手机号
+     */
+    linkPhone?: string
+    /**
+     * 预定数量
+     */
+    num: number
+    /**
+     * 订单备注
+     */
+    orderMemo?: string
+    /**
+     * 游玩人信息列表
+     */
+    peoples?: PeopleItem[]
+    /**
+     * 产品名称
+     */
+    productName?: string
+    /**
+     * 产品ID(pms_scenic_product.product_no)
+     */
+    productNo: number
+    /**
+     * 游玩日期,格式yyyy-MM-dd
+     */
+    travelDate: string
+    [property: string]: any
+  }
+  export interface PeopleItem {
+    /**
+     * 是否成人
+     */
+    adult?: boolean
+    /**
+     * 年龄,儿童必传
+     */
+    age?: number
+    /**
+     * 游玩人快递地址
+     */
+    linkAddress?: string
+    /**
+     * 游玩人证件号
+     */
+    linkCreditNo?: string
+    /**
+     * 游玩人证件类型
+     */
+    linkCreditType?: number
+    /**
+     * @Schema(description = "游玩人名")
+     * 游玩人姓名
+     */
+    linkMan?: string
+    /**
+     * 游玩人手机号
+     */
+    linkPhone?: string
+    /**
+     * 性别 1未知 2男 3女
+     */
+    linkSex?: number
+    [property: string]: any
+  }
+  export interface ScenicPayPreviewVo {
+    /**
+     * 用户可用积分
+     */
+    availablePoints?: number
+    /**
+     * 系统订单号
+     */
+    orderNumber?: string
+    /**
+     * 订单总金额(actualTotal)
+     */
+    orderTotal?: number
+    /**
+     * 积分可抵扣金额
+     */
+    pointsDeduct?: number
+    /**
+     * 微信支付金额
+     */
+    wxPayMoney?: number
+    [property: string]: any
+  }
+  export interface DataScenicOrderListVo {
+    list?: ScenicOrderListVo[]
+    total?: number
+    [property: string]: any
+  }
+
+  /**
+   * 景区订单列表项VO
+   *
+   * ScenicOrderListVo
+   */
+  export interface ScenicOrderListVo {
+    /**
+     * 用户实际支付金额
+     */
+    actualTotal?: number
+    /**
+     * 下单时间
+     */
+    createTime?: string
+    /**
+     * 结束游玩日期
+     */
+    endTravelDate?: string
+    /**
+     * 景点图片
+     */
+    img?: string
+    /**
+     * 系统订单号
+     */
+    orderNumber?: string
+    /**
+     * 产品名称
+     */
+    productName?: string
+    /**
+     * 游玩日期
+     */
+    travelDate?: string
+    /**
+     * 景点名称
+     */
+    viewName?: string
+    /**
+     * 订单状态0-待支付
+     * 60-订单已取消
+     * 70-已支付
+     * 80-订单已完成
+     */
+    hbOrderStatus?: number
+    [property: string]: any
+  }
+  export interface ScenicOrderDetailVo {
+    /**
+     * 实际总值(用户实付)
+     */
+    actualTotal?: number
+    /**
+     * 业务类型
+     */
+    businessType?: string
+    /**
+     * 取消原因
+     */
+    cancelReason?: string
+    /**
+     * 取消退款记录列表
+     */
+    cancelRecords?: OmsScenicOrderCancel
+    /**
+     * 取消时间
+     */
+    cancelTime?: string
+    /**
+     * 创建时间
+     */
+    createTime?: string
+    /**
+     * 海博订单状态:0-待支付,20-已接单,30-待配送,40-配送中,50-取消待审核,60-已取消,70-已送达,80-已完成
+     */
+    hbOrderStatus?: number
+    /**
+     * 是否已支付 1:已支付 0:未支付
+     */
+    isPayed?: number
+    /**
+     * 积分抵扣
+     */
+    offsetPoints?: number
+    /**
+     * 订单总额
+     */
+    orderMoney?: number
+    /**
+     * 系统订单号
+     */
+    orderNumber?: string
+    /**
+     * 付款时间
+     */
+    payTime?: string
+    /**
+     * 支付方式 0-微信 1-积分 2-混合
+     */
+    payType?: number
+    /**
+     * 游玩人列表
+     */
+    peoples?: OmsOrderScenicPeople[]
+    /**
+     * 景区子订单
+     */
+    scenicOrder?: OmsOrderScenic
+    [property: string]: any
+  }
+
+  /**
+   * 景区订单取消退款记录
+   *
+   * OmsScenicOrderCancel
+   */
+  export interface OmsScenicOrderCancel {
+    /**
+     * 回调通知时间
+     */
+    callbackTime?: string
+    /**
+     * 第三方取消审核ID(回调匹配用)
+     */
+    cancelId?: string
+    /**
+     * 取消原因
+     */
+    cancelMemo?: string
+    /**
+     * 取消退款金额
+     */
+    cancelMoney?: number
+    /**
+     * 申请取消数量
+     */
+    cancelNum?: number
+    /**
+     * 取消状态 0申请中 1取消成功 2取消被拒绝
+     */
+    cancelState?: number
+    /**
+     * 创建时间
+     */
+    createTime?: string
+    /**
+     * 逻辑删除 0正常 1已删除
+     */
+    deleted?: number
+    /**
+     * 主键ID
+     */
+    id?: number
+    /**
+     * 申请人(会员ID)
+     */
+    memberId?: number
+    /**
+     * 自我游订单号(第三方)
+     */
+    orderId?: number
+    /**
+     * 系统订单号
+     */
+    orderNumber?: string
+    /**
+     * 拒绝原因
+     */
+    rejectReason?: string
+    /**
+     * 更新时间
+     */
+    updateTime?: string
+    [property: string]: any
+  }
+
+  /**
+   * 景区订单游玩人信息表
+   *
+   * OmsOrderScenicPeople
+   */
+  export interface OmsOrderScenicPeople {
+    /**
+     * 是否成人
+     */
+    adult?: number
+    /**
+     * 游玩人年龄,儿童必须要传
+     */
+    age?: number
+    /**
+     * 创建时间
+     */
+    createTime?: string
+    /**
+     * 主键ID
+     */
+    id?: number
+    /**
+     * 游玩人快递地址
+     */
+    linkAddress?: string
+    /**
+     * 游玩人证件号码
+     */
+    linkCreditNo?: string
+    /**
+     * 游玩人证件类型
+     */
+    linkCreditType?: number
+    /**
+     * 游玩人姓名
+     */
+    linkMan?: string
+    /**
+     * 游玩人手机号
+     */
+    linkPhone?: string
+    /**
+     * 性别 1未知 2男 3女
+     */
+    linkSex?: number
+    /**
+     * 自我游订单号
+     */
+    orderId?: number
+    /**
+     * 系统订单号
+     */
+    orderSourceId?: string
+    /**
+     * 核销时间
+     */
+    verifyTime?: string
+    /**
+     * 凭证码(主码)
+     */
+    voucherCode?: string
+    /**
+     * pdf链接
+     */
+    voucherPdfUrl?: string
+    /**
+     * 二维码链接
+     */
+    voucherQrcodeUrl?: string
+    /**
+     * 凭证状态 0正常 1已核销 2已取消 3申请取消中 4取消处理中
+     */
+    voucherStatus?: number
+    /**
+     * 凭证类型 0凭证码 1二维码链接 2pdf 3链接
+     */
+    voucherType?: number
+    /**
+     * 凭证链接
+     */
+    voucherUrl?: string
+    [property: string]: any
+  }
+
+  /**
+   * 景区子订单
+   *
+   * OmsOrderScenic
+   */
+  export interface OmsOrderScenic {
+    /**
+     * 取消订单日期
+     */
+    cancelDate?: string
+    /**
+     * 创建时间
+     */
+    createTime?: string
+    /**
+     * 结束游玩日期
+     */
+    endTravelDate?: string
+    /**
+     * 总验证数量
+     */
+    finishNum?: number
+    /**
+     * 免费取票说明
+     */
+    freeMemo?: string
+    /**
+     * 快递费用
+     */
+    getPrice?: number
+    /**
+     * 快递方式 0免费 1需要配送 3无须配送
+     */
+    getType?: number
+    /**
+     * 主键ID
+     */
+    id?: number
+    /**
+     * 产品标志图
+     */
+    img?: string
+    /**
+     * 联系人地址
+     */
+    linkAddress?: string
+    /**
+     * 联系人证件号码
+     */
+    linkCreditNo?: string
+    /**
+     * 联系人证件类型
+     */
+    linkCreditType?: number
+    /**
+     * 联系人email
+     */
+    linkEmail?: string
+    /**
+     * 联系人姓名
+     */
+    linkMan?: string
+    /**
+     * 联系人电话
+     */
+    linkPhone?: string
+    /**
+     * 零售总价
+     */
+    memOrderMoney?: number
+    /**
+     * 产品预定数量
+     */
+    num?: number
+    /**
+     * 下单日期
+     */
+    orderDate?: string
+    /**
+     * 自我游订单号
+     */
+    orderId?: number
+    /**
+     * 订单备注
+     */
+    orderMemo?: string
+    /**
+     * 结算总价
+     */
+    orderMoney?: number
+    /**
+     * 系统订单号
+     */
+    orderSourceId?: string
+    /**
+     * 订单状态,0新订单(下单成功未确认状态) 1已确认(下单成功已确认状态,已确认状态才能调用支付接口) 2已成功(已支付成功状态) 3已取消 4已完成(已消费状态)
+     */
+    orderState?: number
+    /**
+     * 订单状态2,可能为空;1已通知(已支付未出票状态) 2已快递(产品需要配送时才有的状态) 3已出票
+     */
+    orderState2?: string
+    /**
+     * 产品标题
+     */
+    productName?: string
+    /**
+     * 产品id
+     */
+    productNo?: number
+    /**
+     * 游玩日期
+     */
+    travelDate?: string
+    /**
+     * 更新时间
+     */
+    updateTime?: string
+    /**
+     * 景点名称
+     */
+    viewName?: string
+    /**
+     * 退改申请类型 0不支持 1支持
+     */
+    isChangeask?: number
+    [property: string]: any
+  }
 
   /** 优惠券领取列表 */
   interface AppMemberCouponVO {

+ 10 - 1
src/api/apiDefinitions.ts

@@ -133,6 +133,15 @@ export default {
   'djk.addWelfareOrder':['POST', '/smqjh-oms/api/v1/djkOrder/addWelfareOrder'],
   'djk.submitRefund': ['POST', '/smqjh-oms/api/v1/djkOrder/submitRefund'],
 
-  'refueling.getPayCode':['POST','/smqjh-pms/api/v1/refueling/generateQrCode'],
+  'refueling.getPayCode': ['POST', '/smqjh-pms/api/v1/refueling/generateQrCode'],
   'refueling.cancelOrder': ['POST', '/smqjh-oms/api/v1/oil/order/cancel'],
+
+  'attractions.findAppByPage':['GET','/smqjh-pms/app-api/v1/sceneryProduct/findAppByPage'],
+  'attractions.detail':['GET','/smqjh-pms/app-api/v1/sceneryProduct/detail'],
+  'attractions.price':['POST','/smqjh-pms/app-api/v1/sceneryProduct/price'],
+  'attractions.createOrder':['POST','/smqjh-oms/app-api/v1/order/scenic/add'],
+  'attractions.payPreview':['GET','/smqjh-oms/app-api/v1/order/scenic/pay-preview'],
+  'attractions.orderList':['GET','/smqjh-oms/app-api/v1/order/scenic/list'],
+  'attractions.orderDetail':['GET','/smqjh-oms/app-api/v1/order/scenic/detail'],
+  'attractions.cancelOrder':['POST','/smqjh-oms/app-api/v1/order/scenic/cancel'],
 };

+ 112 - 0
src/api/globals.d.ts

@@ -1334,6 +1334,118 @@ declare global {
         config: Config
       ): Alova2Method<apiResData<any>, 'refueling.cancelOrder', Config>;
     }
+    attractions: {
+      findAppByPage<
+        Config extends Alova2MethodConfig<apiResData<Api.DataAppProductDetailVo>> & {
+          data: {
+            /**
+            * 页码
+            */
+            pageNum?: number;
+            /**
+             * 每页记录数
+             */
+            pageSize?: number;
+            /**
+             * 产品名称(模糊查询)
+             */
+            productName?: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.DataAppProductDetailVo>, 'attractions.findAppByPage', Config>;
+
+      detail<
+        Config extends Alova2MethodConfig<apiResData<Api.AppProductDetailVo>> & {
+          data: {
+            /**
+            * 产品id
+            */
+            productNo?: number;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.AppProductDetailVo>, 'attractions.detail', Config>;
+
+      price<
+        Config extends Alova2MethodConfig<apiResData<Api.ProductPriceResponseVo>> & {
+          data: {
+            /**
+             * 产品ID
+             */
+            productNo?: number;
+            /**
+             * 开始日期
+             */
+            travelDate?: string;
+            /**
+             * 结束日期,不传默认只查本月的价格
+             */
+            endTravelDate?: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.ProductPriceResponseVo>, 'attractions.price', Config>;
+
+      createOrder<
+        Config extends Alova2MethodConfig<apiResData<any>> & {
+          data: Api.CreateOrderRequest;
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<any>, 'attractions.createOrder', Config>;
+
+      payPreview<
+        Config extends Alova2MethodConfig<apiResData<Api.ScenicPayPreviewVo>> & {
+          data: {
+            /**
+            * 订单号
+            */
+            orderNumber: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.ScenicPayPreviewVo>, 'attractions.payPreview', Config>;
+
+      orderList<
+        Config extends Alova2MethodConfig<apiResData<Api.DataScenicOrderListVo>> & {
+          data: {
+            pageNum: number;
+            pageSize: number;
+            /**
+             * 订单状态:0-全部 1-待支付 2-已支付 3-已取消 4-已完成
+             */
+            status: number;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.DataScenicOrderListVo>, 'attractions.orderList', Config>;
+      orderDetail<
+        Config extends Alova2MethodConfig<apiResData<Api.ScenicOrderDetailVo>> & {
+          data: {
+            orderNumber: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<Api.ScenicOrderDetailVo>, 'attractions.orderDetail', Config>;
+      cancelOrder<
+        Config extends Alova2MethodConfig<apiResData<void>> & {
+          data: {
+            cancelMemo?: string;
+            cancelNum?: number;
+            orderNumber: string;
+          }
+        }
+      >(
+        config: Config
+      ): Alova2Method<apiResData<void>, 'attractions.cancelOrder', Config>;
+    }
   }
 }
 var Apis: Apis;

+ 2 - 0
src/auto-imports.d.ts

@@ -47,6 +47,7 @@ declare global {
   const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
   const effectScope: typeof import('vue')['effectScope']
   const extendRef: typeof import('@vueuse/core')['extendRef']
+  const fixImgStyle: typeof import('./utils/index')['fixImgStyle']
   const getActivePinia: typeof import('pinia')['getActivePinia']
   const getCurrentInstance: typeof import('vue')['getCurrentInstance']
   const getCurrentPath: typeof import('./utils/index')['getCurrentPath']
@@ -412,6 +413,7 @@ declare module 'vue' {
     readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']>
     readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']>
     readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']>
+    readonly fixImgStyle: UnwrapRef<typeof import('./utils/index')['fixImgStyle']>
     readonly getActivePinia: UnwrapRef<typeof import('pinia')['getActivePinia']>
     readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']>
     readonly getCurrentPath: UnwrapRef<typeof import('./utils/index')['getCurrentPath']>

+ 3 - 3
src/config/index.ts

@@ -11,7 +11,7 @@ const mapEnvVersion = {
   // develop: 'http://192.168.0.11:8080', // 王
   develop: 'http://192.168.1.89:8080', // 田
   // develop: 'http://74949mkfh190.vicp.fun', // 付
-  // develop: 'http://47.109.84.152:8081',
+  develop: 'http://47.109.84.152:8081',
   // develop: 'https://5ed0f7cc.r9.vip.cpolar.cn',
   // develop: 'https://smqjh.api.zswlgz.com',
   /**
@@ -19,9 +19,9 @@ const mapEnvVersion = {
    */
   // trial: "http://192.168.1.166:8080/jeecg-boot",
   // trial: 'http://192.168.0.157:8080',
-  // trial: 'http://47.109.84.152:8081',
+  trial: 'http://47.109.84.152:8081',
   // trial: 'http://192.168.1.166:8080,
-  trial: 'https://smqjh.api.zswlgz.com',
+  // trial: 'https://smqjh.api.zswlgz.com',
   /**
    * 正式版
    */

+ 17 - 0
src/pages.json

@@ -669,6 +669,23 @@
             "navigationStyle": "custom"
           }
         },
+        {
+          "path": "attractionsOrderDetail/attractionsOrderDetail",
+          "name": "attractions-order-detail",
+          "islogin": false,
+          "style": {
+            "navigationBarTitleText": "订单详情",
+            "navigationStyle": "custom"
+          }
+        },
+        {
+          "path": "attractionsOrderPay/attractionsOrderPay",
+          "name": "attractions-order-pay",
+          "islogin": false,
+          "style": {
+            "navigationBarTitleText": "订单支付"
+          }
+        },
         {
           "path": "attractionsReservation/attractionsReservation",
           "name": "attractions-reservation-info",

+ 2 - 2
src/pages/index/index.vue

@@ -60,8 +60,8 @@ const navList = computed(() => {
     { icon: `${StaticUrl}/smqjh-sp.png`, title: '电影演出', name: 'film-index', show: true },
     { icon: `${StaticUrl}/smqjh-vip.png`, title: '视频权益', name: 'video-rights-tabbar', show: !isOnlineAudit.value },
     { icon: `${StaticUrl}/smqjh-djk.png`, title: '大健康', name: 'djk-homeTabbar', show: true },
-    { icon: `${StaticUrl}/smqjh-jiayou.png`, title: '加油', name: 'refueling-tabbar', show: true }, // refueling-tabbar
-    { icon: `${StaticUrl}/smqjh-attractions.png`, title: '景区', name: '', show: !isOnlineAudit.value },
+    { icon: `${StaticUrl}/smqjh-jiayou.png`, title: '加油', name: 'refueling-tabbar', show: true },
+    { icon: `${StaticUrl}/smqjh-attractions.png`, title: '景区', name: 'attractions-tabbar', show: true },
     { icon: `${StaticUrl}/smqjh-diancan.png`, title: '大牌点餐', name: '', show: !isOnlineAudit.value },
     { icon: `${StaticUrl}/smqjh-jiudian.png`, title: '酒店民宿', name: '', show: !isOnlineAudit.value },
     { icon: `${StaticUrl}/smqjh-daijia.png`, title: '代驾', name: '', show: !isOnlineAudit.value },

+ 103 - 64
src/subPack-attractions/attractionsDetail/attractionsDetail.vue

@@ -2,61 +2,40 @@
 import DatePicker from '../components/DatePicker.vue'
 import { StaticUrl } from '@/config'
 import router from '@/router'
+import { fixImgStyle } from '@/utils/index'
 
-const { statusBarHeight, opcity } = storeToRefs(useSysStore())
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
 
-// 轮播图数据
-const swiperList = ref([
-  'https://picsum.photos/400/300?random=1',
-  'https://picsum.photos/400/300?random=2',
-  'https://picsum.photos/400/300?random=3',
-])
 const currentSwiper = ref(0)
 
-// 选中的日期
-const selectedDate = ref(new Date(2026, 2, 21)) // 默认选中2026年3月21日
-
-// 日历数据(按月份存储,key为 'YYYY-MM')
-const calendarDataMap = ref<Record<string, Array<{ day: number, status?: string, price?: number, selected?: boolean }>>>({
-  '2026-03': [
-    { day: 21, status: '充足', price: 290 },
-    { day: 27, status: '售罄', price: 290 },
-  ],
-  '2026-04': [
-    { day: 1, status: '充足', price: 280 },
-    { day: 5, status: '紧张', price: 300 },
-    { day: 10, status: '售罄', price: 280 },
-  ],
-})
+const selectedDate = ref()
+
+const calendarDataMap = ref<Record<string, Array<{ day: number, status?: string, price?: number, selected?: boolean }>>>({})
 
-// 当前显示的月份
-const currentYearMonth = ref({ year: 2026, month: 3 })
+const currentYearMonth = ref({ year: new Date().getFullYear(), month: new Date().getMonth() + 1 })
 
-// 获取当前月份的日期数据
 const currentMonthDays = computed(() => {
   const key = `${currentYearMonth.value.year}-${String(currentYearMonth.value.month).padStart(2, '0')}`
   return calendarDataMap.value[key] || []
 })
 
-// 景区信息
-const attractionInfo = ref({
-  name: '贵州黄果树风景名胜区',
-  address: '镇宁布依族苗族自治县-黄果树镇贵黄公路',
-  price: 290,
-  title: '日场门票+观光车+飞越黄果树观影票+吉祥物+冰箱贴 经典必打卡',
-})
-
 definePage({
   name: 'attractions-detail',
-  islogin: false,
+  islogin: true,
   style: {
     navigationBarTitleText: '',
     navigationStyle: 'custom',
   },
 })
 
+const productNo = ref('')
+onLoad((options: any) => {
+  productNo.value = options.productNo || ''
+})
+
 onMounted(() => {
   opcity.value = 0
+  getDetail()
 })
 
 onPageScroll((e) => {
@@ -64,39 +43,82 @@ onPageScroll((e) => {
   opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
 })
 
-function handleNav() {
-  uni.openLocation({
-    latitude: 25.9913,
-    longitude: 105.6687,
-    name: attractionInfo.value.name,
-    address: attractionInfo.value.address,
+const attractionDetail = ref<Api.AppProductDetailVo | null>(null)
+
+const swiperList = computed(() => {
+  const imgs = attractionDetail.value?.imgs
+  return imgs ? imgs.split(',').filter(Boolean) : []
+})
+
+async function getDetail() {
+  const res = await Apis.attractions.detail({ data: { productNo: Number(productNo.value) } })
+  attractionDetail.value = res.data
+  await getPrice()
+}
+
+async function getPrice(year?: number, month?: number) {
+  const targetYear = year ?? currentYearMonth.value.year
+  const targetMonth = month ?? currentYearMonth.value.month
+  const startDate = `${targetYear}-${String(targetMonth).padStart(2, '0')}-01`
+  const lastDay = new Date(targetYear, targetMonth, 0).getDate()
+  const endDate = `${targetYear}-${String(targetMonth).padStart(2, '0')}-${lastDay}`
+  useGlobalLoading().loading({
+    msg: '加载中...',
+  })
+  const res = await Apis.attractions.price({
+    data: {
+      productNo: Number(productNo.value),
+      travelDate: startDate,
+      endTravelDate: endDate,
+    },
   })
+  useGlobalLoading().close()
+  const ticketPrices = res.data?.ticketPrices || []
+  const monthKey = `${targetYear}-${String(targetMonth).padStart(2, '0')}`
+  calendarDataMap.value[monthKey] = ticketPrices.map((item: Api.TicketPriceVo) => ({
+    day: item.date ? new Date(item.date).getDate() : 0,
+    status: item.ticketAvailability,
+    price: item.salePrice,
+  })).filter((item: { day: number }) => item.day > 0)
 }
 
-function handleService() {
-  uni.makePhoneCall({
-    phoneNumber: '400-123-4567',
+function handleNav() {
+  uni.openLocation({
+    latitude: Number(attractionDetail.value?.viewLatitude) || 0,
+    longitude: Number(attractionDetail.value?.viewLongitude) || 0,
+    name: attractionDetail.value?.viewName,
+    address: attractionDetail.value?.viewAddress,
   })
 }
 
 function handleOrder() {
-  router.push({ name: 'attractions-order' })
+  router.push({ name: 'attractions-tabbar', params: { tabbar: '1' } })
 }
 
 function handleBook() {
-  router.push({ name: 'attractions-reservation-info' })
+  router.push({
+    name: 'attractions-reservation-info',
+    params: {
+      productNo: productNo.value,
+      selectDate: selectedDate.value || new Date(),
+      productName: attractionDetail.value?.productName || '',
+      isSingle: String(attractionDetail.value?.isSingle),
+      price: String(attractionDetail.value?.salePrice),
+    },
+  })
 }
 
-// 处理日期选择
 function handleDateSelect(e: { date: Date, day: number, item?: any }) {
   selectedDate.value = e.date
   console.log('选中日期:', e.date, '日期数据:', e.item)
 }
 
-// 处理月份变化
-function handleMonthChange(e: { year: number, month: number }) {
+async function handleMonthChange(e: { year: number, month: number }) {
   currentYearMonth.value = { year: e.year, month: e.month }
-  console.log('切换月份:', e.year, '年', e.month, '月')
+  const monthKey = `${e.year}-${String(e.month).padStart(2, '0')}`
+  if (!calendarDataMap.value[monthKey]) {
+    await getPrice(e.year, e.month)
+  }
 }
 </script>
 
@@ -114,13 +136,14 @@ function handleMonthChange(e: { year: number, month: number }) {
     />
     <!-- 轮播图 -->
     <wd-swiper
+      v-if="swiperList.length"
       v-model:current="currentSwiper"
       :list="swiperList"
       :indicator="false"
       :height="300"
       class="w-full"
     />
-
+    <view v-else :style="{ height: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 30}px` }" />
     <!-- 价格标题区域 -->
     <view class="relative z-10 rounded-t-32rpx bg-white px24rpx pt30rpx -mt-30rpx">
       <view class="flex items-baseline text-#FF4D3A">
@@ -128,14 +151,14 @@ function handleMonthChange(e: { year: number, month: number }) {
           ¥
         </text>
         <text class="mx4rpx text-48rpx font-bold">
-          {{ attractionInfo.price }}
+          {{ attractionDetail?.salePrice }}
         </text>
         <text class="text-24rpx text-gray">
         </text>
       </view>
       <view class="mt16rpx text-32rpx font-semibold line-height-[1.4]">
-        {{ attractionInfo.title }}
+        {{ attractionDetail?.productName }}
       </view>
 
       <!-- 地址导航卡片 -->
@@ -145,10 +168,10 @@ function handleMonthChange(e: { year: number, month: number }) {
       >
         <view class="w450rpx">
           <view class="line-clamp-1 text-32rpx font-semibold">
-            {{ attractionInfo.name }}
+            {{ attractionDetail?.viewName }}
           </view>
           <view class="line-clamp-1 mt12rpx flex items-center text-24rpx text-gray">
-            {{ attractionInfo.address }}
+            {{ attractionDetail?.viewAddress }}
           </view>
         </view>
         <view class="flex flex-col items-center justify-center" @click="handleNav">
@@ -179,19 +202,24 @@ function handleMonthChange(e: { year: number, month: number }) {
         <view class="text-32rpx font-semibold">
           预定须知
         </view>
-        <view class="mt16rpx text-28rpx font-semibold">
+        <!-- <view class="mt16rpx text-28rpx font-semibold">
           退款说明
-        </view>
+        </view> -->
         <view class="mt12rpx text-26rpx text-gray line-height-[1.6]">
-          <view>使用日期当天23:59(含)之前申请取消,不收取损失费</view>
+          <view>
+            <rich-text :nodes="fixImgStyle(attractionDetail?.content || '')" />
+          </view>
+          <view class="mt8rpx">
+            <rich-text :nodes="fixImgStyle(attractionDetail?.orderDesc || '')" />
+          </view>
           <view class="mt8rpx">
-            使用日期当天23:59之后申请取消,收取100%损失费;激活后不可退
+            {{ attractionDetail?.chargeInclude }}
           </view>
           <view class="mt8rpx">
-            如使用优惠,则损失费用按照优惠前金额的比例收取,最高不超过实付金额
+            {{ attractionDetail?.refundNote }}
           </view>
           <view class="mt8rpx">
-            产品不支持部分退
+            {{ attractionDetail?.userNote }}
           </view>
         </view>
       </view>
@@ -206,9 +234,10 @@ function handleMonthChange(e: { year: number, month: number }) {
       :style="{ paddingBottom: `${(Number(statusBarHeight) || 44) - 20}px` }"
     >
       <view class="flex items-center border-t-#EEEEEE">
-        <view class="mr-40rpx flex flex-col items-center" @click="handleService">
-          <wd-icon name="service" size="22px" color="#666" />
-          <text class="mt4rpx text-22rpx text-#666">
+        <view class="relative mr-40rpx flex flex-col items-center">
+          <button open-type="contact" class="zbutton" />
+          <wd-icon name="service" size="24px" color="#666" />
+          <text class="text-22rpx text-#666">
             客服
           </text>
         </view>
@@ -229,4 +258,14 @@ function handleMonthChange(e: { year: number, month: number }) {
   </view>
 </template>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.zbutton{
+  all: unset;
+  width: 70rpx;
+  height: 70rpx;
+  position: absolute;
+  &::after{
+    border: none;
+  }
+}
+</style>

+ 466 - 0
src/subPack-attractions/attractionsOrderDetail/attractionsOrderDetail.vue

@@ -0,0 +1,466 @@
+<script setup lang="ts">
+import OrderDetailStatus from '../components/orderDetailStatus.vue'
+import { columns as creditTypeColumns } from '../attractionsReservation/reservation-data'
+import { orderStatus } from './orderDetail-data'
+import { StaticUrl } from '@/config'
+import router from '@/router'
+
+definePage({
+  name: 'attractions-order-detail',
+  islogin: false,
+  style: {
+    navigationBarTitleText: '订单详情',
+    navigationStyle: 'custom',
+  },
+})
+const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
+const orderNumber = ref('')
+const orderInfo = ref<Api.ScenicOrderDetailVo>()
+const orderPopup = ref(false)
+const refundNum = ref(1)
+const refundReason = ref('')
+const ispay = ref('')
+
+const statusValue = computed(() => orderInfo.value?.hbOrderStatus ?? 0)
+
+/** 当前状态配置 */
+const currentStatus = computed(() => {
+  return orderStatus.find(item => item.value === statusValue.value) || orderStatus[0]
+})
+
+/** 有凭证码的游客列表 */
+const voucherPeoples = computed(() => {
+  return orderInfo.value?.peoples?.filter(p => p.voucherCode) ?? []
+})
+
+/** 是否展示凭证区域 */
+const hasVoucher = computed(() => voucherPeoples.value.length > 0)
+
+const swiperCurrent = ref(0)
+function onSwiperChange(e: any) {
+  swiperCurrent.value = e.detail.current
+}
+
+/** 证件类型文本 */
+function creditTypeText(type?: number) {
+  return creditTypeColumns.value.find(item => item.value === type)?.label ?? '身份证'
+}
+
+async function getData(orderNo: string) {
+  const res = await Apis.attractions.orderDetail({ data: { orderNumber: orderNo } })
+  orderInfo.value = res.data
+}
+
+function handleRefundMinus() {
+  if (refundNum.value > 1)
+    refundNum.value--
+}
+
+function handleRefundPlus() {
+  const maxNum = orderInfo.value?.scenicOrder?.num ?? 1
+  if (refundNum.value < maxNum)
+    refundNum.value++
+}
+
+function handleGoPay() {
+  router.push({
+    name: 'attractions-order-pay',
+    params: {
+      productName: orderInfo.value?.scenicOrder?.productName || '',
+      num: String(orderInfo.value?.scenicOrder?.num) || '',
+      orderNo: orderInfo.value?.orderNumber || '',
+    },
+  })
+}
+
+function handleRebook() {
+  router.push({
+    name: 'attractions-detail',
+    params: {
+      productNo: String(orderInfo.value?.scenicOrder?.productNo),
+    },
+  })
+}
+
+/** 是否显示取消/退款按钮 */
+const showCancelOrRefundButton = computed(() => {
+  const status = statusValue.value
+  const cancelState = orderInfo.value?.cancelRecords?.cancelState
+  const isChangeask = orderInfo.value?.scenicOrder?.isChangeask
+
+  // 必须允许退改申请
+  if (isChangeask !== 1)
+    return false
+
+  // 状态为0(待支付)时可以取消订单
+  if (status === 0)
+    return true
+
+  // 状态为60(已退款)或80(已完成)时不显示
+  if (status === 60 || status === 80)
+    return false
+
+  // 其他状态:没有退款申请或申请已通过时可以再次申请
+  return cancelState == null || cancelState === 1
+})
+
+const isCancel = computed(() => statusValue.value === 0)
+
+/** 取消订单 / 申请退款 */
+async function handleCancelOrder() {
+  orderPopup.value = false
+  useGlobalMessage().confirm({
+    title: '提示',
+    msg: `确定要${isCancel.value ? '取消订单' : '退款'}吗?`,
+    success: async () => {
+      if (isCancel.value) {
+        await Apis.attractions.cancelOrder({
+          data: {
+            orderNumber: orderInfo.value?.orderNumber || '',
+            cancelNum: refundNum.value,
+            cancelMemo: refundReason.value || undefined,
+          },
+        })
+      }
+      else {
+        await Apis.xsb.applyRefund({
+          data: {
+            businessType: 2,
+            buyerDesc: refundReason.value || undefined,
+            orderNumber: orderInfo.value?.orderNumber || '',
+          },
+        })
+      }
+      refundNum.value = 1
+      refundReason.value = ''
+      useGlobalToast().show({ msg: '操作成功' })
+      await getData(orderNumber.value)
+    },
+  })
+}
+
+onLoad((options: any) => {
+  orderNumber.value = options.orderNo
+  ispay.value = options.ispay
+  getData(options.orderNo)
+})
+onMounted(() => {
+  opcity.value = 0
+})
+
+onPageScroll((e) => {
+  const calculatedOpacity = e.scrollTop / 100
+  opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))
+})
+
+function orderDetailBack() {
+  const vrIndex = 'subPack-attractions/commonTab/index'
+  const pages = getCurrentPages()
+  const targetPageIndex = pages.findIndex(page => page.route === vrIndex)
+  if (ispay.value === 'true') {
+    if (targetPageIndex !== -1) {
+      const delta = pages.length - targetPageIndex - 1
+      router.back({ delta, animationType: 'fade-out' })
+    }
+  }
+  else {
+    router.back()
+  }
+}
+</script>
+
+<template>
+  <view class="order-detail-page">
+    <wd-navbar
+      title="景区门票"
+      :custom-style="`background-color: rgba(226, 255, 145, ${opcity})`"
+      :bordered="false"
+      :z-index="9999"
+      safe-area-inset-top
+      left-arrow
+      fixed
+      @click-left="orderDetailBack"
+    />
+    <view :style="{ height: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 30}px` }" />
+    <view v-if="orderInfo" class="px-24rpx">
+      <view class="rounded-16rpx bg-#FFF p-24rpx">
+        <OrderDetailStatus v-if="!hasVoucher || orderInfo.hbOrderStatus == 60" :status="statusValue" @pay="handleGoPay" @rebook="handleRebook" />
+        <view class="flex items-center justify-between gap-50rpx text-32rpx font-bold">
+          <view>{{ orderInfo.scenicOrder?.productName }}</view>
+          <view class="w-100rpx text-24rpx text-#9ED605" @click="router.push({ name: 'attractions-detail', params: { productNo: String(orderInfo.scenicOrder?.productNo) } })">
+            详情
+          </view>
+        </view>
+        <view v-if="hasVoucher && orderInfo.hbOrderStatus != 60" class="text-center">
+          <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+          <view class="mt-24rpx flex items-center justify-center gap-10rpx">
+            <wd-icon :name="currentStatus.icon" size="20px" :color="currentStatus.color" />
+            <text class="text-32rpx font-bold" :style="{ color: currentStatus.color }">
+              {{ currentStatus.label }}
+            </text>
+          </view>
+          <swiper
+            :style="{ height: '340rpx' }"
+            :current="swiperCurrent"
+            :indicator-dots="false"
+            @change="onSwiperChange"
+          >
+            <swiper-item v-for="(people, idx) in voucherPeoples" :key="idx" class="flex flex-col items-center justify-center">
+              <view class="flex items-center justify-center">
+                <QCode class="mb-20rpx rounded-16rpx" :text="people.voucherCode || ''" :qwidth="80" :qr-key="`qr-${idx}`" />
+              </view>
+              <view class="text-28rpx font-bold">
+                {{ people.voucherCode }}
+              </view>
+              <view class="mt-8rpx text-24rpx text-#AAAAAA">
+                ({{ people.voucherStatus === 1 ? '已核销' : '未核销' }})
+              </view>
+            </swiper-item>
+          </swiper>
+          <view class="text-24rpx text-#AAAAAA">
+            {{ currentStatus.desc }}
+          </view>
+          <view class="mt-24rpx flex items-center justify-center gap-10rpx" @click="router.push({ name: 'attractions-tabbar', params: { tabbar: '1' } })">
+            <text class="text-28rpx">
+              查看订单列表
+            </text>
+            <wd-icon name="chevron-right" size="20px" />
+          </view>
+        </view>
+      </view>
+      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx text-#AAAAAA">
+            订单编号
+          </view>
+          <view class="text-28rpx font-bold">
+            {{ orderInfo.orderNumber }}
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx text-#AAAAAA">
+            下单时间
+          </view>
+          <view class="text-28rpx font-bold">
+            {{ orderInfo.createTime }}
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx text-#AAAAAA">
+            游玩时间
+          </view>
+          <view class="text-28rpx font-bold">
+            {{ orderInfo.scenicOrder?.travelDate }} 当天
+          </view>
+        </view>
+        <view v-if="orderInfo.scenicOrder?.orderMemo" class="mt-28rpx rounded-16rpx bg-#F1F1F1 p-24rpx text-28rpx text-#AAAAAA">
+          备注:{{ orderInfo.scenicOrder?.orderMemo }}
+        </view>
+      </view>
+      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="flex items-center justify-between">
+          <view class="text-bold text-28rpx">
+            订单总金额
+          </view>
+          <view class="text-bold text-32rpx text-#FF4A39">
+            <text class="text-24rpx">
+              ¥
+            </text>
+            {{ orderInfo.orderMoney }}
+          </view>
+        </view>
+        <view v-if="orderInfo.offsetPoints" class="mt-20rpx flex items-center justify-between text-24rpx">
+          <view>积分扣减</view>
+          <view class="text-#FF4A39">
+            ¥{{ orderInfo.offsetPoints }}
+          </view>
+        </view>
+        <view class="mt-20rpx flex items-center justify-between text-24rpx">
+          <view>微信支付</view>
+          <view class="text-#FF4A39">
+            ¥{{ orderInfo.actualTotal }}
+          </view>
+        </view>
+      </view>
+      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="text-28rpx font-bold">
+          联系人资料
+        </view>
+        <view class="mt-24rpx flex items-center gap-92rpx">
+          <view class="text-24rpx">
+            联系人
+          </view>
+          <view class="text-bold text-24rpx">
+            {{ orderInfo.scenicOrder?.linkMan }}
+          </view>
+        </view>
+        <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+        <view class="mt-24rpx flex items-center gap-92rpx">
+          <view class="text-24rpx">
+            手机号码
+          </view>
+          <view class="text-bold text-24rpx">
+            {{ orderInfo.scenicOrder?.linkPhone }}
+          </view>
+        </view>
+      </view>
+      <!-- 游客信息 -->
+      <view v-for="(people, idx) in orderInfo.peoples" :key="idx" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="text-28rpx font-bold">
+          游客信息{{ (orderInfo.peoples?.length ?? 0) > 1 ? ` ${idx + 1}` : '' }}
+        </view>
+        <view class="mt-24rpx flex items-center gap-92rpx">
+          <view class="text-24rpx">
+            游客姓名
+          </view>
+          <view class="text-bold text-24rpx">
+            {{ people.linkMan }}
+          </view>
+        </view>
+        <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+        <view class="mt-24rpx flex items-center gap-92rpx">
+          <view class="text-24rpx">
+            证件类型
+          </view>
+          <view class="text-bold text-24rpx">
+            {{ creditTypeText(people.linkCreditType) }}
+          </view>
+        </view>
+        <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+        <view class="mt-24rpx flex items-center gap-92rpx">
+          <view class="text-24rpx">
+            证件号码
+          </view>
+          <view class="text-bold text-24rpx">
+            {{ people.linkCreditNo }}
+          </view>
+        </view>
+      </view>
+      <view v-if="orderInfo.cancelRecords?.cancelId" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="text-28rpx font-bold">
+          退款申请
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx text-#AAAAAA">
+            申请时间
+          </view>
+          <view class="text-28rpx font-bold">
+            {{ orderInfo.cancelRecords?.createTime }}
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx text-#AAAAAA">
+            申请说明
+          </view>
+          <view class="text-28rpx font-bold">
+            {{ orderInfo.cancelRecords?.cancelReason || '--' }}
+          </view>
+        </view>
+        <view class="mt-28rpx flex items-center justify-between">
+          <view class="text-28rpx text-#AAAAAA">
+            处理状态
+          </view>
+          <view v-if="orderInfo.cancelRecords" class="text-28rpx font-bold">
+            <text v-if="orderInfo.cancelRecords?.cancelState === 0">
+              申请中
+            </text>
+            <text v-if="orderInfo.cancelRecords?.cancelState === 1">
+              通过
+            </text>
+            <text v-if="orderInfo.cancelRecords?.cancelState === 2">
+              拒绝
+            </text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view class="h-220rpx" />
+    <view
+      class="fixed bottom-0 left-0 z-100 box-border h-174rpx w-full flex items-center gap-28rpx bg-#FFF px-24rpx"
+      style="border-top: 2rpx solid #EEEEEE;"
+    >
+      <view class="flex items-center gap-40rpx">
+        <view @click="router.replace({ name: 'attractions-tabbar' })">
+          <image
+            :src="`${StaticUrl}/goods-home.png`"
+            class="h44rpx w44rpx"
+          />
+          <view class="text-20rpx">
+            首页
+          </view>
+        </view>
+        <view class="relative">
+          <image
+            :src="`${StaticUrl}/goods-kf.png`"
+            class="h44rpx w44rpx"
+          />
+          <Zcontact>
+            <view class="text-20rpx">
+              客服
+            </view>
+          </Zcontact>
+        </view>
+      </view>
+      <wd-button v-if="showCancelOrRefundButton" custom-class="w-546rpx" block size="large" @click="orderPopup = true">
+        {{ isCancel ? '取消订单' : '退款申请' }}
+      </wd-button>
+    </view>
+    <Zpopup v-model="orderPopup" :showfooter="false" :zindex="9999" bg="#fff">
+      <view>
+        <view class="mt-28rpx text-center text-32rpx font-bold">
+          {{ isCancel ? '取消订单' : '退款申请' }}
+        </view>
+        <view class="px-24rpx">
+          <view class="mt-30rpx flex items-center justify-between">
+            <view class="text-28rpx">
+              退款数量
+            </view>
+            <view v-if="isCancel" class="flex items-center gap-24rpx">
+              <view
+                class="h-36rpx w-36rpx rounded-50% bg-#F0F0F0 text-center text-28rpx text-#AAAAAA font-600 line-height-[36rpx]"
+                @click="handleRefundMinus"
+              >
+                -
+              </view>
+              <view class="text-24rpx font-400">
+                {{ refundNum }}
+              </view>
+              <view
+                class="h-36rpx w-36rpx rounded-50% bg-#E8FFA7 text-center text-28rpx text-#9ED605 font-600 line-height-[36rpx]"
+                @click="handleRefundPlus"
+              >
+                +
+              </view>
+            </view>
+            <view v-else class="text-24rpx font-400">
+              {{ orderInfo?.scenicOrder?.num ?? 0 }}
+            </view>
+          </view>
+          <view class="mt-26rpx">
+            <view class="text-28rpx">
+              退款申请说明
+            </view>
+            <view class="mt-20rpx rounded-16rpx bg-#F1F1F1">
+              <textarea
+                v-model="refundReason"
+                class="h-120rpx w-full rounded-16rpx p-24rpx"
+                placeholder-style="color: #AAAAAA; font-size: 24rpx;"
+                placeholder="请仔细填写,提交后进入审核期,不可重复提交"
+              />
+            </view>
+          </view>
+        </view>
+        <view class="mt-26rpx h-2rpx w-full bg-#EEEEEE" />
+        <view class="flex items-center justify-center">
+          <wd-button custom-class="w-702rpx mt-10rpx" block size="large" @click="handleCancelOrder">
+            确认提交
+          </wd-button>
+        </view>
+        <view class="h-60rpx" />
+      </view>
+    </Zpopup>
+  </view>
+</template>
+
+<style lang="scss" scoped>
+</style>

+ 30 - 0
src/subPack-attractions/attractionsOrderDetail/orderDetail-data.ts

@@ -0,0 +1,30 @@
+export const orderStatus = [
+  {
+    value: 0,
+    label: '待支付',
+    desc: '请在60分钟内完成支付,逾期订单自动取消',
+    icon: 'time-filled',
+    color: '#FFC130',
+  },
+  {
+    value: 70,
+    label: '已支付',
+    desc: '您的订单已付款,您可以查看或者预定更多产品',
+    icon: 'check-circle-filled',
+    color: '#52C41A',
+  },
+  {
+    value: 80,
+    label: '已完成',
+    desc: '您的订单已完成,您可以查看或者预定更多产品',
+    icon: 'check-circle-filled',
+    color: '#52C41A',
+  },
+  {
+    value: 60,
+    label: '已取消',
+    desc: '您的订单已取消,如需帮助请联系客服',
+    icon: 'close-circle-filled',
+    color: '#AAAAAA',
+  },
+]

+ 110 - 0
src/subPack-attractions/attractionsOrderPay/attractionsOrderPay.vue

@@ -0,0 +1,110 @@
+<script setup lang="ts">
+import router from '@/router'
+
+definePage({
+  name: 'attractions-order-pay',
+  islogin: false,
+  style: {
+    navigationBarTitleText: '订单支付',
+  },
+})
+const productName = ref('')
+const num = ref(0)
+const orderNo = ref('')
+onLoad((options: any) => {
+  productName.value = options.productName || ''
+  num.value = Number(options.num) || 0
+  orderNo.value = options.orderNo || ''
+})
+
+onMounted(() => {
+  getPayPreview()
+})
+
+const payPreviewInfo = ref<Api.ScenicPayPreviewVo>()
+const payMethod = ref(['1']) // 默认选中微信支付
+async function getPayPreview() {
+  const res = await Apis.attractions.payPreview({ data: { orderNumber: orderNo.value } })
+  payPreviewInfo.value = res.data
+}
+
+async function submitPay() {
+  const res = await useUserStore().handleCommonPayMent(orderNo.value)
+  if (res.payType !== 1) {
+    try {
+      await useUserStore().getWxCommonPayment(res)
+      router.replace({ name: 'attractions-order-detail', params: { orderNo: String(payPreviewInfo.value?.orderNumber), ispay: 'true' } })
+    }
+    catch {
+      await useUserStore().payError('attractions-tabbar', 'subPack-attractions/commonTab/index')
+    }
+  }
+  else {
+    router.replace({ name: 'attractions-order-detail', params: { orderNo: String(payPreviewInfo.value?.orderNumber), ispay: 'true' } })
+  }
+}
+</script>
+
+<template>
+  <view class="order-pay-page">
+    <view class="px-24rpx">
+      <view class="h-20rpx" />
+      <view class="rounded-16rpx bg-#FFF p-24rpx">
+        <view class="flex items-center justify-between gap-50rpx text-32rpx font-bold">
+          <view>{{ productName }}</view>
+          <view class="text-28rpx font-normal">
+            x{{ num }}
+          </view>
+        </view>
+        <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+        <view class="mt-24rpx flex items-center justify-between">
+          <view class="text-28rpx font-bold">
+            订单总金额
+          </view>
+          <view class="text-32rpx text-#FF4A39 font-bold">
+            <text class="text-26rpx">
+              ¥
+            </text>
+            {{ payPreviewInfo?.orderTotal }}
+          </view>
+        </view>
+        <view class="mt-20rpx flex items-center justify-between text-24rpx">
+          <view>积分扣减</view>
+          <view class="text-#FF4A39 font-bold">
+            ¥{{ payPreviewInfo?.pointsDeduct }}
+          </view>
+        </view>
+        <view class="mt-20rpx flex items-center justify-between text-24rpx">
+          <view>微信支付</view>
+          <view class="text-#FF4A39 font-bold">
+            ¥{{ payPreviewInfo?.wxPayMoney }}
+          </view>
+        </view>
+      </view>
+      <view v-if="(payPreviewInfo?.wxPayMoney ?? 0) > 0" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+        <view class="text-32rpx font-bold">
+          选择支付方式
+        </view>
+        <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+        <view>
+          <wd-cell-group border>
+            <wd-checkbox-group v-model="payMethod" size="large">
+              <wd-cell title="微信支付" center clickable>
+                <view>
+                  <wd-checkbox model-value="1" custom-style="margin:0;" />
+                </view>
+              </wd-cell>
+            </wd-checkbox-group>
+          </wd-cell-group>
+        </view>
+      </view>
+    </view>
+    <view class="fixed bottom-0 h-174rpx w-full border-[1rpx_solid_#EEEEEE] bg-#FFF px-24rpx">
+      <wd-button custom-class="w-702rpx mt-10rpx" block size="large" @click="submitPay">
+        立即支付
+      </wd-button>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 228 - 29
src/subPack-attractions/attractionsReservation/attractionsReservation.vue

@@ -1,4 +1,7 @@
 <script setup lang="ts">
+import { columns } from './reservation-data'
+import router from '@/router'
+
 definePage({
   name: 'attractions-reservation-info',
   islogin: true,
@@ -6,12 +9,176 @@ definePage({
     navigationBarTitleText: '预定信息',
   },
 })
-const columns = ref(['选项1', '选项2', '选项3', '选项4', '选项5', '选项6', '选项7'])
-const value = ref('选项1')
+
+const productNo = ref(0)
+const productName = ref('')
+const selectDate = ref('')
+const isSingle = ref()
+const price = ref(0)
+onLoad((options: any) => {
+  productNo.value = Number(options.productNo) || 0
+  productName.value = options.productName || ''
+  selectDate.value = options.selectDate || ''
+  price.value = Number(options.price)
+  isSingle.value = Number(options.isSingle)
+})
+
+// 数量选择
+const quantity = ref(1)
+function handleMinus() {
+  if (quantity.value > 1) {
+    quantity.value--
+  }
+}
+function handlePlus() {
+  quantity.value++
+}
+
+// 合计价格
+const totalPrice = computed(() => price.value * quantity.value)
+
+// 联系人信息
+const linkMan = ref('')
+const linkCreditType = ref(0)
+const linkCreditNo = ref('')
+const linkPhone = ref('')
+
+// 多游客信息列表
+interface PeopleInfo {
+  linkMan: string
+  linkCreditType: number
+  linkCreditNo: string
+}
+const peopleList = ref<PeopleInfo[]>([{ linkMan: '', linkCreditType: 0, linkCreditNo: '' }])
+
+// 监听数量变化,同步游客信息列表
+watch(quantity, (newVal) => {
+  if (isSingle.value === 1) {
+    const diff = newVal - peopleList.value.length
+    if (diff > 0) {
+      for (let i = 0; i < diff; i++) {
+        peopleList.value.push({ linkMan: '', linkCreditType: 0, linkCreditNo: '' })
+      }
+    }
+    else if (diff < 0) {
+      peopleList.value.splice(newVal)
+    }
+  }
+})
+
 const orderPopup = ref(false)
+const orderMemo = ref('')
+
+const formattedDate = computed(() => {
+  if (!selectDate.value)
+    return ''
+  const date = new Date(selectDate.value)
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  return `${year}年${month}月${day}日`
+})
 
-function handleConfirm({ value: selectedValue }: { value: string }) {
-  value.value = selectedValue
+// 接口需要的日期格式 yyyy-MM-dd
+const travelDate = computed(() => {
+  if (!selectDate.value)
+    return ''
+  const date = new Date(selectDate.value)
+  const year = date.getFullYear()
+  const month = String(date.getMonth() + 1).padStart(2, '0')
+  const day = String(date.getDate()).padStart(2, '0')
+  return `${year}-${month}-${day}`
+})
+
+const { data: info } = useRequest(() =>
+  Apis.xsb.findUserPoints({}),
+)
+
+function handleLinkCreditConfirm({ value: selectedValue }: { value: number }) {
+  linkCreditType.value = selectedValue
+}
+
+function handlePeopleCreditConfirm(index: number, { value: selectedValue }: { value: number }) {
+  peopleList.value[index].linkCreditType = selectedValue
+}
+
+// 表单校验
+function validateForm(): boolean {
+  // 联系人姓名校验
+  if (!linkMan.value.trim()) {
+    useGlobalToast().show({ msg: '请输入联系人姓名' })
+    return false
+  }
+
+  // 单游客模式需要校验证件号码
+  if (isSingle.value === 0) {
+    if (!linkCreditNo.value.trim()) {
+      useGlobalToast().show({ msg: '请输入证件号码' })
+      return false
+    }
+  }
+
+  // 手机号码校验
+  if (!linkPhone.value.trim()) {
+    useGlobalToast().show({ msg: '请输入手机号码' })
+    return false
+  }
+
+  // 多游客模式校验游客信息
+  if (isSingle.value === 1) {
+    for (let i = 0; i < peopleList.value.length; i++) {
+      const people = peopleList.value[i]
+      if (!people.linkMan.trim()) {
+        useGlobalToast().show({ msg: `请输入游客${i + 1}姓名` })
+        return false
+      }
+      if (!people.linkCreditNo.trim()) {
+        useGlobalToast().show({ msg: `请输入游客${i + 1}证件号码` })
+        return false
+      }
+    }
+  }
+
+  return true
+}
+
+// 提交订单
+async function handleSubmit() {
+  // 表单校验
+  if (!validateForm())
+    return
+
+  const peoples: Api.PeopleItem[] = isSingle.value === 1
+    ? peopleList.value.map(p => ({
+        linkMan: p.linkMan,
+        linkCreditType: p.linkCreditType,
+        linkCreditNo: p.linkCreditNo,
+      }))
+    : []
+
+  const params: Api.CreateOrderRequest = {
+    productNo: productNo.value,
+    productName: productName.value,
+    num: quantity.value,
+    travelDate: travelDate.value,
+    linkMan: linkMan.value,
+    linkCreditType: isSingle.value === 0 ? linkCreditType.value : undefined,
+    linkCreditNo: isSingle.value === 0 ? linkCreditNo.value : undefined,
+    linkPhone: linkPhone.value,
+    orderMemo: orderMemo.value,
+    peoples: isSingle.value === 1 ? peoples : undefined,
+  }
+
+  try {
+    useGlobalLoading().loading({ msg: '提交中...' })
+    const res = await Apis.attractions.createOrder({ data: params })
+    useGlobalLoading().close()
+    router.push({ name: 'attractions-order-pay', params: { productName: productName.value, num: String(quantity.value), orderNo: res?.data } })
+  }
+  catch (error) {
+    useGlobalLoading().close()
+    console.error('提交订单失败', error)
+  }
 }
 </script>
 
@@ -21,12 +188,12 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
       <view class="h-20rpx" />
       <view class="rounded-16rpx bg-#FFF p-24rpx">
         <view class="text-32rpx font-bold">
-          日场门票+观光车+飞越黄果树观影票+吉祥物+冰箱贴 经典必打卡
+          {{ productName }}
         </view>
         <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
         <view class="mt-24rpx flex items-center gap-10rpx text-28rpx">
           <wd-icon name="calendar" size="22px" />
-          <text>选定日期:2026年3月22日</text>
+          <text>选定日期:{{ formattedDate }}</text>
         </view>
       </view>
       <view class="mt-20rpx flex items-center justify-between rounded-16rpx bg-#FFF p-24rpx">
@@ -34,82 +201,92 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
           选择数量
         </view>
         <view class="flex items-center gap-24rpx">
-          <view class="h-36rpx w-36rpx rounded-50% bg-#F0F0F0 text-center text-28rpx text-#AAAAAA font-600 line-height-[36rpx]">
+          <view
+            class="h-36rpx w-36rpx rounded-50% text-center text-28rpx font-600 line-height-[36rpx]"
+            :class="quantity > 1 ? 'bg-#E8FFA7 text-#9ED605' : 'bg-#F0F0F0 text-#AAAAAA'"
+            @click="handleMinus"
+          >
             -
           </view>
           <view class="text-24rpx font-400">
-            10
+            {{ quantity }}
           </view>
-          <view class="h-36rpx w-36rpx rounded-50% bg-#E8FFA7 text-center text-28rpx text-#9ED605 font-600 line-height-[36rpx]">
+          <view
+            class="h-36rpx w-36rpx rounded-50% bg-#E8FFA7 text-center text-28rpx text-#9ED605 font-600 line-height-[36rpx]"
+            @click="handlePlus"
+          >
             +
           </view>
         </view>
       </view>
       <!-- 单游客start -->
-      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+      <view v-if="isSingle === 0" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
         <view class="text-28rpx font-bold">
           联系人
         </view>
         <view>
-          <wd-input placeholder="请输入联系人姓名" label="联系人姓名" required />
+          <wd-input v-model="linkMan" placeholder="请输入联系人姓名" label="联系人姓名" required />
         </view>
         <view class="h-2rpx w-full bg-#F0F0F0" />
         <view>
-          <wd-picker v-model="value" required :columns="columns" label="证件类型" @confirm="handleConfirm" />
+          <wd-picker v-model="linkCreditType" required :columns="columns" label="证件类型" @confirm="handleLinkCreditConfirm" />
         </view>
         <view class="h-2rpx w-full bg-#F0F0F0" />
         <view>
-          <wd-input placeholder="请输入证件号码" label="证件号码" required />
+          <wd-input v-model="linkCreditNo" placeholder="请输入证件号码" label="证件号码" required />
         </view>
         <view class="h-2rpx w-full bg-#F0F0F0" />
         <view>
-          <wd-input placeholder="请输入手机号码" label="手机号码" required />
+          <wd-input v-model="linkPhone" placeholder="请输入手机号码" label="手机号码" required />
         </view>
       </view>
       <!-- 单游客end -->
       <!-- 多游客start -->
-      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+      <view v-if="isSingle === 1" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
         <view class="text-28rpx font-bold">
           联系人
         </view>
         <view>
-          <wd-input placeholder="请输入联系人姓名" label="联系人姓名" required />
+          <wd-input v-model="linkMan" placeholder="请输入联系人姓名" label="联系人姓名" required />
         </view>
         <view class="h-2rpx w-full bg-#F0F0F0" />
         <view>
-          <wd-input placeholder="请输入手机号码" label="手机号码" required />
+          <wd-input v-model="linkPhone" placeholder="请输入手机号码" label="手机号码" required />
         </view>
       </view>
-      <view class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
+      <view v-for="(people, index) in peopleList" :key="index" class="mt-20rpx rounded-16rpx bg-#FFF p-24rpx">
         <view class="text-28rpx font-bold">
-          游客信息
+          游客信息{{ index + 1 }}
         </view>
         <view>
-          <wd-input placeholder="请输入游客姓名" label="游客姓名1" required />
+          <wd-input v-model="people.linkMan" placeholder="请输入游客姓名" :label="`游客姓名${index + 1}`" required />
         </view>
         <view class="h-2rpx w-full bg-#F0F0F0" />
         <view>
-          <wd-picker v-model="value" required :columns="columns" label="证件类型" @confirm="handleConfirm" />
+          <wd-picker v-model="people.linkCreditType" required :columns="columns" label="证件类型" @confirm="(e: { value: number }) => handlePeopleCreditConfirm(index, e)" />
         </view>
         <view class="h-2rpx w-full bg-#F0F0F0" />
         <view>
-          <wd-input placeholder="请输入证件号码" label="证件号码" required />
+          <wd-input v-model="people.linkCreditNo" placeholder="请输入证件号码" label="证件号码" required />
         </view>
       </view>
       <!-- 多游客end -->
       <view class="mt-20rpx rounded-16rpx bg-#FFF">
-        <wd-input placeholder="如有特殊需要,请留言" label="订单备注" />
+        <wd-input v-model="orderMemo" placeholder="如有特殊需要,请留言" label="订单备注" />
       </view>
       <view class="mt-20rpx flex items-center justify-between rounded-16rpx bg-#FFF p-24rpx">
         <view class="text-28rpx">
           当前可用积分
         </view>
         <view class="text-32rpx font-bold">
-          1000积分
+          {{ info?.data?.availablePointsTotal || 0 }}积分
         </view>
       </view>
+      <view class="h-190rpx" />
     </view>
-    <view class="fixed bottom-0 left-0 z-100 box-border h-174rpx w-full flex items-center justify-between bg-#FFF px-24rpx">
+    <view
+      class="fixed bottom-0 left-0 z-100 box-border h-174rpx w-full flex items-center justify-between bg-#FFF px-24rpx"
+    >
       <view class="flex items-center">
         <view class="text-24rpx">
           合计
@@ -118,7 +295,7 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
           <text class="text-26rpx">
           </text>
-          290
+          {{ totalPrice }}
         </view>
       </view>
       <view class="flex items-center gap-20rpx">
@@ -128,13 +305,35 @@ function handleConfirm({ value: selectedValue }: { value: string }) {
           </text>
           <wd-icon name="arrow-up" size="18px" />
         </view>
-        <view class="h-80rpx w-180rpx rounded-40rpx bg-#9ED605 text-center text-28rpx text-#FFF font-bold line-height-[80rpx]">
+        <view
+          class="h-80rpx w-180rpx rounded-40rpx bg-#9ED605 text-center text-28rpx text-#FFF font-bold line-height-[80rpx]"
+          @click="handleSubmit"
+        >
           提交
         </view>
       </view>
     </view>
-    <Zpopup v-model="orderPopup" :zindex="9999">
-      <view>明细</view>
+    <Zpopup v-model="orderPopup" :zindex="99" bg="#fff">
+      <view class="p-24rpx">
+        <view class="text-center text-28rpx font-bold">
+          订单明细
+        </view>
+        <view class="mt-24rpx h-2rpx w-full bg-#F0F0F0" />
+        <view class="mt24rpx text-28rpx">
+          <view class="flex items-center gap-56rpx">
+            <view>{{ productName }}</view>
+            <view>
+              <text class="text-#FF4A39 font-bold">
+                ¥{{ price }}
+              </text>
+              <text>×{{ quantity }}</text>
+            </view>
+          </view>
+          <view class="mt-20rpx">
+            {{ formattedDate }}
+          </view>
+        </view>
+      </view>
     </Zpopup>
   </view>
 </template>

+ 24 - 0
src/subPack-attractions/attractionsReservation/reservation-data.ts

@@ -0,0 +1,24 @@
+export const columns = ref([
+  { label: '身份证', value: 0 },
+  { label: '学生证', value: 1 },
+  { label: '军官证', value: 2 },
+  { label: '护照', value: 3 },
+  { label: '户口本(儿童请选择此项)', value: 4 },
+  { label: '港澳通行证', value: 5 },
+  { label: '台湾居民来往大陆通行证', value: 6 },
+  { label: '台湾通行证', value: 7 },
+  { label: '入台证', value: 8 },
+  { label: '香港居民往来内地通行证', value: 9 },
+  { label: '警官证', value: 10 },
+  { label: '驾驶证', value: 11 },
+  { label: '海员证', value: 12 },
+  { label: '外国人在中国永久居留证', value: 13 },
+  { label: '澳门居民往来内地通行证', value: 14 },
+  { label: '港澳居民来往内地通行证', value: 15 },
+  { label: '港澳台居民来往内地通行证', value: 16 },
+  { label: '港澳台居民居住证', value: 17 },
+  { label: '中华人民共和国旅行证', value: 18 },
+  { label: '回乡证', value: 19 },
+  { label: '台胞证', value: 20 },
+  { label: '香港身份证', value: 21 },
+])

+ 76 - 28
src/subPack-attractions/commonTab/components/homeList.vue

@@ -2,11 +2,51 @@
 import router from '@/router'
 import { StaticUrl } from '@/config'
 
+const globalToast = useGlobalToast()
 const { statusBarHeight, MenuButtonHeight, opcity } = storeToRefs(useSysStore())
-
+/**
+ * 获取景区列表
+ */
+const loading = ref(true)
+const productName = ref('')
+const { data: attractionsList, isLastPage, page, refresh, error, reload } = usePagination((pageNum, pageSize) =>
+  Apis.attractions.findAppByPage({ data: { pageNum, pageSize, productName: productName.value } }), {
+  data: (resp) => {
+    return resp.data?.list
+  },
+  initialData: [],
+  initialPage: 1,
+  initialPageSize: 10,
+  append: true,
+  immediate: true,
+}).onSuccess(() => {
+  loading.value = false
+})
+const state = computed(() => {
+  return error.value ? 'error' : !isLastPage.value ? 'loading' : 'finished'
+})
+onReachBottom(() => {
+  if (!isLastPage.value) {
+    page.value++
+  }
+})
 onMounted(() => {
   opcity.value = 0
 })
+
+function handleSearch() {
+  if (productName.value === '') {
+    return globalToast.warning('搜索内容不能为空')
+  }
+  page.value = 1
+  refresh()
+}
+
+function handleClear() {
+  productName.value = ''
+  page.value = 1
+  refresh()
+}
 </script>
 
 <template>
@@ -28,14 +68,16 @@ onMounted(() => {
 
       <view class="absolute left-24rpx right-24rpx top-198rpx">
         <view class="h-60rpx w-full flex items-center justify-between rounded-40rpx bg-white pr-6rpx">
-          <view class="flex items-center pb-14rpx pl-24rpx pt-16rpx">
+          <view class="flex flex-1 items-center pb-14rpx pl-24rpx pt-16rpx">
             <wd-icon name="search" size="14" color="#ccc" />
-            <view class="ml-12rpx text-24rpx text-gray">
-              霸王茶姬
+            <input v-model="productName" type="text" placeholder="请输入景区名称" class="ml-12rpx h-30rpx w-full flex-1 text-24rpx outline-none" placeholder-style="color:#AAA" @confirm="handleSearch">
+            <view v-if="productName" class="w-80rpx flex items-center justify-center" @click="handleClear">
+              <wd-icon name="close" size="14" color="#ccc" class="mr-12rpx" />
             </view>
           </view>
           <view
             class="h-50rpx w-96rpx flex items-center justify-center rounded-26rpx bg-[var(--them-color)] text-24rpx text-white font-semibold"
+            @click="handleSearch"
           >
             搜索
           </view>
@@ -45,33 +87,39 @@ onMounted(() => {
 
     <view class="relative px-24rpx">
       <view>
-        <view v-for="value in 12" :key="value" class="mb-20rpx flex items-center gap-24rpx rounded-16rpx bg-#FFF p-24rpx" @click="router.push({ name: 'attractions-detail' })">
-          <view class="h-160rpx w-160rpx rounded-16rpx">
-            icon
-          </view>
-          <view class="flex-1">
-            <view class="text-32rpx font-bold">
-              日场门票+观光车+飞越黄果树观影票+吉祥物+冰箱贴
-            </view>
-            <view class="mt-24rpx flex items-center justify-between">
-              <view>
-                <text class="text-26rpx text-#FF4D3A">
-                  ¥
-                </text>
-                <text class="text-36rpx text-#FF4D3A font-bold">
-                  290
-                </text>
-                <text class="text-24rpx text-#AAA">
-                  起
-                </text>
-              </view>
+        <scroll-view scroll-y type="custom">
+          <wd-skeleton theme="paragraph" animation="gradient" :loading="loading" :row-col="[{ height: '100px', width: '100%' }, { height: '100px', width: '100%' }, { height: '100px', width: '100%' }]">
+            <view v-for="item in attractionsList" :key="item.productNo" class="mb-20rpx flex items-center gap-24rpx rounded-16rpx bg-#FFF p-24rpx" @click="router.push({ name: 'attractions-detail', params: { productNo: String(item.productNo) } })">
               <image
-                class="h-48rpx w-116rpx"
-                :src="`${StaticUrl}/attractions-home-btn.png`"
+                class="h-160rpx w-160rpx rounded-16rpx"
+                :src="item.img"
               />
+              <view class="flex-1">
+                <view class="text-32rpx font-bold">
+                  {{ item.productName }}
+                </view>
+                <view class="mt-24rpx flex items-center justify-between">
+                  <view>
+                    <text class="text-26rpx text-#FF4D3A">
+                      ¥
+                    </text>
+                    <text class="text-36rpx text-#FF4D3A font-bold">
+                      {{ item.salePrice }}
+                    </text>
+                    <text class="text-24rpx text-#AAA">
+                      起
+                    </text>
+                  </view>
+                  <image
+                    class="h-48rpx w-116rpx"
+                    :src="`${StaticUrl}/attractions-home-btn.png`"
+                  />
+                </view>
+              </view>
             </view>
-          </view>
-        </view>
+          </wd-skeleton>
+        </scroll-view>
+        <wd-loadmore :state="state" :loading-props="{ color: '#9ED605', size: 20 }" @reload="reload" />
       </view>
     </view>
   </view>

+ 63 - 2
src/subPack-attractions/commonTab/components/orderList.vue

@@ -1,15 +1,76 @@
 <script setup lang="ts">
+import { tabsList } from '../order-data'
+import attractionsList from '@/subPack-smqjh/components/attractions-orderList/attractions-orderList.vue?async'
+import { createGlobalLoadingMiddleware } from '@/api/core/middleware'
+
+const tab = ref<number>(0)
 const { statusBarHeight, MenuButtonHeight } = storeToRefs(useSysStore())
+
+// 状态映射:tab索引 -> 接口status
+const statusMap: Record<number, string> = {
+  0: 'all', // 全部
+  1: 'paddingPay', // 待支付
+  2: 'ing', // 已支付
+  3: 'cancel', // 已取消
+  4: 'completed', // 已完成
+}
+
+const { data: orderList, isLastPage, page, error, refresh, reload } = usePagination((pageNum, pageSize) => Apis.xsb.orderList({ data: {
+  businessType: 'JDMP',
+  pageNum,
+  pageSize,
+  orderStatus: statusMap[tab.value],
+} }), {
+  immediate: true,
+  pageNum: 1,
+  pageSize: 10,
+  initialData: [],
+  data: res => res.data?.list,
+  append: true,
+  middleware: createGlobalLoadingMiddleware(),
+})
+onShow(() => {
+  refresh()
+})
+function handleClick(e: { index: number }) {
+  tab.value = e.index
+  orderList.value = []
+  refresh()
+}
+
+onReachBottom(() => {
+  if (!isLastPage.value) {
+    page.value++
+    refresh()
+  }
+})
+const state = computed(() => {
+  return error.value ? 'error' : !isLastPage.value ? 'loading' : 'finished'
+})
 </script>
 
 <template>
-  <view class="video-rights-order-page">
+  <view class="attractions-order-page" style="min-height: 100vh; background-color: #f6f6f6;">
     <wd-navbar
       title="订单列表" custom-style="background-color:#FFF" :bordered="false" :z-index="99"
       safe-area-inset-top fixed
     />
     <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
-    订单
+    <wd-tabs v-model="tab" :offset-top="statusBarHeight + MenuButtonHeight + 12" sticky custom-style="background-color: transparent;" @click="handleClick">
+      <block v-for="(item, index) in tabsList" :key="index">
+        <wd-tab :title="item">
+          <view class="box-border w-full overflow-hidden px24rpx">
+            <view class="h-20rpx" />
+            <StatusTip v-if="!orderList.length" tip="暂无内容" />
+            <view v-for="order in orderList" :key="order.orderNumber">
+              <attractionsList :order="order" />
+            </view>
+            <wd-loadmore :state="state" :loading-props="{ color: '#9ED605', size: 20 }" @reload="reload" />
+            <view class="h-40rpx" />
+          </view>
+        </wd-tab>
+      </block>
+    </wd-tabs>
   </view>
 </template>
 

+ 5 - 2
src/subPack-attractions/commonTab/index.vue

@@ -14,10 +14,13 @@ definePage({
     navigationStyle: 'custom',
   },
 })
-
+onLoad((options: any) => {
+  if (options.tabbar) {
+    tabbar.value = Number(options.tabbar)
+  }
+})
 // 页面级滚动监听 - 必须在页面组件中才能生效
 onPageScroll((e) => {
-  // 只在首页 tab 时更新透明度
   if (tabbar.value === 0) {
     const calculatedOpacity = e.scrollTop / 100
     opcity.value = Math.min(1, Math.max(0.1, calculatedOpacity))

+ 1 - 0
src/subPack-attractions/commonTab/order-data.ts

@@ -0,0 +1 @@
+export const tabsList = ['全部', '待支付', '已支付', '已取消', '已完成']

+ 1 - 1
src/subPack-attractions/components/DatePicker.vue

@@ -169,7 +169,7 @@ watch(() => props.modelValue, (newVal) => {
       <view class="h60rpx w60rpx flex items-center justify-center" @click="prevMonth">
         <wd-icon name="arrow-left" size="20px" color="#999" />
       </view>
-      <view class="rounded-24rpx bg-#F5F5F5 px32rpx py12rpx text-28rpx">
+      <view class="rounded-16rpx bg-#E6E6E6 px12rpx px32rpx py12rpx py8rpx text-28rpx">
         {{ currentMonthText }}
       </view>
       <view class="h60rpx w60rpx flex items-center justify-center" @click="nextMonth">

+ 50 - 0
src/subPack-attractions/components/orderDetailStatus.vue

@@ -0,0 +1,50 @@
+<script setup lang="ts">
+import { orderStatus } from '../attractionsOrderDetail/orderDetail-data'
+import router from '@/router'
+
+const props = defineProps<{
+  status: number
+}>()
+
+const emit = defineEmits<{
+  (e: 'pay'): void
+  (e: 'rebook'): void
+}>()
+
+const currentStatus = computed(() => {
+  return orderStatus.find(item => item.value === props.status) || orderStatus[0]
+})
+</script>
+
+<template>
+  <view class="text-center">
+    <view class="flex items-center justify-center gap-10rpx">
+      <wd-icon :name="currentStatus.icon" size="20px" :color="currentStatus.color" />
+      <text class="text-32rpx font-bold" :style="{ color: currentStatus.color }">
+        {{ currentStatus.label }}
+      </text>
+    </view>
+    <view class="mt-20rpx text-24rpx text-#AAA">
+      {{ currentStatus.desc }}
+    </view>
+    <view v-if="props.status === 0" class="mt-20rpx">
+      <wd-button class="w-456rpx" type="primary" @click="emit('pay')">
+        去支付
+      </wd-button>
+    </view>
+    <view v-if="props.status === 60" class="mt-20rpx">
+      <wd-button class="w-456rpx" type="primary" @click="emit('rebook')">
+        重新预订
+      </wd-button>
+    </view>
+    <view class="mt-24rpx flex items-center justify-center gap-10rpx" @click="router.push({ name: 'attractions-tabbar', params: { tabbar: '1' } })">
+      <text class="text-28rpx">
+        查看订单列表
+      </text>
+      <wd-icon name="chevron-right" size="16px" />
+    </view>
+    <view class="my-24rpx h-2rpx w-full bg-#F0F0F0" />
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 29 - 5
src/subPack-charge/chargeVoucher/chargeVoucher.vue

@@ -60,7 +60,7 @@ async function submitPay() {
     return
   }
   try {
-    uni.showLoading({ title: '下单中...', mask: true })
+    await uni.showLoading({ title: '下单中...', mask: true })
     const orderRes = await Apis.charge.addPurchaseRecord({
       data: {
         couponAmount: selectedLevel.money,
@@ -71,7 +71,7 @@ async function submitPay() {
     const orderNumber = orderRes.data
     if (!orderNumber) {
       uni.hideLoading()
-      uni.showToast({ title: '下单失败', icon: 'none' })
+      await uni.showToast({ title: '下单失败', icon: 'none' })
       return
     }
     const payRes = await Apis.charge.wxJsApiPay({
@@ -81,14 +81,38 @@ async function submitPay() {
     })
     uni.hideLoading()
     await useUserStore().getWxCommonPayment(payRes.data)
-    useUserStore().paySuccess('charge-buy-a-ticket-list', '/subPack-charge/chargeBuyaTicketList/chargeBuyaTicketList')
+    await useUserStore().paySuccess('charge-buy-a-ticket-list', '/subPack-charge/chargeBuyaTicketList/chargeBuyaTicketList')
   }
   catch (error) {
     uni.hideLoading()
     console.error('支付失败:', error)
-    useUserStore().payError('charge-buy-a-ticket-list', '/subPack-charge/chargeBuyaTicketList/chargeBuyaTicketList')
+    await useUserStore().payError('charge-buy-a-ticket-list', '/subPack-charge/chargeBuyaTicketList/chargeBuyaTicketList')
   }
 }
+
+/**
+ * 申请退款
+ */
+function refund() {
+  useGlobalMessage().confirm({
+    title: '提示',
+    msg: '退款按照购券记录进行逐笔退款,可能产生多笔退款到账记录,请注意查收。',
+    success: async () => {
+      const res = await Apis.charge.userCouponRefund({})
+      if (res.code === '00000') {
+        useGlobalMessage().confirm({
+          title: '提示',
+          msg: '申请退款成功,预计3个工作日内分一笔或多笔退还,到期如未到账请联系客服!',
+          success: () => {
+            router.back()
+          },
+          fail: () => {
+          },
+        })
+      }
+    },
+  })
+}
 </script>
 
 <template>
@@ -121,7 +145,7 @@ async function submitPay() {
             充值记录
           </view>
           <view class="h-40rpx w-2rpx bg-#E6E6E6" />
-          <view @click="router.push({ name: 'charge-buy-a-ticket-list' })">
+          <view @click="refund">
             退款
           </view>
         </view>

+ 0 - 1
src/subPack-charge/index/index.vue

@@ -103,7 +103,6 @@ function handleFilterClick(filterKey: number) {
 /**
  * 申请退款
  */
-
 function refund() {
   useGlobalMessage().confirm({
     title: '提示',

+ 85 - 0
src/subPack-smqjh/components/attractions-orderList/attractions-orderList.vue

@@ -0,0 +1,85 @@
+<script setup lang="ts">
+import router from '@/router'
+
+const props = defineProps<{
+  order: Api.xsbOrderList
+}>()
+
+// 订单状态映射(hbOrderStatus)
+const statusMap: Record<number, { text: string, color: string }> = {
+  0: { text: '待支付', color: '#FF9500' },
+  60: { text: '已取消', color: '#999999' },
+  70: { text: '已支付', color: '#52C41A' },
+  80: { text: '已完成', color: '#52C41A' },
+}
+
+// 订单项点击
+function handleOrderClick(order: Api.ScenicOrderListVo | Api.xsbOrderList) {
+  router.push({ name: 'attractions-order-detail', params: { orderNo: String(order.orderNumber) } })
+}
+const statusInfo = computed(() => {
+  const status = props.order?.hbOrderStatus as number
+  return statusMap[status] ?? { text: '', color: '#999999' }
+})
+</script>
+
+<template>
+  <view class="mb-20rpx box-border w-full overflow-hidden rounded-16rpx bg-#FFF p-24rpx" @click="handleOrderClick(order)">
+    <view class="w-full flex items-center justify-between">
+      <view class="text-32rpx font-bold">
+        {{ order?.orderScenic.viewName }}
+      </view>
+      <view class="text-28rpx" :style="{ color: statusInfo.color }">
+        {{ statusInfo.text }}
+      </view>
+    </view>
+    <view class="mt-20rpx w-full flex items-center gap-20rpx">
+      <image v-if="order?.orderScenic.img" :src="order?.orderScenic.img" class="h-160rpx w-160rpx flex-shrink-0 rounded-8rpx" mode="aspectFill" />
+      <view v-else class="h-160rpx w-160rpx flex flex-shrink-0 items-center justify-center rounded-8rpx bg-#f5f5f5 text-#999">
+        暂无图片
+      </view>
+      <view class="min-w-0 flex-1">
+        <view class="line-clamp-2 text-28rpx font-bold">
+          {{ order?.orderScenic.productName }}
+        </view>
+        <view class="mt-20rpx text-24rpx text-#666">
+          游玩日期:{{ order?.orderScenic.travelDate }}
+        </view>
+      </view>
+    </view>
+    <view class="mt-24rpx flex items-center justify-between text-24rpx text-#999">
+      <view>订单编号:{{ order?.orderNumber }}</view>
+      <view>共{{ order?.orderScenic.num }}件商品</view>
+    </view>
+    <view class="mt-20rpx flex items-center justify-between">
+      <view class="text-24rpx text-#999">
+        下单时间:{{ order?.createTime }}
+      </view>
+      <view>
+        <text class="text-24rpx">
+          合计:
+        </text>
+        <text class="text-26rpx text-#FF4A39 font-bold">
+          ¥
+        </text>
+        <text class="text-bold text-32rpx text-#FF4A39">
+          {{ order?.total }}
+        </text>
+      </view>
+    </view>
+    <view v-if="order?.hbOrderStatus === 0" class="my-24rpx flex items-center justify-end">
+      <view class="mr-20rpx">
+        <wd-button size="small" plain type="info">
+          取消订单
+        </wd-button>
+      </view>
+      <view class="mr-20rpx">
+        <wd-button size="small" plain type="error">
+          付款
+        </wd-button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<style lang="scss" scoped></style>

+ 1 - 1
src/subPack-smqjh/components/videoRights-orderList/videoRights-orderList.vue

@@ -21,7 +21,7 @@ function handleItemClick(item: Api.xsbOrderList) {
 </script>
 
 <template>
-  <view class="mb-28rpx rounded-16rpx bg-#FFF p-24rpx" @click="handleItemClick(order)">
+  <view class="mb-20rpx rounded-16rpx bg-#FFF p-24rpx" @click="handleItemClick(order)">
     <view class="flex items-center justify-between">
       <view class="text-28rpx">
         {{ order.createTime }}

+ 5 - 0
src/subPack-smqjh/order/components/OrderRenderer.vue

@@ -5,6 +5,7 @@ import filmList from '../../components/film-orderList/film-orderList.vue'
 import djkorder from '../../components/djk-order/index.vue'
 import videoRightsList from '../../components/videoRights-orderList/videoRights-orderList.vue'
 import Jy from '../../components/refueling-order/index.vue'
+import attractionsList from '../../components/attractions-orderList/attractions-orderList.vue'
 
 interface Props {
   orderList: Api.xsbOrderList
@@ -34,5 +35,9 @@ defineEmits<{
     />
     <videoRightsList v-else-if="orderList.businessType === 'XNSP' || orderList.businessType === 'all'" :order="orderList" />
     <Jy v-else-if="orderList.businessType === 'JY' || orderList.businessType === 'all'" :order="orderList" @refresh="$emit('refresh')" />
+    <attractionsList
+      v-else-if="orderList.businessType === 'JDMP' || orderList.businessType === 'all'" :order="orderList"
+      @refresh="$emit('refresh')"
+    />
   </block>
 </template>

+ 1 - 0
src/subPack-smqjh/order/order-data.ts

@@ -6,6 +6,7 @@ export const navTabTypeList = [
   { name: '视频权益', value: 'XNSP' },
   { name: '大健康', value: 'DJK' },
   { name: '加油', value: 'JY' },
+  { name: '景区', value: 'JDMP' },
 ]
 
 export const orderStatusList = [

+ 1 - 1
src/subPack-videoRights/commonTab/components/order.vue

@@ -50,7 +50,7 @@ function handleClick(e: any) {
       safe-area-inset-top fixed
     />
     <view :style="{ paddingTop: `${(Number(statusBarHeight) || 44) + MenuButtonHeight + 12}px` }" />
-    <wd-tabs v-model="tab" animated @click="handleClick">
+    <wd-tabs v-model="tab" :offset-top="statusBarHeight + MenuButtonHeight + 12" animated @click="handleClick">
       <block v-for="item in tabsList" :key="item">
         <wd-tab :title="item">
           <view class="box-border bg-#f6f6f6 px24rpx">

+ 2 - 0
src/uni-pages.d.ts

@@ -65,6 +65,8 @@ interface NavigateToOptions {
        "/subPack-refueling/orderDetaile/index" |
        "/subPack-refueling/webView/index" |
        "/subPack-attractions/attractionsDetail/attractionsDetail" |
+       "/subPack-attractions/attractionsOrderDetail/attractionsOrderDetail" |
+       "/subPack-attractions/attractionsOrderPay/attractionsOrderPay" |
        "/subPack-attractions/attractionsReservation/attractionsReservation" |
        "/subPack-attractions/commonTab/index";
 }

+ 22 - 0
src/utils/index.ts

@@ -217,3 +217,25 @@ export function parseUrlParams(url: string): Record<string, string> {
     return {}
   }
 }
+
+/**
+ *处理富文本图片溢出
+ * @param html - 富文本字符串
+ * @returns
+ */
+export function fixImgStyle(html: string) {
+  if (!html)
+    return html
+  // 处理已有 style 属性的 img 标签:将样式追加到现有 style 中
+  let result = html.replace(/<img([^>]*)style\s*=\s*["']([^"']*)["']([^>]*)>/gi, (match, before, existingStyle, after) => {
+    // 移除可能存在的 width/height 内联样式,然后添加防溢出样式
+    const cleanedStyle = existingStyle.replace(/\bwidth\s*:[^;]*;?/gi, '').replace(/\bheight\s*:[^;]*;?/gi, '')
+    const newStyle = `${cleanedStyle};max-width:100%;height:auto;display:block;`.replace(/^;+|;+$/g, '').replace(/;{2,}/g, ';')
+    return `<img${before}style="${newStyle}"${after}>`
+  })
+
+  // 处理没有 style 属性的 img 标签:添加新的 style
+  result = result.replace(/<img(?![^>]*style\s*=)([^>]*)>/gi, '<img style="max-width:100%;height:auto;display:block;"$1>')
+
+  return result
+}