支付组件

This commit is contained in:
aixianling
2023-09-26 17:56:17 +08:00
parent 6f3c2a05cc
commit 0a33fe480f
12 changed files with 338 additions and 8060 deletions

View File

@@ -3,10 +3,8 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "dev": "vue-cli-service --env.NODE_ENV=development build-watch --mode development",
"build": "vue-cli-service build", "build": "vue-cli-service build"
"lint": "vue-cli-service lint",
"build-watch": "vue-cli-service --env.NODE_ENV=development build-watch --mode development"
}, },
"dependencies": { "dependencies": {
"@antv/g2plot": "^2.4.31", "@antv/g2plot": "^2.4.31",
@@ -17,6 +15,7 @@
"element-ui": "^2.15.13", "element-ui": "^2.15.13",
"vue": "^2.6.14", "vue": "^2.6.14",
"vue-json-excel": "^0.3.0", "vue-json-excel": "^0.3.0",
"vue-qr": "^4.0.9",
"vue-router": "^3.2.0", "vue-router": "^3.2.0",
"vuex": "^3.4.0", "vuex": "^3.4.0",
"vuex-persistedstate": "^4.1.0" "vuex-persistedstate": "^4.1.0"
@@ -30,8 +29,8 @@
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",
"javascript-obfuscator": "2.6.0", "javascript-obfuscator": "2.6.0",
"sass": "^1.62.1", "sass": "^1.68.0",
"sass-loader": "7.2.0", "sass-loader": "^7.3.1",
"vue-cli-plugin-chrome-extension-cli": "~1.1.4", "vue-cli-plugin-chrome-extension-cli": "~1.1.4",
"vue-template-compiler": "^2.6.14", "vue-template-compiler": "^2.6.14",
"webpack-obfuscator": "2.6.0" "webpack-obfuscator": "2.6.0"

View File

@@ -1,4 +1,4 @@
@import "./styles.scss";
@font-face { @font-face {
font-family: 'iconfont'; /* project id 1995974 */ font-family: 'iconfont'; /* project id 1995974 */
src: url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.eot'); src: url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.eot');
@@ -8,6 +8,7 @@
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.ttf') format('truetype'), url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.ttf') format('truetype'),
url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.svg#iconfont') format('svg'); url('https://at.alicdn.com/t/font_1995974_ihzpmuv4lpk.svg#iconfont') format('svg');
} }
.iconfont { .iconfont {
font-family: "iconfont" !important; font-family: "iconfont" !important;
font-size: 16px; font-size: 16px;
@@ -168,6 +169,7 @@ textarea {
box-sizing: border-box; /* 1 */ box-sizing: border-box; /* 1 */
padding: 0; /* 2 */ padding: 0; /* 2 */
} }
[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button { [type="number"]::-webkit-outer-spin-button {
height: auto; height: auto;
@@ -265,7 +267,7 @@ img {
display: flex; display: flex;
} }
.flex-align { .flex-align, .flex-center {
display: flex; display: flex;
align-items: center; align-items: center;
} }
@@ -295,6 +297,7 @@ img {
.fade-enter-active, .fade-leave-active { .fade-enter-active, .fade-leave-active {
transition: opacity .3s ease-in-out; transition: opacity .3s ease-in-out;
} }
.fade-enter, .fade-leave-to { .fade-enter, .fade-leave-to {
opacity: 0; opacity: 0;
} }
@@ -332,6 +335,7 @@ img {
background: #1FBAD6 !important; background: #1FBAD6 !important;
border-color: #1FBAD6 !important; border-color: #1FBAD6 !important;
} }
.link-hover { .link-hover {
cursor: pointer; cursor: pointer;
transition: all ease .5s; transition: all ease .5s;

View File

@@ -0,0 +1,29 @@
@each $c in (333, 666, 999, red) {
@each $t, $v in (c:color, bg:background) {
.#{$t}-#{$c} {
#{$v}: #{'#'+$c};
}
}
}
@for $i from 1 through 30 {
@each $p, $pv in (margin:m, padding:p) {
.#{$pv}-#{$i} {
#{$p}: #{$i}px;
}
.#{$pv}v-#{$i} {
#{$p}-top: #{$i}px;
#{$p}-bottom: #{$i}px;
}
.#{$pv}h-#{$i} {
#{$p}-left: #{$i}px;
#{$p}-right: #{$i}px;
}
@each $pos, $v in (left:l, right:r, top:t, bottom:b) {
.#{$pv+$v}-#{$i} {
#{$p}-#{$pos}: #{$i}px;
}
}
}
}

BIN
src/assets/wechat_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,333 +0,0 @@
<template>
<div class="ai-article">
<div v-html="value"></div>
</div>
</template>
<script>
export default {
name: 'AiArticle',
props: {
value: {
type: String
}
}
}
</script>
<style lang="scss" scoped>
.ai-article {
width: 100%;
line-height: 1.75;
font-weight: 400;
color: #333;
font-size: 14px;
text-align: justify;
overflow-x: auto;
word-break: break-word;
:deep( h1 ){
margin: 1.3rem 0;
line-height: 1.2
}
:deep( p ){
line-height: 2.27rem
}
:deep( hr ){
border: none;
border-top: 1px solid #ddd;
margin-top: 2.7rem;
margin-bottom: 2.7rem
}
:deep( img:not(.equation)), :deep( iframe), :deep( embed), :deep( video ){
display: block;
margin: 18px auto;
max-width: 100% !important;
}
:deep( img.equation ){
margin: 0 .1em;
max-width: 100% !important;
vertical-align: middle
}
:deep( figure ){
margin: 2.7rem auto;
text-align: center
}
:deep( img:not(.equation) ){
cursor: zoom-in
}
:deep( figure figcaption ){
text-align: center;
font-size: 1rem;
line-height: 2.7rem;
color: #909090
}
:deep( pre ){
line-height: 1.93rem;
overflow: auto
}
:deep( code),
:deep( pre ){
font-family: Menlo, Monaco, Consolas, Courier New, monospace
}
:deep( code ){
font-size: 1rem;
padding: .26rem .53em;
word-break: break-word;
color: #4e5980;
background-color: #f8f8f8;
border-radius: 2px;
overflow-x: auto
}
:deep( pre>code ){
font-size: 1rem;
padding: .67rem 1.3rem;
margin: 0;
word-break: normal;
display: block
}
:deep( a ){
color: #259
}
:deep( a:active),
:deep( a:hover ){
color: #275b8c
}
:deep( table ){
width: 100%;
margin-top: 18px;
margin-bottom: 18px;
overflow: auto;
font-size: 1rem;
text-align: center;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
}
:deep( thead ){
background: #f6f6f6;
color: #000;
text-align: left
}
:deep( td),
:deep( th ){
padding: 3px 5px;
border-bottom: 1px solid #ccc;
border-right: 1px solid #ccc;
}
:deep( td ){
min-width: 10rem
}
:deep( blockquote ){
margin: 1em 0;
border-left: 4px solid #ddd;
padding: 0 1.3rem
}
:deep( blockquote>p ){
margin: .6rem 0
}
:deep( ol),
:deep( ul ){
padding-left: 2.7rem
}
:deep( ol li),
:deep( ul li ){
margin-bottom: .6rem
}
:deep( ol ol),
:deep( ol ul),
:deep( ul ol),
:deep( ul ul ){
margin-top: .27rem
}
:deep( pre>code ){
overflow-x: auto;
-webkit-overflow-scrolling: touch;
color: #333;
background: #f8f8f8
}
:deep( p ){
line-height: inherit;
margin-top: 18px;
margin-bottom: 18px
}
:deep( p:first-child){
margin-top: 0!important;
}
:deep( img ){
max-height: none
}
:deep( a ){
color: #0269c8;
border-bottom: 1px solid #d1e9ff
}
:deep( code ){
background-color: #fff5f5;
color: #ff502c;
font-size: .87em;
padding: .065em .4em
}
:deep( blockquote ){
color: #666;
padding: 1px 23px;
margin: 18px 0;
border-left: 4px solid #cbcbcb;
background-color: #f8f8f8
}
:deep( blockquote:after ){
display: block;
content: ""
}
:deep( blockquote>p ){
margin: 10px 0
}
:deep( blockquote.warning ){
position: relative;
border-left-color: #f75151;
margin-left: 8px
}
:deep( blockquote.warning:before ){
position: absolute;
top: 14px;
left: -12px;
background: #f75151;
border-radius: 50%;
content: "!";
width: 20px;
height: 20px;
color: #fff;
display: flex;
align-items: center;
justify-content: center
}
:deep( ol),
:deep( ul ){
padding-left: 28px
}
:deep( ol li),
:deep( ul li ){
margin-bottom: 0;
list-style: inherit
}
:deep( ol li.task-list-item),
:deep( ul li.task-list-item ){
list-style: none
}
:deep( ol li.task-list-item ol),
:deep( ol li.task-list-item ul),
:deep( ul li.task-list-item ol),
:deep( ul li.task-list-item ul ){
margin-top: 0
}
:deep( ol li ){
padding-left: 6px
}
:deep( pre ){
position: relative;
line-height: 1.75
}
:deep( pre>code ){
padding: 15px 12px
}
:deep( pre>code.hljs[lang] ){
padding: 18px 15px 12px
}
:deep( h1),
:deep( h2),
:deep( h3),
:deep( h4),
:deep( h5),
:deep( h6 ){
color: #333;
line-height: 1.5;
margin-top: 35px;
margin-bottom: 10px;
padding-bottom: 5px;
font-weight: 500;
}
:deep( h1 ){
font-size: 30px;
margin-bottom: 5px
}
:deep( h2 ){
padding-bottom: 12px;
font-size: 24px;
border-bottom: 1px solid #ececec
}
:deep( h3 ){
font-size: 18px;
padding-bottom: 0
}
:deep( h4 ){
font-size: 16px
}
:deep( h5 ){
font-size: 15px
}
:deep( h6 ){
margin-top: 5px
}
:deep( h1.heading+h2.heading ){
margin-top: 20px
}
:deep( h1.heading+h3.heading ){
margin-top: 15px
}
:deep( .heading+.heading ){
margin-top: 0
}
:deep( h1+:not(.heading) ){
margin-top: 25px
}
}
</style>

View File

@@ -0,0 +1,180 @@
<template>
<section class="AiPayment">
<el-tabs type="card" stretch v-model="search.module" @tab-click="getPayments">
<el-tab-pane label="基础会员" name="0"/>
<el-tab-pane label="金币充值" name="1"/>
</el-tabs>
<div class="content">
<div class="payments mb-16">
<div class="card" v-for="pay in payments" :key="pay.id" :class="{active:pay.id==selected}"
@click="getQrcode(pay.id)">
<div v-text="pay.title"/>
<div class="c-red mt-16" v-text="`¥${pay.price}`"/>
</div>
</div>
<el-row type="flex" align="middle">
<ul class="fill">
<li v-for="(desc,i) in descriptions" :key="i" v-text="desc"/>
</ul>
<div class="fill flex-center">
<vue-qr v-if="qrcode" :text="qrcode" :size="120" :margin="8" :logoSrc="wechatLogo"/>
<div v-else class="qrcode c-666">请选择<br>支付方案</div>
<div class="c-999 ml-16">
<div class="flex-center mb-16">
应付金额{{ amount }}
</div>
<div class="wechat flex-center">
微信扫码支付
</div>
</div>
</div>
</el-row>
<div class="bottom flex-center">
<el-button size="small">取消支付</el-button>
<el-button size="small">已扫码支付</el-button>
</div>
</div>
</section>
</template>
<script>
import VueQr from "vue-qr"
export default {
name: "AiPayment",
components: {VueQr},
props: {},
data() {
return {
search: {module: "0"},
show: true,
descriptions: ["抢仓发货", "数据下载", "复制商品", "会员服务"],
payments: [],
qrcode: "",
amount: 0,
selected: ""
}
},
computed: {
wechatLogo: v => require("../assets/wechat_logo.png")
},
methods: {
getPayments() {
this.$http.post("/api/priceConfig/page", null, {
params: {...this.search}
}).then(res => {
if (res?.data) {
this.payments = res.data.records || []
}
})
},
getQrcode(priceConfigId) {
this.selected = priceConfigId
this.$http.post("/api/order/createOrder", null, {
params: {priceConfigId}
}).then(res => {
if (res?.data?.id) {
return res.data.id
}
}).then(id => this.$http.post("/api/order/createPrepayOrder", null, {
params: {id}
})).then(res => {
if (res?.data) {
this.qrcode = res.data.codeUrl
}
})
}
},
created() {
this.getPayments()
}
}
</script>
<style scoped lang="scss">
.AiPayment {
font-size: 16px;
:deep(.el-tabs) {
z-index: 4;
.is-active {
border-bottom-color: transparent;
}
}
ul {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 16px;
li {
list-style-type: circle;
}
}
.payments {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-gap: 32px;
.card {
user-select: none;
text-align: center;
border: 1px solid #ddd;
padding: 32px 64px;
border-radius: 4px;
&.active {
border-color: #26f;
position: relative;
&:after {
position: absolute;
right: 8px;
bottom: 8px;
display: block;
text-align: center;
line-height: 20px;
width: 20px;
height: 20px;
font-size: 16px;
content: "✔";
color: white;
background: #26f;
border-radius: 50%;
}
}
}
}
.content {
padding: 16px 32px;
margin-top: -16px;
border: 1px solid #ddd;
z-index: 9;
.qrcode {
width: 120px;
height: 120px;
background-color: #eee;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
}
.wechat {
line-height: 20px;
padding-left: 28px;
background-image: url("../assets/wechat_logo.png");
background-repeat: no-repeat;
background-position: left center;
background-size: 20px 20px;
}
.bottom {
justify-content: right;
}
}
</style>

View File

@@ -60,7 +60,6 @@ export default new Vuex.Store({
}) })
}) })
}, },
SignOut(store, isClear) { SignOut(store, isClear) {
if (isClear) { if (isClear) {
store.commit('logout') store.commit('logout')

View File

@@ -90,28 +90,8 @@
:close-on-click-modal="false" :close-on-click-modal="false"
width="30%" width="30%"
:before-close="handleClose"> :before-close="handleClose">
<el-form :model="form" label-position="top" ref="form" label-width="100px" class="form">
<el-form-item
prop="mallName"
label="当前绑定账号"
:rules="[{ required: true, message: '请先登录拼多多跨境卖家中心', trigger: 'blur' }]">
<el-input readonly placeholder="请先登录拼多多跨境卖家中心" v-model="form.mallName"></el-input>
</el-form-item>
<el-form-item
prop="mallId"
v-show="false"
:rules="[{ message: '请输入商城ID', trigger: 'blur' }]">
<el-input placeholder="请输入商城ID" v-model="form.mallId"></el-input>
</el-form-item>
<el-form-item
prop="code"
label="激活码"
:rules="[{ required: true, message: '请输入激活码', trigger: 'blur' }]">
<el-input placeholder="请输入激活码" v-model="form.code"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="$store.commit('setActiveDlgShow', false)"> </el-button> <el-button @click="setActiveDlgShow(false)"> </el-button>
<el-button type="primary" @click="active"> </el-button> <el-button type="primary" @click="active"> </el-button>
</span> </span>
</el-dialog> </el-dialog>
@@ -119,9 +99,11 @@
</template> </template>
<script> <script>
import { mapState } from 'vuex' import {mapMutations, mapState} from 'vuex'
import AiPayment from "@/components/AiPayment.vue";
export default { export default {
components: {AiPayment},
data () { data () {
return { return {
isCollapse: false, isCollapse: false,
@@ -168,6 +150,7 @@
}, },
methods: { methods: {
...mapMutations(['setActiveDlgShow']),
handleClick (e) { handleClick (e) {
if (e === 'logout') { if (e === 'logout') {
this.$store.dispatch('SignOut', false) this.$store.dispatch('SignOut', false)
@@ -181,10 +164,10 @@
this.form.mallId = ""; this.form.mallId = "";
this.form.mallName = ""; this.form.mallName = "";
this.form.code = ""; this.form.code = "";
this.$store.commit('setActiveDlgShow', false) this.setActiveDlgShow(false)
}, },
toActive() { toActive() {
this.$store.commit('setActiveDlgShow', true) this.setActiveDlgShow(true)
}, },
getMessage(type) { getMessage(type) {
return `你使用的是“${this.vipType[type]}”兑换券,确定兑换?`; return `你使用的是“${this.vipType[type]}”兑换券,确定兑换?`;
@@ -212,7 +195,7 @@
if (res.code == 0) { if (res.code == 0) {
this.$message.success('激活成功') this.$message.success('激活成功')
this.$store.dispatch('getUserInfo') this.$store.dispatch('getUserInfo')
this.$store.commit('setActiveDlgShow', false) this.setActiveDlgShow(false)
} }
}) })
}) })

View File

@@ -32,6 +32,7 @@
</div> </div>
</ai-card> </ai-card>
</div> </div>
<ai-payment/>
<ai-card title="常用工具" v-if="false"> <ai-card title="常用工具" v-if="false">
<div class=""> <div class="">
dsad dsad
@@ -58,9 +59,11 @@
</template> </template>
<script> <script>
import AiPayment from "@/components/AiPayment.vue";
export default { export default {
name: 'AdminHome', name: 'AdminHome',
components: {AiPayment},
data () { data () {
return { return {
noticeList: [], noticeList: [],

View File

@@ -51,6 +51,6 @@ export default {
} }
</script> </script>
<style> <style lang="scss">
@import '../assets/css/index.scss'; @import '../assets/css/index.scss';
</style> </style>

View File

@@ -7,8 +7,7 @@ const obfuscateConfig = require('./obfuscator.config')
const pages = {} const pages = {}
function getEntryFile (entryPath) { function getEntryFile (entryPath) {
let files = fs.readdirSync(entryPath) return fs.readdirSync(entryPath)
return files
} }
const chromeName = getEntryFile(path.resolve(`src/entry`)) const chromeName = getEntryFile(path.resolve(`src/entry`))
@@ -32,20 +31,20 @@ module.exports = {
pages, pages,
filenameHashing: false, filenameHashing: false,
chainWebpack: (config) => { chainWebpack: (config) => {
config.plugin('copy').use(require('copy-webpack-plugin'), [ // config.plugin('copy').use(require('copy-webpack-plugin'), [
{ // {
patterns: [ // patterns: [
{ // {
from: path.resolve(`src/manifest.${process.env.NODE_ENV}.json`), // from: path.resolve(`src/manifest.${process.env.NODE_ENV}.json`),
to: `${path.resolve('dist')}/manifest.json` // to: `${path.resolve('dist')}/manifest.json`
}, // },
{ // {
from: path.resolve(`public/`), // from: path.resolve(`public/`),
to: `${path.resolve('dist')}/` // to: `${path.resolve('dist')}/`
} // }
] // ]
} // }
]) // ])
}, },
devServer: { devServer: {
port: 8080, port: 8080,

7585
yarn.lock

File diff suppressed because it is too large Load Diff