07b9e059 by simon

1.vuejs基础工程

0 parents
> 1%
last 2 versions
NODE_ENV = 'production'
VUE_APP_TITLE = 'production'
\ No newline at end of file
NODE_ENV = 'production'
VUE_APP_TITLE = 'fev'
\ No newline at end of file
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
// 'eslint:recommended'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
"no-unused-vars": 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
}
.DS_Store
node_modules
/dist
/fev
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# vue-cli3-framework
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your tests
```
npm run test
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/app'
]
}
/**
* Created by pc on 2018/5/11.
* 需要的库为(co, ali-oss, glob)
* npm i co ali-oss glob --save
* ossConfig.json格式如下
{
"region": "oss-cn-shanghai", //OSS region
"accessKeyId": "XXXXXXXX", //OSS accessKeyId
"accessKeySecret": "XXXXXXXX", //OSS accessKeySecret
"bucket": "ogo", //OSS bucket
"localPath": "./dist/**", //本地需要上传的文件目录,(/**)为遍历根号后所有目录
"ossPath": "/mobile/", //oss线上文件目录(不能为根目录,避免误操作,最后加上'/')
"callbackUrl": "http://nodejs.org/dist/index.json" //预留请求服务器更新缓存的API
}
*
*
*/
let co = require('co')
let OSS = require('ali-oss')
let glob = require('glob')
let http = require('http')
let Config = require('./ossConfig.json')
// 配置oss信息
let client = new OSS({
region: Config.region,
accessKeyId: Config.accessKeyId,
accessKeySecret: Config.accessKeySecret,
bucket: Config.bucket
})
// 删除线上目录
function deleteFiles() {
if (Config.ossPath !== '' && Config.ossPath !== '/') {
co(function* () {
let result = yield client.list({
prefix: Config.ossPath.slice(1, -1),
marker: Config.ossPath.slice(0, -1)
})
let index = 0
if (result.objects !== undefined) {
yield result.objects.map(i => {
co(function* () {
yield client.delete(i.name)
index += 1
if (index === result.objects.length) {
console.log(`全部删除成功~,总共${result.objects.length}个文件`)
uploadFiles()
}
})
})
} else {
uploadFiles()
}
}).catch(function (err) {
console.log(err)
})
} else {
console.error('上传失败,线上路径为根目录~')
}
}
function uploadFiles() {
// 遍历目录树之后上传
glob(Config.localPath, {
nodir: true
}, (er, files) => {
let index = 0
files.map(i => {
co(function* () {
let ossPath = Config.ossPath.substr(Config.ossPath.length - 1, 1) === '/' ? Config.ossPath.slice(0, -1) : Config.ossPath
yield client.put(ossPath + i.slice(6), i)
index += 1
if (index === files.length) {
consoleStr(files.length)
}
}).catch(function (err) {
console.error(err.params.object)
})
})
})
}
function consoleStr(length) {
console.log(`全部上传成功~,总共${length}个文件`)
// http.get(Config.callbackUrl, () => {
// console.log('更新缓存成功~')
// }).on('error', (e) => {
// console.error(`错误: ${e.message}`)
// })
}
// 清空目录后上传
// deleteFiles()
// 增量上传
uploadFiles()
\ No newline at end of file
{
"region": "oss-cn-shenzhen",
"accessKeyId": "LTAIhDZsL5yCN90c",
"accessKeySecret": "LIj3OEJ8cMCQeRlUVVznJpMek2dPD2",
"bucket": "kdcdn",
"localPath": "./dist/**",
"ossPath": "/app/rtdn/",
"callbackUrl": "http://nodejs.org/dist/index.json"
}
\ No newline at end of file
This diff could not be displayed because it is too large.
{
"name": "vue-cli3-framework",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"dev": "vue-cli-service serve",
"build": "vue-cli-service build",
"fev": "vue-cli-service build --mode fev",
"lint": "vue-cli-service lint",
"oss": "node build/oss-released.js"
},
"dependencies": {
"ali-oss": "^6.1.1",
"amfe-flexible": "^2.2.1",
"axios": "^0.19.0",
"axios-mock-adapter": "^1.16.0",
"co": "^4.6.0",
"core-js": "^2.6.5",
"glob": "^7.1.4",
"mockjs": "^1.0.1-beta3",
"postcss-pxtorem": "^4.0.1",
"vue": "^2.6.10",
"vue-router": "^3.0.3",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.8.0",
"@vue/cli-plugin-eslint": "^3.8.0",
"@vue/cli-service": "^3.8.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"node-sass": "^4.12.0",
"sass-loader": "^7.1.0",
"vue-template-compiler": "^2.6.10"
}
}
module.exports = {
plugins: {
'autoprefixer': {
browsers: ['Android >= 4.0', 'iOS >= 7']
},
'postcss-pxtorem': {
rootValue: 75,
propList: ['*'],
selectorBlackList: []
}
}
}
\ No newline at end of file
No preview for this file type
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>vue-cli3-framework</title>
</head>
<body>
<noscript>
<strong>We're sorry but vue-cli3-framework doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<!-- <div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>-->
<router-view/>
</div>
</template>
<style lang="scss">
@import './styles/support.scss';
#app {
/* font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px; */
border: 0;
margin: 0;
padding: 0;
}
body,
div {
border: 0;
margin: 0;
padding: 0;
}
.app__width {
width: 750px;
}
.app__width {
width: 750px;
}
.app__inner {
margin: 20px;
}
.app__title {
font-size: $fontSize;
line-height: $fontSize + 4px;
font-weight: bold;
padding-bottom: 10px;
margin-bottom: 20px;
border-bottom: 0.5px solid #eeeeee;
}
.app__desc {
font-size: $fontSizeSmaller;
line-height: $fontSizeSmaller + 2px;
margin-bottom: 20px;
color: $colorGray;
}
.app__bgc {
position: fixed;
background-color: #ffffff;
width: 100%;
height: 100%;
}
.app__bg {
position: absolute;
width: 100%;
height: 100%;
}
.app__top-shadow {
position: fixed;
width: 750px;
height: 1px;
box-shadow: 0px 4px 0.9px 0.1px rgba(6, 0, 1, 0.07);
background-color: #ffffff;
}
.app__content {
position: relative;
}
</style>
module.exports = {
testListGet: '/xxx/xxx/list'
}
\ No newline at end of file
import axios from 'axios';
// import {
// Toast
// } from 'vant';
function Toast(msg) {
console.log("msg:", msg);
}
// axios的默认url
// axios.defaults.baseURL = ""
// 服务器地址
let base = "https://ow.go.qudone.com";
if (location.href.indexOf("//k.wxpai.cn") > 0) {
base = "https://api.k.wxpai.cn/bizproxy"
}
// let base = COM.baseUrl;
// 请求拦截器
// axios.interceptors.request.use(
// config => {
// // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
// // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
// const token = "token"; //这里写入token
// token && (config.headers.Authorization = token);
// return config;
// },
// error => {
// return Promise.error(error);
// })
// 响应拦截器
axios.interceptors.response.use(
response => {
if (response.status === 200) {
if (response.data.code === 200) {
return Promise.resolve(response);
} else {
Toast(response.data.bizMsg);
return Promise.reject(response);
}
} else {
return Promise.reject(response);
}
},
// 服务器状态码不是200的情况
error => {
if (error.response.status) {
switch (error.response.status) {
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
// 403 token过期
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
Toast({
message: '登录过期,请重新登录',
duration: 1000,
forbidClick: true
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
// 404请求不存在
case 404:
Toast({
message: '网络请求不存在',
duration: 1500,
forbidClick: true
});
break;
// 其他错误,直接抛出错误提示
default:
Toast({
message: error.response.data.message,
duration: 1500,
forbidClick: true
});
}
return Promise.reject(error.response);
}
}
);
//formDataHeaders设置
let formDataHeaders = {
headers: {
"Content-Type": "multipart/form-data"
}
}
/**
* 封装get方法
* @param {*} params
*/
export const httpGet = params => {
let {
url,
data
} = params;
return axios.get(`${base}${url}`, {
params: data
}).then(res => res.data.content);
}
/**
* 封装post方法
* @param {*} params
*/
export const httpPost = params => {
let {
url,
data
} = params;
return axios.post(`${base}${url}`, data).then(res => res.data.content);
}
/**
* 封装post方法
* @param {*} params
* data数据是 formdata格式
* 例如:
* this.file = file
let data = new FormData() //使用formData对象
data.append('path', '/pro/mzczcradmin/')
data.append('file', file.file)
*/
export const formdata = params => {
let {
url,
data
} = params;
return axios.post(`${base}${url}`, data, formDataHeaders).then(res => res.data);
}
\ No newline at end of file
import * as api from './api';
export default api;
// @font-face {
// font-family: 'vivo-BoldExtended';
// src: url('./vivo-BoldExtended.ttf');
// font-weight: normal;
// font-style: normal;
// }
// @font-face {
// font-family: 'vivo-Regular';
// src: url('./vivo-Regular.ttf');
// font-weight: normal;
// font-style: normal;
// }
// @font-face {
// font-family: 'regular2';
// src: url('./regular2.otf');
// font-weight: normal;
// font-style: normal;
// }
\ No newline at end of file
<template>
<div class="bottom-tips" v-if="visb">
<div class="line"></div>
<div class="tips-wrap">
<div class="tips">{{innerText ? innerText :'我是有底线的'}}</div>
</div>
</div>
</template>
<script>
export default {
props: ['visb', 'innerText'],
data() {
return {
key: 'value'
}
},
created() {
console.log('visb:', this.visb)
}
}
</script>
<style lang="less" scoped>
/// 底线
.bottom-tips {
position: relative;
padding: 40px 0;
width: 100%;
text-align: center;
color: #666666;
.line {
border-bottom: dashed 1px #cccccc;
width: 80%;
position: absolute;
top: 50%;
left: 0;
right: 0;
margin: 0 auto;
}
.tips-wrap {
font-size: 28px;
display: flex;
justify-content: center;
.tips {
position: relative;
padding: 0 20px;
background-color: #ffffff;
}
}
}
</style>
<template>
<div class="empty-tips" v-if="visb">
<div class="tips">
<span class="iconfont iconempty"></span>
<div class="tips">{{innerText ? innerText :'这里空空如也~'}}</div>
</div>
</div>
</template>
<script>
export default {
props: ['visb', 'innerText'],
data() {
return {
key: 'value'
}
}
}
</script>
<style lang="scss" scoped>
.empty-tips {
box-sizing: border-box;
position: fixed;
text-align: center;
color: #666666;
font-size: 32px;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
top: 35%;
.iconfont {
font-size: 100px;
}
.tips {
position: relative;
padding: 20px;
}
}
</style>
// 全局事件
module.exports = {
NAV_FILTER: '_nav_filter', // 导航菜单过滤,触发请求
TAB_SELECT: '_tab_select', // 选择tab ,主题 classify
EVT_SET_TAB_INDEX: '_evt_set_tab_index', // 选择tab ,主题 classify
EVT_TAB_INDEX_CHANGE: '_evt_tab_index_change', // 从navbar发至index 点击头部导航 index
}
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Mock from './mock'
Mock.bootstrap();
import 'amfe-flexible';
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
\ No newline at end of file
import Mock from 'mockjs';
const LoginUsers = [
{
id: 1,
username: 'admin',
password: 'admin',
avatar: 'https://raw.githubusercontent.com/taylorchen709/markdown-images/master/vueadmin/user.png',
name: '张某某'
}
];
const Users = [];
for (let i = 0; i < 5; i++) {
Users.push(Mock.mock({
id: Mock.Random.guid(),
province: Mock.Random.province(),
city: Mock.Random.city(),
fieldName: Mock.Random.cname(),
address: Mock.mock('@county(true)'),
'age|18-60': 1,
birth: Mock.Random.date(),
sex: Mock.Random.integer(0, 1)
}));
}
export { LoginUsers, Users };
import mock from './mock';
export default mock;
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import {
LoginUsers,
Users
} from './data/user';
let _Users = Users;
export default {
/**
* mock bootstrap
*/
bootstrap() {
return;
// 紧在dev环境下使用
if (process.env.NODE_ENV !== "development") {
return;
}
let mock = new MockAdapter(axios);
// mock success request
mock.onGet('/success').reply(200, {
msg: 'success'
});
// mock error request
mock.onGet('/error').reply(500, {
msg: 'failure'
});
// 拦截 get方法demo
mock.onGet('/path1/path2/getdemo').reply(config => {
// 拦截参数
let {
params1,
params2
} = config.params;
return new Promise((resolve, reject) => {
let content = {};
let success = true;
resolve([200, {
code: 2000,
msg: '请求成功',
success,
content
}]);
});
});
// 拦截post方法demo
mock.onPost('/path1/path2/postdemo').reply(config => {
let {
params1,
params2
} = JSON.parse(config.data);
return new Promise((resolve, reject) => {
let content = {};
let success = true;
resolve([200, {
code: 2000,
msg: '请求成功',
success,
content
}]);
});
});
}
};
<template>
<div class="about">
<h1>This is an about page</h1>
<div class="cc">
<div class="ddd"></div>
</div>
</div>
</template>
<style lang="scss" scoped>
.cc {
.ddd {
width: 746px;
height: 300px;
background-color: wheat;
}
}
</style>
<template>
<div class="home">home</div>
</template>
<script>
export default {
name: 'home'
}
</script>
<style lang="scss" scoped>
.home {
text-align: center;
}
</style>
import api from '../../api/api'
import {
httpGet,
httpPost
} from '../../api/fetch-api.js'
export default {
data() {
return {
key: 'value'
}
},
components: {},
methods: {
initData() {}
},
mounted() {},
created() {
console.log("demo created");
}
}
\ No newline at end of file
@import './../../styles/support';
<template>
<div class="page">
<div class="app__bgc bgc"></div>
<div class="app__bg bg"></div>
<div class="app__content main">
<div class="top-space"></div>
<div class="content">
<span class="iconfont iconclose">demo</span>
</div>
</div>
</div>
</template>
<script src="./index.js"></script>
<style lang="scss" scoped>
// @import './index.scss';
</style>
\ No newline at end of file
import Vue from 'vue'
import Router from 'vue-router'
import Home from './pages/Home.vue'
Vue.use(Router)
const routes = [{
path: '/',
name: 'home',
component: Home,
meta: {
title: '首页'
}
},
{
path: '/demo',
name: 'demo',
component: () => import('./pages/demo/index.vue'),
meta: {
title: '模板'
}
},
{
path: '/about',
name: 'about',
component: () => import('./pages/About.vue'),
meta: {
title: '关于'
}
}
]
// add route path
routes.forEach(route => {
route.path = route.path || '/' + (route.name || '');
});
const router = new Router({
routes
});
router.beforeEach((to, from, next) => {
const title = to.meta && to.meta.title;
if (title) {
document.title = title;
}
next();
});
export default router;
\ No newline at end of file
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
/* 图片字体 */
@font-face {
font-family: 'iconfont';
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAASEAAsAAAAACSAAAAQ3AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDSAqFGIQnATYCJAMYCw4ABCAFhG0HVBvZBxGVnNvIfhzYDV+BAe9wtJiGONTGYuHBZ/Oh77Q3OxupItOeFFTcQjpRXwK+AIbn08ne766XppsiwRKPksQTj7AO4xAOv3fOAdsJc0KNZO3Io89Lf8K9BkY+ce+4df4Dms+yXMacNNbEAOOAAtrbF1mBxAlqy/Dq8uqwrgMBiPGAD4g6dbgGQhSseQRAKstK8iFMmFAVBMHSdsFWFpkNHhYzhbkEYJb3efIGQUQIDCaFtXQ0l1KEhOfKV+G019Ary7GgbzgHAGEXUIAPABZIZ6GrGTSI+oBia7/A4gVAioWBeq58vvHlkJeNr8INBhIyy0dwwV8esJg4MBAgfGCVlKUNj/HguZIawGrqjZgLPHg5xACK1Y2YCwy8Cpdclo4/YIMIcBLANZh9YGkIPHta2NorTKxUSlUNV7Koz2zswo0mRfNNRs9fbFq8YJr5uEXLWo7cEd+6pbl9W3v3rj4g7tzRpU+7HauR0YbmJ2+dalLELZy6ude0uGh+75Zp5iXFCxZMW2Q+0IQOKsa7SMJIKH18h3y9hWY+mN4tEtW0bYT2memWpk1db7L81tQ7dgs3isUbt1rrl0kU0yy1Sza7ZCw0m4lCIzFMF2ww15+Qp1u43sRk/hJT7YJN5uaLluolPZSTvq1m4vmbgR7veM116OjBGp2K21oMbkRGnvqglnCLVharuAM6gl+toTNYPZs5doyZDXyHbx/RSvZMt6tNtx7RlzkWlcysWQySV2I+Pio008Np8mQvL/j0CEVLLIItloiEIPIFnCBDN7ZpC6n3i/erE0uXICT/t+269rVrjx4de+wrwynfjo1BaN/tXQmzJ3wIF9krghUHqN1eFB4fMvuCROrnvVwdkUeWLff2k70IiO8fs2yOabXpHHdlvX+A5rmK6dx4piXlbHunib+iNeVM+UnXFvWZjR2uleVF/jsbK12wo8OWDpY+TRH0jP8syLs0WIlOAIDhFHOP+gIA1TF3kCOBOcbaj9FjgYCJ97CEFvwt35GfKZ2Yq4j5JiGUsAC+Juu7saSZavDK1Wgs/jeaagB/Q0WUsuYutTOdIKDlmTLhATa03MskN0+G0t1vcjyETCMMArY4CLmQiuaDSSIETSgem7dBu0/G6o2REgGeJiAQSrvAkDsKSukyiaU9Bo+Zd+BTZgwxXdZHSrjFro4ZoqKlgj+VSe4UsdaVX3iDfgeR41KP8UIuNkCBfgHpxBUd8hArGj760FgVcZkjpaLbEAJTbWYHWTeltfaNvz9X9KJNIcfBSrIMhApapMAfKSOxjnJ6V6vM+29AewuEXNFR432BrLCDk0B+AhqQrqquUceljG7woR00qhQ7i5OxiKRiBwSIMlJbPMkBqdoo7RDuNfyZblxT1WZ6TbzLfbBZ53QYQglLeIRPBBB9hPTHH9oLMhQ5r5ipDFwwMRwxRezrfzAAAA==')
format('woff2');
}
.iconfont {
font-family: 'iconfont' !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconrefresh:before {
content: '\e874';
}
.iconempty:before {
content: '\e6a6';
}
.iconclose:before {
content: '\e849';
}
\ No newline at end of file
/**
* ------------------------------------------------------------------
* Sass Minxins
*
* 参考收集:
* https://github.com/twbs/bootstrap-sass/tree/master/assets/stylesheets/bootstrap/mixins
* ------------------------------------------------------------------
*
*/
// 文字截取
@mixin text-overflow() {
overflow: hidden;
white-space: normal;
text-overflow: ellipsis;
word-break: break-all;
word-wrap: normal;
}
@mixin word-break() {
word-break: break-all;
word-wrap: break-word;
white-space: normal;
}
// No wrap
@mixin no-wrap() {
word-break: normal;
word-wrap: normal;
white-space: nowrap;
}
// 清除浮动
@mixin clearfix() {
&:before,
&:after {
content: " "; // 1
display: table; // 2
}
&:after {
clear: both;
}
}
// Single side border-radius
@mixin border-top-radius($radius) {
border-top-right-radius: $radius;
border-top-left-radius: $radius;
}
@mixin border-right-radius($radius) {
border-bottom-right-radius: $radius;
border-top-right-radius: $radius;
}
@mixin border-bottom-radius($radius) {
border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius;
}
@mixin border-left-radius($radius) {
border-bottom-left-radius: $radius;
border-top-left-radius: $radius;
}
// Center-align a block level element
@mixin center-block() {
display: block;
margin-left: auto;
margin-right: auto;
}
// CSS image replacement
// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757
@mixin hide-text() {
font-size: 0;
line-height: 0;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
/**
* ------------------------------------------------------------------
* 支持文件
* 需要引用的地方均需要加上这个支持文件
*
* ------------------------------------------------------------------
*
*/
@import "mixins";
@import "var";
// 图标字体
@import "fonticon";
// 字体引入
@import './../assets/fonts/font.scss'
\ No newline at end of file
/**
* ------------------------------------------------------------------
* 原子类
*
* ------------------------------------------------------------------
*
*/
@import "support";
// Margin
.u-mt-smaller {
margin-top: $marginTopSmaller;
}
.u-mt-small {
margin-top: $marginTopSmall;
}
.u-mt-medium {
margin-top: $marginTopMedium;
}
.u-mt-large {
margin-top: $marginTopLarge;
}
.u-mt-larger {
margin-top: $marginTopLarger;
}
.u-mb-smaller {
margin-bottom: $marginTopSmaller;
}
.u-mb-small {
margin-bottom: $marginTopSmall;
}
.u-mb-medium {
margin-bottom: $marginTopMedium;
}
.u-mb-large {
margin-bottom: $marginTopLarge;
}
.u-mb-larger {
margin-bottom: $marginTopLarger;
}
// Padding
.u-pt-smaller {
padding-top: $paddingTopSmaller;
}
.u-pt-small {
padding-top: $paddingTopSmall;
}
.u-pt-medium {
padding-top: $paddingTopMedium;
}
.u-pt-large {
padding-top: $paddingTopLarge;
}
.u-pt-larger {
padding-top: $paddingTopLarger;
}
.u-pb-smaller {
padding-bottom: $paddingTopSmaller;
}
.u-pb-small {
padding-bottom: $paddingTopSmall;
}
.u-pb-medium {
padding-bottom: $paddingTopMedium;
}
.u-pb-large {
padding-bottom: $paddingTopLarge;
}
.u-pb-larger {
padding-bottom: $paddingTopLarger;
}
// 布局方位
.u-ta-c {
text-align: center !important;
}
.u-ta-l {
text-align: left !important;
}
.u-ta-r {
text-align: right !important;
}
.u-fl-l {
float: left;
}
.u-fl-n {
float: none;
}
.u-fl-r {
float: right;
}
.u-d-b {
display: block;
}
.u-d-i {
display: inline !important;
}
.u-d-ib {
display: inline-block !important;
}
.u-d-n {
display: none !important;
}
.u-d-t {
display: table;
table-layout: fixed;
}
.u-d-tc {
display: table-cell;
}
.u-va-b {
vertical-align: bottom;
}
.u-va-m {
vertical-align: middle;
}
.u-va-t {
vertical-align: top;
}
// clearfix
.u-clearfix {
@include clearfix;
}
// 虚拟格式
.u-cur-d {
cursor: default;
}
.u-cur-p {
cursor: pointer;
}
// flex
.u-flex {
display: -webkit-box;
display: -webkit-flex;
display: flex;
}
.u-flex-item {
-webkit-box-flex: 1;
-webkit-flex: 1;
flex: 1;
}
// 小程序中模拟ul、li
.u-ul {
padding-left: 30px;
text-align: left;
display: block;
}
.u-li {
position: relative;
font-size: $fontSizeSmall;
line-height: $fontSizeSmall + 4px;
margin-bottom: $marginTopSmall;
&:before {
position: absolute;
content: " ";
top: 14px;
left: -20px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: $colorBlack;
}
}
/**
* ------------------------------------------------------------------
* Sass 变量
*
* ------------------------------------------------------------------
*
*/
// Margin
$marginTopSmaller: 20px;
$marginTopSmall: 30px;
$marginTopMedium: 40px;
$marginTopLarge: 60px;
$marginTopLarger: 80px;
// Padding
$paddingTopSmaller: 20px;
$paddingTopSmall: 30px;
$paddingTopMedium: 40px;
$paddingTopLarge: 60px;
$paddingTopLarger: 80px;
// Color
$colorBlue: #20A0FF;
$colorGreen: #13CE66;
$colorGray: #475669;
$colorBlack: #000;
$colorRed: #FF4949;
$colorYellow: #F7BA2A;
$color: #787878;
$colorLink: #1D8CE0;
$backGroundColor: #fff;
// Font
$fontSize: 32px;
$fontSizeSmall: 28px;
$fontSizeSmaller: 24px;
$fontSizeLarge: 36px;
$fontSizeLarger: 44px;
// 正在表达式
export const REGEXPS = {
"mobile": /^1\d{10}$/
}
// 验证手机
export function checkMobile(str) {
return REGEXPS.mobile.test(str);
}
/**
* 链接参数转换为obj
* 入参 完整链接
* @param {*} url
*/
export function param2Obj(url) {
const search = url.split('?')[1]
if (!search) {
return {}
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
'"}'
)
}
//获取cookie、
export function getCookie(name) {
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg))
return (arr[2]);
else
return null;
}
//设置cookie
export function setCookie(c_name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
};
//删除cookie
export function delCookie(name) {
var exp = new Date();
exp.setTime(exp.getTime() - 1);
var cval = getCookie(name);
if (cval != null)
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
};
/**
* 获取环境信息
* @return {Object} 环境信息对象
*/
export function getEnv() {
var nav = window.navigator;
var env = {
"iphone": false,
"ipad": false,
"android": false,
"pc": false,
"ios": false,
"ver": "0"
};
var ua = nav.userAgent;
var android = ua.match(/(Android)\s+([\d.]+)/);
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
var iphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/);
if (ipad) {
env.ipad = ipad[1] && true || false;
env.ver = ipad[2] && ipad[2].replace(/-/g, ".") || "";
env.ios = true;
} else if (iphone) {
env.iphone = iphone[1] && true || false;
env.ver = iphone[2] && iphone[2].replace(/-/g, ".") || "";
env.ios = true;
} else if (android) {
env.android = android[1] && true || false;
env.ver = android[2];
} else {
env.pc = true;
}
return env;
}
/**
* 设定页面 title
* @param {[type]} title [description]
*/
export function setTitle(title) {
if (!title) {
return;
}
document.title = title;
// if (ENV.ios && navigator.userAgent.toLowerCase().indexOf("micromessenger") !== -1) {
// 修复微信端IOS无法修改document.title的情况
if (getEnv().ios && (navigator.userAgent.toLowerCase().indexOf("micromessenger") !== -1 || navigator.userAgent.toLowerCase().indexOf("alipay") !== -1)) {
//修复IOS微信端和支付宝无法修改document.title的情况
var $iframe = document.createElement('iframe');
$iframe.className = "C-hiddenIframe";
$iframe.src = "/" + location.pathname.split('/')[1] + "/favicon.ico";
$iframe.style.visibility = 'hidden';
$iframe.style.width = '1px';
$iframe.style.height = '1px';
$iframe.onload = function onIframeLoad() {
setTimeout(function () {
$iframe.onload = null;
onIframeLoad = null;
document.body.removeChild($iframe);
$iframe = null;
}, 0);
};
document.body.appendChild($iframe);
}
}
// 为链接添加参数
export function addQuery(url, query) {
query = query || {}
query = (function (query) {
var q = []
Object.keys(query).forEach(function (_q) {
q.push(_q + '=' + query[_q])
})
return q.join('&')
})(query)
if (url.indexOf('?') !== -1) {
url += '&' + query
} else {
url += '?' + query
}
return url
}
/**
* 获得当前页面的path
* @return {String} 页面path
*/
export function getPath() {
var path = window.location.hash;
path = path || "#/";
path = path === "#/" ? "#/index" : path;
path = path.split("?");
return path[0];
}
// 获取 url 参数
export function getQuery(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ""])[1].replace(/\+/g, '%20')) || null;
}
/**
* 把 \n换行符转换成<br>
* 转换后需要用 v-html渲染
* 用{{}}会当成字符串把 html渲染出来
*/
export function formatBr(str) {
str = str.replace(/\n/g, '<br/>')
return str
};
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
export function debounce(func, wait, immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
} else {
timeout = setTimeout(function () {
func.apply(context, args)
}, wait);
}
}
}
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
* 时间戳版的函数触发是在时间段内开始的时候,而定时器版的函数触发是在时间段内结束的时候。
*/
export function throttle(func, wait, type) {
if (type === 1) {
var previous = 0;
} else if (type === 2) {
var timeout;
}
return function () {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
\ No newline at end of file
import wx from 'weixin-js-sdk';
wx.ready(function () { //通过ready接口处理成功验证
// config信息验证成功后会执行ready方法
wx.onMenuShareAppMessage({ // 分享给朋友 ,在config里面填写需要使用的JS接口列表,然后这个方法才可以用
title: '这里是标题', // 分享标题
desc: 'This is a test!', // 分享描述
link: '链接', // 分享链接
imgUrl: '图片', // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
wx.onMenuShareTimeline({ //分享朋友圈
title: '标题', // 分享标题
link: '链接',
imgUrl: '图片', // 分享图标
success: function () {
// 用户确认分享后执行的回调函数
},
cancel: function () {
// 用户取消分享后执行的回调函数
}
});
});
wx.error(function (res) {//通过error接口处理失败验证
// config信息验证失败会执行error函数
});
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: '', // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名,见附录1
jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
// 打包目录
let webpack_public_path = 'dist'
if (process.env.NODE_ENV === 'production') {
webpack_public_path = process.env.VUE_APP_TITLE
}
module.exports = {
// 部署生产环境和开发环境下的URL。
// 默认情况下,Vue CLI 会假设你的应用是被部署在一个域名的根路径上
//例如 https://www.my-app.com/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.my-app.com/my-app/,则设置 baseUrl 为 /my-app/。
//baseUrl 从 Vue CLI 3.3 起已弃用,请使用publicPath
//baseUrl: process.env.NODE_ENV === "production" ? "./" : "/",
publicPath: process.env.NODE_ENV === "dev" ? "/" : "./",
// outputDir: 在npm run build 或 yarn build 时 ,生成文件的目录名称(要和baseUrl的生产环境路径一致)
outputDir: webpack_public_path,
//用于放置生成的静态资源 (js、css、img、fonts) 的;(项目打包之后,静态资源会放在这个文件夹下)
assetsDir: "assets",
//指定生成的 index.html 的输出路径 (打包之后,改变系统默认的index.html的文件名)
// indexPath: "myIndex.html",
//默认情况下,生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存。你可以通过将这个选项设为 false 来关闭文件名哈希。(false的时候就是让原来的文件名不改变)
filenameHashing: false,
// lintOnSave:{ type:Boolean default:true } 问你是否使用eslint
lintOnSave: true,
//如果你想要在生产构建时禁用 eslint-loader,你可以用如下配置
// lintOnSave: process.env.NODE_ENV !== 'production',
//是否使用包含运行时编译器的 Vue 构建版本。设置为 true 后你就可以在 Vue 组件中使用 template 选项了,但是这会让你的应用额外增加 10kb 左右。(默认false)
// runtimeCompiler: false,
/**
* 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
* 打包之后发现map文件过大,项目文件体积很大,设置为false就可以不输出map文件
* map文件的作用在于:项目打包后,代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。
* 有了map就可以像未加密的代码一样,准确的输出是哪一行哪一列有错。
* */
productionSourceMap: false,
// 它支持webPack-dev-server的所有选项
devServer: {
host: "localhost",
port: 9001, // 端口号
https: false, // https:{type:Boolean}
open: true, //配置自动启动浏览器
// proxy: 'http://localhost:4000' // 配置跨域处理,只有一个代理
}
};
\ No newline at end of file