Commit 8cad5f7b by hanjixin

Merge branch 'master' into 'develop'

初始化控制端



See merge request !1
parents 1f63bd37 f872c89f
**/node_modules
node_modules
node_modules
log/*
\ No newline at end of file
> 1%
last 2 versions
NODE_ENV='development'
VUE_APP_BASE_API='//101.200.226.48:8088'
\ No newline at end of file
NODE_ENV='production'
VUE_APP_BASE_API='//39.97.170.243:9527'
\ No newline at end of file
NODE_ENV='production'
VUE_APP_BASE_API='//101.200.226.48:8088'
\ 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'
},
parserOptions: {
parser: 'babel-eslint'
}
}
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/test/unit/coverage/
/test/e2e/reports/
selenium-debug.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
## 简介
- 该项目提供了基于vue-cli3 创建的项目模板
## 前序准备
你需要在本地安装 [node](http://nodejs.org/)[git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)[vue](https://cn.vuejs.org/index.html)[vuex](https://vuex.vuejs.org/zh-cn/)[vue-router](https://router.vuejs.org/zh-cn/)[axios](https://github.com/axios/axios) 提前了解和学习这些知识会对使用本项目有很大的帮助
## 功能
```
- 登录 / 注销
- 路由拦截
- css 预处理 scss
- request Handle
- build clear 开发日志
- src/utils 常用工具
- 全局环境变量文件
- .env.develop
- .env.test
- .env.production
- 多环境发布
- dev test prod
```
## 开发
```bash
# 克隆项目
git clone git@github.com:hanjixin/vue3-es6-project.git
# 安装依赖
npm install
# 建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 启动服务
npm run dev || npm run start || npm run serve
```
浏览器访问 http://localhost:8080
## 发布
```bash
# 构建测试环境
npm run build:test
# 构建生产环境
npm run build
```
## 其它
```
commit auto fix eslint
```
## 简介
- 该项目提供了基于vue-cli3 创建的项目模板
## 前序准备
你需要在本地安装 [node](http://nodejs.org/)[git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)[vue](https://cn.vuejs.org/index.html)[vuex](https://vuex.vuejs.org/zh-cn/)[vue-router](https://router.vuejs.org/zh-cn/)[axios](https://github.com/axios/axios) 提前了解和学习这些知识会对使用本项目有很大的帮助
## 功能
```
- 登录 / 注销
- 路由拦截
- css 预处理 scss
- request Handle
- build clear 开发日志
- src/utils 常用工具
- 全局环境变量文件
- .env.develop
- .env.test
- .env.production
- 多环境发布
- dev test prod
```
## 开发
```bash
# 克隆项目
git clone git@github.com:hanjixin/vue3-es6-project.git
# 安装依赖
npm install
# 建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 启动服务
npm run dev || npm run start || npm run serve
```
浏览器访问 http://localhost:8080
## 发布
```bash
# 构建测试环境
npm run build:test
# 构建生产环境
npm run build
```
## 其它
```
commit auto fix eslint
```
module.exports = {
presets: [
'@vue/app'
]
}
{
"name": "vue-project-template",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode develop",
"dev": "npm run serve",
"start": "npm run serve",
"build": "vue-cli-service build --mode production",
"build:test": "vue-cli-service build --mode test",
"lint": "vue-cli-service lint",
"test:unit": "vue-cli-service test:unit"
},
"dependencies": {
"axios": "^0.19.0",
"babel-polyfill": "^6.26.0",
"core-js": "^2.6.5",
"cross-env": "^5.2.0",
"lib-flexible": "^0.3.2",
"postcss-pxtorem": "^4.0.1",
"register-service-worker": "^1.6.2",
"uglifyjs-webpack-plugin": "^2.1.3",
"vconsole": "^3.3.4",
"vue": "^2.6.10",
"vue-awesome-swiper": "^3.1.3",
"vue-router": "^3.1.5",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.8.0",
"@vue/cli-plugin-eslint": "^3.8.0",
"@vue/cli-plugin-pwa": "^3.8.0",
"@vue/cli-plugin-unit-mocha": "^3.8.0",
"@vue/cli-service": "^3.8.0",
"@vue/test-utils": "1.0.0-beta.29",
"babel-eslint": "^10.0.1",
"chai": "^4.1.2",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"lint-staged": "^8.1.5",
"node-sass": "^4.9.0",
"sass-loader": "^7.1.0",
"vue-template-compiler": "^2.6.10"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,vue}": [
"vue-cli-service lint --fix --no-verify",
"git add"
]
}
}
module.exports = {
plugins: {
'autoprefixer': {
browsers: ['Android >= 4.0', 'iOS >= 7']
},
// 'postcss-pxtorem': {
// rootValue: 36,
// propList: ['*']
// }
}
}
\ No newline at end of file
//本插件由www.swiper.com.cn提供
//版本1.03
function swiperAnimateCache(a){for(j=0;j<a.slides.length;j++)for(allBoxes=a.slides[j].querySelectorAll(".ani"),i=0;i<allBoxes.length;i++)allBoxes[i].attributes["style"]?allBoxes[i].setAttribute("swiper-animate-style-cache",allBoxes[i].attributes["style"].value):allBoxes[i].setAttribute("swiper-animate-style-cache"," "),allBoxes[i].style.visibility="hidden"}function swiperAnimate(a){clearSwiperAnimate(a);var b=a.slides[a.activeIndex].querySelectorAll(".ani");for(i=0;i<b.length;i++)b[i].style.visibility="visible",effect=b[i].attributes["swiper-animate-effect"]?b[i].attributes["swiper-animate-effect"].value:"",b[i].className=b[i].className+" "+effect+" "+"animated",style=b[i].attributes["style"].value,duration=b[i].attributes["swiper-animate-duration"]?b[i].attributes["swiper-animate-duration"].value:"",duration&&(style=style+"animation-duration:"+duration+";-webkit-animation-duration:"+duration+";"),delay=b[i].attributes["swiper-animate-delay"]?b[i].attributes["swiper-animate-delay"].value:"",delay&&(style=style+"animation-delay:"+delay+";-webkit-animation-delay:"+delay+";"),b[i].setAttribute("style",style)}function clearSwiperAnimate(a){for(j=0;j<a.slides.length;j++)for(allBoxes=a.slides[j].querySelectorAll(".ani"),i=0;i<allBoxes.length;i++)allBoxes[i].attributes["swiper-animate-style-cache"]&&allBoxes[i].setAttribute("style",allBoxes[i].attributes["swiper-animate-style-cache"].value),allBoxes[i].style.visibility="hidden",allBoxes[i].className=allBoxes[i].className.replace("animated"," "),allBoxes[i].attributes["swiper-animate-effect"]&&(effect=allBoxes[i].attributes["swiper-animate-effect"].value,allBoxes[i].className=allBoxes[i].className.replace(effect," "))}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script src="./common/swiper.animate1.0.2.min.js"></script>
<link rel="stylesheet" href="./common/animate.css">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>气象局</title>
</head>
<body>
<noscript>
<strong>We're sorry but vue-project-template 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>
{
"name": "vue-project-template",
"short_name": "vue-project-template",
"icons": [
{
"src": "./img/icons/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "./img/icons/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#4DBA87"
}
User-agent: *
Disallow:
<template>
<div id="app">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</template>
<script>
import index from './views/index'
export default {
components: {
index
}
}
</script>
<style lang="scss">
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
import { apiRequest, post, get } from './index';
export function getToken(code) {
return get(`/wechat/get/accesstoken/${code}`);
}
export function getSignatrue(url) {
return post('/wechat/getSigntrue', {
url
})
}
export function loginout() {
return apiRequest({
url: 'loginOut',
method: 'post',
data: {}
});
}
import request from '@/utils/request'
function requestHandle (res) {
return new Promise((resolve, reject) => {
// console.log(res)
if(res.status == 200 && res.data.code === '0') {
resolve(res)
} else {
reject(res)
}
})
}
export function apiRequest( obj = {
method: 'get'
}) {
if (obj.method === 'get' || obj.method === 'GET') {
obj.method = 'get'
obj.params = obj.params || obj.data
delete obj.data
} else {
obj.data = obj.data || obj.params
delete obj.params
}
return request(obj).then(res => {
console.log('then')
return requestHandle(res)
}).catch(err => {
console.log('catch', JSON.stringify(err))
return requestHandle(err)
})
}
export function get (url, params) {
return apiRequest({
method: 'get',
url,
params
})
}
export function post (url, data) {
return apiRequest({
method: 'post',
url,
data
})
}
export function deleted (url, params) {
return apiRequest({
method: 'delete',
url,
params
})
}
export function put (url, data) {
return apiRequest({
method: 'put',
url,
data
})
}
\ No newline at end of file
import { apiRequest, post } from './index'
export function login (username, password) {
return post('login',{
username,
password
})
}
export function loginout () {
return apiRequest({
url: 'loginOut',
method: 'post',
data: {
}
})
}
\ No newline at end of file
* {
margin: 0;
padding: 0;
}
// @font-face {
// font-family: FZDHTJW;
// src: url(./FZDHTJW.TTF);
// }
body {
font-family: FZDHTJW, Tahoma, Helvetica, Arial;
height: 100%;
}
html, body {
height: 100%;
-webkit-text-size-adjust: none !important;
overflow: hidden;
}
body {
-webkit-text-size-adjust: none !important;
}
body {
-webkit-text-size-adjust: 100% !important;
}
.page-container {
position: relative;
height: 100%;
width: 100%;
}
\ No newline at end of file
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa" target="_blank" rel="noopener">pwa</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-unit-mocha" target="_blank" rel="noopener">unit-mocha</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div>
<img
src='../assets/img/music_icon.png'
alt
:class="{
'runAnimation': isPlay,
'stopAnimation': !isPlay
}"
@click="playAudio"
style="
width: 33.5476px;
height: 33.5476px;
right: 16.875px;
top: 16.875px;
opacity: 1;
position: absolute;
display: block;
z-index: 1000000;
transform-origin: center center;
animation: 5s linear 0s infinite normal forwards running rotateRound;
touch-action: pan-y;
user-select: none;
-webkit-user-drag: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
"
/>
<audio id="bgMp3" src='../assets/bg.mp3' preload loop></audio>
</div>
</template>
<script>
export default {
data() {
return {
isPlay: false
}
},
methods: {
playAudio() {
var audio = document.querySelector('#bgMp3')
if(audio.paused){
this.isPlay = true
audio.play();
return;
} else {
this.isPlay = false
audio.pause();
}
}
},
mounted () {
var audio = document.querySelector('#bgMp3')
var _this = this
document.addEventListener("WeixinJSBridgeReady", function () {
window.WeixinJSBridge.invoke('getNetworkType', {}, function () {
audio.play();
_this.isPlay = true
});
}, false);
console.log(audio.paused)
audio.play();
this.isPlay = true
}
};
</script>
<style lang="scss">
@keyframes rotateRound {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
.stopAnimation {
animation-play-state: paused !important;
}
.runAnimation {
animation-play-state: running !important;
}
</style>
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import router from './router'
import '@/assets/app.scss';
// import '@/assets/animate.scss';
import 'lib-flexible'
// import VConsole from 'vconsole'
// new VConsole();
// console.log('Hello world');
Vue.config.productionTip = false
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')
},
updatefound () {
console.log('New content is downloading.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/views/Home.vue';
import { $url } from '@/utils/share';
import store from '../store';
Vue.use(Router);
const router = new Router({
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: () =>
import(/* webpackChunkName: "about" */ '@/views/About.vue')
}
]
});
router.beforeEach((from, to, next) => {
// 路由拦截
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (pair[0] == variable) {
return pair[1];
}
}
return false;
}
const token = store.state.user.token
const code = getQueryVariable('code');
if (
to.path === '/shop' ||
from.path === '/shop' ||
from.path === '/clear' ||
to.path === '/clear'
) {
next();
return;
}
if (code && !token) {
next()
// store.dispatch('GetToken', code).then(() => {
// next();
// });
} else {
if (!token && !getQueryVariable('code')) {
console.log($url, window.location.href);
window.localStorage.setItem('callbackurl', window.location.href);
setTimeout(() => {
location.replace($url);
}, 1000);
} else {
next();
}
}
});
export default router;
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token
}
export default getters
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
user
},
getters
})
export default store
const app = {
state: {
sidebar: {
opened: !+localStorage.getItem('sidebarStatus'),
withoutAnimation: false
},
device: 'desktop'
},
mutations: {
TOGGLE_SIDEBAR: state => {
if (state.sidebar.opened) {
localStorage.setItem('sidebarStatus', 1)
} else {
localStorage.setItem('sidebarStatus', 0)
}
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
},
CLOSE_SIDEBAR: (state, withoutAnimation) => {
localStorage.setItem('sidebarStatus', 1)
state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation
},
TOGGLE_DEVICE: (state, device) => {
state.device = device
}
},
actions: {
ToggleSideBar: ({
commit
}) => {
commit('TOGGLE_SIDEBAR')
},
CloseSideBar({
commit
}, {
withoutAnimation
}) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
ToggleDevice({
commit
}, device) {
commit('TOGGLE_DEVICE', device)
}
}
}
export default app
import { getToken, setToken } from '@/utils/auth';
import { getToken as getUserToken } from '@/api/api';
const user = {
state: {
token: process.env.NODE_ENV === 'production' ? getToken() : '1',
name: ''
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token;
setToken(token);
localStorage.setItem('token', token)
}
},
actions: {
// 获取用户信息
GetToken({ commit }, code) {
return new Promise((resolve, reject) => {
getUserToken(code)
.then(res => {
commit('SET_TOKEN', res.data.data);
resolve(res);
console.log(res);
})
.catch(err => {
reject(err);
});
});
}
}
};
export default user;
const TokenKey = 'token'
export function getToken() {
return localStorage.getItem(TokenKey)
}
export function setToken(token) {
return localStorage.setItem(TokenKey, token)
}
export function removeToken() {
return localStorage.removeItem(TokenKey)
}
/**
* 从KV集合中获取指定ID的value
* @param {array} _list
* @param {int} _id
*/
export function getValueFromKVs(_list, _id) {
let obj = {};
obj = _list.find(item => {
return item.id === _id;
});
return obj.value;
}
/**
* 是否是合法的下标
* @param {int} index
*/
export const isInvlidIndex = function (index) {
if (isInvlidData(index) && index > -1) {
return true;
} else {
return false;
}
}
/**
* 是否是合法的数据,不为undefined或者null
* @param {int} data
*/
export const isInvlidData = function (data) {
if (typeof (data) != "undefined" && data != null) {
return true;
} else {
return false;
}
}
/**
* 删除某一个数组内的对象, 返回数组对象
* @param {array} _arr
* @param {object} _obj
*/
export function removeObjFromArr(_arr, _obj) {
var length = _arr.length;
for (var i = 0; i < length; i++) {
if (JSON.stringify(_arr[i]) == JSON.stringify(_obj)) {
if (i == 0) {
_arr.shift();
return _arr;
} else if (i == length - 1) {
_arr.pop();
return _arr;
} else {
_arr.splice(i, 1);
return _arr;
}
}
}
}
/**
* 删除某一个数组内的对象, 返回数组对象
* @param {array} _arr
* @param {int} _index
*/
export function removeFromArr(_arr, _index) {
_arr.splice(_index, 1);
return _arr;
}
/**
* 判断数组中是否存在指定属性的对象
* @param {array} _arr
* @param {string} _propName
* @param {string} _prop
*/
export function existInArrWithProp(_arr, _propName, _prop) {
let isExist = false;
var length = _arr.length;
for (var i = 0; i < length; i++) {
if (_arr[i][_propName] && _arr[i][_propName] == _prop) {
isExist = true;
}
}
return isExist;
}
/**
* 判断数组中是否存在
* @param {array} _arr
* @param {object} _obj
*/
export function existInArr(_arr, _obj) {
let isExist = false;
var length = _arr.length;
for (var i = 0; i < length; i++) {
if (JSON.stringify(_arr[i]) == JSON.stringify(_obj)) {
isExist = true;
}
}
return isExist;
}
/**
* 获取某个下拉菜单的value数值
* @param {array} _list
* @param {int} id
*/
export function getValueFromList(_list, id) {
return getPropFromList(_list, id, "value");
}
/**
* 获取某个集合的特定对象的特定属性
* @param {array} _list
* @param {int} id
* @param {string} propName
*/
export function getPropFromList(_list, id, propName) {
let obj = {};
obj = _list.find(item => {
return item.id === id;
});
if (obj) {
return obj[propName];
}
return null;
}
/**
* 获取题干
* @param {string} _content
*/
export function getStemFromContent(_content) {
let stem = "";
if (_content) {
try {
let obj = JSON.parse(_content);
stem = obj.stem;
} catch (e) {
console.log(_content);
console.log(e);
}
}
return stem;
}
/**
* 时间转换
* @param {date} time
* @param {string} cFormat
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null;
}
if (time === null) {
return "-";
}
if ((time + "").length === 10) {
time = +time * 1000;
}
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}";
let date;
if (typeof time === "object") {
date = time;
} else {
date = new Date(parseInt(time));
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key];
if (key === "a") {
return ["一", "二", "三", "四", "五", "六", "日"][value - 1];
}
if (result.length > 0 && value < 10) {
value = "0" + value;
}
return value || 0;
});
return time_str;
}
/**
* 数组中删除一个对象,并返回下标
* @param {array} _arr
* @param {object} _obj
*/
export function arrRemoveLists(_arr, _obj) {
var length = _arr.length;
for (var i = 0; i < length; i++) {
if (JSON.stringify(_arr[i]) == JSON.stringify(_obj)) {
if (i == 0) {
_arr.shift(); //删除并返回数组的第一个元素
return i;
} else if (i == length - 1) {
_arr.pop(); //删除并返回数组的最后一个元素
return i;
} else {
_arr.splice(i, 1); //删除下标为i的元素
return i;
}
} else {
console.log(_obj + "row");
}
}
return -1;
}
(function flexible (window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1
// adjust body font size
function setBodyFontSize () {
if (document.body) {
document.body.style.fontSize = (12 * dpr) + 'px'
}
else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize();
// set 1rem = viewWidth / 10
function setRemUnit () {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}
setRemUnit()
// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})
// detect 0.5px supports
if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)
if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
}(window, document))
/**
* Created by jiachenpan on 16/11/18.
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
if(typeof time === 'string') {
time = time.replace(/-/g,'/')
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if (('' + time).length === 10) time = parseInt(time) * 1000
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
export function formatTime(time, option) {
time = +time * 1000
const d = new Date(time)
const now = Date.now()
const diff = (now - d) / 1000
if (diff < 30) {
return '刚刚'
} else if (diff < 3600) {
// less 1 hour
return Math.ceil(diff / 60) + '分钟前'
} else if (diff < 3600 * 24) {
return Math.ceil(diff / 3600) + '小时前'
} else if (diff < 3600 * 24 * 2) {
return '1天前'
}
if (option) {
return parseTime(time, option)
} else {
return (
d.getMonth() +
1 +
'月' +
d.getDate() +
'日' +
d.getHours() +
'时' +
d.getMinutes() +
'分'
)
}
}
import axios from 'axios'
import store from '../store'
import {
removeToken
} from '@/utils/auth'
// 创建axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // api 的 base_url
timeout: 10 * 1000 // 请求超时时间, 10秒
})
// request拦截器
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['userToken'] = store.state.user.token // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
},
error => {
// Do something with request error
return Promise.reject(error)
}
)
// response 拦截器
service.interceptors.response.use(
response => {
return response
},
/**
* 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
* 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
*/
// const res = response.data;
// if (res.code !== 20000) {
// Message({
// message: res.message,
// type: 'error',
// duration: 5 * 1000
// });
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
// confirmButtonText: '重新登录',
// cancelButtonText: '取消',
// type: 'warning'
// }).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload();// 为了重新实例化vue-router对象 避免bug
// });
// })
// }
// return Promise.reject('error');
// } else {
// return response.data;
// }
err => {
console.dir(err);
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = `${err.response.data.message}`
break
case 401:
//重新登录
removeToken();
err.message = `${err.response.data.message}`
break
case 403: //没有权限
err.message = `${err.response.data.message}`
break
case 404:
if (err.response.data.message) {
err.message = `${err.response.data.message},请检查!`;
} else {
err.message = `请求地址出错: ${err.response.config.url}`
}
break
case 405:
err.message = `方法错误: ${err.response.data.message}`
break
case 406: //请求格式错误
err.message = '请求超时'
break
case 408:
err.message = '请求超时'
break
case 410:
//用户请求的资源被永久删除,且不会再得到的
err.message = '请求超时'
break
case 422:
//当创建一个对象时,发生一个验证错误。
err.message = '请求超时'
break
case 500:
err.message = `${err.response.data.message}`
break
case 501:
err.message = '服务未实现'
break
case 502:
err.message = '网关错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网关超时'
break
case 505:
err.message = 'HTTP版本不受支持'
break
}
}
console.log(err.message)
return Promise.reject(err.response)
}
)
export default service
const wx = window.wx;
const $appid = 'wx04343d403aa2482c';
// const $redirect_uri = encodeURI(location.href);
const $redirect_uri = encodeURI('https://h5.zhuiyuanwenhua.cn');
export const $url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${$appid}&redirect_uri=${$redirect_uri}&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect`;
import { getSignatrue } from '@/api/api';
function isIOS() {
let isIphone = navigator.userAgent.includes('iPhone');
let isIpad = navigator.userAgent.includes('iPad');
return isIphone || isIpad;
}
function Share(title, des, link) {
getSignatrue(location.href.split('#')[0]).then(res => {
console.log(res, 'getSignatrue');
if(isIOS() && window.sessionStorage.getItem('isIosShare')) {
return
}
if(isIOS()) {
window.sessionStorage.setItem('isIosShare', '1')
}
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: $appid, // 必填,企业号的唯一标识,此处填写企业号corpid
timestamp: res.data.data.timestamp, // 必填,生成签名的时间戳
nonceStr: res.data.data.nonceStr, // 必填,生成签名的随机串
signature: res.data.data.signature, // 必填,签名,见附录1
jsApiList: [
'onMenuShareTimeline', // 分享到朋友圈
'onMenuShareAppMessage', // 分享到微信好友
'onMenuShareQQ', // 分享到QQ
'onMenuShareWeibo', // 分享到微博
'onMenuShareQZone', // 分享到空间
'openLocation'
] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});
});
wx.error(function(res) {
alert(JSON.stringify(res));
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
wx.ready(function() {
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
//分享到朋友圈
wx.onMenuShareTimeline({
title: title, // 分享标题
link: link || link, // 分享链接,该链接域名必须与当前企业的可信域名一致
imgUrl: 'https://h5.zhuiyuanwenhua.cn/share.jpeg', // 分享图标
success: function() {
// 用户确认分享后执行的回调函数
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
});
//分享给朋友
wx.onMenuShareAppMessage({
title: title, // 分享标题
desc: des || '', // 分享描述
link: link || link, // 分享链接,该链接域名必须与当前企业的可信域名一致
imgUrl: 'https://h5.zhuiyuanwenhua.cn/share.jpeg', // 分享图标
type: '', // 分享类型,music、video或link,不填默认为link
dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
success: function() {
// 用户确认分享后执行的回调函数
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
});
// 微博
wx.onMenuShareWeibo({
title: title, // 分享标题
desc: des || '', // 分享描述
link: link || link, // 分享链接,该链接域名必须与当前企业的可信域名一致
imgUrl: 'https://h5.zhuiyuanwenhua.cn/share.jpeg', // 分享图标
success: function() {
// 用户确认分享后执行的回调函数
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
});
// QQ
wx.onMenuShareQZone({
title: title, // 分享标题
desc: des || '', // 分享描述
link: link || link, // 分享链接,该链接域名必须与当前企业的可信域名一致
imgUrl: 'https://h5.zhuiyuanwenhua.cn/share.jpeg', // 分享图标
success: function() {
// 用户确认分享后执行的回调函数
},
cancel: function() {
// 用户取消分享后执行的回调函数
}
});
});
}
export default Share;
/**
* Created by jiachenpan on 16/11/18.
*/
export function isvalidUsername(str) {
const valid_map = ['lisi', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
/* 合法uri*/
export function validateURL(textval) {
const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return urlregex.test(textval)
}
/* 小写字母*/
export function validateLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
}
/* 大写字母*/
export function validateUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
}
/* 大小写字母*/
export function validatAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}
<template>
<div>
about
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<div>
home
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
\ No newline at end of file
<template>
<div>
<swiper
:options="swiperOption"
ref="mySwiper"
class="g-container">
<!-- slides -->
<swiper-slide>123</swiper-slide>
<!-- Optional controls -->
<!-- <div class="swiper-pagination" slot="pagination"></div>
<div class="swiper-button-prev" slot="button-prev"></div>
<div class="swiper-button-next" slot="button-next"></div>
<div class="swiper-scrollbar" slot="scrollbar"></div> -->
</swiper>
</div>
</template>
<script>
import "swiper/dist/css/swiper.css";
import { swiper, swiperSlide } from "vue-awesome-swiper";
export default {
name: "carrousel",
components: {
swiper,
swiperSlide
},
data() {
return {
percentNum: 0,
swiperOption: {
direction: "vertical",
loop: true,
// autoplay: {
// delay: 8000
// },
on: {
init: function() {
window.swiperAnimateCache(this); //隐藏动画元素
window.swiperAnimate(this); //初始化完成开始动
},
slideChangeTransitionEnd: function() {
console.log("改变了,activeIndex为" + this.activeIndex);
window.swiperAnimate(this);
}
}
}
};
},
computed: {
// swiper() {
// return this.$refs.mySwiper.swiper;
// }
},
methods: {
},
created() {
},
mounted() {
// current swiper instance
console.log("this is current swiper instance object", this.swiper);
}
};
</script>
<style lang="scss" scoped>
.g-container {
height: 640px;
width: 360px;
margin: 0 auto;
.swiper-slide {
height: 100% !important;
}
margin-top: calc((100vh - 640px) / 2);
}
</style>
\ No newline at end of file
let str = "2018-10-23 16:46:50";
function formatTime(date) {
const just = 1000 * 60 * 3;
const minute = 1000 * 60;
const hour = 1000 * 60 * 60;
const day = hour * 24;
const month = day * 30;
const year = day * 365;
console.log(typeof date);
if (typeof date === "string") {
date = date.replace("-", "/");
}
let times = new Date(date).getTime();
const now = new Date().getTime();
const value = now - times;
console.log(times, now, value, just, 0 <= value && value <= just);
if (0 <= value && value <= just) {
return "刚刚";
} else if (just < value && value < hour) {
return parseInt(value / minute) + "分钟前";
} else if (hour < value && value < day) {
return parseInt(value / hour) + "小时前";
} else if (day < value && value < month) {
return parseInt(value / day) + "天前";
} else if (month < value && value < year) {
return parseInt(value / month) + "月前";
} else if (year < value) {
return parseInt(value / year) + "年前";
} else {
return "未来";
}
}
console.log(formatTime(str));
let str = "2018-10-23 16:46:50";
function formatTime(date) {
const just = 1000 * 60 * 3;
const minute = 1000 * 60;
const hour = 1000 * 60 * 60;
const day = hour * 24;
const month = day * 30;
const year = day * 365;
console.log(typeof date);
if (typeof date === "string") {
date = date.replace("-", "/");
}
let times = new Date(date).getTime();
const now = new Date().getTime();
const value = now - times;
console.log(times, now, value, just, 0 <= value && value <= just);
if (0 <= value && value <= just) {
return "刚刚";
} else if (just < value && value < hour) {
return parseInt(value / minute) + "分钟前";
} else if (hour < value && value < day) {
return parseInt(value / hour) + "小时前";
} else if (day < value && value < month) {
return parseInt(value / day) + "天前";
} else if (month < value && value < year) {
return parseInt(value / month) + "月前";
} else if (year < value) {
return parseInt(value / year) + "年前";
} else {
return "未来";
}
}
console.log(formatTime(str));
module.exports = {
env: {
mocha: true
}
}
\ No newline at end of file
import { expect } from 'chai'
import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld.vue', () => {
it('renders props.msg when passed', () => {
const msg = 'new message'
const wrapper = shallowMount(HelloWorld, {
propsData: { msg }
})
expect(wrapper.text()).to.include(msg)
})
})
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
// 生产环境是否生成 sourceMap 文件
productionSourceMap: false,
//是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
parallel: require('os').cpus().length > 1,
// 所有 webpack-dev-server 的选项都支持
devServer: {
port: 8080, // 配置端口
open: true, // 自动开启浏览器
compress: true, // 开启压缩
// 设置让浏览器 overlay 同时显示警告和错误
overlay: {
warnings: true,
errors: true
},
// 设置请求代理
proxy: {
'/api': {
target: '<url>',
ws: true,
changeOrigin: true
},
'/foo': {
target: '<other_url>'
}
}
},
chainWebpack: config => {
// 引入babel-polyfill
config
.entry('index')
.add('babel-polyfill')
.end();
// 添加文件路径别名
// config.resolve.alias.set("@", resolve("src"));
// if (isProduction) {
// // 生产环境注入cdn
// config.plugin('html')
// .tap(args => {
// args[0].cdn = cdn;
// return args;
// });
// }
},
configureWebpack: config => {
if (isProduction) {
// 为生产环境修改配置...
config.plugins.push(
//添加代码压缩工具,及设置生产环境自动删除console
new UglifyJsPlugin({
uglifyOptions: {
},
sourceMap: false,
parallel: true,
})
);
} else {
// 为开发环境修改配置...
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment