Commit ef7a8349 by li

cashier

parents
NODE_ENV=production
VUE_APP_BASE_URL=
VUE_APP_API_BASE_URL=
\ No newline at end of file
NODE_ENV=development
VUE_APP_BASE_URL=/
VUE_APP_API_BASE_URL=http://38.47.232.137:9216
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
/*
* @Author: your name
* @Date: 2020-12-14 16:32:48
* @LastEditors: 王会峰
* @LastEditTime: 2020-12-24 16:02:58
* @FilePath: \pay\.postcssrc.js
* @SendWord: 永无BUG vite⚡
*/
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {},
"postcss-px2rem": {
"remUnit": 75
}
}
}
\ No newline at end of file
# jeepay-ui-cashier
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "jeepay-ui-cashier",
"version": "1.10.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"amfe-flexible": "^2.2.1",
"axios": "^0.19.0",
"core-js": "^3.6.5",
"lib-flexible": "^0.3.2",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"vue": "^2.6.11",
"vue-router": "^3.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "^4.5.13",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>Jeepay-收银台</title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
import request from '@/http/request'
import wayCode from "@/utils/wayCode";
import channelUserIdUtil from "@/utils/channelUserId";
import config from '@/config'
/** 获取url **/
export function getRedirectUrl () {
return request.request({
url: '/api/cashier/redirectUrl',
method: 'POST',
data: { wayCode: wayCode.getPayWay().wayCode, token: config.cacheToken }
})
}
/** 获取url **/
export function getChannelUserId (redirectData) {
return request.request({
url: '/api/cashier/channelUserId',
method: 'POST',
data: Object.assign({ wayCode: wayCode.getPayWay().wayCode, token: config.cacheToken }, redirectData)
})
}
/** 调起支付接口, 获取支付数据包 **/
export function getPayPackage (amount) {
return request.request({
url: '/api/cashier/pay',
method: 'POST',
data: {
wayCode: wayCode.getPayWay().wayCode,
token: config.cacheToken,
amount: amount,
channelUserId: channelUserIdUtil.getChannelUserId()
}
})
}
/** 调起支付接口, 获取订单信息 **/
export function getPayOrderInfo () {
return request.request({
url: '/api/cashier/payOrderInfo',
method: 'POST',
data: {
token: config.cacheToken
}
})
}
/** 取消订单 **/
export function cancelPay () {
return request.request({
url: '/api/cashier/cancelPay',
method: 'POST',
data: {
token: config.cacheToken
}
})
}
<svg xmlns="http://www.w3.org/2000/svg" width="29" height="40" viewBox="0 0 29 40"><defs><style>.a{fill:#1a1311;}</style></defs><path class="a" d="M2406.045,4386.261h-7.672l-6.828,14.395-6.828-14.395h-7.672l9.439,19.9H2379.3v5.3h8.516v3.515H2379.3v5.3h8.516v5.984h7.451v-5.984h8.516v-5.3h-8.516v-3.515h8.516v-5.3h-7.181Z" transform="translate(-2377.045 -4386.261)"/></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1621938740892" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2364" width="64" height="64" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M512 981.333333C252.8 981.333333 42.666667 771.2 42.666667 512S252.8 42.666667 512 42.666667s469.333333 210.133333 469.333333 469.333333-210.133333 469.333333-469.333333 469.333333z m44.245333-469.333333l159.914667-159.914667a31.274667 31.274667 0 1 0-44.245333-44.245333L512 467.754667 352.085333 307.84a31.274667 31.274667 0 1 0-44.245333 44.245333L467.754667 512l-159.914667 159.914667a31.274667 31.274667 0 1 0 44.245333 44.245333L512 556.245333l159.914667 159.914667a31.274667 31.274667 0 1 0 44.245333-44.245333L556.245333 512z" fill="#FF4B33" p-id="2365"></path></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="42" height="42" viewBox="0 0 42 42"><defs><style>.a{fill:url(#a);}.b{fill:#e7ffe6;}.c{clip-path:url(#b);}.d{clip-path:url(#d);}</style><linearGradient id="a" x1="1" x2="0" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#10d832"/><stop offset="1" stop-color="#00ac34"/></linearGradient><clipPath id="b"><rect class="a" width="42" height="42" rx="8" transform="translate(60 783)"/></clipPath><clipPath id="d"><rect class="b" width="37.233" height="33.096"/></clipPath></defs><g class="c" transform="translate(-60 -783)"><rect class="a" width="42" height="42" rx="8" transform="translate(60 783)"/><g transform="matrix(0.966, -0.259, 0.259, 0.966, -5641.551, -2527.47)"><g transform="translate(4642 4685)"><g class="d" transform="translate(0 0)"><path class="b" d="M4655.413,4706.173a1.167,1.167,0,0,1-.558.13,1.219,1.219,0,0,1-1.08-.65l-.088-.17-3.4-7.459a.642.642,0,0,1,.564-.867.688.688,0,0,1,.387.129l4.008,2.863a2.085,2.085,0,0,0,1.033.3,1.677,1.677,0,0,0,.646-.13l18.795-8.408a19.851,19.851,0,0,0-15.215-6.592c-10.259,0-18.621,6.98-18.621,15.6a14.731,14.731,0,0,0,6.421,11.789,1.289,1.289,0,0,1,.515,1,1.194,1.194,0,0,1-.087.389c-.3,1.168-.82,3.079-.82,3.163a1.55,1.55,0,0,0-.088.478.59.59,0,0,0,.6.607.49.49,0,0,0,.346-.129l4.05-2.385a2.052,2.052,0,0,1,.991-.3,2.3,2.3,0,0,1,.557.088,21.579,21.579,0,0,0,6.082.867c10.256,0,18.621-6.98,18.621-15.6a13.763,13.763,0,0,0-2.112-7.24l-21.417,12.439Zm0,0" transform="translate(-4641.886 -4685.302)"/></g></g></g></g></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1621586617012" class="icon" viewBox="0 0 1146 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6384" xmlns:xlink="http://www.w3.org/1999/xlink" width="17.90625" height="16"><defs><style type="text/css"></style></defs><path d="M0 788.389381a507.469027 108.743363 0 1 0 1014.938053 0 507.469027 108.743363 0 1 0-1014.938053 0Z" fill="#F3F3F8" p-id="6385"></path><path d="M321.880354 246.303717h367.915044l174.714337 220.749026s-174.895575 180.151504-352.328496 179.607788-357.584425-181.238938-357.584425-181.238938z" fill="#FBFBFD" p-id="6386"></path><path d="M797.451327 815.575221H217.486726a63.433628 63.433628 0 0 1-63.433629-63.433628V471.221239h166.558584l14.680354 29.360708A81.738761 81.738761 0 0 0 416.849558 579.964602h199.362831a63.614867 63.614867 0 0 0 63.433629-60.533806L711.72531 471.221239h149.159646v280.920354A63.433628 63.433628 0 0 1 797.451327 815.575221z" fill="#FBFBFD" p-id="6387"></path><path d="M797.451327 806.513274a54.371681 54.371681 0 0 0 54.371682-54.371681v-271.858407h-135.385487L688.707965 522.330619a72.495575 72.495575 0 0 1-72.495576 66.69593H416.849558a90.619469 90.619469 0 0 1-90.61947-86.088496l-11.236814-22.654867H163.115044v271.858407a54.371681 54.371681 0 0 0 54.371682 54.371681h579.964601m0 18.123894H217.486726a72.495575 72.495575 0 0 1-72.495576-72.495575v-289.982301h181.238938l18.123894 36.247788a72.495575 72.495575 0 0 0 72.495576 72.495575h199.362831a54.371681 54.371681 0 0 0 54.371682-54.371682l36.247787-54.371681h163.115045v289.982301a72.495575 72.495575 0 0 1-72.495576 72.495575z" fill="#E2E2EE" p-id="6388"></path><path d="M863.059823 467.958938L684.539469 253.734513H330.398584L151.87823 467.958938l-13.774159-11.599292L322.061593 235.610619h370.814867l183.957522 220.749027z" fill="#E2E2EE" p-id="6389"></path></svg>
\ No newline at end of file
/*
* 全局定义信息
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/8 07:18
*/
const errorPageRouteName = 'Error' //错误页面名称定义
const passGuardRouteList = [errorPageRouteName] // 不进入路由守卫的name
/** 定义支付方式 **/
const payWay = {
WXPAY : {wayCode: "WX_JSAPI", routeName: "CashierWxpay"},
ALIPAY : {wayCode: "ALI_JSAPI", routeName: "CashierAlipay"},
PAYTM : {wayCode: "PAYTM", routeName: "Cashierpaytm"}
}
export default {
errorPageRouteName: errorPageRouteName,
passGuardRouteList: passGuardRouteList,
urlTokenName: "jeepayToken", //URL传递的token名称
payWay: payWay,
cacheToken: ""
}
\ No newline at end of file
// 基准大小
const baseSize = 32
// 设置 rem 函数
function setRem () {
// 当前页面宽度相对于 750 宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / 750
// 设置页面根节点字体大小
document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem()
}
\ No newline at end of file
/**
* Http请求包装对象
* 参考: iview https://githubtest.com/icarusion/iview-admin/blob/master/src/libs/axios.js
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/8 07:18
*/
import axios from 'axios'
class HttpRequest {
constructor (baseUrl = process.env.VUE_APP_API_BASE_URL) {
this.baseUrl = baseUrl
this.queue = {} // 发送队列, 格式为: {请求url: true}, 可以做一些验证之类
}
// 基础配置信息
baseConfig () {
const headers = {}
return {
baseURL: this.baseUrl,
headers: headers
}
}
destroy (url) {
delete this.queue[url]
}
interceptors (instance, url, showErrorMsg, showLoading) {
// 请求拦截
instance.interceptors.request.use(config => {
// 添加全局的loading...
if (!Object.keys(this.queue).length && showLoading) {
//console.log("")
}
this.queue[url] = true
return config
}, error => {
return Promise.reject(error)
})
// 响应拦截
instance.interceptors.response.use(res => {
this.destroy(url, showLoading)
const resData = res.data // 接口实际返回数据 格式为:{code: '', msg: '', data: ''}, res.data 是axios封装对象的返回数据;
if (resData.code !== 0) { // 相应结果不为0, 说明异常
if (showErrorMsg) {
//
}
return Promise.reject(resData)
} else {
return resData.data
}
}, error => {
this.destroy(url, showLoading)
let errorInfo = error.response && error.response.data && error.response.data.data
if (!errorInfo) {
errorInfo = error.response.data
}
if (showErrorMsg) {
//Vue.prototype.$message.error(JSON.stringify(errorInfo)) // 显示异常信息
}
return Promise.reject(errorInfo)
})
}
// interceptorsFlag: 是否进行自定义拦截器处理,默认为: true
// showErrorMsg 发送请求出现异常是否全局提示错误信息
// showLoading 发送请求前后显示全局loading
request (options, interceptorsFlag = true, showErrorMsg = true, showLoading = false) {
const instance = axios.create()
options = Object.assign(this.baseConfig(), options)
if (interceptorsFlag) { // 注入 req, respo 拦截器
this.interceptors(instance, options.url, showErrorMsg, showLoading)
}
return instance(options)
}
}
export default HttpRequest
import HttpRequest from '@/http/HttpRequest'
const request = new HttpRequest()
export default request
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import wayCode from './utils/wayCode';
import config from './config'
import 'amfe-flexible'
Vue.config.productionTip = false
/**
* 路由守卫
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/8 07:18
*/
router.beforeEach((to, from, next) => {
console.log("进入路由守卫",from, to)
// from: 当前导航正要离开的路由
// to: 即将要进入的目标路由对象
// 如果在免登录页面则直接放行
if (config.errorPageRouteName.includes(to.name)) {
// 在免登录名单,直接进入
next()
return false
}
//获取不到参数
let token = to.params[config.urlTokenName];
// let token = 'test'; // 不提交
if(token){ //放置token信息
config.cacheToken = token;
}
config.cacheToken = "66f4f6ad7fc94252e8848196a4e1433fd179b730f070cbca57a138cbabbd8fd6"
if(!config.cacheToken) {
next({ name: config.errorPageRouteName, params: { errInfo: "请通过二维码进入支付页面!" } })
return false;
}
//获取不到支付类型, 需要跳转到错误页面
if( ! wayCode.getPayWay() ) {
next({ name: config.errorPageRouteName, params: { errInfo: "不支持的支付方式! 请在微信/支付宝/银联应用内扫码进入!" } })
return false;
}
next()
})
Vue.prototype.$config = config;
new Vue({
router,
render: h => h(App)
}).$mount('#app')
/**
* 路由配置信息
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/8 07:18
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
// hack router push callback
// [解决 vue-router跳转相同路径报错 ]
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push (location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
}
Vue.use(VueRouter)
const routes = [
{path: '/hub/:jeepayToken', name: 'Hub', component: () => import('../views/Hub.vue')}, //自动分发器
{path: '/error', name: 'Error', component: () => import('../views/Error.vue')},
{path: '/oauth2Callback/:jeepayToken', name: 'Oauth2Callback', component: () => import('../views/Oauth2Callback.vue')}, //oauth回调地址
{path: '/cashier', name: 'Cashier', component: () => import('../views/Cashier.vue'), //收银台(该地址无意义)
children: [
{ path: '/cashier/wxpay', name: 'CashierWxpay', component: () => import('../views/payway/Wxpay.vue') },
{ path: '/cashier/alipay', name: 'CashierAlipay', component: () => import('../views/payway/Alipay.vue') },
{ path: '/cashier/ysfpay', name: 'CashierYsfpay', component: () => import('../views/payway/Ysfpay.vue') },
{ path: '/cashier/paytm', name: 'Cashierpaytm', component: () => import('../views/payway/paytm.vue') }
]
}
]
const router = new VueRouter({
mode: 'hash', //history 需要nginx适配 hash:是#的格式。
base: "",
routes
})
export default router
/**
* 获取渠道用户 工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/8 07:18
*/
const getChannelUserId = function () {
return localStorage.getItem("channelUserId")
}
const setChannelUserId = function (channelUserId) {
localStorage.setItem("channelUserId", channelUserId)
}
export default {
getChannelUserId: getChannelUserId,
setChannelUserId: setChannelUserId
}
/**
* 获取支付方式工具类
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/5/8 07:18
*/
import config from '@/config'
const getToPageRouteName = function () {
const payWay = getPayWay();
return payWay? payWay.routeName : null
}
const getPayWay = function () {
const userAgent = navigator.userAgent;
if(userAgent.indexOf("MicroMessenger") >= 0){
return config.payWay.WXPAY;
}
if(userAgent.indexOf("AlipayClient") >= 0){
return config.payWay.ALIPAY;
}
else{
return config.payWay.PAYTM
}
// return null;
}
export default { getToPageRouteName: getToPageRouteName,
getPayWay: getPayWay
}
<template>
<router-view></router-view>
</template>
<script>
export default {
components: {
},
mounted() {
console.log("进入cashier页面");
}
}
</script>
<template>
<div class="center">
<img src="../assets/icon/error.svg" alt="">
<!-- <p>支付失败,请重新扫码进入!</p>-->
<p>错误: {{msg}}</p>
</div>
</template>
<script>
// 分发器页面, 用户扫码后进入的第一个页面:
// 判断是否存在channelUserId, 如果存在则直接跳到 对应的支付页面,如果不存在则重定向到对应的页面。
export default {
data () {
return {
msg: "请重新扫码进入!",
}
},
components: {
},
mounted() {
this.msg = this.$route.params.errInfo || '请重新扫码进入!'
}
}
</script>
<style lang="css" scoped>
.center {
margin-top:30%;
display: flex;
align-items: center;
flex-direction: column;
}
p {
font-size: 36px;
margin-top: 50px;
}
</style>
<template>
<div class="jump">
<!-- <p style="24px">
正在跳转到支付页面,请稍候~
</p> -->
<img src="@/assets/images/loading.gif" alt="" />
</div>
</template>
<script>
import {getRedirectUrl} from '@/api/api';
import config from "@/config";
// 分发器页面, 用户扫码后进入的第一个页面:
// 判断是否存在channelUserId, 如果存在则直接跳到 对应的支付页面,如果不存在则重定向到对应的页面。
export default {
components: {
},
mounted() {
console.log("正在跳转", this.$router.params)
// eslint-disable-next-line no-constant-condition
// if( true ){
// this.$router.push({name: "CashierAlipay"})
// return;
// }
//TODO 需要获取到不同的商户的userId
// if(channelUserId.getChannelUserId()){// 存在
//
// //重定向到对应的支付页面
// this.$router.push({name: wayCodeUtils.getPayWay().routeName})
// return ;
//
// }
const that = this;
//以下为不存在
getRedirectUrl().then(res => {
location.href = res;
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
}
}
</script>
<style lang="css" scoped>
.jump {
height:100vh;
width: 100vw;
display:flex;
justify-content: center;
align-items: center;
}
</style>
<template>
<div>
<!-- <p style="font-size:16px;">获取用户ID信息</p> -->
<p style="font-size:16px;">正在跳转...</p>
</div>
</template>
<script>
import {getChannelUserId} from '@/api/api'
import wayCodeUtils from '@/utils/wayCode'
import channelUserIdUtil from '@/utils/channelUserId'
import config from "@/config";
export default {
components: {
},
mounted() {
const allQuery = Object.assign({}, this.searchToObject(), this.$route.query)
const that = this;
getChannelUserId(allQuery).then(res => {
//设置channelUserId
channelUserIdUtil.setChannelUserId(res);
this.$router.push({name: wayCodeUtils.getPayWay().routeName})
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
},
methods: {
searchToObject: function() {
if(!window.location.search){
return {};
}
var pairs = window.location.search.substring(1).split("&"),
result = {},
pair,
i;
for ( i in pairs ) {
if ( pairs[i] === "" ) continue;
pair = pairs[i].split("=");
result[ decodeURIComponent( pair[0] ) ] = decodeURIComponent( pair[1] );
}
return result;
}
}
}
</script>
<!--
* @Author: your name
* @Date: 2020-12-23 09:04:09
* @LastEditors: 王会峰
* @LastEditTime: 2021-01-13 11:04:20
* @FilePath: \pay\src\components\dialog\dialog.vue
* @SendWord: 永无BUG vite⚡
-->
<template>
<div class="dialog">
<div class="dialog-box">
<div class="dialog-remark">添加备注</div>
<div class="dialog-input">
<input
type="text"
placeholder="最多输入10个字"
maxlength="10"
v-model="remarkC2"
/>
</div>
<div class="dialog-bnt">
<div class="dialog-bnt-l" @click="myDialogStateFn(false)">取消</div>
<div class="dialog-bnt-r" @click="myDialogStateFn(true)">确认</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "MyDialog",
data() {
return {
// remark: "",
remarkC: "",
remarkC2: "",
};
},
props: {
remark: {
type: String,
default: () => "",
},
},
/* mounted() {
this.remarkC = this.remark
}, */
created() {
this.remarkC = this.remark;
this.remarkC2 = this.remark;
},
methods: {
myDialogStateFn(remarkSate) {
let remark = this.remarkC2;
let remarkC = this.remarkC;
this.$emit("myDialogStateFn", remarkSate ? remark + "" : remarkC + "");
!remarkSate && (this.remarkC2 = remarkC);
remarkSate && (this.remarkC = remark);
},
},
};
</script>
<style lang="css" scoped>
.dialog {
z-index: 999;
top: 0;
left: 0;
position: fixed;
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.6);
}
.dialog-box {
width: 600px;
height: 359px;
background: #ffffff;
border-radius: 15px;
padding: 50px 0;
}
.dialog-remark {
width: 100%;
height: 46px;
font-size: 33px;
font-family: PingFang SC, PingFang SC-Bold;
font-weight: 700;
text-align: center;
color: #000000;
}
.dialog-input {
margin: 50px auto;
width: 510px;
height: 60px;
border-bottom: 1px solid #cccccc;
}
.dialog-input input {
margin-bottom: 5px;
width: 100%;
height: 46px;
font-size: 33px;
font-family: PingFang SC, PingFang SC-Regular;
font-weight: 400;
text-align: left;
border: none;
outline: none;
}
.dialog-bnt {
display: flex;
justify-content: space-between;
width: 100%;
border-top: 1px solid #e5e5e5;
}
.dialog-bnt div {
width: 50%;
height: 100px;
font-size: 30px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: center;
line-height: 100px;
}
.dialog-bnt-l {
color: #b2b2b2;
border-right: 1px solid #e5e5e5;
}
.dialog-bnt-r {
/* border-left: 1px solid #e5e5e5; */
color: #587cca;
}
</style>
\ No newline at end of file
/*
* @Author: your name
* @Date: 2020-12-23 09:05:40
* @LastEditors: 王会峰
* @LastEditTime: 2020-12-23 09:12:16
* @FilePath: \pay\src\components\dialog\index.js
* @SendWord: 永无BUG vite⚡
*/
import Vue from 'vue'
import Dialog from './dialog.vue'
const dialog = Vue.extend(Dialog)
Dialog.install = function(options, type) {
if (options === undefined || options === null) {
options = {
content: ''
}
} else if (typeof options === 'string' || typeof options === 'number') {
options = {
content: options
}
if (type != undefined && options != null) {
options.type = type;
}
}
let instance = new dialog({
data: options
}).$mount()
// document.querySelector('#app')
document.body.appendChild(instance.$el)
Vue.nextTick(() => {
instance.visible = true
})
}
export default Dialog
\ No newline at end of file
<!--
* @Author: your name
* @Date: 2020-12-23 10:46:37
* @LastEditors: 王会峰
* @LastEditTime: 2020-12-30 11:02:25
* @FilePath: \pay\src\components\keyboard\keyboard.vue
* @SendWord: 永无BUG vite⚡
-->
<template>
<div class="keyboard">
<div class="keyboard-top">
<div class="triangle-topleft-k"></div>
<div class="keyboard-tite">@小新支付</div>
<div class="triangle-topleft-k" @click="concealSateFn">
<div
class="triangle-topleft"
:style="
concealSate ? '' : 'transform:rotate(-135deg);margin-top: 12px;'
"
></div>
</div>
</div>
<div
class="keyboard-main"
v-show="concealSate"
style="transition: all 1s ease"
>
<div
v-for="(item, index) in numberList"
:key="index"
class="keyborad-key"
>
<!-- @click="onKeyboard(it, $event)" -->
<div
ref="number"
class="number"
v-for="(it, ind) in item"
:key="ind"
@touchstart.prevent="goTouchstart(it, $event)"
@touchend.prevent="goTouchend(it, $event)"
>
{{ it != "del" ? it : "" }}
<template class="" v-if="it == 'del'">
<!-- <div class="jiao"></div>
<div class="juxing"></div> -->
<img src="../../assets/icon/del.png" alt="" />
</template>
</div>
</div>
<div class="keyborad-key">
<div
class="number"
@touchstart.prevent="goTouchstart('dot', $event)"
@touchend.prevent="goTouchend('dot', $event)"
>
<div class="dot"></div>
</div>
<div
class="number zero"
@touchstart.prevent="goTouchstart('zero', $event)"
@touchend.prevent="goTouchend('zero', $event)"
>
0
</div>
</div>
</div>
<div
:class="paymentClassFn"
:style="'background:' + typeColor + ';'"
@click="payment"
>
<div>付款</div>
</div>
</div>
</template>
<script>
export default {
name: "Keyboard",
data() {
return {
timeOutEvent: 0, //记录触摸时长
tiemIntervalEvent: 0,
concealSateC: true,
numberList: [
[1, 2, 3, "del"],
[4, 5, 6],
[7, 8, 9],
],
};
},
computed: {
paymentClassFn() {
// `this` 指向 vm 实例
let className1 = this.concealSate ? "payment" : "paymentConceal";
let className2 = this.money != -1 && this.money != "" ? "" : "opacityS";
return className1 + " " + className2;
},
},
props: {
typeColor: {
type: String,
default: "#07c160",
},
money: {
type: String | Number,
default: -1,
},
concealSate: {
type: Boolean,
default: true,
},
},
mounted() {
this.concealSateC = this.concealSate;
},
methods: {
f() {},
payment() {
this.$emit("payment");
},
concealSateFn() {
// this.concealSateC = !this.concealSateC;
this.$emit("conceal");
},
onKeyboard(item, $event) {
/* setTimeout(() => {
$event.style.background = "#fafafa";
}, 100); */
// animation: heartBeat 0.2s;
if (item == "del") {
this.$emit("delTheAmount", item);
return;
}
let obj = {
zero: 0,
dot: ".",
};
if (typeof item != "number") {
item = obj[item];
}
this.$emit("enterTheAmount", item);
},
goTouchstart(it, $event) {
if (
$event.srcElement.localName == "img" ||
$event.srcElement.className == "dot"
) {
$event = $event.target.parentNode;
} else {
$event = $event.target;
}
$event.style.background = "rgba(197, 197, 197, 0.7)";
let _this = this;
clearTimeout(_this.timeOutEvent);
_this.timeOutEvent = setTimeout(function () {
_this.timeOutEvent = 0;
if (it == "del") {
clearInterval(_this.tiemIntervalEvent);
_this.delLong(it);
return;
}
// 处理长按事件...
}, 600);
},
//手如果在600毫秒内就释放,则取消长按事件
goTouchend(it, $event) {
console.log("goTouchend");
if (
$event.srcElement.localName == "img" ||
$event.srcElement.className == "dot"
) {
$event = $event.target.parentNode;
} else {
$event = $event.target;
}
$event.style.background = "#fafafa";
let _this = this;
clearTimeout(_this.timeOutEvent);
clearInterval(_this.tiemIntervalEvent);
if (_this.timeOutEvent !== 0) {
// 处理单击事件
this.onKeyboard(it, $event);
}
},
// 长按退格
delLong(item) {
// 定时触发
this.tiemIntervalEvent = setInterval(() => {
this.$emit("delTheAmount", item);
}, 200);
},
},
};
</script>
<style lang="css" scoped>
@keyframes switchColor {
0% {
background-color: #fff;
}
50% {
background-color: #bbbbbb;
}
100% {
background-color: #fff;
}
}
@font-face {
font-family: "wxFirstFont";
src: url("../../assets/wx-zt/WeChatSansSS-Bold.ttf"); /* IE9 */
}
img {
margin: 0;
padding: 0;
}
.keyboard {
position: relative;
background-color: #ffffff;
}
.keyboard-top {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 60px;
background: #fafafa;
border: 1px solid #e1e2e6;
border-bottom: 0px solid #e1e2e6;
}
.keyboard-tite {
/* margin-right: -40px; */
font-size: 22px;
font-family: wxFirstFont SC, PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: center;
color: #bbbdbf;
letter-spacing: 1px;
}
.triangle-topleft-k {
width: 200px;
/* height: 100%; */
display: flex;
justify-content: flex-end;
}
.triangle-topleft {
margin-top: -15px;
margin-right: 30px;
transform: rotate(45deg);
width: 0;
height: 0;
border-bottom: 18px solid #b2b2b2;
border-left: 18px solid transparent;
}
.keyboard-main {
width: 100%;
}
.keyborad-key {
display: flex;
flex-flow: wrap;
}
/* .del {
display: flex;
flex-flow: nowrap;
} */
.jiao {
margin-top: 4px;
margin-right: -16px;
width: 28px;
height: 28px;
transform: rotate(-45deg);
border-top: 3px solid #2c2c2c;
border-left: 3px solid #2c2c2c;
border-radius: 4px;
}
.juxing {
width: 40px;
height: 37px;
border: 3px solid #2c2c2c;
border-left: none;
border-radius: 4px;
}
.keyboard-main .number {
/* flex-grow: 1; */
display: flex;
justify-content: center;
align-items: center;
/* width: 187px; */
width: 25%;
height: 100px;
background: #fafafa;
border: 1px solid #e1e2e6;
border-bottom: none;
border-left: none;
font-size: 56px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: center;
line-height: 100px;
color: #242526;
letter-spacing: 2px;
}
.number img {
height: 37px;
width: 51px;
}
/* .number:active {
background-color: rgba(197, 197, 197, 0.527);
} */
.dot {
width: 6px;
height: 6px;
border-radius: 3px;
background-color: #242526 !important;
}
.keyboard-main .zero {
/* flex-grow: 2; */
width: 50%;
/* width: 374px; */
}
.payment {
flex-grow: 1;
position: absolute;
display: flex;
align-items: center;
bottom: 0;
right: 0;
width: calc(100vw / 4);
height: 300px;
background: #07c160;
transition: all 0.3s ease;
}
.paymentConceal {
flex-grow: 1;
position: absolute;
display: flex;
align-items: center;
right: 30px;
top: -180px;
/* width: 189px; */
width: calc(100vw / 4);
height: 150px;
background: #07c160;
border-radius: 10px;
transition: all 0.3s ease;
}
.payment div {
width: 100%;
font-size: 36px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: center;
color: #ffffff;
letter-spacing: 1px;
}
.paymentConceal div {
width: 100%;
font-size: 36px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: center;
color: #ffffff;
letter-spacing: 1px;
}
.opacityS {
opacity: 0.6;
}
</style>
\ No newline at end of file
<template>
<div>
<header class="header">
<div class="header-text">付款给 {{ payOrderInfo.mchName }}</div>
<div class="header-img">
<img :src="avatar ? avatar : icon_member_default" alt="" />
</div>
</header>
<div class="plus-input">
<!-- ¥字符 货币的符号-->
<div class="S">
<img src="../../assets/icon/S.svg" alt="" />
</div>
<!-- 手写输入框 -->
<div class="input-c">
<div class="input-c-div-1">{{ payOrderInfo.amount/100 }}</div>
</div>
<!-- 手写输入框的提示文字 -->
<div v-show="!amount" class="placeholder">请输入金额</div>
</div>
<ul class="plus-ul" >
<!-- 支付板块 -->
<li style="border-radius:10px;">
<!-- 支付金额板块 -->
<div class="img-div">
<img :src="wxImg" alt="" />
<div class="div-text">
支付宝支付
</div>
</div>
</li>
</ul>
<div class="bnt-pay">
<div
class="bnt-pay-text"
style="background-color:#1678ff"
@click="pay"
>
付款
</div>
</div>
</div>
</template>
<script>
import { getPayPackage, getPayOrderInfo } from '@/api/api'
import config from "@/config";
export default {
data: function (){
return {
merchantName: 'jeepay', // 付款的商户默认
avatar: require("../../assets/images/zfb.jpeg"), // 商户头像默认
amount: 1, // 支付金额默认
resData : {},
wxImg: require("../../assets/images/zfb.jpeg"), // 微信支付图片
payOrderInfo: {}, //订单信息
}
},
mounted() {
this.setPayOrderInfo(true); //获取订单信息 & 调起支付插件
},
methods: {
setPayOrderInfo(isAutoPay){
const that = this
getPayOrderInfo().then(res => {
that.payOrderInfo = res
if(isAutoPay){
that.pay()
}
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
},
pay: function (){
let that = this;
getPayPackage(this.amount).then(res => {
//订单创建异常
if(res.code != '0') {
return alert(res.msg);
}
if(res.data.orderState != 1 ) { //订单不是支付中,说明订单异常
return alert(res.data.errMsg);
}
if (!window.AlipayJSBridge) {
document.addEventListener('AlipayJSBridgeReady', function(){
that.doAlipay(res.data.alipayTradeNo);
}, false);
}else{
that.doAlipay(res.data.alipayTradeNo);
}
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
},
doAlipay(alipayTradeNo){
const that = this
// eslint-disable-next-line no-undef
AlipayJSBridge.call("tradePay", {
tradeNO: alipayTradeNo
}, function (data) {
if ("9000" == data.resultCode) {
// alert('支付成功!');
// //重定向
if(that.payOrderInfo.returnUrl){
location.href = that.payOrderInfo.returnUrl;
}else{
alert('支付成功!');
window.AlipayJSBridge.call('closeWebview')
}
//‘8000’:后台获取支付结果超时,暂时未拿到支付结果;
// ‘6004’:支付过程中网络出错, 暂时未拿到支付结果;
}else if("8000" == data.resultCode || "6004" == data.resultCode){ //其他
alert(JSON.stringify(data));
window.AlipayJSBridge.call('closeWebview')
}else{ ///其他异常信息, 需要取消订单
alert('用户已取消!');
window.AlipayJSBridge.call('closeWebview')
}
});
},
}
}
</script>
<style lang="css" scoped>
@import './pay.css';
</style>
\ No newline at end of file
<template>
<div>
<header class="header">
<div class="header-text">付款给{{ payOrderInfo.mchName }}</div>
<div class="header-img">
<img :src="avatar ? avatar : icon_member_default" alt="" />
</div>
</header>
<div class="plus-input">
<!-- ¥字符 货币的符号-->
<div class="S">
<img src="../../assets/icon/S.svg" alt="" />
</div>
<!-- 输入框光标 -->
<!-- <div class="ttt">
<div
class="input-c-div"
style="background: #07c160"
></div>
</div> -->
<!-- 手写输入框 -->
<div class="input-c">
<div class="input-c-div-1">{{ payOrderInfo.amount/100 }}</div>
<!-- 数字金额后边的光标 -->
<!-- <div class="input-c-div" style="background:#07c160"></div> -->
</div>
<!-- 手写输入框的提示文字 -->
<div v-show="!amount" class="placeholder">请输入金额</div>
</div>
<ul class="plus-ul" >
<!-- 支付板块 -->
<li
style="border-radius:10px;"
>
<!-- 支付金额板块 -->
<div class="img-div">
<img :src="wxImg" alt="" />
<div class="div-text">
微信支付
</div>
</div>
</li>
</ul>
<!-- 备注板块 ,目前不需要添加备注,隐藏-->
<!-- <div class="remark-k" :class="payType != 'wx' ? 'margin-top-30' : ''">
<div class="remark">
<div class="remark-hui" v-show="remark">{{ remark }}</div>
<div @click="myDialogStateFn">{{ remark ? "修改" : "添加备注" }}</div>
</div>
</div> -->
<!-- dialog 对话框 目前不需要添加备注,隐藏-->
<!-- <MyDialog
v-show="myDialogState"
@myDialogStateFn="myDialogStateFn"
:remark="remark"
>
</MyDialog> -->
<!-- 键盘板块 目前不需要键盘 隐藏 -->
<!-- <div class="keyboard-plus" v-if="isAllowModifyAmount">
<Keyboard
@delTheAmount="delTheAmount"
@conceal="conceal"
@enterTheAmount="enterTheAmount"
@payment="payment"
:money="money"
:concealSate="concealSate"
:typeColor="typeColor[payType]"
></Keyboard>
</div> -->
<!-- jeepay中,付款的点击事件 由 payment 修改为 pay -->
<!-- jeepay中,付款页面是唯一的,颜色不在需要v-bind,去掉即可 -->
<!-- <div class="bnt-pay" v-if="!isAllowModifyAmount"> -->
<div class="bnt-pay">
<div
class="bnt-pay-text"
style="background-color:#07c160"
@click="pay"
>
付款
</div>
</div>
</div>
</template>
<script>
// import MyDialog from "./../dialog/dialog"; // 添加备注弹出的对话框
// import Keyboard from "./../keyboard/keyboard"; // 手写键盘
import {getPayPackage, getPayOrderInfo }from '@/api/api'
import config from "@/config";
export default {
// 注册备注对话框,和 手写键盘组件,由于这里是直接掉起支付事件,所以目前不应用
// components: { MyDialog, Keyboard },
data: function (){
return {
merchantName: 'jeepay', // 付款的商户默认
avatar: require("../../assets/icon/wx.svg"), // 商户头像默认
amount: 1, // 支付金额默认
resData : {},
wxImg: require("../../assets/icon/wx.svg"), // 微信支付图片
payOrderInfo: {}, //订单信息
}
},
mounted() {
this.setPayOrderInfo(true); //获取订单信息 & 调起支付插件
},
methods: {
setPayOrderInfo(isAutoPay){
const that = this
getPayOrderInfo().then(res => {
that.payOrderInfo = res
if(isAutoPay){
that.pay()
}
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
},
// 支付事件
pay: function (){
// 该函数执行效果慢
let that = this;
getPayPackage(this.amount).then(res => {
if(res.code != '0') {
return alert(res.msg);
}
if(res.data.orderState != 1 ) { //订单不是支付中,说明订单异常
return alert(res.data.errMsg);
}
that.resData = res.data;
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', that.onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', that.onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', that.onBridgeReady);
}
}else{
that.onBridgeReady();
}
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
},
/* 唤醒微信支付*/
onBridgeReady() {
let that = this;
// eslint-disable-next-line no-undef
WeixinJSBridge.invoke(
'getBrandWCPayRequest', JSON.parse(that.resData.payInfo),
function(res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
// //重定向
if(that.payOrderInfo.returnUrl){
location.href = that.payOrderInfo.returnUrl;
}else{
alert('支付成功!');
window.WeixinJSBridge.call('closeWindow')
}
}
if (res.err_msg == "get_brand_wcpay_request:cancel") {
alert("支付取消");
window.WeixinJSBridge.call('closeWindow')
}
if (res.err_msg == "get_brand_wcpay_request:fail") {
alert('支付失败:' + JSON.stringify(res))
window.WeixinJSBridge.call('closeWindow')
}
if (res.err_msg == "total_fee") {
alert('缺少参数')
window.WeixinJSBridge.call('closeWindow')
}
}
);
},
}
}
</script>
<style lang="css" scoped>
@import './pay.css';
</style>
\ No newline at end of file
<template>
<div>
<header class="header">
<div class="header-text">付款给{{ merchantName }}</div>
<div class="header-img">
<img :src="avatar ? avatar : icon_member_default" alt="" />
</div>
</header>
<div class="plus-input">
<!-- ¥字符 货币的符号-->
<div class="S">
<img src="../../assets/icon/S.svg" alt="" />
</div>
<!-- 手写输入框 -->
<div class="input-c">
<div class="input-c-div-1">{{ amount }}</div>
</div>
<!-- 手写输入框的提示文字 -->
<div v-show="!amount" class="placeholder">请输入金额</div>
</div>
<ul class="plus-ul" >
<!-- 支付板块 -->
<li style="border-radius:10px;">
<!-- 支付金额板块 -->
<div class="img-div">
<img :src="wxImg" alt="" />
<div class="div-text">
云闪付支付
</div>
</div>
</li>
</ul>
<div class="bnt-pay">
<!-- <div
class="bnt-pay-text"
style="background-color:#ff534d"
@click="pay"
>
付款
</div> -->
</div>
</div>
</template>
<script>
import {getPayPackage}from '@/api/api'
import config from "@/config";
export default {
data: function (){
return {
merchantName: 'jeepay', // 付款的商户默认
avatar: require("../../assets/images/ysf.jpg"), // 商户头像默认
amount: 1, // 支付金额默认
resData : {},
wxImg: require("../../assets/images/ysf.jpg") // 微信支付图片
}
},
mounted() {
// this.pay(); //自动调起
},
methods: {
pay: function (){
let that = this;
getPayPackage(this.amount).then(res => {
console.log(res)
if (!window.AlipayJSBridge) {
document.addEventListener('AlipayJSBridgeReady', function(){
that.doAlipay(res.alipayTradeNo);
}, false);
}else{
that.doAlipay(res.alipayTradeNo);
}
}).catch(res => {
that.$router.push({name: config.errorPageRouteName, params: {errInfo: res.msg}})
});
},
doAlipay(alipayTradeNo){
// eslint-disable-next-line no-undef
AlipayJSBridge.call("tradePay", {
tradeNO: alipayTradeNo
}, function (data) {
if ("9000" == data.resultCode) {
alert('支付成功!');
}else{ //其他
}
});
},
}
}
</script>
<style lang="css" scoped>
@import './pay.css';
</style>
\ No newline at end of file
@font-face {
font-family: "wxFirstFont";
src: url("../../assets/wx-zt/WeChatSansSS-Bold.ttf"); /* IE9 */
}
@keyframes blink {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
* {
box-sizing: border-box;
}
body {
background-color: #ededed;
}
.header {
box-sizing: border-box;
display: flex;
width: 100%;
height: 88px;
padding: 50px;
justify-content: space-between;
align-items: center;
}
.margin-top-30 {
margin-top: 30px;
}
.header-text {
width: calc(100% - 120px);
height: 50px;
line-height: 50px;
text-align: left;
height: 50px;
font-size: 36px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
color: #323232;
letter-spacing: 1px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.header-img {
flex-shrink: 0;
width: 80px;
height: 80px;
border-radius: 40px;
/* background-color: #ff7b7b; */
overflow: hidden;
}
.header-img img {
width: 100%;
height: 100%;
}
.plus-input {
padding-top: 60px;
display: flex;
flex-shrink: 0;
justify-content: safe;
margin: 0 auto;
border-bottom: 1px solid #cccccc;
width: calc(100vw - 140px);
min-width: 160px;
height: 180px;
}
.plus-input .S {
position: relative;
width: 30px;
height: 40px;
margin: 15px 15px 15px 0;
}
.plus-input .S img {
position: absolute;
top: 15px;
left: 0;
width: 100%;
height: 100%;
/* margin-top: 10px; */
}
.plus-input input {
height: 98px;
width: 90%;
font-size: 70px;
font-family: wxFirstFont SC, PingFang SC, PingFang SC-Medium;
font-weight: 800;
text-align: left;
color: #000000;
letter-spacing: 2px;
border: none;
outline: none;
/* background-color: #ededed; */
background-color: rgba(220, 20, 60, 0);
}
.ttt {
display: flex;
align-items: center;
height: 98px;
width: 4px;
font-size: 70px;
font-family: wxFirstFont SC, PingFang SC, PingFang SC-Medium;
font-weight: 800;
text-align: center;
color: #000000;
letter-spacing: 2px;
border: none;
outline: none;
background-color: #ededed00;
}
.input-c {
display: flex;
align-items: center;
height: 98px;
width: 40px;
font-size: 70px;
font-family: wxFirstFont SC, PingFang SC, PingFang SC-Medium;
font-weight: 800;
text-align: center;
color: #000000;
letter-spacing: 2px;
border: none;
outline: none;
background-color: #ededed00;
/* background-color: rgb(255, 7, 57); */
}
.input-c-div-1 {
flex-shrink: 0;
width: 36px;
padding-left: 2px;
text-align: center;
/* width: auto; */
}
.input-c-div {
position: relative;
flex-shrink: 0;
margin-left: 5px;
margin-right: 5px;
width: auto;
height: 66px;
/* background: #07c160; */
animation: blink 1s linear infinite;
border: 1px solid #07c160;
}
.placeholder {
color: #6b6b6b;
font-weight: 400;
text-align: left;
padding-top: 4px;
font-size: 60px;
}
.plus-input input::-webkit-input-placeholder {
/* placeholder颜色 */
color: #6b6b6b;
font-weight: 400;
/* placeholder字体大小 */
/* font-size: 12px; */
/* placeholder位置 */
text-align: left;
}
.plus-ul {
margin-top: 20px;
margin-bottom: 0;
padding: 30px;
width: 100%;
}
.plus-ul li {
position: relative;
background: #fafafa;
padding: 41px 30px;
display: flex;
justify-content: space-between;
}
.plus-li {
margin-bottom: 20px;
border-radius: 15px;
}
.border-radius-top {
border-radius: 15px 15px 0 0;
}
.border-radius-bottom {
border-radius: 0 0 15px 15px;
}
.xian {
position: absolute;
bottom: 0px;
right: 0;
width: calc(100% - 103px);
height: 1px;
background: #ebebeb;
}
.img-div {
display: flex;
flex-flow: row;
}
.img-div img {
width: 42px;
height: 42px;
margin-right: 30px;
}
.img-div .div-text {
height: 42px;
font-size: 30px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: left;
color: #323232;
letter-spacing: 1px;
}
.div-go {
display: flex;
flex-flow: row;
align-items: center;
}
.div-go img {
width: 30px;
height: 30px;
}
.div-go-div {
margin-right: 10px;
font-size: 27px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: right;
color: #808080;
letter-spacing: 1px;
}
.pitch-on {
display: flex;
flex-flow: row;
}
.pitch-on-ok {
display: flex;
justify-content: center;
align-items: center;
border-radius: 21px;
width: 42px;
height: 42px;
background: #11c930;
}
.pitch-on-ok img {
width: 22px;
height: 16px;
}
.pitch-on-on {
border-radius: 21px;
width: 42px;
height: 42px;
background: rgba(17, 201, 48, 0);
border: 1px solid #bfbfbf;
}
.remark-k {
margin-top: 30px;
width: 100%;
display: flex;
justify-content: center;
font-size: 25px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: left;
color: #587cca;
letter-spacing: 1px;
}
.remark {
display: flex;
flex-flow: row;
}
.remark-hui {
width: auto;
height: 36px;
font-size: 25px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: left;
color: #808080;
letter-spacing: 1px;
margin-right: 30px;
}
.remark-hu {
font-size: 25px;
font-family: PingFang SC, PingFang SC-Medium;
font-weight: 500;
text-align: left;
color: #808080;
letter-spacing: 1px;
margin-right: 30px;
}
.keyboard-plus {
width: 100%;
position: fixed;
left: 0;
bottom: 0;
}
.bnt-pay {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
bottom: 100px;
width: 100vw;
z-index: 1;
}
.bnt-pay-text {
width: 300px;
color: #fff;
height: 100px;
border-radius: 16px;
background-color: darkgreen;
text-align: center;
line-height: 100px;
font-size: 40px;
}
\ No newline at end of file
<template>
<div>loading.......</div>
</template>
<script>
export default {
methods: {
// 唤醒Paytm应用
openPaytmApp() {
try{
// Paytm的支付URL
var paytmPaymentUrl = "paytmmp://pay?amount=10&orderid=123456789"
// 使用window.location导航到Paytm支付链接
// 构建带参数的 deep link
alert(paytmPaymentUrl)
window.location.href = paytmPaymentUrl;
// 如果无法打开应用,则重定向到网页版支付页面
// setTimeout(function() {
// window.location.href = 'https://www.paytm.com/payment'; // 替换为网页版支付页面的URL
// }, 3000); // 在3秒后重定向
}
catch(e){
alert(e)
}
}
},
created() {
this.openPaytmApp()
}
}
</script>
<style scoped lang="scss"></style>
\ No newline at end of file
// vue.config.js
const vueConfig = {
publicPath: process.env.VUE_APP_BASE_URL, // 前端资源访问根目录, 可配置到cdn目录下。 建议使用命令行环境变量进行替换。
devServer: {
disableHostCheck: true //不检查域名是否正确
},
css: {
loaderOptions: {
postcss: {
plugins: [
require('postcss-px2rem')({ remUnit: 75 }), // 换算的基数
]
}
}
}
}
module.exports = vueConfig
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment