123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- <template>
- <view :class="['uni-container', { 'flex-row': isWideScreen }, isDarkMode ? 'theme-dark' : 'theme-light']" style="flex: 1;">
- <!-- 列表区域 :宽屏时在左侧显示,窄屏时只显示列表 -->
- <list-view class="list-container" :class="{'list-narrow': isWideScreen}" refresher-enabled=true
- @refresherrefresh="onRefresherrefresh" :refresher-triggered="refresherTriggered" enable-back-to-top="true">
- <list-item class="banner" @click="bannerClick(banner)" type=1>
- <image class="banner-img" :src="banner.cover"></image>
- <text class="banner-title">{{ banner.title }}</text>
- </list-item>
- <sticky-section>
- <sticky-header>
- <view class="th-item">
- <text v-for="(name,index) in th_item" :key="index" @click="clickTH(index)" class="th-item-text">
- {{name}}
- </text>
- </view>
- </sticky-header>
- <list-item v-for="(value, index) in listData" :key="index" type=2>
- <view class="uni-list-cell" hover-class="uni-list-cell-hover" @click="goDetail(value, index)">
- <view class="uni-media-list">
- <image v-if="isWideScreen" class="uni-media-list-logo" :src="value.cover"></image>
- <share-element v-else :share-key="'image_'+index">
- <image class="uni-media-list-logo" :src="value.cover"></image>
- </share-element>
- <view class="uni-media-list-body">
- <text class="uni-media-list-text-top">{{ value.title }}</text>
- <view class="uni-media-list-text-bottom">
- <text class="uni-media-list-text">{{ value.author_name }}</text>
- <text class="uni-media-list-text">{{ value.published_at }}</text>
- </view>
- </view>
- </view>
- </view>
- </list-item>
- </sticky-section>
- </list-view>
- <!-- 详情区域:宽屏时,右侧显示-->
- <view v-if="isWideScreen" class="detail-container">
- <detail
- v-if="post_id != '' && title != '' && cover != ''"
- :key="post_id"
- :post_id="post_id"
- :cover="cover"
- :title="title"
- :isWideScreen="isWideScreen"
- :firstDetailContent="currentDetailContent"
- />
- </view>
- </view>
- </template>
- <script>
- import { state } from '@/store/index.uts'
- type Banner = {
- cover : string | null,
- title : string | null,
- post_id : string | null
- }
- type Item = {
- author_name : string,
- cover : string,
- id : number,
- post_id : string,
- published_at : string,
- title : string
- }
- // 导入详情组件,宽屏时,右侧直接展示详情内容
- import detail from './detail/detail.uvue'
- export default {
- components: {
- detail
- },
- data() {
- return {
- th_item: ["排序", "筛选"],
- refresherTriggered: false,
- banner: {} as Banner,
- listData: [] as Item[],
- last_id: '',
- isWideScreen: false,// 是否为宽屏模式
- currentIndex: 0, // 当前选中的列表项索引
- post_id: '',
- cover: '',
- title: '',
- firstDetailContent: '', // 并行预加载的第一个详情内容
- };
- },
- onLoad() {
- // 判断是否为宽屏
- this.checkScreenWidth()
- this.getBanner();
- this.getList();
- },
- onUnload() {
- },
- onResize() {
- // 监听屏幕尺寸变化,动态切换宽屏/窄屏
- this.checkScreenWidth()
- },
- methods: {
- checkScreenWidth() {
- const deviceType = uni.getDeviceInfo().deviceType
- const { windowWidth } = uni.getWindowInfo()
- // 只要是pad/pc,或者宽度大于700,都算宽屏
- this.isWideScreen = (
- deviceType === 'pad' ||
- deviceType === 'pc' ||
- windowWidth > 700
- )
- },
- getBanner() {
- let data = {
- column: 'id,post_id,title,author_name,cover,published_at' //需要的字段名
- };
- uni.request<Banner>({
- url: 'https://unidemo.dcloud.net.cn/api/banner/36kr',
- data: data,
- success: data => {
- this.refresherTriggered = false
- if (data.statusCode == 200) {
- const result = data.data
- if (result != null) {
- this.banner = result;
- }
- }
- },
- fail: (e) => {
- console.log('fail', e);
- }
- });
- },
- getList() {
- let url = "https://unidemo.dcloud.net.cn/api/news?column=id,post_id,title,author_name,cover,published_at";
- /* if (this.last_id != "") {
- const minId = parseInt((this.last_id))
- const time = new Date().getTime() + '';
- const pageSize = 10;
- url = url + "&minId=" + minId + "&time=" + time + "&pageSize=" + pageSize;
- } */
- uni.request<Item[]>({
- url: url,
- method: "GET",
- success: (res) => {
- if (res.statusCode == 200) {
- const result = res.data
- //因本接口没有更多分页数据,所以重新赋值。正常有分页的列表应该如下面push方式增加数组项
- // this.listData.push(...result)
- // this.last_id = this.listData[0].id + "";
- if (result != null) {
- this.listData = result
- // 宽屏模式下,自动选中并展示第一个新闻详情
- if (this.isWideScreen && this.listData.length > 0) {
- this.goDetail(this.listData[0], 0)
- // 并行预加载第一个详情内容,提升右侧展示速度
- const first = this.listData[0]
- uni.request({
- url: 'https://unidemo.dcloud.net.cn/api/news/36kr/' + first.post_id,
- success: (res) => {
- if (res.statusCode == 200) {
- const result = res.data as UTSJSONObject;
- this.firstDetailContent = result["content"] as string
- }
- }
- })
- }
- }
- this.refresherTriggered = false;
- }
- },
- fail: (res) => {
- console.log('fail', res);
- this.refresherTriggered = false
- }
- });
- },
- goDetail(e : Item, key : number) {
- this.currentIndex = key
- const detail = e;
- this.post_id = detail.post_id;
- this.cover = detail.cover;
- this.title = detail.title;
- // 窄屏时跳转到详情页,宽屏时右侧直接展示
- if (!this.isWideScreen) {
- // #ifdef APP-ANDROID
- this.cover = btoa(this.cover);
- // #endif
- uni.navigateTo({
- url: '/pages/template/list-news/detail/detail?post_id=' + this.post_id + "&cover=" + this.cover + "&title=" + this.title + "&shareKey=image_" + key
- });
- }
- },
- bannerClick(e : Banner) {
- const detail = e;
- const post_id = detail.post_id;
- let cover = detail.cover ?? "";
- // #ifdef APP-ANDROID
- cover = btoa(cover);
- // #endif
- const title = detail.title;
- uni.navigateTo({
- url: '/pages/template/list-news/detail/detail?post_id=' + post_id + "&cover=" + cover + "&title=" + title
- });
- },
- clickTH(index : number) {
- uni.showModal({
- content: "点击表头项:" + index,
- showCancel: false
- });
- },
- onRefresherrefresh() {
- this.refresherTriggered = true
- this.getBanner();
- this.getList();
- }
- },
- computed: {
- currentDetailContent() {
- // 只在宽屏且是第一个文章时用预加载内容
- if (
- this.isWideScreen &&
- this.listData.length > 0 &&
- this.post_id === this.listData[0].post_id &&
- this.firstDetailContent !== ''
- ) {
- return this.firstDetailContent
- }
- return ''
- },
- isDarkMode():boolean {
- return state.isDarkMode
- }
- }
- };
- </script>
- <style>
- .flex-row {
- flex-direction: row;
- }
- .list-container {
- width: 100%;
- background-color: var(--list-background-color,#ffffff);
- /* #ifdef APP */
- flex: 1;
- /* #endif */
- }
- .list-narrow {
- /* #ifdef WEB */
- width: 360px;
- /* #endif */
- /* #ifndef WEB */
- width: 100px;
- /* #endif */
- }
- .th-item{
- width: 100%;
- height:44px;
- background-color: var(--list-background-color,#ffffff);
- flex-direction: row;
- justify-content:center;
- align-items:center;
- }
- .th-item-text{
- margin-right: 20px;
- color: var(--text-color,#333333);
- }
- .detail-container {
- flex: 1;
- min-width: 0;
- /* 防止溢出 */
- padding: 20px;
- background-color: var(--background-color,#f8f8f8);
- /* #ifdef WEB */
- overflow: auto;
- /* #endif */
- }
- .banner {
- height: 180px;
- overflow: hidden;
- position: relative;
- background-color: var(--background-color,#f8f8f8);
- }
- .banner-img {
- width: 100%;
- }
- .banner-title {
- max-height: 42px;
- overflow: hidden;
- position: absolute;
- left: 15px;
- bottom: 15px;
- width: 90%;
- font-size: 16px;
- font-weight: 400;
- line-height: 21px;
- color: white;
- }
- .uni-media-list {
- padding: 11px 15px;
- box-sizing: border-box;
- display: flex;
- width: 100%;
- flex-direction: row;
- }
- .uni-media-list-logo {
- width: 90px;
- height: 70px;
- }
- .uni-media-list-body {
- flex: 1;
- padding-left: 7px;
- justify-content: space-around;
- }
- .uni-media-list-text-top {
- /* height: 37px; */
- font-size: 14px;
- lines: 2;
- overflow: hidden;
- color: var(--text-color,#333333);
- }
- .uni-media-list-text-bottom {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- }
- .uni-media-list-text {
- color: #9D9D9F;
- font-size: 13px;
- }
- </style>
|