Commit 576a03c0 authored by WangXu's avatar WangXu

初始化项目,包含美腾包

parents
# 配置支持的浏览器
# > 1%
# last 2 versions
[production staging]
Android >= 4.0
iOS >= 7
[development]
Android >= 6.0
iOS >= 11
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
# just a flag
ENV = 'development'
# base api 后端接口配置
VUE_APP_BASE_API = 'http://192.168.9.17:8080/schedule/'
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
# It only does one thing by converting all import() to require().
# This configuration can significantly increase the speed of hot updates,
# when you have a large number of pages.
# Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
VUE_CLI_BABEL_TRANSPILE_MODULES = true
# 高德地图配置信息
VUE_APP_AMAP_KEY = '8be75819d3c27cf6597d26c0e7db34ce'
VUE_APP_AMAP_VERSION = '1.4.4'
# just a flag
ENV = 'production'
# base api 后端接口配置
VUE_APP_BASE_API = 'http://localhost/schedule/'
/src/views/Schedule/ScheduleForm/components/addAnnex.vue
This diff is collapsed.
.DS_Store
node_modules
/dist
# 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?
# MT-SCHEDULE 美瞳-智信-日程
## 项目须知
* 接口配置在`.env.development``.env.production`
* 路由配置在 `/src/config`
* 项目插件配置在对应配置文件,详见 [项目中的配置文件介绍](项目中的配置文件介绍.md)
## 开发者须知
* `/src/api` 文件夹为相应的接口地址
* 组件选项的顺序
```vue
export default {
name: '',
mixins: [],
components: {},
props: {},
data() {},
computed: {},
watch: {},
created() {},
mounted() {},
destroyed() {},
methods: {}
}
```
* `localStorage` 和 `sessionStorage` 使用 `Vue-ls`
```vue
// Global
Vue.ls.set('name', '王旭')
Vue.ls.get('name')
// Context
this.$ls.set('name', '王旭')
this.$ls.get('name')
```
* 待补充。
## 项目初始化
```
npm install
```
### 开发时
```
npm run serve
```
### 运行时
```
npm run build
```
### 代码校验
```
npm run lint
```
module.exports = {
presets: [
'@vue/app'
],
plugins: [
[
'import',
{libraryName: 'vant', libraryDirectory: 'es', style: true},
'vant'
]
]
}
{
"compilerOptions": {
"target": "es6",
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"],
"include": ["src/**/*"]
}
This diff is collapsed.
{
"name": "mt-schedule",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"@tjmt/wnsdk": "^1.0.7",
"axios": "^0.19.0",
"core-js": "^2.6.5",
"lodash": "^4.17.15",
"moment": "^2.24.0",
"swiper": "^4.5.0",
"vant": "^2.0.6",
"vue": "^2.6.10",
"vue-ls": "^3.2.1",
"vue-router": "^3.0.7",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.0.5",
"@vue/cli-plugin-eslint": "^3.0.5",
"@vue/cli-service": "^3.0.5",
"@vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.1",
"babel-plugin-import": "^1.12.0",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"less": "^3.0.4",
"less-loader": "^4.1.0",
"postcss-px-to-viewport": "^1.1.0",
"style-resources-loader": "^1.2.1",
"vue-cli-plugin-style-resources-loader": "^0.1.3",
"vue-template-compiler": "^2.6.10"
}
}
module.exports = {
plugins: {
autoprefixer: {},
'postcss-px-to-viewport': {
// options
unitToConvert: 'px',
viewportWidth: 375,
unitPrecision: 5,
propList: ['*'],
viewportUnit: 'vw',
fontViewportUnit: 'vw',
selectorBlackList: ['van-circle__layer'],
minPixelValue: 1,
mediaQuery: false,
replace: true,
exclude: [],
landscape: false,
landscapeUnit: 'vw',
landscapeWidth: 568
}
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport" content="width=device-width,height=device-height,inital-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no,minimal-ui;">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>智学</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
import {closeLoading, sendInfoToJava, closeMicroApp} from './utils/mt-utils'
import {Toast} from 'vant'
import wnsdk from '@tjmt/wnsdk'
export default {
name: 'App',
components: {
[Toast.name]: Toast,
},
mounted() {
wnsdk
.systemClick
.hookSystemBack({
success: (result) => {
if(Object.keys(result).length > 0 && result.systemBack == 'back'){
if (this.$route.name == 'home') {
closeMicroApp()
} else {
window.history.back();
}
}
},
error: (error) => {
}
})
},
beforeDestroy() {
this.$ss.clear()
}
}
</script>
<style>
#app {
font-family: PingFang-SC-Regular, 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
position: fixed;
width: 100vw;
}
body {
background-color: #f8f8f8;
-webkit-font-smoothing: antialiased;
}
</style>
import axios from '@/utils/request'
const api = {
test: '/wangxu'
}
export default api
export function test(params) {
console.log('test')
return axios({
url: api.test,
method: 'get',
params: params
})
}
// Color variables
@black: #000;
@white: #fff;
@red: #f44;
@blue: #1989fa;
@orange: #ff976a;
@orange-dark: #ed6a0c;
@orange-light: #fffbe8;
@green: #07c160;
@gray: #c8c9cc;
@gray-light: #e5e5e5;
@gray-darker: #7d7e80;
@gray-dark: #848994;
// Default colors
@text-color: #333333;
@border-color: #ebedf0;
@active-color: #f2f3f5;
@background-color: #f8f8f8;
@background-color-light: #fafafa;
@grey-text-color: #CCCCCC;
@not-active-color: #CCD8DF;
// 按钮主色
@button-primary-color: @blue;
// NavBar
@nav-bar-height: 46px;
@nav-bar-background-color: @white;
@nav-bar-arrow-size: 16px;
@nav-bar-icon-color: @gray-dark;
@nav-bar-text-color: @blue;
@nav-bar-title-font-size: 18px;
@nav-bar-title-text-color: @text-color;
// Step
@finish-color: #CCCCCC;
@process-color: #3BCC80;
@not-started-color: #D1D8E0;
// 五种类型对应的颜色
@schedule-color: #3BCC80; // 日程
@meeting-color: #FEAD15; // 会议
@travel-color: #FEAD12; // 出差
@leave-color: #FEAD12; // 请假
@request-color: #3BCC80; // 工作请示
@commnTitleSize:36px;
@commnSize:30px;
@smallSize:26px;
<template>
<div
class="icon"
:style="customStyle"
:class="{'icon-shadow': shadow}"
>
<slot>
<span>
{{ text }}
</span>
</slot>
</div>
</template>
<script>
export default {
name: 'CircleIcon',
props: {
text: {
type: null,
default: ''
},
background: {
type: String,
default: '#4498F0'
},
fontColor: {
type: String,
default: '#fff'
},
height: {
type: String,
default: '40px'
},
width: {
type: String,
default: '40px'
},
shadow: {
type: Boolean,
default: true
}
},
computed: {
customStyle() {
const height = typeof (this.height) === 'number' ? `${this.height}px` : this.height,
width = typeof (this.width) === 'number' ? `${this.width}px` : this.width,
style = {
background: this.background,
color: this.fontColor,
height,
width
}
return style
}
}
}
</script>
<style lang="less" scoped>
.icon{
border-radius: 50%;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
}
.icon-shadow{
box-shadow:0px 0px 10px 0px rgba(102,102,102,0.5);
}
</style>
<template>
<div class="mt-fixbar">
<!--<div></div>-->
<slot />
</div>
</template>
<script>
export default {
name: 'FixBar'
}
</script>
<style lang="less" scoped>
.mt-fixbar{
position: fixed;
right: 15px;
bottom: 60px;
z-index: 9706;
}
</style>
<template>
<div
class="mt-navbar"
>
<div class="left">
<slot name="left">
<div class="iconSpan">
<template>
<img
@click="back"
class="arrow_back"
src="../assets/images/返回白@3x.png"
alt=""
style="height: 19px;width: 19px"
>
<img
@click="close"
class="arrow_close"
src="../assets/images/关闭白@3x.png"
alt=""
>
</template>
</div>
</slot>
</div>
<div class="title">
<slot name="title">
<span>{{ title }}</span>
</slot>
</div>
<div class="right">
<slot name="right"></slot>
</div>
</div>
</template>
<script>
import {sendInfoToJava} from '../utils/mt-utils'
export default {
name: 'NavBar',
props: {
title: {
type: String,
default: '标题'
},
showBackButton: {
type: Boolean,
default: true
},
showCloseButton: {
type: Boolean,
default: true
}
},
methods: {
// 返回按钮
back() {
console.log(this.$listeners)
this.$router.push('/')
},
// 关闭按钮
close() {
sendInfoToJava('close')
// closeMicroApp()
// this.$router.push('/')
}
}
}
</script>
<style lang="less" scoped>
.mt-navbar {
height: @nav-bar-height;
line-height: @nav-bar-height;
background-color: @nav-bar-background-color;
position: fixed;
top: 0;
width: 100vw;
z-index: 999;
& > .title {
max-width: 60%;
margin: 0 auto;
color: @nav-bar-title-text-color;
font-weight: 500;
font-size: @nav-bar-title-font-size;
}
& > .left, & > .right {
position: absolute;
bottom: 0;
height: 100%;
.iconSpan {
position: relative;
height: 100%;
display: flex;
align-items: center;
.arrow_back {
width: 12px;
height: 21px;
margin-left: 15px;
}
.arrow_close {
width: 19px;
height: 19px;
margin-left: 30px;
}
}
.van-icon {
color: @nav-bar-icon-color;
vertical-align: middle;
margin-left: 10px;
&:nth-child(1) {
margin-left: 15px;
font-size: 24px;
}
&:nth-child(2) {
margin-left: 30px;
font-size: 22px;
}
}
}
& > .right {
right: 15px;
display: flex;
align-items: center;
}
}
</style>
import Home from '@/views/Home/index'
/**
* 基础路由
* @type { *[] }
*/
export const defaultRoutes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/example',
name: 'example',
component: () => import(/* webpackChunkName: "example" */ '@/views/Example.vue')
}
]
export const sessionOptions = {
namespace: 'schedule__', // key prefix
name: 'ss', // name variable Vue.[ss] or this.[$ss],
storage: 'session' // storage name session, local, memory
}
export const localOptions = {
namespace: 'schedule__', // key prefix
name: 'ls', // name variable Vue.[ls] or this.[$ls],
storage: 'local' // storage name session, local, memory
}
<template>
<div />
</template>
<script>
export default {
name: 'BasicLayout'
}
</script>
<style scoped>
</style>
<template>
<div class="wrap">
<nav-bar
class="nav-bar"
@handleBack="handleBack"
>
<template v-slot:title>
<slot name="title" />
<span v-if="!$slots.title">{{ title }}</span>
</template>
<template v-slot:right>
<slot name="right" />
</template>
</nav-bar>
<section class="main">
<slot />
</section>
</div>
</template>
<script>
import {Tabbar, TabbarItem} from 'vant'
import NavBar from '@/components/NavBar'
export default {
name: 'NavBarView',
components: {
[Tabbar.name]: Tabbar,
[TabbarItem.name]: TabbarItem,
NavBar
},
data() {
return {
}
},
props: {
title: {
type: String,
default: '标题'
}
},
computed: {
},
mounted() {
console.log(this.$route)
},
methods: {
handleBack() {
console.log('handleBack')
}
}
}
</script>
<style lang="less" scoped>
.wrap{
overflow: hidden;
}
.main{
height: calc(100vh - @nav-bar-height);
margin-top: @nav-bar-height;
overflow-y: auto;
overflow-x: hidden;
background-color: @background-color;
}
</style>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import Storage from 'vue-ls'
import {sessionOptions, localOptions} from './config/vue-ls.config'
import * as _ from 'lodash'
import 'vant/lib/icon/local.css'
import {Toast} from 'vant'
import wnsdk from '@tjmt/wnsdk'
// 定义全局过滤器
import './utils/filters'
// 引入 Vue-ls`
// this.$ls Vue.ls
Vue.use(Storage, sessionOptions)
// this.$localStorage Vue.localStorage
Vue.use(Object.assign({}, Storage), localOptions)
// 引入 Vant 组件
Vue.use(Toast)
Vue.config.productionTip = false
Vue.prototype._ = _
Vue.prototype.$wnsdk = wnsdk
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
import Vue from 'vue'
import Router from 'vue-router'
import {defaultRoutes} from '@/config/router.config'
Vue.use(Router)
export default new Router({
mode: 'hash',
base: process.env.BASE_URL,
scrollBehavior: (to, from, savedPosition) => {
if (savedPosition) {
return savedPosition
} else {
return {x: 0, y: 0}
}
},
routes: defaultRoutes
})
import Vue from 'vue'
import Vuex from 'vuex'
import example from './modules/example'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
example
},
state: {
},
mutations: {
},
actions: {
}
})
// import Vue from 'vue'
export default {
namespaced: true,
state: {
name: ''
},
getters: {
getName: state => {
return `my name is ${state.name}`
}
},
mutations: {
SET_NAME: (state, data) => {
state.name = data
}
},
actions: {
setName({commit, state}, data) {
commit('SET_NAME', data)
}
}
}
import Vue from 'vue'
export const eventBus = new Vue()
import Vue from 'vue'
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-cn')
Vue.filter('NumberFormat', function(value) {
if (!value) {
return '0'
}
const intPartFormat = value.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断
return intPartFormat
})
Vue.filter('dayjs', function(dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
return moment(dataStr).format(pattern)
})
Vue.filter('moment', function(dataStr, pattern = 'YYYY-MM-DD HH:mm:ss') {
return moment(dataStr).format(pattern)
})
Vue.filter('date', function(dataStr, pattern = 'YYYY-MM-DD') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2018/05/15 09:30
*/
Vue.filter('dateTime', function(dataStr, pattern = 'L LT') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2018/05/15 周二
*/
Vue.filter('YearMonthDayWeek', function(dataStr, pattern = 'L ddd') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2019年8月28日星期三上午10点24分
*/
Vue.filter('YearMonthDayWeekTime', function(dataStr, pattern = 'LLLL') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2018/05/15 周二
*/
Vue.filter('time', function(dataStr, pattern = 'LT') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 05
*/
Vue.filter('dateToMoment', function(dataStr, pattern = 'M月') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 15
*/
Vue.filter('dateToDay', function(dataStr, pattern = 'D') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 9:00
*/
Vue.filter('hour', function(dataStr, pattern = 'HH:mm') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2018/05/15 周二
*/
Vue.filter('YearMonthDayWeekTimeWeek', function(dataStr, pattern = 'YYYY/MM/DD dddd HH:mm') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2018/05/15 周二
*/
Vue.filter('DateWeek', function(dataStr, pattern = 'YYYY/MM/DD HH:mm dddd') {
return moment(dataStr).format(pattern)
})
/**
* 2018-05-15 09:30:00 => 2018/05/15 周二
*/
Vue.filter('MonthDayHM', function(dataStr, pattern = 'MM/D HH:mm') {
return moment(dataStr).format(pattern)
})
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = 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()
},
timeStr = 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 timeStr
}
/**
* @param {number} time
* @param {string} option
* @returns {string}
*/
export function formatTime(time, option) {
if (('' + time).length === 10) {
time = parseInt(time) * 1000
} else {
time = +time
}
const d = new Date(time),
now = Date.now(),
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() +
'分'
)
}
}
/**
* @param {string} url
* @returns {Object}
*/
export function getQueryObject(url) {
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1),
obj = {},
reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj[name] = val
return rs
})
return obj
}
/**
* @param {string} input value
* @returns {number} output value
*/
export function byteLength(str) {
// returns the byte length of an utf8 string
let s = str.length
for (var i = str.length - 1; i >= 0; i--) {
const code = str.charCodeAt(i)
if (code > 0x7f && code <= 0x7ff) {
s++
} else if (code > 0x7ff && code <= 0xffff) {
s += 2
}
if (code >= 0xDC00 && code <= 0xDFFF) {
i--
}
}
return s
}
/**
* @param {Array} actual
* @returns {Array}
*/
export function cleanArray(actual) {
const newArray = []
for (let i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i])
}
}
return newArray
}
/**
* @param {Object} json
* @returns {Array}
*/
export function param(json) {
if (!json) {
return ''
}
return cleanArray(
Object.keys(json).map(key => {
if (json[key] === undefined) {
return ''
}
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
})
).join('&')
}
/**
* @param {string} url
* @returns {Object}
*/
export function param2Obj(url) {
const search = url.split('?')[1]
if (!search) {
return {}
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, ' ') +
'"}'
)
}
/**
* @param {string} val
* @returns {string}
*/
export function html2Text(val) {
const div = document.createElement('div')
div.innerHTML = val
return div.textContent || div.innerText
}
/**
* Merges two objects, giving the last one precedence
* @param {Object} target
* @param {(Object|Array)} source
* @returns {Object}
*/
export function objectMerge(target, source) {
if (typeof target !== 'object') {
target = {}
}
if (Array.isArray(source)) {
return source.slice()
}
Object.keys(source).forEach(property => {
const sourceProperty = source[property]
if (typeof sourceProperty === 'object') {
target[property] = objectMerge(target[property], sourceProperty)
} else {
target[property] = sourceProperty
}
})
return target
}
/**
* @param {HTMLElement} element
* @param {string} className
*/
export function toggleClass(element, className) {
if (!element || !className) {
return
}
let classString = element.className
const nameIndex = classString.indexOf(className)
if (nameIndex === -1) {
classString += '' + className
} else {
classString =
classString.substr(0, nameIndex) +
classString.substr(nameIndex + className.length)
}
element.className = classString
}
/**
* @param {string} type
* @returns {Date}
*/
export function getTime(type) {
if (type === 'start') {
return new Date().getTime() - 3600 * 1000 * 24 * 90
} else {
return new Date(new Date().toDateString())
}
}
/**
* @param {Function} func
* @param {number} wait
* @param {boolean} immediate
* @return {*}
*/
export function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) {
context = args = null
}
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) {
timeout = setTimeout(later, wait)
}
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
export function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
/**
* @param {Array} arr
* @returns {Array}
*/
export function uniqueArr(arr) {
return Array.from(new Set(arr))
}
/**
* @returns {string}
*/
export function createUniqueString() {
const timestamp = +new Date() + '',
randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}
/**
* Check if an element has a class
* @param {HTMLElement} elm
* @param {string} cls
* @returns {boolean}
*/
export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}
/**
* Add class to element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function addClass(ele, cls) {
if (!hasClass(ele, cls)) {
ele.className += ' ' + cls
}
}
/**
* Remove class from element
* @param {HTMLElement} elm
* @param {string} cls
*/
export function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
ele.className = ele.className.replace(reg, ' ')
}
}
import wnsdk from '@tjmt/wnsdk'
import {Toast} from 'vant'
import moment from 'moment/moment'
import Vue from 'vue'
/**
* 获取手机系统
* @returns {string}
* 安卓: 'android' IOS: 'ios'
*/
export function getSystem() {
const u = navigator.userAgent,
isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1, // android终端
isiOS = /iphone/gi.test(navigator.userAgent) // ios终端
if (isAndroid) {
return 'android'
}
if (isiOS) {
return 'ios'
}
}
/**
* mt 提供的发送消息的方法
* 目前使用: close(关闭当前webview)
* @param name(String) 发送的消息String
*/
export function sendInfoToJava(name) {
var u = navigator.userAgent, app = navigator.appVersion,
isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1 // 如果输出结果是true就判定是android终端或者uc浏览器
// var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //根据输出结果true或者false来判断ios终端
const isIOS = /iphone/gi.test(navigator.userAgent) // ios终端
//! !双叹号一般用来将后面的表达式转换为布尔型的数据(boolean)
if (isAndroid) {
window.WebView.showInfoFromJs(name)
}
if (isIOS) {
window.webkit.messageHandlers.sendInfoToJava.postMessage(name)
}
}
// /**
// * 关闭从原生APP进入后的进度条
// */
// export function closeLoading() {
// Toast('123')
// wnsdk
// .ui
// .closeLoadingBar()
// }
/**
* 关闭从原生APP进入后的进度条
*/
export function closeLoading() {
const sys = getSystem(),
obj = {
status: 0
}
if (sys == 'android') {
window.WebView.loading(JSON.stringify(obj))
}
if (sys == 'ios') {
window.webkit.messageHandlers.loading.postMessage(obj)
}
// wnsdk
// .ui
// .closeLoadingBar()
}
/**
* 转发
*/
export function transmit(data) {
const type = data.thingDO.type == 1 ? '日程' : '会议'
wnsdk
.im
.appLinkTransmit({
title: `${data.createPerson.name}发起的${type}`,
url: window.location.href,
type: '4',
style: '1',
owner: '',
time: `主题:${data.thingDO.sub}\n时间:${moment(data.thingDO.startTime).format('LLLL')}${moment(data.thingDO.endTime).format('LLLL')}`,
logo: 'http://127.0.0.1:8001/img/%E6%B7%BB%E5%8A%A0%E6%97%A5%E7%A8%8B@3x.e5cfb2ef.png',
success: function(result) {
},
error: function(error) {
}
})
}
/**
* 架构选人
*/
export function choosePerson(selected = [], editSelect = []) {
console.log(selected);
console.log(editSelect);
return new Promise((resolve, reject) => {
wnsdk
.util
.chooseAddressBook({
// id: Vue.ls.get('corpId'),
id:'6',
type: 2,
editSelect: editSelect,
selected: selected,
success: (result) => {
const data = JSON.parse(result.data)
data.forEach(item => {
item.id = item.corpUserId
})
// Toast({
// duration: 7000,
// message: JSON.stringify(result.data)
// })
resolve(data)
},
error: (error) => {
Toast(JSON.stringify(error))
}
})
})
}
/**
* 关闭微应用
*/
export function closeMicroApp() {
Toast('关闭微应用')
wnsdk
.page
.closeMicroApp()
}
/**
* 获取位置信息
*/
export function getLocation() {
return new Promise((resolve, reject) => {
wnsdk
.device
.location({
success: (result) => {
// Toast(JSON.stringify(result))
resolve(result)
},
error: (error) => {
}
})
})
}
/**
* 预览
*/
export function preView(type, url, name) {
wnsdk
.media
.multimediaPreview({
type,
url,
name
})
}
import axios from 'axios'
// import {Toast} from 'vant'
// import Vue from 'vue'
// import store from '@/store'
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 60000 // request timeout
})
/** 下面是为了刷新token
axios.defaults.isRetryRequest = false
// 刷新token的请求方法
function getRefreshToken() {
// refresh_token使用vuex存在本地的localstorage,之后会详细说
const params = {
refreshToken: Vue.ls.get('schedule_refreshToken')
}
return axios.get('/schedule/tb-user/refreshToken', {params, headers: {'clientType': 'app'}})
}
// request interceptor
service.interceptors.request.use(
config => {
config.headers['clientType'] = 'app'
config.headers['Authorization'] = 'Bearer ' + Vue.ls.get('schedule_accessToken')
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
response => {
const resConfig = response.config,
res = response.data
// 判断是否已经刷新过token
if (!resConfig.isRetryRequest) {
if (res.code === 'G_T_001') {
// if (res.code == "O_T_001") {
return getRefreshToken()
.then((res) => {
if (res.code === 'M0000') {
const data = res.data
console.log('重新请求')
resConfig.isRetryRequest = true
Vue.ls.set('schedule_accessToken', data.access_token)
Vue.ls.set('schedule_refreshToken', data.refresh_token)
resConfig.headers['Authorization'] = 'Bearer ' + Vue.ls.get('schedule_accessToken')
return axios(resConfig)
} else {
Toast.fail('重新请求失败')
}
})
}
} else {
Toast.fail('加载超时')
}
return res
},
error => {
console.log('err' + error) // for debug
if (!navigator.onLine || error === 'Network Error') {
Toast('网络异常,请检查网络')
}
return Promise.reject(error)
}
)
*/
export default service
/**
* Created by PanJiaChen on 16/11/18.
*/
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const validMap = ['admin', 'editor']
return validMap.indexOf(str.trim()) >= 0
}
/**
* @param {string} url
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(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 reg.test(url)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}
/**
* @param {string} email
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true
}
return false
}
/**
* @param {Array} arg
* @returns {Boolean}
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
}
return Array.isArray(arg)
}
<template>
<div class="example">
<h1>This is an example page</h1>
<div>{{ name }}</div>
<div>{{ getName }}</div>
<van-button type="default">
默认按钮
</van-button>
<van-button type="primary">
主要按钮
</van-button>
<van-button type="info">
信息按钮
</van-button>
<van-button type="warning">
警告按钮
</van-button>
<van-button type="danger">
危险按钮
</van-button>
</div>
</template>
<script>
import {mapState, mapGetters, mapActions} from 'vuex'
import {Button} from 'vant'
import {test} from '@/api/test'
export default {
name: 'Example',
components: {
[Button.name]: Button
},
data() {
return {
options: {
down: {
pullingText: '测试'
}
},
isRefreshing: false
}
},
computed: {
...mapState('example', ['name']),
...mapGetters('example', ['getName'])
},
methods: {
...mapActions('example', ['setName']),
async testMock() {
const res = await test()
console.log('testMock', res.data)
},
handleRefresh(e) {
console.log('handleRefresh', e)
}
},
mounted() {
console.log('example2')
this.setName('王旭')
this.testMock()
}
}
</script>
<style lang="less" scoped>
.example {
transform: matrix();
}
</style>
<template>
<div>
主页
</div>
</template>
<script>
export default {
name: 'Home'
}
</script>
<style lang="less" scoped>
</style>
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
outputDir: 'dist',
publicPath: process.env.NODE_ENV === 'production' ? './' : '/',
lintOnSave: false,
devServer: {
// development server port 8001
port: 8001,
// host: '192.168.0.178'
overlay: {
warnings: true,
errors: true
}
},
chainWebpack: (config) => {
config.resolve.alias
.set('@$', resolve('src'))
.set('@api', resolve('src/api'))
.set('@assets', resolve('src/assets'))
.set('@comp', resolve('src/components'))
.set('@views', resolve('src/views'))
.set('@layouts', resolve('src/layouts'))
.set('@static', resolve('src/static'))
},
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [
path.resolve(__dirname, './src/assets/style/global.less')
]
}
}
}
'use strict'
const path = require('path')
function resolve(dir) {
return path.join(__dirname, '.', dir)
}
module.exports = {
context: path.resolve(__dirname, './'),
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src')
}
}
}
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 to comment