Authored by 陈峰

编辑页面及编辑页面的点赞操作等功能开发完毕

  1 +/**
  2 + * 编辑页
  3 + * @author: chenfeng<feng.chen@yoho.cn>
  4 + * @date: 2016/09/05
  5 + */
  6 +'use strict';
  7 +
  8 +const mRoot = '../models';
  9 +const indexModel = require(`${mRoot}/index`);
  10 +const headerModel = require('../../../doraemon/models/header'); // 头部model
  11 +const guangProcess = require(`${global.utils}/guang-process`);
  12 +const Promise = require('bluebird');
  13 +
  14 +/**
  15 + * [编辑页面]
  16 + */
  17 +const _editor = (req, res, next) => {
  18 + let uid = req.user.uid,
  19 + udid = req.sessionID,
  20 + id = req.query.id || 0,
  21 + title = '编辑简介',
  22 + parameter = {},
  23 + isApp = req.query.app_version || req.query.appVersion || false,
  24 + gender = req.query.gender || req.cookies._Channel && channels[req.cookies._Channel] || 1;
  25 +
  26 + if (isApp === false) {
  27 + parameter = {
  28 + pageHeader: headerModel.setNav({
  29 + navTitle: title
  30 + }),
  31 + pageFooter: true
  32 + };
  33 + }
  34 +
  35 + return Promise.all([indexModel.getAuthor(id), indexModel.getArticleList(gender, 0, uid, udid, 1, null, id)]).then(datas => {
  36 + let authorData = datas[0],
  37 + articleListData = datas[1];
  38 + let build = [];
  39 + articleListData.data.list.artList.forEach(articleData => {
  40 + build.push(guangProcess.formatArticle(articleData, true, isApp, false, uid));
  41 + });
  42 + res.render('index/list', Object.assign({
  43 + page: 'index-editor',
  44 + title: title,
  45 + guangList: true,
  46 + gender: gender,
  47 + guang: {
  48 + infos: build,
  49 + isApp: isApp,
  50 + authorInfo: authorData.data
  51 + }
  52 + }, parameter));
  53 + }).catch(next);
  54 +
  55 +};
  56 +
  57 +/**
  58 + * [逛列表页面的资讯分页]
  59 + * @param {[type]} req [description]
  60 + * @param {[type]} res [description]
  61 + * @param {Function} next [description]
  62 + * @return {[type]} [description]
  63 + */
  64 +const _page = (req, res, next) => {
  65 + /* 判断是不是AJAX请求 */
  66 + if (!req.xhr) {
  67 + res.json({ code: 400, message: '非法请求', data: '' });
  68 + return;
  69 + }
  70 +
  71 + /* 判断参数是否有效 */
  72 + let tag = req.query.tag,
  73 + sortId = req.query.type,
  74 + page = req.query.page,
  75 + gender = req.query.gender,
  76 + authorId = req.query.authorId,
  77 + isApp = req.query.isApp,
  78 + isTab = req.query.isTab,
  79 + showAuthor = true;
  80 + let uid = req.user.uid,
  81 + udid = req.sessionID;
  82 + if (sortId && !isNaN(sortId)) {
  83 + res.json({ code: 400, message: '参数错误', data: '' });
  84 + return;
  85 + }
  86 + if (!page && !isNaN(page)) {
  87 + res.json({ code: 400, message: '参数错误', data: '' });
  88 + return;
  89 + }
  90 + if (!authorId && isNaN(authorId)) {
  91 + showAuthor = false;
  92 + }
  93 + return indexModel.getPageData(gender, sortId, uid, udid, page, tag, authorId, isApp, showAuthor, isTab).then(data => {
  94 + if (data) {
  95 + res.render('index/page', Object.assign(data, { layout: false }));
  96 + } else {
  97 + res.json({ code: 400, message: '', data: '' });
  98 + }
  99 + }).catch(next);
  100 +
  101 +};
  102 +
  103 +module.exports = {
  104 + editor: _editor,
  105 + page: _page
  106 +};
  1 +/**
  2 + * 逛操作
  3 + * @author: chenfeng<feng.chen@yoho.cn>
  4 + * @date: 2016/09/06
  5 + */
  6 +'use strict';
  7 +
  8 +const mRoot = '../models';
  9 +const optModel = require(`${mRoot}/opt`);
  10 +const brandModel = require(`${mRoot}/brand`);
  11 +const helpers = global.yoho.helpers;
  12 +const stringProcess = require(`${global.utils}/string-process`);
  13 +
  14 +
  15 +/**
  16 + * [资讯文章点赞 (H5里显示点赞)]
  17 + */
  18 +const _praiseArticle = (req, res, next) => {
  19 + /* 判断是不是AJAX请求 */
  20 + if (!req.xhr) {
  21 + res.json({ code: 400, message: '非法请求', data: '' });
  22 + return;
  23 + }
  24 +
  25 + /* 判断参数是否有效 */
  26 + let id = req.body.id,
  27 + opt = req.body.opt || 'ok',
  28 + udid = req.sessionID;
  29 + if (!stringProcess.isNumeric(id)) {
  30 + res.json({ code: 400, message: '非法请求', data: '' });
  31 + return;
  32 + }
  33 +
  34 + /* 执行点赞或取消操作 */
  35 + return optModel.praiseArticle(udid, id, opt).then((data) => {
  36 + res.json(data);
  37 + }).catch(next);
  38 +};
  39 +
  40 +/**
  41 + * 资讯文章收藏 (APP里显示收藏)
  42 + */
  43 +const _collectArticle = (req, res, next) => {
  44 + let result = {
  45 + code: 400,
  46 + message: '您未登录,无法收藏或者取消收藏。请先登录!',
  47 + data: ''
  48 + };
  49 +
  50 + /* 判断是不是AJAX请求 */
  51 + if (!req.xhr) {
  52 + res.json(result);
  53 + return;
  54 + }
  55 +
  56 + /* 判断参数是否有效 */
  57 + /* 判断用户是否登录 */
  58 + let id = req.body.id,
  59 + opt = req.body.opt || 'ok',
  60 + uid = req.user.uid;
  61 + if (!stringProcess.isNumeric(id) || !stringProcess.isNumeric(uid)) {
  62 + res.json(result);
  63 + return;
  64 + }
  65 +
  66 + /* 执行收藏或取消操作 */
  67 + return optModel.collectArticle(uid, id, opt).then(data => {
  68 + if (!data) {
  69 + res.json({
  70 + code: 400,
  71 + message: '操作失败',
  72 + data: ''
  73 + });
  74 + return;
  75 + }
  76 + res.json({
  77 + code: 200,
  78 + message: '成功',
  79 + data: ''
  80 + });
  81 + });
  82 +};
  83 +
  84 +/**
  85 + * [品牌收藏]
  86 + */
  87 +const _favoriteBrand = (req, res, next) => {
  88 + let refer = helpers.urlFormat('/signin.html', {
  89 + refer: req.headers.referer
  90 + });
  91 + let result = {
  92 + code: 400,
  93 + message: '未登录',
  94 + data: ''
  95 + };
  96 +
  97 + /* 判断是不是AJAX请求 */
  98 + if (!req.xhr) {
  99 + res.json(result);
  100 + return;
  101 + }
  102 +
  103 + /* 判断参数是否有效 */
  104 + let id = req.body.id,
  105 + opt = req.body.opt || 'ok',
  106 + uid = req.user.uid;
  107 + if (!stringProcess.isNumeric(id) || !stringProcess.isNumeric(uid)) {
  108 + res.json(result);
  109 + return;
  110 + }
  111 +
  112 + // 执行收藏或取消操作
  113 + return brandModel.favoriteBrand(uid, id, opt).then(data => {
  114 + if (!data) {
  115 + res.json({
  116 + code: 400,
  117 + message: '操作失败',
  118 + data: ''
  119 + });
  120 + return;
  121 + }
  122 + res.json({
  123 + code: 200,
  124 + message: '成功',
  125 + data: ''
  126 + });
  127 + });
  128 +};
  129 +
  130 +
  131 +module.exports = {
  132 + praiseArticle: _praiseArticle,
  133 + collectArticle: _collectArticle,
  134 + favoriteBrand: _favoriteBrand
  135 +};
  1 +'use strict';
  2 +const api = global.yoho.API;
  3 +
  4 +/**
  5 + * [收藏品牌或者商品]
  6 + * @param {[int]} uid [用户ID]
  7 + * @param {[int]} id [品牌ID]
  8 + * @param {Boolean} isBrand [是品牌还是商品]
  9 + * @param {string} opt [操作(ok:表示确定,cancel:表示取消)]
  10 + * @return {[array]}
  11 + */
  12 +const _favoriteBrand = (uid, id, isBrand, opt) => {
  13 + let param = {
  14 + uid: uid,
  15 + type: isBrand ? 'brand' : 'product'
  16 + };
  17 + if (opt === 'ok') {
  18 + param['id'] = id;
  19 + param['method'] = 'app.favorite.add';
  20 + } else {
  21 + param['fav_id'] = id;
  22 + param['method'] = 'app.favorite.cancel';
  23 + }
  24 + return api.post('', param);
  25 +};
  26 +
  27 +
  28 +module.exports = {
  29 + favoriteBrand: _favoriteBrand
  30 +};
  1 +'use strict';
  2 +const api = global.yoho.API;
  3 +const serviceAPI = global.yoho.ServiceAPI;
  4 +const logger = global.yoho.logger;
  5 +const helpers = global.yoho.helpers;
  6 +const guangProcess = require(`${global.utils}/guang-process`);
  7 +const _ = require('lodash');
  8 +
  9 +/**
  10 + * [获取作者信息]
  11 + * @param {[int]} id [作者id]
  12 + * @return {[object]}
  13 + */
  14 +const _getAuthor = (id) => {
  15 + return serviceAPI.get('guang/service/v1/author/getAuthor', {
  16 + author_id: id
  17 + }).then((result) => {
  18 + if (result && result.code === 200) {
  19 + return result;
  20 + } else {
  21 + logger.error('getAuthor code no 200');
  22 + return {};
  23 + }
  24 + });
  25 +};
  26 +
  27 +/**
  28 + * [逛内容列表]
  29 + * @param {[string]} gender ["1,3"表示男, "2,3"表示女, "1,2,3"表示所有]
  30 + * @param {[int]} sortId [分类ID]
  31 + * @param {Number} uid [用户ID]
  32 + * @param {String} udid [客户端唯一标识]
  33 + * @param {Number} page [分页第几页, 默认第1页]
  34 + * @param {[string]} tag [标签]
  35 + * @param {[int]} authorId [作者ID]
  36 + * @param {[int]} limit [返回的限制数]
  37 + * @param {Boolean} useCache [是否使用缓存]
  38 + * @return {[array]}
  39 + */
  40 +const _getArticleList = (gender, sortId, uid, udid, page, tag, authorId, limit, useCache) => {
  41 + let param = {
  42 + page: page || 1,
  43 + uid: uid || 0,
  44 + udid: udid || '',
  45 + gender: gender || '',
  46 + sort_id: sortId || undefined,
  47 + tag: tag || undefined,
  48 + author_id: authorId || undefined,
  49 + limit: limit || undefined
  50 + };
  51 +
  52 + let cache = useCache ? 300 : false;
  53 +
  54 + return serviceAPI.get('guang/api/v2/article/getList', param, cache).then((result) => {
  55 + if (result && result.code === 200) {
  56 + return result;
  57 + } else {
  58 + logger.error('getAuthor code no 200');
  59 + return [];
  60 + }
  61 + });
  62 +
  63 +};
  64 +
  65 +/**
  66 + * [获取切换逛类别或者分页时的文章数据]
  67 + * @param {[string]} gender ["1,3"表示男, "2,3"表示女]
  68 + * @param {[int]} sortId [分类ID]
  69 + * @param {[int]} uid [用户ID]
  70 + * @param {[string]} udid [客户端唯一标识]
  71 + * @param {[int]} page [分页第几页, 默认第1页]
  72 + * @param {[string]} tag [标签]
  73 + * @param {[string]} authorId [作者ID]
  74 + * @param {Boolean} isApp [是否是APP]
  75 + * @param {[Boolean]} showAuthor [是否显示作者]
  76 + * @param {Boolean} isTab [是否为tab切换操作]
  77 + * @return {[array]}
  78 + */
  79 +const _getPageData = (gender, sortId, uid, udid, page, tag, authorId, isApp, showAuthor, isTab) => {
  80 + return _getArticleList(gender, sortId, uid, udid, page, tag, authorId).then(article => {
  81 + let result = {};
  82 + if (!article['data']['list']['artList']) {
  83 + return result;
  84 + }
  85 +
  86 + let adList = article['data']['list']['adlist'];
  87 +
  88 + // 广告列表
  89 + if (isTab && adList) {
  90 + let build = [];
  91 + adList.forEach(ad => {
  92 + build.push({
  93 + url: guangProcess.getFilterUrl(ad['url']),
  94 + img: helpers.image(ad['src'], 830, 327)
  95 + });
  96 + });
  97 + result['swiper'] = build;
  98 + }
  99 +
  100 + /* 构建资讯文章内容 */
  101 + let build = [];
  102 + let artList = article['data']['list']['artList'];
  103 + artList.forEach(article => {
  104 + build.push(guangProcess.formatArticle(article, true, isApp, showAuthor, uid));
  105 + });
  106 + result['infos'] = build;
  107 + return result;
  108 + });
  109 +
  110 +};
  111 +
  112 +module.exports = {
  113 + getAuthor: _getAuthor,
  114 + getArticleList: _getArticleList,
  115 + getPageData: _getPageData
  116 +};
  1 +'use strict';
  2 +const serviceAPI = global.yoho.ServiceAPI;
  3 +
  4 +/**
  5 + * [逛资讯点赞/取消赞]
  6 + * @param {[int]} udid [唯一客户端标识]
  7 + * @param {[int]} id [唯一资讯的ID]
  8 + * @param {[string]} opt [操作(ok:表示确定,cancel:表示取消)]
  9 + * @return {[array]}
  10 + */
  11 +const _praiseArticle = (udid, id, opt) => {
  12 + let param = {
  13 + article_id: id,
  14 + udid: udid
  15 + };
  16 + if (opt === 'cancel') {
  17 + return serviceAPI.get('guang/api/v2/praise/cancel', param);
  18 + } else {
  19 + return serviceAPI.get('guang/api/v2/praise/setPraise', param);
  20 + }
  21 +};
  22 +
  23 +/**
  24 + * [逛资讯收藏/取消收藏 (APP里调用)]
  25 + * @param {[int]} uid [用户id]
  26 + * @param {[int]} id [唯一资讯的ID]
  27 + * @param {[string]} opt [操作(ok:表示确定,cancel:表示取消)]
  28 + * @return {[array]}
  29 + */
  30 +const _collectArticle = (uid, id, opt) => {
  31 + let param = {
  32 + article_id: id,
  33 + uid: uid
  34 + };
  35 + if (opt === 'cancel') {
  36 + return serviceAPI.get('guang/api/v1/favorite/cancelFavorite', param);
  37 + } else {
  38 + return serviceAPI.get('guang/api/v1/favorite/setFavorite', param);
  39 + }
  40 +};
  41 +
  42 +
  43 +module.exports = {
  44 + praiseArticle: _praiseArticle,
  45 + collectArticle: _collectArticle
  46 +};
@@ -10,6 +10,8 @@ const express = require('express'); @@ -10,6 +10,8 @@ const express = require('express');
10 const cRoot = './controllers'; 10 const cRoot = './controllers';
11 const star = require(cRoot + '/star'); 11 const star = require(cRoot + '/star');
12 const plusstar = require(cRoot + '/plusstar'); 12 const plusstar = require(cRoot + '/plusstar');
  13 +const index = require(cRoot + '/index');
  14 +const opt = require(cRoot + '/opt');
13 15
14 const router = express.Router(); // eslint-disable-line 16 const router = express.Router(); // eslint-disable-line
15 17
@@ -26,4 +28,9 @@ router.post('/star/setFavorite', star.setFavorite); // 收藏文章 @@ -26,4 +28,9 @@ router.post('/star/setFavorite', star.setFavorite); // 收藏文章
26 router.get('/plusstar', plusstar.index); // 潮流优选 28 router.get('/plusstar', plusstar.index); // 潮流优选
27 router.get('/plusstar/resources-template', plusstar.resourcesTemplate); // 潮流优选首页-资源位 29 router.get('/plusstar/resources-template', plusstar.resourcesTemplate); // 潮流优选首页-资源位
28 30
  31 +router.get('/author/list', index.editor); // 编辑简介
  32 +
  33 +router.get('/index/page', index.page); // 逛列表页面的资讯分页
  34 +
  35 +router.post('/opt/praiseArticle', opt.praiseArticle); // 资讯文章点赞 (H5里显示点赞)
29 module.exports = router; 36 module.exports = router;
  1 +<div class="guang-list-page guang-page yoho-page">
  2 +{{# guang}}
  3 + {{# authorInfo}}
  4 + <div id="author-infos" class="editor-header clearfix" data-id={{id}}>
  5 + <div class="avatar">
  6 + <img src="{{avatar}}">
  7 + </div>
  8 + <div class="text">
  9 + <p class="name">{{name}}</p>
  10 + <p class="info">{{author_desc}}</p>
  11 + </div>
  12 + </div>
  13 + {{/ authorInfo}}
  14 +
  15 + <div id="info-list" class="info-list">
  16 + {{# infos}}
  17 + {{> index/info}}
  18 + {{/ infos}}
  19 + </div>
  20 +
  21 + <div id="load-more-info" class="load-more-info">
  22 + <div class="loading status hide">
  23 + 正在加载...
  24 + </div>
  25 + <span class="no-more status">没有更多啦</span>
  26 + </div>
  27 +
  28 + {{#if tag}}
  29 + <input id="tag" type="hidden" value={{tag}}>
  30 + {{/if}}
  31 + {{#if gender}}
  32 + <input id="gender" type="hidden" value={{gender}}>
  33 + {{/if}}
  34 + {{#if isApp}}
  35 + <input id="isApp" type="hidden" value={{isApp}}>
  36 + {{/if}}
  37 +{{/ guang}}
  38 +</div>
  1 +{{#if swiper}}
  2 + <div class="swiper-container">
  3 + <div class="swiper-wrapper">
  4 + <div class="swiper-slide">
  5 + <a href="{{url}}">
  6 + <img class="swiper-lazy" data-src="{{img}}">
  7 + </a>
  8 + <div class="swiper-lazy-preloader"></div>
  9 + </div>
  10 + </div>
  11 + <div class="swiper-pagination"></div>
  12 + </div>
  13 +{{/if}}
  14 +
  15 +{{# infos}}
  16 + {{> index/info}}
  17 +{{/ infos}}
  1 +<div class="guang-info" data-id="{{id}}">
  2 + {{# author}}
  3 + <a class="info-author clearfix" href={{url}}>
  4 + <img class="lazy avatar" data-original={{avatar}}>
  5 + <span class="name">{{name}}</span>
  6 + </a>
  7 + {{/ author}}
  8 +
  9 + <div class="info-img">
  10 + {{#if showTags}}
  11 + <a href="javascript:;" class="info-match">
  12 + {{# isTip}}
  13 + 小贴士
  14 + <div class="info-tag tip"></div>
  15 + {{/ isTip}}
  16 + {{# isCollocation}}
  17 + 搭配
  18 + <div class="info-tag collocation"></div>
  19 + {{/ isCollocation}}
  20 + {{# isFashionMan}}
  21 + 潮人
  22 + <div class="info-tag fashion-man"></div>
  23 + {{/ isFashionMan}}
  24 + {{# isFashionGood}}
  25 + 潮品
  26 + <div class="info-tag fashion-good"></div>
  27 + {{/ isFashionGood}}
  28 + {{# isTopic}}
  29 + 话题
  30 + <div class="info-tag topic"></div>
  31 + {{/ isTopic}}
  32 + {{# isSpecialTopic}}
  33 + 专题
  34 + <div class="info-tag special-topic"></div>
  35 + {{/ isSpecialTopic}}
  36 + </a>
  37 + {{/if}}
  38 + <a href="{{url}}">
  39 + <img class="lazy" data-original="{{img}}" alt="{{alt}}">
  40 + </a>
  41 + </div>
  42 +
  43 + <div class="info-deps">
  44 + <a class="info-title-container" href="{{url}}">
  45 + <h2 class="info-title">{{title}}</h2>
  46 + </a>
  47 + <p class="info-text">{{text}}</p>
  48 + {{> index/tvls}}
  49 + </div>
  50 +</div>
  1 +<div class="time-view-like-share clearfix">
  2 + <i class="iconfont">&#xe603;</i>
  3 + {{publishTime}}&nbsp;&nbsp;&nbsp;&nbsp;
  4 + <i class="iconfont">&#xe602;</i>
  5 + <span class="page-view">{{pageView}}</span>
  6 + <div class="like-share-container">
  7 + {{#like}}
  8 + <i class="iconfont like-btn{{#isLiked}} like{{/isLiked}}">&#xe601;</i>
  9 + <span class="like-count">{{count}}</span>
  10 + {{/ like}}
  11 + {{# collect}}
  12 + <a href={{url}}>
  13 + <i class="iconfont collect-btn{{#isCollected}} collected{{/isCollected}}">&#xe605;</i>
  14 + </a>
  15 + {{/ collect}}
  16 + {{# share}}
  17 + <a href="{{.}}" class="iconfont share-btn">&#xe600;</a>
  18 + {{/ share}}
  19 + </div>
  20 +</div>

225 Bytes | W: | H:

10.1 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
  1 +/**
  2 + * 列表页,编辑页
  3 + * @author: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2015/10/10
  5 + */
  6 +
  7 +var $ = require('yoho-jquery');
  8 +
  9 +var info = require('./info-common'),
  10 + loadMore = info.loadMore;
  11 +
  12 +var winH = $(window).height();
  13 +
  14 +var $author = $('#author-infos');
  15 +var $tag = $('#tag');
  16 +var $gender = $('#gender');
  17 +var $isApp = $('#isApp');
  18 +
  19 +var setting = {
  20 + page: 2,
  21 + end: false
  22 +};
  23 +
  24 +var $infos = $('#info-list');
  25 +
  26 +info.initInfosEvt($infos);
  27 +
  28 +if ($author.length > 0) {
  29 + $.extend(setting, {
  30 + authorId: $author.data('id'),
  31 + isApp: $isApp.val()
  32 + });
  33 +}
  34 +
  35 +if ($tag.length > 0) {
  36 + $.extend(setting, {
  37 + tag: $tag.val(),
  38 + gender: $gender.val(),
  39 + isApp: $isApp.val()
  40 + });
  41 +}
  42 +
  43 +function scrollHandler() {
  44 + if ($(window).scrollTop() + winH >= $(document).height() - 0.25 * $infos.height()) {
  45 + loadMore($infos, setting);
  46 + }
  47 +}
  48 +
  49 +// srcoll to load more
  50 +$(window).scroll(function() {
  51 + window.requestAnimationFrame(scrollHandler);
  52 +});
  1 +/**
  2 + * 资讯相关API
  3 + * @author: xuqi<qi.xu@yoho.cn>
  4 + * @date: 2015/10/10
  5 + */
  6 +
  7 +var $ = require('yoho-jquery'),
  8 + Hammer = require('yoho-hammer'),
  9 + ellipsis = require('yoho-mlellipsis'),
  10 + lazyLoad = require('yoho-jquery-lazyload'),
  11 + Swiper = require('yoho-swiper');
  12 +
  13 +var tip = require('../plugin/tip');
  14 +var loading = require('../plugin/loading');
  15 +
  16 +var $loadMoreInfo = $('#load-more-info');
  17 +var $loading = $(''),
  18 + $noMore = $(''),
  19 + $swiper = $('');
  20 +
  21 +var searching = false;
  22 +var mySwiper = {};
  23 +
  24 +var isLoading = false;
  25 +
  26 +ellipsis.init();
  27 +
  28 +if ($loadMoreInfo.length > 0) {
  29 + $loading = $loadMoreInfo.children('.loading');
  30 + $noMore = $loadMoreInfo.children('.no-more');
  31 +}
  32 +
  33 +// 获取url中的参数
  34 +function getUrlParam(name) {
  35 +
  36 + // 构造一个含有目标参数的正则表达式对象
  37 + var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)');
  38 +
  39 + // 匹配目标参数
  40 + var r = window.location.search.substr(1).match(reg);
  41 +
  42 + // 返回参数值
  43 + if (r != null) {
  44 + return r[2];
  45 + }
  46 +
  47 + return null;
  48 +}
  49 +
  50 +// 初始化swiper
  51 +function initSwiper(typeId) {
  52 + if (typeof typeId === undefined) {
  53 + return;
  54 + }
  55 + mySwiper[typeId] = new Swiper('.swiper-cont-' + typeId, {
  56 + lazyLoading: true,
  57 + wrapperClass: 'swiper-wrap-' + typeId,
  58 + pagination: '.swiper-pagi-' + typeId,
  59 + autoplay: 3000
  60 + });
  61 +}
  62 +
  63 +/**
  64 + * 设置指定资讯项的Lazyload和文字截取
  65 + * @params $infos 资讯项
  66 + */
  67 +
  68 +function setLazyLoadAndMellipsis($infos) {
  69 + lazyLoad($infos.find('img.lazy'));
  70 +
  71 + $infos.each(function() {
  72 + var $this = $(this),
  73 + $title = $this.find('.info-title'),
  74 + $text = $this.find('.info-text');
  75 +
  76 + $title[0].mlellipsis(2);
  77 + $text[0].mlellipsis(2);
  78 + });
  79 +}
  80 +
  81 +/**
  82 + * 初始化资讯列表事件绑定
  83 + * @params $container 逛资讯列表容器
  84 + */
  85 +function initInfosEvt($container) {
  86 + var cHammer;
  87 +
  88 + if (typeof $container === 'undefined') {
  89 + return;
  90 + }
  91 + if (typeof $container[0] === 'undefined') {
  92 + return;
  93 + }
  94 + cHammer = new Hammer($container[0]);
  95 +
  96 + // 点赞或者收藏事件
  97 + cHammer.on('tap', function(e) {
  98 + var $this = $(e.target),
  99 + opt = 'ok',
  100 + $btn,
  101 + $info,
  102 + yhChannel;
  103 +
  104 + // e.preventDefault();
  105 +
  106 + // 点赞
  107 + $btn = $this.closest('.like-btn');
  108 + if ($btn.length > 0 && !isLoading) {
  109 + e.preventDefault();
  110 + if ($btn.hasClass('like')) {
  111 + opt = 'cancel';
  112 + }
  113 +
  114 + $info = $this.closest('.guang-info');
  115 +
  116 + isLoading = true;
  117 +
  118 + $.ajax({
  119 + type: 'POST',
  120 + url: '/guang/opt/praiseArticle',
  121 + data: {
  122 + id: $info.data('id'),
  123 + opt: opt
  124 + },
  125 + success: function(data) {
  126 + var code = data.code;
  127 +
  128 +
  129 + if (code === 200) {
  130 + $btn.next('.like-count').text(data.data);
  131 +
  132 + // 切换点赞状态
  133 + $btn.toggleClass('like');
  134 + }
  135 + },
  136 + error: function() {
  137 + tip.show('网络断开连接了~');
  138 + },
  139 + complete: function() {
  140 + isLoading = false;
  141 + }
  142 + });
  143 + return;
  144 + }
  145 +
  146 + // APP收藏
  147 + $btn = $this.closest('.collect-btn');
  148 + if ($btn.length > 0) {
  149 + e.preventDefault();
  150 + if ($btn.hasClass('collected')) {
  151 + opt = 'cancel';
  152 + }
  153 +
  154 + $info = $this.closest('.guang-info');
  155 +
  156 + if (getUrlParam('yh_channel')) {
  157 + yhChannel = getUrlParam('yh_channel');
  158 + }
  159 +
  160 + $.ajax({
  161 + type: 'POST',
  162 + url: '/guang/opt/collectArticle',
  163 + data: {
  164 + id: $info.data('id'),
  165 + opt: opt,
  166 + yh_channel: yhChannel,
  167 + uid: getUrlParam('uid')
  168 + },
  169 + success: function(data) {
  170 + if (data.code && data.code === 200) {
  171 +
  172 + // 切换收藏状态
  173 + $btn.toggleClass('collected');
  174 + }
  175 + },
  176 + error: function() {
  177 + tip.show('网络断开连接了~');
  178 + }
  179 + });
  180 + }
  181 + });
  182 +
  183 + setLazyLoadAndMellipsis($container.find('.guang-info'));
  184 +}
  185 +
  186 +/**
  187 + * 资讯LoadMore
  188 + * @param $container 资讯容器 jqyeryObject
  189 + * @param opt 请求参数
  190 + * @param url[可选], 扩展请求的url而不使用默认值
  191 + */
  192 +function loadMore($container, opt, url) {
  193 + var num;
  194 +
  195 + if (searching) {
  196 + return;
  197 + }
  198 +
  199 + if (opt.end) {
  200 + return;
  201 + }
  202 +
  203 + if (opt.page === 1) {
  204 +
  205 + // 显示loading
  206 + loading.showLoadingMask();
  207 + }
  208 +
  209 + num = $container.find('.guang-info').length;
  210 + searching = true;
  211 + $.ajax({
  212 + type: 'GET',
  213 + url: url ? url : '/guang/index/page', // 对于指定url的使用指定url(存在不同的控制器)
  214 + data: opt,
  215 + success: function(data) {
  216 + var $newItems;
  217 +
  218 + if (data === ' ') {
  219 + opt.end = true;
  220 + searching = false;
  221 +
  222 + //
  223 + $loading.addClass('hide');
  224 + $noMore.removeClass('hide');
  225 +
  226 + return;
  227 + }
  228 +
  229 + $container.append(data);
  230 +
  231 + $swiper = $container.find('.swiper-container');
  232 + if ($swiper.length) {
  233 + $swiper.addClass('swiper-cont-' + opt.type);
  234 + $swiper.children('.swiper-wrapper').addClass('swiper-wrap-' + opt.type);
  235 + $swiper.children('.swiper-pagination').addClass('swiper-pagi-' + opt.type);
  236 + initSwiper(opt.type);
  237 + }
  238 +
  239 + if (num > 0) {
  240 + $newItems = $container.find('.guang-info:gt(' + (num - 1) + ')');
  241 + } else {
  242 + $newItems = $container.find('.guang-info');
  243 + }
  244 +
  245 + setLazyLoadAndMellipsis($newItems);
  246 +
  247 + if (opt.page === 1) {
  248 + loading.hideLoadingMask();
  249 +
  250 + $loading.removeClass('hide');// 显示空屏加载时hide的隐藏
  251 +
  252 + window.rePosFooter();// 插入内容后重新计算底部位置
  253 + }
  254 +
  255 + opt.page++;
  256 +
  257 + searching = false;
  258 + delete opt.isTab;
  259 + },
  260 + error: function() {
  261 + tip.show('网络断开连接了~');
  262 + searching = false;
  263 + delete opt.isTab;
  264 + }
  265 + });
  266 +}
  267 +
  268 +
  269 +exports.mySwiper = mySwiper;
  270 +exports.initSwiper = initSwiper;
  271 +exports.initInfosEvt = initInfosEvt;
  272 +exports.setLazyLoadAndMellipsis = setLazyLoadAndMellipsis;
  273 +exports.loadMore = loadMore;
@@ -2,3 +2,4 @@ @@ -2,3 +2,4 @@
2 @import "filter"; 2 @import "filter";
3 @import "suspend-cart"; 3 @import "suspend-cart";
4 @import "error"; 4 @import "error";
  5 +@import "loading";
  1 +.load-more-info {
  2 + width: 100%;
  3 + height: 3.5rem;
  4 + line-height: 3.5rem;
  5 + text-align: center;
  6 + font-size: 0.7rem;
  7 + overflow: hidden;
  8 + .status {
  9 + &.hide {
  10 + display: none;
  11 + }
  12 + }
  13 +}
1 @import "star/index"; 1 @import "star/index";
2 @import "plusstar/index"; 2 @import "plusstar/index";
  3 +@import "index/index";
  1 +@import "info-list";
  2 +@import "info";
  3 +@import "tvls";
  1 +.guang-list-page {
  2 + .editor-header {
  3 + margin-bottom: 1.5rem;
  4 + padding-top: 1.8rem;
  5 + padding-bottom: 2.0rem;
  6 + background: #fff;
  7 + border-bottom: 0.05rem solid #e0e0e0;
  8 + }
  9 +
  10 + .avatar {
  11 + float: left;
  12 + margin-left: 1.5rem;
  13 + img {
  14 + width: 5.0rem;
  15 + height: 5.0rem;
  16 + border-radius: 50%;
  17 + }
  18 + }
  19 +
  20 + .text {
  21 + float: left;
  22 + margin-left: 1.6rem;
  23 + width: 23.75rem;
  24 + .name {
  25 + font-size: 1.6rem;
  26 + line-height: 2.0rem;
  27 + }
  28 + .info {
  29 + margin-top: 0.3rem;
  30 + color: #bdbdbf;
  31 + font-size: 1.2rem;
  32 + line-height: 1.6rem;
  33 + }
  34 + }
  35 +
  36 + .swiper-container {
  37 + width: 100%;
  38 + height: 15.5rem;
  39 +
  40 + img {
  41 + height: 100%;
  42 + width: 100%;
  43 + }
  44 +
  45 + .swiper-pagination {
  46 + bottom: 0;
  47 + left: 0;
  48 + width: 100%;
  49 + }
  50 +
  51 + .swiper-pagination-bullet-active {
  52 + background: #fff;
  53 + }
  54 + }
  55 +
  56 + .guang-nav {
  57 + background-color: #fff;
  58 + overflow: hidden;
  59 + height: 4.0rem;
  60 + }
  61 +
  62 +
  63 + .guang-nav-item {
  64 + float: left;
  65 + color: #ccc;
  66 + font-size: 1.4rem;
  67 + padding: 0 1.1rem;
  68 + line-height: 4.0rem;
  69 +
  70 + &.focus {
  71 + color: #000;
  72 + }
  73 + }
  74 +
  75 + .bytouch{
  76 + background:#eee;
  77 + }
  78 +
  79 + .info-list-container {
  80 + overflow-x: hidden;
  81 + background: #f0f0f0;
  82 + }
  83 +
  84 + .info-list.hide {
  85 + display: none;
  86 + }
  87 +}
  1 +.guang-info {
  2 + margin-bottom: 1.5rem;
  3 + padding: 0 0 1.2rem 0;
  4 + border-top: 0.05rem solid #e0e0e0;
  5 + border-bottom: 0.05rem solid #e0e0e0;
  6 + background: #fff;
  7 +
  8 + .info-author {
  9 + display: block;
  10 + width: 100%;
  11 +
  12 + .avatar {
  13 + float: left;
  14 + margin-top: 1.0rem;
  15 + width: 2.5rem;
  16 + height: 2.5rem;
  17 + margin-left: 1.5rem;
  18 + border-radius: 50%;
  19 + }
  20 +
  21 + .name {
  22 + float: left;
  23 + margin-left: 1.5rem;
  24 + padding: 1.5rem 0;
  25 + font-size: 1.4rem;
  26 + color: #000;
  27 + }
  28 + }
  29 +
  30 + &:last-child {
  31 + margin-bottom: 0;
  32 + }
  33 +
  34 + .info-img {
  35 + position: relative;
  36 + width: 100%;
  37 +
  38 + img {
  39 + display: block;
  40 + width: 100%;
  41 + }
  42 + }
  43 +
  44 + .info-match {
  45 + position: absolute;
  46 + top: 0;
  47 + left: 0;
  48 + width: 6.5rem;
  49 + height: 2.5rem;
  50 + line-height: 2.5rem;
  51 + font-size: 1.4rem;
  52 + color: #fff;
  53 + background: #000;
  54 + text-align: center;
  55 + text-decoration: none;
  56 + z-index: 1;
  57 + }
  58 +
  59 + .info-tag {
  60 + position: absolute;
  61 + top: 0;
  62 + left: 5.25rem;
  63 + height: 2.5rem;
  64 + width: 2.5rem;
  65 +
  66 + &.collocation {
  67 + background-image: url("/guang/info/collocation.png");
  68 + }
  69 +
  70 + &.fashion-good {
  71 + background-image: url("/guang/info/fashion-good.png");
  72 + }
  73 +
  74 + &.fashion-man {
  75 + background-image: url("/guang/info/fashion-man.png");
  76 + }
  77 +
  78 + &.tip, &.special-topic {
  79 + background-image: url("/guang/info/tip.png");
  80 + }
  81 +
  82 + &.topic {
  83 + background-image: url("/guang/info/topic.png");
  84 + }
  85 + }
  86 +
  87 + .info-deps {
  88 + margin: 1.6rem 0 0 0;
  89 + padding: 0 2.0rem 0 1.5rem;
  90 +
  91 + .info-title-container {
  92 + text-decoration: none;
  93 + color: #000;
  94 + }
  95 +
  96 + .info-title{
  97 + line-height: 2.2rem;
  98 + color: #000;
  99 + font-size: 2.0rem;
  100 + font-weight:bold;
  101 +
  102 + }
  103 +
  104 + .info-text {
  105 + margin: 0.8rem 0 0 0;
  106 + line-height: 2.3rem;
  107 + font-size: 1.4rem;
  108 + color: #444;
  109 + }
  110 +
  111 + .time-view-like-share {
  112 + margin-top: 0.8rem;
  113 + }
  114 + }
  115 +}
  1 +.time-view-like-share {
  2 + color: #b0b0b0;
  3 + line-height: 1.9rem;
  4 + height: 1.9rem;
  5 + font-size: 1.2rem;
  6 +
  7 + .iconfont {
  8 + vertical-align: 9%;
  9 + margin-right: 0.2rem;
  10 + font-size: 1.2rem;
  11 + }
  12 +
  13 + .like-share-container {
  14 + display: inline-block;
  15 + float: right;
  16 +
  17 + > * {
  18 + float: left;
  19 + }
  20 +
  21 + .iconfont {
  22 + position: relative;
  23 + height: 3.0rem;
  24 + line-height: 3.0rem;
  25 + display: inline-block;
  26 +
  27 + color: #b0b0b0;
  28 + width: 3.0rem;
  29 + top: -0.7rem;
  30 + font-size: 1.7rem;
  31 + text-align: center;
  32 + margin-right: 0;
  33 + outline: none;
  34 + }
  35 +
  36 + .share-btn {
  37 + margin-left: 1.0rem;
  38 + }
  39 +
  40 + .like-btn.like {
  41 + color: #444;
  42 + }
  43 +
  44 + .collect-btn {
  45 + margin-left: 1.0rem;
  46 + &.collected {
  47 + color: #D62927;
  48 + }
  49 + }
  50 + }
  51 +}
  1 +/**
  2 + * 逛处理类
  3 + */
  4 +
  5 +'use strict';
  6 +const helpers = global.yoho.helpers;
  7 +
  8 +/**
  9 + * [格式化资讯文章]
  10 + * @param {[array]} articleData [需要格式化的资讯数据]]
  11 + * @param {[Boolean]} showTag [是否显示左上角标签]]
  12 + * @param {Boolean} isApp [是否显示分享,在APP客户端里嵌入需要传url链接]
  13 + * @param {[Boolean]} showAuthor [控制是否显示作者信息]
  14 + * @param {[int]} uid [当前登录的用户ID]
  15 + * @param {[string]} reqQueryString [查询字符串]
  16 + * @return {[array | false]}
  17 + */
  18 +const _formatArticle = (articleData, showTag, isApp, showAuthor, uid, reqQueryString) => {
  19 + // 资讯ID不存在,则不显示
  20 + if (!articleData['id']) {
  21 + return false;
  22 + }
  23 + var result = {
  24 + id: articleData['id'],
  25 + showTags: showTag,
  26 + img: articleData['src'] ? helpers.image(articleData['src'], 640, 640) : '',
  27 + url: isApp ? `${helpers.https(articleData['url'])}&openby:yohobuy={"action":"go.h5","params":{"param":{"id":"${articleData['id']}"},"shareparam":{"id":"${articleData['id']}"},"share":"/guang/api/v1/share/guang","id":${articleData['id']},"type":1,"url":"http:${helpers.urlFormat('/info/index', null, 'guang')}","islogin":"N"}}` : articleData['url'],
  28 + title: articleData['title'],
  29 + text: articleData['intro'],
  30 + publishTime: articleData['publish_time'],
  31 + pageView: articleData['views_num']
  32 + };
  33 + if (result['url'].includes('feature.yoho.cn') ||
  34 + result['url'].includes('cdn.yoho.cn')) {
  35 + result['url'] = _transHttpsUrl(result['url']);
  36 + }
  37 +
  38 + // 收藏
  39 + if (isApp) {
  40 + result['collect'] = [];
  41 + result['collect']['isCollected'] = articleData['isFavor'] === true;
  42 + let originUrl = helpers.urlFormat('/author/index', null, 'guang') + reqQueryString; // 跳转回的链接
  43 + let collectUrl = 'javascript:;'; // 根据用户是否登录做处理的链接
  44 + if (!uid) {
  45 + let playUrlEncode = originUrl.replace(/\//g, '\\/');
  46 + collectUrl = `${originUrl}?openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"${playUrlEncode}","param":{"from":"app"}},"requesturl":{"url":"","param":{}},"priority":"N"}}`;
  47 + }
  48 + result['collect']['url'] = collectUrl;
  49 + } // 点赞
  50 + else {
  51 + result['like'] = {};
  52 + result['like']['count'] = articleData['praise_num'];
  53 + result['like']['isLiked'] = articleData['isPraise'] === 'Y';
  54 + }
  55 +
  56 + if (isApp && articleData['share']['url']) {
  57 +
  58 + // 分享链接
  59 + result['share'] = `${articleData['share']['url']}?openby:yohobuy={"action":"go.share","params":{"title":"${articleData['title']}","content":"${articleData['intro']}","url":"${articleData['share']['url']}","pic":"https:${result['img']}"}}`;
  60 + }
  61 +
  62 + // 判断是否显示作者信息
  63 + if (showAuthor && articleData['author']) {
  64 + if (!isApp) {
  65 + articleData['author']['url'] = _getFilterUrl(articleData['author']['url']);
  66 + }
  67 +
  68 + // 编辑人员 app跳转url处理 20160601
  69 + let isLogin = uid ? true : false;
  70 + articleData['author']['url'] = `${helpers.https(articleData['author']['url'])}&openby:yohobuy={"action":"go.h5","params":{"param":{"id":"${articleData['author']['author_id']}"},"share":"","id":${articleData['author']['author_id']},"type":0,"islogin":"${isLogin} ","url":"https:${helpers.urlFormat('/author/index', {uid: uid}, 'guang')} "}}&uid=${uid}`;
  71 + result['author'] = articleData['author'];
  72 + if (result['author']['avatar']) {
  73 + result['author']['avatar'] = result['author']['avatar'].replace('http://', '//');
  74 + }
  75 + }
  76 +
  77 + // 模板中需要的标签标识
  78 + if (showTag && articleData['category_id']) {
  79 + switch (articleData['category_id']) {
  80 + case '1': // 话题
  81 + result['isTopic'] = true;
  82 + break;
  83 + case '2': // 搭配
  84 + result['isCollocation'] = true;
  85 + break;
  86 + case '3': // 潮人
  87 + result['isFashionMan'] = true;
  88 + break;
  89 + case '4': // 潮品
  90 + result['isFashionGood'] = true;
  91 + break;
  92 + case '5': // 小贴士
  93 + result['isTip'] = true;
  94 + break;
  95 + case '19': // 专题
  96 + result['isSpecialTopic'] = true;
  97 + break;
  98 + }
  99 + }
  100 + return result;
  101 +};
  102 +
  103 +
  104 +/**
  105 + * [将首字符为//的url转换为http://]
  106 + * @param {[string]} url [需要转换的url]
  107 + * @return {[string]} [description]
  108 + */
  109 +const _transHttpsUrl = (url) => {
  110 + return url.replace(/^\/\//g, 'http://');
  111 +};
  112 +const _getFilterUrl = (url) => {
  113 + url = url.replace('.m.yohobuy.com', global.yoho.config.subDomains.host).replace('www.yohobuy.com', global.yoho.config.siteUrl);
  114 +
  115 + const whiteDomains = ['m.yohobuy.com', 'cdn.yoho.cn/myohobuy'];
  116 + const blackDomains = ['sale.m.yohobuy.com', 'cuxiao.m.yohobuy.com', 'activity.m.yohobuy.com', 'huodong.m.yohobuy.com', '/home/orders/pay'];
  117 +
  118 + if (whiteDomains.every(_ => url.includes(_)) &&
  119 + blackDomains.every(_ => !url.includes(_))) {
  120 + url = url.replace('http://', '//');
  121 + }
  122 +
  123 + if (url.includes('feature.yoho.cn')) {
  124 + url = _transHttpsUrl(url);
  125 + }
  126 + if (url.includes('openby:yohobuy=')) {
  127 + let filters = ['openby:yohobuy=', '&', '?'];
  128 + filters.forEach(_ => {
  129 + url = url.subString(0, url.lastIndexOf(_));
  130 + });
  131 + return url.replace(/(^\s*)|(\s*$)/g, '');
  132 + } else {
  133 + return url;
  134 + }
  135 +};
  136 +
  137 +module.exports = {
  138 + formatArticle: _formatArticle,
  139 + transHttpsUrl: _transHttpsUrl,
  140 + getFilterUrl: _getFilterUrl
  141 +};
  1 +/**
  2 + * 字符串处理
  3 + */
  4 +
  5 +'use strict';
  6 +
  7 +/**
  8 + * [判断数字]
  9 + * @param {[string]} str [验证参数]
  10 + * @return {[Boolean]}
  11 + */
  12 +const _isNumeric = (str) => {
  13 + return /^\d+(\.\d+)?$/.test(str);
  14 +};
  15 +
  16 +module.exports = {
  17 + isNumeric: _isNumeric
  18 +};