6
0
Fork 0

邮储银行前端所有流程走完。待完整测试

This commit is contained in:
xiaogang 2024-06-26 18:37:49 +08:00
parent a633a32b64
commit 4807ac0d60
37 changed files with 510 additions and 694 deletions

3
.env
View File

@ -0,0 +1,3 @@
# 邮储奶茶活动
VITE_YCNC_APPID = '2vikrqptiia9pe9bf5ztrd'
VITE_YCNC_SECRET = '6fpfwdkgcggyk0yf2yb6bt'

View File

@ -1,5 +1,5 @@
#请求url前缀
# 中信建投
# VITE_BASE_URL = 'http://zxjt.test.86698.cn'
# 兴业优酷
VITE_BASE_URL = 'http://192.168.110.39:8083'
# 邮储奶茶活动
VITE_BASE_URL = 'http://milk.api.test.86698.cn'

View File

@ -1,5 +1,5 @@
#请求url前缀
# 中信建投
# VITE_BASE_URL = 'https://zxjt.86698.cn'
# 兴业优酷
VITE_BASE_URL = 'http://192.168.110.39:8083'
# 邮储奶茶活动
VITE_BASE_URL = 'http://milk.api.test.86698.cn'

View File

@ -1,7 +1,7 @@
const config = {
pages:'./src/pages',
pagesInclude:['xyyk']
pagesInclude:['ycnc']
}
export default config

View File

@ -15,7 +15,7 @@
</head>
<body>
<div id="app"><!--app-html--></div>
<!-- <script src="./static/YT_Client_api.js"></script> -->
<script src="./static/YT_Client_api.js"></script>
<script type="module" src="/src/main.js"></script>
<!-- 调试工具 -->
<script src="https://fastly.jsdelivr.net/npm/eruda"></script>

View File

@ -55,7 +55,9 @@
"@dcloudio/uni-mp-xhs": "3.0.0-4010520240507001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4010520240507001",
"@dcloudio/uni-ui": "^1.5.5",
"dayjs": "^1.11.11",
"js-md5": "^0.8.3",
"qs": "^6.12.1",
"vue": "^3.4.21",
"vue-i18n": "^9.1.9",
"wot-design-uni": "^1.2.26"

View File

@ -53,9 +53,15 @@ importers:
'@dcloudio/uni-ui':
specifier: ^1.5.5
version: 1.5.5
dayjs:
specifier: ^1.11.11
version: 1.11.11
js-md5:
specifier: ^0.8.3
version: 0.8.3
qs:
specifier: ^6.12.1
version: 6.12.1
vue:
specifier: ^3.4.21
version: 3.4.28
@ -2059,6 +2065,9 @@ packages:
resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==}
engines: {node: '>=10'}
dayjs@1.11.11:
resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==}
debug@2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
@ -3184,6 +3193,10 @@ packages:
resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==}
engines: {node: '>=0.6'}
qs@6.12.1:
resolution: {integrity: sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==}
engines: {node: '>=0.6'}
querystringify@2.2.0:
resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==}
@ -6770,6 +6783,8 @@ snapshots:
whatwg-mimetype: 2.3.0
whatwg-url: 8.7.0
dayjs@1.11.11: {}
debug@2.6.9:
dependencies:
ms: 2.0.0
@ -8067,6 +8082,10 @@ snapshots:
dependencies:
side-channel: 1.0.6
qs@6.12.1:
dependencies:
side-channel: 1.0.6
querystringify@2.2.0: {}
queue-microtask@1.2.3: {}

10
shims-uni.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
/// <reference types='@dcloudio/types' />
import 'vue'
declare module '@vue/runtime-core' {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {
}
}

View File

@ -1,17 +1,17 @@
import request from "../utils/request";
import http from "../utils/http";
export const checkTradeNo = (params) => request({
export const checkTradeNo = (params) => http({
url:'/backend/zxjt_redpacket/orders/is_exist',
method:'POST',
...params
})
export const getAccessPage = (params) => request({
export const getAccessPage = (params) => http({
url:'/backend/zxjt_redpacket/orders/access_page',
...params
})
export const sendPacket = (params) => request({
export const sendPacket = (params) => http({
url:'/backend/zxjt_redpacket/orders/send_packet',
method:'POST',
...params

View File

@ -1,30 +1,30 @@
import request from "../utils/request";
import http from "../utils/http";
export const login = (params) => request({
export const login = (params) => http({
url:'/v1/xy/login',
method:'POST',
...params
})
export const getProduceList = (params) => request({
export const getProduceList = (params) => http({
url:'/v1/auth/activity',
method:'POST',
...params
})
export const goBuy = (params) => request({
export const goBuy = (params) => http({
url:'/v1/auth/order/buy',
method:'POST',
...params
})
export const getTicketList = (params) => request({
export const getTicketList = (params) => http({
url:'/v1/auth/order/list',
method:'POST',
...params
})
export const queryOrder = (params) => request({
export const queryOrder = (params) => http({
url:'/v1/auth/order/query',
...params
})

View File

@ -1,31 +1,32 @@
import request from "../utils/request";
import http from "../utils/http";
export const login = (params) => request({
export const login = (params) => http({
url:'/api/v1/UnionLogin',
method:'POST',
noToken:true,
...params
})
export const getProductList = (params) => request({
export const getProductList = (params) => http({
url:'/api/v1/VoucherList',
method:'POST',
...params
})
export const detail = (params) => request({
export const queryDetail = (params) => http({
url:'/api/v1/product/detail',
method:'POST',
...params
})
export const getOrderList = (params) => request({
export const getOrderList = (params) => http({
url:'/api/v1/auth/order/list',
method:'POST',
...params
})
export const goPay = (params) => request({
export const goPay = (params) => http({
url:'/api/v1/auth/order/create',
method:'POST',
...params

View File

@ -0,0 +1 @@
export { requestInterceptor } from './request'

View File

@ -0,0 +1,40 @@
import qs from 'qs'
// 请求基准地址
const baseUrl = import.meta.env.VITE_BASE_URL
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options) {
// 接口请求支持通过 query 参数配置 queryString
console.log('options', options)
if (options.query) {
const queryStr = qs.stringify(options.query)
if (options.url.includes('?')) {
options.url += `&${queryStr}`
} else {
options.url += `?${queryStr}`
}
}
if (options.params) {
options.data = options.params || {}
}
options.url = baseUrl + options.url
options.method = options.method || 'GET'
// 1. 请求超时
options.timeout = 10000 // 10s
// 2. 添加 token 请求头标识
const token = uni.getStorageSync('token');
if (token && !options.noToken) {
options.header.Authorization = `Bearer ${token}`
}
}
}
export const requestInterceptor = {
install() {
// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
},
}

View File

@ -1,454 +0,0 @@
/**
* @author 何杰
* @date 2016-08-01 12:00:00
* @address www.yitong.com.cn
* @mail hj@yitong.com.cn
* @desc: 屹通客户端组件api
*/
var Fw = {}; Fw.device = {};
Fw.device.Device = function () {
var userAgent = navigator.userAgent;
//ios 事件队列
var eventQueue = [];
return {
//是否iOS设备
is_ios: userAgent.indexOf('iPhone') > -1 || userAgent.indexOf('iPad') > -1,
//是否Android设备
is_android: userAgent.indexOf('Android') > -1,
/**
* ios
* 注册事件
* @param code 事件编码
* @param options 参数
*/
addEvent : function(code, options) {
if (options && code) {
eventQueue.push(JSON.stringify({
code : code,
name : options
}));
}
},
/**
* ios
* 原生调用从队列中获取事件
* @returns {string}
*/
getEvent : function() {
return eventQueue.length > 0 ? eventQueue.shift() : '0';
}
};
}();
/**
* 供第三方调用API
*/
Fw.device.api = function () {
var device = Fw.device.Device;
return {
/**
* @brief 获取经纬度
*/
handCodeGetLocation : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.callBack = fn;
device.is_ios && device.addEvent("51",JSON.stringify(option));
device.is_android && GetInfoJs.getLocation(JSON.stringify(option));
},
/**
* @brief 获取用户信息
*/
getUserInfo : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.callback = fn;
device.is_ios && device.addEvent("getUserInfo",JSON.stringify(option));
device.is_android && GetInfoJs.getUserInfo(JSON.stringify(option));
},
/**
* @brief
*/
getCustNo : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("getCustNo",fn);
device.is_android && GetInfoJs.getCustNo(fn);
},
initTitle : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("initTitle",JSON.stringify(option));
device.is_android && GetInfoJs.initTitle(JSON.stringify(option));
},
setBackFun : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("goBack",JSON.stringify(option));
device.is_android && GetInfoJs.goBack(JSON.stringify(option));
},
setRightButton : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("setRightButton",JSON.stringify(option));
device.is_android && GetInfoJs.setRightButton(JSON.stringify(option));
},
getBackFun : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("getBackFun",fn);
device.is_android && GetInfoJs.getBackFun(option);
},
startRecordVoice : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("startRecordVoice",JSON.stringify(option));
device.is_android && GetInfoJs.startRecordVoice();
},
stopRecordVoice : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("stopRecordVoice",fn);
device.is_android && GetInfoJs.stopRecordVoice(fn);
},
getPhoneNo : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("getPhoneNo",fn);
device.is_android && GetInfoJs.getPhoneNo(fn);
},
/**
*扫一扫
*/
openScanPage : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("goToQrCode",JSON.stringify(option));
device.is_android && GetInfoJs.openScanPage();
},
/**
*付款码
*/
openPaymentCode : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("gotoPaymentCode",JSON.stringify(option));
device.is_android && GetInfoJs.openPaymentCode(JSON.stringify(option));
},
/**
* 拨打电话
*/
gotoSystemPhone : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("gotoSystemPhone",fn);
device.is_android && GetInfoJs.gotoSystemPhone(fn);
},
/**
* 关闭当前页面
*/
goBack : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("getBackFun",JSON.stringify(option));
device.is_android && GetInfoJs.goBack();
},
/**
* 调用物理返回键
*/
nativeBack : function () {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
option = {};
// device.is_ios && device.addEvent("getBackFun",JSON.stringify(option));
device.is_android && GetInfoJs.nativeBack();
},
/**
* 地图导航
*/
openMap : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("openMap",JSON.stringify(option));
device.is_android && GetInfoJs.openMap(JSON.stringify(option));
},
/**
* 登录
*/
gotoLoginCallback : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("goToLoginView",JSON.stringify(fn));
device.is_android && GetInfoJs.gotoLoginCallback(JSON.stringify(fn));
},
loginStatus : function (option) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("loginStatus",JSON.stringify(option));
device.is_android && GetInfoJs.loginStatus(JSON.stringify(option));
},
checkRecordVoicePermission : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
// device.is_ios && device.addEvent("getBackFun",JSON.stringify(option));
device.is_android && GetInfoJs.checkRecordVoicePermission(fn);
},
openMenu : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
// device.is_ios && device.addEvent("getBackFun",JSON.stringify(option));
device.is_android && GetInfoJs.gotoCommonlyUsedMenu(fn);
},
/**
* @brief 分享
*/
handCodeShare : function (param,fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
option.param = param;
device.is_ios && device.addEvent("41",JSON.stringify(param));
device.is_android && GetInfoJs.showShare(JSON.stringify(option));
},
/**
* @brief 拍照相册
*/
handCodeGetPhotos : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
device.is_ios && device.addEvent("41",JSON.stringify(param));
device.is_android && GetInfoJs.takePhotos(JSON.stringify(option));
},
/**
* @brief 拍照
*/
openCamera : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
// device.is_ios && device.addEvent("41",JSON.stringify(param));
device.is_android && GetInfoJs.openCamera(JSON.stringify(option));
},
/**
* @brief 相册
*/
photoAlbum : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
// device.is_ios && device.addEvent("41",JSON.stringify(param));
device.is_android && GetInfoJs.photoAlbum(JSON.stringify(option));
},
/**
* @brief 复制到粘贴板
*/
pasteStringToSystem : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("pasteStringToSystem",fn);
device.is_android && GetInfoJs.pasteStringToSystem(fn);
},
queryAppFamily : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
//TODO ios粘贴方法
device.is_android && GetInfoJs.queryAppFamily(fn);
},
getHeaderImg : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
//TODO ios粘贴方法
device.is_android && GetInfoJs.getHeaderImg(fn);
},
getSystemVersion : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("getEquipmentInfo",fn);
device.is_android && GetInfoJs.getSystemVersion(fn);
},
/**
* @brief 跳转VUE
*/
goVUEPage : function (param,fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
option.param = param;
device.is_ios && device.addEvent("goToAresPage",JSON.stringify(param));
device.is_android && GetInfoJs.showShare(JSON.stringify(option));
},
/**
甘肃宁波观影
*/
checkDiscountLevel : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = "callbackCheckDiscountLevel";
option.shopid = "1100529310001000001";
option.sign = "bd91222d6fcff0de67dd28583926ae92"
device.is_ios && device.addEvent("checkDiscountLevel",JSON.stringify(option));
device.is_android && GetInfoJs.checkDiscountLevel(fn);
},
/**
宁波活动
*/
checkBFMLevel : function (fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = "callbackCheckBFMLevel";
option.shopid = "1100529310001000009";
device.is_ios && device.addEvent("checkBFMLevel",JSON.stringify(option));
device.is_android && GetInfoJs.checkBFMLevel(option);
},
uploadThirdCertifyEvents : function (param ,fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = "callBackUploadThirdCertifyEvents";
option.param = param;
device.is_ios && device.addEvent("uploadThirdCertifyEvents",JSON.stringify(param));
device.is_android && GetInfoJs.uploadThirdCertifyEvents(option);
},
checkUserChangeOrNoAndLoginStatus : function (param,fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
option.param = param;
device.is_ios && device.addEvent("checkUserChangeOrNoAndLoginStatus",JSON.stringify(param));
device.is_android && GetInfoJs.checkUserChangeOrNoAndLoginStatus(JSON.stringify(option));
},
handCodePay : function (param,fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
option.param = param;
device.is_ios && device.addEvent("handCodePay",JSON.stringify(param));
device.is_android && GetInfoJs.go2pay(JSON.stringify(option));
},
publicActivityEvents : function (param,fn) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
var option = {};
option.fn = fn;
option.param = param;
device.is_ios && device.addEvent("publicActivityEvents",JSON.stringify(option));
device.is_android && GetInfoJs.publicActivityEvents(JSON.stringify(option));
},
getNewAuthorization : function (param) {
if(!device.is_ios && !device.is_android){
alert("请在ios/android设备上使用");
return;
}
device.is_ios && device.addEvent("getNewAuthorization",JSON.stringify(param));
device.is_android && GetInfoJs.getNewAuthorization(JSON.stringify(param));
}
}
}();

View File

@ -4,10 +4,11 @@ import {
} from "vue";
import App from "./App.vue";
import 'virtual:uno.css';
import '@/lib/YT_Client_api.js'
import { requestInterceptor } from './interceptors'
export function createApp() {
const app = createSSRApp(App);
app.use(requestInterceptor)
return {
app,
};

View File

@ -1,12 +1,28 @@
{
"pages": [
{
"path": "pages/xyyk/index",
"type": "page"
"path": "pages/ycnc/index",
"type": "home",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "奶茶活动"
}
},
{
"path": "pages/xyyk/tickets",
"type": "page"
"path": "pages/ycnc/detail",
"type": "page",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "商品详情"
}
},
{
"path": "pages/ycnc/order",
"type": "page",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "我的订单"
}
}
],
"globalStyle": {

View File

@ -1,31 +1,45 @@
<template>
<view class="pro-container flex flex-wrap flex-justify-between box-border">
<view v-for="(item,index) in products" :key="index">
<ProductItem :detail="item"/>
<scroll-view scroll-y class="pro-container box-border" :style="{backgroundImage: 'url('+config[brandName].src+')',height:`${config[brandName].height}rpx`}">
<view class="pro-wrapper flex flex-wrap">
<view v-for="(item,index) in products" :key="index">
<ProductItem :detail="item" :index="index"/>
</view>
</view>
</view>
</scroll-view>
</template>
<script setup>
import ProductItem from './product-item'
import config from '../config'
const props = defineProps({
products:{
type:Array,
required: true,
default:() => ([])
},
brandName:{
type:String,
required:true,
default:''
}
})
</script>
<style lang="scss">
.pro-container{
//稿30
width:750rpx;
width:774rpx;
// height:938rpx;
padding:123rpx 60rpx 20rpx;
background: url('../../../static/ycnc/bg-content.png') no-repeat;
// background-size: 100% auto;
background-size:cover ;
margin-bottom:20rpx;
padding:108rpx 48rpx 60rpx;
// background: url('../../../static/ycnc/bg-content.png') no-repeat;
background-repeat: no-repeat;
background-size: 100% 100%;
// margin-bottom:20rpx;
overflow-y: auto;
}
.pro-wrapper{
view:nth-child(3n) > .pro-item-wrapper{
margin-right:0 !important;
}
}
</style>

View File

@ -7,7 +7,7 @@
<view class="order-info">
<view class="content flex">
<image
src=""
:src="detail.main_image"
class="pro-img"
/>
<view class="flex flex-1 flex-col">
@ -23,33 +23,28 @@
</view>
</view>
</view>
<view class="time">下单时间2021-08-31 16:37:05</view>
<view class="time">下单时间{{ detail.create_time }}</view>
</view>
<view class="btns flex flex-justify-end">
<!-- <view class="btn del" v-if="[1,2].includes(detail.state)">删除订单</view> -->
<view class="btn pay" v-if="[1].includes(detail.state)" @click="goPay">立即付款</view>
<view class="btn view" v-if="[3].includes(detail.state)">查看卡密</view>
</view>
<!-- <view class="btns flex flex-justify-end">
<view class="btn del">删除订单</view>
<view class="btn pay">立即付款</view>
<view class="btn view">查看卡密</view>
</view> -->
</view>
</template>
<script setup>
import { stateConfig } from '../config';
const props = defineProps({
detail:{
type:Object,
required: true,
default:() => ({})
type:Object,
required: true,
default:() => ({})
}
})
const stateConfig = {
1: '待支付',
2: '已支付',
3: '充值完成',
4: '充值异常',
5: '订单核销',
6: '退款中',
7: '退款完成',
8: '退款失败'
const emits = defineEmits(['pay-event'])
function goPay(){
emits('pay-event', detail);
}
</script>
@ -81,7 +76,6 @@
display: block;
width:90rpx;
height:90rpx;
border:1rpx solid red;
margin-right:34rpx;
}
}

View File

@ -1,20 +1,27 @@
<template>
<view class="pro-item-wrapper flex flex-col flex-justify-end box-border" @click="toDetail">
<view class="brand">{{ detail.brandFlag }}</view>
<view class="name">{{ detail.voucherTitle }}</view>
<view class="flex flex-justify-between flex-items-end">
<view class="price">{{ detail.voucherAmount }}<text></text>
<view class="pro-item-wrapper flex flex-col box-border" @click="toDetail">
<image
:src="detail.voucherUrl"
class="img"
/>
<view class="bottom-container">
<view class="brand">{{ config[detail.brandFlag].name}}</view>
<view class="name">{{ detail.voucherTitle }}</view>
<view class="flex flex-justify-between flex-items-end">
<view class="price">{{ detail.voucherAmount }}<text></text>
</view>
<view class="ori">{{ detail.voucherOriginalPrice }}</view>
</view>
<view class="btn flex flex-justify-center flex-items-center">
<view class="btn-content flex flex-justify-center flex-items-center" @click="goBuy">点击购买</view>
</view>
<view class="ori">{{ detail.voucherOriginalPrice }}</view>
</view>
<view class="btn flex flex-justify-center flex-items-center">
<view class="btn-content" @click="goBuy">点击购买</view>
</view>
</view>
</template>
<script setup>
import { inject } from 'vue';
import config from '../config'
const clickBuy = inject('handleBuy');
const goDetail = inject('goDetail');
const props = defineProps({
@ -22,6 +29,11 @@
type:Object,
required: true,
default:() => ({})
},
index:{
type:Number,
required:true,
default:0,
}
})
const goBuy = (e) => {
@ -29,23 +41,30 @@
if(e.stopPropagation) { //W3C
e.stopPropagation();
}
clickBuy(props.detail.ProductId)
clickBuy(props.detail)
}
const toDetail = (event) => {
goDetail()
const toDetail = () => {
goDetail(props.detail)
}
</script>
<style lang="scss">
.pro-item-wrapper{
width:206rpx;
width:212rpx;
height:370rpx;
// background: url('../../../static/ycnc/bg-product.png') no-repeat;
// background: url('/static/ycnc/bg-product.png') no-repeat;
background: url('/static/ycnc/bg-product.jpg') no-repeat;
background-size: 100% 100%;
padding: 0 16rpx 10rpx;
margin-bottom:20rpx;
padding: 4rpx 4rpx 10rpx;
margin-top:20rpx;
margin-right: 20rpx;
&:nth-child(3n){
margin-right:0 !important;
}
}
.bottom-container{
padding: 0 12rpx;
}
.brand{
font-weight: 400;
@ -53,11 +72,23 @@
color: #887F6E;
}
.img{
width:100%;
height:156rpx;
display: block;
box-sizing: border-box;
border:1px solid red;
margin-bottom:12rpx;
border-radius:16rpx;
}
.name{
font-weight: 400;
font-size: 28rpx;
color: #3B2609;
margin:4rpx 0;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.price{
font-weight: 400;
@ -104,8 +135,6 @@
font-weight: 400;
font-size: 26rpx;
color: #FFFFFF;
text-align: center;
line-height: 48rpx;
}
}
</style>

66
src/pages/ycnc/config.js Normal file
View File

@ -0,0 +1,66 @@
import MX from '../../static/ycnc/bg-mxbc.png'
import BW from '../../static/ycnc/bg-bwcj.png'
import NX from '../../static/ycnc/bg-nxdc.png'
import CoCo from '../../static/ycnc/bg-coco.png'
import CBD from '../../static/ycnc/bg-cbd.png'
import CYYS from '../../static/ycnc/bg-cyys.png'
const config = {
"MX":{
name:'蜜雪冰城',
src:MX,
height:948,
},
"BW":{
name:'霸王茶姬',
src:BW,
height:948,
},
"NX":{
name:'奈雪的茶',
src:NX,
height:558,
},
"CoCo":{
name:'COCO',
src:CoCo,
height:558,
},
"CBD":{
name:'茶百道',
src:CBD,
height:558,
},
"CYYS":{
name:'茶颜悦色',
src:CYYS,
height:948,
},
}
export const stateConfig = {
1: '待支付',
2: '已支付',
3: '充值完成',
4: '充值异常',
5: '订单核销',
6: '退款中',
7: '退款完成',
8: '退款失败'
}
export const tabs = [{
tabName:'全部订单',
state:0,
},{
tabName:'待付款',
state:1,
},{
tabName:'处理中',
state:2,
},{
tabName:'已完成',
state:3,
}]
export default config

View File

@ -19,13 +19,12 @@
<text class="ori">{{ detailObj.price }}</text>
</view>
</view>
<view class="notice">
<view class="title">购买须知</view>
<!-- <view>购买须知这一块的数据待商议</view> -->
<view class="notice" v-html="detailObj.description">
</view>
</view>
</scroll-view>
<view class="pay-btn" @="toPay">
<view class="pay-btn" @click="toPay">
立即支付
</view>
</view>
@ -34,7 +33,8 @@
<script setup>
import { onMounted, reactive, ref, unref } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import { detail, goPay } from '../../api/ycnc'
import { queryDetail, goPay } from '../../api/ycnc';
import usePay from './hooks/usePay';
const id = ref('')
@ -53,19 +53,19 @@
const params = {
product_id:unref(id)
}
detail({params}).then(res => {
queryDetail({params}).then(res => {
Object.assign(detailObj,res)
})
}
const pay = () => {
const toPay = () => {
const params = {
product_id:unref(id)
}
goPay({params}).then(res => {
const {respCode} = res;
window.location.href = respCode
const {order_no,notify_url} = res;
const {payFunc} = usePay();
payFunc({order_no,notify_url,voucherAmount})
}).catch(err => {
console.log(err);
})
@ -77,7 +77,7 @@
width: 100%;
height:600rpx;
display: block;
border: 1rpx solid red;
// border: 1rpx solid red;
box-sizing: border-box;
}
.detail{
@ -105,16 +105,16 @@
text-decoration: line-through;
}
}
.notice{
width: 694rpx;
margin:0 auto;
padding-top:40rpx;
.title{
font-weight: normal;
font-size: 40rpx;
color: #3D3D3D;
}
}
// .notice{
// width: 694rpx;
// margin:0 auto;
// padding-top:40rpx;
// .title{
// font-weight: normal;
// font-size: 40rpx;
// color: #3D3D3D;
// }
// }
.pay-btn{
width: 600rpx;
height: 88rpx;

View File

@ -0,0 +1,28 @@
import md5 from 'js-md5';
export default function useCode(){
return new Promise((resolve,reject) => {
window.authCallback = (params) => {
console.log('authCallback-use',params);
const {code} = params
resolve(code)
}
const getNewAuthorization = () => {
let appId = import.meta.env.VITE_YCNC_APPID;
let time = Date.now().toString();
let secret = import.meta.env.VITE_YCNC_SECRET;
let signBefore = appId + time + secret;
let sign = md5(signBefore);//普通md5
let param = {
appId: appId,
sign: sign,
time: time,
tran_code: "157",
fn: "authCallback",
needBind: ""
};
console.log('auth-param157-use',param);
Fw.device.api.getNewAuthorization(param)
};
getNewAuthorization()
})
}

View File

@ -0,0 +1,32 @@
import dayjs from "dayjs";
const handleParams = (obj) => Object.entries(obj).reduce((total,curr) => {
if(!total){
total += `${curr[0]}=${curr[1]}`
}else{
total += `|${curr[0]}=${curr[1]}`
}
return total
},'')
export default function usePay(){
const payFunc = (args) => {
const {order_no,notify_url,voucherAmount} = args;
const Plain = {
MercUrl:notify_url,
TranAmt:Number(voucherAmount).toFixed(2),
TermSsn:order_no,
BackLink:`${window.location.origin}/#/pages/ycnc/order`,
psbcmcc:'LSXD',
TxnDt:dayjs(Date.now()).format('YYYY-MM-DD'),
MercCode:'100610100019029'
}
const params = {
Plain:handleParams(Plain),
}
console.log('handCodePay-params',params);
Fw.device.api.handCodePay(params);
}
return {payFunc}
}

View File

@ -12,7 +12,7 @@
<view class="nav-btn" @click="toOrder">我的订单</view>
<view class="wrapper flex flex-col flex-items-center box-border">
<view v-for="(item,key) in productList" :key="key">
<brand :products="item"/>
<brand :products="item" :brandName="key"/>
</view>
</view>
</scroll-view>
@ -23,28 +23,35 @@
import md5 from 'js-md5';
import { getProductList, goPay, login } from '../../api/ycnc'
import { onMounted, ref, provide, unref } from 'vue';
import { getQueryString , isIOS, isAndroid } from '../../utils/utils';
// import { getQueryString , isIOS, isAndroid } from '../../utils/utils';
import useCode from './hooks/useCode';
import usePay from './hooks/usePay';
const productList = ref([]);
const authCode = ref('');
const handleBuy = (product_id) => {
pay(product_id)
const handleBuy = (productData) => {
pay(productData)
}
const goDetail = () => {
const goDetail = (productData) => {
const {ProductId} = productData
uni.navigateTo({
url:'/pages/ycnc/detail?product_id=1'
url:`/pages/ycnc/detail?product_id=${ProductId}`
})
}
const pay = (id) => {
const pay = (productData) => {
const {ProductId,voucherAmount} = productData
console.log('商品数据',productData);
const params = {
product_id:id
product_id:ProductId
}
goPay({params}).then(res => {
const {order_no,notify_url} = res;
payFunc({order_no,notify_url})
const {payFunc} = usePay();
payFunc({order_no,notify_url,voucherAmount})
}).catch(err => {
console.log(err);
})
@ -53,75 +60,82 @@
provide('handleBuy', handleBuy);
provide('goDetail', goDetail);
window.authoriCallback = (params) => {
console.log('authoriCallback',params);
window.authCallback = (params) => {
console.log('authCallback-index',params);
const {code} = params;
authCode.value = code;
toLogin()
console.log('code',code);
}
const getNewAuthorization = () => {
let appId = "2vikrqptiia9pe9bf5ztrd";
let appId = import.meta.env.VITE_YCNC_APPID;
let time = Date.now().toString();
let secret = '6fpfwdkgcggyk0yf2yb6bt';
let secret = import.meta.env.VITE_YCNC_SECRET;
let signBefore = appId + time + secret;
let sign = md5(signBefore);//md5
let param = {
appId: appId,
sign: sign,
time: time,
tran_code: "104",
fn: "authoriCallback",
tran_code: "157",
fn: "authCallback",
needBind: ""
};
console.log('auth-param104',param);
console.log('auth-param157-index',param);
Fw.device.api.getNewAuthorization(param)
}
window.payCallback = (params) => {
console.log('payCallback',params);
}
// function handleParams(obj){
// return Object.entries(obj).reduce((total,curr) => {
// if(!total){
// total += `${curr[0]}=${curr[1]}`
// }else{
// total += `|${curr[0]}=${curr[1]}`
// }
// return total
// },'')
// }
const payFunc = (args) => {
const {order_no,notify_url} = args;
const params = {
MercUrl:notify_url,
TermSsn:order_no
}
console.log('handCodePay-params',params);
if(isAndroid){
Fw.device.api.handCodePay(params,payCallback)
}else if(isIOS){
Fw.device.api.handCodePay(params)
}
}
// const payFunc = (args) => {
// const {order_no,notify_url,voucherAmount} = args;
// const Plain = {
// MercUrl:notify_url,
// TranAmt:Number(voucherAmount).toFixed(2),
// TermSsn:order_no,
// BackLink:`${window.location.origin}/#/pages/ycnc/order`,
// psbcmcc:'LSXD',
// TxnDt:dayjs(Date.now()).format('YYYY-MM-DD'),
// MercCode:'100610100019029'
// }
// const params = {
// Plain:handleParams(Plain),
// }
// console.log('handCodePay-params',params);
// Fw.device.api.handCodePay(params);
// }
const toOrder = () => {
uni.navigateTo({
url:'/pages/ycnc/order'
})
// uni.navigateTo({
// url:'/pages/ycnc/detail?product_id=1'
// })
};
const toLogin = () => {
const params = {
code: unref(authCode) || 'De0chzOWs6Zsi3fAo3vhFQ'
}
login({params}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
}
onMounted(()=>{
toLogin()
queryProducts()
// window.authoriCallback = authoriCallback;
onMounted(async ()=>{
// getNewAuthorization();
// const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0Tm8iOiIzOTY3ODA2ODcwMjIyIiwiZXhwIjoxNzE5Mzk3Nzc0LCJpZCI6IjIifQ.bL7N5E0WMXDtvnbNrY58p-BuWDgBovz1VwpWrKd1_UU'
// uni.setStorageSync('token',token)
// queryProducts();
// const token = uni.getStorageSync('token') || '';
// if(!token){
// const code = await useCode();
// authCode.value = code
// const {token} = await login({params:{code:unref(authCode)}})
// uni.setStorageSync('token',token)
// }
getNewAuthorization()
queryProducts();
// const authCode = await useCode()
// console.log('authCallback-mounted',authCode);
});
function handleData(arg,args){
@ -180,6 +194,6 @@
min-height:100%;
background: url('../../static/ycnc/bg.png') no-repeat;
background-size: 100% auto;
padding-top:750rpx;
padding-top:725rpx;
}
</style>

View File

@ -8,13 +8,13 @@
</route>
<template>
<wd-tabs color="#333" inactiveColor="#888" @click="handleClick">
<wd-tabs color="#333" inactiveColor="#888" @click="handleClick">
<block v-for="item in tabs" :key="item.type">
<wd-tab :title="item.tabName" :name="item.state">
<scroll-view scroll-y class="page-wrapper">
<view class="wrapper flex flex-col flex-items-center">
<view v-for="(ele,index) in list" :key="ele.id">
<OrderItem :detail="ele"/>
<OrderItem :detail="ele" @pay-event="pay"/>
</view>
</view>
</scroll-view>
@ -25,29 +25,16 @@
<script setup>
import OrderItem from './components/order-item';
import { getOrderList } from '../../api/ycnc';
import usePay from './hooks/usePay';
import { getOrderList, goPay } from '../../api/ycnc';
import { onMounted, ref, unref } from 'vue';
import { tabs } from './config';
const page = ref(1);
const pageSize = 10;
const activeName = ref(0);
const total = ref(0);
const list = ref([]);
const tabs = [{
tabName:'全部订单',
state:0,
},{
tabName:'待付款',
state:1,
},{
tabName:'处理中',
state:2,
},{
tabName:'已完成',
state:3,
}];
const isLastPage = () => unref(page) === Math.ceil(unref(total) / pageSize)
//
const queryOrderList = () => {
@ -79,6 +66,21 @@
}
function pay(orderData){
const {product_id,voucherAmount} = orderData
console.log('订单数据',orderData);
const params = {
product_id:product_id
}
goPay({params}).then(res => {
const {order_no,notify_url} = res;
const {payFunc} = usePay();
payFunc({order_no,notify_url,voucherAmount})
}).catch(err => {
console.log(err);
})
}
onMounted(()=>{
queryOrderList()
})
@ -91,6 +93,7 @@
width:100%;
height: 100%;
overflow-y: auto;
background: #FAFBFD;
}
.wrapper{
width:100%;

View File

@ -428,8 +428,8 @@ Fw.device.api = function () {
var option = {};
option.fn = fn;
option.param = param;
device.is_ios && device.addEvent("handCodePay",JSON.stringify(param));
device.is_android && GetInfoJs.go2pay(JSON.stringify(option));
device.is_ios && device.addEvent("HandCodePay",JSON.stringify(param));
device.is_android && GetInfoJs.go2Pay(JSON.stringify(param));
},
publicActivityEvents : function (param,fn) {
if(!device.is_ios && !device.is_android){

BIN
src/static/ycnc/bg-bwcj.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
src/static/ycnc/bg-cbd.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
src/static/ycnc/bg-coco.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

BIN
src/static/ycnc/bg-cyys.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
src/static/ycnc/bg-mxbc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
src/static/ycnc/bg-nxdc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

65
src/utils/http.js Normal file
View File

@ -0,0 +1,65 @@
//邮储银行专用的
import useCode from "../pages/ycnc/hooks/useCode";
import {login} from '../api/ycnc'
function http(options) {
uni.showLoading({
title: "加载中",
mask: true,
});
return new Promise((resolve, reject) => {
uni.request({
...options,
header: {
// 'content-type': 'application/json',
'content-type': 'application/x-www-form-urlencoded',
},
responseType: 'json',
success: async (res) => {
if (res.statusCode && res.statusCode != 200) {
uni.hideLoading().then(() => {
uni.showToast({
title: "api错误" + res.errMsg,
icon: 'none'
});
})
reject()
} else {
if(res.data?.code >= 200 && res.data?.code < 300){
uni.hideLoading()
resolve(res.data.data)
}else if(res.data?.code === 401){
//邮储银行专用的
const authCode = await useCode();
const params = {code:authCode};
const {token} = await login({params});
uni.setStorageSync('token',token);
http(options).then(ress => {
resolve(ress)
})
}else{
uni.hideLoading().then(() => {
uni.showToast({
title: '请求错误',
icon: 'none'
});
})
reject(res.data.message)
}
}
},
// 这里的接口请求,如果出现问题就输出接口请求失败
fail: (err) => {
uni.hideLoading().then(() => {
uni.showToast({
title: err,
icon: 'none'
});
})
reject(err)
}
})
})
}
export default http

View File

@ -1,69 +0,0 @@
const baseUrl = import.meta.env.VITE_BASE_URL
function request(options) {
uni.showLoading({
title: "加载中",
mask: true,
});
let defaultHeader = {
}
// // 如果使用params传参则以&符拼接的格式传参
if (options.params) {
options.data = options.params
// defaultHeader['Content-Type'] = 'application/json'
defaultHeader['Content-Type'] = 'application/x-www-form-urlencoded'
}
const token = uni.getStorageSync('token');
if (token) {
defaultHeader.Authorization = `Bearer ${token}`
}
return new Promise((resolve, reject) => {
uni.request({
url: baseUrl + options.url, // 接口地址:前缀+方法中传入的地址
method: options.method || 'GET', // 请求方法传入的方法或者默认是“GET”
data: options.data || {}, // 传递参数:传入的参数或者默认传递空集合
header: {
...defaultHeader,
...options.header
},
success: (res) => {
if (res.statusCode && res.statusCode != 200) {
uni.hideLoading().then(() => {
uni.showToast({
title: "api错误" + res.errMsg,
icon: 'none'
});
})
reject()
} else {
const resData = res.data
if (resData.code == 200) {
uni.hideLoading()
resolve(resData.data)
} else {
uni.hideLoading().then(() => {
uni.showToast({
title: '请求失败了,稍后再试',
icon: 'none'
});
})
reject(res.msg)
}
}
},
// 这里的接口请求,如果出现问题就输出接口请求失败
fail: (err) => {
uni.hideLoading().then(() => {
uni.showToast({
title: err,
icon: 'none'
});
})
reject(err)
}
})
})
}
export default request

5
uni-pages.d.ts vendored
View File

@ -4,8 +4,9 @@
// Generated by vite-plugin-uni-pages
interface NavigateToOptions {
url: "/pages/xyyk/index" |
"/pages/xyyk/tickets";
url: "/pages/ycnc/index" |
"/pages/ycnc/detail" |
"/pages/ycnc/order";
}
interface RedirectToOptions extends NavigateToOptions {}