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
|
||||
371
App.vue
371
App.vue
|
|
@ -1,194 +1,227 @@
|
|||
<script>
|
||||
export default {
|
||||
globalData: {
|
||||
NativeEvent: true,
|
||||
recentNativeEvent: "", // 初始化一个全局变量
|
||||
recentNativeData: 0 // 初始化一个全局变量
|
||||
},
|
||||
onLaunch: function (options) {
|
||||
// === wgt 包启动诊断日志 ===
|
||||
console.log('=== App Launch 开始 ===')
|
||||
console.log('启动参数:', JSON.stringify(options))
|
||||
console.log('环境:', process.env.NODE_ENV)
|
||||
export default {
|
||||
globalData: {
|
||||
NativeEvent: true,
|
||||
recentNativeEvent: "", // 初始化一个全局变量
|
||||
recentNativeData: 0 // 初始化一个全局变量
|
||||
},
|
||||
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');
|
||||
const startTime = Date.now()
|
||||
|
||||
uni.setStorageSync('onNativeEventReceive', "no")
|
||||
// 清除上次遗留的跳转指令,防止正常启动时自动跳转
|
||||
uni.removeStorageSync('jumpTarget_url');
|
||||
const startTime = Date.now()
|
||||
// 1. 获取并存储系统信息(只获取一次)
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
uni.setStorageSync('systemInfo', {
|
||||
platform: systemInfo.platform,
|
||||
system: systemInfo.system,
|
||||
osName: systemInfo.osName,
|
||||
osVersion: systemInfo.osVersion,
|
||||
statusBarHeight: systemInfo.statusBarHeight,
|
||||
windowWidth: systemInfo.windowWidth,
|
||||
windowHeight: systemInfo.windowHeight,
|
||||
isIOS: systemInfo.platform === 'ios',
|
||||
isAndroid: systemInfo.platform === 'android'
|
||||
})
|
||||
|
||||
// 1. 获取并存储系统信息(只获取一次)
|
||||
const systemInfo = uni.getSystemInfoSync()
|
||||
uni.setStorageSync('systemInfo', {
|
||||
platform: systemInfo.platform,
|
||||
system: systemInfo.system,
|
||||
osName: systemInfo.osName,
|
||||
osVersion: systemInfo.osVersion,
|
||||
statusBarHeight: systemInfo.statusBarHeight,
|
||||
windowWidth: systemInfo.windowWidth,
|
||||
windowHeight: systemInfo.windowHeight,
|
||||
isIOS: systemInfo.platform === 'ios',
|
||||
isAndroid: systemInfo.platform === 'android'
|
||||
})
|
||||
// 2. 立即设置宿主消息监听(避免错过消息)
|
||||
this.setupNativeEventListener()
|
||||
|
||||
// 2. 立即设置宿主消息监听(避免错过消息)
|
||||
this.setupNativeEventListener()
|
||||
// 3. 同步初始化配置(必须完成)
|
||||
this.initConfig(options)
|
||||
|
||||
// 3. 同步初始化配置(必须完成)
|
||||
this.initConfig(options)
|
||||
// 启动完成
|
||||
console.log(`=== App 启动完成,耗时: ${Date.now() - startTime}ms ===`)
|
||||
|
||||
// 启动完成
|
||||
console.log(`=== App 启动完成,耗时: ${Date.now() - startTime}ms ===`)
|
||||
// 初始化埋点,进入支付宝模拟器首页
|
||||
this.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'index',
|
||||
value: "进入支付宝模拟器首页",
|
||||
})
|
||||
},
|
||||
|
||||
// 初始化埋点,进入支付宝模拟器首页
|
||||
this.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'index',
|
||||
value: "进入支付宝模拟器首页",
|
||||
})
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
// 监听已在 onLaunch 中设置,这里不再重复
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
console.log('App Show')
|
||||
// 监听已在 onLaunch 中设置,这里不再重复
|
||||
},
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
},
|
||||
onExit: function() {
|
||||
// 关闭数据库
|
||||
// #ifdef APP
|
||||
// plus.sqlite.closeDatabase({ name: 'zyds' })
|
||||
uni.sendNativeEvent('unimp_stop_alipay', "stop", ret => {
|
||||
// console.log('宿主App回传的数据:' + ret);
|
||||
});
|
||||
// #endif
|
||||
console.log('App onExit')
|
||||
},
|
||||
|
||||
onHide: function () {
|
||||
console.log('App Hide')
|
||||
},
|
||||
onExit: function () {
|
||||
// 关闭数据库
|
||||
// #ifdef APP
|
||||
// plus.sqlite.closeDatabase({ name: 'zyds' })
|
||||
uni.sendNativeEvent('unimp_stop_alipay', "stop", ret => {
|
||||
// console.log('宿主App回传的数据:' + ret);
|
||||
});
|
||||
// #endif
|
||||
console.log('App onExit')
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 设置宿主消息监听(在 onLaunch 中调用)
|
||||
*/
|
||||
setupNativeEventListener() {
|
||||
if (this.globalData.NativeEvent) {
|
||||
this.globalData.NativeEvent = false
|
||||
console.log('开始监听宿主消息')
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* 设置宿主消息监听(在 onLaunch 中调用)
|
||||
*/
|
||||
setupNativeEventListener() {
|
||||
if (this.globalData.NativeEvent) {
|
||||
this.globalData.NativeEvent = false
|
||||
console.log('开始监听宿主消息')
|
||||
if (typeof uni.onNativeEventReceive === 'function') {
|
||||
uni.onNativeEventReceive((event, data) => {
|
||||
if (event) {
|
||||
console.log('接收到宿主消息:', event, data)
|
||||
|
||||
uni.onNativeEventReceive((event, data) => {
|
||||
if (event) {
|
||||
console.log('接收到宿主消息:', event, data)
|
||||
if (event == "token") {
|
||||
let header = uni.getStorageSync('header') || {}
|
||||
header["x-token"] = data
|
||||
uni.setStorageSync('header', header)
|
||||
console.log('已更新 token')
|
||||
|
||||
if (event == "token") {
|
||||
let header = uni.getStorageSync('header') || {}
|
||||
header["x-token"] = data
|
||||
uni.setStorageSync('header', header)
|
||||
console.log('已更新 token')
|
||||
|
||||
//获取宿主用户信息
|
||||
try {
|
||||
this.$getUserInfo()
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
//获取宿主用户信息
|
||||
try {
|
||||
this.$getUserInfo()
|
||||
} catch (error) {
|
||||
console.error('获取用户信息失败:', error)
|
||||
}
|
||||
} else if (event == "jump") {
|
||||
if (data) {
|
||||
console.log('接收到跳转指令,已缓存目标地址:', data);
|
||||
uni.setStorageSync('jumpTarget_url', data);
|
||||
// 强制重定向到首页,触发onShow获取用户信息后再跳转
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
} else if (event == 'wx_pay_result' || event == 'ios_pay_result') {
|
||||
this.globalData.recentNativeEvent = event
|
||||
this.globalData.recentNativeData = data
|
||||
}
|
||||
}
|
||||
} else if (event == "jump") {
|
||||
if (data) {
|
||||
console.log('接收到跳转指令,已缓存目标地址:', data);
|
||||
uni.setStorageSync('jumpTarget_url', data);
|
||||
// 强制重定向到首页,触发onShow获取用户信息后再跳转
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
})
|
||||
} else {
|
||||
console.log('uni.onNativeEventReceive 不可用,跳过监听')
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 初始化应用配置
|
||||
*/
|
||||
initConfig(options) {
|
||||
console.log('=== 配置初始化 ===')
|
||||
|
||||
// 检查是否有外部传入的配置数据
|
||||
const hasExtraData = options?.referrerInfo?.extraData &&
|
||||
JSON.stringify(options.referrerInfo.extraData) !== '{}'
|
||||
|
||||
console.log('宿主是否传递配置:', hasExtraData)
|
||||
|
||||
if (hasExtraData) {
|
||||
console.log('→ 使用宿主 extraData')
|
||||
this.initFromExtraData(options.referrerInfo.extraData)
|
||||
} else {
|
||||
console.log('→ 宿主未传递配置,使用默认配置')
|
||||
// ⚠️ 关键修改:不再强制退出,使用默认配置
|
||||
this.initDevelopmentConfig()
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 从外部数据初始化配置
|
||||
*/
|
||||
initFromExtraData(extraData) {
|
||||
// 批量设置 Storage,减少 I/O 次数
|
||||
let storageData={}
|
||||
if(uni.getStorageSync('isTest')){
|
||||
storageData = {
|
||||
host: extraData.host,
|
||||
header: {
|
||||
"x-token": extraData['x-token'],
|
||||
"x-version": extraData['x-version'],
|
||||
"x-platform": extraData['x-platform'],
|
||||
"x-device-id": extraData['x-device-id'],
|
||||
"x-mobile-brand": extraData['x-mobile-brand'],
|
||||
"x-mobile-model": extraData['x-mobile-model'],
|
||||
"x-channel": extraData['x-channel'],
|
||||
"x-package": extraData['x-package'],
|
||||
"x-click-id": extraData['x-click-id'],
|
||||
// #ifdef APP-PLUS
|
||||
"header": {
|
||||
"version": this.$version,
|
||||
}
|
||||
} else if (event == 'wx_pay_result' || event == 'ios_pay_result') {
|
||||
this.globalData.recentNativeEvent = event
|
||||
this.globalData.recentNativeData = data
|
||||
// #endif
|
||||
},
|
||||
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' : '')
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 初始化开发环境配置(也作为默认配置)
|
||||
*/
|
||||
initDevelopmentConfig() {
|
||||
console.log('初始化默认配置')
|
||||
|
||||
// 批量设置开发环境配置
|
||||
const devConfig = {
|
||||
host: "https://flaunt.batiao8.com/",
|
||||
header: {
|
||||
"x-token": "55e2481e-cbd2-4d2d-82d3-b47e191fcfc0"
|
||||
},
|
||||
decrypt: "e4rOtnF8tJjtHO7ecZeJHN1rapED5ImB",
|
||||
encrypt: "xn08hYoizXhZ1zHP8DVqfCm2yHxPmhil"
|
||||
}
|
||||
|
||||
Object.keys(devConfig).forEach(key => {
|
||||
uni.setStorageSync(key, devConfig[key])
|
||||
})
|
||||
|
||||
console.log('默认配置初始化完成')
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 初始化应用配置
|
||||
*/
|
||||
initConfig(options) {
|
||||
console.log('=== 配置初始化 ===')
|
||||
|
||||
// 检查是否有外部传入的配置数据
|
||||
const hasExtraData = options?.referrerInfo?.extraData &&
|
||||
JSON.stringify(options.referrerInfo.extraData) !== '{}'
|
||||
|
||||
console.log('宿主是否传递配置:', hasExtraData)
|
||||
|
||||
if (hasExtraData) {
|
||||
console.log('→ 使用宿主 extraData')
|
||||
this.initFromExtraData(options.referrerInfo.extraData)
|
||||
} else {
|
||||
console.log('→ 宿主未传递配置,使用默认配置')
|
||||
// ⚠️ 关键修改:不再强制退出,使用默认配置
|
||||
this.initDevelopmentConfig()
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 从外部数据初始化配置
|
||||
*/
|
||||
initFromExtraData(extraData) {
|
||||
// 批量设置 Storage,减少 I/O 次数
|
||||
const storageData = {
|
||||
host: extraData.host,
|
||||
header: {
|
||||
"x-token": extraData['x-token'],
|
||||
"x-version": extraData['x-version'],
|
||||
"x-platform": extraData['x-platform'],
|
||||
"x-device-id": extraData['x-device-id'],
|
||||
"x-mobile-brand": extraData['x-mobile-brand'],
|
||||
"x-mobile-model": extraData['x-mobile-model'],
|
||||
"x-channel": extraData['x-channel'],
|
||||
"x-package": extraData['x-package'],
|
||||
"x-click-id": extraData['x-click-id'],
|
||||
// #ifdef APP-PLUS
|
||||
"header": {
|
||||
"version": this.$version,
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
encrypt: extraData['encrypt'],
|
||||
decrypt: extraData['decrypt']
|
||||
}
|
||||
|
||||
// 批量写入
|
||||
Object.keys(storageData).forEach(key => {
|
||||
uni.setStorageSync(key, storageData[key])
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 初始化开发环境配置(也作为默认配置)
|
||||
*/
|
||||
initDevelopmentConfig() {
|
||||
console.log('初始化默认配置')
|
||||
|
||||
// 批量设置开发环境配置
|
||||
const devConfig = {
|
||||
host: "https://flaunt.batiao8.com/",
|
||||
header: { "x-token": "ebe14dab-1879-4c5d-9148-727b96b30aad" },
|
||||
decrypt: "e4rOtnF8tJjtHO7ecZeJHN1rapED5ImB",
|
||||
encrypt: "xn08hYoizXhZ1zHP8DVqfCm2yHxPmhil"
|
||||
}
|
||||
|
||||
Object.keys(devConfig).forEach(key => {
|
||||
uni.setStorageSync(key, devConfig[key])
|
||||
})
|
||||
|
||||
console.log('默认配置初始化完成')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import "./common/color.css";
|
||||
/* #ifndef APP-NVUE */
|
||||
@import "./common/color.css";
|
||||
/* #endif */
|
||||
</style>
|
||||
|
|
@ -30,4 +30,4 @@ page {
|
|||
line-height: 1.5;
|
||||
color: var(--text-color);
|
||||
background-color: var(--page-bg-color);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,276 +82,294 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import popup from '../popup/popup.vue'
|
||||
import {
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs
|
||||
} from 'vue'
|
||||
import popup from '../popup/popup.vue'
|
||||
import {
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
toRefs
|
||||
} from 'vue'
|
||||
|
||||
const topPopup = ref()
|
||||
const topPopup = ref()
|
||||
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#000'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
buttonGroup: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
isRightIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isRightButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rightButtonText: {
|
||||
type: String,
|
||||
default: '确定'
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 999
|
||||
},
|
||||
noBack: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tipLayerText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isTipLayer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tipLayerType: {
|
||||
type: String,
|
||||
default: ''
|
||||
// 定义组件属性
|
||||
const props = defineProps({
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#000'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
buttonGroup: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
isRightIcon: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isRightButton: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rightButtonText: {
|
||||
type: String,
|
||||
default: '确定'
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 999
|
||||
},
|
||||
noBack: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isBack: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
tipLayerText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isTipLayer: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
tipLayerType: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isClickNavBarOpenPopup: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['back', 'right-click', 'button-click', 'refresh'])
|
||||
|
||||
const data = reactive({
|
||||
statusBarHeight: 0,
|
||||
showTipLayer: true,
|
||||
})
|
||||
|
||||
let {
|
||||
showTipLayer
|
||||
} = toRefs(data)
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
// 同步获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
data.statusBarHeight = systemInfo.statusBarHeight || 0;
|
||||
|
||||
if (props.isTipLayer) {
|
||||
if (uni.getStorageSync(props.tipLayerType) == props.tipLayerType) {
|
||||
showTipLayer.value = false
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const closeTipLayer = () => {
|
||||
showTipLayer.value = false
|
||||
uni.setStorageSync(props.tipLayerType, props.tipLayerType)
|
||||
emit("refresh")
|
||||
}
|
||||
})
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(['back', 'right-click', 'button-click', 'refresh'])
|
||||
|
||||
const data = reactive({
|
||||
statusBarHeight: 0,
|
||||
showTipLayer: true,
|
||||
})
|
||||
|
||||
let {
|
||||
showTipLayer
|
||||
} = toRefs(data)
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
// 同步获取系统信息
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
data.statusBarHeight = systemInfo.statusBarHeight || 0;
|
||||
|
||||
if (props.isTipLayer) {
|
||||
if (uni.getStorageSync(props.tipLayerType) == props.tipLayerType) {
|
||||
showTipLayer.value = false
|
||||
const openPopup = () => {
|
||||
if (props.buttonGroup.length > 0) {
|
||||
topPopup.value.open()
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
const closeTipLayer = () => {
|
||||
showTipLayer.value = false
|
||||
uni.setStorageSync(props.tipLayerType, props.tipLayerType)
|
||||
emit("refresh")
|
||||
}
|
||||
|
||||
const openPopup = () => {
|
||||
if (props.buttonGroup.length > 0) {
|
||||
topPopup.value.open()
|
||||
// 返回按钮点击事件
|
||||
const onBack = () => {
|
||||
emit('back')
|
||||
// 默认返回上一页
|
||||
if (props.noBack) return
|
||||
uni.navigateBack()
|
||||
}
|
||||
}
|
||||
|
||||
// 返回按钮点击事件
|
||||
const onBack = () => {
|
||||
emit('back')
|
||||
// 默认返回上一页
|
||||
if (props.noBack) return
|
||||
uni.navigateBack()
|
||||
}
|
||||
// 右侧按钮点击事件
|
||||
const onRightClick = () => {
|
||||
emit('right-click')
|
||||
}
|
||||
|
||||
// 右侧按钮点击事件
|
||||
const onRightClick = () => {
|
||||
emit('right-click')
|
||||
}
|
||||
const closeTopPopup = () => {
|
||||
topPopup.value.close()
|
||||
}
|
||||
|
||||
|
||||
const buttonClick = (button) => {
|
||||
topPopup.value.close()
|
||||
emit('button-click', button)
|
||||
}
|
||||
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 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.status-placeholder {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep .uni-navbar__content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav-bar-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.nav-icon-back {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.nav-icon-more {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.nav-bar-title {
|
||||
flex: 1;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-bar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.right-button {
|
||||
font-size: 12px;
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
min-width: 60px;
|
||||
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
|
||||
}
|
||||
|
||||
.button-box {
|
||||
width: calc(50% - 8rpx);
|
||||
text-align: center;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.button {
|
||||
border: 1px solid #E4E4E4;
|
||||
border-radius: 8px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.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;
|
||||
.nav-bar-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
::v-deep text {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #006ADD;
|
||||
.nav-bar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.triangleImg {
|
||||
width: 111px;
|
||||
height: 52px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: -23px;
|
||||
left: calc(50% - 111px);
|
||||
}
|
||||
.status-placeholder {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.triangle {
|
||||
position: absolute;
|
||||
top: -57px;
|
||||
left: calc(50% - 40px);
|
||||
pointer-events: none;
|
||||
}
|
||||
::v-deep .uni-navbar__content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
.nav-bar-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.nav-icon-back {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.nav-icon-more {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.nav-bar-title {
|
||||
flex: 1;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.nav-bar-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.right-button {
|
||||
font-size: 12px;
|
||||
border-radius: 16px;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
height: 30px;
|
||||
min-width: 60px;
|
||||
background: linear-gradient(90deg, #187AFF 0%, #3295FC 100%);
|
||||
}
|
||||
|
||||
.button-box {
|
||||
width: calc(50% - 8rpx);
|
||||
text-align: center;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.button {
|
||||
border: 1px solid #E4E4E4;
|
||||
border-radius: 8px;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.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,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.
76
main.js
76
main.js
|
|
@ -16,20 +16,78 @@ 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 {
|
||||
app
|
||||
|
|
|
|||
144
manifest.json
144
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" // 启动页背景颜色
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"app-plus" : {
|
||||
"darkmode" : false,
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : false,
|
||||
"delay" : 0
|
||||
},
|
||||
"optimization": {
|
||||
"subPackages": true
|
||||
|
||||
"compatible" : {
|
||||
"runtimeVersion": "4.75",
|
||||
"compilerVersion": "5.14",
|
||||
"ignoreVersion" : true
|
||||
},
|
||||
"optimization" : {
|
||||
"subPackages" : true
|
||||
},
|
||||
"runmode": "liberate", // 开启分包优化后,必须配置资源释放模式
|
||||
"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
58
package.json
58
package.json
|
|
@ -1,20 +1,40 @@
|
|||
{
|
||||
"id": "lius-DomVideoPlayer",
|
||||
"name": "video-player 视频播放器 html5视频播放器-解决频层级、覆盖",
|
||||
"displayName": "video-player 视频播放器 html5视频播放器-解决频层级、覆盖",
|
||||
"version": "2.0.0",
|
||||
"description": "APP 项目中,uniapp 提供的的 video 原生视频组件层级太高,难以遮挡;该视频播放器可以被其他元素进行覆盖、遮挡,页面具有更高的定制性。",
|
||||
"keywords": [
|
||||
"video-player",
|
||||
"视频播放器",
|
||||
"视频覆盖",
|
||||
"视频层级",
|
||||
"视频遮挡"
|
||||
],
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
]
|
||||
}
|
||||
}
|
||||
"id": "lius-DomVideoPlayer",
|
||||
"name": "video-player 视频播放器 html5视频播放器-解决频层级、覆盖",
|
||||
"displayName": "video-player 视频播放器 html5视频播放器-解决频层级、覆盖",
|
||||
"version": "2.0.0",
|
||||
"description": "APP 项目中,uniapp 提供的的 video 原生视频组件层级太高,难以遮挡;该视频播放器可以被其他元素进行覆盖、遮挡,页面具有更高的定制性。",
|
||||
"keywords": [
|
||||
"video-player",
|
||||
"视频播放器",
|
||||
"视频覆盖",
|
||||
"视频层级",
|
||||
"视频遮挡"
|
||||
],
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
]
|
||||
},
|
||||
"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,7 +87,8 @@
|
|||
<view class="info-item">
|
||||
<view class="label">总计额度</view>
|
||||
<view class="value">{{
|
||||
numberUtil.formatMoneyWithThousand(Number(huabeiInfo.totalAmount) - Number(huabeiInfo.money))
|
||||
huabeiInfo.isPayOff ? numberUtil.formatMoneyWithThousand(Number(huabeiInfo.totalAmount)) :
|
||||
numberUtil.formatMoneyWithThousand(Number(huabeiInfo.totalAmount) - Number(huabeiInfo.money))
|
||||
}}可用
|
||||
</view>
|
||||
</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,82 +410,97 @@ const serviceDetailRightTextList = [{
|
|||
}
|
||||
]
|
||||
// switch选项
|
||||
const switchOptions = [{
|
||||
"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,
|
||||
showTypeIds: [12, 13],
|
||||
key: 'refund',
|
||||
change: (value) => {
|
||||
if (billData.value.selectId == 12 || billData.value.selectId == 13) {
|
||||
if (value) {
|
||||
billData.value.orderStatus = "已全额退款"
|
||||
} else {
|
||||
billData.value.orderStatus = "交易成功"
|
||||
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,
|
||||
showTypeIds: [12, 13],
|
||||
key: 'refund',
|
||||
change: (value) => {
|
||||
if (billData.value.selectId == 12 || billData.value.selectId == 13) {
|
||||
if (value) {
|
||||
billData.value.orderStatus = "已全额退款"
|
||||
} else {
|
||||
billData.value.orderStatus = "交易成功"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"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',
|
||||
}
|
||||
},
|
||||
{
|
||||
"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',
|
||||
}
|
||||
|
||||
]
|
||||
|
||||
|
|
@ -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,134 +1,151 @@
|
|||
<!-- 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 {
|
||||
ref,
|
||||
reactive,
|
||||
watch,
|
||||
nextTick,
|
||||
getCurrentInstance,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
toRefs,
|
||||
computed
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onReady,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
watch,
|
||||
nextTick,
|
||||
getCurrentInstance,
|
||||
onMounted,
|
||||
onBeforeUnmount,
|
||||
toRefs,
|
||||
computed
|
||||
} from "vue";
|
||||
import {
|
||||
onLoad,
|
||||
onReady,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: "",
|
||||
bgColor: '#ffffff',
|
||||
},
|
||||
dark: "dark",
|
||||
// 状态栏高度
|
||||
systemBarHeight: "0",
|
||||
})
|
||||
const data = reactive({
|
||||
navBar: {
|
||||
title: "",
|
||||
bgColor: '#ffffff',
|
||||
},
|
||||
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) => {
|
||||
uni.getSystemInfo({
|
||||
success: res => {
|
||||
systemBarHeight.value = res.statusBarHeight; // 获取状态栏高度
|
||||
onLoad((options) => {
|
||||
if (options.isClose) {
|
||||
isClose.value = options.isClose
|
||||
}
|
||||
uni.getSystemInfo({
|
||||
success: res => {
|
||||
systemBarHeight.value = res.statusBarHeight; // 获取状态栏高度
|
||||
}
|
||||
})
|
||||
if (options.url) {
|
||||
url.value = decodeURIComponent(options.url)
|
||||
// const videoExps = [/\.mp4$/i, /\.m3u8$/i, /\.flv$/i, /\.avi$/i, /\.mov$/i, /\.wmv$/i, /\.webm$/i,
|
||||
// /\.mkv$/i
|
||||
// ];
|
||||
// const isVideo = videoExps.some(exp => exp.test(url.value))
|
||||
// console.log(isVideo)
|
||||
// if (isVideo) {
|
||||
// plus.navigator.setStatusBarStyle("light");
|
||||
// } else {
|
||||
// plus.navigator.setStatusBarStyle("dark");
|
||||
// }
|
||||
}
|
||||
console.log("options参数", options);
|
||||
if (options.title) {
|
||||
console.log("标题", options.title);
|
||||
pageTitle.value = decodeURIComponent(options.title)
|
||||
}
|
||||
})
|
||||
if (options.url) {
|
||||
url.value = decodeURIComponent(options.url)
|
||||
// const videoExps = [/\.mp4$/i, /\.m3u8$/i, /\.flv$/i, /\.avi$/i, /\.mov$/i, /\.wmv$/i, /\.webm$/i,
|
||||
// /\.mkv$/i
|
||||
// ];
|
||||
// const isVideo = videoExps.some(exp => exp.test(url.value))
|
||||
// console.log(isVideo)
|
||||
// if (isVideo) {
|
||||
// plus.navigator.setStatusBarStyle("light");
|
||||
// } else {
|
||||
// plus.navigator.setStatusBarStyle("dark");
|
||||
// }
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS&&!APP-HARMONY
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500);
|
||||
// #endif
|
||||
})
|
||||
|
||||
const onConfirm = () => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
}
|
||||
console.log("options参数", options);
|
||||
if (options.title) {
|
||||
console.log("标题", options.title);
|
||||
pageTitle.value = decodeURIComponent(options.title)
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// #ifdef APP-PLUS
|
||||
util.setAndroidSystemBarColor('#ffffff')
|
||||
setTimeout(() => {
|
||||
plus.navigator.setStatusBarStyle("dark");
|
||||
}, 500);
|
||||
// #endif
|
||||
})
|
||||
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 goBack = () => {
|
||||
uni.navigateBack()
|
||||
}
|
||||
|
||||
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(() => {
|
||||
return {
|
||||
top: `${Number(systemBarHeight.value) + 40}px`,
|
||||
bottom: '0px',
|
||||
'padding-bottom': '20px'
|
||||
}
|
||||
})
|
||||
const webviewStyles = computed(() => {
|
||||
return {
|
||||
top: `${Number(systemBarHeight.value) + 40}px`,
|
||||
bottom: '0px',
|
||||
'padding-bottom': '20px'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.webview-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.webview-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
.header {
|
||||
padding: 20rpx;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.video-web {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: #000;
|
||||
}
|
||||
.video-web {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: #000;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
page {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
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">
|
||||
|
|
@ -188,13 +188,13 @@
|
|||
</view>
|
||||
<canvas canvas-id="crop-canvas"
|
||||
style="position: fixed; left: -9999px; width: 750rpx; height: 100vh; pointer-events: none;"></canvas>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 底部导航栏 -->
|
||||
<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)">
|
||||
<image class="video-help-img" :src="item.icon"></image>
|
||||
<text class="video-help-title">{{ item.name }}</text>
|
||||
</view>
|
||||
<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>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,93 +1,140 @@
|
|||
<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)">
|
||||
<!-- Background Watermark -->
|
||||
<image class="watermark" :src="item.bgImage" mode="heightFix"></image>
|
||||
<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>
|
||||
|
||||
<!-- Front Content -->
|
||||
<view class="card-left">
|
||||
<view class="logo-box">
|
||||
<image class="logo" :src="item.logo" mode="aspectFit"></image>
|
||||
<!-- Hot Tag for Fliggy -->
|
||||
<view v-if="item.isHot" class="hot-tag">
|
||||
<image style="width: 72rpx;height:32rpx" src="/static/image/index/hot-icon.png"
|
||||
mode="aspectFit"></image>
|
||||
<!-- Front Content -->
|
||||
<view class="card-left">
|
||||
<view class="logo-box">
|
||||
<image class="logo" :src="item.logo" mode="aspectFit"></image>
|
||||
<!-- Hot Tag for Fliggy -->
|
||||
<view v-if="item.isHot" class="hot-tag">
|
||||
<image style="width: 72rpx;height:32rpx" src="/static/image/index/hot-icon.png"
|
||||
mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
<text class="app-name">{{ item.name }}</text>
|
||||
</view>
|
||||
<text class="app-name">{{ item.name }}</text>
|
||||
</view>
|
||||
|
||||
<uni-icons type="right" size="18" color="#CCCCCC"></uni-icons>
|
||||
</view>
|
||||
<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) => {
|
||||
// 进入机票页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'ticket',
|
||||
prefix: '.uni.other.',
|
||||
value: "机票"
|
||||
})
|
||||
})
|
||||
|
||||
const handleItemClick = (item) => {
|
||||
if (item.path) {
|
||||
util.goPage(item.path)
|
||||
const appType = option.type
|
||||
if (appType == "trainTicket") {
|
||||
type.value = "trainTicket"
|
||||
// 进入高铁票页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'train_ticket',
|
||||
prefix: '.uni.other.',
|
||||
value: "高铁票"
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '开发中',
|
||||
icon: 'none'
|
||||
type.value = "airTicket"
|
||||
// 进入机票页面埋点
|
||||
proxy.$apiUserEvent('all', {
|
||||
type: 'event',
|
||||
key: 'ticket',
|
||||
prefix: '.uni.other.',
|
||||
value: "机票"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* 跳转火车票/飞机票页面
|
||||
*/
|
||||
const handleItemClick = (item) => {
|
||||
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": [
|
||||
{
|
||||
"name": "张元英",
|
||||
"type": "成人票",
|
||||
"seatType": "商务座",
|
||||
"carriage": "01",
|
||||
"seatNo": "03C",
|
||||
"idType": "外国护照(KR)",
|
||||
"price": "2110",
|
||||
"status": "已支付",
|
||||
"isMe": true
|
||||
}
|
||||
],
|
||||
"passengerList": [{
|
||||
"name": "张元英",
|
||||
"type": "成人票",
|
||||
"seatType": "商务座",
|
||||
"carriage": "01",
|
||||
"seatNo": "03C",
|
||||
"idType": "外国护照(KR)",
|
||||
"idNumber": "123456789012345678",
|
||||
"price": "2110",
|
||||
"status": "已支付",
|
||||
"isMe": true,
|
||||
"points": 9632
|
||||
}],
|
||||
"hotelInfo": {
|
||||
"city": "上海",
|
||||
"cashback": "25",
|
||||
"startDay": "01-01",
|
||||
"endDay": "01-02"
|
||||
}
|
||||
},
|
||||
serviceText: "多人连坐 ¥10x2份"
|
||||
}
|
||||
// 车票类型
|
||||
const ticketType = [
|
||||
{
|
||||
label: '成人票',
|
||||
value: '1'
|
||||
},
|
||||
{
|
||||
label: '儿童票',
|
||||
value: '2'
|
||||
},
|
||||
{
|
||||
label: '学生票',
|
||||
value: '3'
|
||||
},
|
||||
{
|
||||
label: '残疾军人票',
|
||||
value: '4'
|
||||
}
|
||||
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];
|
||||
})
|
||||
|
||||
|
|
@ -754,4 +859,4 @@ page {
|
|||
.placeholder {
|
||||
height: 60rpx;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
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"
|
||||
:src="videoData.micOn ? '/static/image/other/video-call/mic-on.png' : '/static/image/other/video-call/mic-off.png'">
|
||||
</image>
|
||||
</view>
|
||||
<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 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"
|
||||
:src="videoData.speakerOn ? '/static/image/other/video-call/speaker-on.png' : '/static/image/other/video-call/speaker-off.png'">
|
||||
</image>
|
||||
</view>
|
||||
<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 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"
|
||||
:src="videoData.cameraOn ? '/static/image/other/video-call/camera-on.png' : '/static/image/other/video-call/camera-off.png'">
|
||||
</image>
|
||||
</view>
|
||||
<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 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
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue