Authored by 陈峰

commit

... ... @@ -5,6 +5,9 @@
}]
],
"plugins": [
"transform-vue-jsx"
"transform-runtime",
"transform-vue-jsx",
"transform-async-to-generator",
"transform-object-rest-spread"
]
}
\ No newline at end of file
... ...
src/router.js
src/libs/util.js
src/vendors.js
\ No newline at end of file
node_modules
dist
\ No newline at end of file
... ...
{
"parser": "babel-eslint",
"root": true,
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"env": {
"browser": true
"es6": true,
"browser": true,
"node": true
},
"extends": "eslint:recommended",
"plugins": ["html"],
... ...
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>iView project</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
<link rel="stylesheet" href="/dist/vendors.css">
<link rel="stylesheet" href="/dist/app-home.css">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/dist/vendors.js"></script>
<script type="text/javascript" src="/dist/app-home.js"></script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<title>iView project</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
<link rel="stylesheet" href="/dist/vendors.css">
<link rel="stylesheet" href="/dist/app-sort.css">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/dist/vendors.js"></script>
<script type="text/javascript" src="/dist/app-sort.js"></script>
</body>
</html>
\ No newline at end of file
... ... @@ -17,24 +17,31 @@
"license": "MIT",
"dependencies": {
"axios": "^0.15.3",
"bignumber.js": "^8.0.1",
"clipboard": "^1.5.12",
"dayjs": "^1.7.7",
"iview": "^3.1.5",
"js-cookie": "^2.1.3",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vuex": "^2.2.1"
"vuex": "^2.2.1",
"xlsx": "^0.14.1",
"yoho-qs": "^1.0.1"
},
"devDependencies": {
"autoprefixer-loader": "^3.2.0",
"babel": "^6.23.0",
"babel-core": "^6.23.1",
"babel-eslint": "^10.0.1",
"babel-loader": "^7.1.2",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.12.0",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-plugin-transform-vue-jsx": "^3.7.0",
"babel-preset-es2015": "^6.9.0",
"babel-runtime": "^6.11.6",
"clean-webpack-plugin": "^1.0.0",
"css-loader": "^0.28.7",
"eslint": "^3.12.2",
"eslint-plugin-html": "^1.7.0",
... ...
import util from '@/libs/util';
import iView from 'iview';
import qs from 'qs';
class Api {
constructor() {
}
_get(url, data) {
if (!PRODUCTION) {
data = Object.assign({}, data, {
debug: 'XYZ'
}).catch(this.catch);
_get(url, data, options) {
let params = this._2params(data);
if (!PRODUCTION) { //eslint-disable-line
params.debug = 'XYZ';
}
return util.ajax.get(url, data).then(result => result.data);
return util.ajax.get(url, Object.assign({params}, options)).then(result => result.data).catch(this.catch);
}
_post(url, data, json = false) {
if (!PRODUCTION) {
url += '?debug=XYZ';
}
_post(url, data, json = false, options) {
let params = this._2params(data);
const params = json ? data : this._2params(data);
if (!PRODUCTION) { //eslint-disable-line
url += (url.indexOf('?') >= 0 ? '&' : '?') + 'debug=XYZ';
}
if (!json) {
params = qs.stringify(params);
}
return util.ajax.post(url, params).then(result => {
return util.ajax.post(url, params, options).then(result => {
return result.data;
}).catch(this.catch);
}
... ... @@ -30,18 +33,16 @@ class Api {
catch({message}) {
iView.Message.destroy();
iView.Message.warning(message || '接口错误');
return Promise.resolve()
return Promise.resolve({});
}
_2params(data) {
const params = new URLSearchParams();
for (let i of Object.keys(data)) {
if (typeof data[i] !== 'undefined') {
params.append(i, data[i]);
const params = {};
Object.keys(data).forEach(k => {
if (data[k] || data[k] === 0) {
params[k] = data[k];
}
}
});
return params;
}
}
... ...
import Vue from 'vue';
export default new Vue({
data() {
return {
data() {
return {
};
},
computed: {
};
},
computed: {
},
methods: {
},
methods: {
}
}
});
\ No newline at end of file
... ...
import Layout from './layout'
import Layout from './layout';
export default {
Layout,
}
\ No newline at end of file
};
\ No newline at end of file
... ...
import LayoutContent from './layout-content'
import LayoutFilter from './layout-filter'
import LayoutTable from './layout-table'
import LayoutTools from './layout-tools'
import FilterItem from './filter-item'
import LayoutContent from './layout-content';
import LayoutFilter from './layout-filter';
import LayoutTable from './layout-table';
import LayoutTools from './layout-tools';
import FilterItem from './filter-item';
export default {
... ... @@ -11,4 +11,4 @@ export default {
LayoutTable,
LayoutTools,
FilterItem
}
\ No newline at end of file
};
\ No newline at end of file
... ...
... ... @@ -13,10 +13,10 @@ export default {
name: 'LayoutFilter',
methods: {
onFilter() {
this.$emit('on-filter')
this.$emit('on-filter');
},
onClear() {
this.$emit('on-clear')
this.$emit('on-clear');
}
}
}
... ...
... ... @@ -26,12 +26,12 @@ export default {
return {
current: 1,
pageSize: 10
}
};
},
methods: {
onChange(page) {
this.current = page
this.$emit('on-page-change', page)
this.current = page;
this.$emit('on-page-change', page);
}
}
}
... ... @@ -39,6 +39,8 @@ export default {
<style lang="scss" scoped>
.layout-table {
padding: 10px 0;
.footer {
width: 100%;
display: flex;
... ...
import Env from './env';
let config = {
env: Env
env: Env
};
export default config;
\ No newline at end of file
... ...
export default "development";
\ No newline at end of file
export default 'development';
\ No newline at end of file
... ...
... ... @@ -3,23 +3,23 @@ import iView from 'iview';
import 'iview/dist/styles/iview.css';
import emitter from './mixins/emitter';
import bus from './bus';
import components from './components'
import './statics/base.scss'
import components from './components';
import './statics/base.scss';
Vue.use(iView);
Vue.prototype.$bus = bus;
Object.keys(components).forEach(cm => {
Object.keys(components[cm]).forEach(ck => {
Vue.component(components[cm][ck].name, components[cm][ck])
})
})
Vue.component(components[cm][ck].name, components[cm][ck]);
});
});
Vue.mixin(emitter);
export default (App) => {
return new Vue({
el: '#app',
render: h => h(App)
el: '#app',
render: h => h(App)
});
};
... ...
const resolveBlobData = blobData => {
return new Promise((resolve, reject) => {
if (blobData.type === 'application/msexcel') {
resolve(blobData);
} else if (blobData.type === 'application/json') {
const fr = new FileReader();
fr.onload = function() {
const rs = JSON.parse(this.result);
reject(rs);
};
fr.readAsText(blobData);
} else {
reject();
}
});
};
const downloadBlob = (blob, name) => {
const URL = window.URL || window.webkitURL;
const blobUrl = URL.createObjectURL(blob);
const anchor = document.createElement('a');
if ('download' in anchor) {
anchor.style.visibility = 'hidden';
anchor.href = blobUrl;
anchor.download = name;
document.body.appendChild(anchor);
let evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, true);
anchor.dispatchEvent(evt);
document.body.removeChild(anchor);
} else if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, name);
} else {
location.href = blobUrl;
}
};
const dataURL2Blob = dataUrl => {
let arr = dataUrl.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
let dataStr = atob(arr[1]);
let n = dataStr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = dataStr.charCodeAt(n);
}
return new Blob([u8arr], {type: mime });
};
export default {
resolveBlobData,
downloadBlob,
dataURL2Blob
};
... ...
import axios from 'axios';
import env from '../config/env';
let util = {
};
util.title = function(title) {
title = title ? title + ' - Home' : 'iView project';
window.document.title = title;
title = title ? title + ' - Home' : 'iView project';
window.document.title = title;
};
const ajaxUrl = env === 'development' ?
'/' :
env === 'production' ?
'https://www.url.com' :
'https://debug.url.com';
util.ajax = axios.create({
baseURL: ajaxUrl,
timeout: 30000
timeout: 30000
});
function getQueryString(name) {
let urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name)
let urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
util.getQueryString = getQueryString
util.getQueryString = getQueryString;
export default util;
\ No newline at end of file
... ...
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.name;
this.$children.forEach(child => {
const name = child.$options.name;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
// todo 如果 params 是空数组,接收到的会是 undefined
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
export default {
methods: {
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.name;
methods: {
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.name;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
if (parent) {
name = parent.$options.name;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
\ No newline at end of file
... ...
<template>
<i-modal v-model="visiable" :loading="loading" title="创建/编辑优惠券" @on-ok="onOk" width="600">
<i-form ref="formCoupon" :rules="ruleValidate" :model="formData" :label-width="80">
<i-modal v-model="visiable" :loading="posting" :title="readonly ? '查看优惠券' : '创建/编辑优惠券'" @on-ok="onOk" width="600">
<i-spin v-if="loading"></i-spin>
<i-form v-else ref="formCoupon" :rules="ruleValidate" :model="formData" :label-width="80">
<i-form-item class="form-group" label="基本信息"></i-form-item>
<i-form-item label="Token" v-if="couponToken">
{{couponToken}}
</i-form-item>
<i-form-item label="名称" prop="couponName">
<i-input placeholder="名称建议30字以内" v-model="formData.couponName" style="width: 200px"></i-input>
<i-input placeholder="名称建议30字以内" v-model="formData.couponName" :disabled="readonly" style="width: 200px"></i-input>
</i-form-item>
<i-form-item label="数量" prop="couponNum">
<i-input-number placeholder="数量" v-model="formData.couponNum" style="width: 100px;"></i-input-number>
<i-input-number placeholder="数量" v-model="formData.couponNum" :disabled="readonly" style="width: 100px;"></i-input-number>
</i-form-item>
<i-form-item label="使用次数" prop="useNum">
<i-input placeholder="使用次数" v-model="formData.useNum" disabled style="width: 100px;"></i-input>
</i-form-item>
<i-form-item label="使用期限" prop="time">
<i-date-picker type="datetimerange" v-model="formData.time" placeholder="使用期限" format="yyyy-MM-dd HH:mm" style="width: 250px"></i-date-picker>
<i-date-picker type="datetimerange" v-model="formData.time" :disabled="readonly" placeholder="使用期限" format="yyyy-MM-dd HH:mm" style="width: 250px"></i-date-picker>
</i-form-item>
<i-form-item label="优惠券说明" prop="remark">
<i-input type="textarea" placeholder="优惠券使用条件简介" v-model="formData.remark"></i-input>
<i-input type="textarea" placeholder="优惠券使用条件简介" :disabled="readonly" v-model="formData.remark"></i-input>
</i-form-item>
<i-form-item class="form-group" label="使用条件"></i-form-item>
<i-form-item label="优惠条件" prop="useLimitType" style="display: inline-block; width: 100%">
<i-select style="width: 100px" v-model="formData.useLimitType">
<i-select style="width: 100px" :disabled="readonly" v-model="formData.useLimitType">
<i-option :value="0">无限制</i-option>
<i-option :value="2">金额</i-option>
</i-select>
<div style="display: inline-block" v-if="formData.useLimitType === 2">
&nbsp;
金额满:
<i-input-number style="width: 100px" placeholder="限制金额" v-model="formData.useLimitValue">
<i-input-number style="width: 100px" :disabled="readonly" placeholder="限制金额" v-model="formData.useLimitValue">
</i-input-number>
</div>
</i-form-item>
<i-form-item label="优惠金额" prop="couponAmount">
<i-input-number placeholder="优惠金额" v-model="formData.couponAmount" style="width: 100px">
<i-input-number placeholder="优惠金额" :disabled="readonly" v-model="formData.couponAmount" style="width: 100px">
</i-input-number>
</i-form-item>
<i-form-item label="适用范围(指定商品)" prop="productLimitValue">
<i-input type="textarea" placeholder="填写商品编码,多个商品编码用英文逗号分隔" v-model="formData.productLimitValue"></i-input>
<i-button type="success" size="small">导入</i-button>
<i-input type="textarea" :disabled="readonly" placeholder="填写商品编码,多个商品编码用英文逗号分隔" v-model="formData.productLimitValue"></i-input>
<i-poptip trigger="hover">
<div slot="content">
<p>1.上传文件必须是xlsx文件</p>
<p>2.第一行标题栏:商品编码</p>
<p>3.<a href="javascript:;" @click="onExample">下载样例</a></p>
</div>
<i-upload action="" :format="['xlsx']" :max-size="1024" :before-upload="onBeforeUpload">
<i-button type="success" size="small" :disabled="readonly">导入</i-button>
<p>{{uploadTxt}}</p>
</i-upload>
</i-poptip>
</i-form-item>
</i-form>
</i-modal>
</template>
<script>
import Api from '@/api/api'
import dayjs from 'dayjs'
import Api from 'api/api';
import dayjs from 'dayjs';
import xlsx from 'xlsx';
const api = new Api()
const api = new Api();
export default {
name: 'ModalCreateCoupon',
data() {
return {
visiable: true,
loading: true,
readonly: false,
visiable: false,
loading: false,
posting: true,
uploadTxt: '',
couponToken: '',
formData: {
id: 0,
couponName: '',
couponNum: 0,
useNum: 1,
couponAmount: 0,
useLimitType: 0,
remark: '',
... ... @@ -67,81 +92,182 @@ export default {
couponAmount: {type: 'number', required: true, min: 1, message: '请输入优惠金额'},
time: {required: true, validator: (rule, value, callback) => {
if (value.some(v => !v)) {
callback(new Error('请选择使用期限'))
callback(new Error('请选择使用期限'));
} else {
callback()
callback();
}
}},
remark: {required: true, message: '请输入优惠券说明'},
useLimitType: {required: true, validator: (rule, value, callback) => {
console.log(this.formData.useLimitValue)
if (parseInt(value) >= 0) {
if (value >= 0) {
if (value === 2) {
if (parseInt(this.formData.useLimitValue) > 0) {
callback()
callback();
} else {
callback(new Error('请输入限制金额'))
callback(new Error('请输入限制金额'));
}
} else {
callback();
}
} else {
callback(new Error('请选择优惠条件'))
callback(new Error('请选择优惠条件'));
}
}},
productLimitValue: {required: true, validator: (rule, value, callback) => {
const ids = value.split(',')
const ids = (value || '').split(',');
if (!value || !ids.length) {
callback(new Error('请输入适用范围'))
callback(new Error('请输入适用范围'));
} else if(ids.some(id => id ? !parseInt(id) : false)) {
callback(new Error('适用范围格式错误'))
callback(new Error('适用范围格式错误'));
} else {
callback()
callback();
}
}},
}
}
};
},
methods: {
show() {
this.loading = this.visiable = true
async show(id, readonly) {
this.readonly = readonly;
this.posting = this.visiable = true;
this.$refs.formCoupon.resetFields();
let initData = {
id: 0,
couponName: '',
couponNum: 0,
useNum: 1,
couponAmount: 0,
useLimitType: 0,
remark: '',
productLimitValue: '',
useLimitValue: 0,
time: ['', '']
};
if (id) {
this.loading = true;
const result = await api._get('/ufoPlatform/coupon/getCouponInfo', {
id
});
this.loading = false;
if (result.code === 200) {
const coupon = result.data.coupon;
this.couponToken = coupon.couponToken;
initData = {
id,
couponName: coupon.couponName,
couponNum: coupon.couponNum,
useNum: coupon.useNum,
couponAmount: coupon.couponAmount,
useLimitType: coupon.useLimitType,
remark: coupon.remark,
productLimitValue: coupon.productLimitValue,
useLimitValue: coupon.useLimitValue,
time: [dayjs.unix(coupon.startTime).format('YYYY-MM-DD HH:mm:ss'), dayjs.unix(coupon.endTime).format('YYYY-MM-DD HH:mm:ss')]
};
} else {
result.message && this.$Message.warning(result.message);
}
}
this.formData = initData;
},
onOk() {
this.$refs.formCoupon.validate(valid => {
if (!valid) {
this.loading = false
this.posting = false;
this.$nextTick(() => {
this.loading = true
})
this.posting = true;
});
} else {
this.saveData(this.formData)
this.saveData(this.formData);
}
})
});
},
async saveData(params) {
if (this.readonly) {
this.visiable = false;
return;
}
const result = await api._post('/ufoPlatform/coupon/saveOrUpdateCoupon', {
id: params.id || void 0,
couponName: params.couponName || void 0,
couponAmount: params.couponAmount || void 0,
couponNum: params.couponNum || void 0,
useNum: 1,
useLimitValue: params.useLimitValue || void 0,
productLimitValue: params.productLimitValue || void 0,
remark: params.remark || void 0,
couponName: params.couponName,
couponAmount: params.couponAmount,
couponNum: params.couponNum,
useNum: params.useNum,
useLimitValue: params.useLimitValue,
productLimitValue: params.productLimitValue,
remark: params.remark,
useLimitType: parseInt(params.useLimitType) >= 0 ? params.useLimitType : void 0,
startTime: params.time[0] ? dayjs(params.time[0]).unix() : void 0,
endTime: params.time[1] ? dayjs(params.time[1]).unix() : void 0,
})
});
if (result && result.code === 200) {
if (result.code === 200) {
this.$Message.success('保存成功');
this.visiable = false;
this.$emit('on-created');
} else {
this.loading = false
result.message && this.$Message.warning(result.message);
this.posting = false;
this.$nextTick(() => {
this.loading = true
})
this.posting = true;
});
}
},
onBeforeUpload(file) {
const fileExt = file.name.split('.').pop().toLocaleLowerCase();
if (fileExt !== 'xlsx') {
this.$Message.warning('文件格式错误');
return false;
}
if (file.size > 1024 * 1024) {
this.$Message.warning('文件大小超过1M');
return false;
}
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onloadstart = () => {
this.uploadTxt = '开始读取';
};
reader.onprogress = e => {
this.uploadTxt = `进度:${Math.round(e.loaded / e.total * 100)}...`;
};
reader.onerror = () => {
this.uploadTxt = '文件读取出错';
};
reader.onload = e => {
this.uploadTxt = '';
try {
const data = e.target.result;
const workbook = xlsx.read(data, { type: 'array' });
const firstSheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[firstSheetName];
const results = xlsx.utils.sheet_to_json(worksheet);
this.formData.productLimitValue = results.map(r => r['商品编码']).filter(r => r).join(',');
} catch (error) {
this.uploadTxt = '文件解析失败,请按照格式上传';
}
};
return false;
},
onExample() {
const wb = xlsx.utils.book_new();
const ws = xlsx.utils.json_to_sheet([{
'商品编码': '123456'
}]);
xlsx.utils.book_append_sheet(wb, ws, '优惠券适用范围示例');
xlsx.writeFile(wb, '优惠券适用范围示例.xlsx');
}
}
}
};
</script>
<style lang="scss" scoped>
... ...
import App from './index.vue';
import createApp from 'create-app'
import createApp from 'create-app';
createApp(App)
\ No newline at end of file
createApp(App);
\ No newline at end of file
... ...
... ... @@ -9,12 +9,11 @@
<i-input placeholder="输入券名称" v-model="filter.name"></i-input>
</i-form-item>
<i-form-item prop="status">
<i-select v-model="filter.status" style="width: 100px;">
<i-option :value="0">待审核</i-option>
<i-option :value="99">未生效</i-option>
<i-option :value="1">有效</i-option>
<i-option :value="2">审核驳回</i-option>
<i-option :value="3">作废</i-option>
<i-select placeholder="选择状态" v-model="filter.status" style="width: 100px;">
<i-option :value="0">未生效</i-option>
<i-option :value="1">生效中</i-option>
<i-option :value="2">已过期</i-option>
<i-option :value="3">已作废</i-option>
</i-select>
</i-form-item>
<i-form-item prop="time">
... ... @@ -28,21 +27,22 @@
<LayoutTable :total="total" @on-page-change="onPageChange">
<i-table :columns="columns" :data="data"></i-table>
<template slot="footer" class="btns">
<i-button type="primary" icon="ios-cloud-download">导出</i-button>
<i-button type="primary" icon="ios-cloud-download" @click="onExport">导出</i-button>
</template>
</LayoutTable>
<ModalCreateCoupon ref="modalCreateCoupon"></ModalCreateCoupon>
<ModalCreateCoupon ref="modalCreateCoupon" @on-created="onCreated"></ModalCreateCoupon>
</LayoutContent>
</template>
<script>
import {Button} from 'iview'
import Api from '@/api/api'
import dayjs from 'dayjs'
import {Button} from 'iview'; //eslint-disable-line
import Api from '@/api/api';
import dayjs from 'dayjs';
import BlobUtil from 'libs/blob';
import ModalCreateCoupon from './components/modal-create-coupon'
import ModalCreateCoupon from './components/modal-create-coupon';
const api = new Api()
const api = new Api();
export default {
name: 'CouponPage',
... ... @@ -67,19 +67,9 @@ export default {
key: 'amount'
}, {
title: '使用期限',
width: 180,
render(h, {row}) {
return (
<div>
{dayjs(row.startTime).format('YYYY-MM-DD HH:mm:ss')}<br/>
{dayjs(row.endTime).format('YYYY-MM-DD HH:mm:ss')}
</div>
)
}
key: 'useTime',
}, {
title: '优惠券说明',
width: 200,
key: 'remark'
}, {
title: '状态',
... ... @@ -87,63 +77,97 @@ export default {
}, {
title: '操作',
width: 270,
render() {
align: 'center',
render: (h, {row}) => {
return (
<div>
<i-button type="primary" size="small">修改</i-button>&nbsp;
<i-button type="error" size="small">作废</i-button>&nbsp;
<i-button type="warning" size="small">发放记录</i-button>
<i-button type="success" size="small" onClick={() => this.onEditCoupon(row, true)}>查看详情</i-button>&nbsp;
{row.status === '待审核' ?
(<i-button type="primary" size="small" onClick={() => this.onEditCoupon(row)}>修改</i-button>) :
void 0}
&nbsp;
<i-button type="warning" size="small" onClick={() => this.onToRecord(row)}>发放记录</i-button>
</div>
);
}
}]
}
};
},
created() {
this.fetchData(this.filter)
this.fetchData(this.filter);
},
methods: {
onToRecord({id}) {
location.href = `send-record.html?id=${id}`;
},
onCreated() {
this.fetchData(this.filter);
},
onFilter() {
this.fetchData(this.filter)
this.fetchData(this.filter);
},
onClear() {
this.$refs.filterForm.resetFields()
this.fetchData(this.filter)
this.$refs.filterForm.resetFields();
this.fetchData(this.filter);
},
onPageChange(page) {
this.fetchData(this.filter, page)
this.fetchData(this.filter, page);
},
onCreateCoupon() {
this.$refs.modalCreateCoupon.show()
this.$refs.modalCreateCoupon.show();
},
onEditCoupon({id}, readonly) {
this.$refs.modalCreateCoupon.show(id, readonly);
},
async onExport() {
this.$Loading.start();
const result = await api._get('/ufoPlatform/coupon/export', {
param: {
method: 'coupon',
param: api._2params(this.getParams(this.filter))
}
}, {
responseType: 'blob'
});
if (result instanceof Blob) {
BlobUtil.downloadBlob(result, `优惠券导出_${dayjs().format('YYYY-MM-DD')}.xlsx`);
this.$Loading.finish();
} else if (result) {
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
},
async fetchData(params, page = 1) {
let startTime, endTime, status
this.$Loading.start();
const result = await api._get('/ufoPlatform/coupon/queryCoupons', Object.assign({
page,
}, this.getParams(params)));
if (params.status === 99) {
startTime = params.time[0] ? dayjs(params.time[0]).unix() : void 0
endTime = params.time[1] ? dayjs(params.time[1]).unix() : void 0
if (result.code === 200) {
this.total = result.data.total;
this.data = result.data.coupons;
this.$Loading.finish();
} else {
startTime = params.time[0] ? dayjs(params.time[0]).unix() : void 0
endTime = params.time[1] ? dayjs(params.time[1]).unix() : void 0
status = parseInt(params.status) >= 0 ? params.status : void 0
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
const result = await api._post('/ufoPlatform/coupon/queryCoupons', {
id: params.id || void 0,
name: params.name || void 0,
status: parseInt(params.status) >= 0 ? params.status : void 0,
startTime: params.time[0] ? dayjs(params.time[0]).unix() : void 0,
endTime: params.time[1] ? dayjs(params.time[1]).unix() : void 0,
page
})
},
getParams(params) {
let startTime = params.time[0] ? dayjs(params.time[0]).unix() : void 0;
let endTime = params.time[1] ? dayjs(params.time[1]).unix() : void 0;
let status = parseInt(params.status) >= 0 ? params.status : void 0;
if (result && result.code === 200) {
this.total = result.data.total
this.data = result.data.coupons
}
return {
id: params.id,
name: params.name,
status,
startTime,
endTime,
};
}
},
components: {ModalCreateCoupon}
}
};
</script>
<style>
... ...
import App from './index.vue';
import createApp from 'create-app'
import createApp from 'create-app';
createApp(App);
\ No newline at end of file
... ...
import App from './index.vue';
import createApp from 'create-app';
createApp(App);
\ No newline at end of file
... ...
<template>
<LayoutContent>
<LayoutFilter @on-filter="onFilter" @on-clear="onClear">
<i-form ref="filterForm" inline :model="filter">
<i-form-item prop="sku">
<i-input placeholder="SKU" v-model="filter.sku"></i-input>
</i-form-item>
<i-form-item prop="productId">
<i-input placeholder="商品编码" v-model="filter.productId"></i-input>
</i-form-item>
<i-form-item prop="status">
<i-select placeholder="选择状态" v-model="filter.status" style="width: 100px;">
<i-option :value="0">正常</i-option>
<i-option :value="1">异常</i-option>
</i-select>
</i-form-item>
<i-form-item prop="productName">
<i-input placeholder="商品名称" v-model="filter.productName"></i-input>
</i-form-item>
<i-form-item prop="sizeName">
<i-input placeholder="尺码" v-model="filter.sizeName"></i-input>
</i-form-item>
</i-form>
</LayoutFilter>
<LayoutTable :total="total" @on-page-change="onPageChange">
<i-table :columns="columns" :data="data"></i-table>
<template slot="footer" class="btns">
<i-button type="primary" icon="ios-cloud-download" @click="onExport">导出</i-button>
</template>
</LayoutTable>
</LayoutContent>
</template>
<script>
import {Icon, Tooltip, InputNumber} from 'iview'; //eslint-disable-line
import Api from '@/api/api';
import dayjs from 'dayjs';
import BlobUtil from 'libs/blob';
import {BigNumber} from 'bignumber.js';
const api = new Api();
const rateComponent = (h, row, key) => {
const value = BigNumber(row[key]).times(100).toNumber();
return (
<i-input-number
value={value}
style="width: 70px"
max={100}
min={0}
formatter={value => `${value}%`}
onInput={val => (row[key] = BigNumber(val).div(100).toNumber())}>
</i-input-number>
);
};
export default {
name: 'SendRecordPage',
data() {
return {
filter: {
productId: '',
sku: '',
status: '',
productName: '',
sizeName: '',
},
total: 0,
data: [],
columns: [{
title: '商品编码',
key: 'productId'
}, {
title: 'SKU',
key: 'sku'
}, {
title: '商品名称',
key: 'productName'
}, {
title: '尺码',
key: 'sizeName'
}, {
renderHeader: () => {
return (
<span>毒当前价<br/>(A)</span>
);
},
key: 'channelPrice'
}, {
renderHeader: () => {
return (
<span>价格低于<br/>(a%)</span>
);
},
width: 150,
render: (h, {row}) => {
if (row._editing) {
return (
<div>
{rateComponent(h, row, 'lowRate')}
&nbsp;
<i-tooltip content="保存">
<i-icon class="icon-edit" type="md-checkmark-circle" onClick={() => (this.onSaveRate(row))} />
</i-tooltip>
</div>
);
}
return (
<span>
{BigNumber(row.lowRate).times(100).toNumber()}%
&nbsp;
<i-tooltip content="修改比例">
<i-icon class="icon-edit" type="md-create" onClick={() => (this.onEditRate(row))} />
</i-tooltip>
</span>
);
}
}, {
renderHeader: () => {
return (
<span>价格高于<br/>(b%)</span>
);
},
width: 150,
render: (h, {row}) => {
if (row._editing) {
return (
<div>
{rateComponent(h, row, 'highRate')}
&nbsp;
<i-tooltip content="保存">
<i-icon class="icon-edit" type="md-checkmark-circle" onClick={() => (this.onSaveRate(row))} />
</i-tooltip>
</div>
);
}
return (
<span>
{BigNumber(row.highRate).times(100).toNumber()}%
&nbsp;
<i-tooltip content="修改比例">
<i-icon class="icon-edit" type="md-create" onClick={() => (this.onEditRate(row))} />
</i-tooltip>
</span>
);
}
}, {
renderHeader: () => {
return (
<span>对标毒的价格区间<br/>A(1-a%)~A(1+b%)</span>
);
},
width: 150,
key: 'channelPriceRange'
}, {
title: '平台建议售价',
key: 'suggestPriceRange'
}, {
title: 'UFO当前价',
key: 'ufoCurrentPrice'
}, {
title: 'UFO价格红线',
key: 'ufoMinPrice'
}, {
title: '状态',
render(h, {row}) {
return (
<span>{row.status ? '异常' : '正常'}</span>
);
}
}, {
title: '操作',
render(h, {row}) {
return (
<div>
{row.status ?
(<i-button type="primary" size="small" onClick={() => this.onEditPrice(row)}>确认变更</i-button>) :
(<span>-</span>)}
</div>
);
}
}]
};
},
created() {
this.fetchData(this.filter);
},
methods: {
onFilter() {
this.fetchData(this.filter);
},
onClear() {
this.$refs.filterForm.resetFields();
this.fetchData(this.filter);
},
onPageChange(page) {
this.fetchData(this.filter, page);
},
onEditRate(row) {
row._editing = true;
},
async onSaveRate(row) {
const {lowRate, highRate, id} = row;
this.$Loading.start();
const result = await api._get('/ufoPlatform/channelSkuCompare/updateSuggestRate', {
id,
suggestLowRate: lowRate,
suggestHighRate: highRate
});
if (result.code === 200) {
this.$Message.success('保存成功');
this.$Loading.finish();
row._editing = false;
} else {
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
},
async fetchData(params, page = 1) {
this.$Loading.start();
const result = await api._get('/ufoPlatform/channelSkuCompare/queryList', Object.assign({
page,
}, this.getParams(params)));
if (result.code === 200) {
let total = 0;
let data = [];
if (result.data && result.data.length !== 0) {
total = result.data.total;
data = result.data.list;
}
this.total = total;
this.data = data.map(sku => {
sku.lowRate = 0.051;
sku.highRate = 0.051;
sku._editing = false;
sku._lowRate = sku.lowRate;
sku._highRate = sku.highRate;
return sku;
});
this.$Loading.finish();
} else {
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
},
async onExport() {
this.$Loading.start();
const result = await api._get('/ufoPlatform/batch/export', {
type: 'channelSkuCompareServiceImpl',
queryConf: this.getParams(this.filter)
}, {
responseType: 'blob'
});
if (result instanceof Blob) {
BlobUtil.downloadBlob(result, `比价跟价导出_${dayjs().format('YYYY-MM-DD')}.xlsx`);
this.$Loading.finish();
} else if (result) {
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
},
getParams(params) {
return {
productId: params.productId,
sku: params.sku,
status: parseInt(params.status) >= 0 ? params.status : void 0,
productName: params.productName,
sizeName: params.sizeName,
};
}
},
};
</script>
<style lang="scss" scoped>
/deep/ .icon-edit {
font-size: 16px;
cursor: pointer;
vertical-align: bottom;
}
</style>
... ...
import App from './index.vue';
import createApp from 'create-app'
import createApp from 'create-app';
createApp(App)
\ No newline at end of file
createApp(App);
\ No newline at end of file
... ...
... ... @@ -9,7 +9,7 @@
<i-input placeholder="输入uid" v-model="filter.uid"></i-input>
</i-form-item>
<i-form-item prop="status">
<i-select v-model="filter.status" style="width: 100px;">
<i-select placeholder="选择状态" v-model="filter.status" style="width: 100px;">
<i-option :value="0">未使用</i-option>
<i-option :value="1">已使用</i-option>
</i-select>
... ... @@ -18,23 +18,29 @@
</LayoutFilter>
<LayoutTable :total="total" @on-page-change="onPageChange">
<i-table :columns="columns" :data="data"></i-table>
<template slot="footer" class="btns">
<i-button type="primary" icon="ios-cloud-download" @click="onExport">导出</i-button>
</template>
</LayoutTable>
</LayoutContent>
</template>
<script>
import Api from '@/api/api'
import dayjs from 'dayjs'
import Api from '@/api/api';
import dayjs from 'dayjs';
import BlobUtil from 'libs/blob';
import qs from 'yoho-qs';
const api = new Api()
const api = new Api();
export default {
name: 'SendRecordPage',
data() {
return {
filter: {
couponId: 0,
couponCode: '',
uid: '500031478',
uid: '',
status: '',
},
total: 0,
... ... @@ -50,53 +56,79 @@ export default {
render(h, {row}) {
return (
<span>{dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss')}</span>
)
);
}
}, {
title: '使用状态',
render(h, {row}) {
return (
<span>{row.status === 0 ? '未使用' : '已使用'}</span>
)
}
key: 'status'
}, {
title: '使用时间',
render(h, {row}) {
return (
<span>{dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss')}</span>
)
<span>{dayjs(row.useTime).format('YYYY-MM-DD HH:mm:ss')}</span>
);
}
}]
}
};
},
created() {
this.filter.couponId = qs.id;
this.fetchData(this.filter);
},
methods: {
onFilter() {
this.fetchData(this.filter)
this.fetchData(this.filter);
},
onClear() {
this.$refs.filterForm.resetFields()
this.fetchData(this.filter)
this.$refs.filterForm.resetFields();
this.fetchData(this.filter);
},
onPageChange(page) {
this.fetchData(this.filter, page)
this.fetchData(this.filter, page);
},
async fetchData(params, page = 1) {
const result = await api._post('/ufoPlatform/coupon/queryUserCoupons', {
couponCode: params.couponCode || void 0,
uid: params.uid || void 0,
status: parseInt(params.status) >= 0 ? params.status : void 0,
page
})
this.$Loading.start();
const result = await api._get('/ufoPlatform/coupon/queryUserCoupons', Object.assign({
page,
}, this.getParams(params)));
if (result && result.code === 200) {
this.total = result.data.total
this.data = result.data.userCoupons
if (result.code === 200) {
this.total = result.data.total;
this.data = result.data.userCoupons;
this.$Loading.finish();
} else {
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
},
async onExport() {
this.$Loading.start();
const result = await api._get('/ufoPlatform/coupon/export', {
param: {
method: 'userCoupon',
param: api._2params(this.getParams(this.filter))
}
}, {
responseType: 'blob'
});
if (result instanceof Blob) {
BlobUtil.downloadBlob(result, `优惠券发放记录导出_${dayjs().format('YYYY-MM-DD')}.xlsx`);
this.$Loading.finish();
} else if (result) {
result.message && this.$Message.warning(result.message);
this.$Loading.error();
}
},
getParams(params) {
return {
couponId: params.couponId,
couponCode: params.couponCode,
uid: params.uid,
status: parseInt(params.status) >= 0 ? params.status : void 0,
};
}
},
}
};
</script>
<style>
... ...
import App from './index.vue';
import createApp from 'create-app'
import createApp from 'create-app';
createApp(App)
\ No newline at end of file
createApp(App);
\ No newline at end of file
... ...
... ... @@ -3,98 +3,98 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const fs = require('fs');
const entry = {}
const plugins = []
const entry = {};
const plugins = [];
fs
.readdirSync(path.join(__dirname, './src/views'))
.forEach(file => {
entry[file] = `./src/views/${file}/index.js`
plugins.push(new HtmlWebpackPlugin({
.readdirSync(path.join(__dirname, './src/views'))
.forEach(file => {
entry[file] = `./src/views/${file}/index.js`;
plugins.push(new HtmlWebpackPlugin({
filename: `${file}.html`,
template: './src/template/index.ejs',
inject: true,
chunks: ['vendors', file]
}))
});
}));
});
module.exports = {
entry,
output: {
path: path.join(__dirname, './dist')
entry,
output: {
path: path.join(__dirname, './dist')
},
module: {
rules: [{
test: /.vue$/,
use: [{
loader: 'vue-loader',
options: {
loaders: {
sass: ExtractTextPlugin.extract({
use: ['css-loader?minimize', 'autoprefixer-loader', 'sass-loader'],
fallback: 'vue-style-loader'
}),
css: ExtractTextPlugin.extract({
use: ['css-loader', 'autoprefixer-loader', 'sass-loader'],
fallback: 'vue-style-loader'
})
}
}
},
{
loader: 'iview-loader',
options: {
prefix: true
}
}
]
},
// {
// test: /iview\/.*?js$/,
// loader: 'babel-loader',
// },
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?minimize', 'autoprefixer-loader'],
fallback: 'style-loader'
})
},
module: {
rules: [{
test: /.vue$/,
use: [{
loader: 'vue-loader',
options: {
loaders: {
sass: ExtractTextPlugin.extract({
use: ['css-loader?minimize', 'autoprefixer-loader', 'sass-loader'],
fallback: 'vue-style-loader'
}),
css: ExtractTextPlugin.extract({
use: ['css-loader', 'autoprefixer-loader', 'sass-loader'],
fallback: 'vue-style-loader'
})
}
}
},
{
loader: 'iview-loader',
options: {
prefix: true
}
}
]
},
{
test: /iview\/.*?js$/,
loader: 'babel-loader'
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: ['css-loader?minimize', 'autoprefixer-loader'],
fallback: 'style-loader'
})
},
{
test: /\.scss/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'autoprefixer-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
{
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader: 'url-loader?limit=1024'
},
{
test: /\.(html|tpl)$/,
loader: 'html-loader'
}
]
{
test: /\.scss/,
use: ExtractTextPlugin.extract({
use: ['css-loader', 'autoprefixer-loader', 'sass-loader'],
fallback: 'style-loader'
})
},
resolve: {
extensions: ['.js', '.vue'],
modules: [
path.join(__dirname, './src'),
'node_modules'
],
alias: {
'vue': 'vue/dist/vue.esm.js',
'@': path.join(process.cwd() ,'src'),
'components': path.join(process.cwd() ,'src/components'),
'assets': path.join(process.cwd(), 'src/assets')
}
{
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader: 'url-loader?limit=1024'
},
plugins: plugins
{
test: /\.(html|tpl)$/,
loader: 'html-loader'
}
]
},
resolve: {
extensions: ['.js', '.vue'],
modules: [
path.join(__dirname, './src'),
'node_modules'
],
alias: {
'vue': 'vue/dist/vue.esm.js',
'@': path.join(process.cwd(), 'src'),
'components': path.join(process.cwd(), 'src/components'),
'assets': path.join(process.cwd(), 'src/assets')
}
},
plugins: plugins
};
\ No newline at end of file
... ...
... ... @@ -5,47 +5,48 @@ const webpackBaseConfig = require('./webpack.base.config.js');
const fs = require('fs');
fs.open('./src/config/env.js', 'w', function(err, fd) {
const buf = new Buffer('export default "development";');
fs.write(fd, buf, 0, buf.length, 0, function(err, written, buffer) {});
const buf = new Buffer('export default "development";');
fs.write(fd, buf, 0, buf.length, 0, function() {});
});
module.exports = merge(webpackBaseConfig, {
// devtool: '#source-map',
output: {
publicPath: '/dist/',
filename: '[name].js',
chunkFilename: '[name].chunk.js'
output: {
publicPath: '/dist/',
filename: '[name].js',
chunkFilename: '[name].chunk.js'
},
plugins: [
new webpack.DefinePlugin({
PRODUCTION: 'false'
}),
new ExtractTextPlugin({
filename: '[name].css',
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.js',
minChunks: 2
})
],
devServer: {
openPage: 'dist/coupon.html',
proxy: {
'/ufoPlatform/**': {
target: 'http://java-ufo-platform.test3.ingress.dev.yohocorp.com',
changeOrigin: true
},
'/ufoPlatform': {
target: 'http://java-ufo-platform.test3.ingress.dev.yohocorp.com',
changeOrigin: true
}
},
plugins: [
new webpack.DefinePlugin({
PRODUCTION: 'false'
}),
new ExtractTextPlugin({
filename: '[name].css',
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.js'
})
],
devServer: {
openPage: 'dist/coupon.html',
proxy: {
'/ufoPlatform/**': {
target: 'http://java-ufo-platform.test3.ingress.dev.yohocorp.com',
changeOrigin: true
},
'/ufoPlatform': {
target: 'http://java-ufo-platform.test3.ingress.dev.yohocorp.com',
changeOrigin: true
}
},
headers: {
"Access-Control-Allow-Origin": "*",
headers: {
'Access-Control-Allow-Origin': '*',
// "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
// "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
},
},
// disableHostCheck: true
}
}
});
\ No newline at end of file
... ...
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const merge = require('webpack-merge');
const webpackBaseConfig = require('./webpack.base.config.js');
const fs = require('fs');
fs.open('./src/config/env.js', 'w', function(err, fd) {
const buf = new Buffer('export default "production";');
fs.write(fd, buf, 0, buf.length, 0, function(err, written, buffer) {});
const buf = new Buffer('export default "production";');
fs.write(fd, buf, 0, buf.length, 0, function() {});
});
module.exports = merge(webpackBaseConfig, {
output: {
publicPath: '/dist/',
filename: '[name].[hash].js',
chunkFilename: '[name].[hash].chunk.js'
},
plugins: [
new webpack.DefinePlugin({
PRODUCTION: 'true'
}),
new ExtractTextPlugin({
filename: '[name].[hash].css',
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.[hash].js'
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
output: {
// publicPath: '/dist/',
filename: 'js/[name].[hash].js',
chunkFilename: 'js/[name].[hash].chunk.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new webpack.DefinePlugin({
PRODUCTION: 'true'
}),
new ExtractTextPlugin({
filename: 'css/[name].[hash].css',
allChunks: true
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendors',
filename: 'vendors.[hash].js',
minChunks: 2
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
]
});
\ No newline at end of file
... ...
... ... @@ -2,6 +2,84 @@
# yarn lockfile v1
"@babel/code-frame@^7.0.0":
version "7.0.0"
resolved "http://npm.yohops.com/@babel%2fcode-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
dependencies:
"@babel/highlight" "^7.0.0"
"@babel/generator@^7.1.6":
version "7.1.6"
resolved "http://npm.yohops.com/@babel%2fgenerator/-/generator-7.1.6.tgz#001303cf87a5b9d093494a4bf251d7b5d03d3999"
dependencies:
"@babel/types" "^7.1.6"
jsesc "^2.5.1"
lodash "^4.17.10"
source-map "^0.5.0"
trim-right "^1.0.1"
"@babel/helper-function-name@^7.1.0":
version "7.1.0"
resolved "http://npm.yohops.com/@babel%2fhelper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53"
dependencies:
"@babel/helper-get-function-arity" "^7.0.0"
"@babel/template" "^7.1.0"
"@babel/types" "^7.0.0"
"@babel/helper-get-function-arity@^7.0.0":
version "7.0.0"
resolved "http://npm.yohops.com/@babel%2fhelper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
dependencies:
"@babel/types" "^7.0.0"
"@babel/helper-split-export-declaration@^7.0.0":
version "7.0.0"
resolved "http://npm.yohops.com/@babel%2fhelper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813"
dependencies:
"@babel/types" "^7.0.0"
"@babel/highlight@^7.0.0":
version "7.0.0"
resolved "http://npm.yohops.com/@babel%2fhighlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
dependencies:
chalk "^2.0.0"
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/parser@^7.0.0", "@babel/parser@^7.1.2", "@babel/parser@^7.1.6":
version "7.1.6"
resolved "http://npm.yohops.com/@babel%2fparser/-/parser-7.1.6.tgz#16e97aca1ec1062324a01c5a6a7d0df8dd189854"
"@babel/template@^7.1.0":
version "7.1.2"
resolved "http://npm.yohops.com/@babel%2ftemplate/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644"
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/parser" "^7.1.2"
"@babel/types" "^7.1.2"
"@babel/traverse@^7.0.0":
version "7.1.6"
resolved "http://npm.yohops.com/@babel%2ftraverse/-/traverse-7.1.6.tgz#c8db9963ab4ce5b894222435482bd8ea854b7b5c"
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/generator" "^7.1.6"
"@babel/helper-function-name" "^7.1.0"
"@babel/helper-split-export-declaration" "^7.0.0"
"@babel/parser" "^7.1.6"
"@babel/types" "^7.1.6"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.10"
"@babel/types@^7.0.0", "@babel/types@^7.1.2", "@babel/types@^7.1.6":
version "7.1.6"
resolved "http://npm.yohops.com/@babel%2ftypes/-/types-7.1.6.tgz#0adb330c3a281348a190263aceb540e10f04bcce"
dependencies:
esutils "^2.0.2"
lodash "^4.17.10"
to-fast-properties "^2.0.0"
abbrev@1:
version "1.1.1"
resolved "http://npm.yohops.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
... ... @@ -37,6 +115,13 @@ acorn@^5.0.0, acorn@^5.5.0:
version "5.7.3"
resolved "http://npm.yohops.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
adler-32@~1.2.0:
version "1.2.0"
resolved "http://npm.yohops.com/adler-32/-/adler-32-1.2.0.tgz#6a3e6bf0a63900ba15652808cb15c6813d1a5f25"
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
ajv-keywords@^1.0.0:
version "1.5.1"
resolved "http://npm.yohops.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
... ... @@ -337,6 +422,17 @@ babel-core@^6.23.1, babel-core@^6.26.0:
slash "^1.0.0"
source-map "^0.5.7"
babel-eslint@^10.0.1:
version "10.0.1"
resolved "http://npm.yohops.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed"
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/parser" "^7.0.0"
"@babel/traverse" "^7.0.0"
"@babel/types" "^7.0.0"
eslint-scope "3.7.1"
eslint-visitor-keys "^1.0.0"
babel-generator@^6.26.0:
version "6.26.1"
resolved "http://npm.yohops.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
... ... @@ -407,6 +503,16 @@ babel-helper-regex@^6.24.1:
babel-types "^6.26.0"
lodash "^4.17.4"
babel-helper-remap-async-to-generator@^6.24.1:
version "6.24.1"
resolved "http://npm.yohops.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
dependencies:
babel-helper-function-name "^6.24.1"
babel-runtime "^6.22.0"
babel-template "^6.24.1"
babel-traverse "^6.24.1"
babel-types "^6.24.1"
babel-helper-replace-supers@^6.24.1:
version "6.24.1"
resolved "http://npm.yohops.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
... ... @@ -445,10 +551,26 @@ babel-plugin-check-es2015-constants@^6.22.0:
dependencies:
babel-runtime "^6.22.0"
babel-plugin-syntax-async-functions@^6.8.0:
version "6.13.0"
resolved "http://npm.yohops.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
babel-plugin-syntax-jsx@^6.18.0:
version "6.18.0"
resolved "http://npm.yohops.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
babel-plugin-syntax-object-rest-spread@^6.8.0:
version "6.13.0"
resolved "http://npm.yohops.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
babel-plugin-transform-async-to-generator@^6.24.1:
version "6.24.1"
resolved "http://npm.yohops.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
dependencies:
babel-helper-remap-async-to-generator "^6.24.1"
babel-plugin-syntax-async-functions "^6.8.0"
babel-runtime "^6.22.0"
babel-plugin-transform-es2015-arrow-functions@^6.22.0:
version "6.22.0"
resolved "http://npm.yohops.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
... ... @@ -617,13 +739,20 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1:
babel-runtime "^6.22.0"
regexpu-core "^2.0.0"
babel-plugin-transform-object-rest-spread@^6.26.0:
version "6.26.0"
resolved "http://npm.yohops.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz#0f36692d50fef6b7e2d4b3ac1478137a963b7b06"
dependencies:
babel-plugin-syntax-object-rest-spread "^6.8.0"
babel-runtime "^6.26.0"
babel-plugin-transform-regenerator@^6.24.1:
version "6.26.0"
resolved "http://npm.yohops.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
dependencies:
regenerator-transform "^0.10.0"
babel-plugin-transform-runtime@^6.12.0:
babel-plugin-transform-runtime@^6.23.0:
version "6.23.0"
resolved "http://npm.yohops.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
dependencies:
... ... @@ -773,6 +902,10 @@ big.js@^3.1.3:
version "3.2.0"
resolved "http://npm.yohops.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
bignumber.js@^8.0.1:
version "8.0.1"
resolved "http://npm.yohops.com/bignumber.js/-/bignumber.js-8.0.1.tgz#5d419191370fb558c64e3e5f70d68e5947138832"
binary-extensions@^1.0.0:
version "1.12.0"
resolved "http://npm.yohops.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14"
... ... @@ -1031,6 +1164,15 @@ center-align@^0.1.1:
align-text "^0.1.3"
lazy-cache "^1.0.3"
cfb@^1.1.0:
version "1.1.0"
resolved "http://npm.yohops.com/cfb/-/cfb-1.1.0.tgz#44fb1b30eee014fa5633a0ed5f26c87fd765799a"
dependencies:
adler-32 "~1.2.0"
commander "^2.16.0"
crc-32 "~1.2.0"
printj "~1.1.2"
chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
version "1.1.3"
resolved "http://npm.yohops.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
... ... @@ -1041,7 +1183,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.4.1:
chalk@^2.0.0, chalk@^2.4.1:
version "2.4.1"
resolved "http://npm.yohops.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
dependencies:
... ... @@ -1134,6 +1276,12 @@ clean-css@4.2.x:
dependencies:
source-map "~0.6.0"
clean-webpack-plugin@^1.0.0:
version "1.0.0"
resolved "http://npm.yohops.com/clean-webpack-plugin/-/clean-webpack-plugin-1.0.0.tgz#f184b9c26d12983d639828e0548ae2080e84b6a7"
dependencies:
rimraf "^2.6.1"
cli-cursor@^1.0.1:
version "1.0.2"
resolved "http://npm.yohops.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
... ... @@ -1190,6 +1338,13 @@ code-point-at@^1.0.0:
version "1.1.0"
resolved "http://npm.yohops.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
codepage@~1.14.0:
version "1.14.0"
resolved "http://npm.yohops.com/codepage/-/codepage-1.14.0.tgz#8cbe25481323559d7d307571b0fff91e7a1d2f99"
dependencies:
commander "~2.14.1"
exit-on-epipe "~1.0.1"
collection-visit@^1.0.0:
version "1.0.0"
resolved "http://npm.yohops.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
... ... @@ -1259,6 +1414,14 @@ commander@2.9.x:
dependencies:
graceful-readlink ">= 1.0.0"
commander@^2.16.0:
version "2.19.0"
resolved "http://npm.yohops.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
commander@~2.14.1:
version "2.14.1"
resolved "http://npm.yohops.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
commondir@^1.0.1:
version "1.0.1"
resolved "http://npm.yohops.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
... ... @@ -1375,6 +1538,13 @@ cosmiconfig@^2.1.0, cosmiconfig@^2.1.1:
parse-json "^2.2.0"
require-from-string "^1.1.0"
crc-32@~1.2.0:
version "1.2.0"
resolved "http://npm.yohops.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
create-ecdh@^4.0.0:
version "4.0.3"
resolved "http://npm.yohops.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff"
... ... @@ -1580,6 +1750,12 @@ debug@^3.1.0:
dependencies:
ms "^2.1.1"
debug@^4.1.0:
version "4.1.0"
resolved "http://npm.yohops.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87"
dependencies:
ms "^2.1.1"
decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
version "1.2.0"
resolved "http://npm.yohops.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
... ... @@ -1946,6 +2122,17 @@ eslint-plugin-html@^1.7.0:
dependencies:
htmlparser2 "^3.8.2"
eslint-scope@3.7.1:
version "3.7.1"
resolved "http://npm.yohops.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "http://npm.yohops.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
eslint@^3.12.2:
version "3.19.0"
resolved "http://npm.yohops.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
... ... @@ -2073,6 +2260,10 @@ exit-hook@^1.0.0:
version "1.1.1"
resolved "http://npm.yohops.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
exit-on-epipe@~1.0.1:
version "1.0.1"
resolved "http://npm.yohops.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
expand-brackets@^0.1.4:
version "0.1.5"
resolved "http://npm.yohops.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
... ... @@ -2353,6 +2544,10 @@ forwarded@~0.1.2:
version "0.1.2"
resolved "http://npm.yohops.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
frac@~1.1.2:
version "1.1.2"
resolved "http://npm.yohops.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
fragment-cache@^0.2.1:
version "0.2.1"
resolved "http://npm.yohops.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
... ... @@ -2477,6 +2672,10 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.1.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
globals@^11.1.0:
version "11.9.0"
resolved "http://npm.yohops.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249"
globals@^9.14.0, globals@^9.18.0:
version "9.18.0"
resolved "http://npm.yohops.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
... ... @@ -3250,7 +3449,7 @@ js-cookie@^2.1.3:
version "2.2.0"
resolved "http://npm.yohops.com/js-cookie/-/js-cookie-2.2.0.tgz#1b2c279a6eece380a12168b92485265b35b1effb"
"js-tokens@^3.0.0 || ^4.0.0":
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "http://npm.yohops.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
... ... @@ -3280,6 +3479,10 @@ jsesc@^1.3.0:
version "1.3.0"
resolved "http://npm.yohops.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
jsesc@^2.5.1:
version "2.5.2"
resolved "http://npm.yohops.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
jsesc@~0.5.0:
version "0.5.0"
resolved "http://npm.yohops.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
... ... @@ -4562,6 +4765,10 @@ pretty-error@^2.0.2:
renderkid "^2.0.1"
utila "~0.4"
printj@~1.1.0, printj@~1.1.2:
version "1.1.2"
resolved "http://npm.yohops.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
private@^0.1.6, private@^0.1.8, private@~0.1.5:
version "0.1.8"
resolved "http://npm.yohops.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
... ... @@ -5320,7 +5527,7 @@ source-map@0.4.x, source-map@^0.4.2:
dependencies:
amdefine ">=0.0.4"
source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1:
source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1:
version "0.5.7"
resolved "http://npm.yohops.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
... ... @@ -5383,6 +5590,12 @@ sprintf-js@~1.0.2:
version "1.0.3"
resolved "http://npm.yohops.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
ssf@~0.10.2:
version "0.10.2"
resolved "http://npm.yohops.com/ssf/-/ssf-0.10.2.tgz#65b2b4fcdfd967bc8e8383a41349009893115976"
dependencies:
frac "~1.1.2"
sshpk@^1.7.0:
version "1.15.2"
resolved "http://npm.yohops.com/sshpk/-/sshpk-1.15.2.tgz#c946d6bd9b1a39d0e8635763f5242d6ed6dcb629"
... ... @@ -5626,6 +5839,10 @@ to-fast-properties@^1.0.3:
version "1.0.3"
resolved "http://npm.yohops.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "http://npm.yohops.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
to-object-path@^0.3.0:
version "0.3.0"
resolved "http://npm.yohops.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
... ... @@ -6108,6 +6325,18 @@ write@^0.2.1:
dependencies:
mkdirp "^0.5.1"
xlsx@^0.14.1:
version "0.14.1"
resolved "http://npm.yohops.com/xlsx/-/xlsx-0.14.1.tgz#ecedf536bd1e94055486ff484f5888dcaa89bd3d"
dependencies:
adler-32 "~1.2.0"
cfb "^1.1.0"
codepage "~1.14.0"
commander "~2.17.1"
crc-32 "~1.2.0"
exit-on-epipe "~1.0.1"
ssf "~0.10.2"
xml-char-classes@^1.0.0:
version "1.0.0"
resolved "http://npm.yohops.com/xml-char-classes/-/xml-char-classes-1.0.0.tgz#64657848a20ffc5df583a42ad8a277b4512bbc4d"
... ... @@ -6204,3 +6433,7 @@ yargs@~3.10.0:
cliui "^2.1.0"
decamelize "^1.0.0"
window-size "0.1.0"
yoho-qs@^1.0.1:
version "1.0.1"
resolved "http://npm.yohops.com/yoho-qs/-/yoho-qs-1.0.1.tgz#8e9e559fb05c26f910e09844b9101cf9e231fa44"
... ...