39f68355 by lttnew

道馆页面更改

1 parent a4aa5d24
...@@ -5,7 +5,9 @@ ...@@ -5,7 +5,9 @@
5 "WebFetch(domain:minimax-algeng-chat-tts.oss-cn-wulanchabu.aliyuncs.com)", 5 "WebFetch(domain:minimax-algeng-chat-tts.oss-cn-wulanchabu.aliyuncs.com)",
6 "Bash(node -c pages/index/perfect.vue)", 6 "Bash(node -c pages/index/perfect.vue)",
7 "Bash(git checkout:*)", 7 "Bash(git checkout:*)",
8 "Bash(git restore:*)" 8 "Bash(git restore:*)",
9 "Bash(git:*)",
10 "Bash(python3 -c \"import json,sys; d=json.load\\(sys.stdin\\); print\\('tabBar list:', [l['pagePath'] for l in d.get\\('tabBar',{}\\).get\\('list',[]\\)]\\)\")"
9 ] 11 ]
10 } 12 }
11 } 13 }
......
...@@ -11,22 +11,28 @@ ...@@ -11,22 +11,28 @@
11 baseUrl_api: '', 11 baseUrl_api: '',
12 user: null 12 user: null
13 }, 13 },
14 onLaunch: function(options) { 14 onLaunch: async function(options) {
15 console.log('App Launch', options); 15 console.log('App Launch', options);
16 this.globalData.baseUrl_api = config.baseUrl_api; 16 this.globalData.baseUrl_api = config.baseUrl_api;
17 17
18 let userName = uni.getStorageSync('userName') 18 let userName = uni.getStorageSync('userName')
19 if (userName) { 19 if (userName) {
20 getInfo().then(() => { 20 await getInfo(this)
21 this.globalData.isLogin = true 21 this.globalData.isLogin = true
22 // 道馆用户跳转到道馆首页
23 const deptType = this.globalData.deptType
24 const userType = this.globalData.userType
25
26 // 道馆判断:deptType=6 或者 userType='4'
27 if (deptType == 6 || deptType == '6' || userType == '4') {
22 uni.reLaunch({ 28 uni.reLaunch({
23 url: '/pages/index/home' 29 url: '/pages/index/daoGuanPerson'
24 }) 30 })
25 }).catch(() => { 31 } else {
26 uni.reLaunch({ 32 uni.reLaunch({
27 url: '/login/login' 33 url: '/pages/index/home'
28 }) 34 })
29 }) 35 }
30 return 36 return
31 } 37 }
32 38
...@@ -62,4 +68,4 @@ ...@@ -62,4 +68,4 @@
62 /*每个页面公共css */ 68 /*每个页面公共css */
63 @import '/common/uni.css'; 69 @import '/common/uni.css';
64 @import '/common/mystyle.scss'; 70 @import '/common/mystyle.scss';
65 </style>
...\ No newline at end of file ...\ No newline at end of file
71 </style>
......
...@@ -10,7 +10,13 @@ function pcLogin(data) { ...@@ -10,7 +10,13 @@ function pcLogin(data) {
10 params: data 10 params: data
11 }).then((res) => { 11 }).then((res) => {
12 uni.setStorageSync('token', 'Bearer ' + res.data.token) 12 uni.setStorageSync('token', 'Bearer ' + res.data.token)
13 pcLoginOpenId() 13 return new Promise((resolve) => {
14 pcLoginOpenId()
15 // 延迟一下确保 token 设置完成
16 setTimeout(() => {
17 resolve()
18 }, 100)
19 })
14 }).then(getInfo) 20 }).then(getInfo)
15 } 21 }
16 22
...@@ -98,14 +104,16 @@ function loginByPhone(phonenumber, code) { ...@@ -98,14 +104,16 @@ function loginByPhone(phonenumber, code) {
98 } 104 }
99 105
100 // 获取用户详细信息 106 // 获取用户详细信息
101 function getInfo() { 107 function getInfo(appInstance) {
102 return request({ 108 console.log('getInfo 开始调用')
103 url: '/getInfo', 109 return request({
104 method: 'get' 110 url: '/getInfo',
105 }).then(res => { 111 method: 'get'
106 const userStore = useUserStore() 112 }).then(res => {
107 const app = getApp() 113 console.log('getInfo 成功', res.data)
108 const user = res.data.user 114 const userStore = useUserStore()
115 const app = appInstance || getApp()
116 const user = res.data.user
109 117
110 uni.setStorageSync('userName', user.userName) 118 uni.setStorageSync('userName', user.userName)
111 uni.removeStorageSync('webUserName') 119 uni.removeStorageSync('webUserName')
...@@ -126,6 +134,12 @@ function getInfo() { ...@@ -126,6 +134,12 @@ function getInfo() {
126 } else { 134 } else {
127 app.globalData.userType = '3' 135 app.globalData.userType = '3'
128 } 136 }
137
138 console.log('getInfo跳转判断 - deptType:', deptType, 'userType:', app.globalData.userType)
139 // 道馆用户跳转道馆首页
140 return res
141 }).catch(err => {
142 console.error('getInfo 失败:', err)
129 }) 143 })
130 } 144 }
131 145
......
1 <template>
2 <view class="dao-guan-tab-bar">
3 <image
4 v-if="currentIndex >= 0"
5 :src="config.baseUrl_api + '/fs/static/img/toolbar.png'"
6 class="dg-tab-bar-bg"
7 mode="scaleToFill"
8 :style="{ left: tabBgLeft }"
9 ></image>
10 <view
11 v-for="(item, index) in tabs"
12 :key="index"
13 class="dg-tab-item"
14 :class="{ active: currentIndex === index }"
15 @click="handleClick(index, item.url)"
16 >
17 <image :src="currentIndex === index ? item.activeIcon : item.icon" class="dg-tab-icon"></image>
18 <text class="dg-tab-text">{{ item.text }}</text>
19 </view>
20 </view>
21 </template>
22
23 <script setup>
24 import config from '@/config.js'
25 import { computed, ref } from 'vue'
26
27 const props = defineProps({
28 currentIndex: {
29 type: Number,
30 default: 0
31 }
32 })
33
34 const emit = defineEmits(['switch'])
35 const switching = ref(false)
36
37 const tabs = [
38 { text: '人员', url: '/pages/index/daoGuanPerson', icon: '/static/img/tool01.png', activeIcon: '/static/img/tool01_dwn.png' },
39 { text: '订单', url: '/pages/index/daoGuanOrder', icon: '/static/img/tool02.png', activeIcon: '/static/img/tool02_dwn.png' },
40 { text: '通知', url: '/pages/index/daoGuanNotice', icon: '/static/img/tool03.png', activeIcon: '/static/img/tool03_dwn.png' },
41 { text: '级位', url: '/pages/index/daoGuanLevel', icon: '/static/img/tool04.png', activeIcon: '/static/img/tool04_dwn.png' },
42 { text: '我的', url: '/pages/index/daoGuanMy', icon: '/static/img/tool05.png', activeIcon: '/static/img/tool05_dwn.png' },
43 ]
44
45 const tabBgLeft = computed(() => {
46 if (props.currentIndex < 0) return '0'
47 return `${props.currentIndex * 20}%`
48 })
49
50 const handleClick = (index, url) => {
51 if (switching.value || index === props.currentIndex) return
52
53 switching.value = true
54 emit('switch', index, url)
55
56 uni.redirectTo({
57 url,
58 fail: () => {
59 switching.value = false
60 }
61 })
62 }
63 </script>
64
65 <style lang="scss" scoped>
66 .dao-guan-tab-bar {
67 position: fixed;
68 bottom: 0;
69 left: 0;
70 right: 0;
71 height: 120rpx;
72 display: flex;
73 justify-content: flex-start;
74 align-items: stretch;
75 padding-bottom: env(safe-area-inset-bottom);
76 z-index: 9999;
77 background-color: #d9d9d9;
78 overflow: hidden;
79 }
80
81 .dg-tab-bar-bg {
82 position: absolute;
83 top: 0rpx;
84 width: 20%;
85 height: calc(100% - 35rpx);
86 z-index: 0;
87 transition: left 0.3s ease;
88 pointer-events: none;
89 }
90
91 .dg-tab-item {
92 display: flex;
93 flex-direction: column;
94 align-items: center;
95 justify-content: center;
96 width: 20%;
97 height: 100%;
98 position: relative;
99 z-index: 1;
100 }
101
102 .dg-tab-icon {
103 width: 50rpx;
104 height: 50rpx;
105 margin-bottom: 4rpx;
106 }
107
108 .dg-tab-text {
109 font-size: 20rpx;
110 color: #666;
111 }
112
113 .dg-tab-item.active .dg-tab-text {
114 color: #C30D23;
115 font-weight: bold;
116 }
117 </style>
1 <template> 1 <template>
2 <view class="role-entry-page"> 2 <view class="role-entry-page">
3 <!-- 全屏背景图 --> 3 <!-- 全屏背景图 -->
4 <image :src="config.loginImage_api + '/fs/static/dg/bg@3x.png'" class="page-bg" mode="aspectFill"></image> 4 <image :src="config.baseUrl_api + '/fs/static/img/home_bg.png'" class="page-bg" mode="aspectFill"></image>
5 5
6 <!-- 顶部 Logo 区域 --> 6 <!-- 顶部 Logo 区域 -->
7 <view class="header-wrapper"> 7 <!-- <view class="header-wrapper">
8 <view class="logo-box"> 8 <view class="logo-box">
9 <image :src="config.loginImage_api + '/fs/static/dg/ztx_b.svg'" class="logo" mode="aspectFit"></image> 9 <image :src="config.loginImage_api + '/fs/static/dg/ztx_b.svg'" class="logo" mode="aspectFit"></image>
10 </view> 10 </view>
11 </view> 11 </view> -->
12 12
13 <!-- 功能按钮区域 --> 13 <!-- 功能按钮区域 -->
14 <view class="btn-container"> 14 <view class="btn-container">
15 <view @click="goToPage('/personal/addVip_per')"> 15 <view
16 <image :src="config.loginImage_api + '/fs/static/dg/btn01@3x.png'" class="btn-item"></image> 16 class="entry-btn"
17 </view> 17 :class="{ active: activeEntry === 'unit' }"
18 <view @click="goToPage('/personal/home')"> 18 @click="goUnitLogin"
19 <image :src="config.loginImage_api + '/fs/static/dg/btn02@3x.png'" class="btn-item"></image> 19 >
20 </view> 20 <image :src="activeEntry === 'unit' ? '/static/img/home_btn2.png' : '/static/img/home_btn.png'" class="btn-bg" mode="scaleToFill"></image>
21 <view @click="goToPage('/login/loginC')"> 21 <text>单位会员入口</text>
22 <image :src="config.loginImage_api + '/fs/static/dg/btn03@3x.png'" class="btn-item"></image> 22 </view>
23 </view> 23
24 </view> 24 <view
25 25 class="entry-btn"
26 26 :class="{ active: activeEntry === 'personal' }"
27 </view> 27 @click="showLoginPopup"
28 </template> 28 >
29 <script setup> 29 <image :src="activeEntry === 'personal' ? '/static/img/home_btn2.png' : '/static/img/home_btn.png'" class="btn-bg" mode="scaleToFill"></image>
30 import {ref} from 'vue' 30 <text>个人会员入口</text>
31 import {onShow} from '@dcloudio/uni-app' 31 </view>
32 import config from '@/config.js' 32 </view>
33 33
34 onShow(() => { 34 <!-- 个人会员登录注册弹框 -->
35 uni.hideLoading(); 35 <uni-popup ref="loginPopup" :mask-click="true" type="center" @change="handlePopupChange">
36 }) 36 <view class="login-popup-content">
37 37 <!-- <view class="popup-title">请选择办理方式</view> -->
38 const goToPage = (url) => { 38 <view class="popup-btn active-btn" @click="goToPage('/personal/addVip_per')">
39 uni.navigateTo({ 39 个人会员注册
40 url, 40 </view>
41 }) 41 <view class="popup-btn plain-btn" @click="goToPage('/personal/home')">
42 } 42 个人会员登录
43 </script> 43 </view>
44 <style lang="scss" scoped> 44 </view>
45 .role-entry-page { 45 </uni-popup>
46 width: 100%; 46
47 min-height: 100vh; 47 </view>
48 position: relative; 48 </template>
49 padding: 20rpx; 49 <script setup>
50 box-sizing: border-box; 50 import {ref} from 'vue'
51 } 51 import {onShow} from '@dcloudio/uni-app'
52 52 import config from '@/config.js'
53 .page-bg { 53
54 position: absolute; 54 const loginPopup = ref(null)
55 top: 0; 55 const activeEntry = ref('')
56 left: 0; 56
57 width: 100%; 57 onShow(() => {
58 height: 100%; 58 uni.hideLoading();
59 z-index: -1; 59 })
60 } 60
61 61 const showLoginPopup = () => {
62 .header-wrapper { 62 activeEntry.value = 'personal'
63 text-align: center; 63 loginPopup.value.open()
64 // padding: 40rpx 0; 64 }
65 border-radius: 16rpx; 65
66 margin-top: 100rpx; 66 const goUnitLogin = () => {
67 } 67 activeEntry.value = 'unit'
68 68 uni.navigateTo({
69 .btn-container { 69 url: '/login/loginC',
70 display: flex; 70 })
71 flex-direction: column; 71 }
72 align-items: center; 72
73 margin: 0 auto; 73 const goToPage = (url) => {
74 74 loginPopup.value?.close()
75 img, image { 75 uni.navigateTo({
76 width: 509rpx; 76 url,
77 height: 117rpx; 77 })
78 margin: 40rpx 0; 78 }
79 79
80 } 80 const handlePopupChange = (e) => {
81 } 81 if (!e.show && activeEntry.value === 'personal') {
82 82 activeEntry.value = ''
83 .loading-overlay { 83 }
84 position: fixed; 84 }
85 top: 0; 85 </script>
86 left: 0; 86 <style lang="scss" scoped>
87 right: 0; 87 .role-entry-page {
88 bottom: 0; 88 width: 100%;
89 background-color: rgba(0, 0, 0, 0.5); 89 min-height: 100vh;
90 display: flex; 90 position: relative;
91 justify-content: center; 91 padding: 20rpx 0;
92 align-items: center; 92 box-sizing: border-box;
93 z-index: 999; 93 overflow: hidden;
94 } 94 }
95 95
96 .loading-content { 96 .page-bg {
97 color: white; 97 position: absolute;
98 font-size: 28rpx; 98 top: 0;
99 } 99 left: 0;
100 </style> 100 width: 100%;
101 height: 100%;
102 z-index: -1;
103 }
104
105 .header-wrapper {
106 text-align: center;
107 // padding: 40rpx 0;
108 border-radius: 16rpx;
109 margin-top: 100rpx;
110 }
111
112 .btn-container {
113 display: flex;
114 flex-direction: column;
115 align-items: center;
116 margin: 0 auto;
117 padding-top: 1040rpx;
118 gap: 52rpx;
119 }
120
121 .entry-btn {
122 position: relative;
123 width: 424rpx;
124 height: 86rpx;
125 display: flex;
126 align-items: center;
127 justify-content: center;
128 color: #2f2f2f;
129 font-size: 34rpx;
130 font-weight: 700;
131 letter-spacing: 2rpx;
132 }
133
134 .entry-btn.active {
135 color: #fff;
136 }
137
138 .btn-bg {
139 position: absolute;
140 inset: 0;
141 width: 100%;
142 height: 100%;
143 }
144
145 .entry-btn text {
146 position: relative;
147 z-index: 1;
148 }
149
150 .loading-overlay {
151 position: fixed;
152 top: 0;
153 left: 0;
154 right: 0;
155 bottom: 0;
156 background-color: rgba(0, 0, 0, 0.5);
157 display: flex;
158 justify-content: center;
159 align-items: center;
160 z-index: 999;
161 }
162
163 .loading-content {
164 color: white;
165 font-size: 28rpx;
166 }
167
168 .login-popup-content {
169 width: 560rpx;
170 background: #fff;
171 border-radius: 28rpx;
172 padding: 42rpx 42rpx 50rpx;
173 display: flex;
174 flex-direction: column;
175 align-items: center;
176 box-shadow: 0 20rpx 60rpx rgba(50, 0, 0, 0.25);
177 }
178
179 .popup-title {
180 margin-bottom: 22rpx;
181 color: #222;
182 font-size: 34rpx;
183 font-weight: 700;
184 }
185
186 .popup-btn {
187 position: relative;
188 width: 424rpx;
189 height: 86rpx;
190 line-height: 86rpx;
191 text-align: center;
192 border-radius: 16rpx;
193 font-size: 34rpx;
194 font-weight: 700;
195 margin: 18rpx 0;
196 box-sizing: border-box;
197 }
198
199 .active-btn {
200 background: linear-gradient(90deg, #ff9a00 0%, #e50012 100%);
201 color: #fff;
202 }
203
204 .plain-btn {
205 background: #fff;
206 color: #2f2f2f;
207 border: 4rpx solid #0b94d2;
208 box-shadow: inset 4rpx 0 0 #f7a100;
209 }
210 </style>
......
...@@ -118,25 +118,29 @@ ...@@ -118,25 +118,29 @@
118 <view class="popup-title">系统提示</view> 118 <view class="popup-title">系统提示</view>
119 <view class="popup-content"> 119 <view class="popup-content">
120 <view class="popup-text">尊敬的用户,您好!</view> 120 <view class="popup-text">尊敬的用户,您好!</view>
121 <view class="popup-text">在开始注册团体会员前,请您提前准备好以下材料,以便顺利完成申请</view> 121 <view class="popup-text">开始注册单位会员前,请提前准备以下材料(建议拍照或扫描,确保文字清晰、无遮挡)</view>
122 <view class="popup-item"> 122 <view class="popup-item">
123 <text class="popup-num ml10">1.</text> 123 <text class="popup-num ml10">1.</text>
124 单位营业执照 124 单位营业执照
125 </view> 125 </view>
126 <view class="popup-desc">请提供清晰的营业执照原件照片或扫描件(加盖公章更佳)</view> 126 <view class="popup-desc">原件照片或扫描件(加盖公章更佳)</view>
127 <view class="popup-item"> 127 <view class="popup-item">
128 <text class="popup-tip">!</text> 128 <text class="popup-tip">!</text>
129 <text class="popup-num"> 2.</text> 129 <text class="popup-num"> 2.</text>
130 法人身份证正反面照片 130 法人身份证
131 </view> 131 </view>
132 <view class="popup-desc">请分别上传身份证正面及反面清晰照片</view> 132 <view class="popup-desc">正、反面清晰照片(信息完整、无模糊)</view>
133 <view class="popup-desc">确保信息完整、无遮挡、无模糊</view> 133 <!-- <view class="popup-desc">确保信息完整、无遮挡、无模糊</view> -->
134 <view class="popup-item"> 134 <view class="popup-item">
135 <text class="popup-num ml10">3.</text> 135 <text class="popup-num ml10">3.</text>
136 机构照片 136 机构照片
137 </view> 137 </view>
138 <view class="popup-desc">请提供体现单位实际经营或办公环境的照片1-2张</view> 138 <view class="popup-desc">1–2张能体现单位真实经营或办公环境的照片,例如:门头、办公场所、活动场地等</view>
139 <view class="popup-desc">如门头、办公场所、活动场地等(能展示机构真实存在即可)</view> 139 <!-- <view class="popup-desc">如门头、办公场所、活动场地等(能展示机构真实存在即可)</view> -->
140 <view class="popup-text">
141 <!-- <text class="popup-num ml10">3.</text> -->
142 感谢您的配合,祝您注册顺利!
143 </view>
140 </view> 144 </view>
141 <view class="popup-btns"> 145 <view class="popup-btns">
142 <view class="popup-btn cancel" @click="closeRegisterPopup">取消</view> 146 <view class="popup-btn cancel" @click="closeRegisterPopup">取消</view>
...@@ -151,7 +155,7 @@ ...@@ -151,7 +155,7 @@
151 import {onLoad, onReady} from '@dcloudio/uni-app'; 155 import {onLoad, onReady} from '@dcloudio/uni-app';
152 import {ref, nextTick} from 'vue' 156 import {ref, nextTick} from 'vue'
153 import config from '@/config.js' 157 import config from '@/config.js'
154 import {getCodeImg, getSmsCodeImg, pcLogin, loginByPhone} from '@/common/login.js' 158 import {getCodeImg, getSmsCodeImg, pcLogin, loginByPhone, getInfo} from '@/common/login.js'
155 159
156 const isActive = ref(0) 160 const isActive = ref(0)
157 const agree = ref(false) 161 const agree = ref(false)
...@@ -182,6 +186,14 @@ const countDown = ref({ ...@@ -182,6 +186,14 @@ const countDown = ref({
182 186
183 const app = getApp() 187 const app = getApp()
184 188
189 function goHomeAfterLogin() {
190 const deptType = app.globalData.deptType
191 const userType = app.globalData.userType
192 uni.reLaunch({
193 url: (deptType == 6 || deptType == '6' || userType == '4') ? '/pages/index/daoGuanPerson' : '/pages/index/home'
194 })
195 }
196
185 onLoad(() => { 197 onLoad(() => {
186 getCode() 198 getCode()
187 if (uni.showShareMenu) { 199 if (uni.showShareMenu) {
...@@ -220,9 +232,12 @@ function login() { ...@@ -220,9 +232,12 @@ function login() {
220 } 232 }
221 if (loading.value) return; 233 if (loading.value) return;
222 loading.value = true 234 loading.value = true
223 pcLogin(form.value).then((res) => { 235 pcLogin(form.value).then(() => {
224 app.globalData.isLogin = true 236 app.globalData.isLogin = true
225 uni.redirectTo({url: '/pages/index/home'}) 237 goHomeAfterLogin()
238 }).catch((err) => {
239 console.error('登录失败:', err)
240 uni.showToast({title: '登录失败', icon: 'none'})
226 }).finally(() => { 241 }).finally(() => {
227 loading.value = false 242 loading.value = false
228 }) 243 })
...@@ -244,9 +259,8 @@ function login() { ...@@ -244,9 +259,8 @@ function login() {
244 loading.value = true 259 loading.value = true
245 loginByPhone(form2.value.telNo, form2.value.code) 260 loginByPhone(form2.value.telNo, form2.value.code)
246 .then(() => { 261 .then(() => {
247 loading.value = false
248 app.globalData.isLogin = true 262 app.globalData.isLogin = true
249 uni.redirectTo({url: '/pages/index/home'}) 263 goHomeAfterLogin()
250 }).finally(() => { 264 }).finally(() => {
251 loading.value = false 265 loading.value = false
252 }) 266 })
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 <!-- 温馨提示 --> 22 <!-- 温馨提示 -->
23 <view v-if="form.selfSelect == '1'" class="tip-box"> 23 <view v-if="form.selfSelect == '1'" class="tip-box">
24 <text class="tip-text">温馨提示: 24 <text class="tip-text">温馨提示:
25 您可以自行录入考官信息,如果暂时没有合适的考官,也可以选择由省跆协指派(支持多选)进行考点申报,同时请尽快完成考点考官的认证。 25 您可以自行录入考官信息,如果暂时没有考官,可以选择由省跆协指派进行考点申报,请尽快完成考点考官的认证。
26 </text> 26 </text>
27 </view> 27 </view>
28 28
......
...@@ -48,8 +48,12 @@ ...@@ -48,8 +48,12 @@
48 48
49 <!-- 金额说明 --> 49 <!-- 金额说明 -->
50 <view class="card notice-card"> 50 <view class="card notice-card">
51 <view class="notice-line">1. 请通过网上银行(网银)或银行柜台或手机银行向以下账号划转款项。</view> 51 <view class="danger-title">
52 <view class="notice-line">2. 转账金额与订单金额必须保持一致,不得多转、少转。</view> 52 <text>请使用认证机构下的账号进行对公转账。</text>
53 </view>
54 <view class="notice-line">1. 本订单将为您保留7天,请您及时支付;逾期未支付,订单将自动取消。</view>
55 <view class="notice-line">2. 请通过网上银行(网银)或银行柜台或手机银行向以下账号划转款项。</view>
56 <view class="notice-line">3. 转账金额与订单金额必须保持一致,不得多转、少转。</view>
53 </view> 57 </view>
54 58
55 <!-- 温馨提示 --> 59 <!-- 温馨提示 -->
...@@ -293,6 +297,14 @@ function handelClose() { ...@@ -293,6 +297,14 @@ function handelClose() {
293 } 297 }
294 } 298 }
295 } 299 }
300 .danger-title{
301 display: flex;
302 align-items: center;
303 font-size: 28rpx;
304 color: #F56C6C;
305 font-weight: 600;
306 margin-bottom: 16rpx;
307 }
296 308
297 /* 温馨提示 */ 309 /* 温馨提示 */
298 .warning-card { 310 .warning-card {
......
...@@ -20,6 +20,56 @@ ...@@ -20,6 +20,56 @@
20 } 20 }
21 }, 21 },
22 { 22 {
23 "path": "pages/index/daoGuanPerson",
24 "style": {
25 "navigationBarTitleText": "人员",
26 "backgroundColor": "#ffffff",
27 "navigationStyle": "custom",
28 "navigationBarTextStyle": "black",
29 "navigationBarBackgroundColor": "#ffffff"
30 }
31 },
32 {
33 "path": "pages/index/daoGuanLevel",
34 "style": {
35 "navigationBarTitleText": "级位",
36 "backgroundColor": "#ffffff",
37 "navigationStyle": "custom",
38 "navigationBarTextStyle": "black",
39 "navigationBarBackgroundColor": "#ffffff"
40 }
41 },
42 {
43 "path": "pages/index/daoGuanOrder",
44 "style": {
45 "navigationBarTitleText": "订单",
46 "backgroundColor": "#ffffff",
47 "navigationStyle": "custom",
48 "navigationBarTextStyle": "black",
49 "navigationBarBackgroundColor": "#ffffff"
50 }
51 },
52 {
53 "path": "pages/index/daoGuanNotice",
54 "style": {
55 "navigationBarTitleText": "通知",
56 "backgroundColor": "#ffffff",
57 "navigationStyle": "custom",
58 "navigationBarTextStyle": "black",
59 "navigationBarBackgroundColor": "#ffffff"
60 }
61 },
62 {
63 "path": "pages/index/daoGuanMy",
64 "style": {
65 "navigationBarTitleText": "我的",
66 "backgroundColor": "#ffffff",
67 "navigationStyle": "custom",
68 "navigationBarTextStyle": "black",
69 "navigationBarBackgroundColor": "#ffffff"
70 }
71 },
72 {
23 "path": "pages/webview/webview", 73 "path": "pages/webview/webview",
24 "style": { 74 "style": {
25 "navigationBarTitleText": "中国跆拳道协会", 75 "navigationBarTitleText": "中国跆拳道协会",
...@@ -189,6 +239,7 @@ ...@@ -189,6 +239,7 @@
189 } 239 }
190 } 240 }
191 ], 241 ],
242
192 "globalStyle": { 243 "globalStyle": {
193 "navigationStyle": "default", 244 "navigationStyle": "default",
194 "navigationBarTextStyle": "black", 245 "navigationBarTextStyle": "black",
......
1 <template>
2 <view class="level-page">
3 <view class="hero">
4 <image class="hero-bg" :src="config.baseUrl_api + '/fs/static/img/top.png'" mode="aspectFill"></image>
5 <view class="hero-brand">
6 <view class="brand-cn">中国跆拳道协会</view>
7 <view class="brand-en">CHINESE TAEKWONDO ASSOCIATION</view>
8 </view>
9 </view>
10
11 <view class="content-panel">
12 <image class="panel-bg" :src="config.baseUrl_api + '/fs/static/img/red_bg2.png'" mode="scaleToFill"></image>
13 <view class="panel-content">
14 <view class="section-title">
15 <view class="title-cn">级位考试</view>
16 <view style="width:50rpx;height:8rpx;background:#C30D23;margin-top:20rpx;"></view>
17 <view class="title-en">LEVEL EXAM</view>
18 </view>
19
20 <view class="level-grid">
21 <image class="level-card" :src="config.baseUrl_api + '/fs/static/img/jw_btn01.png'" mode="aspectFit" @click="goPath('/level/addApply')"></image>
22 <image class="level-card" :src="config.baseUrl_api + '/fs/static/img/jw_btn02.png'" mode="aspectFit" @click="goPath('/personalVip/addChangeLevel')"></image>
23 <image class="level-card" :src="config.baseUrl_api + '/fs/static/img/jw_btn03.png'" mode="aspectFit" @click="goPath('/level/apply')"></image>
24 <image class="level-card" :src="config.baseUrl_api + '/fs/static/img/jw_btn04.png'" mode="aspectFit" @click="goPath('/personalVip/changeLevel')"></image>
25 </view>
26 </view>
27 </view>
28
29 <dao-guan-tab-bar :currentIndex="3" @switch="onTabSwitch" />
30 </view>
31 </template>
32
33 <script setup>
34 import config from '@/config.js'
35 import DaoGuanTabBar from '@/components/dao-guan-tab-bar.vue'
36
37 const onTabSwitch = () => {
38 // tab switch handled by component
39 }
40
41 const goPath = (url) => {
42 uni.navigateTo({ url })
43 }
44 </script>
45
46 <style lang="scss" scoped>
47 .level-page {
48 position: relative;
49 min-height: 100vh;
50 overflow-x: hidden;
51 background: #ededf0;
52 overflow-y: hidden;
53 // padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
54 box-sizing: border-box;
55 }
56
57 .hero {
58 position: relative;
59 height: 1060rpx;
60 overflow: hidden;
61 z-index: 1;
62 }
63
64 .hero-bg {
65 position: absolute;
66 left: 0;
67 top: -116px;
68 width: 100%;
69 height: 100%;
70 }
71
72 .hero-brand {
73 position: relative;
74 z-index: 1;
75 padding: calc(env(safe-area-inset-top) + 170rpx) 44rpx 0;
76 color: #fff;
77 }
78
79 .brand-cn {
80 font-size: 38rpx;
81 letter-spacing: 2rpx;
82 }
83
84 .brand-en {
85 margin-top: 8rpx;
86 color: rgba(255, 255, 255, 0.62);
87 font-size: 16rpx;
88 }
89
90 .content-panel {
91 position: relative;
92 z-index: 3;
93 min-height: 760rpx;
94 margin-top: -300rpx;
95 overflow: visible;
96 }
97
98 .panel-bg {
99 position: absolute;
100 left: 0;
101 top: -674rpx;
102 z-index:10;
103 width: 100%;
104 height: 1700rpx;
105 }
106
107 .panel-content {
108 position: relative;
109 z-index: 12;
110 padding: 0rpx 46rpx 40rpx;
111 }
112
113 .section-title {
114 margin-bottom: 30rpx;
115 }
116
117 .title-cn {
118 color: #2a2a2a;
119 font-size: 58rpx;
120 line-height: 1;
121 }
122
123 .title-en {
124 margin-top: 12rpx;
125 color: #9a9a9a;
126 font-size: 24rpx;
127 font-weight: 700;
128 }
129
130 .level-grid {
131 display: grid;
132 grid-template-columns: repeat(2, 1fr);
133 gap: 14rpx 14rpx;
134 }
135
136 .level-card {
137 width: 100%;
138 height: 236rpx;
139 border-radius: 10rpx;
140 }
141 </style>
1 <template>
2 <view class="page dao-my-page">
3 <image class="page-red-bg" :src="config.baseUrl_api + '/fs/static/img/red_bg.png'" mode="scaleToFill"></image>
4 <view class="profile-hero">
5 <view class="hero-content">
6 <view class="profile-row">
7 <view class="avatar-wrap">
8 <image v-if="state.user.avatar" :src="state.user.avatar" mode="aspectFill"/>
9 <image v-else :src="config.baseUrl_api + '/fs/static/nodata.png'" mode="aspectFill"/>
10 </view>
11 <!-- <view class="profile-main">
12 <view class="name-row">
13 <view class="dept-name">{{ state.user?.dept?.deptName || deptInfo.deptName || memberInfo.name || '--' }}</view>
14 <view class="member-badge">
15 <text class="badge-star"></text>
16 <text>金牌会员</text>
17 </view>
18 </view>
19 <view class="id-row">
20 <text>ID:{{ memberInfo.menCode || memberInfo.memberCode || memberInfo.memberNo || state.user?.userName || '--' }}</text>
21 <text class="join-days">您已加入{{ joinDays }}</text>
22 </view>
23 </view> -->
24 </view>
25 <view class="motto">每一次的成功都不是偶然,是千锤百炼,永不放弃的结果。{{ state.user?.dept?.deptName || '龙威天成跆拳道馆' }},以专业铸就辉煌!</view>
26 <view class="edit-btn" @click="goPath('/myCenter/teamInfo')">修改资料</view>
27 </view>
28 </view>
29
30 <view class="menu-panel">
31 <image class="menu-bg" :src="config.baseUrl_api + '/fs/static/img/red_bg2.png'" mode="scaleToFill"></image>
32 <view class="menu-item" @click="goPath('/myCenter/teamInfo')">
33 <view class="menu-left">
34 <image class="menu-icon" :src="config.baseUrl_api + '/fs/static/img/user01.png'" mode="aspectFit"></image>
35 <text>单位信息</text>
36 </view>
37 <text class="arrow">></text>
38 </view>
39
40 <view class="menu-item" @click="goPath('/myCenter/auth')">
41 <view class="menu-left">
42 <image class="menu-icon" :src="config.baseUrl_api + '/fs/static/img/user02.png'" mode="aspectFit"></image>
43 <text>会员认证</text>
44 </view>
45 <text class="arrow">></text>
46 </view>
47
48 <view class="menu-item" @click="goPath('/myCenter/safe')">
49 <view class="menu-left">
50 <image class="menu-icon" :src="config.baseUrl_api + '/fs/static/img/user03.png'" mode="aspectFit"></image>
51 <text>账号安全</text>
52 </view>
53 <text class="arrow">></text>
54 </view>
55 </view>
56
57 <view class="logout-area">
58 <button class="logout-btn" @click="loginOut">退出登录</button>
59 </view>
60
61 <!-- 底部导航 -->
62 <dao-guan-tab-bar :currentIndex="4" @switch="onTabSwitch" />
63 </view>
64 </template>
65
66 <script setup>
67 import * as api from '@/common/api.js';
68 import * as loginServer from '@/common/login.js';
69 import config from '@/config.js'
70 import {
71 onLoad,
72 onShow,
73 onReady,
74 onPullDownRefresh
75 } from '@dcloudio/uni-app';
76 import {
77 ref, reactive, computed,
78 getCurrentInstance
79 } from 'vue';
80 import DaoGuanTabBar from '@/components/dao-guan-tab-bar.vue'
81
82
83 const {
84 proxy
85 } = getCurrentInstance()
86 const app = getApp();
87 const userType = ref('1')
88 const memberInfo = ref({})
89 const deptInfo = ref({})
90 let proId;
91 const svId = ref(null);
92 const numData = ref({});
93
94 const messageList = ref([])
95 const state = reactive({
96 user: {},
97 roleGroup: {},
98 postGroup: {}
99 })
100
101 const joinDays = computed(() => {
102 const value = memberInfo.value.createTime || memberInfo.value.joinTime || memberInfo.value.createDate
103 if (!value) return '--'
104 const start = new Date(String(value).replace(/-/g, '/')).getTime()
105 if (!start) return '--'
106 const days = Math.floor((Date.now() - start) / (24 * 60 * 60 * 1000)) + 1
107 return days > 0 ? days : 1
108 })
109 onShow(() => {
110 if (app.globalData.isLogin) {
111 init()
112 } else {
113 app.firstLoadCallback = () => {
114 init()
115 };
116 }
117 })
118 onLoad(option => {
119 if (option.scene) {
120 proId = decodeURIComponent(option.scene);
121 } else {
122 proId = option.proId;
123 }
124 if (uni.showShareMenu) {
125 uni.showShareMenu({
126 withShareTicket: true,
127 menus: ['shareAppMessage', 'shareTimeline']
128 });
129 }
130 });
131
132 function loginOut() {
133 uni.showModal({
134 content: `确认退出吗?`,
135 success: function (res) {
136 if (res.confirm) {
137 loginServer.logout().finally(() => {
138 let path = '/login/login';
139 uni.reLaunch({
140 url: path
141 });
142 })
143 }
144 }
145 })
146 }
147
148 function getUser() {
149 api.getUserProfile().then((response) => {
150 state.user = response.data.user
151 if (state.user.avatar && state.user.avatar.indexOf('http') == -1) {
152 state.user.avatar = config.baseUrl_api + state.user.avatar
153 }
154 state.roleGroup = response.data.roleGroup
155 state.postGroup = response.data.postGroup
156 uni.hideLoading();
157 })
158 }
159
160 function init() {
161 uni.showLoading({
162 title: '加载中'
163 });
164 getUser()
165 loginServer.getMyOwnMemberInfo().then(res => {
166 userType.value = app.globalData.userType
167 memberInfo.value = app.globalData.memberInfo
168 deptInfo.value = app.globalData.dept || {}
169 uni.hideLoading();
170 })
171 }
172
173 function goPath(url) {
174 uni.navigateTo({
175 url: url
176 })
177 }
178
179 function onTabSwitch(index, url) {
180 // tab switch handled by component
181 }
182
183 </script>
184 <style lang="scss" scoped>
185 .dao-my-page {
186 position: relative;
187 min-height: 100vh;
188 width: 100vw;
189 overflow-x: hidden;
190 box-sizing: border-box;
191 padding-bottom: calc(210rpx + env(safe-area-inset-bottom));
192 background: #ededf0;
193 }
194
195 .page-red-bg {
196 position: absolute;
197 left: 0;
198 top: 0;
199 z-index: 0;
200 width: 100%;
201 height: 720rpx;
202 }
203
204 .profile-hero {
205 position: relative;
206 z-index: 1;
207 min-height: 460rpx;
208 }
209
210 .hero-content {
211 position: relative;
212 z-index: 2;
213 padding: calc(env(safe-area-inset-top) + 126rpx) 48rpx 0;
214 color: #fff;
215 }
216
217 .profile-row {
218 display: flex;
219 align-items: center;
220 }
221
222 .avatar-wrap {
223 width: 132rpx;
224 height: 132rpx;
225 padding: 6rpx;
226 flex: 0 0 132rpx;
227 overflow: hidden;
228 border-radius: 50%;
229 background: #fff;
230 box-shadow: 0 8rpx 26rpx rgba(65, 0, 0, 0.28);
231
232 image {
233 width: 100%;
234 height: 100%;
235 border-radius: 50%;
236 }
237 }
238
239 .profile-main {
240 flex: 1;
241 min-width: 0;
242 margin-left: 26rpx;
243 }
244
245 .name-row,
246 .id-row {
247 display: flex;
248 align-items: center;
249 justify-content: space-between;
250 }
251
252 .dept-name {
253 max-width: 330rpx;
254 overflow: hidden;
255 white-space: nowrap;
256 text-overflow: ellipsis;
257 font-size: 34rpx;
258 font-weight: 700;
259 }
260
261 .member-badge {
262 display: flex;
263 align-items: center;
264 gap: 8rpx;
265 color: #dba12d;
266 font-size: 24rpx;
267 white-space: nowrap;
268 }
269
270 .badge-star {
271 color: #f7c342;
272 font-size: 24rpx;
273 }
274
275 .id-row {
276 margin-top: 12rpx;
277 color: rgba(255, 255, 255, 0.86);
278 font-size: 26rpx;
279 }
280
281 .join-days {
282 margin-left: 18rpx;
283 white-space: nowrap;
284 }
285
286 .motto {
287 margin-top: 52rpx;
288 color: rgba(255, 255, 255, 0.86);
289 font-size: 24rpx;
290 line-height: 1.75;
291 }
292
293 .edit-btn {
294 width: 168rpx;
295 height: 48rpx;
296 margin: 34rpx 0 0 auto;
297 border-radius: 6rpx;
298 background: #fff;
299 color: #333;
300 font-size: 24rpx;
301 line-height: 48rpx;
302 text-align: center;
303 }
304
305 .menu-panel {
306 position: relative;
307 z-index: 2;
308 min-height: 560rpx;
309 margin-top: -72rpx;
310 padding: 178rpx 48rpx 0;
311 overflow: hidden;
312 }
313
314 .menu-bg {
315 position: absolute;
316 left: 0;
317 top: -400rpx;
318 z-index: 0;
319 width: 100%;
320 height: 1400rpx;
321 }
322
323 .menu-item {
324 position: relative;
325 z-index: 1;
326 display: flex;
327 align-items: center;
328 justify-content: space-between;
329 height: 132rpx;
330 color: #111;
331 font-size: 31rpx;
332 font-weight: 700;
333 }
334
335 .menu-left {
336 display: flex;
337 align-items: center;
338 }
339
340 .menu-icon {
341 width: 38rpx;
342 height: 38rpx;
343 margin-right: 18rpx;
344 }
345
346 .arrow {
347 color: #111;
348 font-size: 42rpx;
349 font-weight: 400;
350 line-height: 1;
351 }
352
353 .logout-area {
354 position: fixed;
355 left: 0;
356 right: 0;
357 bottom: calc(124rpx + env(safe-area-inset-bottom));
358 z-index: 9998;
359 padding: 16rpx 48rpx 18rpx;
360 background: transparent;
361 box-sizing: border-box;
362 }
363
364 .logout-btn {
365 height: 76rpx;
366 border-radius: 50rpx;
367 background: #ad181f;
368 color: #fff;
369 font-size: 28rpx;
370 line-height: 76rpx;
371 }
372
373 .logout-btn::after {
374 border: none;
375 }
376 </style>
1 <template>
2 <view class="notice-page">
3 <z-paging
4 ref="paging"
5 v-model="dataList"
6 class="notice-paging"
7 emptyViewImg="/static/nodata.png"
8 @query="queryList"
9 >
10 <template #top>
11 <view class="notice-hero">
12 <view class="hero-title-row">
13 <view>
14 <view class="hero-title">中国跆拳道协会</view>
15 <view class="hero-subtitle">CHINESE TAEKWONDO ASSOCIATION</view>
16 </view>
17 <view class="hero-page-title">
18 <text>协会资讯</text>
19 <view class="title-line"></view>
20 </view>
21 </view>
22
23 <view class="search-bar">
24 <uni-easyinput
25 v-model="query.keyword"
26 :input-border="false"
27 class="search-input"
28 placeholder="请输入公告标题"
29 placeholderStyle="font-size:28rpx;color:#999"
30 prefixIcon="search"
31 @confirm="handleSearch"
32 @clear="handleSearch"
33 />
34 <view class="search-btn" @click="handleSearch">搜索</view>
35 </view>
36 </view>
37
38 <!-- <view class="notice-tabs">
39 <view class="tab-item active">公告</view>
40 </view> -->
41 </template>
42
43 <view class="notice-list">
44 <view v-for="item in dataList" :key="item.id || item.noteId" class="notice-item" @click="goDetail(item)">
45 <view class="notice-title">{{ item.name || item.title || '--' }}</view>
46 <view v-if="item.introduction || item.remark || item.content" class="notice-summary">
47 {{ item.introduction || item.remark || item.content }}
48 </view>
49 <image
50 v-if="getCover(item)"
51 :src="getCover(item)"
52 class="notice-cover"
53 mode="aspectFill"
54 />
55 <view class="notice-meta">
56 <text>{{ formatDate(item.belongTime || item.createTime || item.publishTime) }}</text>
57 <!-- <view class="meta-right">
58 <text class="heart">♡</text>
59 <text>{{ item.readNum || item.views || item.likeNum || 0 }}</text>
60 <text class="more">...</text>
61 </view> -->
62 </view>
63 </view>
64 </view>
65 </z-paging>
66
67 <dao-guan-tab-bar :currentIndex="2" @switch="onTabSwitch" />
68 </view>
69 </template>
70
71 <script setup>
72 import { ref, reactive } from 'vue'
73 import * as api from '@/common/api.js'
74 import dayjs from 'dayjs'
75 import DaoGuanTabBar from '@/components/dao-guan-tab-bar.vue'
76
77 const dataList = ref([])
78 const paging = ref(null)
79 const query = reactive({
80 keyword: ''
81 })
82
83 const queryList = (pageNum, pageSize) => {
84 api.notice({
85 pageNum,
86 pageSize,
87 name: query.keyword
88 }).then(res => {
89 paging.value?.complete(res.rows || [])
90 }).catch(() => {
91 paging.value?.complete(false)
92 })
93 }
94
95 const handleSearch = () => {
96 paging.value?.reload()
97 }
98
99 const getCover = (item) => {
100 return item.coverUrl || item.cover || item.picUrl || item.imageUrl || item.imgUrl || ''
101 }
102
103 const formatDate = (value) => {
104 if (!value) return ''
105 return dayjs(value).format('YYYY-MM-DD')
106 }
107
108 const goDetail = (item) => {
109 uni.navigateTo({
110 url: `/pages/index/newsDetail?noteId=${item.noteId}`
111 })
112 }
113
114 const onTabSwitch = () => {
115 // tab switch handled by component
116 }
117 </script>
118
119 <style lang="scss" scoped>
120 .notice-page {
121 position: relative;
122 min-height: 100vh;
123 background: #ededf0;
124 box-sizing: border-box;
125 }
126
127 .notice-hero {
128 padding: calc(env(safe-area-inset-top) + 88rpx) 40rpx 34rpx;
129 background: linear-gradient(135deg, #b00005 0%, #760000 100%);
130 color: #fff;
131 }
132
133 .hero-title-row {
134 display: flex;
135 justify-content: space-between;
136 align-items: flex-end;
137 margin-bottom: 42rpx;
138 }
139
140 .hero-title {
141 font-size: 38rpx;
142 letter-spacing: 2rpx;
143 }
144
145 .hero-subtitle {
146 margin-top: 8rpx;
147 color: rgba(255, 255, 255, 0.6);
148 font-size: 16rpx;
149 }
150
151 .hero-page-title {
152 color: #f4b536;
153 font-size: 36rpx;
154 font-weight: 500;
155 text-align: right;
156 }
157
158 .title-line {
159 width: 54rpx;
160 height: 6rpx;
161 margin: 14rpx 0 0 auto;
162 border-radius: 10rpx;
163 background: #f4b536;
164 }
165
166 .search-bar {
167 display: flex;
168 align-items: center;
169 height: 64rpx;
170 border-radius: 34rpx;
171 background: #fff;
172 overflow: hidden;
173 }
174
175 .search-input {
176 flex: 1;
177
178 :deep(.uni-easyinput__content) {
179 height: 64rpx;
180 padding: 0 18rpx 0 28rpx;
181 border-radius: 34rpx;
182 background: #fff;
183 }
184 }
185
186 .search-btn {
187 width: 88rpx;
188 height: 52rpx;
189 margin-right: 6rpx;
190 border-radius: 28rpx;
191 background: #c91c34;
192 color: #fff;
193 font-size: 24rpx;
194 font-weight: 700;
195 line-height: 52rpx;
196 text-align: center;
197 }
198
199 .notice-tabs {
200 display: flex;
201 align-items: center;
202 padding: 24rpx 40rpx 8rpx;
203 }
204
205 .tab-item {
206 position: relative;
207 margin-right: 54rpx;
208 padding-bottom: 14rpx;
209 color: #555;
210 font-size: 30rpx;
211 }
212
213 .tab-item.active {
214 color: #c30d23;
215 font-weight: 700;
216 }
217
218 .tab-item.active::after {
219 content: '';
220 position: absolute;
221 left: 50%;
222 bottom: 0;
223 width: 52rpx;
224 height: 4rpx;
225 border-radius: 4rpx;
226 background: #c30d23;
227 transform: translateX(-50%);
228 }
229
230 .notice-paging {
231 height: 100vh;
232 background: #ededf0;
233 }
234
235 .notice-list {
236 padding: 0 10rpx calc(160rpx + env(safe-area-inset-bottom));
237 }
238
239 .notice-item {
240 margin-bottom: 34rpx;
241 background: #fff;
242 padding: 24rpx;
243 border-radius: 16rpx;
244 margin: 20rpx;
245 }
246
247 .notice-title {
248 color: #111;
249 font-size: 31rpx;
250 font-weight: 800;
251 line-height: 1.42;
252 }
253
254 .notice-summary {
255 display: -webkit-box;
256 margin-top: 12rpx;
257 overflow: hidden;
258 color: #666;
259 font-size: 25rpx;
260 line-height: 1.45;
261 text-overflow: ellipsis;
262 -webkit-box-orient: vertical;
263 -webkit-line-clamp: 2;
264 }
265
266 .notice-cover {
267 width: 100%;
268 height: 330rpx;
269 margin-top: 14rpx;
270 border-radius: 0;
271 background: #ddd;
272 }
273
274 .notice-meta {
275 display: flex;
276 align-items: center;
277 justify-content: space-between;
278 margin-top: 10rpx;
279 color: #999;
280 font-size: 24rpx;
281 }
282
283 .meta-right {
284 display: flex;
285 align-items: center;
286 gap: 8rpx;
287 }
288
289 .heart {
290 font-size: 28rpx;
291 }
292
293 .more {
294 margin-left: 14rpx;
295 letter-spacing: 2rpx;
296 }
297 </style>
1 <template>
2 <view :class="{ 'no-scroll': isPopupOpen }" class="order-page">
3 <view class="order-hero">
4 <view class="hero-title-row">
5 <view>
6 <view class="hero-title">中国跆拳道协会</view>
7 <view class="hero-subtitle">CHINESE TAEKWONDO ASSOCIATION</view>
8 </view>
9 <view class="hero-page-title">
10 <text>订单管理</text>
11 <view class="title-line"></view>
12 </view>
13 </view>
14
15 <view class="search-bar">
16 <uni-easyinput
17 v-model="queryParams.wfCode"
18 :input-border="false"
19 class="search-input"
20 placeholder="输入订单编号/名称/单位/日期"
21 placeholderStyle="font-size:28rpx;color:#999"
22 prefixIcon="search"
23 @blur="handelSearch"
24 @clear="handelSearch">
25 </uni-easyinput>
26 <view class="add-btn" @click="handelSearch">
27 <text class="add-text">搜索</text>
28 </view>
29 </view>
30 </view>
31
32 <view class="tab-bar">
33 <view
34 v-for="(tab, index) in tabs"
35 :key="index"
36 :class="{ active: currentTab === tab.type }"
37 class="tab-item"
38 @click="switchTab(tab.type)"
39 >
40 {{ tab.name }}
41 </view>
42 </view>
43
44 <view class="status-filter">
45 <view
46 v-for="(tab, index) in statusTabs"
47 :key="index"
48 :class="{ active: currentStatus === tab.type }"
49 class="status-filter-item"
50 @click="switchStatus(tab.type)"
51 >
52 {{ tab.name }}
53 </view>
54 <!-- <view class="filter-entry">
55 <text class="filter-icon"></text>
56 <text>筛选</text>
57 </view> -->
58 </view>
59
60 <!-- 订单列表 -->
61 <scroll-view
62 :scroll-enabled="!isPopupOpen"
63 :show-scrollbar="false"
64 class="order-list-scroll"
65 lower-threshold="200"
66 scroll-y
67 @scrolltolower="loadMore"
68 >
69 <view class="order-list">
70 <!-- 有数据才循环 -->
71 <!-- <view v-if="list.length > 0">-->
72 <!-- <view-->
73 <!-- v-for="(item, index) in list"-->
74 <!-- :key="index"-->
75 <!-- class="order-card"-->
76 <!-- @click="goToDetail(item)"-->
77 <!-- >-->
78 <!-- &lt;!&ndash; 订单头部:日期 + 状态 &ndash;&gt;-->
79 <!-- <view class="card-header">-->
80 <!-- <view class="date">-->
81 <!-- &lt;!&ndash; <image :src="config.baseUrl_api + '/fs/static/calendar@2x.png'" mode="widthFix" style="width:30rpx;height:30rpx;"/> &ndash;&gt;-->
82 <!-- &lt;!&ndash; &ndash;&gt;-->
83 <!-- <text class="value text-primary">{{ item.wfCode || '——' }}</text>-->
84 <!-- </view>-->
85 <!-- <view class="status-tags">-->
86 <!-- &lt;!&ndash; <view-->
87 <!-- class="status-tag"-->
88 <!-- :class="{-->
89 <!-- success: item.payStatus == 1,-->
90 <!-- danger: item.payStatus == 2,-->
91 <!-- pending: item.payStatus == 0-->
92 <!-- }"-->
93 <!-- >-->
94 <!-- {{ getStatusText(item.payStatus) }}-->
95 <!-- </view> &ndash;&gt;-->
96 <!-- <view-->
97 <!-- :class="{-->
98 <!-- 'status-wait': item.auditStatus == 0,-->
99 <!-- 'status-pending': item.auditStatus == 1,-->
100 <!-- 'status-success': item.auditStatus == 2,-->
101 <!-- 'status-danger': item.auditStatus == 3-->
102 <!-- }"-->
103 <!-- class="status-tag ml-10"-->
104 <!-- >-->
105 <!-- {{ getAuditStatusText(item.auditStatus) }}-->
106 <!-- </view>-->
107 <!-- </view>-->
108 <!-- </view>-->
109 <!-- -->
110 <!-- &lt;!&ndash; 订单编号、缴费编号 &ndash;&gt;-->
111 <!-- <view class="info-row">-->
112 <!-- <text class="label">订单编号:</text>-->
113 <!-- <text class="value">{{ item.tradeNo || '——' }}</text>-->
114 <!-- </view>-->
115 <!-- <view v-if="item.orderName" class="info-row">-->
116 <!-- <text class="label">缴费名称:</text>-->
117 <!-- <text class="value">{{ item.orderName || '' }}</text>-->
118 <!-- </view>-->
119 <!-- &lt;!&ndash; <view class="info-row">-->
120 <!-- <text class="label">缴费编号:</text>-->
121 <!-- -->
122 <!-- </view> &ndash;&gt;-->
123 <!-- -->
124 <!-- &lt;!&ndash; 核心:前2tab仅展示缴费年限,后2tab仅展示人数合计 &ndash;&gt;-->
125 <!-- <view v-if="item.content" class="info-section flex f-j-s">-->
126 <!-- &lt;!&ndash; 个人/单位会员(仅缴费年限) &ndash;&gt;-->
127 <!-- <view v-if="currentTab === '0' || currentTab === '1'" class="single-info">-->
128 <!-- <view class="label">缴费年限:</view>-->
129 <!-- <view class="value">{{ item.content.yearCount || 0 }}</view>-->
130 <!-- </view>-->
131 <!-- &lt;!&ndash; 级位/段位考试(仅人数合计) &ndash;&gt;-->
132 <!-- <view v-if="currentTab === '2' || currentTab === '3' || currentTab === '4'" class="single-info">-->
133 <!-- <view class="label">人数合计</view>-->
134 <!-- <view class="value">{{ item.content.personCount || 0 }}</view>-->
135 <!-- </view>-->
136 <!-- <view class="line"></view>-->
137 <!-- <view class="single-info">-->
138 <!-- <view class="label">订单状态</view>-->
139 <!-- <view :class="item.effect == 1 ? 'text-success' : 'text-warning'" class="value">-->
140 <!-- {{ item.effect == 1 ? '已生效' : '未生效' }}-->
141 <!-- </view>-->
142 <!-- </view>-->
143 <!-- <view class="line"></view>-->
144 <!-- <view class="single-info">-->
145 <!-- <view class="label">缴费状态</view>-->
146 <!-- <view-->
147 <!-- :class="{-->
148 <!-- 'text-primary': item.payStatus == 0,-->
149 <!-- 'text-success': item.payStatus == 1,-->
150 <!-- 'text-danger': item.payStatus == 2-->
151 <!-- }"-->
152 <!-- class="value"-->
153 <!-- >-->
154 <!-- {{ item.payStatus == 0 ? '待缴费' : item.payStatus == 1 ? '缴费成功' : '订单取消' }}-->
155 <!-- </view>-->
156 <!-- </view>-->
157 <!-- </view>-->
158 <!-- -->
159 <!-- &lt;!&ndash; 费用合计 + 缴费方式 &ndash;&gt;-->
160 <!-- <view class="price-section">-->
161 <!-- <view class="price-row">-->
162 <!-- <text class="price-label">费用合计</text>-->
163 <!-- <text class="price-value">¥{{ (Number(item.price) || 0).toFixed(2) }}</text>-->
164 <!-- </view>-->
165 <!-- <view class="price-row">-->
166 <!-- <text class="price-label">缴费方式</text>-->
167 <!-- <text class="price-value">{{ item.ziZhangBu ? '对公转账' : '民生付' }}</text>-->
168 <!-- </view>-->
169 <!-- </view>-->
170 <!-- -->
171 <!-- &lt;!&ndash; 按钮组:靠右紧凑展示 &ndash;&gt;-->
172 <!-- <view class="btn-group">-->
173 <!-- &lt;!&ndash; 已缴费:申请开票/已开票(需要审核通过才能开票) &ndash;&gt;-->
174 <!-- <template v-if="item.payStatus == 1 && item.invoiceStatus != 1&& item.auditStatus == 2 &&item.price>0">-->
175 <!-- <button :disabled="item.invoiceStatus === 1" class="btn btn-view-invoice" @click="makeInvoiceFN(item)">-->
176 <!-- 开票-->
177 <!-- </button>-->
178 <!-- </template>-->
179 <!-- &lt;!&ndash; 已开票:查看发票 &ndash;&gt;-->
180 <!-- <template v-if="item.invoiceStatus == 1">-->
181 <!-- <button class="btn btn-invoice" @click.stop="viewInvoice(item)">查看发票</button>-->
182 <!-- </template>-->
183 <!-- &lt;!&ndash; 未缴费:去缴费 + 取消订单 &ndash;&gt;-->
184 <!-- &lt;!&ndash; <template v-if="item.payStatus == 0">-->
185 <!-- <button class="btn btn-cancel" @click="handleCancel(item)">取消订单</button>-->
186 <!-- <button class="btn btn-pay" @click="handlePay(item)">去缴费</button>-->
187 <!-- </template> &ndash;&gt;-->
188 <!-- </view>-->
189 <!-- </view>-->
190 <!-- </view>-->
191
192 <!-- 有数据才循环 -->
193 <view v-if="list.length > 0">
194 <view
195 v-for="(item, index) in list"
196 :key="index"
197 class="order-card-new"
198 @click="goToDetail(item)"
199 >
200 <!-- 订单头部:日期 + 状态 -->
201 <view class="card-header">
202 <view class="date">
203 <view class="data-header">
204 <text class="member-label">{{ getOrderLabel(item) }}·</text>
205 <text class="value ">{{ item.orderName || '——' }}</text>
206 </view>
207 <text :class="{
208 'status-wait': item.auditStatus == 0,
209 'status-pending': item.auditStatus == 1,
210 'status-success': item.auditStatus == 2,
211 'status-danger': item.auditStatus == 3
212 }"
213 class="status-tag ">{{ getAuditStatusText(item.auditStatus) }}
214 </text>
215 </view>
216 </view>
217 <!-- <view class="card-header code-row">
218 <view class="date">
219 <view class="data-header">
220 <text class="value">
221 <text class="tradeNo">订单编号:</text>
222 {{ item.tradeNo || '——' }}
223 </text>
224 </view>
225 </view>
226 </view> -->
227 <!-- <view class="card-header code-row">
228 <view class="date">
229 <view class="data-header">
230 <text class="value">
231 <text class="tradeNo">缴费编号:</text>
232 {{ item.wfCode || '——' }}
233 </text>
234 </view>
235 </view>
236 </view> -->
237 <view class="member-time">
238 <view class="label">
239 <text class="star"></text>
240 {{ `${filterTime(item.genTime)}${filterType(item.type)}` }}
241 </view>
242 <view class="price">
243 <view>¥{{ item.price || '0.00' }}</view>
244 <view v-if="item.type==0" class="person">共{{ item.content?.allPersonCount || 0 }}人</view>
245 <view v-if="item.type==1" class="person">共{{ item.content?.yearCount || 0 }}年</view>
246 <view v-if="item.type==2||item.type==3||item.type==4" class="person">共{{
247 item.content?.personCount || 0
248 }}人
249 </view>
250 </view>
251 </view>
252
253 <!-- 核心:前2tab仅展示缴费年限,后2tab仅展示人数合计 -->
254 <!-- <view v-if="item.content" class="info-section flex f-j-s">
255 <view v-if="currentTab === '0' || currentTab === '1'" class="single-info">
256 <view class="label">缴费年限:</view>
257 <view class="value">{{ item.content.yearCount || 0 }}</view>
258 </view>
259 <view v-if="currentTab === '2' || currentTab === '3' || currentTab === '4'" class="single-info">
260 <view class="label">人数合计</view>
261 <view class="value">{{ item.content.personCount || 0 }}</view>
262 </view>
263 <view class="line"></view>
264 <view class="single-info">
265 <view class="label">订单状态</view>
266 <view :class="item.effect == 1 ? 'text-success' : 'text-warning'" class="value">
267 {{ item.effect == 1 ? '已生效' : '未生效' }}
268 </view>
269 </view>
270 <view class="line"></view>
271 <view class="single-info">
272 <view class="label">缴费状态</view>
273 <view
274 :class="{
275 'text-primary': item.payStatus == 0,
276 'text-success': item.payStatus == 1,
277 'text-danger': item.payStatus == 2
278 }"
279 class="value"
280 >
281 {{ item.payStatus == 0 ? '待缴费' : item.payStatus == 1 ? '缴费成功' : '订单取消' }}
282 </view>
283 </view>
284 </view> -->
285
286 <!-- 按钮组:靠右紧凑展示 -->
287 <view class="btn-group">
288 <view>
289 <text class="more" @click.stop="goToDetail(item)">更多</text>
290 </view>
291 <view class="btn-flex">
292 <!-- 已缴费:申请开票/已开票(需要审核通过才能开票) -->
293 <template>
294 <button class="btn btn-info" @click.stop="goToDetail(item)">查看明细</button>
295 </template>
296 <!-- 已缴费:申请开票/已开票(需要审核通过才能开票) -->
297 <template v-if="item.payStatus == 1 && item.invoiceStatus != 1&& item.auditStatus == 2 &&item.price>0">
298 <button :disabled="item.invoiceStatus === 1" class="btn btn-view-invoice"
299 @click.stop="makeInvoiceFN(item)">
300 申请票据
301 </button>
302 </template>
303 <!-- 已申请票据:查看票据 -->
304 <template v-if="item.invoiceStatus == 1">
305 <button class="btn btn-invoice" @click.stop="viewInvoice(item)">查看票据</button>
306 </template>
307 <!-- 未缴费:去缴费 + 取消订单 -->
308 <!-- <template v-if="item.payStatus == 0">
309 <button class="btn btn-cancel" @click="handleCancel(item)">取消订单</button>
310 <button class="btn btn-pay" @click="handlePay(item)">去缴费</button>
311 </template> -->
312 </view>
313
314 </view>
315 </view>
316 </view>
317
318 <!-- 空状态 -->
319 <view v-else class="empty">
320 <image :src="config.baseUrl_api + '/fs/static/nodata.png'" class="empty-img" mode="aspectFit"></image>
321 <text class="empty-text">暂无订单记录</text>
322 </view>
323
324 <!-- 加载/无更多提示 -->
325 <view v-if="loading" class="loading-tip">加载中...</view>
326 <view v-if="!loading && !hasMore && list.length" class="no-more">没有更多了</view>
327 </view>
328 </scroll-view>
329
330 <!-- 票据信息弹窗(级位/段位/越段考试) -->
331 <view v-if="showInvoicePopup" class="invoice-popup-mask" @click="closeInvoicePopup">
332 <view class="invoice-popup-content" @click.stop>
333 <view class="invoice-popup-header">
334 <text class="invoice-popup-title">票据信息</text>
335 <view class="invoice-popup-close" @click="closeInvoicePopup"></view>
336 </view>
337 <view class="invoice-popup-body">
338 <view class="invoice-info-list">
339 <view class="invoice-info-row">
340 <view class="invoice-info-label">票据类型</view>
341 <view :class="{ 'vat-type': invoiceData.invoiceType == 2 }" class="invoice-type-badge">
342 {{ invoiceData.invoiceType == 1 ? '普通票据' : '增值税专用票据' }}
343 </view>
344 </view>
345 <view class="invoice-info-row">
346 <text class="invoice-info-label">票据抬头</text>
347 <text class="invoice-info-value">{{ invoiceData.invoiceBuyerName || '—' }}</text>
348 </view>
349 <view v-if="invoiceData.invoiceBuyerTaxno" class="invoice-info-row">
350 <text class="invoice-info-label">纳税人识别号</text>
351 <text class="invoice-info-value">{{ invoiceData.invoiceBuyerTaxno }}</text>
352 </view>
353 <view class="invoice-info-row">
354 <text class="invoice-info-label">接收邮箱</text>
355 <text class="invoice-info-value">{{ invoiceData.invoicePushPhone || '—' }}</text>
356 </view>
357 <view class="invoice-info-row">
358 <text class="invoice-info-label">申请时间</text>
359 <text class="invoice-info-value">{{ invoiceData.invoiceTime || '—' }}</text>
360 </view>
361 <view class="invoice-info-row">
362 <text class="invoice-info-label">票据金额</text>
363 <text class="invoice-info-value">¥{{ invoiceData.price || '—' }}</text>
364 </view>
365 </view>
366 </view>
367 </view>
368 </view>
369
370 <!-- 票据Webview弹窗(个人/单位会员) -->
371 <view v-if="showInvoiceWebview" class="invoice-popup-mask" @click="closeInvoiceWebview">
372 <view class="invoice-webview-content" @click.stop>
373 <view class="invoice-popup-header">
374 <text class="invoice-popup-title">票据</text>
375 <view class="invoice-popup-close" @click="closeInvoiceWebview"></view>
376 </view>
377 <view class="invoice-webview-body">
378 <web-view :src="invoiceWebviewUrl"></web-view>
379 </view>
380 </view>
381 </view>
382
383 <!-- 自定义删除确认弹窗 -->
384 <view v-if="showDelPopup" class="popup-mask" @touchmove.stop.prevent @click.stop="closeDelPopup">
385 <view class="custom-modal" @click.stop>
386 <view class="modal-title">提示</view>
387 <view class="modal-content">{{ delModalContent }}</view>
388 <view class="modal-btns">
389 <button class="modal-btn-cancel" @click="closeDelPopup">取消</button>
390 <button class="modal-btn-confirm" @click="confirmDel">确定</button>
391 </view>
392 </view>
393 </view>
394
395 <!-- 自定义取消订单确认弹窗 -->
396 <view v-if="showCancelPopup" class="popup-mask" @touchmove.stop.prevent @click.stop="closeCancelPopup">
397 <view class="custom-modal" @click.stop>
398 <view class="modal-title">提示</view>
399 <view class="modal-content">{{ cancelModalContent }}</view>
400 <view class="modal-btns">
401 <button class="modal-btn-cancel" @click="closeCancelPopup">取消</button>
402 <button class="modal-btn-confirm" @click="confirmCancel">确定</button>
403 </view>
404 </view>
405 </view>
406
407 <!-- 底部导航 -->
408 <dao-guan-tab-bar :currentIndex="1" @switch="onTabSwitch" />
409 </view>
410 </template>
411
412 <script setup>
413 import {ref, reactive, onMounted, computed} from 'vue';
414 import {
415 onShow,
416 onLoad
417 } from '@dcloudio/uni-app'
418 import * as api from '@/common/api.js'
419 import config from '@/config.js'
420 import dayjs from 'dayjs'
421 import DaoGuanTabBar from '@/components/dao-guan-tab-bar.vue'
422 // 获取deptType值(初始值为0,在onMounted中设置实际值)
423 const deptType = ref(0);
424
425
426 // 标签栏配置(根据deptType动态生成)
427 const tabs = computed(() => {
428 const dt = Number(deptType.value)
429 console.log('tabs computed, deptType:', deptType.value, 'dt:', dt, 'dt===6:', dt === 6, 'dt==6:', dt == 6);
430
431 if (dt === 6) {
432 console.log('返回3个tab: 个人会员、单位会员、级位考试');
433 return [
434 {name: '个人会员', type: '0', label: "会员"},
435 {name: '单位会员', type: '1', label: "单位"},
436 {name: '级位考试', type: '2', label: "级位"}
437 ];
438 } else if (dt === 2) {
439 console.log('返回3个tab: 单位会员、段位考试、越段考试');
440 return [
441 // {name: '单位会员', type: '1'},
442 {name: '段位考试', type: '3', label: "段位"},
443 {name: '越段考试', type: '4', label: "越段"}
444 ];
445 } else if (dt === 1) {
446 console.log('返回默认5个tab, dt值为:', dt);
447 return [
448 {name: '个人会员', type: '0', label: "会员"},
449 {name: '单位会员', type: '1', label: "单位"},
450 {name: '级位考试', type: '2', label: "级位"},
451 {name: '段位考试', type: '3', label: "段位"},
452 {name: '越段考试', type: '4', label: "越段"}
453 ];
454 } else {
455 return [
456 {name: '单位会员', type: '1', label: "单位"},
457 ];
458 }
459 });
460 const currentTab = ref('0');
461 const currentStatus = ref('');
462 const statusTabs = [
463 { name: '全部', type: '' },
464 { name: '待缴费', type: '0' },
465 { name: '缴费成功', type: '1' },
466 { name: '订单取消', type: '2' }
467 ]
468
469 // 数据与分页配置
470 const list = ref([]);
471 const loading = ref(false);
472 const hasMore = ref(true);
473 const pageNum = ref(1);
474 const pageSize = ref(10);
475
476 // 查询参数
477 const queryParams = reactive({
478 pageNum: 1,
479 pageSize: 10,
480 type: '0',
481 queryType: '1',
482 payStatus: ''
483 });
484
485 // 弹窗控制
486 const showDelPopup = ref(false);
487 const showCancelPopup = ref(false);
488 const isPopupOpen = ref(false);
489 const showInvoicePopup = ref(false);
490 const showInvoiceWebview = ref(false);
491 const invoiceWebviewUrl = ref('');
492 const invoiceData = ref({});
493
494 // 弹窗内容
495 const delModalContent = ref('');
496 const cancelModalContent = ref('');
497
498 // 当前操作的订单
499 const currentOrder = ref(null);
500
501 // 页面挂载初始化
502 onLoad((option) => {
503 // 获取app实例和deptType
504 const app = getApp();
505 deptType.value = Number(app.globalData?.deptType || 0);
506 const firstType = tabs.value[0]?.type ?? '0';
507 // currentTab.value = option.type || firstType;
508 // queryParams.type = option.type || firstType;
509 currentTab.value = firstType;
510 queryParams.type = firstType;
511 initData();
512 });
513
514 // 页面显示时刷新数据(从开票页面返回时)
515 onShow(() => {
516 // 如果有缓存的刷新标记,则刷新列表
517 if (needRefresh.value) {
518 needRefresh.value = false;
519 pageNum.value = 1;
520 list.value = [];
521 hasMore.value = true;
522 initData();
523 }
524 });
525
526 // 是否需要刷新
527 const needRefresh = ref(false);
528
529 // 上拉加载更多
530 const loadMore = () => {
531 console.log("触发上拉加载");
532 if (loading.value || !hasMore.value || isPopupOpen.value) return;
533 pageNum.value++;
534 initData();
535 };
536
537 // 切换标签
538 const switchTab = (type) => {
539 currentTab.value = type;
540 queryParams.type = type;
541 pageNum.value = 1;
542 list.value = [];
543 hasMore.value = true;
544 initData();
545 };
546
547 const switchStatus = (type) => {
548 currentStatus.value = type;
549 queryParams.payStatus = type;
550 pageNum.value = 1;
551 list.value = [];
552 hasMore.value = true;
553 initData();
554 };
555
556 // 状态文本映射
557 const getStatusText = (status) => {
558 const map = {
559 0: '待缴费',
560 1: '缴费成功',
561 2: '订单取消'
562 };
563 return map[status] || '';
564 };
565
566 // 审核状态文本映射
567 const getAuditStatusText = (status) => {
568 const map = {
569 0: '待提交',
570 1: '审核中',
571 2: '审核通过',
572 3: '审核拒绝'
573 };
574 return map[status] || '';
575 };
576
577 const getOrderLabel = (item) => {
578 const map = {
579 0: '会员',
580 1: '单位',
581 2: '级位',
582 3: '段位',
583 4: '越段'
584 }
585 return map[item.type] || tabs.value.find(t => t.type === currentTab.value)?.label || '订单'
586 }
587
588 const filterTime = (row) => {
589 if (!row) return ''
590 return dayjs(row).format('YYYY年MM月DD日')
591 }
592
593 const filterType = (row) => {
594 if (row == 0) return '个人会员缴费办理'
595 if (row == 1) return '单位会员缴费办理'
596 if (row == 2) return '级位考试办理'
597 if (row == 3) return '段位考试办理'
598 if (row == 4) return '越位考试办理'
599 }
600
601
602 // 数据请求核心方法
603 const initData = async () => {
604 loading.value = true;
605 queryParams.pageNum = pageNum.value;
606
607 try {
608 const res = await api.orderList(queryParams);
609 console.log("接口返回:", res);
610
611 if (!res || !res.rows || res.rows.length === 0) {
612 hasMore.value = false;
613 loading.value = false;
614 return;
615 }
616 // 安全解析content字段
617 res.rows.forEach(item => {
618 if (item.content) {
619 try {
620 item.content = JSON.parse(item.content);
621 } catch (e) {
622 item.content = null;
623 }
624 }
625 });
626 // 第一页覆盖,后面页数追加
627 if (pageNum.value === 1) {
628 list.value = res.rows;
629 } else {
630 list.value.push(...res.rows);
631 }
632 // 关键修复:只要返回条数 < pageSize 就说明没有更多了
633 hasMore.value = res.rows.length === pageSize.value;
634 } catch (e) {
635 console.error('订单加载异常:', e);
636 uni.showToast({title: '加载失败', icon: 'none'});
637 hasMore.value = false;
638 } finally {
639 loading.value = false;
640 }
641 };
642
643 const handelSearch = () => {
644 pageNum.value = 1
645 list.value = []
646 initData()
647 }
648
649 // 删除订单
650 const handleDelete = (item) => {
651 currentOrder.value = item;
652 delModalContent.value = `是否确认删除订单编号为"${item.tradeNo}"的订单?`;
653 showDelPopup.value = true;
654 isPopupOpen.value = true;
655 };
656
657 // 确认删除
658 const confirmDel = async () => {
659 if (!currentOrder.value) return;
660 try {
661 await api.deleteOrder(currentOrder.value.id);
662 uni.showToast({title: '删除成功', icon: 'success'});
663 pageNum.value = 1;
664 list.value = [];
665 await initData();
666 closeDelPopup();
667 } catch (e) {
668 uni.showToast({title: '删除失败', icon: 'error'});
669 }
670 };
671
672 const goToDetail = (item) => {
673 console.log("goToDetail:", item);
674 console.log("currentTab.value", currentTab.value);
675 const form = encodeURIComponent(JSON.stringify(item))
676 switch (currentTab.value) {
677 case '1':
678 uni.navigateTo({url: `/group/groupOrderDetail?form=${form}`});
679 break;
680 case '2':
681 case '3':
682 case '4':
683 uni.navigateTo({url: `/pages/rank/applyDetail?examId=${item.sourceId || item.id}&type=${queryParams.type}`});
684 break;
685 case '0':
686 default:
687 uni.navigateTo({url: `/personalVip/orderDetail?rangeId=${item.sourceId || item.id}&type=${queryParams.type}`});
688 break;
689 }
690 // uni.navigateTo({url: `/pages/rank/applyDetail?examId=${item.sourceId || item.id}&type=${queryParams.type}`});
691 }
692
693 // 关闭删除弹窗
694 const closeDelPopup = () => {
695 showDelPopup.value = false;
696 isPopupOpen.value = false;
697 currentOrder.value = null;
698 };
699
700 // 去缴费
701 const handlePay = async (item) => {
702 if (item.payStatus !== 0) return;
703 try {
704 await api.goPay({id: item.id});
705 uni.navigateTo({url: `/pages/pay/pay?orderId=${item.id}`});
706 } catch (e) {
707 uni.showToast({title: '发起支付失败', icon: 'none'});
708 }
709 };
710
711 // 申请开票
712 const makeInvoiceFN = (item) => {
713 // 开票条件:缴费成功 && 未开票 && 审核通过
714 // if (item.payStatus !== 1 || item.invoiceStatus === 1 || item.auditStatus !== 2) {
715 // return;
716 // }
717 // 设置刷新标记,从开票页面返回时刷新列表
718 needRefresh.value = true;
719 // 根据tab类型决定跳转页面:个人/单位会员开非税票,级位/段位/越段考试开增值税票
720 let url = '';
721 if (currentTab.value === '0' || currentTab.value === '1') {
722 // 个人/单位会员 - 非税开票
723 url = `/pages/invoice/applyFeisui?orderId=${item.id}&amount=${item.price}`;
724 } else {
725 // 级位/段位/越段考试 - 增值税开票
726 url = `/pages/invoice/apply?orderId=${item.id}&amount=${item.price}`;
727 }
728 uni.navigateTo({ url });
729 };
730
731 // 查看发票
732 const viewInvoice = (item) => {
733 // 个人/单位会员(type 0或1)直接跳转webview页面展示发票
734 if (item.type === 0 || item.type === '0' || item.type === 1 || item.type === '1') {
735 if (item.invoiceUrl) {
736 const encodedUrl = encodeURIComponent(item.invoiceUrl);
737 uni.navigateTo({
738 url: `/pages/webview/webview?url=${encodedUrl}`
739 });
740 } else {
741 uni.showToast({ title: '暂无发票', icon: 'none' });
742 }
743 return;
744 }
745 // 其他类型显示发票信息弹窗
746 invoiceData.value = {
747 invoiceType: item.invoiceType || 1,
748 invoiceBuyerName: item.invoiceTitle || item.invoiceBuyerName || '—',
749 invoiceBuyerTaxno: item.invoiceTaxno || item.invoiceBuyerTaxno || '',
750 invoicePushPhone: item.invoiceEmail || item.invoicePushPhone || '—',
751 price: item.price || '-',
752 invoiceTime: item.invoiceTime || '—'
753 };
754 showInvoicePopup.value = true;
755 isPopupOpen.value = true;
756 };
757
758 // 关闭发票弹窗
759 const closeInvoicePopup = () => {
760 showInvoicePopup.value = false;
761 isPopupOpen.value = false;
762 };
763
764 // 关闭发票Webview弹窗
765 const closeInvoiceWebview = () => {
766 showInvoiceWebview.value = false;
767 isPopupOpen.value = false;
768 };
769
770 // 取消订单
771 const handleCancel = (item) => {
772 currentOrder.value = item;
773 cancelModalContent.value = `是否确认取消订单编号为"${item.tradeNo}"的订单?`;
774 showCancelPopup.value = true;
775 isPopupOpen.value = true;
776 };
777
778 // 确认取消订单
779 const confirmCancel = async () => {
780 if (!currentOrder.value) return;
781 try {
782 await api.cancelPay(currentOrder.value.id);
783 uni.showToast({title: '取消成功', icon: 'success'});
784 pageNum.value = 1;
785 list.value = [];
786 await initData();
787 closeCancelPopup();
788 } catch (e) {
789 uni.showToast({title: '取消失败', icon: 'error'});
790 }
791 };
792
793 // 关闭取消订单弹窗
794 const closeCancelPopup = () => {
795 showCancelPopup.value = false;
796 isPopupOpen.value = false;
797 currentOrder.value = null;
798 };
799
800 // 底部导航切换
801 const onTabSwitch = (index, url) => {
802 // tab switch handled by component
803 };
804 </script>
805
806 <style lang="scss" scoped>
807 .order-page {
808 background: #ededf0;
809 height: 100vh;
810 display: flex;
811 flex-direction: column;
812 padding-bottom: calc(120rpx + env(safe-area-inset-bottom));
813 box-sizing: border-box;
814
815 &.no-scroll {
816 overflow: hidden;
817 height: 100vh;
818 }
819 }
820
821 .order-hero {
822 flex-shrink: 0;
823 padding: calc(env(safe-area-inset-top) + 90rpx) 44rpx 34rpx;
824 background: linear-gradient(135deg, #b00005 0%, #7a0000 100%);
825 color: #fff;
826 }
827
828 .hero-title-row {
829 display: flex;
830 justify-content: space-between;
831 align-items: flex-end;
832 margin-bottom: 42rpx;
833 }
834
835 .hero-title {
836 font-size: 38rpx;
837 letter-spacing: 2rpx;
838 }
839
840 .hero-subtitle {
841 margin-top: 8rpx;
842 color: rgba(255, 255, 255, 0.58);
843 font-size: 16rpx;
844 }
845
846 .hero-page-title {
847 color: #f4b536;
848 font-size: 36rpx;
849 font-weight: 500;
850 text-align: right;
851 }
852
853 .title-line {
854 width: 54rpx;
855 height: 6rpx;
856 margin: 14rpx 0 0 auto;
857 border-radius: 10rpx;
858 background: #f4b536;
859 }
860
861 /* 搜索栏 */
862 .search-bar {
863 display: flex;
864 align-items: center;
865 height: 64rpx;
866 padding: 0;
867 border-radius: 34rpx;
868 background-color: #ffffff;
869 overflow: hidden;
870
871 .search-input {
872 flex: 1;
873 margin-right: 0;
874
875 :deep(.uni-easyinput__content) {
876 border-radius: 34rpx;
877 background-color: #fff;
878 height: 64rpx;
879 padding: 0 18rpx 0 28rpx;
880 }
881
882 :deep(.uni-easyinput__content-input) {
883 font-size: 28rpx;
884 color: #333;
885 }
886 }
887
888 .add-btn {
889 display: flex;
890 align-items: center;
891 justify-content: center;
892 width: 88rpx;
893 height: 52rpx;
894 margin-right: 6rpx;
895 background-color: #c91c34;
896 border-radius: 28rpx;
897 font-size: 24rpx;
898 font-weight: 700;
899 color: #ffffff;
900 }
901
902 .add-icon {
903 font-size: 36rpx;
904 margin-right: 10rpx;
905 font-weight: bold;
906 }
907 }
908
909 // 标签栏样式
910 .tab-bar {
911 display: flex;
912 flex-shrink: 0;
913 padding: 22rpx 30rpx 4rpx;
914 background: #ededf0;
915 flex-shrink: 0;
916
917 .tab-item {
918 flex: none;
919 margin-right: 48rpx;
920 padding: 0 0 14rpx;
921 font-size: 30rpx;
922 color: #666;
923 position: relative;
924 font-weight: bold;
925
926 &.active {
927 color: #c30d23;
928 font-weight: bold;
929
930 &::after {
931 content: '';
932 position: absolute;
933 bottom: 0;
934 left: 50%;
935 transform: translateX(-50%);
936 width: 72rpx;
937 height: 4rpx;
938 background: #c30d23;
939 border-radius: 2rpx;
940 }
941 }
942 }
943 }
944
945 .status-filter {
946 display: flex;
947 align-items: center;
948 flex-shrink: 0;
949 padding: 10rpx 26rpx 18rpx;
950 background: #ededf0;
951 }
952
953 .status-filter-item {
954 height: 48rpx;
955 line-height: 48rpx;
956 margin-right: 18rpx;
957 padding: 0 24rpx;
958 border-radius: 8rpx;
959 background: #fff;
960 color: #777;
961 font-size: 26rpx;
962 }
963
964 .status-filter-item.active {
965 color: #c30d23;
966 font-weight: 700;
967 }
968
969 .filter-entry {
970 margin-left: auto;
971 display: flex;
972 flex-direction: column;
973 align-items: center;
974 color: #999;
975 font-size: 20rpx;
976 }
977
978 .filter-icon {
979 font-size: 28rpx;
980 line-height: 22rpx;
981 }
982
983 // 滚动列表容器
984 .order-list-scroll {
985 flex: 1;
986 height: auto;
987 overflow: auto;
988 background: #ededf0;
989 }
990
991 // 订单列表
992 .order-list {
993 padding: 0 24rpx 34rpx;
994
995 .order-card {
996 background: #fff;
997 margin-bottom: 20rpx;
998 padding: 20rpx;
999 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
1000 border-radius: 12rpx;
1001 display: flex;
1002 flex-direction: column;
1003 // border-top: 6rpx solid transparent;
1004 // background-clip: padding-box, border-box;
1005 // background-origin: padding-box, border-box;
1006 // background-image: linear-gradient(#fff, #fff), linear-gradient(90deg, #FF755A, #F51722);
1007 }
1008 }
1009
1010 // 卡片头部
1011 .card-header {
1012 display: flex;
1013 justify-content: space-between;
1014 align-items: center;
1015 padding-bottom: 10rpx;
1016 // margin-bottom: 20rpx;
1017 // border-bottom: 1rpx dashed #eee;
1018
1019 .date {
1020 display: flex;
1021 align-items: center;
1022 gap: 8rpx;
1023 font-size: 26rpx;
1024
1025 .date-text {
1026 color: #666;
1027 }
1028 }
1029
1030 .status-tags {
1031 display: flex;
1032 gap: 10rpx;
1033 }
1034
1035 .status-tag {
1036 font-size: 22rpx;
1037 //padding: 6rpx 16rpx;
1038 //border-radius: 20rpx;
1039
1040 &.success {
1041 //background: #e6f7ef;
1042 color: #52c41a;
1043 }
1044
1045 &.danger {
1046 //background: #fff1f0;
1047 color: #ff4d4f;
1048 }
1049
1050 &.pending {
1051 //background: #f5f5f5;
1052 color: #999;
1053 }
1054
1055 &.ml-10 {
1056 margin-left: 10rpx;
1057 }
1058
1059 &.status-wait {
1060 //background: #f0f5ff;
1061 color: #597ef7;
1062 //border: 1rpx solid rgba(89, 126, 247, 0.3);
1063 }
1064
1065 &.status-pending {
1066 //background: #fff7e6;
1067 color: #faad14;
1068 //border: 1rpx solid rgba(250, 173, 20, 0.3);
1069 }
1070
1071 &.status-success {
1072 //background: #e6f7ef;
1073 color: #52c41a;
1074 //border: 1rpx solid rgba(82, 196, 26, 0.3);
1075 }
1076
1077 &.status-danger {
1078 //background: #fff1f0;
1079 color: #ff4d4f;
1080 //border: 1rpx solid rgba(232, 52, 29, 0.3);
1081 }
1082 }
1083 }
1084
1085 // 基础信息行
1086 .info-row {
1087 display: flex;
1088 align-items: center;
1089 margin-bottom: 20rpx;
1090 font-size: 26rpx;
1091
1092 .label {
1093 color: #999;
1094 flex-shrink: 0;
1095 width: 140rpx;
1096 }
1097
1098 .value {
1099 color: #333;
1100 word-break: break-all;
1101 }
1102 }
1103
1104 .info-section {
1105 background: #f3f6fc;
1106 display: flex;
1107 align-items: center;
1108 justify-content: space-between;
1109 //margin: 20rpx 0;
1110 padding: 0 20rpx;
1111 min-height: 100rpx;
1112 border-radius: 20rpx;
1113 }
1114
1115 .line {
1116 width: 1rpx;
1117 height: 60rpx;
1118 background: #e5e5e5;
1119 flex-shrink: 0;
1120 }
1121
1122 .single-info {
1123 flex: 1;
1124 padding: 16rpx 20rpx;
1125 border-radius: 8rpx;
1126 font-size: 26rpx;
1127 text-align: center;
1128
1129 .label {
1130 color: #999;
1131 text-align: center;
1132 }
1133
1134 .value {
1135 color: #333;
1136 font-weight: 500;
1137 text-align: center;
1138 margin-top: 10rpx;
1139
1140 &.text-primary {
1141 color: #597ef7;
1142 }
1143
1144 &.text-success {
1145 color: #52c41a;
1146 }
1147
1148 &.text-danger {
1149 color: #ff4d4f;
1150 }
1151
1152 &.text-warning {
1153 color: #faad14;
1154 }
1155 }
1156 }
1157
1158 // 费用合计
1159 .price-section {
1160 // border-top: 1rpx dashed #eee;
1161 // padding-top: 16rpx;
1162 margin-top: 8rpx;
1163
1164 .price-row {
1165 display: flex;
1166 justify-content: space-between;
1167 align-items: center;
1168 padding: 8rpx 0;
1169
1170 .price-label {
1171 font-size: 26rpx;
1172 color: #333;
1173 }
1174
1175 .price-value {
1176 font-size: 26rpx;
1177 color: #666;
1178
1179 &.text-success {
1180 color: #52c41a;
1181 }
1182
1183 &.text-warning {
1184 color: #faad14;
1185 }
1186 }
1187 }
1188 }
1189
1190 // 按钮组
1191 .btn-group {
1192 display: flex;
1193 justify-content: space-between;
1194 align-items: center;
1195 gap: 16rpx;
1196 width: 100%;
1197 margin-top: 16rpx;
1198
1199 .more {
1200 color: #999;
1201 font-size: 26rpx;
1202 font-weight: 700;
1203 }
1204
1205 .btn-flex {
1206 display: flex;
1207 justify-content: flex-end;
1208 gap: 16rpx;
1209 }
1210
1211 .btn {
1212 // 固定宽度,所有按钮一样大
1213 width: 126rpx;
1214 height: 44rpx;
1215 line-height: 44rpx;
1216 padding: 0;
1217 border-radius: 10rpx;
1218 font-size: 24rpx;
1219 white-space: nowrap;
1220 font-weight: bold;
1221 border: none;
1222 background: transparent;
1223 text-align: center;
1224 margin: 0;
1225
1226 &::after {
1227 border: none;
1228 display: none; // 关键:隐藏伪元素
1229 }
1230
1231 &.btn-delete {
1232 background: #fff;
1233 //color: #e4393c;
1234 color: #c30d23;
1235 border: 1rpx solid #c30d23;
1236 }
1237
1238 &.btn-invoice {
1239 background: #fff;
1240 color: #c30d23;
1241 border: 1rpx solid #c30d23;
1242 }
1243
1244 &.btn-view-invoice {
1245 //background: linear-gradient(90deg, #FF755A, #F51722);
1246 color: #c30d23;
1247 //border: none;
1248 border: 1rpx solid #c30d23;
1249 }
1250
1251 &.btn-info {
1252 color: #444;
1253 border: 1rpx solid #d7d7d7;
1254 background: #fff;
1255 }
1256
1257 &.btn-cancel {
1258 background: #fff;
1259 color: #666;
1260 border: 1rpx solid #ccc;
1261 }
1262
1263 &.btn-pay {
1264 //background: linear-gradient(90deg, #FF755A, #F51722);
1265 color: #c30d23;
1266 //border: none;
1267 border: 1rpx solid #c30d23;
1268 }
1269
1270 &:disabled {
1271 opacity: 0.6;
1272 pointer-events: none;
1273 }
1274 }
1275 }
1276
1277
1278 // 加载/无更多提示
1279 .loading-tip, .no-more {
1280 text-align: center;
1281 padding: 20rpx 0;
1282 color: #999;
1283 font-size: 26rpx;
1284 }
1285
1286 // 弹窗遮罩层
1287 .popup-mask {
1288 position: fixed;
1289 top: 0;
1290 left: 0;
1291 right: 0;
1292 bottom: 0;
1293 background-color: rgba(0, 0, 0, 0.5);
1294 display: flex;
1295 align-items: center;
1296 justify-content: center;
1297 z-index: 999;
1298 }
1299
1300 // 自定义弹窗样式
1301 .custom-modal {
1302 width: 600rpx;
1303 background: #fff;
1304 border-radius: 20rpx;
1305 padding: 40rpx 30rpx;
1306 box-sizing: border-box;
1307 text-align: center;
1308 box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.2);
1309 }
1310
1311 .modal-title {
1312 font-size: 36rpx;
1313 font-weight: 600;
1314 color: #333;
1315 margin-bottom: 30rpx;
1316 }
1317
1318 .modal-content {
1319 font-size: 30rpx;
1320 color: #666;
1321 line-height: 1.6;
1322 margin-bottom: 40rpx;
1323 word-break: break-word;
1324 }
1325
1326 .modal-btns {
1327 display: flex;
1328 justify-content: space-between;
1329 gap: 20rpx;
1330 }
1331
1332 .modal-btn-cancel {
1333 flex: 1;
1334 height: 80rpx;
1335 line-height: 80rpx;
1336 background: #f5f5f5;
1337 color: #666;
1338 border-radius: 40rpx;
1339 font-size: 32rpx;
1340 border: none;
1341 margin: 0;
1342 padding: 0;
1343
1344 &::after {
1345 border: none;
1346 }
1347 }
1348
1349 .modal-btn-confirm {
1350 flex: 1;
1351 height: 80rpx;
1352 line-height: 80rpx;
1353 background: #C4121B;
1354 color: #fff;
1355 border-radius: 40rpx;
1356 font-size: 32rpx;
1357 border: none;
1358 margin: 0;
1359 padding: 0;
1360
1361 &::after {
1362 border: none;
1363 }
1364 }
1365
1366 .code-text {
1367 font-size: 28rpx;
1368 font-weight: 600;
1369 color: #e8341d;
1370 letter-spacing: 1rpx;
1371 }
1372
1373 // 发票弹窗样式
1374 .invoice-popup-mask {
1375 position: fixed;
1376 top: 0;
1377 left: 0;
1378 right: 0;
1379 bottom: 0;
1380 background-color: rgba(0, 0, 0, 0.5);
1381 display: flex;
1382 align-items: center;
1383 justify-content: center;
1384 z-index: 999;
1385 }
1386
1387 .invoice-popup-content {
1388 width: 600rpx;
1389 background: #fff;
1390 border-radius: 20rpx;
1391 overflow: hidden;
1392 box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.2);
1393 }
1394
1395 .invoice-webview-content {
1396 width: 90%;
1397 height: 85vh;
1398 background: #fff;
1399 border-radius: 20rpx;
1400 overflow: hidden;
1401 display: flex;
1402 flex-direction: column;
1403 }
1404
1405 .invoice-webview-body {
1406 flex: 1;
1407 overflow: hidden;
1408 }
1409
1410 .invoice-popup-header {
1411 display: flex;
1412 justify-content: space-between;
1413 align-items: center;
1414 padding: 30rpx;
1415 background: linear-gradient(135deg, #AD181F 0%, #E4393C 100%);
1416
1417 .invoice-popup-title {
1418 font-size: 32rpx;
1419 font-weight: 600;
1420 color: #fff;
1421 }
1422
1423 .invoice-popup-close {
1424 width: 44rpx;
1425 height: 44rpx;
1426 display: flex;
1427 align-items: center;
1428 justify-content: center;
1429 font-size: 28rpx;
1430 color: rgba(255, 255, 255, 0.8);
1431 }
1432 }
1433
1434 .invoice-popup-body {
1435 padding: 30rpx;
1436 }
1437
1438 .invoice-type-badge {
1439 display: inline-flex;
1440 align-items: center;
1441 padding: 8rpx 24rpx;
1442 background: linear-gradient(135deg, #FF755A 0%, #F51722 100%);
1443 color: #fff;
1444 border-radius: 30rpx;
1445 font-size: 24rpx;
1446 font-weight: 500;
1447
1448 &.vat-type {
1449 background: linear-gradient(135deg, #6aaaf2 0%, #178cd7 100%);
1450 }
1451 }
1452
1453 .invoice-info-list {
1454 .invoice-info-row {
1455 display: flex;
1456 justify-content: space-between;
1457 align-items: flex-start;
1458 padding: 24rpx 0;
1459 border-bottom: 1rpx dashed #eee;
1460
1461 &:last-child {
1462 border-bottom: none;
1463 }
1464
1465 .invoice-info-label {
1466 font-size: 26rpx;
1467 color: #999;
1468 flex-shrink: 0;
1469 }
1470
1471 .invoice-info-value {
1472 font-size: 26rpx;
1473 color: #333;
1474 text-align: right;
1475 word-break: break-all;
1476 max-width: 340rpx;
1477 }
1478 }
1479 }
1480
1481 .order-card-new {
1482 background: #fff;
1483 margin-bottom: 22rpx;
1484 padding: 22rpx 18rpx 18rpx;
1485 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
1486 border-radius: 18rpx;
1487 display: flex;
1488 flex-direction: column;
1489
1490
1491 // 卡片头部
1492 .card-header {
1493 display: flex;
1494 justify-content: space-between;
1495 align-items: center;
1496 padding-bottom: 10rpx;
1497 // margin-bottom: 20rpx;
1498 // border-bottom: 1rpx dashed #eee;
1499
1500 .date {
1501 width: 100%;
1502 display: flex;
1503 align-items: center;
1504 justify-content: space-between;
1505 gap: 8rpx;
1506 font-size: 26rpx;
1507
1508 .data-header {
1509 display: flex;
1510 }
1511
1512 .member-label {
1513 color: #c30d23;
1514 font-size: 28rpx;
1515 font-weight: bold;
1516 }
1517
1518 .value {
1519 color: #000;
1520 font-size: 27rpx;
1521 font-weight: bold;
1522 max-width: 460rpx;
1523 overflow: hidden;
1524 white-space: nowrap;
1525 text-overflow: ellipsis;
1526
1527 .tradeNo {
1528 color: #999;
1529 font-size: 24rpx;
1530 }
1531 }
1532
1533 .date-text {
1534 color: #666;
1535 }
1536 }
1537
1538
1539 .status-tags {
1540 display: flex;
1541 gap: 10rpx;
1542 }
1543
1544 .status-tag {
1545 font-size: 24rpx;
1546 color: #999;
1547 //padding: 6rpx 16rpx;
1548 //border-radius: 20rpx;
1549
1550 &.success {
1551 //background: #e6f7ef;
1552 color: #52c41a;
1553 }
1554
1555 &.danger {
1556 //background: #fff1f0;
1557 color: #ff4d4f;
1558 }
1559
1560 &.pending {
1561 //background: #f5f5f5;
1562 color: #999;
1563 }
1564
1565 &.ml-10 {
1566 margin-left: 10rpx;
1567 }
1568
1569 &.status-wait {
1570 //background: #f0f5ff;
1571 color: #597ef7;
1572 //border: 1rpx solid rgba(89, 126, 247, 0.3);
1573 }
1574
1575 &.status-pending {
1576 //background: #fff7e6;
1577 color: #faad14;
1578 //border: 1rpx solid rgba(250, 173, 20, 0.3);
1579 }
1580
1581 &.status-success {
1582 //background: #e6f7ef;
1583 color: #52c41a;
1584 //border: 1rpx solid rgba(82, 196, 26, 0.3);
1585 }
1586
1587 &.status-danger {
1588 //background: #fff1f0;
1589 color: #ff4d4f;
1590 //border: 1rpx solid rgba(232, 52, 29, 0.3);
1591 }
1592 }
1593 }
1594
1595 .member-time {
1596 width: 100%;
1597 display: flex;
1598 justify-content: space-between;
1599 padding-bottom: 4rpx;
1600
1601 .label {
1602 max-width: 480rpx;
1603 color: #555;
1604 font-size: 26rpx;
1605 font-weight: 700;
1606 line-height: 1.4;
1607
1608 .star {
1609 color: #777;
1610 font-size: 26rpx;
1611 }
1612 }
1613
1614 .price {
1615 min-width: 130rpx;
1616 color: #333;
1617 font-size: 26rpx;
1618 font-weight: 500;
1619 text-align: right;
1620
1621 .person {
1622 font-size: 24rpx;
1623 color: #999;
1624 text-align: right;
1625 }
1626 }
1627 }
1628 }
1629 </style>
1 <template>
2 <view class="person-dashboard">
3 <view class="hero">
4 <image class="hero-bg" :src="config.baseUrl_api + '/fs/static/img/red_bg.png'" mode="aspectFill"></image>
5
6 <view class="hero-nav">
7 <view>
8 <view class="brand-cn">中国跆拳道协会</view>
9 <view class="brand-en">CHINESE TAEKWONDO ASSOCIATION</view>
10 </view>
11 <view class="page-title">
12 <text>人员管理</text>
13 <view class="title-line"></view>
14 </view>
15 </view>
16
17 <view class="member-card">
18 <view class="member-content">
19 <view class="member-left">
20 <view class="hello">您好!</view>
21 <view class="member-name">{{ memberName }}</view>
22 <view class="member-desc">您已经是中国跆拳道协会的金牌会员了</view>
23 <view class="name-line"></view>
24 </view>
25 <view class="level-box" @click="goPath('/myCenter/reviewList')">
26 <image class="star" :src="config.baseUrl_api + '/fs/static/img/star.png'" mode="aspectFit"></image>
27 <view class="level-title">晋级考点</view>
28 <view class="detail-btn">查看详情</view>
29 </view>
30 </view>
31 </view>
32 </view>
33
34 <view class="main-actions">
35 <image class="actions-bg" :src="config.baseUrl_api + '/fs/static/img/red_bg2.png'" mode="aspectFill"></image>
36 <view class="member-bottom">
37 <view class="info-item">
38 <view class="info-label">单位会员编号</view>
39 <view class="info-value">{{ memberInfo.memCode }}</view>
40 </view>
41 <view class="info-item">
42 <view class="info-label">有效期</view>
43 <view class="info-value">{{ validityDate }}</view>
44 </view>
45 </view>
46 <image class="action-card" :src="config.baseUrl_api + '/fs/static/img/btn01.png'" mode="widthFix" @click="goPath('/myCenter/examPointApplyList')"></image>
47 <image class="action-card" :src="config.baseUrl_api + '/fs/static/img/btn02.png'" mode="widthFix" @click="goAuthPayV2"></image>
48 <image class="action-card" :src="config.baseUrl_api + '/fs/static/img/btn03.png'" mode="widthFix" @click="goPath('/personalVip/addVip')"></image>
49 <image class="action-card" :src="config.baseUrl_api + '/fs/static/img/btn04.png'" mode="widthFix" @click="goPath('/personalVip/payment')"></image>
50 <image class="action-card" :src="config.baseUrl_api + '/fs/static/img/btn05.png'" mode="widthFix" @click="goPath('/personalVip/list')"></image>
51 <image class="action-card" :src="config.baseUrl_api + '/fs/static/img/btn06.png'" mode="widthFix" @click="goPath('/personalVip/mobilize')"></image>
52 </view>
53
54 <dao-guan-tab-bar :currentIndex="0" @switch="onTabSwitch" />
55
56 <uni-popup ref="authPayPopup" :mask-click="false" type="center">
57 <view class="dialog-wrapper">
58 <view class="dialog-title">提示</view>
59 <view class="dialog-message">{{ authPayPopupMsg }}</view>
60 <view class="dialog-footer">
61 <button class="dialog-btn confirm" @click="closeAuthPayDialog">确定</button>
62 </view>
63 </view>
64 </uni-popup>
65
66 <uni-popup ref="examPointPopup" :mask-click="false" >
67 <view class="dialog-wrapper">
68 <view class="dialog-title">申请成为考点</view>
69 <view class="dialog-message">
70 <text>恭喜您成为中国跆拳道协会单位会员!</text>
71 <text>根据协会考点管理办法,需成为考点单位才能进行考级业务的办理。</text>
72 <text>是否现在申请成为考点。</text>
73 </view>
74 <view class="dialog-footer">
75 <button class="dialog-btn cancel" @click="closeExamPointDialog">取消</button>
76 <button class="dialog-btn confirm" @click="goExamPointApply">去申请</button>
77 </view>
78 <view class="no-display" @click="handleNoDisplay">不再显示</view>
79 </view>
80 </uni-popup>
81
82 <uni-popup ref="passwordTipPopup" :mask-click="false" type="center">
83 <view class="dialog-wrapper">
84 <view class="dialog-title">温馨提示</view>
85 <view class="dialog-message">密码长期未更新,请及时更新</view>
86 <view class="dialog-footer">
87 <button class="dialog-btn confirm" @click="closePasswordTipDialog">确定</button>
88 </view>
89 </view>
90 </uni-popup>
91 </view>
92 </template>
93
94 <script setup>
95 import config from '@/config.js'
96 import { computed, ref } from 'vue'
97 import { onLoad, onShow } from '@dcloudio/uni-app'
98 import * as api from '@/common/api.js'
99 import { getInfo } from '@/common/login'
100 import DaoGuanTabBar from '@/components/dao-guan-tab-bar.vue'
101
102 const app = getApp()
103 const userType = ref('1')
104 const memberInfo = ref({})
105 const deptInfo = ref({})
106 const numData = ref({})
107 const isBlack = ref(0)
108 const authPayDisabled = ref(true)
109 const authPayPopup = ref(null)
110 const authPayPopupMsg = ref('')
111 const passwordTipPopup = ref(null)
112 const examPointPopup = ref(null)
113 const showDirectlyForAuthPay = ref(false)
114 const directUnderFlagForAuthPay = ref(0)
115 const associateIdForAuthPay = ref(0)
116
117 const memberName = computed(() => {
118 return memberInfo.value.name || deptInfo.value.deptName || app.globalData?.dept?.deptName || '--'
119 })
120
121 const memberCode = computed(() => {
122 return memberInfo.value.menCode || memberInfo.value.memberCode || memberInfo.value.memberNo || '--'
123 })
124
125 const validityDate = computed(() => {
126 const value = memberInfo.value.validityDate || memberInfo.value.validityEndDate || memberInfo.value.expireTime
127 return value ? String(value).slice(0, 10) : '--'
128 })
129
130 onLoad((option) => {
131 const userName = uni.getStorageSync('userName')
132 if (!userName) {
133 app.globalData.isLogin = false
134 uni.reLaunch({ url: '/login/login' })
135 return
136 }
137
138 if (option.scene) {
139 decodeURIComponent(option.scene)
140 }
141
142 if (uni.showShareMenu) {
143 uni.showShareMenu({
144 withShareTicket: true,
145 menus: ['shareAppMessage', 'shareTimeline']
146 })
147 }
148 })
149
150 onShow(() => {
151 if (app.globalData.isLogin) {
152 init()
153 } else {
154 app.firstLoadCallback = () => {
155 init()
156 }
157 }
158 })
159
160 function init() {
161 api.getMyOwnMemberInfo().then(res => {
162 const data = res && res.data ? res.data : {}
163 app.globalData.authenticationStatus = data.authenticationStatus
164 app.globalData.memberInfo = data.memberInfo || {}
165 app.globalData.dept = data.dept || app.globalData.dept || {}
166 app.globalData.isExam = data.memberInfo?.isPoints
167
168 userType.value = app.globalData.userType
169 memberInfo.value = data.memberInfo || app.globalData.memberInfo || {}
170 deptInfo.value = data.dept || app.globalData.dept || {}
171
172 updateAuthPayDisabled(data)
173 updateAuthPayRule(data)
174 handleAccountStatus()
175 checkDialogs()
176 })
177
178 api.getRemindCount().then(res => {
179 numData.value = res.data || {}
180 })
181
182 api.getBlack().then(res => {
183 isBlack.value = res.data
184 })
185 }
186
187 function handleAccountStatus() {
188 console.log('handleAccountStatus22',userType.value , app.globalData.authenticationStatus)
189 if (userType.value != '1' && app.globalData.authenticationStatus != '2' && app.globalData.authenticationStatus != '4') {
190 uni.navigateTo({ url: '/pages/index/perfect' })
191 return
192 }
193
194 if (app.globalData.authenticationStatus == '5') {
195 const content = app.globalData.genFlag == 1 ? '您的会员已过期' : '会员已过期,请及时续费'
196 uni.showModal({
197 title: '提示',
198 content,
199 success: (res) => {
200 if (res.confirm && app.globalData.genFlag != 1) {
201 uni.navigateTo({ url: '/myCenter/auth' })
202 }
203 }
204 })
205 return
206 }
207
208 if (app.globalData.authenticationStatus == '4') {
209 uni.showModal({
210 title: '提示',
211 content: '你的会员即将过期,将会影响你的业务,请及时续费'
212 })
213 }
214
215 if (app.globalData.memberInfo?.activeStatus == 0) {
216 uni.showModal({
217 content: '账号未激活,请前去激活',
218 success: (res) => {
219 if (res.confirm) {
220 uni.navigateTo({ url: '/myCenter/auth' })
221 }
222 }
223 })
224 }
225 }
226
227 function goPath(path) {
228 if (isBlack.value == '1') {
229 uni.showModal({
230 title: '提示',
231 content: '您的账号已被拉黑,请联系中跆协!'
232 })
233 return
234 }
235
236 if (app.globalData.authenticationStatus == '5') {
237 if (app.globalData.genFlag == 1) {
238 uni.showModal({
239 title: '提示',
240 content: '您的会员已过期'
241 })
242 } else {
243 uni.showModal({
244 title: '提示',
245 content: '会员已过期,请及时续费',
246 success: (res) => {
247 if (res.confirm) {
248 uni.navigateTo({ url: '/myCenter/auth' })
249 }
250 }
251 })
252 }
253 return
254 }
255
256 if (app.globalData.memberInfo?.activeStatus == 0) {
257 uni.showModal({
258 title: '提示',
259 content: '账号未激活,请前去激活',
260 success: (res) => {
261 if (res.confirm) {
262 uni.navigateTo({ url: '/myCenter/auth' })
263 }
264 }
265 })
266 return
267 }
268
269 uni.navigateTo({ url: path })
270 }
271
272 function updateAuthPayDisabled(data = {}) {
273 const authStatus = data.authenticationStatus
274 const resultNoProvince = data.resultNoProvince2
275 if (authStatus == 0) {
276 authPayDisabled.value = false
277 } else if (authStatus == 1) {
278 authPayDisabled.value = true
279 } else {
280 const canPay = resultNoProvince === true || resultNoProvince == 1
281 authPayDisabled.value = !canPay
282 }
283 }
284
285 function updateAuthPayRule(data = {}) {
286 const memberInfoData = data.memberInfo || {}
287 const associateId = Number(memberInfoData.associateId || 0)
288 showDirectlyForAuthPay.value = !associateId
289 directUnderFlagForAuthPay.value = Number(memberInfoData.directUnderFlag || 0)
290 associateIdForAuthPay.value = associateId
291 }
292
293 function canAuthPayByAccountStatus() {
294 return showDirectlyForAuthPay.value &&
295 directUnderFlagForAuthPay.value === 0 &&
296 associateIdForAuthPay.value === 0
297 }
298
299 function showAuthPayDialog(message) {
300 authPayPopupMsg.value = message
301 authPayPopup.value?.open()
302 }
303
304 function closeAuthPayDialog() {
305 authPayPopup.value?.close()
306 }
307
308 function closePasswordTipDialog() {
309 passwordTipPopup.value?.close()
310 }
311
312 function goAuthPayV2() {
313 if (!canAuthPayByAccountStatus()) {
314 showAuthPayDialog('当前账号状态暂无法办理缴费业务')
315 return
316 }
317 if (authPayDisabled.value) {
318 showAuthPayDialog('您有一笔缴费正在审核中,请勿重复缴费。您可前往【认证详情】查看审核进度。')
319 return
320 }
321 goPath('/myCenter/perfect')
322 }
323
324 function closeExamPointDialog() {
325 examPointPopup.value?.close()
326 }
327
328 function goExamPointApply() {
329 closeExamPointDialog()
330 uni.navigateTo({ url: '/myCenter/examPointApplyList' })
331 }
332
333 async function handleNoDisplay() {
334 await api.noDisplay()
335 await getInfo()
336 closeExamPointDialog()
337 }
338
339 function checkDialogs() {
340 const user = app.globalData.userInfo || {}
341 const memberInfoData = app.globalData.memberInfo || {}
342
343 if (app.globalData.changePassFlag == '1' &&
344 app.globalData.memberInfo?.activeStatus == '1' &&
345 app.globalData.authenticationStatus == 2) {
346 const hasShown = uni.getStorageSync('passwordTipShown')
347 if (!hasShown) {
348 uni.setStorageSync('passwordTipShown', true)
349 passwordTipPopup.value?.open()
350 }
351 }
352 console.log('checkDialogs',app.globalData.memberInfo?.activeStatus,app.globalData.authenticationStatus,app.globalData.deptType,memberInfoData.isPoints)
353 if (app.globalData.memberInfo?.activeStatus == 1 &&
354 app.globalData.authenticationStatus == 2 &&
355 app.globalData.deptType == 6 &&
356 memberInfoData.isPoints == 1 ) {
357 examPointPopup.value?.open()
358 }
359 }
360
361 const onTabSwitch = () => {
362 // tab switch handled by component
363 }
364 </script>
365
366 <style lang="scss" scoped>
367 .person-dashboard {
368 min-height: 100vh;
369 background: #ededf0;
370 overflow: hidden;
371 }
372
373 .hero {
374 position: relative;
375 min-height: 610rpx;
376 padding: calc(env(safe-area-inset-top) + 62rpx) 28rpx 0;
377 overflow: hidden;
378 padding-top: 150rpx;
379 }
380
381 .hero-bg {
382 position: absolute;
383 inset: 0;
384 width: 100%;
385 height: 100%;
386 }
387
388 .hero-nav {
389 position: relative;
390 z-index: 1;
391 display: flex;
392 justify-content: space-between;
393 align-items: flex-end;
394 padding: 0 18rpx;
395 color: #fff;
396 }
397
398 .brand-cn {
399 font-size: 38rpx;
400 letter-spacing: 2rpx;
401 }
402
403 .brand-en {
404 margin-top: 8rpx;
405 font-size: 16rpx;
406 opacity: 0.55;
407 }
408
409 .page-title {
410 color: #f4b536;
411 font-size: 34rpx;
412 font-weight: 500;
413 text-align: right;
414 }
415
416 .title-line {
417 width: 54rpx;
418 height: 6rpx;
419 margin: 12rpx 0 0 auto;
420 background: #f4b536;
421 border-radius: 10rpx;
422 }
423
424 .member-card {
425 position: relative;
426 z-index: 1;
427 height: 460rpx;
428 margin-top: 47rpx;
429 border-radius: 22rpx;
430 overflow: hidden;
431 background: #E2CECF;
432 }
433
434 .member-content {
435 position: relative;
436 z-index: 1;
437 display: flex;
438 justify-content: space-between;
439 padding: 48rpx 46rpx 0;
440 }
441
442 .hello {
443 color: #ff6d40;
444 font-size: 52rpx;
445 line-height: 1;
446 }
447
448 .member-name {
449 margin-top: 28rpx;
450 color: #181818;
451 font-size: 34rpx;
452 font-weight: 700;
453 }
454
455 .member-desc {
456 margin-top: 10rpx;
457 color: #8f817f;
458 font-size: 22rpx;
459 }
460
461 .name-line {
462 width: 112rpx;
463 height: 6rpx;
464 margin-top: 14rpx;
465 background: #111;
466 border-radius: 8rpx;
467 }
468
469 .level-box {
470 display: flex;
471 flex-direction: column;
472 align-items: center;
473 padding-top: 8rpx;
474 }
475
476 .star {
477 width: 100rpx;
478 height: 82rpx;
479 }
480
481 .level-title {
482 margin-top: 12rpx;
483 color: #d99b1d;
484 font-size: 28rpx;
485 font-weight: 700;
486 }
487
488 .detail-btn {
489 margin-top: 8rpx;
490 padding: 4rpx 14rpx;
491 border-radius: 4rpx;
492 background: rgba(255, 255, 255, 0.8);
493 color: #5a5552;
494 font-size: 20rpx;
495 font-weight: 600;
496 }
497
498 .member-bottom {
499 position: relative;
500 z-index: 12;
501 display: flex;
502 gap: 76rpx;
503 grid-column: 1 / -1;
504 padding: 98rpx 46rpx 34rpx;
505 padding-bottom: 50px;
506 }
507
508 .info-label {
509 color: #e55f73;
510 font-size: 24rpx;
511 font-weight: 600;
512 }
513
514 .info-value {
515 margin-top: 6rpx;
516 color: #343434;
517 font-size: 25rpx;
518 }
519
520 .main-actions {
521 position: relative;
522 display: grid;
523 grid-template-columns: repeat(2, 1fr);
524 gap: 8rpx 10rpx;
525 margin-top: -255rpx;
526 padding: 0 28rpx 0;
527 overflow: hidden;
528 }
529
530 .actions-bg {
531 position: absolute;
532 top: 0;
533 left: 0;
534 width: 100%;
535 height: 596rpx;
536 z-index: 9;
537 }
538
539 .action-card {
540 position: relative;
541 z-index: 10;
542 width: 100%;
543 border-radius: 8rpx;
544 }
545
546 .dialog-wrapper {
547 width: 610rpx;
548 padding: 42rpx 34rpx 32rpx;
549 border-radius: 22rpx;
550 background: #fff;
551 box-sizing: border-box;
552 }
553
554 .dialog-title {
555 text-align: center;
556 color: #222;
557 font-size: 34rpx;
558 font-weight: 700;
559 }
560
561 .dialog-message {
562 display: flex;
563 flex-direction: column;
564 gap: 10rpx;
565 margin-top: 26rpx;
566 color: #555;
567 font-size: 28rpx;
568 line-height: 1.6;
569 text-align: center;
570 }
571
572 .dialog-footer {
573 display: flex;
574 gap: 24rpx;
575 margin-top: 36rpx;
576 }
577
578 .dialog-btn {
579 flex: 1;
580 height: 76rpx;
581 border-radius: 40rpx;
582 font-size: 28rpx;
583 line-height: 76rpx;
584 }
585
586 .dialog-btn.cancel {
587 color: #666;
588 background: #f2f2f2;
589 }
590
591 .dialog-btn.confirm {
592 color: #fff;
593 background: #ad181f;
594 }
595
596 .no-display {
597 margin-top: 24rpx;
598 color: #999;
599 font-size: 24rpx;
600 text-align: center;
601 }
602 </style>
...@@ -552,13 +552,14 @@ ...@@ -552,13 +552,14 @@
552 <uni-popup ref="examPointPopup" :mask-click="false" type="center"> 552 <uni-popup ref="examPointPopup" :mask-click="false" type="center">
553 <view class="dialog-wrapper exam-dialog"> 553 <view class="dialog-wrapper exam-dialog">
554 <view class="dialog-close" @click="closeExamPointDialog"></view> 554 <view class="dialog-close" @click="closeExamPointDialog"></view>
555 <view class="dialog-icon success-icon"> 555 <view class="dialog-icon success-icon">
556 <uni-icons color="#29c490" size="48" type="checkmark"></uni-icons> 556 <uni-icons color="#ffffff" size="40" type="check"></uni-icons>
557 </view> 557 </view>
558 <view class="dialog-title">申请成为考点</view> 558 <view class="dialog-title">申请成为考点</view>
559 <view class="dialog-message"> 559 <view class="dialog-message">
560 <text>恭喜您成为中国跆拳道协会团体会员!</text> 560 <text>恭喜您成为中国跆拳道协会单位会员!</text>
561 <text>根据协会考点管理办法,需成为考点单位才能进行考级业务的办理。</text> 561 <text>根据协会考点管理办法,需成为考点单位才能进行考级业务的办理。</text>
562 <text>是否现在申请成为考点?</text>
562 </view> 563 </view>
563 <view class="dialog-footer"> 564 <view class="dialog-footer">
564 <button class="dialog-btn cancel" @click="closeExamPointDialog">取消</button> 565 <button class="dialog-btn cancel" @click="closeExamPointDialog">取消</button>
...@@ -1049,11 +1050,11 @@ function checkDialogs() { ...@@ -1049,11 +1050,11 @@ function checkDialogs() {
1049 refreshCaptcha() 1050 refreshCaptcha()
1050 bindingPhonePopup.value.open() 1051 bindingPhonePopup.value.open()
1051 } 1052 }
1053 console.log(99,app.globalData.memberInfo?.activeStatus,app.globalData.authenticationStatus,user.hintFlag,app.globalData.deptType,memberInfoData.isPoints,app.globalData.deptType)
1052 1054
1053 // 申请考点条件: activeStatus=1 && authenticationStatus=2 && hintFlag=1 && deptType=6 && isPoints=1 1055 // 申请考点条件: activeStatus=1 && authenticationStatus=2 && hintFlag=1 && deptType=6 && isPoints=1
1054 if (app.globalData.memberInfo?.activeStatus == 1 && 1056 if (app.globalData.memberInfo?.activeStatus == 1 &&
1055 app.globalData.authenticationStatus == 2 && 1057 app.globalData.authenticationStatus == 2 &&
1056 user.hintFlag == 1 &&
1057 app.globalData.deptType == 6 && 1058 app.globalData.deptType == 6 &&
1058 memberInfoData.isPoints == 1) { 1059 memberInfoData.isPoints == 1) {
1059 examPointPopup.value.open() 1060 examPointPopup.value.open()
...@@ -1481,7 +1482,7 @@ function checkDialogs() { ...@@ -1481,7 +1482,7 @@ function checkDialogs() {
1481 } 1482 }
1482 1483
1483 .success-icon { 1484 .success-icon {
1484 color: #29c490; 1485 color: #29c490;
1485 } 1486 }
1486 1487
1487 /* 密码提示弹框样式 */ 1488 /* 密码提示弹框样式 */
......
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
13 useUserStore 13 useUserStore
14 } from '../../store/modules/user'; 14 } from '../../store/modules/user';
15 15
16 const userStore = useUserStore() 16 const userStore = useUserStore()
17 const app = getApp()
17 18
18 onShow(() => { 19 onShow(() => {
19 let user = userStore.user 20 let user = userStore.user
...@@ -25,11 +26,21 @@ ...@@ -25,11 +26,21 @@
25 } 26 }
26 27
27 let userName = uni.getStorageSync('userName') 28 let userName = uni.getStorageSync('userName')
29 console.log('userName', userName)
30 console.log('app.globalData.userType ', app.globalData.userType )
28 if (userName) { 31 if (userName) {
29 uni.reLaunch({ 32 if(app.globalData.userType == 4){
33 uni.reLaunch({
34 url: '/pages/index/daoGuanPerson'
35 })
36 return
37 }else{
38 uni.reLaunch({
30 url: '/pages/index/home' 39 url: '/pages/index/home'
31 }) 40 })
32 return 41 return
42 }
43
33 } 44 }
34 45
35 let webUserName = uni.getStorageSync('webUserName') 46 let webUserName = uni.getStorageSync('webUserName')
...@@ -43,4 +54,4 @@ ...@@ -43,4 +54,4 @@
43 </script> 54 </script>
44 <style scope lang="scss"> 55 <style scope lang="scss">
45 56
46 </style>
...\ No newline at end of file ...\ No newline at end of file
57 </style>
......
...@@ -204,7 +204,6 @@ import { ...@@ -204,7 +204,6 @@ import {
204 import config from "/config.js"; 204 import config from "/config.js";
205 import { 205 import {
206 wxLogin, 206 wxLogin,
207 logout,
208 getWebInfo 207 getWebInfo
209 } from '@/common/login.js'; 208 } from '@/common/login.js';
210 import {useUserStore} from "@/store/modules/user.js"; 209 import {useUserStore} from "@/store/modules/user.js";
...@@ -238,6 +237,9 @@ const showConfirm = ref(false) ...@@ -238,6 +237,9 @@ const showConfirm = ref(false)
238 let hasOpenedBindPopup = false 237 let hasOpenedBindPopup = false
239 238
240 onShow(() => { 239 onShow(() => {
240 // 重置绑定弹框标志,确保每次进入页面都能正确弹出
241 hasOpenedBindPopup = false
242
241 let webUserName = uni.getStorageSync('webUserName') 243 let webUserName = uni.getStorageSync('webUserName')
242 if (!webUserName) { 244 if (!webUserName) {
243 // 登录后需要等待数据加载完成 245 // 登录后需要等待数据加载完成
...@@ -245,7 +247,13 @@ onShow(() => { ...@@ -245,7 +247,13 @@ onShow(() => {
245 getWebInfo().then(() => { 247 getWebInfo().then(() => {
246 // 数据加载完成后检查是否需要弹出绑定框 248 // 数据加载完成后检查是否需要弹出绑定框
247 checkAndOpenBindPopup() 249 checkAndOpenBindPopup()
250 }).catch(() => {
251 // getWebInfo 失败时也检查一下
252 checkAndOpenBindPopup()
248 }) 253 })
254 }).catch(() => {
255 // wxLogin 失败时也检查一下
256 checkAndOpenBindPopup()
249 }) 257 })
250 } else { 258 } else {
251 // 已登录,直接检查 259 // 已登录,直接检查
...@@ -516,14 +524,23 @@ const cancelLogout = () => { ...@@ -516,14 +524,23 @@ const cancelLogout = () => {
516 }; 524 };
517 525
518 // 确认退出登录 526 // 确认退出登录
519 const confirmLogout = () => { 527 const confirmLogout = async () => {
520 // 调用退出登录接口 528 showConfirm.value = false
521 logout().then(() => { 529
522 // 跳转到登录页 530 uni.showLoading({ title: '退出中...', mask: true })
523 uni.reLaunch({ 531
524 url: '/login/login' 532 // 调用解绑接口
525 }) 533 await to(unbindUser())
526 }); 534
535 // 清除缓存和用户信息
536 uni.removeStorageSync('webUserName')
537 userStore.setPerInfo(null)
538 userStore.setUser(null)
539
540 // 跳转到登录页
541 uni.reLaunch({
542 url: '/login/login'
543 })
527 }; 544 };
528 </script> 545 </script>
529 546
......
1 <template> 1 <template>
2 <view> 2 <view class="change-level-page">
3 <view class="searchbar"> 3 <view class="page-hero">
4 <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search" 4 <view class="hero-title-row">
5 v-model="queryParams.code" placeholder="搜索变更单号" @blur="getList" @clear="getList"> 5 <view>
6 </uni-easyinput> 6 <view class="hero-title">中国跆拳道协会</view>
7 <view class="invertedbtn-red" @click="goAdd">+ 新建级位变更</view> 7 <view class="hero-subtitle">CHINESE TAEKWONDO ASSOCIATION</view>
8 </view> 8 </view>
9 9 <view class="hero-page-title">
10 <view class="appList"> 10 <text>级位变更审核</text>
11 <view class="appItem" v-for="(item,index) in list" :key="index"> 11 <view class="title-line"></view>
12 <view class="status" @click="goDetail(item)"> 12 </view>
13 <view> 13 </view>
14 <text v-if="item.status == 0" class="text-warning">待提交</text> 14
15 <text v-if="item.status == 1" class="text-primary">审核中</text> 15 <view class="search-row">
16 <text v-if="item.status == 2" class="text-success">审核通过</text> 16 <view class="search-box">
17 <text v-if="item.status == 3" class="text-danger">审核拒绝</text> 17 <uni-easyinput
18 <text v-if="item.status == 4" class="text-warning">已撤回</text> 18 v-model="queryParams.code"
19 </view> 19 :input-border="false"
20 </view> 20 class="search-input"
21 21 placeholder="输入变更单号"
22 <view class="name mt0" @click="goDetail(item)"> 22 placeholderStyle="font-size:28rpx;color:#999"
23 <text class="text-primary">{{item.code}}</text>-{{item.shenMemName}} 23 prefixIcon="search"
24 </view> 24 @confirm="getList"
25 <view class="flexbox" @click="goDetail(item)"> 25 @clear="getList"
26 <view> 26 />
27 变更人数 27 <view class="search-btn" @click="getList">搜索</view>
28 <view> 28 </view>
29 <text class="text-danger">{{item.count}}</text> 29 <view class="add-btn" @click="goAdd">
30 </view> 30 <text class="add-icon"></text>
31 31 <text>新建变更</text>
32 </view> 32 </view>
33 33 </view>
34 <view class="w50"> 34 </view>
35 提交时间 35
36 <view>{{item.commitTime||'--'}}</view> 36 <view class="status-tabs">
37 </view> 37 <view
38 </view> 38 v-for="tab in statusTabs"
39 <view class="func" v-if="(item.status==0||item.status==3||item.status==4)"> 39 :key="tab.value"
40 <button @click="handleUpdate(item)">编辑</button> 40 class="status-tab"
41 <button @click="commitFN(item)">提交审核</button> 41 :class="{ active: activeStatus === tab.value }"
42 <button @click="handleDelete(item)">删除</button> 42 @click="switchStatus(tab.value)"
43 </view> 43 >
44 44 {{ tab.label }}
45 </view> 45 </view>
46 </view> 46 </view>
47 47
48 48 <scroll-view scroll-y class="list-scroll">
49 49 <view class="card-list">
50 <view class="nodata" v-if="list.length==0"> 50 <view v-for="item in list" :key="item.id" class="change-card">
51 <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image> 51 <view class="card-top">
52 <text>暂无数据</text> 52 <view class="code-line">编号:{{ item.code || '--' }}</view>
53 </view> 53 <view class="status-text" :class="statusClass(item.status)">{{ statusText(item.status) }}</view>
54 </view> 54 </view>
55
56 <view class="org-name">{{ item.shenMemName || '--' }}</view>
57
58 <view class="info-grid">
59 <view class="info-cell">
60 <view class="info-label">变更人数</view>
61 <view class="info-value">{{ item.count || 0 }}</view>
62 </view>
63 <view class="info-cell time-cell">
64 <view class="info-label">变更时间</view>
65 <view class="info-value">{{ item.commitTime || '--' }}</view>
66 </view>
67 </view>
68
69 <view class="card-actions">
70 <view class="detail-link" @click="goDetail(item)">查看详情&gt;</view>
71 <view class="action-buttons">
72 <button class="action-btn delete" :disabled="!canEdit(item)" @click.stop="handleDelete(item)">删除</button>
73 <button class="action-btn edit" :disabled="!canEdit(item)" @click.stop="handleUpdate(item)">编辑</button>
74 <button class="action-btn submit" :disabled="!canEdit(item)" @click.stop="commitFN(item)">提交审核</button>
75 </view>
76 </view>
77 </view>
78
79 <view v-if="list.length === 0" class="nodata">
80 <image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image>
81 <text>暂无数据</text>
82 </view>
83 </view>
84 </scroll-view>
85 </view>
55 </template> 86 </template>
56 87
57 <script setup> 88 <script setup>
58 import * as api from '@/common/api.js' 89 import * as api from '@/common/api.js'
59 import config from '@/config.js' 90 import config from '@/config.js'
60 import { 91 import { ref } from 'vue'
61 ref 92 import { onShow } from '@dcloudio/uni-app'
62 } from 'vue' 93
63 import { 94 const queryParams = ref({
64 onLoad, 95 code: '',
65 onShow 96 status: ''
66 } from '@dcloudio/uni-app' 97 })
67 const app = getApp(); 98 const list = ref([])
68 const queryParams = ref({ 99 const total = ref(0)
69 code:'' 100 const activeStatus = ref('')
70 }) 101 const statusTabs = [
71 const list = ref([]) 102 { label: '全部', value: '' },
72 const total = ref(0) 103 { label: '待提交', value: '0' },
73 onShow(()=>{ 104 { label: '审核中', value: '1' },
74 getList() 105 { label: '已通过', value: '2' },
75 }) 106 { label: '已拒绝', value: '3' }
76 function goAdd(){ 107 ]
77 let path = `/personalVip/addChangeLevel` 108
78 uni.navigateTo({ 109 onShow(() => {
79 url: path 110 getList()
80 }); 111 })
81 } 112
82 function getList(){ 113 function switchStatus(status) {
83 uni.showLoading({ 114 activeStatus.value = status
84 title:'加载中' 115 queryParams.value.status = status
85 }) 116 getList()
86 api.getChangelevelList(queryParams.value).then(res=>{ 117 }
87 list.value = res.rows 118
88 total.value = res.total 119 function statusText(status) {
89 uni.hideLoading() 120 const map = {
90 }) 121 0: '待提交',
91 } 122 1: '审核中',
92 function goDetail(item){ 123 2: '已通过',
93 let path = `/personalVip/changeLevelDetail?rangeId=${item.id}` 124 3: '已拒绝',
94 uni.navigateTo({ 125 4: '已撤回'
95 url: path 126 }
96 }); 127 return map[status] || ''
97 } 128 }
98 function handleUpdate(item){ 129
99 // 编辑 130 function statusClass(status) {
100 let path = `/personalVip/addChangeLevel?rangeId=${item.id}` 131 const map = {
101 uni.navigateTo({ 132 0: 'pending',
102 url: path 133 1: 'reviewing',
103 }); 134 2: 'passed',
104 } 135 3: 'rejected',
105 function commitFN(row){ 136 4: 'pending'
106 uni.showModal({ 137 }
107 title: '提示', 138 return map[status] || ''
108 content: `确定提交吗`, 139 }
109 success: function(res) { 140
110 if (res.confirm) { 141 function canEdit(item) {
111 api.commitLevelChange(row.id).then(Response=>{ 142 return item.status == 0 || item.status == 3 || item.status == 4
112 uni.showToast({ 143 }
113 icon:"none", 144
114 title:'提交成功!' 145 function goAdd() {
115 }) 146 uni.navigateTo({
116 getList() 147 url: '/personalVip/addChangeLevel'
117 }) 148 })
118 } 149 }
119 }
120 })
121 }
122 function handleDelete(row){
123 uni.showModal({
124 title: '提示',
125 content: `确定删除吗`,
126 success: function(res) {
127 if (res.confirm) {
128 api.levelModRangeDelete([row.id]).then(Response=>{
129 uni.showToast({
130 icon:"none",
131 title:'删除成功!'
132 })
133 getList()
134 })
135 }
136 }
137 })
138 }
139 150
151 function getList() {
152 uni.showLoading({
153 title: '加载中'
154 })
155 api.getChangelevelList(queryParams.value).then(res => {
156 list.value = res.rows || []
157 total.value = res.total || 0
158 }).finally(() => {
159 uni.hideLoading()
160 })
161 }
162
163 function goDetail(item) {
164 uni.navigateTo({
165 url: `/personalVip/changeLevelDetail?rangeId=${item.id}`
166 })
167 }
168
169 function handleUpdate(item) {
170 uni.navigateTo({
171 url: `/personalVip/addChangeLevel?rangeId=${item.id}`
172 })
173 }
174
175 function commitFN(row) {
176 uni.showModal({
177 title: '提示',
178 content: '确定提交吗',
179 success: function(res) {
180 if (res.confirm) {
181 api.commitLevelChange(row.id).then(() => {
182 uni.showToast({
183 icon: 'none',
184 title: '提交成功!'
185 })
186 getList()
187 })
188 }
189 }
190 })
191 }
192
193 function handleDelete(row) {
194 uni.showModal({
195 title: '提示',
196 content: '确定删除吗',
197 success: function(res) {
198 if (res.confirm) {
199 api.levelModRangeDelete([row.id]).then(() => {
200 uni.showToast({
201 icon: 'none',
202 title: '删除成功!'
203 })
204 getList()
205 })
206 }
207 }
208 })
209 }
140 </script> 210 </script>
141 211
142 <style lang='scss' scoped> 212 <style lang="scss" scoped>
143 .searchbar { 213 .change-level-page {
144 display: flex; 214 min-height: 100vh;
145 align-items: center; 215 background: #ededf0;
146 padding: 25rpx; 216 overflow: hidden;
147 box-sizing: border-box; 217 }
218
219 .page-hero {
220 padding: calc(env(safe-area-inset-top) + 88rpx) 36rpx 28rpx;
221 background: linear-gradient(135deg, #b00005 0%, #760000 100%);
222 color: #fff;
223 }
224
225 .hero-title-row {
226 display: flex;
227 align-items: flex-end;
228 justify-content: space-between;
229 margin-bottom: 40rpx;
230 }
231
232 .hero-title {
233 font-size: 38rpx;
234 letter-spacing: 2rpx;
235 }
236
237 .hero-subtitle {
238 margin-top: 8rpx;
239 color: rgba(255, 255, 255, 0.62);
240 font-size: 16rpx;
241 }
242
243 .hero-page-title {
244 color: #f4b536;
245 font-size: 36rpx;
246 font-weight: 500;
247 text-align: right;
248 }
249
250 .title-line {
251 width: 54rpx;
252 height: 6rpx;
253 margin: 14rpx 0 0 auto;
254 border-radius: 10rpx;
255 background: #f4b536;
256 }
257
258 .search-row {
259 display: flex;
260 align-items: center;
261 gap: 16rpx;
262 }
263
264 .search-box {
265 flex: 1;
266 display: flex;
267 align-items: center;
268 height: 64rpx;
269 overflow: hidden;
270 border-radius: 34rpx;
271 background: #fff;
272 }
273
274 .search-input {
275 flex: 1;
276
277 :deep(.uni-easyinput__content) {
278 height: 64rpx;
279 padding: 0 12rpx 0 22rpx;
280 border-radius: 34rpx;
281 background: #fff;
282 }
283 }
284
285 .search-btn {
286 width: 88rpx;
287 height: 52rpx;
288 margin-right: 6rpx;
289 border-radius: 28rpx;
290 background: #c91c34;
291 color: #fff;
292 font-size: 24rpx;
293 font-weight: 700;
294 line-height: 52rpx;
295 text-align: center;
296 }
297
298 .add-btn {
299 display: flex;
300 align-items: center;
301 justify-content: center;
302 width: 194rpx;
303 height: 64rpx;
304 border-radius: 34rpx;
305 background: #fff;
306 color: #222;
307 font-size: 28rpx;
308 font-weight: 700;
309 }
310
311 .add-icon {
312 margin-right: 6rpx;
313 color: #c30d23;
314 font-size: 40rpx;
315 line-height: 1;
316 }
317
318 .status-tabs {
319 display: flex;
320 align-items: center;
321 justify-content: space-around;
322 height: 92rpx;
323 background: #fff;
324 }
325
326 .status-tab {
327 position: relative;
328 height: 92rpx;
329 color: #666;
330 font-size: 30rpx;
331 font-weight: 700;
332 line-height: 92rpx;
333 }
334
335 .status-tab.active {
336 color: #c30d23;
337 }
338
339 .status-tab.active::after {
340 content: '';
341 position: absolute;
342 left: 50%;
343 bottom: 18rpx;
344 width: 54rpx;
345 height: 4rpx;
346 border-radius: 4rpx;
347 background: #c30d23;
348 transform: translateX(-50%);
349 }
350
351 .list-scroll {
352 height: calc(100vh - 364rpx);
353 }
354
355 .card-list {
356 padding: 22rpx 30rpx 40rpx;
357 }
358
359 .change-card {
360 margin-bottom: 20rpx;
361 padding: 20rpx 20rpx 18rpx;
362 border-radius: 18rpx;
363 background: #fff;
364 }
365
366 .card-top {
367 display: flex;
368 align-items: center;
369 justify-content: space-between;
370 }
371
372 .code-line {
373 color: #0076ce;
374 font-size: 26rpx;
375 }
376
377 .status-text {
378 font-size: 26rpx;
379 font-weight: 700;
380 }
381
382 .status-text.pending {
383 color: #f0a000;
384 }
385
386 .status-text.reviewing {
387 color: #0076ce;
388 }
389
390 .status-text.passed {
391 color: #28a745;
392 }
393
394 .status-text.rejected {
395 color: #e60012;
396 }
397
398 .org-name {
399 margin-top: 8rpx;
400 color: #333;
401 font-size: 30rpx;
402 }
403
404 .info-grid {
405 display: grid;
406 grid-template-columns: 1fr 1.5fr;
407 margin-top: 18rpx;
408 }
409
410 .info-label {
411 color: #999;
412 font-size: 24rpx;
413 }
414
415 .info-value {
416 margin-top: 4rpx;
417 color: #555;
418 font-size: 34rpx;
419 line-height: 1.2;
420 }
421
422 .time-cell .info-value {
423 font-size: 32rpx;
424 }
425
426 .card-actions {
427 display: flex;
428 align-items: center;
429 justify-content: space-between;
430 margin-top: 20rpx;
431 }
432
433 .detail-link {
434 color: #333;
435 font-size: 24rpx;
436 font-weight: 700;
437 }
438
439 .action-buttons {
440 display: flex;
441 align-items: center;
442 gap: 16rpx;
443 }
444
445 .action-btn {
446 width: 112rpx;
447 height: 42rpx;
448 margin: 0;
449 padding: 0;
450 border-radius: 10rpx;
451 background: #fff;
452 font-size: 24rpx;
453 line-height: 42rpx;
454
455 &::after {
456 border: none;
457 }
458 }
459
460 .action-btn.delete {
461 color: #e60012;
462 border: 1rpx solid #e60012;
463 }
148 464
149 :deep(.uni-easyinput .uni-easyinput__content) { 465 .action-btn.edit {
150 border-radius: 35rpx; 466 color: #333;
151 border: none; 467 border: 1rpx solid #999;
152 height: 70rpx; 468 }
153 }
154 469
155 :deep(.uni-easyinput__content-input) { 470 .action-btn.submit {
156 font-size: 26rpx; 471 color: #0076ce;
157 } 472 border: 1rpx solid #0076ce;
473 }
158 474
159 .invertedbtn-red { 475 .action-btn[disabled] {
160 border-radius: 50px; 476 color: #c9c9c9;
161 background-color: #fff; 477 border-color: #e1e1e1;
478 background: #fff;
479 }
162 480
163 font-size: 30rpx; 481 .nodata {
164 padding: 10rpx 20rpx; 482 display: flex;
165 } 483 flex-direction: column;
166 } 484 align-items: center;
485 padding-top: 120rpx;
486 color: #999;
487 font-size: 28rpx;
167 488
489 image {
490 width: 220rpx;
491 height: 220rpx;
492 margin-bottom: 20rpx;
493 }
494 }
168 </style> 495 </style>
......
1 <template> 1 <template>
2 <view class="hasfixedbottom"> 2 <view class="hasfixedbottom">
3 <view class="searchbar"> 3 <view class="searchbar">
4
4 <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search" 5 <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search"
5 v-model="queryParams.perName" placeholder="搜索姓名或证件号码" @blur="getList" @clear="getList"> 6 v-model="queryParams.perName" placeholder="搜索姓名或证件号码" @blur="getList" @clear="getList">
6 </uni-easyinput> 7 </uni-easyinput>
7 <view class="invertedbtn-red" @click="goVipList">+ 添加会员</view> 8 <view class="invertedbtn-red" @click="showAddPopup">+ 添加</view>
9 <view class="invertedbtn-red" @click="goVipList">+ 在线选择</view>
8 </view> 10 </view>
9 <view style="padding:0 20rpx"> 11 <view style="padding:0 20rpx">
10 12
...@@ -58,6 +60,33 @@ ...@@ -58,6 +60,33 @@
58 </view> 60 </view>
59 </view> 61 </view>
60 </uni-popup> 62 </uni-popup>
63
64 <!-- 添加会员弹框 -->
65 <uni-popup ref="addPopup" type="center">
66 <view class="add-popup">
67 <view class="popup-title">添加会员</view>
68 <view class="popup-form">
69 <view class="form-item">
70 <view class="form-label">证件类型</view>
71 <view class="form-input">
72 <picker :value="idcListIndex" :range="idcList" range-key="label" @change="onIdcTypeChange">
73 <view class="picker-value">{{ idcList[idcListIndex]?.label }}</view>
74 </picker>
75 </view>
76 </view>
77 <view class="form-item">
78 <view class="form-label">证件号</view>
79 <view class="form-input">
80 <input v-model="addForm.idcCode" placeholder="请输入证件号" placeholder-class="placeholder-class"/>
81 </view>
82 </view>
83 </view>
84 <view class="popup-btns">
85 <view class="popup-btn cancel" @click="closeAddPopup">取消</view>
86 <view class="popup-btn confirm" @click="confirmAdd">确定</view>
87 </view>
88 </view>
89 </uni-popup>
61 </view> 90 </view>
62 </template> 91 </template>
63 92
...@@ -78,7 +107,18 @@ ...@@ -78,7 +107,18 @@
78 const nowYear = ref(1) 107 const nowYear = ref(1)
79 const nowItem = ref({}) 108 const nowItem = ref({})
80 const pickView = ref(null) 109 const pickView = ref(null)
110 const addPopup = ref(null)
81 const visible = ref(true) 111 const visible = ref(true)
112 const addForm = ref({
113 idcCode: '',
114 idType: '0'
115 })
116 const idcList = ref([
117 { label: '身份证', value: '0' },
118 { label: '来往大陆(内地)通行证', value: '1' },
119 { label: '香港身份证', value: '5' }
120 ])
121 const idcListIndex = ref(0)
82 const yearlist = ref([{ 122 const yearlist = ref([{
83 text: '一年', 123 text: '一年',
84 value: 1 124 value: 1
...@@ -197,6 +237,50 @@ ...@@ -197,6 +237,50 @@
197 url: `/myCenter/payOrder?rangeId=${queryParams.value.rangeId}` 237 url: `/myCenter/payOrder?rangeId=${queryParams.value.rangeId}`
198 }) 238 })
199 } 239 }
240
241 // 显示添加弹框
242 function showAddPopup() {
243 addForm.value.idcCode = ''
244 idcListIndex.value = 0
245 addPopup.value.open()
246 }
247
248 // 关闭添加弹框
249 function closeAddPopup() {
250 addPopup.value.close()
251 }
252
253 // 证件类型选择
254 function onIdcTypeChange(e) {
255 idcListIndex.value = e.detail.value
256 addForm.value.idType = idcList.value[idcListIndex.value].value
257 }
258
259 // 确认添加
260 async function confirmAdd() {
261 if (!addForm.value.idcCode) {
262 uni.showToast({ title: '请输入证件号', icon: 'none' })
263 return
264 }
265 if (!queryParams.value.rangeId) {
266 uni.showToast({ title: '缺少rangeId', icon: 'none' })
267 return
268 }
269
270 try {
271 await api.memberInsertPersons({
272 rangeId: queryParams.value.rangeId,
273 year: 1,
274 idcCode: addForm.value.idcCode
275 })
276 uni.showToast({ title: '添加成功', icon: 'success' })
277 closeAddPopup()
278 getList()
279 getCount()
280 } catch (e) {
281 console.error(e)
282 }
283 }
200 </script> 284 </script>
201 285
202 <style scoped lang="scss"> 286 <style scoped lang="scss">
...@@ -301,4 +385,86 @@ ...@@ -301,4 +385,86 @@
301 font-size: 32rpx; 385 font-size: 32rpx;
302 border: none; 386 border: none;
303 } 387 }
388
389 /* 添加会员弹框 */
390 .add-popup {
391 width: 600rpx;
392 background: #ffffff;
393 border-radius: 24rpx;
394 overflow: hidden;
395 }
396
397 .popup-title {
398 font-size: 32rpx;
399 font-weight: 500;
400 color: #333;
401 text-align: center;
402 padding: 40rpx 30rpx 20rpx;
403 }
404
405 .popup-form {
406 padding: 20rpx 30rpx 40rpx;
407 }
408
409 .form-item {
410 display: flex;
411 align-items: center;
412 margin-bottom: 24rpx;
413 }
414
415 .form-item:last-child {
416 margin-bottom: 0;
417 }
418
419 .form-label {
420 width: 140rpx;
421 font-size: 28rpx;
422 color: #333;
423 flex-shrink: 0;
424 }
425
426 .form-input {
427 flex: 1;
428 background: #f5f5f5;
429 border-radius: 12rpx;
430 padding: 20rpx 24rpx;
431 }
432
433 .form-input input {
434 font-size: 28rpx;
435 color: #333;
436 width: 100%;
437 }
438
439 .picker-value {
440 font-size: 28rpx;
441 color: #333;
442 }
443
444 .placeholder-class {
445 color: #999;
446 }
447
448 .popup-btns {
449 display: flex;
450 border-top: 1rpx solid #eee;
451 }
452
453 .popup-btn {
454 flex: 1;
455 height: 100rpx;
456 line-height: 100rpx;
457 text-align: center;
458 font-size: 30rpx;
459 }
460
461 .popup-btn.cancel {
462 color: #666;
463 border-right: 1rpx solid #eee;
464 }
465
466 .popup-btn.confirm {
467 color: #E60012;
468 font-weight: 500;
469 }
304 </style> 470 </style>
...\ No newline at end of file ...\ No newline at end of file
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!