Authored by TaoHuang

init

{
"presets": [
[
"@babel/env",
{
"modules": false,
"targets": {}
}
]
],
"exclude": [
"node_modules/*"
]
}
\ No newline at end of file
... ...
{
"env": {
"browser": true,
"es6": true
},
"globals": {
"__$styleInject": true,
"ENV": true
},
"extends": "eslint:recommended",
"parserOptions": {
"sourceType": "module"
},
"rules": {
"indent": [
"warn",
4
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"warn",
"single"
],
"semi": [
"warn",
"always"
],
"no-empty": 1,
"no-undef": 2,
"no-console": 1,
"no-unused-vars": 1
}
}
\ No newline at end of file
... ...
*.iml
.idea/
.ipr
.iws
*~
~*
*.diff
*.patch
*.bak
.DS_Store
Thumbs.db
.project
.*proj
.svn/
*.swp
*.swo
*.pyc
*.pyo
.build
node_modules
_site
sea-modules
spm_modules
.cache
dist
web.log
npm-debug
package-lock
... ...
registry=http://npm.yohops.com
package-lock=false
\ No newline at end of file
... ...
## YOHO!App前端js的功能封装包,主要用于第三方应用中,对主要功能的封装。
## 封装实现的功能
### 1. 用户相关
1. 获取用户的信息和状态
2. 验证登录
3. 收藏商品
### 3. 分享相关
1. 分享到微信好友
2. 分享到朋友圈
### 4. 个性化展示
1. 个性化数据页面内元素标记
2. 获取数据绑定到界面
### 5. 移动端打开app
1. 通过url的openapp参数来判断是否打开 app。
## 使用说明
1. 本插件jssdk 依赖于jQuery, 所以请先加载 jQuery;
2. 然后加载本插件jssdk;
## 功能说明
1. 获取用户信息和状态:
app: url中的uid 来判断用户是否登录
浏览器:jsonp调用接口来判断用户是否登录
2. 验证登录:auth()
若用户未登录,则会将所以的 `<a class="auth">`标签的`href`属性 替换为 登录url
3. 收藏商品:favout(skn)
收藏传入`skn`所相对应的商品
4. 优惠券领取:
<a> 标签加上`yoho-conpon`类名,并加上 `data-token` 属性,值为后台生成的 token。
示例:
```html
<a class="yoho-conpon" href="javascript:;" data-token="29-6ea9ab1baa0efb9e19094440c317e21b">
<h1>领券按钮</h1>
</a>
```
5. 有货币领取:
<a> 标签加上`yoho-coin`类名,并加上 `data-token` 属性,值为后台生成的 token。
示例:
```html
<a class="yoho-coin" href="javascript:;" data-token="22e369853df766fa44e1ed0ff613f563bd">
<h1>有货币领取按钮</h1>
</a>
```
6. 红包领取:
<a> 标签加上`yoho-redenvelope`类名,并加上 `data-token` 属性,值为后台生成的 token。
示例:
```html
<a class="yoho-redenvelope" href="javascript:;" data-token="29-6ea9ab1baa0efb9e19094440c317e21b">
<h1>红包按钮</h1>
</a>
```
7. 分享相关:
如果需要定制分享参数时,通过<input type="hidden">方式自定义
示例:
```html
<input id="shareLink" type="hidden" value="http://feature.yoho.cn/1228/1228MEMBER/index.html">
<input id="shareDesc" type="hidden" value="VIP专场劲爆开启->VIP独享4重福利,超值冬品限时5折,更有专享年终福利券等你抢!">
<input id="shareImg" type="hidden" value="http://feature.yoho.cn/public/shareimg/1228member.png">
<input id="shareTitle" type="hidden" value="【YOHO!BUY有货】12月28日潮集会员日">
```
8. 个性化推荐:
8.1. 定义商品模版
示例:
```html
<div class="product-source" cloneitem="true" condition='{"sort":"111","limit":10, "pid":1}'>
<input class="imgwh" type="hidden" name="" value="450x500">
<div class="feature-product-info">
<a class="product-detail" href='http://item.yohobuy.com/product/pro_330189_424569/PUMADUPLEXEVOPARTYDiBangXie36146103.html?from=search-s-51184789_1_1&openby:yohobuy={"action":"go.productDetail","params":{"product_id":"330189","from":"search-s-51184789_1_1"}}'>
<div>
<img class="product-detail-img" src="http://img10.static.yhbimg.com/goodsimg/2016/11/21/12/01c6529b3ecdc8c6085a48446f331fae4c.jpg?imageMogr2/thumbnail/450x500/extent/450x500/background/d2hpdGU=/position/center/quality/60">
</div>
<div class="product-detail-text">
<div class="name">
<span class="product-name">双贴袋连帽棉夹克【两色可选】</span>
</div>
<div class="price">
<span class="sale-price">¥589.00</span>
<span class="market-price">¥779.00</span>
</div>
</div>
</a>
<a class="product-brand" href="http://m.yohobuy.com/product/index/brand?shop_id=1540">
<span class="brand-name">Life After Life</span>
<span class="brand-go">进入店铺</span>
</a>
</div>
</div>
```
8.2. 详细说明
以下属性class/id 需要固定不变,引入的 jssdk 会通过class名 来做动态替换
class/id | 说明
------- | ----
.product-source | 一个商品池标示,属性condition是检索条件(详细说明见7.3)
.imgwh | value值为 商品图片显示的宽x高
.feature-product-info | 标示一个商品item
.brand-name | 店铺名称(如果不需要显示店铺,可不写)
a.product-brand | 进入店铺的url (如果不需要显示店铺,可不写)
a.product-detail | 进入商品详情页 url
.product-detail-img | 商品图片url
.product-name | 商品名称 (如果不需要显示,可不写)
.sale-price | 销售价格
.market-price | 市场价格
8.3. condition 说明
参数名称 | 说明 | 示范
------- | ---- | ----
sort | 商品的小分类,如果是多个,用逗号隔开 | 123,111,114
misort | 商品的中分类,如果是多个,用逗号隔开 | 123,111,114
msort | 商品的大分类,如果是多个,用逗号隔开 | 123,111,114
gender | 性别 | 1,3
brand | 商品的品牌,如果是多个,用逗号隔开 | 144,349
pid | 活动id | 123
enum | 是否是枚举:1:是,0:不是 | 1
limit | 获取个数,当enum为1时,limit无效 | 10
sn | 库存筛选条件 | 10 (库存 > 10)
pd | 折扣筛选条件 | 0.45,0.55 (5折)
... ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<textarea type="text" placeholder="券号" value="" onchange="onChange(event, 'coupon1')">wangdachui233</textarea>
<div id="coupon1" class="yoho-conpon" data-token="wangdachui233" data-type="ufo">
<a href="javascript:;">点我领取UFO优惠券</a>
</div>
<div class="yoho-tencentCaptcha" data-appid="2008945059" data-on="1">
<div>
<script src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
<script src="//cdn.yoho.cn/js-sdk/1.3.15/jssdk.js"></script>
<script src="../dist/js-sdk/1.3.26-beta1/jssdk.js"></script>
<script>
function onChange(e) {
$('#coupon1').data('token', e.target.value)
}
</script>
</body>
</html>
... ...
import jssdk from './src/js/jssdk';
(function(factory) {
/* eslint-disable */
if (typeof module === 'object' && typeof module.exports === 'object') {
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
define([], factory);
} else {
window._jssdk = factory();
}
/* eslint-disable */
}(function() {
return jssdk;
}));
\ No newline at end of file
... ...
This diff could not be displayed because it is too large.
{
"name": "yohoapp-bridge-sdk",
"version": "1.3.27-0",
"description": "YOHO! app js的功能封装包,主要用于第三方应用使用app的功能。",
"keywords": [
"YOHO!",
"JS-SDK"
],
"main": "index.js",
"scripts": {
"build": "rollup -c --no-treeshake",
"dev": "rollup -c --watch --no-treeshake",
"fix": "eslint --fix src/**/*",
"example": "http-server ./ -p 8081 -d -o"
},
"repository": {
"type": "git",
"url": "git@git.yoho.cn:fe/yohoapp-bridge-sdk.git"
},
"author": "htoo <tao.huang@yoho.cn>",
"licenses": "MIT",
"devDependencies": {
"@babel/core": "^7.1.0",
"@babel/plugin-external-helpers": "^7.0.0",
"@babel/preset-env": "^7.1.0",
"cssnano": "^4.1.3",
"http-server": "^0.11.1",
"postcss-cssnext": "^3.1.0",
"postcss-nested": "^4.1.0",
"postcss-simple-vars": "^5.0.1",
"rollup": "^0.66.2",
"rollup-plugin-babel": "^4.0.3",
"rollup-plugin-commonjs": "^9.1.8",
"rollup-plugin-eslint": "^5.0.0",
"rollup-plugin-json": "^3.1.0",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-postcss": "^1.6.2",
"rollup-plugin-uglify": "^6.0.0",
"rollup-watch": "^4.3.1"
},
"dependencies": {
"jquery-lazyload": "^1.9.7",
"yoho-jquery": "^2.2.4"
}
}
... ...
// Rollup plugins
import babel from 'rollup-plugin-babel';
import {eslint} from 'rollup-plugin-eslint';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import {uglify} from 'rollup-plugin-uglify';
import json from 'rollup-plugin-json';
import postcss from 'rollup-plugin-postcss';
import simplevars from 'postcss-simple-vars';
import nested from 'postcss-nested';
import cssnext from 'postcss-cssnext';
import cssnano from 'cssnano';
const pkg = require('./package.json');
export default {
input: 'index.js',
output: {
file: `dist/js-sdk/${pkg.version}/yohoapp-bridge-sdk.js`,
format: 'iife',
globals: {
jquery: 'jQuery'
}
},
external: ['jquery'],
plugins: [
json({
include: 'node_modules/**',
preferConst: true, // Default: false
}),
postcss({
plugins: [
simplevars(),
nested(),
cssnext({ warnForDuplicates: false, }),
cssnano({zindex: false}),
],
extensions: ['.css'],
}),
resolve({
jsnext: true,
main: true,
browser: true,
}),
commonjs(),
eslint({
exclude: [
'src/css/**'
]
}),
babel(),
uglify()
],
};
... ...
.feature-coin {
&.tip-wrap {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background: rgba(0, 0, 0, .5);
}
.tip {
position: fixed;
left: 50%;
top: 50%;
margin-left: -140px;
margin-top: -140px;
width: 280px;
background: #fff;
text-align: center;
line-height: 1.25;
background-repeat: no-repeat;
}
.tip .tip-close{
position: absolute;
right: 0;
top: 0;
width: 25px;
height: 25px;
line-height: 25px;
text-align: center;
font-size: 16px;
color: #fff;
background: #000;
cursor: pointer;
}
.tip .title {
margin: 21px auto;
font-size: 22px;
font-weight: 700;
text-align: center;
}
.tip .highlight {
font-size: 18px;
}
.tip .content {
padding: 4px;
font-size: 16px;
color: #444;
text-align: center;
height: 48px;
overflow: hidden;
}
.bottom-button {
text-align: center;
}
.tip .button, .tip .coin {
display: inline-block;
margin: 20px auto;
width: 116px;
height: 26px;
font-size: 14px;
line-height: 26px;
text-align: center;
color: #fff;
background: #000;
text-decoration: none;
border: 2px solid #000;
}
.tip .coin {
color: #000;
background: #fff;
}
}
\ No newline at end of file
... ...
.featuretip {
&.tip-wrap {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background: rgba(0, 0, 0, .5);
}
.tip {
position: fixed;
left: 50%;
top: 50%;
margin-left: -140px;
margin-top: -140px;
width: 280px;
background: #fff;
border-top: 40px solid #000;
text-align: center;
line-height: 1.25;
z-index: 10;
}
.tip .title {
margin: 25px auto 30px;
font-size: 20px;
font-weight: 700;
text-align: center;
}
.tip .highlight {
font-size: 18px;
}
.tip .content {
font-size: 14px;
color: #444;
text-align: center;
line-height: 20px;
}
.tip .button {
display: block;
margin: 20px auto;
width: 150px;
height: 30px;
font-size: 14px;
line-height: 30px;
text-align: center;
color: #fff;
background: #000;
text-decoration: none;
}
.tip.coupon-tip {
border-top: 0;
background: url('//img11.static.yhbimg.com/sns/2018/10/16/19/0172232208d89e64d308dae5c4f5d5ac79.png') no-repeat;
background-size: 100%;
width: 200px;
margin-left: -100px;
padding-top: 100px;
&:after {
content: '';
position: absolute;
left: 0;
right: 0;
top: 50%;
bottom: 0;
z-index: -1;
background-color: #ce1230;
}
.title {
font-size: 20px;
color: #fff;
}
.content {
font-size: 12px;
color: #fff;
}
.button {
background: none;
color: #fff;
border: 1px solid #fff;
}
}
}
.feature-toast {
width: 100%;
position: fixed;
bottom: 10%;
z-index: 9999;
display: none;
text-align: center;
.feature-toast-content {
max-width: 50%;
font-size: 12px;
background-color: #333;
padding: 6px 10px;
border-radius: 3px;
color: #fff;
opacity: 0.8;
-webkit-opacity: 0.8;
word-break: break-all;
text-align: center;
display: inline-block;
}
}
... ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<style>
body {
text-align: center;
}
a {
text-decoration: none;
color: #444;
}
hr {
margin-top: 30px;
margin-bottom: 30px;
}
img {
max-width: 90%;
}
</style>
</head>
<body>
<h1>测试 Token </h1>
<div class="yoho-tencentCaptcha" data-appid="2008945059" data-open="1">
<div>
<a class="yoho-conpon yoho-captcha" href="javascript:;" data-token="50f033ab37c3" data-type="1">
<h1>50f033ab37c3</h1>
</a>
<hr>
<a class="auth yoho-conpon" href="javascript:;" data-token="4e35f4a8d465">
<h1>4e35f4a8d465</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="4cfbd7939d67">
<h1>4cfbd7939d67</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="4aad61ab1432">
<h1>4aad61ab1432</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="467cbbc409ec">
<img src="http://img02.yohoboys.com/staticimg/2016/04/22/14/02a8b1c09363f84c34aa56d11bb5cd7eb4.png">
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="5693db85ed90">
<h1>5693db85ed90</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="582a38a4a931">
<h1>582a38a4a931</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="5a8613985ec4">
<h1>5a8613985ec4</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="5c92cc227532">
<h1>5c92cc227532</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="5ef4b9ec30ad">
<h1>5ef4b9ec30ad</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="62ed3d2c2199">
<h1>62ed3d2c2199</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="6026657d5ff9">
<h1>6026657d5ff9</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="7e069059b7ef">
<h1>7e069059b7ef</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="8602522a2b27">
<h1>8602522a2b27</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="8465ded5353c">
<h1>8465ded5353c</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="4bd09bf41544">
<h1>4bd09bf41544</h1>
</a>
<hr>
<a class="yoho-conpon" href="javascript:;" data-token="4d28dd2c7955">
<h1>4d28dd2c7955</h1>
</a>
<hr>
<h1>测试 Token </h1>
<a class="auth yoho-coin" href="javascript:;" data-token="22e369853df766fa44e1ed0ff613f563bd">
<h1>ccc已经结束 22e369853df766fa44e1ed0ff613f563bd</h1>
</a>
<hr>
<a class="auth yoho-coin" href="javascript:;" data-token="2419ca14e7ea6328a42e0eb13d585e4c22">
<h1>ccc还未开始 2419ca14e7ea6328a42e0eb13d585e4c22</h1>
</a>
<hr>
<a class="yoho-coin" href="javascript:;" data-token="26a5771bce93e200c36f7cd9dfd0e5deaa">
<h1>ccc后台已删除 26a5771bce93e200c36f7cd9dfd0e5deaa</h1>
</a>
<hr>
<a class="yoho-coin" href="javascript:;" data-token="28d645920e395fedad7bbbed0eca3fe2e0">
<h1>ccc已经领取完 28d645920e395fedad7bbbed0eca3fe2e0</h1>
</a>
<hr>
<a class="yoho-coin" href="javascript:;" data-token="2aa1d0c6e83f027327d8461063f4ac58a6">
<h1>领取成功验证 2aa1d0c6e83f027327d8461063f4ac58a6</h1>
</a>
<hr>
<a class="yoho-coin" href="javascript:;" data-token="2cf7177163c833dff4b38fc8d2872f1ec6">
<h1>ccc只能领取1次已领完 2cf7177163c833dff4b38fc8d2872f1ec6</h1>
</a>
<hr>
<h1>测试 红包 </h1>
<a class="auth yoho-redenvelope" href="javascript:;" data-token="bf7867128e0bd248">
<h1>ccc还未开始 bf7867128e0bd248</h1>
</a>
<hr>
<a class="auth yoho-redenvelope" href="javascript:;" data-token="bf7867128e0bd248">
<h1>ccc还未开始 bf7867128e0bd248</h1>
</a>
<a class="auth yoho-redenvelope" href="javascript:;" data-token="bf7867128e0bd248">
<h1>ccc还未开始 bf7867128e0bd248</h1>
</a>
<hr>
<hr>
<hr>
<hr>
<a class="yoho-redenvelope" href="javascript:;" data-token="2aa1d0c6e83f027327d8461063f4ac58a6">
<img src="http://img02.yohoboys.com/staticimg/2016/04/22/14/02a8b1c09363f84c34aa56d11bb5cd7eb4.png">
</a>
<a class="anchor" href='http://union.yoho.cn/union/downapp.html'></a>
<div class="product-source" condition='{"sort":"123,3213,3123,3123","enum":1, "pid":1}'>
<input id="imgwh" type="hidden" value="200x300">
<div class="feature-product-info">
<a class="product-brand" href="xxx">
<span class="brand-name">xxx</span>
<span class="brand-go">进入店铺</span>
</a>
<a class="product-detail" href="xxx">
<div>
<img class="product-detail-img" src="xxx">
</div>
<div class="product-detail-text">
<div class="name">
<span class="product-name">xxx</span>
</div>
<div class="price">
<span class="sale-price">xxx</span>
<span class="market-price">xxx</span>
</div>
</div>
</a>
</div>
<div class="feature-product-info">
<a class="product-brand" href="">
<span class="brand-name"></span>
<span class="brand-go">进入店铺</span>
</a>
<a class="product-detail" href="">
<div>
<img class="product-detail-img" src="">
</div>
<div class="product-detail-text">
<div class="name">
<span class="product-name"></span>
</div>
<div class="price">
<span class="sale-price"></span>
<span class="market-price"></span>
</div>
</div>
</a>
</div>
<div class="feature-product-info">
<a class="product-brand" href="">
<span class="brand-name"></span>
<span class="brand-go">进入店铺</span>
</a>
<a class="product-detail" href="">
<div>
<img class="product-detail-img" src="">
</div>
<div class="product-detail-text">
<div class="name">
<span class="product-name"></span>
</div>
<div class="price">
<span class="sale-price"></span>
<span class="market-price"></span>
</div>
</div>
</a>
</div>
</div>
<script src="//cdn.bootcss.com/jquery/1.8.3/jquery.min.js"></script>
<script src="../dist/js-sdk/1.3.26-beta1/jssdk.js"></script>
</body>
</html>
... ...
import $ from 'jquery';
const url = 'https://ssl.captcha.qq.com/TCaptcha.js';
function _initScript() {
return $.getScript(url);
}
const store = {
appId: ''
};
export default {
init() {
let $tencentCaptcha = $('.yoho-tencentCaptcha');
store.appId = $tencentCaptcha.data('appid');
if (store.appId) {
return _initScript();
}
return $.Deferred().resolve();
},
getInstance(cb) {
// eslint-disable-next-line
return new TencentCaptcha(store.appId+'', cb, {});
}
};
... ...
function cookie(name) {
var re = new RegExp(name + '=([^;$]*)', 'i'),
matchPattern = '$1';
return re.test(decodeURIComponent(document.cookie)) ? RegExp[matchPattern] : '';
}
function setCookie(name, value, options) {
var expires = '',
path,
domain,
secure,
date;
if (typeof value !== 'undefined') {
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
if (options.expires &&
(typeof options.expires === 'number' || options.expires.toUTCString)) {
if (typeof options.expires === 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString();
}
path = options.path ? '; path=' + options.path : '';
domain = options.domain ? '; domain=' + options.domain : '';
secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
}
}
export default {
cookie,
setCookie
};
\ No newline at end of file
... ...
import './webp-support';
const defaultQuality = 60;
/**
* 图片链接处理
*/
const imgSrcHandle = (imgUrl, params) => {
if (!imgUrl) {
return imgUrl;
}
params = Object.assign({
q: defaultQuality
}, params);
let splits = imgUrl.split('?');
let url = splits[0];
let query = splits[1] || '';
if (!query || query === 'imageslim') {
if (window.supportWebp) {
url += `?imageView2/0/interlace/1/format/webp/q/${params.q}`;
} else {
let extQuery = params.q === defaultQuality ? '?imageslim' : `?imageView2/0/interlace/1/q/${params.q}`;
url += extQuery;
}
imgUrl = url;
} else if (/imageView/.test(query)) { // imageView2 || imageView
if (!/\/q\/\d+/.test(query)) {
imgUrl += `/q/${params.q}`;
} else {
imgUrl = imgUrl.replace(/\/q\/\d+/g, '/q/' + params.q);
}
if (window.supportWebp && !/format\//i.test(query)) {
imgUrl += '/format/webp';
}
if (window.supportWebp && (/format\/png/i.test(query) || /format\/jpg/i.test(query))) {
imgUrl = imgUrl.replace(/format\/png/i, 'format/webp').replace(/format\/jpg/i, 'format/webp');
}
} else if (/imageMogr/.test(query)) {
if (!/\/quality\/\d+/.test(query)) {
imgUrl += `/quality/${params.q}`;
} else {
imgUrl = imgUrl.replace(/\/quality\/\d+/g, '/quality/' + params.q);
}
if (window.supportWebp && !/format\//.test(query)) {
imgUrl += '/format/webp';
}
if (window.supportWebp && (/format\/png/i.test(query) || /format\/jpg/i.test(query))) {
imgUrl = imgUrl.replace(/format\/png/i, 'format/webp').replace(/format\/jpg/i, 'format/webp');
}
}
return imgUrl;
};
export default imgSrcHandle;
... ...
import $ from 'jquery';
import jsonp from './jsonp';
import user from './user';
import utils from './utils';
import cookies from './cookies';
import lazyLoad from './lazyload';
let abTestFlag = false; // ab测试
let getPname = function () {
let pName = '';
if (utils.isMobile.iOS()) {
pName = 'iFP_SalesPromotion_h5';
}
if (utils.isMobile.Android()) {
pName = 'aFP_SalesPromotion_h5';
}
return pName;
};
let _replaceData = function(el, cond, data, wh, fp) {
if (!data) {
return;
}
let product_url = `//m.yohobuy.com/product/${data.product_skn}.html?openby:yohobuy={"action":"go.productDetail","params":{"product_skn":${data.product_skn},"from_page_name":"${getPname()}","from_page_param":"${location.href.split('?')[0]}"}}`;
if (data.collage_price && data.collage_activity_id) {
product_url = `//m.yohobuy.com/activity/group/detail?activityId=${data.collage_activity_id}&productSkn=${data.product_skn}&openby:yohobuy={"action":"go.productDetail","params":{"product_skn":"${data.product_skn}","activity_id":"${data.collage_activity_id}","activity_type":"groupPurchase"}}`;
}
el.find('.brand-name').html(data.brand_name);
el.find('.product-detail').attr('href', product_url);
el.find('.product-name').html(data.product_name);
el.find('.vip-price-val').html(${data.vip_price}`);
el.find('.sale-price').html(${data.sales_price}`);
el.data('skn', data.product_skn);
if (data.curPlanPrice) {
el.find('.advance .advance-price').html(${data.curPlanPrice}`);
el.find('.advance').css({display: 'inline-block'});
}
const $productDetailImg = el.find('.product-detail-img');
if ($productDetailImg.hasClass('lazy')) {
$productDetailImg.attr('data-original', utils.image(data.default_images, wh.w, wh.h, 2, 75));
} else {
$productDetailImg.attr('src', utils.image(data.default_images, wh.w, wh.h, 2, 75));
}
if (data.sales_price === data.market_price) {
el.find('.market-price').hide();
} else {
el.find('.market-price').html(${data.market_price}`).show();
}
let brandDom = el.find('.product-brand');
if (brandDom) {
if (data.shop_id) {
// eslint-disable-next-line
brandDom.attr('href', `//m.yohobuy.com/product/index/brand?shop_id=${data.shop_id}&openby:yohobuy={"action":"go.shop","params":{"shop_id":${data.shop_id},"shop_template_type":${data.shop_template_type || "1"},"is_red_shop":${data.is_red_shop || 1}}}`);
} else {
brandDom.attr('href', `//m.yohobuy.com/product/index/brand?domain=${data.brand_domain}&openby:yohobuy={"action":"go.brand","params":{"brand_id":${data.brand_id}}}`);
}
}
// 楼层数据
if (fp) {
if (!fp.I_INDEX) fp.I_INDEX = 0;
fp.I_INDEX++;
el.find('.product-detail').attr('fp', JSON.stringify(fp));
if (brandDom) {
fp.I_INDEX++;
brandDom.attr('fp', JSON.stringify(fp));
}
}
let listDom = el.find('.list-product');
if (listDom) {
let sortStr = '',
gender = cond.gender ? cond.gender : '1,3',
url = `//list.m.yohobuy.com?gender=${gender}`;
if (listDom.data('sort')) {
sortStr += `,"sort":${data.small_sort_id}`;
url += `&sort=${data.small_sort_id}`;
}
if (listDom.data('misort')) {
sortStr += `,"misort":${data.middle_sort_id}`;
url += `&misort=${data.middle_sort_id}`;
}
if (listDom.data('msort')) {
sortStr += `,"msort":${data.max_sort_id}`;
url += `&msort=${data.max_sort_id}`;
}
url += `&openby:yohobuy={"action":"go.list","params":{"actiontype":1,"gender":${gender}${sortStr}}}`;
listDom.attr('href', url);
}
el.html(el.html());
return el;
};
let _getProductData = function(dataArr){
if (!dataArr.length) {
return;
}
var data = dataArr.shift();
if (!data || !data.default_images) {
return _getProductData(dataArr);
}
return data;
};
let _jsonp = function(el, param, cond){
let cloneitem = el.attr('cloneitem');
let loading = el.find('.loading');
let goods = el.find('.feature-product-info');
let rowNum = el.data('rownum');
if (!goods.length) {
return;
}
if (cond.abtest) {
// ab测试,访客 和 >=512的uid 显示默认推荐
if (!param.uid || (Number(param.uid) % 1024 >= 512)) {
if (cloneitem) {
$(goods[0]).remove();
} else {
goods.removeClass('novisible');
loading.hide();
}
return;
}
}
let imgwh = el.find('.imgwh').val() || ''; // 获取图片宽x高
imgwh = imgwh.split('x') || [];
let wh = {
w: imgwh[0] || 300,
h: imgwh[1] || 400
};
// 楼层数据
let fp = el.attr('fp');
fp = fp ? JSON.parse(fp) : '';
jsonp({
url: '//m.yohobuy.com/activity/individuation?callback=?',
data: $.extend({}, param, cond)
}).then(function(res) {
if (!res || !res.length) {
if (cloneitem) {
$(goods[0]).remove();
} else {
goods.removeClass('novisible');
loading.hide();
}
return;
}
// 最后商品数量不足一行,截掉
res.length = res.length - (res.length % rowNum);
if (cloneitem) { // 可复制item
var cnt = isNaN(Number(cloneitem)) ? res.length : Number(cloneitem);
for (let indx = 0; indx < cnt; indx++) {
let data = _getProductData(res); // 获取商品数据
if (indx === 0) {
let gel = $(goods[0]);
let nel = _replaceData(gel, cond, data, wh, fp);
if (nel) {
nel.removeClass('novisible');
} else {
gel.remove();
}
} else {
let nel = _replaceData($(goods[0]).clone(), cond, data, wh, fp);
if (nel) {
nel.removeClass('novisible');
nel.appendTo(el);
}
}
}
} else {
for (let i = 1; i < res.length; i++) {
goods.last().after(goods.clone());
}
let $newGoods = el.find('.feature-product-info');
$newGoods.each(function(indx, perProduct) {
let $perProduct = $(perProduct);
_replaceData($perProduct, cond, _getProductData(res), wh, fp);
});
$newGoods.removeClass('novisible');
loading.hide();
}
lazyLoad($('.product-source img.lazy'));
}, function(){
if (cloneitem) {
$(goods[0]).remove();
} else {
goods.removeClass('novisible');
loading.hide();
}
});
};
let _abTest = function() {
let mkt_code = user.getMktCode();
// cover覆盖mkt_code
utils.sParamByIframe('callback=jQueryMktCode&cover=1&mkt_code=' + mkt_code +'&expires=' + (7 * 24 * 60 * 60 * 1000));
// 上报曝光事件
let actionUrl = [];
$('a').each(function(){
let href = $(this).attr('href');
if (href && !/^#.*$/.test(href) && !/^javascript.*$/i.test(href)) {
actionUrl.push(href);
}
});
var cnt = 0;
var timer = setInterval(function() {
cnt++;
if (cnt > 3) {
clearInterval(timer);
return;
}
if (window._yas && window._yas.sendAppLogs && window.appBaseLogs) {
clearInterval(timer);
window._yas.sendAppLogs({
appop: 'YB_H5_PAGE_AB_OPEN_L',
param: JSON.stringify({
C_ID: utils.queryString().yh_channel || 1,
PAGE_URL: window.originUrl,
PAGE_NAME: decodeURI(window.qs.title || document.title),
ACTION_URL: actionUrl,
CROWD_CODE: mkt_code + ''
})
}, true);
$('a').click(function() {
let furl = $(this).attr('href');
if (furl && !/^#.*$/.test(furl) && !/^javascript.*$/i.test(furl)) {
window._yas.sendAppLogs({
appop: 'YB_H5_PAGE_AB_FLR_C',
param: JSON.stringify({
C_ID: utils.queryString().yh_channel || 1,
PAGE_URL: window.originUrl,
PAGE_NAME: decodeURI(window.qs.title || document.title),
F_URL: furl,
CROWD_CODE: mkt_code + ''
})
}, true);
}
});
}
}, 1000);
};
let _getProduct = function(param) {
$('.product-source').each(function(i, el){
el = $(el);
let cond = el.attr('condition');
if (!cond) {
return;
}
cond = JSON.parse(cond);
let yh_channel = utils.queryString().yh_channel;
if (cond.abtest) {
abTestFlag = true;
}
if (yh_channel) {
cond.yh_channel = yh_channel;
}
if (i > 3) {
setTimeout(function(){
_jsonp(el, param, cond);
}, 300);
} else {
_jsonp(el, param, cond);
}
});
abTestFlag && _abTest();
};
export default {
init(uid) {
if (!uid && utils.isApp()) {
// document.addEventListener('deviceready', function() {
// window.yohoInterface.triggerEvent(function(data) {
// // 获取个性话数据
// _getProduct({
// uid: data.uid,
// udid: data.udid
// });
// }, function() {}, {
// method: 'get.analyticAppData'
// });
// }, false);
_getProduct({
uid: '',
udid: utils.queryString().udid || ''
});
} else {
// 获取个性话数据
_getProduct({
uid: uid,
udid: cookies.cookie('_yasvd')
});
}
}
};
... ...
import $ from 'jquery';
/* eslint-disable */
// Noop
function noop() {
}
// Generic callback
function genericCallback( data ) {
lastValue = [ data ];
}
// Call if defined
function callIfDefined( method , object , parameters ) {
return method && method.apply && method.apply( object.context || object , parameters );
}
// Give joining character given url
function qMarkOrAmp( url ) {
return /\?/ .test( url ) ? "&" : "?";
}
var // String constants (for better minification)
STR_ASYNC = "async",
STR_CHARSET = "charset",
STR_EMPTY = "",
STR_ERROR = "error",
STR_INSERT_BEFORE = "insertBefore",
STR_JQUERY_JSONP = "_jqjsp",
STR_ON = "on",
STR_ON_CLICK = STR_ON + "click",
STR_ON_ERROR = STR_ON + STR_ERROR,
STR_ON_LOAD = STR_ON + "load",
STR_ON_READY_STATE_CHANGE = STR_ON + "readystatechange",
STR_READY_STATE = "readyState",
STR_REMOVE_CHILD = "removeChild",
STR_SCRIPT_TAG = "<script>",
STR_SUCCESS = "success",
STR_TIMEOUT = "timeout",
// Window
win = window,
// Deferred
Deferred = $.Deferred,
// Head element
head = $( "head" )[ 0 ] || document.documentElement,
// Page cache
pageCache = {},
// Counter
count = 0,
// Last returned value
lastValue,
// ###################### DEFAULT OPTIONS ##
xOptionsDefaults = {
//beforeSend: undefined,
//cache: false,
callback: STR_JQUERY_JSONP,
//callbackParameter: undefined,
//charset: undefined,
//complete: undefined,
//context: undefined,
//data: "",
//dataFilter: undefined,
//error: undefined,
//pageCache: false,
//success: undefined,
//timeout: 0,
//traditional: false,
url: location.href
},
// opera demands sniffing :/
opera = win.opera,
// IE < 10
oldIE = !!$( "<div>" ).html( "<!--[if IE]><i><![endif]-->" ).find("i").length;
// ###################### MAIN FUNCTION ##
function jsonp( xOptions ) {
// Build data with default
xOptions = $.extend( {} , xOptionsDefaults , xOptions );
// References to xOptions members (for better minification)
var successCallback = xOptions.success,
errorCallback = xOptions.error,
completeCallback = xOptions.complete,
dataFilter = xOptions.dataFilter,
callbackParameter = xOptions.callbackParameter,
successCallbackName = xOptions.callback,
cacheFlag = xOptions.cache,
pageCacheFlag = xOptions.pageCache,
charset = xOptions.charset,
url = xOptions.url,
data = xOptions.data,
timeout = xOptions.timeout,
pageCached,
// Abort/done flag
done = 0,
// Life-cycle functions
cleanUp = noop,
// Support vars
supportOnload,
supportOnreadystatechange,
// Request execution vars
firstChild,
script,
scriptAfter,
timeoutTimer;
// If we have Deferreds:
// - substitute callbacks
// - promote xOptions to a promise
Deferred && Deferred(function( defer ) {
defer.done( successCallback ).fail( errorCallback );
successCallback = defer.resolve;
errorCallback = defer.reject;
}).promise( xOptions );
// Create the abort method
xOptions.abort = function() {
!( done++ ) && cleanUp();
};
// Call beforeSend if provided (early abort if false returned)
if ( callIfDefined( xOptions.beforeSend , xOptions , [ xOptions ] ) === !1 || done ) {
return xOptions;
}
// Control entries
url = url || STR_EMPTY;
data = data ? ( (typeof data) == "string" ? data : $.param( data , xOptions.traditional ) ) : STR_EMPTY;
// Build final url
url += data ? ( qMarkOrAmp( url ) + data ) : STR_EMPTY;
// Add callback parameter if provided as option
callbackParameter && ( url += qMarkOrAmp( url ) + encodeURIComponent( callbackParameter ) + "=?" );
// Add anticache parameter if needed
!cacheFlag && !pageCacheFlag && ( url += qMarkOrAmp( url ) + "_" + ( new Date() ).getTime() + "=" );
// Replace last ? by callback parameter
url = url.replace( /=\?(&|$)/ , "=" + successCallbackName + "$1" );
// Success notifier
function notifySuccess( json ) {
if ( !( done++ ) ) {
cleanUp();
// Pagecache if needed
pageCacheFlag && ( pageCache [ url ] = { s: [ json ] } );
// Apply the data filter if provided
dataFilter && ( json = dataFilter.apply( xOptions , [ json ] ) );
// Call success then complete
callIfDefined( successCallback , xOptions , [ json , STR_SUCCESS, xOptions ] );
callIfDefined( completeCallback , xOptions , [ xOptions , STR_SUCCESS ] );
}
}
// Error notifier
function notifyError( type ) {
if ( !( done++ ) ) {
// Clean up
cleanUp();
// If pure error (not timeout), cache if needed
pageCacheFlag && type != STR_TIMEOUT && ( pageCache[ url ] = type );
// Call error then complete
callIfDefined( errorCallback , xOptions , [ xOptions , type ] );
callIfDefined( completeCallback , xOptions , [ xOptions , type ] );
}
}
// Check page cache
if ( pageCacheFlag && ( pageCached = pageCache[ url ] ) ) {
pageCached.s ? notifySuccess( pageCached.s[ 0 ] ) : notifyError( pageCached );
} else {
// Install the generic callback
// (BEWARE: global namespace pollution ahoy)
win[ successCallbackName ] = genericCallback;
// Create the script tag
script = $( STR_SCRIPT_TAG )[ 0 ];
script.id = STR_JQUERY_JSONP + count++;
// Set charset if provided
if ( charset ) {
script[ STR_CHARSET ] = charset;
}
opera && opera.version() < 11.60 ?
// onerror is not supported: do not set as async and assume in-order execution.
// Add a trailing script to emulate the event
( ( scriptAfter = $( STR_SCRIPT_TAG )[ 0 ] ).text = "document.getElementById('" + script.id + "')." + STR_ON_ERROR + "()" )
:
// onerror is supported: set the script as async to avoid requests blocking each others
( script[ STR_ASYNC ] = STR_ASYNC )
;
// Internet Explorer: event/htmlFor trick
if ( oldIE ) {
script.htmlFor = script.id;
script.event = STR_ON_CLICK;
}
// Attached event handlers
script[ STR_ON_LOAD ] = script[ STR_ON_ERROR ] = script[ STR_ON_READY_STATE_CHANGE ] = function ( result ) {
// Test readyState if it exists
if ( !script[ STR_READY_STATE ] || !/i/.test( script[ STR_READY_STATE ] ) ) {
try {
script[ STR_ON_CLICK ] && script[ STR_ON_CLICK ]();
} catch(_) {
}
result = lastValue;
lastValue = 0;
result ? notifySuccess( result[ 0 ] ) : notifyError( STR_ERROR );
}
};
// Set source
script.src = url;
// Re-declare cleanUp function
cleanUp = function( i ) {
timeoutTimer && clearTimeout( timeoutTimer );
script[ STR_ON_READY_STATE_CHANGE ] = script[ STR_ON_LOAD ] = script[ STR_ON_ERROR ] = null;
head[ STR_REMOVE_CHILD ]( script );
scriptAfter && head[ STR_REMOVE_CHILD ]( scriptAfter );
};
// Append main script
head[ STR_INSERT_BEFORE ]( script , ( firstChild = head.firstChild ) );
// Append trailing script if needed
scriptAfter && head[ STR_INSERT_BEFORE ]( scriptAfter , firstChild );
// If a timeout is needed, install it
timeoutTimer = timeout > 0 && setTimeout( function() {
notifyError( STR_TIMEOUT );
} , timeout );
}
return xOptions;
}
// ###################### SETUP FUNCTION ##
jsonp.setup = function( xOptions ) {
$.extend( xOptionsDefaults , xOptions );
};
// ###################### INSTALL in jQuery ##
$.jsonp = jsonp;
export default jsonp;
/* eslint-disable */
\ No newline at end of file
... ...
// app.js
import $ from 'jquery';
import user from './user';
import utils from './utils';
import share from './share';
import openapp from './openapp';
import promotion from './promotion';
import individuation from './individuation';
import captcha from './captcha';
$(function() {
openapp.init();
user.init().then(uid => {
individuation.init(uid); // 个性化推荐
captcha.init().then(() => {
promotion.init(uid); // 促销
});
user.auth(); // 权限验证
share.init(); // 分享
utils.init();
});
});
export default {
auth: user.auth,
favout: user.favout,
getMktCode: function(){
return user.getMktCode();
},
getUid: function(){
return user.uid;
}
};
... ...
import $ from 'jquery';
import imgSrcHandle from './img-src-handle';
import 'jquery-lazyload';
/**
* 图片链接预处理后使用原生 lazyload
*/
const rawLazyload = (selector, options) => {
let $imgs;
let params = {
threshold: 700 * 2 // 一页大概700 ,提前加载三、四页
};
if (selector instanceof $) {
$imgs = selector;
} else {
$imgs = $(selector).find('img.lazy');
}
$.extend(params, options);
const imgsProcess = () => {
$imgs.each((index, elem) => {
$(elem).attr('data-original', imgSrcHandle($(elem).data('original'), options));
});
$imgs.lazyload(params);
};
if (typeof window.supportWebp !== 'undefined') {
imgsProcess();
} else {
$(document).on('supportWebp', imgsProcess);
}
};
export default rawLazyload;
... ...
/**
* 移动端尝试打开 app
*/
import utils from './utils';
import cookies from './cookies';
const channelMap = {
'baidu.com': 100000000000055,
'so.com': 100000000000049,
'sogou.com': 100000000000053,
'bing.com': 100000000000057,
'm.sm.cn': 100000000000059,
'google.com': 100000000000061
};
const getMktcBySeo = () => {
var mktc,
rf = document.referrer;
for (var domain in channelMap) {
if (rf.indexOf(domain) > -1) {
mktc = channelMap[domain];
break;
}
}
return mktc;
};
const getAppPath = () => {
let qs = utils.queryString();
let ct = qs.mkt_code || qs.union_type || cookies.cookie('unionTypeYas') || getMktcBySeo() || '100000000000349';
delete qs.openapp; // 防止重复打开
let shareParams = qs.share_id ? '"share":"/operations/api/v5/webshare/getShare","shareparam":{"share_id":"' + qs.share_id + '"},' : '',
appPath = 'yohobuy://yohobuy.com/goapp?ct='+ ct +'&openby:yohobuy={"action":"go.h5",' + shareParams +
'"params":{"islogin":"N","url":"http://feature.yoho.cn' + location.pathname + '","param":' + JSON.stringify(qs) + '}}';
return appPath;
};
export default {
init() {
if (utils.queryString().openapp) {
let u = navigator.userAgent.toLowerCase();
let isiOS = u.indexOf('os') > -1 || u.indexOf('iphone') > -1 || u.indexOf('mac') > -1 || u.indexOf('ipad') > -1;
let appPath = getAppPath();
if (isiOS) {
window.location.href = appPath;
} else {
let ifr = document.createElement('iframe');
ifr.src = appPath;
ifr.style.display = 'none';
document.body.appendChild(ifr);
}
}
}
};
\ No newline at end of file
... ...
/* global wx */
// 1. 优惠券领取
// 2. YOHO币领取
import $ from 'jquery';
import utils from './utils';
import user from './user';
import cookies from './cookies';
import jsonp from './jsonp';
import captcha from './captcha';
const miniAppEntrance = '/pages/common/webback';
let _getMiniappLoginUrl = function(url) {
if (url.indexOf('openby:yohobuy') > 0) {
url = url.substring(0, url.indexOf('openby:yohobuy'));
}
let h5Url = `http://m.yohobuy.com/signin.html?openby:yohobuy={"action":"go.miniapp_login","params":{"h5back":"${encodeURIComponent(url)}"}}`;
return `${miniAppEntrance}?url=${encodeURIComponent(h5Url)}`;
};
const gotoLogin = function() {
if (window.__wxjs_environment === 'miniprogram' && typeof wx !== 'undefined' && wx.miniProgram) {
wx.miniProgram.navigateTo({
url: _getMiniappLoginUrl(location.href)
});
return;
}
if ($('#intimacy-link').length <= 0) {
$('body').append('<a href=\'' + user.noLoginUrl() + '\' style="display:none;" id="intimacy-link"><span class="intimacy-link"></span></a>');
}
$('.intimacy-link').click();
};
let isSendCoin = false;
let _getCoin = function(data) {
data.app = utils.queryString();
data.app.uid = data.uid;
if (isSendCoin) {
return;
}
isSendCoin = true;
jsonp({
url: '//m.yohobuy.com/activity/coin/sendCoin?callback=?',
timeout: 5000, // 5s
data: data
}).then(function(res) {
isSendCoin = false;
if (res.code === 200 && res.data) {
if (res.data.code === 200) {
utils.showCoinTip({
title: '恭喜您,成功领取有货币!',
content: '特殊情况下到账有延时<br>请耐心等待',
close: true,
coin: true,
img: res.data.popupImg
});
} else if (res.data.code === 501) {
utils.showCoinTip({
title: '领取失败',
content: '哎呀,你来的有点早,活动还没开始呢<br/>稍后再来哦',
close: true,
img: res.data.popupImg
});
} else if (res.data.code === 502) {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,活动已结束了,下次要快哟~~',
close: true,
img: res.data.popupImg
});
} else if (res.data.code === 503) {
utils.showCoinTip({
title: '已经领取',
content: '贪心会长胖,你已经领取过了啦~~',
close: true,
img: res.data.popupImg
});
} else if (res.data.code === 504) {
utils.showCoinTip({
title: '领取失败',
content: '哎呀,你来晚了,有货币已经领完了,<br/>下次早点来哦',
close: true,
img: res.data.popupImg
});
} else if (res.data.msg) {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,系统错误,有货君正奋力解决中...请稍后再来',
close: true,
img: res.data.popupImg
});
}
} else if (res.code === 401 && res.auth) {
utils.showCoinTip({
title: '领取失败',
content: '登录信息失效,请重新登录',
close: true,
img: res.data && res.data.popupImg
});
setTimeout(() => {
gotoLogin();
}, 1000);
} else if (res.message) {
utils.showCoinTip({
title: '领取失败',
content: '抱歉,系统错误,有货君正奋力解决中...请稍后再来',
close: true,
img: res.data && res.data.popupImg
});
}
}, function(){
isSendCoin = false;
utils.showCoinTip({
title: '领取失败',
content: '抱歉,系统错误,有货君正奋力解决中...请稍后再来',
close: true
});
});
};
let isSendCoupon = false;
let _getCoupon = function(data){
const qs = utils.queryString();
data.app = {
uid: qs.uid || cookies.cookie('app_uid'),
app_version: qs.app_version || cookies.cookie('app_version'),
client_type: qs.client_type || cookies.cookie('app_client_type'),
session_key: qs.session_key || cookies.cookie('app_session_key')
};
if (isSendCoupon) {
return;
}
let options = {
bottom: '48%',
paddingX: 20,
paddingY: 20,
radius: 6
};
isSendCoupon = true;
jsonp({
url: '//m.yohobuy.com/activity/feature/couponSend?callback=?',
timeout: 5000, // 5s
data: data
}).then(function(res) {
isSendCoupon = false;
if (res.code === 200) {
utils.toast('领取成功', options);
let $img = $(`#${data.token}`);
if($img) {
let statusImgs = $img.data('status-imgs');
if(statusImgs && statusImgs.received) {
$img.attr('src', statusImgs.received);
}
}
} else if (res.code === 401) {
if(res.auth) {
utils.toast('登录信息失效,请重新登录', options);
setTimeout(() => {
gotoLogin();
}, 1000);
}
if(res.message === '优惠券已经领取') {
utils.toast(res.message, options);
let $img = $(`#${data.token}`);
if($img) {
let statusImgs = $img.data('status-imgs');
if(statusImgs && statusImgs.received) {
$img.attr('src', statusImgs.received);
}
}
}
} else if (res.message) {
utils.toast(res.message, options);
} else {
utils.toast('领取失败', options);
}
}, function(){
isSendCoupon = false;
utils.toast('领取失败', options);
});
};
let isCheckCoupon = false;
let _getCouponCheck = function(data) {
const qs = utils.queryString();
data.app = {
uid: qs.uid || cookies.cookie('app_uid'),
app_version: qs.app_version || cookies.cookie('app_version'),
client_type: qs.client_type || cookies.cookie('app_client_type'),
session_key: qs.session_key || cookies.cookie('app_session_key')
};
if (isCheckCoupon) {
return;
}
isCheckCoupon = true;
return jsonp({
url: '//m.yohobuy.com/activity/feature/couponCheck?callback=?',
timeout: 5000, // 5s
data: data
}).then(function(res) {
isCheckCoupon = false;
return res;
}, function(){
isSendCoupon = false;
return {
code: 400,
message: '出错了~'
}
});
};
let _getCaptchaCoupon = function(data) {
let options = {
bottom: '48%',
paddingX: 20,
paddingY: 20,
radius: 6
};
_getCouponCheck(data).then(result => {
if (result.code !== 200) {
return utils.toast(result.message, options);
}
if (result.data.checkRequired) {
let captchaInstance = captcha.getInstance((result) => {
if (result.ret !== 0) {
return utils.toast('出错了~', options);
}
_getCoupon({
token: data.token,
coupontype: data.couponType,
uid: data.uid,
ticket: result.ticket,
randstr: result.randstr
});
});
captchaInstance.show();
} else {
_getCoupon({
token: data.token,
coupontype: data.couponType,
uid: data.uid,
});
}
})
}
let isSendRedEnevlope = false;
let _getRedEnevlope = function(data){
data.app = utils.queryString();
data.app.uid = data.app.uid || cookies.cookie('app_uid');
data.app.app_version = data.app.app_version || cookies.cookie('app_version');
data.app.client_type = data.app.client_type || cookies.cookie('app_client_type');
data.app.session_key = data.app.session_key || cookies.cookie('app_session_key');
if (isSendRedEnevlope) {
return;
}
isSendRedEnevlope = true;
jsonp({
url: '//m.yohobuy.com/activity/feature/redenvelope?callback=?',
timeout: 5000, // 5s
data: data
}).then(function(res) {
isSendRedEnevlope = false;
if (res.code === 200 && res.data) {
if (res.data.addMsg === '领取成功') {
utils.showTip({
title: '领取成功',
content: `成功领取${res.data.amount}元红包!`,
close: true
});
} else {
utils.showTip({
title: '已领取过',
content: '今日领取机会已用完',
close: true
});
}
} else if (res.code === 401 && res.auth) {
utils.showTip({
title: '领取失败',
content: '登录信息失效,请重新登录',
close: false
});
setTimeout(() => {
gotoLogin();
}, 1000);
} else if (res.message) {
utils.showTip({
title: '领取失败',
content: res.message,
close: false
});
} else {
utils.showTip({
title: '领取失败',
content: '请刷新重新领取,若多次领取失败,<br>可能网络故障或活动已结束。',
close: false
});
}
}, function(){
isSendRedEnevlope = false;
utils.showTip({
title: '领取失败<br>请刷新重新领取',
content: '如多次领取失败,请联系客服人员<br>带来不便敬请谅解',
close: false
});
});
};
let _initCoin = function(uid){
if (uid) {
let cointoken = cookies.cookie('yoho-coin-token');
if (cointoken) {
_getCoin({
token: cointoken,
uid: uid
});
cookies.setCookie('yoho-coin-token', '');
}
}
$('body').on('click', '.yoho-coin', function() {
let token = $(this).data('token');
if (user.uid) {
_getCoin({
token: token,
uid: user.uid
});
} else {
cookies.setCookie('yoho-coin-token', token);
gotoLogin();
return;
}
});
};
let _initCoupon = function(uid) {
if (uid) {
let token = cookies.cookie('yoho-coupon-token');
let couponType = cookies.cookie('yoho-coupon-type');
if (token) {
_getCaptchaCoupon({
token,
couponType,
uid
});
cookies.setCookie('yoho-coupon-token', '');
cookies.setCookie('yoho-coupon-type', '');
}
}
$('body').on('click', '.yoho-conpon', function() {
let token = $(this).data('token');
let type = $(this).data('type');
if (user.uid) {
_getCaptchaCoupon({
token,
couponType: type,
uid: user.uid
});
} else {
cookies.setCookie('yoho-coupon-token', token);
cookies.setCookie('yoho-coupon-type', type);
gotoLogin();
return;
}
});
};
let _initRedEnvelope = function(uid) {
if (uid) {
let redevenlopetoken = cookies.cookie('yoho-redenvelope-token');
if (redevenlopetoken) {
_getRedEnevlope({
token: redevenlopetoken,
uid: uid
});
cookies.setCookie('yoho-redenvelope-token', '');
}
}
$('body').on('click', '.yoho-redenvelope', function() {
let token = $(this).data('token');
if (user.uid) {
_getRedEnevlope({
token: token,
uid: user.uid
});
} else {
cookies.setCookie('yoho-redenvelope-token', token);
gotoLogin();
return;
}
});
};
export default {
init(uid) {
_initCoin(uid); // 初始化有货币
_initCoupon(uid); // 初始化优惠券
_initRedEnvelope(uid); // 初始化红包
}
};
... ...
import $ from 'jquery';
import utils from './utils';
import jsonp from './jsonp';
let jsApiList = [
'checkJsApi',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone'
];
let shareData = {
title: document.title,
link: location.href,
desc: 'YOHO!BUY',
imgUrl: 'http://static.yohobuy.com/m/v1/img/touch/apple-touch-icon-144x144-precomposed-new.png'
};
let _getShareDataById = function() {
let shareId = utils.queryString().share_id;
if (shareId) {
return jsonp({
url: '//m.yohobuy.com/activity/share?callback=?',
data: {
shareId: shareId
}
}).then(function(res) {
if (res && res.code === 200 && res.data) {
shareData.title = res.data.title;
shareData.link = res.data.link || location.href;
shareData.desc = res.data.content || res.data.title;
shareData.imgUrl = res.data.pic;
}
return $.Deferred().resolve();
}, function(){
return $.Deferred().resolve();
});
} else {
let shareTitle = $('#shareTitle').val();
let shareImg = $('#shareImg').val();
let shareDesc = $('#shareDesc').val();
let shareLink = $('#shareLink').val();
shareData.title = shareTitle ? shareTitle : shareData.title;
shareData.imgUrl = shareImg ? shareImg : shareData.imgUrl;
shareData.desc = shareDesc ? shareDesc : shareData.desc;
shareData.link = shareLink ? shareLink : shareData.link;
return $.Deferred().resolve();
}
};
export default {
init() {
if (/QQ/i.test(navigator.userAgent)) {
$.ajax({
url: '//qzonestyle.gtimg.cn/qzone/qzact/common/share/share.js',
dataType: 'script',
cache: true,
success: function() {
_getShareDataById().then(function(){
window.setShareInfo && window.setShareInfo({
title: shareData.title,
summary: shareData.desc,
pic: shareData.imgUrl,
url: shareData.link
});
});
}
});
}
if (/MicroMessenger/i.test(navigator.userAgent)) {
$.ajax({
url: '//res.wx.qq.com/open/js/jweixin-1.3.2.js',
dataType: 'script',
cache: true,
success: function() {
jsonp({
url: '//m.yohobuy.com/activity/wechat/share?callback=?',
data: {
url: location.href
}
}).then(function(res) {
if (window.wx) {
window.wx.config({
debug: false,
appId: res.appId,
timestamp: res.timestamp,
nonceStr: res.nonceStr,
signature: res.signature,
jsApiList: jsApiList
});
_getShareDataById().then(function() {
window.wx.ready(function() {
window.wx.onMenuShareAppMessage(shareData);
window.wx.onMenuShareTimeline(shareData);
window.wx.onMenuShareQQ(shareData);
window.wx.onMenuShareWeibo(shareData);
window.wx.onMenuShareQZone(shareData);
});
});
}
});
}
});
}
}
};
... ...
import $ from 'jquery';
import jsonp from './jsonp';
import utils from './utils';
import cookies from './cookies';
let _noLoginUrl = function() {
let referrer = location.href.split('?')[0];
let domain = 'm.yohobuy.com';
let url = utils.urlParse(referrer);
if (url.host !== 'm.yohobuy.com' && url.host !== 'activity.yoho.cn' && url.host !== 'feature.yoho.cn') {
domain = 'www.yohobuy.com';
}
if (/AliApp/i.test(navigator.userAgent)) {
return `${location.protocol}//xianyu.yohobuy.com/xianyu/passport/login/taobao`;
}
return `//${domain}/signin.html?refer=` + encodeURIComponent(location.href) + '&openby:yohobuy={"action":"go.weblogin","params":{"jumpurl":{"url":"' + referrer.replace(/\//g, '\\/') + '","param":{"from":"app"}},"requesturl":{"url":"","param":{}},"priority":"N"}}';
};
export default {
uid: '',
noLoginUrl: _noLoginUrl,
init() {
let _this = this;
return jsonp({
url: '//m.yohobuy.com/passport/login/user?callback=?'
}).then(function(res){
if (res.code === 200) {
_this.uid = Number(res.data) || 0;
}
if (!_this.uid && utils.isApp()) {
_this.uid = Number(utils.queryString().uid) || 0;
}
if (res.unionType) {
cookies.setCookie('unionTypeYas', res.unionType, {
path: '/'
});
}
return $.Deferred().resolve(_this.uid);
}, function() {
utils.isApp() && (_this.uid = Number(utils.queryString().uid) || 0);
return $.Deferred().resolve(_this.uid);
});
},
auth() {
if (!this.uid) {
let noLoginUrl = _noLoginUrl();
$('a.auth').attr('href', noLoginUrl);
}
},
favout(skn) {
if (!skn || !this.uid) {
return;
}
jsonp({
url: `//service.yoho.cn/activity/favorite/addFavorite?productSkn=${skn}&uid=${this.uid}&callback=?`,
}).then(function(res) {
if (res.code === 200) {
utils.showTip({
content: '恭喜您,收藏成功',
close: true
});
} else {
utils.showTip({
content: res.message,
close: true
});
}
}, function(){
utils.showTip({
title: '收藏失败<br>请刷新重新领取',
content: '如多次收藏失败,请联系客服人员<br>带来不便敬请谅解',
close: false
});
});
},
getMktCode() {
let mkt_code;
if (this.uid) {
if (Number(this.uid) % 1024 >= 512) {
mkt_code = 100000000000195; // 默认的值
} else {
mkt_code = 100000000000193; // 个性化,动态接口数据
}
} else {
mkt_code = 100000000000197; // 访客接口数据
}
return mkt_code;
}
};
... ...
import tip from '../css/featuretip.css'; //eslint-disable-line
import cointip from '../css/featuretip-coin.css'; //eslint-disable-line
import $ from 'jquery';
const isMobile = {
Android() {
return navigator.userAgent.match(/Android/i) ? true : false;
},
BlackBerry() {
return navigator.userAgent.match(/BlackBerry/i) ? true : false;
},
iOS() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i) ? true : false;
},
Windows() {
return navigator.userAgent.match(/IEMobile/i) ? true : false;
},
any() {
return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Windows());
}
};
const mycurrency = isMobile.any() ? '//m.yohobuy.com/home/mycurrency' : '//www.yohobuy.com/home/currency';
const $tipTmpl = $('<div class="featuretip tip-wrap"><div class="tip"><div class="title"></div><div class="content"></div><a class="button" href="">返回</a></div></div>'); // eslint-disable-line
const $cointipTmpl = $('<div class="feature-coin tip-wrap"><div class="tip"><div class="tip-close">&times;</div><div class="title"></div><div class="content"></div><div class="bottom-button"><a class="button" href="">去逛逛</a><a class="coin" href=\'' + mycurrency + '?openby:yohobuy={"action":"go.mine"}\'>查看有货币</a></div></div></div>'); // eslint-disable-line
const $toastTmpl = $('<div class="feature-toast feature-toast-wrap"><div class="feature-toast-content"></div></div>');
let _queryString = function() {
if (!window._jssdkQS) {
let vars = {},
hash,
i,
hashes = window.location.search.slice(1).split('&');
for (i = 0; i < hashes.length; i++) {
hash = hashes[i].split('=');
vars[hash[0]] = hash[1];
}
window._jssdkQS = vars;
}
return $.extend({}, window._jssdkQS);
};
let _urlParse = function(url) {
var parser = document.createElement('a');
parser.href = url;
return parser;
};
let _sParamByIframe = function() {
let paramsObj = _queryString();
let queryArray = [];
let queryString = '?';
delete paramsObj['uid'];
delete paramsObj['app_version'];
delete paramsObj['client_type'];
delete paramsObj['session_key'];
delete paramsObj['client_secret'];
for(let i in paramsObj) {
queryArray.push(i + '=' + paramsObj[i]);
}
if (!paramsObj['expires']) {
queryArray.push('expires=' + (7 * 24 * 60 * 60 * 1000));
}
queryArray.push('callback=jQueryMktCode');
queryString += queryArray.join('&');
$.getScript('//m.yohobuy.com/activity/wechat/1111' + queryString, function(){});
// $('<iframe style="display:none;" src="//m.yohobuy.com/activity/wechat/1111' + queryString + '"></iframe>').prependTo('body');
};
let _bindEvent = function() {
let $body = $('body');
$body.on('click', '.feature-coin .close,.feature-coin .tip-close', function(e) {
$cointipTmpl.fadeOut();
e.preventDefault();
});
$body.on('click', '.feature-coin.tip-wrap', function(e) {
if ('feature-coin tip-wrap' === e.target.className) {
$cointipTmpl.fadeOut();
e.preventDefault();
}
});
$body.on('click', '.featuretip .close', function(e) {
$tipTmpl.fadeOut();
e.preventDefault();
});
$body.on('click', '.featuretip .refresh', function() {
location.reload();
});
$body.on('click', '.featuretip.tip-wrap', function(e) {
if ('featuretip tip-wrap' === e.target.className) {
$tipTmpl.fadeOut();
e.preventDefault();
}
});
};
export default {
queryString: _queryString,
isMobile: isMobile,
urlParse: _urlParse,
init() {
//发送活动页参数
_sParamByIframe();
// 绑定事件
_bindEvent();
},
isApp() {
let qs = _queryString();
let isApp = !!qs.app_version || (qs.openrefer === 'app' && qs.uid);
return !!isApp;
},
image(url, width, height, mode, quality) {
mode = !isNaN(Number(mode)) ? mode : 2;
url = url || '';
url = url.replace(/{width}/g, width).replace(/{height}/g, height).replace(/{mode}/g, mode);
if (url.indexOf('imageView2') > 0) {
quality = quality || 90;
url += '/q/' + quality;
}
return url.replace('quality/80', 'quality/60').replace('http:', '');
},
sParamByIframe(params) {
$.getScript('//m.yohobuy.com/activity/wechat/1111' + params, function(){});
// $('<iframe style="display:none;" src="//m.yohobuy.com/activity/wechat/1111?' + params + '"></iframe>').prependTo('body');
},
showTip(data) {
data = data || {
title: '',
content: '',
close: true
};
$tipTmpl.find('.title').html(data.title);
$tipTmpl.find('.content').html(data.content);
if (data.close) {
$tipTmpl.find('.button').addClass('close');
} else {
$tipTmpl.find('.button').addClass('refresh').html('刷新');
}
if (data.tipClassName) {
$tipTmpl.find('.tip').addClass(data.tipClassName);
}
$('body').append($tipTmpl);
$tipTmpl.show();
},
showCoinTip(data) {
data = data || {
title: '',
content: '',
close: true
};
$cointipTmpl.find('.title').html(data.title);
$cointipTmpl.find('.content').html(data.content);
if (data.close) {
$cointipTmpl.find('.button').addClass('close');
}
if (data.coin) {
$cointipTmpl.find('.coin').css('display', 'inline-block');
} else {
$cointipTmpl.find('.coin').hide();
}
if (data.img) {
$cointipTmpl.find('.tip').css('background-image', 'url(' + data.img + ')');
}
$('body').append($cointipTmpl);
$cointipTmpl.show();
},
toast(content, options = {}) {
if (typeof content === 'undefined') {
return;
}
let {bottom, paddingX, paddingY, radius, duration} = $.extend({
bottom: '10%',
paddingX: 6,
paddingY: 10,
radius: 3
}, options);
$toastTmpl.css('bottom', bottom);
$toastTmpl.find('.feature-toast-content').html(content).css({
padding: `${paddingY || 6}px ${paddingX || 10}px`,
'border-radius': `${radius}px`
});
if (!this.toastAppended) {
this.toastAppended = true;
$('body').append($toastTmpl);
}
$toastTmpl.show();
this.toastTimer && clearTimeout(this.toastTimer);
this.toastTimer = setTimeout(function() {
$toastTmpl.hide();
}, (duration && duration > 0) ? duration : 2000);
}
};
... ...
import $ from 'jquery';
/**
* 检测浏览器是否支持 webp 图片格式
*/
const checkWebpSupport = (feature) => {
// iOS APP 拦截网络请求,支持 webp
if (/yoho/i.test(navigator.userAgent) && /supportWebp/i.test(navigator.userAgent)) {
window.supportWebp = true;
return;
}
let kTestImages = {
lossy: 'UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA',
/* eslint-disable */
/* lossless: 'UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==',
alpha: 'UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==', // eslint-disable-line
animation: 'UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA' // eslint-disable-line */
/* eslint-enable */
};
let img = new Image();
img.onload = () => {
let result = (img.width > 0) && (img.height > 0);
window.supportWebp = result || false;
$(document).trigger('supportWebp');
};
img.onerror = () => {
window.supportWebp = false;
$(document).trigger('supportWebp');
};
img.src = 'data:image/webp;base64,' + kTestImages[feature];
};
checkWebpSupport('lossy');
... ...
This diff could not be displayed because it is too large.