Compare commits
236 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
a7849b78a7 | |
|
|
5d4c0d30e0 | |
|
|
bd3a2e9cce | |
|
|
d9459b1bd0 | |
|
|
738f058281 | |
|
|
a215b9b263 | |
|
|
deca26c218 | |
|
|
ca06240e86 | |
|
|
9172ced172 | |
|
|
8c96536d11 | |
|
|
6242e47490 | |
|
|
2c28dd5cfd | |
|
|
80ae3c1e1e | |
|
|
c933a2c663 | |
|
|
007f0c7238 | |
|
|
1b65430bd2 | |
|
|
a2ab06de2b | |
|
|
3467d370ca | |
|
|
125e6694d6 | |
|
|
f842ab9d6a | |
|
|
b47742884b | |
|
|
7bfa56cf5b | |
|
|
597ace78aa | |
|
|
2f57b85609 | |
|
|
ccdab994a8 | |
|
|
d985f0dd25 | |
|
|
cce9d63ef1 | |
|
|
8ce81540d9 | |
|
|
76a25d329b | |
|
|
8791695869 | |
|
|
c7496e73e1 | |
|
|
3b2396ec5c | |
|
|
b90c0c6774 | |
|
|
fe48026d19 | |
|
|
476acc7571 | |
|
|
c625b3472f | |
|
|
7aec27d81b | |
|
|
bc0c917efa | |
|
|
bc53f9552e | |
|
|
d047299489 | |
|
|
82e922eab0 | |
|
|
b3f3f33c90 | |
|
|
906293b350 | |
|
|
ee086eec01 | |
|
|
77c3590e5b | |
|
|
1f71a0240d | |
|
|
c6a3e2072d | |
|
|
86281a76b6 | |
|
|
e7705b1162 | |
|
|
4e16330877 | |
|
|
dbc666a90d | |
|
|
4d15da3c52 | |
|
|
9e3926548e | |
|
|
f67ac5b73a | |
|
|
d234c1a48a | |
|
|
4b1d7c168d | |
|
|
34a6810681 | |
|
|
8657afdbd7 | |
|
|
e1775a67e3 | |
|
|
ab1b4b48c8 | |
|
|
9c5f267b5f | |
|
|
d54877fb85 | |
|
|
b1f41cfcbb | |
|
|
503a4e1194 | |
|
|
4fcbc5b06f | |
|
|
bbfe66093e | |
|
|
bf57816244 | |
|
|
ebd2c2111c | |
|
|
cb56b3ae7e | |
|
|
e501d35d6b | |
|
|
aea48b6c58 | |
|
|
216af408cc | |
|
|
65270811da | |
|
|
507973d7dc | |
|
|
45b2bf3f7f | |
|
|
0616283418 | |
|
|
a47cc2a9cd | |
|
|
b560d901ab | |
|
|
6569f821e8 | |
|
|
1cd2226f2b | |
|
|
8ec9c844f0 | |
|
|
cffb2c29fb | |
|
|
72674f4d77 | |
|
|
73b2b3cf25 | |
|
|
a6074b340b | |
|
|
37cf237ff1 | |
|
|
7836f9855a | |
|
|
c9b393b117 | |
|
|
7eb68e8c15 | |
|
|
788f4e6b5e | |
|
|
c1e4e7be24 | |
|
|
5dbb4add21 | |
|
|
724138f672 | |
|
|
85996e19b1 | |
|
|
dab4d15c24 | |
|
|
88ebca65e7 | |
|
|
033a3bd9ba | |
|
|
e3e29f7f18 | |
|
|
5e02decbf5 | |
|
|
d72a0da52c | |
|
|
ce76f694b8 | |
|
|
43efe376ec | |
|
|
9210162f17 | |
|
|
dc692498db | |
|
|
8eca8cc6ce | |
|
|
b0af3d1d5e | |
|
|
4b8dc92739 | |
|
|
4cb094c272 | |
|
|
0cef1a2016 | |
|
|
ca12683f7e | |
|
|
f0bb586b14 | |
|
|
1d87a13e69 | |
|
|
86434ab815 | |
|
|
1d4fd42cbb | |
|
|
eb59411bda | |
|
|
cfe224cf83 | |
|
|
d04cf2cd2f | |
|
|
ce4a66ac3c | |
|
|
865c3e5715 | |
|
|
4cb7784d4a | |
|
|
1bb582d51a | |
|
|
2d488612b4 | |
|
|
b7e2889875 | |
|
|
5b40a807e4 | |
|
|
970a252352 | |
|
|
00946076aa | |
|
|
b46210a235 | |
|
|
d690a8d48c | |
|
|
07d50cc1e9 | |
|
|
519c0f85d6 | |
|
|
55c624621d | |
|
|
7012a8624c | |
|
|
b250034b47 | |
|
|
2d13055961 | |
|
|
026d39a0e5 | |
|
|
20c4e7a0de | |
|
|
56e34166ba | |
|
|
5acaddf086 | |
|
|
b3b76b9bd9 | |
|
|
133ec5b7ff | |
|
|
5e7738a6db | |
|
|
feb6491733 | |
|
|
3586dc4a35 | |
|
|
38cbbd2ed1 | |
|
|
c54c630b30 | |
|
|
1601a3e4ae | |
|
|
f3be53fe2f | |
|
|
e6aa5f29ed | |
|
|
8c39d28ff0 | |
|
|
0962120ab4 | |
|
|
de27c2770d | |
|
|
6983450d59 | |
|
|
c6ecc56060 | |
|
|
c506a7fd42 | |
|
|
2b46401bd8 | |
|
|
8c560a0b8d | |
|
|
009422675d | |
|
|
2ea96ae0fa | |
|
|
436c94b9a8 | |
|
|
8c2355c8a0 | |
|
|
e01f4865e6 | |
|
|
bce2fd578f | |
|
|
21eb405746 | |
|
|
52af4ca4ff | |
|
|
c7a434a24d | |
|
|
3fc1fd8261 | |
|
|
712b19dc4b | |
|
|
ad67486e13 | |
|
|
107f39efef | |
|
|
8c3298af2a | |
|
|
a2dc82ab4b | |
|
|
7c65356773 | |
|
|
2eb5f2be92 | |
|
|
ebe71e1688 | |
|
|
c00cb2e135 | |
|
|
fb3eec2ea3 | |
|
|
755aff7422 | |
|
|
b839c6c4ff | |
|
|
4b25dc3b07 | |
|
|
a5d27a3283 | |
|
|
583ea5a536 | |
|
|
b17e6c0147 | |
|
|
7dcc94c937 | |
|
|
0a87094581 | |
|
|
01500366f2 | |
|
|
30a63eda71 | |
|
|
c97560d691 | |
|
|
bd995c7d04 | |
|
|
3fd398ffa4 | |
|
|
4dbe88a024 | |
|
|
935ea47b92 | |
|
|
fb6942abbd | |
|
|
6229949c1a | |
|
|
f96b11a0cc | |
|
|
cfbcb6ac8d | |
|
|
78c99caaa5 | |
|
|
3b14a94cce | |
|
|
7b1d55dfa3 | |
|
|
003d11355c | |
|
|
bd829907f4 | |
|
|
cab9b6b4fd | |
|
|
288b62c8b1 | |
|
|
f005971605 | |
|
|
7856f31273 | |
|
|
2eb1981b8d | |
|
|
16d2ea2cbd | |
|
|
2c7da360f4 | |
|
|
261918d871 | |
|
|
b5685a0d6f | |
|
|
a88ddf46bc | |
|
|
0959867786 | |
|
|
eefe793b8f | |
|
|
21c79178fd | |
|
|
bd99f8e013 | |
|
|
48eec51491 | |
|
|
ef71a0a669 | |
|
|
465f53d15b | |
|
|
6095979884 | |
|
|
b1e6fa9368 | |
|
|
41fa7f7398 | |
|
|
16b3a536a4 | |
|
|
b8975f5015 | |
|
|
46de3cbd57 | |
|
|
0e43722c8e | |
|
|
b149dbd858 | |
|
|
4a63d5415f | |
|
|
62f9f50d35 | |
|
|
b77ee8073d | |
|
|
bf692f48e5 | |
|
|
b7ae173cd5 | |
|
|
14d4245a62 | |
|
|
cfce21f87e | |
|
|
a092014941 | |
|
|
b15217007a | |
|
|
e233f84b4d | |
|
|
d8f440ed1f |
|
|
@ -0,0 +1,8 @@
|
|||
node_modules/
|
||||
uni_modules/
|
||||
unpackage/
|
||||
dist/
|
||||
*.min.js
|
||||
*.css
|
||||
*.scss
|
||||
*.json
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
'vue/setup-compiler-macros': true
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-essential'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: [
|
||||
'vue'
|
||||
],
|
||||
// 核心拦截规则
|
||||
rules: {
|
||||
'no-undef': 'error', // 静态拦截致命错误:防止引用不存在的参数(造成崩溃的主因)
|
||||
'no-unused-vars': 'warn', // 变量未使用仅作黄牌警告,降低大盘爆红率
|
||||
'vue/multi-word-component-names': 'off', // 兼容历史单字组件命名
|
||||
'no-empty': 'warn',
|
||||
'no-constant-condition': 'warn'
|
||||
},
|
||||
globals: {
|
||||
uni: 'readonly',
|
||||
plus: 'readonly',
|
||||
wx: 'readonly',
|
||||
getApp: 'readonly',
|
||||
getCurrentPages: 'readonly',
|
||||
setTimeout: 'readonly',
|
||||
clearTimeout: 'readonly',
|
||||
setInterval: 'readonly',
|
||||
clearInterval: 'readonly',
|
||||
console: 'readonly',
|
||||
__dirname: 'readonly'
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,10 @@
|
|||
"customPlaygroundType" : "local",
|
||||
"playground" : "custom",
|
||||
"type" : "uni-app:app-android"
|
||||
},
|
||||
{
|
||||
"playground" : "standard",
|
||||
"type" : "uni-app:app-harmony"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
#!/usr/bin/env sh
|
||||
npx lint-staged
|
||||
53
App.vue
53
App.vue
|
|
@ -1,17 +1,19 @@
|
|||
<script>
|
||||
export default {
|
||||
export default {
|
||||
globalData: {
|
||||
NativeEvent: true,
|
||||
recentNativeEvent: "", // 初始化一个全局变量
|
||||
recentNativeData: 0 // 初始化一个全局变量
|
||||
},
|
||||
onLaunch: function (options) {
|
||||
onLaunch: function(options) {
|
||||
uni.setStorageSync('AppUser', {})
|
||||
uni.setStorageSync('userInfo', {})
|
||||
// console.log=()=>{}
|
||||
// === wgt 包启动诊断日志 ===
|
||||
console.log('=== App Launch 开始 ===')
|
||||
console.log('启动参数:', JSON.stringify(options))
|
||||
console.log('环境:', process.env.NODE_ENV)
|
||||
|
||||
|
||||
uni.setStorageSync('onNativeEventReceive', "no")
|
||||
// 清除上次遗留的跳转指令,防止正常启动时自动跳转
|
||||
uni.removeStorageSync('jumpTarget_url');
|
||||
|
|
@ -48,15 +50,15 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
// 监听已在 onLaunch 中设置,这里不再重复
|
||||
},
|
||||
|
||||
onHide: function () {
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
},
|
||||
onExit: function () {
|
||||
onExit: function() {
|
||||
// 关闭数据库
|
||||
// #ifdef APP
|
||||
// plus.sqlite.closeDatabase({ name: 'zyds' })
|
||||
|
|
@ -76,6 +78,7 @@ export default {
|
|||
this.globalData.NativeEvent = false
|
||||
console.log('开始监听宿主消息')
|
||||
|
||||
if (typeof uni.onNativeEventReceive === 'function') {
|
||||
uni.onNativeEventReceive((event, data) => {
|
||||
if (event) {
|
||||
console.log('接收到宿主消息:', event, data)
|
||||
|
|
@ -107,6 +110,9 @@ export default {
|
|||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log('uni.onNativeEventReceive 不可用,跳过监听')
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -137,7 +143,9 @@ export default {
|
|||
*/
|
||||
initFromExtraData(extraData) {
|
||||
// 批量设置 Storage,减少 I/O 次数
|
||||
const storageData = {
|
||||
let storageData={}
|
||||
if(uni.getStorageSync('isTest')){
|
||||
storageData = {
|
||||
host: extraData.host,
|
||||
header: {
|
||||
"x-token": extraData['x-token'],
|
||||
|
|
@ -158,11 +166,32 @@ export default {
|
|||
encrypt: extraData['encrypt'],
|
||||
decrypt: extraData['decrypt']
|
||||
}
|
||||
}else{
|
||||
if (extraData['safeBottom']) {
|
||||
this.$store.state["safeBottomAz"]=Number(extraData['safeBottom'])||0
|
||||
}
|
||||
storageData = {
|
||||
host: extraData.host,
|
||||
header: {
|
||||
// #ifdef APP-PLUS
|
||||
"header": {
|
||||
"version": this.$version,
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量写入
|
||||
Object.keys(storageData).forEach(key => {
|
||||
uni.setStorageSync(key, storageData[key])
|
||||
})
|
||||
if (extraData['isCombo']) {
|
||||
uni.setStorageSync('isCombo', extraData['isCombo'])
|
||||
}
|
||||
if (extraData['paytype']) {
|
||||
uni.setStorageSync('isCombo', extraData['paytype'] == 'combo' ? 'ok' : '')
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
@ -174,7 +203,9 @@ export default {
|
|||
// 批量设置开发环境配置
|
||||
const devConfig = {
|
||||
host: "https://flaunt.batiao8.com/",
|
||||
header: { "x-token": "ebe14dab-1879-4c5d-9148-727b96b30aad" },
|
||||
header: {
|
||||
"x-token": "55e2481e-cbd2-4d2d-82d3-b47e191fcfc0"
|
||||
},
|
||||
decrypt: "e4rOtnF8tJjtHO7ecZeJHN1rapED5ImB",
|
||||
encrypt: "xn08hYoizXhZ1zHP8DVqfCm2yHxPmhil"
|
||||
}
|
||||
|
|
@ -186,9 +217,11 @@ export default {
|
|||
console.log('默认配置初始化完成')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import "./common/color.css";
|
||||
/* #ifndef APP-NVUE */
|
||||
@import "./common/color.css";
|
||||
/* #endif */
|
||||
</style>
|
||||
|
|
@ -130,401 +130,401 @@ text {
|
|||
}
|
||||
|
||||
.codefun-ml-2 {
|
||||
margin-left: 4rpx;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.codefun-mt-2 {
|
||||
margin-top: 4rpx;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.codefun-ml-4 {
|
||||
margin-left: 8rpx;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.codefun-mt-4 {
|
||||
margin-top: 8rpx;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.codefun-ml-6 {
|
||||
margin-left: 12rpx;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.codefun-mt-6 {
|
||||
margin-top: 12rpx;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.codefun-ml-8 {
|
||||
margin-left: 16rpx;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.codefun-mt-8 {
|
||||
margin-top: 16rpx;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.codefun-ml-10 {
|
||||
margin-left: 20rpx;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.codefun-mt-10 {
|
||||
margin-top: 20rpx;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.codefun-ml-12 {
|
||||
margin-left: 24rpx;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.codefun-mt-12 {
|
||||
margin-top: 24rpx;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.codefun-ml-14 {
|
||||
margin-left: 28rpx;
|
||||
margin-left: 14px;
|
||||
}
|
||||
|
||||
.codefun-mt-14 {
|
||||
margin-top: 28rpx;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.codefun-ml-16 {
|
||||
margin-left: 32rpx;
|
||||
margin-left: 16px;
|
||||
}
|
||||
|
||||
.codefun-mt-16 {
|
||||
margin-top: 32rpx;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.codefun-ml-18 {
|
||||
margin-left: 36rpx;
|
||||
margin-left: 18px;
|
||||
}
|
||||
|
||||
.codefun-mt-18 {
|
||||
margin-top: 36rpx;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.codefun-ml-20 {
|
||||
margin-left: 40rpx;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.codefun-mt-20 {
|
||||
margin-top: 40rpx;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.codefun-ml-22 {
|
||||
margin-left: 44rpx;
|
||||
margin-left: 22px;
|
||||
}
|
||||
|
||||
.codefun-mt-22 {
|
||||
margin-top: 44rpx;
|
||||
margin-top: 22px;
|
||||
}
|
||||
|
||||
.codefun-ml-24 {
|
||||
margin-left: 48rpx;
|
||||
margin-left: 24px;
|
||||
}
|
||||
|
||||
.codefun-mt-24 {
|
||||
margin-top: 48rpx;
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.codefun-ml-26 {
|
||||
margin-left: 52rpx;
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.codefun-mt-26 {
|
||||
margin-top: 52rpx;
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
.codefun-ml-28 {
|
||||
margin-left: 56rpx;
|
||||
margin-left: 28px;
|
||||
}
|
||||
|
||||
.codefun-mt-28 {
|
||||
margin-top: 56rpx;
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
.codefun-ml-30 {
|
||||
margin-left: 60rpx;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.codefun-mt-30 {
|
||||
margin-top: 60rpx;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.codefun-ml-32 {
|
||||
margin-left: 64rpx;
|
||||
margin-left: 32px;
|
||||
}
|
||||
|
||||
.codefun-mt-32 {
|
||||
margin-top: 64rpx;
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.codefun-ml-34 {
|
||||
margin-left: 68rpx;
|
||||
margin-left: 34px;
|
||||
}
|
||||
|
||||
.codefun-mt-34 {
|
||||
margin-top: 68rpx;
|
||||
margin-top: 34px;
|
||||
}
|
||||
|
||||
.codefun-ml-36 {
|
||||
margin-left: 72rpx;
|
||||
margin-left: 36px;
|
||||
}
|
||||
|
||||
.codefun-mt-36 {
|
||||
margin-top: 72rpx;
|
||||
margin-top: 36px;
|
||||
}
|
||||
|
||||
.codefun-ml-38 {
|
||||
margin-left: 76rpx;
|
||||
margin-left: 38px;
|
||||
}
|
||||
|
||||
.codefun-mt-38 {
|
||||
margin-top: 76rpx;
|
||||
margin-top: 38px;
|
||||
}
|
||||
|
||||
.codefun-ml-40 {
|
||||
margin-left: 80rpx;
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.codefun-mt-40 {
|
||||
margin-top: 80rpx;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.codefun-ml-42 {
|
||||
margin-left: 84rpx;
|
||||
margin-left: 42px;
|
||||
}
|
||||
|
||||
.codefun-mt-42 {
|
||||
margin-top: 84rpx;
|
||||
margin-top: 42px;
|
||||
}
|
||||
|
||||
.codefun-ml-44 {
|
||||
margin-left: 88rpx;
|
||||
margin-left: 44px;
|
||||
}
|
||||
|
||||
.codefun-mt-44 {
|
||||
margin-top: 88rpx;
|
||||
margin-top: 44px;
|
||||
}
|
||||
|
||||
.codefun-ml-46 {
|
||||
margin-left: 92rpx;
|
||||
margin-left: 46px;
|
||||
}
|
||||
|
||||
.codefun-mt-46 {
|
||||
margin-top: 92rpx;
|
||||
margin-top: 46px;
|
||||
}
|
||||
|
||||
.codefun-ml-48 {
|
||||
margin-left: 96rpx;
|
||||
margin-left: 48px;
|
||||
}
|
||||
|
||||
.codefun-mt-48 {
|
||||
margin-top: 96rpx;
|
||||
margin-top: 48px;
|
||||
}
|
||||
|
||||
.codefun-ml-50 {
|
||||
margin-left: 100rpx;
|
||||
margin-left: 50px;
|
||||
}
|
||||
|
||||
.codefun-mt-50 {
|
||||
margin-top: 100rpx;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.codefun-ml-52 {
|
||||
margin-left: 104rpx;
|
||||
margin-left: 52px;
|
||||
}
|
||||
|
||||
.codefun-mt-52 {
|
||||
margin-top: 104rpx;
|
||||
margin-top: 52px;
|
||||
}
|
||||
|
||||
.codefun-ml-54 {
|
||||
margin-left: 108rpx;
|
||||
margin-left: 54px;
|
||||
}
|
||||
|
||||
.codefun-mt-54 {
|
||||
margin-top: 108rpx;
|
||||
margin-top: 54px;
|
||||
}
|
||||
|
||||
.codefun-ml-56 {
|
||||
margin-left: 112rpx;
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
.codefun-mt-56 {
|
||||
margin-top: 112rpx;
|
||||
margin-top: 56px;
|
||||
}
|
||||
|
||||
.codefun-ml-58 {
|
||||
margin-left: 116rpx;
|
||||
margin-left: 58px;
|
||||
}
|
||||
|
||||
.codefun-mt-58 {
|
||||
margin-top: 116rpx;
|
||||
margin-top: 58px;
|
||||
}
|
||||
|
||||
.codefun-ml-60 {
|
||||
margin-left: 120rpx;
|
||||
margin-left: 60px;
|
||||
}
|
||||
|
||||
.codefun-mt-60 {
|
||||
margin-top: 120rpx;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.codefun-ml-62 {
|
||||
margin-left: 124rpx;
|
||||
margin-left: 62px;
|
||||
}
|
||||
|
||||
.codefun-mt-62 {
|
||||
margin-top: 124rpx;
|
||||
margin-top: 62px;
|
||||
}
|
||||
|
||||
.codefun-ml-64 {
|
||||
margin-left: 128rpx;
|
||||
margin-left: 64px;
|
||||
}
|
||||
|
||||
.codefun-mt-64 {
|
||||
margin-top: 128rpx;
|
||||
margin-top: 64px;
|
||||
}
|
||||
|
||||
.codefun-ml-66 {
|
||||
margin-left: 132rpx;
|
||||
margin-left: 66px;
|
||||
}
|
||||
|
||||
.codefun-mt-66 {
|
||||
margin-top: 132rpx;
|
||||
margin-top: 66px;
|
||||
}
|
||||
|
||||
.codefun-ml-68 {
|
||||
margin-left: 136rpx;
|
||||
margin-left: 68px;
|
||||
}
|
||||
|
||||
.codefun-mt-68 {
|
||||
margin-top: 136rpx;
|
||||
margin-top: 68px;
|
||||
}
|
||||
|
||||
.codefun-ml-70 {
|
||||
margin-left: 140rpx;
|
||||
margin-left: 70px;
|
||||
}
|
||||
|
||||
.codefun-mt-70 {
|
||||
margin-top: 140rpx;
|
||||
margin-top: 70px;
|
||||
}
|
||||
|
||||
.codefun-ml-72 {
|
||||
margin-left: 144rpx;
|
||||
margin-left: 72px;
|
||||
}
|
||||
|
||||
.codefun-mt-72 {
|
||||
margin-top: 144rpx;
|
||||
margin-top: 72px;
|
||||
}
|
||||
|
||||
.codefun-ml-74 {
|
||||
margin-left: 148rpx;
|
||||
margin-left: 74px;
|
||||
}
|
||||
|
||||
.codefun-mt-74 {
|
||||
margin-top: 148rpx;
|
||||
margin-top: 74px;
|
||||
}
|
||||
|
||||
.codefun-ml-76 {
|
||||
margin-left: 152rpx;
|
||||
margin-left: 76px;
|
||||
}
|
||||
|
||||
.codefun-mt-76 {
|
||||
margin-top: 152rpx;
|
||||
margin-top: 76px;
|
||||
}
|
||||
|
||||
.codefun-ml-78 {
|
||||
margin-left: 156rpx;
|
||||
margin-left: 78px;
|
||||
}
|
||||
|
||||
.codefun-mt-78 {
|
||||
margin-top: 156rpx;
|
||||
margin-top: 78px;
|
||||
}
|
||||
|
||||
.codefun-ml-80 {
|
||||
margin-left: 160rpx;
|
||||
margin-left: 80px;
|
||||
}
|
||||
|
||||
.codefun-mt-80 {
|
||||
margin-top: 160rpx;
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.codefun-ml-82 {
|
||||
margin-left: 164rpx;
|
||||
margin-left: 82px;
|
||||
}
|
||||
|
||||
.codefun-mt-82 {
|
||||
margin-top: 164rpx;
|
||||
margin-top: 82px;
|
||||
}
|
||||
|
||||
.codefun-ml-84 {
|
||||
margin-left: 168rpx;
|
||||
margin-left: 84px;
|
||||
}
|
||||
|
||||
.codefun-mt-84 {
|
||||
margin-top: 168rpx;
|
||||
margin-top: 84px;
|
||||
}
|
||||
|
||||
.codefun-ml-86 {
|
||||
margin-left: 172rpx;
|
||||
margin-left: 86px;
|
||||
}
|
||||
|
||||
.codefun-mt-86 {
|
||||
margin-top: 172rpx;
|
||||
margin-top: 86px;
|
||||
}
|
||||
|
||||
.codefun-ml-88 {
|
||||
margin-left: 176rpx;
|
||||
margin-left: 88px;
|
||||
}
|
||||
|
||||
.codefun-mt-88 {
|
||||
margin-top: 176rpx;
|
||||
margin-top: 88px;
|
||||
}
|
||||
|
||||
.codefun-ml-90 {
|
||||
margin-left: 180rpx;
|
||||
margin-left: 90px;
|
||||
}
|
||||
|
||||
.codefun-mt-90 {
|
||||
margin-top: 180rpx;
|
||||
margin-top: 90px;
|
||||
}
|
||||
|
||||
.codefun-ml-92 {
|
||||
margin-left: 184rpx;
|
||||
margin-left: 92px;
|
||||
}
|
||||
|
||||
.codefun-mt-92 {
|
||||
margin-top: 184rpx;
|
||||
margin-top: 92px;
|
||||
}
|
||||
|
||||
.codefun-ml-94 {
|
||||
margin-left: 188rpx;
|
||||
margin-left: 94px;
|
||||
}
|
||||
|
||||
.codefun-mt-94 {
|
||||
margin-top: 188rpx;
|
||||
margin-top: 94px;
|
||||
}
|
||||
|
||||
.codefun-ml-96 {
|
||||
margin-left: 192rpx;
|
||||
margin-left: 96px;
|
||||
}
|
||||
|
||||
.codefun-mt-96 {
|
||||
margin-top: 192rpx;
|
||||
margin-top: 96px;
|
||||
}
|
||||
|
||||
.codefun-ml-98 {
|
||||
margin-left: 196rpx;
|
||||
margin-left: 98px;
|
||||
}
|
||||
|
||||
.codefun-mt-98 {
|
||||
margin-top: 196rpx;
|
||||
margin-top: 98px;
|
||||
}
|
||||
|
||||
.codefun-ml-100 {
|
||||
margin-left: 200rpx;
|
||||
margin-left: 100px;
|
||||
}
|
||||
|
||||
.codefun-mt-100 {
|
||||
margin-top: 200rpx;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
|
@ -256,7 +256,12 @@
|
|||
display: flex;
|
||||
}
|
||||
|
||||
.shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
|
@ -282,6 +287,11 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-align-start {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.flex-justify-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,10 @@
|
|||
<!-- eslint-disable -->
|
||||
<template>
|
||||
<view
|
||||
class="player-wrapper"
|
||||
:id="videoWrapperId"
|
||||
:parentId="id"
|
||||
:randomNum="randomNum"
|
||||
:change:randomNum="domVideoPlayer.randomNumChange"
|
||||
:viewportProps="viewportProps"
|
||||
:change:viewportProps="domVideoPlayer.viewportChange"
|
||||
:videoSrc="videoSrc"
|
||||
:change:videoSrc="domVideoPlayer.initVideoPlayer"
|
||||
:command="eventCommand"
|
||||
:change:command="domVideoPlayer.triggerCommand"
|
||||
:func="renderFunc"
|
||||
:change:func="domVideoPlayer.triggerFunc"
|
||||
/>
|
||||
<view class="player-wrapper" :id="videoWrapperId" :parentId="id" :randomNum="randomNum"
|
||||
:change:randomNum="domVideoPlayer.randomNumChange" :viewportProps="viewportProps"
|
||||
:change:viewportProps="domVideoPlayer.viewportChange" :videoSrc="videoSrc"
|
||||
:change:videoSrc="domVideoPlayer.initVideoPlayer" :command="eventCommand"
|
||||
:change:command="domVideoPlayer.triggerCommand" :func="renderFunc" :change:func="domVideoPlayer.triggerFunc" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -158,6 +148,14 @@ export default {
|
|||
params: { sec, isDelay }
|
||||
}
|
||||
}
|
||||
},
|
||||
// 组件销毁前自动清理 renderjs 层的原生 video 元素,
|
||||
// 防止 v-if 移除组件后视频仍在后台播放声音("僵尸视频"问题)
|
||||
beforeUnmount() {
|
||||
this.renderFunc = {
|
||||
name: 'removeHandler',
|
||||
params: null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -173,7 +171,11 @@ export default {
|
|||
loadingEl: null,
|
||||
// 延迟生效的函数
|
||||
delayFunc: null,
|
||||
renderProps: {}
|
||||
renderProps: {},
|
||||
// 是否主动暂停(通过父组件调用 pause() 方法)
|
||||
intentionalPause: false,
|
||||
// 上次自动恢复的时间戳,用于冷却控制
|
||||
lastAutoRecoverTime: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -215,7 +217,9 @@ export default {
|
|||
videoEl.muted = muted
|
||||
videoEl.playbackRate = playbackRate
|
||||
videoEl.id = this.playerId
|
||||
// videoEl.setAttribute('x5-video-player-type', 'h5')
|
||||
// 开启 X5 内核的 H5 同层渲染,防止原生视频组件层级过高在拖拽时脱离或卡死
|
||||
videoEl.setAttribute('x5-video-player-type', 'h5')
|
||||
videoEl.setAttribute('x5-video-player-fullscreen', 'false')
|
||||
videoEl.setAttribute('preload', 'auto')
|
||||
videoEl.setAttribute('playsinline', true)
|
||||
videoEl.setAttribute('webkit-playsinline', true)
|
||||
|
|
@ -315,6 +319,18 @@ export default {
|
|||
key: 'playing',
|
||||
value: false
|
||||
})
|
||||
|
||||
// 自动恢复机制:仅在非主动暂停时触发,并带有 2 秒冷却期防止循环拖动
|
||||
const { loop, autoplay } = this.renderProps
|
||||
const now = Date.now()
|
||||
if (loop && autoplay && this.videoEl && !this.intentionalPause && (now - this.lastAutoRecoverTime > 2000)) {
|
||||
this.lastAutoRecoverTime = now
|
||||
setTimeout(() => {
|
||||
if (this.videoEl && this.videoEl.paused && !this.intentionalPause) {
|
||||
this.videoEl.play().catch(() => {})
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
this.videoEl.removeEventListener('pause', pauseHandler)
|
||||
this.videoEl.addEventListener('pause', pauseHandler)
|
||||
|
|
@ -367,7 +383,13 @@ export default {
|
|||
this.videoEl.addEventListener('loadedmetadata', loadedMetadataHandler)
|
||||
|
||||
// 播放进度监听
|
||||
let lastTime = 0;
|
||||
const timeupdateHandler = (e) => {
|
||||
const now = Date.now();
|
||||
// 增加节流阀,每 500ms 触发一次通信,极大地减少 renderjs 和逻辑层的通讯开销
|
||||
if (now - lastTime < 500) return;
|
||||
lastTime = now;
|
||||
|
||||
const currentTime = e.target.currentTime
|
||||
this.$ownerInstance.callMethod('eventEmit', {
|
||||
event: 'timeupdate',
|
||||
|
|
@ -457,6 +479,12 @@ export default {
|
|||
},
|
||||
triggerCommand(eventType) {
|
||||
if (eventType) {
|
||||
// 标记主动暂停/播放状态,用于自动恢复机制的判断
|
||||
if (eventType === 'pause') {
|
||||
this.intentionalPause = true
|
||||
} else if (eventType === 'play') {
|
||||
this.intentionalPause = false
|
||||
}
|
||||
this.$ownerInstance.callMethod('resetEventCommand')
|
||||
this.videoEl && this.videoEl[eventType]()
|
||||
}
|
||||
|
|
@ -519,6 +547,16 @@ export default {
|
|||
randomNumChange(val) {
|
||||
this.num = val
|
||||
}
|
||||
},
|
||||
// renderjs 层直接清理原生 video 元素,
|
||||
// 确保组件被 v-if 销毁时视频立即停止播放和声音输出
|
||||
beforeUnmount() {
|
||||
if (this.videoEl) {
|
||||
this.videoEl.pause()
|
||||
this.videoEl.src = ''
|
||||
this.videoEl.load()
|
||||
this.videoEl = null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -529,5 +567,7 @@ export default {
|
|||
height: 100%;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
/* 开启硬件加速,将视频提升为独立合成层 */
|
||||
transform: translateZ(0);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
</view>
|
||||
<view class="money alipay-font"
|
||||
:class="item.isAdd ? (isBalance ? 'add-color' : 'red-add-color') : 'minus-color', { 'line-height-51rpx': isBalance }">
|
||||
{{ item.isAdd ? '+' : '-' }}{{ Number(item.money).toFixed(2) }}
|
||||
{{ item.isAdd ? '+' : '-' }}{{ numberUtil.formatMoneyWithThousand(item.money) }}
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
<view v-if="item.isRefund" class="refund" :class="{ 'item-box': !isBalance }">已全额退款</view>
|
||||
<view v-if="isBalance" class="balance secondary" :class="{ 'item-box': !isBalance }">余额
|
||||
<text class="balance-text wx-font-regular">{{
|
||||
Number(item.balance).toFixed(2)
|
||||
numberUtil.formatMoneyWithThousand(item.balance)
|
||||
}}</text>元
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -58,6 +58,10 @@ import {
|
|||
reactive
|
||||
} from 'vue'
|
||||
|
||||
import {
|
||||
numberUtil
|
||||
} from '@/utils/common.js'
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
list: {
|
||||
|
|
@ -94,7 +98,7 @@ const handleTouchStart = (e, item) => {
|
|||
event: e,
|
||||
item
|
||||
})
|
||||
}, 1500)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const handleTouchMove = (e) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,232 @@
|
|||
<template>
|
||||
<view class="header" :class="['header_'+type]">
|
||||
<view class="title" v-if="type!='vivo'">
|
||||
{{title}}
|
||||
</view>
|
||||
<view class="search" v-if="type!='oppo'&&type!='huawei'&&type!='vivo'">
|
||||
<view class="left" >
|
||||
<image src="/static/image/call/iosSearchLeft.png" mode=""></image>
|
||||
{{searchTitle}}
|
||||
</view>
|
||||
<image v-if="type=='ios'" src="/static/image/call/iosSearchRight.png" mode=""></image>
|
||||
</view>
|
||||
<view class="selectType" v-if="type=='huawei'">
|
||||
<view class="btn " :class="{'active':active}" @click.stop="setActive(true)">
|
||||
全部来电
|
||||
</view>
|
||||
<view class="btn" :class="{'active':!active}" @click.stop="setActive(false)">
|
||||
未接来电
|
||||
</view>
|
||||
</view>
|
||||
<view class="selectTypeVivo" v-if="type=='vivo'">
|
||||
<view class="btn " :class="{'active':active}" @click.stop="setActive(true)">
|
||||
全部
|
||||
</view>
|
||||
<view class="btn" :class="{'active':!active}" @click.stop="setActive(false)">
|
||||
未接
|
||||
</view>
|
||||
</view>
|
||||
<view class="select" v-if="type=='xiaomi'">
|
||||
全部通话
|
||||
<image src="/static/image/call/xiaomiHeaderSelectImg.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs
|
||||
} from 'vue'
|
||||
|
||||
const topPopup = ref()
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
|
||||
type: {
|
||||
type: String,
|
||||
default: 'ios'
|
||||
},
|
||||
})
|
||||
|
||||
const data = reactive({
|
||||
active:true,
|
||||
statusBarHeight: 0,
|
||||
showTipLayer: true,
|
||||
title:'最近通话',
|
||||
searchTitle:"搜索",
|
||||
list:[
|
||||
"个人收藏",
|
||||
"最近通话",
|
||||
"通讯录",
|
||||
"拨号键盘",
|
||||
"语音留言"
|
||||
]
|
||||
})
|
||||
|
||||
let {
|
||||
active,
|
||||
searchTitle,
|
||||
title,
|
||||
list,
|
||||
showTipLayer
|
||||
} = toRefs(data)
|
||||
|
||||
onMounted(() => {
|
||||
if(props.type=='xiaomi'){
|
||||
searchTitle.value="搜索联系人"
|
||||
title.value="通话"
|
||||
// console.log('aaaaaaaaaaa')
|
||||
}else if(props.type=='oppo'){
|
||||
title.value="通话"
|
||||
}else if(props.type=='huawei'){
|
||||
title.value="电话"
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
function setActive(status){
|
||||
active.value=status
|
||||
uni.$emit('setActive',status)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.header{
|
||||
padding: 0 15px;
|
||||
background-color: #fff;
|
||||
.title{
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
.search{
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
background: #EEEEF0;
|
||||
border-radius: 12px 12px 12px 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.left{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
color: #838383;
|
||||
}
|
||||
image{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
.select{
|
||||
padding-left: 15px;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
color: #8B8DA5;
|
||||
image{
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.selectTypeVivo{
|
||||
padding-top: 18px;
|
||||
height: 48px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.btn{
|
||||
width: 62px;
|
||||
background-color: #F6F6F6;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
color: #555555;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
border-radius: 8px 0 0 8px;
|
||||
margin: 0 1px;
|
||||
}
|
||||
.btn:nth-child(2){
|
||||
border-radius:0 8px 8px 0;
|
||||
}
|
||||
.active{
|
||||
font-size: 13px;
|
||||
color: #1A1A1A;
|
||||
background: #DCF6E6;
|
||||
}
|
||||
}
|
||||
.header_huawei{
|
||||
padding-bottom: 14px;
|
||||
.title{
|
||||
padding-left: 3px;
|
||||
font-weight: bold;
|
||||
font-size: 30px !important;
|
||||
color: #1A1A1A !important;
|
||||
}
|
||||
.selectType{
|
||||
margin-top: 18px;
|
||||
height: 38px;
|
||||
background: #F4F4F4;
|
||||
border-radius: 19px 19px 19px 19px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 2px;
|
||||
.btn{
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
color: #555555;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
}
|
||||
.active{
|
||||
font-size: 13px;
|
||||
color: #1A1A1A;
|
||||
background: #fff;
|
||||
border-radius: 19px 19px 19px 19px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
.header_xiaomi{
|
||||
.title{
|
||||
padding-left: 15px;
|
||||
font-weight: 400 !important;
|
||||
font-size: 30px !important;
|
||||
color: #1A1A1A !important;
|
||||
}
|
||||
.search{
|
||||
margin-top: 10px;
|
||||
height: 41px !important;
|
||||
background: #F0F0F0 !important;
|
||||
border-radius: 21px 21px 21px 21px !important;
|
||||
.left{
|
||||
font-size: 16px !important;
|
||||
color: #A9A9A9 !important;
|
||||
}
|
||||
image{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: 0 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.header_xiaomi{
|
||||
.search{
|
||||
.left{
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,375 @@
|
|||
<template>
|
||||
<view>
|
||||
<uni-nav-bar :backgroundColor="navBgColor" class="nav-bar" :border="false" :title="title" fixed="true"
|
||||
statusBar="true">
|
||||
<template v-slot:left>
|
||||
<slot name="left">
|
||||
<view :class="[type+'LeftTitle']" :style="{opacity:(type!='huawei'&&type!='oppo'?1: navOpacity)}">
|
||||
{{LeftTitle}}
|
||||
</view>
|
||||
|
||||
</slot>
|
||||
</template>
|
||||
<view class="nav-bar-title " :class="['nav-bar-title-'+type]">
|
||||
<slot>
|
||||
<view class="iosBox" v-if="type=='ios'">
|
||||
<view class="btn " :class="{'active':active}" @click.stop="setActive(true)">
|
||||
全部来电
|
||||
</view>
|
||||
<view class="btn" :class="{'active':!active}" @click.stop="setActive(false)">
|
||||
未接来电
|
||||
</view>
|
||||
</view>
|
||||
<view class="oppoBox" v-if="type=='oppo'" :style="{opacity: navOpacity?1-navOpacity:1}">
|
||||
<view class="btn " :class="{'active':active}" @click.stop="setActive(true)">
|
||||
全部
|
||||
</view>
|
||||
<view class="btn" :class="{'active':!active}" @click.stop="setActive(false)">
|
||||
未接
|
||||
</view>
|
||||
</view>
|
||||
<view class="title" v-else-if="type=='xiaomi'" :style="{opacity: navOpacity}">
|
||||
通话
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<template v-slot:right>
|
||||
<slot name="right">
|
||||
<view class="rightImgBox" :class="['rightImgBox'+type]">
|
||||
|
||||
<image v-if="type=='oppo'||type=='vivo'" class="rightImg"
|
||||
:src="`/static/image/call/${type}NavRightImg2.png`"></image>
|
||||
<image v-if="type!='ios'" class="rightImg" :class="['rightImg_'+type]"
|
||||
:src="`/static/image/call/${type}NavRightImg.png`"></image>
|
||||
</view>
|
||||
</slot>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
|
||||
<view class="tipLayer" :style="{ top: `${45 + data.statusBarHeight}px` }" v-if="isTipLayer&&showTipLayer">
|
||||
<view class="tipLayer-content">
|
||||
<view class="title">
|
||||
<slot name="tipLayer">点击此处<text>[{{ tipLayerText }}]</text></slot>
|
||||
</view>
|
||||
<image class="close" src="/static/image/common/tipLayer-close.png" mode="" @click="closeTipLayer"></image>
|
||||
<image v-if="type=='ios'||type=='oppo'" class="triangleImg" src="/static/image/common/tipLayer-eye2.png"></image>
|
||||
<image v-else class="triangleImg" src="/static/image/common/tipLayer-eye.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs,
|
||||
watch
|
||||
} from 'vue'
|
||||
|
||||
const topPopup = ref()
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#000'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'ios'
|
||||
},
|
||||
scrollTop: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
tipLayerText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isTipLayer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
})
|
||||
|
||||
const data = reactive({
|
||||
active: true,
|
||||
statusBarHeight: 0,
|
||||
LeftTitle: '',
|
||||
showTipLayer: true,
|
||||
navOpacity: 0, // 导航栏透明度
|
||||
navBgColor: props.bgColor // 导航栏背景色
|
||||
})
|
||||
|
||||
let {
|
||||
active,
|
||||
LeftTitle,
|
||||
showTipLayer,
|
||||
navOpacity,
|
||||
navBgColor
|
||||
} = toRefs(data)
|
||||
|
||||
// 监听 scrollTop 变化
|
||||
watch(() => props.scrollTop, (newValue, oldValue) => {
|
||||
// console.log('scrollTop changed:', newValue);
|
||||
// 根据 scrollTop 的值计算导航栏透明度
|
||||
if (newValue > 0) {
|
||||
// 当 scrollTop 大于 0 时,透明度逐渐增加
|
||||
navOpacity.value = Math.min(1, newValue / 100);
|
||||
// 可以根据需要调整背景色
|
||||
// navBgColor.value = `rgba(255, 255, 255, ${navOpacity.value})`;
|
||||
} else {
|
||||
// 当 scrollTop 为 0 时,透明度为 1
|
||||
navOpacity.value = 0;
|
||||
// navBgColor.value = props.bgColor;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (props.type == 'ios') {
|
||||
LeftTitle.value = '编辑'
|
||||
} else if (props.type == 'vivo') {
|
||||
LeftTitle.value = '拨号'
|
||||
} else if (props.type == 'oppo') {
|
||||
LeftTitle.value = '通话'
|
||||
} else if (props.type == 'huawei') {
|
||||
LeftTitle.value = '电话'
|
||||
} else {
|
||||
LeftTitle.value = ''
|
||||
}
|
||||
// 同步获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
data.statusBarHeight = systemInfo.statusBarHeight || 0;
|
||||
if (props.isTipLayer) {
|
||||
if (uni.getStorageSync("call_" + props.type) == props.type) {
|
||||
showTipLayer.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function setActive(status) {
|
||||
active.value = status
|
||||
uni.$emit('setActive', status)
|
||||
}
|
||||
|
||||
const closeTipLayer = () => {
|
||||
showTipLayer.value = false
|
||||
uni.setStorageSync("call_" + props.type, props.type)
|
||||
emit("refresh")
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
::v-deep .uni-navbar__header-btns {
|
||||
width: 27vw !important;
|
||||
}
|
||||
|
||||
.iosLeftTitle {
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #018AE0;
|
||||
}
|
||||
|
||||
.rightImgBox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.rightImg_oppo {
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.rightImg_vivo {
|
||||
margin-left: 26px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.oppoLeftTitle {
|
||||
padding-left: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 32px;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.huaweiLeftTitle {
|
||||
padding-left: 8px;
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.vivoLeftTitle {
|
||||
padding-left: 34px;
|
||||
font-weight: bold;
|
||||
font-size: 30px;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.nav-bar-title-xiaomi {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.nav-bar-title-oppo {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.oppoBox {
|
||||
padding: 0 2px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
width: 137px;
|
||||
height: 34px;
|
||||
background: #E9E9E9;
|
||||
border-radius: 17px 17px 17px 17px;
|
||||
|
||||
.btn {
|
||||
font-size: 12px;
|
||||
color: #6B6B6B;
|
||||
width: 67px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #1A1A1A;
|
||||
background: #FFFFFF;
|
||||
border-radius: 17px 17px 17px 17px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bar-title-ios {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.iosBox {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
width: 145px;
|
||||
height: 30px;
|
||||
background: #EEEEEE;
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
|
||||
.btn {
|
||||
font-size: 12px;
|
||||
color: #1A1A1A;
|
||||
width: 69px;
|
||||
height: 26px;
|
||||
text-align: center;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 6px 6px 6px 6px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rightImg_xiaomi {
|
||||
width: 20px !important;
|
||||
height: 20px !important;
|
||||
}
|
||||
|
||||
.rightImg_huawei {
|
||||
width: 38px !important;
|
||||
height: 38px !important;
|
||||
}
|
||||
|
||||
.tipLayer {
|
||||
box-sizing: border-box;
|
||||
min-width: 200px !important;
|
||||
height: 48px;
|
||||
background: #B8EDFE;
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
position: fixed;
|
||||
/* top: 115px; */
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 999;
|
||||
|
||||
.tipLayer-content {
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
font-weight: 450;
|
||||
font-size: 14px;
|
||||
color: #268FFF;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
|
||||
text {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #006ADD;
|
||||
}
|
||||
|
||||
::v-deep text {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #006ADD;
|
||||
}
|
||||
}
|
||||
|
||||
.triangleImg {
|
||||
width: 111px;
|
||||
height: 52px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: -23px;
|
||||
left: calc(50% - 111px);
|
||||
}
|
||||
|
||||
.triangle {
|
||||
position: absolute;
|
||||
top: -57px;
|
||||
left: calc(50% - 40px);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,193 @@
|
|||
<template>
|
||||
<view class="footer" :class="['footer_'+type]" :style="data.style" >
|
||||
<view class="item" v-for="(item,index) in list" :key="index" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<image :src="`/static/image/call/${type}TabbarImg${index+1}.png`" mode=""></image>
|
||||
<text>{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="footer footerZhangwei" :class="['footer_'+type]" :style="{'margin-top':$store.state.safeBottomAz+'px'}">
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs
|
||||
} from 'vue'
|
||||
|
||||
const topPopup = ref()
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#000'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'ios'
|
||||
},
|
||||
type2: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
})
|
||||
|
||||
const data = reactive({
|
||||
statusBarHeight: 0,
|
||||
showTipLayer: true,
|
||||
style:{},
|
||||
list: [
|
||||
"个人收藏",
|
||||
"最近通话",
|
||||
"通讯录",
|
||||
"拨号键盘",
|
||||
"语音留言"
|
||||
]
|
||||
})
|
||||
|
||||
let {
|
||||
list,
|
||||
showTipLayer
|
||||
} = toRefs(data)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.type == 'xiaomi') {
|
||||
list.value = ["通话",
|
||||
"联系人",
|
||||
"营业厅"
|
||||
]
|
||||
}else if (props.type == 'oppo') {
|
||||
list.value = ["通话",
|
||||
"联系人",
|
||||
"营业厅"
|
||||
]
|
||||
}else if (props.type == 'huawei') {
|
||||
list.value = ["电话",
|
||||
"联系人",
|
||||
"收藏"
|
||||
]
|
||||
}else if (props.type == 'vivo') {
|
||||
list.value = ["拨号",
|
||||
"联系人",
|
||||
"收藏"
|
||||
]
|
||||
}
|
||||
if(props.type2=='ios'){
|
||||
data.style={'background-color':props.bgColor}
|
||||
}
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
background: #f7f7f7;
|
||||
padding-top: 2px;
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 10px;
|
||||
color: #959597;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer_ios {
|
||||
padding-bottom: constant(safe-area-inset-bottom) !important; // 兼容 IOS<11.2
|
||||
padding-bottom: env(safe-area-inset-bottom) !important; // 兼容 IOS>11.2
|
||||
.item:nth-child(2) {
|
||||
text {
|
||||
color: #007AFC;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footerZhangwei{
|
||||
position: relative !important;
|
||||
opacity: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
height: 47px;
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
.footer_huawei {
|
||||
background: #FAFAFA !important;
|
||||
padding-top: 3px;
|
||||
.item {
|
||||
image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
.item:nth-child(1) {
|
||||
text {
|
||||
color: #0060EA;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer_vivo {
|
||||
background: #FAFAFA !important;
|
||||
padding-top: 13px;
|
||||
padding-bottom: 13px;
|
||||
.item {
|
||||
image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
.item:nth-child(1) {
|
||||
text {
|
||||
color: #1BA552;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer_xiaomi ,.footer_oppo{
|
||||
padding-top: 7px;
|
||||
padding-bottom: 17px;
|
||||
background-color: #fff !important;
|
||||
.item {
|
||||
image {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 10px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
.item:nth-child(1) {
|
||||
text {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
<template>
|
||||
<view class="auto-width-input-container" :class="{ 'is-textarea': type === 'textarea' }">
|
||||
<!-- 测量层:用于计算宽度的影藏文本,必须保持与 input 相同的字体样式 -->
|
||||
<text v-if="type !== 'textarea'" class="measure-text"
|
||||
:style="[inputStyle, { visibility: 'hidden', position: 'absolute', whiteSpace: 'nowrap' }]">
|
||||
{{ modelValue || placeholder }}
|
||||
</text>
|
||||
|
||||
<!-- 输入层 -->
|
||||
<template v-if="type !== 'textarea'">
|
||||
<input v-if="!disabled" class="auto-input" :type="type" :value="modelValue" :placeholder="placeholder"
|
||||
:placeholder-style="placeholderStyle" :style="[inputStyle, { width: finalInputWidth }]" @input="onInput"
|
||||
:maxlength="maxlength" :focus="isFocus" @blur="onBlur" :readonly="readonly" />
|
||||
<view v-else class="auto-input flex-align-center"
|
||||
:style="[inputStyle, { width: finalInputWidth }, !modelValue ? placeholderStyleObject : {}]">
|
||||
{{ modelValue || placeholder }}
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<textarea v-if="!disabled" class="auto-textarea" :value="modelValue" :placeholder="placeholder"
|
||||
:placeholder-style="placeholderStyle" :style="[inputStyle]" @input="onInput" :maxlength="maxlength"
|
||||
auto-height :focus="isFocus" @blur="onBlur" :readonly="readonly" />
|
||||
<view v-else class="auto-textarea" :style="[inputStyle, !modelValue ? placeholderStyleObject : {}]">
|
||||
{{ modelValue || placeholder }}
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 编辑图标 -->
|
||||
<image v-if="showEdit" class="edit-icon" src="/static/image/common/edit.png" @click="handleFocusIcon"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, nextTick, getCurrentInstance, onMounted } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text' // 支持所有原生类型如 'number', 'tel', 'digit' 或 'textarea'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请输入'
|
||||
},
|
||||
placeholderStyle: {
|
||||
type: String,
|
||||
default: 'color: #999;'
|
||||
},
|
||||
fontSize: {
|
||||
type: String,
|
||||
default: '28rpx'
|
||||
},
|
||||
fontWeight: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#1A1A1A'
|
||||
},
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 140
|
||||
},
|
||||
minWidth: {
|
||||
type: String,
|
||||
default: '20rpx'
|
||||
},
|
||||
extraWidth: {
|
||||
type: Number,
|
||||
default: 10 // 额外的缓冲像素,防止文字抖动
|
||||
},
|
||||
showEdit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
readonly: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'change']);
|
||||
const instance = getCurrentInstance();
|
||||
const inputWidth = ref(props.minWidth);
|
||||
// 最终应用的宽度样式
|
||||
const finalInputWidth = computed(() => {
|
||||
// 如果是 textarea 或者设置了填满父级,则不使用测量出的宽度
|
||||
if (props.type === 'textarea') return '100%';
|
||||
// 尝试检测 class 中是否包含撑开逻辑
|
||||
const classStr = instance.proxy.$attrs.class || '';
|
||||
if (classStr.includes('flex-1') || classStr.includes('w100')) {
|
||||
return '100%';
|
||||
}
|
||||
return inputWidth.value;
|
||||
});
|
||||
const isFocus = ref(false);
|
||||
|
||||
const placeholderStyleObject = computed(() => {
|
||||
const style = {};
|
||||
if (!props.placeholderStyle) return style;
|
||||
const parts = props.placeholderStyle.split(';');
|
||||
parts.forEach(part => {
|
||||
const [key, value] = part.split(':');
|
||||
if (key && value) {
|
||||
const camelKey = key.trim().replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
||||
style[camelKey] = value.trim();
|
||||
}
|
||||
});
|
||||
return style;
|
||||
});
|
||||
|
||||
const inputStyle = computed(() => ({
|
||||
fontSize: props.fontSize,
|
||||
fontWeight: props.fontWeight,
|
||||
color: props.color,
|
||||
fontFamily: 'inherit'
|
||||
}));
|
||||
|
||||
/**
|
||||
* 点击图标触发聚焦
|
||||
*/
|
||||
const handleFocusIcon = () => {
|
||||
isFocus.value = false;
|
||||
nextTick(() => {
|
||||
isFocus.value = true;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 失去焦点处理
|
||||
*/
|
||||
const onBlur = () => {
|
||||
isFocus.value = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 核心逻辑:测量隐藏文本的物理宽度
|
||||
*/
|
||||
const updateWidth = () => {
|
||||
if (props.type === 'textarea') return;
|
||||
// 如果是强制撑开模式,理论上不需要测量,但为了防止切换状态时的布局闪烁,我们仍保持测量
|
||||
nextTick(() => {
|
||||
const query = uni.createSelectorQuery().in(instance.proxy);
|
||||
query.select('.measure-text').boundingClientRect(data => {
|
||||
if (data && data.width) {
|
||||
heatWidth(data.width);
|
||||
}
|
||||
}).exec();
|
||||
});
|
||||
};
|
||||
|
||||
const heatWidth = (width) => {
|
||||
// 加上一点额外的空间,避免在某些平台上因为小数点或字体渲染导致的文字换行
|
||||
inputWidth.value = (width + props.extraWidth) + 'px';
|
||||
};
|
||||
|
||||
const onInput = (e) => {
|
||||
const val = e.detail.value;
|
||||
emit('update:modelValue', val);
|
||||
emit('change', val);
|
||||
};
|
||||
|
||||
// 监听值的变化实时更新宽度
|
||||
watch(() => props.modelValue, () => {
|
||||
updateWidth();
|
||||
});
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
updateWidth();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.auto-width-input-container {
|
||||
position: relative;
|
||||
display: inline-flex; // 默认维持自适应宽度
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
// 当父级赋予 flex-1 或手动设置 width: 100% 时,转为标准 flex 布局
|
||||
&.flex-1,
|
||||
&.w100 {
|
||||
display: flex !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
&.is-textarea {
|
||||
display: flex !important;
|
||||
width: 100%;
|
||||
align-items: flex-start;
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
.measure-text {
|
||||
left: -9999rpx;
|
||||
top: -9999rpx;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.auto-input {
|
||||
min-width: v-bind('props.minWidth');
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: inherit;
|
||||
height: 1.4em;
|
||||
line-height: 1.4em;
|
||||
flex-shrink: 0;
|
||||
|
||||
// 如果容器是撑开的,input 也应该撑开
|
||||
& {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.auto-textarea {
|
||||
flex: 1 !important;
|
||||
width: 0 !important;
|
||||
min-width: 0;
|
||||
min-height: 1.4em;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
line-height: 1.4em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
margin-left: 8rpx;
|
||||
flex-shrink: 0;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
<template>
|
||||
<view>
|
||||
<view class="right-btn" @click="open">
|
||||
<image src="/static/image/recharge/rightBtnImg.png" mode=""></image>
|
||||
</view>
|
||||
<view class="maskExchange" v-if="isMaskExchange">
|
||||
<view class="box">
|
||||
<view class="info" v-if="!isExchange">
|
||||
<view :style="styles">
|
||||
<uni-easyinput :styles="styles" v-model="code" placeholder="请输入兑换码" :inputBorder="false"
|
||||
placeholderStyle="text-align: center;"></uni-easyinput>
|
||||
</view>
|
||||
<view class="btn" :class="{'noValue':code==''}" @click="getExchange">
|
||||
兑换
|
||||
</view>
|
||||
</view>
|
||||
<view class="info" v-else>
|
||||
<view class="title">
|
||||
{{couponVip.exchange_name}}
|
||||
</view>
|
||||
<view class="title">
|
||||
{{couponVip.exchange_value}}
|
||||
</view>
|
||||
<view class="time">
|
||||
截至日期:{{couponVip.expire_time}}
|
||||
</view>
|
||||
<view class="btn btn2" @click="submit">
|
||||
兑换
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="close" @click="close">
|
||||
<image src="/static/image/recharge/closeE.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
postJson
|
||||
} from "@/utils/requests.js"
|
||||
export default {
|
||||
name: "exchange",
|
||||
data() {
|
||||
return {
|
||||
code: "",
|
||||
isMaskExchange: false,
|
||||
isExchange: false,
|
||||
couponVip: {
|
||||
|
||||
},
|
||||
styles: {
|
||||
backgroundColor: '#FFFCEC',
|
||||
padding: '10px ',
|
||||
'border-radius': '10px'
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.isMaskExchange = true
|
||||
this.isExchange = false
|
||||
this.code = ''
|
||||
},
|
||||
close() {
|
||||
this.isMaskExchange = false
|
||||
this.code = ''
|
||||
},
|
||||
async getExchange() {
|
||||
if (this.code == '') {
|
||||
return
|
||||
}
|
||||
let couponVip = await this.$requestPromise({
|
||||
url: 'api/activity/exchange',
|
||||
method: "GET",
|
||||
data: {
|
||||
code: this.code
|
||||
}
|
||||
})
|
||||
console.log(couponVip)
|
||||
if (couponVip.code != 0) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "兑换码有误"
|
||||
})
|
||||
return
|
||||
}
|
||||
this.isExchange = true
|
||||
this.couponVip = couponVip.data
|
||||
},
|
||||
async submit() {
|
||||
let exchangeRes = await postJson('q', 'api/activity/exchange', {
|
||||
code: this.code
|
||||
})
|
||||
if (exchangeRes.code != 0) {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "券已使用过了"
|
||||
})
|
||||
return
|
||||
} else {
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "兑换成功"
|
||||
})
|
||||
//获取app用户信息
|
||||
let user = await proxy.$requestPromise({
|
||||
url: 'api/user',
|
||||
method: "GET",
|
||||
data: {}
|
||||
})
|
||||
if (user.code == 0) {
|
||||
data.appUser = user.data
|
||||
console.log("app用户信息", data.appUser);
|
||||
}
|
||||
this.isMaskExchange = false
|
||||
this.isExchange = false
|
||||
uni.navigateBack({
|
||||
delta: 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.maskExchange {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 999;
|
||||
background-color: rgba(0, 0, 0, .5);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.box {
|
||||
background-image: url('/static/image/recharge/exchange.png');
|
||||
background-size: 307px 120px;
|
||||
background-repeat: no-repeat;
|
||||
width: 307px;
|
||||
padding: 120px 0 20px 0;
|
||||
|
||||
.info {
|
||||
padding: 16px;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 26px 26px;
|
||||
|
||||
input {
|
||||
background: #FFFCEC;
|
||||
border-radius: 11px 11px 11px 11px;
|
||||
padding: 18px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.time {
|
||||
font-size: 16px;
|
||||
color: #AAAAAA;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
color: #fff;
|
||||
margin-top: 32px;
|
||||
font-size: 18px;
|
||||
padding: 16px 0;
|
||||
color: #FFFFFF;
|
||||
background: linear-gradient(360deg, #4B3F30 0%, #181713 56.43%, #504834 100%), #D8D8D8;
|
||||
border-radius: 60px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.noValue {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
margin-top: 16px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-btn {
|
||||
position: fixed;
|
||||
top: 100rpx;
|
||||
right: 36rpx;
|
||||
z-index: 1;
|
||||
width: 54px;
|
||||
height: 26px;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,327 @@
|
|||
<template>
|
||||
<view class="preview-container" :class="phone === 'mi' ? 'mi-bg' : 'oppo-bg'" v-if="show">
|
||||
<template v-if="phone === 'oppo' || !phone || phone === 'iphone' || phone === 'huawei' || phone === 'vivo'">
|
||||
<view class="header" @tap.stop :style="{ 'padding-top': statusBarHeight }">
|
||||
<image class="icon-back" src="/static/image/phone-message/oppo/back-white.png" @tap="close"></image>
|
||||
<image class="icon-download" src="/static/image/phone-message/oppo/save-white.png"></image>
|
||||
</view>
|
||||
<!-- 图片显示 -->
|
||||
<swiper class="preview-swiper" :current="current" @change="onChange">
|
||||
<swiper-item v-for="(imgSrc, index) in images" :key="index">
|
||||
<image class="preview-img" :src="imgSrc" mode="aspectFit"></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
|
||||
<template v-else-if="phone === 'mi'">
|
||||
<view class="mi-header" @tap.stop :style="{ 'padding-top': statusBarHeight }">
|
||||
<!-- 复用现有返回图标并通过滤镜反色 -->
|
||||
<image class="mi-icon-back" src="/static/image/phone-message/oppo/back-white.png" @tap="close"></image>
|
||||
<view class="mi-header-center">
|
||||
<view class="mi-date">{{ currentFormatDate }}</view>
|
||||
<view class="mi-time">{{ currentFormatTime }}</view>
|
||||
</view>
|
||||
<view class="mi-icon-right"></view> <!-- 占位符以居中 -->
|
||||
</view>
|
||||
<swiper class="preview-swiper mi-swiper" :current="current" @change="onChange">
|
||||
<swiper-item v-for="(imgSrc, index) in images" :key="index">
|
||||
<view class="mi-img-container">
|
||||
<image class="mi-preview-img" :src="imgSrc" mode="aspectFill"></image>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="mi-footer">
|
||||
<view class="mi-footer-item">
|
||||
<image class="mi-footer-icon" src="/static/image/phone-message/mi/baocun.png"></image>
|
||||
<view class="mi-footer-text">保存</view>
|
||||
</view>
|
||||
<view class="mi-footer-item">
|
||||
<view class="mi-more-icon">⋯</view>
|
||||
<view class="mi-footer-text">更多</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, computed } from 'vue';
|
||||
|
||||
const statusBarHeight = (uni.getSystemInfoSync().statusBarHeight || 44) + 'px';
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean,
|
||||
images: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
times: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
currentIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
phone: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(['update:show']);
|
||||
|
||||
const current = ref(0);
|
||||
|
||||
watch(() => props.currentIndex, (val) => {
|
||||
current.value = val;
|
||||
});
|
||||
|
||||
const onChange = (e) => {
|
||||
current.value = e.detail.current;
|
||||
};
|
||||
|
||||
const currentFormatDate = computed(() => {
|
||||
if (props.times && props.times.length > current.value) {
|
||||
const timeVal = props.times[current.value];
|
||||
if (timeVal) {
|
||||
if (typeof timeVal === 'string' && timeVal.includes('-')) {
|
||||
const parts = timeVal.split(' ');
|
||||
if (parts.length > 0) {
|
||||
const dateParts = parts[0].split('-');
|
||||
if (dateParts.length === 3) {
|
||||
return `${dateParts[0]}年${parseInt(dateParts[1])}月${parseInt(dateParts[2])}日`;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback
|
||||
const safeTimeStr = String(timeVal).replace(/-/g, '/');
|
||||
const d = new Date(safeTimeStr);
|
||||
if (!isNaN(d.getTime())) {
|
||||
return `${d.getFullYear()}年${d.getMonth() + 1}月${d.getDate()}日`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
const currentFormatTime = computed(() => {
|
||||
if (props.times && props.times.length > current.value) {
|
||||
const timeVal = props.times[current.value];
|
||||
if (timeVal) {
|
||||
if (typeof timeVal === 'string' && timeVal.includes(':')) {
|
||||
const parts = timeVal.split(' ');
|
||||
if (parts.length > 1) {
|
||||
return parts[1];
|
||||
}
|
||||
}
|
||||
// Fallback
|
||||
const safeTimeStr = String(timeVal).replace(/-/g, '/');
|
||||
const d = new Date(safeTimeStr);
|
||||
if (!isNaN(d.getTime())) {
|
||||
const h = d.getHours().toString().padStart(2, '0');
|
||||
const m = d.getMinutes().toString().padStart(2, '0');
|
||||
return `${h}:${m}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
const close = () => {
|
||||
emit('update:show', false);
|
||||
};
|
||||
|
||||
// const download = () => {
|
||||
// const currentSrc = props.images[current.value];
|
||||
// if (!currentSrc) return;
|
||||
|
||||
// // 触发下载逻辑
|
||||
// uni.saveImageToPhotosAlbum({
|
||||
// filePath: currentSrc,
|
||||
// success: function () {
|
||||
// uni.showToast({
|
||||
// title: '保存成功',
|
||||
// icon: 'success'
|
||||
// });
|
||||
// },
|
||||
// fail: function () {
|
||||
// uni.showToast({
|
||||
// title: '保存失败',
|
||||
// icon: 'none'
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.preview-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: 999999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.oppo-bg {
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.mi-bg {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.header {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
/* 预留状态栏高度 */
|
||||
height: 98rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
.icon-back {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin: 0 34rpx;
|
||||
}
|
||||
|
||||
.icon-download {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin: 0 34rpx;
|
||||
}
|
||||
|
||||
.preview-swiper {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ================= 小米样式 ================= */
|
||||
.mi-header {
|
||||
box-sizing: content-box;
|
||||
width: 100%;
|
||||
height: 98rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.mi-icon-back {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin: 0 34rpx;
|
||||
filter: invert(1);
|
||||
/* 白变黑 */
|
||||
}
|
||||
|
||||
.mi-icon-right {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin: 0 34rpx;
|
||||
}
|
||||
|
||||
.mi-header-center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mi-date {
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.mi-time {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.mi-swiper {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mi-img-container {
|
||||
width: 100vw;
|
||||
height: 100vw;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.mi-preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mi-footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 160rpx;
|
||||
background-color: #FFFFFF;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-start;
|
||||
padding-top: 20rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.mi-footer-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mi-footer-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.mi-more-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
line-height: 38rpx;
|
||||
font-size: 40rpx;
|
||||
text-align: center;
|
||||
color: #000;
|
||||
margin-bottom: 8rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mi-footer-text {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,778 @@
|
|||
<template>
|
||||
<view :style="`${phone}-style`">
|
||||
<uni-swipe-action class="swipe-action">
|
||||
<!-- 使用插槽 (请自行给定插槽内容宽度)-->
|
||||
<uni-swipe-action-item class="swipe-action-item" v-for="item in list" :key="item.id">
|
||||
<view class="flex flex-align-center " @click="clickItem(item)">
|
||||
|
||||
<view class="item flex w100">
|
||||
<view class="flex flex-align-center left-box">
|
||||
<view :class="{ 'opacity-0': !item.unRead }" class="dot shrink-0"><text
|
||||
v-if="phone == 'huawei' || phone == 'oppo'">{{ item.unReadNumber
|
||||
> 99
|
||||
? '99+' : (item.unReadNumber || 1) }}</text>
|
||||
</view>
|
||||
<image class="img avatar shrink-0" :class="item.imgShape"
|
||||
:src="item.img || `/static/image/phone-message/${phone}/default.png`" mode="aspectFill">
|
||||
</image>
|
||||
</view>
|
||||
<view class="border-box m-l-24 flex-1 flex flex-align-start">
|
||||
<view class="main-box flex-1">
|
||||
<view class="title-box flex-between">
|
||||
<text class="title">{{ displayTitle(item.title) }}</text>
|
||||
<text class="time">{{ formatDate(getLastMessage(item.chatList)?.time || item.time)
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="content">
|
||||
<view v-if="isImageMsg(getLastMessage(item.chatList))"
|
||||
class="flex flex-align-center">
|
||||
<template v-if="phone === 'iphone'">
|
||||
<text>附件: 1张照片</text>
|
||||
</template>
|
||||
<template v-else-if="phone === 'huawei'">
|
||||
<text>您的好友给您发了一个图片</text>
|
||||
</template>
|
||||
<template v-else-if="phone == 'oppo'">
|
||||
<image style="width: 24rpx;height: 24rpx;margin-right: 16rpx;"
|
||||
src="/static/image/phone-message/oppo/link.png"></image>
|
||||
<text>[图片]</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text>[图片]</text>
|
||||
</template>
|
||||
</view>
|
||||
<rich-text v-else :nodes="getLastMessage(item.chatList)?.content || ''"></rich-text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="box-right h100 flex-column flex-align-center">
|
||||
<image v-if="phone == 'iphone'" src="/static/image/phone-message/iphone/right.png">
|
||||
</image>
|
||||
<image v-if="item.noNotice && phone == 'iphone'" class="m-t-8"
|
||||
src="/static/image/phone-message/iphone/notice.png">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<template v-slot:right>
|
||||
<view class="flex flex-align-center" style="margin-left: 1px;">
|
||||
<view class="btn flex-center flex-align-center edit" style="color: #fff;"
|
||||
@click="editItem(item)">
|
||||
<image :src="`/static/image/phone-message/edit.png`">
|
||||
</image>
|
||||
</view>
|
||||
<view class="btn flex-center flex-align-center delete" @click="deleteItem(item)">
|
||||
<image
|
||||
:src="`/static/image/phone-message/${phone == 'huawei' || phone == 'vivo' ? 'huawei' : 'iphone'}/delete.png`">
|
||||
</image>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
</uni-swipe-action-item>
|
||||
</uni-swipe-action>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
dateUtil
|
||||
} from '@/utils/common.js';
|
||||
// 定义事件
|
||||
const emit = defineEmits(['item-click', 'delete-item', 'edit-item'])
|
||||
const props = defineProps({
|
||||
// 手机品牌
|
||||
phone: {
|
||||
type: String,
|
||||
default: 'iphone'
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 时间日期格式化判断
|
||||
* @param date
|
||||
*/
|
||||
const formatDate = (date) => {
|
||||
if (props.phone == 'oppo') {
|
||||
return dateUtil.formatMessageTime(date, true)
|
||||
} else if (props.phone == 'huawei') {
|
||||
return dateUtil.formatMessageTime(date, true, 'YYYY年M月D日')
|
||||
} else if (props.phone == 'vivo') {
|
||||
let d = date;
|
||||
if (typeof d === 'string') {
|
||||
d = new Date(d.replace(/-/g, '/'));
|
||||
} else if (typeof d === 'number') {
|
||||
d = new Date(d);
|
||||
}
|
||||
const isCurrentYear = d.getFullYear() === new Date().getFullYear();
|
||||
return dateUtil.formatMessageTime(date, true, isCurrentYear ? 'M月D日' : 'YYYY/M/D')
|
||||
} else {
|
||||
return dateUtil.formatMessageTime(date)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化联系人名称,处理 OPPO 纯数字11位手机号显示
|
||||
*/
|
||||
const displayTitle = (title) => {
|
||||
let t = title || '';
|
||||
if (props.phone === 'oppo') {
|
||||
const noSpace = t.replace(/\s+/g, '');
|
||||
if (/^\d{11}$/.test(noSpace)) {
|
||||
return noSpace.replace(/(\d{3})(\d{4})(\d{4})/, '$1 $2 $3');
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断该消息是否为图片消息
|
||||
*/
|
||||
const isImageMsg = (message) => {
|
||||
if (!message) return false;
|
||||
if (message.type === 'image') return true;
|
||||
if (message.content && typeof message.content === 'string') {
|
||||
const str = message.content.trim();
|
||||
if (str.startsWith('<img') && str.endsWith('/>') && str.indexOf('<img') === str.lastIndexOf('<img')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新一条有效消息
|
||||
*/
|
||||
const getLastMessage = (chatList) => {
|
||||
if (!chatList || chatList.length === 0) return null;
|
||||
return chatList[chatList.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击列表元素
|
||||
*/
|
||||
const clickItem = (item) => {
|
||||
emit('item-click', item)
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除列表元素
|
||||
*/
|
||||
const deleteItem = (item) => {
|
||||
emit('delete-item', item)
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改元素
|
||||
* @param item
|
||||
*/
|
||||
const editItem = (item) => {
|
||||
emit('edit-item', item)
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
.m-t-4 {
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
|
||||
.m-t-8 {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.m-l-24 {
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.opacity-0 {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.swipe-action-item {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.edit {
|
||||
background-color: #5855D6;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
|
||||
.title {
|
||||
width: 20px;
|
||||
flex: 1;
|
||||
color: #1A1A1A;
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
white-space: nowrap;
|
||||
font-weight: 600;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.time {
|
||||
flex-shrink: 0;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 苹果样式
|
||||
.iphone-style {
|
||||
.circle {
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
|
||||
.square {
|
||||
border-radius: 16rpx !important;
|
||||
}
|
||||
|
||||
.swipe-action {
|
||||
margin-top: 28rpx;
|
||||
}
|
||||
|
||||
.swipe-action-item:first-child {
|
||||
.border-box {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.border-box::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #D8D8D8;
|
||||
transform: scaleY(0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
padding: 0 0 0 14rpx;
|
||||
height: 146rpx;
|
||||
align-items: center;
|
||||
|
||||
.dot {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: #007BFD;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 84rpx;
|
||||
height: 84rpx;
|
||||
margin-left: 16rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.border-box {
|
||||
position: relative;
|
||||
padding: 18rpx 24rpx 14rpx 0;
|
||||
height: 100%;
|
||||
// box-shadow: inset 0 -0.3px 0 0 #D8D8D8;
|
||||
}
|
||||
|
||||
.border-box::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #D8D8D8;
|
||||
transform: scaleY(0.3);
|
||||
}
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
.title {
|
||||
color: #1A1A1A;
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #838383;
|
||||
font-size: 28rpx;
|
||||
line-height: 28rpx;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 28rpx;
|
||||
line-height: 38rpx;
|
||||
color: #838383;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.box-right {
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 140rpx;
|
||||
height: 146rpx;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-color: #FC3E30;
|
||||
}
|
||||
|
||||
.edit {
|
||||
background-color: #5855D6;
|
||||
}
|
||||
}
|
||||
|
||||
// 小米样式
|
||||
.mi-style {
|
||||
.item {
|
||||
padding-top: 44rpx;
|
||||
height: 170rpx;
|
||||
|
||||
.left-box {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
align-items: flex-start;
|
||||
padding-left: 54rpx;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: #FA3D30;
|
||||
border-radius: 50%;
|
||||
left: 16rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.border-box {
|
||||
position: relative;
|
||||
padding: 4rpx 52rpx 8rpx 0;
|
||||
margin-left: 22rpx;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
.title {
|
||||
color: #1A1A1A;
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #9A9A9A;
|
||||
font-size: 26rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 26rpx;
|
||||
line-height: 38rpx;
|
||||
color: #656565;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.box-right {
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 140rpx;
|
||||
height: 146rpx;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-color: #FC3E30;
|
||||
}
|
||||
|
||||
.edit {
|
||||
background-color: #5855D6;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// oppo样式
|
||||
.oppo-style {
|
||||
.item {
|
||||
padding-top: 28rpx;
|
||||
height: 178rpx;
|
||||
|
||||
.left-box {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
align-items: flex-start;
|
||||
padding-left: 34rpx;
|
||||
}
|
||||
|
||||
.dot {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #E93A22;
|
||||
color: #FFFFFF;
|
||||
line-height: 18rpx;
|
||||
font-size: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
right: -8rpx;
|
||||
top: -4rpx;
|
||||
z-index: 1;
|
||||
border: 2rpx solid #FFFFFF;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.border-box {
|
||||
position: relative;
|
||||
padding: 4rpx 0 28rpx 0;
|
||||
margin-left: 32rpx;
|
||||
margin-right: 34rpx;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.border-box::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #E2E2E2;
|
||||
transform: scaleY(0.3);
|
||||
}
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.title {
|
||||
color: #1A1A1A;
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #656565;
|
||||
font-size: 26rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 28rpx;
|
||||
line-height: 38rpx;
|
||||
color: #737373;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.box-right {
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 140rpx;
|
||||
height: 146rpx;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-color: #FC3E30;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 华为样式
|
||||
.huawei-style {
|
||||
.item {
|
||||
padding: 0 32rpx;
|
||||
height: 156rpx;
|
||||
align-items: center;
|
||||
|
||||
.left-box {
|
||||
position: relative;
|
||||
height: 40px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
padding: 6rpx 10rpx;
|
||||
background-color: #E93A22;
|
||||
color: #FFFFFF;
|
||||
line-height: 20rpx;
|
||||
font-size: 20rpx;
|
||||
border-radius: 16rpx;
|
||||
right: -8rpx;
|
||||
top: -12rpx;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
|
||||
.border-box {
|
||||
padding: 18rpx 0;
|
||||
position: relative;
|
||||
margin-left: 30rpx;
|
||||
margin-top: 2rpx;
|
||||
height: 100%;
|
||||
box-shadow: 0 -0.3px 0 0 #CFCFCF;
|
||||
}
|
||||
|
||||
// .border-box::after {
|
||||
// position: absolute;
|
||||
// content: '';
|
||||
// width: 100%;
|
||||
// height: 1px;
|
||||
// bottom: 0;
|
||||
// left: 0;
|
||||
// right: 0;
|
||||
// background-color: #CFCFCF;
|
||||
// transform: scaleY(0.3);
|
||||
// }
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
.title {
|
||||
color: #1A1A1A;
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #656565;
|
||||
font-size: 24rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 28rpx;
|
||||
line-height: 38rpx;
|
||||
color: #6F6F6F;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.box-right {
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 140rpx;
|
||||
height: 156rpx;
|
||||
|
||||
image {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-color: #F4F4F4;
|
||||
}
|
||||
|
||||
.edit {
|
||||
background-color: #5855D6;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vivo样式
|
||||
.vivo-style {
|
||||
.item {
|
||||
padding: 0 50rpx 0 24rpx;
|
||||
height: 172rpx;
|
||||
align-items: center;
|
||||
|
||||
|
||||
.dot {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background-color: #409DFE;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
|
||||
.img {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.border-box {
|
||||
padding: 28rpx 0 18rpx;
|
||||
position: relative;
|
||||
margin-left: 24rpx;
|
||||
margin-top: 2rpx;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.main-box {
|
||||
.title-box {
|
||||
margin-bottom: 18rpx;
|
||||
|
||||
.title {
|
||||
color: #1A1A1A;
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.time {
|
||||
color: #7C7C7C;
|
||||
font-size: 26rpx;
|
||||
line-height: 26rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-size: 28rpx;
|
||||
line-height: 38rpx;
|
||||
color: #6F6F6F;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.box-right {
|
||||
image {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 140rpx;
|
||||
height: 156rpx;
|
||||
|
||||
image {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
background-color: #F4F4F4;
|
||||
}
|
||||
|
||||
.edit {
|
||||
background-color: #5855D6;
|
||||
|
||||
image {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,596 @@
|
|||
<template>
|
||||
<view :class="`${phone}-style`">
|
||||
<!-- 导航样式 -->
|
||||
<view class="nav-bar-box" :class="{ 'border-nav-bar-box': isScroll }">
|
||||
<NavBar :isBack="false" :bgColor="isScroll ? navBarBgColor : '#fff'" :buttonGroup="buttonGroup"
|
||||
@button-click="util.clickTitlePopupButton" tipLayerType="message-list-tip" isTipLayer isClickNavBarOpenPopup
|
||||
tipLayerText="添加短信" @add="emit('add')">
|
||||
<!-- 左侧文字图标 -->
|
||||
<template v-slot:left>
|
||||
<view v-if="phone == 'iphone'" class="flex flex-align-center">
|
||||
<image @click="util.goBack" class="left-icon" src="/static/image/phone-message/iphone/back.png" mode="">
|
||||
</image>
|
||||
<text class="left-text">过滤条件</text>
|
||||
</view>
|
||||
<view v-if="(phone == 'huawei' && isScroll) || phone == 'vivo'" class="flex flex-align-center">
|
||||
<text class="left-text">信息</text>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 中间标题 -->
|
||||
<template v-slot:center>
|
||||
<view v-if="phone == 'iphone' && isScroll" class="center-text">
|
||||
信息
|
||||
</view>
|
||||
</template>
|
||||
<!-- 右侧图标 -->
|
||||
<template v-slot:right>
|
||||
<!-- iphone -->
|
||||
<view v-if="phone == 'iphone'">
|
||||
<image class="right-icon mg-r-30" src="/static/image/phone-message/iphone/more.png" mode="">
|
||||
</image>
|
||||
<image class="right-icon mg-r-5" src="/static/image/phone-message/iphone/edit.png" mode="">
|
||||
</image>
|
||||
</view>
|
||||
<!-- mi -->
|
||||
<view v-if="phone == 'mi'">
|
||||
<image class="right-icon" src="/static/image/phone-message/mi/setting.png" mode=""></image>
|
||||
</view>
|
||||
<!-- oppo -->
|
||||
<view v-if="phone == 'oppo'">
|
||||
<image class="right-icon mg-r-52" src="/static/image/phone-message/oppo/search.png" mode="">
|
||||
</image>
|
||||
<image class="right-icon mg-r-14" src="/static/image/phone-message/oppo/more.png" mode="">
|
||||
</image>
|
||||
</view>
|
||||
<!-- huawei -->
|
||||
<view v-if="phone == 'huawei'">
|
||||
<image v-if="isScroll" class="right-icon" src="/static/image/phone-message/huawei/nav-search.png" mode="">
|
||||
</image>
|
||||
<image class="right-icon" src="/static/image/phone-message/huawei/add.png" mode=""></image>
|
||||
<image class="right-icon" src="/static/image/phone-message/huawei/more.png" mode=""></image>
|
||||
</view>
|
||||
<!-- vivo -->
|
||||
<view v-if="phone == 'vivo'">
|
||||
<image class="right-icon" src="/static/image/phone-message/vivo/select.png" mode="">
|
||||
</image>
|
||||
<image class="right-icon" src="/static/image/phone-message/vivo/add.png" mode=""></image>
|
||||
<image class="right-icon m-r-34" src="/static/image/phone-message/vivo/more.png" mode="">
|
||||
</image>
|
||||
</view>
|
||||
</template>
|
||||
</NavBar>
|
||||
</view>
|
||||
|
||||
<!-- 主体内容 -->
|
||||
<view class="main-container">
|
||||
<!-- 顶部搜索栏样式 -->
|
||||
<view class="top-box">
|
||||
<view v-if="showInfo.text" class="text">{{ showInfo.text }}</view>
|
||||
<view v-if="showInfo.secondText" class="second-text">{{ showInfo.secondText }}</view>
|
||||
<view v-if="showInfo.placeholder" class="search-box flex flex-align-center">
|
||||
<image class="icon" :src="`/static/image/phone-message/${props.phone}/search.png`">
|
||||
</image>
|
||||
<input class="input flex-1" :placeholder="showInfo.placeholder" type="text" disabled>
|
||||
<image v-if="phone != 'mi'" class="icon" :src="`/static/image/phone-message/${props.phone}/mic.png`">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<slot>
|
||||
</slot>
|
||||
</view>
|
||||
<view class="bottom-placeholder" :style="{'margin-top':$store.state.safeBottomAz+'px'}"></view>
|
||||
<!-- 底部样式 -->
|
||||
<template v-if="phone == 'mi' || phone == 'oppo'">
|
||||
<image class="add-message" @click="emit('add')"
|
||||
:src="`/static/image/phone-message/${props.phone}/add-message.png`"></image>
|
||||
<view class="bottom-box " :style="{height: (74+$store.state.safeBottomAz)+'px'}">
|
||||
<view class="flex" :style="{height: '148rpx'}">
|
||||
<view class="item flex-1 h100">
|
||||
<image class="icon" :src="`/static/image/phone-message/${props.phone}/bottom-left.png`"></image>
|
||||
<text>{{ showInfo.bottomLtext }}</text>
|
||||
</view>
|
||||
<view class="item flex-1 h100">
|
||||
<image class="icon" :src="`/static/image/phone-message/${props.phone}/bottom-right.png`"></image>
|
||||
<text class="grey">{{ showInfo.bottomRtext }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import {
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue'
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js';
|
||||
|
||||
const emit = defineEmits(['add', 'setSim', 'setNoticeCount'])
|
||||
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
// 手机品牌
|
||||
phone: {
|
||||
type: String,
|
||||
default: 'iphone'
|
||||
},
|
||||
// 是否向下滚动
|
||||
isScroll: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
noticeCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const buttonGroup = computed(() => {
|
||||
const groups = [{
|
||||
name: "添加短信",
|
||||
click: () => {
|
||||
emit('add')
|
||||
}
|
||||
}, {
|
||||
name: "设置卡1卡2运营商",
|
||||
click: () => {
|
||||
emit('setSim')
|
||||
}
|
||||
}]
|
||||
|
||||
if (props.phone == 'huawei') {
|
||||
groups.push({
|
||||
name: "设置通知信息未读数",
|
||||
click: () => {
|
||||
emit('setNoticeCount')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return groups
|
||||
})
|
||||
|
||||
|
||||
const navBarBgColor = computed(() => {
|
||||
return props.phone === 'iphone' ? '#F8F8F8' : '#FFFFFF';
|
||||
})
|
||||
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: '信息',
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
// 展示文字信息
|
||||
const showInfo = computed(() => {
|
||||
let text, placeholder, secondText, bottomLtext, bottomRtext
|
||||
switch (props.phone) {
|
||||
case "iphone":
|
||||
text = "信息"
|
||||
placeholder = '搜索'
|
||||
break;
|
||||
case "mi":
|
||||
text = "主要"
|
||||
placeholder = '搜索短信'
|
||||
bottomLtext = "主要"
|
||||
bottomRtext = "推广"
|
||||
break;
|
||||
case "oppo":
|
||||
text = "消息"
|
||||
placeholder = ''
|
||||
bottomLtext = "消息"
|
||||
bottomRtext = "通知"
|
||||
break;
|
||||
case "huawei":
|
||||
text = "信息"
|
||||
placeholder = '搜索信息'
|
||||
secondText = props.noticeCount > 0 ? `${props.noticeCount} 条未读` : ''
|
||||
break;
|
||||
case "vivo":
|
||||
placeholder = '搜索信息'
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return {
|
||||
text,
|
||||
placeholder,
|
||||
secondText,
|
||||
bottomLtext,
|
||||
bottomRtext
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
|
||||
page {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
::v-deep .uni-navbar__header-btns {
|
||||
width: 100px !important;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
::v-deep .uni-navbar__header {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.bottom-box {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 120rpx;
|
||||
border-top: 1rpx solid #E7E7E7;
|
||||
background-color: #ffffff;
|
||||
z-index: 9;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 20rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.grey {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 苹果机型样式
|
||||
.iphone-style {
|
||||
.mg-r-30 {
|
||||
margin-right: 60rpx;
|
||||
}
|
||||
|
||||
.mg-r-5 {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.left-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
.left-text {
|
||||
font-size: 32rpx;
|
||||
color: #0278E2;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.center-text {
|
||||
font-size: 32rpx;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.border-nav-bar-box {
|
||||
::v-deep .nav-bar-container {
|
||||
box-shadow: 0 -0.3px 0 0 #B5B5B5 inset;
|
||||
}
|
||||
}
|
||||
|
||||
.main-container {
|
||||
.top-box {
|
||||
padding: 20rpx 32rpx 0;
|
||||
|
||||
.text {
|
||||
color: #1A1A1A;
|
||||
font-size: 64rpx;
|
||||
font-weight: 700;
|
||||
line-height: 72rpx;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
margin-top: 20rpx;
|
||||
background-color: #EEEEF0;
|
||||
height: 68rpx;
|
||||
border-radius: 24rpx;
|
||||
padding: 0 16rpx;
|
||||
|
||||
.icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
margin: 0 14rpx;
|
||||
|
||||
::v-deep .input-placeholder {
|
||||
color: #838383;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 小米机型样式
|
||||
.mi-style {
|
||||
.right-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
|
||||
.top-box {
|
||||
padding: 0 22rpx 0;
|
||||
|
||||
.text {
|
||||
color: #1A1A1A;
|
||||
font-size: 60rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
margin-top: 32rpx;
|
||||
background-color: #F0F0F0;
|
||||
height: 84rpx;
|
||||
border-radius: 42rpx;
|
||||
padding: 0 34rpx;
|
||||
|
||||
.icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
margin: 0 18rpx;
|
||||
|
||||
::v-deep .input-placeholder {
|
||||
color: #A9A9A9;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-message {
|
||||
position: fixed;
|
||||
bottom: 168rpx;
|
||||
right: 44rpx;
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
}
|
||||
|
||||
.bottom-placeholder {
|
||||
height: 120rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// oppo机型
|
||||
.oppo-style {
|
||||
.mg-r-52 {
|
||||
margin-right: 52rpx;
|
||||
}
|
||||
|
||||
.mg-r-14 {
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
|
||||
|
||||
.top-box {
|
||||
padding: 16rpx 34rpx 0;
|
||||
margin-bottom: 50rpx;
|
||||
|
||||
.text {
|
||||
color: #1A1A1A;
|
||||
font-size: 64rpx;
|
||||
font-weight: 900;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-message {
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
position: fixed;
|
||||
bottom: 200rpx;
|
||||
right: 46rpx;
|
||||
}
|
||||
|
||||
.bottom-placeholder {
|
||||
height: 148rpx;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.bottom-box {
|
||||
|
||||
background-color: #FAFAFA;
|
||||
border-top: 1rpx solid #DCDCDC;
|
||||
|
||||
.item {
|
||||
.icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
color: #191919;
|
||||
}
|
||||
|
||||
.grey {
|
||||
color: #717171;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 华为机型
|
||||
.huawei-style {
|
||||
|
||||
::v-deep .uni-navbar__header-container {
|
||||
flex: 0;
|
||||
}
|
||||
|
||||
.left-text {
|
||||
color: #1a1a1a;
|
||||
font-size: 50rpx;
|
||||
font-weight: 700;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
margin: 0 8rpx;
|
||||
}
|
||||
|
||||
.border-nav-bar-box {
|
||||
::v-deep .nav-bar {
|
||||
border-bottom: 1rpx solid #D1D1D1;
|
||||
}
|
||||
}
|
||||
|
||||
.main-container {
|
||||
|
||||
|
||||
.top-box {
|
||||
padding: 40rpx 34rpx 0;
|
||||
|
||||
.text {
|
||||
color: #1A1A1A;
|
||||
font-size: 60rpx;
|
||||
font-weight: 700;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.second-text {
|
||||
color: #646464;
|
||||
font-size: 28rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
margin-top: 40rpx;
|
||||
background-color: #F4F4F4;
|
||||
height: 76rpx;
|
||||
border-radius: 38rpx;
|
||||
padding: 0 24rpx;
|
||||
|
||||
.icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.input {
|
||||
margin: 0 14rpx;
|
||||
|
||||
::v-deep .input-placeholder {
|
||||
color: #646464;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vivo机型
|
||||
.vivo-style {
|
||||
::v-deep .uni-navbar__header-container {
|
||||
flex: 0;
|
||||
}
|
||||
|
||||
.m-r-34 {
|
||||
margin-right: 34rpx !important;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
margin-right: 52rpx;
|
||||
}
|
||||
|
||||
.left-text {
|
||||
font-size: 54rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 700;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
.top-box {
|
||||
padding: 0 46rpx;
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
margin-top: 70rpx;
|
||||
background-color: #ffffff;
|
||||
height: 76rpx;
|
||||
border-radius: 38rpx;
|
||||
padding: 0 10rpx;
|
||||
|
||||
.icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
margin: 0 20rpx;
|
||||
|
||||
::v-deep .input-placeholder {
|
||||
color: #9A9A9A;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-box::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 12rpx;
|
||||
background-color: #F0F0F0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<text
|
||||
class="custom-icon"
|
||||
:class="iconClass"
|
||||
:style="{ color: color, fontSize: size + 'px' }"
|
||||
@click="$emit('click')"
|
||||
></text>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "my-icon",
|
||||
props: {
|
||||
// 图标名称,例如 'icon-home'
|
||||
name: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 图标颜色
|
||||
color: {
|
||||
type: String,
|
||||
default: "#333333"
|
||||
},
|
||||
// 图标大小,单位 rpx
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 16
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconClass() {
|
||||
// 这里的 'custom-icon' 必须和下面 font-family 的定义或者样式前缀对应
|
||||
const name = `icon-${this.name}`;
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 1. 引入并定义字体名称 */
|
||||
@font-face {
|
||||
font-family: 'myIconFont';
|
||||
/* 微信小程序若本地引用报错,可换成 base64 字符串或网络绝对路径 */
|
||||
src: url('@/static/font/iconfont.ttf') format('truetype');
|
||||
}
|
||||
|
||||
/* 2. 定义基础样式 */
|
||||
.custom-icon {
|
||||
font-family: "myIconFont" !important;
|
||||
font-size: inherit;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.icon-sanjiaozhou-maohao:before {
|
||||
content: "\e630";
|
||||
}
|
||||
.icon-sanjiaozhou-fengexian:before {
|
||||
content: "\e631";
|
||||
}
|
||||
.icon-sanjiaozhou-douhao:before {
|
||||
content: "\e626";
|
||||
}
|
||||
.icon-sanjiaozhou-0:before {
|
||||
content: "\e629";
|
||||
}
|
||||
.icon-sanjiaozhou-1:before {
|
||||
content: "\e627";
|
||||
}
|
||||
.icon-sanjiaozhou-2:before {
|
||||
content: "\e62b";
|
||||
}
|
||||
.icon-sanjiaozhou-3:before {
|
||||
content: "\e62c";
|
||||
}
|
||||
.icon-a-sanjiaozhou-4:before {
|
||||
content: "\e62f";
|
||||
}
|
||||
.icon-sanjiaozhou-5:before {
|
||||
content: "\e62d";
|
||||
}
|
||||
.icon-sanjiaozhou-6:before {
|
||||
content: "\e628";
|
||||
}
|
||||
.icon-sanjiaozhou-7:before {
|
||||
content: "\e625";
|
||||
}
|
||||
.icon-sanjiaozhou-8:before {
|
||||
content: "\e62a";
|
||||
}
|
||||
.icon-sanjiaozhou-9:before {
|
||||
content: "\e62e";
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,19 +1,19 @@
|
|||
<template>
|
||||
<view style="width: 100%;" :style="{ height: `calc(${data.statusBarHeight}px + 88rpx)` }">
|
||||
<view class="placeholder-box" style="width: 100%;" :style="{ height: `calc(${data.statusBarHeight}px + 88rpx)` }">
|
||||
<!-- <slot name="statusBar"></slot> -->
|
||||
</view>
|
||||
<view class="nav-bar-container" :style="{ backgroundColor: bgColor, zIndex: zIndex }">
|
||||
<view class="status-placeholder" :style="{ height: `${data.statusBarHeight}px` }">
|
||||
<slot name="statusBar"></slot>
|
||||
</view>
|
||||
<view style="width: 100%;height: 88rpx;" @click="openPopup">
|
||||
<view class="nav-box" style="width: 100%;height: 88rpx;" @click="openPopup">
|
||||
<slot>
|
||||
<uni-nav-bar backgroundColor="#00000000" class="nav-bar" :border="false" :title="title" v-bind="$attrs"
|
||||
v-on="$attrs">
|
||||
<template v-slot:left>
|
||||
<view class="nav-bar-left">
|
||||
<view class="nav-bar-left" @click.stop="isClickNavBarOpenPopup ? openPopup() : ''">
|
||||
<slot name="left">
|
||||
<view class="left-icon" @click.stop="onBack">
|
||||
<view v-if="isBack" class="left-icon" @click.stop="onBack">
|
||||
<image class="nav-icon-back"
|
||||
:src="`/static/image/nav-bar/back-${textColor == '#fff' || textColor == '#fffffff' ? 'white' : 'black'}.png`"
|
||||
mode="">
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
</slot>
|
||||
</view>
|
||||
<template v-slot:right>
|
||||
<view class="nav-bar-right" @click.stop="onRightClick">
|
||||
<view class="nav-bar-right" @click.stop="isClickNavBarOpenPopup ? openPopup() : onRightClick()">
|
||||
<slot name="right">
|
||||
<view v-if="isRightIcon" class="right-icon">
|
||||
<image class="nav-icon-more"
|
||||
|
|
@ -82,18 +82,18 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import popup from '../popup/popup.vue'
|
||||
import {
|
||||
import popup from '../popup/popup.vue'
|
||||
import {
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs
|
||||
} from 'vue'
|
||||
} from 'vue'
|
||||
|
||||
const topPopup = ref()
|
||||
const topPopup = ref()
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
|
|
@ -130,6 +130,10 @@ const props = defineProps({
|
|||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isBack: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
tipLayerText: {
|
||||
type: String,
|
||||
default: ''
|
||||
|
|
@ -141,23 +145,27 @@ const props = defineProps({
|
|||
tipLayerType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isClickNavBarOpenPopup: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['back', 'right-click', 'button-click', 'refresh'])
|
||||
// 定义事件
|
||||
const emit = defineEmits(['back', 'right-click', 'button-click', 'refresh'])
|
||||
|
||||
const data = reactive({
|
||||
const data = reactive({
|
||||
statusBarHeight: 0,
|
||||
showTipLayer: true,
|
||||
})
|
||||
})
|
||||
|
||||
let {
|
||||
let {
|
||||
showTipLayer
|
||||
} = toRefs(data)
|
||||
} = toRefs(data)
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(() => {
|
||||
// 同步获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
data.statusBarHeight = systemInfo.statusBarHeight || 0;
|
||||
|
|
@ -168,44 +176,54 @@ onMounted(() => {
|
|||
}
|
||||
}
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
const closeTipLayer = () => {
|
||||
const closeTipLayer = () => {
|
||||
showTipLayer.value = false
|
||||
uni.setStorageSync(props.tipLayerType, props.tipLayerType)
|
||||
emit("refresh")
|
||||
}
|
||||
}
|
||||
|
||||
const openPopup = () => {
|
||||
const openPopup = () => {
|
||||
if (props.buttonGroup.length > 0) {
|
||||
topPopup.value.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 返回按钮点击事件
|
||||
const onBack = () => {
|
||||
// 返回按钮点击事件
|
||||
const onBack = () => {
|
||||
emit('back')
|
||||
// 默认返回上一页
|
||||
if (props.noBack) return
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
|
||||
// 右侧按钮点击事件
|
||||
const onRightClick = () => {
|
||||
// 右侧按钮点击事件
|
||||
const onRightClick = () => {
|
||||
emit('right-click')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const buttonClick = (button) => {
|
||||
const closeTopPopup = () => {
|
||||
topPopup.value.close()
|
||||
}
|
||||
|
||||
|
||||
const buttonClick = (button) => {
|
||||
closeTopPopup()
|
||||
emit('button-click', button)
|
||||
}
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法
|
||||
defineExpose({
|
||||
openPopup,
|
||||
closeTopPopup
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@import "/common/main.css";
|
||||
@import "/common/main.css";
|
||||
|
||||
.nav-bar-container {
|
||||
.nav-bar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed !important;
|
||||
|
|
@ -213,42 +231,42 @@ const buttonClick = (button) => {
|
|||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
.nav-bar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.status-placeholder {
|
||||
.status-placeholder {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .uni-navbar__content {
|
||||
::v-deep .uni-navbar__content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bar-left {
|
||||
.nav-bar-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-icon-back {
|
||||
.nav-icon-back {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-icon-more {
|
||||
.nav-icon-more {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bar-title {
|
||||
.nav-bar-title {
|
||||
flex: 1;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
|
|
@ -256,15 +274,15 @@ const buttonClick = (button) => {
|
|||
justify-content: center;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-bar-right {
|
||||
.nav-bar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.right-button {
|
||||
.right-button {
|
||||
font-size: 12px;
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
|
|
@ -273,23 +291,23 @@ const buttonClick = (button) => {
|
|||
height: 30px;
|
||||
min-width: 60px;
|
||||
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.button-box {
|
||||
.button-box {
|
||||
width: calc(50% - 8rpx);
|
||||
text-align: center;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
.button {
|
||||
border: 1px solid #E4E4E4;
|
||||
border-radius: 8px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tipLayer {
|
||||
.tipLayer {
|
||||
box-sizing: border-box;
|
||||
min-width: 200px !important;
|
||||
height: 48px;
|
||||
|
|
@ -303,15 +321,15 @@ const buttonClick = (button) => {
|
|||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.tipLayer-content {
|
||||
.tipLayer-content {
|
||||
position: relative;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
.title {
|
||||
font-weight: 450;
|
||||
font-size: 14px;
|
||||
color: #268FFF;
|
||||
|
|
@ -329,29 +347,29 @@ const buttonClick = (button) => {
|
|||
font-weight: bold;
|
||||
color: #006ADD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.triangleImg {
|
||||
.triangleImg {
|
||||
width: 111px;
|
||||
height: 52px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: -23px;
|
||||
left: calc(50% - 111px);
|
||||
}
|
||||
}
|
||||
|
||||
.triangle {
|
||||
.triangle {
|
||||
position: absolute;
|
||||
top: -57px;
|
||||
left: calc(50% - 40px);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
.close {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<view class="safeBottomBox">
|
||||
<view class="safeBottomFiexd" :style="{ height: safeBottomAz + 'px', backgroundColor: bgColor }">
|
||||
</view>
|
||||
<view class="safeBottomZhangwei" :style="{ height: safeBottomAz + 'px' }">
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, getCurrentInstance } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#EDEDED'
|
||||
}
|
||||
})
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
const safeBottomAz = computed(() => {
|
||||
const store = instance?.appContext?.config?.globalProperties?.$store
|
||||
const height = store?.state?.safeBottomAz
|
||||
return Number(height) || 0
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.safeBottomBox {
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
z-index: 999;
|
||||
overflow: hidden;
|
||||
.safeBottomFiexd {
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,831 @@
|
|||
<template>
|
||||
<view class="shopping-card" @longpress="onLongPress">
|
||||
<!-- Header -->
|
||||
<view class="card-header">
|
||||
<view class="shop-info">
|
||||
<!-- <view class="">
|
||||
|
||||
</view> -->
|
||||
<image v-if="item.shopType === 'self'" style="width: 50rpx;margin-right: 12rpx;border-radius: 4rpx;"
|
||||
src="/static/image/shopping/jingdong/detail/ziyin.png" mode="widthFix"></image>
|
||||
<image v-if="item.shopType === 'waimai'" style="width: 50rpx;margin-right: 8rpx;border-radius: 4rpx;"
|
||||
src="/static/image/shopping/jingdong/waimai/waimai.png" mode="widthFix"></image>
|
||||
<!-- <view class="tag waimai-tag">外卖</view> -->
|
||||
<image class="jd-tag" v-if="item.shopType === 'jd'" src="/static/image/shopping/jingdong/JD.png">
|
||||
</image>
|
||||
<text class="shop-name">{{ item.shopName }}</text>
|
||||
<uni-icons class="right-icon" type="right" size="12" color="#1A1A1A"></uni-icons>
|
||||
</view>
|
||||
<view class="order-status">
|
||||
<view v-if="item.status === '等待付款'" class="status-warning">
|
||||
<image style="width: 116rpx;height: 30rpx;" src="/static/image/shopping/jingdong/dengdaifukuan.png">
|
||||
</image>
|
||||
<text class="status-desc" v-if="item.statusDesc">{{
|
||||
item.shopType != 'waimai' ? formatStatusDesc(item.statusDesc) :
|
||||
formatWaimaiStatusDesc(item.statusDesc) }}</text>
|
||||
</view>
|
||||
<text v-else class="status-text"
|
||||
:class="{ red: item.statusColor === 'red' || item.status === '正在出库' || item.status === '商家备餐中' || item.status === '骑手到店取餐中' || item.status === '骑手已到店' }">{{
|
||||
item.status }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Tracking -->
|
||||
<view class="tracking-box" :class="{ 'waimai-tracking': item.shopType === 'waimai' }"
|
||||
v-if="item.trackingTitle || item.trackingDesc">
|
||||
<view class="waimai-tracking-icon" v-if="item.shopType === 'waimai'">
|
||||
<image style="width: 32rpx; height: 32rpx;" src="/static/image/shopping/jingdong/waimai-logo.png"
|
||||
mode="aspectFit" v-if="!item.trackingIcon">
|
||||
</image>
|
||||
<!-- <image style="width: 28rpx; height: 28rpx;" :src="item.trackingIcon" mode="aspectFit" v-else></image> -->
|
||||
</view>
|
||||
<view class="tracking-content">
|
||||
<view class="tracking-header" v-if="item.shopType !== 'waimai'">
|
||||
<image class="truck-icon" v-if="!item.trackingIcon"
|
||||
src="/static/image/shopping/jingdong/cangku.png">
|
||||
</image>
|
||||
<image class="truck-icon" :src="item.trackingIcon" mode="aspectFit" v-else></image>
|
||||
<text class="tracking-title">{{ item.trackingTitle }}</text>
|
||||
</view>
|
||||
<view class="tracking-main-title" v-else>
|
||||
<view class="rich-title">预计<span style="color:#E40C24">{{ item.trackingTitle }}</span> 可送达</view>
|
||||
</view>
|
||||
<text class="tracking-desc" v-if="item.trackingDesc">{{ item.trackingDesc }}</text>
|
||||
<text class="tracking-time">{{ item.trackingTime }}</text>
|
||||
</view>
|
||||
<uni-icons v-if="item.shopType !== 'waimai'" class="right-icon" type="right" size="14"
|
||||
color="#3D3D3D"></uni-icons>
|
||||
</view>
|
||||
|
||||
<!-- Product -->
|
||||
<view class="product-box"
|
||||
:class="{ multiple: (item.products && item.products.length > 1) || (item.images && item.images.length > 0) }">
|
||||
<template v-if="item.products && item.products.length > 1">
|
||||
<scroll-view class="product-images-scroll" scroll-x :show-scrollbar="false">
|
||||
<image class="product-img small" v-for="(prod, idx) in item.products" :key="idx" :src="prod.image"
|
||||
mode="aspectFill"></image>
|
||||
</scroll-view>
|
||||
</template>
|
||||
<template v-else-if="item.products && item.products.length === 1">
|
||||
<image class="product-img" :src="item.products[0].image" mode="aspectFill"></image>
|
||||
</template>
|
||||
<template v-else-if="item.images && item.images.length > 0">
|
||||
<scroll-view class="product-images-scroll" scroll-x :show-scrollbar="false">
|
||||
<image class="product-img small" v-for="(img, idx) in item.images" :key="idx" :src="img"
|
||||
mode="aspectFill"></image>
|
||||
</scroll-view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<image class="product-img" :src="item.image" mode="aspectFill"></image>
|
||||
<view class="product-info">
|
||||
<text class="product-title" :class="{ 'shopping-title': item.shopType !== 'waimai' }">{{
|
||||
truncatedTitle }}</text>
|
||||
<text class="product-desc" v-if="item.desc">{{ item.desc }}</text>
|
||||
<view class="product-tags" v-if="item.tags && item.tags.length">
|
||||
<text class="tag" v-for="(tag, index) in item.tags" :key="index">{{ tag }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class='flex flex-justify-between flex-align-center'
|
||||
:class="{ 'flex-1': item.products && item.products.length === 1 }">
|
||||
<view class="product-info flex-1">
|
||||
<template v-if="item.products && item.products.length === 1">
|
||||
<text class="product-title" :class="{ 'shopping-title': item.shopType !== 'waimai' }">{{
|
||||
truncatedTitle }}</text>
|
||||
<text class="product-desc" v-if="item.products[0].desc">{{ item.products[0].desc }}</text>
|
||||
<view class="product-tags" v-if="item.products[0].service">
|
||||
<text class="tag">{{ item.products[0].service }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<view class="product-price-box">
|
||||
<view class="price-wrap wx-font-regular">
|
||||
<text class="price-symbol">¥</text>
|
||||
<text class="price-num">{{ item.shopType === 'waimai' ?
|
||||
(item.totalPrice ? Number(item.totalPrice).toFixed(2) : '0.00')
|
||||
:
|
||||
safeFormatPrice(item)
|
||||
}}</text>
|
||||
</view>
|
||||
<text class="product-count"
|
||||
v-if="item.count || (item.products && item.products[0] && item.products[0].count)">共{{
|
||||
item.count || (item.products && item.products[0] && item.products[0].count) }}件</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- Promo -->
|
||||
<view class="promo-box"
|
||||
:class="{ 'plus-promo': item.promoType === 'plus', 'cashback-promo': item.shopType == 'waimai' && (item.status == '骑手到店取餐中' || item.status == '商家备餐中'), 'coupon-promo': item.promoType === 'coupon' }">
|
||||
<template v-if="item.promoType === 'plus'">
|
||||
<view class="plus-row">
|
||||
<image class="plus-tag" src="/static/image/shopping/jingdong/plus.png"></image>
|
||||
<text class="promo-text">{{ item.promoText }}</text>
|
||||
</view>
|
||||
<text class="promo-action">解锁权益 <uni-icons type="right" size="10" color="#654629"></uni-icons> </text>
|
||||
</template>
|
||||
<template v-else-if="item.shopType == 'waimai' && (item.status == '骑手到店取餐中' || item.status == '商家备餐中')">
|
||||
<text class="promo-text text-basic">当笔订单返现成功到账,<text style="color: #E31700;">点击领取</text></text>
|
||||
<uni-icons type="right" size="10" color="#1A1A1A"></uni-icons>
|
||||
</template>
|
||||
<template v-else-if="item.promoType === 'coupon'">
|
||||
<view class="coupon-row">
|
||||
<view class="coupon-tag">购物券</view>
|
||||
<text class="promo-text">{{ item.promoText }}</text>
|
||||
</view>
|
||||
<text class="promo-action red">{{ item.promoAction || '去领券' }} <uni-icons type="right" size="10"
|
||||
color="#ED1C04"></uni-icons></text>
|
||||
</template>
|
||||
<template v-else-if="item.promoType === 'text'">
|
||||
<text class="promo-text text-basic">本单可享 <text class="highlight">{{ item.promoHighlight
|
||||
}}</text>,快去支付吧~</text>
|
||||
</template>
|
||||
<template v-else>
|
||||
<text class="promo-text text-basic">当笔订单返现成功到账,<text style="color: #E31700;">点击领取</text></text>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
<!-- Footer -->
|
||||
<view class="footer-actions">
|
||||
<view class="more-box" v-if="item.status == '完成' && item.shopType != 'waimai'">
|
||||
<text class="more-text">更多</text>
|
||||
</view>
|
||||
<view class="empty-space" v-else></view>
|
||||
<view class="action-buttons">
|
||||
<view class="btn" :class="btn.type || 'default'"
|
||||
v-for="(btn, index) in getButtons(item.shopType, item.status, item)" :key="index"
|
||||
@click="$emit('btnClick', btn)">
|
||||
{{ btn.text }}
|
||||
<view class="btn-badge" v-if="btn.badge">{{ btn.badge }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, ref, onMounted, watch, getCurrentInstance } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: () => ({})
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['btnClick', 'longpress']);
|
||||
|
||||
const onLongPress = (e) => {
|
||||
emit('longpress', { event: e, item: props.item });
|
||||
};
|
||||
|
||||
// --- JS 标题截断逻辑开始 ---
|
||||
const instance = getCurrentInstance();
|
||||
const truncatedTitle = ref('');
|
||||
|
||||
const calculateFitTitle = () => {
|
||||
const originalTitle = props.item.products?.[0]?.title || props.item.title || '';
|
||||
if (props.item.shopType === 'waimai') {
|
||||
truncatedTitle.value = originalTitle;
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
const query = uni.createSelectorQuery().in(instance);
|
||||
// 测量所在的容器宽度
|
||||
query.select('.product-info').boundingClientRect(res => {
|
||||
if (res && res.width) {
|
||||
const containerWidth = res.width;
|
||||
const fontSize = uni.upx2px(26); // 26rpx 对应的像素大小
|
||||
|
||||
let currentWidth = 0;
|
||||
let cutIndex = 0;
|
||||
let found = false;
|
||||
|
||||
for (let i = 0; i < originalTitle.length; i++) {
|
||||
const char = originalTitle[i];
|
||||
const charCode = char.charCodeAt(0);
|
||||
let weight = 1;
|
||||
|
||||
if (charCode <= 255) {
|
||||
if (/[A-Z]/.test(char)) weight = 0.7;
|
||||
else if (/[a-z]/.test(char)) weight = 0.5;
|
||||
else if (/[0-9]/.test(char)) weight = 0.55;
|
||||
else if (char === ' ') weight = 0.25;
|
||||
else weight = 0.5;
|
||||
}
|
||||
|
||||
currentWidth += weight * fontSize;
|
||||
|
||||
if (currentWidth > containerWidth - uni.upx2px(4)) {
|
||||
cutIndex = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
truncatedTitle.value = found ? originalTitle.slice(0, cutIndex - 1) : originalTitle;
|
||||
} else {
|
||||
truncatedTitle.value = originalTitle;
|
||||
}
|
||||
}).exec();
|
||||
}, 200);
|
||||
};
|
||||
|
||||
onMounted(calculateFitTitle);
|
||||
watch(() => props.item, calculateFitTitle, { deep: true, immediate: true });
|
||||
// --- JS 标题截断逻辑结束 ---
|
||||
|
||||
const formatWaimaiStatusDesc = (desc) => {
|
||||
if (!desc || !desc.includes(':')) return desc;
|
||||
const parts = desc.split(':');
|
||||
if (parts.length === 2) {
|
||||
const m = parseInt(parts[0]) || 0;
|
||||
const s = parseInt(parts[1]) || 0;
|
||||
if (m > 0) {
|
||||
return `${m}分钟`;
|
||||
} else {
|
||||
return `${s}秒`;
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
const formatStatusDesc = (desc) => {
|
||||
if (!desc || !desc.includes(' : ')) return desc;
|
||||
const parts = desc.split(' : ');
|
||||
if (parts.length >= 2) {
|
||||
return `${parts[0]}时${parts[1]}分`;
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
|
||||
const safeFormatPrice = (item) => {
|
||||
const val = item.price || (item.products && item.products[0] && item.products[0].price);
|
||||
const num = Number(val);
|
||||
return isNaN(num) ? '0.00' : num.toFixed(2);
|
||||
};
|
||||
|
||||
const getButtons = (shopType, status, item) => {
|
||||
const buttons = [];
|
||||
if (status == '等待付款') {
|
||||
buttons.push({ text: '取消订单', type: 'default' });
|
||||
buttons.push({ text: '查看发票', type: 'default' });
|
||||
buttons.push({ text: '修改订单', type: 'default' });
|
||||
buttons.push({ text: '去支付', type: 'primary' });
|
||||
}
|
||||
if (shopType == 'waimai') {
|
||||
|
||||
if (status == '骑手到店取餐中') {
|
||||
buttons.push({ text: '申请退款', type: 'default' });
|
||||
buttons.push({ text: '查看发票', type: 'default' });
|
||||
}
|
||||
if (status == '商家备餐中') {
|
||||
buttons.push({ text: '申请退款', type: 'default' });
|
||||
buttons.push({ text: '查看发票', type: 'default' });
|
||||
}
|
||||
if (status == '完成') {
|
||||
buttons.push({ text: '删除订单', type: 'default' });
|
||||
buttons.push({ text: '查看发票', type: 'default' });
|
||||
buttons.push({ text: '退换/售后', type: 'default' });
|
||||
buttons.push({ text: '再次购买', type: 'primary' });
|
||||
}
|
||||
if (status == '已取消') {
|
||||
buttons.push({ text: '删除订单', type: 'default' });
|
||||
buttons.push({ text: '钱款去向', type: 'default' });
|
||||
buttons.push({ text: '再次购买', type: 'primary' });
|
||||
}
|
||||
} else if (shopType != 'waimai') {
|
||||
if (status == '正在出库') {
|
||||
buttons.push({ text: '查看发票', type: 'default' });
|
||||
buttons.push({ text: '再次购买', type: 'default' });
|
||||
buttons.push({ text: '申请退款', type: 'default' });
|
||||
buttons.push({ text: '修改订单', type: 'default' });
|
||||
}
|
||||
if (status == '完成') {
|
||||
if (item?.trackingTitle == '已签收') {
|
||||
buttons.push({ text: '卖了换钱', type: 'default' });
|
||||
buttons.push({ text: '退还/售后', type: 'default' });
|
||||
buttons.push({ text: '再次购买', type: 'primary' });
|
||||
} else {
|
||||
buttons.push({ text: '再次购买', type: 'default' });
|
||||
buttons.push({ text: '申请退款', type: 'default' });
|
||||
buttons.push({ text: '修改订单', type: 'default' });
|
||||
}
|
||||
}
|
||||
if (status == '已取消') {
|
||||
buttons.push({ text: '再次购买', type: 'default' });
|
||||
buttons.push({ text: '申请退款', type: 'default' });
|
||||
buttons.push({ text: '修改订单', type: 'primary' });
|
||||
}
|
||||
}
|
||||
console.log(shopType, status);
|
||||
return buttons;
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@import "/common/main.css";
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
.shopping-card {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 24rpx;
|
||||
padding: 34rpx 18rpx 30rpx;
|
||||
margin: 0 0 16rpx 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.shop-info {
|
||||
flex: 1;
|
||||
width: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.tag {
|
||||
font-size: 20rpx;
|
||||
padding: 2rpx 6rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 8rpx;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
line-height: 26rpx;
|
||||
flex-shrink: 0;
|
||||
|
||||
&.self-tag {
|
||||
background-color: #FC3538;
|
||||
}
|
||||
|
||||
&.waimai-tag {
|
||||
background-color: #FEE74B;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
}
|
||||
|
||||
.jd-tag {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.shop-name {
|
||||
white-space: nowrap;
|
||||
font-size: 26rpx;
|
||||
line-height: 28rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 700;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
margin-right: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-status {
|
||||
flex-shrink: 0;
|
||||
font-size: 26rpx;
|
||||
|
||||
.waimai-status-warning {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 32rpx;
|
||||
border: 2rpx solid #ED1C04;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.w-badge {
|
||||
background-color: #ED1C04;
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
height: 100%;
|
||||
line-height: 32rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.w-time {
|
||||
color: #ED1C04;
|
||||
font-size: 20rpx;
|
||||
line-height: 32rpx;
|
||||
padding: 0 10rpx;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #FEE4E5;
|
||||
border-radius: 24rpx;
|
||||
height: 30rpx;
|
||||
padding-right: 8rpx;
|
||||
|
||||
.status-badge {
|
||||
background-color: #E40C24;
|
||||
color: #FFFFFF;
|
||||
font-size: 22rpx;
|
||||
padding: 0 12rpx;
|
||||
height: 32rpx;
|
||||
line-height: 32rpx;
|
||||
border-radius: 16rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.status-desc {
|
||||
font-size: 22rpx;
|
||||
line-height: 24rpx;
|
||||
margin-left: 4rpx;
|
||||
color: #ED1C04;
|
||||
}
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 22rpx;
|
||||
color: #87868E;
|
||||
|
||||
&.red {
|
||||
color: #ED1C04;
|
||||
}
|
||||
|
||||
&.gray {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
&.black {
|
||||
color: #1A1A1A;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tracking-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: #F9F9F9;
|
||||
padding: 12rpx 20rpx 18rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&.waimai-tracking {
|
||||
align-items: flex-start;
|
||||
background-color: #F7F8FC;
|
||||
border-radius: 12rpx;
|
||||
padding: 12rpx 20rpx 18rpx;
|
||||
|
||||
.waimai-tracking-icon {
|
||||
margin-right: 10rpx;
|
||||
margin-top: 2rpx;
|
||||
}
|
||||
|
||||
.tracking-main-title {
|
||||
font-size: 26rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 700;
|
||||
line-height: 36rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.tracking-desc {
|
||||
margin-top: 0;
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #1A1A1A;
|
||||
margin-left: -42rpx;
|
||||
}
|
||||
|
||||
.tracking-time {
|
||||
margin-left: -42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tracking-content {
|
||||
flex: 1;
|
||||
|
||||
.tracking-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 32rpx;
|
||||
margin-bottom: 14rpx;
|
||||
|
||||
.truck-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.tracking-title {
|
||||
font-size: 26rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.tracking-desc {
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #1A1A1A;
|
||||
display: block;
|
||||
|
||||
}
|
||||
|
||||
.tracking-time {
|
||||
margin-top: 12rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #767676;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.right-icon {}
|
||||
}
|
||||
|
||||
.product-box {
|
||||
display: flex;
|
||||
margin-bottom: 24rpx;
|
||||
align-items: center;
|
||||
|
||||
&.multiple {
|
||||
.product-images-scroll {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
white-space: nowrap;
|
||||
|
||||
.product-img {
|
||||
display: inline-block;
|
||||
width: 132rpx;
|
||||
height: 132rpx;
|
||||
margin-right: 14rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
}
|
||||
|
||||
.product-price-box {
|
||||
margin-left: 10rpx;
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.product-img {
|
||||
width: 144rpx;
|
||||
height: 144rpx;
|
||||
border-radius: 12rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 14rpx;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 20rpx;
|
||||
|
||||
.product-title {
|
||||
font-size: 26rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 36rpx;
|
||||
// white-space: nowrap;
|
||||
text-overflow: clip;
|
||||
overflow: hidden;
|
||||
|
||||
&.shopping-title {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.product-desc {
|
||||
font-size: 22rpx;
|
||||
line-height: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
color: #87868E;
|
||||
overflow: hidden;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
line-clamp: 2;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.product-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 8rpx;
|
||||
|
||||
.tag {
|
||||
font-size: 20rpx;
|
||||
line-height: 20rpx;
|
||||
color: #C59446;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-price-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
margin-left: 20rpx;
|
||||
|
||||
.price-wrap {
|
||||
color: #1A1A1A;
|
||||
font-size: 30rpx;
|
||||
margin-bottom: 4rpx;
|
||||
line-height: 36rpx;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.price-symbol {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.price-num {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.product-count {
|
||||
font-size: 22rpx;
|
||||
color: #87868E;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.promo-box {
|
||||
background-color: #FEEFF2;
|
||||
padding: 14rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-bottom: 24rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
|
||||
&.plus-promo,
|
||||
&.cashback-promo,
|
||||
&.coupon-promo {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 52rpx;
|
||||
padding: 0 16rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
&.plus-promo {
|
||||
background-color: #FFEDDF;
|
||||
|
||||
.plus-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.plus-tag {
|
||||
width: 56rpx;
|
||||
height: 26rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.promo-text {
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #654629;
|
||||
}
|
||||
}
|
||||
|
||||
.promo-action {
|
||||
font-size: 22rpx;
|
||||
color: #A3824E;
|
||||
}
|
||||
}
|
||||
|
||||
&.cashback-promo,
|
||||
&.coupon-promo {
|
||||
background-color: #FCF5F5;
|
||||
|
||||
.promo-text {
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #1A1A1A;
|
||||
|
||||
.highlight {
|
||||
color: #ED1C04;
|
||||
}
|
||||
}
|
||||
|
||||
.promo-action {
|
||||
font-size: 22rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&.red {
|
||||
color: #ED1C04;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.coupon-promo {
|
||||
.coupon-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.coupon-tag {
|
||||
font-size: 20rpx;
|
||||
background-color: #ED1C04;
|
||||
color: #FFFFFF;
|
||||
padding: 2rpx 8rpx;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.text-basic {
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #1A1A1A;
|
||||
display: block;
|
||||
|
||||
.highlight {
|
||||
font-size: 22rpx;
|
||||
line-height: 22rpx;
|
||||
color: #E31700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.more-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.more-text {
|
||||
white-space: nowrap;
|
||||
font-size: 22rpx;
|
||||
color: #87868E;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-space {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
position: relative;
|
||||
z-index: 998;
|
||||
|
||||
.btn {
|
||||
position: relative;
|
||||
// z-index: 998;
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
padding: 0 24rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 22rpx;
|
||||
margin-left: 16rpx;
|
||||
border: 0.5px solid #C7C7C7;
|
||||
color: #1A1A1A;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
&.primary {
|
||||
border-color: #ED1C04;
|
||||
color: #ED1C04;
|
||||
}
|
||||
|
||||
.btn-badge {
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -1px;
|
||||
background-image: url(/static/image/shopping/jingdong/bubble.png);
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
color: #FFFFFF;
|
||||
font-size: 10px;
|
||||
line-height: 11px;
|
||||
padding: 2px 4px 0;
|
||||
white-space: nowrap;
|
||||
width: 45px;
|
||||
height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
<image v-else class="colse" src="/static/image/watermarkColseDark.png" mode=""></image> -->
|
||||
<image class="watermarkImg" src="/static/image/watermark.png" mode=""></image>
|
||||
<image class="colse" src="/static/image/watermarkColse.png" mode=""
|
||||
@click="$goRechargePage('watermark_close')"></image>
|
||||
@click="$goRechargePage('watermark_close', source)"></image>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
|
@ -19,6 +19,10 @@ export default {
|
|||
dark: {
|
||||
type: String,
|
||||
default: 'light'
|
||||
},
|
||||
source: {
|
||||
type: String,
|
||||
default: 'uni_alipay_other'
|
||||
}
|
||||
},
|
||||
name: "watermark",
|
||||
|
|
@ -56,7 +60,7 @@ export default {
|
|||
justify-content: center;
|
||||
z-index: 99 !important;
|
||||
background-image: url('/static/image/watermarkBG.png');
|
||||
background-size: 125px 125px;
|
||||
background-size: 500rpx 500rpx;
|
||||
|
||||
.watermarkBox {
|
||||
width: 200px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
## 自定义水印添加
|
||||
***
|
||||
一款声明版权立场的组件
|
||||
该组件参考了 [315500033@qq.com](https://ext.dcloud.net.cn/plugin?id=362) 大神的组件 修改后符合自己的编码习惯 让水印有更多的展示方式
|
||||
|
||||
### 使用方式
|
||||
#### 在 ``script`` 中引入组件:
|
||||
```javascript
|
||||
import wmWatermark from '../../components/wm-watermark.vue';
|
||||
export default {
|
||||
components: {wmWatermark}
|
||||
}
|
||||
```
|
||||
|
||||
#### 在 ``template`` 中使用组件:
|
||||
|
||||
```html
|
||||
<wm-watermark text="这是水印信息"></wm-watermark>
|
||||
```
|
||||
|
||||
### **属性说明**
|
||||
|
||||
| 属性 | 类型 | 默认值 | 说明 |
|
||||
| :---: | :---: | :---: | :--------: |
|
||||
| text | String | 无 | 设置水印文字 注:(文字优先图片) |
|
||||
| imgUrl | String | 无 | 设置水印图片链接 注:(文字优先图片) |
|
||||
| opacity | Number,String | 0.6 | 设置显示透明度 |
|
||||
| num | Number | 20 | 设置水印数量 |
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view class="watermark">
|
||||
<block v-for="(item,index) in num" :key="index">
|
||||
<view class="watermark-text" v-if="text != ''" :style="{opacity:opacity}">{{text}}</view>
|
||||
<image class="watermark-img" :src="imgUrl" mode="aspectFill" v-if="imgUrl !='' && text ==''" :style="{opacity:opacity}"></image>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name:'wm-watermark',
|
||||
props:{
|
||||
text:{ //设置水印文字
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
imgUrl:{ //设置水印图片
|
||||
type:String,
|
||||
default:''
|
||||
},
|
||||
opacity:{ //设置透明度
|
||||
type:[Number,String],
|
||||
default:0.6
|
||||
},
|
||||
num:{ //设置水印数量
|
||||
type:Number,
|
||||
default:30
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.watermark{
|
||||
position: fixed;
|
||||
width: 1200upx;
|
||||
height: 100%;
|
||||
top:0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
pointer-events: none;
|
||||
z-index: 9999999;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
transform: rotate(-33deg) translateX(-20px);
|
||||
.watermark-text{
|
||||
width: 350upx;
|
||||
height: 80upx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
// color: red;
|
||||
color: rgba(0,0,0,0.1);
|
||||
font-size: 18upx;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.watermark-img{
|
||||
width: 375upx;
|
||||
height: 375upx;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Binary file not shown.
74
main.js
74
main.js
|
|
@ -16,19 +16,77 @@ app.$mount()
|
|||
import {
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
import {
|
||||
store,
|
||||
useStore
|
||||
} from './store'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
// 从缓存读取系统信息(已在App.vue中获取)
|
||||
app.config.globalProperties.$pageData = pageData
|
||||
const systemInfo = uni.getStorageSync('systemInfo') || {}
|
||||
let systemInfo = uni.getStorageSync('systemInfo') || {}
|
||||
if (!systemInfo.platform) {
|
||||
systemInfo = uni.getSystemInfoSync() || {}
|
||||
}
|
||||
const windowInfo = uni.getWindowInfo();
|
||||
app.config.globalProperties.$store = {
|
||||
state: {
|
||||
safeBottom: windowInfo.safeAreaInsets?.bottom || 0,
|
||||
safeBottomAz: 0
|
||||
}
|
||||
}
|
||||
app.config.globalProperties.$system = systemInfo.platform == 'ios' ? 'iOS' : 'Android'
|
||||
app.config.globalProperties.$systemInfo = systemInfo
|
||||
uni.setStorageSync('version', '1.0.2.sp4')
|
||||
app.config.globalProperties.$version = uni.getStorageSync('version')
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
app.config.globalProperties.$system = plus.os.name;
|
||||
// #endif
|
||||
app.config.globalProperties.$systemInfo = systemInfo;
|
||||
uni.setStorageSync('version', '1.0.7.sp6');
|
||||
app.config.globalProperties.$version = uni.getStorageSync('version');
|
||||
// 环境:development→测试,production→正式(跟构建环境走,无需手改)
|
||||
const isTest = process.env.NODE_ENV === 'development';
|
||||
app.config.globalProperties.$isTest = isTest;
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
const version = plus.runtime.version;
|
||||
// #endif
|
||||
|
||||
const compareVersion = (v1, v2) => {
|
||||
const a = String(v1).split('.')
|
||||
const b = String(v2).split('.')
|
||||
const len = Math.max(a.length, b.length)
|
||||
for (let i = 0; i < len; i++) {
|
||||
const n1 = parseInt(a[i] || '0', 10)
|
||||
const n2 = parseInt(b[i] || '0', 10)
|
||||
if (n1 > n2) return 1
|
||||
if (n1 < n2) return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//安卓和ios
|
||||
// #ifdef APP-PLUS && !APP-HARMONY
|
||||
if (plus.os.name == 'iOS') {
|
||||
if (compareVersion(version, '1.9') >= 0 && !isTest) {
|
||||
uni.setStorageSync('isTest', false)
|
||||
} else {
|
||||
uni.setStorageSync('isTest', true)
|
||||
}
|
||||
} else {
|
||||
if (compareVersion(version, '2.2.0') >= 0 && !isTest) {
|
||||
uni.setStorageSync('isTest', false)
|
||||
} else {
|
||||
uni.setStorageSync('isTest', true)
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
//鸿蒙
|
||||
// #ifdef APP-PLUS && APP-HARMONY
|
||||
if (compareVersion(version, '2.1.7') >= 0&&!isTest) {
|
||||
uni.setStorageSync('isTest', false)
|
||||
} else {
|
||||
uni.setStorageSync('isTest', true)
|
||||
}
|
||||
// #endif
|
||||
//h5环境
|
||||
// #ifndef APP-PLUS
|
||||
uni.setStorageSync('isTest', true)
|
||||
// #endif
|
||||
|
||||
|
||||
app.use(globalMethods);
|
||||
return {
|
||||
|
|
|
|||
142
manifest.json
142
manifest.json
|
|
@ -1,37 +1,64 @@
|
|||
{
|
||||
"name": "alipay-emulator",
|
||||
"appid": "__UNI__D535736",
|
||||
"description": "",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": 100,
|
||||
"transformPx": false,
|
||||
"name" : "alipay-emulator",
|
||||
"appid" : "__UNI__D535736",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : 100,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus": {
|
||||
"darkmode": false,
|
||||
"usingComponents": true,
|
||||
"nvueStyleCompiler": "uni-app",
|
||||
"compilerVersion": 3,
|
||||
"splashscreen": {
|
||||
"alwaysShowBeforeRender": true,
|
||||
"waiting": true,
|
||||
"autoclose": true,
|
||||
"delay": 0
|
||||
"app-harmony" : {
|
||||
"distribute" : {
|
||||
"splashScreens" : {
|
||||
"startWindowIcon" : "resource/icon.png", // 启动页图标路径
|
||||
"startWindowBackground" : "#123456" // 启动页背景颜色
|
||||
},
|
||||
"optimization": {
|
||||
"subPackages": true
|
||||
"bundleName" : "cn.zuom8.jsloction",
|
||||
"signingConfigs" : {
|
||||
"default" : {
|
||||
"certpath" : "C:\\Users\\Administrator\\Desktop\\jisuloca\\test\\debug.cer",
|
||||
"keyAlias" : "__uni__1be0b2f",
|
||||
"keyPassword" : "000000189B31358AF1B1A6FD1CB2D1011E32DF02389A1F92604ECEB091A66654CDCDF6DB4DD18BC3",
|
||||
"profile" : "C:\\Users\\Administrator\\Desktop\\jisuloca\\test\\jsloction_debugDebug.p7b",
|
||||
"signAlg" : "SHA256withECDSA",
|
||||
"storeFile" : "C:\\Users\\Administrator\\Desktop\\jisuloca\\hmos.p12",
|
||||
"storePassword" : "000000185660236954705CE2E46C7A2FA76565A93989A8DDD5810CC2760ED8D2B479EDD9C488B982"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"runmode": "liberate", // 开启分包优化后,必须配置资源释放模式
|
||||
"app-plus" : {
|
||||
"darkmode" : false,
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : false,
|
||||
"delay" : 0
|
||||
},
|
||||
|
||||
"compatible" : {
|
||||
"runtimeVersion": "4.75",
|
||||
"compilerVersion": "5.14",
|
||||
"ignoreVersion" : true
|
||||
},
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
},
|
||||
"runmode" : "liberate", // 开启分包优化后,必须配置资源释放模式
|
||||
|
||||
/* 模块配置 */
|
||||
"modules": {
|
||||
"Camera": {},
|
||||
"Payment": {},
|
||||
"LivePusher": {}
|
||||
"modules" : {
|
||||
"Camera" : {},
|
||||
"Payment" : {},
|
||||
"LivePusher" : {}
|
||||
},
|
||||
/* 应用发布信息 */
|
||||
"distribute": {
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android": {
|
||||
"permissions": [
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
|
|
@ -50,52 +77,51 @@
|
|||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios": {
|
||||
"dSYMs": false
|
||||
"ios" : {
|
||||
"dSYMs" : false
|
||||
},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs": {
|
||||
"payment": {
|
||||
"weixin": {
|
||||
"__platform__": [
|
||||
"ios",
|
||||
"android"
|
||||
],
|
||||
"appid": "123456",
|
||||
"UniversalLinks": "https://hhhhh.com/apple-app-site-association/"
|
||||
"sdkConfigs" : {
|
||||
"payment" : {
|
||||
"weixin" : {
|
||||
"__platform__" : [ "ios", "android" ],
|
||||
"appid" : "123456",
|
||||
"UniversalLinks" : "https://hhhhh.com/apple-app-site-association/"
|
||||
},
|
||||
"alipay": {
|
||||
"__platform__": [
|
||||
"ios",
|
||||
"android"
|
||||
]
|
||||
"alipay" : {
|
||||
"__platform__" : [ "ios", "android" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"nvueLaunchMode": ""
|
||||
"nvueLaunchMode" : ""
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp": {},
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin": {
|
||||
"appid": "",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
},
|
||||
"usingComponents": true
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay": {
|
||||
"usingComponents": true
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu": {
|
||||
"usingComponents": true
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao": {
|
||||
"usingComponents": true
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion": "3"
|
||||
"vueVersion" : "3",
|
||||
"h5" : {
|
||||
"router" : {
|
||||
"mode" : "history"
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
|
|
@ -16,5 +16,25 @@
|
|||
"前端组件",
|
||||
"通用组件"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@batiao/batiao-sdk-uniapp-unimp": "1.0.374",
|
||||
"crypto-js": "^4.2.0",
|
||||
"lottie-web": "^5.13.0",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,vue}": [
|
||||
"eslint"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-vue": "^9.33.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "husky"
|
||||
}
|
||||
}
|
||||
374
pages.json
374
pages.json
|
|
@ -10,6 +10,150 @@
|
|||
}
|
||||
],
|
||||
"subPackages": [
|
||||
{
|
||||
"root": "pages/call-log",
|
||||
"pages": [
|
||||
{
|
||||
"path": "call",
|
||||
"style": {
|
||||
"navigationBarTitleText": "通话记录页面",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "detail/callDetail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "通话记录详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/message",
|
||||
"pages": [
|
||||
{
|
||||
"path": "list-index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "短信列表首页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "chat-page/chat-page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "短信聊天页面",
|
||||
"navigationStyle": "custom",
|
||||
"app-plus": {
|
||||
"softinputMode": "adjustResize"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/shopping",
|
||||
"pages": [
|
||||
{
|
||||
"path": "index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "购物app首页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "jingdong/list-index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "京东列表首页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "jingdong/order-detail/order-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "jingdong/add-order/add-order",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加订单",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "jingdong/add-waimai/add-waimai",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加外卖订单页面",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "jingdong/waimai-order-detail/waimai-order-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "外卖订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "taobao/list-index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "淘宝购物外卖订单列表",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "taobao/shopping-order-detail/shopping-order-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "淘宝购物详情页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "taobao/add-shopping-order/add-shopping-order",
|
||||
"style": {
|
||||
"navigationBarTitleText": "新增淘宝购物订单",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "taobao/shangou-order-detail/shangou-order-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "淘宝闪购订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "taobao/add-shangou-order/add-shangou-order",
|
||||
"style": {
|
||||
"navigationBarTitleText": "添加淘宝闪购订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pdd/list-index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "拼多多购物列表",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pdd/order-detail/order-detail",
|
||||
"style": {
|
||||
"navigationBarTitleText": "拼多多订单详情",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pdd/add-order/add-order",
|
||||
"style": {
|
||||
"navigationBarTitleText": "pdd添加修改订单信息",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"root": "pages/balance",
|
||||
"pages": [
|
||||
|
|
@ -27,6 +171,27 @@
|
|||
"navigationBarTitleText": "快速入口页面",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "transfer/transfer",
|
||||
"style": {
|
||||
"navigationBarTitleText": "转账模拟",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pay-successful/pay-successful",
|
||||
"style": {
|
||||
"navigationBarTitleText": "支付成功",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pay-successful/edit",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改支付成功",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -170,6 +335,197 @@
|
|||
"navigationStyle": "custom",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "card/card",
|
||||
"style": {
|
||||
"navigationBarTitleText": "身份证",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "qf-image/qf-image",
|
||||
"style": {
|
||||
"navigationBarTitleText": "图片裁剪",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "train-tickets/ctrip-train-tickets/ctrip-train-tickets",
|
||||
"style": {
|
||||
"navigationBarTitleText": "携程火车票",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "train-tickets/qunar-train-tickets/qunar-train-tickets",
|
||||
"style": {
|
||||
"navigationBarTitleText": "去哪儿火车票",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "train-tickets/fliggy-train-tickets/fliggy-train-tickets",
|
||||
"style": {
|
||||
"navigationBarTitleText": "飞猪火车票",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "ranking/ranking",
|
||||
"style": {
|
||||
"navigationBarTitleText": "从夯倒拉排名",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "certificate/graduate",
|
||||
"style": {
|
||||
"navigationBarTitleText": "证书",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "silkBanner/silkBanner",
|
||||
"style": {
|
||||
"navigationBarTitleText": "锦旗",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "certificate/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "证书",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "about-this-iphone/about-this-iphone",
|
||||
"style": {
|
||||
"navigationBarTitleText": "苹果关于本机",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bank/zsyh",
|
||||
"style": {
|
||||
"navigationBarTitleText": "招商银行",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bank/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "选择银行卡",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bank/gsyh",
|
||||
"style": {
|
||||
"navigationBarTitleText": "工商银行",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bank/nyyh",
|
||||
"style": {
|
||||
"navigationBarTitleText": "农业银行",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "bank/jsyh",
|
||||
"style": {
|
||||
"navigationBarTitleText": "建设银行",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "game/honor-of-kings",
|
||||
"style": {
|
||||
"navigationBarTitleText": "王者荣耀",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "game/sanjiaozhou",
|
||||
"style": {
|
||||
"navigationBarTitleText": "三角洲",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "game/hepingjingying",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "和平精英",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "game/wuweiqiyue",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "无畏契约",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "game/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "游戏首页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "wx-payment-success/wx-payment-success",
|
||||
"style": {
|
||||
"navigationBarTitleText": "微信支付成功",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "高考分数",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/center",
|
||||
"style": {
|
||||
"navigationBarTitleText": "查询中心",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/chongqing",
|
||||
"style": {
|
||||
"navigationBarTitleText": "重庆",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/hebei",
|
||||
"style": {
|
||||
"navigationBarTitleText": "河北",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "score/guandong",
|
||||
"style": {
|
||||
"navigationBarTitleText": "广东",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "video-chat/video-chat",
|
||||
"style": {
|
||||
"navigationBarTitleText": "视频单聊",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -203,6 +559,20 @@
|
|||
"navigationBarTitleText": "充值页",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "call-and-message-entry/call-and-message-entry",
|
||||
"style": {
|
||||
"navigationBarTitleText": "呼叫和短信入口",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "shipinjiaocheng/shipinjiaocheng",
|
||||
"style": {
|
||||
"navigationBarTitleText": "视频教程",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -216,7 +586,9 @@
|
|||
"pages/common",
|
||||
"pages/finance-management",
|
||||
"pages/ant-credit-pay",
|
||||
"pages/other"
|
||||
"pages/other",
|
||||
"pages/message",
|
||||
"pages/call-log"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,21 +1,22 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark :dark="data.dark" source="uni_alipay_huabei" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_huabei')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="page-container">
|
||||
<view class="main-container">
|
||||
<NavBar v-if="!selectedImage" title="花呗" :bgColor="data.navBar.bgColor" tipLayerType="huabei-tip" isTipLayer
|
||||
tipLayerText="修改花呗信息" :buttonGroup="buttonGroup" @button-click="clickTitlePopupButton">
|
||||
<NavBar ref="navBarRef" v-if="!selectedImage" title="花呗" :bgColor="data.navBar.bgColor"
|
||||
tipLayerType="huabei-tip" isTipLayer tipLayerText="修改花呗信息" :buttonGroup="buttonGroup"
|
||||
@button-click="clickTitlePopupButton">
|
||||
<!-- 使用作用域插槽自定义按钮渲染,特别是switch的checked绑定 -->
|
||||
<template #button="{ button }">
|
||||
<view class="button flex-align-center flex-justify-center">
|
||||
{{ button.name }}
|
||||
<view @tap.stop>
|
||||
<switch v-if="button.isSwitch" :checked="data.huabeiInfo.isOverdue" @change="button.click"
|
||||
<switch v-if="button.isSwitch" :checked="data.huabeiInfo[button.key]" @change="button.click"
|
||||
style="transform: scale(0.7);"></switch>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -44,11 +45,13 @@
|
|||
<view v-if="huabeiInfo.styleType == 1" class="current-month">{{ huabeiInfo.mouth }}月应还(元)</view>
|
||||
<view v-else class="current-month">{{ huabeiInfo.mouth }}月账单累计中(元)</view>
|
||||
<view class="money-box flex-align-center">
|
||||
<text class="money alipay-font">{{ numberUtil.formatMoneyWithThousand(huabeiInfo.money) }}</text>
|
||||
<text class="money alipay-font" style="font-size: 48rpx;" v-if="data.huabeiInfo.isPayOff">已还清</text>
|
||||
<text class="money alipay-font" v-else>{{ numberUtil.formatMoneyWithThousand(huabeiInfo.money) }}</text>
|
||||
<uni-icons type="right" size="18" color="#B9D6FF"></uni-icons>
|
||||
</view>
|
||||
<!-- 样式一 按钮样式 -->
|
||||
<view v-if="huabeiInfo.styleType == 1 || !huabeiInfo.styleType" class="style-1 button-group">
|
||||
<view v-if="(huabeiInfo.styleType == 1 || !huabeiInfo.styleType) && !huabeiInfo.isPayOff"
|
||||
class="style-1 button-group">
|
||||
<view class="button-item second-button" :class="{ 'ios-button': $system == 'iOS' }">立即还款</view>
|
||||
<view v-if="!huabeiInfo.isInstallment" class="button-item primary-button"
|
||||
:class="{ 'ios-button': $system == 'iOS' }">
|
||||
|
|
@ -58,17 +61,20 @@
|
|||
</view>
|
||||
</view>
|
||||
<!-- 样式二 纯气泡样式 -->
|
||||
<view v-if="huabeiInfo.styleType == 2" class="style-2 bubble-container">
|
||||
<view v-if="(huabeiInfo.styleType == 2) && !huabeiInfo.isPayOff" class="style-2 bubble-container">
|
||||
<view class="bubble-box">
|
||||
<view class="arrow"></view>
|
||||
<text class="text">{{ huabeiInfo.descText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 样式三 气泡带箭头样式 -->
|
||||
<view v-if="huabeiInfo.styleType == 3" class="style-3 bubble-container">
|
||||
<view v-if="huabeiInfo.styleType == 3 || huabeiInfo.isPayOff" class="style-3 bubble-container">
|
||||
<view class="bubble-box">
|
||||
<view class="arrow"></view>
|
||||
<text class="text flex-align-center">{{ huabeiInfo.descText }}
|
||||
<text class="text flex-align-center">
|
||||
<text style="line-height: 18px;">{{ huabeiInfo.isPayOff ? huabeiInfo.showDescText :
|
||||
huabeiInfo.descText
|
||||
}}</text>
|
||||
<uni-icons type="right" size="18" color="#B9D6FF"></uni-icons>
|
||||
</text>
|
||||
</view>
|
||||
|
|
@ -81,6 +87,7 @@
|
|||
<view class="info-item">
|
||||
<view class="label">总计额度</view>
|
||||
<view class="value">{{
|
||||
huabeiInfo.isPayOff ? numberUtil.formatMoneyWithThousand(Number(huabeiInfo.totalAmount)) :
|
||||
numberUtil.formatMoneyWithThousand(Number(huabeiInfo.totalAmount) - Number(huabeiInfo.money))
|
||||
}}可用
|
||||
</view>
|
||||
|
|
@ -111,6 +118,7 @@
|
|||
</view>
|
||||
<canvas canvas-id="crop-canvas"
|
||||
style="position: fixed; left: -9999px; width: 750rpx; height: 100vh; pointer-events: none;"></canvas>
|
||||
<ZdySafeBottom bgColor="#fff"/>
|
||||
<!-- 编辑弹窗 -->
|
||||
<uni-popup ref="popup" type="center" :mask-click="false">
|
||||
<view class="popup-content">
|
||||
|
|
@ -183,6 +191,7 @@
|
|||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar'
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
import {
|
||||
numberUtil,
|
||||
util
|
||||
|
|
@ -201,6 +210,8 @@ import {
|
|||
const instance = getCurrentInstance();
|
||||
const { proxy } = instance;
|
||||
|
||||
const navBarRef = ref(null)
|
||||
|
||||
|
||||
const buttonGroup = [{
|
||||
name: "编辑花呗数据",
|
||||
|
|
@ -221,6 +232,7 @@ const buttonGroup = [{
|
|||
}, {
|
||||
name: "花呗逾期",
|
||||
isSwitch: true,
|
||||
key: 'isOverdue',
|
||||
click: () => {
|
||||
data.huabeiInfo.isOverdue = !data.huabeiInfo.isOverdue
|
||||
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
|
||||
|
|
@ -229,6 +241,20 @@ const buttonGroup = [{
|
|||
url: '/pages/ant-credit-pay/overdue-payment/overdue-payment'
|
||||
})
|
||||
}
|
||||
navBarRef.value.closeTopPopup()
|
||||
}
|
||||
}, {
|
||||
name: "还清花呗",
|
||||
isSwitch: true,
|
||||
key: 'isPayOff',
|
||||
click: () => {
|
||||
data.huabeiInfo.isPayOff = !data.huabeiInfo.isPayOff
|
||||
// uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
|
||||
if (data.huabeiInfo.isPayOff) {
|
||||
data.huabeiInfo.showDescText = `${Number(data.huabeiInfo.mouth) + 1}月已累计0.00,查看消费详情报告`
|
||||
}
|
||||
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
|
||||
navBarRef.value.closeTopPopup()
|
||||
}
|
||||
}]
|
||||
|
||||
|
|
@ -316,7 +342,7 @@ onLoad((option) => {
|
|||
})
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
@ -439,7 +465,9 @@ const confirmImage = () => {
|
|||
data.huabeiInfo.image = saveRes.savedFilePath
|
||||
selectedImage.value = '' // 隐藏编辑模式
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
// #endif
|
||||
}, 200)
|
||||
// 保存到缓存
|
||||
uni.setStorageSync(data.huabeiInfoStorageKey, data.huabeiInfo)
|
||||
|
|
@ -500,7 +528,9 @@ const chooseImage = () => {
|
|||
selectedImage.value = res.tempFilePaths[0]
|
||||
data.showMask = true
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
// #endif
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
|
|
@ -537,7 +567,9 @@ const handleTouchEnd = () => {
|
|||
const closeImage = () => {
|
||||
selectedImage.value = ''
|
||||
data.showMask = false
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
// #endif
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -704,7 +736,7 @@ const goBack = () => {
|
|||
justify-content: center;
|
||||
|
||||
.text {
|
||||
color: #ffffff;
|
||||
color: #B9D6FF;
|
||||
font-size: 26rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
|
@ -738,7 +770,7 @@ const goBack = () => {
|
|||
}
|
||||
|
||||
.value {
|
||||
color: #ffffff;
|
||||
color: #B9D6FF;
|
||||
font-size: 26rpx;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<template>
|
||||
<template>
|
||||
|
||||
<view class="page-container">
|
||||
<view class="main-container">
|
||||
|
|
@ -206,9 +206,9 @@
|
|||
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark :dark="data.dark" source="uni_alipay_huabei" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_huabei')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</template>
|
||||
|
|
@ -407,18 +407,22 @@ onPageScroll((e) => {
|
|||
data.navBar.bgColor = '#F6F6F6'
|
||||
data.navBar.textColor = '#1a1a1a'
|
||||
data.isTop = false
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
// #endif
|
||||
} else {
|
||||
// 回到顶部时恢复原色
|
||||
data.navBar.bgColor = '#717E91'
|
||||
data.navBar.textColor = '#fff'
|
||||
data.isTop = true
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
// #endif
|
||||
}
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F6F6F6')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark :dark="data.dark" source="uni_alipay_balance" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_balance')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container" :style="{ height: data.windowHeight + 'px' }">
|
||||
<view class="bg-container"></view>
|
||||
<NavBar class="nav-bar" isRightIcon title="" tipLayerType="balance-tip" isTipLayer tipLayerText="修改余额"
|
||||
<nav-bar class="nav-bar" isRightIcon title="" tipLayerType="balance-tip" isTipLayer tipLayerText="修改余额"
|
||||
:bgColor="data.navBar.bgColor" :buttonGroup="buttonGroup" @button-click="clickTitlePopupButton">
|
||||
<template v-slot:left>
|
||||
<view class="nav-bar-left" @click="util.goBack()">
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<image class="nav-icon" src="/static/image/nav-bar/more-white.png" mode=""></image>
|
||||
</view>
|
||||
</template>
|
||||
</NavBar>
|
||||
</nav-bar>
|
||||
<scroll-view class="scroll-view" :style="{ height: (data.windowHeight - 44 - data.statusBarHeight) + 'px' }"
|
||||
scroll-y="true">
|
||||
<view class="h100 w100 flex-between" style="flex-direction: column;">
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
<scroll-view class="menu-scroll-view" scroll-x="true" @scroll="onMenuScroll"
|
||||
:show-scrollbar="false">
|
||||
<view class="menu-content">
|
||||
<view class="item menu-icon-box" v-for="item in menuList">
|
||||
<view class="item menu-icon-box" v-for="(item, index) in menuList" :key="index" >
|
||||
<image class="menu-icon" :src="`/static/image/balance/menu-icon/${item.label}.png`"
|
||||
mode="">
|
||||
</image>
|
||||
|
|
@ -89,6 +89,8 @@
|
|||
<view class="blue-text">我的客服</view>
|
||||
<view class="footer-text">余额升级服务由支付宝和网商银行提供</view>
|
||||
</view>
|
||||
|
||||
<safeBottom bgColor="#F0F3F8"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
|
|
@ -111,8 +113,10 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar'
|
||||
//import NavBar from '@/components/nav-bar/nav-bar'
|
||||
import BalanceList from '@/components/balance-list/balance-list.vue'
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
import { fastEntranceList } from '@/static/json/initial.json'
|
||||
import {
|
||||
util,
|
||||
|
|
@ -211,7 +215,7 @@ onLoad(async () => {
|
|||
})
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F0F3F8')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
@ -515,11 +519,12 @@ const onMenuScroll = (e) => {
|
|||
}
|
||||
|
||||
.nav-text {
|
||||
font-size: 18px;
|
||||
font-size: 36rpx;
|
||||
margin-right: 4px;
|
||||
color: #FFFFFF;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
::v-deep .uni-navbar__header-btns-left {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
{
|
||||
"randomData": [
|
||||
{
|
||||
"title": "充值满减券",
|
||||
"tag": "特惠充",
|
||||
"desc": "满50元可用",
|
||||
"price": "1",
|
||||
"butText": "去看看",
|
||||
"imgUrl": "/static/image/balance/pay-successful/chongzhi.png"
|
||||
},
|
||||
{
|
||||
"title": "芭芭农场肥料",
|
||||
"tag": "芭芭农场",
|
||||
"desc": "现实翻倍",
|
||||
"price": "",
|
||||
"butText": "去看看",
|
||||
"imgUrl": "/static/image/balance/pay-successful/88nongchang.png"
|
||||
},
|
||||
{
|
||||
"title": "心相印抽纸优惠券",
|
||||
"tag": "分期生活",
|
||||
"desc": "满一元可用",
|
||||
"price": "1",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/xinxiangyin.png"
|
||||
},
|
||||
{
|
||||
"title": "蜜雪冰城全场券",
|
||||
"tag": "外卖福利",
|
||||
"desc": "满10元可用",
|
||||
"price": "3",
|
||||
"butText": "去领取",
|
||||
"imgUrl": "/static/image/balance/pay-successful/mixue.png"
|
||||
},
|
||||
{
|
||||
"title": "充值满减券",
|
||||
"tag": "中国石化",
|
||||
"desc": "满50元可用",
|
||||
"price": "3",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shiyou.png"
|
||||
},
|
||||
{
|
||||
"title": "零售购物券",
|
||||
"tag": "淘宝闪购",
|
||||
"desc": "满29元可用",
|
||||
"price": "8",
|
||||
"butText": "去领取",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shangou.png"
|
||||
},
|
||||
{
|
||||
"title": "公交乘车券",
|
||||
"tag": "公交地铁",
|
||||
"desc": "享3笔0.3乘车优惠",
|
||||
"price": "0.8",
|
||||
"butText": "去看看",
|
||||
"imgUrl": "/static/image/balance/pay-successful/chengche.png"
|
||||
},
|
||||
{
|
||||
"title": "电燃费优惠红包",
|
||||
"tag": "生活缴费",
|
||||
"desc": "缴电燃气费立减",
|
||||
"price": "0.5",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shuidian.png"
|
||||
}
|
||||
],
|
||||
"defaultData": {
|
||||
"user": "小王",
|
||||
"money": "88888.88",
|
||||
"payMethod": "招商银行卡(8888)",
|
||||
"bannerTime": "07月12日12:22",
|
||||
"styleType": "style3",
|
||||
"style1": {
|
||||
"couponlist": [
|
||||
{
|
||||
"title": "充值满减券",
|
||||
"tag": "中国石化",
|
||||
"desc": "满50元可用",
|
||||
"price": "3",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shiyou.png"
|
||||
}
|
||||
],
|
||||
"bannerUrl": "/static/image/balance/transfer/bottom-banner-1.png"
|
||||
},
|
||||
"style2": {
|
||||
"couponlist": [
|
||||
{
|
||||
"title": "蜜雪冰城全场券",
|
||||
"tag": "外卖福利",
|
||||
"desc": "满10元可用",
|
||||
"price": "3",
|
||||
"butText": "去领取",
|
||||
"imgUrl": "/static/image/balance/pay-successful/mixue.png"
|
||||
},
|
||||
{
|
||||
"title": "充值满减券",
|
||||
"tag": "中国石化",
|
||||
"desc": "满50元可用",
|
||||
"price": "3",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shiyou.png"
|
||||
},
|
||||
{
|
||||
"title": "零售购物券",
|
||||
"tag": "淘宝闪购",
|
||||
"desc": "满29元可用",
|
||||
"price": "8",
|
||||
"butText": "去领取",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shangou.png"
|
||||
},
|
||||
{
|
||||
"title": "公交乘车券",
|
||||
"tag": "公交地铁",
|
||||
"desc": "享3笔0.3乘车优惠",
|
||||
"price": "0.8",
|
||||
"butText": "去看看",
|
||||
"imgUrl": "/static/image/balance/pay-successful/chengche.png"
|
||||
}
|
||||
]
|
||||
},
|
||||
"style3": {
|
||||
"couponlist": [
|
||||
{
|
||||
"title": "充值满减券",
|
||||
"tag": "中国石化",
|
||||
"desc": "满50元可用",
|
||||
"price": "3",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/shiyou.png"
|
||||
},
|
||||
{
|
||||
"title": "心相印抽纸优惠券",
|
||||
"tag": "分期生活",
|
||||
"desc": "满一元可用",
|
||||
"price": "1",
|
||||
"butText": "免费领",
|
||||
"imgUrl": "/static/image/balance/pay-successful/xinxiangyin.png"
|
||||
},
|
||||
{
|
||||
"title": "蜜雪冰城全场券",
|
||||
"tag": "外卖福利",
|
||||
"desc": "满10元可用",
|
||||
"price": "3",
|
||||
"butText": "去领取",
|
||||
"imgUrl": "/static/image/balance/pay-successful/mixue.png"
|
||||
}
|
||||
],
|
||||
"bannerTime": "07月12日12:22"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,691 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<nav-bar bgColor="#F5F5F5" :isBack="true" title="编辑账单详情" isRightButton @right-click="saveData"></nav-bar>
|
||||
|
||||
<view class="tabs">
|
||||
<view class="tab-item" :class="{ active: payData.styleType == 'style1' }"
|
||||
@click="payData.styleType = 'style1'">样式1
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: payData.styleType == 'style2' }"
|
||||
@click="payData.styleType = 'style2'">样式2
|
||||
</view>
|
||||
<view class="tab-item" :class="{ active: payData.styleType == 'style3' }"
|
||||
@click="payData.styleType = 'style3'">样式3
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="main-content">
|
||||
<!-- 基础信息卡片 -->
|
||||
<view class="card basic-card">
|
||||
<view class="amount-wrap">
|
||||
<text class="symbol">¥</text>
|
||||
<auto-width-input class="alipay-font" type="digit" v-model="payData.money" fontSize="88rpx"
|
||||
fontWeight="500" color="#1A1A1A" :showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
|
||||
<view class="info-row">
|
||||
<view class="info-item">
|
||||
<auto-width-input v-model="payData.user" fontSize="28rpx" color="#333"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
<view class="info-item" style="justify-content: flex-end;">
|
||||
<text class="value-symbol">¥ </text>
|
||||
<auto-width-input type="digit" v-model="payData.money" fontSize="28rpx" color="#333"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-row" style="margin-top: 16rpx;">
|
||||
<view class="info-item">
|
||||
<text class="label">付款方式</text>
|
||||
</view>
|
||||
<view class="info-item" style="justify-content: flex-end;">
|
||||
<auto-width-input v-model="payData.payMethod" fontSize="28rpx" color="#333"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 样式1 -->
|
||||
<template v-if="payData.styleType == 'style1'">
|
||||
<view class="card list-card">
|
||||
<view class="card-title" style="display: flex; justify-content: space-between;">
|
||||
支付有礼
|
||||
<image style="width: 24px;height: 24px;" src="/static/image/common/random-dice.png"
|
||||
mode="widthFix" @click="randomCoupon('style1')"></image>
|
||||
</view>
|
||||
<!-- 券1 -->
|
||||
<view class="list-item" v-if="payData.style1.couponlist && payData.style1.couponlist[0]">
|
||||
<view class="left-icon-wrap" @click="chooseImage('style1_coupon_0')">
|
||||
<image v-if="payData.style1.couponlist[0].imgUrl" class="item-img"
|
||||
:src="payData.style1.couponlist[0].imgUrl" mode="aspectFill"></image>
|
||||
<image v-else class="edit-icon-center" src="/static/image/common/edit.png"></image>
|
||||
</view>
|
||||
<view class="item-content">
|
||||
<view class="row-flex" style="flex-wrap: wrap;">
|
||||
<view class="row-flex" style="margin-right: 12rpx;"
|
||||
v-if="payData.style1.couponlist[0].price !== undefined">
|
||||
<auto-width-input v-model="payData.style1.couponlist[0].price" fontSize="28rpx"
|
||||
color="#E6372D" fontWeight="500"></auto-width-input>
|
||||
<text class="main-title" style="color: #E6372D; width: auto;">元</text>
|
||||
<image class="edit-icon" src="/static/image/common/edit.png"
|
||||
style="margin-left: 8rpx; width: 24rpx; height: 24rpx;"></image>
|
||||
</view>
|
||||
<view class="row-flex">
|
||||
<auto-width-input v-model="payData.style1.couponlist[0].title" fontSize="28rpx"
|
||||
color="#333" fontWeight="500" :showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
<view class="row-flex mt">
|
||||
<view class="tag-red" style="margin-right: 12rpx; display: flex; align-items: center;"
|
||||
v-if="payData.style1.couponlist[0].tag !== undefined">
|
||||
<auto-width-input v-model="payData.style1.couponlist[0].tag" fontSize="20rpx"
|
||||
color="#E6372D" :showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
<view class="row-flex" v-if="payData.style1.couponlist[0].desc !== undefined">
|
||||
<auto-width-input v-model="payData.style1.couponlist[0].desc" fontSize="24rpx"
|
||||
color="#999" :showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-btn btn-get"
|
||||
style="display: flex; align-items: center; justify-content: center;"
|
||||
@click="toggleBtnText(payData.style1.couponlist[0])">
|
||||
<text style="font-size: 24rpx; color: #fff; font-weight: 500;">{{
|
||||
payData.style1.couponlist[0].butText || '免费领' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 飞猪广告 -->
|
||||
<view class="card fliggy-card">
|
||||
<view class="banner-wrap" @click="toggleBanner">
|
||||
<image class="banner-img"
|
||||
:src="payData.style1.bannerUrl || '/static/image/balance/transfer/bottom-banner-1.png'"
|
||||
mode="widthFix"></image>
|
||||
<view class="guanggao-tag">
|
||||
<image style="width: 70rpx;height: 32rpx;"
|
||||
src="/static/image/balance/transfer/guanggao.png"></image>
|
||||
</view>
|
||||
<view class="yaoyiyao-container">
|
||||
<view class="yaoyiyao-box">
|
||||
<image class="img" src="/static/image/balance/transfer/yaoyiyao.png" mode="widthFix">
|
||||
</image>
|
||||
<text class="text">摇动或点击查看详情</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fliggy-footer"
|
||||
v-if="payData.style1.bannerUrl == '/static/image/balance/transfer/bottom-banner-1.png'">
|
||||
<view class="logo-box">
|
||||
<image class="logo" src="/static/image/balance/transfer/feizhu.png" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info">
|
||||
<view class="text-content">
|
||||
<text class="b-title">飞猪旅行</text>
|
||||
<text class="b-desc">飞猪出行 超多折扣</text>
|
||||
</view>
|
||||
<view class="b-btn">领优惠</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fliggy-footer"
|
||||
v-if="payData.style1.bannerUrl == '/static/image/balance/transfer/bottom-banner-2.png'">
|
||||
<view class="logo-box">
|
||||
<image class="logo" src="/static/image/balance/transfer/taobaoshangou.png" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info" style="padding: 0;">
|
||||
<view class="text-content">
|
||||
<text class="b-title">淘宝闪购</text>
|
||||
<text class="b-desc">每天领大额外面红包</text>
|
||||
</view>
|
||||
<view class="b-btn">去领取</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 样式2 -->
|
||||
<template v-if="payData.styleType == 'style2'">
|
||||
<view class="card list-card">
|
||||
<view class="card-title" style="display: flex; justify-content: space-between;">支付有礼
|
||||
<image style="width: 24px;height: 24px;" src="/static/image/common/random-dice.png"
|
||||
mode="widthFix" @click="randomCoupon('style2')"></image>
|
||||
</view>
|
||||
|
||||
<view class="list-item" v-for="(item, index) in payData.style2.couponlist" :key="index">
|
||||
<view class="left-icon-wrap" @click="chooseImage('style2_coupon_' + index)">
|
||||
<image v-if="item.imgUrl" class="item-img" :src="item.imgUrl" mode="aspectFill"></image>
|
||||
<image v-else class="edit-icon-center" src="/static/image/common/edit.png"></image>
|
||||
</view>
|
||||
<view class="item-content">
|
||||
<view class="row-flex" style="flex-wrap: wrap;">
|
||||
<view class="row-flex" style="margin-right: 12rpx;" v-if="item.price !== undefined">
|
||||
<auto-width-input v-model="item.price" fontSize="28rpx"
|
||||
:color="item.price.includes('g') ? '#333' : '#E6372D'"
|
||||
fontWeight="500"></auto-width-input>
|
||||
<text class="main-title"
|
||||
:style="{ color: item.price.includes('g') ? '#333' : '#E6372D', width: 'auto' }">{{
|
||||
item.price.includes('g') ? '' : '元' }}</text>
|
||||
<image class="edit-icon" src="/static/image/common/edit.png"
|
||||
style="margin-left: 8rpx; width: 24rpx; height: 24rpx;"></image>
|
||||
</view>
|
||||
<view class="row-flex">
|
||||
<auto-width-input v-model="item.title" fontSize="28rpx" color="#333"
|
||||
fontWeight="500" :showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
<view class="row-flex mt">
|
||||
<view class="tag-red" :class="{ 'tag-orange': item.tag == '芭芭农场' }"
|
||||
style="margin-right: 12rpx; display: flex; align-items: center;"
|
||||
v-if="item.tag !== undefined">
|
||||
<auto-width-input v-model="item.tag" fontSize="20rpx"
|
||||
:color="item.tag == '芭芭农场' ? '#EF673C' : '#E6372D'"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
<view class="row-flex" v-if="item.desc !== undefined">
|
||||
<auto-width-input v-model="item.desc" fontSize="24rpx" color="#999"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-btn btn-get" :class="{ 'btn-look': item.butText == '去看看' }"
|
||||
style="display: flex; align-items: center; justify-content: center;"
|
||||
@click="toggleBtnText(item)">
|
||||
<text style="font-size: 24rpx; color: #fff; font-weight: 500;">{{ item.butText || '免费领'
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 样式3 -->
|
||||
<template v-if="payData.styleType == 'style3'">
|
||||
<view class="card list-card" style="padding-bottom: 24rpx;">
|
||||
<view class="flex-between" style="margin-bottom: 24rpx;">
|
||||
<text class="card-title" style="margin-bottom: 0;">碰一下立减</text>
|
||||
<view class="row-flex">
|
||||
<auto-width-input v-model="payData.style3.bannerTime" fontSize="24rpx"
|
||||
color="#666"></auto-width-input>
|
||||
<text class="time-text" style="width: auto;">后过期</text>
|
||||
<image class="edit-icon" src="/static/image/common/edit.png"
|
||||
style="margin-left: 8rpx; width: 24rpx; height: 24rpx;"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="banner-box">
|
||||
<text class="banner-time">{{ payData.style3.bannerTime }}后过期</text>
|
||||
<image src="/static/image/balance/pay-successful/pengyipengbanner.png"
|
||||
style="width: 100%; border-radius: 12rpx; display: block;" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="card-title" style="display: flex; justify-content: flex-end;padding: 0 16px;">
|
||||
<image style="width: 24px;height: 24px;" src="/static/image/common/random-dice.png" mode="widthFix"
|
||||
@click="randomCoupon('style3')">
|
||||
</image>
|
||||
</view>
|
||||
|
||||
<view class="card list-card" style="margin-top: 24rpx;">
|
||||
<view class="list-item" v-for="(item, index) in payData.style3.couponlist" :key="index">
|
||||
<view class="left-icon-wrap" @click="chooseImage('style3_coupon_' + index)">
|
||||
<image v-if="item.imgUrl" class="item-img" :src="item.imgUrl" mode="aspectFill"></image>
|
||||
<image v-else class="edit-icon-center" src="/static/image/common/edit.png"></image>
|
||||
</view>
|
||||
<view class="item-content" style="flex: 1;">
|
||||
<view class="row-flex">
|
||||
<auto-width-input v-model="item.title" fontSize="28rpx" color="#333" fontWeight="500"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
<view class="row-flex mt">
|
||||
<view class="tag-red" style="margin-right: 12rpx; display: flex; align-items: center;"
|
||||
v-if="item.tag !== undefined">
|
||||
<auto-width-input v-model="item.tag" fontSize="20rpx" color="#E6372D"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
<view class="row-flex" v-if="item.desc !== undefined">
|
||||
<auto-width-input v-model="item.desc" fontSize="24rpx" color="#999"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="row-flex" style="align-items: baseline;" v-if="item.price !== undefined">
|
||||
<auto-width-input v-model="item.price" fontSize="40rpx" color="#E6372D" fontWeight="500"
|
||||
:showEdit="true"></auto-width-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { defaultData, randomData } from './data.json';
|
||||
import { util } from '@/utils/common.js';
|
||||
import autoWidthInput from '@/components/common/auto-width-input.vue';
|
||||
|
||||
const payData = ref(JSON.parse(JSON.stringify(defaultData)));
|
||||
|
||||
const PAY_STORAGE_KEY = 'alipay_pay_successful_data';
|
||||
|
||||
const randomCoupon = (styleName) => {
|
||||
// #ifdef APP-PLUS
|
||||
const oldList = payData.value[styleName].couponlist || [];
|
||||
oldList.forEach(item => {
|
||||
if (item.imgUrl && !item.imgUrl.startsWith('/static') && !item.imgUrl.startsWith('http')) {
|
||||
uni.removeSavedFile({ filePath: item.imgUrl });
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
const count = payData.value[styleName].couponlist.length;
|
||||
const shuffled = [...randomData].sort(() => 0.5 - Math.random());
|
||||
const selected = shuffled.slice(0, count);
|
||||
payData.value[styleName].couponlist = JSON.parse(JSON.stringify(selected));
|
||||
};
|
||||
const loadStorageData = () => {
|
||||
const savedData = uni.getStorageSync(PAY_STORAGE_KEY);
|
||||
if (savedData) {
|
||||
payData.value = Object.assign({}, payData.value, savedData);
|
||||
}
|
||||
};
|
||||
|
||||
onLoad(() => {
|
||||
loadStorageData();
|
||||
});
|
||||
|
||||
const saveData = () => {
|
||||
uni.setStorageSync(PAY_STORAGE_KEY, payData.value);
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const chooseImage = (type) => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
const tempPath = res.tempFilePaths[0];
|
||||
|
||||
let oldPath = '';
|
||||
if (type === 'style1_coupon_0') {
|
||||
oldPath = payData.value.style1.couponlist[0].imgUrl;
|
||||
} else if (type.startsWith('style2_coupon_')) {
|
||||
const idx = parseInt(type.split('_')[2]);
|
||||
oldPath = payData.value.style2.couponlist[idx].imgUrl;
|
||||
} else if (type.startsWith('style3_coupon_')) {
|
||||
const idx = parseInt(type.split('_')[2]);
|
||||
oldPath = payData.value.style3.couponlist[idx].imgUrl;
|
||||
}
|
||||
|
||||
const updateImgUrl = (path) => {
|
||||
if (type === 'style1_coupon_0') {
|
||||
payData.value.style1.couponlist[0].imgUrl = path;
|
||||
} else if (type.startsWith('style2_coupon_')) {
|
||||
const idx = parseInt(type.split('_')[2]);
|
||||
payData.value.style2.couponlist[idx].imgUrl = path;
|
||||
} else if (type.startsWith('style3_coupon_')) {
|
||||
const idx = parseInt(type.split('_')[2]);
|
||||
payData.value.style3.couponlist[idx].imgUrl = path;
|
||||
}
|
||||
};
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
if (oldPath && !oldPath.startsWith('/static') && !oldPath.startsWith('http')) {
|
||||
// 尝试删除旧的本地文件,避免存储空间堆积
|
||||
uni.removeSavedFile({ filePath: oldPath });
|
||||
}
|
||||
uni.saveFile({
|
||||
tempFilePath: tempPath,
|
||||
success: (saveRes) => {
|
||||
updateImgUrl(saveRes.savedFilePath);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-PLUS
|
||||
updateImgUrl(tempPath);
|
||||
// #endif
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const toggleBtnText = (item) => {
|
||||
const textList = ['免费领', '去看看', '去领取'];
|
||||
const currentIndex = textList.indexOf(item.butText);
|
||||
if (currentIndex > -1) {
|
||||
item.butText = textList[(currentIndex + 1) % textList.length];
|
||||
} else {
|
||||
item.butText = '免费领';
|
||||
}
|
||||
};
|
||||
|
||||
const toggleBanner = () => {
|
||||
const current = payData.value.style1.bannerUrl || '/static/image/balance/transfer/bottom-banner-1.png';
|
||||
if (current.includes('bottom-banner-1.png')) {
|
||||
payData.value.style1.bannerUrl = '/static/image/balance/transfer/bottom-banner-2.png';
|
||||
} else {
|
||||
payData.value.style1.bannerUrl = '/static/image/balance/transfer/bottom-banner-1.png';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "@/common/main.css";
|
||||
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #F5F5F5;
|
||||
padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #3884FD;
|
||||
color: #fff;
|
||||
font-size: 26rpx;
|
||||
padding: 10rpx 32rpx;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20rpx;
|
||||
margin: 24rpx 0;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
padding: 12rpx 40rpx;
|
||||
background-color: #fff;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #fff;
|
||||
}
|
||||
|
||||
.tab-item.active {
|
||||
color: #3884FD;
|
||||
border-color: #3884FD;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 0 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin: 24rpx;
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
.basic-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.amount-wrap {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: center;
|
||||
color: #1A1A1A;
|
||||
margin-top: 10rpx;
|
||||
margin-bottom: 50rpx;
|
||||
|
||||
.symbol {
|
||||
font-size: 60rpx;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.info-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
width: 200rpx;
|
||||
}
|
||||
|
||||
.value-symbol {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.edit-icon-center {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.left-icon-wrap {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #F5F5F5;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
.card-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #1A1A1A;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.row-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mt {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.main-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sub-title {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.tag-red {
|
||||
font-size: 20rpx;
|
||||
color: #E6372D;
|
||||
background: #FFF1F0;
|
||||
padding: 4rpx 10rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.tag-orange {
|
||||
color: #EF673C;
|
||||
background: #FFF2F1;
|
||||
}
|
||||
|
||||
.right-btn {
|
||||
padding: 10rpx 28rpx;
|
||||
border-radius: 26rpx;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-get {
|
||||
background-color: #E6372D;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-look {
|
||||
background-color: #E6372D;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.fliggy-card {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.banner-wrap {
|
||||
position: relative;
|
||||
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.guanggao-tag {
|
||||
position: absolute;
|
||||
top: 16rpx;
|
||||
right: 16rpx;
|
||||
}
|
||||
|
||||
.yaoyiyao-container {
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.yaoyiyao-box {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
padding: 10rpx 24rpx;
|
||||
border-radius: 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.img {
|
||||
width: 24rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fliggy-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx;
|
||||
|
||||
.logo-box {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
margin-right: 20rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
|
||||
.logo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.text-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.b-title {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.b-desc {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.b-btn {
|
||||
background-color: #E6372D;
|
||||
color: #fff;
|
||||
padding: 10rpx 28rpx;
|
||||
border-radius: 26rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.flex-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.time-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.banner-box {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.banner-time {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
left: 170rpx;
|
||||
top: 68rpx;
|
||||
font-size: 20rpx;
|
||||
color: #C70B0C;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,769 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_pay-successful" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_pay-successful')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container">
|
||||
<!-- 蓝色背景区域 -->
|
||||
<view class="header-section">
|
||||
<nav-bar ref="navBarRef" bgColor="transparent" :isBack="false" :buttonGroup="buttonGroup"
|
||||
tipLayerType="pay-successful-tip" isTipLayer tipLayerText="修改支付数据" @button-click="handleButtonClick">
|
||||
<template v-slot:right>
|
||||
<view class="nav-link w100"
|
||||
style="display: flex; align-items: center; justify-content: flex-end; white-space: nowrap; padding: 0;">
|
||||
<text @click="util.goBack()" style="margin-right: 20rpx;">回首页</text>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:center>
|
||||
<view class="status-box">
|
||||
<image class="image" src="/static/image/balance/transfer/success.png"></image>
|
||||
<text class="status-text">支付成功</text>
|
||||
</view>
|
||||
</template>
|
||||
</nav-bar>
|
||||
|
||||
<!-- 转账状态信息 -->
|
||||
<view class="success-info">
|
||||
<view class="amount-box" @click="goEdit">
|
||||
<text class="symbol">¥</text>
|
||||
<text class="amount alipay-font">{{ Number(payData.money).toFixed(2) }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 收款方/付款方式 -->
|
||||
<view class="details-box">
|
||||
<view class="detail-item">
|
||||
<text class="label">{{ payData.user }}</text>
|
||||
<text class="value">{{ Number(payData.money).toFixed(2) }}</text>
|
||||
</view>
|
||||
<view class="detail-item">
|
||||
<text class="label">付款方式</text>
|
||||
<text class="value">{{ payData.payMethod }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<view class="main-content" :style="{ top: `${190 + statusBarHeight}px` }">
|
||||
<!-- 样式1 -->
|
||||
<template v-if="payData.styleType == 'style1'">
|
||||
<view class="pay-success-card">
|
||||
<image class="title-img" style="width: 106rpx;height: 28rpx;"
|
||||
src="/static/image/balance/pay-successful/zhifuyouli.png" mode="widthFix"></image>
|
||||
<view class="banner-footer" style="padding: 0 16rpx;">
|
||||
<view class="logo-box">
|
||||
<image class="logo" src="/static/image/balance/pay-successful/zhifufuli.png"
|
||||
mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info" style="border-top: none;">
|
||||
<view class="text-content">
|
||||
<text class="b-title">领取<text style="color: #EA4833;">今日</text>支付福利</text>
|
||||
<text class="b-desc">领优惠,支付更省钱</text>
|
||||
</view>
|
||||
<view class="b-btn">去看看</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="banner-footer" style="padding: 0 16rpx;">
|
||||
<view class="logo-box">
|
||||
<image class="logo" :src="payData.style1.couponlist[0].imgUrl" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info">
|
||||
<view class="text-content">
|
||||
<text class="b-title">
|
||||
<text
|
||||
v-if="payData.style1.couponlist[0].price && payData.style1.couponlist[0].price > 0"
|
||||
style="color: #EA4833;">{{ payData.style1.couponlist[0].price }}元</text>
|
||||
{{ payData.style1.couponlist[0].title }}
|
||||
</text>
|
||||
<text class="b-desc">
|
||||
<text class="b-desc-tag">{{ payData.style1.couponlist[0].tag }}</text>
|
||||
{{ payData.style1.couponlist[0].desc }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="b-btn">{{ payData.style1.couponlist[0].butText }}</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="content-section">
|
||||
<!-- 飞猪广告 -->
|
||||
<view class="card fliggy-card">
|
||||
<image class="banner-img" :src="payData.style1.bannerUrl" mode="widthFix" @click="toggleBanner">
|
||||
</image>
|
||||
<view class="guanggao-tag">
|
||||
<image style="width: 70rpx;height: 32rpx;"
|
||||
src="/static/image/balance/transfer/guanggao.png">
|
||||
</image>
|
||||
</view>
|
||||
<view class="yaoyiyao-container">
|
||||
<view class="yaoyiyao-box">
|
||||
<image class="img" src="/static/image/balance/transfer/yaoyiyao.png" mode="widthFix">
|
||||
</image>
|
||||
<text class="text">摇动或点击查看详情</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="banner-footer"
|
||||
v-if="payData.style1.bannerUrl == '/static/image/balance/transfer/bottom-banner-1.png'">
|
||||
<view class="logo-box">
|
||||
<image class="logo" src="/static/image/balance/transfer/feizhu.png" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info" style="padding: 0;">
|
||||
<view class="text-content">
|
||||
<text class="b-title">飞猪旅行</text>
|
||||
<text class="b-desc">飞猪出行 超多折扣</text>
|
||||
</view>
|
||||
<view class="b-btn">领优惠</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
<view class="banner-footer"
|
||||
v-if="payData.style1.bannerUrl == '/static/image/balance/transfer/bottom-banner-2.png'">
|
||||
<view class="logo-box">
|
||||
<image class="logo" src="/static/image/balance/transfer/taobaoshangou.png"
|
||||
mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info" style="padding: 0;">
|
||||
<view class="text-content">
|
||||
<text class="b-title">淘宝闪购</text>
|
||||
<text class="b-desc">每天领大额外面红包</text>
|
||||
</view>
|
||||
<view class="b-btn">去领取</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<!-- 样式2 -->
|
||||
<template v-if="payData.styleType == 'style2'">
|
||||
<view class="pay-success-card">
|
||||
<image class="title-img" style="width: 106rpx;height: 28rpx;"
|
||||
src="/static/image/balance/pay-successful/zhifuyouli.png" mode="widthFix"></image>
|
||||
<view class="banner-footer" style="padding: 0 16rpx;">
|
||||
<view class="logo-box">
|
||||
<image class="logo" src="/static/image/balance/pay-successful/zhifufuli.png"
|
||||
mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info" style="border-top: none;">
|
||||
<view class="text-content">
|
||||
<text class="b-title">领取<text style="color: #EA4833;">今日</text>支付福利</text>
|
||||
<text class="b-desc">领优惠,支付更省钱</text>
|
||||
</view>
|
||||
<view class="b-btn">去看看</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="banner-footer" style="padding: 0 16rpx;"
|
||||
v-for="item, index in payData.style2.couponlist" :key="index">
|
||||
<view class="logo-box">
|
||||
<image class="logo" :src="item.imgUrl" mode="aspectFit">
|
||||
</image>
|
||||
</view>
|
||||
<view class="banner-info">
|
||||
<view class="text-content">
|
||||
<text class="b-title">
|
||||
<text v-if="item.price" style="color: #EA4833;">{{ item.price }}元</text>{{
|
||||
item.title
|
||||
}}</text>
|
||||
<text class="b-desc">
|
||||
<text class="b-desc-tag">{{ item.tag }}</text>
|
||||
{{ item.desc }}</text>
|
||||
</view>
|
||||
<view class="b-btn">{{ payData.style1.couponlist[0].butText }}</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-if="payData.styleType == 'style3'">
|
||||
<view style="padding: 24rpx 20rpx;margin-bottom: 24rpx;" class="pay-success-card">
|
||||
<text class="title">支付有礼</text>
|
||||
<view class="banner-box">
|
||||
<text class="banner-time">{{ payData.style3.bannerTime }}后过期</text>
|
||||
<image src="/static/image/balance/pay-successful/pengyipengbanner.png" style="width: 100%;"
|
||||
mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="promo-card" v-for="item, index in payData.style3.couponlist" :key="index">
|
||||
<view class="promo-left-box">
|
||||
<image class="img" :src="item.imgUrl" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="promo-right">
|
||||
<view class="promo-content">
|
||||
<text class="promo-title">{{ item.title }}</text>
|
||||
<view class="promo-tags">
|
||||
<text class="tag">{{ item.tag }}</text>
|
||||
<text class="tag-desc">{{ item.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="promo-right-box">
|
||||
|
||||
<view class="price-box">
|
||||
<text class="p-num alipay-font">{{ item.price }}</text>
|
||||
<text class="p-unit">元</text>
|
||||
</view>
|
||||
<view class="free-btn">{{ item.butText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 底部操作区 -->
|
||||
<view class="footer-section" :style="{'padding-bottom':($store.state.safeBottomAz+24)+'px'}">
|
||||
<view class="finish-btn" @click="goBack">完成</view>
|
||||
</view>
|
||||
<ZdySafeBottom bgColor="#f5f5f5"/>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
onMounted,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onShow,
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js';
|
||||
import {
|
||||
defaultData
|
||||
} from './data.json';
|
||||
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
const statusBarHeight = ref(0);
|
||||
const PAY_STORAGE_KEY = 'alipay_pay_successful_data';
|
||||
const payData = ref(defaultData);
|
||||
|
||||
const bannerImages = [
|
||||
'/static/image/balance/transfer/bottom-banner-1.png',
|
||||
'/static/image/balance/transfer/bottom-banner-2.png'
|
||||
];
|
||||
|
||||
// 从缓存加载数据
|
||||
const loadStorageData = () => {
|
||||
const savedData = uni.getStorageSync(PAY_STORAGE_KEY);
|
||||
if (savedData) {
|
||||
payData.value = savedData;
|
||||
}
|
||||
};
|
||||
loadStorageData();
|
||||
|
||||
const navBarRef = ref(null);
|
||||
const buttonGroup = ref([{
|
||||
name: '编辑支付数据',
|
||||
action: 'edit'
|
||||
}]);
|
||||
const handleButtonClick = (button) => {
|
||||
if (button.action === 'edit') {
|
||||
goEdit()
|
||||
}
|
||||
};
|
||||
|
||||
const goEdit = () => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/balance/pay-successful/edit'
|
||||
});
|
||||
}
|
||||
|
||||
const toggleBanner = () => {
|
||||
const currentIndex = bannerImages.indexOf(payData.value.style1.bannerUrl);
|
||||
const nextIndex = (currentIndex + 1) % bannerImages.length;
|
||||
payData.value.style1.bannerUrl = bannerImages[nextIndex];
|
||||
uni.setStorageSync(PAY_STORAGE_KEY, payData.value);
|
||||
};
|
||||
|
||||
onLoad(() => {
|
||||
// 进入支付成功页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
key: 'pay-successful',
|
||||
value: "支付成功"
|
||||
})
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
if (systemInfo.statusBarHeight) {
|
||||
statusBarHeight.value = systemInfo.statusBarHeight;
|
||||
}
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
loadStorageData();
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F5F5F5')
|
||||
uni.setNavigationBarColor({
|
||||
animation: { // 动画效果
|
||||
duration: 100,
|
||||
timingFunc: 'easeIn'
|
||||
}
|
||||
})
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
}, 500);
|
||||
// #endif
|
||||
})
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "@/common/main.css";
|
||||
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
background-color: #F5F5F5;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
height: 860rpx;
|
||||
background: linear-gradient(181deg, #3884FD 60%, rgba(30, 128, 253, 0.5) 81.75%, rgba(30, 128, 253, 0) 100%);
|
||||
|
||||
::v-deep .nav-bar-container {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
::v-deep .placeholder-box {
|
||||
display: none !important;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::v-deep .tipLayer {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
::v-deep .uni-navbar__header-btns {
|
||||
width: 100px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 40rpx;
|
||||
}
|
||||
|
||||
|
||||
.nav-link {
|
||||
padding: 0 30rpx;
|
||||
text-align: right;
|
||||
font-size: 28rpx;
|
||||
line-height: 28rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.success-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pay-success-card {
|
||||
margin: 24rpx;
|
||||
margin-top: 16rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 0;
|
||||
|
||||
.title-img {
|
||||
width: 106rpx;
|
||||
height: 28rpx;
|
||||
margin-top: 22rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: 700;
|
||||
font-size: 24rpx;
|
||||
color: #252525;
|
||||
line-height: 24rpx;
|
||||
}
|
||||
|
||||
.banner-box {
|
||||
position: relative;
|
||||
width: 660rpx;
|
||||
height: 166rpx;
|
||||
margin-top: 18rpx;
|
||||
|
||||
.banner-time {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
left: 156rpx;
|
||||
top: 68rpx;
|
||||
font-weight: 400;
|
||||
font-size: 20rpx;
|
||||
color: #C70B0C;
|
||||
line-height: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 10rpx;
|
||||
height: 34rpx;
|
||||
|
||||
.image {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
font-size: 34rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: 500;
|
||||
line-height: 34rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.amount-box {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
color: #fff;
|
||||
margin-top: 20rpx;
|
||||
margin-bottom: 60rpx;
|
||||
|
||||
.symbol {
|
||||
font-size: 68rpx;
|
||||
margin-right: 4rpx;
|
||||
}
|
||||
|
||||
.amount {
|
||||
font-size: 92rpx;
|
||||
line-height: 92rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.details-box {
|
||||
width: 100%;
|
||||
padding: 0 46rpx;
|
||||
|
||||
.detail-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20rpx;
|
||||
height: 26rpx;
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
line-height: 26rpx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.content-section {
|
||||
padding: 24rpx;
|
||||
padding-bottom: 16rpx;
|
||||
// background-color: #F5F5F5;
|
||||
border-radius: 30rpx 30rpx 0 0;
|
||||
}
|
||||
|
||||
.card {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 24rpx;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
.fliggy-card {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.banner-img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.guanggao-tag {
|
||||
position: absolute;
|
||||
top: 16rpx;
|
||||
right: 16rpx;
|
||||
}
|
||||
|
||||
.yaoyiyao-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: -80rpx;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
.yaoyiyao-box {
|
||||
padding: 12rpx 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #000000;
|
||||
border-radius: 28rpx;
|
||||
opacity: 0.5;
|
||||
|
||||
.img {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
line-height: 24rpx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.banner-footer {
|
||||
padding: 24rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.logo-box {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 20rpx;
|
||||
|
||||
.logo {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.banner-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-top: 1rpx solid #F6F6F6;
|
||||
padding: 30rpx 0;
|
||||
|
||||
|
||||
.text-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.b-title {
|
||||
font-size: 28rpx;
|
||||
line-height: 28rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.b-desc {
|
||||
margin-top: 12rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 24rpx;
|
||||
color: #969696;
|
||||
|
||||
.b-desc-tag {
|
||||
font-size: 24rpx;
|
||||
color: #E4711F;
|
||||
background-color: #FDF6F3;
|
||||
line-height: 24rpx;
|
||||
padding: 2px 4px;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.b-btn {
|
||||
padding: 0 20rpx;
|
||||
background-color: #FF3A31;
|
||||
color: #fff;
|
||||
font-size: 26rpx;
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: url('/static/image/balance/pay-successful/more.png');
|
||||
top: 16rpx;
|
||||
right: 20rpx;
|
||||
width: 24rpx;
|
||||
height: 12rpx;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-section {
|
||||
padding: 0px 40rpx 0;
|
||||
margin-top: 50rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-bottom: 24rpx;
|
||||
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||||
padding-bottom: calc(24rpx + constant(safe-area-inset-bottom));
|
||||
|
||||
.finish-btn {
|
||||
height: 84rpx;
|
||||
width: 390rpx;
|
||||
line-height: 84rpx;
|
||||
text-align: center;
|
||||
border: 1px solid #2172CA;
|
||||
border-radius: 42rpx;
|
||||
color: #2172CA;
|
||||
font-size: 32rpx;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.main-content {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 190px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.promo-card {
|
||||
// padding: 30rpx;
|
||||
margin: 16rpx;
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
|
||||
|
||||
.promo-left-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 34rpx;
|
||||
background-image: url("/static/image/balance/transfer/card-bg-2-left.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
height: 144rpx;
|
||||
margin-right: -1px;
|
||||
|
||||
|
||||
.img {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
.promo-right {
|
||||
height: 144rpx;
|
||||
background-image: url("/static/image/balance/transfer/card-bg-2-right.png");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx 32rpx 24rpx;
|
||||
|
||||
.promo-title {
|
||||
font-size: 28rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.promo-tags {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 8rpx;
|
||||
|
||||
.tag {
|
||||
font-size: 24rpx;
|
||||
line-height: 34rpx;
|
||||
height: 34rpx;
|
||||
color: #EF673C;
|
||||
background-color: #FFF2F1;
|
||||
border-radius: 4rpx;
|
||||
margin-right: 12rpx;
|
||||
padding: 0 12rpx;
|
||||
}
|
||||
|
||||
.tag-desc {
|
||||
font-size: 24rpx;
|
||||
line-height: 24rpx;
|
||||
color: #969696;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.promo-right-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.price-box {
|
||||
color: #F93950;
|
||||
|
||||
.p-num {
|
||||
font-size: 34rpx;
|
||||
line-height: 24rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.p-unit {
|
||||
font-size: 24rpx;
|
||||
line-height: 24rpx;
|
||||
margin-left: 2rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.free-btn {
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
padding: 0 24rpx;
|
||||
background-color: #FA3A49;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
border-radius: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -27,8 +27,10 @@
|
|||
<!-- 隐藏的text用于测量宽度 -->
|
||||
<text class="text-measure">{{ billData.name }}</text>
|
||||
|
||||
<input class="text-input" type="text" v-model="billData.name" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"></image>
|
||||
<input class="text-input" type="text" :focus="data.focusState.name" v-model="billData.name"
|
||||
@blur="data.focusState.name = false" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png" @click="triggerFocus('name')">
|
||||
</image>
|
||||
</view>
|
||||
<!-- 金额 -->
|
||||
<view class="money-box flex-align-center">
|
||||
|
|
@ -39,8 +41,10 @@
|
|||
<text class="text-measure font-w500" style="font-size: 64rpx;">{{ billData.money }}</text>
|
||||
|
||||
<input class="text-input font-w500" style="font-size: 64rpx;" type="digit"
|
||||
v-model="billData.money" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"></image>
|
||||
:focus="data.focusState.money" v-model="billData.money"
|
||||
@blur="data.focusState.money = false" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="triggerFocus('money')"></image>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -52,9 +56,13 @@
|
|||
<!-- 详情信息列表 -->
|
||||
<view class="detail-info-container">
|
||||
<template v-for="item in billData.itemInfoList" :key="item.id">
|
||||
<view class="info-item-box" v-if="item.key != 'paymentReward'">
|
||||
<view class="item-label">
|
||||
{{ item.label }}
|
||||
<view class="info-item-box"
|
||||
v-if="item.key != 'paymentReward' && (item.key != 'transferNote' || billData.merchantOption.isTransferNote)">
|
||||
<view class="item-label" :class="{ 'switchable-label': item.key === 'createTime' }"
|
||||
@click="toggleCreateTimeLabel(item)">
|
||||
<text>{{ item.label }}</text>
|
||||
<image v-if="item.key === 'createTime'" class="switch-icon"
|
||||
src="/static/image/bill/add-bill/edit.png"></image>
|
||||
</view>
|
||||
<view v-if="item.type != 'link'" class="info-item-input" @click="onClickItemInfo(item)">
|
||||
<!-- 隐藏的text用于测量宽度 -->
|
||||
|
|
@ -66,7 +74,8 @@
|
|||
<input
|
||||
v-if="(item.type == 'text' || item.type == 'digit' || item.type == 'number') && !(data.type == 1 && item.key == 'payMethod')"
|
||||
:style="{ color: item.textColor ? item.textColor : '#1a1a1a' }" class="text-input"
|
||||
:type="item.type" :focus="item.focus" v-model="item.value" @click.stop />
|
||||
:type="item.type" :focus="item.focus" v-model="item.value" @click.stop
|
||||
@blur="item.focus = false" />
|
||||
</view>
|
||||
<image v-if="item.type != 'link' && !(data.type == 1 && item.key == 'payMethod')"
|
||||
class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
|
|
@ -97,7 +106,7 @@
|
|||
<view class="right-input-box flex-align-center">
|
||||
<!-- <text class="right-text">共{{ item.value.number }}件</text> -->
|
||||
<input class="right-text" :focus="item.focus" type="text" v-model="item.value.quantity"
|
||||
@click.stop />
|
||||
@blur="item.focus = false" @click.stop />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="onClickItemInfo(item, 'foucs')">
|
||||
</image>
|
||||
|
|
@ -111,9 +120,11 @@
|
|||
<view class="info-item-input">
|
||||
<!-- 隐藏的text用于测量宽度 -->
|
||||
<text class="text-measure">{{ billData.balance }}</text>
|
||||
<input class="text-input" type="digit" v-model="billData.balance" />
|
||||
<input class="text-input" type="digit" :focus="data.focusState.balance"
|
||||
v-model="billData.balance" @blur="data.focusState.balance = false" />
|
||||
</view>
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png">
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="triggerFocus('balance')">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -122,7 +133,8 @@
|
|||
<view class="switch-option-container">
|
||||
<template v-for="option in data.switchOptions" :key="option.id">
|
||||
<view v-if="option.showTypeIds ? option.showTypeIds.includes(billData.selectId) : true"
|
||||
class="border-bottom" :class="{ 'no-border-bottom': isNoBorderBottom(option) }">
|
||||
class="border-bottom"
|
||||
:class="{ 'no-border-bottom': isNoBorderBottom(option) || option.isMarginBottom, 'margin-bottom-16rpx': option.isMarginBottom }">
|
||||
<view class="switch-option">
|
||||
<view class="switch-option-text">{{ option.name }}</view>
|
||||
<switch v-if="option.isSwitch" color="#1676FE" :checked="billData.merchantOption[option.key]"
|
||||
|
|
@ -172,6 +184,7 @@
|
|||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png">
|
||||
</image>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
</view>
|
||||
|
|
@ -187,8 +200,12 @@
|
|||
billData.merchantOption.serviceDetailInfo.text }}</text>
|
||||
|
||||
<input class="text-input" maxlength="20" style="font-size: 22rpx;" type="text"
|
||||
v-model="billData.merchantOption.serviceDetailInfo.text" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"></image>
|
||||
:focus="data.focusState.serviceDetail"
|
||||
v-model="billData.merchantOption.serviceDetailInfo.text"
|
||||
@blur="data.focusState.serviceDetail = false" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="triggerFocus('serviceDetail')">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<uni-data-select class="select" style="flex: none;width: 80px;"
|
||||
|
|
@ -207,8 +224,11 @@
|
|||
billData.merchantOption.recommendServiceInfo.text }}</text>
|
||||
|
||||
<input class="text-input" maxlength="20" style="font-size: 22rpx;" type="text"
|
||||
v-model="billData.merchantOption.recommendServiceInfo.text" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"></image>
|
||||
:focus="data.focusState.recommendService"
|
||||
v-model="billData.merchantOption.recommendServiceInfo.text"
|
||||
@blur="data.focusState.recommendService = false" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="triggerFocus('recommendService')"></image>
|
||||
</view>
|
||||
</view>
|
||||
<text class="right-text">去看看</text>
|
||||
|
|
@ -224,12 +244,34 @@
|
|||
billData.merchantOption.serviceRecommendInfo.text }}</text>
|
||||
|
||||
<input class="text-input" maxlength="20" style="font-size: 22rpx;" type="text"
|
||||
v-model="billData.merchantOption.serviceRecommendInfo.text" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"></image>
|
||||
:focus="data.focusState.serviceRecommend"
|
||||
v-model="billData.merchantOption.serviceRecommendInfo.text"
|
||||
@blur="data.focusState.serviceRecommend = false" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="triggerFocus('serviceRecommend')"></image>
|
||||
</view>
|
||||
</view>
|
||||
<image class="right-icon" src="/static/image/common/right-grey.png" />
|
||||
</view>
|
||||
<view class="bill-analysis-box"
|
||||
v-if="option.key == 'isShowBillAnalysis' && billData.merchantOption.isShowBillAnalysis">
|
||||
<view class="bill-analysis-text-box">
|
||||
<view class="flex-1 over-hidden">
|
||||
<view class="service-detail-info info-item-input">
|
||||
<!-- 隐藏的text用于测量宽度 -->
|
||||
<text class="text-measure" style="font-size: 22rpx;">{{
|
||||
billData.merchantOption.billAnalysisInfo.text }}</text>
|
||||
|
||||
<input class="text-input" maxlength="20" style="font-size: 22rpx;" type="text"
|
||||
:focus="data.focusState.billAnalysis"
|
||||
v-model="billData.merchantOption.billAnalysisInfo.text"
|
||||
@blur="data.focusState.billAnalysis = false" />
|
||||
<image class="edit-image" src="/static/image/bill/add-bill/edit.png"
|
||||
@click="triggerFocus('billAnalysis')"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
|
@ -307,6 +349,41 @@ const timepopup = ref(null)
|
|||
// 账单管理弹窗
|
||||
const billManagementPopupRef = ref(null)
|
||||
|
||||
// 输入框引用定义
|
||||
const nameInputRef = ref(null)
|
||||
const moneyInputRef = ref(null)
|
||||
const balanceInputRef = ref(null)
|
||||
const serviceDetailInputRef = ref(null)
|
||||
const recommendServiceInputRef = ref(null)
|
||||
const serviceRecommendInputRef = ref(null)
|
||||
const billAnalysisInputRef = ref(null)
|
||||
|
||||
/**
|
||||
* 通用聚焦函数
|
||||
* @param {Object} inputRef 目标输入框的 ref
|
||||
*/
|
||||
const onFocusShortcut = (inputRef) => {
|
||||
if (!inputRef) return
|
||||
nextTick(() => {
|
||||
// uni-app 中 input 组件聚焦通常需要通过设置 focus 属性,但直接调用 focus() 在部分平台更直接
|
||||
// 我们主要通过 ref 操作或设置数据层状态实现
|
||||
if (inputRef.value && typeof inputRef.value.focus === 'function') {
|
||||
inputRef.value.focus()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 触发指定输入框聚焦(响应式变量方式)
|
||||
* @param {String} key focusState 中的键名
|
||||
*/
|
||||
const triggerFocus = (key) => {
|
||||
data.focusState[key] = false
|
||||
nextTick(() => {
|
||||
data.focusState[key] = true
|
||||
})
|
||||
}
|
||||
|
||||
const {
|
||||
addBill,
|
||||
getBillList,
|
||||
|
|
@ -333,46 +410,54 @@ const serviceDetailRightTextList = [{
|
|||
}
|
||||
]
|
||||
// switch选项
|
||||
const switchOptions = [{
|
||||
const switchOptions = [
|
||||
{
|
||||
"id": 11,
|
||||
"name": "转账备注",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [7],
|
||||
key: 'isTransferNote',
|
||||
isMarginBottom: true
|
||||
}, {
|
||||
"id": 7,
|
||||
"name": "账单分类",
|
||||
"isSwitch": false,
|
||||
key: 'billClassify',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "标签",
|
||||
"isSwitch": false,
|
||||
key: 'tag',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"name": "备注",
|
||||
"isSwitch": false,
|
||||
key: 'note',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"name": "服务详情",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [3, 4, 10],
|
||||
key: 'serviceDetail',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "推荐服务",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [4],
|
||||
key: 'recommendService',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "服务推荐",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [6, 7],
|
||||
key: 'serviceRecommend',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"name": "退款",
|
||||
"isSwitch": true,
|
||||
|
|
@ -387,28 +472,35 @@ const switchOptions = [{
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"name": "支付奖励",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [1, 3, 4, 13],
|
||||
key: 'payReward',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"name": "计入收支",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13],
|
||||
key: 'countInAndOut',
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"name": "商家订单号转换条形码",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [1, 2, 3],
|
||||
key: 'isShowBarcode',
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "账单分析",
|
||||
"isSwitch": true,
|
||||
showTypeIds: [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13],
|
||||
key: 'isShowBillAnalysis',
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
|
@ -460,6 +552,7 @@ const data = reactive({
|
|||
merchantOption: {
|
||||
serviceDetail: false,
|
||||
isShowBarcode: false,
|
||||
isTransferNote: false,
|
||||
serviceDetailInfo: {
|
||||
imgUrl: '',
|
||||
rightText: 0,
|
||||
|
|
@ -481,6 +574,10 @@ const data = reactive({
|
|||
note: {
|
||||
isImage: false,
|
||||
text: ''
|
||||
},
|
||||
isShowBillAnalysis: false,
|
||||
billAnalysisInfo: {
|
||||
text: '本笔登上月收入榜,看看分析吧'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -492,7 +589,17 @@ const data = reactive({
|
|||
tagInputValue: "",
|
||||
showTagInput: false,
|
||||
// switch选项
|
||||
switchOptions: switchOptions
|
||||
switchOptions: switchOptions,
|
||||
// 输入框聚焦状态
|
||||
focusState: {
|
||||
name: false,
|
||||
money: false,
|
||||
balance: false,
|
||||
serviceDetail: false,
|
||||
recommendService: false,
|
||||
serviceRecommend: false,
|
||||
billAnalysis: false
|
||||
}
|
||||
})
|
||||
|
||||
let {
|
||||
|
|
@ -502,7 +609,7 @@ let {
|
|||
} = toRefs(data)
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F5F5F5')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
|
|
@ -882,6 +989,15 @@ const onRightClick = async () => {
|
|||
}, 500)
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换创建时间/支付时间标签
|
||||
*/
|
||||
const toggleCreateTimeLabel = (item) => {
|
||||
if (item.key === 'createTime') {
|
||||
item.label = item.label === '创建时间' ? '支付时间' : '创建时间'
|
||||
}
|
||||
}
|
||||
|
||||
// 点击itemInfo
|
||||
const onClickItemInfo = async (item, action) => {
|
||||
console.log(item)
|
||||
|
|
@ -955,7 +1071,7 @@ const uploadImage = () => {
|
|||
*/
|
||||
const saveAndDisplayImage = (file) => {
|
||||
// #ifdef H5
|
||||
return Promise.resolve(file)
|
||||
// return Promise.resolve(file)
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
|
|
@ -1230,6 +1346,22 @@ page {
|
|||
font-size: 26rpx;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.switchable-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 4rpx 10rpx 4rpx 10rpx;
|
||||
margin-left: -10rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1px dashed #d9d9d9;
|
||||
background-color: #fcfcfc;
|
||||
|
||||
.switch-icon {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-item-input {
|
||||
|
|
@ -1279,11 +1411,11 @@ page {
|
|||
|
||||
.switch-option-container {
|
||||
margin: 16rpx 24rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx 16rpx 16rpx 16rpx;
|
||||
|
||||
.border-bottom {
|
||||
border-bottom: 1px solid #efefef
|
||||
border-bottom: 1px solid #efefef;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.no-border-bottom {
|
||||
|
|
@ -1468,4 +1600,24 @@ page {
|
|||
|
||||
|
||||
}
|
||||
|
||||
.bill-analysis-box {
|
||||
border-top: 0.5px solid #E4E4E4;
|
||||
padding: 14rpx 22rpx;
|
||||
|
||||
.bill-analysis-text-box {
|
||||
color: #B7971B;
|
||||
font-size: 26rpx;
|
||||
background-color: #FBF8F1;
|
||||
height: 76rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 16rpx;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.margin-bottom-16rpx {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark :dark="data.dark" source="uni_alipay_bill_details" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_bill_details')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view style="overflow: hidden;overflow-y: scroll; height: 100vh;">
|
||||
|
|
@ -29,7 +29,8 @@
|
|||
<!-- 金额 -->
|
||||
<view class=" money info-item-input alipay-font" style="height: 77rpx;">
|
||||
<!-- 隐藏的text用于测量宽度 -->
|
||||
<text class="text-measure font-w500" style="font-size: 64rpx;">{{ billData.money }}</text>
|
||||
<text class="text-measure font-w500" style="font-size: 64rpx;">{{
|
||||
numberUtil.formatMoneyWithThousand(billData.money) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -41,7 +42,9 @@
|
|||
<!-- 详情信息列表 -->
|
||||
<view class="detail-info-container">
|
||||
<template v-for="item in visibleItemInfoList" :key="item.id">
|
||||
<view class="info-item-box" :class="{ 'bottom-border': item.key == 'relatedRecord' }">
|
||||
<view class="info-item-box"
|
||||
v-if="item.key != 'transferNote' || billData.merchantOption.isTransferNote"
|
||||
:class="{ 'bottom-border': item.key == 'relatedRecord' }">
|
||||
<view class="item-label">
|
||||
{{ item.label }}
|
||||
</view>
|
||||
|
|
@ -171,8 +174,9 @@
|
|||
|
||||
<view class="bill-management">
|
||||
<view class="title">账单管理</view>
|
||||
<view class="top-box" style="background-color: #FBF8F1;">
|
||||
<text style="font-size: 24rpx;color: #B7971B;">本笔登上月收入榜,看看分析吧</text>
|
||||
<view v-if="billData.merchantOption.isShowBillAnalysis" class="top-box" style="background-color: #FBF8F1;">
|
||||
<text style="font-size: 24rpx;color: #B7971B;">{{
|
||||
billData.merchantOption.billAnalysisInfo.text || '本笔登上月收入榜,看看分析吧' }}</text>
|
||||
<uni-icons type="right" size="10" color="#B7971B"></uni-icons>
|
||||
</view>
|
||||
<view class="bill-classification bill-management-item">
|
||||
|
|
@ -237,6 +241,8 @@
|
|||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<ZdySafeBottom bgColor="#F5F5F5"/>
|
||||
</view>
|
||||
|
||||
|
||||
|
|
@ -247,13 +253,15 @@
|
|||
import navBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import billManagementPopup from '@/components/bill-management-popup/bill-management-popup.vue'
|
||||
import addBillJson from '@/static/json/add-bill.json'
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
const {
|
||||
billBottomIconList,
|
||||
classifyTabBar
|
||||
} = addBillJson
|
||||
import {
|
||||
util,
|
||||
randomUtil
|
||||
randomUtil,
|
||||
numberUtil
|
||||
} from '@/utils/common.js'
|
||||
|
||||
import {
|
||||
|
|
@ -359,7 +367,7 @@ const visibleItemInfoList = computed(() => {
|
|||
|
||||
onShow(() => {
|
||||
getBillData(data.billId)
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F5F5F5')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark :dark="data.dark" source="uni_alipay_bill" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_bill')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view style="overflow: hidden;height: 100vh;;">
|
||||
|
|
@ -49,9 +49,9 @@
|
|||
<view class="income-ande-outCome flex-between">
|
||||
<view class="flex">
|
||||
<view class="item"><text>支出¥</text><text class="money wx-font-regular">{{
|
||||
Number(currentMonthData.outCome).toFixed(2) }}</text></view>
|
||||
numberUtil.formatMoneyWithThousand(currentMonthData.outCome) }}</text></view>
|
||||
<view class="item"><text>收入¥</text><text class="money wx-font-regular">{{
|
||||
Number(currentMonthData.inCome).toFixed(2) }}</text></view>
|
||||
numberUtil.formatMoneyWithThousand(currentMonthData.inCome) }}</text></view>
|
||||
|
||||
</view>
|
||||
<view class="">
|
||||
|
|
@ -83,13 +83,13 @@
|
|||
<view class="outCome item">
|
||||
<text class="title">支出</text>
|
||||
<text class="amount alipay-font"><text class="font-11 wx-font-regular">¥</text>{{
|
||||
Number(item.outCome).toFixed(2)
|
||||
numberUtil.formatMoneyWithThousand(item.outCome)
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="income item">
|
||||
<text class="title">收入</text>
|
||||
<text class="amount alipay-font"><text class="font-11 wx-font-regular">¥</text>{{
|
||||
Number(item.inCome).toFixed(2)
|
||||
numberUtil.formatMoneyWithThousand(item.inCome)
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -112,6 +112,7 @@
|
|||
<view class="bill-list">
|
||||
<BalanceList :isBalance="false" :list="item.list" @longPress="onLongPress" @onBill="billClick" />
|
||||
</view>
|
||||
<ZdySafeBottom bgColor="#F5F5F5"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
|
|
@ -129,10 +130,12 @@
|
|||
<script setup>
|
||||
import {
|
||||
dateUtil,
|
||||
util
|
||||
util,
|
||||
numberUtil
|
||||
} from '@/utils/common.js'
|
||||
import navBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import BalanceList from '@/components/balance-list/balance-list.vue'
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
import {
|
||||
reactive,
|
||||
|
|
@ -246,7 +249,7 @@ onShow(() => {
|
|||
// 初始获取状态栏高度和屏幕高度
|
||||
updateStatusBarHeight()
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F5F5F5')
|
||||
uni.setNavigationBarColor({
|
||||
animation: { // 动画效果
|
||||
|
|
@ -283,7 +286,7 @@ const getBillDataList = () => {
|
|||
const createTimeItem = item.itemInfoList.find(info => info.key == 'createTime')
|
||||
const createTime = createTimeItem ? createTimeItem.value : new Date()
|
||||
|
||||
const date = new Date(createTime)
|
||||
const date = dateUtil.parseSafe(createTime)
|
||||
const year = date.getFullYear() + ''
|
||||
const month = (date.getMonth() + 1) + ''
|
||||
|
||||
|
|
@ -341,7 +344,7 @@ const getBillDataList = () => {
|
|||
|
||||
//每个月内的账单按时间倒序
|
||||
groupList.forEach(group => {
|
||||
group.list.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp))
|
||||
group.list.sort((a, b) => dateUtil.parseSafe(b.timestamp) - dateUtil.parseSafe(a.timestamp))
|
||||
})
|
||||
|
||||
data.billList = groupList
|
||||
|
|
@ -623,6 +626,13 @@ page {
|
|||
overflow: hidden;
|
||||
overflow-x: scroll;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0;
|
||||
height: 0;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
background-color: #ffffff;
|
||||
color: var(--text-primary);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_other_call" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_call')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container">
|
||||
<!-- 自定义头部导航栏 -->
|
||||
<ZdyNavbar tipLayerText="新增记录" :isTipLayer="true" :type="data.type" :scrollTop="data.scrollTop" @click="open" />
|
||||
<ZdyHeader :type="data.type" />
|
||||
<callList :type="data.type" ref="callLogList"></callList>
|
||||
<tabbar :type="data.type" />
|
||||
<image v-if="data.type != 'ios'" :src="`/static/image/call/${data.type}BtnImg.png`" mode="" class="btnImg"
|
||||
:class="['btnImg_' + data.type]" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ZdyNavbar from "@/components/call-log/nav-bar/nav-bar.vue"
|
||||
import ZdyHeader from "@/components/call-log/header/header.vue"
|
||||
import callList from "@/components/call-log/list/list.vue"
|
||||
import tabbar from "@/components/call-log/tabbar/tabbar.vue"
|
||||
import { util } from "@/utils/common.js"
|
||||
|
||||
import { ref, reactive, watch, nextTick, getCurrentInstance } from "vue";
|
||||
import { onLoad, onShow, onReady, onPageScroll, onReachBottom } from "@dcloudio/uni-app";
|
||||
const { appContext, proxy } = getCurrentInstance();
|
||||
const data = reactive({
|
||||
type: 'vivo',
|
||||
scrollTop: 0
|
||||
})
|
||||
let callLogList = ref();
|
||||
onLoad((option) => {
|
||||
data.type = option.type
|
||||
})
|
||||
onReady(() => {
|
||||
|
||||
})
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
try {
|
||||
if (plus.os.name === 'Android') {
|
||||
let colorTabbar = "#FAFAFA"
|
||||
if (data.type == 'xiaomi' || data.type == 'oppo') {
|
||||
colorTabbar = "#FFFFFF"
|
||||
}
|
||||
console.log(colorTabbar);
|
||||
util.setAndroidSystemBarColor(colorTabbar)
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500)
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log("修改导航条颜色失败", error);
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
onPageScroll((e) => {
|
||||
// console.log(e)
|
||||
data.scrollTop = e.scrollTop
|
||||
|
||||
})
|
||||
onReachBottom(() => {
|
||||
|
||||
})
|
||||
function open() {
|
||||
// console.log(callLogList.value)
|
||||
callLogList.value.openAddModal()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.btnImg {
|
||||
position: fixed;
|
||||
|
||||
}
|
||||
|
||||
.btnImg_vivo {
|
||||
width: 80px;
|
||||
height: 96px;
|
||||
left: 40px;
|
||||
bottom: 130px;
|
||||
}
|
||||
|
||||
.btnImg_huawei {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
left: calc(50% - 27px);
|
||||
bottom: 65px;
|
||||
}
|
||||
|
||||
.btnImg_oppo {
|
||||
width: 58px;
|
||||
height: 58px;
|
||||
right: 20px;
|
||||
bottom: 100px;
|
||||
}
|
||||
|
||||
.btnImg_xiaomi {
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
right: 34px;
|
||||
bottom: 100px;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,176 @@
|
|||
<template>
|
||||
<view class="page">
|
||||
|
||||
<!-- 顶部折叠头部 -->
|
||||
<view
|
||||
class="header"
|
||||
:style="{ height: headerHeight + 'px' }"
|
||||
>
|
||||
|
||||
<!-- 背景 -->
|
||||
<view class="header-bg"></view>
|
||||
|
||||
<!-- 内容层 -->
|
||||
<view
|
||||
class="header-content"
|
||||
:style="{
|
||||
transform: `translateY(${contentY}px)`
|
||||
}"
|
||||
>
|
||||
|
||||
<!-- 头像(单独动画) -->
|
||||
<image
|
||||
class="avatar"
|
||||
src="/static/avatar.png"
|
||||
:style="{
|
||||
transform: `scale(${avatarScale}) translateY(${avatarY}px)`
|
||||
}"
|
||||
/>
|
||||
|
||||
<!-- 文本 -->
|
||||
<view class="info">
|
||||
<view class="name">张三</view>
|
||||
<view class="desc">iOS通讯录详情页</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- 内容(重点:不会被遮挡) -->
|
||||
<view class="content">
|
||||
<view class="card" v-for="i in 30" :key="i">
|
||||
详情内容 {{ i }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
scrollY: 0,
|
||||
|
||||
headerMax: 260,
|
||||
headerMin: 90,
|
||||
|
||||
avatarScale: 1,
|
||||
avatarY: 0,
|
||||
contentY: 0
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
headerHeight() {
|
||||
const y = this.scrollY;
|
||||
// 🔥 折叠高度(关键)
|
||||
return Math.max(this.headerMin, this.headerMax - y);
|
||||
}
|
||||
},
|
||||
|
||||
onPageScroll(e) {
|
||||
const y = e.scrollTop;
|
||||
this.scrollY = y;
|
||||
|
||||
// =========================
|
||||
// 1. 进度(0~1)
|
||||
// =========================
|
||||
const max = 160;
|
||||
let p = Math.min(y / max, 1);
|
||||
|
||||
// =========================
|
||||
// 2. 头像缩小(只影响头像)
|
||||
// =========================
|
||||
this.avatarScale = 1 - p * 0.4; // 1 → 0.6
|
||||
|
||||
// =========================
|
||||
// 3. 头像上移(贴近顶部)
|
||||
// =========================
|
||||
this.avatarY = -p * 20;
|
||||
|
||||
// =========================
|
||||
// 4. 内容层轻微上移
|
||||
// =========================
|
||||
this.contentY = -p * 10;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.page {
|
||||
background: #f5f6f7;
|
||||
}
|
||||
|
||||
/* =====================
|
||||
header(核心)
|
||||
===================== */
|
||||
.header {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* 背景 */
|
||||
.header-bg {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(180deg, #3b82f6, #1e40af);
|
||||
}
|
||||
|
||||
/* 内容区 */
|
||||
.header-content {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 头像 */
|
||||
.avatar {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 20rpx;
|
||||
border: 4rpx solid rgba(255,255,255,0.6);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
/* 文本 */
|
||||
.info {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 24rpx;
|
||||
opacity: 0.85;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
|
||||
/* =====================
|
||||
内容(关键:防遮挡)
|
||||
===================== */
|
||||
.content {
|
||||
padding-top: 260px; /* ⭐ 解决你说的遮挡问题 */
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fff;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 10rpx 30rpx rgba(0,0,0,0.05);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container">
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<image ref="bgImage" class="bg-image" src="@/static/image/alipay-bill/main-bg.png" mode="widthFix"></image>
|
||||
<image ref="bgImage" class="bg-image" :src="billBgImage" mode="widthFix"></image>
|
||||
<image class="eye-image" src="@/static/image/alipay-bill/hide.png" mode="widthFix"></image>
|
||||
<image class="find-more" src="@/static/image/alipay-bill/find-more.png" mode=""></image>
|
||||
|
||||
|
|
@ -32,18 +32,18 @@
|
|||
<view class="frist-money money-type-item">
|
||||
<view class="type-input-box">
|
||||
<!-- <{{ moneyFrist.type }}>支出最多! -->
|
||||
<<view class="percentage-input-box">
|
||||
<<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyFrist.type }}</text>
|
||||
<input class="percentage-input" type="text" v-model="moneyFrist.type"
|
||||
@input="inputPercentage($event, 'moneyFrist')" maxlength="4"></input>
|
||||
</view>>支出最多!
|
||||
@input="inputPercentage($event, 'moneyFrist')" maxlength="4" />
|
||||
</view>>支出最多!
|
||||
</view>
|
||||
<view class="money">
|
||||
占
|
||||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyFrist.percentage }}</text>
|
||||
<input class="percentage-input" type="digit" v-model="moneyFrist.percentage"
|
||||
@input="inputPercentage($event, 'moneyFrist')"></input>
|
||||
@input="inputPercentage($event, 'moneyFrist')" />
|
||||
</view>
|
||||
<view>%</view>
|
||||
</view>
|
||||
|
|
@ -54,7 +54,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneySecond.type }}</text>
|
||||
<input class="percentage-input" type="text" v-model="moneySecond.type"
|
||||
@input="inputPercentage($event, 'moneySecond')"></input>
|
||||
@input="inputPercentage($event, 'moneySecond')" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="money">
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneySecond.percentage }}</text>
|
||||
<input class="percentage-input" type="digit" v-model="moneySecond.percentage"
|
||||
@input="inputPercentage($event, 'moneySecond')"></input>
|
||||
@input="inputPercentage($event, 'moneySecond')" />
|
||||
</view>
|
||||
<view>%</view>
|
||||
</view>
|
||||
|
|
@ -73,7 +73,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyThird.type }}</text>
|
||||
<input class="percentage-input" type="text" v-model="moneyThird.type"
|
||||
@input="inputPercentage($event, 'moneyThird')"></input>
|
||||
@input="inputPercentage($event, 'moneyThird')" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="money">
|
||||
|
|
@ -81,7 +81,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyThird.percentage }}</text>
|
||||
<input class="percentage-input" type="digit" v-model="moneyThird.percentage"
|
||||
@input="inputPercentage($event, 'moneyThird')"></input>
|
||||
@input="inputPercentage($event, 'moneyThird')" />
|
||||
</view>
|
||||
<view>%</view>
|
||||
</view>
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyFourth.type }}</text>
|
||||
<input class="percentage-input" type="text" v-model="moneyFourth.type"
|
||||
@input="inputPercentage($event, 'moneyFourth')"></input>
|
||||
@input="inputPercentage($event, 'moneyFourth')" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="money">
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyFourth.percentage }}</text>
|
||||
<input class="percentage-input" type="digit" v-model="moneyFourth.percentage"
|
||||
@input="inputPercentage($event, 'moneyFourth')"></input>
|
||||
@input="inputPercentage($event, 'moneyFourth')" />
|
||||
</view>
|
||||
<view>%</view>
|
||||
</view>
|
||||
|
|
@ -111,7 +111,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyFifth.type }}</text>
|
||||
<input class="percentage-input" type="text" v-model="moneyFifth.type"
|
||||
@input="inputPercentage($event, 'moneyFifth')"></input>
|
||||
@input="inputPercentage($event, 'moneyFifth')" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="money">
|
||||
|
|
@ -119,7 +119,7 @@
|
|||
<view class="percentage-input-box">
|
||||
<text class="ghost-text">{{ moneyFifth.percentage }}</text>
|
||||
<input class="percentage-input" type="digit" v-model="moneyFifth.percentage"
|
||||
@input="inputPercentage($event, 'moneyFifth')"></input>
|
||||
@input="inputPercentage($event, 'moneyFifth')" />
|
||||
</view>
|
||||
<view>%</view>
|
||||
</view>
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
<!-- <view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view> -->
|
||||
</template>
|
||||
|
|
@ -169,10 +169,9 @@ import {
|
|||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onUnload
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
const statusBarHeight = ref(0);
|
||||
const dialogPopup = ref(null);
|
||||
const timeDialogPopup = ref(null);
|
||||
|
|
@ -203,7 +202,7 @@ const data = reactive({
|
|||
type: '服饰装扮',
|
||||
percentage: "83"
|
||||
},
|
||||
navBarHeight: 0
|
||||
billBgImage: ''
|
||||
})
|
||||
|
||||
let {
|
||||
|
|
@ -214,11 +213,11 @@ let {
|
|||
moneyFourth,
|
||||
moneyFifth,
|
||||
time,
|
||||
navBarHeight
|
||||
billBgImage
|
||||
} = toRefs(data)
|
||||
|
||||
|
||||
onLoad(() => {
|
||||
onLoad(async () => {
|
||||
// 进入花呗页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
|
|
@ -228,6 +227,9 @@ onLoad(() => {
|
|||
time.value = getYesterday();
|
||||
statusBarHeight.value = uni.getSystemInfoSync().statusBarHeight;
|
||||
|
||||
data.billBgImage = await imgLocal.getLocalImage('alipay-bill/main-bg.png');
|
||||
console.log("data.billBgImage", data.billBgImage)
|
||||
|
||||
const config = uni.getStorageSync('config')
|
||||
console.log("---config---", config);
|
||||
const font = config.config['client.uniapp.font']
|
||||
|
|
|
|||
|
|
@ -0,0 +1,178 @@
|
|||
<template>
|
||||
<view>
|
||||
<NavBar :title="data.navBar.title" :bgColor="data.navBar.bgColor" />
|
||||
<view class="list-container">
|
||||
<view class="item" v-for="item in source" :key="item.id"
|
||||
:style="{ background: `linear-gradient( -270deg, ${item.color.bgColor} 0%, #FFFFFF 70%), #FFFFFF` }">
|
||||
<view class="content flex flex-align-center">
|
||||
<image class="logo" :src="`/static/image/common/phone/${item.icon}.png`" mode=""></image>
|
||||
<view class="name flex-1">{{ item.name }}机型</view>
|
||||
<view class="right-button" :style="{ background: item.color.buttonColor }"
|
||||
@click="goPage(data.type == 'message' ? item.messageUrl : item.callUrl)">立即进入</view>
|
||||
</view>
|
||||
<view class="line" :style="{ background: item.color.lineColor }"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad
|
||||
} from "@dcloudio/uni-app";
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js';
|
||||
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
// 列表
|
||||
const source = ref([{
|
||||
name: '苹果',
|
||||
color: {
|
||||
bgColor: '#F3EAFF',
|
||||
lineColor: '#B78EF5',
|
||||
buttonColor: '#BA8DFF',
|
||||
},
|
||||
icon: 'iphone',
|
||||
messageUrl: "/pages/message/list-index?phone=iphone",
|
||||
callUrl: "/pages/call-log/call?type=ios"
|
||||
},
|
||||
{
|
||||
name: '华为',
|
||||
color: {
|
||||
bgColor: '#FFE9E9',
|
||||
lineColor: '#FF6969',
|
||||
buttonColor: '#FB6767',
|
||||
},
|
||||
icon: 'huawei',
|
||||
messageUrl: "/pages/message/list-index?phone=huawei",
|
||||
callUrl: "/pages/call-log/call?type=huawei"
|
||||
},
|
||||
{
|
||||
name: '小米',
|
||||
color: {
|
||||
bgColor: '#FFF0DD',
|
||||
lineColor: '#FFA143',
|
||||
buttonColor: '#FFA64D',
|
||||
},
|
||||
icon: 'mi',
|
||||
messageUrl: "/pages/message/list-index?phone=mi",
|
||||
callUrl: "/pages/call-log/call?type=xiaomi"
|
||||
},
|
||||
{
|
||||
name: 'oppo',
|
||||
color: {
|
||||
bgColor: '#E0FFD9',
|
||||
lineColor: '#56B745',
|
||||
buttonColor: '#5DCD49',
|
||||
},
|
||||
icon: 'oppo',
|
||||
messageUrl: "/pages/message/list-index?phone=oppo",
|
||||
callUrl: "/pages/call-log/call?type=oppo"
|
||||
}, {
|
||||
name: 'vivo',
|
||||
color: {
|
||||
bgColor: '#D4F4FF',
|
||||
lineColor: '#52C2FF',
|
||||
buttonColor: '#50C1FE',
|
||||
},
|
||||
icon: 'vivo',
|
||||
messageUrl: "/pages/message/list-index?phone=vivo",
|
||||
callUrl: "/pages/call-log/call?type=vivo"
|
||||
},
|
||||
])
|
||||
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: '选择机型',
|
||||
bgColor: '#F0F4F9',
|
||||
},
|
||||
type: "message"
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.type) {
|
||||
data.type = options.type
|
||||
}
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: data.type == 'message' ? 'message' : 'call-log',
|
||||
prefix: '.uni.other.',
|
||||
value: data.type == 'message' ? '短信' : "通话"
|
||||
})
|
||||
})
|
||||
|
||||
function goPage(url) {
|
||||
if (url) {
|
||||
util.goPage(url)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
</style>
|
||||
<style lang="less">
|
||||
.list-container {
|
||||
background-color: #F0F4F9;
|
||||
padding: 24rpx 32rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 188rpx;
|
||||
border-radius: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 40rpx 36rpx 24rpx 28rpx;
|
||||
|
||||
.content {
|
||||
.logo {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-left: 32rpx;
|
||||
color: #1A1A1A;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.right-button {
|
||||
width: 140rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 16rpx;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
line-height: 64rpx !important;
|
||||
text-align: center;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100rpx;
|
||||
height: 8rpx;
|
||||
filter: blur(5px);
|
||||
opacity: 0.5;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,83 @@
|
|||
<template>
|
||||
|
||||
<view>
|
||||
<nav-bar title="视频教程" bg-color="transparent">
|
||||
<template v-slot:statusBar>
|
||||
<view class="top-bg-box">
|
||||
<image style="width: 100%;" src="/static/image/common/shipinjiaocheng/top-bg.png" mode="widthFix">
|
||||
</image>
|
||||
</view>
|
||||
</template>
|
||||
</nav-bar>
|
||||
<view class="video-list">
|
||||
<view class="video-item" v-for="item in videoHelpList" :key="item.id" @click="clickVideoHelp(item)">
|
||||
<image class="video-help-img" :src="item.icon"></image>
|
||||
<text class="video-help-title flex-1">{{ item.text }}</text>
|
||||
<uni-icons type="forward" size="18" color="#AEAEAE"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<ZdySafeBottom bgColor="#f0f3f8"/>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { storage } from "../../../utils/storage";
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js'
|
||||
const videoHelpList = ref([]);
|
||||
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
onLoad(() => {
|
||||
const configData = storage.get("config")
|
||||
videoHelpList.value = configData.config['client.uniapp.alipay.video_help'] || []
|
||||
})
|
||||
|
||||
/**
|
||||
* 点击视频教程
|
||||
* @param item
|
||||
*/
|
||||
const clickVideoHelp = (item) => {
|
||||
const url = item.url
|
||||
util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${item.text}`)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.video-list {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 32rpx;
|
||||
margin: 0 32rpx;
|
||||
|
||||
.video-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 32rpx;
|
||||
border-bottom: 1rpx solid #E4E4E4;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.video-help-title {
|
||||
width: 100%;
|
||||
font-size: 32rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 42rpx;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.video-help-img {
|
||||
flex-shrink: 0;
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,18 +1,24 @@
|
|||
<!-- pages/webview/webview.vue -->
|
||||
<template>
|
||||
<view class="webview-container">
|
||||
<navBar class="nav-bar" :title="pageTitle" :bgColor="data.navBar.bgColor" isBack></navBar>
|
||||
<navBar class="nav-bar" :title="pageTitle" :bgColor="data.navBar.bgColor" isBack>
|
||||
<template v-if="isClose" v-slot:right>
|
||||
<image style="width:22px;height: 22px;" src='/static/image/close.png' @click="onConfirm()"></image>
|
||||
</template>
|
||||
</navBar>
|
||||
<web-view :src="url" :webview-styles="webviewStyles"></web-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 自定义头部
|
||||
// import ZdyNavbar from "@/components/navbar/navbar.vue"
|
||||
import navBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import { util } from '@/utils/common.js'
|
||||
// 自定义头部
|
||||
// import ZdyNavbar from "@/components/navbar/navbar.vue"
|
||||
import navBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js'
|
||||
|
||||
import {
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
watch,
|
||||
|
|
@ -22,14 +28,14 @@ import {
|
|||
onBeforeUnmount,
|
||||
toRefs,
|
||||
computed
|
||||
} from "vue";
|
||||
import {
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onReady,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
} from '@dcloudio/uni-app'
|
||||
|
||||
const data = reactive({
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: "",
|
||||
bgColor: '#ffffff',
|
||||
|
|
@ -37,16 +43,21 @@ const data = reactive({
|
|||
dark: "dark",
|
||||
// 状态栏高度
|
||||
systemBarHeight: "0",
|
||||
})
|
||||
isClose: false
|
||||
})
|
||||
|
||||
let {
|
||||
systemBarHeight
|
||||
} = toRefs(data)
|
||||
let {
|
||||
systemBarHeight,
|
||||
isClose
|
||||
} = toRefs(data)
|
||||
|
||||
const url = ref('')
|
||||
const pageTitle = ref('')
|
||||
const url = ref('')
|
||||
const pageTitle = ref('')
|
||||
|
||||
onLoad((options) => {
|
||||
onLoad((options) => {
|
||||
if (options.isClose) {
|
||||
isClose.value = options.isClose
|
||||
}
|
||||
uni.getSystemInfo({
|
||||
success: res => {
|
||||
systemBarHeight.value = res.statusBarHeight; // 获取状态栏高度
|
||||
|
|
@ -70,65 +81,71 @@ onLoad((options) => {
|
|||
console.log("标题", options.title);
|
||||
pageTitle.value = decodeURIComponent(options.title)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500);
|
||||
// #endif
|
||||
})
|
||||
})
|
||||
|
||||
const goBack = () => {
|
||||
const onConfirm = () => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
|
||||
const isVideo = computed(() => {
|
||||
const isVideo = computed(() => {
|
||||
if (!url.value) return false
|
||||
const videoExps = [/\.mp4$/i, /\.m3u8$/i, /\.flv$/i, /\.avi$/i, /\.mov$/i, /\.wmv$/i, /\.webm$/i,
|
||||
/\.mkv$/i
|
||||
];
|
||||
return videoExps.some(exp => exp.test(url.value));
|
||||
})
|
||||
})
|
||||
|
||||
const webviewStyles = computed(() => {
|
||||
const webviewStyles = computed(() => {
|
||||
return {
|
||||
top: `${Number(systemBarHeight.value) + 40}px`,
|
||||
bottom: '0px',
|
||||
'padding-bottom': '20px'
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.webview-container {
|
||||
.webview-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
.header {
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.video-web {
|
||||
.video-web {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: #000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
page {
|
||||
page {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark :dark="data.dark" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark dark="light" source="uni_alipay_finance" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_finance')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container flex flex-column" @touchstart="handleTouchStart" @touchmove.stop.prevent="handleTouchMove"
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="!selectedImage" class="content flex-1 flex-column flex" @touchstart="clickHandleTouchStart"
|
||||
<view v-if="!selectedImage" class="content flex-1 flex-column flex" @touchstart="clickHandleTouchStart" :style="{'padding-bottom':$store.state.safeBottomAz+'px'}"
|
||||
@touchend="clickHandleTouchEnd">
|
||||
<view v-if="financeInfo.bgImage" class="w100 h100" style="margin-top: -1px;">
|
||||
<image class="w100 h100" :src="financeInfo.bgImage" mode="widthFix">
|
||||
|
|
@ -193,8 +193,8 @@
|
|||
|
||||
<!-- 底部导航栏 -->
|
||||
<view class="bottom-box"
|
||||
:class="`navigation-menu-${financeInfo.navigationMenuStyle}`, { 'ios-bottom-box': $system == 'iOS' }">
|
||||
<view class="bottom-item" v-for="item in navigationMenu" :key="item.name" @click="clickBottomItem(item)">
|
||||
:class="`navigation-menu-${financeInfo.navigationMenuStyle}` + ($system == 'iOS' ? ' ios-bottom-box' : '')">
|
||||
<view class="bottom-item" v-for="item in navigationMenu" :key="item.name" @click="clickBottomItem(item)" :style="{'padding-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<image
|
||||
:src="`/static/image/finance-management/navigation-menu/${financeInfo.navigationMenuStyle}/${item.icon}.png`">
|
||||
</image>
|
||||
|
|
@ -244,6 +244,7 @@
|
|||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
import {
|
||||
ref,
|
||||
toRefs,
|
||||
|
|
@ -263,6 +264,7 @@ import {
|
|||
navigationMenu,
|
||||
myAssets
|
||||
} from '@/static/json/fortune.json'
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
import {
|
||||
numberUtil,
|
||||
util
|
||||
|
|
@ -298,7 +300,7 @@ const buttonGroup = [{
|
|||
}
|
||||
}]
|
||||
|
||||
const defualtData = {
|
||||
let defualtData = {
|
||||
benefitsText: '尊享礼遇18000元/年',
|
||||
cardHolderName: 'XiaoMing',
|
||||
vipLevel: "v3",
|
||||
|
|
@ -355,13 +357,16 @@ onReady(() => {
|
|||
}).exec()
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
onShow(async () => {
|
||||
defualtData.bgImage = await imgLocal.getLocalImage('finance-management/bg-style/style-1.png');
|
||||
console.log(defualtData.bgImage)
|
||||
|
||||
financeInfo.value = {
|
||||
...defualtData,
|
||||
...uni.getStorageSync('financeInfo')
|
||||
}
|
||||
console.log("financeInfo.value", financeInfo.value)
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor(financeInfo.value.navigationMenuStyle == 'style-1' ? '#ffffff' : '#F8F8F8')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
@ -580,7 +585,9 @@ const chooseImage = () => {
|
|||
selectedImage.value = res.tempFilePaths[0]
|
||||
data.showMask = true
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
// #endif
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
|
|
@ -659,7 +666,9 @@ const confirmImage = () => {
|
|||
financeInfo.value.bgImage = saveRes.savedFilePath
|
||||
selectedImage.value = '' // 隐藏编辑模式
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
// #endif
|
||||
}, 200)
|
||||
// 保存到缓存
|
||||
uni.setStorageSync("financeInfo", financeInfo.value)
|
||||
|
|
@ -708,7 +717,9 @@ const clickHandleTouchEnd = () => {
|
|||
const closeImage = () => {
|
||||
selectedImage.value = ''
|
||||
data.showMask = false
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
// #endif
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -746,7 +757,7 @@ const closeStyleDialog = () => {
|
|||
const confirmStyleDialog = (type) => {
|
||||
financeInfo.value.navigationMenuStyle = type
|
||||
uni.setStorageSync('financeInfo', financeInfo.value)
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor(financeInfo.value.navigationMenuStyle == 'style-1' ? '#ffffff' : '#F8F8F8')
|
||||
// #endif
|
||||
stylePopup.value.close()
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
<view>
|
||||
<NavBar title="选择理财图片样式" bgColor="#F5F5F5" isRightButton @right-click="handleRightButtonClick"></NavBar>
|
||||
<view class="conatiner flex flex-justify-between">
|
||||
<view v-for="index in 6" :key="index" class="cover-item flex flex-column flex-align-center"
|
||||
<view v-for="(item, index) in bgList" :key="index" class="cover-item flex flex-column flex-align-center"
|
||||
@click="data.selectedImage = index">
|
||||
<view class="image-box" :class="{ 'active': index == data.selectedImage }">
|
||||
<image class="w100 h100" :src="`/static/image/finance-management/covers/cover-${index}.png`"
|
||||
mode="widthFix"></image>
|
||||
<image class="w100 h100" :src="item" mode="widthFix"></image>
|
||||
</view>
|
||||
<view class="text">样式{{ index }}</view>
|
||||
<view class="text">样式{{ index + 1 }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -17,6 +16,8 @@
|
|||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import { ref, reactive, toRefs, onMounted } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
|
||||
const defualtData = {
|
||||
benefitsText: '尊享礼遇18000元/年',
|
||||
|
|
@ -82,6 +83,14 @@ const data = reactive({
|
|||
})
|
||||
|
||||
const { bgImage, selectedImage, financeInfo } = toRefs(data)
|
||||
const bgList = ref([])
|
||||
|
||||
onLoad(async () => {
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
const imgPath = await imgLocal.getLocalImage(`finance-management/covers/cover-${i}.png`)
|
||||
bgList.value.push(imgPath)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
financeInfo.value = {
|
||||
|
|
@ -90,11 +99,12 @@ onMounted(() => {
|
|||
}
|
||||
})
|
||||
|
||||
const handleRightButtonClick = () => {
|
||||
const handleRightButtonClick = async () => {
|
||||
const financeInfoData = {
|
||||
...financeInfo.value
|
||||
}
|
||||
financeInfoData.bgImage = `/static/image/finance-management/bg-style/style-${data.selectedImage}.png`
|
||||
// financeInfoData.bgImage = `finance-management/bg-style/style-${data.selectedImage}.png`
|
||||
financeInfoData.bgImage = await imgLocal.getLocalImage(`finance-management/bg-style/style-${data.selectedImage + 1}.png`)
|
||||
uni.setStorageSync('financeInfo', financeInfoData)
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<view class="container" :style="{ height: data.windowHeight + 'px' }">
|
||||
<image class="index-bg-img" :style="{ width: windowWidth + 'px' }" src="/static/image/index/index-bg.png"
|
||||
mode="widthFix">
|
||||
<image v-if="isReady" class="index-bg-img" :style="{ width: windowWidth + 'px' }"
|
||||
src="/static/image/index/index-bg.png" mode="widthFix">
|
||||
</image>
|
||||
<view class="nav-bar-box" :style="{ backgroundColor: data.navBarBgColor }">
|
||||
<view v-if="isReady" class="nav-bar-box" :style="{ backgroundColor: data.navBarBgColor }">
|
||||
<view class="status-box" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
<view class="nav-box">
|
||||
<view class="left-box" @click="exit" @tap="exit" @touchstart.stop="exit">
|
||||
|
|
@ -15,14 +15,13 @@
|
|||
</view>
|
||||
|
||||
</view>
|
||||
<view class="content-box" :style="{ height: windowHeight + 'px' }">
|
||||
|
||||
<view v-if="isReady" class="content-box" :style="{ height: windowHeight + 'px' }">
|
||||
<scroll-view scroll-y="true" class="scroll-view"
|
||||
:style="{ height: (windowHeight - statusBarHeight - 44) + 'px', marginTop: (statusBarHeight + 44) + 'px' }"
|
||||
@scroll="handleScroll">
|
||||
<view>
|
||||
<!-- iOS专用:透明点击区域覆盖导航栏左上角 -->
|
||||
<view @click="exit" @tap="exit" :style="{
|
||||
<view @click="exit" :style="{
|
||||
position: 'fixed',
|
||||
top: statusBarHeight + 'px',
|
||||
left: '0px',
|
||||
|
|
@ -40,7 +39,7 @@
|
|||
:src="`/static/image/index/${userInfo.vip > 1 ? (userInfo.vip == 3 ? 'lifetime-vip-bg' : 'vip-bg') : 'no-vip-bg'}.png`"
|
||||
mode=""></image>
|
||||
<view class="user-info-box" :style="{ width: (windowWidth - 32) + 'px' }">
|
||||
<image class="user-avatar" :src="userInfo.avater"></image>
|
||||
<image v-if="userInfo.avater" class="user-avatar" :src="userInfo.avater"></image>
|
||||
<view class="user-info">
|
||||
<view class="name-box">
|
||||
<text class="phone-text">ID:{{ userInfo.user_id }}</text>
|
||||
|
|
@ -77,16 +76,16 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<view class="group-box">
|
||||
<!-- <view class="group-box">
|
||||
<image class="title-img" src="/static/image/index/shipingjiaocheng.png"></image>
|
||||
<view class="video-help-box">
|
||||
<view class="video-help-item" :style="{ width: (windowWidth - 50) / 4 + 'px' }"
|
||||
<view class="video-help-item" :style="{ width: (windowWidth - 32) / 4 + 'px' }"
|
||||
v-for="item in videoHelpList" :key="item.id" @click="clickVideoHelp(item)">
|
||||
<image class="video-help-img" :src="item.icon"></image>
|
||||
<text class="video-help-title">{{ item.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<view class="group-box">
|
||||
<image class="title-img" src="/static/image/index/monixiaobao.png"></image>
|
||||
|
|
@ -108,31 +107,36 @@
|
|||
|
||||
<view class="activity-box">
|
||||
<image class="alipay-year-bill" :style="{ width: (windowWidth - 32) + 'px' }"
|
||||
src="/static/image/index/alipay-year-bill.png" mode="widthFix"
|
||||
@click="util.goPage(`/pages/common/alipay-annual-bill/alipay-annual-bill`)"></image>
|
||||
src="/static/image/index/shipinjiaocheng-banner.png" mode="widthFix"
|
||||
@click="util.goPage(`/pages/common/shipinjiaocheng/shipinjiaocheng`)"></image>
|
||||
</view>
|
||||
|
||||
<view class="group-box">
|
||||
<image class="title-img" src="/static/image/index/qita.png"></image>
|
||||
<view class="video-help-box">
|
||||
<view class="video-help-item" :style="{ width: (windowWidth - 50) / 4 + 'px' }"
|
||||
v-for="item in otherList" :key="item.id" @click="clickMenu(item)">
|
||||
<template v-for="item in otherList" :key="item.id">
|
||||
<view class="video-help-item" :style="{ width: (windowWidth - 36) / 4 + 'px' }"
|
||||
@click="clickMenu(item)" v-if="isShowBankIdCard(item)">
|
||||
<image class="video-help-img" :src="item.icon"></image>
|
||||
<text class="video-help-title">{{ item.name }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view style="border: 1px solid red; text-align: center;padding: 10px;" @click="exit">退出模拟器</view> -->
|
||||
|
||||
<view class="footer-box" :class="{ 'ios-padding-bottom': platform === 'ios' }">
|
||||
<text class="vision-text">版本:{{ vision }}</text>
|
||||
<text class="vision-text margin-l-6" v-if="qqgroup.enable">{{ qqgroup.text }}</text>
|
||||
<text class="vision-text" @click="copyNumber(qqgroup.number)">{{ qqgroup.number }}</text>
|
||||
</view>
|
||||
<view v-if="platform != 'ios'" :style="{'height':'40px','background':'#F0F4F9'}">
|
||||
|
||||
</view>
|
||||
<view v-if="platform != 'ios'" class="footer-box-safeBottom" :style="{'height':'40px','background':'#F0F4F9',width:data.windowWidth+'px'}">
|
||||
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
|
@ -158,8 +162,18 @@ import {
|
|||
onLoad,
|
||||
onShow,
|
||||
onHide,
|
||||
onUnload
|
||||
onUnload,
|
||||
onReady
|
||||
} from '@dcloudio/uni-app';
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
onReady(() => {
|
||||
setTimeout(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.navigator.closeSplashscreen();
|
||||
// #endif
|
||||
}, 500);
|
||||
});
|
||||
|
||||
// 内部埋点方法
|
||||
const apiUserEvent = async (type, adminData) => {
|
||||
|
|
@ -189,7 +203,7 @@ const goRechargePage = () => {
|
|||
}
|
||||
})
|
||||
uni.navigateTo({
|
||||
url: '/pages/common/recharge/index'
|
||||
url: '/pages/common/recharge/index?source=uni_alipay_index'
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -218,46 +232,131 @@ const menuList = [{
|
|||
name: "花呗",
|
||||
isHot: false,
|
||||
path: "/pages/ant-credit-pay/index"
|
||||
}, {
|
||||
icon: "zhuanzhang",
|
||||
name: "转账模拟",
|
||||
isHot: false,
|
||||
path: "/pages/balance/transfer/transfer"
|
||||
}, {
|
||||
icon: "zhifuchenggong",
|
||||
name: "支付成功",
|
||||
isHot: false,
|
||||
path: "/pages/balance/pay-successful/pay-successful"
|
||||
}, {
|
||||
icon: "nianduzhangdan",
|
||||
name: "年度账单",
|
||||
isHot: false,
|
||||
path: "/pages/common/alipay-annual-bill/alipay-annual-bill"
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
const otherList = [{
|
||||
icon: "/static/image/index/qita/jipiao.png",
|
||||
name: "机票",
|
||||
path: "/pages/other/tickets-app/index"
|
||||
path: "/pages/other/tickets-app/index?type=airTicket"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/huochepiao.png",
|
||||
name: "火车票",
|
||||
path: "/pages/other/train-tickets/12306-tickets/12306-tickets"
|
||||
// path: "/pages/other/train-tickets/12306-tickets/12306-tickets"
|
||||
path: "/pages/other/tickets-app/index?type=trainTicket"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/gongzidan.png",
|
||||
name: "工资单",
|
||||
path: "/pages/other/splash/splash"
|
||||
icon: "/static/image/index/qita/gouwu.png",
|
||||
name: "购物",
|
||||
path: "/pages/shopping/index"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/other/bank/bank.png",
|
||||
name: "银行卡",
|
||||
path: "/pages/other/bank/index"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/message.png",
|
||||
name: "短信",
|
||||
path: "/pages/common/call-and-message-entry/call-and-message-entry?type=message"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/call.png",
|
||||
name: "通话",
|
||||
path: "/pages/common/call-and-message-entry/call-and-message-entry?type=call"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/shipinqunliao.png",
|
||||
name: "视频群聊",
|
||||
path: "/pages/other/video-group-chat/video-group-chat"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/danliao.png",
|
||||
name: "视频聊天",
|
||||
path: "/pages/other/video-chat/video-chat"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/zhifuchenggong-wx.png",
|
||||
name: "微信支付",
|
||||
path: "/pages/other/wx-payment-success/wx-payment-success"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/gongzidan.png",
|
||||
name: "工资条",
|
||||
path: "/pages/other/splash/splash"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/card.png",
|
||||
name: "身份证",
|
||||
path: "/pages/other/card/card"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/about-iphone.png",
|
||||
name: "关于本机",
|
||||
path: "/pages/other/about-this-iphone/about-this-iphone"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/game.png",
|
||||
name: "游戏",
|
||||
path: "/pages/other/game/index"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/other/certificate/certificate.png",
|
||||
name: "证书",
|
||||
path: "/pages/other/certificate/index"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/other/silkBanner/silkBanner.png",
|
||||
name: "锦旗",
|
||||
path: "/pages/other/silkBanner/silkBanner"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/index/qita/ranking.png",
|
||||
name: "从夯倒拉排名",
|
||||
path: "/pages/other/ranking/ranking"
|
||||
},
|
||||
{
|
||||
icon: "/static/image/other/score/gaokao.png",
|
||||
name: "高考",
|
||||
path: "/pages/other/score/index"
|
||||
},
|
||||
]
|
||||
|
||||
const data = reactive({
|
||||
isReady: false,
|
||||
navBarBgColor: 'transparent',
|
||||
statusBarHeight: 0,
|
||||
windowWidth: 0,
|
||||
windowHeight: 0,
|
||||
windowWidth: 390, // 防0导致初次Weex负数高度白屏崩溃
|
||||
windowHeight: 844, // 防0导致初次Weex负数高度白屏崩溃
|
||||
userInfo: {},
|
||||
videoHelpList: [],
|
||||
noticeInfo: {},
|
||||
vision: "",
|
||||
platform: '', // 添加平台信息,
|
||||
qqgroup: {}
|
||||
qqgroup: {},
|
||||
idcard: false,
|
||||
bank: false,
|
||||
payslip: false,
|
||||
score: false,
|
||||
})
|
||||
|
||||
const {
|
||||
isReady,
|
||||
statusBarHeight,
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
|
|
@ -289,24 +388,58 @@ onLoad(async () => {
|
|||
data.vision = uni.getStorageSync('version')
|
||||
})
|
||||
|
||||
const updateSystemSize = () => {
|
||||
try {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
// 防止安卓宿主中首次热更新进入,短暂状态下获取宽高均为0导致的白屏bug
|
||||
if (systemInfo.windowHeight > 0 && systemInfo.windowWidth > 0) {
|
||||
data.statusBarHeight = systemInfo.statusBarHeight;
|
||||
data.windowWidth = systemInfo.windowWidth;
|
||||
data.windowHeight = systemInfo.windowHeight;
|
||||
|
||||
// 针对部分小米/底层ROM的顽疾:
|
||||
// 强制延迟挂载超重DOM,让其宿主完全完成测绘后再放入节点,避免Weex渲染主线程卡死白屏
|
||||
setTimeout(() => {
|
||||
data.isReady = true;
|
||||
}, 300);
|
||||
} else {
|
||||
// 未获取到正常宽高,延迟再次进行重试
|
||||
setTimeout(updateSystemSize, 100);
|
||||
}
|
||||
} catch (error) {
|
||||
setTimeout(updateSystemSize, 100);
|
||||
}
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
// 启动时获取数据
|
||||
fetchUserData()
|
||||
// 每次显示时刷新数据
|
||||
setUserData()
|
||||
// 获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
data.statusBarHeight = systemInfo.statusBarHeight;
|
||||
data.windowWidth = systemInfo.windowWidth;
|
||||
data.windowHeight = systemInfo.windowHeight;
|
||||
// 循环检测更新真实屏幕宽高
|
||||
updateSystemSize();
|
||||
// #ifdef APP-PLUS
|
||||
util.setAndroidSystemBarColor('#F0F4F9')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500)
|
||||
// util.setAndroidSystemBarColor('#F0F4F9');
|
||||
// plus.navigator.setStatusBarStyle("dark");
|
||||
}, 800);
|
||||
// #endif
|
||||
})
|
||||
|
||||
function isShowBankIdCard(item) {
|
||||
if (item.name != '银行卡' && item.name != '身份证' && item.name != '工资条' && item.name != '高考') {
|
||||
return true
|
||||
} else if (item.name == '银行卡' && data.bank) {
|
||||
return true
|
||||
} else if (item.name == '身份证' && data.idcard) {
|
||||
return true
|
||||
} else if (item.name == '工资条' && data.payslip) {
|
||||
return true
|
||||
} else if (item.name == '高考' && data.score) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 获取用户数据(从服务器)
|
||||
*/
|
||||
|
|
@ -330,11 +463,23 @@ const fetchUserData = async () => {
|
|||
|
||||
// 处理用户配置结果
|
||||
if (configResult.status === 'fulfilled') {
|
||||
console.log('用户配置获取成功')
|
||||
console.log('用户配置获取成功', configResult)
|
||||
} else {
|
||||
console.error('获取用户配置失败:', configResult.reason)
|
||||
}
|
||||
|
||||
if (configResult.value.config['client.uniapp.bank'] || false) {
|
||||
data.bank = true
|
||||
}
|
||||
if (configResult.value.config['client.uniapp.idcard'] || false) {
|
||||
data.idcard = true
|
||||
}
|
||||
if (configResult.value.config['client.uniapp.score'] || false) {
|
||||
data.score = true
|
||||
}
|
||||
if (configResult.value.config['client.uniapp.payslip'] || false) {
|
||||
data.payslip = true
|
||||
}
|
||||
// 刷新页面数据
|
||||
setUserData()
|
||||
|
||||
|
|
@ -387,7 +532,7 @@ const setUserData = () => {
|
|||
const userInfoData = storage.get("userInfo")
|
||||
data.userInfo = userInfoData || {
|
||||
user_id: '加载中...',
|
||||
avater: '/static/default-avatar.png',
|
||||
avater: '',
|
||||
vip: 0,
|
||||
vip_expire: ''
|
||||
}
|
||||
|
|
@ -445,15 +590,6 @@ const openVip = () => {
|
|||
goRechargePage()
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击视频教程
|
||||
* @param item
|
||||
*/
|
||||
const clickVideoHelp = (item) => {
|
||||
const url = item.url
|
||||
util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${item.text}`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击公告
|
||||
*/
|
||||
|
|
@ -461,7 +597,7 @@ const clickNotice = () => {
|
|||
console.log("点击公告", noticeInfo.value)
|
||||
if (!noticeInfo.value.url) return
|
||||
const url = noticeInfo.value.url + `&uni_id=${userInfo.value.user_id}`
|
||||
util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${noticeInfo.value.title}`)
|
||||
util.goPage(`/pages/common/webview/webview?url=${encodeURIComponent(url)}&title=${noticeInfo.value.title}&isClose=${true}`)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -499,7 +635,9 @@ const exit = () => {
|
|||
console.log('宿主App回传的数据:' + ret);
|
||||
});
|
||||
} else {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.runtime.quit();
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -633,6 +771,11 @@ onUnload(() => {
|
|||
})
|
||||
</script>
|
||||
<style>
|
||||
.footer-box-safeBottom{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.container {
|
||||
background-color: #F0F4F9;
|
||||
}
|
||||
|
|
@ -830,7 +973,7 @@ onUnload(() => {
|
|||
}
|
||||
|
||||
.group-box {
|
||||
margin: 32rpx;
|
||||
margin: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
|
@ -843,7 +986,7 @@ onUnload(() => {
|
|||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-start;
|
||||
background-color: #FFFFFF;
|
||||
padding: 24rpx 0;
|
||||
border-radius: 24rpx;
|
||||
|
|
@ -887,7 +1030,7 @@ onUnload(() => {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 32rpx;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
|
|
@ -924,6 +1067,7 @@ onUnload(() => {
|
|||
|
||||
.activity-box {
|
||||
margin: 0 32rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
|
|
@ -933,6 +1077,7 @@ onUnload(() => {
|
|||
justify-content: center;
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 10rpx;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.vision-text {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,234 @@
|
|||
[
|
||||
{
|
||||
"id": 12365458895222,
|
||||
"unRead": true,
|
||||
"unReadNumber": 2,
|
||||
"noNotice": true,
|
||||
"img": "",
|
||||
"title": "京东快递",
|
||||
"content": "【京东快递】您的快递已送达博朗郡二期...",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-001-a1",
|
||||
"time": "2026-03-15 10:24",
|
||||
"content": "<p>【京东快递】快递尾号29398已放在博朗郡二期惠美家便利店,快递员电话15320547739。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
},
|
||||
{
|
||||
"id": "uuid-001-a2",
|
||||
"time": "2026-03-16 08:31",
|
||||
"content": "<p>【京东快递】您的包裹已签收,感谢使用京东快递,期待再次为您服务。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
}
|
||||
],
|
||||
"time": "2026-03-16 08:31:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895223,
|
||||
"unRead": false,
|
||||
"unReadNumber": 0,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "招商银行",
|
||||
"content": "【招商银行】账户变动提醒",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-002-b1",
|
||||
"time": "2026-03-15 12:00",
|
||||
"content": "<p>【招商银行】您尾号8888的账户于03月15日11:58收入人民币90000.00元,余额965600.50元。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
}
|
||||
],
|
||||
"time": "2026-03-15 12:00:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895224,
|
||||
"unRead": true,
|
||||
"unReadNumber": 1,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "中国移动",
|
||||
"content": "【中国移动】流量使用周报",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-003-c1",
|
||||
"time": "2026-03-14 09:00",
|
||||
"content": "<p>【中国移动】截至14日09时,您本月已使用通用流量18.5GB,剩余3.2GB。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
},
|
||||
{
|
||||
"id": "uuid-003-c2",
|
||||
"time": "2026-03-14 18:30",
|
||||
"content": "<p>【中国移动】流量包订购成功!您已成功领取5GB周末流量包,立即生效。</p>",
|
||||
"isMe": false,
|
||||
"simKa: 1"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-14 18:30:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895225,
|
||||
"unRead": false,
|
||||
"unReadNumber": 0,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "验证码中心",
|
||||
"content": "【抖音】您的验证码是 882931",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-004-d1",
|
||||
"time": "2026-03-16 01:10",
|
||||
"content": "<p>【抖音】验证码 882931,用于手机绑定。5分钟内有效,请勿泄露给他人。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
}
|
||||
],
|
||||
"time": "2026-03-16 01:10:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895226,
|
||||
"unRead": false,
|
||||
"unReadNumber": 0,
|
||||
"noNotice": true,
|
||||
"img": "",
|
||||
"title": "美团外卖",
|
||||
"content": "【美团】订单配送通知",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-005-e1",
|
||||
"time": "2026-03-15 18:30",
|
||||
"content": "<p>【美团】商家已接单,骑手正在赶往商家,请耐心等待。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 2
|
||||
},
|
||||
{
|
||||
"id": "uuid-005-e2",
|
||||
"time": "2026-03-15 19:15",
|
||||
"content": "<p>【美团】骑手已送达!祝您用餐愉快,给个五星好评吧!</p>",
|
||||
"isMe": false,
|
||||
"simKa": 2
|
||||
}
|
||||
],
|
||||
"time": "2026-03-15 19:15:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895227,
|
||||
"unRead": true,
|
||||
"unReadNumber": 3,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "建设银行",
|
||||
"content": "【建设银行】还款提醒",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-006-f1",
|
||||
"time": "2026-03-10 10:00",
|
||||
"content": "<p>【建设银行】您03月信用卡账单已出,应还款额为¥3,200.00。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
},
|
||||
{
|
||||
"id": "uuid-006-f2",
|
||||
"time": "2026-03-13 14:00",
|
||||
"content": "<p>【建设银行】温馨提醒:您的账单将于3天后到期,请确保扣款账户余额充足。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
},
|
||||
{
|
||||
"id": "uuid-006-f3",
|
||||
"time": "2026-03-16 09:00",
|
||||
"content": "<p>【建设银行】扣款成功。感谢您使用建设银行信用卡。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
}
|
||||
],
|
||||
"time": "2026-03-16 09:00:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895228,
|
||||
"unRead": false,
|
||||
"unReadNumber": 0,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "12306",
|
||||
"content": "【12306】购票成功通知",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-007-g1",
|
||||
"time": "2026-03-11 11:00",
|
||||
"content": "<p>【12306】订单EG12345678支付成功。北京南-上海虹桥,03月20日14:00开。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 2
|
||||
}
|
||||
],
|
||||
"time": "2026-03-11 11:00:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895229,
|
||||
"unRead": false,
|
||||
"unReadNumber": 0,
|
||||
"noNotice": true,
|
||||
"img": "",
|
||||
"title": "腾讯科技",
|
||||
"content": "【腾讯科技】安全提醒",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-008-h1",
|
||||
"time": "2026-03-13 22:30",
|
||||
"content": "<p>【腾讯科技】您的QQ账号在异地登录,登录地点:广州。如非本人操作请及时改密。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
}
|
||||
],
|
||||
"time": "2026-03-13 22:30:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895230,
|
||||
"unRead": true,
|
||||
"unReadNumber": 1,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "菜鸟驿站",
|
||||
"content": "【菜鸟驿站】取件通知",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-009-i1",
|
||||
"time": "2026-03-16 10:15",
|
||||
"content": "<p>【菜鸟驿站】您的中通包裹已到达。凭取件码 8-2-4002 领取,地址:博朗郡东门。</p>",
|
||||
"isMe": false,
|
||||
"simKa: 1"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-16 10:15:00"
|
||||
},
|
||||
{
|
||||
"id": 12365458895231,
|
||||
"unRead": false,
|
||||
"unReadNumber": 0,
|
||||
"noNotice": false,
|
||||
"img": "",
|
||||
"title": "阿里云",
|
||||
"content": "【阿里云】资源包即将到期",
|
||||
"chatList": [
|
||||
{
|
||||
"id": "uuid-010-j1",
|
||||
"time": "2026-03-12 09:00",
|
||||
"content": "<p>【阿里云】尊敬的用户,您的OSS存储包将于7天后到期,请及时续费。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
},
|
||||
{
|
||||
"id": "uuid-010-j2",
|
||||
"time": "2026-03-15 15:00",
|
||||
"content": "<p>【阿里云】续费成功。您的OSS存储包有效期已延长至2027年03月。</p>",
|
||||
"isMe": false,
|
||||
"simKa": 1
|
||||
}
|
||||
],
|
||||
"time": "2026-03-15 15:00:00"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,778 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_other_message" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_message')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view>
|
||||
<MessageNavBar :phone="data.phone" :isScroll="data.isScroll" @add="openAddPopup" @setSim="setSim"
|
||||
:noticeCount="allNoticeCount" @setNoticeCount="setNoticeCount">
|
||||
<view v-if="data.phone == 'huawei'" class="huawei-notice">
|
||||
<view class="img-box">
|
||||
<image class="img" src="/static/image/phone-message/huawei/notice.png" mode="aspectFill"></image>
|
||||
<view class="dot" v-if="data.noticeCount > 0">{{ data.noticeCount > 99 ? '99+' : data.noticeCount }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="text">通知信息</view>
|
||||
<image class="right-img" src="/static/image/phone-message/huawei/right.png" mode="aspectFill"></image>
|
||||
</view>
|
||||
<MessageList :phone="data.phone" :list="defaultList" @item-click="itemClick" @delete-item="deleteItem"
|
||||
@edit-item="editItem">
|
||||
</MessageList>
|
||||
</MessageNavBar>
|
||||
<ZdySafeBottom v-if="data.phone!='oppo'&&data.phone!='xiaomi'" bgColor="#fff"/>
|
||||
<!-- 添加短信弹窗 -->
|
||||
<view v-if="showAddPopup" class="add-mask" @tap="closeAddPopup">
|
||||
<view class="add-popup" @tap.stop>
|
||||
<view class="add-header">{{ editingItem ? '编辑短信' : '新建短信' }}</view>
|
||||
<view class="add-body">
|
||||
<view class="add-row">
|
||||
<text class="add-label">头像URL:</text>
|
||||
<view style="position: relative;">
|
||||
<view class="image-box" :class="addForm.imgShape" style="width: 84rpx;height: 84rpx;"
|
||||
@tap="selectImage">
|
||||
<image v-if="addForm.img" class="image w100 h100" :src="addForm.img" mode="aspectFill">
|
||||
</image>
|
||||
<image v-else class="image w100 h100" src="/static/image/phone-message/add.png"
|
||||
mode="aspectFill">
|
||||
</image>
|
||||
</view>
|
||||
<view v-if="addForm.img" class="delete-img-icon" @tap.stop="deleteImage">
|
||||
×
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="data.phone == 'iphone'"
|
||||
style="flex: 1;display: flex;align-items: center;justify-content: flex-end;">
|
||||
<uni-data-checkbox style="display: flex;justify-content: flex-end;"
|
||||
v-model="addForm.imgShape" :localdata="shape"></uni-data-checkbox>
|
||||
</view>
|
||||
</view>
|
||||
<view class="add-row">
|
||||
<text class="add-label required">联系人</text>
|
||||
<input class="add-input" v-model="addForm.title" placeholder="请输入名称或号码" />
|
||||
</view>
|
||||
<view class="add-row" v-if="data.phone == 'oppo'">
|
||||
<text class="add-label">地区</text>
|
||||
<input class="add-input" v-model="addForm.area" placeholder="请输入地区" />
|
||||
</view>
|
||||
<view class="add-row between" v-if="data.phone == 'iphone'">
|
||||
<text class="add-label">取消通知</text>
|
||||
<switch :checked="addForm.noNotice" @change="addForm.noNotice = !addForm.noNotice" />
|
||||
</view>
|
||||
<view class="add-row between">
|
||||
<text class="add-label">是否未读</text>
|
||||
<switch :checked="addForm.unRead" @change="addForm.unRead = !addForm.unRead" />
|
||||
</view>
|
||||
<view class="add-row"
|
||||
v-if="addForm.unRead && (data.phone == 'oppo' || data.phone == 'huawei' || data.phone == 'iphone')">
|
||||
<text class="add-label">未读数量</text>
|
||||
<input class="add-input" type="number" v-model="addForm.unReadNumber" placeholder="请输入未读数量" />
|
||||
</view>
|
||||
<view class="add-row" v-if="addForm.chatList.length == 0 && editingItem">
|
||||
<text class="add-label">消息时间</text>
|
||||
<view class="time-picker-group">
|
||||
<picker mode="date" :value="addForm.date" @change="onAddDateChange">
|
||||
<view class="time-picker-item">
|
||||
<text>{{ addForm.date || '选择日期' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
<picker mode="time" :value="addForm.timeOfDay" @change="onAddTimeChange">
|
||||
<view class="time-picker-item">
|
||||
<text>{{ addForm.timeOfDay || '选择时刻' }}</text>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="add-footer">
|
||||
<view class="add-btn cancel" @tap="closeAddPopup">取消</view>
|
||||
<view class="add-btn confirm" @tap="confirmAdd">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 设置运营商弹窗 -->
|
||||
<view v-if="showSimPopup" class="add-mask" @tap="closeSimPopup">
|
||||
<view class="add-popup" @tap.stop>
|
||||
<view class="add-header">设置卡1卡2运营商</view>
|
||||
<view class="add-body">
|
||||
<view class="add-row">
|
||||
<text class="add-label">卡1运营商</text>
|
||||
<input class="add-input" v-model="simForm.sim1" placeholder="请输入卡1运营商名称" />
|
||||
</view>
|
||||
<view class="add-row">
|
||||
<text class="add-label">卡2运营商</text>
|
||||
<input class="add-input" v-model="simForm.sim2" placeholder="请输入卡2运营商名称" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="add-footer">
|
||||
<view class="add-btn cancel" @tap="closeSimPopup">取消</view>
|
||||
<view class="add-btn confirm" @tap="confirmSim">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 设置通知信息未读数弹窗 -->
|
||||
<view v-if="showNoticePopup" class="add-mask" @tap="closeNoticePopup">
|
||||
<view class="add-popup" @tap.stop>
|
||||
<view class="add-header">设置通知信息</view>
|
||||
<view class="add-body">
|
||||
<view class="add-row">
|
||||
<text class="add-label">未读数量</text>
|
||||
<input class="add-input" type="number" v-model="noticeForm.count" placeholder="请输入通知信息数量" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="add-footer">
|
||||
<view class="add-btn cancel" @tap="closeNoticePopup">取消</view>
|
||||
<view class="add-btn confirm" @tap="confirmNotice">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import MessageNavBar from '@/components/message/list/message-nav-bar.vue'
|
||||
import MessageList from '@/components/message/list/list.vue'
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
import defaultData from './defaultData.json'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
computed
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onPageScroll
|
||||
} from "@dcloudio/uni-app";
|
||||
import {
|
||||
stringUtil,
|
||||
util
|
||||
} from '@/utils/common.js';
|
||||
|
||||
const defaultList = ref(defaultData)
|
||||
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: '信息',
|
||||
bgColor: '#FFFFFF',
|
||||
},
|
||||
phone: 'iphone',
|
||||
isScroll: false,
|
||||
noticeCount: 256
|
||||
})
|
||||
|
||||
const shape = [{
|
||||
text: '圆形',
|
||||
value: 'circle'
|
||||
}, {
|
||||
text: '方形',
|
||||
value: 'square',
|
||||
}]
|
||||
|
||||
const STORAGE_KEY = 'message_list'
|
||||
const SIM_STORAGE_KEY = 'sim_info'
|
||||
const NOTICE_COUNT_KEY = 'huawei_notice_count'
|
||||
|
||||
const allNoticeCount = computed(() => {
|
||||
let count = 0
|
||||
defaultList.value.forEach(element => {
|
||||
if (element.unRead) {
|
||||
count += element.unReadNumber
|
||||
}
|
||||
});
|
||||
return Number(data.noticeCount) + Number(count)
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.phone) {
|
||||
data.phone = options.phone
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
if (data.phone == 'oppo') {
|
||||
util.setAndroidSystemBarColor('#FAFAFA')
|
||||
} else {
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
}
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500)
|
||||
// #endif
|
||||
// 优先从缓存加载列表
|
||||
try {
|
||||
const cached = uni.getStorageSync(STORAGE_KEY)
|
||||
if (cached) {
|
||||
defaultList.value = JSON.parse(cached)
|
||||
}
|
||||
// 加载通知数量
|
||||
const cachedNotice = uni.getStorageSync(NOTICE_COUNT_KEY)
|
||||
if (cachedNotice !== '') {
|
||||
data.noticeCount = Number(cachedNotice)
|
||||
}
|
||||
} catch (e) { console.error(e) }
|
||||
})
|
||||
|
||||
|
||||
onPageScroll((e) => {
|
||||
if (e.scrollTop > 60) {
|
||||
data.isScroll = true
|
||||
} else {
|
||||
data.isScroll = false
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* 将图片保存到本地持久化存储
|
||||
* @param {string} tempFilePath 临时文件路径
|
||||
* @returns {Promise<string>} 持久化后的文件路径
|
||||
*/
|
||||
const saveImageToLocal = (tempFilePath) => {
|
||||
return new Promise((resolve) => {
|
||||
// 如果是已经持久化的路径或是静态资源,直接返回
|
||||
if (!tempFilePath || tempFilePath.startsWith('_doc') || tempFilePath.startsWith('/static')) {
|
||||
return resolve(tempFilePath)
|
||||
}
|
||||
uni.saveFile({
|
||||
tempFilePath: tempFilePath,
|
||||
success: (res) => {
|
||||
console.log('图片持久化成功:', res.savedFilePath)
|
||||
resolve(res.savedFilePath)
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('图片持久化失败:', err)
|
||||
resolve(tempFilePath) // 失败则回退使用原路径,确保业务不中断
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除本地持久化文件
|
||||
* @param {string} filePath 文件路径
|
||||
*/
|
||||
const removeLocalFile = (filePath) => {
|
||||
if (filePath && filePath.startsWith('_doc')) {
|
||||
uni.removeSavedFile({
|
||||
filePath: filePath,
|
||||
success: () => {
|
||||
console.log('本地文件删除成功:', filePath)
|
||||
},
|
||||
fail: (err) => {
|
||||
console.warn('本地文件删除失败:', filePath, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除元素
|
||||
* @param item
|
||||
*/
|
||||
const deleteItem = (item) => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要删除吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
const idx = defaultList.value.findIndex(i => i.id === item.id)
|
||||
if (idx > -1) {
|
||||
// 删除关联的本地图片文件(头像)
|
||||
if (item.img) {
|
||||
removeLocalFile(item.img)
|
||||
}
|
||||
// 删除该对话中所有的图片文件
|
||||
if (item.chatList && item.chatList.length > 0) {
|
||||
item.chatList.forEach(msg => {
|
||||
if (msg.type === 'image' && msg.imgUrl && msg.imgUrl.includes('_doc/')) {
|
||||
removeLocalFile(msg.imgUrl)
|
||||
}
|
||||
})
|
||||
}
|
||||
defaultList.value.splice(idx, 1)
|
||||
uni.setStorageSync(STORAGE_KEY, JSON.stringify(defaultList.value))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择图片
|
||||
*/
|
||||
const selectImage = () => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
addForm.img = res.tempFilePaths[0]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const deleteImage = () => {
|
||||
addForm.img = ''
|
||||
}
|
||||
|
||||
const itemClick = (item) => {
|
||||
util.goPage(`/pages/message/chat-page/chat-page?phone=${data.phone}&id=${item.id}`)
|
||||
}
|
||||
|
||||
// ===== 添加短信弹窗 =====
|
||||
const showAddPopup = ref(false)
|
||||
const addForm = reactive({
|
||||
title: '',
|
||||
img: '',
|
||||
content: '',
|
||||
date: '',
|
||||
timeOfDay: ''
|
||||
})
|
||||
|
||||
// 弹窗模式:null=新增,有值=编辑中的条目
|
||||
const editingItem = ref(null)
|
||||
|
||||
const openAddPopup = () => {
|
||||
// 重置表单,默认时间为当前
|
||||
const now = new Date()
|
||||
const pad = v => String(v).padStart(2, '0')
|
||||
editingItem.value = null
|
||||
addForm.title = ''
|
||||
addForm.img = ''
|
||||
addForm.content = ''
|
||||
addForm.area = ''
|
||||
addForm.unRead = false
|
||||
addForm.unReadNumber = 1
|
||||
addForm.noNotice = false
|
||||
addForm.chatList = []
|
||||
addForm.imgShape = 'circle'
|
||||
addForm.date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`
|
||||
addForm.timeOfDay = `${pad(now.getHours())}:${pad(now.getMinutes())}`
|
||||
showAddPopup.value = true
|
||||
}
|
||||
|
||||
const closeAddPopup = () => {
|
||||
showAddPopup.value = false
|
||||
}
|
||||
|
||||
const onAddDateChange = (e) => {
|
||||
addForm.date = e.detail.value
|
||||
}
|
||||
|
||||
const onAddTimeChange = (e) => {
|
||||
addForm.timeOfDay = e.detail.value
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑元素:回填表单并打开弹窗
|
||||
*/
|
||||
const editItem = (item) => {
|
||||
editingItem.value = item
|
||||
const lastMsg = item.chatList && item.chatList.length ? item.chatList[item.chatList.length - 1] : null
|
||||
const timeStr = lastMsg ? lastMsg.time : (item.time || '')
|
||||
const parts = timeStr.split(' ')
|
||||
addForm.title = item.title || ''
|
||||
addForm.img = item.img || ''
|
||||
addForm.imgShape = item.imgShape || 'circle'
|
||||
addForm.content = ''
|
||||
addForm.area = item.area || ''
|
||||
addForm.unRead = !!item.unRead
|
||||
addForm.unReadNumber = item.unReadNumber || 0
|
||||
addForm.noNotice = item.noNotice || false
|
||||
addForm.date = parts[0] || ''
|
||||
addForm.timeOfDay = parts[1] || ''
|
||||
addForm.chatList = item.chatList || []
|
||||
showAddPopup.value = true
|
||||
}
|
||||
|
||||
const confirmAdd = async () => {
|
||||
if (!addForm.title.trim()) {
|
||||
uni.showToast({ title: '请输入联系人名称', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
const time = `${addForm.date} ${addForm.timeOfDay}`.trim()
|
||||
|
||||
// 处理图片持久化
|
||||
let finalImgPath = addForm.img
|
||||
if (editingItem.value) {
|
||||
// 编辑模式:如果图片发生了变化,保存新图并删除旧图
|
||||
if (addForm.img !== editingItem.value.img) {
|
||||
finalImgPath = await saveImageToLocal(addForm.img)
|
||||
removeLocalFile(editingItem.value.img)
|
||||
}
|
||||
} else {
|
||||
// 新增模式:直接持久化
|
||||
finalImgPath = await saveImageToLocal(addForm.img)
|
||||
}
|
||||
|
||||
if (editingItem.value) {
|
||||
// ===== 编辑模式:更新已有条目 =====
|
||||
const idx = defaultList.value.findIndex(i => i.id === editingItem.value.id)
|
||||
if (idx > -1) {
|
||||
defaultList.value[idx].title = addForm.title.trim()
|
||||
defaultList.value[idx].img = finalImgPath
|
||||
defaultList.value[idx].unRead = addForm.unRead
|
||||
defaultList.value[idx].unReadNumber = addForm.unReadNumber
|
||||
defaultList.value[idx].noNotice = addForm.noNotice
|
||||
defaultList.value[idx].imgShape = addForm.imgShape
|
||||
defaultList.value[idx].area = addForm.area
|
||||
defaultList.value[idx].time = time
|
||||
}
|
||||
} else {
|
||||
// ===== 新增模式 =====
|
||||
const newItem = {
|
||||
id: Date.now(),
|
||||
unRead: addForm.unRead,
|
||||
unReadNumber: addForm.unReadNumber,
|
||||
noNotice: addForm.noNotice,
|
||||
img: finalImgPath,
|
||||
title: addForm.title.trim(),
|
||||
imgShape: addForm.imgShape,
|
||||
area: addForm.area,
|
||||
chatList: addForm.content.trim() ? [
|
||||
{
|
||||
id: stringUtil.uuid(),
|
||||
time: time,
|
||||
content: `<p>${addForm.content.trim()}</p>`,
|
||||
isMe: false
|
||||
}
|
||||
] : [],
|
||||
time: time
|
||||
}
|
||||
defaultList.value.unshift(newItem)
|
||||
}
|
||||
|
||||
// 按最新消息时间降序排列
|
||||
defaultList.value.sort((a, b) => {
|
||||
const timeA = new Date(((a.chatList && a.chatList.length ? a.chatList[a.chatList.length - 1].time : null) || a.time || '').replace(/-/g, '/')).getTime()
|
||||
const timeB = new Date(((b.chatList && b.chatList.length ? b.chatList[b.chatList.length - 1].time : null) || b.time || '').replace(/-/g, '/')).getTime()
|
||||
return timeB - timeA
|
||||
})
|
||||
try {
|
||||
uni.setStorageSync(STORAGE_KEY, JSON.stringify(defaultList.value))
|
||||
} catch (e) { console.error(e) }
|
||||
closeAddPopup()
|
||||
}
|
||||
|
||||
// ===== 设置运营商弹窗 =====
|
||||
const showSimPopup = ref(false)
|
||||
const simForm = reactive({
|
||||
sim1: '',
|
||||
sim2: ''
|
||||
})
|
||||
|
||||
const setSim = () => {
|
||||
try {
|
||||
const cached = uni.getStorageSync(SIM_STORAGE_KEY)
|
||||
const simInfo = cached ? JSON.parse(cached) : { sim1: '中国电信', sim2: '中国移动' }
|
||||
simForm.sim1 = simInfo.sim1
|
||||
simForm.sim2 = simInfo.sim2
|
||||
} catch (e) {
|
||||
simForm.sim1 = '中国电信'
|
||||
simForm.sim2 = '中国移动'
|
||||
}
|
||||
showSimPopup.value = true
|
||||
}
|
||||
|
||||
const closeSimPopup = () => {
|
||||
showSimPopup.value = false
|
||||
}
|
||||
|
||||
const confirmSim = () => {
|
||||
try {
|
||||
uni.setStorageSync(SIM_STORAGE_KEY, JSON.stringify({
|
||||
sim1: simForm.sim1.trim() || '联通',
|
||||
sim2: simForm.sim2.trim() || '移动'
|
||||
}))
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
} catch (e) { console.error(e) }
|
||||
closeSimPopup()
|
||||
}
|
||||
|
||||
// ===== 设置通知信息未读数弹窗 =====
|
||||
const showNoticePopup = ref(false)
|
||||
const noticeForm = reactive({
|
||||
count: 256
|
||||
})
|
||||
|
||||
const setNoticeCount = () => {
|
||||
noticeForm.count = data.noticeCount
|
||||
showNoticePopup.value = true
|
||||
}
|
||||
|
||||
const closeNoticePopup = () => {
|
||||
showNoticePopup.value = false
|
||||
}
|
||||
|
||||
const confirmNotice = () => {
|
||||
data.noticeCount = Number(noticeForm.count) || 0
|
||||
try {
|
||||
uni.setStorageSync(NOTICE_COUNT_KEY, data.noticeCount)
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
} catch (e) { console.error(e) }
|
||||
closeNoticePopup()
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
|
||||
page {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
::v-deep .uni-navbar__header-btns {
|
||||
width: 100px !important;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.iphone-style {
|
||||
.mg-r-30 {
|
||||
margin-right: 60rpx;
|
||||
}
|
||||
|
||||
.mg-r-5 {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
|
||||
.left-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
.left-text {
|
||||
font-size: 32rpx;
|
||||
color: #0278E2;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
|
||||
.center-text {
|
||||
font-size: 32rpx;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
}
|
||||
|
||||
.mi-style {
|
||||
.right-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== 添加短信弹窗 ===== */
|
||||
.add-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.add-popup {
|
||||
width: 88%;
|
||||
background-color: #ffffff;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.add-header {
|
||||
padding: 36rpx 40rpx 20rpx;
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #1A1A1A;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.add-body {
|
||||
padding: 8rpx 0;
|
||||
}
|
||||
|
||||
.add-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 32rpx;
|
||||
gap: 16rpx;
|
||||
|
||||
.image-box {
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.square {
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.required {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.required::before {
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
content: '*';
|
||||
top: 0;
|
||||
color: #EA0000;
|
||||
}
|
||||
|
||||
.add-label {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
width: 150rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.add-input {
|
||||
flex: 1;
|
||||
height: 70rpx;
|
||||
background-color: #F6F6F6;
|
||||
border-radius: 14rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
|
||||
::v-deep .uni-input {
|
||||
color: #aaaaaa;
|
||||
}
|
||||
}
|
||||
|
||||
.add-footer {
|
||||
padding: 32rpx 24rpx;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
flex: 1;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
background-color: #F1F1F1;
|
||||
margin: 0 16rpx;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.add-btn.cancel {
|
||||
color: #767676;
|
||||
}
|
||||
|
||||
.add-btn.confirm {
|
||||
color: #fff;
|
||||
background-color: #1777FF;
|
||||
}
|
||||
|
||||
.time-picker-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 16rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.time-picker-item {
|
||||
flex: 1;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
background-color: #F8F8F8;
|
||||
border-radius: 8rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333333;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.huawei-notice {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 32rpx;
|
||||
height: 124rpx;
|
||||
|
||||
.img-box {
|
||||
position: relative;
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
flex-shrink: 0;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dot {
|
||||
position: absolute;
|
||||
top: -12rpx;
|
||||
right: -8rpx;
|
||||
height: 28rpx;
|
||||
line-height: 30rpx;
|
||||
padding: 0 10rpx;
|
||||
background-color: #EA0000;
|
||||
border-radius: 16rpx;
|
||||
font-size: 20rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
flex: 1;
|
||||
font-size: 30rpx;
|
||||
color: #1A1A1A;
|
||||
margin: 0 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.right-img {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.delete-img-icon {
|
||||
position: absolute;
|
||||
top: -12rpx;
|
||||
right: -12rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
padding-bottom: 2rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,425 @@
|
|||
<template>
|
||||
<view>
|
||||
<!-- Custom Nav Bar -->
|
||||
<view class="custom-nav-bar" :class="{ 'android-nav': isAndroid }">
|
||||
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
<view class="nav-content">
|
||||
<view class="left-icon" @click="back">
|
||||
<image class="back-icon" src="/static/image/common/iphone-back.png" />
|
||||
</view>
|
||||
<view class="title">关于本机</view>
|
||||
<view class="right-placeholder"></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Placeholder to push content down -->
|
||||
<view class="nav-placeholder" :style="{ height: statusBarHeight + 74 + 'px' }"></view>
|
||||
|
||||
<view class="info-container">
|
||||
<block v-for="(group, groupIndex) in listData" :key="groupIndex">
|
||||
<!-- Group Header (Optional) -->
|
||||
<view v-if="group.groupTitle" class="group-header">
|
||||
<text class="header-text">{{ group.groupTitle }}</text>
|
||||
</view>
|
||||
|
||||
<!-- Group Items -->
|
||||
<view class="info-group">
|
||||
<view class="info-item" v-for="(item, itemIndex) in group.items" :key="item.id"
|
||||
:class="{ 'no-border': itemIndex === group.items.length - 1 }"
|
||||
@click="handleEdit(groupIndex, itemIndex)">
|
||||
<text class="item-label">{{ item.label }}</text>
|
||||
<view class="item-value-box">
|
||||
<text class="item-value" v-if="item.value !== undefined">{{ item.value }}</text>
|
||||
<!-- <view class="chevron"></view> -->
|
||||
<image class="chevron" v-if="item.hasArrow"
|
||||
src="/static/image/common/about-iphone-right.png">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!-- Custom Modal -->
|
||||
<view class="custom-modal-mask" v-if="isModalVisible" @click="closeModal">
|
||||
<view class="custom-modal" @click.stop>
|
||||
<view class="modal-header">
|
||||
<text class="modal-title">{{ modalTitle }}</text>
|
||||
</view>
|
||||
<view class="modal-body">
|
||||
<input class="modal-input" v-model="modalInputValue" :placeholder="modalPlaceholder"
|
||||
cursor-spacing="20" />
|
||||
</view>
|
||||
<view class="modal-footer">
|
||||
<view class="modal-btn cancel-btn" @click="closeModal">取消</view>
|
||||
<view class="modal-btn confirm-btn" @click="confirmModal">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<ZdySafeBottom bgColor="#f0f3f8"/>
|
||||
</view>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_shopping_about_iphone" />
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_shopping_about_iphone')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, getCurrentInstance } from 'vue';
|
||||
import { util } from '@/utils/common.js'
|
||||
import { onShow, onLoad, onPageScroll } from '@dcloudio/uni-app'
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
const CACHE_KEY = 'about_iphone_data';
|
||||
|
||||
// Removed scroll logic, styling is now fully CSS-driven
|
||||
|
||||
const defaultData = [
|
||||
{
|
||||
groupTitle: '',
|
||||
items: [
|
||||
{ id: 'name', label: '名称', value: '胡英俊的iPhone', hasArrow: true },
|
||||
{ id: 'iosVersion', label: 'iOS版本', value: '26.4.2', hasArrow: true },
|
||||
{ id: 'modelName', label: '型号名称', value: 'iPhone 17 Pro Max', hasArrow: false },
|
||||
{ id: 'modelNumber', label: '型号', value: 'MG8W4CH/A', hasArrow: false },
|
||||
{ id: 'serialNumber', label: '序列号', value: 'J5YQ2R5F8R', hasArrow: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
groupTitle: '',
|
||||
items: [
|
||||
{ id: 'warranty', label: '有限保修', value: '到期日期:2026/12/13', hasArrow: true }
|
||||
]
|
||||
},
|
||||
{
|
||||
groupTitle: '',
|
||||
items: [
|
||||
{ id: 'songs', label: '歌曲', value: '0', hasArrow: false },
|
||||
{ id: 'videos', label: '视频', value: '456', hasArrow: false },
|
||||
{ id: 'photos', label: '照片', value: '6,568', hasArrow: false },
|
||||
{ id: 'apps', label: '应用程序', value: '64', hasArrow: false },
|
||||
{ id: 'capacity', label: '总容量', value: '2 TB', hasArrow: false },
|
||||
{ id: 'available', label: '可用容量', value: '1.56 TB', hasArrow: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
groupTitle: '',
|
||||
items: [
|
||||
{ id: 'wifi', label: '无线局域网地址', value: '87:5F:4D:48:DF:36', hasArrow: false },
|
||||
{ id: 'bluetooth', label: '蓝牙', value: '87:5F:4D:2B:DF:68', hasArrow: false },
|
||||
{ id: 'firmware', label: '调制解调器固件', value: '1.55.25', hasArrow: false },
|
||||
{ id: 'seid', label: 'SEID', value: '', hasArrow: true },
|
||||
{ id: 'carrierLock', label: '运营商锁', value: '无SIM卡限制', hasArrow: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
groupTitle: '主号',
|
||||
items: [
|
||||
{ id: 'primaryNetwork', label: '网络', value: '中国移动全球通', hasArrow: false },
|
||||
{ id: 'primaryCarrier', label: '运营商', value: '中国移动 69.0', hasArrow: false },
|
||||
{ id: 'primaryIMEI', label: 'IMEI', value: '35 756481 6466451 3', hasArrow: false },
|
||||
{ id: 'primaryICCID', label: 'ICCID', value: '45632144856512347896', hasArrow: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
groupTitle: '个人',
|
||||
items: [
|
||||
{ id: 'personalNetwork', label: '网络', value: '中国电信', hasArrow: false },
|
||||
{ id: 'personalCarrier', label: '运营商', value: '中国电信 69.0', hasArrow: false },
|
||||
{ id: 'personalIMEI', label: 'IMEI', value: '35 756481 6466451 3', hasArrow: false },
|
||||
{ id: 'personalICCID', label: 'ICCID', value: '45632144856512347896', hasArrow: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
groupTitle: '',
|
||||
items: [
|
||||
{ id: 'trustSettings', label: '证书信任设置', value: '', hasArrow: true }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const listData = ref([]);
|
||||
const statusBarHeight = ref(0);
|
||||
const isAndroid = ref(false);
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#F2F1F6')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500);
|
||||
// #endif
|
||||
|
||||
})
|
||||
|
||||
onLoad(() => {
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'ios-about-phone',
|
||||
prefix: '.uni.other.',
|
||||
value: '设置-关于本机'
|
||||
})
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
statusBarHeight.value = systemInfo.statusBarHeight || 0;
|
||||
|
||||
if (systemInfo.osName === 'android' || systemInfo.platform === 'android') {
|
||||
isAndroid.value = true;
|
||||
}
|
||||
|
||||
const cached = uni.getStorageSync(CACHE_KEY);
|
||||
if (cached) {
|
||||
try {
|
||||
listData.value = JSON.parse(cached);
|
||||
} catch (e) {
|
||||
listData.value = JSON.parse(JSON.stringify(defaultData));
|
||||
}
|
||||
} else {
|
||||
listData.value = JSON.parse(JSON.stringify(defaultData));
|
||||
}
|
||||
});
|
||||
|
||||
const back = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const isModalVisible = ref(false);
|
||||
const modalTitle = ref('');
|
||||
const modalPlaceholder = ref('');
|
||||
const modalInputValue = ref('');
|
||||
let currentEditGroupIndex = -1;
|
||||
let currentEditItemIndex = -1;
|
||||
|
||||
const handleEdit = (groupIndex, itemIndex) => {
|
||||
const item = listData.value[groupIndex].items[itemIndex];
|
||||
|
||||
currentEditGroupIndex = groupIndex;
|
||||
currentEditItemIndex = itemIndex;
|
||||
modalTitle.value = `修改${item.label}`;
|
||||
modalPlaceholder.value = `请输入新的${item.label}`;
|
||||
modalInputValue.value = item.value || '';
|
||||
isModalVisible.value = true;
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
isModalVisible.value = false;
|
||||
};
|
||||
|
||||
const confirmModal = () => {
|
||||
if (currentEditGroupIndex !== -1 && currentEditItemIndex !== -1) {
|
||||
listData.value[currentEditGroupIndex].items[currentEditItemIndex].value = modalInputValue.value;
|
||||
uni.setStorageSync(CACHE_KEY, JSON.stringify(listData.value));
|
||||
}
|
||||
isModalVisible.value = false;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.custom-nav-bar {
|
||||
opacity: .97;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
background: linear-gradient(180deg, rgba(242, 242, 246, 0.5) 0%, rgba(242, 242, 246, 0) 100%);
|
||||
backdrop-filter: saturate(220%) blur(14px);
|
||||
-webkit-backdrop-filter: saturate(220%) blur(14px);
|
||||
-webkit-mask-image: linear-gradient(180deg, rgba(242, 242, 246, 0.5) 0%, rgba(242, 242, 246, 0) 100%);
|
||||
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 1) calc(100% - 50rpx), rgba(0, 0, 0, 0) 100%);
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10rpx 26rpx 50rpx;
|
||||
}
|
||||
|
||||
.left-icon,
|
||||
.right-placeholder {
|
||||
width: 86rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
}
|
||||
|
||||
/* 安卓手机降级:取消复杂的渐变、滤镜与遮罩,直接使用纯色 */
|
||||
.custom-nav-bar.android-nav {
|
||||
opacity: 1 !important;
|
||||
background: #F2F1F6 !important;
|
||||
backdrop-filter: none !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
mask-image: none !important;
|
||||
-webkit-mask-image: none !important;
|
||||
|
||||
.nav-content {
|
||||
padding-bottom: 10rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-placeholder {
|
||||
width: 100%;
|
||||
padding-top: 146rpx;
|
||||
}
|
||||
|
||||
/* .blur-nav removed */
|
||||
|
||||
.back-icon {
|
||||
box-shadow: 0rpx 0rpx 20rpx 0rpx #E1E1E6;
|
||||
border: 2rpx solid #FFFFFF;
|
||||
border-radius: 50%;
|
||||
width: 86rpx;
|
||||
height: 86rpx;
|
||||
}
|
||||
|
||||
.info-container {
|
||||
padding: 30rpx;
|
||||
padding-top: 0;
|
||||
padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.info-group {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 48rpx;
|
||||
margin-bottom: 64rpx;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-left: 30rpx;
|
||||
margin-right: 30rpx;
|
||||
border-bottom: 0.5px solid #E4E4E4;
|
||||
line-height: 32rpx;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.info-item.no-border {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.item-label {
|
||||
font-size: 32rpx;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.item-value-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item-value {
|
||||
font-size: 32rpx;
|
||||
color: #8A8A8A;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.group-header {
|
||||
padding: 0 0 10rpx 30rpx;
|
||||
}
|
||||
|
||||
.header-text {
|
||||
font-size: 32rpx;
|
||||
line-height: 32rpx;
|
||||
margin-bottom: 16rpx;
|
||||
color: #85858A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.custom-modal-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.custom-modal {
|
||||
width: 600rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 48rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
padding: 40rpx 30rpx 30rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 34rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 0 40rpx 40rpx;
|
||||
}
|
||||
|
||||
.modal-input {
|
||||
background-color: #F2F1F6;
|
||||
height: 80rpx;
|
||||
border-radius: 20rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 32rpx;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
border-top: 0.5px solid #E4E4E4;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.modal-btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
color: #8A8A8A;
|
||||
border-right: 0.5px solid #E4E4E4;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
color: #007AFF;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
page {
|
||||
background-color: #F2F1F6;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark dark="light" source="uni_alipay_other_airTickets_ctrip" />
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_airTickets_ctrip')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="codefun-flex-col page" :style="{ '--font-weight-bold': $system == 'iOS' ? 500 : 700 }">
|
||||
|
|
@ -270,7 +271,7 @@
|
|||
<text class="codefun-shrink-0 codefun-self-start font_13 text_47">出行人</text>
|
||||
<view class="codefun-flex-col codefun-flex-1 codefun-relative group_16 ml-41">
|
||||
<text class="codefun-self-start text_23" @click="goEdit"><text
|
||||
style="margin-right: 6px;" v-for="value in airTicketsInfo.passengersInfo">{{
|
||||
style="margin-right: 6px;" v-for="(value, index) in airTicketsInfo.passengersInfo" :key="index">{{
|
||||
value.name }}</text></text>
|
||||
<view class="codefun-flex-row codefun-items-center codefun-self-stretch codefun-mt-8">
|
||||
<text class="font_14 text_49">查看证件、航司预订号、修改姓名/证件</text>
|
||||
|
|
@ -308,8 +309,8 @@
|
|||
<image class="image_19 pos_15" src="/static/image/other/air-tickets/ctrip-air/connect-icon.png" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-col codefun-mt-8">
|
||||
<view class="codefun-flex-col section_12">
|
||||
<view class="codefun-flex-col codefun-mt-8" :style="{'padding-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<view class="codefun-flex-col section_12" >
|
||||
<text class="codefun-self-start font_6 text_52">出行服务</text>
|
||||
<view class="codefun-self-stretch grid_2 mt-19">
|
||||
<view class="codefun-flex-col codefun-items-center grid-item_4">
|
||||
|
|
@ -343,7 +344,7 @@
|
|||
<text class="font_8 text_54">更多服务</text>
|
||||
<image class="image_11 codefun-ml-6" src="/static/image/other/air-tickets/ctrip-air/more.png" />
|
||||
</view>
|
||||
<view class="codefun-flex-col codefun-justify-start section_14">
|
||||
<view class="codefun-flex-col codefun-justify-start section_14" :style="{'padding-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<view class="codefun-flex-row equal-division_3">
|
||||
<view
|
||||
class="codefun-flex-col codefun-justify-start codefun-items-center text-wrapper_5 text-wrapper_1">
|
||||
|
|
@ -366,12 +367,14 @@
|
|||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
import { reactive, ref, computed, toRefs } from 'vue';
|
||||
import { reactive, computed, toRefs } from 'vue';
|
||||
import { onShow, onPageScroll } from '@dcloudio/uni-app';
|
||||
import { util } from '@/utils/common.js';
|
||||
import defualtData from '@/pages/other/air-tickets/commom/defualt.json';
|
||||
import airlineJson from '@/static/json/air-line.json';
|
||||
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
const buttonGroup = [{
|
||||
name: "编辑机票信息",
|
||||
click: () => {
|
||||
|
|
@ -425,7 +428,7 @@ onShow(() => {
|
|||
if (stored) {
|
||||
Object.assign(data.airTicketsInfo, stored);
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
|
|||
|
|
@ -86,10 +86,10 @@
|
|||
<text class="label">到达机场</text>
|
||||
<input class="input" v-model="ticketsInfo.flightInfo.endAirport" />
|
||||
</view>
|
||||
<!-- <view class="form-item">
|
||||
<view class="form-item">
|
||||
<text class="label">时长</text>
|
||||
<input class="input" v-model="ticketsInfo.flightInfo.duration" placeholder="例: 2时5分" />
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">机型</text>
|
||||
<input class="input" v-model="ticketsInfo.flightInfo.aircraftType" />
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark dark="light" source="uni_alipay_other_airTickets_fliggy" />
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_airTickets_fliggy')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="page-container">
|
||||
|
|
@ -204,8 +205,8 @@
|
|||
<text class="label" :class="{ 'empty': index !== 0 }">乘机人</text>
|
||||
<view class="info" @click="goEdit">
|
||||
<text class="name">{{ item.name }}</text>
|
||||
<text class="id-card">{{ item.idType }}:{{ item.idType === '身份证' ?
|
||||
stringUtil.maskIdCard(item.idNumber) : (item.idType === '护照' ?
|
||||
<text class="id-card">{{ item.idType }}:{{ item.idType.includes('身份证') ?
|
||||
showFristAndLastNumber(item.idNumber) : (item.idType.includes('护照') ?
|
||||
stringUtil.maskPassport(item.idNumber) : item.idNumber) }}</text>
|
||||
<view class="ticket-row">
|
||||
<text class="ticket-no">票号:{{ item.ticketNo }}</text>
|
||||
|
|
@ -278,10 +279,13 @@
|
|||
<!-- Note: User image shows floating bottom bar but cut off. Assuming standard action buttons -->
|
||||
</view>
|
||||
<view class="safe-area-inset-bottom"></view> <!-- Spacer -->
|
||||
<view class="" :style="{'height':$store.state.safeBottomAz+'px'}">
|
||||
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="footer-bar">
|
||||
<view class="flex flex-justify-between">
|
||||
<view class="flex flex-justify-between" :style="{'padding-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<view class="flex-1 flex flex-align-center flex-justify-center">
|
||||
<image class="footer-icon" src="/static/image/other/air-tickets/fliggy-air/zhibo.png" />
|
||||
<text class="text">联系飞猪</text>
|
||||
|
|
@ -298,11 +302,11 @@
|
|||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
import { ref, onMounted, reactive, toRefs, computed } from 'vue';
|
||||
import { onMounted, reactive, toRefs, computed } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import defualtData from '@/pages/other/air-tickets/commom/defualt.json';
|
||||
import airlineJson from '@/static/json/air-line.json';
|
||||
import { util, numberUtil, stringUtil } from '@/utils/common.js';
|
||||
import { util, stringUtil } from '@/utils/common.js';
|
||||
|
||||
const buttonGroup = [{
|
||||
name: "编辑机票信息",
|
||||
|
|
@ -371,6 +375,17 @@ const deepMerge = (target, source) => {
|
|||
return target;
|
||||
};
|
||||
|
||||
const showFristAndLastNumber = (str) => {
|
||||
if (!str) {
|
||||
return '';
|
||||
}
|
||||
const len = str.length;
|
||||
if (len <= 2) {
|
||||
return str;
|
||||
}
|
||||
return str.slice(0, 1) + '*'.repeat(len - 2) + str.slice(-1);
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
const stored = uni.getStorageSync(data.STORAGE_KEY) || "";
|
||||
if (stored) {
|
||||
|
|
@ -380,7 +395,7 @@ onShow(() => {
|
|||
const mergedData = deepMerge(baseData, stored);
|
||||
Object.assign(data.airTickrtInfo, mergedData);
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark dark="light" source="uni_alipay_other_airTickets_qunar" />
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_airTickets_qunar')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="page-container">
|
||||
|
|
@ -198,8 +199,8 @@
|
|||
<view class="row-content"
|
||||
@click="util.goPage('/pages/other/air-tickets/edit/edit')">
|
||||
<view class="p-name">{{ p.name }}</view>
|
||||
<view class="p-sub">{{ p.idType }}: {{ p.idType === '身份证' ?
|
||||
stringUtil.maskIdCard(p.idNumber) : (p.idType === '护照' ?
|
||||
<view class="p-sub">{{ p.idType }}: {{ p.idType.includes('身份证') ?
|
||||
stringUtil.maskIdCard(p.idNumber) : (p.idType.includes('护照') ?
|
||||
stringUtil.maskPassport(p.idNumber) : p.idNumber) }}</view>
|
||||
<view class="p-sub">
|
||||
<text>票号:{{ p.ticketNo }}</text>
|
||||
|
|
@ -333,16 +334,19 @@
|
|||
</view>
|
||||
|
||||
<!-- Branding -->
|
||||
<view class="branding-area">
|
||||
<view class="branding-area" >
|
||||
<image class="image" src="/static/image/other/air-tickets/qunar/branding-area-image.png"
|
||||
mode="widthFix">
|
||||
</image>
|
||||
</view>
|
||||
<view class="" :style="{'height':$store.state.safeBottomAz+'px'}">
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Bottom Fixed -->
|
||||
<view class="bottom-bar">
|
||||
<view class="bottom-bar" :style="{'padding-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<button class="invoice-btn">开具发票</button>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -375,7 +379,7 @@ const data = reactive({
|
|||
ticketData: JSON.parse(JSON.stringify(defualtData))
|
||||
})
|
||||
|
||||
let { navBar, ticketData } = toRefs(data);
|
||||
let { ticketData } = toRefs(data);
|
||||
|
||||
// 计算截止办理值机时间
|
||||
const ofCheckInTime = computed(() => {
|
||||
|
|
@ -403,7 +407,7 @@ onShow(() => {
|
|||
Object.assign(data.ticketData, stored);
|
||||
}
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,171 @@
|
|||
<template>
|
||||
<view>
|
||||
<NavBar :title="data.navBar.title" :bgColor="data.navBar.bgColor" />
|
||||
<view class="list-container">
|
||||
<view class="item" v-for="item in source" :key="item.id" @click="goPage(item.callUrl,item.name)"
|
||||
:style="{ background: ` #FFFFFF` }">
|
||||
<view class="content flex flex-align-center">
|
||||
<image class="logo" :src="`/static/image/other/bank/${item.icon}.png`" mode=""></image>
|
||||
<view class="name flex-1">{{ item.name }}银行</view>
|
||||
<view class="right-button">
|
||||
<uni-icons type="right" size="16"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="line" :style="{ background: item.color.lineColor }"></view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad
|
||||
} from "@dcloudio/uni-app";
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js';
|
||||
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
// 列表
|
||||
const source = ref([{
|
||||
name: '招商',
|
||||
color: {
|
||||
bgColor: '#F3EAFF',
|
||||
lineColor: '#B78EF5',
|
||||
buttonColor: '#BA8DFF',
|
||||
},
|
||||
icon: 'zsyh',
|
||||
callUrl: "/pages/other/bank/zsyh"
|
||||
},
|
||||
{
|
||||
name: '工商',
|
||||
color: {
|
||||
bgColor: '#FFE9E9',
|
||||
lineColor: '#FF6969',
|
||||
buttonColor: '#FB6767',
|
||||
},
|
||||
icon: 'gsyh',
|
||||
callUrl: "/pages/other/bank/gsyh"
|
||||
},
|
||||
{
|
||||
name: '农业',
|
||||
color: {
|
||||
bgColor: '#FFF0DD',
|
||||
lineColor: '#FFA143',
|
||||
buttonColor: '#FFA64D',
|
||||
},
|
||||
icon: 'nyyh',
|
||||
callUrl: "/pages/other/bank/nyyh"
|
||||
},
|
||||
{
|
||||
name: '建设',
|
||||
color: {
|
||||
bgColor: '#E0FFD9',
|
||||
lineColor: '#56B745',
|
||||
buttonColor: '#5DCD49',
|
||||
},
|
||||
icon: 'jsyh',
|
||||
callUrl: "/pages/other/bank/jsyh"
|
||||
}
|
||||
])
|
||||
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: '选择机型',
|
||||
bgColor: '#F0F4F9',
|
||||
},
|
||||
type: "message"
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.type) {
|
||||
data.type = options.type
|
||||
}
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'bank',
|
||||
prefix: '.uni.other.',
|
||||
value:'银行卡首页'
|
||||
})
|
||||
})
|
||||
|
||||
function goPage(url,name) {
|
||||
if (url) {
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'bank',
|
||||
prefix: '.uni.other.',
|
||||
value:name+'银行'
|
||||
})
|
||||
util.goPage(url)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
</style>
|
||||
<style lang="less">
|
||||
.list-container {
|
||||
background-color: #F0F4F9;
|
||||
padding: 24rpx 32rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 188rpx;
|
||||
border-radius: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 40rpx 36rpx 24rpx 28rpx;
|
||||
|
||||
.content {
|
||||
.logo {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-left: 32rpx;
|
||||
color: #1A1A1A;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.right-button {
|
||||
width: 140rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 16rpx;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
line-height: 64rpx !important;
|
||||
text-align: right;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100rpx;
|
||||
height: 8rpx;
|
||||
filter: blur(5px);
|
||||
opacity: 0.5;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,732 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 自定义头部导航栏 -->
|
||||
<ZdyNavbar @right-click="edit" isRightButton rightButtonText="编辑" :title="data.navbar.title"
|
||||
:bgColor="data.navbar.bgColor" :isBack="true" />
|
||||
|
||||
<view style="display: flex;align-items: center;background: #fff;border-radius: 6px;margin: 10px;padding: 4px;color: #767676;">
|
||||
<image src="/static/image/other/notice.png" style="width: 16px;height: 16px;margin-right: 10rpx;margin-left: 10rpx;"></image>
|
||||
此功能不具备真实性,仅供娱乐
|
||||
</view>
|
||||
<image :src="data.code" mode="widthFix" style="width: 100vw;" @click="previewImage"></image>
|
||||
<view class="button-container">
|
||||
<button class="btn-save-image" @click="saveImage">保存图片</button>
|
||||
</view>
|
||||
<view style="width: 0px;height: 0;overflow: hidden;" v-if="data.shuaxing && data.bgImg">
|
||||
<l-painter isCanvasToTempFilePath @success="successImage" @progress="progress"
|
||||
:css="`width:${data.width}px;height:${data.height }px;background-color:#fff;`">
|
||||
<l-painter-view
|
||||
:css="`margin-top:109px;margin-left:75px;position: relative;width:666px;height:406px;`">
|
||||
<!-- 背景图:用 image 替代 background-image,避免鸿蒙本地路径不生效 -->
|
||||
<l-painter-image :src="data.bgImg" css="width:666px;height:406px;position:absolute;left:0;top:0;object-fit:fill;" />
|
||||
<!-- 姓名 -->
|
||||
<l-painter-view :css="`position: absolute;left:122px;top:54px;`">
|
||||
<l-painter-text :css="data.textCss+data.textCssLeft" :text="data.form.name" />
|
||||
</l-painter-view>
|
||||
<l-painter-view :css="`position: absolute;left:122px;top:102px;`">
|
||||
<l-painter-text :css="data.textCss2+data.textCssLeft" :text="data.form.gender" />
|
||||
</l-painter-view>
|
||||
<l-painter-view :css="`position: absolute;left:262px;top:102px;`">
|
||||
<l-painter-text :css="data.textCss2+data.textCssLeft" :text="data.form.nation" />
|
||||
</l-painter-view>
|
||||
<!-- 出生年:逐字绝对定位,避免鸿蒙下多 text 竖排/重叠 -->
|
||||
<l-painter-text
|
||||
v-for="(item, index) in String(data.form.year)"
|
||||
:key="'year-' + index"
|
||||
:css="data.textCssDigit + `position:absolute;left:${122 + index * 18}px;top:152px;`"
|
||||
:text="item"
|
||||
/>
|
||||
<!-- 月 / 日 -->
|
||||
<l-painter-view :css="`position: absolute;left:216px;top:152px;`">
|
||||
<l-painter-text :css="data.textCssMonthDay" :text="String(data.form.month)" />
|
||||
</l-painter-view>
|
||||
<l-painter-view :css="`position: absolute;left:278px;top:152px;`">
|
||||
<l-painter-text :css="data.textCssMonthDay" :text="String(data.form.day)" />
|
||||
</l-painter-view>
|
||||
<!-- 住址 -->
|
||||
<l-painter-text
|
||||
v-for="(item, index) in addressChars"
|
||||
:key="'addr-' + index"
|
||||
:css="data.textCssDigit + `position:absolute;left:${item.left}px;top:${item.top}px;`"
|
||||
:text="item.text"
|
||||
/>
|
||||
<!-- 身份证号 -->
|
||||
<l-painter-text
|
||||
v-for="(item, index) in String(data.form.idNumber || '')"
|
||||
:key="'id-' + index"
|
||||
:css="data.textCssId + `position:absolute;left:${223 + index * 20}px;top:322px;`"
|
||||
:text="item"
|
||||
/>
|
||||
<!-- 照片(right 在鸿蒙易失效,改为 left) -->
|
||||
<l-painter-view :css="`position: absolute;left:422px;top:62px;`">
|
||||
<l-painter-image v-if="data.form.photo" :src="data.form.photo" css="width: 196px; height: 230px;" />
|
||||
<l-painter-view v-else css="width: 196px; height: 230px;background-color:#fff;">
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
<l-painter-view v-if="$isVip()" :css="`position: absolute;left:535px;bottom:-78px;`">
|
||||
<l-painter-image src="/static/image/other/card/shuiyin2.png" css="width: 170px;height: 50px;" />
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<view v-if="showEditPopup" class="popup-overlay">
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">编辑身份证</text>
|
||||
<text class="popup-close" @click="closeEditPopup">×</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view class="form-row">
|
||||
<text class="form-label">姓名:</text>
|
||||
<input class="form-input" v-model="editForm.name" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">性别:</text>
|
||||
<input class="form-input" v-model="editForm.gender" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">民族:</text>
|
||||
<input class="form-input" v-model="editForm.nation" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">出生日期:</text>
|
||||
<input class="form-input" v-model="editForm.year" type="number" style="width: 100px;" />
|
||||
<text class="form-separator">-</text>
|
||||
<input class="form-input" v-model="editForm.month" type="number" style="width: 80px;" />
|
||||
<text class="form-separator">-</text>
|
||||
<input class="form-input" v-model="editForm.day" type="number" style="width: 80px;" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">住址:</text>
|
||||
<input class="form-input" v-model="editForm.address" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">身份证号:</text>
|
||||
<input class="form-input" v-model="editForm.idNumber" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">照片:</text>
|
||||
<view class="upload-container">
|
||||
<image v-if="editForm.photo" :src="editForm.photo" class="upload-image" @click="chooseImage" />
|
||||
<view v-else class="upload-btn" @click="chooseImage">
|
||||
<text class="upload-text">点击上传照片</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<button class="btn-cancel" @click="closeEditPopup">取消</button>
|
||||
<button class="btn-save" @click="saveEditForm">保存</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_card')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 自定义头部
|
||||
import ZdyNavbar from "@/components/nav-bar/nav-bar.vue"
|
||||
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
computed,
|
||||
watch,
|
||||
nextTick,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onUnload,
|
||||
onReady,
|
||||
onPullDownRefresh,
|
||||
onReachBottom
|
||||
} from "@dcloudio/uni-app";
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const data = reactive({
|
||||
shuaxing: false,
|
||||
navbar: {
|
||||
title: "身份证",
|
||||
bgColor: '#EDEDED',
|
||||
},
|
||||
width: 800,
|
||||
height: 600,
|
||||
code: '',
|
||||
bgImg: '',
|
||||
form: {
|
||||
name: '某某',
|
||||
gender: '男',
|
||||
nation: '汉',
|
||||
year: 2000,
|
||||
month: 1,
|
||||
day: 1,
|
||||
address: '翻斗大街翻斗花园二号楼1001室',
|
||||
idNumber: '110000200001010000',
|
||||
photo: '',
|
||||
},
|
||||
textCss: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:100px;color:#3D3D3D;font-size:24px;',
|
||||
textCss2: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:100px;text-align: left;color:#3D3D3D;font-size:22px;',
|
||||
// 年/月/日/住址单字
|
||||
textCssDigit: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:22px;color:#3D3D3D;font-size:22px;',
|
||||
textCssMonthDay: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:40px;text-align:center;color:#3D3D3D;font-size:22px;',
|
||||
// 身份证号单字(专用字体)
|
||||
textCssId: 'font-family: "card", "Microsoft YaHei", sans-serif;width:22px;color:#1a1a1a;font-size:28px;',
|
||||
textCssLeft: 'text-align: left;',
|
||||
textCssCenter: 'text-align: center;'
|
||||
})
|
||||
|
||||
/** 住址逐字坐标(固定字宽换行,避免鸿蒙流式布局异常) */
|
||||
const addressChars = computed(() => {
|
||||
const chars = String(data.form.address || '').split('')
|
||||
const startLeft = 122
|
||||
const startTop = 200
|
||||
const step = 26
|
||||
const lineHeight = 32
|
||||
const perLine = 10
|
||||
return chars.map((text, index) => ({
|
||||
text,
|
||||
left: startLeft + (index % perLine) * step,
|
||||
top: startTop + Math.floor(index / perLine) * lineHeight
|
||||
}))
|
||||
})
|
||||
|
||||
function loadCardFont() {
|
||||
return new Promise((resolve) => {
|
||||
uni.loadFontFace({
|
||||
family: 'card',
|
||||
source: 'url("/static/font/card.ttf")',
|
||||
success: () => resolve(true),
|
||||
fail: (err) => {
|
||||
console.warn('身份证号码字体加载失败', err)
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
async function loadCardBg() {
|
||||
try {
|
||||
const localPath = await imgLocal.getLocalImage('other/card/cardBGImg.png')
|
||||
return localPath || ''
|
||||
} catch (e) {
|
||||
console.error('身份证背景图加载失败', e)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗相关
|
||||
const showEditPopup = ref(false);
|
||||
const editForm = ref({});
|
||||
onLoad(async(option) => {
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
await loadCardFont()
|
||||
data.bgImg = await loadCardBg()
|
||||
data.shuaxing = !!data.bgImg
|
||||
if (!data.bgImg) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '背景图加载失败', icon: 'none' })
|
||||
}
|
||||
// 进入身份证页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'idcard',
|
||||
prefix: '.uni.other.',
|
||||
value: "身份证"
|
||||
})
|
||||
let formdata=uni.getStorageSync("cardForm")
|
||||
if(formdata){
|
||||
data.form=formdata
|
||||
}
|
||||
uni.$on("editFormPhoto",(info)=>{
|
||||
data.code = ""
|
||||
editForm.value.photo = info;
|
||||
data.form.photo = info;
|
||||
})
|
||||
})
|
||||
onUnload(() => {
|
||||
uni.$off('editFormPhoto')
|
||||
})
|
||||
onReady(() => {
|
||||
|
||||
})
|
||||
onShow(() => {})
|
||||
onPullDownRefresh(() => {
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 1000);
|
||||
})
|
||||
onReachBottom(() => {
|
||||
|
||||
})
|
||||
function successImage(e) {
|
||||
data.code = e
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
function progress(e) {
|
||||
// console.log(e)
|
||||
|
||||
}
|
||||
// 打开编辑弹窗
|
||||
function edit() {
|
||||
console.log(data.form)
|
||||
// 复制当前表单数据到编辑表单
|
||||
editForm.value = JSON.parse(JSON.stringify(data.form));
|
||||
// 显示弹窗
|
||||
showEditPopup.value = true;
|
||||
}
|
||||
|
||||
// 关闭编辑弹窗
|
||||
function closeEditPopup() {
|
||||
showEditPopup.value = false;
|
||||
}
|
||||
|
||||
// 保存编辑表单
|
||||
function saveEditForm() {
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
data.shuaxing=false
|
||||
// 将编辑后的数据复制回原始表单
|
||||
data.form = editForm.value
|
||||
data.form.photo=editForm.value.photo
|
||||
setTimeout(()=>{
|
||||
data.shuaxing=true
|
||||
},100)
|
||||
uni.setStorageSync("cardForm",data.form)
|
||||
// 关闭弹窗
|
||||
showEditPopup.value = false;
|
||||
}
|
||||
|
||||
// 选择图片
|
||||
function chooseImage() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
// crop:{
|
||||
// width:'196px',
|
||||
// height:"230px"
|
||||
// },
|
||||
success: (res) => {
|
||||
uni.navigateTo({
|
||||
url:'/pages/other/qf-image/qf-image?src='+res.tempFilePaths[0]
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('选择图片失败', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将本地图片路径通过 Canvas 转换为 File 对象
|
||||
* @param {string} localPath - 本地图片路径(如从 uni.chooseImage 获取的 tempFilePath)
|
||||
* @param {Object} options - 可选参数
|
||||
* @param {string} options.format - 输出格式 'image/png' 或 'image/jpeg',默认 'image/png'
|
||||
* @param {number} options.quality - 图片质量(仅 jpeg 有效),0~1,默认 0.92
|
||||
* @param {number} options.maxWidth - 最大宽度(等比缩放),不填则使用原图尺寸
|
||||
* @param {number} options.maxHeight - 最大高度(等比缩放),不填则使用原图尺寸
|
||||
* @returns {Promise<File>} 返回一个 Promise,resolve 为 File 对象
|
||||
*/
|
||||
function convertLocalImageToFile(localPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
// 1. 读取本地图片为 Base64(避免 Image 对象直接加载本地路径的兼容问题)
|
||||
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
|
||||
entry.file((file) => {
|
||||
const reader = new plus.io.FileReader();
|
||||
reader.onload = (e) => {
|
||||
const base64Data = e.target.result; // 格式如 data:image/jpeg;base64,/9j/...
|
||||
resolve(e.target.result)
|
||||
};
|
||||
reader.onerror = (err) => reject(err);
|
||||
reader.readAsDataURL(file); // 读取为 DataURL
|
||||
}, reject);
|
||||
}, reject);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
reject(new Error('plus.io not supported'))
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
// 预览图片
|
||||
function previewImage() {
|
||||
if (data.code) {
|
||||
uni.previewImage({
|
||||
urls: [data.code],
|
||||
current: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 保存图片
|
||||
function saveImage() {
|
||||
if (data.code) {
|
||||
console.log(data.code)
|
||||
uni.showLoading({
|
||||
title: '保存中...'
|
||||
});
|
||||
try {
|
||||
// 检查是否为base64格式
|
||||
if (data.code.startsWith('data:image')) {
|
||||
// 处理base64格式图片
|
||||
console.log('开始处理base64图片');
|
||||
uni.base64ToTempFile({
|
||||
base64: data.code.split(',')[1], // 去除base64前缀
|
||||
success: (res) => {
|
||||
console.log('base64转换成功', res);
|
||||
if (res.tempFilePath) {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
console.log('保存图片成功');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('保存图片失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('base64转换失败,无临时文件路径');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '转换失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('base64转换失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '转换失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (data.code.startsWith('_') || data.code.includes('temp') || data.code.includes('cache') || data
|
||||
.code.includes('_doc') || data.code.includes('_tmp')) {
|
||||
// 处理本地临时文件
|
||||
console.log('开始处理本地临时文件');
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: data.code,
|
||||
success: () => {
|
||||
console.log('保存本地文件成功');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('保存本地文件失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 处理网络图片
|
||||
console.log('开始处理网络图片');
|
||||
uni.downloadFile({
|
||||
url: data.code,
|
||||
success: (res) => {
|
||||
console.log('下载图片成功', res);
|
||||
if (res.statusCode === 200 && res.tempFilePath) {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
console.log('保存图片成功');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('保存图片失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('下载图片失败,状态码:', res.statusCode);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '下载失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('下载图片失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '下载失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('保存图片异常', error);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '暂无图片可保存',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" >
|
||||
page {
|
||||
background-color: #ededed;
|
||||
}
|
||||
@font-face {
|
||||
font-family: "card";
|
||||
src: url("/static/font/card.ttf");
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.aadadad {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heiti {
|
||||
font-family: "SimHei", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
.popup-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 48rpx;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin-bottom: 30rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
width: 200rpx;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
flex: 1;
|
||||
padding: 15rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 4rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.form-separator {
|
||||
margin: 0 10rpx;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-total {
|
||||
margin-top: 10rpx;
|
||||
padding-top: 10rpx;
|
||||
border-top: 1rpx dashed #ddd;
|
||||
}
|
||||
|
||||
.form-total-input {
|
||||
background-color: #f9f9f9;
|
||||
color: #ff6b35;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 上传图片样式 */
|
||||
.upload-container {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
width: 120rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx dashed #ddd;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-image {
|
||||
width: 98rpx;
|
||||
height: 115rpx;
|
||||
border-radius: 1rpx;
|
||||
object-fit: cover;
|
||||
border: 1px dashed #ddd;
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.btn-cancel,
|
||||
.btn-save {
|
||||
width: 48%;
|
||||
padding: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
border: 1rpx solid #ddd;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background-color: #187AFF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 保存图片按钮 */
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.btn-save-image {
|
||||
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 60rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: bold;
|
||||
box-shadow: 0 3rpx 10rpx rgba(7, 66, 193, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
text-align: center;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
|
||||
.btn-save-image:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 4rpx 12rpx rgba(7, 72, 193, 0.4);
|
||||
}
|
||||
|
||||
.btn-save-image:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2rpx 6rpx rgba(7, 140, 193, 0.3);
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,163 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<ZdyNavbar :title="data.navbar.title" :bgColor="data.navbar.bgColor" :isAdd="true" :isSearch="$system=='Android'">
|
||||
</ZdyNavbar>
|
||||
|
||||
<view class="card-grid">
|
||||
<view class="card" v-for="(item, index) in cardList" :key="index">
|
||||
<view class="title">
|
||||
{{item.title}}
|
||||
</view>
|
||||
<image :src="item.img" class="card-img" />
|
||||
<button class="card-btn" @click="create(index)">立即制作</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import ZdyNavbar from "@/components/nav-bar/nav-bar.vue"
|
||||
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onUnload,
|
||||
onReady,
|
||||
onPullDownRefresh,
|
||||
onReachBottom
|
||||
} from "@dcloudio/uni-app";
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const data = reactive({
|
||||
navbar: {
|
||||
title: '证件选择',
|
||||
bgColor: ''
|
||||
}
|
||||
})
|
||||
const cardList = ref([
|
||||
{
|
||||
title: '身份证',
|
||||
img: '/static/image/other/certificate/certificate1.png',
|
||||
},
|
||||
{
|
||||
title: '毕业证',
|
||||
img: '/static/image/other/certificate/certificate2.png',
|
||||
},
|
||||
{
|
||||
title: '情侣证',
|
||||
img: '/static/image/other/certificate/certificate3.png',
|
||||
},
|
||||
{
|
||||
title: '分手证',
|
||||
img: '/static/image/other/certificate/certificate4.png',
|
||||
},
|
||||
{
|
||||
title: '奖状',
|
||||
img: '/static/image/other/certificate/certificate5.png',
|
||||
},
|
||||
{
|
||||
title: '颜值证',
|
||||
img: '/static/image/other/certificate/certificate6.png',
|
||||
},
|
||||
])
|
||||
onLoad(()=>{
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'certificate',
|
||||
prefix: '.uni.other.',
|
||||
value:'证书首页'
|
||||
})
|
||||
const config = uni.getStorageSync('config').config
|
||||
const themeConfig = config?.['client.uniapp.idcard']
|
||||
if (!themeConfig) {
|
||||
cardList.value.shift()
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
||||
function create(index){
|
||||
if(index){
|
||||
|
||||
uni.navigateTo({
|
||||
url:'/pages/other/certificate/graduate?styleType='+(index-1)
|
||||
})
|
||||
}else{
|
||||
uni.navigateTo({
|
||||
url:'/pages/other/card/card'
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background-color: #F0F4F9;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.card-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 48%;
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
align-items: center;
|
||||
/* box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.05); */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.title{
|
||||
font-size: 14px;
|
||||
color: #1A1A1A;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
padding-top: 10rpx;
|
||||
}
|
||||
.card-img {
|
||||
width: 130px;
|
||||
height: 80px;
|
||||
/* border-radius: 8px 8px 8px 8px; */
|
||||
margin-top: 21px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
|
||||
.card-btn {
|
||||
width: 68px;
|
||||
height: 28px;
|
||||
background: linear-gradient(327deg, #1777FF 0%, #17CDFF 100%);
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
font-size: 12px;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
button::after{
|
||||
border: none;
|
||||
}
|
||||
button{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,637 @@
|
|||
<template>
|
||||
<view class="honor-of-kings">
|
||||
<nav-bar title="和平精英" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
|
||||
@right-click="onRightClick">
|
||||
</nav-bar>
|
||||
<view style="padding: 8px;box-sizing: border-box;">
|
||||
<view class="painter-container" @click="handlePreview"
|
||||
:style="`width:calc(100vw - 16px) ; height: ${posterContainerHeight}px; overflow: hidden; position: relative; transform: translateZ(0);`">
|
||||
<!-- 运用 js 算出的无误差纯数字 scale 来实现高清画板的等比缩小,彻底兼容所有老旧内核,不再被截断 -->
|
||||
<view
|
||||
:style="`width: 822px; transform: scale(${posterScaleRatio}); transform-origin: left top; position: absolute; left: 0; top: 0;`">
|
||||
<l-painter v-if="bgImage" isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:822px;`">
|
||||
<l-painter-view :css="`width: 822px; position: relative;`">
|
||||
<!-- 直接使用主背景图撑开父容器,移除不必要的 opacity: 0 占位图,避免在大屏渲染时产生黑块 -->
|
||||
<l-painter-image :src="bgImage" css="width: 822px; display: block;"></l-painter-image>
|
||||
|
||||
<!-- 人物图片 -->
|
||||
<l-painter-image :src="hePingData.imgUrl" :css="characterStyle"></l-painter-image>
|
||||
<template v-if="hePingData.type == 2">
|
||||
<!-- 头像 -->
|
||||
<l-painter-image :src="hePingData.avatar"
|
||||
css="position:absolute;left:50px;bottom:13px;width:36px;height:36px"></l-painter-image>
|
||||
<!-- 头像框 -->
|
||||
<l-painter-image src="/static/image/other/game/heping/touxiang.png"
|
||||
css="position:absolute;left:0;bottom:0;width:100px;height:60px"></l-painter-image>
|
||||
<!-- 昵称 -->
|
||||
<l-painter-text :text="hePingData.nickname"
|
||||
css="position: absolute; left: 102px; bottom: 15px; font-size: 10px; color: #EFF9FF;"></l-painter-text>
|
||||
</template>
|
||||
|
||||
<!-- 水印 -->
|
||||
<l-painter-image v-if="$isVip()" src="/static/image/other/shuiying.png"
|
||||
:css="`position: absolute; left: 18.8px; bottom: 17.1px; width: 145.38px;height:42.76px`"></l-painter-image>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_game_heping')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
|
||||
<view class="save-action">
|
||||
<button class="save-btn" @click="handleSave">保存</button>
|
||||
</view>
|
||||
|
||||
<!-- 主题选择区域 -->
|
||||
<view class="theme-selector" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<scroll-view scroll-x="true" class="theme-scroll" :show-scrollbar="false">
|
||||
<view class="theme-list" >
|
||||
<view class="theme-item" v-for="(item, index) in ['样式一', '样式二']" :key="index + 1"
|
||||
:class="{ active: hePingData.type == index + 1 }" @click="handleChangeTheme(index + 1)">
|
||||
<text class="theme-text">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 数据编辑弹窗 -->
|
||||
<uni-popup ref="editPopup" type="center">
|
||||
<view class="edit-popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="title">编辑主页数据</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="popup-scroll">
|
||||
<view class="form-item avatar-form-item">
|
||||
<text class="label">人物图片</text>
|
||||
<view class=" avatar-uploader img-box" @click="handleChooseImgUrl">
|
||||
<view class="avatar-preview" v-if="tempData.imgUrl">
|
||||
<image class="preview-img" :src="tempData.imgUrl" mode="widthFix"></image>
|
||||
<view class="delete-icon" @click.stop="handleDeleteImgUrl">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="upload-btn" v-else>
|
||||
<text class="plus">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item avatar-form-item" v-if="tempData.type == 2">
|
||||
<text class="label">头像</text>
|
||||
<view class="avatar-uploader" @click="handleChooseAvatar">
|
||||
<view class="avatar-preview" v-if="tempData.avatar">
|
||||
<image class="preview-img" :src="tempData.avatar" mode="aspectFill"></image>
|
||||
<view class="delete-icon" @click.stop="handleDeleteAvatar">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="upload-btn" v-else @click="handleChooseAvatar">
|
||||
<text class="plus">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 2">
|
||||
<text class="label">昵称</text>
|
||||
<input class="input" type="text" v-model="tempData.nickname" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<button class="cancel-btn" @click="closeEditPopup">取消</button>
|
||||
<button class="confirm-btn" @click="confirmEdit">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 横向全屏放大预览层 -->
|
||||
<view class="preview-overlay" v-if="showPreview" @click="showPreview = false">
|
||||
<image class="preview-image" :src="finalPosterPath" mode="aspectFill"></image>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, watch, onMounted, getCurrentInstance } from 'vue'
|
||||
import { onLoad, onReady, onUnload } from '@dcloudio/uni-app'
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
const instance = getCurrentInstance();
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 页面表单数据字段
|
||||
const hePingData = reactive({
|
||||
type: 1, // 样式类型 1.2
|
||||
avatar: '/static/image/shopping/pdd/avatars/avatars1.jpg', // 头像
|
||||
imgUrl: '/static/image/other/game/heping/default.png', // 人物图片
|
||||
nickname: '甜喵小贝', // 昵称
|
||||
})
|
||||
|
||||
const characterImgWidth = ref(300); // 初始宽度兜底
|
||||
|
||||
const characterStyle = computed(() => {
|
||||
if (hePingData.type == 1) {
|
||||
return `position: absolute; left: 50%; bottom:43%; transform: translate(-50%,50%); height: 300px; width: 300px;`;
|
||||
} else {
|
||||
return `position: absolute; left: 300px; bottom: 50%;transform: translate(-50%,50%); height: 300px; width: 300px;`;
|
||||
}
|
||||
});
|
||||
|
||||
// 监听人物图片变化,动态获取其原始宽高并计算比例宽度,解决画布必须写明尺寸才能渲染的问题
|
||||
watch(() => hePingData.imgUrl, (newUrl) => {
|
||||
if (!newUrl) return;
|
||||
uni.getImageInfo({
|
||||
src: newUrl,
|
||||
success: (res) => {
|
||||
// 固定高度 300px,宽度等比例拉伸
|
||||
const calcWidth = (300 / res.height) * res.width;
|
||||
characterImgWidth.value = Math.round(calcWidth);
|
||||
},
|
||||
fail: () => {
|
||||
characterImgWidth.value = 300; // 获取失败提供兜底宽度
|
||||
}
|
||||
});
|
||||
}, { immediate: true });
|
||||
|
||||
const bgImage = ref('')
|
||||
|
||||
// 获取系统宽度计算海报缩放比例,代替容易失效的 css calc(),确保全端兼容防截断
|
||||
const sysInfo = uni.getSystemInfoSync();
|
||||
const windowWidth = sysInfo.windowWidth || 375;
|
||||
// 扣除左右共 16px 的 padding,再基于实际画板宽度 822 计算精确缩放比,防止右侧被截断
|
||||
const posterScaleRatio = (windowWidth - 16) / 822;
|
||||
const posterContainerHeight = 374 * posterScaleRatio;
|
||||
|
||||
onLoad(async () => {
|
||||
const cachedData = uni.getStorageSync('hePingData');
|
||||
if (cachedData) {
|
||||
Object.assign(hePingData, cachedData);
|
||||
// 兼容处理:强制把历史缓存里的 .jpg 替换为最新的 .png,防止 404
|
||||
if (hePingData.imgUrl === '/static/image/other/game/heping/default.jpg') {
|
||||
hePingData.imgUrl = '/static/image/other/game/heping/default.png';
|
||||
uni.setStorageSync('hePingData', hePingData);
|
||||
}
|
||||
}
|
||||
try {
|
||||
bgImage.value = await imgLocal.getLocalImage(`other/game/heping/bg-${hePingData.type}.jpg`);
|
||||
} catch (e) {
|
||||
console.error('获取背景图失败:', e);
|
||||
uni.showToast({ title: '背景图加载失败', icon: 'none' });
|
||||
}
|
||||
|
||||
uni.$on('editFormPhoto', (info) => {
|
||||
if (currentEditImgField.value) {
|
||||
tempData[currentEditImgField.value] = info;
|
||||
}
|
||||
// #ifndef H5
|
||||
if (info && !info.startsWith('/static/')) {
|
||||
newAvatars.value.push(info);
|
||||
}
|
||||
// #endif
|
||||
});
|
||||
|
||||
// 进入页面埋点
|
||||
if (proxy && proxy.$apiUserEvent) {
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
key: 'heping',
|
||||
prefix: '.uni.other.',
|
||||
value: "和平精英"
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
uni.$off('editFormPhoto');
|
||||
})
|
||||
|
||||
const rightButtonText = ref("编辑");
|
||||
const finalPosterPath = ref('');
|
||||
const showPreview = ref(false); // 控制全屏预览
|
||||
|
||||
const editPopup = ref(null);
|
||||
const tempData = reactive({});
|
||||
const newAvatars = ref([]);
|
||||
const currentEditImgField = ref('');
|
||||
|
||||
function onRightClick() {
|
||||
Object.assign(tempData, JSON.parse(JSON.stringify(hePingData)));
|
||||
newAvatars.value = [];
|
||||
editPopup.value.open();
|
||||
}
|
||||
|
||||
const handleChooseAvatar = () => {
|
||||
currentEditImgField.value = 'avatar';
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=200&height=200`
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleChooseImgUrl = () => {
|
||||
currentEditImgField.value = 'imgUrl';
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths[0]) {
|
||||
// 跳转到 qf-image 组件进行 300x300 尺寸(传参150)的裁剪,并通过 isMatting=1 触发后续抠图
|
||||
uni.navigateTo({
|
||||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=150&height=150&isMatting=1`
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteAvatar = () => {
|
||||
tempData.avatar = '';
|
||||
};
|
||||
|
||||
const handleDeleteImgUrl = () => {
|
||||
tempData.imgUrl = '';
|
||||
};
|
||||
|
||||
function closeEditPopup() {
|
||||
// #ifndef H5
|
||||
newAvatars.value.forEach(path => {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
});
|
||||
// #endif
|
||||
editPopup.value.close();
|
||||
}
|
||||
|
||||
function confirmEdit() {
|
||||
// #ifndef H5
|
||||
// 删除多余的新上传文件
|
||||
newAvatars.value.forEach(path => {
|
||||
if (path !== tempData.avatar && path !== tempData.imgUrl) {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
}
|
||||
});
|
||||
// 删除被替换掉的原本地头像
|
||||
if (hePingData.avatar !== tempData.avatar && hePingData.avatar && !hePingData.avatar.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: hePingData.avatar });
|
||||
}
|
||||
if (hePingData.imgUrl !== tempData.imgUrl && hePingData.imgUrl && !hePingData.imgUrl.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: hePingData.imgUrl });
|
||||
}
|
||||
// #endif
|
||||
|
||||
Object.assign(hePingData, tempData);
|
||||
uni.setStorageSync('hePingData', hePingData);
|
||||
editPopup.value.close();
|
||||
|
||||
// 数据修改后,重新渲染海报
|
||||
finalPosterPath.value = '';
|
||||
let tempBg = bgImage.value;
|
||||
bgImage.value = ''; // 强制卸载旧画板,确保能重新渲染和生成新海报
|
||||
setTimeout(() => {
|
||||
bgImage.value = tempBg;
|
||||
}, 50);
|
||||
}
|
||||
|
||||
async function handleChangeTheme(typeIndex) {
|
||||
// 切换主题时,先清空旧海报,触发界面“加载中”提示
|
||||
finalPosterPath.value = '';
|
||||
bgImage.value = ''; // 强制卸载旧画板,确保能重新渲染和生成新海报
|
||||
hePingData.type = typeIndex;
|
||||
uni.setStorageSync('hePingData', hePingData);
|
||||
try {
|
||||
bgImage.value = await imgLocal.getLocalImage(`other/game/heping/bg-${typeIndex}.jpg`);
|
||||
} catch (e) {
|
||||
console.error('切换主题加载背景图失败:', e);
|
||||
uni.showToast({ title: '背景加载失败', icon: 'none' });
|
||||
}
|
||||
}
|
||||
|
||||
// 点击画布触发横向预览
|
||||
const handlePreview = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '海报仍在生成中,请稍候', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
showPreview.value = true;
|
||||
}
|
||||
|
||||
// 画布生成成功后触发,保存最终的海报路径
|
||||
const onPainterSuccess = (path) => {
|
||||
finalPosterPath.value = path;
|
||||
}
|
||||
|
||||
// 点击保存按钮,将带有渐变字体的最终图片存入相册
|
||||
const handleSave = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '图片仍在生成中,请稍候', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: finalPosterPath.value,
|
||||
success: () => {
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本地图片路径通过 Canvas 转换为 File 对象
|
||||
* @param {string} localPath - 本地图片路径(如从 uni.chooseImage 获取的 tempFilePath)
|
||||
* @param {Object} options - 可选参数
|
||||
* @param {string} options.format - 输出格式 'image/png' 或 'image/jpeg',默认 'image/png'
|
||||
* @param {number} options.quality - 图片质量(仅 jpeg 有效),0~1,默认 0.92
|
||||
* @param {number} options.maxWidth - 最大宽度(等比缩放),不填则使用原图尺寸
|
||||
* @param {number} options.maxHeight - 最大高度(等比缩放),不填则使用原图尺寸
|
||||
* @returns {Promise<File>} 返回一个 Promise,resolve 为 File 对象
|
||||
*/
|
||||
function convertLocalImageToFile(localPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
// 1. 读取本地图片为 Base64(避免 Image 对象直接加载本地路径的兼容问题)
|
||||
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
|
||||
entry.file((file) => {
|
||||
const reader = new plus.io.FileReader();
|
||||
reader.onload = (e) => {
|
||||
const base64Data = e.target.result; // 格式如 data:image/jpeg;base64,/9j/...
|
||||
resolve(e.target.result)
|
||||
};
|
||||
reader.onerror = (err) => reject(err);
|
||||
reader.readAsDataURL(file); // 读取为 DataURL
|
||||
}, reject);
|
||||
}, reject);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
reject(new Error('plus.io not supported'))
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.preview-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #000;
|
||||
z-index: 99999;
|
||||
/* 抛弃 flex 布局,防止 width: 100vh 被父级限制而发生坍缩 */
|
||||
}
|
||||
|
||||
.preview-overlay .preview-image {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100vh;
|
||||
height: 100vw;
|
||||
/* 先拉回自身中心点,再围绕中心点旋转 90 度 */
|
||||
transform: translate(-50%, -50%) rotate(90deg);
|
||||
}
|
||||
|
||||
.honor-of-kings {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.painter-container {
|
||||
/* 强制画板缩放到设备屏幕宽度,避免物理 px 超出屏幕 */
|
||||
padding: 8px;
|
||||
zoom: calc(100vw / 798);
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
/* 限制PC/iPad端的最大宽度 */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.save-action {
|
||||
margin-top: 60rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 220rpx;
|
||||
/* 留出底部主题固定栏的安全空间 */
|
||||
|
||||
.save-btn {
|
||||
margin-top: 60rpx;
|
||||
width: 316rpx;
|
||||
background: #1777FF;
|
||||
color: #fff;
|
||||
border-radius: 56rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.theme-selector {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding-top: 20rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
z-index: 99;
|
||||
|
||||
.theme-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-list {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.theme-item {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
margin: 0 10rpx;
|
||||
padding: 0 40rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx solid transparent;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
border-color: #3B7BFF;
|
||||
|
||||
.theme-text {
|
||||
color: #3B7BFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 85vw;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40rpx 0 20rpx 0;
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-scroll {
|
||||
max-height: 55vh;
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
.label {
|
||||
width: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.upload-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #999DA7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
margin-top: -6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
position: absolute;
|
||||
top: -4rpx;
|
||||
right: -4rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.img-box {
|
||||
width: 200rpx !important;
|
||||
|
||||
.avatar-preview {
|
||||
width: 200rpx !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
background-color: #F7F7F7;
|
||||
border-radius: 12rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 40rpx 40rpx;
|
||||
|
||||
button {
|
||||
width: 46%;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
font-size: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
margin: 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #F4F4F4;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #3B7BFF;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,829 @@
|
|||
<template>
|
||||
<view class="honor-of-kings">
|
||||
<nav-bar title="王者主页" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
|
||||
@right-click="onRightClick">
|
||||
</nav-bar>
|
||||
<view style="padding: 8px;box-sizing: border-box;">
|
||||
<view class="painter-container" @click="handlePreview"
|
||||
:style="`width:calc(100vw - 16px) ; height: ${posterContainerHeight}px; overflow: hidden; position: relative; transform: translateZ(0);`">
|
||||
<!-- 运用 js 算出的无误差纯数字 scale 来实现高清画板的等比缩小,彻底兼容所有老旧内核,不再被截断 -->
|
||||
<view
|
||||
:style="`width: 750px; transform: scale(${posterScaleRatio}); transform-origin: left top; position: absolute; left: 0; top: 0;`">
|
||||
<l-painter isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:750px;`">
|
||||
<l-painter-view :css="`width: 750.0px; position: relative;`">
|
||||
<!-- 直接使用主背景图撑开父容器,移除不必要的 opacity: 0 占位图,避免在大屏渲染时产生黑块 -->
|
||||
<l-painter-image :src="`/static/image/other/game/wangzhe/style-${honorData.type}.jpg`"
|
||||
css="width: 750.0px; display: block;"></l-painter-image>
|
||||
<!-- 头像 (纯百分比绝对定位,完美适配所有大屏分辨率) -->
|
||||
<l-painter-image :src="honorData.avatar"
|
||||
css="position: absolute; left: 117.0px; top: 76.8px; width: 66px; height: 66px; border-radius: 200px; object-fit: cover; display: block;"></l-painter-image>
|
||||
|
||||
<!-- 头像框 (压在头像上方) -->
|
||||
<l-painter-image :src="headerImage"
|
||||
css="position: absolute; left: 0; top: 0; width: 183px; height: 141px"></l-painter-image>
|
||||
|
||||
<!-- 性别图标 -->
|
||||
<l-painter-image :src="`/static/image/other/game/wangzhe/${honorData.gender}.png`"
|
||||
:css="`position: absolute; left: ${honorData.type == 3 ? '217.5px' : '202.5px'}; top: 87.0px; width: 11.8px; height: 11.7px;`"></l-painter-image>
|
||||
<!-- 昵称渐变图片 -->
|
||||
<l-painter-image v-if="nicknameImage" :src="nicknameImage"
|
||||
:css="`position: absolute; left: ${honorData.type == 3 ? '230.3px' : '215.3px'}; top: ${$system == 'iOS' ? '83px' : '85.6px'}; width: ${honorData.nickname.length * 14.9}px;`"></l-painter-image>
|
||||
<!-- 收到花束 -->
|
||||
<l-painter-text :text="honorData.receivedFlowers"
|
||||
css="position: absolute; left: 338.5px; top: 131.4px; width: 40px; text-align: center; font-size: 9px; color: #DAF2FF;font-family: WangZheFont2;"></l-painter-text>
|
||||
<!-- 热度数 -->
|
||||
<l-painter-text :text="honorData.popularityCount"
|
||||
css="position: absolute; left: 366.3px; top: 131.4px; width: 40px; text-align: center; font-size: 9px; color: #DAF2FF;font-family: WangZheFont2;"></l-painter-text>
|
||||
<!-- 点赞数 -->
|
||||
<l-painter-text :text="honorData.likeCount"
|
||||
css="position: absolute; left: 394.0px; top: 131.4px; width: 40px; text-align: center; font-size: 9px; color: #DAF2FF;font-family: WangZheFont2;"></l-painter-text>
|
||||
<!-- 荣誉一 -->
|
||||
<l-painter-text :text="honorData.honor1"
|
||||
css="position: absolute; left: 207.5px; top: 145.6px; width: 80px; text-align: center; font-size: 9px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 荣誉二(文案较长,需足够宽度避免换行下移) -->
|
||||
<l-painter-text :text="honorData.honor2"
|
||||
css="position: absolute; left: 300.6px; top: 149px; width: 180px; text-align: center; font-size: 7px; line-height: 1em; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 巅峰万强 -->
|
||||
<l-painter-text v-if="honorData.type == 4" :text="honorData.peakStrong"
|
||||
css="position: absolute; left: 227.3px; top: 192.8px; width: 60px; text-align: center; font-size: 8px; color: #E9F5FB;"></l-painter-text>
|
||||
<!-- 对战场次 -->
|
||||
<l-painter-text :text="honorData.matchCount"
|
||||
css="position: absolute; left: 113.0px; top: 242.3px; width: 50px; text-align: center; font-size: 12px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 对战被赞 -->
|
||||
<l-painter-text :text="honorData.matchLikeCount"
|
||||
css="position: absolute; left: 174.5px; top: 242.3px; width: 50px; text-align: center; font-size: 12px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 图鉴等级 -->
|
||||
<l-painter-text :text="honorData.pokedexLevel"
|
||||
css="position: absolute; left: 299.5px; top: 238.8px; width: 40px; text-align: center; font-size:9px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 皮肤数 -->
|
||||
<l-painter-text :text="honorData.skinCount"
|
||||
css="position: absolute; left: 357.3px; top: 238.8px; width: 40px; text-align: center; font-size:9px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 游戏天数 -->
|
||||
<l-painter-text v-if="honorData.type == 1 || honorData.type == 2" :text="honorData.gameDays"
|
||||
css="position: absolute; left: 177.1px; top: 282.2px; width: 50px; text-align: center; font-size:10px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 峡谷对战局数 -->
|
||||
<l-painter-text v-if="honorData.type == 1 || honorData.type == 2"
|
||||
:text="honorData.riftMatchCount"
|
||||
css="position: absolute; left: 297.2px; top: 282.2px; width: 50px; text-align: center; font-size:10px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 大乱斗对战局数 -->
|
||||
<l-painter-text v-if="honorData.type == 1 || honorData.type == 2"
|
||||
:text="honorData.aramMatchCount"
|
||||
css="position: absolute; left: 354.9px; top: 282.2px; width: 50px; text-align: center; font-size:10px; color: #71B1D3;"></l-painter-text>
|
||||
<!-- 亲密度 -->
|
||||
<l-painter-text v-if="honorData.type == 3 || honorData.type == 4" :text="honorData.intimacy"
|
||||
css="position: absolute; left: 323.0px; top: 296.2px; width: 50px; text-align: center; font-size:10px; color: #71B1D3;font-family: WangZheFont2;"></l-painter-text>
|
||||
|
||||
<!-- 水印 -->
|
||||
<l-painter-image v-if="$isVip()" src="/static/image/other/shuiying.png"
|
||||
:css="`position: absolute; left: 18.8px; bottom: 17.1px; width: 145.38px;height:42.76px`"></l-painter-image>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_wangzhe')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
|
||||
<view class="save-action">
|
||||
<button class="save-btn" @click="handleSave">保存</button>
|
||||
</view>
|
||||
|
||||
<!-- 主题选择区域 -->
|
||||
<view class="theme-selector" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<scroll-view scroll-x="true" class="theme-scroll" :show-scrollbar="false">
|
||||
<view class="theme-list">
|
||||
<view class="theme-item" v-for="(item, index) in ['样式一', '样式二', '样式三', '样式四']" :key="index + 1"
|
||||
:class="{ active: honorData.type == index + 1 }" @click="handleChangeTheme(index + 1)">
|
||||
<text class="theme-text">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 数据编辑弹窗 -->
|
||||
<uni-popup ref="editPopup" type="center">
|
||||
<view class="edit-popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="title">编辑主页数据</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="popup-scroll">
|
||||
<!-- <view class="form-item">
|
||||
<text class="label">样式类型</text>
|
||||
<input class="input" type="number" v-model="tempData.type" placeholder="1-4" />
|
||||
</view> -->
|
||||
<view class="form-item avatar-form-item">
|
||||
<text class="label">头像</text>
|
||||
<view class="avatar-uploader" @click="handleChooseAvatar">
|
||||
<view class="avatar-preview" v-if="tempData.avatar">
|
||||
<image class="preview-img" :src="tempData.avatar" mode="aspectFill"></image>
|
||||
<view class="delete-icon">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="upload-btn" v-else @click="handleChooseAvatar">
|
||||
<text class="plus">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">昵称</text>
|
||||
<input class="input" type="text" v-model="tempData.nickname" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">性别</text>
|
||||
<view class="radio-group">
|
||||
<view class="radio-item" @click="tempData.gender = 'man'">
|
||||
<view class="radio-icon" :class="{ active: tempData.gender === 'man' }"></view>
|
||||
<text class="radio-text" :class="{ active: tempData.gender === 'man' }">男</text>
|
||||
</view>
|
||||
<view class="radio-item" @click="tempData.gender = 'female'">
|
||||
<view class="radio-icon" :class="{ active: tempData.gender === 'female' }"></view>
|
||||
<text class="radio-text" :class="{ active: tempData.gender === 'female' }">女</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">荣誉一</text>
|
||||
<input class="input" type="text" v-model="tempData.honor1" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">荣誉二</text>
|
||||
<input class="input" type="text" v-model="tempData.honor2" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">巅峰万强</text>
|
||||
<input class="input" type="text" v-model="tempData.peakStrong" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">收到花束</text>
|
||||
<input class="input" type="text" v-model="tempData.receivedFlowers" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">热度</text>
|
||||
<input class="input" type="text" v-model="tempData.popularityCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">点赞数</text>
|
||||
<input class="input" type="text" v-model="tempData.likeCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">对战场次</text>
|
||||
<input class="input" type="number" v-model="tempData.matchCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">对战被赞</text>
|
||||
<input class="input" type="number" v-model="tempData.matchLikeCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">图鉴等级</text>
|
||||
<input class="input" type="number" v-model="tempData.pokedexLevel" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">皮肤数</text>
|
||||
<input class="input" type="number" v-model="tempData.skinCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">游戏天数</text>
|
||||
<input class="input" type="number" v-model="tempData.gameDays" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">峡谷对战局数</text>
|
||||
<input class="input" type="number" v-model="tempData.riftMatchCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">大乱斗局数</text>
|
||||
<input class="input" type="number" v-model="tempData.aramMatchCount" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">亲密度</text>
|
||||
<input class="input" type="number" v-model="tempData.intimacy" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<button class="cancel-btn" @click="closeEditPopup">取消</button>
|
||||
<button class="confirm-btn" @click="confirmEdit">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 隐藏的画布:用于原生绘制带有纯正渐变色的文本,再转成图片给到海报插件 -->
|
||||
<view style="position: absolute; left: -9999px; top: -9999px; width: 0; height: 0; overflow: hidden;">
|
||||
<canvas canvas-id="gradientTextCanvas" id="gradientTextCanvas" style="width: 300px; height: 60px;"></canvas>
|
||||
</view>
|
||||
|
||||
<!-- 横向全屏放大预览层 -->
|
||||
<view class="preview-overlay" v-if="showPreview" @click="showPreview = false">
|
||||
<image class="preview-image" :src="finalPosterPath" mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, getCurrentInstance } from 'vue'
|
||||
import { onLoad, onReady, onUnload } from '@dcloudio/uni-app'
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
const rightButtonText = ref("编辑");
|
||||
const instance = getCurrentInstance();
|
||||
const { proxy } = getCurrentInstance();
|
||||
const nicknameImage = ref('');
|
||||
const showPreview = ref(false); // 控制全屏预览
|
||||
const isMountedReady = ref(false);
|
||||
const isFontLoaded = ref(false);
|
||||
const headerImage = ref('')
|
||||
|
||||
// 获取系统宽度计算海报缩放比例,代替容易失效的 css calc(),确保全端兼容防截断
|
||||
const sysInfo = uni.getSystemInfoSync();
|
||||
const windowWidth = sysInfo.windowWidth || 375;
|
||||
const posterScaleRatio = windowWidth / 750;
|
||||
const posterContainerHeight = 342 * posterScaleRatio;
|
||||
|
||||
// 页面表单数据字段
|
||||
const honorData = reactive({
|
||||
type: 1, // 样式类型 1.2.3.4
|
||||
avatar: '/static/image/shopping/pdd/avatars/avatars1.jpg', // 头像
|
||||
nickname: '甜喵小贝', // 昵称
|
||||
gender: 'female', // 性别
|
||||
region: '重庆市两江新区', // 地区
|
||||
honor1: '国服第一小乔', // 荣誉1
|
||||
honor2: '888级大师收藏家·珍耀无双', // 荣誉2
|
||||
matchCount: 58965, // 对战场次
|
||||
matchLikeCount: 9746, // 对战被赞数
|
||||
gameDays: 3127, // 游戏天数
|
||||
pokedexLevel: 104, // 图鉴等级
|
||||
skinCount: 444, // 皮肤数
|
||||
riftMatchCount: 7368, // 峡谷对战局数
|
||||
aramMatchCount: 5193, // 大乱斗对战局数
|
||||
receivedFlowers: 520, // 收到花束
|
||||
popularityCount: '6.0W', // 热度数
|
||||
likeCount: 4883, // 点赞数
|
||||
intimacy: '25147',//亲密度
|
||||
peakStrong: '5632'
|
||||
})
|
||||
|
||||
onLoad(async () => {
|
||||
const cachedData = uni.getStorageSync('wangzheHonorData');
|
||||
if (cachedData) {
|
||||
Object.assign(honorData, cachedData);
|
||||
}
|
||||
headerImage.value = await imgLocal.getLocalImage(`other/game/wangzhe/avatar-frame-${honorData.type}.png`)
|
||||
|
||||
uni.$on('editFormPhoto', (info) => {
|
||||
tempData.avatar = info;
|
||||
// #ifndef H5
|
||||
if (info && !info.startsWith('/static/')) {
|
||||
newAvatars.value.push(info);
|
||||
}
|
||||
// #endif
|
||||
});
|
||||
|
||||
// 进入页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
key: 'wangzhe',
|
||||
prefix: '.uni.other.',
|
||||
value: "王者主页"
|
||||
})
|
||||
const config = uni.getStorageSync('config')
|
||||
console.log("---config---", config);
|
||||
let fontConfig = config.config['client.uniapp.font'];
|
||||
try {
|
||||
if (typeof fontConfig === 'string') {
|
||||
fontConfig = JSON.parse(fontConfig);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('字体配置解析失败', e);
|
||||
}
|
||||
|
||||
console.log("字体地址信息", fontConfig?.wangzhe);
|
||||
// Font loading logic
|
||||
const fontUrl = fontConfig?.wangzhe;
|
||||
const fontUrl2 = fontConfig?.wangzhe2;
|
||||
|
||||
let loadedCount = 0;
|
||||
const totalFonts = 2;
|
||||
const checkAllLoaded = () => {
|
||||
loadedCount++;
|
||||
if (loadedCount >= totalFonts) {
|
||||
isFontLoaded.value = true;
|
||||
if (isMountedReady.value) drawGradientText();
|
||||
}
|
||||
};
|
||||
|
||||
const loadSingleFont = (url, name, storageKey, onComplete) => {
|
||||
if (!url) {
|
||||
console.warn(`未获取到 ${name} 字体地址,回退使用系统默认字体`);
|
||||
onComplete && onComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
const doLoad = (path) => {
|
||||
uni.loadFontFace({
|
||||
family: name,
|
||||
source: `url("${path}")`,
|
||||
success() {
|
||||
console.log(`${name} 字体加载成功`);
|
||||
onComplete && onComplete();
|
||||
},
|
||||
fail(err) {
|
||||
console.error(`${name} 字体加载失败`, err);
|
||||
onComplete && onComplete();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// #ifdef H5
|
||||
// H5 环境直接从 URL 加载字体
|
||||
doLoad(url);
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
// 非 H5 环境使用下载和保存逻辑
|
||||
const savedPath = uni.getStorageSync(storageKey);
|
||||
if (savedPath) {
|
||||
doLoad(savedPath);
|
||||
} else {
|
||||
uni.downloadFile({
|
||||
url: url,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: (saveRes) => {
|
||||
const saved = saveRes.savedFilePath;
|
||||
uni.setStorageSync(storageKey, saved);
|
||||
console.log(`${name} 字体保存路径`, saved);
|
||||
doLoad(saved);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error(`保存 ${name} 文件失败`, err);
|
||||
// Fallback: 尝试加载临时路径
|
||||
doLoad(res.tempFilePath);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
onComplete && onComplete();
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error(`下载 ${name} 字体失败`, err);
|
||||
onComplete && onComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
};
|
||||
|
||||
loadSingleFont(fontUrl, 'WangZheFont', 'wangzhe_font_path', checkAllLoaded);
|
||||
loadSingleFont(fontUrl2, 'WangZheFont2', 'wangzhe_font2_path', checkAllLoaded);
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
uni.$off('editFormPhoto');
|
||||
})
|
||||
|
||||
const finalPosterPath = ref('');
|
||||
|
||||
const editPopup = ref(null);
|
||||
const tempData = reactive({});
|
||||
const newAvatars = ref([]);
|
||||
|
||||
async function handleChangeTheme(typeIndex) {
|
||||
// 切换主题时,先清空旧海报,触发界面“加载中”提示
|
||||
finalPosterPath.value = '';
|
||||
honorData.type = typeIndex;
|
||||
uni.setStorageSync('wangzheHonorData', honorData);
|
||||
headerImage.value = await imgLocal.getLocalImage(`other/game/wangzhe/avatar-frame-${typeIndex}.png`)
|
||||
}
|
||||
|
||||
function onRightClick() {
|
||||
Object.assign(tempData, honorData);
|
||||
newAvatars.value = [];
|
||||
editPopup.value.open();
|
||||
}
|
||||
|
||||
const handleChooseAvatar = () => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=200&height=200`
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteAvatar = () => {
|
||||
tempData.avatar = '';
|
||||
};
|
||||
|
||||
function closeEditPopup() {
|
||||
// #ifndef H5
|
||||
newAvatars.value.forEach(path => {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
});
|
||||
// #endif
|
||||
editPopup.value.close();
|
||||
}
|
||||
|
||||
function confirmEdit() {
|
||||
const isNicknameChanged = honorData.nickname !== tempData.nickname;
|
||||
|
||||
// #ifndef H5
|
||||
// 删除多余的新上传文件
|
||||
newAvatars.value.forEach(path => {
|
||||
if (path !== tempData.avatar) {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
}
|
||||
});
|
||||
// 删除被替换掉的原本地头像
|
||||
if (honorData.avatar !== tempData.avatar && honorData.avatar && !honorData.avatar.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: honorData.avatar });
|
||||
}
|
||||
// #endif
|
||||
|
||||
Object.assign(honorData, tempData);
|
||||
uni.setStorageSync('wangzheHonorData', honorData);
|
||||
editPopup.value.close();
|
||||
|
||||
// 数据修改后,清空旧海报触发“加载中”提示,等待重新生成
|
||||
finalPosterPath.value = '';
|
||||
|
||||
// 如果昵称改变了,需要重新绘制原生的渐变文字
|
||||
if (isNicknameChanged && isFontLoaded.value) {
|
||||
drawGradientText();
|
||||
}
|
||||
}
|
||||
|
||||
// 点击画布触发横向预览
|
||||
const handlePreview = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '海报仍在生成中,请稍候', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
showPreview.value = true;
|
||||
}
|
||||
|
||||
// 画布生成成功后触发,保存最终的海报路径
|
||||
const onPainterSuccess = (path) => {
|
||||
finalPosterPath.value = path;
|
||||
}
|
||||
|
||||
// 点击保存按钮,将带有渐变字体的最终图片存入相册
|
||||
const handleSave = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '图片仍在生成中,请稍候', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: finalPosterPath.value,
|
||||
success: () => {
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
isMountedReady.value = true;
|
||||
if (isFontLoaded.value) {
|
||||
drawGradientText();
|
||||
}
|
||||
})
|
||||
|
||||
// 原生 Canvas 绘制渐变文本导出为图片
|
||||
const drawGradientText = () => {
|
||||
// 以较大的像素绘制以保证生成的图片清晰
|
||||
const fontSize = 40;
|
||||
const textLen = honorData.nickname.length;
|
||||
// 文本的实际像素宽度
|
||||
const canvasWidth = fontSize * textLen;
|
||||
|
||||
const ctx = uni.createCanvasContext('gradientTextCanvas', instance.proxy);
|
||||
ctx.clearRect(0, 0, 300, 60);
|
||||
|
||||
// 设置粗体与字号,使用指定的 WangZheFont 字体
|
||||
ctx.font = `${fontSize}px "WangZheFont", sans-serif`;
|
||||
|
||||
// 原生创建横向线性渐变
|
||||
const grd = ctx.createLinearGradient(0, 0, canvasWidth, 0);
|
||||
grd.addColorStop(0, '#F9D577');
|
||||
grd.addColorStop(1, '#FFF5C4');
|
||||
|
||||
ctx.setFillStyle(grd);
|
||||
ctx.setTextBaseline('top');
|
||||
// 绘制文字
|
||||
ctx.fillText(honorData.nickname, 0, 0);
|
||||
|
||||
ctx.draw(false, () => {
|
||||
// 稍微延迟确保绘制完毕
|
||||
setTimeout(() => {
|
||||
uni.canvasToTempFilePath({
|
||||
canvasId: 'gradientTextCanvas',
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: canvasWidth,
|
||||
height: fontSize + 10,
|
||||
destWidth: canvasWidth * 2, // 2倍图保证海报中的清晰度
|
||||
destHeight: (fontSize + 10) * 2,
|
||||
success: (res) => {
|
||||
nicknameImage.value = res.tempFilePath;
|
||||
}
|
||||
}, instance.proxy)
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.preview-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #000;
|
||||
z-index: 99999;
|
||||
/* 抛弃 flex 布局,防止 width: 100vh 被父级限制而发生坍缩 */
|
||||
}
|
||||
|
||||
.preview-overlay .preview-image {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100vh;
|
||||
height: 100vw;
|
||||
/* 先拉回自身中心点,再围绕中心点旋转 90 度 */
|
||||
transform: translate(-50%, -50%) rotate(90deg);
|
||||
}
|
||||
|
||||
.honor-of-kings {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.painter-container {
|
||||
/* 强制画板缩放到设备屏幕宽度,避免物理 px 超出屏幕 */
|
||||
padding: 8px;
|
||||
zoom: calc(100vw / 798);
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
/* 限制PC/iPad端的最大宽度 */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.save-action {
|
||||
margin-top: 60rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 220rpx;
|
||||
/* 留出底部主题固定栏的安全空间 */
|
||||
|
||||
.save-btn {
|
||||
margin-top: 60rpx;
|
||||
width: 316rpx;
|
||||
background: #1777FF;
|
||||
color: #fff;
|
||||
border-radius: 56rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.theme-selector {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding-top: 20rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
z-index: 99;
|
||||
|
||||
.theme-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-list {
|
||||
display: inline-block;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.theme-item {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
margin: 0 10rpx;
|
||||
padding: 0 40rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx solid transparent;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
border-color: #3B7BFF;
|
||||
|
||||
.theme-text {
|
||||
color: #3B7BFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 85vw;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40rpx 0 20rpx 0;
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-scroll {
|
||||
height: 55vh;
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
.label {
|
||||
width: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.upload-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #999DA7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
margin-top: -6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
position: absolute;
|
||||
top: -4rpx;
|
||||
right: -4rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
background-color: #F7F7F7;
|
||||
border-radius: 12rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 40rpx;
|
||||
|
||||
.radio-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.radio-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
margin-right: 12rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.active {
|
||||
border-color: #3B7BFF;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #3B7BFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.radio-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
|
||||
&.active {
|
||||
color: #3B7BFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 40rpx 40rpx;
|
||||
|
||||
button {
|
||||
width: 46%;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
font-size: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
margin: 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #F4F4F4;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #3B7BFF;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<nav-bar title="游戏平台" bgColor="#F0F4F9"></nav-bar>
|
||||
<view class="menu-container">
|
||||
<view class="card" v-for="(item, index) in menuList" :key="index" style=" background: #ffffff ">
|
||||
<text class="card-title">{{ item.name }}</text>
|
||||
<view class="icon-wrapper">
|
||||
<view class="icon-shadow" :style="{ background: item.shadowColor }"></view>
|
||||
<image class="icon-img" :src="`/static/image/other/game/${item.icon}.png`" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="btn" style="background: linear-gradient( 327deg, #1777FF 0%, #17CDFF 100%);"
|
||||
@click="goTo(item.url)">立即进入</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
onLoad(() => {
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'game',
|
||||
prefix: '.uni.other.',
|
||||
value: '游戏'
|
||||
})
|
||||
})
|
||||
|
||||
const menuList = ref([{
|
||||
name: "王者荣耀",
|
||||
icon: "wangzhe",
|
||||
shadowColor: "#FF604F",
|
||||
url: "/pages/other/game/honor-of-kings"
|
||||
}, {
|
||||
name: "三角洲",
|
||||
icon: "sanjiaozhou",
|
||||
shadowColor: "#12C96A",
|
||||
url: "/pages/other/game/sanjiaozhou"
|
||||
}, {
|
||||
name: "和平精英",
|
||||
icon: "hepingjingying",
|
||||
shadowColor: "#4992F2",
|
||||
url: "/pages/other/game/hepingjingying"
|
||||
}, {
|
||||
name: "无畏契约",
|
||||
icon: "wuweiqiyue",
|
||||
shadowColor: "#FF3333",
|
||||
url: "/pages/other/game/wuweiqiyue"
|
||||
}]);
|
||||
|
||||
const goTo = (url) => {
|
||||
if (url) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "开发中",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #F0F4F9;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: calc(50% - 14rpx);
|
||||
border-radius: 28rpx 28rpx 28rpx 28rpx;
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 48rpx;
|
||||
padding-bottom: 40rpx;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 62rpx;
|
||||
position: relative;
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-img {
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.icon-shadow {
|
||||
position: absolute;
|
||||
bottom: -10rpx;
|
||||
width: 100rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
filter: blur(5px);
|
||||
z-index: 1;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 20rpx;
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
border-radius: 16rpx 16rpx 16rpx 16rpx;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,819 @@
|
|||
<template>
|
||||
<view class="honor-of-kings">
|
||||
<nav-bar title="三角洲结算页" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
|
||||
@right-click="onRightClick">
|
||||
</nav-bar>
|
||||
<view style="padding: 8px;box-sizing: border-box;">
|
||||
<view class="painter-container" @click="handlePreview"
|
||||
:style="`width:calc(100vw - 16px) ; height: ${posterContainerHeight}px; overflow: hidden; position: relative; transform: translateZ(0);`">
|
||||
<!-- 运用 js 算出的无误差纯数字 scale 来实现高清画板的等比缩小,彻底兼容所有老旧内核,不再被截断 -->
|
||||
<view
|
||||
:style="`width: 750px; transform: scale(${posterScaleRatio}); transform-origin: left top; position: absolute; left: 0; top: 0;`">
|
||||
<l-painter isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:750px;`">
|
||||
<l-painter-view :css="`width: 750.0px; position: relative;`">
|
||||
<!-- 直接使用主背景图撑开父容器,移除不必要的 opacity: 0 占位图,避免在大屏渲染时产生黑块 -->
|
||||
<l-painter-image :src="`/static/image/other/game/sanjiaozhou/style-${data.type}.jpg`"
|
||||
css="width: 750.0px; display: block;"></l-painter-image>
|
||||
|
||||
<!-- 顶部信息栏:绝对定位,避免鸿蒙 inline-block 竖排 -->
|
||||
<!-- 地图 -->
|
||||
<l-painter-image src="/static/image/other/game/sanjiaozhou/line.png"
|
||||
css="position:absolute;left:73px;top:113px;height:22px;width:1px;"></l-painter-image>
|
||||
<l-painter-text
|
||||
css="position:absolute;left:78px;top:113px;color:#CDCDCD;font-size:6px;line-height:1em;"
|
||||
:text="data.map.level"></l-painter-text>
|
||||
<l-painter-text
|
||||
css="position:absolute;left:78px;top:123px;color:#CDCDCD;font-size:10px;line-height:1em;"
|
||||
:text="data.map.name"></l-painter-text>
|
||||
<!-- 撤离点 -->
|
||||
<l-painter-image src="/static/image/other/game/sanjiaozhou/line.png"
|
||||
css="position:absolute;left:155px;top:113px;height:22px;width:1px;"></l-painter-image>
|
||||
<l-painter-text
|
||||
css="position:absolute;left:160px;top:113px;color:#CDCDCD;font-size:6px;line-height:1em;"
|
||||
text="撤离点"></l-painter-text>
|
||||
<l-painter-text
|
||||
css="position:absolute;left:160px;top:123px;color:#CDCDCD;font-size:10px;line-height:1em;"
|
||||
:text="data.extractionPoint"></l-painter-text>
|
||||
<!-- 时长 -->
|
||||
<l-painter-image src="/static/image/other/game/sanjiaozhou/line.png"
|
||||
css="position:absolute;left:237px;top:113px;height:22px;width:1px;"></l-painter-image>
|
||||
<l-painter-text
|
||||
css="position:absolute;left:242px;top:113px;color:#CDCDCD;font-size:6px;line-height:1em;"
|
||||
text="时长"></l-painter-text>
|
||||
<l-painter-text v-for="(item, idx) in durationChars" :key="'durationNum_' + idx"
|
||||
:css="item.css" :text="item.text"></l-painter-text>
|
||||
<!-- 对局时间 -->
|
||||
<l-painter-image src="/static/image/other/game/sanjiaozhou/line.png"
|
||||
css="position:absolute;left:319px;top:113px;height:22px;width:1px;"></l-painter-image>
|
||||
<l-painter-text
|
||||
css="position:absolute;left:324px;top:113px;color:#CDCDCD;font-size:6px;line-height:1em;"
|
||||
text="对局时间"></l-painter-text>
|
||||
<l-painter-text v-for="(item, idx) in matchTimeChars" :key="'matchTimeNum_' + idx"
|
||||
:css="item.css" :text="item.text"></l-painter-text>
|
||||
|
||||
<!-- 本局收获 -->
|
||||
<l-painter-text v-for="(item, idx) in harvestChars" :key="'harvestNum_' + idx"
|
||||
:css="item.css" :text="item.text"></l-painter-text>
|
||||
|
||||
<!-- 击败干员 -->
|
||||
<l-painter-text v-for="(item, idx) in defeatChars" :key="'bigNum_' + idx"
|
||||
:css="item.css" :text="item.text"></l-painter-text>
|
||||
|
||||
<!-- 高光击败 -->
|
||||
<template v-for="(item, index) in data.defeatInfo" :key="'kill_' + index">
|
||||
<l-painter-image src="/static/image/other/game/sanjiaozhou/kill.png"
|
||||
:css="`position:absolute;left:73px;top:${295 + index * 16}px;width:12px;height:12px;`"></l-painter-image>
|
||||
<l-painter-text
|
||||
:css="`position:absolute;left:87px;top:${297 + index * 16}px;color:#DBE5E6;font-size:9px;line-height:1em;`"
|
||||
:text="`${item.name} [${item.rank}]`"></l-painter-text>
|
||||
</template>
|
||||
|
||||
<!-- 玩家名称(鸿蒙不支持 rotate,保持位置) -->
|
||||
<l-painter-text
|
||||
css="color:#CDCDCD;font-size:10px;line-height:1em;position:absolute;left:424px;top:310px;transform: rotate(12deg);"
|
||||
:text="data.name"></l-painter-text>
|
||||
<l-painter-text
|
||||
css="color:#CDCDCD;font-size:7px;line-height:1em;position:absolute;left:422px;top:321px;opacity:0.6;transform: rotate(12deg);"
|
||||
text="信守不渝"></l-painter-text>
|
||||
|
||||
<!-- 水印 -->
|
||||
<l-painter-image v-if="$isVip()" src="/static/image/other/shuiying.png"
|
||||
:css="`position: absolute; left: 18.8px; bottom: 17.1px; width: 145.38px;height:42.76px`"></l-painter-image>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_sanjiaozhou')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
|
||||
<view class="save-action">
|
||||
<button class="save-btn" @click="handleSave">保存</button>
|
||||
</view>
|
||||
|
||||
<!-- 主题选择区域 -->
|
||||
<view class="theme-selector" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<scroll-view scroll-x="true" class="theme-scroll" :show-scrollbar="false">
|
||||
<view class="theme-list">
|
||||
<view class="theme-item" v-for="(item, index) in ['样式一', '样式二', '样式三', '样式四']" :key="index + 1"
|
||||
:class="{ active: data.type == index + 1 }" @click="handleChangeTheme(index + 1)">
|
||||
<text class="theme-text">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 数据编辑弹窗 -->
|
||||
<uni-popup ref="editPopup" type="center">
|
||||
<view class="edit-popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="title">编辑主页数据</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="popup-scroll">
|
||||
<view class="form-item">
|
||||
<text class="label">玩家名称</text>
|
||||
<input class="input" type="text" v-model="tempData.name" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">地图级别</text>
|
||||
<view class="button-group">
|
||||
<view class="button-item" :class="{ active: tempData.map.level === '普通' }"
|
||||
@click="tempData.map.level = '普通'">普通</view>
|
||||
<view class="button-item" :class="{ active: tempData.map.level === '机密' }"
|
||||
@click="tempData.map.level = '机密'">机密</view>
|
||||
<view class="button-item" :class="{ active: tempData.map.level === '绝密' }"
|
||||
@click="tempData.map.level = '绝密'">绝密</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">地图名称</text>
|
||||
<input class="input" type="text" v-model="tempData.map.name" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">撤离点</text>
|
||||
<input class="input" type="text" v-model="tempData.extractionPoint" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">对局时间</text>
|
||||
<picker mode="multiSelector" :range="matchTimeRange" :value="matchTimeIndex"
|
||||
@change="onMatchTimeChange" class="input"
|
||||
style="height: 36px; line-height: 36px; display: flex; align-items: center;">
|
||||
<text>{{ tempData.matchTime || '请选择时间' }}</text>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">时长</text>
|
||||
<picker mode="multiSelector" :range="durationRange" :value="durationIndex"
|
||||
@change="onDurationChange" class="input"
|
||||
style="height: 36px; line-height: 36px; display: flex; align-items: center;">
|
||||
<text>{{ tempData.duration || '请选择时长' }}</text>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">本局收获</text>
|
||||
<input class="input" type="text" v-model="tempData.harvest" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">击败干员</text>
|
||||
<input class="input" type="text" v-model="tempData.defeat" @input="onDefeatChange" />
|
||||
</view>
|
||||
<view style="border: 1px dashed #007aff;padding: 10px;border-radius: 8px;"
|
||||
v-if="tempData.defeatInfo && tempData.defeatInfo.length > 0">
|
||||
<view v-for="(item, index) in tempData.defeatInfo" :key="'defeat_' + index"
|
||||
style="margin-bottom: 10px;">
|
||||
<view
|
||||
style="display: flex; justify-content: flex-end; gap: 15px; margin-bottom: 5px; font-size: 12px; height: 16px;"
|
||||
v-if="tempData.defeatInfo.length > 1">
|
||||
<text v-if="index > 0" @click="moveDefeatUp(index)"
|
||||
style="color: #007aff; cursor: pointer;">↑ 上移</text>
|
||||
<text v-if="index < tempData.defeatInfo.length - 1" @click="moveDefeatDown(index)"
|
||||
style="color: #007aff; cursor: pointer;">↓ 下移</text>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">被击败者{{ index + 1 }}昵称</text>
|
||||
<input class="input" type="text" v-model="item.name" />
|
||||
</view>
|
||||
<view class="form-item" style="margin-bottom: 0;">
|
||||
<text class="label">被击败者{{ index + 1 }}段位</text>
|
||||
<input class="input" type="text" v-model="item.rank" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<button class="cancel-btn" @click="closeEditPopup">取消</button>
|
||||
<button class="confirm-btn" @click="confirmEdit">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 横向全屏放大预览层 -->
|
||||
<view class="preview-overlay" v-if="showPreview" @click="showPreview = false">
|
||||
<image class="preview-image" :src="finalPosterPath" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted, getCurrentInstance } from 'vue'
|
||||
import { onLoad, onUnload } from '@dcloudio/uni-app'
|
||||
const rightButtonText = ref("编辑");
|
||||
const { proxy } = getCurrentInstance();
|
||||
const showPreview = ref(false); // 控制全屏预览
|
||||
const isMountedReady = ref(false);
|
||||
|
||||
// 获取系统宽度计算海报缩放比例,代替容易失效的 css calc(),确保全端兼容防截断
|
||||
const sysInfo = uni.getSystemInfoSync();
|
||||
const windowWidth = sysInfo.windowWidth || 375;
|
||||
const posterScaleRatio = windowWidth / 750;
|
||||
const posterContainerHeight = 430 * posterScaleRatio;
|
||||
|
||||
// 页面表单数据字段
|
||||
const data = reactive({
|
||||
type: 1, // 样式类型 1.2.3.4
|
||||
name: '大坝猛攻哥',
|
||||
map: {
|
||||
name: '零号大坝',
|
||||
level: '机密'
|
||||
},
|
||||
extractionPoint: '工业电梯',
|
||||
duration: "00:25:19",
|
||||
matchTime: '02-32 21:02',
|
||||
harvest: '13526559',
|
||||
defeat: '1',
|
||||
defeatInfo: [
|
||||
{
|
||||
name: '大坝贪吃鼠',
|
||||
rank: "黑鹰II"
|
||||
},
|
||||
]
|
||||
|
||||
})
|
||||
|
||||
// 数字到 my-icon iconfont Unicode 的映射字典
|
||||
const digitIconMap = {
|
||||
'0': '\ue629', '1': '\ue627', '2': '\ue62b', '3': '\ue62c', '4': '\ue62f',
|
||||
'5': '\ue62d', '6': '\ue628', '7': '\ue625', '8': '\ue62a', '9': '\ue62e',
|
||||
',': '\ue626', ':': '\ue630',
|
||||
};
|
||||
|
||||
const getDefeatIconText = (defeatStr) => {
|
||||
if (!defeatStr && defeatStr !== 0) return '';
|
||||
return String(defeatStr).split('').map(char => digitIconMap[char] || char).join('');
|
||||
};
|
||||
|
||||
/** 时长/对局时间:按步进绝对定位(鸿蒙 inline-block 不横排) */
|
||||
function layoutTimeChars(str, startLeft, startTop) {
|
||||
let x = startLeft
|
||||
return String(str || '').split('').map((char) => {
|
||||
const fontSize = char === '-' ? 12 : (char === ':' ? 4 : 10)
|
||||
const step = char === ':' ? 4 : (char === '-' ? 10 : (char === ' ' ? 6 : 8))
|
||||
const left = x
|
||||
x += step
|
||||
return {
|
||||
text: getDefeatIconText(char),
|
||||
css: `position:absolute;left:${left}px;top:${startTop}px;color:#CDCDCD;font-size:${fontSize}px;line-height:1em;font-family:myIconFont;`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 本局收获数字 */
|
||||
function layoutHarvestChars(str, startLeft, startTop) {
|
||||
const formatted = String(str || '').replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
let x = startLeft
|
||||
return formatted.split('').map((char) => {
|
||||
const fontSize = char === ',' ? 6 : 22
|
||||
const step = char === ',' ? 8 : 19
|
||||
const top = char === ',' ? startTop + 3 : startTop
|
||||
const left = x
|
||||
x += step
|
||||
return {
|
||||
text: getDefeatIconText(char),
|
||||
css: `position:absolute;left:${left}px;top:${top}px;color:#DBE5E6;font-size:${fontSize}px;line-height:1em;font-family:myIconFont;`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 击败干员数字 */
|
||||
function layoutDefeatChars(str, startLeft, startTop) {
|
||||
let x = startLeft
|
||||
return String(str || '').split('').map((char) => {
|
||||
const left = x
|
||||
x += 20
|
||||
return {
|
||||
text: getDefeatIconText(char),
|
||||
css: `position:absolute;left:${left}px;top:${startTop}px;color:#DBE5E6;font-size:22px;line-height:1em;font-family:myIconFont;`
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const durationChars = computed(() => layoutTimeChars(data.duration, 242, 123))
|
||||
const matchTimeChars = computed(() => layoutTimeChars(data.matchTime, 324, 123))
|
||||
const harvestChars = computed(() => layoutHarvestChars(data.harvest, 73, 182))
|
||||
const defeatChars = computed(() => layoutDefeatChars(data.defeat, 73, 250))
|
||||
|
||||
onLoad(() => {
|
||||
const cachedData = uni.getStorageSync('sanjiaozhouData');
|
||||
if (cachedData) {
|
||||
Object.assign(data, cachedData);
|
||||
}
|
||||
|
||||
uni.$on('editFormPhoto', (info) => {
|
||||
tempData.avatar = info;
|
||||
// #ifndef H5
|
||||
if (info && !info.startsWith('/static/')) {
|
||||
newAvatars.value.push(info);
|
||||
}
|
||||
// #endif
|
||||
});
|
||||
|
||||
// 进入页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
key: 'sanjiaozhou',
|
||||
prefix: '.uni.other.',
|
||||
value: "三角洲结算页"
|
||||
})
|
||||
|
||||
// 加载海报需要用到的自定义数字字体
|
||||
uni.loadFontFace({
|
||||
family: 'myIconFont',
|
||||
source: `url("/static/font/iconfont.ttf")`,
|
||||
success() {
|
||||
console.log('myIconFont 字体加载成功');
|
||||
},
|
||||
fail(err) {
|
||||
console.error('myIconFont 字体加载失败', err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onUnload(() => {
|
||||
uni.$off('editFormPhoto');
|
||||
})
|
||||
|
||||
const finalPosterPath = ref('');
|
||||
|
||||
const editPopup = ref(null);
|
||||
const tempData = reactive({
|
||||
map: {},
|
||||
defeatInfo: [{}]
|
||||
});
|
||||
const newAvatars = ref([]);
|
||||
|
||||
const onDefeatChange = (e) => {
|
||||
const val = parseInt(e.detail.value) || 0;
|
||||
const maxAllowed = Math.min(3, Math.max(0, val));
|
||||
|
||||
if (tempData.defeatInfo.length < maxAllowed) {
|
||||
const toAdd = maxAllowed - tempData.defeatInfo.length;
|
||||
for (let i = 0; i < toAdd; i++) {
|
||||
tempData.defeatInfo.push({ name: '', rank: '' });
|
||||
}
|
||||
} else if (tempData.defeatInfo.length > maxAllowed) {
|
||||
tempData.defeatInfo.splice(maxAllowed);
|
||||
}
|
||||
};
|
||||
|
||||
const moveDefeatUp = (index) => {
|
||||
if (index > 0) {
|
||||
const item = tempData.defeatInfo.splice(index, 1)[0];
|
||||
tempData.defeatInfo.splice(index - 1, 0, item);
|
||||
}
|
||||
};
|
||||
|
||||
const moveDefeatDown = (index) => {
|
||||
if (index < tempData.defeatInfo.length - 1) {
|
||||
const item = tempData.defeatInfo.splice(index, 1)[0];
|
||||
tempData.defeatInfo.splice(index + 1, 0, item);
|
||||
}
|
||||
};
|
||||
|
||||
// 时长选择器数据
|
||||
const durationRange = ref([
|
||||
Array.from({ length: 100 }, (_, i) => (i < 10 ? '0' + i : i + '')),
|
||||
Array.from({ length: 60 }, (_, i) => (i < 10 ? '0' + i : i + '')),
|
||||
Array.from({ length: 60 }, (_, i) => (i < 10 ? '0' + i : i + ''))
|
||||
]);
|
||||
const durationIndex = ref([0, 0, 0]);
|
||||
|
||||
const onDurationChange = (e) => {
|
||||
const val = e.detail.value;
|
||||
durationIndex.value = val;
|
||||
tempData.duration = `${durationRange.value[0][val[0]]}:${durationRange.value[1][val[1]]}:${durationRange.value[2][val[2]]}`;
|
||||
};
|
||||
|
||||
// 对局时间选择器数据
|
||||
const matchTimeRange = ref([
|
||||
Array.from({ length: 12 }, (_, i) => (i + 1 < 10 ? '0' + (i + 1) : (i + 1) + '')),
|
||||
Array.from({ length: 31 }, (_, i) => (i + 1 < 10 ? '0' + (i + 1) : (i + 1) + '')),
|
||||
Array.from({ length: 24 }, (_, i) => (i < 10 ? '0' + i : i + '')),
|
||||
Array.from({ length: 60 }, (_, i) => (i < 10 ? '0' + i : i + ''))
|
||||
]);
|
||||
const matchTimeIndex = ref([0, 0, 0, 0]);
|
||||
|
||||
const onMatchTimeChange = (e) => {
|
||||
const val = e.detail.value;
|
||||
matchTimeIndex.value = val;
|
||||
tempData.matchTime = `${matchTimeRange.value[0][val[0]]}-${matchTimeRange.value[1][val[1]]} ${matchTimeRange.value[2][val[2]]}:${matchTimeRange.value[3][val[3]]}`;
|
||||
};
|
||||
|
||||
const initPickerIndexes = () => {
|
||||
if (tempData.duration) {
|
||||
const parts = tempData.duration.split(':');
|
||||
if (parts.length === 3) {
|
||||
durationIndex.value = [parseInt(parts[0]) || 0, parseInt(parts[1]) || 0, parseInt(parts[2]) || 0];
|
||||
}
|
||||
}
|
||||
if (tempData.matchTime) {
|
||||
const spaceSplit = tempData.matchTime.split(' ');
|
||||
if (spaceSplit.length === 2) {
|
||||
const dateParts = spaceSplit[0].split('-');
|
||||
const timeParts = spaceSplit[1].split(':');
|
||||
if (dateParts.length === 2 && timeParts.length === 2) {
|
||||
matchTimeIndex.value = [(parseInt(dateParts[0]) || 1) - 1, (parseInt(dateParts[1]) || 1) - 1, parseInt(timeParts[0]) || 0, parseInt(timeParts[1]) || 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function handleChangeTheme(typeIndex) {
|
||||
// 切换主题时,先清空旧海报,触发界面“加载中”提示
|
||||
finalPosterPath.value = '';
|
||||
data.type = typeIndex;
|
||||
uni.setStorageSync('sanjiaozhouData', data);
|
||||
}
|
||||
|
||||
function onRightClick() {
|
||||
Object.assign(tempData, JSON.parse(JSON.stringify(data)));
|
||||
initPickerIndexes();
|
||||
newAvatars.value = [];
|
||||
editPopup.value.open();
|
||||
}
|
||||
|
||||
function closeEditPopup() {
|
||||
// #ifndef H5
|
||||
newAvatars.value.forEach(path => {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
});
|
||||
// #endif
|
||||
editPopup.value.close();
|
||||
}
|
||||
|
||||
function confirmEdit() {
|
||||
// #ifndef H5
|
||||
// 删除多余的新上传文件
|
||||
newAvatars.value.forEach(path => {
|
||||
if (path !== tempData.avatar) {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
}
|
||||
});
|
||||
// 删除被替换掉的原本地头像
|
||||
if (data.avatar !== tempData.avatar && data.avatar && !data.avatar.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: data.avatar });
|
||||
}
|
||||
// #endif
|
||||
|
||||
Object.assign(data, tempData);
|
||||
uni.setStorageSync('sanjiaozhouData', data);
|
||||
editPopup.value.close();
|
||||
|
||||
// 数据修改后,清空旧海报触发“加载中”提示,等待重新生成
|
||||
finalPosterPath.value = '';
|
||||
}
|
||||
|
||||
// 点击画布触发横向预览
|
||||
const handlePreview = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '海报仍在生成中,请稍候', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
showPreview.value = true;
|
||||
}
|
||||
|
||||
// 画布生成成功后触发,保存最终的海报路径
|
||||
const onPainterSuccess = (path) => {
|
||||
finalPosterPath.value = path;
|
||||
}
|
||||
|
||||
// 点击保存按钮,将带有渐变字体的最终图片存入相册
|
||||
const handleSave = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '图片仍在生成中,请稍候', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: finalPosterPath.value,
|
||||
success: () => {
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
isMountedReady.value = true;
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.preview-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #000;
|
||||
z-index: 99999;
|
||||
/* 抛弃 flex 布局,防止 width: 100vh 被父级限制而发生坍缩 */
|
||||
}
|
||||
|
||||
.preview-overlay .preview-image {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100vh;
|
||||
height: 100vw;
|
||||
/* 先拉回自身中心点,再围绕中心点旋转 90 度 */
|
||||
transform: translate(-50%, -50%) rotate(90deg);
|
||||
}
|
||||
|
||||
.honor-of-kings {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.painter-container {
|
||||
/* 强制画板缩放到设备屏幕宽度,避免物理 px 超出屏幕 */
|
||||
padding: 8px;
|
||||
zoom: calc(100vw / 798);
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
/* 限制PC/iPad端的最大宽度 */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.save-action {
|
||||
margin-top: 60rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 220rpx;
|
||||
/* 留出底部主题固定栏的安全空间 */
|
||||
|
||||
.save-btn {
|
||||
margin-top: 60rpx;
|
||||
width: 316rpx;
|
||||
background: #1777FF;
|
||||
color: #fff;
|
||||
border-radius: 56rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.theme-selector {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding-top: 20rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
z-index: 99;
|
||||
|
||||
.theme-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-list {
|
||||
display: inline-block;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.theme-item {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
margin: 0 10rpx;
|
||||
padding: 0 40rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx solid transparent;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
border-color: #3B7BFF;
|
||||
|
||||
.theme-text {
|
||||
color: #3B7BFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 85vw;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40rpx 0 20rpx 0;
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-scroll {
|
||||
height: 55vh;
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
.label {
|
||||
width: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.upload-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #999DA7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
margin-top: -6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
position: absolute;
|
||||
top: -4rpx;
|
||||
right: -4rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
background-color: #F7F7F7;
|
||||
border-radius: 12rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.radio-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 40rpx;
|
||||
|
||||
.radio-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.radio-icon {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #d9d9d9;
|
||||
margin-right: 12rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.active {
|
||||
border-color: #3B7BFF;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #3B7BFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.radio-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
|
||||
&.active {
|
||||
color: #3B7BFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
.button-item {
|
||||
padding: 4rpx 16rpx;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
margin-right: 16rpx;
|
||||
color: #666;
|
||||
background-color: #F7F7F7;
|
||||
border: 2rpx solid transparent;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
|
||||
&.active {
|
||||
color: #3B7BFF;
|
||||
background-color: rgba(59, 123, 255, 0.1);
|
||||
border-color: #3B7BFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 40rpx 40rpx;
|
||||
|
||||
button {
|
||||
width: 46%;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
font-size: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
margin: 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #F4F4F4;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #3B7BFF;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,727 @@
|
|||
<template>
|
||||
<view class="honor-of-kings">
|
||||
<nav-bar title="无畏契约" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
|
||||
@right-click="onRightClick">
|
||||
</nav-bar>
|
||||
<view style="padding: 8px;box-sizing: border-box;">
|
||||
<view class="painter-container" @click="handlePreview"
|
||||
:style="`width:calc(100vw - 16px) ; height: ${posterContainerHeight}px; overflow: hidden; position: relative; transform: translateZ(0);`">
|
||||
<!-- 运用 js 算出的无误差纯数字 scale 来实现高清画板的等比缩小,彻底兼容所有老旧内核,不再被截断 -->
|
||||
<view
|
||||
:style="`width: 822px; transform: scale(${posterScaleRatio}); transform-origin: left top; position: absolute; left: 0; top: 0;`">
|
||||
<l-painter v-if="bgImage" isCanvasToTempFilePath @success="onPainterSuccess" :css="`width:822px;`">
|
||||
<l-painter-view :css="`width: 822px; position: relative;`">
|
||||
<!-- 直接使用主背景图撑开父容器,移除不必要的 opacity: 0 占位图,避免在大屏渲染时产生黑块 -->
|
||||
<l-painter-image :src="bgImage" css="width: 822px; display: block;"></l-painter-image>
|
||||
|
||||
<!-- 人物图片 -->
|
||||
<l-painter-image :src="wuweiData.imgUrl" :css="characterStyle"></l-painter-image>
|
||||
<template v-if="wuweiData.type == 1">
|
||||
<!-- 击败 -->
|
||||
<l-painter-text :text="wuweiData.killCount"
|
||||
:css="`${style1TextCommonStyle}; left:61px;`"></l-painter-text>
|
||||
<!-- 精准射击 -->
|
||||
<l-painter-text :text="wuweiData.shooting"
|
||||
:css="`${style1TextCommonStyle}; left:131px;`"></l-painter-text>
|
||||
<!-- 输出伤害 -->
|
||||
<l-painter-text :text="wuweiData.output"
|
||||
:css="`${style1TextCommonStyle}; left:201px;`"></l-painter-text>
|
||||
<!-- 获得资金 -->
|
||||
<l-painter-text :text="wuweiData.harvest"
|
||||
:css="`${style1TextCommonStyle}; left:272px;`"></l-painter-text>
|
||||
<!-- 三连击败 -->
|
||||
<l-painter-text :text="wuweiData.threeKill"
|
||||
:css="`${style1TextCommonStyle}; left:342px;`"></l-painter-text>
|
||||
</template>
|
||||
<template v-if="wuweiData.type == 2">
|
||||
<!-- 击败 -->
|
||||
<l-painter-text :text="wuweiData.killCount"
|
||||
css="position: absolute; left: 70px; bottom: 122px; width:40px; text-align:center; font-size: 18px;font-weight: 700;color: #FFFFFF;line-height: 18px;"></l-painter-text>
|
||||
<!-- 头像 -->
|
||||
<l-painter-image :src="wuweiData.avatar"
|
||||
css="position:absolute;left:65.5px;bottom:68.5px;width:42px;height:42px"></l-painter-image>
|
||||
<!-- 昵称 -->
|
||||
<l-painter-text :text="truncatedNickname"
|
||||
css="position: absolute; left: 119px; bottom: 82px; font-size: 13px; font-family: Arial, sans-serif; color: #FFFFFF; width: 117px;"></l-painter-text>
|
||||
<!-- 阵败 -->
|
||||
<l-painter-text :text="wuweiData.defeatsCount"
|
||||
css="position: absolute; left: 132.5px; bottom: 122px; width: 40px; text-align: center; font-size: 18px;font-weight: 700;color: #FFFFFF;line-height: 18px;"></l-painter-text>
|
||||
<!-- 助攻 -->
|
||||
<l-painter-text :text="wuweiData.assistCount"
|
||||
css="position: absolute; left: 195px; bottom: 122px; width: 40px; text-align: center; font-size: 18px;font-weight: 700;color: #FFFFFF;line-height: 18px;"></l-painter-text>
|
||||
<!-- 战斗分 -->
|
||||
<l-painter-text :text="`平均战斗评分:${wuweiData.battlePoints}`"
|
||||
css="position: absolute; left: 80px; bottom: 153px; width: 140px; text-align: center; font-size:10px;color: #FFFFFF;line-height: 10px;"></l-painter-text>
|
||||
</template>
|
||||
<!-- 水印 -->
|
||||
<l-painter-image v-if="$isVip()" src="/static/image/other/shuiying.png"
|
||||
:css="`position: absolute; left: 18.8px; bottom: 17.1px; width: 145.38px;height:42.76px`"></l-painter-image>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_game_wuweiqiyue')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
|
||||
<view class="save-action">
|
||||
<button class="save-btn" @click="handleSave">保存</button>
|
||||
</view>
|
||||
|
||||
<!-- 主题选择区域 -->
|
||||
<view class="theme-selector" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<scroll-view scroll-x="true" class="theme-scroll" :show-scrollbar="false">
|
||||
<view class="theme-list">
|
||||
<view class="theme-item" v-for="(item, index) in ['样式一', '样式二']" :key="index + 1"
|
||||
:class="{ active: wuweiData.type == index + 1 }" @click="handleChangeTheme(index + 1)">
|
||||
<text class="theme-text">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 数据编辑弹窗 -->
|
||||
<uni-popup ref="editPopup" type="center">
|
||||
<view class="edit-popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="title">编辑主页数据</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="popup-scroll">
|
||||
<view class="form-item avatar-form-item">
|
||||
<text class="label">人物图片</text>
|
||||
<view class=" avatar-uploader img-box" @click="handleChooseImgUrl">
|
||||
<view class="avatar-preview" v-if="tempData.imgUrl">
|
||||
<image class="preview-img" :src="tempData.imgUrl" mode="widthFix"></image>
|
||||
<view class="delete-icon" @click.stop="handleDeleteImgUrl">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="upload-btn" v-else>
|
||||
<text class="plus">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item avatar-form-item" v-if="tempData.type == 2">
|
||||
<text class="label">头像</text>
|
||||
<view class="avatar-uploader" @click="handleChooseAvatar">
|
||||
<view class="avatar-preview" v-if="tempData.avatar">
|
||||
<image class="preview-img" :src="tempData.avatar" mode="aspectFill"></image>
|
||||
<view class="delete-icon" @click.stop="handleDeleteAvatar">
|
||||
<text>×</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="upload-btn" v-else @click="handleChooseAvatar">
|
||||
<text class="plus">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 2">
|
||||
<text class="label">昵称</text>
|
||||
<input class="input" type="text" v-model="tempData.nickname" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<text class="label">击败</text>
|
||||
<input class="input" type="number" v-model="tempData.killCount" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 1">
|
||||
<text class="label">精准射击</text>
|
||||
<input class="input" type="number" v-model="tempData.shooting" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 1">
|
||||
<text class="label">输出伤害</text>
|
||||
<input class="input" type="number" v-model="tempData.output" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 1">
|
||||
<text class="label">获得资金</text>
|
||||
<input class="input" type="number" v-model="tempData.harvest" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 1">
|
||||
<text class="label">三连击败</text>
|
||||
<input class="input" type="number" v-model="tempData.threeKill" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 2">
|
||||
<text class="label">阵败</text>
|
||||
<input class="input" type="number" v-model="tempData.defeatsCount" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 2">
|
||||
<text class="label">助攻</text>
|
||||
<input class="input" type="number" v-model="tempData.assistCount" />
|
||||
</view>
|
||||
<view class="form-item" v-if="tempData.type == 2">
|
||||
<text class="label">战斗评分</text>
|
||||
<input class="input" type="number" v-model="tempData.battlePoints" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer">
|
||||
<button class="cancel-btn" @click="closeEditPopup">取消</button>
|
||||
<button class="confirm-btn" @click="confirmEdit">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 横向全屏放大预览层 -->
|
||||
<view class="preview-overlay" v-if="showPreview" @click="showPreview = false">
|
||||
<image class="preview-image" :src="finalPosterPath" mode="aspectFill"></image>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, watch, onMounted, getCurrentInstance } from 'vue'
|
||||
import { onLoad, onReady, onUnload } from '@dcloudio/uni-app'
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
const instance = getCurrentInstance();
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 页面表单数据字段
|
||||
const wuweiData = reactive({
|
||||
type: 1, // 样式类型 1.2
|
||||
avatar: '/static/image/shopping/pdd/avatars/avatars1.jpg', // 头像
|
||||
imgUrl: '/static/image/other/game/heping/default.png', // 人物图片
|
||||
nickname: '甜喵小贝', // 昵称
|
||||
killCount: 24,
|
||||
defeatsCount: 2,
|
||||
assistCount: 12,
|
||||
battlePoints: 3854,
|
||||
shooting: 7,
|
||||
output: 4109,
|
||||
harvest: 41750,
|
||||
threeKill: 5
|
||||
})
|
||||
|
||||
const characterImgHeight = ref(350); // 初始高度兜底
|
||||
|
||||
const characterStyle = computed(() => {
|
||||
if (wuweiData.type == 1) {
|
||||
return `position: absolute; right: 77px; bottom: 0; width: 300px; height: 350px;`;
|
||||
} else {
|
||||
return `position: absolute; right: 210px; bottom: 0; width: 300px; height: 350px;`;
|
||||
}
|
||||
});
|
||||
|
||||
const style1TextCommonStyle = `position: absolute; bottom:79px; width:40px; text-align:center; font-size: 16px;color: #FFFFFF;line-height: 16px;`;
|
||||
|
||||
|
||||
// 手动处理中英文混合宽度的截断,避免依赖 line-clamp 和底层画布可能引发的居中对齐问题
|
||||
const truncatedNickname = computed(() => {
|
||||
let name = wuweiData.nickname || '';
|
||||
let width = 0;
|
||||
let result = '';
|
||||
let max = 117 - 15; // 保留大约 15px 的空间给省略号 "..."
|
||||
for (let i = 0; i < name.length; i++) {
|
||||
let charCode = name.charCodeAt(i);
|
||||
if (charCode >= 0 && charCode <= 128) {
|
||||
width += 7.5; // 英文及数字近似宽度
|
||||
} else {
|
||||
width += 13; // 中文字符宽度(font-size: 13px)
|
||||
}
|
||||
if (width > max) {
|
||||
return result + '...';
|
||||
}
|
||||
result += name[i];
|
||||
}
|
||||
return name;
|
||||
});
|
||||
|
||||
// 监听人物图片变化,动态获取其原始宽高并计算比例高度,解决画布必须写明尺寸才能渲染的问题
|
||||
watch(() => wuweiData.imgUrl, (newUrl) => {
|
||||
if (!newUrl) return;
|
||||
uni.getImageInfo({
|
||||
src: newUrl,
|
||||
success: (res) => {
|
||||
// 固定宽度 300px,高度等比例计算
|
||||
const calcHeight = (300 / res.width) * res.height;
|
||||
characterImgHeight.value = Math.round(calcHeight);
|
||||
},
|
||||
fail: () => {
|
||||
characterImgHeight.value = 350; // 获取失败提供兜底高度
|
||||
}
|
||||
});
|
||||
}, { immediate: true });
|
||||
|
||||
const bgImage = ref('')
|
||||
|
||||
// 获取系统宽度计算海报缩放比例,代替容易失效的 css calc(),确保全端兼容防截断
|
||||
const sysInfo = uni.getSystemInfoSync();
|
||||
const windowWidth = sysInfo.windowWidth || 375;
|
||||
// 扣除左右共 16px 的 padding,再基于实际画板宽度 822 计算精确缩放比,防止右侧被截断
|
||||
const posterScaleRatio = (windowWidth - 16) / 822;
|
||||
const posterContainerHeight = 374 * posterScaleRatio;
|
||||
|
||||
onLoad(async () => {
|
||||
const cachedData = uni.getStorageSync('wuweiData');
|
||||
if (cachedData) {
|
||||
Object.assign(wuweiData, cachedData);
|
||||
// 兼容处理:强制把历史缓存里的 .jpg 替换为最新的 .png,防止 404
|
||||
if (wuweiData.imgUrl === '/static/image/other/game/heping/default.jpg') {
|
||||
wuweiData.imgUrl = '/static/image/other/game/heping/default.png';
|
||||
uni.setStorageSync('wuweiData', wuweiData);
|
||||
}
|
||||
}
|
||||
try {
|
||||
bgImage.value = await imgLocal.getLocalImage(`other/game/wuwei/bg-${wuweiData.type}.jpg`);
|
||||
} catch (e) {
|
||||
console.error('获取背景图失败:', e);
|
||||
uni.showToast({ title: '背景图加载失败', icon: 'none' });
|
||||
}
|
||||
|
||||
uni.$on('editFormPhoto', (info) => {
|
||||
if (currentEditImgField.value) {
|
||||
tempData[currentEditImgField.value] = info;
|
||||
}
|
||||
// #ifndef H5
|
||||
if (info && !info.startsWith('/static/')) {
|
||||
newAvatars.value.push(info);
|
||||
}
|
||||
// #endif
|
||||
});
|
||||
|
||||
// 进入页面埋点
|
||||
if (proxy && proxy.$apiUserEvent) {
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
key: 'wuwei',
|
||||
prefix: '.uni.other.',
|
||||
value: "无畏契约"
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
onUnload(() => {
|
||||
uni.$off('editFormPhoto');
|
||||
})
|
||||
|
||||
const rightButtonText = ref("编辑");
|
||||
const finalPosterPath = ref('');
|
||||
const showPreview = ref(false); // 控制全屏预览
|
||||
|
||||
const editPopup = ref(null);
|
||||
const tempData = reactive({});
|
||||
const newAvatars = ref([]);
|
||||
const currentEditImgField = ref('');
|
||||
|
||||
function onRightClick() {
|
||||
Object.assign(tempData, JSON.parse(JSON.stringify(wuweiData)));
|
||||
newAvatars.value = [];
|
||||
editPopup.value.open();
|
||||
}
|
||||
|
||||
const handleChooseAvatar = () => {
|
||||
currentEditImgField.value = 'avatar';
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
uni.navigateTo({
|
||||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=200&height=200`
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleChooseImgUrl = () => {
|
||||
currentEditImgField.value = 'imgUrl';
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths[0]) {
|
||||
// 跳转到 qf-image 组件进行 300x350 尺寸(传参150x175)的裁剪,并通过 isMatting=1 触发后续抠图
|
||||
uni.navigateTo({
|
||||
url: `/pages/other/qf-image/qf-image?src=${res.tempFilePaths[0]}&width=150&height=175&isMatting=1`
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteAvatar = () => {
|
||||
tempData.avatar = '';
|
||||
};
|
||||
|
||||
const handleDeleteImgUrl = () => {
|
||||
tempData.imgUrl = '';
|
||||
};
|
||||
|
||||
function closeEditPopup() {
|
||||
// #ifndef H5
|
||||
newAvatars.value.forEach(path => {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
});
|
||||
// #endif
|
||||
editPopup.value.close();
|
||||
}
|
||||
|
||||
function confirmEdit() {
|
||||
// #ifndef H5
|
||||
// 删除多余的新上传文件
|
||||
newAvatars.value.forEach(path => {
|
||||
if (path !== tempData.avatar && path !== tempData.imgUrl) {
|
||||
uni.removeSavedFile({ filePath: path });
|
||||
}
|
||||
});
|
||||
// 删除被替换掉的原本地头像
|
||||
if (wuweiData.avatar !== tempData.avatar && wuweiData.avatar && !wuweiData.avatar.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: wuweiData.avatar });
|
||||
}
|
||||
if (wuweiData.imgUrl !== tempData.imgUrl && wuweiData.imgUrl && !wuweiData.imgUrl.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: wuweiData.imgUrl });
|
||||
}
|
||||
// #endif
|
||||
|
||||
Object.assign(wuweiData, tempData);
|
||||
uni.setStorageSync('wuweiData', wuweiData);
|
||||
editPopup.value.close();
|
||||
|
||||
// 数据修改后,重新渲染海报
|
||||
finalPosterPath.value = '';
|
||||
let tempBg = bgImage.value;
|
||||
bgImage.value = ''; // 强制卸载旧画板,确保能重新渲染和生成新海报
|
||||
setTimeout(() => {
|
||||
bgImage.value = tempBg;
|
||||
}, 50);
|
||||
}
|
||||
|
||||
async function handleChangeTheme(typeIndex) {
|
||||
// 切换主题时,先清空旧海报,触发界面“加载中”提示
|
||||
finalPosterPath.value = '';
|
||||
bgImage.value = ''; // 强制卸载旧画板,确保能重新渲染和生成新海报
|
||||
wuweiData.type = typeIndex;
|
||||
uni.setStorageSync('wuweiData', wuweiData);
|
||||
try {
|
||||
bgImage.value = await imgLocal.getLocalImage(`other/game/wuwei/bg-${typeIndex}.jpg`);
|
||||
} catch (e) {
|
||||
console.error('切换主题加载背景图失败:', e);
|
||||
uni.showToast({ title: '背景加载失败', icon: 'none' });
|
||||
}
|
||||
}
|
||||
|
||||
// 点击画布触发横向预览
|
||||
const handlePreview = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '海报仍在生成中,请稍候', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
showPreview.value = true;
|
||||
}
|
||||
|
||||
// 画布生成成功后触发,保存最终的海报路径
|
||||
const onPainterSuccess = (path) => {
|
||||
finalPosterPath.value = path;
|
||||
}
|
||||
|
||||
// 点击保存按钮,将带有渐变字体的最终图片存入相册
|
||||
const handleSave = () => {
|
||||
if (!finalPosterPath.value) {
|
||||
uni.showToast({ title: '图片仍在生成中,请稍候', icon: 'none' })
|
||||
return
|
||||
}
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: finalPosterPath.value,
|
||||
success: () => {
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '保存失败', icon: 'none' })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本地图片路径通过 Canvas 转换为 File 对象
|
||||
* @param {string} localPath - 本地图片路径(如从 uni.chooseImage 获取的 tempFilePath)
|
||||
* @param {Object} options - 可选参数
|
||||
* @param {string} options.format - 输出格式 'image/png' 或 'image/jpeg',默认 'image/png'
|
||||
* @param {number} options.quality - 图片质量(仅 jpeg 有效),0~1,默认 0.92
|
||||
* @param {number} options.maxWidth - 最大宽度(等比缩放),不填则使用原图尺寸
|
||||
* @param {number} options.maxHeight - 最大高度(等比缩放),不填则使用原图尺寸
|
||||
* @returns {Promise<File>} 返回一个 Promise,resolve 为 File 对象
|
||||
*/
|
||||
function convertLocalImageToFile(localPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
// 1. 读取本地图片为 Base64(避免 Image 对象直接加载本地路径的兼容问题)
|
||||
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
|
||||
entry.file((file) => {
|
||||
const reader = new plus.io.FileReader();
|
||||
reader.onload = (e) => {
|
||||
const base64Data = e.target.result; // 格式如 data:image/jpeg;base64,/9j/...
|
||||
resolve(e.target.result)
|
||||
};
|
||||
reader.onerror = (err) => reject(err);
|
||||
reader.readAsDataURL(file); // 读取为 DataURL
|
||||
}, reject);
|
||||
}, reject);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
reject(new Error('plus.io not supported'))
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.preview-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #000;
|
||||
z-index: 99999;
|
||||
/* 抛弃 flex 布局,防止 width: 100vh 被父级限制而发生坍缩 */
|
||||
}
|
||||
|
||||
.preview-overlay .preview-image {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100vh;
|
||||
height: 100vw;
|
||||
/* 先拉回自身中心点,再围绕中心点旋转 90 度 */
|
||||
transform: translate(-50%, -50%) rotate(90deg);
|
||||
}
|
||||
|
||||
.honor-of-kings {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.painter-container {
|
||||
/* 强制画板缩放到设备屏幕宽度,避免物理 px 超出屏幕 */
|
||||
padding: 8px;
|
||||
zoom: calc(100vw / 798);
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
/* 限制PC/iPad端的最大宽度 */
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.save-action {
|
||||
margin-top: 60rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 220rpx;
|
||||
/* 留出底部主题固定栏的安全空间 */
|
||||
|
||||
.save-btn {
|
||||
margin-top: 60rpx;
|
||||
width: 316rpx;
|
||||
background: #1777FF;
|
||||
color: #fff;
|
||||
border-radius: 56rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.theme-selector {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding-top: 20rpx;
|
||||
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||||
z-index: 99;
|
||||
|
||||
.theme-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
display: none;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-list {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
padding: 0 20rpx;
|
||||
|
||||
.theme-item {
|
||||
display: inline-flex;
|
||||
vertical-align: top;
|
||||
margin: 0 10rpx;
|
||||
padding: 0 40rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #FFFFFF;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx solid transparent;
|
||||
box-sizing: border-box;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
border-color: #3B7BFF;
|
||||
|
||||
.theme-text {
|
||||
color: #3B7BFF;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.theme-text {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx;
|
||||
width: 85vw;
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40rpx 0 20rpx 0;
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-scroll {
|
||||
max-height: 55vh;
|
||||
padding: 20rpx 40rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
padding-bottom: 16rpx;
|
||||
|
||||
.label {
|
||||
width: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.upload-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #999DA7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
margin-top: -6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
position: absolute;
|
||||
top: -4rpx;
|
||||
right: -4rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.img-box {
|
||||
width: 200rpx !important;
|
||||
|
||||
.avatar-preview {
|
||||
width: 200rpx !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
background-color: #F7F7F7;
|
||||
border-radius: 12rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx;
|
||||
padding: 0 20rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx 40rpx 40rpx;
|
||||
|
||||
button {
|
||||
width: 46%;
|
||||
height: 76rpx;
|
||||
line-height: 76rpx;
|
||||
font-size: 30rpx;
|
||||
border-radius: 12rpx;
|
||||
margin: 0;
|
||||
|
||||
&::after {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background-color: #F4F4F4;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #3B7BFF;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<template>
|
||||
<view>
|
||||
<qf-image-cropper :src="data.src" :width="data.width" :height="data.height" :radius="0" @crop="handleCrop"
|
||||
:reverseRotatable="true"></qf-image-cropper>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
watch,
|
||||
nextTick,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onReady,
|
||||
onPullDownRefresh,
|
||||
onReachBottom
|
||||
} from "@dcloudio/uni-app";
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const data = reactive({
|
||||
src: "",
|
||||
width:196,
|
||||
height:230,
|
||||
isCard:true
|
||||
})
|
||||
onLoad((option) => {
|
||||
console.log(option)
|
||||
data.src = option.src
|
||||
if(option.width){
|
||||
data.width=option.width*2
|
||||
data.isCard=false
|
||||
}
|
||||
if(option.height){
|
||||
data.height=option.height*2
|
||||
data.isCard=false
|
||||
}
|
||||
if (option.isMatting === '1') {
|
||||
data.isCard = true; // 强制开启抠图
|
||||
}
|
||||
})
|
||||
|
||||
function handleCrop(e) {
|
||||
if(data.isCard){
|
||||
uni.showLoading({
|
||||
title:"抠图中"
|
||||
})
|
||||
convertLocalImageToFile(e.tempFilePath).then(file => {
|
||||
proxy.$imageUpload(file.split(',', 2)[1]).then(resimage => {
|
||||
uni.hideLoading()
|
||||
// editForm.value.photo = decodeURI(resimage.data);
|
||||
uni.$emit("editFormPhoto", decodeURI(resimage.data))
|
||||
uni.navigateBack()
|
||||
}).catch(err => {
|
||||
uni.hideLoading()
|
||||
console.log(err.data.message)
|
||||
uni.showToast({
|
||||
icon: "none",
|
||||
title: "图片不是人像或者过大"
|
||||
})
|
||||
})
|
||||
|
||||
}).catch(err => {
|
||||
uni.hideLoading()
|
||||
})
|
||||
}else{
|
||||
uni.saveFile({
|
||||
tempFilePath: e.tempFilePath,
|
||||
success: function(res) {
|
||||
console.log(res)
|
||||
uni.$emit("editFormPhoto", decodeURI(res.savedFilePath))
|
||||
uni.navigateBack()
|
||||
// res.avatar = res.savedFilePath
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* 将本地图片路径通过 Canvas 转换为 File 对象
|
||||
* @param {string} localPath - 本地图片路径(如从 uni.chooseImage 获取的 tempFilePath)
|
||||
* @param {Object} options - 可选参数
|
||||
* @param {string} options.format - 输出格式 'image/png' 或 'image/jpeg',默认 'image/png'
|
||||
* @param {number} options.quality - 图片质量(仅 jpeg 有效),0~1,默认 0.92
|
||||
* @param {number} options.maxWidth - 最大宽度(等比缩放),不填则使用原图尺寸
|
||||
* @param {number} options.maxHeight - 最大高度(等比缩放),不填则使用原图尺寸
|
||||
* @returns {Promise<File>} 返回一个 Promise,resolve 为 File 对象
|
||||
*/
|
||||
function convertLocalImageToFile(localPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
// 1. 读取本地图片为 Base64(避免 Image 对象直接加载本地路径的兼容问题)
|
||||
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
|
||||
entry.file((file) => {
|
||||
const reader = new plus.io.FileReader();
|
||||
reader.onload = (e) => {
|
||||
const base64Data = e.target.result; // 格式如 data:image/jpeg;base64,/9j/...
|
||||
resolve(e.target.result)
|
||||
};
|
||||
reader.onerror = (err) => reject(err);
|
||||
reader.readAsDataURL(file); // 读取为 DataURL
|
||||
}, reject);
|
||||
}, reject);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
reject(new Error('plus.io not supported'))
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,790 @@
|
|||
<template>
|
||||
<view class="ranking-page">
|
||||
<nav-bar title="从夯到拉" bgColor="#F5F5F5" isRightButton :rightButtonText="rightButtonText"
|
||||
@right-click="onRightClick">
|
||||
</nav-bar>
|
||||
|
||||
<view class="content-container">
|
||||
<view :class="{ 'skin-box': type == 'skin', 'table-box': type != 'skin' }"
|
||||
:style="type == 'skin' ? { backgroundColor: skinBgColor } : {}">
|
||||
<template v-if="type == 'skin'">
|
||||
<view v-if="!isEdit" class="title">{{ title }}</view>
|
||||
<input v-else class="title title-input" v-model="title" maxlength="12" placeholder="请输入排名标题" />
|
||||
<image class="img happy" src="/static/image/other/ranking/happy.png"></image>
|
||||
<image class="img sad" src="/static/image/other/ranking/sad.png"></image>
|
||||
</template>
|
||||
<image v-if="$isVip()" class="watermark" :class="{}" src="/static/image/other/card/shuiyin2.png"
|
||||
mode="heightFix">
|
||||
</image>
|
||||
|
||||
<view class="ranking-table">
|
||||
<view v-for="(item, index) in tierList" :key="index" class="ranking-row">
|
||||
<view class="label-box" :style="{ backgroundColor: item.bgColor }"
|
||||
@click="changeRowBgColor(index)">
|
||||
<!-- <text class="label-text" :class="{ 'with-stroke': item.hasStroke }"
|
||||
:style="{ color: item.textColor }">
|
||||
{{ item.label }}
|
||||
</text> -->
|
||||
<image :style="`height:60rpx;width:160rpx;`"
|
||||
:src="`/static/image/other/ranking/${type == 'skin' ? item.img + '_skin' : item.img}.png`">
|
||||
</image>
|
||||
</view>
|
||||
|
||||
<view class="items-box ranking-item-list" :id="'row-' + index">
|
||||
<view v-for="(img, imgIdx) in item.images" :key="imgIdx" class="item-wrapper"
|
||||
:class="{ 'is-dragging': drag.tierIndex === index && drag.imgIdx === imgIdx }"
|
||||
:style="getDragStyle(index, imgIdx)" @touchstart="onTouchStart($event, index, imgIdx)"
|
||||
@touchmove.stop.prevent="onTouchMove" @touchend="onTouchEnd">
|
||||
|
||||
<image :src="img" mode="aspectFill" class="item-img"></image>
|
||||
<view v-if="isEdit" class="del-btn" @click.stop="deleteImage(index, imgIdx)">×</view>
|
||||
</view>
|
||||
|
||||
<view v-if="isEdit && item.images.length < 4" class="add-btn" @click="chooseImage(index)">
|
||||
<image class="add-icon" src="/static/image/common/add.png"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="save-action">
|
||||
<button v-if="!isEdit" class="save-btn" @click="handleSave">保存图片</button>
|
||||
<!-- 编辑模式下的全局颜色控制器 -->
|
||||
<view v-else-if="type == 'skin'" class="bottom-edit-actions">
|
||||
<view class="color-picker-wrapper">
|
||||
<view class="color-picker">
|
||||
<view v-for="color in ['#FFDFDF', '#DFF0FF', '#E0FFDF', '#FDF5C8', '#F3DFFF']" :key="color"
|
||||
class="color-dot" :style="{ backgroundColor: color }" @click="skinBgColor = color">
|
||||
</view>
|
||||
</view>
|
||||
<input v-if="false" class="hex-input" v-model="skinBgColor" placeholder="#HEX" maxlength="7" />
|
||||
</view>
|
||||
<view class="spectrum-picker" @touchstart="handleHueTouch" @touchmove.stop.prevent="handleHueTouch">
|
||||
<view class="spectrum-bar"></view>
|
||||
<view class="slider-thumb" :style="{ left: (skinHue / 360 * 100) + '%' }"></view>
|
||||
</view>
|
||||
|
||||
<text class="edit-tip">点击左侧分类标签可切换背景色</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-tabs" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<view class="tab-item" :class="{ active: type == 'base' }" @click="switchType('base')">基础</view>
|
||||
<view class="tab-item" :class="{ active: type == 'skin' }" @click="switchType('skin')">皮肤</view>
|
||||
</view>
|
||||
|
||||
<view class="painter-container" v-if="isSnapshot">
|
||||
<l-painter isCanvasToTempFilePath @success="onPainterSuccess"
|
||||
:css="`width:750rpx; padding: 40rpx; background-color:${type == 'skin' ? skinBgColor : '#F8F8F8'};`">
|
||||
<l-painter-view
|
||||
:css="`width: 100%; display: flex; flex-direction: column; position: relative; ${type == 'skin' ? 'padding-top: 120rpx;padding-bottom: 120rpx;' : ''}`">
|
||||
<template v-if="type == 'skin'">
|
||||
<l-painter-text :text="title"
|
||||
css="position: absolute; top: 26rpx; left: 50%; transform: translateX(-50%); font-size: 36rpx; font-weight: bold; color: #333;" />
|
||||
<l-painter-image src="/static/image/other/ranking/happy.png"
|
||||
css="position: absolute;top: 58rpx;right: 24rpx; width: 96rpx; height: 96rpx;" />
|
||||
</template>
|
||||
|
||||
<l-painter-view css="border: 3rpx solid #333; background-color: #fff; width: 100%;">
|
||||
<l-painter-view v-for="(item, index) in tierList" :key="index"
|
||||
:css="`display: flex; min-height: 148rpx; border-bottom: ${index === tierList.length - 1 ? 'none' : '3rpx solid #333'};`">
|
||||
<l-painter-view
|
||||
:css="`width: 176rpx; min-height: 148rpx; background-color: ${item.bgColor}; display: flex; align-items: center; justify-content: center; border-right: 3rpx solid #333;`">
|
||||
<!-- <l-painter-text :text="item.label"
|
||||
:css="`font-size: 52rpx; font-weight: bold; color: ${item.textColor}; ${item.hasStroke ? 'text-shadow: 2rpx 2rpx 0 #000, -2rpx -2rpx 0 #000, 2rpx -2rpx 0 #000, -2rpx 2rpx 0 #000, 0 2rpx 0 #000, 0 -2rpx 0 #000, 2rpx 0 0 #000, -2rpx 0 0 #000;' : ''}`" /> -->
|
||||
<l-painter-image
|
||||
:src="`/static/image/other/ranking/${type == 'skin' ? item.img + '_skin' : item.img}.png`"
|
||||
:css="`height: 60rpx; width: 160rpx;`" mode="heightFix" />
|
||||
</l-painter-view>
|
||||
<l-painter-view
|
||||
:css="`flex: 1; display: flex; align-items: center;height: 148rpx;width:490rpx;padding:0 12rpx;`">
|
||||
<l-painter-image v-for="(img, imgIdx) in item.images" :key="imgIdx" :src="img"
|
||||
css="width: 105rpx; height: 105rpx; margin: 0 8rpx; object-fit: cover;"
|
||||
mode="aspectFill" />
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
<l-painter-view v-if="$isVip()"
|
||||
:css="type == 'skin' ? `position: absolute;bottom: 32rpx;right: 14rpx;` : `position: absolute;top: 50%;right: 50%;transform: translate(50%, -50%);`">
|
||||
<l-painter-image src="/static/image/other/card/shuiyin2.png"
|
||||
css="width: 194rpx;height: 56rpx;" />
|
||||
</l-painter-view>
|
||||
<l-painter-image v-if="type == 'skin'" src="/static/image/other/ranking/sad.png"
|
||||
css="position: absolute;bottom: 76rpx;left: 116rpx; width: 96rpx; height: 96rpx;" />
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_ranking')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
const type = ref("base");
|
||||
const title = ref("xx排名");
|
||||
const skinBgColor = ref("#FFDFDF");
|
||||
const skinHue = ref(0); // 记录色相位置
|
||||
const isSnapshot = ref(false);
|
||||
const isEdit = ref(false);
|
||||
const rightButtonText = ref("编辑");
|
||||
|
||||
const tierList = ref([{
|
||||
label: '夯',
|
||||
bgColor: '#D5171C',
|
||||
img: 'hang',
|
||||
textColor: '#FFFFFF',
|
||||
hasStroke: true,
|
||||
images: [],
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
label: '顶级',
|
||||
bgColor: '#FF6A0B',
|
||||
img: 'dingji',
|
||||
textColor: '#FFFFFF',
|
||||
hasStroke: true,
|
||||
images: [],
|
||||
width: 104,
|
||||
},
|
||||
{
|
||||
label: '人上人',
|
||||
bgColor: '#FFF06A',
|
||||
img: 'renshangren',
|
||||
textColor: '#FFFFFF',
|
||||
hasStroke: true,
|
||||
images: [],
|
||||
width: 156,
|
||||
},
|
||||
{
|
||||
label: 'NPC',
|
||||
bgColor: '#FDF5C8',
|
||||
img: 'npc',
|
||||
textColor: '#FFFFFF',
|
||||
hasStroke: true,
|
||||
images: [],
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
label: '拉完了',
|
||||
bgColor: '#FFFFFF',
|
||||
img: 'lawanle',
|
||||
textColor: '#FFFFFF',
|
||||
hasStroke: true,
|
||||
images: [],
|
||||
width: 156,
|
||||
}
|
||||
]);
|
||||
|
||||
// --- 生命周期:加载缓存 ---
|
||||
onLoad(() => {
|
||||
// 进入页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'click',
|
||||
key: 'ranking',
|
||||
value: "从夯倒拉排名"
|
||||
})
|
||||
// 获取缓存数据
|
||||
const cache = uni.getStorageSync('ranking_config_data');
|
||||
if (cache) {
|
||||
title.value = cache.title || title.value;
|
||||
type.value = cache.type || type.value;
|
||||
skinBgColor.value = cache.skinBgColor || skinBgColor.value;
|
||||
skinHue.value = cache.skinHue ?? skinHue.value;
|
||||
if (cache.tierList) tierList.value = cache.tierList;
|
||||
console.log(tierList.value);
|
||||
}
|
||||
});
|
||||
|
||||
// --- 拖拽排序逻辑 ---
|
||||
const drag = reactive({
|
||||
tierIndex: -1,
|
||||
imgIdx: -1,
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
moveX: 0,
|
||||
moveY: 0
|
||||
});
|
||||
|
||||
// 计算拖拽样式
|
||||
const getDragStyle = (tIdx, iIdx) => {
|
||||
if (drag.tierIndex === tIdx && drag.imgIdx === iIdx) {
|
||||
return {
|
||||
transform: `translate(${drag.moveX}px, ${drag.moveY}px)`,
|
||||
zIndex: 99,
|
||||
transition: 'none'
|
||||
};
|
||||
}
|
||||
return {
|
||||
transition: 'transform 0.3s ease'
|
||||
};
|
||||
};
|
||||
|
||||
const onTouchStart = (e, tIdx, iIdx) => {
|
||||
if (!isEdit.value) return;
|
||||
const touch = e.touches[0];
|
||||
drag.tierIndex = tIdx;
|
||||
drag.imgIdx = iIdx;
|
||||
drag.startX = touch.clientX;
|
||||
drag.startY = touch.clientY;
|
||||
drag.moveX = 0;
|
||||
drag.moveY = 0;
|
||||
};
|
||||
|
||||
const onTouchMove = (e) => {
|
||||
if (drag.tierIndex === -1) return;
|
||||
const touch = e.touches[0];
|
||||
drag.moveX = touch.clientX - drag.startX;
|
||||
drag.moveY = touch.clientY - drag.startY;
|
||||
};
|
||||
|
||||
const onTouchEnd = () => {
|
||||
if (drag.tierIndex === -1) return;
|
||||
|
||||
const {
|
||||
tierIndex,
|
||||
imgIdx,
|
||||
moveX
|
||||
} = drag;
|
||||
const rowData = tierList.value[tierIndex].images;
|
||||
|
||||
// 估算单个item跨度 (100rpx宽度 + 12rpx间距 ≈ 56px,建议根据真机微调)
|
||||
const itemWidth = 56;
|
||||
const offset = Math.round(moveX / itemWidth);
|
||||
let newIndex = imgIdx + offset;
|
||||
|
||||
// 限制索引范围
|
||||
newIndex = Math.max(0, Math.min(newIndex, rowData.length - 1));
|
||||
|
||||
if (newIndex !== imgIdx) {
|
||||
const temp = rowData.splice(imgIdx, 1)[0];
|
||||
rowData.splice(newIndex, 0, temp);
|
||||
}
|
||||
|
||||
// 重置拖拽状态
|
||||
drag.tierIndex = -1;
|
||||
drag.imgIdx = -1;
|
||||
};
|
||||
|
||||
// --- 其他业务逻辑 ---
|
||||
const chooseImage = (index) => {
|
||||
const currentCount = tierList.value[index].images.length;
|
||||
uni.chooseImage({
|
||||
count: 4 - currentCount,
|
||||
sizeType: ['compressed'],
|
||||
success: (res) => {
|
||||
tierList.value[index].images.push(...res.tempFilePaths);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const deleteImage = (tIdx, iIdx) => {
|
||||
const path = tierList.value[tIdx].images[iIdx];
|
||||
removeLocalFile(path); // 物理删除已有文件
|
||||
tierList.value[tIdx].images.splice(iIdx, 1);
|
||||
};
|
||||
|
||||
const onRightClick = async () => {
|
||||
if (isEdit.value) {
|
||||
uni.showLoading({
|
||||
title: '正在持久化图片...',
|
||||
mask: true
|
||||
});
|
||||
// 1. 深度遍历并持久化所有临时图片
|
||||
for (let tierIdx = 0; tierIdx < tierList.value.length; tierIdx++) {
|
||||
const tier = tierList.value[tierIdx];
|
||||
for (let i = 0; i < tier.images.length; i++) {
|
||||
const path = tier.images[i];
|
||||
// 逻辑逻辑:如果是 static 或者是已经保存的 _doc/usr 路径,则跳过
|
||||
const isStatic = path.startsWith('/static/') || path.startsWith('static/');
|
||||
const isPersistent = path.indexOf('_doc/') !== -1 || path.indexOf('usr/') !== -1;
|
||||
|
||||
if (!isStatic && !isPersistent) {
|
||||
console.log('检测到待持久化图片:', path);
|
||||
const newPath = await saveImageToLocal(path);
|
||||
if (newPath) {
|
||||
tier.images[i] = newPath;
|
||||
console.log('持久化成功,新路径:', newPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 全部处理完后,进行数据持久化
|
||||
uni.setStorageSync('ranking_config_data', {
|
||||
title: title.value,
|
||||
type: type.value,
|
||||
skinBgColor: skinBgColor.value,
|
||||
skinHue: skinHue.value,
|
||||
tierList: tierList.value
|
||||
});
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '已保存',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
isEdit.value = !isEdit.value;
|
||||
rightButtonText.value = isEdit.value ? "确定" : "编辑";
|
||||
};
|
||||
|
||||
/**
|
||||
* 将临时图片保存到本地永久目录
|
||||
*/
|
||||
const saveImageToLocal = (tempFilePath) => {
|
||||
return new Promise((resolve) => {
|
||||
// 如果已经是持久化路径,直接返回
|
||||
if (tempFilePath.indexOf('_doc/') !== -1 || tempFilePath.indexOf('usr/') !== -1) {
|
||||
return resolve(tempFilePath);
|
||||
}
|
||||
|
||||
uni.saveFile({
|
||||
tempFilePath: tempFilePath,
|
||||
success: (res) => {
|
||||
resolve(res.savedFilePath);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('本地持久化保存失败:', err);
|
||||
// 提示:H5 环境不支持 saveFile 持久化,仅 App/小程序支持
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 物理删除本地已保存的文件
|
||||
*/
|
||||
const removeLocalFile = (path) => {
|
||||
if (!path) return;
|
||||
// 仅针对非静态资源的本地文件进行删除
|
||||
if (path.indexOf('_doc/') !== -1 || path.indexOf('usr/') !== -1) {
|
||||
uni.removeSavedFile({
|
||||
filePath: path,
|
||||
success: () => console.log('文件物理删除成功:', path),
|
||||
fail: (err) => console.log('文件删除失败:', err)
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = () => {
|
||||
uni.showLoading({
|
||||
title: '生成中...',
|
||||
mask: true
|
||||
});
|
||||
isSnapshot.value = true;
|
||||
};
|
||||
|
||||
const onPainterSuccess = (path) => {
|
||||
const done = () => {
|
||||
isSnapshot.value = false;
|
||||
uni.hideLoading();
|
||||
};
|
||||
if (!path) return done();
|
||||
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: path,
|
||||
success: () => uni.showToast({
|
||||
title: '保存成功'
|
||||
}),
|
||||
fail: () => uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
}),
|
||||
complete: done
|
||||
});
|
||||
};
|
||||
|
||||
const switchType = (val) => {
|
||||
type.value = val;
|
||||
if (val == 'skin') {
|
||||
tierList.value[0].bgColor = '#F3575B'
|
||||
tierList.value[1].bgColor = '#FF9B5B'
|
||||
tierList.value[2].bgColor = '#FFF59E'
|
||||
tierList.value[3].bgColor = '#FFFBE1'
|
||||
tierList.value[4].bgColor = '#FFFFFF'
|
||||
} else {
|
||||
tierList.value[0].bgColor = '#D5171C'
|
||||
tierList.value[1].bgColor = '#FF6A0B'
|
||||
tierList.value[2].bgColor = '#FFF06A'
|
||||
tierList.value[3].bgColor = '#FDF5C8'
|
||||
tierList.value[4].bgColor = '#FFFFFF'
|
||||
}
|
||||
|
||||
// 切换时由于改变了 type,立即同步到缓存中以便记录最后选择的模式
|
||||
const cache = uni.getStorageSync('ranking_config_data') || {};
|
||||
cache.type = val;
|
||||
uni.setStorageSync('ranking_config_data', cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* 循环切换行背景色 (编辑模式下)
|
||||
*/
|
||||
const changeRowBgColor = (index) => {
|
||||
if (!isEdit.value) return;
|
||||
const colors = ['#D5171C', '#FF6A0B', '#FFF06A', '#FDF5C8', '#FFFFFF', '#1777FF', '#333333'];
|
||||
const curr = tierList.value[index].bgColor;
|
||||
let nextIdx = (colors.indexOf(curr.toUpperCase()) + 1) % colors.length;
|
||||
if (nextIdx === -1) nextIdx = 0;
|
||||
tierList.value[index].bgColor = colors[nextIdx];
|
||||
|
||||
// 自动适配文字颜色 (深色背景用白色,浅色用黑色)
|
||||
const darkColors = ['#D5171C', '#1777FF', '#333333'];
|
||||
tierList.value[index].textColor = darkColors.includes(colors[nextIdx]) ? '#FFFFFF' : '#FFFFFF';
|
||||
};
|
||||
|
||||
/**
|
||||
* 处理色域滑动
|
||||
*/
|
||||
const handleHueTouch = (e) => {
|
||||
const touch = e.touches[0];
|
||||
uni.createSelectorQuery().select('.spectrum-picker').boundingClientRect(rect => {
|
||||
if (rect) {
|
||||
const x = Math.max(0, Math.min(touch.clientX - rect.left, rect.width));
|
||||
skinHue.value = Math.round((x / rect.width) * 360);
|
||||
|
||||
// 1. 获取 HSL 的数值
|
||||
const h = skinHue.value;
|
||||
const s = 70;
|
||||
const l = 90;
|
||||
|
||||
// 2. 转换为 16 进制色值
|
||||
skinBgColor.value = hslToHex(h, s, l);
|
||||
}
|
||||
}).exec();
|
||||
};
|
||||
|
||||
/**
|
||||
* HSL 转 Hex 工具函数
|
||||
*/
|
||||
function hslToHex(h, s, l) {
|
||||
l /= 100;
|
||||
const a = s * Math.min(l, 1 - l) / 100;
|
||||
const f = n => {
|
||||
const k = (n + h / 30) % 12;
|
||||
const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
||||
return Math.round(255 * color).toString(16).padStart(2, '0');
|
||||
};
|
||||
return `#${f(0)}${f(8)}${f(4)}`.toUpperCase();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.ranking-page {
|
||||
min-height: 100vh;
|
||||
background-color: #F8F8F8;
|
||||
padding-bottom: 200rpx;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
position: relative;
|
||||
padding: 12rpx 24rpx;
|
||||
|
||||
}
|
||||
|
||||
.table-box {
|
||||
position: relative;
|
||||
|
||||
.watermark {
|
||||
position: absolute;
|
||||
height: 56rpx;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 99;
|
||||
}
|
||||
}
|
||||
|
||||
.ranking-table {
|
||||
border: 3rpx solid #333;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.ranking-row {
|
||||
display: flex;
|
||||
min-height: 148rpx;
|
||||
border-bottom: 3rpx solid #333;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label-box {
|
||||
width: 176rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 3rpx solid #333;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 48rpx;
|
||||
font-weight: bold;
|
||||
|
||||
&.with-stroke {
|
||||
text-shadow: 2rpx 2rpx 0 #000, -2rpx -2rpx 0 #000, 2rpx -2rpx 0 #000, -2rpx 2rpx 0 #000;
|
||||
}
|
||||
}
|
||||
|
||||
.items-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 14rpx 12rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
width: 105rpx;
|
||||
height: 105rpx;
|
||||
position: relative;
|
||||
margin: 0 6rpx;
|
||||
touch-action: none;
|
||||
/* 关键:禁止浏览器默认触摸行为 */
|
||||
|
||||
&.is-dragging {
|
||||
opacity: 0.7;
|
||||
scale: 1.1;
|
||||
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.del-btn {
|
||||
position: absolute;
|
||||
top: -12rpx;
|
||||
right: -12rpx;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
background: #ff4d4f;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 24rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
background: #eee;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 4rpx;
|
||||
|
||||
.add-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
margin-top: 60rpx;
|
||||
width: 400rpx;
|
||||
background: #1777FF;
|
||||
color: #fff;
|
||||
border-radius: 50rpx;
|
||||
}
|
||||
|
||||
.bottom-tabs {
|
||||
position: fixed;
|
||||
bottom: 40rpx;
|
||||
bottom: calc(32rpx + env(safe-area-inset-bottom));
|
||||
bottom: calc(32rpx + constant(safe-area-inset-bottom));
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
.tab-item {
|
||||
width: 180rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
margin: 0 20rpx;
|
||||
border-radius: 10rpx;
|
||||
|
||||
&.active {
|
||||
border: 4rpx solid #1777FF;
|
||||
color: #1777FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.skin-box {
|
||||
position: relative;
|
||||
padding: 120rpx 12rpx;
|
||||
background-color: #FFDFDF;
|
||||
|
||||
.watermark {
|
||||
height: 56rpx !important;
|
||||
position: absolute;
|
||||
right: 14rpx !important;
|
||||
bottom: 32rpx !important;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 260px;
|
||||
position: absolute;
|
||||
top: 30rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.title-input {
|
||||
min-width: 260px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 8rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border: 1rpx dashed #1777FF;
|
||||
}
|
||||
|
||||
.title-input {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
border-radius: 8rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
width: 300rpx;
|
||||
border: 1rpx dashed #1777FF;
|
||||
}
|
||||
|
||||
.img {
|
||||
position: absolute;
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
}
|
||||
|
||||
.happy {
|
||||
top: 40rpx;
|
||||
right: 30rpx;
|
||||
}
|
||||
|
||||
.sad {
|
||||
bottom: 60rpx;
|
||||
left: 100rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.save-action {
|
||||
margin-top: 60rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.bottom-edit-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.edit-tip {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.color-picker {
|
||||
display: flex;
|
||||
gap: 16rpx;
|
||||
background: #fff;
|
||||
padding: 12rpx 20rpx;
|
||||
border-radius: 40rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.color-picker-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 12rpx 0;
|
||||
}
|
||||
|
||||
.hex-input {
|
||||
width: 150rpx;
|
||||
height: 56rpx;
|
||||
background: #fff;
|
||||
border-radius: 28rpx;
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
color: #333;
|
||||
border: 1rpx solid #eee;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.spectrum-picker {
|
||||
width: 600rpx;
|
||||
height: 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 4rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
position: relative;
|
||||
margin: 12rpx 0;
|
||||
}
|
||||
|
||||
.slider-thumb {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.3);
|
||||
border: 2rpx solid #fff;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.spectrum-bar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 12rpx;
|
||||
background: linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
}
|
||||
|
||||
.color-dot {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #fff;
|
||||
box-shadow: 0 0 4rpx rgba(0, 0, 0, 0.2);
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
|
||||
.painter-container {
|
||||
position: fixed;
|
||||
left: -9999rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const list = ref([
|
||||
{ label: '澶?, bgColor: '#BE0012', textColor: '#FFFFFF', hasShadow: true },
|
||||
{ label: '椤剁骇', bgColor: '#F17415', textColor: '#FFFFFF', hasShadow: true },
|
||||
{ label: '浜轰笂浜?, bgColor: '#F9E962', textColor: '#FFFFFF', hasShadow: true },
|
||||
{ label: 'NPC', bgColor: '#FDF5C0', textColor: '#555555', hasShadow: false },
|
||||
{ label: '鎷夊畬浜?, bgColor: '#FFFFFF', textColor: '#555555', hasShadow: false }
|
||||
]);
|
||||
|
||||
const handleAdd = (index) => {
|
||||
console.log('娣诲姞椤?, index);
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="ranking-container">
|
||||
<view class="ranking-table">
|
||||
<view v-for="(item, index) in list" :key="index" class="ranking-row">
|
||||
<!-- 鏍囩鍒?-->
|
||||
<view class="label-col" :style="{ backgroundColor: item.bgColor }">
|
||||
<text class="label-text" :class="{ 'with-shadow': item.hasShadow }" :style="{ color: item.textColor }">
|
||||
{{ item.label }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 鍐呭鍒?-->
|
||||
<view class="content-col">
|
||||
<!-- 浠呭湪绗竴琛屽睍绀烘紨绀哄浘鐗?-->
|
||||
<template v-if="index === 0">
|
||||
<view class="item-box">
|
||||
<image src="/static/images/food.jpg" mode="aspectFill" class="item-img" />
|
||||
</view>
|
||||
</template>
|
||||
<!-- 娣诲姞鎸夐挳 -->
|
||||
<view class="add-btn" @tap="handleAdd(index)">
|
||||
<text class="plus-icon">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
.ranking-container {
|
||||
padding: 30rpx 20rpx;
|
||||
background-color: #F8F8F8;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.ranking-table {
|
||||
border: 2rpx solid #333;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ranking-row {
|
||||
display: flex;
|
||||
min-height: 180rpx;
|
||||
border-bottom: 2rpx solid #333;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.label-col {
|
||||
width: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-right: 2rpx solid #333;
|
||||
padding: 0 10rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 52rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 1.2;
|
||||
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
|
||||
|
||||
&.with-shadow {
|
||||
/* 寮哄姏榛戣壊鎻忚竟锛屾ā鎷?:1鏁堟灉 */
|
||||
text-shadow:
|
||||
2rpx 2rpx 0 #000,
|
||||
-2rpx -2rpx 0 #000,
|
||||
2rpx -2rpx 0 #000,
|
||||
-2rpx 2rpx 0 #000,
|
||||
0 2rpx 0 #000,
|
||||
0 -2rpx 0 #000,
|
||||
2rpx 0 0 #000,
|
||||
-2rpx 0 0 #000;
|
||||
}
|
||||
}
|
||||
|
||||
.content-col {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
padding: 20rpx;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.item-box {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
background-color: #eee;
|
||||
border: 1rpx solid #ddd;
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
background-color: #F2F2F2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.plus-icon {
|
||||
font-size: 70rpx;
|
||||
color: #DBDBDB;
|
||||
font-weight: 200;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,983 @@
|
|||
<script setup>
|
||||
import { reactive, ref, onMounted, computed } from 'vue';
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
const CACHE_KEY = 'score_center_info';
|
||||
|
||||
const data = reactive({
|
||||
form: {
|
||||
examYear: '2016',
|
||||
idNumber: '***********1234',
|
||||
name: '肖战',
|
||||
chinese: '113',
|
||||
math: '123',
|
||||
english: '116',
|
||||
comprehensive: '195'
|
||||
}
|
||||
});
|
||||
|
||||
const total = computed(() => {
|
||||
const sum = Number(data.form.chinese || 0) + Number(data.form.math || 0) + Number(data.form.english || 0) + Number(data.form.comprehensive || 0);
|
||||
return sum || '';
|
||||
});
|
||||
|
||||
const editDialog = reactive({
|
||||
show: false,
|
||||
data: {}
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
loadCache();
|
||||
});
|
||||
|
||||
function loadCache() {
|
||||
const cache = uni.getStorageSync(CACHE_KEY);
|
||||
if (cache) {
|
||||
data.form = { ...data.form, ...cache };
|
||||
}
|
||||
}
|
||||
|
||||
function saveCache() {
|
||||
uni.setStorageSync(CACHE_KEY, data.form);
|
||||
}
|
||||
|
||||
function openEditDialog() {
|
||||
editDialog.data = JSON.parse(JSON.stringify(data.form));
|
||||
editDialog.show = true;
|
||||
}
|
||||
|
||||
function saveEdit() {
|
||||
data.form = { ...data.form, ...editDialog.data };
|
||||
saveCache();
|
||||
editDialog.show = false;
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
|
||||
const editTotal = computed(() => {
|
||||
const sum = Number(editDialog.data.chinese || 0) + Number(editDialog.data.math || 0) + Number(editDialog.data.english || 0) + Number(editDialog.data.comprehensive || 0);
|
||||
return sum || '';
|
||||
});
|
||||
function back(){
|
||||
uni.navigateBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="div">
|
||||
<view v-if="$isVip()" >
|
||||
<watermark dark="light" source="uni_alipay_other_score" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_score')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
|
||||
<view class="headerBox" :style="{'padding-top':$systemInfo.statusBarHeight*2+'rpx'}">
|
||||
<view class="header" >
|
||||
<view class="left" @click="back()">
|
||||
<image src="/static/image/other/score/center/home.png" mode=""></image>
|
||||
</view>
|
||||
<view class="center">
|
||||
查询专区
|
||||
</view>
|
||||
<view class="right">
|
||||
<image src="/static/image/other/score/center/rightBtn.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="" :style="{height:$systemInfo.statusBarHeight*2+88+'rpx'}">
|
||||
|
||||
</view>
|
||||
<view class="flexcontainer" @click="openEditDialog">
|
||||
<view class="rectangle_23375">
|
||||
<text class="text_2"> 普通高考成绩查询 </text>
|
||||
</view>
|
||||
<view class="rectangle_23377">
|
||||
<view class="flexcontainer_1"><text class="text_3"> 考试年份: </text><text class="text_4"> {{data.form.examYear}} 年 </text></view>
|
||||
<view class="div_424"></view>
|
||||
<view class="flexcontainer_2"><text class="text_5"> 身份证号: </text><text class="text_6"> {{data.form.idNumber}} </text></view>
|
||||
<view class="div_425"></view>
|
||||
<view class="flexcontainer_3"><view class="text_7"> 姓 <text>名:</text> </view><text class="text_8"> {{data.form.name}} </text></view>
|
||||
<view class="div_426"></view>
|
||||
<text class="text_9"> 科目成绩: </text>
|
||||
<view class="group_48319">
|
||||
<text class="text_10"> 语文 </text>
|
||||
<view class="div_427"></view>
|
||||
<text class="text_11"> {{data.form.chinese}} </text>
|
||||
</view>
|
||||
<view class="group_48320">
|
||||
<text class="text_12"> 数学 </text>
|
||||
<view class="div_427_1"></view>
|
||||
<text class="text_13"> {{data.form.math}} </text>
|
||||
</view>
|
||||
<view class="group_48321">
|
||||
<text class="text_14"> 外语 </text>
|
||||
<view class="div_427_2"></view>
|
||||
<text class="text_15"> {{data.form.english}} </text>
|
||||
</view>
|
||||
<view class="group_48322">
|
||||
<text class="text_16"> 综合 </text>
|
||||
<view class="div_427_3"></view>
|
||||
<text class="text_17"> {{data.form.comprehensive}} </text>
|
||||
</view>
|
||||
<view class="group_48323">
|
||||
<text class="text_18"> 总分 </text>
|
||||
<view class="div_427_4"></view>
|
||||
<text class="text_19"> {{total}} </text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="group_48324">
|
||||
<text class="text_20"> 返回查询页 </text>
|
||||
</view>
|
||||
<view class="home">
|
||||
<view class="home_indicator"></view>
|
||||
</view>
|
||||
|
||||
<safeBottom bgColor="#f4f7fb" />
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<view v-if="editDialog.show" class="editDialog">
|
||||
<view class="editDialog_bg">
|
||||
<view class="editDialog_header">
|
||||
<text class="title">编辑成绩信息</text>
|
||||
</view>
|
||||
<view class="editDialog_body">
|
||||
<view class="formItem">
|
||||
<text>考试年份</text>
|
||||
<input v-model="editDialog.data.examYear" type="digit" placeholder="如: 2016" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>身份证号</text>
|
||||
<input v-model="editDialog.data.idNumber" placeholder="如: ***********1234" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>姓名</text>
|
||||
<input v-model="editDialog.data.name" placeholder="请输入姓名" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>语文</text>
|
||||
<input v-model="editDialog.data.chinese" type="digit" placeholder="请输入语文成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>数学</text>
|
||||
<input v-model="editDialog.data.math" type="digit" placeholder="请输入数学成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>外语</text>
|
||||
<input v-model="editDialog.data.english" type="digit" placeholder="请输入外语成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>综合</text>
|
||||
<input v-model="editDialog.data.comprehensive" type="digit" placeholder="请输入综合成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>总分</text>
|
||||
<text style="flex:1;text-align:right;font-size:28rpx;color:#333;">{{editTotal}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<view class="btn-cancel" @click="editDialog.show=false">取消</view>
|
||||
<view class="btn-save" @click="saveEdit">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.flex-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.justify-start {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.justify-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.justify-end {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.justify-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.items-start {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.items-end {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.items-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.no-shrink {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 编辑弹窗样式 */
|
||||
.editDialog {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.editDialog_bg {
|
||||
width: 680rpx;
|
||||
max-height: 80vh;
|
||||
background-color: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.editDialog_header {
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
text-align: center;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.editDialog_body {
|
||||
padding: 20rpx 30rpx;
|
||||
overflow-y: auto;
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
.formItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
text {
|
||||
width: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
padding: 20rpx 30rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
gap: 20rpx;
|
||||
|
||||
.btn-cancel,
|
||||
.btn-save {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #f5f5f5;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background-color: #187AFF;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
/* 查询中心 */
|
||||
.div {
|
||||
position: relative;
|
||||
width: 750rpx;
|
||||
// height: 1624rpx;
|
||||
overflow: hidden;
|
||||
background-color: #f4f7fb;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
isolation: isolate;
|
||||
.headerBox{
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-color: #fff;
|
||||
z-index: 999 !important;
|
||||
width: 100%;
|
||||
}
|
||||
.header{
|
||||
min-height: 88rpx;
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.center{
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
.left,.right{
|
||||
width: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.left{
|
||||
margin-left: 30rpx;
|
||||
image{
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
margin-right: 30rpx;
|
||||
image{
|
||||
width: 200rpx;
|
||||
height: 66rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* flexContainer */
|
||||
.flexcontainer {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 750rpx;
|
||||
height: 1222rpx;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
isolation: isolate;
|
||||
z-index: 2;
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
|
||||
/* 矩形 23375 */
|
||||
.rectangle_23375 {
|
||||
position: relative;
|
||||
width: 750rpx;
|
||||
height: 260rpx;
|
||||
background-color: #1a92ef;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
z-index: 0;
|
||||
margin-top: 0;
|
||||
border-radius: 0 0 24rpx 24rpx;
|
||||
/* 消息类型设置 */
|
||||
.text_2 {
|
||||
position: relative;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 50rpx;
|
||||
color: #ffffff;
|
||||
white-space: pre;
|
||||
height: 50rpx;
|
||||
margin-top: 24rpx;
|
||||
margin-bottom: -7rpx;
|
||||
width: max-content;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* 矩形 23377 */
|
||||
.rectangle_23377 {
|
||||
position: relative;
|
||||
width: 688rpx;
|
||||
height: 1056rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #ffffff;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
isolation: isolate;
|
||||
z-index: 2;
|
||||
margin-top: -94rpx;
|
||||
|
||||
/* flexContainer */
|
||||
.flexcontainer_1 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 344rpx;
|
||||
height: 32rpx;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 0;
|
||||
margin-top: 32rpx;
|
||||
margin-left: 30rpx;
|
||||
|
||||
/* 考试年份: */
|
||||
.text_3 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: 0.34em;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 0;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* 2016 年 */
|
||||
.text_4 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #333333;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 0;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 直线 424 */
|
||||
.div_424 {
|
||||
width: 626rpx;
|
||||
height: 0;
|
||||
border: 1rpx solid #f1f1f1;
|
||||
z-index: 4;
|
||||
position: relative;
|
||||
margin-top: 46rpx;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
/* flexContainer */
|
||||
.flexcontainer_2 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 482rpx;
|
||||
height: 32rpx;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 1;
|
||||
margin-top: 32rpx;
|
||||
margin-left: 30rpx;
|
||||
|
||||
/* 身份证号: */
|
||||
.text_5 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: 0.34em;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 0;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* ***********1234 */
|
||||
.text_6 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #333333;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 0;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 直线 425 */
|
||||
.div_425 {
|
||||
width: 626rpx;
|
||||
height: 0;
|
||||
border: 1rpx solid #f1f1f1;
|
||||
z-index: 5;
|
||||
position: relative;
|
||||
margin-top: 46rpx;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
/* flexContainer */
|
||||
.flexcontainer_3 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
// width: 288rpx;
|
||||
height: 32rpx;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 3;
|
||||
margin-top: 34rpx;
|
||||
margin-left: 30rpx;
|
||||
|
||||
/* 姓 名: */
|
||||
.text_7 {
|
||||
width: 210rpx;
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: 0.34em;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 0;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* 肖战 */
|
||||
.text_8 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #333333;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 0;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 64rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 直线 426 */
|
||||
.div_426 {
|
||||
width: 626rpx;
|
||||
height: 0;
|
||||
border: 1rpx solid #f1f1f1;
|
||||
z-index: 6;
|
||||
position: relative;
|
||||
margin-top: 46rpx;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
/* 科目成绩: */
|
||||
.text_9 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: 0.34em;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 32rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
margin-left: 30rpx;
|
||||
}
|
||||
|
||||
/* 组 48319 */
|
||||
.group_48319 {
|
||||
width: 626rpx;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 7;
|
||||
margin-top: 48rpx;
|
||||
margin-left: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #f4f7f9;
|
||||
isolation: isolate;
|
||||
|
||||
/* 语文 */
|
||||
.text_10 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
margin-left: 128rpx;
|
||||
}
|
||||
|
||||
/* 直线 427 */
|
||||
.div_427 {
|
||||
width: 40rpx;
|
||||
height: 0;
|
||||
transform: rotate(90deg);
|
||||
border: 1rpx solid #e5e8ea;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
margin-left: 84rpx;
|
||||
margin-top: 44rpx;
|
||||
}
|
||||
|
||||
/* 113 */
|
||||
.text_11 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: -0.04em;
|
||||
color: #0087cf;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
margin-left: 122rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 组 48320 */
|
||||
.group_48320 {
|
||||
width: 626rpx;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 9;
|
||||
margin-top: 32rpx;
|
||||
margin-left: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #f4f7f9;
|
||||
isolation: isolate;
|
||||
|
||||
/* 数学 */
|
||||
.text_12 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
margin-left: 128rpx;
|
||||
}
|
||||
|
||||
/* 直线 427 */
|
||||
.div_427_1 {
|
||||
width: 40rpx;
|
||||
height: 0;
|
||||
transform: rotate(90deg);
|
||||
border: 1rpx solid #e5e8ea;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
margin-left: 84rpx;
|
||||
margin-top: 44rpx;
|
||||
}
|
||||
|
||||
/* 123 */
|
||||
.text_13 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: -0.04em;
|
||||
color: #0087cf;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
margin-left: 122rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 组 48321 */
|
||||
.group_48321 {
|
||||
width: 626rpx;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 8;
|
||||
margin-top: 32rpx;
|
||||
margin-left: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #f4f7f9;
|
||||
isolation: isolate;
|
||||
|
||||
/* 外语 */
|
||||
.text_14 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
margin-left: 128rpx;
|
||||
}
|
||||
|
||||
/* 直线 427 */
|
||||
.div_427_2 {
|
||||
width: 40rpx;
|
||||
height: 0;
|
||||
transform: rotate(90deg);
|
||||
border: 1rpx solid #e5e8ea;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
margin-left: 84rpx;
|
||||
margin-top: 44rpx;
|
||||
}
|
||||
|
||||
/* 116 */
|
||||
.text_15 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: -0.04em;
|
||||
color: #0087cf;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
margin-left: 122rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 组 48322 */
|
||||
.group_48322 {
|
||||
width: 626rpx;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 10;
|
||||
margin-top: 32rpx;
|
||||
margin-left: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #f4f7f9;
|
||||
isolation: isolate;
|
||||
|
||||
/* 综合 */
|
||||
.text_16 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
margin-left: 128rpx;
|
||||
}
|
||||
|
||||
/* 直线 427 */
|
||||
.div_427_3 {
|
||||
width: 40rpx;
|
||||
height: 0;
|
||||
transform: rotate(90deg);
|
||||
border: 1rpx solid #e5e8ea;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
margin-left: 84rpx;
|
||||
margin-top: 44rpx;
|
||||
}
|
||||
|
||||
/* 195 */
|
||||
.text_17 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: -0.04em;
|
||||
color: #0087cf;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
margin-left: 122rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 组 48323 */
|
||||
.group_48323 {
|
||||
width: 626rpx;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
z-index: 11;
|
||||
margin-top: 32rpx;
|
||||
margin-left: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: #f4f7f9;
|
||||
isolation: isolate;
|
||||
|
||||
/* 总分 */
|
||||
.text_18 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
color: #6f6f6f;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 0;
|
||||
position: relative;
|
||||
margin-left: 128rpx;
|
||||
}
|
||||
|
||||
/* 直线 427 */
|
||||
.div_427_4 {
|
||||
width: 40rpx;
|
||||
height: 0;
|
||||
transform: rotate(90deg);
|
||||
border: 1rpx solid #e5e8ea;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
margin-left: 84rpx;
|
||||
margin-top: 44rpx;
|
||||
}
|
||||
|
||||
/* 549 */
|
||||
.text_19 {
|
||||
font-size: 32rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 44rpx;
|
||||
letter-spacing: -0.04em;
|
||||
color: #0087cf;
|
||||
white-space: pre;
|
||||
height: 44rpx;
|
||||
margin-top: 26rpx;
|
||||
margin-bottom: -6rpx;
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
margin-left: 122rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* 组 48324 */
|
||||
.group_48324 {
|
||||
width: 688rpx;
|
||||
height: 90rpx;
|
||||
position: relative;
|
||||
font-size: 28rpx;
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
line-height: 40rpx;
|
||||
color: #ffffff;
|
||||
white-space: pre;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
z-index: 3;
|
||||
margin-top: 48rpx;
|
||||
margin-left: 32rpx;
|
||||
border-radius: 298rpx;
|
||||
background-color: #1689f9;
|
||||
|
||||
/* 返回查询页 */
|
||||
.text_20 {
|
||||
height: 40rpx;
|
||||
margin-top: 32rpx;
|
||||
margin-bottom: -6rpx;
|
||||
position: relative;
|
||||
margin-left: 274rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* home */
|
||||
.home {
|
||||
position: absolute;
|
||||
width: 750rpx;
|
||||
height: 68rpx;
|
||||
top: auto;
|
||||
left: 0;
|
||||
background-color: rgba(255, 255, 255, 0);
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.home_indicator {}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,622 @@
|
|||
<script setup>
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
import wmWatermark from "@/components/wm-watermark/wm-watermark.vue"
|
||||
import DateTimePicker from '@/components/dengrq-datetime-picker/dateTimePicker/index.vue';
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
import {
|
||||
reactive,
|
||||
ref,
|
||||
onMounted,
|
||||
computed
|
||||
} from 'vue';
|
||||
|
||||
const CACHE_KEY = 'score_guandong_info';
|
||||
|
||||
const data = reactive({
|
||||
bgImg:'',
|
||||
form: {
|
||||
subject: '文科',
|
||||
avatar: '',
|
||||
name: '大王',
|
||||
idNumber: '',
|
||||
examNumber: '123456789',
|
||||
chinese: '116',
|
||||
math: '104',
|
||||
english: '104',
|
||||
history: '104',
|
||||
politics: '104',
|
||||
geography: '104',
|
||||
total: '104',
|
||||
undergraduateTotal: '104',
|
||||
ranking: '104',
|
||||
technicalTotal: '104',
|
||||
technicalRanking: '1455',
|
||||
time: '2025-6-25'
|
||||
}
|
||||
});
|
||||
|
||||
const total = computed(() => {
|
||||
const sum = Number(data.form.chinese || 0) + Number(data.form.math || 0) + Number(data.form.english || 0) +
|
||||
Number(data.form.history || 0) + Number(data.form.politics || 0) + Number(data.form.geography || 0);
|
||||
return sum || '';
|
||||
});
|
||||
|
||||
function getSubjectLabels(subject) {
|
||||
const isScience = subject === '理科'
|
||||
return {
|
||||
subject3: isScience ? '物理' : '历史',
|
||||
subject4: isScience ? '化学' : '思想政治',
|
||||
subject5: isScience ? '生物学' : '地理',
|
||||
trackName: isScience ? '物理' : '历史',
|
||||
}
|
||||
}
|
||||
|
||||
const subjectLabels = computed(() => getSubjectLabels(data.form.subject || '文科'))
|
||||
|
||||
const editDialog = reactive({
|
||||
show: false,
|
||||
data: {}
|
||||
});
|
||||
|
||||
const editSubjectLabels = computed(() => getSubjectLabels(editDialog.data.subject || '文科'))
|
||||
|
||||
onMounted(async() => {
|
||||
|
||||
data.bgImg= await imgLocal.getLocalImage('other/score/guandong/guandongbg.png');
|
||||
loadCache();
|
||||
});
|
||||
|
||||
function loadCache() {
|
||||
const cache = uni.getStorageSync(CACHE_KEY);
|
||||
if (cache) {
|
||||
data.form = {
|
||||
...data.form,
|
||||
...cache,
|
||||
subject: cache.subject || '文科'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function saveCache() {
|
||||
uni.setStorageSync(CACHE_KEY, data.form);
|
||||
}
|
||||
|
||||
function openEditDialog() {
|
||||
editDialog.data = JSON.parse(JSON.stringify(data.form));
|
||||
if (!editDialog.data.subject) {
|
||||
editDialog.data.subject = '文科';
|
||||
}
|
||||
editDialog.show = true;
|
||||
}
|
||||
|
||||
function saveEdit() {
|
||||
data.form = {
|
||||
...data.form,
|
||||
...editDialog.data
|
||||
};
|
||||
saveCache();
|
||||
editDialog.show = false;
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
}
|
||||
|
||||
const editTotal = computed(() => {
|
||||
const sum = Number(editDialog.data.chinese || 0) + Number(editDialog.data.math || 0) + Number(editDialog.data
|
||||
.english || 0) + Number(editDialog.data.history || 0) + Number(editDialog.data.politics || 0) + Number(
|
||||
editDialog.data.geography || 0);
|
||||
return sum || '';
|
||||
});
|
||||
function back(){
|
||||
uni.navigateBack()
|
||||
}
|
||||
function onChangeStartDate(e){
|
||||
editDialog.data.time=e
|
||||
console.log(e)
|
||||
}
|
||||
function getTime(times,status){
|
||||
let list=times.split('-')
|
||||
if(status){
|
||||
return list[0]+'年'
|
||||
}else{
|
||||
return list[0]+'年'+list[1]+'月'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<wmWatermark :text="'广东省教育考试院'+data.form.time"/>
|
||||
<view v-if="$isVip()" >
|
||||
<watermark dark="light" source="uni_alipay_other_score" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_score')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container">
|
||||
<view class="headerBox" :style="{'padding-top':$systemInfo.statusBarHeight*2+'rpx'}">
|
||||
<view class="header" >
|
||||
<view class="left" @click="back()">
|
||||
<image src="/static/image/other/score/guandong/leftIcon.png" mode=""></image>
|
||||
</view>
|
||||
<view class="center">
|
||||
考试成绩结果
|
||||
</view>
|
||||
<view class="right">
|
||||
<image src="/static/image/other/score/guandong/rightIcon.png" mode=""></image>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
<view class="" :style="{height:$systemInfo.statusBarHeight*2+88+'rpx'}">
|
||||
|
||||
</view>
|
||||
<view class="content">
|
||||
<view class="title">
|
||||
{{ getTime(data.form.time,0) }}
|
||||
</view>
|
||||
<view class="dec">
|
||||
{{ getTime(data.form.time,1) }}广东省普通高等学校招生全国统一考试
|
||||
</view>
|
||||
</view>
|
||||
<image class="bgimg" :src="data.bgImg" mode="widthFix"></image>
|
||||
<view class="list" @click="openEditDialog">
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
姓名
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.name}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
考生号
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.examNumber}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
语文
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.chinese}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
数学
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.math}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
英语
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.english}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
{{ subjectLabels.subject3 }}
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.history}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
{{ subjectLabels.subject4 }}
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.politics}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
{{ subjectLabels.subject5 }}
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.geography}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
普通类 ({{ subjectLabels.trackName }})总分
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.total}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
本科普通类 ({{ subjectLabels.trackName }})总分 (含加分)
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.undergraduateTotal}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
排位
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.ranking}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
专科普通类 ({{ subjectLabels.trackName }})总分 (含加分)
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.technicalTotal}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="item">
|
||||
<view class="text1">
|
||||
排位
|
||||
</view>
|
||||
<view class="text2">
|
||||
{{data.form.technicalRanking}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<safeBottom bgColor="#F3F8FB" />
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<view v-if="editDialog.show" class="editDialog">
|
||||
<view class="editDialog_bg">
|
||||
<view class="editDialog_header">
|
||||
<text class="title">编辑成绩信息</text>
|
||||
</view>
|
||||
<view class="editDialog_body">
|
||||
<view class="formItem">
|
||||
<text>科目</text>
|
||||
<view class="subject-options">
|
||||
<view class="subject-option" :class="{ active: editDialog.data.subject === '文科' }"
|
||||
@click="editDialog.data.subject = '文科'">文科</view>
|
||||
<view class="subject-option" :class="{ active: editDialog.data.subject === '理科' }"
|
||||
@click="editDialog.data.subject = '理科'">理科</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>姓名</text>
|
||||
<input v-model="editDialog.data.name" placeholder="请输入姓名" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>证件号</text>
|
||||
<input v-model="editDialog.data.idNumber" placeholder="请输入证件号" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>考生号</text>
|
||||
<input v-model="editDialog.data.examNumber" placeholder="请输入考生号" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>语文</text>
|
||||
<input v-model="editDialog.data.chinese" type="digit" placeholder="请输入语文成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>数学</text>
|
||||
<input v-model="editDialog.data.math" type="digit" placeholder="请输入数学成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>英语</text>
|
||||
<input v-model="editDialog.data.english" type="digit" placeholder="请输入英语成绩" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>{{ editSubjectLabels.subject3 }}</text>
|
||||
<input v-model="editDialog.data.history" type="digit" :placeholder="'请输入' + editSubjectLabels.subject3 + '成绩'" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>{{ editSubjectLabels.subject4 }}</text>
|
||||
<input v-model="editDialog.data.politics" type="digit" :placeholder="'请输入' + editSubjectLabels.subject4 + '成绩'" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>{{ editSubjectLabels.subject5 }}</text>
|
||||
<input v-model="editDialog.data.geography" type="digit" :placeholder="'请输入' + editSubjectLabels.subject5 + '成绩'" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>普通类 ({{ editSubjectLabels.trackName }})总分</text>
|
||||
<text style="flex:1;text-align:right;font-size:28rpx;color:#333;">{{editTotal}}</text>
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>本科普通类 ({{ editSubjectLabels.trackName }})总分 (含加分)</text>
|
||||
<input v-model="editDialog.data.undergraduateTotal" type="digit" placeholder="请输入本科总分" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>排位</text>
|
||||
<input v-model="editDialog.data.ranking" type="digit" placeholder="请输入排位" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>专科普通类 ({{ editSubjectLabels.trackName }})总分 (含加分)</text>
|
||||
<input v-model="editDialog.data.technicalTotal" type="digit" placeholder="请输入专科总分" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>排位</text>
|
||||
<input v-model="editDialog.data.technicalRanking" type="digit" placeholder="请输入排位" />
|
||||
</view>
|
||||
<view class="formItem">
|
||||
<text>时间</text>
|
||||
<view style="width:100%;">
|
||||
<DateTimePicker :defaultDate="editDialog.data.time" :mode="1" @onChange="onChangeStartDate" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<view class="btn-cancel" @click="editDialog.show=false">取消</view>
|
||||
<view class="btn-save" @click="saveEdit">保存</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
page{
|
||||
background-color: #F3F8FB;
|
||||
}
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.justify-start {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.justify-center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.justify-end {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.justify-between {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.items-start {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.items-end {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.items-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.no-shrink {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 编辑弹窗样式 */
|
||||
.editDialog {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.editDialog_bg {
|
||||
width: 680rpx;
|
||||
max-height: 80vh;
|
||||
background-color: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.editDialog_header {
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
text-align: center;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.editDialog_body {
|
||||
padding: 20rpx 30rpx;
|
||||
overflow-y: auto;
|
||||
max-height: 60vh;
|
||||
}
|
||||
|
||||
.formItem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx 0;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
text {
|
||||
width: 200rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
input {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.subject-options {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.subject-option {
|
||||
padding: 8rpx 32rpx;
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 8rpx;
|
||||
|
||||
&.active {
|
||||
color: #187AFF;
|
||||
border-color: #187AFF;
|
||||
background-color: rgba(24, 122, 255, 0.08);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
padding: 20rpx 30rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
gap: 20rpx;
|
||||
|
||||
.btn-cancel,
|
||||
.btn-save {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
border-radius: 10rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #f5f5f5;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background-color: #187AFF;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.headerBox{
|
||||
z-index: 999;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.header{
|
||||
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.left{
|
||||
width: 216rpx;
|
||||
height: 88rpx;
|
||||
image{
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
margin-left: 30rpx;
|
||||
margin-top:46rpx;
|
||||
}
|
||||
}
|
||||
.center{
|
||||
font-weight: 400;
|
||||
font-size: 19px;
|
||||
color: #FFFFFF;
|
||||
padding-top: 30rpx;
|
||||
}
|
||||
|
||||
.right{
|
||||
width: 216rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
image{
|
||||
width: 200rpx;
|
||||
height: 64rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bgimg{
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.content{
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
padding-left: 40rpx;
|
||||
margin-top: 100rpx;
|
||||
.title{
|
||||
font-weight: 400;
|
||||
font-size: 25px;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.dec{
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
.list{
|
||||
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
margin: 72rpx 40rpx 0;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.1);
|
||||
border-radius: 12px 12px 12px 12px;
|
||||
padding-left: 32rpx;
|
||||
.item{
|
||||
height: 72rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1rpx solid #F2F2F2;
|
||||
.text1{
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #898D96;
|
||||
}
|
||||
.text2{
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
color: #1A1A1A;
|
||||
margin-right: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,180 @@
|
|||
<template>
|
||||
<view>
|
||||
<NavBar :title="data.navBar.title" :bgColor="data.navBar.bgColor" />
|
||||
<view class="list-container">
|
||||
<view class="item" v-for="item in source" :key="item.id" @click="goPage(item.callUrl,item.name)"
|
||||
:style="{ 'background-image': `url('/static/image/other/score/${item.icon}bg.png')` }">
|
||||
<view class="content flex flex-align-center">
|
||||
<image class="logo" :src="`/static/image/other/score/${item.icon}.png`" mode=""></image>
|
||||
<view class="name flex-1">{{ item.name }}</view>
|
||||
<view class="right-button">
|
||||
<!-- <uni-icons type="right" size="16"></uni-icons> -->
|
||||
</view>
|
||||
</view>
|
||||
<!-- <view class="line" :style="{ background: item.color.lineColor }"></view> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue'
|
||||
import {
|
||||
onLoad
|
||||
} from "@dcloudio/uni-app";
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js';
|
||||
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
// 列表
|
||||
const source = ref([{
|
||||
name: '查询中心',
|
||||
color: {
|
||||
bgColor: '#F3EAFF',
|
||||
lineColor: '#B78EF5',
|
||||
buttonColor: '#BA8DFF',
|
||||
},
|
||||
icon: 'icon1',
|
||||
callUrl: "/pages/other/score/center"
|
||||
},
|
||||
{
|
||||
name: '广东省',
|
||||
color: {
|
||||
bgColor: '#FFE9E9',
|
||||
lineColor: '#FF6969',
|
||||
buttonColor: '#FB6767',
|
||||
},
|
||||
icon: 'guandong',
|
||||
callUrl: "/pages/other/score/guandong"
|
||||
},
|
||||
{
|
||||
name: '重庆市',
|
||||
color: {
|
||||
bgColor: '#FFF0DD',
|
||||
lineColor: '#FFA143',
|
||||
buttonColor: '#FFA64D',
|
||||
},
|
||||
icon: 'chongqing',
|
||||
callUrl: "/pages/other/score/chongqing"
|
||||
},
|
||||
{
|
||||
name: '河北省',
|
||||
color: {
|
||||
bgColor: '#E0FFD9',
|
||||
lineColor: '#56B745',
|
||||
buttonColor: '#5DCD49',
|
||||
},
|
||||
icon: 'hebei',
|
||||
callUrl: "/pages/other/score/hebei"
|
||||
}
|
||||
])
|
||||
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: '高考成绩',
|
||||
bgColor: '#F0F4F9',
|
||||
},
|
||||
type: "message"
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.type) {
|
||||
data.type = options.type
|
||||
}
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'score',
|
||||
prefix: '.uni.other.',
|
||||
value:'高考查询'
|
||||
})
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
// 保存定时器引用,以便在页面卸载时清理
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500)
|
||||
// #endif
|
||||
})
|
||||
|
||||
function goPage(url,name) {
|
||||
if (url) {
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'score',
|
||||
prefix: '.uni.other.',
|
||||
value:name
|
||||
})
|
||||
util.goPage(url)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import '@/common/main.css';
|
||||
</style>
|
||||
<style lang="less">
|
||||
.list-container {
|
||||
background-color: #F0F4F9;
|
||||
padding: 24rpx 32rpx;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 160rpx;
|
||||
border-radius: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
padding: 40rpx 36rpx 24rpx 28rpx;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
.content {
|
||||
.logo {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-left: 32rpx;
|
||||
color: #1A1A1A;
|
||||
font-size: 36rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.right-button {
|
||||
width: 140rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 16rpx;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
line-height: 64rpx !important;
|
||||
text-align: right;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.line {
|
||||
width: 100rpx;
|
||||
height: 8rpx;
|
||||
filter: blur(5px);
|
||||
opacity: 0.5;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,869 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<!-- 自定义头部导航栏 -->
|
||||
<ZdyNavbar @right-click="edit" isRightButton rightButtonText="编辑" :title="data.navbar.title"
|
||||
:bgColor="data.navbar.bgColor" :isBack="true" />
|
||||
<view class="footer-box">
|
||||
<view class="btn" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}" v-for="(item, index) in data.typeList" :key="index" :class="{ active: data.type == index }"
|
||||
@click="setType(index)">
|
||||
{{item}}
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
style="display: flex;align-items: center;background: #fff;border-radius: 6px;margin: 10px;padding: 4px;color: #767676;">
|
||||
<image src="/static/image/other/notice.png"
|
||||
style="width: 16px;height: 16px;margin-right: 10rpx;margin-left: 10rpx;"></image>
|
||||
此功能不具备真实性,仅供娱乐
|
||||
</view>
|
||||
<image :src="data.code" mode="widthFix" style="width:calc( 100vw - 24px);margin:0 12px;" @click="previewImage">
|
||||
</image>
|
||||
<view class="button-container" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<button class="btn-save-image" @click="saveImage">保存图片</button>
|
||||
</view>
|
||||
<view style="width: 0px;height: 0;overflow: hidden;" v-if="data.shuaxing && currentBgImg">
|
||||
<l-painter isCanvasToTempFilePath @success="successImage" @progress="progress" css="width:351px;height:460px;"
|
||||
v-if="data.type == 0">
|
||||
<l-painter-view css="width:351px;height:460px;position: relative;">
|
||||
<l-painter-image :src="data.bgImg1" css="width:351px;height:460px;position:absolute;left:0;top:0;object-fit:fill;" />
|
||||
<!-- 落款日期 -->
|
||||
<l-painter-view css="position: absolute;left:82px;bottom:100px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss" :text="toVerticalText(data.banner.dateText)" />
|
||||
</l-painter-view>
|
||||
<!-- 敬赠落款 -->
|
||||
<l-painter-view css="position: absolute;left:100px;bottom:100px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss" :text="toVerticalText(data.banner.donorLine)" />
|
||||
</l-painter-view>
|
||||
<!-- 受赠对象(画布宽351,原 right:72 → left:267,避免鸿蒙 right 定位失效) -->
|
||||
<l-painter-view css="position: absolute;top:80px;left:267px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss" :text="toVerticalText(data.banner.recipientLine)" />
|
||||
</l-painter-view>
|
||||
<!-- 中心大字装饰(原 right 均改为 left,字宽按 20px) -->
|
||||
<l-painter-view css="position: absolute;top:80px;left:168px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="position: absolute;top:108px;left:120px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="position: absolute;top:108px;left:219px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="position: absolute;top:150px;left:102px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="position: absolute;top:150px;left:235px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="position: absolute;top:192px;left:136px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="position: absolute;top:192px;left:211px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss1" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<!-- 中心主字 -->
|
||||
<l-painter-view css="position: absolute;top:105px;left:135px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss2" :text="data.banner.centerChar" />
|
||||
</l-painter-view>
|
||||
<!-- 上句赞语 -->
|
||||
<l-painter-view css="position: absolute;bottom:160px;left:0;">
|
||||
<l-painter-text :css="data.textFont+data.textCss3" :text="data.banner.phraseTop" />
|
||||
</l-painter-view>
|
||||
<!-- 下句赞语 -->
|
||||
<l-painter-view css="position: absolute;bottom:118px;left:0;">
|
||||
<l-painter-text :css="data.textFont+data.textCss3" :text="data.banner.phraseBottom" />
|
||||
</l-painter-view>
|
||||
|
||||
<l-painter-view v-if="$isVip()" css="position: absolute;left:127px;bottom:132px;">
|
||||
<l-painter-image src="/static/image/other/card/shuiyin2.png" css="width: 97px;height: 28px;" />
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
<l-painter isCanvasToTempFilePath @success="successImage" @progress="progress" css="width:351px;height:460px;"
|
||||
v-else-if="data.type == 1">
|
||||
<l-painter-view css="width:351px;height:460px;position: relative;">
|
||||
<l-painter-image :src="data.bgImg2" css="width:351px;height:460px;position:absolute;left:0;top:0;object-fit:fill;" />
|
||||
<!-- 落款日期 -->
|
||||
<l-painter-view css="position: absolute;left:82px;bottom:100px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss" :text="toVerticalText(data.banner.dateText)" />
|
||||
</l-painter-view>
|
||||
<!-- 敬赠落款 -->
|
||||
<l-painter-view css="position: absolute;left:100px;bottom:100px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss" :text="toVerticalText(data.banner.donorLine)" />
|
||||
</l-painter-view>
|
||||
<!-- 受赠对象 -->
|
||||
<l-painter-view css="position: absolute;top:80px;left:267px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss" :text="toVerticalText(data.banner.recipientLine)" />
|
||||
</l-painter-view>
|
||||
<!-- 上句赞语(右列) -->
|
||||
<l-painter-view css="position: absolute;top:95px;left:188px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss4" :text="toVerticalText(data.banner.phraseTop)" />
|
||||
</l-painter-view>
|
||||
<!-- 下句赞语(左列) -->
|
||||
<l-painter-view css="position: absolute;top:95px;left:118px;">
|
||||
<l-painter-text :css="data.textFont+data.textCss4" :text="toVerticalText(data.banner.phraseBottom)" />
|
||||
</l-painter-view>
|
||||
|
||||
<l-painter-view v-if="$isVip()" css="position: absolute;left:127px;bottom:132px;">
|
||||
<l-painter-image src="/static/image/other/card/shuiyin2.png" css="width: 97px;height: 28px;" />
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
</view>
|
||||
<!-- 编辑弹窗 -->
|
||||
<view v-if="showEditPopup" class="popup-overlay">
|
||||
<view class="popup-content">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">编辑锦旗</text>
|
||||
<text class="popup-close" @click="closeEditPopup">×</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<view class="form-row">
|
||||
<text class="form-label">落款日期:</text>
|
||||
<input class="form-input" v-model="editForm.dateText" type="text" placeholder="如:二零二六年四月" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">敬赠落款:</text>
|
||||
<input class="form-input" v-model="editForm.donorLine" type="text" placeholder="如:张三敬赠" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">受赠对象:</text>
|
||||
<input class="form-input" v-model="editForm.recipientLine" type="text" placeholder="如:赠:某某团队" />
|
||||
</view>
|
||||
<view class="form-row" v-if="data.type == 0">
|
||||
<text class="form-label">中心大字:</text>
|
||||
<input class="form-input" v-model="editForm.centerChar" type="text" maxlength="1" placeholder="单字,如:牛" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">上句赞语:</text>
|
||||
<input class="form-input" v-model="editForm.phraseTop" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">下句赞语:</text>
|
||||
<input class="form-input" v-model="editForm.phraseBottom" type="text" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<button class="btn-cancel" @click="closeEditPopup">取消</button>
|
||||
<button class="btn-save" @click="saveEditForm">保存</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_silkBanner')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 自定义头部
|
||||
import ZdyNavbar from "@/components/nav-bar/nav-bar.vue"
|
||||
import { imgLocal } from '@/utils/common.js';
|
||||
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
computed,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onReady,
|
||||
onPullDownRefresh,
|
||||
onReachBottom
|
||||
} from "@dcloudio/uni-app";
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
function defaultBanner(type) {
|
||||
const banners = {
|
||||
0: {
|
||||
dateText: '二零二六年四月',
|
||||
donorLine: '安娜敬赠',
|
||||
recipientLine: '赠:良子大胃袋',
|
||||
centerChar: '牛',
|
||||
phraseTop: '焖子大王',
|
||||
phraseBottom: '靠谱'
|
||||
},
|
||||
1: {
|
||||
dateText: '二零二六年五月',
|
||||
donorLine: '小狗敬赠',
|
||||
recipientLine: '赠:大小姐',
|
||||
phraseTop: '我勒个豆',
|
||||
phraseBottom: '太有实力'
|
||||
}
|
||||
// 可以继续扩展更多 type
|
||||
}
|
||||
|
||||
// 返回对应 type 的数据,如果没有则返回默认 type 1
|
||||
return banners[type] || banners[1]
|
||||
}
|
||||
|
||||
function mergeBanner(raw, type) {
|
||||
return Object.assign(defaultBanner(type), raw && typeof raw === 'object' ? raw : {})
|
||||
}
|
||||
|
||||
/** 竖排:用换行代替窄 width 自动折行(鸿蒙 canvas measureText 下窄宽不换行) */
|
||||
function toVerticalText(text) {
|
||||
return String(text ?? '').split('').join('\n')
|
||||
}
|
||||
|
||||
async function loadBannerBg(path, fallback) {
|
||||
try {
|
||||
const localPath = await imgLocal.getLocalImage(path)
|
||||
return localPath || fallback
|
||||
} catch (e) {
|
||||
console.error('背景图加载失败,使用本地兜底', path, e)
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
|
||||
function refreshPainter() {
|
||||
data.shuaxing = false
|
||||
setTimeout(() => {
|
||||
data.shuaxing = true
|
||||
}, 80)
|
||||
}
|
||||
|
||||
const data = reactive({
|
||||
isShow:false,
|
||||
type: 0,
|
||||
bgImg1:'',
|
||||
bgImg2:'',
|
||||
banner: mergeBanner(null, 0),
|
||||
shuaxing: false,
|
||||
navbar: {
|
||||
title: "锦旗",
|
||||
bgColor: '#EDEDED',
|
||||
},
|
||||
width: 800,
|
||||
height: 600,
|
||||
code: '',
|
||||
textCss: 'text-align:center;font-weight:400;width:12px;color:#FFDD6D;font-size:12px;line-height:1.15em;',
|
||||
textCss1: 'text-align:center;font-weight:400;width:20px;color:#FFDD6D;font-size:20px;line-height:1em;',
|
||||
textCss2: 'text-align:center;font-weight:400;width:82px;color:#FFDD6D;font-size:78px;line-height:1em;',
|
||||
textCss3: 'text-align:center;width:351px;font-weight:400;letter-spacing:16px;color:#FFDD6D;font-size:28px;line-height:1em;',
|
||||
textCss4: 'text-align:center;width:44px;font-weight:400;color:#FFDD6D;font-size:40px;line-height:1.15em;',
|
||||
textFont: 'font-family:"certificate2";',
|
||||
typeList: ['样式1', '样式2']
|
||||
})
|
||||
|
||||
const currentBgImg = computed(() => data.type === 0 ? data.bgImg1 : data.bgImg2)
|
||||
|
||||
// 弹窗相关
|
||||
const showEditPopup = ref(false);
|
||||
const editForm = ref({});
|
||||
onLoad(async(option) => {
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
data.bgImg1 = await loadBannerBg('other/silkBanner/banner1.png', '/static/image/other/silkBanner/banner1.png')
|
||||
data.bgImg2 = await loadBannerBg('other/silkBanner/banner2.png', '/static/image/other/silkBanner/banner2.png')
|
||||
// 进入锦旗页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'silkBanner',
|
||||
prefix: '.uni.other.',
|
||||
value: "锦旗"
|
||||
})
|
||||
data.banner = mergeBanner(uni.getStorageSync("silkBanner" + data.type), data.type)
|
||||
const config = uni.getStorageSync('config')
|
||||
console.log("---config---", config);
|
||||
const font = config?.config?.['client.uniapp.font']
|
||||
|
||||
const startPaint = () => {
|
||||
data.isShow = true
|
||||
data.shuaxing = true
|
||||
}
|
||||
|
||||
if (!font?.certificate2) {
|
||||
console.warn('字体配置缺失,直接生成锦旗')
|
||||
startPaint()
|
||||
return
|
||||
}
|
||||
|
||||
console.log("字体地址信息", font.certificate2);
|
||||
const fontUrl = font.certificate2;
|
||||
const fontName = 'certificate2';
|
||||
|
||||
const loadFont = (path) => {
|
||||
uni.loadFontFace({
|
||||
family: fontName,
|
||||
source: `url("${path}")`,
|
||||
success() {
|
||||
startPaint()
|
||||
console.log('字体加载成功');
|
||||
},
|
||||
fail(err) {
|
||||
startPaint()
|
||||
console.error('字体加载失败', err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// #ifdef H5
|
||||
loadFont(fontUrl);
|
||||
// #endif
|
||||
|
||||
// #ifndef H5
|
||||
const savedFontPath = uni.getStorageSync('certificate2_font_path');
|
||||
if (savedFontPath) {
|
||||
loadFont(savedFontPath);
|
||||
} else {
|
||||
uni.downloadFile({
|
||||
url: fontUrl,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveFile({
|
||||
tempFilePath: res.tempFilePath,
|
||||
success: (saveRes) => {
|
||||
const savedPath = saveRes.savedFilePath;
|
||||
uni.setStorageSync('certificate2_font_path', savedPath);
|
||||
console.log("字体保存路径", savedPath);
|
||||
loadFont(savedPath);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('保存文件失败', err);
|
||||
loadFont(res.tempFilePath);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
startPaint()
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('下载字体失败', err);
|
||||
startPaint()
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
})
|
||||
onReady(() => {
|
||||
|
||||
})
|
||||
onShow(() => {})
|
||||
onPullDownRefresh(() => {
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 1000);
|
||||
})
|
||||
onReachBottom(() => {
|
||||
|
||||
})
|
||||
function setType(index) {
|
||||
if (data.type === index) return
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
data.type = index
|
||||
data.banner = mergeBanner(uni.getStorageSync("silkBanner" + data.type), data.type)
|
||||
data.code = ''
|
||||
refreshPainter()
|
||||
}
|
||||
|
||||
function successImage(e) {
|
||||
data.code = e
|
||||
uni.hideLoading()
|
||||
}
|
||||
|
||||
function progress(e) {
|
||||
// console.log(e)
|
||||
|
||||
}
|
||||
// 打开编辑弹窗
|
||||
function edit() {
|
||||
editForm.value = mergeBanner(JSON.parse(JSON.stringify(data.banner)), data.type)
|
||||
showEditPopup.value = true;
|
||||
}
|
||||
|
||||
// 关闭编辑弹窗
|
||||
function closeEditPopup() {
|
||||
showEditPopup.value = false;
|
||||
}
|
||||
|
||||
// 保存编辑表单
|
||||
function saveEditForm() {
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
data.banner = mergeBanner(editForm.value, data.type)
|
||||
data.code = ''
|
||||
refreshPainter()
|
||||
uni.setStorageSync("silkBanner" + data.type, data.banner)
|
||||
// 关闭弹窗
|
||||
showEditPopup.value = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将本地图片路径通过 Canvas 转换为 File 对象
|
||||
* @param {string} localPath - 本地图片路径(如从 uni.chooseImage 获取的 tempFilePath)
|
||||
* @param {Object} options - 可选参数
|
||||
* @param {string} options.format - 输出格式 'image/png' 或 'image/jpeg',默认 'image/png'
|
||||
* @param {number} options.quality - 图片质量(仅 jpeg 有效),0~1,默认 0.92
|
||||
* @param {number} options.maxWidth - 最大宽度(等比缩放),不填则使用原图尺寸
|
||||
* @param {number} options.maxHeight - 最大高度(等比缩放),不填则使用原图尺寸
|
||||
* @returns {Promise<File>} 返回一个 Promise,resolve 为 File 对象
|
||||
*/
|
||||
function convertLocalImageToFile(localPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {
|
||||
entry.file((file) => {
|
||||
const reader = new plus.io.FileReader();
|
||||
reader.onload = (e) => {
|
||||
resolve(e.target.result)
|
||||
};
|
||||
reader.onerror = (err) => reject(err);
|
||||
reader.readAsDataURL(file);
|
||||
}, reject);
|
||||
}, reject);
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
reject(new Error('plus.io not supported'))
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
// 预览图片
|
||||
function previewImage() {
|
||||
if (data.code) {
|
||||
uni.previewImage({
|
||||
urls: [data.code],
|
||||
current: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 保存图片
|
||||
function saveImage() {
|
||||
if (data.code) {
|
||||
console.log(data.code)
|
||||
uni.showLoading({
|
||||
title: '保存中...'
|
||||
});
|
||||
try {
|
||||
// 检查是否为base64格式
|
||||
if (data.code.startsWith('data:image')) {
|
||||
// 处理base64格式图片
|
||||
console.log('开始处理base64图片');
|
||||
uni.base64ToTempFile({
|
||||
base64: data.code.split(',')[1], // 去除base64前缀
|
||||
success: (res) => {
|
||||
console.log('base64转换成功', res);
|
||||
if (res.tempFilePath) {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
console.log('保存图片成功');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('保存图片失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('base64转换失败,无临时文件路径');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '转换失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('base64转换失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '转换失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (data.code.startsWith('_') || data.code.includes('temp') || data.code.includes('cache') || data
|
||||
.code.includes('_doc') || data.code.includes('_tmp')) {
|
||||
// 处理本地临时文件
|
||||
console.log('开始处理本地临时文件');
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: data.code,
|
||||
success: () => {
|
||||
console.log('保存本地文件成功');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('保存本地文件失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 处理网络图片
|
||||
console.log('开始处理网络图片');
|
||||
uni.downloadFile({
|
||||
url: data.code,
|
||||
success: (res) => {
|
||||
console.log('下载图片成功', res);
|
||||
if (res.statusCode === 200 && res.tempFilePath) {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
console.log('保存图片成功');
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('保存图片失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('下载图片失败,状态码:', res.statusCode);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '下载失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('下载图片失败', err);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '下载失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('保存图片异常', error);
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '暂无图片可保存',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
page {
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
.box {
|
||||
width: 750rpx;
|
||||
height: 500rpx;
|
||||
// background-image: url('/static/image/other/certificate/graduate/graduate1.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
position: relative;
|
||||
|
||||
.title {
|
||||
position: absolute;
|
||||
width: 288rpx;
|
||||
height: 36rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
left: 92rpx;
|
||||
top: 134rpx;
|
||||
|
||||
image {
|
||||
height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
width: 108rpx;
|
||||
height: 108rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
right: 82rpx;
|
||||
bottom: 124rpx;
|
||||
|
||||
image {
|
||||
height: 108rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "card";
|
||||
src: url("/static/font/card.ttf");
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
.aadadad {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.heiti {
|
||||
font-family: "SimHei", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
.popup-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
font-size: 48rpx;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin-bottom: 30rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
width: 200rpx;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
flex: 1;
|
||||
padding: 15rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 4rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.form-separator {
|
||||
margin: 0 10rpx;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.form-total {
|
||||
margin-top: 10rpx;
|
||||
padding-top: 10rpx;
|
||||
border-top: 1rpx dashed #ddd;
|
||||
}
|
||||
|
||||
.form-total-input {
|
||||
background-color: #f9f9f9;
|
||||
color: #ff6b35;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* 上传图片样式 */
|
||||
.upload-container {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
width: 120rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1rpx dashed #ddd;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.upload-image {
|
||||
width: 98rpx;
|
||||
height: 115rpx;
|
||||
border-radius: 1rpx;
|
||||
object-fit: cover;
|
||||
border: 1px dashed #ddd;
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.btn-cancel,
|
||||
.btn-save {
|
||||
width: calc(48% - 40rpx);
|
||||
padding: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
// border: 1rpx solid #ddd;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background-color: #187AFF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
|
||||
}
|
||||
|
||||
/* 保存图片按钮 */
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 86px;
|
||||
width: 100vw;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.btn-save-image {
|
||||
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 18rpx 60rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
box-shadow: 0 3rpx 10rpx rgba(7, 66, 193, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
text-align: center;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
|
||||
.btn-save-image:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 4rpx 12rpx rgba(7, 72, 193, 0.4);
|
||||
}
|
||||
.btn-save-image:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2rpx 6rpx rgba(7, 140, 193, 0.3);
|
||||
}
|
||||
.container {
|
||||
padding-bottom: 220rpx;
|
||||
}
|
||||
.footer-box {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 16px;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
|
||||
padding-bottom: env(safe-area-inset-bottom); // 兼容 IOS>11.2
|
||||
z-index: 10;
|
||||
.btn {
|
||||
font-size: 18px;
|
||||
color: #767676;
|
||||
width: 180rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
background: #FFFFFF;
|
||||
text-align: center;
|
||||
margin: 0 24rpx;
|
||||
border: 2px solid #FFFFFF;
|
||||
color: #767676;
|
||||
}
|
||||
.active {
|
||||
color: #1777FF;
|
||||
border: 2px solid #1777FF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -3,15 +3,20 @@
|
|||
<!-- 自定义头部导航栏 -->
|
||||
<ZdyNavbar @right-click="edit" isRightButton rightButtonText="编辑" :title="data.navbar.title"
|
||||
:bgColor="data.navbar.bgColor" :isBack="true" />
|
||||
|
||||
<image :src="data.code" mode="widthFix" style="width: 100vw;" @click="previewImage"></image>
|
||||
<view class="button-container">
|
||||
<view class="footer-box">
|
||||
<view class="btn" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}" v-for="(item, index) in data.typeList" :key="index" :class="{ active: data.type == index }"
|
||||
@click="setType(index)">
|
||||
样式{{index+1}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="button-container" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}">
|
||||
<button class="btn-save-image" @click="saveImage">保存图片</button>
|
||||
</view>
|
||||
<l-painter isCanvasToTempFilePath @success="data.code = $event" hidden
|
||||
:css="`width:${data.width}px;height:${data.width / 4 * 3}px;`">
|
||||
<l-painter isCanvasToTempFilePath @success="successImage" @progress="progress" hidden
|
||||
v-if="data.bgImage&&data.type==0" :css="`width:${data.width}px;height:${data.width / 4 * 3}px;`">
|
||||
<l-painter-view
|
||||
:css="`position: relative;width:${data.width}px;height:${data.width / 4 * 3}px;background-image: url('/static/image/other/gzd.png');`">
|
||||
:css="`position: relative;width:${data.width}px;height:${data.width / 4 * 3}px;background-image: url('${data.bgImage}');`">
|
||||
<!-- 头部年月 -->
|
||||
<l-painter-view :css="`position: absolute;left:480px;top:336px;`">
|
||||
<l-painter-text :css="data.textCssTime" :text="data.form.year" />
|
||||
|
|
@ -76,6 +81,123 @@
|
|||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
<l-painter isCanvasToTempFilePath @success="successImage" @progress="progress" hidden v-else-if="data.type==1"
|
||||
:css="`width:375px;height:1150px;`">
|
||||
<l-painter-view :css="`position: relative;width:375px;height:1150px;background-color:#F6F8FA;`">
|
||||
<!-- 头部 -->
|
||||
<l-painter-view
|
||||
css="background-color:#EFEFEF;height:44px;display:flex;justify-content: space-between;align-items: center;padding:0 12px;">
|
||||
<l-painter-image src="/static/image/close.png" css="width: 24px; height: 24px;" />
|
||||
<l-painter-text text="工资条详情" />
|
||||
<l-painter-image src="/static/image/more.png" css="width: 24px; height: 24px;" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="padding:12px 18px;">
|
||||
<l-painter-view css="background-color:#FFFFFF;padding:12px;border-radius: 6px 6px 6px 6px;">
|
||||
<l-painter-view css="display: flex; flex-direction: column;align-items: center;margin-top:23px;">
|
||||
<l-painter-text css="font-size:24px;color:#373737;font-weight: bold;" :text="formatMoney(data.form.money11)" />
|
||||
<l-painter-text css="font-size:12px;color:#767676;" text="实发工资" />
|
||||
<l-painter-image src="/static/image/other/salary/dashed.png"
|
||||
css="margin-top:24px;width:100%; height: 2px;" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:12px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="姓名" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.name + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="任职部门" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.department + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="职务" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.work + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="专员薪酬标准" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.salaryStandard + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="应出勤天数" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.shouldWorkDays + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="事假" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.personalLeave + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="病假" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.sickLeave + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="实出勤天数" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.actualWorkDays + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="补贴" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.subsidy + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="绩效" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.performance + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="应发合计" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.money5 + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="个人社保代扣" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.money6 + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="个人公积金代扣" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.housingFund + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="个人所得税代扣" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.money7 + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="应扣事假" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.deductPersonalLeave + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="应扣病假" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.deductSickLeave + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="其他扣款" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.money9 + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="应扣合计" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.money10 + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="实发工资" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.money11 + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="display:flex;justify-content: space-between;padding:0 24px;margin-top:22px;">
|
||||
<l-painter-text css="font-size:14px;color:#373737;" text="备注" />
|
||||
<l-painter-text css="font-size:14px;color:#373737;" :text="data.form.remark + ''" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="margin-top:24px;">
|
||||
<l-painter-image src="/static/image/other/salary/dashed.png" css="width:100%; height: 2px;" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="margin-top:60px;display:flex;justify-content: space-between;align-items: center;">
|
||||
|
||||
<l-painter-view css="width: 143px;height: 38px;border-radius: 4px 4px 4px 4px;border: 1px solid #3B9BDF;background-color:#3B9BDF;display:flex;justify-content: center;align-items: center;">
|
||||
<l-painter-text css="font-size:14px;color:#ffffff;" text="签名确认" />
|
||||
</l-painter-view>
|
||||
<l-painter-view css="width: 143px;height: 38px;border-radius: 4px 4px 4px 4px;border: 1px solid #3B9BDF;display:flex;justify-content: center;align-items: center;">
|
||||
<l-painter-text css="font-size:14px;color:#3B9BDF;" text="对工资有疑问" />
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
<l-painter-view v-if="$isVip()" :css="`position: absolute;right:20px;bottom:20px;`">
|
||||
<l-painter-image src="/static/image/other/shuiying.png" css="width: 170rpx; height: 50rpx;" />
|
||||
</l-painter-view>
|
||||
</l-painter-view>
|
||||
</l-painter>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<view v-if="showEditPopup" class="popup-overlay">
|
||||
|
|
@ -85,6 +207,8 @@
|
|||
<text class="popup-close" @click="closeEditPopup">×</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<!-- 样式1编辑表单 -->
|
||||
<template v-if="data.type == 0">
|
||||
<view class="form-row">
|
||||
<text class="form-label">岗位:</text>
|
||||
<input class="form-input" v-model="editForm.work" type="text" />
|
||||
|
|
@ -104,28 +228,23 @@
|
|||
<text class="section-title">收入部分</text>
|
||||
<view class="form-row">
|
||||
<text class="form-label">基本工资:</text>
|
||||
<input class="form-input" v-model.number="editForm.money1" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money1" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">绩效工资:</text>
|
||||
<input class="form-input" v-model.number="editForm.money2" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money2" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">全勤工资:</text>
|
||||
<input class="form-input" v-model.number="editForm.money3" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money3" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">其他奖金:</text>
|
||||
<input class="form-input" v-model.number="editForm.money4" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money4" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row form-total">
|
||||
<text class="form-label">合计:</text>
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money5" type="number"
|
||||
disabled />
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money5" type="number" disabled />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -133,36 +252,124 @@
|
|||
<text class="section-title">扣款部分</text>
|
||||
<view class="form-row">
|
||||
<text class="form-label">社保缴纳:</text>
|
||||
<input class="form-input" v-model.number="editForm.money6" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money6" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">个税缴纳:</text>
|
||||
<input class="form-input" v-model.number="editForm.money7" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money7" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">考勤扣款:</text>
|
||||
<input class="form-input" v-model.number="editForm.money8" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money8" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">其他扣款:</text>
|
||||
<input class="form-input" v-model.number="editForm.money9" type="number"
|
||||
@input="calculateValues" />
|
||||
<input class="form-input" v-model.number="editForm.money9" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row form-total">
|
||||
<text class="form-label">合计:</text>
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money10" type="number"
|
||||
disabled />
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money10" type="number" disabled />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-row form-total">
|
||||
<text class="form-label">实发工资:</text>
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money11" type="number"
|
||||
disabled />
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money11" type="number" disabled />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 样式2编辑表单 -->
|
||||
<template v-else>
|
||||
<view class="form-row">
|
||||
<text class="form-label">姓名:</text>
|
||||
<input class="form-input" v-model="editForm.name" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">任职部门:</text>
|
||||
<input class="form-input" v-model="editForm.department" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">职务:</text>
|
||||
<input class="form-input" v-model="editForm.work" type="text" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">专员薪酬标准:</text>
|
||||
<input class="form-input" v-model.number="editForm.salaryStandard" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">应出勤天数:</text>
|
||||
<input class="form-input" v-model.number="editForm.shouldWorkDays" type="number" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">事假:</text>
|
||||
<input class="form-input" v-model.number="editForm.personalLeave" type="number" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">病假:</text>
|
||||
<input class="form-input" v-model.number="editForm.sickLeave" type="number" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">实出勤天数:</text>
|
||||
<input class="form-input" v-model.number="editForm.actualWorkDays" type="number" />
|
||||
</view>
|
||||
|
||||
<view class="form-section">
|
||||
<text class="section-title">收入部分</text>
|
||||
<view class="form-row">
|
||||
<text class="form-label">补贴:</text>
|
||||
<input class="form-input" v-model.number="editForm.subsidy" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">绩效:</text>
|
||||
<input class="form-input" v-model.number="editForm.performance" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row form-total">
|
||||
<text class="form-label">应发合计:</text>
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money5" type="number" disabled />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-section">
|
||||
<text class="section-title">扣款部分</text>
|
||||
<view class="form-row">
|
||||
<text class="form-label">个人社保代扣:</text>
|
||||
<input class="form-input" v-model.number="editForm.money6" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">个人公积金代扣:</text>
|
||||
<input class="form-input" v-model.number="editForm.housingFund" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">个人所得税代扣:</text>
|
||||
<input class="form-input" v-model.number="editForm.money7" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">应扣事假:</text>
|
||||
<input class="form-input" v-model.number="editForm.deductPersonalLeave" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">应扣病假:</text>
|
||||
<input class="form-input" v-model.number="editForm.deductSickLeave" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">其他扣款:</text>
|
||||
<input class="form-input" v-model.number="editForm.money9" type="number" @input="calculateValues" />
|
||||
</view>
|
||||
<view class="form-row form-total">
|
||||
<text class="form-label">应扣合计:</text>
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money10" type="number" disabled />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-row form-total">
|
||||
<text class="form-label">实发工资:</text>
|
||||
<input class="form-input form-total-input" v-model.number="editForm.money11" type="number" disabled />
|
||||
</view>
|
||||
<view class="form-row">
|
||||
<text class="form-label">备注:</text>
|
||||
<input class="form-input" v-model="editForm.remark" type="text" />
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<button class="btn-cancel" @click="closeEditPopup">取消</button>
|
||||
|
|
@ -170,40 +377,43 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_gongzhitiao')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
// 自定义头部
|
||||
import ZdyNavbar from "@/components/nav-bar/nav-bar.vue"
|
||||
|
||||
import {
|
||||
// 自定义头部
|
||||
import ZdyNavbar from "@/components/nav-bar/nav-bar.vue"
|
||||
import {
|
||||
imgLocal
|
||||
} from '@/utils/common.js';
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
watch,
|
||||
nextTick,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import {
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onShow,
|
||||
onReady,
|
||||
onPullDownRefresh,
|
||||
onReachBottom
|
||||
} from "@dcloudio/uni-app";
|
||||
const {
|
||||
} from "@dcloudio/uni-app";
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const data = reactive({
|
||||
navbar: {
|
||||
title: "工资条",
|
||||
bgColor: '#EDEDED',
|
||||
},
|
||||
width: 375,
|
||||
height: 495,
|
||||
code: '',
|
||||
form: {
|
||||
} = getCurrentInstance();
|
||||
|
||||
function defaultForm(type) {
|
||||
const forms = {
|
||||
0: {
|
||||
work: "销售",
|
||||
name: '小明',
|
||||
money1: 5000,
|
||||
|
|
@ -220,65 +430,139 @@ const data = reactive({
|
|||
year: 2026,
|
||||
month: 1,
|
||||
},
|
||||
1: {
|
||||
name: '校长',
|
||||
department: '市场推广部',
|
||||
work: '推广专员',
|
||||
salaryStandard: 7500,
|
||||
shouldWorkDays: 22,
|
||||
personalLeave: 0,
|
||||
sickLeave: 0,
|
||||
actualWorkDays: 22,
|
||||
subsidy: 500,
|
||||
performance: 1000,
|
||||
money5: 9000,
|
||||
money6: 512,
|
||||
housingFund: 300,
|
||||
money7: 120,
|
||||
deductPersonalLeave: 0,
|
||||
deductSickLeave: 0,
|
||||
money9: 0,
|
||||
money10: 932,
|
||||
money11: 8068,
|
||||
remark: '餐饮饭卡补贴200元',
|
||||
}
|
||||
}
|
||||
|
||||
return forms[type] || forms[0]
|
||||
}
|
||||
|
||||
function mergeForm(raw, type) {
|
||||
return Object.assign(defaultForm(type), raw && typeof raw === 'object' ? raw : {})
|
||||
}
|
||||
|
||||
function formatMoney(val) {
|
||||
const num = Number(val) || 0
|
||||
return '¥' + num.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
||||
}
|
||||
const data = reactive({
|
||||
navbar: {
|
||||
title: "工资条",
|
||||
bgColor: '#EDEDED',
|
||||
},
|
||||
type: 0,
|
||||
bgImage: '',
|
||||
width: 375,
|
||||
height: 495,
|
||||
code: '',
|
||||
form: mergeForm(null, 0),
|
||||
textCss: ' letter-spacing: 10px;font-family: "SimHei", "Microsoft YaHei", sans-serif;width:50px;text-align: center;color:#505156;transform: scale(0.4);font-size:26rpx;font-weight: bold; mix-blend-mode: overlay;',
|
||||
textCssMoney: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:50px;text-align: center;color:#505156;transform: scale(0.4);font-size:12px;font-weight: bold; mix-blend-mode: overlay;',
|
||||
textCssTime: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:50px;text-align: center;color:#505156;transform: scale(0.4);font-size:18px;font-weight: bold; mix-blend-mode: overlay;'
|
||||
})
|
||||
textCssTime: 'font-family: "SimHei", "Microsoft YaHei", sans-serif;width:50px;text-align: center;color:#505156;transform: scale(0.4);font-size:18px;font-weight: bold; mix-blend-mode: overlay;',
|
||||
typeList: ['样式1', '样式2']
|
||||
})
|
||||
|
||||
// 弹窗相关
|
||||
const showEditPopup = ref(false);
|
||||
const editForm = ref({});
|
||||
// 弹窗相关
|
||||
const showEditPopup = ref(false);
|
||||
const editForm = ref({});
|
||||
|
||||
// 打开编辑弹窗
|
||||
function edit() {
|
||||
console.log(data.form)
|
||||
// 复制当前表单数据到编辑表单
|
||||
editForm.value = JSON.parse(JSON.stringify(data.form));
|
||||
// 计算初始值
|
||||
calculateValues();
|
||||
// 显示弹窗
|
||||
showEditPopup.value = true;
|
||||
}
|
||||
function setType(index) {
|
||||
uni.setStorageSync("salary" + data.type, data.form)
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
data.type = index
|
||||
data.form = mergeForm(uni.getStorageSync("salary" + data.type), data.type)
|
||||
}
|
||||
//
|
||||
function successImage(e) {
|
||||
data.code = e
|
||||
}
|
||||
|
||||
// 关闭编辑弹窗
|
||||
function closeEditPopup() {
|
||||
function progress(e) {
|
||||
if (e < 0.03) {
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
}
|
||||
if (e == 1) {
|
||||
uni.hideLoading()
|
||||
}
|
||||
// console.log(e)
|
||||
}
|
||||
// 打开编辑弹窗
|
||||
function edit() {
|
||||
editForm.value = mergeForm(JSON.parse(JSON.stringify(data.form)), data.type)
|
||||
calculateValues()
|
||||
showEditPopup.value = true
|
||||
}
|
||||
|
||||
// 关闭编辑弹窗
|
||||
function closeEditPopup() {
|
||||
showEditPopup.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 保存编辑表单
|
||||
function saveEditForm() {
|
||||
// 将编辑后的数据复制回原始表单
|
||||
data.form = JSON.parse(JSON.stringify(editForm.value));
|
||||
// 关闭弹窗
|
||||
showEditPopup.value = false;
|
||||
}
|
||||
// 保存编辑表单
|
||||
function saveEditForm() {
|
||||
calculateValues()
|
||||
uni.showLoading({
|
||||
title: "生成中"
|
||||
})
|
||||
data.form = mergeForm(editForm.value, data.type)
|
||||
uni.setStorageSync("salary" + data.type, data.form)
|
||||
showEditPopup.value = false
|
||||
}
|
||||
|
||||
// 计算值
|
||||
function calculateValues() {
|
||||
// 计算收入合计 (money5 = money1 + money2 + money3 + money4)
|
||||
// 计算值
|
||||
function calculateValues() {
|
||||
if (data.type === 0) {
|
||||
editForm.value.money5 = (editForm.value.money1 || 0) + (editForm.value.money2 || 0) + (editForm.value.money3 ||
|
||||
0) + (editForm.value.money4 || 0);
|
||||
|
||||
// 计算扣款合计 (money10 = money6 + money7 + money8 + money9)
|
||||
0) + (editForm.value.money4 || 0)
|
||||
editForm.value.money10 = (editForm.value.money6 || 0) + (editForm.value.money7 || 0) + (editForm.value.money8 ||
|
||||
0) + (editForm.value.money9 || 0);
|
||||
0) + (editForm.value.money9 || 0)
|
||||
editForm.value.money11 = editForm.value.money5 - editForm.value.money10
|
||||
} else {
|
||||
editForm.value.money5 = (editForm.value.salaryStandard || 0) + (editForm.value.subsidy || 0) + (editForm.value
|
||||
.performance || 0)
|
||||
editForm.value.money10 = (editForm.value.money6 || 0) + (editForm.value.housingFund || 0) + (editForm.value
|
||||
.money7 || 0) + (editForm.value.deductPersonalLeave || 0) + (editForm.value.deductSickLeave || 0) + (
|
||||
editForm.value.money9 || 0)
|
||||
editForm.value.money11 = editForm.value.money5 - editForm.value.money10
|
||||
}
|
||||
}
|
||||
|
||||
// 计算实发工资 (money11 = money5 - money10)
|
||||
editForm.value.money11 = editForm.value.money5 - editForm.value.money10;
|
||||
}
|
||||
|
||||
// 预览图片
|
||||
function previewImage() {
|
||||
// 预览图片
|
||||
function previewImage() {
|
||||
if (data.code) {
|
||||
uni.previewImage({
|
||||
urls: [data.code],
|
||||
current: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存图片
|
||||
function saveImage() {
|
||||
// 保存图片
|
||||
function saveImage() {
|
||||
if (data.code) {
|
||||
console.log(data.code)
|
||||
uni.showLoading({
|
||||
|
|
@ -414,9 +698,9 @@ function saveImage() {
|
|||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onLoad((option) => {
|
||||
onLoad(async (option) => {
|
||||
// 进入工资单页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
|
|
@ -424,36 +708,39 @@ onLoad((option) => {
|
|||
prefix: '.uni.other.',
|
||||
value: "工资单"
|
||||
})
|
||||
})
|
||||
onReady(() => {
|
||||
|
||||
})
|
||||
onShow(() => { })
|
||||
onPullDownRefresh(() => {
|
||||
data.bgImage = await imgLocal.getLocalImage('other/gzd.png');
|
||||
data.form = mergeForm(uni.getStorageSync("salary" + data.type), data.type)
|
||||
})
|
||||
onReady(() => {
|
||||
|
||||
})
|
||||
onShow(() => {})
|
||||
onPullDownRefresh(() => {
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
}, 1000);
|
||||
})
|
||||
onReachBottom(() => {
|
||||
})
|
||||
onReachBottom(() => {
|
||||
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
* {
|
||||
* {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
}
|
||||
|
||||
.aadadad {
|
||||
.aadadad {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.heiti {
|
||||
.heiti {
|
||||
font-family: "SimHei", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
.popup-overlay {
|
||||
/* 弹窗样式 */
|
||||
.popup-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
|
@ -464,129 +751,139 @@ onReachBottom(() => {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
.popup-content {
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 80vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
.popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-close {
|
||||
.popup-close {
|
||||
font-size: 48rpx;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
.popup-body {
|
||||
padding: 20rpx;
|
||||
}
|
||||
height:60vh;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
.form-section {
|
||||
margin-bottom: 30rpx;
|
||||
padding: 20rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
.section-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.form-row {
|
||||
.form-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-label {
|
||||
.form-label {
|
||||
width: 200rpx;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.form-input {
|
||||
.form-input {
|
||||
flex: 1;
|
||||
padding: 15rpx;
|
||||
border: 1rpx solid #ddd;
|
||||
border-radius: 4rpx;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.form-separator {
|
||||
.form-separator {
|
||||
margin: 0 10rpx;
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
|
||||
.form-total {
|
||||
.form-total {
|
||||
margin-top: 10rpx;
|
||||
padding-top: 10rpx;
|
||||
border-top: 1rpx dashed #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.form-total-input {
|
||||
.form-total-input {
|
||||
background-color: #f9f9f9;
|
||||
color: #ff6b35;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-footer {
|
||||
.popup-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 20rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-cancel,
|
||||
.btn-save {
|
||||
width: 48%;
|
||||
.btn-cancel,
|
||||
.btn-save {
|
||||
width: calc(48% - 40rpx);
|
||||
padding: 20rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
.btn-cancel {
|
||||
background-color: #f5f5f5;
|
||||
color: #333;
|
||||
border: 1rpx solid #ddd;
|
||||
}
|
||||
// border: 1rpx solid #ddd;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
background-color: #ff6b35;
|
||||
.btn-save {
|
||||
background-color: #187AFF;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* 保存图片按钮 */
|
||||
.button-container {
|
||||
}
|
||||
|
||||
/* 保存图片按钮 */
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 86px;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
|
||||
padding-bottom: env(safe-area-inset-bottom); // 兼容 IOS>11.2
|
||||
}
|
||||
|
||||
.btn-save-image {
|
||||
.btn-save-image {
|
||||
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
|
||||
color: #fff;
|
||||
border: none;
|
||||
|
|
@ -598,15 +895,46 @@ onReachBottom(() => {
|
|||
transition: all 0.3s ease;
|
||||
text-align: center;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-save-image:hover {
|
||||
.btn-save-image:hover {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 4rpx 12rpx rgba(7, 72, 193, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
.btn-save-image:active {
|
||||
.btn-save-image:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2rpx 6rpx rgba(7, 140, 193, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 16px;
|
||||
width: 100vw;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-bottom: constant(safe-area-inset-bottom); // 兼容 IOS<11.2
|
||||
padding-bottom: env(safe-area-inset-bottom); // 兼容 IOS>11.2
|
||||
|
||||
.btn {
|
||||
font-size: 18px;
|
||||
color: #767676;
|
||||
width: 180rpx;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 8px 8px 8px 8px;
|
||||
background: #FFFFFF;
|
||||
text-align: center;
|
||||
margin: 0 24rpx;
|
||||
border: 2px solid #FFFFFF;
|
||||
color: #767676;
|
||||
}
|
||||
|
||||
.active {
|
||||
color: #1777FF;
|
||||
border: 2px solid #1777FF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<NavBar title="选择机票" bgColor="#F0F4F9" isBack></NavBar>
|
||||
<NavBar :title="`选择${type == 'airTicket' ? '机票' : '火车票'}`" bgColor="#F0F4F9" isBack></NavBar>
|
||||
|
||||
<view class="content">
|
||||
<view class="app-card" v-for="(item, index) in appList" :key="index" @click="handleItemClick(item)">
|
||||
<template v-for="(item, index) in appList" :key="index">
|
||||
<view class="app-card"
|
||||
v-if="(type == 'airTicket' && item.airPath) || (type == 'trainTicket' && item.trainPath)"
|
||||
@click="handleItemClick(item)">
|
||||
<!-- Background Watermark -->
|
||||
<image class="watermark" :src="item.bgImage" mode="heightFix"></image>
|
||||
|
||||
|
|
@ -22,52 +25,79 @@
|
|||
|
||||
<uni-icons type="right" size="18" color="#CCCCCC"></uni-icons>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
import { reactive, toRefs, getCurrentInstance } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import { util } from '@/utils/common.js'; // Assuming util exists for navigation, similar to previous tasks
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
getCurrentInstance,
|
||||
ref
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app';
|
||||
import {
|
||||
util
|
||||
} from '@/utils/common.js'; // Assuming util exists for navigation, similar to previous tasks
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
let type = ref('airTicket')
|
||||
|
||||
const appList = [
|
||||
{
|
||||
name: '携程APP',
|
||||
logo: '/static/image/other/tickets-app/trip-com-logo.png',
|
||||
bgImage: '/static/image/other/tickets-app/trip-com-bg.png',
|
||||
airPath: '/pages/other/air-tickets/ctrip-air-tickets/ctrip-air-tickets',
|
||||
trainPath: "/pages/other/train-tickets/ctrip-train-tickets/ctrip-train-tickets",
|
||||
isHot: false
|
||||
},
|
||||
{
|
||||
name: '铁路12306',
|
||||
logo: '/static/image/other/tickets-app/12306-logo.png',
|
||||
bgImage: '/static/image/other/tickets-app/12306-bg.png',
|
||||
airPath: '',
|
||||
trainPath: "/pages/other/train-tickets/12306-tickets/12306-tickets",
|
||||
isHot: false
|
||||
}, {
|
||||
name: '去哪儿APP',
|
||||
logo: '/static/image/other/tickets-app/qvnar-logo.png',
|
||||
bgImage: '/static/image/other/tickets-app/qvnar-bg.png',
|
||||
path: '/pages/other/air-tickets/qunar-air-tickets/qunar-air-tickets',
|
||||
airPath: '/pages/other/air-tickets/qunar-air-tickets/qunar-air-tickets',
|
||||
trainPath: "/pages/other/train-tickets/qunar-train-tickets/qunar-train-tickets",
|
||||
isHot: false
|
||||
},
|
||||
{
|
||||
name: '飞猪APP',
|
||||
logo: '/static/image/other/tickets-app/fliggy-logo.png',
|
||||
bgImage: '/static/image/other/tickets-app/fliggy-bg.png',
|
||||
path: '/pages/other/air-tickets/fliggy-air-tickets/fliggy-air-tickets',
|
||||
airPath: '/pages/other/air-tickets/fliggy-air-tickets/fliggy-air-tickets',
|
||||
trainPath: "/pages/other/train-tickets/fliggy-train-tickets/fliggy-train-tickets",
|
||||
isHot: true
|
||||
},
|
||||
{
|
||||
name: '携程APP',
|
||||
logo: '/static/image/other/tickets-app/trip-com-logo.png',
|
||||
bgImage: '/static/image/other/tickets-app/trip-com-bg.png',
|
||||
path: '/pages/other/air-tickets/ctrip-air-tickets/ctrip-air-tickets',
|
||||
isHot: false
|
||||
},
|
||||
// {
|
||||
// name: '铁路12306',
|
||||
// logo: '/static/image/other/tickets-app/12306-logo.png',
|
||||
// bgImage: '/static/image/other/tickets-app/12306-bg.png',
|
||||
// path: '/pages/other/train-tickets/12306-tickets/12306-tickets',
|
||||
// isHot: false
|
||||
// }
|
||||
]
|
||||
|
||||
onLoad((option) => {
|
||||
const appType = option.type
|
||||
if (appType == "trainTicket") {
|
||||
type.value = "trainTicket"
|
||||
// 进入高铁票页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'train_ticket',
|
||||
prefix: '.uni.other.',
|
||||
value: "高铁票"
|
||||
})
|
||||
} else {
|
||||
type.value = "airTicket"
|
||||
// 进入机票页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
|
|
@ -75,19 +105,36 @@ onLoad((option) => {
|
|||
prefix: '.uni.other.',
|
||||
value: "机票"
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* 跳转火车票/飞机票页面
|
||||
*/
|
||||
const handleItemClick = (item) => {
|
||||
if (item.path) {
|
||||
util.goPage(item.path)
|
||||
if (type.value == 'trainTicket') {
|
||||
if (item.trainPath && item.trainPath != "开发中") {
|
||||
util.goPage(item.trainPath)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item.airPath) {
|
||||
util.goPage(item.airPath)
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '开发中',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark dark="light" source="uni_alipay_other_tickets_12306" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_tickets_12306')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container">
|
||||
|
|
@ -24,8 +24,8 @@
|
|||
<view class="order-info-box">
|
||||
<view class="order-number-row">
|
||||
<text class="order-label">订单号:{{ ticketsInfo.orderInfo.orderNo }}</text>
|
||||
<image class="copy-btn" @click="copyOrderNo"
|
||||
src="/static/image/other/train-tickets/12306-tickets/copy-button.png"></image>
|
||||
<image class="copy-btn" src="/static/image/other/train-tickets/12306-tickets/copy-button.png">
|
||||
</image>
|
||||
</view>
|
||||
<text class="order-time">下单时间:{{ ticketsInfo.orderInfo.orderTime }}</text>
|
||||
</view>
|
||||
|
|
@ -144,8 +144,7 @@
|
|||
<!-- 分享区 -->
|
||||
<view class="share-section">
|
||||
<text class="share-tips">美好旅途,快与朋友一起分享吧~</text>
|
||||
<image style="width: 158rpx;height: 50rpx;"
|
||||
src="/static/image/other/train-tickets/12306-tickets/share.png">
|
||||
<image style="width: 158rpx;height: 50rpx;" src="/static/image/other/train-tickets/12306-tickets/share.png">
|
||||
</image>
|
||||
</view>
|
||||
|
||||
|
|
@ -157,11 +156,9 @@
|
|||
|
||||
<!-- 广告Banner -->
|
||||
<view class="ad-banner">
|
||||
<image class="bg-image" src="/static/image/other/train-tickets/12306-tickets/hotel-bg.png"
|
||||
mode="widthFix">
|
||||
<image class="bg-image" src="/static/image/other/train-tickets/12306-tickets/hotel-bg.png" mode="widthFix">
|
||||
</image>
|
||||
<image class="bg-image" style="opacity: 0;position: relative;"
|
||||
src="/static/image/other/train-tickets/12306-tickets/hotel-bg.png" mode="widthFix">
|
||||
<image class="bg-image" style="opacity: 0;position: relative;" src="/static/image/other/train-tickets/12306-tickets/hotel-bg.png" mode="widthFix">
|
||||
</image>
|
||||
<view class="hotel-ad">
|
||||
<view class="hotel-search-row">
|
||||
|
|
@ -190,6 +187,7 @@
|
|||
src="/static/image/other/train-tickets/12306-tickets/bottom-bg.png" mode="widthFix">
|
||||
</image>
|
||||
</view>
|
||||
<ZdySafeBottom bgColor="#fff"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
|
@ -197,12 +195,13 @@
|
|||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
toRefs,
|
||||
computed,
|
||||
getCurrentInstance
|
||||
computed
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad,
|
||||
|
|
@ -210,11 +209,6 @@ import {
|
|||
} from '@dcloudio/uni-app';
|
||||
|
||||
import { util } from '@/utils/common.js';
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
const buttonGroup = [{
|
||||
name: "编辑车票信息",
|
||||
click: () => {
|
||||
|
|
@ -226,24 +220,7 @@ function goEdit() {
|
|||
util.goPage('/pages/other/train-tickets/edit/edit')
|
||||
}
|
||||
|
||||
const ticketType = [
|
||||
{
|
||||
label: '成人票',
|
||||
value: '1'
|
||||
},
|
||||
{
|
||||
label: '儿童票',
|
||||
value: '2'
|
||||
},
|
||||
{
|
||||
label: '学生票',
|
||||
value: '3'
|
||||
},
|
||||
{
|
||||
label: '残疾军人票',
|
||||
value: '4'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const statusBarHeight = ref(20);
|
||||
const data = reactive({
|
||||
|
|
@ -364,14 +341,6 @@ const calculateNightCount = () => {
|
|||
onLoad(() => {
|
||||
const sys = uni.getSystemInfoSync();
|
||||
statusBarHeight.value = sys.statusBarHeight || 20;
|
||||
|
||||
// 进入高铁票页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'train_ticket',
|
||||
prefix: '.uni.other.',
|
||||
value: "高铁票"
|
||||
})
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
|
|
@ -379,7 +348,7 @@ onShow(() => {
|
|||
Object.assign(data.ticketsInfo, uni.getStorageSync('ticketsInfo'))
|
||||
calculateNightCount()
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("light");
|
||||
|
|
@ -393,22 +362,6 @@ onShow(() => {
|
|||
}
|
||||
});
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const copyOrderNo = () => {
|
||||
uni.setClipboardData({
|
||||
data: orderInfo.value.orderNo,
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: '复制成功',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleAction = (action) => {
|
||||
uni.showToast({
|
||||
title: `点击了${action}`,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -14,13 +14,21 @@
|
|||
<text class="label">订单号</text>
|
||||
<input class="input" v-model="ticketsInfo.orderInfo.orderNo" />
|
||||
</view>
|
||||
<picker mode="date" fields="day" :value="getPickerDate(ticketsInfo.orderInfo.orderTime)"
|
||||
@change="onOrderTimeChange">
|
||||
<picker v-if="app == '12306'" mode="date" fields="day"
|
||||
:value="getPickerDate(ticketsInfo.orderInfo.orderTime)" @change="onOrderTimeChange">
|
||||
<view class="form-item">
|
||||
<text class="label">下单时间</text>
|
||||
<view class="input">{{ ticketsInfo.orderInfo.orderTime }}</view>
|
||||
</view>
|
||||
</picker>
|
||||
<view v-if="app != '12306' && app != 'fliggy'" class="form-item">
|
||||
<text class="label">订单总价</text>
|
||||
<input class="input" type="number" v-model="ticketsInfo.orderInfo.price" />
|
||||
</view>
|
||||
<view v-if="app == 'fliggy'" class="form-item">
|
||||
<text class="label">已购服务</text>
|
||||
<input class="input" v-model="ticketsInfo.serviceText" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -71,10 +79,18 @@
|
|||
<view class="input">{{ ticketsInfo.ticketInfo.arrivalTime }}</view>
|
||||
</view>
|
||||
</picker>
|
||||
<!-- <view class="form-item">
|
||||
<view class="form-item">
|
||||
<text class="label">历时</text>
|
||||
<input class="input" v-model="ticketsInfo.ticketInfo.duration" disabled />
|
||||
</view> -->
|
||||
<input class="input" v-model="ticketsInfo.ticketInfo.duration" />
|
||||
</view>
|
||||
<view v-if="app == 'ctrip'" class="form-item">
|
||||
<text class="label">火车名称</text>
|
||||
<input class="input" v-model="ticketsInfo.ticketInfo.trainName" />
|
||||
</view>
|
||||
<view v-if="app == 'fliggy'" class="form-item">
|
||||
<text class="label">车票状态</text>
|
||||
<input class="input" v-model="ticketsInfo.ticketInfo.status" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -95,7 +111,8 @@
|
|||
<text class="label">姓名</text>
|
||||
<input class="input" v-model="passenger.name" />
|
||||
</view>
|
||||
<picker :range="ticketType" range-key="label" @change="(e) => onTicketTypeChange(e, index)">
|
||||
<picker v-if="app != 'fliggy'" :range="ticketType" range-key="label"
|
||||
@change="(e) => onTicketTypeChange(e, index)">
|
||||
<view class="form-item" style="border-bottom: 1rpx solid #F5F5F5;">
|
||||
<text class="label">票种</text>
|
||||
<view class="input">{{ passenger.type }}</view>
|
||||
|
|
@ -116,13 +133,21 @@
|
|||
|
||||
<view class="form-item">
|
||||
<text class="label">票价</text>
|
||||
<input class="input" v-model="passenger.price" />
|
||||
<input class="input" type="number" v-model="passenger.price" @input="onPriceInput" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view v-if="app == 'ctrip'" class="form-item">
|
||||
<text class="label">积分</text>
|
||||
<input class="input" type="number" v-model="passenger.points" />
|
||||
</view>
|
||||
<view v-if="app != 'ctrip'" class="form-item">
|
||||
<text class="label">证件类型</text>
|
||||
<input class="input" v-model="passenger.idType" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view v-if="app != 'ctrip'" class="form-item">
|
||||
<text class="label">证件号</text>
|
||||
<input class="input" v-model="passenger.idNumber" />
|
||||
</view>
|
||||
<view v-if="app != 'qunar'" class="form-item">
|
||||
<text class="label">是否本人</text>
|
||||
<switch :checked="passenger.isMe" @change="(e) => passenger.isMe = e.detail.value" />
|
||||
</view>
|
||||
|
|
@ -136,16 +161,20 @@
|
|||
</view>
|
||||
|
||||
<!-- 酒店广告 -->
|
||||
<view class="section-container">
|
||||
<view v-if="app == '12306' || app == 'ctrip'" class="section-container">
|
||||
<view class="section-header" @click="toggleSection('hotelInfo')">
|
||||
<text class="section-title">酒店广告</text>
|
||||
<text class="section-title">{{ app == '12306' ? '酒店广告' : '返现任务' }}</text>
|
||||
<uni-icons :type="collapsed.hotelInfo ? 'bottom' : 'top'" size="16" color="#666"></uni-icons>
|
||||
</view>
|
||||
<view class="card" v-show="!collapsed.hotelInfo">
|
||||
<view class="form-item">
|
||||
<view v-if="app == '12306'" class="form-item">
|
||||
<text class="label">城市</text>
|
||||
<input class="input" v-model="ticketsInfo.hotelInfo.city" />
|
||||
</view>
|
||||
<view v-if="app == 'ctrip'" class="form-item">
|
||||
<text class="label">返现金额</text>
|
||||
<input class="input" type="number" v-model="ticketsInfo.hotelInfo.cashback" />
|
||||
</view>
|
||||
<uni-datetime-picker type="daterange" v-model="hotelDateRange" :border="false">
|
||||
<view class="form-item">
|
||||
<text class="label">入住/离店日期</text>
|
||||
|
|
@ -163,12 +192,19 @@
|
|||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue'
|
||||
import { reactive, toRefs, onMounted, computed } from 'vue';
|
||||
import {
|
||||
reactive,
|
||||
toRefs,
|
||||
onMounted,
|
||||
computed
|
||||
} from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
|
||||
const defaultData = {
|
||||
"orderInfo": {
|
||||
"orderNo": "EJ66223536",
|
||||
"orderTime": "2026.01.01"
|
||||
"orderTime": "2026.01.01",
|
||||
"price": "4440"
|
||||
},
|
||||
"ticketInfo": {
|
||||
"departureTime": "01-01 09:19",
|
||||
|
|
@ -179,45 +215,47 @@ const defaultData = {
|
|||
"duration": "4时45分",
|
||||
"date": "2026.01.01",
|
||||
"weekDay": "星期四",
|
||||
"gate": "6B"
|
||||
"gate": "6B",
|
||||
"trainName": "复兴号"
|
||||
},
|
||||
"passengerList": [
|
||||
{
|
||||
"passengerList": [{
|
||||
"name": "张元英",
|
||||
"type": "成人票",
|
||||
"seatType": "商务座",
|
||||
"carriage": "01",
|
||||
"seatNo": "03C",
|
||||
"idType": "外国护照(KR)",
|
||||
"idNumber": "123456789012345678",
|
||||
"price": "2110",
|
||||
"status": "已支付",
|
||||
"isMe": true
|
||||
}
|
||||
],
|
||||
"isMe": true,
|
||||
"points": 9632
|
||||
}],
|
||||
"hotelInfo": {
|
||||
"city": "上海",
|
||||
"cashback": "25",
|
||||
"startDay": "01-01",
|
||||
"endDay": "01-02"
|
||||
}
|
||||
},
|
||||
serviceText: "多人连坐 ¥10x2份"
|
||||
}
|
||||
// 车票类型
|
||||
const ticketType = [
|
||||
{
|
||||
const ticketType = [{
|
||||
label: '成人票',
|
||||
value: '1'
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
label: '儿童票',
|
||||
value: '2'
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
label: '学生票',
|
||||
value: '3'
|
||||
},
|
||||
{
|
||||
},
|
||||
{
|
||||
label: '残疾军人票',
|
||||
value: '4'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
const data = reactive({
|
||||
|
|
@ -227,11 +265,28 @@ const data = reactive({
|
|||
ticketInfo: false, // Default open ticket info as it is most likely to be edited
|
||||
passengerList: false,
|
||||
hotelInfo: true
|
||||
}
|
||||
},
|
||||
app: '12306',
|
||||
STORAGE_KEY: 'ticketsInfo'
|
||||
})
|
||||
|
||||
let { app } = toRefs(data)
|
||||
|
||||
const { ticketsInfo, collapsed } = toRefs(data)
|
||||
|
||||
const {
|
||||
ticketsInfo,
|
||||
collapsed
|
||||
} = toRefs(data)
|
||||
|
||||
onLoad((options) => {
|
||||
console.log("options", options)
|
||||
if (options.app) {
|
||||
data.app = options.app
|
||||
}
|
||||
if (options.storageKey) {
|
||||
data.STORAGE_KEY = options.storageKey
|
||||
}
|
||||
})
|
||||
|
||||
const ticketYear = computed(() => {
|
||||
const dateStr = data.ticketsInfo.ticketInfo.date;
|
||||
|
|
@ -242,14 +297,17 @@ const ticketYear = computed(() => {
|
|||
})
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取酒店日期范围
|
||||
*/
|
||||
const hotelDateRange = computed({
|
||||
get() {
|
||||
const year = ticketYear.value;
|
||||
const start = data.ticketsInfo.hotelInfo.startDay ? `${year}-${data.ticketsInfo.hotelInfo.startDay}` : '';
|
||||
const end = data.ticketsInfo.hotelInfo.endDay ? `${year}-${data.ticketsInfo.hotelInfo.endDay}` : '';
|
||||
const start = data.ticketsInfo.hotelInfo.startDay ?
|
||||
`${year}-${data.ticketsInfo.hotelInfo.startDay}` : '';
|
||||
const end = data.ticketsInfo.hotelInfo.endDay ? `${year}-${data.ticketsInfo.hotelInfo.endDay}` :
|
||||
'';
|
||||
if (start && end) {
|
||||
return [start, end];
|
||||
}
|
||||
|
|
@ -264,12 +322,39 @@ const hotelDateRange = computed({
|
|||
})
|
||||
|
||||
onMounted(() => {
|
||||
const stored = uni.getStorageSync('ticketsInfo')
|
||||
const stored = uni.getStorageSync(data.STORAGE_KEY)
|
||||
if (stored) {
|
||||
Object.assign(data.ticketsInfo, stored)
|
||||
}
|
||||
|
||||
// 初始化时同步车票日期到出发时间
|
||||
const ticketDate = data.ticketsInfo.ticketInfo.date;
|
||||
if (ticketDate) {
|
||||
const parts = ticketDate.split('.');
|
||||
if (parts.length === 3) {
|
||||
const mmdd = `${parts[1]}-${parts[2]}`;
|
||||
const oldDepTime = data.ticketsInfo.ticketInfo.departureTime || '';
|
||||
const timePart = oldDepTime.split(' ')[1] || '00:00';
|
||||
data.ticketsInfo.ticketInfo.departureTime = `${mmdd} ${timePart}`;
|
||||
}
|
||||
}
|
||||
|
||||
updateDuration();
|
||||
})
|
||||
/**
|
||||
* 更新总价
|
||||
*/
|
||||
const onPriceInput = () => {
|
||||
setTimeout(() => {
|
||||
let total = 0;
|
||||
data.ticketsInfo.passengerList.forEach(item => {
|
||||
const price = Number(item.price) || 0;
|
||||
total += price;
|
||||
});
|
||||
data.ticketsInfo.orderInfo.price = total.toString();
|
||||
}, 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认
|
||||
*/
|
||||
|
|
@ -305,7 +390,7 @@ const handleRightButtonClick = () => {
|
|||
}
|
||||
}
|
||||
|
||||
uni.setStorageSync('ticketsInfo', data.ticketsInfo)
|
||||
uni.setStorageSync(data.STORAGE_KEY, data.ticketsInfo)
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
|
|
@ -327,7 +412,8 @@ const removePassenger = (index) => {
|
|||
content: '确定要删除该乘客吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
data.ticketsInfo.passengerList.splice(index, 1)
|
||||
data.ticketsInfo.passengerList.splice(index, 1);
|
||||
onPriceInput();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -347,9 +433,11 @@ const addPassenger = () => {
|
|||
idType: '中国居民身份证',
|
||||
price: oldPassenger.price || '0',
|
||||
status: '已支付',
|
||||
isMe: false
|
||||
isMe: false,
|
||||
points: oldPassenger.points || '2898',
|
||||
}
|
||||
data.ticketsInfo.passengerList.push(newPassenger)
|
||||
data.ticketsInfo.passengerList.push(newPassenger);
|
||||
onPriceInput();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -407,6 +495,15 @@ const onTicketDateChange = (e) => {
|
|||
const dateObj = new Date(val.replace(/-/g, '/')); // Compatible
|
||||
const days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
|
||||
data.ticketsInfo.ticketInfo.weekDay = days[dateObj.getDay()];
|
||||
|
||||
// 同步出发时间日期
|
||||
const parts = val.split('-');
|
||||
if (parts.length === 3) {
|
||||
const mmdd = `${parts[1]}-${parts[2]}`;
|
||||
const oldDepTime = data.ticketsInfo.ticketInfo.departureTime || '';
|
||||
const timePart = oldDepTime.split(' ')[1] || '00:00';
|
||||
data.ticketsInfo.ticketInfo.departureTime = `${mmdd} ${timePart}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -432,8 +529,12 @@ const departureTimeHHMM = computed(() => {
|
|||
* 获取出发时间选择器范围
|
||||
*/
|
||||
const departureTimeRange = computed(() => {
|
||||
const hours = Array.from({ length: 24 }, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
const minutes = Array.from({ length: 60 }, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
const hours = Array.from({
|
||||
length: 24
|
||||
}, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
const minutes = Array.from({
|
||||
length: 60
|
||||
}, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
return [hours, minutes];
|
||||
})
|
||||
|
||||
|
|
@ -470,8 +571,12 @@ const arrivalRange = computed(() => {
|
|||
} else {
|
||||
dates.push('MM-DD');
|
||||
}
|
||||
const hours = Array.from({ length: 24 }, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
const minutes = Array.from({ length: 60 }, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
const hours = Array.from({
|
||||
length: 24
|
||||
}, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
const minutes = Array.from({
|
||||
length: 60
|
||||
}, (_, i) => i < 10 ? '0' + i : '' + i);
|
||||
return [dates, hours, minutes];
|
||||
})
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,279 @@
|
|||
<template>
|
||||
<view class="box">
|
||||
<view class="codefun-flex-row codefun-justify-between codefun-items-center section_5 codefun-mt-8">
|
||||
<view class="codefun-flex-row codefun-items-center">
|
||||
<image class="codefun-shrink-0 image_11" src="/static/image/other/train-tickets/qunar/plan.png" />
|
||||
<text class="font_3 text_31 codefun-ml-4">抢票方案详情</text>
|
||||
</view>
|
||||
<image class="image_4 image_12" src="/static/image/other/train-tickets/qunar/right.png" />
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-items-center section_6 codefun-mt-8">
|
||||
<view class="codefun-flex-row codefun-flex-1">
|
||||
<image class="codefun-shrink-0 image_13" src="/static/image/other/train-tickets/qunar/child.png" />
|
||||
<view class="codefun-flex-col codefun-items-start codefun-flex-1 group_14 codefun-ml-10">
|
||||
<text class="font_9 text_32">免费携带儿童申报</text>
|
||||
<text class="font_5 text_34 codefun-mt-8">每名成人可免费携带1名6岁以下儿童</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="codefun-flex-col codefun-justify-start codefun-items-center codefun-shrink-0 text-wrapper_4 ml-15 codefun-justify-center">
|
||||
<text class="font_9 text_33">去申报</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-col codefun-justify-start section_7 codefun-mt-8">
|
||||
<view class="codefun-flex-col group_15">
|
||||
<text class="codefun-self-start text_35">专属服务</text>
|
||||
<view
|
||||
class="codefun-flex-row codefun-justify-between codefun-items-center codefun-self-stretch group_16">
|
||||
<view class="codefun-flex-row codefun-items-baseline">
|
||||
<text class="codefun-shrink-0 font_3 text_36">全能抢票套餐</text>
|
||||
<text class="font_19 codefun-ml-24">20元接送站代金券 x2份</text>
|
||||
</view>
|
||||
<image class="image_7" src="/static/image/other/train-tickets/qunar/right.png" />
|
||||
</view>
|
||||
<view v-for="(item, index) in services" :key="index"
|
||||
class="codefun-flex-row codefun-justify-between codefun-items-center codefun-self-end service-item-right">
|
||||
<text class="font_19">{{ item }}</text>
|
||||
<image class="image_7" src="/static/image/other/train-tickets/qunar/right.png" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-col section_8 codefun-mt-8">
|
||||
<text class="codefun-self-start font_12 text_41">你可能遇到的问题</text>
|
||||
<view class="codefun-flex-col codefun-self-stretch mt-25">
|
||||
<view v-for="(question, index) in questions" :key="index"
|
||||
class="codefun-flex-row codefun-justify-between codefun-items-center faq-item"
|
||||
:class="{ 'mt-34': index > 0 }">
|
||||
<view class="codefun-flex-row codefun-items-center codefun-flex-1">
|
||||
<view class="codefun-flex-col codefun-items-center indicator-wrap">
|
||||
<view class="codefun-shrink-0 section_9"></view>
|
||||
</view>
|
||||
<text class="font_3" style="margin-left: 14rpx;">{{ question.text }}</text>
|
||||
</view>
|
||||
<image class="image_7 faq-arrow" src="/static/image/other/train-tickets/qunar/right.png" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
|
||||
const services = ref([
|
||||
'腾讯视频vip月卡 x2份',
|
||||
'加速包 x2份',
|
||||
'24小时专人抢票 x2份'
|
||||
]);
|
||||
|
||||
const questions = ref([
|
||||
{ text: '为什么会退票失败' },
|
||||
{ text: '退款什么时候到账' },
|
||||
{ text: '已在车站或12306办理退票,退款何时到账' },
|
||||
{ text: '如何退票' }
|
||||
]);
|
||||
</script>
|
||||
<style>
|
||||
@import '/common/global.css';
|
||||
|
||||
page {
|
||||
background-color: #F2F5F9;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
.mt-25 {
|
||||
margin-top: 50rpx;
|
||||
}
|
||||
|
||||
.box {
|
||||
// padding: 0 16rpx;
|
||||
|
||||
.section_5 {
|
||||
padding: 24rpx 28rpx 23.5rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 20rpx;
|
||||
background-color: #ffffff;
|
||||
|
||||
.image_11 {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.font_3 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.text_31 {
|
||||
font-size: 28rpx;
|
||||
line-height: 26.04rpx;
|
||||
}
|
||||
|
||||
.image_4 {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
|
||||
.image_12 {
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.section_6 {
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #ffffff;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.image_13 {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
}
|
||||
|
||||
.group_14 {
|
||||
margin-top: 6.4rpx;
|
||||
|
||||
.text_32 {
|
||||
font-size: 28rpx;
|
||||
line-height: 26.12rpx;
|
||||
}
|
||||
|
||||
.font_5 {
|
||||
font-size: 26rpx;
|
||||
line-height: 21.14rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.text_34 {
|
||||
color: #999999;
|
||||
font-size: 24rpx;
|
||||
line-height: 22.48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.text-wrapper_4 {
|
||||
background-image: linear-gradient(106.4deg, #ff912b -19.9%, #fc6a11 100.3%);
|
||||
border-radius: 32rpx;
|
||||
width: 140rpx;
|
||||
height: 64rpx;
|
||||
|
||||
.text_33 {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.font_9 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
font-weight: 700;
|
||||
color: #363636;
|
||||
}
|
||||
}
|
||||
|
||||
.section_7 {
|
||||
padding: 46rpx 0 48rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.group_15 {
|
||||
margin-left: 30rpx;
|
||||
margin-right: 36rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.text_35 {
|
||||
color: #363636;
|
||||
font-size: 30rpx;
|
||||
font-weight: 700;
|
||||
line-height: 27.7rpx;
|
||||
}
|
||||
|
||||
.group_16 {
|
||||
margin-top: 34.76rpx;
|
||||
|
||||
.font_3 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.text_36 {
|
||||
line-height: 24.24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.font_19 {
|
||||
font-size: 26rpx;
|
||||
line-height: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.image_7 {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
|
||||
.service-item-right {
|
||||
margin-top: 24rpx;
|
||||
width: 450rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section_8 {
|
||||
padding: 36.12rpx 20.54rpx 46.56rpx 28.54rpx;
|
||||
background-image: linear-gradient(180deg, #f1fbfb -21.5%, #ffffff 67.4%);
|
||||
border-radius: 20rpx;
|
||||
border: solid 4rpx #ffffff;
|
||||
|
||||
.font_12 {
|
||||
font-size: 32rpx;
|
||||
line-height: 29.6rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.text_41 {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
line-height: 31.44rpx;
|
||||
}
|
||||
|
||||
.section_9 {
|
||||
background-color: #02c8e7;
|
||||
border-radius: 50%;
|
||||
width: 8rpx;
|
||||
height: 8rpx;
|
||||
}
|
||||
|
||||
.indicator-wrap {
|
||||
width: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.font_3 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.image_7 {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
|
||||
.faq-arrow {
|
||||
margin-right: 15rpx;
|
||||
}
|
||||
|
||||
.mt-34 {
|
||||
margin-top: 34rpx;
|
||||
}
|
||||
|
||||
.group_21 {
|
||||
line-height: 24.62rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,683 @@
|
|||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_other_tickets_qunar" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_tickets_qunar')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="codefun-flex-col section">
|
||||
<NavBar :bgColor="data.navBar.bgColor" :buttonGroup="buttonGroup" @button-click="util.clickTitlePopupButton"
|
||||
tipLayerType="qunar-train-tickets-tip" isTipLayer tipLayerText="修改车票信息">
|
||||
<template v-slot:right>
|
||||
<view class="codefun-flex-col group_2">
|
||||
<view class="codefun-flex-row group_3">
|
||||
<image class="image_4" src="/static/image/other/train-tickets/qunar/tuigaishuoming.png" />
|
||||
<image class="image_4 ml-25" src="/static/image/other/train-tickets/qunar/kefu.png" />
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-mt-4">
|
||||
<text class="font text">退改说明</text>
|
||||
<text class="font text_2 ml-11">客服</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</NavBar>
|
||||
<view class="codefun-flex-col">
|
||||
<view class="codefun-flex-row codefun-justify-between codefun-items-center group_4">
|
||||
<view class="codefun-flex-row codefun-items-center">
|
||||
<image class="codefun-shrink-0 image_5" src="/static/image/other/train-tickets/qunar/success.png" />
|
||||
<text class="text_5 ml-7">出票完成</text>
|
||||
<view
|
||||
class="codefun-flex-col codefun-justify-start codefun-items-center codefun-shrink-0 text-wrapper ml-7 codefun-justify-center">
|
||||
<text class="font_5 text_6">订返程</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-col section_2">
|
||||
<view class="codefun-self-start group_5">
|
||||
<text class="font_2 text_3">¥</text>
|
||||
<text class="font_2 text_4">{{ trainTickets.orderInfo.price }}</text>
|
||||
</view>
|
||||
<image class="codefun-shrink-0 codefun-self-end image_7 image_8"
|
||||
src="/static/image/other/train-tickets/qunar/right.png" />
|
||||
<text class="codefun-self-start text_7">支付明细</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="main-box">
|
||||
<view class="codefun-flex-col section_3">
|
||||
<view class="codefun-flex-col view">
|
||||
<view class="codefun-flex-row codefun-items-baseline codefun-self-stretch codefun-justify-between">
|
||||
<text class="font_5 text_8">取票号:{{ trainTickets.orderInfo.orderNo }}</text>
|
||||
<view class="group_9 ml-25">
|
||||
<text class="font_6">{{ trainTickets.ticketInfo.gate }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-row equal-division codefun-justify-between">
|
||||
<view class="codefun-flex-col group_10 group_28">
|
||||
<text class="codefun-self-stretch font_3 text_16">{{
|
||||
formatDateTime(trainTickets.ticketInfo.departureTime,
|
||||
trainTickets.ticketInfo.date) }}</text>
|
||||
<text class="codefun-self-start font_8 mt-7">{{
|
||||
trainTickets.ticketInfo.departureTime.split(' ')[1]
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="codefun-flex-col codefun-items-center group_10 group_29">
|
||||
<text class="font_5 text_17">{{ trainTickets.ticketInfo.duration }}</text>
|
||||
<image class="image_9 mt-11" src="/static/image/other/train-tickets/qunar/jingtingzhan.png" />
|
||||
</view>
|
||||
<view class="codefun-flex-col group_10 group_26">
|
||||
<text class="codefun-self-start font_3 text_18">{{
|
||||
formatDateTime(trainTickets.ticketInfo.arrivalTime,
|
||||
trainTickets.ticketInfo.date) }}</text>
|
||||
<text class="codefun-self-end font_8 mt-7">{{ trainTickets.ticketInfo.arrivalTime.split(' ')[1]
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-justify-center codefun-self-stretch codefun-relative group_11">
|
||||
<view class="codefun-flex-row codefun-items-center pos">
|
||||
<text class="font_9 text_19">{{ trainTickets.ticketInfo.departureStation }}</text>
|
||||
<image class="codefun-shrink-0 image_4 ml-3"
|
||||
src="/static/image/other/train-tickets/qunar/location.png" />
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-items-center">
|
||||
<text class="font_19 text_21">{{ trainTickets.ticketInfo.trainNo }}</text>
|
||||
<image class="codefun-shrink-0 image_10 codefun-ml-2"
|
||||
src="/static/image/other/train-tickets/qunar/info.png" />
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-items-center pos_2">
|
||||
<image class="codefun-shrink-0 image_4"
|
||||
src="/static/image/other/train-tickets/qunar/location.png" />
|
||||
<text class="font_9 text_20 codefun-ml-4">{{ trainTickets.ticketInfo.arrivalStation }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-col group_12">
|
||||
<view class="codefun-flex-col section_1" v-for="item in trainTickets.passengerList" :key="item.id">
|
||||
<view class="codefun-flex-col">
|
||||
<view class="codefun-flex-row codefun-justify-between codefun-items-center">
|
||||
<view class="codefun-flex-row codefun-items-baseline">
|
||||
<text class="font_10">{{ item.name }}</text>
|
||||
<text class="font_11 text_22 codefun-ml-10">{{ item.idType }}</text>
|
||||
</view>
|
||||
<view class="codefun-flex-row">
|
||||
<view
|
||||
class="codefun-flex-col codefun-justify-start codefun-items-center codefun-shrink-0 text-wrapper_8">
|
||||
<text v-if="computeSeatNo(item.seatNo)" class="font_4 text_23">{{
|
||||
computeSeatNo(item.seatNo) }}</text>
|
||||
</view>
|
||||
<text class="font_12 text_51 codefun-ml-6">{{ item.carriage }}车{{ item.seatNo }}号</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-justify-between codefun-mt-8">
|
||||
<text class="codefun-self-start font_13">{{ item.idType.includes('身份证') ?
|
||||
stringUtil.maskIdCard(item.idNumber) : (item.idType.includes('护照') ?
|
||||
stringUtil.maskPassport(item.idNumber) : item.idNumber) }}</text>
|
||||
<text class="codefun-self-center font_14 text_25">{{ item.seatType }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="codefun-flex-row codefun-justify-between codefun-items-center group_27 mt-19">
|
||||
<text class="font_15 text_50">出票成功</text>
|
||||
<view class="codefun-flex-row">
|
||||
<view class="codefun-flex-col codefun-justify-center codefun-items-center action-btn">
|
||||
<text class="font_16">分享</text>
|
||||
</view>
|
||||
<view
|
||||
class="codefun-flex-col codefun-justify-center codefun-items-center action-btn codefun-ml-6">
|
||||
<text class="font_16">改签</text>
|
||||
</view>
|
||||
<view
|
||||
class="codefun-flex-col codefun-justify-center codefun-items-center action-btn codefun-ml-6">
|
||||
<text class="font_16">退票</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<Box />
|
||||
<view class="" style="width: 100%;overflow: hidden;">
|
||||
<ZdySafeBottom bgColor="#f0f3f8" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import NavBar from '@/components/nav-bar/nav-bar.vue';
|
||||
import Box from './components/box.vue';
|
||||
import { reactive, toRefs } from 'vue';
|
||||
import { onShow, onPageScroll } from '@dcloudio/uni-app';
|
||||
import { util, stringUtil } from '@/utils/common.js';
|
||||
import ZdySafeBottom from '@/components/safeBottom/safeBottom.vue'
|
||||
|
||||
const buttonGroup = [{
|
||||
name: "编辑机票信息",
|
||||
click: () => {
|
||||
goEdit()
|
||||
}
|
||||
}]
|
||||
|
||||
function goEdit() {
|
||||
util.goPage(`/pages/other/train-tickets/edit/edit?app=qunar&storageKey=${data.STORAGE_KEY}`)
|
||||
}
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
bgColor: 'transparent'
|
||||
},
|
||||
trainTickets: {
|
||||
"orderInfo": {
|
||||
"orderNo": "EJ66223536",
|
||||
"price": "4440"
|
||||
},
|
||||
"ticketInfo": {
|
||||
"departureTime": "01-01 09:19",
|
||||
"departureStation": "北京南",
|
||||
"arrivalTime": "01-01 14:04",
|
||||
"arrivalStation": "上海虹桥",
|
||||
"trainNo": "G905",
|
||||
"duration": "4时45分",
|
||||
"date": "2026.01.01",
|
||||
"weekDay": "星期四",
|
||||
"gate": "6A、7A进站检票口,6B、7B进站检票",
|
||||
"trainName": "复兴号"
|
||||
},
|
||||
"passengerList": [
|
||||
{
|
||||
"name": "张元英",
|
||||
"type": "成人票",
|
||||
"seatType": "商务座",
|
||||
"carriage": "01",
|
||||
"seatNo": "03C",
|
||||
"idType": "外国护照(KR)",
|
||||
"idNumber": "KR123456789",
|
||||
"price": "2110",
|
||||
"status": "已支付",
|
||||
"isMe": true,
|
||||
"points": 9632
|
||||
}
|
||||
]
|
||||
},
|
||||
STORAGE_KEY: 'qunarTrainTickets'
|
||||
})
|
||||
|
||||
let { trainTickets } = toRefs(data)
|
||||
|
||||
onShow(() => {
|
||||
const stored = uni.getStorageSync(data.STORAGE_KEY)
|
||||
if (stored) {
|
||||
Object.assign(data.trainTickets, stored)
|
||||
}
|
||||
})
|
||||
|
||||
onPageScroll((e) => {
|
||||
data.navBar.bgColor = e.scrollTop > 40 ? '#F2F5F9' : 'transparent';
|
||||
})
|
||||
|
||||
|
||||
const computeSeatNo = (seatNo) => {
|
||||
if (seatNo.includes('C') || seatNo.includes('F')) {
|
||||
return '靠窗';
|
||||
} else if (seatNo.includes('A') || seatNo.includes('D')) {
|
||||
return '过道';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
const formatDateTime = (timeStr, dateStr) => {
|
||||
if (!timeStr) return '';
|
||||
const parts = timeStr.split(' ');
|
||||
const md = parts[0];
|
||||
if (!md) return '';
|
||||
const mdParts = md.split('-');
|
||||
let year, month, day;
|
||||
|
||||
if (mdParts.length === 3) {
|
||||
year = mdParts[0];
|
||||
month = mdParts[1];
|
||||
day = mdParts[2];
|
||||
} else if (mdParts.length === 2) {
|
||||
month = mdParts[0];
|
||||
day = mdParts[1];
|
||||
year = new Date().getFullYear();
|
||||
if (dateStr) {
|
||||
year = dateStr.split('.')[0];
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
|
||||
const dateObj = new Date(Number(year), Number(month) - 1, Number(day));
|
||||
const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
const week = isNaN(dateObj.getTime()) ? '' : weekDays[dateObj.getDay()];
|
||||
|
||||
return `${month}月${day}日 ${week}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import '/common/global.css';
|
||||
|
||||
page {
|
||||
background-color: #F2F5F9;
|
||||
width: 100vw;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
::v-deep .uni-navbar__header-btns-right {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.ml-11 {
|
||||
margin-left: 22rpx;
|
||||
}
|
||||
|
||||
.ml-7 {
|
||||
margin-left: 14rpx;
|
||||
}
|
||||
|
||||
.ml-25 {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.mt-7 {
|
||||
margin-top: 14rpx;
|
||||
}
|
||||
|
||||
.mt-11 {
|
||||
margin-top: 22rpx;
|
||||
}
|
||||
|
||||
.ml-3 {
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
|
||||
.mt-19 {
|
||||
margin-top: 38rpx;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: linear-gradient(180deg, #CDF2F6 0%, #F2F5F9 100%);
|
||||
|
||||
.image_5 {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
.group_2 {
|
||||
.group_3 {
|
||||
padding-left: 23.26rpx;
|
||||
padding-right: 4.64rpx;
|
||||
|
||||
.image_4 {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.font {
|
||||
font-size: 18rpx;
|
||||
line-height: 16.88rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.text {
|
||||
line-height: 16.68rpx;
|
||||
}
|
||||
|
||||
.text_2 {
|
||||
line-height: 16.74rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group_4 {
|
||||
padding-left: 20rpx;
|
||||
padding-bottom: 30rpx;
|
||||
|
||||
.text_5 {
|
||||
color: #363636;
|
||||
font-size: 44rpx;
|
||||
font-weight: 700;
|
||||
line-height: 41.18rpx;
|
||||
}
|
||||
|
||||
.text-wrapper {
|
||||
border-radius: 25rpx;
|
||||
width: 106rpx;
|
||||
height: 24px;
|
||||
border: solid 0.5px #28c2dd;
|
||||
|
||||
.text_6 {
|
||||
color: #28c2dd;
|
||||
font-size: 24rpx;
|
||||
line-height: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.section_2 {
|
||||
padding: 19.76rpx 16.2rpx 13.54rpx;
|
||||
background: linear-gradient(270deg, rgba(255, 255, 255, 0) 0%, #FFFFFF 100%);
|
||||
border-radius: 16rpx 0rpx 0rpx 16rpx;
|
||||
width: 160rpx;
|
||||
height: 94rpx;
|
||||
|
||||
.group_5 {
|
||||
line-height: 20.46rpx;
|
||||
|
||||
.font_2 {
|
||||
font-size: 26rpx;
|
||||
line-height: 21.14rpx;
|
||||
color: #fb8517;
|
||||
}
|
||||
|
||||
.text_3 {
|
||||
font-size: 28rpx;
|
||||
line-height: 19.9rpx;
|
||||
}
|
||||
|
||||
.text_4 {
|
||||
font-size: 28rpx;
|
||||
line-height: 20.46rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.image_7 {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
|
||||
.image_8 {
|
||||
margin-right: 11.8rpx;
|
||||
}
|
||||
|
||||
.text_7 {
|
||||
margin-left: 2.52rpx;
|
||||
margin-top: 3.84rpx;
|
||||
color: #363636;
|
||||
font-size: 20rpx;
|
||||
line-height: 18.62rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-box {
|
||||
padding: 10rpx 16rpx;
|
||||
padding-bottom: 10rpx;
|
||||
padding-bottom: calc(10rpx + constant(safe-area-inset-bottom));
|
||||
padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
|
||||
.ml-25 {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
|
||||
.section_3 {
|
||||
padding: 20rpx 18rpx 0;
|
||||
background-color: #ffffff;
|
||||
border-radius: 20rpx;
|
||||
|
||||
.view {
|
||||
margin: 0 14rpx;
|
||||
padding-top: 2.96rpx;
|
||||
|
||||
.font_5 {
|
||||
font-size: 26rpx;
|
||||
line-height: 21.14rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.text_8 {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.group_9 {
|
||||
line-height: 21.76rpx;
|
||||
height: 21.76rpx;
|
||||
overflow: hidden;
|
||||
overflow-x: auto;
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
|
||||
/* 隐藏横向滚动条,但保留滑动效果 */
|
||||
scrollbar-width: none;
|
||||
-ms-overflow-style: none;
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.font_6 {
|
||||
white-space: nowrap;
|
||||
font-size: 22rpx;
|
||||
line-height: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #4FB26E;
|
||||
}
|
||||
}
|
||||
|
||||
.equal-division {
|
||||
align-self: flex-start;
|
||||
margin-top: 21rpx;
|
||||
width: 100%;
|
||||
|
||||
.group_10 {
|
||||
flex-shrink: 0;
|
||||
|
||||
.font_3 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.text_16 {
|
||||
font-size: 28rpx;
|
||||
line-height: 24rpx;
|
||||
}
|
||||
|
||||
.font_8 {
|
||||
font-size: 52rpx;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.text_17 {
|
||||
font-size: 24rpx;
|
||||
line-height: 22.04rpx;
|
||||
}
|
||||
|
||||
.image_9 {
|
||||
width: 234rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
.text_18 {
|
||||
font-size: 28rpx;
|
||||
line-height: 24rpx;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.group_28 {
|
||||
padding: 16rpx 0;
|
||||
width: 200rpx;
|
||||
}
|
||||
|
||||
.group_29 {
|
||||
padding: 18.84rpx 0 3.54rpx;
|
||||
}
|
||||
|
||||
.group_26 {
|
||||
padding: 16rpx 0;
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.group_11 {
|
||||
|
||||
.pos {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.text_19 {
|
||||
font-size: 28rpx;
|
||||
line-height: 25.96rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.font_19 {
|
||||
font-size: 26rpx;
|
||||
line-height: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.text_21 {
|
||||
font-size: 24rpx;
|
||||
line-height: 17.54rpx;
|
||||
}
|
||||
|
||||
.image_10 {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
.pos_2 {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.text_20 {
|
||||
font-size: 28rpx;
|
||||
line-height: 25.82rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.image_4 {
|
||||
width: 28rpx;
|
||||
height: 28rpx;
|
||||
}
|
||||
|
||||
.font_9 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
font-weight: 700;
|
||||
color: #363636;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group_12 {
|
||||
padding: 38rpx 0 0;
|
||||
|
||||
.section_1 {
|
||||
padding: 28rpx 10.58rpx 22rpx 19.1rpx;
|
||||
background-color: #f9fbfc;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.text_22 {
|
||||
font-size: 24rpx;
|
||||
line-height: 22.22rpx;
|
||||
}
|
||||
|
||||
.text-wrapper_8 {
|
||||
background-color: #9db2bd;
|
||||
border-radius: 8rpx;
|
||||
width: 56rpx;
|
||||
height: 32rpx;
|
||||
|
||||
.text_23 {
|
||||
line-height: 32rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.text_51 {
|
||||
margin-top: 2.92rpx;
|
||||
}
|
||||
|
||||
.text_25 {
|
||||
margin-right: 4.38rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.group_27 {
|
||||
padding: 0 8.98rpx;
|
||||
|
||||
.text_50 {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.font_10 {
|
||||
font-size: 26rpx;
|
||||
line-height: 23.74rpx;
|
||||
font-weight: 700;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.font_11 {
|
||||
font-size: 26rpx;
|
||||
line-height: 21.14rpx;
|
||||
font-weight: 500;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.font_4 {
|
||||
font-size: 20rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.font_12 {
|
||||
font-size: 32rpx;
|
||||
line-height: 29.6rpx;
|
||||
color: #363636;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.font_13 {
|
||||
font-size: 26rpx;
|
||||
line-height: 19rpx;
|
||||
font-weight: 500;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.font_14 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
color: #545356;
|
||||
}
|
||||
|
||||
.font_15 {
|
||||
font-size: 26rpx;
|
||||
line-height: 25.92rpx;
|
||||
font-weight: 700;
|
||||
color: #f5882c;
|
||||
}
|
||||
|
||||
.font_16 {
|
||||
font-size: 26rpx;
|
||||
line-height: 21.14rpx;
|
||||
font-weight: 700;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
background-color: #ffffff;
|
||||
border-radius: 30rpx;
|
||||
width: 104rpx;
|
||||
height: 60rpx;
|
||||
border: solid 1rpx #e0e4e3;
|
||||
|
||||
text {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<template>
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark')">
|
||||
<c-lottie ref="cLottieRef" :src='$watermark()' width="94px" height='74px' :loop="true"></c-lottie>
|
||||
<watermark dark="light" source="uni_alipay_other_groupChat" />
|
||||
<liu-drag-button :canDocking="false" @clickBtn="$goRechargePage('watermark', 'uni_alipay_other_groupChat')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
<view class="container">
|
||||
|
|
@ -64,39 +64,43 @@
|
|||
<view class="control-buttons">
|
||||
<!-- 麦克风 -->
|
||||
<view class="control-item">
|
||||
<view class="control-btn" :class="{ active: videoData.micOn }" @click="changeInfo('micOn')">
|
||||
<image class="control-icon"
|
||||
<image class="control-btn" :class="{ active: videoData.micOn }" @click="changeInfo('micOn')"
|
||||
:src="videoData.micOn ? '/static/image/other/video-call/mic-on.png' : '/static/image/other/video-call/mic-off.png'">
|
||||
</image>
|
||||
</view>
|
||||
<!-- <view class="" :class="{ active: videoData.micOn }" >
|
||||
|
||||
</view> -->
|
||||
<text class="control-label">{{ videoData.micOn ? '麦克风已开' : '麦克风已关' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 扬声器 -->
|
||||
<view class="control-item">
|
||||
<view class="control-btn" :class="{ active: videoData.speakerOn }" @click="changeInfo('speakerOn')">
|
||||
<image class="control-icon"
|
||||
<image class="control-btn" :class="{ active: videoData.speakerOn }" @click="changeInfo('speakerOn')"
|
||||
:src="videoData.speakerOn ? '/static/image/other/video-call/speaker-on.png' : '/static/image/other/video-call/speaker-off.png'">
|
||||
</image>
|
||||
</view>
|
||||
<!-- <view class="" :class="{ active: videoData.speakerOn }" @click="changeInfo('speakerOn')">
|
||||
|
||||
</view> -->
|
||||
<text class="control-label">{{ videoData.speakerOn ? '扬声器已开' : '扬声器已关' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 摄像头 -->
|
||||
<view class="control-item">
|
||||
<view class="control-btn" :class="{ active: videoData.cameraOn }" @click="changeInfo('cameraOn')">
|
||||
<image class="control-icon"
|
||||
<image class="control-btn" :class="{ active: videoData.cameraOn }" @click="changeInfo('cameraOn')"
|
||||
:src="videoData.cameraOn ? '/static/image/other/video-call/camera-on.png' : '/static/image/other/video-call/camera-off.png'">
|
||||
</image>
|
||||
</view>
|
||||
<!-- <view class="control-btn" :class="{ active: videoData.cameraOn }" @click="changeInfo('cameraOn')">
|
||||
|
||||
</view> -->
|
||||
<text class="control-label">{{ videoData.cameraOn ? '摄像头已开' : '摄像头已关' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 挂断按钮 -->
|
||||
<view class="hangup-btn" @click="hangup">
|
||||
<image class="hangup-icon" src="/static/image/other/video-call/hangup.png"></image>
|
||||
</view>
|
||||
<image class="hangup-btn" @click="hangup" src="/static/image/other/video-call/hangup.png" :style="{'margin-bottom':$store.state.safeBottomAz+'px'}"></image>
|
||||
<!-- <view class="hangup-btn" @click="hangup">
|
||||
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
|
@ -142,11 +146,10 @@
|
|||
<script setup>
|
||||
import NavBar from "@/components/nav-bar/nav-bar.vue"
|
||||
|
||||
import { ref, toRefs, onMounted, onUnmounted, reactive, computed, getCurrentInstance } from 'vue'
|
||||
import { toRefs, onMounted, onUnmounted, reactive, computed, getCurrentInstance } from 'vue'
|
||||
import { onLoad, onShow, onHide } from '@dcloudio/uni-app'
|
||||
import { util } from '@/utils/common.js'
|
||||
const {
|
||||
appContext,
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
|
|
@ -265,7 +268,10 @@ onLoad(() => {
|
|||
...videoData,
|
||||
iconType: videoData.onMic ? videoData.iconType : 1,
|
||||
videoList: videoData.videoList.map((item) => {
|
||||
item.videoUrl = item.savedVideoUrl
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
item.videoUrl = plus.io.convertLocalFileSystemURL(item.savedVideoUrl)
|
||||
// #endif
|
||||
return item
|
||||
})
|
||||
}
|
||||
|
|
@ -290,7 +296,7 @@ onShow(() => {
|
|||
}
|
||||
startTimer()
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#232323')
|
||||
// 保存定时器引用,以便在页面卸载时清理
|
||||
statusBarTimer = setTimeout(() => {
|
||||
|
|
@ -523,7 +529,10 @@ const chooseVideo = () => {
|
|||
camera: 'back',
|
||||
success: async (res) => {
|
||||
console.log('选择视频成功:', res)
|
||||
const videoUrl = plus.io.convertLocalFileSystemURL(res.tempFilePath)
|
||||
let videoUrl = res.tempFilePath
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
videoUrl = plus.io.convertLocalFileSystemURL(res.tempFilePath)
|
||||
// #endif
|
||||
const savedVideoUrl = await new Promise((resolve, reject) => {
|
||||
uni.saveFile({
|
||||
tempFilePath: videoUrl,
|
||||
|
|
@ -661,7 +670,7 @@ const removeFile = (filePath) => {
|
|||
|
||||
console.log('🗑️ 准备删除文件:', filePath)
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
// 尝试使用 plus.io 删除 (支持 file:// 协议和 _downloads 等路径)
|
||||
if (filePath.startsWith('file://') || filePath.includes('_downloads') || filePath.includes('saved_video_')) {
|
||||
plus.io.resolveLocalFileSystemURL(filePath, (entry) => {
|
||||
|
|
@ -681,7 +690,7 @@ const removeFile = (filePath) => {
|
|||
// 尝试使用 uni.removeSavedFile (主要针对 uni.saveFile 保存的文件)
|
||||
uni.removeSavedFile({
|
||||
filePath: filePath,
|
||||
success: (res) => {
|
||||
success: () => {
|
||||
console.log('✅ uni.removeSavedFile 删除成功:', filePath)
|
||||
},
|
||||
fail: (err) => {
|
||||
|
|
@ -718,7 +727,7 @@ const handleTouchStart = (event, index) => {
|
|||
}
|
||||
|
||||
// 触摸移动 - 实时更新位置偏移
|
||||
const handleTouchMove = (event, index) => {
|
||||
const handleTouchMove = (event) => {
|
||||
if (!data.dragState.isDragging) return
|
||||
|
||||
const touch = event.touches[0]
|
||||
|
|
@ -731,7 +740,7 @@ const handleTouchMove = (event, index) => {
|
|||
}
|
||||
|
||||
// 触摸结束 - 完成拖动并保存
|
||||
const handleTouchEnd = (event, index) => {
|
||||
const handleTouchEnd = () => {
|
||||
// 清除长按定时器
|
||||
if (data.dragState.longPressTimer) {
|
||||
clearTimeout(data.dragState.longPressTimer)
|
||||
|
|
@ -1024,7 +1033,6 @@ const stopTimer = () => {
|
|||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #4a4a4a;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,361 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<nav-bar bgColor="transparent" :isBack="false">
|
||||
<template v-slot:center>
|
||||
<view class="flex-cneter title-box flex" style="margin-top: 24rpx;">
|
||||
<image class="wx-logo" src="/static/image/other/payment-success/payment-success.png"></image>
|
||||
<text class="title">支付成功</text>
|
||||
</view>
|
||||
</template>
|
||||
</nav-bar>
|
||||
<view class="content-box flex-column flex-cneter" @click="editPaymentInfo">
|
||||
<image v-if="paymetInfo.userImg" class="user-img" :src="paymetInfo.userImg" mode="aspectFill"></image>
|
||||
<text class="product-name">{{ paymetInfo.productName }}</text>
|
||||
<view class="money flex wx-font-medium" :style="{ 'margin-top': paymetInfo.userImg ? '78rpx' : '46rpx' }">
|
||||
<image class="symbol" src="/static/image/other/payment-success/symbol-yuan.png"></image>{{
|
||||
Number(paymetInfo.money).toFixed(2) }}
|
||||
</view>
|
||||
<image v-if="paymetInfo.isAd" class="ad-img" src="/static/image/other/payment-success/ad-img.png"
|
||||
mode="widthFix">
|
||||
</image>
|
||||
</view>
|
||||
<view class="finish-butn" @click="util.goBack()">完成</view>
|
||||
|
||||
<!-- 修改支付信息弹窗 -->
|
||||
<uni-popup ref="editPaymentInfoPopup" type="center">
|
||||
<view class="edit-popup">
|
||||
<view class="title">修改支付信息</view>
|
||||
<view class="input-item flex-align-center">
|
||||
<text class="label">用户头像</text>
|
||||
<view class="avatar-uploader flex-1">
|
||||
<view class="avatar-preview" v-if="paymetInfo.userImg">
|
||||
<image class="preview-img" :src="paymetInfo.userImg" mode="aspectFill"></image>
|
||||
<view class="delete-icon" @click="handleDeleteAvatar">×</view>
|
||||
</view>
|
||||
<view class="upload-btn" v-else @click="handleChooseAvatar">
|
||||
<text class="plus">+</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="input-item flex-align-center">
|
||||
<text class="label"><text style="color: #FF3B30;">*</text>商品名称</text>
|
||||
<input class="flex-1" type="text" v-model="paymetInfo.productName" placeholder="请输入商品名称" />
|
||||
</view>
|
||||
<view class="input-item flex-align-center">
|
||||
<text class="label"><text style="color: #FF3B30;">*</text>支付金额</text>
|
||||
<input class="flex-1" type="digit" v-model="paymetInfo.money" placeholder="请输入支付金额" />
|
||||
</view>
|
||||
<view class="input-item flex-align-center">
|
||||
<text class="label">展示广告</text>
|
||||
<switch class="flex-1" :checked="paymetInfo.isAd" @change="paymetInfo.isAd = $event.detail.value"
|
||||
color="#16B264" style="transform:scale(0.8);transform-origin:left center;" />
|
||||
</view>
|
||||
<view class="btn-group flex">
|
||||
<view class="btn cancel flex-1" @click="editPaymentInfoPopup.close()">取消</view>
|
||||
<view style="width: 30rpx;"></view>
|
||||
<view class="btn confirm flex-1" @click="confirmEditPaymentInfo">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<!-- 水印 -->
|
||||
<view v-if="$isVip()">
|
||||
<watermark dark="light" source="uni_alipay_other_wx_pay_success" />
|
||||
<liu-drag-button :canDocking="false"
|
||||
@clickBtn="$goRechargePage('watermark', 'uni_alipay_other_wx_pay_success')">
|
||||
<image src='/static/lottie/watermark.gif' mode="widthFix" style="width:94px;height:74px;" ></image>
|
||||
</liu-drag-button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, getCurrentInstance } from 'vue';
|
||||
import { onShow, onLoad } from '@dcloudio/uni-app';
|
||||
import { util } from '@/utils/common';
|
||||
import { storage } from '@/utils/storage';
|
||||
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
|
||||
const editPaymentInfoPopup = ref(null);
|
||||
|
||||
const editPaymentInfo = () => {
|
||||
editPaymentInfoPopup.value.open('center');
|
||||
}
|
||||
|
||||
const handleChooseAvatar = () => {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
const tempFilePath = res.tempFilePaths[0];
|
||||
// #ifndef H5
|
||||
uni.saveFile({
|
||||
tempFilePath: tempFilePath,
|
||||
success: (saveRes) => {
|
||||
if (paymetInfo.value.userImg && !paymetInfo.value.userImg.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: paymetInfo.value.userImg });
|
||||
}
|
||||
paymetInfo.value.userImg = saveRes.savedFilePath;
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
paymetInfo.value.userImg = tempFilePath;
|
||||
// #endif
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteAvatar = () => {
|
||||
// #ifndef H5
|
||||
if (paymetInfo.value.userImg && !paymetInfo.value.userImg.startsWith('/static/')) {
|
||||
uni.removeSavedFile({ filePath: paymetInfo.value.userImg });
|
||||
}
|
||||
// #endif
|
||||
paymetInfo.value.userImg = '';
|
||||
};
|
||||
|
||||
const confirmEditPaymentInfo = () => {
|
||||
editPaymentInfoPopup.value.close();
|
||||
storage.set('wx_payment_success_info', paymetInfo.value);
|
||||
}
|
||||
|
||||
const buttonGroup = [
|
||||
{
|
||||
name: "修改支付信息",
|
||||
click: () => {
|
||||
editPaymentInfo()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
const paymetInfo = ref({
|
||||
userImg: '',
|
||||
productName: '王者荣耀',
|
||||
money: 298,
|
||||
isAd: false,
|
||||
});
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#FFFFFF')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500)
|
||||
// #endif
|
||||
})
|
||||
|
||||
onLoad(async () => {
|
||||
const cachedInfo = storage.get('wx_payment_success_info');
|
||||
if (cachedInfo) {
|
||||
paymetInfo.value = cachedInfo;
|
||||
} else {
|
||||
paymetInfo.value = { productName: '王者荣耀', money: 168 };
|
||||
}
|
||||
|
||||
// 微信支付成功页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'wx_pay_success',
|
||||
prefix: '.uni.other.',
|
||||
value: "微信支付成功"
|
||||
})
|
||||
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.title-box {
|
||||
.wx-logo {
|
||||
width: 40rpx;
|
||||
height: 36rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #16B264;
|
||||
line-height: 32rpx;
|
||||
font-weight: 500;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content-box {
|
||||
margin-top: 162rpx;
|
||||
align-items: center;
|
||||
|
||||
.user-img {
|
||||
width: 94rpx;
|
||||
height: 94rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #D8D8D8;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 32rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 32rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.money {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 46rpx;
|
||||
font-weight: 500;
|
||||
font-size: 88rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 88rpx;
|
||||
|
||||
.symbol {
|
||||
width: 32rpx;
|
||||
height: 46rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.ad-img {
|
||||
margin-top: 100rpx;
|
||||
width: 654rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.finish-butn {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 348rpx;
|
||||
height: 92rpx;
|
||||
background-color: #F1F1F1;
|
||||
color: #1A1A1A;
|
||||
line-height: 92rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
margin: 0 auto;
|
||||
bottom: 170rpx;
|
||||
bottom: calc(170rpx + env(safe-area-inset-bottom));
|
||||
bottom: calc(170rpx + constant(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.edit-popup {
|
||||
width: 600rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.input-item {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
width: 140rpx;
|
||||
}
|
||||
|
||||
input {
|
||||
height: 72rpx;
|
||||
background-color: #F8F8F8;
|
||||
border-radius: 12rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.upload-btn {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #F8F8F8;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 2rpx dashed #CCCCCC;
|
||||
|
||||
.plus {
|
||||
font-size: 60rpx;
|
||||
color: #999;
|
||||
font-weight: 300;
|
||||
margin-top: -6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.delete-icon {
|
||||
position: absolute;
|
||||
top: -4rpx;
|
||||
right: -4rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background-color: red;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
line-height: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
margin-top: 50rpx;
|
||||
justify-content: space-between;
|
||||
|
||||
.btn {
|
||||
height: 80rpx;
|
||||
border-radius: 12rpx;
|
||||
text-align: center;
|
||||
line-height: 80rpx;
|
||||
font-size: 30rpx;
|
||||
|
||||
&.cancel {
|
||||
background-color: #F1F1F1;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
&.confirm {
|
||||
background-color: #3b82f6;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
@import '/common/main.css';
|
||||
|
||||
page {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<template>
|
||||
<view class="container">
|
||||
<nav-bar title="购物平台" bgColor="#F0F4F9"></nav-bar>
|
||||
<view class="menu-container">
|
||||
<view class="card" v-for="(item, index) in menuList" :key="index"
|
||||
:style="{ background: `linear-gradient(to bottom, ${item.bgColor[0]} 0%, ${item.bgColor[1]} 80%)` }">
|
||||
<text class="card-title">{{ item.name }}</text>
|
||||
<view class="icon-wrapper">
|
||||
<view class="icon-shadow" :style="{ background: item.shadowColor }"></view>
|
||||
<image class="icon-img" :src="`/static/image/shopping/${item.icon}.png`" mode="aspectFit"></image>
|
||||
</view>
|
||||
<view class="btn" :style="{ background: item.btnBg }" @click="goTo(item.url)">立即进入</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
getCurrentInstance
|
||||
} from 'vue';
|
||||
import {
|
||||
onLoad
|
||||
} from '@dcloudio/uni-app'
|
||||
|
||||
const {
|
||||
proxy
|
||||
} = getCurrentInstance();
|
||||
const data = reactive({
|
||||
phone: ''
|
||||
})
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.phone) {
|
||||
data.phone = options.phone
|
||||
}
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'shopping',
|
||||
prefix: '.uni.other.',
|
||||
value: '购物'
|
||||
})
|
||||
})
|
||||
|
||||
const menuList = ref([{
|
||||
name: "京东",
|
||||
icon: "jingdong",
|
||||
bgColor: ["#FFE0DF", "#FFFFFF"],
|
||||
btnBg: "#FF4848",
|
||||
shadowColor: "#FF4848",
|
||||
url: "/pages/shopping/jingdong/list-index"
|
||||
}, {
|
||||
name: "淘宝",
|
||||
icon: "taobao",
|
||||
bgColor: ["#FFF0DA", "#FFFFFF"],
|
||||
btnBg: "#FF953C",
|
||||
shadowColor: "#FF953C",
|
||||
url: "/pages/shopping/taobao/list-index"
|
||||
}, {
|
||||
name: "拼多多",
|
||||
icon: "pinduoduo",
|
||||
bgColor: ["#FFE0DF", "#FFFFFF"],
|
||||
btnBg: "#FF4848",
|
||||
shadowColor: "#FF4848",
|
||||
url: "/pages/shopping/pdd/list-index"
|
||||
}, {
|
||||
name: "快手",
|
||||
icon: "kuaishou",
|
||||
bgColor: ["#FFF0DA", "#FFFFFF"],
|
||||
btnBg: "#FF953C",
|
||||
shadowColor: "#FF953C",
|
||||
url: ""
|
||||
}, {
|
||||
name: "抖音",
|
||||
icon: "douyin",
|
||||
bgColor: ["#FAE5FF", "#FFFFFF"],
|
||||
btnBg: "#393939",
|
||||
shadowColor: "#D15CFF",
|
||||
url: ""
|
||||
}, {
|
||||
name: "得物",
|
||||
icon: "dewu",
|
||||
bgColor: ["#FAE5FF", "#FFFFFF"],
|
||||
btnBg: "#393939",
|
||||
shadowColor: "#D15CFF",
|
||||
url: ""
|
||||
}]);
|
||||
|
||||
const goTo = (url) => {
|
||||
if (url) {
|
||||
uni.navigateTo({
|
||||
url: url
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "开发中",
|
||||
icon: "none"
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
page {
|
||||
background-color: #F0F4F9;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: calc(50% - 14rpx);
|
||||
border-radius: 28rpx 28rpx 28rpx 28rpx;
|
||||
margin-bottom: 24rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 48rpx;
|
||||
padding-bottom: 40rpx;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ffffff;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 62rpx;
|
||||
position: relative;
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-img {
|
||||
width: 116rpx;
|
||||
height: 116rpx;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.icon-shadow {
|
||||
position: absolute;
|
||||
bottom: -10rpx;
|
||||
width: 100rpx;
|
||||
height: 8rpx;
|
||||
border-radius: 50%;
|
||||
filter: blur(5px);
|
||||
z-index: 1;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 20rpx;
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
border-radius: 16rpx 16rpx 16rpx 16rpx;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue