Ver código fonte

使用 v-card 实现了 status 页面

reghao 4 anos atrás
pai
commit
68305770e3

+ 19 - 0
package-lock.json

@@ -10838,6 +10838,11 @@
         "neo-async": "^2.6.0"
       }
     },
+    "throttle-debounce": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-2.3.0.tgz",
+      "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ=="
+    },
     "through": {
       "version": "2.3.8",
       "resolved": "https://registry.npm.taobao.org/through/download/through-2.3.8.tgz",
@@ -11348,6 +11353,15 @@
       "integrity": "sha1-sj5DWK+oogL+ehAK8fX4g/AgB+4=",
       "dev": true
     },
+    "v-viewer": {
+      "version": "1.6.4",
+      "resolved": "https://registry.npmmirror.com/v-viewer/-/v-viewer-1.6.4.tgz",
+      "integrity": "sha512-LVkiUHpmsbsZXebeNXnu8krRCi5i2n07FeLFxoIVGhw8lVvTBO0ffpbDC6mLEuacCjrIh09HjIqpciwUtWE8lQ==",
+      "requires": {
+        "throttle-debounce": "^2.0.1",
+        "viewerjs": "^1.5.0"
+      }
+    },
     "v8-compile-cache": {
       "version": "2.1.1",
       "resolved": "https://registry.npm.taobao.org/v8-compile-cache/download/v8-compile-cache-2.1.1.tgz?cache=0&sync_timestamp=1590871780233&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8-compile-cache%2Fdownload%2Fv8-compile-cache-2.1.1.tgz",
@@ -11387,6 +11401,11 @@
         "extsprintf": "^1.2.0"
       }
     },
+    "viewerjs": {
+      "version": "1.10.4",
+      "resolved": "https://registry.npmmirror.com/viewerjs/-/viewerjs-1.10.4.tgz",
+      "integrity": "sha512-CjMt64yC9D+XUx2t3F0TPbh/Yt5+/ke8/s3IizXa6NtksdJUFDoCcNxi/KRZ9eiZPR/D77pHnnQzAtCoLDaGIw=="
+    },
     "vm-browserify": {
       "version": "1.1.2",
       "resolved": "https://registry.npm.taobao.org/vm-browserify/download/vm-browserify-1.1.2.tgz?cache=0&sync_timestamp=1572870717730&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvm-browserify%2Fdownload%2Fvm-browserify-1.1.2.tgz",

+ 1 - 0
package.json

@@ -22,6 +22,7 @@
     "hls.js": "^1.1.2",
     "js-cookie": "2.2.0",
     "shaka-player": "^3.2.1",
+    "v-viewer": "^1.6.4",
     "vue": "^2.6.12",
     "vue-cookies": "^1.7.4",
     "vue-filepond": "^6.0.3",

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
src/assets/debug-data/data/status.js


+ 73 - 188
src/components/status/status-card.vue

@@ -1,68 +1,75 @@
 <template>
-  <div class="content" @click="goDetailContent">
-    <div class="list-header">
-      <img v-if="x.user" class="avatar" :src="x.user.avatar_large">
-      <div class="user-info">
-        <h3 v-if="x.user" class="user-name">{{ x.user.name }}</h3>
-        <span class="user-source" v-html="x.source" />
-      </div>
-      <span class="user-time">{{ formatTime(x.created_at) }}</span>
-    </div>
-    <div class="list-content">
-      <span class="content-text" v-html="formatContent(x.text)" />
-      <div class="content-img">
-        <ul class="content-img-ul clear-fix">
-          <li v-for="y in x.pic_urls" :key="y" class="img-li-default" :class="imgClass(x.pic_urls.length)">
-            <div class="img-div" :style="{backgroundImage:'url(' + formatThumbImg(y.thumbnail_pic) + ')'}" @click.stop="imageZoom(y.thumbnail_pic)" />
-          </li>
-        </ul>
-      </div>
-      <div v-if="x.retweeted_status" class="content-re-content">
-        <span
-          class="re-content-text"
-          v-html="formatContent( '@' + x.retweeted_status.user.name + ': '
-            + x.retweeted_status.text)"
-        />
-        <div v-if="x.retweeted_status.pic_urls" class="content-img">
-          <ul class="content-img-ul clear-fix">
-            <li v-for="z in x.retweeted_status.pic_urls" :key="z" class="img-li-default" :class="imgClass(x.retweeted_status.pic_urls.length)">
-              <div
-                class="img-div"
-                :style="{backgroundImage:'url(' + formatThumbImg(z.thumbnail_pic) + ')'}"
-                @click.stop="imageZoom(z.thumbnail_pic)"
-              />
-            </li>
-          </ul>
-        </div>
-      </div>
-    </div>
-    <div class="list-footer">
-      <div class="footer-tag">
-        <svg viewBox="0 0 62 72" style="display: inline-block; fill: currentcolor; height: 1.25rem; max-width: 100%; position: relative; user-select: none; vertical-align: text-bottom;"><g><path d="M41 31h-9V19a2.999 2.999 0 0 0-4.817-2.386l-21 16a3 3 0 0 0-.001 4.773l21 16a3.006 3.006 0 0 0 3.15.301A2.997 2.997 0 0 0 32 51V39h9c5.514 0 10 4.486 10 10a4 4 0 0 0 8 0c0-9.925-8.075-18-18-18z" /></g></svg>
-        <span class="tag-style">{{ formatNum(x.reposts_count) }}</span>
-      </div>
-      <div class="footer-tag">
-        <svg class="" viewBox="0 0 74 72" style="display: inline-block; fill: currentcolor; height: 1.25rem; max-width: 100%; position: relative; user-select: none; vertical-align: text-bottom;"><g><path d="M70.676 36.644A3 3 0 0 0 68 35h-7V19a4 4 0 0 0-4-4H34a4 4 0 0 0 0 8h18a1 1 0 0 1 1 .998V35h-7a3.001 3.001 0 0 0-2.419 4.775l11 15a3.003 3.003 0 0 0 4.839-.001l11-15a3.001 3.001 0 0 0 .256-3.13zM40.001 48H22a.995.995 0 0 1-.992-.96L21.001 36h7a3.001 3.001 0 0 0 2.419-4.775l-11-15a3.003 3.003 0 0 0-4.839.001l-11 15A3 3 0 0 0 6.001 36h7l.011 16.003a4 4 0 0 0 4 3.997h22.989a4 4 0 0 0 0-8z" /></g></svg>
-        <span class="tag-style">{{ formatNum(x.comments_count) }}</span>
-      </div>
-      <div class="footer-tag">
-        <svg class="" viewBox="0 0 54 72" style="display: inline-block; fill: currentcolor; height: 1.25rem; max-width: 100%; position: relative; user-select: none; vertical-align: text-bottom;"><g><path d="M38.723 12c-7.187 0-11.16 7.306-11.723 8.131C26.437 19.306 22.504 12 15.277 12 8.791 12 3.533 18.163 3.533 24.647 3.533 39.964 21.891 55.907 27 56c5.109-.093 23.467-16.036 23.467-31.353C50.467 18.163 45.209 12 38.723 12z" /></g></svg>
-        <span class="tag-style">{{ formatNum(x.attitudes_count) }}</span>
-      </div>
-    </div>
-  </div>
+  <v-card
+    class-name="mx-auto"
+    color="#000000"
+    dark
+    max-width="400"
+  >
+    <v-card-title>
+      <v-avatar>
+        <img
+          v-if="x.user"
+          :src="x.user.avatar_large"
+          alt="social"
+        >
+      </v-avatar>
+      <span class="text-body-1 font-weight-light">{{ x.user.name }}</span>
+      <span class="text-body-1 font-weight-light">{{ formatTime(x.created_at) }}</span>
+    </v-card-title>
+
+    <v-card-text class-name="text-h5 font-weight-bold">
+      <span v-html="formatContent(x.text)" />
+      <v-row>
+        <v-col
+          v-for="y in x.pic_urls"
+          :key="y.thumbnail_pic"
+          class="d-flex child-flex"
+          cols="4"
+        >
+          <v-img
+            :src="y.thumbnail_pic"
+            :lazy-src="y.thumbnail_pic"
+            aspect-ratio="1"
+            class="grey lighten-2"
+            @click="showImage(y.thumbnail_pic)"
+          >
+            <template v-slot:placeholder>
+              <v-row
+                class="fill-height ma-0"
+                align="center"
+                justify="center"
+              >
+                <v-progress-circular
+                  indeterminate
+                  color="grey lighten-5"
+                />
+              </v-row>
+            </template>
+          </v-img>
+        </v-col>
+      </v-row>
+    </v-card-text>
+    <v-icon
+      small
+      left
+    >
+      mdi-twitter
+    </v-icon>
+  </v-card>
 </template>
 
 <script>
 import * as DateUtils from '@/utils/date-utils'
 import * as StringUtils from '@/utils/string-utils'
 import { mapActions } from 'vuex'
+
 export default {
   name: 'StatusCard',
   props: {
     x: {
       type: Object,
-      default: () => {}
+      default: () => {
+      }
     }
   },
   data() {
@@ -74,6 +81,18 @@ export default {
       'setImageZoom',
       'setDetailContent'
     ]),
+    showImage(imgs) {
+      const arr = []
+      arr[0] = imgs
+      this.$viewerApi({
+        images: arr,
+        options: {
+          movable: false,
+          fullscreen: false,
+          keyboard: true
+        }
+      })
+    },
     goDetailContent() {
       this.setDetailContent(this.x)
       this.$router.push({ name: 'detail-content' })
@@ -125,139 +144,5 @@ export default {
 }
 </script>
 
-<style lang="css">
-a {
-  color: #007AFF;
-}
-
-.content .list-header {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  flex-flow: row;
-}
-
-.content .list-footer {
-  width: 68%;
-  margin-top: .7rem;
-  color: #cdcdcd;
-  display: flex;
-  flex-flow: row;
-}
-
-.content .list-footer .footer-tag {
-  width: 100%;
-  height: 1.3rem;
-  color: inherit;
-}
-
-.content .list-footer .footer-tag .tag-style {
-  font-size: 12px;
-}
-
-.content .avatar {
-  width: 3.5rem;
-  height: 3.5rem;
-  border-radius: 50%;
-  border: 1px solid rgba(0, 0, 0, .05);
-}
-
-.content .user-info {
-  margin-left: 1rem;
-  display: flex;
-  flex-flow: column;
-  flex: 1;
-}
-
-.content .user-time {
-  font-size: 1rem;
-  color: #A4A8AC;
-  height: 100%;
-  display: table-cell
-}
-
-.content .user-info .user-name {
-  margin: 0;
-  flex: 1;
-  font-size: 1.5rem;
-}
-
-.content .user-info .user-source {
-  margin: 0;
-  flex: 1;
-  font-size: 1rem;
-  color: #A4A8AC
-}
-
-.content .user-info .user-source a {
-  color: #A4A8AC;
-}
-
-.content .list-content {
-  margin-top: .7rem;
-}
-
-.content .list-content .content-text {
-  font-size: 1.3rem;
-  line-height: 1rem;
-}
-
-.content .list-content .content-at {
-  color: #007AFF;
-}
-
-.clear-fix::after {
-  content: '';
-  display: block;
-  clear: both;
-}
-
-.content .list-content .content-img .content-img-ul {
-  margin: 0;
-  padding: 0;
-  list-style: none;
-}
-
-.content-img .content-img-ul .img-li-default {
-  float: left;
-  height: 0;
-  margin-top: .4rem;
-  margin-right: .4rem
-}
-
-.content-img .content-img-ul .img-li-one {
-  width: 52%;
-  padding-bottom: 52%;
-}
-
-.content-img .content-img-ul .img-li-two {
-  width: 43%;
-  padding-bottom: 43%;
-}
-
-.content-img .content-img-ul .img-li-other {
-  width: 28%;
-  padding-bottom: 28%;
-}
-
-.content-img .content-img-ul .img-div {
-  width: 100%;
-  padding-bottom: 100%;
-  background-position: center;
-  background-repeat: no-repeat;
-}
-
-.content .list-content .content-re-content {
-  width: 100%;
-  margin-top: .7rem;
-  border: 1px solid rgba(0, 0, 0, .05);
-  border-radius: 3px;
-  background-color: #f5f5f5;
-  padding: .5rem;
-}
-
-.content .list-content .content-re-content .re-content-text {
-  font-size: 1.3rem;
-  line-height: 1rem;
-}
+<style>
 </style>

+ 1 - 1
src/layout/index.vue

@@ -99,7 +99,7 @@ export default {
     keyword: '',
     items: [
       { icon: 'mdi-home', text: '首页', link: '/' },
-      { icon: 'mdi-trending-up', text: '时下流行', link: '/hot' },
+      { icon: 'mdi-trending-up', text: '状态', link: '/hot' },
       { icon: 'mdi-youtube-subscription', text: '订阅', link: '/subscribe' },
       { icon: 'mdi-history', text: '历史记录', link: '/history' },
       { icon: 'mdi-playlist-play', text: '稍后再看', link: '/playlist' }

+ 3 - 0
src/main.js

@@ -5,9 +5,12 @@ import store from './store'
 import vuetify from './plugins/vuetify'
 import VueCookies from 'vue-cookies'
 import infiniteScroll from 'vue-infinite-scroll'
+import 'viewerjs/dist/viewer.css'
+import VueViewer from 'v-viewer'
 
 Vue.use(VueCookies)
 Vue.use(infiniteScroll)
+Vue.use(VueViewer)
 
 Vue.config.productionTip = false
 

+ 2 - 2
src/router/index.js

@@ -21,8 +21,8 @@ const routes = [
       {
         path: '/hot',
         name: 'Hot',
-        component: () => import('@/views/home/MyContent.vue'),
-        meta: { title: 'HerTube 时下流行' }
+        component: () => import('@/views/home/status.vue'),
+        meta: { title: 'HerTube 状态' }
       },
       {
         path: '/subscribe',

+ 3 - 7
src/views/home/hot.vue

@@ -7,12 +7,8 @@
         no-gutters
       >
         <status-card :x="x" />
+        <v-divider />
       </v-row>
-      <!--      <v-row no-gutters>
-        <div v-for="x in list" :key="x.id" class="list">
-          <status-card :x="x" />
-        </div>
-      </v-row>-->
     </div>
   </v-container>
 </template>
@@ -77,10 +73,10 @@ export default {
       this.getMyContent(page)
     },
     loadMore() {
-      const vue = this
+      /* const vue = this
       vue.option.refresh = true
       var page = vue.option.page + 1
-      vue.myContent(page)
+      vue.myContent(page)*/
     },
     scrollBar() {
       var a = document.documentElement.scrollTop === 0 ? document.body.clientHeight : document.documentElement.clientHeight

+ 241 - 0
src/views/home/status.vue

@@ -0,0 +1,241 @@
+<template>
+  <v-container class="grey lighten-5">
+    <v-row justify="space-between">
+      <v-col md="4">
+        <v-card
+          class="mx-auto"
+          color="#26c6da"
+          dark
+          max-width="400"
+        >
+          <v-card-title>
+            <v-icon
+              small
+              left
+            >
+              mdi-twitter
+            </v-icon>
+            <span class="text-h6 font-weight-light">用户名</span>
+          </v-card-title>
+          <v-card-text class="text-h5 font-weight-light">
+            用户签名
+          </v-card-text>
+          <v-card-text class="text-h5 font-weight-light">
+            关注 | 被关注
+          </v-card-text>
+        </v-card>
+      </v-col>
+      <v-col md="4">
+        <v-row dense>
+          <v-col cols="12">
+            <v-card
+              color="#385F73"
+              dark
+            >
+              <v-row dense>
+                <v-textarea
+                  solo
+                  falt
+                  filled
+                  auto-grow
+                  label="想和大家分享点什么呢?"
+                  rows="3"
+                />
+              </v-row>
+              <v-row dense>
+                <v-col>
+                  <v-card-actions>
+                    <v-btn text>
+                      发布
+                    </v-btn>
+                  </v-card-actions>
+                </v-col>
+              </v-row>
+            </v-card>
+          </v-col>
+          <v-col cols="12">
+            <v-sheet
+              class="mx-auto"
+              max-width="700"
+            >
+              <v-slide-group
+                multiple
+                show-arrows
+              >
+                <v-slide-item
+                  v-for="n in 25"
+                  :key="n"
+                  v-slot="{ active }"
+                >
+                  <v-btn
+                    class="mx-2"
+                    :input-value="active"
+                    active-class="purple white--text"
+                    depressed
+                    rounded
+                    @click="selectUser"
+                  >
+                    关注的用户 {{ n }}
+                  </v-btn>
+                </v-slide-item>
+              </v-slide-group>
+            </v-sheet>
+          </v-col>
+          <v-col cols="12">
+            <v-card
+              color="#385F73"
+              dark
+            >
+              <v-card-actions @click="selectCategory">
+                <v-btn text>
+                  全部
+                </v-btn>
+                <v-btn text>
+                  视频
+                </v-btn>
+                <v-btn text>
+                  图片
+                </v-btn>
+              </v-card-actions>
+            </v-card>
+          </v-col>
+          <v-col
+            v-for="x in list"
+            :key="x.id"
+            cols="12"
+          >
+            <status-card :x="x" />
+          </v-col>
+        </v-row>
+      </v-col>
+      <v-col md="4">
+        <v-row dense>
+          <v-col cols="12">
+            <v-card
+              color="#385F73"
+              light
+            >
+              <v-card-title class="text-h5">
+                热门搜索
+              </v-card-title>
+              <v-card-text>
+                <p class="text-body-1 text--primary">
+                  1.第1条
+                </p>
+                <p class="text-body-1 text--primary">
+                  2.第2条
+                </p>
+              </v-card-text>
+            </v-card>
+          </v-col>
+          <v-col cols="12">
+            <v-card
+              color="#385F73"
+              light
+            >
+              <v-card-title class="text-h5">
+                热门视频
+              </v-card-title>
+              <v-card-text>
+                <p class="text-body-1 text--primary">
+                  1.第1条
+                </p>
+                <p class="text-body-1 text--primary">
+                  2.第2条
+                </p>
+              </v-card-text>
+            </v-card>
+          </v-col>
+        </v-row>
+      </v-col>
+    </v-row>
+  </v-container>
+</template>
+
+<script>
+import { mapActions, mapGetters } from 'vuex'
+import StatusCard from '@/components/status/status-card'
+
+export default {
+  name: 'Home',
+  components: {
+    StatusCard
+  },
+  data() {
+    return {
+      list: [],
+      model: null
+    }
+  },
+  computed: {
+    ...mapGetters({
+      statuses: 'my_content',
+      option: 'my_content_option',
+      showImage: 'image_zoom_show'
+    })
+  },
+  watch: {
+    option: {
+      handler: function(val, oldVal) {
+        if (val && val.page === 1) {
+          this.list = []
+        }
+      },
+      deep: true
+    },
+    statuses: function(val, oldVal) {
+      if (val) {
+        if (this.option.page === 1) {
+          this.list = val
+        } else {
+          this.list = [...this.list, ...val]
+        }
+      }
+    }
+  },
+  created() {
+    this.myContent(1)
+  },
+  mounted() {
+
+  },
+  activated() {
+    window.addEventListener('scroll', this.scrollBar)
+  },
+  deactivated() {
+    window.removeEventListener('scroll', this.scrollBar)
+  },
+  methods: {
+    ...mapActions([
+      'getMyContent'
+    ]),
+    myContent(page) {
+      this.getMyContent(page)
+    },
+    selectUser() {
+      console.log('加载选中用户的状态...')
+    },
+    selectCategory() {
+      console.log('加载选中分类的用户状态...')
+    },
+    loadMore() {
+      /* const vue = this
+      vue.option.refresh = true
+      var page = vue.option.page + 1
+      vue.myContent(page)*/
+    },
+    scrollBar() {
+      var a = document.documentElement.scrollTop === 0 ? document.body.clientHeight : document.documentElement.clientHeight
+      var b = document.documentElement.scrollTop === 0 ? document.body.scrollTop : document.documentElement.scrollTop
+      var c = document.documentElement.scrollTop === 0 ? document.body.scrollHeight : document.documentElement.scrollHeight
+      if (a + b === c && !this.showImage) {
+        console.log(a + b)
+        this.loadMore()
+      }
+    }
+  }
+
+}
+</script>
+
+<style></style>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff