Merge remote-tracking branch 'origin/feature_教代会代表证' into release_20260831

This commit is contained in:
2026-08-31 09:07:09 +08:00
8 changed files with 125 additions and 100 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 KiB

@@ -0,0 +1,8 @@
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="24" cy="24" r="22" fill="#EAF3FF"/>
<rect x="15" y="11" width="18" height="17" rx="4" fill="#2F7CF6"/>
<path d="M12 24C10.8954 24 10 24.8954 10 26V32C10 33.1046 10.8954 34 12 34H36C37.1046 34 38 33.1046 38 32V26C38 24.8954 37.1046 24 36 24C34.8954 24 34 24.8954 34 26V29H14V26C14 24.8954 13.1046 24 12 24Z" fill="#1769E8"/>
<rect x="14" y="28" width="20" height="7" rx="2.5" fill="#2F7CF6"/>
<path d="M16 34H20L19 38H15L16 34Z" fill="#1769E8"/>
<path d="M28 34H32L33 38H29L28 34Z" fill="#1769E8"/>
</svg>

After

Width:  |  Height:  |  Size: 637 B

@@ -1005,7 +1005,7 @@ layout("/layouts/platform_h5.html"){
width: 100%;
height: 100%;
object-fit: contain;
transform: scale(1.45);
transform: scale(1.6);
transform-origin: center;
}
@@ -1126,32 +1126,79 @@ layout("/layouts/platform_h5.html"){
}
.mobile-bottom-panel {
padding: 11px 14px calc(11px + env(safe-area-inset-bottom));
border-top: 1px solid #edf0f5;
padding: 0 0 env(safe-area-inset-bottom);
border-top: 0;
background: #fff;
box-shadow: 0 -5px 18px rgba(36, 55, 80, .08);
box-shadow: none;
}
.mobile-bottom-panel.is-empty {
padding-top: 12px;
padding-top: 0;
}
.mobile-bottom-selected {
display: grid;
grid-template-columns: 105px minmax(0, 1fr);
gap: 12px;
grid-template-columns: 42px max-content 1px minmax(0, 1fr);
gap: 9px;
align-items: center;
padding: 15px 9px;
background: #fff;
border: 1px solid #e8eef7;
border-radius: 0;
box-shadow: 0 5px 15px rgba(49, 93, 157, .12);
}
.mobile-bottom-summary {
display: block;
min-height: auto;
display: flex;
height: 50px;
margin: 0;
padding: 5px 8px;
align-items: center;
box-sizing: border-box;
color: #202b3c;
font-size: 15px;
background: #fff;
border: 1px solid #e8eef7;
border-radius: 23px;
box-shadow: 0 4px 12px rgba(51, 103, 178, .1);
white-space: nowrap;
}
.mobile-seat-status-icon {
width: 42px;
height: 42px;
object-fit: contain;
}
.mobile-seat-status-copy {
display: flex;
min-width: 0;
flex-direction: column;
align-items: flex-start;
justify-content: center;
text-align: left;
}
.mobile-seat-status-value {
color: #1677ff;
font-size: 15px;
font-weight: 600;
line-height: 20px;
}
.mobile-seat-status-tag {
margin-bottom: 1px;
color: #7d899a;
font-size: 10px;
line-height: 14px;
}
.mobile-seat-status-divider {
width: 1px;
height: 28px;
background: #dfe5ed;
}
.mobile-bottom-summary strong {
margin: 0 4px;
color: #1677ff;
@@ -1160,12 +1207,13 @@ layout("/layouts/platform_h5.html"){
}
.mobile-confirm-button {
height: 46px;
height: 38px;
border: 0;
border-radius: 8px;
background: #1677ff;
font-size: 16px;
font-weight: 500;
border-radius: 9px;
background: linear-gradient(90deg, #458df8 0%, #0869f5 100%);
box-shadow: none;
font-size: 14px;
font-weight: 600;
}
.mobile-confirm-button.van-button--disabled {
@@ -1174,12 +1222,13 @@ layout("/layouts/platform_h5.html"){
opacity: 1;
}
.seat-confirm-sheet {
border-radius: 18px 18px 0 0;
.seat-confirm-dialog {
width: calc(100% - 48px);
border-radius: 12px;
}
.seat-confirm-content {
padding: 21px 18px calc(18px + env(safe-area-inset-bottom));
.seat-confirm-dialog .seat-confirm-content {
padding: 21px 18px 18px;
}
.seat-confirm-header {
@@ -1216,17 +1265,28 @@ layout("/layouts/platform_h5.html"){
.seat-confirm-submit {
height: 46px;
margin-top: 18px;
border: 0;
border-radius: 8px;
background: #ff3344;
background: #69aefc;
font-size: 16px;
font-weight: 600;
}
@media (max-width: 375px) {
.mobile-bottom-selected {
grid-template-columns: 95px minmax(0, 1fr);
gap: 9px;
grid-template-columns: 38px max-content 1px minmax(0, 1fr);
gap: 8px;
}
.mobile-bottom-summary {
padding: 5px 6px;
font-size: 14px;
}
.mobile-seat-status-icon {
width: 38px;
height: 38px;
}
.mobile-seat {
@@ -1248,7 +1308,8 @@ layout("/layouts/platform_h5.html"){
<!-- 头部信息 -->
<div class="mobile-header" v-if="meeting">
<div class="meeting-title">{{ meeting.name }}</div>
<div class="meeting-time"><van-icon name="clock-o"></van-icon>{{ formatMeetingRange(meeting) }}</div>
<div class="meeting-time"><van-icon name="clock-o"></van-icon>开始时间:{{ formatMeetingTime(meeting.startTime) }}</div>
<div class="meeting-time"><van-icon name="calendar-o"></van-icon>结束时间:{{ formatMeetingTime(meeting.endTime) }}</div>
<div class="meeting-address"><van-icon name="location-o"></van-icon>{{ meeting.address || '会议地点待定' }}</div>
<div class="mobile-header-visual">
<img src="/assets/mobile/img/democratic/teachercongress/meeting-dais.png" alt="会议主席台">
@@ -1337,68 +1398,23 @@ layout("/layouts/platform_h5.html"){
<!-- 图例 -->
<div class="mobile-legend">
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f8f9fa" stroke="#dee2e6"
stroke-width="1"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ffffff" stroke="#dee2e6"
stroke-width="1"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
stroke-width="1"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#e9ecef" stroke="#dee2e6"
stroke-width="1"/>
</svg>
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-available.png" alt="">
<span>可选</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#adb5bd" stroke="#6c757d"
stroke-width="1"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#d0d0d0" stroke="#6c757d"
stroke-width="1"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
stroke-width="1"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#adb5bd" stroke="#6c757d"
stroke-width="1"/>
</svg>
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-occupied.png" alt="">
<span>占用</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#0d47a1" stroke="#1867b0"
stroke-width="2"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#1867b0" stroke="#0d47a1"
stroke-width="2"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
stroke-width="2"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#0d47a1" stroke="#1867b0"
stroke-width="2"/>
</svg>
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-selected.png" alt="">
<span>选中</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#c62828" stroke="#ff3742"
stroke-width="2"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#ff4757" stroke="#c62828"
stroke-width="2"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
stroke-width="2"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#c62828" stroke="#ff3742"
stroke-width="2"/>
</svg>
<span>我的</span>
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-mine.png" alt="">
<span>已选</span>
</div>
<div class="mobile-legend-item">
<svg class="mobile-legend-seat" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" fill="#f5f5f5" stroke="#cccccc"
stroke-width="1"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" fill="#f0f0f0" stroke="#cccccc"
stroke-width="1"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
stroke-width="1"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" fill="#f5f5f5" stroke="#cccccc"
stroke-width="1"/>
</svg>
<img class="mobile-legend-seat" src="/assets/mobile/img/democratic/teachercongress/seat-disabled.png" alt="">
<span>禁用</span>
</div>
</div>
@@ -1426,13 +1442,7 @@ layout("/layouts/platform_h5.html"){
class="mobile-seat"
:class="[seat ? getSeatClass(seat) : 'seat-placeholder', {'has-aisle': seatIndex + 1 === aisleStartColumn}]"
@click="seat && selectSeat(seat)">
<svg class="mobile-seat-icon" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="5" width="34" height="20" rx="3" ry="3" class="seat-back"/>
<rect x="5" y="22" width="40" height="18" rx="4" ry="4" class="seat-cushion"/>
<rect x="2" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
<rect x="42" y="20" width="6" height="15" rx="2" ry="2" class="seat-armrest"/>
</svg>
<van-icon v-if="seat === selectedSeat" class="mobile-seat-check" name="success"></van-icon>
<img v-if="seat" class="mobile-seat-icon" :src="getSeatIcon(seat)" alt="">
</div>
</div>
</div>
@@ -1444,32 +1454,33 @@ layout("/layouts/platform_h5.html"){
<!-- 底部操作面板 -->
<div class="mobile-bottom-panel" :class="{'is-empty': !selectedSeat}">
<div class="mobile-bottom-selected">
<div class="mobile-bottom-summary">
<template v-if="myCurrentSeat">{{ myCurrentSeat.rowNumber }}排{{ myCurrentSeat.colNumber }}列(已选)</template>
<template v-else>未选择</template>
</div>
<img class="mobile-seat-status-icon"
src="/assets/mobile/img/democratic/teachercongress/seat-status-icon.svg" alt="座位">
<span class="mobile-seat-status-copy">
<span class="mobile-seat-status-tag">{{ myCurrentSeat ? '已选座位' : '座位状态' }}</span>
<span class="mobile-seat-status-value">
<template v-if="myCurrentSeat">{{ myCurrentSeat.rowNumber }}排{{ myCurrentSeat.colNumber }}列</template>
<template v-else>未选择</template>
</span>
</span>
<span class="mobile-seat-status-divider"></span>
<van-button class="mobile-confirm-button" type="info" block :disabled="!selectedSeat"
@click="openSeatConfirm">
<template v-if="selectedSeat">确认换座 {{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}列</template>
<template v-if="selectedSeat">{{ myCurrentSeat ? '确认换座' : '确认选座' }} {{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}列</template>
<template v-else>{{ myCurrentSeat ? '点击座位更新' : '请先选择座位' }}</template>
</van-button>
</div>
</div>
<van-action-sheet v-model="showSeatConfirm" class="seat-confirm-sheet" safe-area-inset-bottom>
<van-dialog v-model="showSeatConfirm" class="seat-confirm-dialog"
show-cancel-button confirm-button-text="确认" cancel-button-text="取消"
@confirm="confirmSelection">
<div class="seat-confirm-content">
<div class="seat-confirm-header">
<span>已选座位</span>
<button type="button" class="seat-confirm-clear" @click="clearSelectedSeat">清空</button>
<span v-if="selectedSeat">确认{{ myCurrentSeat ? '换座' : '选座' }} {{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}列吗?</span>
</div>
<div class="seat-confirm-value" v-if="selectedSeat">
{{ selectedSeat.rowNumber }}排{{ selectedSeat.colNumber }}座
</div>
<div class="seat-confirm-tip">请确认座位信息</div>
<van-button class="seat-confirm-submit" type="danger" block :loading="submitting"
@click="confirmSelection">确认选座</van-button>
</div>
</van-action-sheet>
</van-dialog>
</div>
<script nonce="${cspNonce!}">
@@ -1557,11 +1568,8 @@ layout("/layouts/platform_h5.html"){
}
})
},
formatMeetingRange(item) {
if (!item) return ''
const start = item.startTime ? this.$moment(item.startTime).format('YYYY-MM-DD HH:mm') : '--'
const end = item.endTime ? this.$moment(item.endTime).format('YYYY-MM-DD HH:mm') : '--'
return start + ' 至 ' + end
formatMeetingTime(time) {
return time ? this.$moment(time).format('YYYY-MM-DD HH:mm') : '--'
},
// 查询选座情况
async loadSeats(loading = createListLoading()) {
@@ -1670,6 +1678,15 @@ layout("/layouts/platform_h5.html"){
return 'available';
},
getSeatIcon(seat) {
const iconPath = '/assets/mobile/img/democratic/teachercongress/'
if (!seat.enable) return iconPath + 'seat-disabled.png'
if (seat.isMine) return iconPath + 'seat-mine.png'
if (seat === this.selectedSeat) return iconPath + 'seat-selected.png'
if (seat.isOccupied) return iconPath + 'seat-occupied.png'
return iconPath + 'seat-available.png'
},
getSeatTitle(seat) {
if (seat.isMine) return '我的座位';
if (seat === this.selectedSeat) return '当前选择';