dbdf4c4c by lttnew

样式优化

1 parent 9d8dc7ee
1 // dev 1 // dev
2 const baseUrl_api = 'http://192.168.1.137:8787' 2 // const baseUrl_api = 'http://192.168.1.137:8787'
3 // const baseUrl_api = 'http://tk001.wxjylt.com/stage-api' 3 const baseUrl_api = 'http://tk001.wxjylt.com/stage-api'
4 const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do' 4 const payUrl = 'https://wxpay.cmbc.com.cn/mobilePlatform/appserver/lcbpPay.do'
5 5
6 // prod 6 // prod
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
22 22
23 <uni-list-item thumb="/static/user_icon03.png" title="账号安全" showArrow clickable @click="goPath('/myCenter/safe')"> 23 <uni-list-item thumb="/static/user_icon03.png" title="账号安全" showArrow clickable @click="goPath('/myCenter/safe')">
24 </uni-list-item> 24 </uni-list-item>
25 <uni-list-item thumb="/static/user_icon03.png" v-if="userType==2 || userType==6" title="我的订单" showArrow clickable @click="goPath('/myCenter/order')"> 25 <uni-list-item thumb="/static/user_icon04.png" v-if="userType==2 || userType==6" title="我的订单" showArrow clickable @click="goPath('/myCenter/order')">
26 </uni-list-item> 26 </uni-list-item>
27 27
28 </uni-list> 28 </uni-list>
......
...@@ -33,8 +33,9 @@ ...@@ -33,8 +33,9 @@
33 <!-- 订单头部:日期 + 状态 --> 33 <!-- 订单头部:日期 + 状态 -->
34 <view class="card-header"> 34 <view class="card-header">
35 <view class="date"> 35 <view class="date">
36 <image :src="config.baseUrl_api + '/fs/static/calendar@2x.png'" v-if="item.payTime" mode="widthFix" style="width:30rpx;height:30rpx;"/> 36 <image :src="config.baseUrl_api + '/fs/static/calendar@2x.png'" mode="widthFix" style="width:30rpx;height:30rpx;"/>
37 <text class="date-text" v-if="item.payTime">{{ item.payTime }}</text> 37 <!-- -->
38 <text class="value code-text" @click="goToDetail(item)">{{ item.wfCode || '——' }}</text>
38 </view> 39 </view>
39 <view class="status-tags"> 40 <view class="status-tags">
40 <view 41 <view
...@@ -65,10 +66,10 @@ ...@@ -65,10 +66,10 @@
65 <text class="label">订单编号:</text> 66 <text class="label">订单编号:</text>
66 <text class="value">{{ item.tradeNo || '——' }}</text> 67 <text class="value">{{ item.tradeNo || '——' }}</text>
67 </view> 68 </view>
68 <view class="info-row"> 69 <!-- <view class="info-row">
69 <text class="label">缴费编号:</text> 70 <text class="label">缴费编号:</text>
70 <text class="value">{{ item.wfCode || '——' }}</text> 71
71 </view> 72 </view> -->
72 73
73 <!-- 核心:前2tab仅展示缴费年限,后2tab仅展示人数合计 --> 74 <!-- 核心:前2tab仅展示缴费年限,后2tab仅展示人数合计 -->
74 <view class="info-section flex f-j-s" v-if="item.content"> 75 <view class="info-section flex f-j-s" v-if="item.content">
...@@ -168,7 +169,9 @@ import * as api from '@/common/api.js' ...@@ -168,7 +169,9 @@ import * as api from '@/common/api.js'
168 import config from '@/config.js' 169 import config from '@/config.js'
169 // 获取deptType值(初始值为0,在onMounted中设置实际值) 170 // 获取deptType值(初始值为0,在onMounted中设置实际值)
170 const deptType = ref(0); 171 const deptType = ref(0);
171 172 const goToDetail = (item) => {
173 uni.navigateTo({ url: `/pages/rank/applyDetail?examId=${item.sourceId || item.id}&type=${queryParams.type}` });
174 }
172 175
173 // 标签栏配置(根据deptType动态生成) 176 // 标签栏配置(根据deptType动态生成)
174 const tabs = computed(() => { 177 const tabs = computed(() => {
...@@ -803,4 +806,10 @@ const closeCancelPopup = () => { ...@@ -803,4 +806,10 @@ const closeCancelPopup = () => {
803 border: none; 806 border: none;
804 } 807 }
805 } 808 }
809 .code-text {
810 font-size: 28rpx;
811 font-weight: 600;
812 color: #e8341d;
813 letter-spacing: 1rpx;
814 }
806 </style> 815 </style>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -119,7 +119,7 @@ ...@@ -119,7 +119,7 @@
119 信息变更 119 信息变更
120 </view> 120 </view>
121 <view @click="goPath('/group/auditRecord1')"> 121 <view @click="goPath('/group/auditRecord1')">
122 <image :src="config.baseUrl_api+'/fs/static/icon/27.png'" /> 122 <image :src="config.baseUrl_api+'/fs/static/icon/17.png'" />
123 审核记录 123 审核记录
124 </view> 124 </view>
125 <view @click="goPath('/level/ztx/examinationVerification')"> 125 <view @click="goPath('/level/ztx/examinationVerification')">
...@@ -141,11 +141,11 @@ ...@@ -141,11 +141,11 @@
141 级位变更 141 级位变更
142 </view> 142 </view>
143 <view @click="goPath('/level/auditRecord2')"> 143 <view @click="goPath('/level/auditRecord2')">
144 <image :src="config.baseUrl_api+'/fs/static/icon/27.png'" /> 144 <image :src="config.baseUrl_api+'/fs/static/icon/17.png'" />
145 审核记录 145 审核记录
146 </view> 146 </view>
147 <view @click="goPath('/level/ztx/costSettlement')"> 147 <view @click="goPath('/level/ztx/costSettlement')">
148 <image :src="config.baseUrl_api+'/fs/static/icon/27.png'" /> 148 <image :src="config.baseUrl_api+'/fs/static/icon/10.png'" />
149 费用结算 149 费用结算
150 </view> 150 </view>
151 </view> 151 </view>
...@@ -237,7 +237,7 @@ ...@@ -237,7 +237,7 @@
237 证书发布 237 证书发布
238 </view> 238 </view>
239 <view @click="goPath('/level/ztx/mail')"> 239 <view @click="goPath('/level/ztx/mail')">
240 <image :src="config.baseUrl_api+'/fs/static/icon/18.png'" /> 240 <image :src="config.baseUrl_api+'/fs/static/icon/3.png'" />
241 证书邮寄 241 证书邮寄
242 </view> 242 </view>
243 <view @click="goPath('/personalVip/changeLevelAudit')"> 243 <view @click="goPath('/personalVip/changeLevelAudit')">
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 <view class="page-container"> 2 <view class="page-container">
3 <!-- 会员卡区域 --> 3 <!-- 会员卡区域 -->
4 <view class="member-card"> 4 <view class="member-card">
5 <image class="card-bg" :src="config.baseUrl_api + '/fs/static/slices/user_01@2x.png'" mode="aspectFill"> 5 <image class="card-bg" :src="config.baseUrl_api + '/fs/static/user_01@2x.png'" mode="aspectFill">
6 </image> 6 </image>
7 7
8 <!-- 绑定/解绑学员 --> 8 <!-- 绑定/解绑学员 -->
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 <!-- <image class="avatar" v-if="perInfo.photo" :src="config.baseUrl_api + perInfo.photo" 18 <!-- <image class="avatar" v-if="perInfo.photo" :src="config.baseUrl_api + perInfo.photo"
19 mode="aspectFill"> 19 mode="aspectFill">
20 </image> --> 20 </image> -->
21 <image class="avatar" :src="config.baseUrl_api + '/fs/static/slices/tx@2x.png'" 21 <image class="avatar" :src="config.baseUrl_api + '/fs/static/tx@2x.png'"
22 mode="aspectFill"> 22 mode="aspectFill">
23 </image> 23 </image>
24 </view> 24 </view>
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
35 35
36 <!-- 已过期印章 --> 36 <!-- 已过期印章 -->
37 <image v-if="perInfo?.perValidDateFlag == 0" class="expired-stamp" 37 <image v-if="perInfo?.perValidDateFlag == 0" class="expired-stamp"
38 :src="config.baseUrl_api + '/fs/static/slices/end@2x.png'" mode="aspectFit"> 38 :src="config.baseUrl_api + '/fs/static/end@2x.png'" mode="aspectFit">
39 </image> 39 </image>
40 </view> 40 </view>
41 41
......
1 <template> 1 <template>
2 <view class="page-container"> 2 <view class="page-container">
3 3 <!-- 加载状态 -->
4 <!-- 表格头部 --> 4 <view v-if="loading" class="loading-container">
5 <view class="table-header"> 5 <uni-load-more status="loading"></uni-load-more>
6 <view class="table-cell table-cell-1">序号</view>
7 <view class="table-cell table-cell-2">级位</view>
8 <view class="table-cell table-cell-3">级位号</view>
9 <view class="table-cell table-cell-4">获得证书时间</view>
10 <view class="table-cell table-cell-5">操作</view>
11 </view> 6 </view>
12 7
13 <!-- 表格内容 --> 8 <!-- 列表内容 -->
14 <view v-if="loading" class="loading-container"> 9 <view v-else class="list-content">
15 <uni-icons type="spinner" size="40" color="#409eff" class="loading-icon" /> 10 <view class="record-card" v-for="(item, index) in levelRecords" :key="index">
16 <view class="loading-text">加载中...</view> 11 <!-- <view class="card-header">
12 <text class="card-index">{{ index + 1 }}</text>
13 <text class="card-level">{{ szToHz(item.level) }}</text>
14 </view> -->
15 <view class="card-body">
16 <view class="card-row">
17 <text class="row-label">级位</text>
18 <text class="row-value">{{ szToHz(item.level)}}</text>
19 </view>
20 <view class="card-row">
21 <text class="row-label">级位号</text>
22 <text class="row-value">{{ item.certCode || '-' }}</text>
23 </view>
24 <view class="card-row">
25 <text class="row-label">获得证书时间</text>
26 <text class="row-value">{{ item.createTime ? item.createTime.substring(0, 10) : '-' }}</text>
27 </view>
28 <view class="card-row" v-if="item.remark?.length > 0">
29 <text class="row-label">变更记录</text>
30 <text class="row-value link" @click="showChangeRecord(item)">查看详情</text>
17 </view> 31 </view>
18 <view v-else class="table-content">
19 <view class="table-row" v-for="(item, index) in levelRecords" :key="index">
20 <view class="table-cell table-cell-1">{{ index + 1 }}</view>
21 <view class="table-cell table-cell-2">{{ szToHz(item.level) }}</view>
22 <view class="table-cell table-cell-3">{{ item.certCode }}</view>
23 <view class="table-cell table-cell-4">{{ item.createTime ? item.createTime.substring(0, 10) : '--' }}</view>
24 <view class="table-cell table-cell-5">
25 <view class="change-record-btn" @click="showChangeRecord(item)" v-if="item.remark?.length>0">变更记录</view>
26 </view> 32 </view>
27 </view> 33 </view>
28 34
...@@ -46,30 +52,22 @@ ...@@ -46,30 +52,22 @@
46 <view v-if="currentChangeRecord" class="change-details"> 52 <view v-if="currentChangeRecord" class="change-details">
47 <view class="change-item"> 53 <view class="change-item">
48 <view class="change-label">变更名称:{{ currentChangeRecord.modName || '等级变更' }}</view> 54 <view class="change-label">变更名称:{{ currentChangeRecord.modName || '等级变更' }}</view>
49 <!-- <view class="change-value"></view> -->
50 </view> 55 </view>
51 <view class="change-item"> 56 <view class="change-item">
52 <view class="change-label">考级级别:{{ szToHz(currentChangeRecord.oldJi) }}</view> 57 <view class="change-label">考级级别:{{ szToHz(currentChangeRecord.oldJi) }}</view>
53 <!-- <view class="change-value"></view> -->
54 </view> 58 </view>
55 <view class="change-item"> 59 <view class="change-item">
56 <view class="change-label">变更后级位:{{ szToHz(currentChangeRecord.newJi) }}</view> 60 <view class="change-label">变更后级位:{{ szToHz(currentChangeRecord.newJi) }}</view>
57 <!-- <view class="change-value"></view> -->
58 </view> 61 </view>
59 <view class="change-item"> 62 <view class="change-item">
60 <view class="change-label">变更时间:{{ parseTime(currentChangeRecord.modTime) }}</view> 63 <view class="change-label">变更时间:{{ parseTime(currentChangeRecord.modTime) }}</view>
61 <!-- <view class="change-value">/view> -->
62 </view> 64 </view>
63 </view> 65 </view>
64 <!-- 空状态 -->
65 <view v-else class="empty-state"> 66 <view v-else class="empty-state">
66 <uni-icons type="empty" size="60" color="#ccc" /> 67 <uni-icons type="empty" size="60" color="#ccc" />
67 <view class="empty-text">暂无变更记录</view> 68 <view class="empty-text">暂无变更记录</view>
68 </view> 69 </view>
69 </view> 70 </view>
70 <!-- <view class="popup-footer">
71 <button class="confirm-btn" @click="closeChangeRecord">确定</button>
72 </view> -->
73 </view> 71 </view>
74 </uni-popup> 72 </uni-popup>
75 </view> 73 </view>
...@@ -189,133 +187,91 @@ ...@@ -189,133 +187,91 @@
189 .page-container { 187 .page-container {
190 min-height: 100vh; 188 min-height: 100vh;
191 background: #f5f5f5; 189 background: #f5f5f5;
190 padding: 20rpx;
192 } 191 }
193 192
194 /* 导航栏 */ 193 /* 加载状态 */
195 .nav-bar { 194 .loading-container {
196 display: flex;
197 align-items: center;
198 justify-content: space-between;
199 height: 88rpx;
200 background: #ffffff;
201 padding: 0 30rpx;
202 box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
203 position: sticky;
204 top: 0;
205 z-index: 100;
206 }
207
208 .nav-left {
209 width: 44rpx;
210 height: 44rpx;
211 display: flex; 195 display: flex;
196 flex-direction: column;
212 align-items: center; 197 align-items: center;
213 justify-content: center; 198 justify-content: center;
199 height: 500rpx;
214 } 200 }
215 201
216 .nav-title { 202 /* 列表内容 */
217 font-size: 32rpx; 203 .list-content {
218 font-weight: 500; 204 padding-bottom: 20rpx;
219 color: #333;
220 }
221
222 .nav-right {
223 width: 44rpx;
224 }
225
226 /* 表格头部 */
227 .table-header {
228 display: flex;
229 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
230 padding: 0 30rpx;
231 position: sticky;
232 // top: 88rpx;
233 z-index: 90;
234 } 205 }
235 206
236 /* 表格内容 */ 207 /* 卡片 */
237 .table-content { 208 .record-card {
238 background: #ffffff; 209 background: #fff;
239 margin: 20rpx 20rpx;
240 border-radius: 16rpx; 210 border-radius: 16rpx;
211 margin-bottom: 20rpx;
241 overflow: hidden; 212 overflow: hidden;
242 box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); 213 box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
243 } 214 }
244 215
245 /* 表格行 */ 216 .card-header {
246 .table-row {
247 display: flex; 217 display: flex;
248 padding: 0 30rpx; 218 align-items: center;
249 border-bottom: 1rpx solid #f0f0f0; 219 padding: 24rpx 30rpx;
250 transition: all 0.3s ease; 220 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
251 }
252
253 .table-row:last-child {
254 border-bottom: none;
255 }
256
257 .table-row:hover {
258 background: #fff9f0;
259 }
260 221
261 /* 表格单元格 */ 222 .card-index {
262 .table-cell { 223 width: 44rpx;
263 padding: 24rpx 0; 224 height: 44rpx;
264 font-size: 26rpx; 225 background: rgba(255, 255, 255, 0.3);
265 color: #333; 226 border-radius: 50%;
266 display: flex; 227 display: flex;
267 align-items: center; 228 align-items: center;
268 justify-content: center; 229 justify-content: center;
269 text-align: center; 230 font-size: 24rpx;
231 color: #fff;
232 margin-right: 16rpx;
270 } 233 }
271 234
272 .table-header .table-cell { 235 .card-level {
273 color: #ffffff; 236 font-size: 32rpx;
274 font-weight: 500; 237 font-weight: 600;
238 color: #fff;
275 } 239 }
276
277 /* 单元格宽度 */
278 .table-cell-1 {
279 width: 80rpx;
280 } 240 }
281 241
282 .table-cell-2 { 242 .card-body {
283 width: 120rpx; 243 padding: 8rpx 24rpx 24rpx;
284 } 244 }
285 245
286 .table-cell-3 { 246 .card-row {
287 flex: 1; 247 display: flex;
288 padding: 0 10rpx; 248 justify-content: space-between;
289 } 249 align-items: center;
250 padding: 20rpx 0;
251 border-bottom: 1rpx solid #f5f5f5;
290 252
291 .table-cell-4 { 253 &:last-child {
292 width: 200rpx; 254 border-bottom: none;
293 } 255 }
294 256
295 .table-cell-5 { 257 .row-label {
296 width: 150rpx; 258 font-size: 26rpx;
259 color: #999;
260 flex-shrink: 0;
297 } 261 }
298 262
299 /* 变更记录按钮 */ 263 .row-value {
300 .change-record-btn { 264 font-size: 26rpx;
301 background: linear-gradient(135deg, #ff6b6b, #ff9f43); 265 color: #333;
302 color: #ffffff; 266 text-align: right;
303 padding: 8rpx 16rpx; 267 flex: 1;
304 border-radius: 20rpx; 268 margin-left: 20rpx;
305 font-size: 24rpx; 269 word-break: break-all;
306 text-align: center;
307 cursor: pointer;
308 transition: all 0.3s ease;
309 }
310 270
311 .change-record-btn:hover { 271 &.link {
312 transform: scale(1.05); 272 color: #1890ff;
313 box-shadow: 0 4rpx 8rpx rgba(255, 107, 107, 0.3); 273 }
314 } 274 }
315
316 .change-record-btn:disabled {
317 background: #ccc;
318 cursor: not-allowed;
319 } 275 }
320 276
321 /* 空状态 */ 277 /* 空状态 */
...@@ -335,11 +291,10 @@ ...@@ -335,11 +291,10 @@
335 291
336 /* 弹窗 */ 292 /* 弹窗 */
337 .popup-content { 293 .popup-content {
338 width: 300px; 294 width: 600rpx;
339 background: #ffffff; 295 background: #ffffff;
340 border-radius: 20rpx; 296 border-radius: 20rpx;
341 overflow: hidden; 297 overflow: hidden;
342 box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
343 } 298 }
344 299
345 .popup-header { 300 .popup-header {
...@@ -366,148 +321,25 @@ ...@@ -366,148 +321,25 @@
366 border-radius: 50%; 321 border-radius: 50%;
367 } 322 }
368 323
369 .popup-close uni-icons {
370 color: #ffffff;
371 }
372
373 .popup-body { 324 .popup-body {
374 padding: 40rpx; 325 padding: 40rpx;
375 } 326 }
376 327
377 /* 变更记录详情 */
378 .change-details { 328 .change-details {
379 width: 100%; 329 width: 100%;
380 } 330 }
381 331
382 .change-item { 332 .change-item {
383 margin-bottom: 30rpx; 333 margin-bottom: 30rpx;
384 }
385 334
386 .change-item:last-child { 335 &:last-child {
387 margin-bottom: 0; 336 margin-bottom: 0;
388 } 337 }
338 }
389 339
390 .change-label { 340 .change-label {
391 font-size: 26rpx; 341 font-size: 26rpx;
392 color: #666; 342 color: #666;
393 margin-bottom: 10rpx;
394 font-weight: 500;
395 }
396
397 .change-value {
398 font-size: 28rpx;
399 color: #333;
400 padding: 16rpx 24rpx;
401 background: #fff9f0;
402 border-radius: 12rpx;
403 border-left: 4rpx solid #ff6b6b;
404 }
405
406 .popup-footer {
407 padding: 0 30rpx 30rpx;
408 }
409
410 .confirm-btn {
411 width: 100%;
412 height: 80rpx;
413 background: linear-gradient(135deg, #ff6b6b, #ff9f43);
414 color: #ffffff;
415 border: none;
416 border-radius: 40rpx;
417 font-size: 28rpx;
418 font-weight: 500; 343 font-weight: 500;
419 transition: all 0.3s ease;
420 }
421
422 .confirm-btn:hover {
423 transform: translateY(-2rpx);
424 box-shadow: 0 4rpx 12rpx rgba(255, 107, 107, 0.3);
425 }
426
427 /* 加载状态 */
428 .loading-container {
429 display: flex;
430 flex-direction: column;
431 align-items: center;
432 justify-content: center;
433 height: 500rpx;
434 }
435
436 .loading-icon {
437 animation: spin 1s linear infinite;
438 color: #ff6b6b;
439 }
440
441 .loading-text {
442 margin-top: 20rpx;
443 font-size: 28rpx;
444 color: #ff6b6b;
445 }
446
447 @keyframes spin {
448 from {
449 transform: rotate(0deg);
450 }
451 to {
452 transform: rotate(360deg);
453 }
454 }
455
456 /* 响应式调整 */
457 @media (max-width: 375px) {
458 .table-header,
459 .table-row {
460 padding: 0 20rpx;
461 }
462
463 .table-cell {
464 font-size: 24rpx;
465 padding: 20rpx 0;
466 }
467
468 .table-cell-1 {
469 width: 60rpx;
470 }
471
472 .table-cell-2 {
473 width: 100rpx;
474 }
475
476 .table-cell-4 {
477 width: 160rpx;
478 }
479
480 .table-cell-5 {
481 width: 120rpx;
482 }
483
484 .change-record-btn {
485 font-size: 22rpx;
486 padding: 6rpx 12rpx;
487 }
488
489 .popup-content {
490 width: 300px;
491 max-width: 450rpx;
492 }
493
494 .popup-header,
495 .popup-body,
496 .popup-footer {
497 padding: 24rpx 32rpx;
498 }
499
500 .change-label {
501 font-size: 28rpx;
502 }
503
504 .change-value {
505 font-size: 26rpx;
506 padding: 12rpx 20rpx;
507 }
508
509 .change-item {
510 margin-bottom: 20rpx;
511 }
512 } 344 }
513 </style> 345 </style>
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -137,9 +137,9 @@ const queryParams = reactive({ ...@@ -137,9 +137,9 @@ const queryParams = reactive({
137 pageNum: 1, 137 pageNum: 1,
138 pageSize: 10, 138 pageSize: 10,
139 type: '0', // 0表示个人会员 139 type: '0', // 0表示个人会员
140 queryType: '1', 140 // queryType: '1',
141 // payStatus: '', 141 // payStatus: '',
142 // perId: '' 142 perId: ''
143 }); 143 });
144 144
145 // 弹窗控制 145 // 弹窗控制
...@@ -157,12 +157,12 @@ const currentOrder = ref(null); ...@@ -157,12 +157,12 @@ const currentOrder = ref(null);
157 // 页面挂载初始化 157 // 页面挂载初始化
158 onMounted(() => { 158 onMounted(() => {
159 // 获取用户信息 159 // 获取用户信息
160 // if (userInfo.value && userInfo.value.perId) { 160 if (userInfo.value && userInfo.value.perId) {
161 // queryParams.perId = userInfo.value.perId; 161 queryParams.perId = userInfo.value.perId;
162 initData(); 162 initData();
163 // } else { 163 } else {
164 // uni.showToast({ title: '获取用户信息失败', icon: 'none' }); 164 uni.showToast({ title: '获取用户信息失败', icon: 'none' });
165 // } 165 }
166 }); 166 });
167 167
168 // 小程序原生触底加载 168 // 小程序原生触底加载
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!