Commit 663f7447 authored by zhangsan's avatar zhangsan

1

parent 2e2ba9cf
......@@ -25,7 +25,7 @@
},
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"build": "vite build",
"build:test": "vue-tsc --noEmit && vite build --mode test",
"preinstall": "npx only-allow pnpm",
"prepare": "husky install",
......@@ -45,6 +45,7 @@
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"mitt": "^3.0.1",
"qrcode": "^1.5.4",
"vant": "^4.8.5",
"vue": "^3.4.21"
},
......@@ -54,8 +55,10 @@
"@commitlint/config-conventional": "^19.1.0",
"@iconify-json/carbon": "^1.1.31",
"@ls-lint/ls-lint": "^2.2.2",
"@types/crypto-js": "^4.2.2",
"@types/fs-extra": "^11.0.4",
"@types/node": "20.9.0",
"@types/qrcode": "^1.5.5",
"@unocss/eslint-plugin": "^0.58.6",
"@unocss/preset-rem-to-px": "^0.58.6",
"@varlet/import-resolver": "^3.8.5",
......
......@@ -3,10 +3,6 @@
"path": "404",
"title": "404-页面未找到"
},
{
"path": "detail",
"title": "项目详情"
},
{
"path": "guquan",
"title": "股权"
......
......@@ -26,6 +26,9 @@ importers:
mitt:
specifier: ^3.0.1
version: 3.0.1
qrcode:
specifier: ^1.5.4
version: 1.5.4
vant:
specifier: ^4.8.5
version: 4.8.5(vue@3.4.21(typescript@5.4.2))
......@@ -48,12 +51,18 @@ importers:
'@ls-lint/ls-lint':
specifier: ^2.2.2
version: 2.2.2
'@types/crypto-js':
specifier: ^4.2.2
version: 4.2.2
'@types/fs-extra':
specifier: ^11.0.4
version: 11.0.4
'@types/node':
specifier: 20.9.0
version: 20.9.0
'@types/qrcode':
specifier: ^1.5.5
version: 1.5.5
'@unocss/eslint-plugin':
specifier: ^0.58.6
version: 0.58.6(eslint@8.57.0)(typescript@5.4.2)
......@@ -1417,6 +1426,9 @@ packages:
'@types/conventional-commits-parser@5.0.0':
resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==}
'@types/crypto-js@4.2.2':
resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
'@types/eslint@8.56.5':
resolution: {integrity: sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw==}
......@@ -1450,6 +1462,9 @@ packages:
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
'@types/qrcode@1.5.5':
resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==}
'@types/semver@7.5.5':
resolution: {integrity: sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==}
......@@ -2042,6 +2057,10 @@ packages:
resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==}
engines: {node: '>=4'}
camelcase@5.3.1:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
......@@ -2119,6 +2138,9 @@ packages:
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
engines: {node: '>=18'}
cliui@6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
......@@ -2347,6 +2369,9 @@ packages:
resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==}
engines: {node: '>=12.20'}
dijkstrajs@1.0.3:
resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==}
dir-glob@2.2.2:
resolution: {integrity: sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==}
engines: {node: '>=4'}
......@@ -3992,6 +4017,10 @@ packages:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
pngjs@5.0.0:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
posix-character-classes@0.1.1:
resolution: {integrity: sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==}
engines: {node: '>=0.10.0'}
......@@ -4146,6 +4175,11 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
qrcode@1.5.4:
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
engines: {node: '>=10.13.0'}
hasBin: true
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
......@@ -4261,6 +4295,9 @@ packages:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
require-main-filename@2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
resolve-from@3.0.0:
resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==}
engines: {node: '>=4'}
......@@ -4354,6 +4391,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
set-value@2.0.1:
resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==}
engines: {node: '>=0.10.0'}
......@@ -5057,6 +5097,9 @@ packages:
webpack-virtual-modules@0.6.1:
resolution: {integrity: sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==}
which-module@2.0.1:
resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
which@1.3.1:
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
hasBin: true
......@@ -5071,6 +5114,10 @@ packages:
engines: {node: ^16.13.0 || >=18.0.0}
hasBin: true
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
......@@ -5105,6 +5152,9 @@ packages:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
y18n@4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
......@@ -5126,10 +5176,18 @@ packages:
yargs-parser@10.1.0:
resolution: {integrity: sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==}
yargs-parser@18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
yargs@15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
......@@ -6556,6 +6614,8 @@ snapshots:
dependencies:
'@types/node': 20.9.0
'@types/crypto-js@4.2.2': {}
'@types/eslint@8.56.5':
dependencies:
'@types/estree': 1.0.5
......@@ -6593,6 +6653,10 @@ snapshots:
'@types/normalize-package-data@2.4.4': {}
'@types/qrcode@1.5.5':
dependencies:
'@types/node': 20.9.0
'@types/semver@7.5.5': {}
'@types/unist@2.0.10': {}
......@@ -7416,6 +7480,8 @@ snapshots:
camelcase@4.1.0: {}
camelcase@5.3.1: {}
camelcase@6.3.0: {}
caniuse-lite@1.0.30001597: {}
......@@ -7501,6 +7567,12 @@ snapshots:
slice-ansi: 5.0.0
string-width: 7.1.0
cliui@6.0.0:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
cliui@8.0.1:
dependencies:
string-width: 4.2.3
......@@ -7687,6 +7759,8 @@ snapshots:
detect-indent@7.0.1: {}
dijkstrajs@1.0.3: {}
dir-glob@2.2.2:
dependencies:
path-type: 3.0.0
......@@ -9442,6 +9516,8 @@ snapshots:
pluralize@8.0.0: {}
pngjs@5.0.0: {}
posix-character-classes@0.1.1: {}
postcss-html@0.36.0(postcss-syntax@0.36.2(postcss-html@1.6.0)(postcss-scss@4.0.9(postcss@8.4.35))(postcss@8.4.35))(postcss@7.0.39):
......@@ -9579,6 +9655,12 @@ snapshots:
punycode@2.3.1: {}
qrcode@1.5.4:
dependencies:
dijkstrajs: 1.0.3
pngjs: 5.0.0
yargs: 15.4.1
queue-microtask@1.2.3: {}
quick-lru@1.1.0: {}
......@@ -9735,6 +9817,8 @@ snapshots:
require-from-string@2.0.2: {}
require-main-filename@2.0.0: {}
resolve-from@3.0.0: {}
resolve-from@4.0.0: {}
......@@ -9824,6 +9908,8 @@ snapshots:
dependencies:
lru-cache: 6.0.0
set-blocking@2.0.0: {}
set-value@2.0.1:
dependencies:
extend-shallow: 2.0.1
......@@ -10682,6 +10768,8 @@ snapshots:
webpack-virtual-modules@0.6.1: {}
which-module@2.0.1: {}
which@1.3.1:
dependencies:
isexe: 2.0.0
......@@ -10694,6 +10782,12 @@ snapshots:
dependencies:
isexe: 3.1.1
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
......@@ -10729,6 +10823,8 @@ snapshots:
xtend@4.0.2: {}
y18n@4.0.3: {}
y18n@5.0.8: {}
yallist@3.1.1: {}
......@@ -10747,8 +10843,27 @@ snapshots:
dependencies:
camelcase: 4.1.0
yargs-parser@18.1.3:
dependencies:
camelcase: 5.3.1
decamelize: 1.2.0
yargs-parser@21.1.1: {}
yargs@15.4.1:
dependencies:
cliui: 6.0.0
decamelize: 1.2.0
find-up: 4.1.0
get-caller-file: 2.0.5
require-directory: 2.1.1
require-main-filename: 2.0.0
set-blocking: 2.0.0
string-width: 4.2.3
which-module: 2.0.1
y18n: 4.0.3
yargs-parser: 18.1.3
yargs@17.7.2:
dependencies:
cliui: 8.0.1
......
......@@ -3,7 +3,6 @@ import App from './App.vue';
import Varlet from '@varlet/ui'
import router from './router';
import './assets/global.css'; // 引入全局样式
'
const app = createApp(App);
app.use(router);
......
<template>
<defaultLayout>
<div class="container">
<GuideModal :show="showGuide" :guide-list="content" @close="showGuide = false" />
<GuideModal v-model="showGuide" :guide-list="content" />
<div class="imgwarp">
<img src="@/static/common/login.png" />
</div>
......@@ -99,12 +99,16 @@ const navigateTo = (path) => {
async function handleGetCard() {
if (userData.value.data !== 'true') {
showFailToast('请先实名注册后启用此卡');
setTimeout(() => {
navigateTo('/user/shiming.html');
}, 2000)
return;
}
if (userData.value.smCount < 3) {
showFailToast('需邀请3位用户参与一带一路即可启用此卡');
setTimeout(() => {
navigateTo('/user/invite.html');
}, 2000)
return;
}
if (cardinfo.value?.bankNum) {
......@@ -112,7 +116,7 @@ async function handleGetCard() {
return;
}
try {
const res = await post('/ops/bankcard/add', { cardtype: 2 });
const res = await request.post('/ops/bankcard/add', { cardtype: 2 });
if (res.code === 200) {
showSuccessToast('启用成功');
await getCardList(); // 刷新卡片列表
......@@ -125,12 +129,16 @@ async function handleGetCard() {
function gotx(balance, type, title) {
if (userData.value.data != 'true') {
showFailToast('请先实名注册后启用此卡')
setTimeout(() => {
navigateTo('/user/shiming.html')
}, 2000)
return
}
if (userData.value.smCount < 3) {
showFailToast('需邀请3位用户参与一带一路即可启用此卡')
setTimeout(() => {
navigateTo('/user/invite.html')
}, 2000)
return
}
if (balance && balance > 0) {
......
......@@ -13,6 +13,12 @@ import png6 from '@/static/my/a6.png'
import png7 from '@/static/my/a7.png'
import png8 from '@/static/my/a8.png'
import png9 from '@/static/my/a9.png'
const kfurl = ref('')
request.get('/system/config/configKey/mous/apk_version', {}).then(res => {
if (res.code === 200) {
kfurl.value = res.msg
}
})
const MENU_ITEMS = ref([
{ name: '实名认证', icon: png1, path: '/user/shiming.html' },
......@@ -23,7 +29,7 @@ const MENU_ITEMS = ref([
{ name: 'APP下载', icon: png6, path: '/user/appdownload.html' },
{ name: '我的团队', icon: png7, path: '/user/myteam.html' },
{ name: '账号安全', icon: png8, path: '/user/accountSecurity.html' },
{ name: '邀请好友', icon: png9, path: '/yaoqing.html' },
{ name: '邀请好友', icon: png9, path: '/user/invite.html' },
])
const navigateTo = (path) => {
window.location.href = window.location.origin + path
......@@ -79,6 +85,9 @@ function logout() {
navigateTo('/login.html')
})
}
function navigateTo1(kfurl) {
window.location.href = kfurl
}
onMounted(fetchData)
</script>
......@@ -115,7 +124,7 @@ onMounted(fetchData)
<img src="@/static/my/qd.png" alt="sign">
<span>每日签到</span>
</div>
<div v-ripple class="qd" style="margin-top: 4px;">
<div v-ripple class="qd" style="margin-top: 4px;" @click="navigateTo1(kfurl)">
<img src="@/static/my/kf.png" alt="sign">
<span>在线客服</span>
</div>
......
......@@ -40,7 +40,7 @@
立即注册
</div>
<div class="infowarp">
<div class="register">
<div class="register" @click="navigateTo(kfurl)">
联系我们
</div>
<div class="line">
......@@ -60,7 +60,6 @@ const navigateTo = (path: string) => {
import { ref, reactive } from 'vue'
import request from '@/utils/request'
import { showFailToast, showSuccessToast } from 'vant'
interface FormData {
username: string
password: string
......@@ -80,7 +79,14 @@ const formData = reactive<FormData>({
inviteCode: '',
extend3: '',
})
const kfurl = ref('')
request.get('/system/config/configKey/mous/apk_version', {}).then(res => {
if (res.code === 200) {
kfurl.value = res.msg
}
})
formData.inviteCode = window.location.search.split('=')[1]
function validateForm(): boolean {
if (!formData.username) {
showFailToast('请输入手机号')
......@@ -128,7 +134,7 @@ async function handleSubmit() {
if (res.code === 200) {
showSuccessToast('注册成功')
setTimeout(() => {
navigateTo('/')
window.location.href = '/login.html'
}, 1000)
} else {
showFailToast(res.msg || '注册失败')
......
......@@ -111,7 +111,7 @@ onMounted(() => {
</div> -->
<!-- 昵称设置 -->
<div class="menu-item" @click="navigateTo('/user/resetNickname')">
<div class="menu-item" @click="navigateTo('/user/resetNickname.html')">
<div class="left">
<van-icon name="contact" class="menu-icon" />
<span>姓名</span>
......@@ -123,7 +123,7 @@ onMounted(() => {
</div>
<!-- 登录密码 -->
<div class="menu-item" @click="navigateTo('/user/resetPass')">
<div class="menu-item" @click="navigateTo('/user/resetPass.html')">
<div class="left">
<van-icon name="lock" class="menu-icon" />
<span>修改登录密码</span>
......@@ -134,7 +134,7 @@ onMounted(() => {
</div>
<!-- 交易密码 -->
<div class="menu-item" @click="navigateTo('/user/resetPayPass')">
<div class="menu-item" @click="navigateTo('/user/resetPayPass.html')">
<div class="left">
<van-icon name="shield-o" class="menu-icon" />
<span>修改交易密码</span>
......
......@@ -2,10 +2,8 @@
import { ref } from 'vue'
import AppHeader from '@/components/AppHeader.vue'
const isqq = ref(false)
// const downloadUrl = ref('https://dwlink.dwzhengs13.com')
const downloadUrl = ref('')
const downloadUrl = ref('https://down.yidaiyilu2025.com')
const handleDownload = () => {
return false
window.open(downloadUrl.value, '_blank')
}
......
......@@ -8,12 +8,12 @@
<meta name="description" content="一带一路" />
<meta name="keywords" content="ares-admin,ares-mobile,ares admin,ares mobile,ares,mpa,vue,h5,template">
<meta name="format-detection" content="telephone=no" />
<title>项目详情</title>
<title>邀请好友</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./detail/main.ts"></script>
<script type="module" src="./invite/main.ts"></script>
</body>
</html>
\ No newline at end of file
<template>
<AppHeader title="邀请好友"/>
<div class="container">
<img class="logo" src="@/static/invite/logo.png" alt="邀请好友">
<div class="invite-code" @click="handleCopy(userInfo.yqm)">
您的专属邀请码:<span>{{ userInfo.yqm }}</span>
<img class="copy" src="@/static/invite/copy.png" alt="">
</div>
<div class="imgwarp">
<img class="invite" src="@/static/invite/invite.png" alt="邀请好友">
</div>
<div class="qr-section">
<img :src="QRImgUrl" alt="QR Code" />
</div>
<div class="tips">
扫描二维码,注册世界银行APP
</div>
<div class="action-buttons">
<div @click="saveImage" class="btn1" style="margin-right: 112px;">
<img src="@/static/invite/download.png" alt="">
<span>保存图片</span>
</div>
<div @click="copyFullLink" class="btn1">
<img src="@/static/invite/copyl.png" alt="">
<span>复制链接</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import QRCode from 'qrcode'
import request from '@/utils/request'
import { showSuccessToast, showFailToast } from 'vant';
import AppHeader from '@/components/AppHeader.vue'
// 类型定义
interface UserInfo {
yqm: string
}
// 响应式状态
const QRImgUrl = ref('')
const linkstr = ref('')
const userInfo = reactive<UserInfo>({
yqm: ''
})
// 生成二维码
const generateQRCode = async () => {
const opts = {
errorCorrectionLevel: 'L',
type: 'image/png',
quality: 0.3,
margin: 1,
width: 200,
height: 200,
color: {
dark: '#333333',
light: '#fff'
}
}
try {
QRImgUrl.value = await QRCode.toDataURL(linkstr.value, opts)
} catch (error) {
console.error('Failed to generate QR code:', error)
}
}
// 复制文本
const handleCopy = (text: string) => {
const textarea = document.createElement('textarea')
textarea.value = text
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
showSuccessToast('复制成功')
}
// 获取用户信息
const fetchUserInfo = async () => {
try {
const res = await request.get('/system/user/', {})
if (res.code === 200) {
userInfo.yqm = res.yqm || ''
}
} catch (error) {
console.error('Failed to fetch user info:', error)
}
}
// 获取邀请码和链接
const fetchInviteInfo = async () => {
try {
const res = await request.get('/system/user/qRCode', {})
linkstr.value = `https://${location.host}/register.html?yqm=${res.data.slice(-6)}`
await generateQRCode()
} catch (error) {
console.error('Failed to fetch invite info:', error)
}
}
// 修改保存图片方法
const saveImage = async () => {
try {
// 获取二维码图片的 base64 数据
const imageData = QRImgUrl.value
// 判断是否在 Android 环境
if (window.android && window.android.saveImage) {
// 调用 Android 的保存图片方法
window.android.saveImage(imageData)
showSuccessToast('保存成功')
}
// 判断是否在 iOS 环境
else if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.saveImage) {
// 调用 iOS 的保存图片方法
window.webkit.messageHandlers.saveImage.postMessage(imageData)
showSuccessToast('保存成功')
}
// 其他环境(PC浏览器等)
else {
const link = document.createElement('a')
link.href = imageData
link.download = '邀请二维码.png'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
showSuccessToast('保存成功')
}
} catch (error) {
console.error('Failed to save image:', error)
showFailToast('保存失败')
}
}
// 为了 TypeScript 类型检查,添加全局类型声明
declare global {
interface Window {
android?: {
saveImage: (base64: string) => void
}
webkit?: {
messageHandlers: {
saveImage: {
postMessage: (base64: string) => void
}
}
}
}
}
// 复制完整链接
const copyFullLink = () => {
const textarea = document.createElement('textarea')
textarea.value = linkstr.value
document.body.appendChild(textarea)
textarea.select()
document.execCommand('copy')
document.body.removeChild(textarea)
showSuccessToast('复制成功')
}
// 初始化
onMounted(async () => {
await Promise.all([
fetchUserInfo(),
fetchInviteInfo()
])
})
</script>
<style lang="scss" scoped>
.container {
margin-top: 54px;
min-height: 100vh;
padding: 20px 0;
background: url('@/static/invite/bg.png') no-repeat;
background-size: 100% 100%;
.imgwarp{
display: flex;
justify-content: center;
align-items: center;
}
.logo {
width: 337px;
height: 80px;
display: block;
margin: 61px auto 313px;
}
.invite-code {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-size: 16px;
width: 308px;
height: 32px;
line-height: 32px;
font-weight: 400;
font-size: 17px;
background-color: #fff9e8;
margin: 0 auto;
text-align: center;
color: #9b3500;
span {
font-weight: 700;
}
.copy {
width: 16px;
height: 16px;
margin-left: 5px;
}
}
.invite {
width: 186px;
height: 20px;
margin: 20px auto 22px;
}
.qr-section {
text-align: center;
margin: 20px;
img {
width: 122px;
height: 120px;
margin: 0 auto;
}
}
.tips {
font-family: HarmonyOS Sans SC;
font-weight: 700;
font-size: 14px;
color: #9B3500;
line-height: 20px;
text-align: center;
}
.action-buttons {
display: flex;
justify-content: center;
gap: 20px;
padding: 0 20px;
margin-top: 30px;
img {
width: 26px;
height: 26px;
margin-bottom: 10px;
}
.btn1 {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
span {
font-weight: 400;
font-size: 14px;
color: #9B3500;
line-height: 20px;
}
}
}
}
</style>
\ No newline at end of file
import 'virtual:uno.css'
import '@/styles/index.scss'
import Varlet from '@varlet/ui'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).use(Varlet).mount('#app')
\ No newline at end of file
<template>
<div class="container">
reset-nickname
<AppHeader title="修改昵称"/>
<div class="auth-container">
<div class="label">修改昵称</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input type="texat" maxlength="20" v-model="nickname" placeholder="请输入修改昵称" />
</div>
<div class="count">{{ nickname.length }}/20</div>
</div>
<div class="tips">
* 昵称长度为2-20个字符
</div>
<div class="buynow" @click="() => handleSubmit()" v-ripple>确定修改</div>
</div>
</template>
<script setup lang="ts">
// import { ref } from 'vue'
import { ref } from 'vue'
import { showFailToast, showSuccessToast } from 'vant'
import request from '@/utils/request'
import { useDebounceFn } from '@vueuse/core'
import AppHeader from '@/components/AppHeader.vue'
const navigateTo = (path: string) => {
window.location.href = window.location.origin + path
}
// 响应式状态
const loading = ref(false)
const nickname = ref('')
// 表单验证
const validateForm = (): boolean => {
if (!nickname.value) {
showFailToast('请输入昵称')
return false
}
if (nickname.value.length < 2) {
showFailToast('昵称长度不能少于2个字符')
return false
}
if (nickname.value.length > 20) {
showFailToast('昵称长度不能超过20个字符')
return false
}
return true
}
const getUserInfo = () => {
request.get('/system/user/info',{}).then(res => {
nickname.value = res.extend2 || res.nickName
})
}
getUserInfo()
// 提交处理
const handleUpdateNickname = async () => {
if (loading.value) return
try {
loading.value = true
const res = await request.post('/system/user/edit/edityhxx', {
extend2: nickname.value
})
console.log(res)
if (res.code === 200) {
showSuccessToast('昵称修改成功')
// 修改成功后延迟返回
setTimeout(() => window.location.replace('/user/accountSecurity.html'), 2000)
} else {
showFailToast(res.msg || '修改失败')
}
} catch (error) {
console.error('Update nickname error:', error)
showFailToast('修改失败,请稍后重试')
} finally {
loading.value = false
}
}
// 表单提交(带防抖)
const handleSubmit = useDebounceFn(async () => {
if (!validateForm()) return
await handleUpdateNickname()
}, 500)
</script>
<style lang="scss">
body {
background-color: #f5f6f6;
<style lang="scss" scoped>
.auth-container {
margin-top: 54px;
padding: 20px 20px 49px;
background: url('@/static/common/commonbg.png') no-repeat;
background-size: 100% 100%;
min-height: 100vh;
.label {
font-size: 14px;
color: #460A0B;
margin-bottom: 10px;
margin-left: 5px;
}
.warpinput {
display: flex;
background: #fff;
border-radius: 10px;
margin-bottom: 20px;
align-items: center;
justify-content: space-between;
padding: 15px;
input {
margin-left: 12px;
background-color: #fff !important;
border: none;
outline: none;
color: #460A0B;
font-size: 14px;
width: 100%;
&::placeholder {
color: #999;
font-size: 14px;
}
&:-webkit-autofill {
-webkit-box-shadow: 0 0 0 30px white inset !important;
-webkit-text-fill-color: #460A0B !important;
}
}
.count {
color: #999;
font-size: 12px;
margin-left: 10px;
}
}
.tips {
color: #999;
font-size: 12px;
padding: 0 15px;
margin-top: 10px;
margin-bottom: 40px;
}
.buynow {
width: 291px;
height: 63px;
background: url('@/static/common/btn.png') no-repeat;
background-size: 100% 100%;
font-weight: 500;
margin: 0 auto;
font-size: 21px;
color: #FFF7E9;
text-align: center;
line-height: 46px;
}
}
</style>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<meta name="description" content="一带一路" />
<meta name="keywords" content="ares-admin,ares-mobile,ares admin,ares mobile,ares,mpa,vue,h5,template">
<meta name="format-detection" content="telephone=no" />
<title>修改登录密码</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./resetPass/main.ts"></script>
</body>
</html>
<template>
<AppHeader title="修改登录密码"/>
<div class="auth-container">
<div class="label">原密码</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input :type="showOldPass ? 'text' : 'password'" v-model="formData.oldPassword" placeholder="请输入原密码" />
</div>
<van-icon name="closed-eye" @click="showOldPass = !showOldPass" v-if="!showOldPass" />
<van-icon name="eye-o" @click="showOldPass = !showOldPass" v-if="showOldPass" />
</div>
<div class="label">新密码</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input :type="showNewPass ? 'text' : 'password'" v-model="formData.newPassword" placeholder="请输入新密码" />
</div>
<van-icon name="closed-eye" @click="showNewPass = !showNewPass" v-if="!showNewPass" />
<van-icon name="eye-o" @click="showNewPass = !showNewPass" v-if="showNewPass" />
</div>
<div class="label">确认新密码</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input :type="showConfirmPass ? 'text' : 'password'" v-model="formData.confirmPassword" placeholder="请确认新密码" />
</div>
<van-icon name="closed-eye" @click="showConfirmPass = !showConfirmPass" v-if="!showConfirmPass" />
<van-icon name="eye-o" @click="showConfirmPass = !showConfirmPass" v-if="showConfirmPass" />
</div>
<div class="buynow" @click="() => handleSubmit()" v-ripple>确定修改</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { encrypt } from '@/utils/encrypt'
import { useDebounceFn } from '@vueuse/core'
import AppHeader from '@/components/AppHeader.vue'
import { showFailToast, showSuccessToast } from 'vant'
import request from '@/utils/request'
const navigateTo = (path: string) => {
window.location.href = window.location.origin + path
}
// 类型定义
interface ResetPasswordForm {
oldPassword: string
newPassword: string
confirmPassword: string
}
// 响应式状态
const showOldPass = ref(false)
const showNewPass = ref(false)
const showConfirmPass = ref(false)
const loading = ref(false)
// 表单数据
const formData = reactive<ResetPasswordForm>({
oldPassword: '',
newPassword: '',
confirmPassword: ''
})
// 表单验证
const validateForm = (): boolean => {
if (!formData.oldPassword) {
showFailToast('请输入原密码')
return false
}
if (!formData.newPassword) {
showFailToast('请输入新密码')
return false
}
if (!formData.confirmPassword) {
showFailToast('请确认新密码')
return false
}
if (formData.newPassword !== formData.confirmPassword) {
showFailToast('两次输入的密码不一致')
return false
}
return true
}
// 提交处理
const handleResetPassword = async () => {
if (loading.value) return
try {
loading.value = true
const res = await request.put('/system/user/profile/updatePwd', {
oldPassword: encrypt(formData.oldPassword),
newPassword: encrypt(formData.newPassword)
})
if (res.code === 200) {
showSuccessToast('密码修改成功')
localStorage.clear()
window.location.replace('/login.html')
// 修改成功后延迟返回
// setTimeout(() => navigateTo('/user/accountSecurity'), 1000)
setTimeout(() => window.location.replace('/login.html'), 2000)
} else {
showFailToast(res.msg || '修改失败')
}
} catch (error) {
console.error('Reset password error:', error)
showFailToast('修改失败,请稍后重试')
} finally {
loading.value = false
}
}
// 表单提交(带防抖)
const handleSubmit = useDebounceFn(async () => {
if (!validateForm()) return
await handleResetPassword()
}, 500)
</script>
<style lang="scss" scoped>
.auth-container {
margin-top: 54px;
padding: 20px 20px 49px;
background: url('@/static/common/commonbg.png') no-repeat;
background-size: 100% 100%;
min-height: 100vh;
.label {
font-size: 14px;
color: #460A0B;
margin-bottom: 10px;
margin-left: 5px;
}
.warpinput {
display: flex;
background: #fff;
border-radius: 10px;
margin-bottom: 40px;
align-items: center;
justify-content: space-between;
padding: 15px;
input {
margin-left: 12px;
background-color: #fff !important;
border: none;
outline: none;
color: #460A0B;
font-size: 14px;
width: 100%;
&::placeholder {
color: #999;
font-size: 14px;
}
&:-webkit-autofill {
-webkit-box-shadow: 0 0 0 30px white inset !important;
-webkit-text-fill-color: #460A0B !important;
}
}
}
.buynow {
width: 291px;
height: 63px;
background: url('@/static/common/btn.png') no-repeat;
background-size: 100% 100%;
font-weight: 500;
margin: 0 auto;
margin-top: 60px;
font-size: 21px;
color: #FFF7E9;
text-align: center;
line-height: 46px;
}
}
</style>
\ No newline at end of file
import 'virtual:uno.css'
import '@/styles/index.scss'
import Varlet from '@varlet/ui'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).use(Varlet).mount('#app')
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<meta name="description" content="一带一路" />
<meta name="keywords" content="ares-admin,ares-mobile,ares admin,ares mobile,ares,mpa,vue,h5,template">
<meta name="format-detection" content="telephone=no" />
<title>修改交易密码</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./resetPayPass/main.ts"></script>
</body>
</html>
\ No newline at end of file
<template>
<AppHeader title="修改交易密码"/>
<div class="auth-container">
<div class="label">原密码</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input type="password" maxlength="6" v-model="formData.oldPassword" placeholder="请输入原交易密码" />
</div>
</div>
<div class="label">新密码</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input type="password" maxlength="6" v-model="formData.newPassword" placeholder="请输入新交易密码" />
</div>
</div>
<div class="label">确认新密码</div>
<div class="warpinput">
<div style="display: flex;align-items: center;">
<input type="password" maxlength="6" v-model="formData.confirmPassword" placeholder="请确认新交易密码" />
</div>
</div>
<div class="tips">
* 交易密码为6位数字
</div>
<div class="buynow" @click="() => handleSubmit()" v-ripple>确定修改</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { useDebounceFn } from '@vueuse/core'
import { showFailToast, showSuccessToast } from 'vant'
import AppHeader from '@/components/AppHeader.vue'
import request from '@/utils/request'
const navigateTo = (path: string) => {
window.location.replace(window.location.origin + path)
}
// 类型定义
interface PayPasswordForm {
oldPassword: string
newPassword: string
confirmPassword: string
}
// 响应式状态
const loading = ref(false)
// 表单数据
const formData = reactive<PayPasswordForm>({
oldPassword: '',
newPassword: '',
confirmPassword: ''
})
// 表单验证
const validateForm = (): boolean => {
if (!formData.oldPassword) {
showFailToast('请输入原交易密码')
return false
}
if (!formData.newPassword) {
showFailToast('请输入新交易密码')
return false
}
if (!formData.confirmPassword) {
showFailToast('请确认新交易密码')
return false
}
if (formData.newPassword !== formData.confirmPassword) {
showFailToast('两次输入的密码不一致')
return false
}
return true
}
// 提交处理
const handleResetPayPassword = async () => {
if (loading.value) return
try {
loading.value = true
const res = await request.put('/system/user/profile/updatePwdEx3', {
oldPassword: formData.oldPassword,
newPassword: formData.newPassword
})
if (res.code === 200) {
showSuccessToast('交易密码修改成功')
// 修改成功后延迟返回
setTimeout(() => window.location.replace('/user/accountSecurity.html'), 1000)
} else {
showFailToast(res.msg || '修改失败')
}
} catch (error) {
console.error('Reset pay password error:', error)
showFailToast('修改失败,请稍后重试')
} finally {
loading.value = false
}
}
// 表单提交(带防抖)
const handleSubmit = useDebounceFn(async () => {
if (!validateForm()) return
await handleResetPayPassword()
}, 500)
</script>
<style lang="scss" scoped>
.auth-container {
margin-top: 54px;
padding: 20px 20px 49px;
background: url('@/static/common/commonbg.png') no-repeat;
background-size: 100% 100%;
min-height: 100vh;
.label {
font-size: 14px;
color: #460A0B;
margin-bottom: 10px;
margin-left: 5px;
}
.warpinput {
display: flex;
background: #fff;
border-radius: 10px;
margin-bottom: 20px;
align-items: center;
justify-content: space-between;
padding: 15px;
input {
margin-left: 12px;
background-color: #fff !important;
border: none;
outline: none;
color: #460A0B;
font-size: 14px;
width: 100%;
&::placeholder {
color: #999;
font-size: 14px;
}
&:-webkit-autofill {
-webkit-box-shadow: 0 0 0 30px white inset !important;
-webkit-text-fill-color: #460A0B !important;
}
}
}
.tips {
color: #460A0B;
font-size: 12px;
padding: 0 15px;
margin-top: 10px;
margin-bottom: 40px;
}
.buynow {
width: 291px;
height: 63px;
background: url('@/static/common/btn.png') no-repeat;
background-size: 100% 100%;
font-weight: 500;
margin: 0 auto;
font-size: 21px;
color: #FFF7E9;
text-align: center;
line-height: 46px;
}
}
</style>
import 'virtual:uno.css'
import '@/styles/index.scss'
import Varlet from '@varlet/ui'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).use(Varlet).mount('#app')
\ No newline at end of file
......@@ -76,7 +76,7 @@ const add = async () => {
})
setTimeout(() => {
navigateTo('/')
window.location.href = '/index.html'
}, 1000)
} else {
showToast(res.msg)
......
......@@ -9,23 +9,16 @@ declare module 'vue' {
export interface GlobalComponents {
AppHeader: typeof import('./../src/components/AppHeader.vue')['default']
GuideModal: typeof import('./../src/components/GuideModal.vue')['default']
ICarbonWorshipMuslim: typeof import('~icons/carbon/worship-muslim')['default']
ICustomGithub: typeof import('~icons/custom/github')['default']
KLineChart: typeof import('./../src/components/KLineChart.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Tabbar: typeof import('./../src/components/tabbar.vue')['default']
VanButton: typeof import('vant/es')['Button']
VanCell: typeof import('vant/es')['Cell']
VanCheckbox: typeof import('vant/es')['Checkbox']
VanIcon: typeof import('vant/es')['Icon']
VanImage: typeof import('vant/es')['Image']
VanList: typeof import('vant/es')['List']
VanPopup: typeof import('vant/es')['Popup']
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
VanTab: typeof import('vant/es')['Tab']
VanTabs: typeof import('vant/es')['Tabs']
VarAppBar: typeof import('@varlet/ui')['AppBar']
VarButton: typeof import('@varlet/ui')['Button']
VarDivider: typeof import('@varlet/ui')['Divider']
......
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