Authored by 陈峰

Merge branch 'feature/hole' into 'release/3.1'

Feature/hole



See merge request !28
  1 +<template>
  2 + <editor :content="value" @change="change"></editor>
  3 +</template>
  4 +
  5 +<script>
  6 +import xss from 'util/xss';
  7 +
  8 +export default {
  9 + name: 'editor-safe',
  10 + props: ['content'],
  11 + data() {
  12 + return {
  13 + value: this.content
  14 + };
  15 + },
  16 + methods: {
  17 + change(val) {
  18 + let currentVal = val;
  19 +
  20 + val = xss.replaceScript(val);
  21 + this.$emit('change', val);
  22 + if (currentVal !== val) {
  23 + this.value = val;
  24 + this.$Message.error('输入内容有敏感字符,已自动清除');
  25 + }
  26 + }
  27 + }
  28 +};
  29 +</script>
  30 +
  31 +<style>
  32 +
  33 +</style>
1 import Editor from './editor'; 1 import Editor from './editor';
  2 +import EditorSafe from './editor-safe';
2 3
3 -export default Editor; 4 +export {
  5 + Editor,
  6 + EditorSafe
  7 +};
@@ -9,7 +9,7 @@ import LayoutTab from './layout-tab'; @@ -9,7 +9,7 @@ import LayoutTab from './layout-tab';
9 import LayoutFilter from './layout-filter'; 9 import LayoutFilter from './layout-filter';
10 import LayoutPrint from './layout-print'; 10 import LayoutPrint from './layout-print';
11 import ActionGroup from './action-group'; 11 import ActionGroup from './action-group';
12 -import Editor from './editor'; 12 +import {Editor, EditorSafe} from './editor';
13 import FileUpload from './file-upload'; 13 import FileUpload from './file-upload';
14 import DragFileUpload from './drag-file-upload'; 14 import DragFileUpload from './drag-file-upload';
15 import IFrame from './iframe'; 15 import IFrame from './iframe';
@@ -28,6 +28,7 @@ export default { @@ -28,6 +28,7 @@ export default {
28 LayoutPrint, 28 LayoutPrint,
29 ActionGroup, 29 ActionGroup,
30 Editor, 30 Editor,
  31 + EditorSafe,
31 FileUpload, 32 FileUpload,
32 DragFileUpload, 33 DragFileUpload,
33 IFrame, 34 IFrame,
@@ -7,6 +7,7 @@ import Pop from './pop'; @@ -7,6 +7,7 @@ import Pop from './pop';
7 import Radio from './radio'; 7 import Radio from './radio';
8 import Select from './select'; 8 import Select from './select';
9 import Table from './table'; 9 import Table from './table';
  10 +import Input from './input';
10 11
11 export default { 12 export default {
12 Cell, 13 Cell,
@@ -17,5 +18,6 @@ export default { @@ -17,5 +18,6 @@ export default {
17 Pop, 18 Pop,
18 Radio, 19 Radio,
19 Select, 20 Select,
20 - Table 21 + Table,
  22 + Input
21 }; 23 };
  1 +import InputSafe from './input-safe';
  2 +
  3 +export default {
  4 + InputSafe
  5 +};
  1 +<template>
  2 + <Input :value="value" v-bind="$attrs" v-on="$listeners" />
  3 +</template>
  4 +
  5 +<script>
  6 +import xss from 'util/xss';
  7 +
  8 +export default {
  9 + name: 'input-safe',
  10 + props: ['value'],
  11 + created() {
  12 + this.$listeners.input = this.input;
  13 + },
  14 + methods: {
  15 + input(val) {
  16 + if (typeof val === 'string') {
  17 + this.value = xss.replaceIllegal(val);
  18 + } else {
  19 + this.value = val;
  20 + }
  21 + this.$emit('input', this.value);
  22 + if (this.value !== val) {
  23 + this.$Message.error('输入内容有敏感字符,已自动清除');
  24 + }
  25 + }
  26 + }
  27 +};
  28 +</script>
@@ -52,7 +52,7 @@ export default { @@ -52,7 +52,7 @@ export default {
52 return <span>颜色展示名称</span>; 52 return <span>颜色展示名称</span>;
53 } 53 }
54 if (this.isExist(params.index)) { 54 if (this.isExist(params.index)) {
55 - return h('Input', { 55 + return h('input-safe', {
56 props: { 56 props: {
57 value: params.row.factoryGoodsName 57 value: params.row.factoryGoodsName
58 }, 58 },
@@ -109,11 +109,11 @@ export default { @@ -109,11 +109,11 @@ export default {
109 109
110 if (this.isExist(params.index)) { 110 if (this.isExist(params.index)) {
111 return ( 111 return (
112 - <i-input 112 + <input-safe
113 value={params.row.factoryCode} 113 value={params.row.factoryCode}
114 placeholder='请输入...' 114 placeholder='请输入...'
115 onInput={val => (params.row.factoryCode = val)} 115 onInput={val => (params.row.factoryCode = val)}
116 - style={{width: '100%'}}></i-input> 116 + style={{width: '100%'}}></input-safe>
117 ); 117 );
118 } 118 }
119 return null; 119 return null;
@@ -149,7 +149,7 @@ export default { @@ -149,7 +149,7 @@ export default {
149 <div class={{'row-span': true}}> 149 <div class={{'row-span': true}}>
150 <div style={{position: 'relative'}}> 150 <div style={{position: 'relative'}}>
151 <div class={{'size-code-error': size.validate && !size.name}}> 151 <div class={{'size-code-error': size.validate && !size.name}}>
152 - <i-input 152 + <input-safe
153 value={size.name} 153 value={size.name}
154 onInput={val => (size.name = val)} 154 onInput={val => (size.name = val)}
155 disabled={!params.row.operator[i].value} 155 disabled={!params.row.operator[i].value}
@@ -58,7 +58,9 @@ export default { @@ -58,7 +58,9 @@ export default {
58 }; 58 };
59 }, 59 },
60 created() { 60 created() {
61 - this.isCaptcha = this.$cookie.get('_captcha'); 61 + this.isCaptcha = true;
  62 +
  63 + // this.isCaptcha = this.$cookie.get('_captcha');
62 }, 64 },
63 methods: { 65 methods: {
64 handleSubmit(name) { 66 handleSubmit(name) {
@@ -16,15 +16,15 @@ @@ -16,15 +16,15 @@
16 <Form-item label="类目"> <span>{{sortName}}</span> </Form-item> 16 <Form-item label="类目"> <span>{{sortName}}</span> </Form-item>
17 17
18 <Form-item label="商品名称" prop="productName"> 18 <Form-item label="商品名称" prop="productName">
19 - <Input v-model="product.productName" placeholder="请输入..." style="width: 400px;"/> 19 + <input-safe v-model="product.productName" placeholder="请输入..." style="width: 400px;"/>
20 </Form-item> 20 </Form-item>
21 21
22 <Form-item label="商品卖点"> 22 <Form-item label="商品卖点">
23 - <Input v-model="product.phrase" :maxlength="12" placeholder="最多12个字符" style="width: 400px;"/> 23 + <input-safe v-model="product.phrase" :maxlength="12" placeholder="最多12个字符" style="width: 400px;"/>
24 </Form-item> 24 </Form-item>
25 25
26 <Form-item label="商家商品编码" prop="factoryCode"> 26 <Form-item label="商家商品编码" prop="factoryCode">
27 - <Input v-model="product.factoryCode" placeholder="请输入..." style="width: 400px;"/> 27 + <input-safe v-model="product.factoryCode" placeholder="请输入..." style="width: 400px;"/>
28 </Form-item> 28 </Form-item>
29 29
30 <Form-item label="货品年" prop="goodsYears"> 30 <Form-item label="货品年" prop="goodsYears">
@@ -73,11 +73,11 @@ @@ -73,11 +73,11 @@
73 <Row> <div class="create-item-title">商品价格</div> </Row> 73 <Row> <div class="create-item-title">商品价格</div> </Row>
74 74
75 <Form-item label="吊牌价" prop="retailPrice"> 75 <Form-item label="吊牌价" prop="retailPrice">
76 - <Input v-model="product.retailPrice" :number="true" placeholder="请输入..." style="width: 400px;"/> 76 + <input-safe v-model="product.retailPrice" :number="true" placeholder="请输入..." style="width: 400px;"/>
77 </Form-item> 77 </Form-item>
78 78
79 <Form-item label="销售价" prop="salesPrice"> 79 <Form-item label="销售价" prop="salesPrice">
80 - <Input v-model="product.salesPrice" :number="true" placeholder="请输入..." style="width: 400px;"/> 80 + <input-safe v-model="product.salesPrice" :number="true" placeholder="请输入..." style="width: 400px;"/>
81 </Form-item> 81 </Form-item>
82 </Form> 82 </Form>
83 83
@@ -118,7 +118,7 @@ @@ -118,7 +118,7 @@
118 118
119 <Row> 119 <Row>
120 <Col> 120 <Col>
121 - <editor :content="desc" :z-index="2" @change="updateProductDesc"></editor> 121 + <editor-safe :content="desc" :z-index="2" @change="updateProductDesc"></editor-safe>
122 </Col> 122 </Col>
123 </Row> 123 </Row>
124 124
@@ -14,13 +14,13 @@ @@ -14,13 +14,13 @@
14 <span>{{product.smallSortName}}</span> 14 <span>{{product.smallSortName}}</span>
15 </Form-item> 15 </Form-item>
16 <Form-item label="商品名称" prop="productName"> 16 <Form-item label="商品名称" prop="productName">
17 - <Input v-model="product.productName" placeholder="请输入..." /> 17 + <input-safe v-model="product.productName" placeholder="请输入..." />
18 </Form-item> 18 </Form-item>
19 <Form-item label="商品卖点"> 19 <Form-item label="商品卖点">
20 - <Input v-model="product.phrase" :maxlength="12" placeholder="最多12个字符"/> 20 + <input-safe v-model="product.phrase" :maxlength="12" placeholder="最多12个字符"/>
21 </Form-item> 21 </Form-item>
22 <Form-item label="商家商品编码" prop="factoryCode"> 22 <Form-item label="商家商品编码" prop="factoryCode">
23 - <Input v-model="product.factoryCode" placeholder="请输入..." /> 23 + <input-safe v-model="product.factoryCode" placeholder="请输入..." />
24 </Form-item> 24 </Form-item>
25 <Form-item label="货品年"> 25 <Form-item label="货品年">
26 <Date-picker :value="product.goodsYears.toString()" type="year" placeholder="选择年" disabled> 26 <Date-picker :value="product.goodsYears.toString()" type="year" placeholder="选择年" disabled>
@@ -62,10 +62,10 @@ @@ -62,10 +62,10 @@
62 </Form-item> 62 </Form-item>
63 <div class="create-item-title">商品价格</div> 63 <div class="create-item-title">商品价格</div>
64 <Form-item label="吊牌价"> 64 <Form-item label="吊牌价">
65 - <Input v-model="product.retailPrice" disabled placeholder="请输入..." /> 65 + <input-safe v-model="product.retailPrice" disabled placeholder="请输入..." />
66 </Form-item> 66 </Form-item>
67 <Form-item label="销售价"> 67 <Form-item label="销售价">
68 - <Input v-model="product.salesPrice" disabled placeholder="请输入..." /> 68 + <input-safe v-model="product.salesPrice" disabled placeholder="请输入..." />
69 </Form-item> 69 </Form-item>
70 <div class="create-group"> 70 <div class="create-group">
71 <span class="create-group-indicator"></span> 71 <span class="create-group-indicator"></span>
@@ -81,9 +81,9 @@ @@ -81,9 +81,9 @@
81 <div class="create-item-title">商品描述 81 <div class="create-item-title">商品描述
82 <span class="create-group-sub-title">(详情页内容)</span> 82 <span class="create-group-sub-title">(详情页内容)</span>
83 </div> 83 </div>
84 - <editor :content="product.productIntro" 84 + <editor-safe :content="product.productIntro"
85 @change="updateProductDesc" 85 @change="updateProductDesc"
86 - :z-index="2"></editor> 86 + :z-index="2"></editor-safe>
87 <div class="create-item-title">商品属性 87 <div class="create-item-title">商品属性
88 <span class="create-group-sub-title">(请认真选择所列的属性项,所填内容会对商品搜索、智能推荐等功能产生影响,从而影响商品曝光展示)</span> 88 <span class="create-group-sub-title">(请认真选择所列的属性项,所填内容会对商品搜索、智能推荐等功能产生影响,从而影响商品曝光展示)</span>
89 </div> 89 </div>
@@ -3,7 +3,8 @@ export default function() { @@ -3,7 +3,8 @@ export default function() {
3 return { 3 return {
4 showLoading: true, 4 showLoading: true,
5 product: { 5 product: {
6 - seasons: '' 6 + seasons: '',
  7 + productIntro: ''
7 }, 8 },
8 table: { 9 table: {
9 data: [], 10 data: [],
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 8
9 <div style="text-align: center"> 9 <div style="text-align: center">
10 <filter-item :label="'分类名称'"> 10 <filter-item :label="'分类名称'">
11 - <Input v-model="name" @on-enter="submit"/> 11 + <input-safe v-model="name" @on-enter="submit"/>
12 </filter-item> 12 </filter-item>
13 </div> 13 </div>
14 14
@@ -12,8 +12,12 @@ export default function() { @@ -12,8 +12,12 @@ export default function() {
12 }, 12 },
13 { 13 {
14 title: '分类名称', 14 title: '分类名称',
15 - key: 'categoryName',  
16 align: 'center', 15 align: 'center',
  16 + render(h, params) {
  17 + return (
  18 + <span>{params.row.categoryName}</span>
  19 + );
  20 + }
17 }, 21 },
18 { 22 {
19 title: '创建时间', 23 title: '创建时间',
@@ -24,8 +24,8 @@ @@ -24,8 +24,8 @@
24 <em class="upload-img-tip">尺寸要求150px*150px&nbsp;&nbsp;不大于500KB</em> 24 <em class="upload-img-tip">尺寸要求150px*150px&nbsp;&nbsp;不大于500KB</em>
25 </Form-item> 25 </Form-item>
26 <Form-item label="店铺简介:"> 26 <Form-item label="店铺简介:">
27 - <editor :content="shopData.shopIntro" @change="updateData" :z-index="2">  
28 - </editor> 27 + <editor-safe :content="shopData.shopIntro" @change="updateData" :z-index="2">
  28 + </editor-safe>
29 </Form-item> 29 </Form-item>
30 <Form-item label="品牌-供应商:"> 30 <Form-item label="品牌-供应商:">
31 <Table :columns="tableCols" width="700" :data="tableData"></Table> 31 <Table :columns="tableCols" width="700" :data="tableData"></Table>
  1 +export default {
  2 + replaceIllegal: (str) => {
  3 + return str.replace(/<[^<>]+>/g, '');
  4 + },
  5 + replaceScript: (str) => {
  6 + return str.replace(/<\/?script>/g, '').replace(/javascript:/g, '').replace(/src=.*?\/\/.*?\.js('|")?/g, '');
  7 + }
  8 +};
@@ -22,8 +22,8 @@ @@ -22,8 +22,8 @@
22 </div> 22 </div>
23 </Form-item> 23 </Form-item>
24 <Form-item label="简介:" prop="intro"> 24 <Form-item label="简介:" prop="intro">
25 - <editor :content="modelData.intro" @change="editorChange" :z-index="2">  
26 - </editor> 25 + <editor-safe :content="modelData.intro" @change="editorChange" :z-index="2">
  26 + </editor-safe>
27 </Form-item> 27 </Form-item>
28 <Form-item> 28 <Form-item>
29 <Button type="primary" @click="submit">保存</Button> 29 <Button type="primary" @click="submit">保存</Button>
@@ -27,28 +27,29 @@ class CaptchaController extends Context { @@ -27,28 +27,29 @@ class CaptchaController extends Context {
27 return request(`${captcha.verifiedGraphicCode}?imageView2/0/format/jpg/q/70|watermark/2/text/${uuid.v4()}/fontsize/120/dissolve/10`).pipe(res); // eslint-disable-line 27 return request(`${captcha.verifiedGraphicCode}?imageView2/0/format/jpg/q/70|watermark/2/text/${uuid.v4()}/fontsize/120/dissolve/10`).pipe(res); // eslint-disable-line
28 } 28 }
29 check(req, res, next) { 29 check(req, res, next) {
30 - let isCaptcha = req.session.isCaptcha; 30 + // let isCaptcha = req.session.isCaptcha;
31 31
32 - if (isCaptcha) {  
33 - if (req.body.captcha === req.session.captcha) {  
34 - if (new Date().getTime() > req.session.captchaTimeout) {  
35 - return res.json({  
36 - code: 400,  
37 - captcha: true,  
38 - expired: true,  
39 - message: '验证码过期'  
40 - });  
41 - }  
42 - return next();  
43 - } else { 32 + // if (isCaptcha) {
  33 + if (req.body.captcha === req.session.captcha) {
  34 + if (new Date().getTime() > req.session.captchaTimeout) {
44 return res.json({ 35 return res.json({
45 code: 400, 36 code: 400,
46 captcha: true, 37 captcha: true,
47 - message: '验证码错误' 38 + expired: true,
  39 + message: '验证码过期'
48 }); 40 });
49 } 41 }
  42 + return next();
  43 + } else {
  44 + return res.json({
  45 + code: 400,
  46 + captcha: true,
  47 + message: '验证码错误'
  48 + });
50 } 49 }
51 - return next(); 50 +
  51 + // }
  52 + // return next();
52 } 53 }
53 } 54 }
54 55
@@ -46,21 +46,21 @@ module.exports = (req, res, next) => { @@ -46,21 +46,21 @@ module.exports = (req, res, next) => {
46 46
47 if (currentShop) { 47 if (currentShop) {
48 let baseParams = { 48 let baseParams = {
49 - pid: req.session.LOGIN_UID,  
50 - founder: req.session.LOGIN_UID, 49 + pid: req.user.uid,
  50 + founder: req.user.uid,
51 shopsId: currentShop.shopsId, 51 shopsId: currentShop.shopsId,
52 shopId: currentShop.shopsId, 52 shopId: currentShop.shopsId,
53 shop: currentShop.shopsId, 53 shop: currentShop.shopsId,
54 supplierId: currentShop.shopsBrands.length ? _.first(currentShop.shopsBrands).supplierId : 0, 54 supplierId: currentShop.shopsBrands.length ? _.first(currentShop.shopsBrands).supplierId : 0,
55 platform_id: config.platform, 55 platform_id: config.platform,
56 - userId: req.session.LOGIN_UID 56 + userId: req.user.uid
57 }; 57 };
58 let reqParams = Object.assign({ 58 let reqParams = Object.assign({
59 url: apiUrl, 59 url: apiUrl,
60 method: req.method.toLowerCase(), 60 method: req.method.toLowerCase(),
61 headers: { 61 headers: {
62 'x-shop-id': currentShop.shopsId, 62 'x-shop-id': currentShop.shopsId,
63 - 'x-user-id': req.session.LOGIN_UID, 63 + 'x-user-id': req.user.uid,
64 'Content-Type': 'application/json' 64 'Content-Type': 'application/json'
65 } 65 }
66 }); 66 });
@@ -71,7 +71,7 @@ module.exports = (req, res, next) => { @@ -71,7 +71,7 @@ module.exports = (req, res, next) => {
71 } 71 }
72 72
73 if (req.method.toLowerCase() === 'get') { 73 if (req.method.toLowerCase() === 'get') {
74 - reqParams.qs = Object.assign(baseParams, req.query, req.body); 74 + reqParams.qs = Object.assign({}, req.query, req.body, baseParams);
75 } else if (files.length) { 75 } else if (files.length) {
76 let reqFiles = {}; 76 let reqFiles = {};
77 77