Browse Source

阅读记录

natasha 1 year ago
parent
commit
c8f86822d2

+ 169 - 140
src/utils/index.js

@@ -5,29 +5,30 @@ import { getStaticContent } from '@/api/ajax';
 import { setConfig } from './auth'
 
 export function getConfigInfor() {
-  return new Promise((resolve, reject) => {
-    let MethodName = 'sys_config_manager-GetLogo';
-    getStaticContent(MethodName, {}).then(res => {
-      setConfig(res);
-      resolve(res)
-    }).catch(err => {
-      reject(err);
+    return new Promise((resolve, reject) => {
+        let MethodName = 'sys_config_manager-GetLogo';
+        getStaticContent(MethodName, {}).then(res => {
+            setConfig(res);
+            resolve(res)
+        }).catch(err => {
+            reject(err);
+        })
     })
-  })
 }
 
 //分:秒转秒
 export function timeStrToSen(time) {
-  if (!time) {
-    return -1;
-  }
-  var pos = time.indexOf(':');
-  var min = 0, sec = 0;;
-  if (pos > 0) {
-    min = parseInt(time.substring(0, pos));
-    sec = parseFloat(time.substring(pos + 1))
-  }
-  return min * 60 + sec;
+    if (!time) {
+        return -1;
+    }
+    var pos = time.indexOf(':');
+    var min = 0,
+        sec = 0;;
+    if (pos > 0) {
+        min = parseInt(time.substring(0, pos));
+        sec = parseFloat(time.substring(pos + 1))
+    }
+    return min * 60 + sec;
 }
 
 /**
@@ -41,46 +42,46 @@ export function timeStrToSen(time) {
  * @returns {string | null}
  */
 export function parseTime(time, cFormat) {
-  if (arguments.length === 0 || !time) {
-    return null
-  }
-  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
-  let date
-  if (typeof time === 'object') {
-    date = time
-  } else {
-    if ((typeof time === 'string')) {
-      if ((/^[0-9]+$/.test(time))) {
-        // support "1548221490638"
-        time = parseInt(time)
-      } else {
-        // support safari
-        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
-        time = time.replace(new RegExp(/-/gm), '/')
-      }
+    if (arguments.length === 0 || !time) {
+        return null
     }
+    const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
+    let date
+    if (typeof time === 'object') {
+        date = time
+    } else {
+        if ((typeof time === 'string')) {
+            if ((/^[0-9]+$/.test(time))) {
+                // support "1548221490638"
+                time = parseInt(time)
+            } else {
+                // support safari
+                // https://stackoverflow.com/questions/4310953/invalid-date-in-safari
+                time = time.replace(new RegExp(/-/gm), '/')
+            }
+        }
 
-    if ((typeof time === 'number') && (time.toString().length === 10)) {
-      time = time * 1000
+        if ((typeof time === 'number') && (time.toString().length === 10)) {
+            time = time * 1000
+        }
+        date = new Date(time)
     }
-    date = new Date(time)
-  }
-  const formatObj = {
-    y: date.getFullYear(),
-    m: date.getMonth() + 1,
-    d: date.getDate(),
-    h: date.getHours(),
-    i: date.getMinutes(),
-    s: date.getSeconds(),
-    a: date.getDay()
-  }
-  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
-    const value = formatObj[key]
-    // Note: getDay() returns 0 on Sunday
-    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
-    return value.toString().padStart(2, '0')
-  })
-  return time_str
+    const formatObj = {
+        y: date.getFullYear(),
+        m: date.getMonth() + 1,
+        d: date.getDate(),
+        h: date.getHours(),
+        i: date.getMinutes(),
+        s: date.getSeconds(),
+        a: date.getDay()
+    }
+    const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
+        const value = formatObj[key]
+            // Note: getDay() returns 0 on Sunday
+        if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
+        return value.toString().padStart(2, '0')
+    })
+    return time_str
 }
 
 /**
@@ -89,41 +90,41 @@ export function parseTime(time, cFormat) {
  * @returns {string}
  */
 export function formatTime(time, option) {
-  if (('' + time).length === 10) {
-    time = parseInt(time) * 1000
-  } else {
-    time = +time
-  }
-  const d = new Date(time)
-  const now = Date.now()
+    if (('' + time).length === 10) {
+        time = parseInt(time) * 1000
+    } else {
+        time = +time
+    }
+    const d = new Date(time)
+    const now = Date.now()
 
-  const diff = (now - d) / 1000
+    const diff = (now - d) / 1000
 
-  if (diff < 30) {
-    return '刚刚'
-  } else if (diff < 3600) {
-    // less 1 hour
-    return Math.ceil(diff / 60) + '分钟前'
-  } else if (diff < 3600 * 24) {
-    return Math.ceil(diff / 3600) + '小时前'
-  } else if (diff < 3600 * 24 * 2) {
-    return '1天前'
-  }
-  if (option) {
-    return parseTime(time, option)
-  } else {
-    return (
-      d.getMonth() +
-      1 +
-      '月' +
-      d.getDate() +
-      '日' +
-      d.getHours() +
-      '时' +
-      d.getMinutes() +
-      '分'
-    )
-  }
+    if (diff < 30) {
+        return '刚刚'
+    } else if (diff < 3600) {
+        // less 1 hour
+        return Math.ceil(diff / 60) + '分钟前'
+    } else if (diff < 3600 * 24) {
+        return Math.ceil(diff / 3600) + '小时前'
+    } else if (diff < 3600 * 24 * 2) {
+        return '1天前'
+    }
+    if (option) {
+        return parseTime(time, option)
+    } else {
+        return (
+            d.getMonth() +
+            1 +
+            '月' +
+            d.getDate() +
+            '日' +
+            d.getHours() +
+            '时' +
+            d.getMinutes() +
+            '分'
+        )
+    }
 }
 
 /**
@@ -131,68 +132,96 @@ export function formatTime(time, option) {
  * @returns {Object}
  */
 export function param2Obj(url) {
-  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
-  if (!search) {
-    return {}
-  }
-  const obj = {}
-  const searchArr = search.split('&')
-  searchArr.forEach(v => {
-    const index = v.indexOf('=')
-    if (index !== -1) {
-      const name = v.substring(0, index)
-      const val = v.substring(index + 1, v.length)
-      obj[name] = val
+    const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
+    if (!search) {
+        return {}
     }
-  })
-  return obj
+    const obj = {}
+    const searchArr = search.split('&')
+    searchArr.forEach(v => {
+        const index = v.indexOf('=')
+        if (index !== -1) {
+            const name = v.substring(0, index)
+            const val = v.substring(index + 1, v.length)
+            obj[name] = val
+        }
+    })
+    return obj
 }
 
 
 export function createComprisonFunction(propertyName) {
-  return function (object1, object2) {
-    var value1 = object1[propertyName];
-    var value2 = object2[propertyName];
-    if (value1 < value2) {
-      return -1;
-    } else if (value1 > value2) {
-      return 1;
-    } else {
-      return 0;
+    return function(object1, object2) {
+        var value1 = object1[propertyName];
+        var value2 = object2[propertyName];
+        if (value1 < value2) {
+            return -1;
+        } else if (value1 > value2) {
+            return 1;
+        } else {
+            return 0;
+        }
     }
-  }
 }
 
 // 混淆数字
 export function handleNumber(number) {
-  let numberArr;
-  numberArr = [
-    number - 3,
-    number - 2,
-    number - 1,
-    number + 1,
-    number + 2,
-    number + 3,
-  ];
-  numberArr = getRandomArrayElements(
-    numberArr,
-    3
-  );
-  numberArr.push(number);
-  numberArr.sort();
-  return numberArr;
+    let numberArr;
+    numberArr = [
+        number - 3,
+        number - 2,
+        number - 1,
+        number + 1,
+        number + 2,
+        number + 3,
+    ];
+    numberArr = getRandomArrayElements(
+        numberArr,
+        3
+    );
+    numberArr.push(number);
+    numberArr.sort();
+    return numberArr;
 }
 export function getRandomArrayElements(arr, count) {
-  var shuffled = arr.slice(0),
-    i = arr.length,
-    min = i - count,
-    temp,
-    index;
-  while (i-- > min) {
-    index = Math.floor((i + 1) * Math.random());
-    temp = shuffled[index];
-    shuffled[index] = shuffled[i];
-    shuffled[i] = temp;
-  }
-  return shuffled.slice(min);
+    var shuffled = arr.slice(0),
+        i = arr.length,
+        min = i - count,
+        temp,
+        index;
+    while (i-- > min) {
+        index = Math.floor((i + 1) * Math.random());
+        temp = shuffled[index];
+        shuffled[index] = shuffled[i];
+        shuffled[i] = temp;
+    }
+    return shuffled.slice(min);
+}
+//秒数转化为时分秒
+export function formatSeconds(value) {
+    var secondTime = parseInt(value); // 秒
+    var minuteTime = 0; // 分
+    var hourTime = 0; // 小时
+    if (secondTime > 60) { //如果秒数大于60,将秒数转换成整数
+        //获取分钟,除以60取整数,得到整数分钟
+        minuteTime = parseInt(secondTime / 60);
+        //获取秒数,秒数取余,得到整数秒数
+        secondTime = parseInt(secondTime % 60);
+        //如果分钟大于60,将分钟转换成小时
+        if (minuteTime > 60) {
+            //获取小时,获取分钟除以60,得到整数小时
+            hourTime = parseInt(minuteTime / 60);
+            //获取小时后取余的分,获取分钟除以60取余的分
+            minuteTime = parseInt(minuteTime % 60);
+        }
+    }
+    var result = "" + parseInt(secondTime) + "秒";
+
+    if (minuteTime > 0) {
+        result = "" + parseInt(minuteTime) + "分" + result;
+    }
+    if (hourTime > 0) {
+        result = "" + parseInt(hourTime) + "小时" + result;
+    }
+    return result;
 }

+ 107 - 18
src/views/bookShelf/articleDetail.vue

@@ -22,9 +22,22 @@
             <div class="atricle-data">
                 <normal-model :titleFontsize="wordFontsize+30" :wordFontsize="wordFontsize" :colorObj="bgColorList[activeIndex]" :articleType="articleType" :style="{'padding':'0 40px'}"></normal-model>
                 <div class="article-btn">
-                    <el-button type="text" class="btn-left" @click="handlePage('-')"><svg-icon icon-class="arrow-left-line"></svg-icon>上一篇</el-button>
-                    <el-button class="explain-video"><svg-icon icon-class="check-double-line"></svg-icon>已读</el-button>
-                    <el-button type="text" class="btn-right" @click="handlePage('+')">下一篇<svg-icon icon-class="arrow-right-line"></svg-icon></el-button>
+                    <div class="left">
+                        <span :class="['support',support?'active':'']" @click="changeStatus('support')"><svg-icon icon-class="support"></svg-icon>2847</span>
+                        <span :class="['oppose',oppose?'active':'']" @click="changeStatus('oppose')"><svg-icon icon-class="oppose"></svg-icon></span>
+                    </div>
+                    <div class="center">
+                        <el-button type="text" class="btn-left" @click="handlePage('-')"><svg-icon icon-class="arrow-left-line"></svg-icon>上一篇</el-button>
+                        <el-button type="text" class="btn-right" @click="handlePage('+')">下一篇<svg-icon icon-class="arrow-right-line"></svg-icon></el-button>
+                    </div>
+                    <div class="right">
+                        <template v-if="noRead">
+                            <span class="support" @click="handleReadArticle"><svg-icon icon-class="no-read"></svg-icon>标记为已读</span>
+                        </template>
+                        <template v-else>
+                            <span class="support readed"><svg-icon icon-class="readed"></svg-icon>已读</span>
+                        </template>
+                    </div>
                 </div>
             </div>
             <!-- 词汇表 -->
@@ -479,6 +492,11 @@ export default {
         ],
         articleType:this.$route.query.type?this.$route.query.type*1:1,
         articleId:this.$route.query.id?this.$route.query.id:'',
+        noRead: true, // 未读
+        support: false, // 点赞
+        oppose: false, // 不支持
+        timer: null,
+        readLength: 0,
     }
   },
   methods: {
@@ -563,6 +581,7 @@ export default {
         }
     },
     getArticleDetail(){
+        let this_ = this;
         let MethodName = "/PaperServer/Client/Article/GetArticleDetail";
         let data = {
             id: this.articleId,
@@ -571,11 +590,38 @@ export default {
         .then((res) => {
             if(res.status===1){
                 
+                if(!this.noRead){
+                    clearInterval(this_.timer);
+                    this_.timer = null;
+                }
             }
         })
         .catch(() => {
             
         }); 
+    },
+    handleReadArticle(){
+        let this_ = this;
+        clearInterval(this_.timer);
+        this_.timer = null;
+        let MethodName = "/ShopServer/Client/ReadingRecordManager/AddReadingRecord_Article";
+        let data = {
+            goods_type: 21,
+            article_id: this.articleId,
+            duration: this.readLength
+        }
+        getLogin(MethodName, data)
+        .then((res) => {
+            if(res.status===1){
+                this.noRead = false
+            }
+        })
+        .catch(() => {
+            
+        }); 
+    },
+    changeStatus(flag){
+        this[flag] = !this[flag]
     }
   },
   created(){
@@ -585,6 +631,12 @@ export default {
   },
   mounted(){
     this.inityuan()
+    let this_ = this;
+    this_.timer = null;
+    this_.readLength = 0
+    this_.timer = setInterval(() => {
+        this_.readLength++;
+    }, 1000);
   }
 }
 </script>
@@ -728,12 +780,60 @@ export default {
 }
 .article-btn{
     display: flex;
-    align-items: center;
     justify-content: space-between;
+    align-items: center;
+    .right{
+        width: 145px;
+        margin-right: -8px;
+        text-align: right;
+    }
+    .support{
+        padding: 8px 16px;
+        border-radius: 20px;
+        background: #E5E6EB;
+        margin-right: 8px;
+        color:rgba(0, 0, 0, 0.88);
+        font-size: 16px;
+        font-weight: 400;
+        line-height: 24px;
+        cursor: pointer;
+        .svg-icon{
+            margin-right: 8px;
+            color: rgba(23, 93, 255, 1);
+        }
+        &.active{
+            background: rgba(48, 110, 255, 1);
+            color: #fff;
+            .svg-icon{
+                color: #fff;
+            }
+        }
+    }
+    .oppose{
+        padding: 12px;
+        border-radius: 20px;
+        background: #E5E6EB;
+        height: 40px;
+        font-size: 16px;
+        line-height: 16px;
+        display: inline-block;
+        cursor: pointer;
+        .svg-icon{
+            width: 16px;
+            height: 16px;
+        }
+        &.active{
+            background: rgba(48, 110, 255, 1);
+            .svg-icon{
+                color: #fff;
+            }
+        }
+    }
     .btn-left,.btn-right{
         color: #3459D2;
         font-size: 16px;
         line-height: 24px;
+        padding: 0;
         .svg-icon{
             margin-right: 12px;
         }
@@ -744,20 +844,9 @@ export default {
             margin-left: 12px;
         }
     }
-    .explain-video{
-        font-weight: 400;
-        font-size: 16px;
-        line-height: 40px;
-        padding: 0;
-        color: rgba(255, 255, 255, 0.88);
-        width: 120px;
-        height: 40px;
-        background: #3459D2;
-        border-radius: 30px;
-        border: none;
-        .svg-icon{
-            margin-right: 24px;
-        }
+    .readed{
+        background: rgba(231, 238, 255, 1);
+        color: rgba(23, 93, 255, 1);
     }
 }
 </style>

+ 85 - 28
src/views/personalCenter/components/PersonalInfo.vue

@@ -1,42 +1,39 @@
 <template>
-  <div class="personal-info">
+  <div class="personal-info" v-loading="loading" v-if="readInfo">
     <div class="personal-info-top">
         <div class="avator-box">
            <el-image
             :src="data.avatar?data.avatar:require('../../../assets/avatar.png')"
             fit="cover" style="width:96px;height:96px;">
           </el-image>
-          <a @click="toggleShow" class="img-crop">
-            <svg-icon icon-class="camera"></svg-icon>
-          </a>
         </div>
         <div class="center">
             <p class="name">{{data.name}}</p>
-            <span class="school">{{data.school}}</span>
+            <span class="org_name">{{data.org_name}}</span>
             <!-- <span class="class">{{data.class}}</span> -->
         </div>
         <div class="right">
             <div class="item">
                 <p>共阅读文章</p>
-                <b class="number">{{data.totalArticle}}</b>
+                <b class="number">{{readInfo.article_count}}</b>
                 <span>篇</span>
             </div>
             <el-divider direction="vertical"></el-divider>
             <div class="item">
                 <p>累计阅读时长</p>
-                <b class="number">{{data.totalTime}}</b>
+                <b class="number">{{readInfo.durationStr}}</b>
                 <span>小时</span>
             </div>
             <el-divider direction="vertical"></el-divider>
             <div class="item">
                 <p>共阅读词数</p>
-                <b class="number">{{data.totalWords}}</b>
+                <b class="number">{{readInfo.article_diff_word_count}}</b>
                 <span>词</span>
             </div>
             <el-divider direction="vertical"></el-divider>
             <div class="item">
                 <p>累计阅读长度</p>
-                <b class="number">{{data.totalLength}}</b>
+                <b class="number">{{readInfo.article_word_count}}</b>
                 <span>词</span>
             </div>
         </div>
@@ -52,27 +49,27 @@
                 :data="articleList"
             >
                 <el-table-column
-                    prop="number"
+                    type="index"
                     label="#"
-                    sortable
-                    width="72">
+                    width="72"
+                    :index="(pageNumber-1)*pageSize+1">
                 </el-table-column>
                 <el-table-column
                     prop="title"
                     label="文章">
                     <template slot-scope="scope">
                         <a @click="handleLink(scope.row)" style="color:#165DFF">
-                            {{scope.row.title}}
+                            {{scope.row.article_title}}
                         </a>
                     </template>
                 </el-table-column>
                 <el-table-column
-                    prop="study"
+                    prop="study_phase_name"
                     label="学段"
                     width="81">
                 </el-table-column>
                 <el-table-column
-                    prop="source"
+                    prop="issue_no_name"
                     label="来源"
                     width="197">
                 </el-table-column>
@@ -80,16 +77,25 @@
                     prop="words"
                     label="词数/长度"
                     width="140">
+                    <template slot-scope="scope">
+                        {{scope.row.article_diff_word_count+'/'+scope.row.article_word_count}}
+                    </template>
                 </el-table-column>
                 <el-table-column
-                    prop="readTime"
+                    prop="duration"
                     label="阅读时长"
                     width="140">
+                    <template slot-scope="scope">
+                        {{formatterDuration(scope.row)}}
+                    </template>
                 </el-table-column>
                 <el-table-column
-                    prop="readDate"
+                    prop="reading_time"
                     label="阅读时间"
                     width="160">
+                    <template slot-scope="scope">
+                        {{scope.row.reading_time?scope.row.reading_time.substring(0,16):'-'}}
+                    </template>
                 </el-table-column>
             </el-table>
             <el-pagination
@@ -110,8 +116,8 @@
                 <el-table-column
                     prop="number"
                     label="#"
-                    sortable
-                    width="72">
+                    width="72"
+                    :index="(pageNumber-1)*pageSize+1">
                 </el-table-column>
                 <el-table-column
                     prop="word"
@@ -177,15 +183,15 @@
 <script>
 //这里可以导入其它文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
 //例如:import 《组件名称》from ‘《组件路径》';
-
+import { getLogin } from "@/api/ajax";
+import { formatSeconds } from "@/utils/index";
 export default {
   //import引入的组件需要注入到对象中才能使用
   components: { },
-  props: ["data"],
+  props: [],
   data() {
     //这里存放数据
     return {
-        show: false, // 编辑头像flag
         tabsIndex: 0, // tab
         articleList: [
             {
@@ -329,7 +335,14 @@ export default {
         ],
         filterTypeArr: [],
         total_count_a: 0,
-        total_count_w: 0
+        total_count_w: 0,
+        data: {
+            avatar: '',
+            name: '',
+            org_name: ''
+        },
+        loading: false,
+        readInfo: null
     }
   },
   //计算属性 类似于data概念
@@ -340,9 +353,14 @@ export default {
   },
   //方法集合
   methods: {
-    // 编辑头像
-    toggleShow() {
-      this.show = !this.show;
+    formatterDuration(row){
+        let studyCn = ''
+        if(row.duration){
+            studyCn = formatSeconds(row.duration)
+        }else{
+            studyCn = '0'
+        }
+        return studyCn
     },
     // 切换tabs
     handleChangeTabs(value){
@@ -374,10 +392,49 @@ export default {
     handleWordList(){
         this.filterTypeArr=[]
     },
-    
+    getInfo(){
+        let MethodName = "/OrgServer/Client/PersonManager/GetMyInfo";
+        let data = {}
+        getLogin(MethodName, data)
+        .then((res) => {
+            if(res.status===1){
+                this.data.name = res.person.user_name
+                this.data.avatar = res.person.image_url
+                this.data.org_name = res.person.org_name
+            }
+        }).catch((res) =>{
+        })
+    },
+    getList(){
+        this.loading = true
+        let MethodName = "/ShopServer/Client/ReadingRecordManager/PageQueryMyReadingRecord_Article";
+        let data = {
+            page_capacity: this.pageSize,
+            cur_page: this.pageNumber,
+            order_column_list: []
+        }
+        getLogin(MethodName, data)
+        .then((res) => {
+            this.loading = false
+            if(res.status===1){
+                this.readInfo = res.sum_info
+                this.total_count_a = res.total_count
+                if(res.sum_info.duration<3600){
+                    this.readInfo.durationStr = '<1'
+                }else{
+                    this.readInfo.durationStr = Math.ceil(res.sum_info.duration/3600)
+                }
+                this.articleList = res.reading_record_list
+            }
+        }).catch((res) =>{
+            this.loading = false
+        })
+    }
   },
   //生命周期 - 创建完成(可以访问当前this实例)
   created() {
+    this.getInfo()
+    this.getList()
   },
   //生命周期 - 挂载完成(可以访问DOM元素)
   mounted() {
@@ -451,7 +508,7 @@ export default {
                 line-height: 24px;
                 color: #1D2129;
             }
-            .school{
+            .org_name{
                 margin-right: 40px;
             }
         }

+ 1 - 1
src/views/personalCenter/components/Setting.vue

@@ -411,7 +411,7 @@ export default {
     },
     // 级联选择器
     handleCity(value){
-        console.log(value)
+        // console.log(value)
     },
     // 提交表单
     onSubmit(formName){

+ 1 - 1
src/views/personalCenter/index.vue

@@ -16,7 +16,7 @@
         </ul>
         <div class="main-right">
             <!-- 个人中心 -->
-            <personal-info :data="personalInfo" v-if="menuType==='user'"></personal-info>
+            <personal-info v-if="menuType==='user'"></personal-info>
             <!-- 收藏夹 -->
             <collect v-if="menuType==='like'"></collect>
             <!-- 兑换码 -->