| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727 |
- <template>
- <!-- 农技课堂:上区搜索 + 主 Tab + 子类 Chip;下区虚拟列表,每行两列卡片(视频课程 / 实战培训 底部样式不同) -->
- <view :class="pageRootClass" class="tab-page ac-page" :style="pageStyle">
- <view class="ac-top">
- <up-search
- v-model="searchKeyword"
- shape="round"
- :placeholder="$t('agriClassroomPage.searchPlaceholder')"
- :show-action="false"
- :clearabled="true"
- bg-color="#f5f2ef"
- border-color="#e5ded6"
- />
- <up-tabs
- :current="mainTabIndex"
- class="ac-tabs"
- :list="mainTabsList"
- key-name="name"
- :scrollable="false"
- line-color="#22C55E"
- :active-style="{ color: '#15803d', fontWeight: '600' }"
- :inactive-style="{ color: '#78716c' }"
- @update:current="onMainTabUpdate"
- />
- <!-- 第三行:子类 Chip,圆角线框;未选中灰,选中绿框绿字 -->
- <view class="ac-chips" role="tablist">
- <view
- v-for="code in subTypeCodes"
- :key="code"
- class="ac-chip"
- :class="{ 'ac-chip--on': chipSelected(code) }"
- role="button"
- @click="onPickSub(code)"
- >
- <text class="text-body ac-chip__txt">{{ subLabel(code) }}</text>
- </view>
- </view>
- </view>
- <view class="ac-body">
- <view v-if="listLoading && !pairedRows.length" class="ac-empty">
- <text class="text-body ac-empty__txt">{{ $t('agriClassroomPage.loading') }}</text>
- </view>
- <view v-else-if="!pairedRows.length" class="ac-empty">
- <text class="text-body ac-empty__txt">{{ $t('agriClassroomPage.empty') }}</text>
- </view>
- <view v-else class="ac-list-wrap">
- <up-virtual-list
- ref="acVList"
- class="ac-vlist"
- :list-data="pairedRows"
- :item-height="slotHeightPx"
- :height="listHeightPx"
- :buffer="4"
- key-field="id"
- :scroll-top="vScrollTop"
- @update:scrollTop="vScrollTop = $event"
- @scroll="onVirtualListScroll"
- >
- <template #default="{ item }">
- <view class="ac-pair-cell">
- <view class="ac-pair" :style="{ height: rowBodyPx + 'px' }">
- <view class="ac-pair__col">
- <view v-if="item.left" class="ac-card" role="button" @click="openCourseDetail(item.left)">
- <up-lazy-load
- class="ac-card__img"
- :image="articleCover(item.left)"
- height="120"
- :border-radius="12"
- img-mode="aspectFill"
- :threshold="200"
- :index="item.left.id"
- @click.stop="() => onPreviewCover(item.left)"
- />
- <text class="ac-card__title">{{ item.left.title }}</text>
- <view v-if="item.left.type === 'video'" class="ac-card__foot ac-card__foot--video">
- <text class="text-body ac-card__meta">{{ videoSubLabel(item.left.typeCode) }}</text>
- <text class="text-body ac-card__meta ac-card__meta--muted">{{ item.left.publishTime || $t('agriClassroomPage.noDate') }}</text>
- </view>
- <view v-else class="ac-card__foot ac-card__foot--train">
- <text class="text-body ac-card__meta">{{ trainingSubLabel(item.left.typeCode) }}</text>
- <up-icon name="account-fill" color="#22C55E" :size="16" />
- <text class="text-body ac-card__meta ac-card__meta--num">
- {{ item.left.enrolled }}/{{ item.left.total }}
- </text>
- </view>
- </view>
- </view>
- <view class="ac-pair__col">
- <view v-if="item.right" class="ac-card" role="button" @click="openCourseDetail(item.right)">
- <up-lazy-load
- class="ac-card__img"
- :image="articleCover(item.right)"
- height="120"
- :border-radius="12"
- img-mode="aspectFill"
- :threshold="200"
- :index="item.right.id"
- @click.stop="() => onPreviewCover(item.right)"
- />
- <text class="ac-card__title">{{ item.right.title }}</text>
- <view v-if="item.right.type === 'video'" class="ac-card__foot ac-card__foot--video">
- <text class="text-body ac-card__meta">{{ videoSubLabel(item.right.typeCode) }}</text>
- <text class="text-body ac-card__meta ac-card__meta--muted">{{ item.right.publishTime || $t('agriClassroomPage.noDate') }}</text>
- </view>
- <view v-else class="ac-card__foot ac-card__foot--train">
- <text class="text-body ac-card__meta">{{ trainingSubLabel(item.right.typeCode) }}</text>
- <up-icon name="account-fill" color="#22C55E" :size="16" />
- <text class="text-body ac-card__meta ac-card__meta--num">
- {{ item.right.enrolled }}/{{ item.right.total }}
- </text>
- </view>
- </view>
- </view>
- </view>
- </view>
- </template>
- </up-virtual-list>
- </view>
- </view>
- </view>
- </template>
- <script>
- import USearch from 'uview-plus/components/u-search/u-search.vue'
- import UTabs from 'uview-plus/components/u-tabs/u-tabs.vue'
- import UIcon from 'uview-plus/components/u-icon/u-icon.vue'
- import ULazyLoad from 'uview-plus/components/u-lazy-load/u-lazy-load.vue'
- import UVirtualList from 'uview-plus/components/u-virtual-list/u-virtual-list.vue'
- import tabPage from '@/mixins/tabPage'
- import { resolveResourceUrl } from '@/utils/resourceUrl'
- import { listAgriculturalCourse } from '@/api/agriculturalCourse'
- /** 视频课程 course_topic(005001–005004) */
- const VIDEO_TYPE_CODES = ['005001', '005002', '005003', '005004']
- /** 实战培训 training_status(006001–006004) */
- const TRAINING_TYPE_CODES = ['006001', '006002', '006003', '006004']
- const LIST_PAGE_SIZE = 20
- const ROW_BODY_RPX = 320
- const ROW_GAP_RPX = 20
- const AC_BODY_PAD_RPX = 40
- const COVER = '/static/ai/hero.png'
- /** 视频课程详情 */
- const COURSE_DETAIL_PATH = '/package-a/course-detail/index'
- /** 实战培训详情(英文路径) */
- const TRAINING_DETAIL_PATH = '/package-a/training-detail/index'
- export default {
- components: {
- 'up-search': USearch,
- 'up-tabs': UTabs,
- 'up-icon': UIcon,
- 'up-lazy-load': ULazyLoad,
- 'up-virtual-list': UVirtualList
- },
- mixins: [tabPage],
- data() {
- return {
- navTitleKey: 'agriClassroomPage.navTitle',
- searchKeyword: '',
- /** 0 视频课程 1 实战培训 */
- mainTabIndex: 0,
- selectedVideoType: '005001',
- selectedTrainingType: '006002',
- allCards: [],
- listLoading: false,
- listLoadingMore: false,
- listTotal: 0,
- pageNum: 1,
- pageSize: LIST_PAGE_SIZE,
- _searchTimer: null,
- loadMoreTimer: null,
- rowBodyPx: 140,
- marginPx: 10,
- slotHeightPx: 150,
- listHeightPx: 400,
- pageHeightPx: 0,
- vScrollTop: 0,
- coverSrc: COVER
- }
- },
- computed: {
- mainTabsList() {
- return [
- { name: this.$t('agriClassroomPage.mainVideo'), id: 'video' },
- { name: this.$t('agriClassroomPage.mainTraining'), id: 'training' }
- ]
- },
- isVideoMain() {
- return this.mainTabIndex === 0
- },
- subTypeCodes() {
- return this.isVideoMain ? VIDEO_TYPE_CODES : TRAINING_TYPE_CODES
- },
- selectedTypeCode() {
- return this.isVideoMain ? this.selectedVideoType : this.selectedTrainingType
- },
- listNoMore() {
- return this.listTotal > 0 && this.allCards.length >= this.listTotal
- },
- pageStyle() {
- if (this.pageHeightPx > 0) {
- return { height: `${this.pageHeightPx}px` }
- }
- return {}
- },
- /** 虚拟列表每行 2 个卡片 */
- pairedRows() {
- const cards = this.allCards
- const rows = []
- for (let i = 0; i < cards.length; i += 2) {
- const L = cards[i]
- const R = cards[i + 1] || null
- rows.push({
- id: `${L.id}_${R ? R.id : 'x'}`,
- left: L,
- right: R
- })
- }
- return rows
- }
- },
- watch: {
- searchKeyword() {
- this.vScrollTop = 0
- clearTimeout(this._searchTimer)
- this._searchTimer = setTimeout(() => {
- this.loadCourseList(true)
- }, 300)
- },
- selectedVideoType() {
- if (this.isVideoMain) {
- this.vScrollTop = 0
- this.loadCourseList(true)
- }
- },
- selectedTrainingType() {
- if (!this.isVideoMain) {
- this.vScrollTop = 0
- this.loadCourseList(true)
- }
- }
- },
- created() {
- this.loadCourseList(true)
- },
- onReady() {
- try {
- this.marginPx = Math.ceil(uni.upx2px(ROW_GAP_RPX))
- this.rowBodyPx = Math.max(120, Math.ceil(uni.upx2px(ROW_BODY_RPX)))
- this.slotHeightPx = this.rowBodyPx + this.marginPx
- } catch (e) {
- this.marginPx = 10
- this.rowBodyPx = 140
- this.slotHeightPx = 150
- }
- this.applyListHeightFallback()
- this.$nextTick(() => this.calcLayoutHeights())
- },
- onShow() {
- this.$nextTick(() => this.calcLayoutHeights())
- },
- onUnload() {
- if (this.loadMoreTimer) clearTimeout(this.loadMoreTimer)
- if (this._searchTimer) clearTimeout(this._searchTimer)
- },
- methods: {
- isTrainingType(typeCode) {
- return String(typeCode || '').startsWith('006')
- },
- mapCourseRow(row) {
- const typeCode = row.type || ''
- const isTraining = this.isTrainingType(typeCode)
- return {
- id: String(row.id != null ? row.id : ''),
- type: isTraining ? 'training' : 'video',
- typeCode,
- title: row.title || '',
- introduction: row.introduction || '',
- coverFileUrl: row.coverFileUrl || '',
- contentFileUrl: row.contentFileUrl || '',
- publishTime: row.publishTime || '',
- enrolled: row.actualEnrolledCount != null ? Number(row.actualEnrolledCount) : 0,
- total: row.plannedHeadCount != null ? Number(row.plannedHeadCount) : 0,
- registrationStartTime: row.registrationStartTime || '',
- registrationEndTime: row.registrationEndTime || '',
- trainingTime: row.trainingTime || '',
- expectedOutcome: row.expectedOutcome || ''
- }
- },
- loadCourseList(reset = false) {
- const type = this.selectedTypeCode
- if (!type) {
- this.allCards = []
- this.listTotal = 0
- return Promise.resolve()
- }
- if (!reset) {
- if (this.listLoading || this.listLoadingMore || this.listNoMore) {
- return Promise.resolve()
- }
- this.pageNum += 1
- this.listLoadingMore = true
- } else {
- this.pageNum = 1
- this.listLoading = true
- }
- const params = {
- type,
- pageNum: this.pageNum,
- pageSize: this.pageSize
- }
- const titleKw = (this.searchKeyword || '').trim()
- if (titleKw) {
- params.title = titleKw
- }
- return listAgriculturalCourse(params)
- .then((res) => {
- const rows = res.rows || []
- this.listTotal = res.total != null ? Number(res.total) : 0
- const mapped = rows.map((row) => this.mapCourseRow(row))
- this.allCards = reset ? mapped : this.allCards.concat(mapped)
- this.$nextTick(() => {
- this.calcLayoutHeights()
- if (this.allCards.length < this.listTotal) {
- this.tryAutoLoadMore()
- }
- })
- })
- .catch(() => {
- if (reset) {
- this.allCards = []
- this.listTotal = 0
- } else {
- this.pageNum -= 1
- }
- })
- .finally(() => {
- if (reset) {
- this.listLoading = false
- } else {
- this.listLoadingMore = false
- }
- })
- },
- tryAutoLoadMore() {
- if (this.listLoading || this.listLoadingMore || this.listNoMore) return
- const totalH = this.pairedRows.length * this.slotHeightPx
- const viewH = this.listHeightPx
- if (totalH > 0 && totalH <= viewH) {
- this.loadCourseList(false)
- }
- },
- onVirtualListScroll(scrollTop) {
- if (this.loadMoreTimer) clearTimeout(this.loadMoreTimer)
- this.loadMoreTimer = setTimeout(() => {
- this.loadMoreTimer = null
- this.tryLoadMoreOnScroll(typeof scrollTop === 'number' ? scrollTop : 0)
- }, 180)
- },
- tryLoadMoreOnScroll(scrollTop) {
- if (this.listLoading || this.listLoadingMore || this.listNoMore) return
- const totalH = this.pairedRows.length * this.slotHeightPx
- const viewH = this.listHeightPx
- const threshold = Math.max(this.slotHeightPx * 2, 120)
- if (totalH <= viewH) {
- this.loadCourseList(false)
- return
- }
- if (scrollTop + viewH >= totalH - threshold) {
- this.loadCourseList(false)
- }
- },
- getNavigationBarHeight() {
- const sys = uni.getSystemInfoSync()
- const statusBar = sys.statusBarHeight || 0
- // #ifdef MP-WEIXIN
- try {
- const menu = uni.getMenuButtonBoundingClientRect()
- if (menu && menu.height) {
- return statusBar + (menu.top - statusBar) * 2 + menu.height
- }
- } catch (e) {
- /* noop */
- }
- // #endif
- return statusBar + 44
- },
- getViewportContentHeight() {
- const sys = uni.getSystemInfoSync()
- const navH = this.getNavigationBarHeight()
- // #ifdef H5
- if (typeof window !== 'undefined' && window.innerHeight) {
- return Math.max(320, window.innerHeight - navH)
- }
- // #endif
- const screenH = sys.screenHeight || sys.windowHeight || 600
- return Math.max(320, screenH - navH)
- },
- applyListHeightFallback() {
- const contentH = this.getViewportContentHeight()
- const topFallback = Math.ceil(uni.upx2px(280))
- const bodyPad = Math.ceil(uni.upx2px(AC_BODY_PAD_RPX))
- this.pageHeightPx = contentH
- this.listHeightPx = Math.max(240, contentH - topFallback - bodyPad)
- },
- calcLayoutHeights() {
- const contentH = this.getViewportContentHeight()
- const bodyPad = Math.ceil(uni.upx2px(AC_BODY_PAD_RPX))
- this.pageHeightPx = contentH
- uni.createSelectorQuery()
- .in(this)
- .select('.ac-top')
- .boundingClientRect((topRect) => {
- const acTopH =
- topRect && topRect.height > 0 ? Math.ceil(topRect.height) : Math.ceil(uni.upx2px(280))
- this.listHeightPx = Math.max(240, contentH - acTopH - bodyPad)
- this.$nextTick(() => {
- this.$refs.acVList?.measureContainerHeight?.()
- })
- })
- .exec()
- },
- subLabel(typeCode) {
- return this.isVideoMain ? this.videoSubLabel(typeCode) : this.trainingSubLabel(typeCode)
- },
- chipSelected(typeCode) {
- return this.selectedTypeCode === typeCode
- },
- onPickSub(typeCode) {
- if (this.isVideoMain) {
- this.selectedVideoType = typeCode
- } else {
- this.selectedTrainingType = typeCode
- }
- },
- typeCodeIndex(typeCode, codes) {
- const idx = codes.indexOf(typeCode)
- return idx >= 0 ? idx : 0
- },
- videoSubLabel(typeCode) {
- const idx = this.typeCodeIndex(typeCode, VIDEO_TYPE_CODES)
- return this.$t(`agriClassroomPage.videoSubs.s${idx}`)
- },
- trainingSubLabel(typeCode) {
- const idx = this.typeCodeIndex(typeCode, TRAINING_TYPE_CODES)
- return this.$t(`agriClassroomPage.trainingSubs.s${idx}`)
- },
- articleCover(card) {
- if (card.coverFileUrl) {
- return resolveResourceUrl(card.coverFileUrl)
- }
- return this.coverSrc
- },
- onPreviewCover(card) {
- const url = this.articleCover(card)
- if (!url) return
- uni.previewImage({ urls: [url], current: 0 })
- },
- openCourseDetail(card) {
- if (!card) return
- if (card.type === 'training') {
- const q = [
- `id=${encodeURIComponent(card.id)}`,
- `date=${encodeURIComponent(card.publishTime || '')}`,
- `title=${encodeURIComponent(card.title || '')}`,
- `type=${encodeURIComponent(card.typeCode || '')}`,
- `enrolled=${encodeURIComponent(card.enrolled)}`,
- `total=${encodeURIComponent(card.total)}`,
- `introduction=${encodeURIComponent(card.introduction || '')}`,
- `trainingTime=${encodeURIComponent(card.trainingTime || '')}`,
- `expectedOutcome=${encodeURIComponent(card.expectedOutcome || '')}`,
- `cover=${encodeURIComponent(card.coverFileUrl || '')}`,
- `regStart=${encodeURIComponent(card.registrationStartTime || '')}`,
- `regEnd=${encodeURIComponent(card.registrationEndTime || '')}`
- ].join('&')
- uni.navigateTo({ url: `${TRAINING_DETAIL_PATH}?${q}` })
- return
- }
- const q = [
- `id=${encodeURIComponent(card.id)}`,
- `date=${encodeURIComponent(card.publishTime || '')}`,
- `title=${encodeURIComponent(card.title || '')}`,
- `type=${encodeURIComponent(card.typeCode || '')}`,
- `introduction=${encodeURIComponent(card.introduction || '')}`,
- `src=${encodeURIComponent(card.contentFileUrl || '')}`,
- `cover=${encodeURIComponent(card.coverFileUrl || '')}`,
- 'mode=video'
- ].join('&')
- uni.navigateTo({ url: `${COURSE_DETAIL_PATH}?${q}` })
- },
- /** 主 Tab 切换:恢复各 Tab 默认子类并重新拉列表 */
- onMainTabUpdate(idx) {
- const i = typeof idx === 'number' ? idx : 0
- if (this.mainTabIndex === i) return
- this.mainTabIndex = i
- this.vScrollTop = 0
- if (i === 0) {
- this.selectedVideoType = '005001'
- } else {
- this.selectedTrainingType = '006002'
- }
- this.loadCourseList(true)
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- @import '@/styles/morandi.scss';
- @import '@/styles/tab-page.scss';
- .ac-page {
- display: flex;
- flex-direction: column;
- min-width: 0;
- width: 100%;
- height: 100%;
- min-height: 100%;
- overflow: hidden;
- box-sizing: border-box;
- background: $morandi-bg-page;
- }
- .ac-top {
- flex-shrink: 0;
- display: flex;
- flex-direction: column;
- gap: 16rpx;
- min-width: 0;
- padding: 20rpx 24rpx 16rpx;
- box-sizing: border-box;
- background: $morandi-bg-page;
- border-bottom: 1rpx solid $morandi-border-soft;
- }
- .ac-tabs {
- width: 100%;
- min-width: 0;
- }
- .ac-chips {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- min-width: 0;
- justify-content: space-between;
- }
- .ac-chip {
- padding: 2rpx 30rpx;
- box-sizing: border-box;
- border-radius: 999rpx;
- border: 1rpx solid $morandi-border-strong;
- background: $morandi-bg-card-inner;
- }
- .ac-chip--on {
- border-color: #22c55e;
- background: rgba(34, 197, 94, 0.08);
- }
- .ac-chip__txt {
- font-size: 24rpx;
- color: $morandi-text-secondary;
- text-align: center;
- word-break: break-word;
- overflow-wrap: anywhere;
- }
- .ac-chip--on .ac-chip__txt {
- color: #15803d;
- font-weight: 600;
- }
- .ac-body {
- flex: 1;
- min-height: 0;
- height: 0;
- min-width: 0;
- display: flex;
- flex-direction: column;
- padding: 16rpx 24rpx 24rpx;
- box-sizing: border-box;
- overflow: hidden;
- }
- .ac-list-wrap {
- flex: 1;
- min-height: 0;
- display: flex;
- flex-direction: column;
- min-width: 0;
- }
- .ac-vlist {
- flex: 1;
- min-height: 0;
- width: 100%;
- height: 100%;
- }
- .ac-empty {
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- min-height: 0;
- padding: 48rpx 24rpx;
- box-sizing: border-box;
- }
- .ac-empty__txt {
- color: $morandi-text-muted;
- text-align: center;
- }
- .ac-pair-cell {
- height: 100%;
- box-sizing: border-box;
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- }
- /* 一行两列,列间距 20rpx(文档) */
- .ac-pair {
- display: flex;
- flex-direction: row;
- align-items: stretch;
- gap: 20rpx;
- min-width: 0;
- box-sizing: border-box;
- }
- .ac-pair__col {
- flex: 1;
- min-width: 0;
- display: flex;
- flex-direction: column;
- }
- .ac-card {
- flex: 1;
- min-height: 0;
- min-width: 0;
- display: flex;
- flex-direction: column;
- gap: 12rpx;
- padding: 12rpx;
- box-sizing: border-box;
- border-radius: 16rpx;
- background: $morandi-bg-card;
- border: 1rpx solid $morandi-border;
- }
- .ac-card__img {
- width: 100%;
- display: block;
- }
- .ac-card__title {
- font-size: 30rpx;
- font-weight: 600;
- line-height: 1.4;
- color: #111827;
- word-break: break-word;
- overflow-wrap: anywhere;
- }
- .ac-card__foot {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- align-items: center;
- gap: 8rpx 12rpx;
- min-width: 0;
- }
- .ac-card__foot--video {
- justify-content: flex-start;
- }
- .ac-card__foot--train {
- justify-content: flex-start;
- }
- .ac-card__meta {
- font-size: 22rpx;
- line-height: 1.45;
- color: $morandi-accent-soft;
- }
- .ac-card__meta--muted {
- color: $morandi-text-soft;
- }
- .ac-card__meta--num {
- color: $morandi-text-secondary;
- }
- .ac-page.lang-bo {
- .ac-chip__txt {
- font-size: 22rpx;
- line-height: 1.75;
- letter-spacing: 2rpx;
- font-family: 'Noto Sans Tibetan', 'PingFang SC', 'Microsoft YaHei', sans-serif;
- }
- .ac-card__title {
- font-size: 28rpx;
- line-height: 1.75;
- letter-spacing: 2rpx;
- font-family: 'Noto Sans Tibetan', 'PingFang SC', 'Microsoft YaHei', sans-serif;
- }
- .ac-card__meta {
- font-size: 20rpx;
- line-height: 1.75;
- letter-spacing: 2rpx;
- font-family: 'Noto Sans Tibetan', 'PingFang SC', 'Microsoft YaHei', sans-serif;
- }
- }
- </style>
|