Commit 74afb124 authored by Nature's avatar Nature

Initial commit

parents
{
"presets": [
["env", {
"modules": false
}],
"stage-2"
],
"plugins": ["transform-runtime"]
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
build/
config/
static/
test/
dist/
src/assets/
src/libs/
!src/data/config/
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
// 指定环境
env: {
browser: true,
node: true,
jest: true,
es6: true,
},
// 全局变量
"globals": {
navigator: false,
cordova: false,
HandBridge: false,
process: true,
$config: true,
JMessagePlugin:true,
vum:true,
hlsPopup:true,
hlsHttp:true,
hlsUtil:true
},
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
extends: ['plugin:vue/recommended', 'standard'],
// required to lint *.vue files
plugins: ['vue', 'import'],
// check if imports actually resolve
settings: {
'import/resolver': {
webpack: {
config: 'build/webpack.base.conf.js'
}
}
},
// add your custom rules here
// "off" 或 0 - 关闭规则
// "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
// "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
rules: {
// 以下为自定义的 javascript 规则:
// 箭头函数当只有一个参数时允许省略圆括号
'arrow-parens': 0,
// 允许生成器
'generator-star-spacing': 0,
// 对象和数组结尾强制分号
"comma-dangle": [2, {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "ignore",
}],
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
"no-array-constructor": 0,
"no-irregular-whitespace": 0,
"no-new-wrappers": 0,
"no-alert": 0,
"no-eq-null": 2,
// 以下为自定义的 plugin-vue 规则:
// 单行中允许多个属性
"vue/max-attributes-per-line": ['error', {
"singleline": 4,
"multiline": {
"max": 4,
"allowFirstLine": false
}
}],
// 关闭属性名必须是 '-' 连接
"vue/attribute-hyphenation": 0,
"vue/require-v-for-key": 0,
// 以下为自定义的 plugin-import 规则:
// https://github.com/benmosher/eslint-plugin-import
// don't require .vue extension when importing
'import/extensions': ['error', 'always', {
js: 'never',
vue: 'never'
}],
// allow optionalDependencies
'import/no-extraneous-dependencies': ['error', {
optionalDependencies: ['test/unit/index.js']
}],
// 关闭必须默认输出
'import/prefer-default-export': ['off'],
}
}
.DS_Store
node_modules/
platforms/
www/
.idea/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*~
*.sw[mnpcod]
*.log
*.tmp
*.tmp.*
log.txt
*.sublime-project
*.sublime-workspace
Thumbs.db
UserInterfaceState.xcuserstate
# OS X
.DS_Store
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"postcss-import": {},
"autoprefixer": {}
}
}
*.min.css
iconfont.css
// https://stylelint.io/user-guide/configuration
module.exports = {
defaultSeverity: 'warning',
extends: 'stylelint-config-standard',
rules: {
'rule-empty-line-before': null,
'selector-list-comma-newline-after': 'always-multi-line',
},
};
# hls-car-vue
> A Vue.js project
## Build Setup
``` bash
# install dependencies
yarn install
# serve with hot reload at localhost:8080
npm run dev
# build for uat with minification
npm run build:uat
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
### 文件命名规范
1. 文件夹全部采用驼峰命名法,即首字母小写后面每个单词首字母大写
2. 文件名全部采用驼峰命名法,如 **userInfo.vue,userInfoDetail.vue**,
3. 路由的注册 `import` 语句后的单词采用 Pascal命名法,所有单词的首字母大写,其余字母小写,单词与单词之间不使用任何符号风格。如
```javascript
import HomeManager from '@/pages/homeManager/homeManager'
import UserInfo from '@/pages/userInfo/userInfo'
import UserInfoDetail from '@/pages/userInfo/userInfoDetail'
```
4. 实际路由注册需安照如下写法,`path``/tab/文件名`,`/tab`是否保留视实际情况而定。`component`后接的单词需和`import`的单词保持一致,`name`后接的单词也需和`import`的单词保持一致
```javascript
{path: "/tab/homeManager", component: HomeManager, name: 'HomeManager', meta: {keepAlive: true}},
{path: '/tab/userInfo', component: UserInfo, name: 'UserInfo', meta: {keepAlive: true}},
```
# keyStore签名信息
keystore文件 hlscar.keystore
别名 HLSkey
密码 com.hls.easy.car
# 签名
jarsigner -verbose -keystore hls.keystore -signedjar 车租易.apk hls.apk HLSkey
# 打包冲突解决
各项目如果安装了 com.hls.plugins.barcode 扫码插件与cordova-plugin-open-camera 媒体插件
两个插件之间存在一些冲突 请注释掉媒体插件 plugin.xml 第83行 <uses-feature android:name="android.hardware.camera" />
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}
require('./check-versions')()
var config = require('../config')
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
var app = express()
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
})
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})
var server = app.listen(port)
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const pkg = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const px2remLoader = {
loader: 'px2rem-loader',
options: {
remUnit: options.remUnit,
},
};
var postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
//const loaders = options.usePostCSS ? [cssLoader, postcssLoader,px2remLoader] : [cssLoader]
let loaders = options.useFlexible ? [cssLoader, px2remLoader]: [cssLoader]
loaders = options.usePostCSS ? [...loaders, postcssLoader] : loaders
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
publicPath:'../../'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = function () {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') {
return
}
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: pkg.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
useFlexible: config.base.useFlexible,
remUnit: config.base.remUnit,
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const vuxLoader = require('vux-loader')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
let webpackConfig = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}
module.exports = vuxLoader.merge(webpackConfig, {
plugins: [
'vux-ui',
'progress-bar',
{
name: 'duplicate-style',
options: {
cssProcessorOptions : {
safe: true,
zindex: false,
autoprefixer: {
add: true,
browsers: [
'iOS >= 7',
'Android >= 4.1'
]
}
}
}
},
{name: 'less-theme', path: 'src/styles/variables.less'}
]
})
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: true,
hot: true,
compress: true,
host: process.env.HOST || config.dev.host,
port: process.env.PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay ? {
warnings: false,
errors: true,
} : false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env'),
$config: require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${config.dev.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
//console.log(config)
const env = require(`../config/${config.ENV}.env`)
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: false
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env,
$config: env,
}),
// UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// set the following option to `true` if you want to extract CSS from
// codesplit chunks into this main css file as well.
// This will result in *all* of your app's CSS being loaded upfront.
allChunks: false,
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vender modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
CONFIG_ENV: JSON.stringify(process.env.CONFIG_ENV),
debug: true,
isMobilePlatform: false,
appCode:'"HLS_APP"',
clearTable: true,
loginPath: '"http://hlsapp.hand-china.com/core/oauth/token?client_id=hQGCtxTItRa34PUOgxaD0r7oSPeuEaIB&client_secret=7ee8338c-4a06-44a1-87cc-afa63f8e1bc3&grant_type=password&username=app&password=" ',
basePath: '"http://hlsapp.hand-china.com/core/r/api?sysName=HLS_APP&apiName="',
rootPath: '"http://hlsapp.hand-china.com/core/r/api"',
riskPath: '"http://hlsapp.hand-china.com/core/r/api/app/riskQuery?sysName=HLS_RISK&apiName="',
riskKey: '"pIGBbSRyThA4Xg"',
pushKey: '"45ace0e521f01edb2f1c753a"',
file_url: '"http://hlsapp.hand-china.com/file/"',
appId: '"com.hls.easy.car"',
currentVersion: '"1.0.0"',
dbName: '"Function.db"',
dbLocation: 0,
});
'use strict'
// Template version: 1.2.4
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
const CONFIG_ENV = process.env.CONFIG_ENV
module.exports = {
ENV:CONFIG_ENV,
base: {
// Use Flexible?
useFlexible: true,
remUnit: 50, // 启用flexible时的根字体大小(px)
// Use PostCSS?
usePostCSS: false,
},
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false,
ENV:CONFIG_ENV
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../www/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../www'),
assetsSubDirectory: 'static',
assetsPublicPath: './',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report,
ENV:CONFIG_ENV
}
}
'use strict'
module.exports = {
NODE_ENV: '"production"',
CONFIG_ENV: JSON.stringify(process.env.CONFIG_ENV),
debug: false,
isMobilePlatform: true,
appCode:'"HLS_APP"',
clearTable: true,
loginPath: '"http://hlsapp.hand-china.com/core/oauth/token?client_id=hQGCtxTItRa34PUOgxaD0r7oSPeuEaIB&client_secret=7ee8338c-4a06-44a1-87cc-afa63f8e1bc3&grant_type=password&username=app&password=" ',
basePath: '"http://hlsapp.hand-china.com/core/r/api?sysName=HLS_APP&apiName="',
rootPath: '"http://hlsapp.hand-china.com/core/r/api"',
riskPath: '"http://hlsapp.hand-china.com/core/r/api/app/riskQuery?sysName=HLS_RISK&apiName="',
riskKey: '"pIGBbSRyThA4Xg"',
pushKey: '"45ace0e521f01edb2f1c753a"',
file_url: '"http://hlsapp.hand-china.com/file/"',
appId: '"com.hls.easy.car"',
currentVersion: '"1.0.0"',
dbName: '"Function.db"',
dbLocation: 0,
}
'use strict'
module.exports = {
NODE_ENV: '"production"',
CONFIG_ENV: JSON.stringify(process.env.CONFIG_ENV),
debug: false,
isMobilePlatform: true,
appCode:'"HLS_APP"',
clearTable: true,
loginPath: '"http://hlsapp.hand-china.com/core/oauth/token?client_id=hQGCtxTItRa34PUOgxaD0r7oSPeuEaIB&client_secret=7ee8338c-4a06-44a1-87cc-afa63f8e1bc3&grant_type=password&username=app&password=" ',
basePath: '"http://hlsapp.hand-china.com/core/r/api?sysName=HLS_APP&apiName="',
rootPath: '"http://hlsapp.hand-china.com/core/r/api"',
riskPath: '"http://hlsapp.hand-china.com/core/r/api/app/riskQuery?sysName=HLS_RISK&apiName="',
riskKey: '"pIGBbSRyThA4Xg"',
pushKey: '"45ace0e521f01edb2f1c753a"',
file_url: '"http://hlsapp.hand-china.com/file/"',
appId: '"com.hls.easy.car"',
currentVersion: '"1.0.0"',
dbName: '"Function.db"',
dbLocation: 0,
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, width=device-width, viewport-fit=cover">
<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="email=no">
<!-- safari私有meta标签 允许全屏模式浏览 指定safari顶部状态栏样式(黑色) -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<script type="text/javascript" src="../../cordova.js"></script>
<title>车租易</title>
</head>
<body>
<div id="app-box"></div>
<!-- built files will be auto injected -->
</body>
</html>
{
"name": "hls-vue-app",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "JingChao <jingchao.wu@hand-china.com>",
"private": true,
"scripts": {
"dev": "cross-env CONFIG_ENV=dev webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build:uat": "cross-env CONFIG_ENV=uat node build/build.js",
"build": "cross-env CONFIG_ENV=prod node build/build.js"
},
"dependencies": {
"autosize": "^3.0.20",
"better-scroll": "^1.10.3",
"crypto-js": "^3.1.9-1",
"fastclick": "https://github.com/fiso/fastclick.git",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vuex": "^2.1.1",
"vuex-i18n": "^1.3.1",
"vux": "^2.9.2",
"hls-easy-ui": "https://hel.hand-china.com/easyUI/hls-easy-ui.git"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-loader": "^7.1.1",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"cross-env": "^5.2.0",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-import-resolver-webpack": "^0.8.3",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.5.0",
"eventsource-polyfill": "^0.9.6",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"less": "^2.7.1",
"less-loader": "^2.2.3",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"prelude-ls": "^1.1.2",
"px2rem-loader": "^0.1.9",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"stylelint": "^8.0.0",
"stylelint-config-standard": "^18.2.0",
"stylelint-webpack-plugin": "^0.10.4",
"style-loader": "^0.21.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"url-loader": "^0.5.8",
"vconsole": "^3.2.0",
"vue-infinite-scroll": "^2.0.2",
"vue-loader": "^13.3.0",
"vue-loading-template": "^1.3.0",
"vue-slim-better-scroll": "^1.4.1",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"vux-loader": "^1.0.56",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-middleware": "^1.10.0",
"webpack-dev-server": "^2.9.1",
"webpack-hot-middleware": "^2.16.1",
"webpack-merge": "^4.1.0",
"yaml-loader": "^0.4.0"
},
"cordovaPlugins": [
"cordova-plugin-console",
"cordova-plugin-device",
"cordova-plugin-statusbar",
"cordova-plugin-splashscreen",
"cordova-plugin-whitelist",
"ionic-plugin-keyboard",
"cordova-plugin-inappbrowser"
],
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"iOS >= 7",
"Android >= 4.1"
],
"cordova": {
"platforms": [
"android"
],
"plugins": {
"cordova-plugin-camera": {},
"cordova-plugin-device": {},
"cordova-plugin-whitelist": {},
"cordova-plugin-crosswalk-webview": {
"XWALK_VERSION": "22+",
"XWALK_LITEVERSION": "xwalk_core_library_canary:17+",
"XWALK_COMMANDLINE": "--disable-pull-to-refresh-effect",
"XWALK_MODE": "embedded",
"XWALK_MULTIPLEAPK": "true"
}
}
}
}
<template>
<div id="app">
<transition :name="transitionName">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"/>
</keep-alive>
</transition>
<transition :name="transitionName">
<router-view v-if="!$route.meta.keepAlive"/>
</transition>
</div>
</template>
<script>
export default {
data () {
return {
pathList: [],
transitionName: 'slide-left',
}
},
watch: { // 监听路由变化
$route (to, from) {
if (this.pathList.includes(to.path)) {
const index = (this.pathList.findIndex(() => {
return from.path
}))
this.pathList.splice(index, 1)
this.$router.isBack = true
} else {
this.pathList.push(to.path)
this.$router.isBack = false
}
if (to.path === '/home') {
this.$router.isBack = true
this.pathList = []
}
let isBack = this.$router.isBack
if (isBack) {
this.transitionName = 'router-slide-right'
} else {
this.transitionName = 'router-slide-left'
}
this.$router.isBack = false
},
},
mounted () {
this.getAccessToken()
},
methods: {
getAccessToken () {
let vm = this
let url = process.env.loginPath + 'appadmin'
let param = {}
vm.hlsHttp.post(url, param).then(function (res) {
window.localStorage.setItem('access_token', res.access_token)
})
},
// 右滑返回上一页
onSwipeRight () {
if (this.$route.name === 'Home') return
this.$router.go(-1)
},
},
}
</script>
<style lang="less">
html, body, #app {
height: 100%;
width: 100%;
overflow-x: hidden;
//overflow: auto;
//-webkit-overflow-scrolling: touch;
//overflow-scrolling: touch;
}
</style>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="rolling" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
<path fill="#ccc" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
<animateTransform
attributeName="transform"
attributeType="XML"
type="rotate"
dur="1s"
from="0 50 50"
to="360 50 50"
repeatCount="indefinite"/>
</path>
</svg>
### 此文件夹存放第三方js
/**
* 基础 mixins
*/
import { case2Param } from '../utils'
const preName = 'hls'
export default {
methods: {
/**
* 生成 css class helper
* c() // 'hls-componentName'
* c('wrap') // 'hls-componentName-wrap'
* c('wrap--active') // 'hls-componentName-wrap--active'
* @param {String} className 类名
* @returns String
*/
c (className) {
const { name } = this.$options // 组件名
return className ? `${preName}-${case2Param(name)}-${className}` : `${preName}-${case2Param(name)}`
},
},
}
import base from './base'
import prefix from './prefix'
import touch from './touch'
export {
base,
prefix,
touch,
}
const preName = 'hls'
export default {
methods: {
// 生成 css class
b (className) {
return className ? `${preName}-${className}` : ''
},
},
}
export default {
methods: {
onTouchStart (event) {
this.direction = ''
this.deltaX = 0
this.deltaY = 0
this.offsetX = 0
this.offsetY = 0
this.startX = event.touches[0].clientX
this.startY = event.touches[0].clientY
},
onTouchMove (event) {
const touch = event.touches[0]
this.deltaX = touch.clientX - this.startX
this.deltaY = touch.clientY - this.startY
this.offsetX = Math.abs(this.deltaX)
this.offsetY = Math.abs(this.deltaY)
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : ''
},
},
}
/**
* 一些帮助函数
*/
/**
* setTimeout 的 promise 封装
* @param {Number} time
* @returns
*/
export function timeout (time) {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
/**
* 断言
* @param {any} condition 条件
* @param {any} msg 信息
*/
export function assert (condition, msg) {
if (!condition) throw new Error(`[hips] ${msg}`)
}
/**
* 改变 case 格式为 param
* @param {String} str 字符串
*/
export function case2Param (str) {
assert(typeof str === 'string', 'case2Param 传入数据类型错误:应为 String')
str = str.replace(/^[A-Z]/g, $0 => $0.toLowerCase())
return str.replace(/[A-Z]/g, $0 => `-${$0.toLowerCase()}`)
}
/**
* 判断平台
* @return {String} 平台
*/
export function detectOS () {
const ua = navigator.userAgent.toLowerCase()
if (/MicroMessenger/i.test(ua)) {
return 'weixin'
} else if (/iPhone|iPad|iPod|iOS/i.test(ua)) {
return 'ios'
} else if (/Android/i.test(ua)) {
return 'android'
} else {
return 'other'
}
}
/* eslint-disable */
/**
* YDUI 可伸缩布局方案
* rem计算方式:设计图尺寸px / 50 = 实际rem 例: 100px = 2rem
*/
!(function(window) {
/* 设计图文档宽度 */
var docWidth = 750;
var doc = window.document,
docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
var recalc = (function refreshRem() {
var clientWidth = docEl.getBoundingClientRect().width;
/* 8.55:小于320px不再缩小,11.2:大于420px不再放大 */
docEl.style.fontSize = Math.max(Math.min(20 * (clientWidth / docWidth), 11.2), 8.55) * 5 + 'px';
return refreshRem;
})();
/* 添加倍屏标识,安卓倍屏为1 */
docEl.setAttribute('data-dpr', window.navigator.appVersion.match(/iphone/gi) ? window.devicePixelRatio : 1);
if (/iP(hone|od|ad)/.test(window.navigator.userAgent)) {
/* 添加IOS标识 */
doc.documentElement.classList.add('ios');
/* IOS8以上给html添加hairline样式,以便特殊处理 */
if (parseInt(window.navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/)[1], 10) >= 8) doc.documentElement.classList.add('hairline');
}
if (!doc.addEventListener) return;
window.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(window);
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import FastClick from 'fastclick'
import App from './App'
import Vuex from 'vuex'
import vuexI18n from 'vuex-i18n'
import router from './router/index'
import flexible from './common/ydui.flexible'
import {componentInstall, appStyle} from 'hls-easy-ui'
/**
* 指令
*/
import directives from './scripts/directives'
import filter from './scripts/filter'
/**
* 组件
*/
import {
ViewBox,
Tabbar,
TabbarItem,
XHeader,
Picker,
PopupHeader,
} from 'vux'
import './scripts/prototype'
import './scripts/vuePlatform'
/**
* 弹框组件
*/
import hlsPopup from './scripts/hlsPopup'
/**
* http
*/
import { post, get } from './scripts/hlsHttp'
/** 全局函数hlsUtil**/
import hlsUtil from './scripts/hlsUtil'
Vue.use(componentInstall)
Vue.use(appStyle)
/** end**/
if (process.env.CONFIG_ENV === 'uat') {
const VConsole = require('vconsole')
new VConsole() // eslint-disable-line
}
Vue.use(flexible)
Vue.use(directives)
Vue.use(filter)
Vue.use(Vuex)
// Vue.directive('transfer-dom', TransferDom);
Vue.component('x-header', XHeader)
Vue.component('view-box', ViewBox)
Vue.component('tabbar', Tabbar)
Vue.component('tabbar-item', TabbarItem)
Vue.component('PopupHeader', PopupHeader)
Vue.component('picker', Picker)
/** i18n **/
let store = new Vuex.Store({
modules: {
i18n: vuexI18n.store,
},
})
Vue.use(vuexI18n.plugin, store)
Vue.prototype.hlsPopup = window.hlsPopup = hlsPopup
Vue.prototype.$devicePixelRatio = 2
Vue.prototype.$post = post
Vue.prototype.$get = get
let hlsHttp = {
get: get,
post: post,
}
Vue.prototype.hlsHttp = window.hlsHttp = hlsHttp
Vue.prototype.hlsUtil = window.hlsUtil = hlsUtil
/**
* 全局返回上一页面
* @param index
*/
let routeGo = function (index) {
if (!index) {
index = -1
}
this.$router.go(index)
}
Vue.prototype.$routeGo = routeGo
let hlsExit = function () {
if (vum.Platform.isIOS()) {
cordova.exec(null, null, 'BridgePlugin', 'closeWebView', [])
} else if (vum.Platform.isIOS()) {
var dict = {
'className': 'WebBridge',
'function': 'close',
'successCallBack': 'sCallBack',
'failureCallBack': 'eCallBack',
}
HandBridge.postMessage(JSON.stringify(dict))
}
}
Vue.prototype.$hlsExit = hlsExit
FastClick.attach(document.body)
Vue.config.productionTip = false
vum.$vumPlatform.ready(function () {
if ((vum.Platform.isAndroid()) || (vum.Platform.isIOS())) {
}
})
vum.$vumPlatform.registerBackButtonAction(function (e) {
}, 101)
/* eslint-disable no-new */
new Vue({
data () {
return {
pathList: [],
transitionName: null,
}
},
router,
watch: { // 监听路由变化
$route (to, from) {
document.body.scrollTop = 0
document.documentElement.scrollTop = 0
},
},
render: h => h(App),
}).$mount('#app-box')
<template>
<h-view class="public-style hls-popup" style="height: 100%">
<h-header class="bar-custom">
<div slot="left" class="h-header-btn" @click="$routeGo()">
<i class="ion-ios-arrow-back"/>
</div>
<div slot="center">封装测试</div>
<div slot="right" class="h-header-btn">
操作
</div>
</h-header>
<!-- <s-tab @tabClick="stablick" cusClass="popup-tab">
<tab-item>测试</tab-item>
<tab-item>你好</tab-item>
<tab-item>再见</tab-item>
<tab-item>按钮</tab-item>
</s-tab>-->
<h-content
class="has-header has-footer">
<h-button class="button-class" type="primary" @click.native="showLoading">showLoading</h-button>
<h-button class="button-class" type="primary" @click.native="hideLoading">hideLoading</h-button>
<h-button class="button-class" type="primary" @click.native="showLongTop">showLongTop</h-button>
<h-button class="button-class" type="primary" @click.native="showLongCenter">showLongCenter</h-button>
<h-button class="button-class" type="primary" @click.native="showLongBottom">showLongBottom</h-button>
<h-button class="button-class" type="primary" @click.native="showSuccess">showSuccess</h-button>
<h-button class="button-class" type="primary" @click.native="showError">showError</h-button>
<h-button class="button-class" type="primary" @click.native="showConfirm">showConfirm</h-button>
<h-button class="button-class" type="primary" @click.native="showPopup">showPopup</h-button>
<h-button class="button-class" type="primary" @click.native="showActionSheet">showActionSheet</h-button>
<h-button class="button-class" type="primary" @click.native="showActionSheetButton">showActionSheet 区分按钮颜色
</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY')">showTime YYYY</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM')">showTime YYYY-MM</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM-DD')">showTime YYYY-MM-DD
</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM-DD HH')">showTime YYYY-MM-DD HH
</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM-DD HH:mm')">showTime YYYY-MM-DD
HH:mm
</h-button>
<h-button class="button-class" type="primary" @click.native="showBigPicture">showBigPicture</h-button>
<h-button class="button-class" type="primary" @click.native="selectListOne">selectList 普通下拉框</h-button>
<h-button class="button-class" type="primary" @click.native="selectListTwo">selectList 二级联动</h-button>
<h-button class="button-class" type="primary" @click.native="selectList">selectList 三级联动</h-button>
<h2 class="item-title">按钮类型</h2>
<h-button class="button-class" type="rimless">rimless 按钮</h-button>
<h-button class="button-class" type="default">default 按钮</h-button>
<h-button class="button-class" type="primary">primary 按钮</h-button>
<h-button class="button-class" type="safety">safety 按钮</h-button>
<h-button class="button-class" type="warning">warning 按钮</h-button>
<h-button class="button-class" type="danger">danger 按钮</h-button>
<h2 class="item-title">按钮尺寸</h2>
<h-button class="button-class" size="mini">mini 按钮</h-button>
<h-button class="button-class" size="small">small 按钮</h-button>
<h-button class="button-class" size="normal">normal 按钮</h-button>
<h-button class="button-class" size="large">large 按钮</h-button>
<h-button class="button-class" size="huge">huge 按钮</h-button>
<h2 class="item-title">自定义圆角 (直接通过class设置)</h2>
<h-button class="button-class radius-small">rimless 按钮</h-button>
<h-button class="button-class radius-normal">default 按钮</h-button>
<h-button class="button-class radius-large">primary 按钮</h-button>
<h2 class="item-title">默认点击效果</h2>
<h-button class="button-class radius-small" type="rimless">基础按钮(无边框)</h-button>
<h-button class="button-class radius-small" type="rimless" shadow>基础按钮(无边框、有阴影效果)</h-button>
<h-button class="button-class radius-small purple">基础按钮(有背景色)</h-button>
<h2 class="item-title">禁用效果</h2>
<h-button class="button-class radius-small" disabled>基础按钮(禁用)</h-button>
<h2 class="item-title">Swip基础使用</h2>
<swipe :interval="5000" @start="start" @move="move" @change="change">
<swipe-item>
<div :style="{'background': bgColor[0]}" class="item-bg">0</div>
</swipe-item>
<swipe-item>
<div :style="{'background': bgColor[1]}" class="item-bg">1</div>
</swipe-item>
<swipe-item>
<div :style="{'background': bgColor[2]}" class="item-bg">2</div>
</swipe-item>
</swipe>
<h2 class="item-title">纵向滚动</h2>
<swipe :vertical="true" style="height: 200px">
<swipe-item v-for="key in count" :key="key" :style="{'background': bgColor[key-1]}">
<div class="item-bg">{{ key-1 }}</div>
</swipe-item>
</swipe>
<h2 class="item-title">定制indicators</h2>
<swipe :index.sync="index">
<swipe-item v-for="key in count" :key="key" :style="{'background': bgColor[key-1]}">
<div class="item-bg">{{ key-1 }}</div>
</swipe-item>
<div v-for="key in count" slot="indicators" :key="key" :class="['indicators', {'active': key-1 === index}]"/>
</swipe>
<h2 class="item-title">Spin-CSS</h2>
<div class="spin-container">
<spin size="20px" color="#ccc"/>
<spin size="30px" color="#999"/>
<spin size="40px" color="#666"/>
<spin size="50px" color="#333"/>
</div>
<h2 class="item-title">SVG</h2>
<div class="spin-container">
&lt;!&ndash; 颜色要通过修改svg来实现,无法通过属性修改 &ndash;&gt;
<spin :svg-src="svgSrc" size="40px"/>
<spin :svg-src="svgSrc" size="50px"/>
<spin :svg-src="svgSrc" size="60px"/>
<spin :svg-src="svgSrc" size="70px"/>
</div>
<h2 class="item-title">top-tip</h2>
<div class="local-region">
<top-tip v-model="show" entry-direction="down" content="顶部消息提示内容"/>
参考文案
</div>
<h-button class="button-class" type="rimless" shadow @click.native="showTopTip">TopTip</h-button>
<h2 class="item-title">notify</h2>
<div class="local-region">
<notify v-model="show1" content="提示内容" type="success"/>
<notify v-model="show2" :time="3000" position="bottom" content="提示内容"/>
</div>
<h2 class="item-title">notify标签用法 (通常在局部显示时使用)</h2>
<h-button class="button-class" type="rimless" shadow @click.native="showNotifyAtTop">Notify (top)</h-button>
<h-button class="button-class" type="rimless" shadow @click.native="showNotifyAtBottom">Notify (bottom)</h-button>
<h2 class="item-title">notify 插件用法</h2>
<h-button class="button-class purple" type="rimless" shadow @click.native="handleNotify">NotifyPlugin</h-button>
<h2 class="item-title">数字键盘</h2>
<div class="list">
<div class="item">
<div class="contents">
<div class="add-name">
<div>数字键盘</div>
</div>
<div class="add-content readonly" @click="keyboradShow">
<input v-model="value" type="number" placeholder="输入" readonly>
</div>
</div>
</div>
</div>
<list-item :item-height="45">
<item>
<div slot="name">数字键盘</div>
<input
slot="content" v-model="value" type="number" placeholder="输入"
readonly @click="keyboradShow">
</item>
</list-item>
<div class="list">
<item-option
v-for="(color,index) in colors" :key="index"
class="mySlider">
<div>{{ color.name }}</div>
<div>{{ color.hex }}</div>
<div slot="buttons">
<option-button type="default" text="默认" @click.native="deleteFun"/>
<option-button type="primary" text="编辑" @click.native="deleteFun"/>
<option-button type="warn" text="删除" @click.native="deleteFun"/>
</div>
</item-option>
</div>
<h2>picker</h2>
<picker
ref="picker1" :data="year7" :columns="3" v-model="year7Value"
style="width: 100%"
@on-change="change"/>
<list-item :item-height="45">
<item>
<img slot="left-icon" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name" class="required">检查更新</div>
<div slot="content">检查更新</div>
<img slot="right-icon" src="../assets/image/arrow-down@2x.png" style="width: 8px" class="right-icon">
</item>
<item>
<img slot="left" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name" class="required">字数测试</div>
<div slot="content">我是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文字</div>
</item>
<item :showArrow="true">
<img slot="left" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name">客户名称</div>
<input slot="content" v-model="bp_name" type="text" placeholder="请输入">
</item>
<item :show-arrow="true">
<img slot="left-icon" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name">保存照片</div>
<label slot="right" class="toggle toggle-positive toggle-check" @click="savePhotoFun">
<input :checked="savePhoto" type="checkbox" >
<div class="track">
<div class="handle"/>
</div>
</label>
<check-box slot="content" v-model="savePhoto" @checkClick="savePhotoFun"/>
</item>
</list-item>
<h2 class="item-title">s-tab</h2>
<div class="local-region">
<s-tab :show-divider="true" @tabClick="stabClick">
<tab-item>测试</tab-item>
<tab-item>你好</tab-item>
<tab-item>再见</tab-item>
<tab-item>按钮</tab-item>
</s-tab>
<s-tab :default-active="2" position="bottom" cusClass="class" @tabClick="stabClick">
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
</s-tab>
</div>
<h2 class="item-title">Modal</h2>
<h-button class="button-class" type="primary" @click.native="showModal">Modal</h-button>
</h-content>
<bottom-tab :show-divider="true">
<tab-button cusClass="button-exit" @click.native="showConfirm"><img
src="../assets/image/warning@2x.png">退出
</tab-button>
<tab-button :disable="true" @click.native="showSuccess">登陆</tab-button>
</bottom-tab>
<!-- <number-keyboard
:show="true"
title="数字键盘"
extra-key="."
@input="onInput"
@delete="onDelete"/>-->
<h-modal ref="modal" v-model="showModalValue" position="bottom" cus-class="sign-modal">
<h-view>
<h-header style="height: 43px !important;padding-top:0px">
<div slot="left" class="h-header-btn">确定</div>
<div slot="right" class="h-header-btn">清除</div>
</h-header>
<h-content style="top:44px !important;">
<div id="draw" class="draw"/>
</h-content>
</h-view>
</h-modal>
</h-view>
</template>
<script>
import svg from '@/assets/image/loading/rolling.svg'
export default {
data () {
return {
index: 0,
count: 3,
value: '',
show: false,
items: [],
infiniteCount: 0,
deleteText: '删除',
editText: '编辑',
colors: [{name: 'Yellow', hex: '#f4d03f'}, {name: 'Green', hex: '#229954'}, {name: 'Purple', hex: '#9b59b6'}],
svgSrc: svg,
show1: false,
show2: false,
bp_name: '',
savePhoto: new Boolean(window.localStorage.savePhoto) || false,
year7Value: [],
year7: [{
name: '中国',
value: 'china',
parent: '0', // 为一级时可以不写 parent,但是此时允许为数字 0、空字符串或者字符串 '0'
}, {
name: '美国',
value: 'USA',
parent: '0',
}, {
name: '广东',
value: 'china001',
parent: 'china',
}, {
name: '广西',
value: 'china002',
parent: 'china',
}, {
name: '美国001',
value: 'usa001',
parent: 'USA',
}, {
name: '美国002',
value: 'usa002',
parent: 'USA',
}, {
name: '广州',
value: 'gz',
parent: 'china001',
}, {
name: '深圳',
value: 'sz',
parent: 'china001',
}, {
name: '广西001',
value: 'gx001',
parent: 'china002',
}, {
name: '广西002',
value: 'gx002',
parent: 'china002',
}, {
name: '美国001_001',
value: '0003',
parent: 'usa001',
}, {
name: '美国001_002',
value: '0004',
parent: 'usa001',
}, {
name: '美国002_001',
value: '0005',
parent: 'usa002',
}, {
name: '美国002_002',
value: '0006',
parent: 'usa002',
}],
modal: '',
showModalValue: false,
}
},
watch: {
bp_name (value) {
console.log('bp_name:' + value)
},
},
activated () {
for (let i = 1; i <= 20; i++) {
this.items.push(i + ' - keep walking, be 2 with you.')
}
this.top = 1
// this.bottom = 20;
},
created: function () {
this.bgColor = ['#5D98F6', '#1aad19', '#eebe41']
},
mounted () {
/* HlsModal.fromComponent(popup, {
cusClass:"login-modal",
onHide: () => {
console.log('modal hide')
},
onShow: () => {
console.log('modal show')
}
}).then((modal) => {
this.modal = modal;
}) */
},
methods: {
stab () {
console.log('tab-click')
},
stabClick (index) {
console.log('tabClickIndex:' + index)
},
// 标签用法
showNotifyAtTop () {
if (this.show1) return
this.show1 = true
},
showNotifyAtBottom () {
if (this.show2) return
this.show2 = true
},
handleNotify () {
hlsPopup.showNotify({
content: '提示内容',
position: 'top',
time: 2000,
type: 'warning',
})
},
showTopTip () {
if (this.show) return
this.show = true
},
start (i) {
console.log(`start: ${i}`)
},
move (i) {
console.log(`move: ${i}`)
},
change (i) {
// console.log(`change: ${i}`)
},
showLoading () {
hlsPopup.showLoading('请稍等!')
},
hideLoading () {
hlsPopup.hideLoading()
},
showLongTop () {
hlsPopup.showLongTop('操作成功操作成功操作成功操作成功操作成功操作成功操作成功操作成功操作成功')
},
showLongCenter () {
hlsPopup.showLongCenter('操作成功操作成功操作成功')
},
showLongBottom () {
hlsPopup.showLongBottom('操作成功操作成功操作成功操作成功')
},
showSuccess () {
hlsPopup.showSuccess('操作成功')
},
showError () {
hlsPopup.showError('操作失败')
},
showConfirm () {
hlsPopup.showConfirm({
title: '确定退出',
content: '退出后需从新登录',
onConfirm: function (index) {
alert(index)
},
})
},
showPopup () {
hlsPopup.showPopup({
title: '确定退出',
content: '退出后需从新登录',
onConfirm: function () {
alert('to do something')
},
})
},
showActionSheet () {
hlsPopup.showActionSheet({
titleText: '请选择照片',
buttonArray: ['拍照', '从相册取'],
callback: (index) => {
alert(index)
},
})
},
showActionSheetButton () {
hlsPopup.showActionSheet({
titleText: '照片',
buttonArray: [{text: '拍照', type: 'warn'}, {text: '从相册取', type: 'primary'}],
callback: (index) => {
alert(index)
},
})
},
showTime (format) {
hlsPopup.showTime({
nowDate: '2017-08-12',
format: format,
callback: (date) => {
alert(date)
},
})
},
showBigPicture () {
hlsPopup.showBigPicture({
imgUrl: 'http://hlsapp.hand-china.com/hls_file/2018/05/F1B6D85E409A4714A8540504B2D133AD',
})
},
selectListOne () {
var bpClassList = [
{
'code': 'NP',
'code_name': '个人',
}, {
'code': 'NP1',
'code_name': '个人1',
}, {
'code': 'NP2',
'code_name': '个人2',
},
]
hlsPopup.selectList({
list: bpClassList,
code: 'bp_type',
object: {},
returnItem: function (index, obj, child) {
console.log('index:' + index + ',object:' + vum.toJson(obj) + ',:child' + vum.toJson(child))
},
})
},
selectListTwo () {
var bpClassList = [
{
'code': 'NP',
'code_name': '个人',
}, {
'code': 'NP1',
'code_name': '个人1',
}, {
'code': 'NP2',
'code_name': '个人2',
}, {
'code': 'NP3',
'code_name': '个人3',
'parent': 'NP',
}, {
'code': 'NP4',
'code_name': '个人4',
'parent': 'NP1',
}, {
'code': 'NP5',
'code_name': '个人5',
'parent': 'NP2',
},
]
hlsPopup.selectList({
list: bpClassList,
code: 'bp_type',
object: {},
returnItem: function (index, obj, child) {
console.log('index:' + index + ',object:' + vum.toJson(obj) + ',:child' + vum.toJson(child))
},
})
},
selectList () {
var bpClassList = [
{
'code': 'NP',
'code_name': '个人',
}, {
'code': 'NP1',
'code_name': '个人1',
}, {
'code': 'NP2',
'code_name': '个人2',
}, {
'code': 'NP3',
'code_name': '个人3',
'parent': 'NP',
}, {
'code': 'NP4',
'code_name': '个人4',
'parent': 'NP',
}, {
'code': 'NP5',
'code_name': '个人5',
'parent': 'NP2',
}, {
'code': 'NP6',
'code_name': '个人6',
'parent': 'NP3',
}, {
'code': 'NP7',
'code_name': '个人7',
'parent': 'NP4',
},
{
'code': 'NP8',
'code_name': '个人8',
'parent': 'NP1',
},
]
hlsPopup.selectList({
list: bpClassList,
code: 'bp_type',
object: {},
returnItem: function (index, obj, child) {
console.log('index:' + index + ',object:' + vum.toJson(obj) + ',:child' + vum.toJson(child))
},
})
},
onRefresh (done) {
setTimeout(() => {
let start = this.top - 1
for (let i = start; i > start - 10; i--) {
this.items.splice(0, 0, i + ' - keep walking, be 2 with you.')
}
this.top = this.top - 10
done()
}, 1500)
},
onInfinite (done) {
setTimeout(() => {
if (this.infiniteCount < 2) {
let start = this.bottom + 1
for (let i = start; i < start + 10; i++) {
this.items.push(i + ' - keep walking, be 2 with you.')
}
this.bottom = this.bottom + 10
this.infiniteCount++
}
done()
}, 1500)
},
onItemClick (index) {
console.log(index)
},
onInput (value) {
this.value += ('' + value)
console.log(value)
},
onDelete () {
this.value = ''
console.log('delete')
},
keyboradShow () {
let vm = this
hlsPopup.showNumberKeyborad({
title: '数字键盘',
keyDown: (text) => {
vm.onInput(text)
},
keyDelete: () => {
vm.onDelete()
},
})
},
// e为该元素在数组的下标
deleteFun (e) {
console.log(e)
},
// e为该元素在数组的下标
editFun (e) {
console.log(e)
},
savePhotoFun (value) {
this.savePhoto = value
window.localStorage.setItem('savePhoto', value)
},
showModal () {
this.showModalValue = true
},
},
}
</script>
<style lang="less" rel="stylesheet">
.hls-popup {
height: 100%;
width: 100%;
.vue-better-scroll__wrapper {
width: 100%;
}
.list {
width: 100%;
}
.content {
.scrollContent {
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
flex-direction: column;
-webkit-flex-direction: column;
}
.button-class {
width: 90%;
margin: 10px 5%;
display: block;
&.image {
width: auto;
margin-right: 0;
display: inline-block;
}
&.radius-small {
border-radius: 6px;
}
&.radius-normal {
border-radius: 16px;
}
&.radius-large {
border-radius: 40px;
}
.spin {
vertical-align: middle;
}
.text {
font-size: 28px;
margin-left: 16px;
vertical-align: middle;
}
}
.purple {
color: #fff;
background-color: #7e57c2;
border: 1px solid #7e57c2;
}
.button {
background-color: @theme-color;
color: #ffffff;
height: 100px;
width: 600px;
border: 20px;
margin-top: 20px;
}
}
.item-bg {
height: 200px;
line-height: 200px;
text-align: center;
font-size: 20px;
font-weight: 500;
}
.indicators {
height: 14px;
width: 14px;
background-image: url('../assets/image/logo.png');
background-position: center;
background-size: cover;
opacity: 0.5;
&.active {
opacity: 1;
}
}
.local-region {
overflow: hidden;
position: relative;
height: 200px;
background-color: #eee;
width: 90%;
}
.sign-modal {
top: 50%;
.content {
background-color: #fff;
}
}
}
.login-modal {
height: 50%;
top: 50%
}
</style>
<template>
<h-view class="public-style home" style="height: 100%">
<h-header class="bar-custom">
<div slot="left" class="h-header-btn" @click="$routeGo()">
<i class="ion-ios-arrow-back"/>
</div>
<div slot="center">封装测试</div>
<div slot="right" class="h-header-btn">
操作
</div>
</h-header>
<!-- <s-tab @tabClick="stablick" cusClass="popup-tab">
<tab-item>测试</tab-item>
<tab-item>你好</tab-item>
<tab-item>再见</tab-item>
<tab-item>按钮</tab-item>
</s-tab>-->
<h-content
class="has-header has-footer">
<h-button class="button-class" type="primary" @click.native="showLoading">showLoading</h-button>
<h-button class="button-class" type="primary" @click.native="hideLoading">hideLoading</h-button>
<h-button class="button-class" type="primary" @click.native="showLongTop">showLongTop</h-button>
<h-button class="button-class" type="primary" @click.native="showLongCenter">showLongCenter</h-button>
<h-button class="button-class" type="primary" @click.native="showLongBottom">showLongBottom</h-button>
<h-button class="button-class" type="primary" @click.native="showSuccess">showSuccess</h-button>
<h-button class="button-class" type="primary" @click.native="showError">showError</h-button>
<h-button class="button-class" type="primary" @click.native="showConfirm">showConfirm</h-button>
<h-button class="button-class" type="primary" @click.native="showPopup">showPopup</h-button>
<h-button class="button-class" type="primary" @click.native="showActionSheet">showActionSheet</h-button>
<h-button class="button-class" type="primary" @click.native="showActionSheetButton">showActionSheet 区分按钮颜色
</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY')">showTime YYYY</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM')">showTime YYYY-MM</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM-DD')">showTime YYYY-MM-DD
</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM-DD HH')">showTime YYYY-MM-DD HH
</h-button>
<h-button class="button-class" type="primary" @click.native="showTime('YYYY-MM-DD HH:mm')">showTime YYYY-MM-DD
HH:mm
</h-button>
<h-button class="button-class" type="primary" @click.native="showBigPicture">showBigPicture</h-button>
<h-button class="button-class" type="primary" @click.native="selectListOne">selectList 普通下拉框</h-button>
<h-button class="button-class" type="primary" @click.native="selectListTwo">selectList 二级联动</h-button>
<h-button class="button-class" type="primary" @click.native="selectList">selectList 三级联动</h-button>
<h2 class="item-title">按钮类型</h2>
<h-button class="button-class" type="rimless">rimless 按钮</h-button>
<h-button class="button-class" type="default">default 按钮</h-button>
<h-button class="button-class" type="primary">primary 按钮</h-button>
<h-button class="button-class" type="safety">safety 按钮</h-button>
<h-button class="button-class" type="warning">warning 按钮</h-button>
<h-button class="button-class" type="danger">danger 按钮</h-button>
<h2 class="item-title">按钮尺寸</h2>
<h-button class="button-class" size="mini">mini 按钮</h-button>
<h-button class="button-class" size="small">small 按钮</h-button>
<h-button class="button-class" size="normal">normal 按钮</h-button>
<h-button class="button-class" size="large">large 按钮</h-button>
<h-button class="button-class" size="huge">huge 按钮</h-button>
<h2 class="item-title">自定义圆角 (直接通过class设置)</h2>
<h-button class="button-class radius-small">rimless 按钮</h-button>
<h-button class="button-class radius-normal">default 按钮</h-button>
<h-button class="button-class radius-large">primary 按钮</h-button>
<h2 class="item-title">默认点击效果</h2>
<h-button class="button-class radius-small" type="rimless">基础按钮(无边框)</h-button>
<h-button class="button-class radius-small" type="rimless" shadow>基础按钮(无边框、有阴影效果)</h-button>
<h-button class="button-class radius-small purple">基础按钮(有背景色)</h-button>
<h2 class="item-title">禁用效果</h2>
<h-button class="button-class radius-small" disabled>基础按钮(禁用)</h-button>
<h2 class="item-title">Swip基础使用</h2>
<swipe :interval="5000" @start="start" @move="move" @change="change">
<swipe-item>
<div :style="{'background': bgColor[0]}" class="item-bg">0</div>
</swipe-item>
<swipe-item>
<div :style="{'background': bgColor[1]}" class="item-bg">1</div>
</swipe-item>
<swipe-item>
<div :style="{'background': bgColor[2]}" class="item-bg">2</div>
</swipe-item>
</swipe>
<h2 class="item-title">纵向滚动</h2>
<swipe :vertical="true" style="height: 200px">
<swipe-item v-for="key in count" :key="key" :style="{'background': bgColor[key-1]}">
<div class="item-bg">{{ key-1 }}</div>
</swipe-item>
</swipe>
<h2 class="item-title">定制indicators</h2>
<swipe :index.sync="index">
<swipe-item v-for="key in count" :key="key" :style="{'background': bgColor[key-1]}">
<div class="item-bg">{{ key-1 }}</div>
</swipe-item>
<div v-for="key in count" slot="indicators" :key="key" :class="['indicators', {'active': key-1 === index}]"/>
</swipe>
<h2 class="item-title">Spin-CSS</h2>
<div class="spin-container">
<spin size="20px" color="#ccc"/>
<spin size="30px" color="#999"/>
<spin size="40px" color="#666"/>
<spin size="50px" color="#333"/>
</div>
<h2 class="item-title">SVG</h2>
<div class="spin-container">
&lt;!&ndash; 颜色要通过修改svg来实现,无法通过属性修改 &ndash;&gt;
<spin :svg-src="svgSrc" size="40px"/>
<spin :svg-src="svgSrc" size="50px"/>
<spin :svg-src="svgSrc" size="60px"/>
<spin :svg-src="svgSrc" size="70px"/>
</div>
<h2 class="item-title">top-tip</h2>
<div class="local-region">
<top-tip v-model="show" entry-direction="down" content="顶部消息提示内容"/>
参考文案
</div>
<h-button class="button-class" type="rimless" shadow @click.native="showTopTip">TopTip</h-button>
<h2 class="item-title">notify</h2>
<div class="local-region">
<notify v-model="show1" content="提示内容" type="success"/>
<notify v-model="show2" :time="3000" position="bottom" content="提示内容"/>
</div>
<h2 class="item-title">notify标签用法 (通常在局部显示时使用)</h2>
<h-button class="button-class" type="rimless" shadow @click.native="showNotifyAtTop">Notify (top)</h-button>
<h-button class="button-class" type="rimless" shadow @click.native="showNotifyAtBottom">Notify (bottom)</h-button>
<h2 class="item-title">notify 插件用法</h2>
<h-button class="button-class purple" type="rimless" shadow @click.native="handleNotify">NotifyPlugin</h-button>
<h2 class="item-title">数字键盘</h2>
<div class="list">
<div class="item">
<div class="contents">
<div class="add-name">
<div>数字键盘</div>
</div>
<div class="add-content readonly" @click="keyboradShow">
<input v-model="value" type="number" placeholder="输入" readonly>
</div>
</div>
</div>
</div>
<list-item :item-height="45">
<item>
<div slot="name">数字键盘</div>
<input
slot="content" v-model="value" type="number" placeholder="输入"
readonly @click="keyboradShow">
</item>
</list-item>
<div class="list">
<item-option
v-for="(color,index) in colors" :key="index"
class="mySlider">
<div>{{ color.name }}</div>
<div>{{ color.hex }}</div>
<div slot="buttons">
<option-button type="default" text="默认" @click.native="deleteFun"/>
<option-button type="primary" text="编辑" @click.native="deleteFun"/>
<option-button type="warn" text="删除" @click.native="deleteFun"/>
</div>
</item-option>
</div>
<h2>picker</h2>
<picker
ref="picker1" :data="year7" :columns="3" v-model="year7Value"
style="width: 100%"
@on-change="change"/>
<list-item :item-height="45">
<item>
<img slot="left-icon" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name" class="required">检查更新</div>
<div slot="content">检查更新</div>
<img slot="right-icon" src="../assets/image/arrow-down@2x.png" style="width: 8px" class="right-icon">
</item>
<item>
<img slot="left" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name" class="required">字数测试</div>
<div slot="content">我是一段很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的文字</div>
</item>
<item :showArrow="true">
<img slot="left" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name">客户名称</div>
<input slot="content" v-model="bp_name" type="text" placeholder="请输入">
</item>
<item :show-arrow="true">
<img slot="left-icon" src="../assets/image/warning@2x.png" class="left-icon">
<div slot="name">保存照片</div>
<label slot="right" class="toggle toggle-positive toggle-check" @click="savePhotoFun">
<input :checked="savePhoto" type="checkbox" >
<div class="track">
<div class="handle"/>
</div>
</label>
<check-box slot="content" v-model="savePhoto" @checkClick="savePhotoFun"/>
</item>
</list-item>
<h2 class="item-title">s-tab</h2>
<div class="local-region">
<s-tab :show-divider="true" @tabClick="stabClick">
<tab-item>测试</tab-item>
<tab-item>你好</tab-item>
<tab-item>再见</tab-item>
<tab-item>按钮</tab-item>
</s-tab>
<s-tab :default-active="2" position="bottom" cusClass="class" @tabClick="stabClick">
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
<tab-item><img src="../assets/image/warning@2x.png" style="width: 18px"></tab-item>
</s-tab>
</div>
<h2 class="item-title">Modal</h2>
<h-button class="button-class" type="primary" @click.native="showModal">Modal</h-button>
</h-content>
<bottom-tab :show-divider="true">
<tab-button cusClass="button-exit" @click.native="showConfirm"><img
src="../assets/image/warning@2x.png">退出
</tab-button>
<tab-button :disable="true" @click.native="showSuccess">登陆</tab-button>
</bottom-tab>
<!-- <number-keyboard
:show="true"
title="数字键盘"
extra-key="."
@input="onInput"
@delete="onDelete"/>-->
<h-modal ref="modal" v-model="showModalValue" position="bottom" cus-class="sign-modal">
<h-view>
<h-header style="height: 43px !important;padding-top:0px">
<div slot="left" class="h-header-btn">确定</div>
<div slot="right" class="h-header-btn">清除</div>
</h-header>
<h-content style="top:44px !important;">
<div id="draw" class="draw"/>
</h-content>
</h-view>
</h-modal>
</h-view>
</template>
<script>
import svg from '@/assets/image/loading/rolling.svg'
export default {
data () {
return {
index: 0,
count: 3,
value: '',
show: false,
items: [],
infiniteCount: 0,
deleteText: '删除',
editText: '编辑',
colors: [{name: 'Yellow', hex: '#f4d03f'}, {name: 'Green', hex: '#229954'}, {name: 'Purple', hex: '#9b59b6'}],
svgSrc: svg,
show1: false,
show2: false,
bp_name: '',
savePhoto: new Boolean(window.localStorage.savePhoto) || false,
year7Value: [],
year7: [{
name: '中国',
value: 'china',
parent: '0', // 为一级时可以不写 parent,但是此时允许为数字 0、空字符串或者字符串 '0'
}, {
name: '美国',
value: 'USA',
parent: '0',
}, {
name: '广东',
value: 'china001',
parent: 'china',
}, {
name: '广西',
value: 'china002',
parent: 'china',
}, {
name: '美国001',
value: 'usa001',
parent: 'USA',
}, {
name: '美国002',
value: 'usa002',
parent: 'USA',
}, {
name: '广州',
value: 'gz',
parent: 'china001',
}, {
name: '深圳',
value: 'sz',
parent: 'china001',
}, {
name: '广西001',
value: 'gx001',
parent: 'china002',
}, {
name: '广西002',
value: 'gx002',
parent: 'china002',
}, {
name: '美国001_001',
value: '0003',
parent: 'usa001',
}, {
name: '美国001_002',
value: '0004',
parent: 'usa001',
}, {
name: '美国002_001',
value: '0005',
parent: 'usa002',
}, {
name: '美国002_002',
value: '0006',
parent: 'usa002',
}],
modal: '',
showModalValue: false,
}
},
watch: {
bp_name (value) {
console.log('bp_name:' + value)
},
},
activated () {
for (let i = 1; i <= 20; i++) {
this.items.push(i + ' - keep walking, be 2 with you.')
}
this.top = 1
// this.bottom = 20;
},
created: function () {
this.bgColor = ['#5D98F6', '#1aad19', '#eebe41']
},
mounted () {
/* HlsModal.fromComponent(popup, {
cusClass:"login-modal",
onHide: () => {
console.log('modal hide')
},
onShow: () => {
console.log('modal show')
}
}).then((modal) => {
this.modal = modal;
}) */
},
methods: {
stab () {
console.log('tab-click')
},
stabClick (index) {
console.log('tabClickIndex:' + index)
},
// 标签用法
showNotifyAtTop () {
if (this.show1) return
this.show1 = true
},
showNotifyAtBottom () {
if (this.show2) return
this.show2 = true
},
handleNotify () {
hlsPopup.showNotify({
content: '提示内容',
position: 'top',
time: 2000,
type: 'warning',
})
},
showTopTip () {
if (this.show) return
this.show = true
},
start (i) {
console.log(`start: ${i}`)
},
move (i) {
console.log(`move: ${i}`)
},
change (i) {
// console.log(`change: ${i}`)
},
showLoading () {
hlsPopup.showLoading('请稍等!')
},
hideLoading () {
hlsPopup.hideLoading()
},
showLongTop () {
hlsPopup.showLongTop('操作成功操作成功操作成功操作成功操作成功操作成功操作成功操作成功操作成功')
},
showLongCenter () {
hlsPopup.showLongCenter('操作成功操作成功操作成功')
},
showLongBottom () {
hlsPopup.showLongBottom('操作成功操作成功操作成功操作成功')
},
showSuccess () {
hlsPopup.showSuccess('操作成功')
},
showError () {
hlsPopup.showError('操作失败')
},
showConfirm () {
hlsPopup.showConfirm({
title: '确定退出',
content: '退出后需从新登录',
onConfirm: function (index) {
alert(index)
},
})
},
showPopup () {
hlsPopup.showPopup({
title: '确定退出',
content: '退出后需从新登录',
onConfirm: function () {
alert('to do something')
},
})
},
showActionSheet () {
hlsPopup.showActionSheet({
titleText: '请选择照片',
buttonArray: ['拍照', '从相册取'],
callback: (index) => {
alert(index)
},
})
},
showActionSheetButton () {
hlsPopup.showActionSheet({
titleText: '照片',
buttonArray: [{text: '拍照', type: 'warn'}, {text: '从相册取', type: 'primary'}],
callback: (index) => {
alert(index)
},
})
},
showTime (format) {
hlsPopup.showTime({
nowDate: '2017-08-12',
format: format,
callback: (date) => {
alert(date)
},
})
},
showBigPicture () {
hlsPopup.showBigPicture({
imgUrl: 'http://hlsapp.hand-china.com/hls_file/2018/05/F1B6D85E409A4714A8540504B2D133AD',
})
},
selectListOne () {
var bpClassList = [
{
'code': 'NP',
'code_name': '个人',
}, {
'code': 'NP1',
'code_name': '个人1',
}, {
'code': 'NP2',
'code_name': '个人2',
},
]
hlsPopup.selectList({
list: bpClassList,
code: 'bp_type',
object: {},
returnItem: function (index, obj, child) {
console.log('index:' + index + ',object:' + vum.toJson(obj) + ',:child' + vum.toJson(child))
},
})
},
selectListTwo () {
var bpClassList = [
{
'code': 'NP',
'code_name': '个人',
}, {
'code': 'NP1',
'code_name': '个人1',
}, {
'code': 'NP2',
'code_name': '个人2',
}, {
'code': 'NP3',
'code_name': '个人3',
'parent': 'NP',
}, {
'code': 'NP4',
'code_name': '个人4',
'parent': 'NP1',
}, {
'code': 'NP5',
'code_name': '个人5',
'parent': 'NP2',
},
]
hlsPopup.selectList({
list: bpClassList,
code: 'bp_type',
object: {},
returnItem: function (index, obj, child) {
console.log('index:' + index + ',object:' + vum.toJson(obj) + ',:child' + vum.toJson(child))
},
})
},
selectList () {
var bpClassList = [
{
'code': 'NP',
'code_name': '个人',
}, {
'code': 'NP1',
'code_name': '个人1',
}, {
'code': 'NP2',
'code_name': '个人2',
}, {
'code': 'NP3',
'code_name': '个人3',
'parent': 'NP',
}, {
'code': 'NP4',
'code_name': '个人4',
'parent': 'NP',
}, {
'code': 'NP5',
'code_name': '个人5',
'parent': 'NP2',
}, {
'code': 'NP6',
'code_name': '个人6',
'parent': 'NP3',
}, {
'code': 'NP7',
'code_name': '个人7',
'parent': 'NP4',
},
{
'code': 'NP8',
'code_name': '个人8',
'parent': 'NP1',
},
]
hlsPopup.selectList({
list: bpClassList,
code: 'bp_type',
object: {},
returnItem: function (index, obj, child) {
console.log('index:' + index + ',object:' + vum.toJson(obj) + ',:child' + vum.toJson(child))
},
})
},
onRefresh (done) {
setTimeout(() => {
let start = this.top - 1
for (let i = start; i > start - 10; i--) {
this.items.splice(0, 0, i + ' - keep walking, be 2 with you.')
}
this.top = this.top - 10
done()
}, 1500)
},
onInfinite (done) {
setTimeout(() => {
if (this.infiniteCount < 2) {
let start = this.bottom + 1
for (let i = start; i < start + 10; i++) {
this.items.push(i + ' - keep walking, be 2 with you.')
}
this.bottom = this.bottom + 10
this.infiniteCount++
}
done()
}, 1500)
},
onItemClick (index) {
console.log(index)
},
onInput (value) {
this.value += ('' + value)
console.log(value)
},
onDelete () {
this.value = ''
console.log('delete')
},
keyboradShow () {
let vm = this
hlsPopup.showNumberKeyborad({
title: '数字键盘',
keyDown: (text) => {
vm.onInput(text)
},
keyDelete: () => {
vm.onDelete()
},
})
},
// e为该元素在数组的下标
deleteFun (e) {
console.log(e)
},
// e为该元素在数组的下标
editFun (e) {
console.log(e)
},
savePhotoFun (value) {
this.savePhoto = value
window.localStorage.setItem('savePhoto', value)
},
showModal () {
this.showModalValue = true
},
},
}
</script>
<style lang="less" rel="stylesheet">
.home {
height: 100%;
width: 100%;
.vue-better-scroll__wrapper {
width: 100%;
}
.list {
width: 100%;
}
.content {
.scrollContent {
display: flex;
display: -webkit-flex;
align-items: center;
-webkit-align-items: center;
flex-direction: column;
-webkit-flex-direction: column;
}
.button-class {
width: 90%;
margin: 10px 5%;
display: block;
&.image {
width: auto;
margin-right: 0;
display: inline-block;
}
&.radius-small {
border-radius: 6px;
}
&.radius-normal {
border-radius: 16px;
}
&.radius-large {
border-radius: 40px;
}
.spin {
vertical-align: middle;
}
.text {
font-size: 28px;
margin-left: 16px;
vertical-align: middle;
}
}
.purple {
color: #fff;
background-color: #7e57c2;
border: 1px solid #7e57c2;
}
.button {
background-color: @theme-color;
color: #ffffff;
height: 100px;
width: 600px;
border: 20px;
margin-top: 20px;
}
}
.item-bg {
height: 200px;
line-height: 200px;
text-align: center;
font-size: 20px;
font-weight: 500;
}
.indicators {
height: 14px;
width: 14px;
background-image: url('../assets/image/logo.png');
background-position: center;
background-size: cover;
opacity: 0.5;
&.active {
opacity: 1;
}
}
.local-region {
overflow: hidden;
position: relative;
height: 200px;
background-color: #eee;
width: 90%;
}
.sign-modal {
top: 50%;
.content {
background-color: #fff;
}
}
}
.login-modal {
height: 50%;
top: 50%
}
</style>
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/home'
// test工具类
import HlsPopup from '@/pages/hlsPopup'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect: '/home',
},
{path: '/home', component: Home, name: 'Home', meta: {keepAlive: true}},
// test工具类
{path: '/hls-popup', component: HlsPopup, name: 'HlsPopup', meta: {keepAlive: false}},
],
scrollBehavior (to, from, savedPosition) {
if (to.hash) {
return {
selector: to.hash,
}
}
},
})
import Autosize from 'autosize'
function vueTouch (el, binding, type) {
var _this = this
this.obj = el
this.binding = binding
this.touchType = type
this.vueTouches = {x: 0, y: 0}
this.vueMoves = true
this.vueLeave = true
this.longTouch = true
this.vueCallBack = typeof (binding.value) === 'object' ? binding.value.fn : binding.value
this.obj.addEventListener('touchstart', function (e) {
_this.start(e)
}, false)
this.obj.addEventListener('touchend', function (e) {
_this.end(e)
}, false)
this.obj.addEventListener('touchmove', function (e) {
_this.move(e)
}, false)
};
vueTouch.prototype = {
start: function (e) {
this.vueMoves = true
this.vueLeave = true
this.longTouch = true
this.vueTouches = {x: e.changedTouches[0].pageX, y: e.changedTouches[0].pageY}
this.time = setTimeout(function () {
if (this.vueLeave && this.vueMoves) {
this.touchType === 'longtap' && this.vueCallBack(this.binding.value, e)
this.longTouch = false
}
}.bind(this), 1000)
},
end: function (e) {
var disX = e.changedTouches[0].pageX - this.vueTouches.x
var disY = e.changedTouches[0].pageY - this.vueTouches.y
clearTimeout(this.time)
if (Math.abs(disX) > 100 || Math.abs(disY) > 100) {
this.touchType === 'swipe' && this.vueCallBack(this.binding.value, e)
if (Math.abs(disX) > Math.abs(disY)) {
if (disX > 100) {
this.touchType === 'swiperight' && this.vueCallBack(this.binding.value, e)
}
if (disX < -100) {
this.touchType === 'swipeleft' && this.vueCallBack(this.binding.value, e)
}
} else {
if (disY > 100) {
this.touchType === 'swipedown' && this.vueCallBack(this.binding.value, e)
}
if (disY < -100) {
this.touchType === 'swipeup' && this.vueCallBack(this.binding.value, e)
}
}
} else {
if (this.longTouch && this.vueMoves) {
this.touchType === 'tap' && this.vueCallBack(this.binding.value, e)
this.vueLeave = false
}
}
},
move: function (e) {
this.vueMoves = false
},
} // prop.autosize
export default (Vue) => {
Vue.directive('focus', {
// 自动获取鼠标焦点
inserted: function (el) {
el.focus()
},
})
Vue.directive('tap', {// 点击事件
bind: function (el, binding) {
new vueTouch(el, binding, 'tap') // eslint-disable-line
},
})
Vue.directive('swipe', {// 滑动事件
bind: function (el, binding) {
new vueTouch(el, binding, 'swipe') // eslint-disable-line
},
})
Vue.directive('swipeleft', {// 左滑事件
bind: function (el, binding) {
new vueTouch(el, binding, 'swipeleft') // eslint-disable-line
},
})
Vue.directive('swiperight', {// 右滑事件
bind: function (el, binding) {
new vueTouch(el, binding, 'swiperight') // eslint-disable-line
},
})
Vue.directive('swipedown', {// 下滑事件
bind: function (el, binding) {
new vueTouch(el, binding, 'swipedown') // eslint-disable-line
},
})
Vue.directive('swipeup', {// 上滑事件
bind: function (el, binding) {
new vueTouch(el, binding, 'swipeup') // eslint-disable-line
},
})
Vue.directive('longtap', {// 长按事件
bind: function (el, binding) {
new vueTouch(el, binding, 'longtap') // eslint-disable-line
},
})
Vue.directive('hlsImgZoom', {
componentUpdated: function (element) {
var elWidth, elHeight
// mode : 'pinch' or 'swipe'
var mode = ''
// distance between two touche points (mode : 'pinch')
var distance = 0
var initialDistance = 0
// image scaling
var scale = 1
var relativeScale = 1
var initialScale = 1
var maxScale = 5
if (isNaN(maxScale) || maxScale <= 1) {
maxScale = 3
}
// position of the upper left corner of the element
var positionX = 0
var positionY = 0
var initialPositionX = 0
var initialPositionY = 0
// central origin (mode : 'pinch')
var originX = 0
var originY = 0
// start coordinate and amount of movement (mode : 'swipe')
var startX = 0
var startY = 0
var moveX = 0
var moveY = 0
var image = new Image()
image.onload = function () {
elWidth = element.clientWidth
elHeight = element.clientHeight
element.style.webkitTransformOrigin = '0px 0px 0px'
element.style.transformOrigin = '0px 0px 0px'
element.addEventListener('touchstart', touchstartHandler)
element.addEventListener('touchmove', touchmoveHandler)
element.addEventListener('touchend', touchendHandler)
}
image.src = element.src
/**
* @param {object} evt
*/
function touchstartHandler (evt) {
var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches
startX = touches[0].clientX
startY = touches[0].clientY
initialPositionX = positionX
initialPositionY = positionY
moveX = 0
moveY = 0
}
/**
* @param {object} evt
*/
function touchmoveHandler (evt) {
var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches
if (mode === '') {
if (touches.length === 1 && scale > 1) {
mode = 'swipe'
} else if (touches.length === 2) {
mode = 'pinch'
initialScale = scale
initialDistance = getDistance(touches)
originX = touches[0].clientX -
parseInt((touches[0].clientX - touches[1].clientX) / 2, 10) -
element.offsetLeft - initialPositionX
originY = touches[0].clientY -
parseInt((touches[0].clientY - touches[1].clientY) / 2, 10) -
element.offsetTop - initialPositionY
}
}
if (mode === 'swipe') {
evt.preventDefault()
moveX = touches[0].clientX - startX
moveY = touches[0].clientY - startY
positionX = initialPositionX + moveX
positionY = initialPositionY + moveY
transformElement()
} else if (mode === 'pinch') {
evt.preventDefault()
distance = getDistance(touches)
relativeScale = distance / initialDistance
scale = relativeScale * initialScale
positionX = originX * (1 - relativeScale) + initialPositionX + moveX
positionY = originY * (1 - relativeScale) + initialPositionY + moveY
transformElement()
}
}
/**
* @param {object} evt
*/
function touchendHandler (evt) {
var touches = evt.originalEvent ? evt.originalEvent.touches : evt.touches
if (mode === '' || touches.length > 0) {
return
}
if (scale < 1) {
scale = 1
positionX = 0
positionY = 0
} else if (scale > maxScale) {
scale = maxScale
relativeScale = scale / initialScale
positionX = originX * (1 - relativeScale) + initialPositionX + moveX
positionY = originY * (1 - relativeScale) + initialPositionY + moveY
} else {
if (positionX > 0) {
positionX = 0
} else if (positionX < elWidth * (1 - scale)) {
positionX = elWidth * (1 - scale)
}
if (positionY > 0) {
positionY = 0
} else if (positionY < elHeight * (1 - scale)) {
positionY = elHeight * (1 - scale)
}
}
transformElement(0.1)
mode = ''
}
/**
* @param {Array} touches
* @return {number}
*/
function getDistance (touches) {
var d = Math.sqrt(Math.pow(touches[0].clientX - touches[1].clientX, 2) +
Math.pow(touches[0].clientY - touches[1].clientY, 2))
return parseInt(d, 10)
}
/**
* @param {number} [duration]
*/
function transformElement (duration) {
var transition = duration ? 'all cubic-bezier(0,0,.5,1) ' + duration + 's' : ''
var matrixArray = [scale, 0, 0, scale, positionX, positionY]
var matrix = 'matrix(' + matrixArray.join(',') + ')'
element.style.webkitTransition = transition
element.style.transition = transition
element.style.webkitTransform = matrix + ' translate3d(0,0,0)'
element.style.transform = matrix + ' translate3d(0,0,0)'
}
},
})
Vue.directive('keyboardAttach', {// 监听键盘
inserted: function (el, binding) {
let KEYBOARD_OPEN_CSS = 'foot-keyboard-open'
function keyboardHeight () {
let innerHeight = window.innerHeight
let innerWidth = window.innerWidth
if (vum.Platform.isIOS()) {
if (!vum.Platform.isWebView()) {
return 266
}
if (innerWidth >= 375 && innerHeight >= 812) {
return 330
}
return 300
} else {
return 275
}
}
let height = keyboardHeight()
function hasClass (element, csName) {
return element.className.match(RegExp('(\\s|^)' + csName + '(\\s|$)'))
}
function addClass (element, csName) {
if (!hasClass(element, csName)) {
element.className += ' ' + csName
}
element.style.marginBottom = height + 'px'
}
function removeClass (element, csName) {
if (hasClass(element, csName)) {
element.classList.remove(csName)
}
element.style.marginBottom = 0 + 'px'
}
window.addEventListener('native.keyboardshow', function (e) {
addClass(el, KEYBOARD_OPEN_CSS)
})
window.addEventListener('native.keyboardhide', function (e) {
removeClass(el, KEYBOARD_OPEN_CSS)
})
},
unbind: function (el, binding) {
let KEYBOARD_OPEN_CSS = 'foot-keyboard-open'
function hasClass (element, csName) {
return element.className.match(RegExp('(\\s|^)' + csName + '(\\s|$)'))
}
function removeClass (element, csName) {
if (hasClass(element, csName)) {
element.classList.remove(csName)
}
element.style.marginBottom = 0 + 'px'
}
removeClass(el, KEYBOARD_OPEN_CSS)
window.removeEventListener('native.keyboardshow', function (e) {
})
window.removeEventListener('native.keyboardhide', function (e) {
})
},
})
Vue.directive('autoSize', {
bind: function (el, binding) {
if (el.nodeName === 'TEXTAREA') {
Autosize(el)
}
el.addEventListener('oninput', function (e) {
Autosize.update(el)
})
},
unbind: function (el, binding) {
Autosize.update(el)
Autosize.destroy(el)
el.removeEventListener('oninput', function (e) {
})
},
})
}
export default{
createElement: function (marker, tag) {
let el = document.createElement(tag || 'div')
el.setAttribute(marker, '')
document.body.appendChild(el)
},
removeElement: function (marker) {
let el = document.querySelector(marker) || document.querySelector(`[${marker}]`)
if (el) { document.body.removeChild(el) }
},
timeout: function (duration = 0) {
return new Promise((resolve, reject) => {
setTimeout(resolve, duration)
})
},
}
export default (Vue) => {
Vue.filter('currency', function (val) {
if (!val) return '0.00'
var intPart = Number(val).toFixed(0) // 获取整数部分
var intPartFormat = intPart.toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,') // 将整数部分逢三一断
var floatPart = '.00' // 预定义小数部分
var value2Array = (val + '').split('.')
// =2表示数据有小数位
if (value2Array.length === 2) {
floatPart = value2Array[1].toString() // 拿到小数部分
if (floatPart.length === 1) { // 补0,实际上用不着
return intPartFormat + '.' + floatPart + '0'
} else {
return intPartFormat + '.' + floatPart
}
} else {
return intPartFormat + floatPart
}
})
Vue.filter('datetime', timestamp => {
function format (number) {
return number.toString().padStart(2, '0')
}
const date = new Date(Number.parseInt(timestamp, 10))
const YYYY = date.getFullYear()
const MM = date.getMonth() + 1
const DD = date.getDate()
const hh = date.getHours()
const mm = date.getMinutes()
const ss = date.getSeconds()
return `${YYYY}-${format(MM)}-${format(DD)} ${format(hh)}:${format(mm)}:${format(ss)}`
})
}
// 引入axios
import axios from 'axios'
import hlsPopup from './hlsPopup'
let promiseArr = {}
let cancel = {}
const CancelToken = axios.CancelToken
// 请求拦截器
axios.interceptors.request.use(config => {
// 发起请求时,取消掉当前正在进行的相同请求
if (promiseArr[config.url]) {
promiseArr[config.url]('操作取消')
promiseArr[config.url] = cancel
} else {
promiseArr[config.url] = cancel
}
return config
}, error => {
return Promise.reject(error)
})
// 响应拦截器即异常处理
axios.interceptors.response.use(response => {
if ($config.debug) {
let postName = 'post'
console.log(postName + ' success')
console.log(postName + ' response ' + JSON.stringify(response.data, '', 2))
console.log(postName + ' End!')
}
if (response.data.result === 'E' || response.data.code === 'E') {
hlsPopup.hideLoading()
const err = {}
err.message = response.data.message
hlsPopup.showError(err.message)
return Promise.resolve(err)
} else {
return response.data
}
}, err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '错误请求'
break
case 401:
err.message = '登录已失效,请重新登录'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = '请求错误,未找到该资源'
break
case 405:
err.message = '不支持的请求类型'
break
case 408:
err.message = '请求超时'
break
case 500:
err.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
default:
err.message = `连接错误${err.response.status}`
}
} else {
err.message = '连接到服务器失败'
}
if (err.response && err.response.status === 401) {
hlsPopup.hideLoading()
hlsPopup.showPopup({
title: '登录失效,重新登录',
onConfirm: () => {
// router.push({name: 'Login'})
if (vum.Platform.isIOS()) {
cordova.exec(null, null, 'BridgePlugin', 'closeWebView', [])
} else if (vum.Platform.isIOS()) {
var dict = {
'className': 'WebBridge',
'function': 'close',
'successCallBack': 'sCallBack',
'failureCallBack': 'eCallBack',
}
HandBridge.postMessage(JSON.stringify(dict))
}
},
})
} else {
hlsPopup.hideLoading()
hlsPopup.showError(err.message)
}
return Promise.resolve(err)
})
axios.defaults.baseURL = ''
axios.defaults.timeout = 10000
// get请求
export function get (url) {
let param = {}
let headers = {}
if (window.localStorage.access_token) {
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + window.localStorage.access_token,
}
} else {
headers = {
'Content-Type': 'application/json',
}
}
return new Promise((resolve, reject) => {
axios({
method: 'get',
url,
headers: headers,
params: param,
cancelToken: new CancelToken(c => {
cancel = c
}),
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
// post请求
export function post (url, param) {
param.user_id = window.localStorage.user_id
param.access_token = window.localStorage.access_token
let headers = {}
if (window.localStorage.access_token) {
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + window.localStorage.access_token,
}
} else {
headers = {
'Content-Type': 'application/json',
}
}
if (process.env.debug) {
let postName = 'POST'
console.log(postName + ' Start!')
console.log(postName + ' url ' + url)
console.log(postName + ' parameter ' + JSON.stringify(param, '', 2))
}
return new Promise((resolve, reject) => {
axios({
method: 'post',
headers: headers,
url,
data: param,
cancelToken: new CancelToken(c => {
cancel = c
}),
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
import Vue from 'vue'
import {ToastPlugin, AlertPlugin, ConfirmPlugin, LoadingPlugin, DatetimePlugin} from 'vux'
import {ActionSheetPlugin, ShowPicturePlugin, SelectPlugin, NotifyPlugin, HlsModalPlugin, NumberKeyboardPlugin} from 'hls-easy-ui'
Vue.use(ToastPlugin)
Vue.use(AlertPlugin)
Vue.use(ConfirmPlugin)
Vue.use(LoadingPlugin)
Vue.use(DatetimePlugin)
Vue.use(ActionSheetPlugin)
Vue.use(ShowPicturePlugin)
Vue.use(SelectPlugin)
Vue.use(NumberKeyboardPlugin)
Vue.use(NotifyPlugin)
Vue.use(HlsModalPlugin)
export default {
isLoading: false,
SHOW_TIMES: 2000,
IS_SHOW_MASK: true,
/**
* 锁屏函数 超过10s后自动解屏用于防止屏幕锁死
* 自动截屏成弹出错误提示框
* @param content 锁屏内容
*/
showLoading: function (content) {
let vm = this
Vue.$vux.loading.show({
text: content || 'Loading',
})
this.isLoading = true
// 10s后自动解屏用于防止屏幕锁死
setTimeout(() => {
if (vm.isLoading) {
Vue.$vux.loading.hide()
vm.isLoading = false
// 弹出操作失败
Vue.$vux.toast.show({
text: '操作失败',
type: 'warn',
time: vm.SHOW_TIMES,
isShowMask: vm.IS_SHOW_MASK,
position: 'middle',
})
}
}, 10000)
},
/**
* 隐藏
*/
hideLoading: function () {
Vue.$vux.loading.hide()
this.isLoading = false
},
/**
* 长时间顶部提示toast
* @param content
*/
showLongTop: function (content) {
let vm = this
let text = content || '操作失败'
if (!process.env.isMobilePlatform) {
Vue.$vux.toast.show({
text: text,
type: 'text',
time: vm.SHOW_TIMES,
isShowMask: vm.IS_SHOW_MASK,
position: 'top',
})
} else {
window.plugins.toast.showLongTop(content, function (success) {
}, function (error) { // eslint-disable-line
})
}
},
/**
* 长时间中部提示toast
* @param content
*/
showLongCenter: function (content) {
let vm = this
let text = content || '操作失败'
if (!process.env.isMobilePlatform) {
Vue.$vux.toast.show({
text: text,
type: 'text',
time: vm.SHOW_TIMES,
isShowMask: vm.IS_SHOW_MASK,
position: 'middle',
})
} else {
window.plugins.toast.showLongCenter(content, function (success) {
}, function (error) { // eslint-disable-line
})
}
},
/**
* 长时间中部提示toast
* @param content
*/
showLongBottom: function (content) {
let vm = this
let text = content || '操作失败'
if (!process.env.isMobilePlatform) {
Vue.$vux.toast.show({
text: text,
time: vm.SHOW_TIMES,
type: 'text',
isShowMask: vm.IS_SHOW_MASK,
position: 'bottom',
})
} else {
window.plugins.toast.showLongBottom(content, function (success) {
}, function (error) { // eslint-disable-line
})
}
},
/**
* 成功提示框
* @param content
*/
showSuccess: function (content) {
let vm = this
Vue.$vux.toast.show({
text: content || '操作成功',
time: vm.SHOW_TIMES,
isShowMask: vm.IS_SHOW_MASK,
type: 'success',
position: 'middle',
})
},
/**
* 成功提示框
* @param content
*/
showError: function (content) {
let vm = this
Vue.$vux.toast.show({
text: content || '操作失败',
type: 'warn',
isShowMask: vm.IS_SHOW_MASK,
time: vm.SHOW_TIMES,
position: 'middle',
})
},
/**
* 弹出是否确认的窗口
* @param confirmObject.title 标题
* @param confirmObject.content 内容
* @param confirmObject.onConfirm 确定函数
*/
showConfirm: function (confirmObject) {
if (!process.env.isMobilePlatform) {
let def = {
title: confirmObject.title || '提示',
content: confirmObject.content || '',
confirmText: '确定',
cancelText: '取消',
onConfirm: () => {
confirmObject.onConfirm(1)
},
onCancel: () => {
confirmObject.onConfirm(0)
},
}
Vue.$vux.confirm.show(def)
} else {
let message = confirmObject.content || ''
let onConfirm = function (index) {
confirmObject.onConfirm(index)
}
let title = confirmObject.title
navigator.notification.confirm(
message, // message
function (index) {
onConfirm(index - 1)
},
title, // title
['取消', '确定'] // buttonLabels
)
}
},
/*
* 弹出确认的窗口
* @param confirmObject.title 标题
* @param confirmObject.content 内容
* @param confirmObject.onConfirm 确定函数
*
*/
showPopup: function (confirmObject) {
if (!process.env.isMobilePlatform) {
let def = {
title: confirmObject.title || '提示',
content: confirmObject.content || '',
confirmText: '确定',
showCancelButton: false,
onConfirm: () => {
confirmObject.onConfirm()
},
}
Vue.$vux.confirm.show(def)
} else {
var alertDismissed = function (index) {
confirmObject.onConfirm()
}
let title = confirmObject.title || '提示'
var message = confirmObject.content || ''
navigator.notification.alert(
message, // message
alertDismissed, // callback
title || '提示', // title
'确定' // buttonName
)
}
},
/**
* @param actionObject.titleText 弹出框的标题可空
* @param actionObject.callback 点击按钮的回调函数 回传buttonArray数组下标
* @param actionObject.buttonArray 按钮数组支持[string,string],[object,object],
* 当为后一种是 object为{text:'拍照',type:'primary'},type支持 primary,warn,disabled
*
* {
* titleText: '照片',
* buttonArray: [{text:'拍照',type:'warn'}, {text:'从相册取',type:'primary'}],
* callback: (index) => {
* alert(index);
* }
* }
*
* {
* buttonArray: ['拍照','从相册取'],
* callback: (index) => {
* alert(index);
* }
* }
*
*/
showActionSheet: function (actionObject) {
if (typeof actionObject === 'object') {
let buttons = []
for (let i = 0; i < actionObject.buttonArray.length; i++) {
if (typeof actionObject.buttonArray[i] === 'object') {
buttons.push({
text: actionObject.buttonArray[i].text,
type: actionObject.buttonArray[i].type,
callback: actionObject.callback,
})
} else {
buttons.push({
text: actionObject.buttonArray[i],
callback: actionObject.callback,
})
}
}
ActionSheetPlugin.show({
title: actionObject.titleText || '',
buttons: buttons,
})
}
},
/**
* 时间选择函数
* @param timeObject.nowDate 当前展示的时间 可不填
* @param timeObject.format 时间格式支持不支持秒
* @param timeObject.callback 点击确定的回调函数
*
*/
showTime: function (timeObject) {
let date = new Date().format('yyyy-MM-dd')
let format = 'YYYY-MM-DD'
if (timeObject.nowDate) {
date = timeObject.nowDate
}
if (timeObject.format) {
format = timeObject.format
}
Vue.$vux.datetime.show({
cancelText: '取消',
confirmText: '确定',
minYear: '1900',
maxYear: '2200',
format: format,
value: date,
onConfirm (val) {
timeObject.callback(val)
},
})
},
/**
* 图片放大预览
* @param imgObject.imgUrl
*/
showBigPicture: function (imgObject) {
if (typeof imgObject === 'object') {
ShowPicturePlugin.show({
imgUrl: imgObject.imgUrl,
width: imgObject.width,
})
}
},
/**
* 下拉框 支持级联操作 需指定 parent 属性
* @param selectOption.list Array [{"code": "NP","code_name": "个人"}]
* @param selectOption.code String "bp_type"
* @param selectOption.object Object 当前数据对象
* @param selectOption.returnItem function 回调函数返回index与object
* var bp_class_list = [
* {
* "code": "NP",
* "code_name": "个人"
* },{
* "code": "NP1",
* "code_name": "个人1"
* }];
* hlsPopup.selectList({
* list: bp_class_list,
* code: 'bp_type',
* object: {},
* returnItem: function (index, obj) {
* console.log(obj)
* }
* })
*
*/
selectList: function (selectOption) {
if (typeof selectOption === 'object') {
let list = []
let length = selectOption.list.length
vum.forEach(selectOption.list, function (date, index, array) {
list.push({
value: date.code,
name: date.code_name,
parent: date.parent,
})
if (index === (length - 1)) {
SelectPlugin.show({
list: list,
callBack: selectOption.returnItem,
code: selectOption.code,
object: selectOption.object,
})
}
})
}
},
/**
* 弹出数字键盘
* @param keyboardObject.title 键盘的title
* @param keyboardObject.closeButtonText 键盘的关闭按钮文字
* @param keyboardObject.keyDown 普通按键按下去事件
* @param keyboardObject.keyDelete 删除按键按下去事件
*/
showNumberKeyborad: function (keyboardObject) {
if (typeof keyboardObject === 'object') {
NumberKeyboardPlugin.show({
title: keyboardObject.title,
closeButtonText: keyboardObject.closeButtonText,
extraKey: keyboardObject.extraKey || '.',
keyDown: function (text) {
keyboardObject.keyDown(text)
},
keyDelete: function () {
keyboardObject.keyDelete()
// console.log('delete')
},
})
}
},
/**
* 弹出Notify
* @param notifyObject.content 内容
* @param notifyObject.position 位置
* @param notifyObject.time 显示时长
* @param notifyObject.type 类型 success warning default
*/
showNotify: function (notifyObject) {
if (typeof notifyObject === 'object') {
NotifyPlugin.show({
show: true,
content: notifyObject.content,
position: notifyObject.position || 'top',
time: notifyObject.time || 3000,
type: notifyObject.type || 'default',
})
}
},
}
export default {
city: {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外',
},
// 检查号码是否符合规范,包括长度,类型
isCardNo (card) {
// 身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X
card = card.toUpperCase()
let reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
return reg.test(card)
},
// 取身份证前两位,校验省份
checkProvince: function (card) {
card = card.toUpperCase()
let province = card.substr(0, 2)
if (this.city[province] === undefined) {
return false
}
return true
},
// 检查生日是否正确
checkBirthday: function (card) {
card = card.toUpperCase()
let len = card.length
let arrData
let year
let month
let day
let birthday
// 身份证15位时,次序为省(3位)市(3位)年(2位)月(2位)日(2位)校验位(3位),皆为数字
if (len === 15) {
let reFifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/
arrData = card.match(reFifteen)
year = arrData[2]
month = arrData[3]
day = arrData[4]
birthday = new Date('19' + year + '/' + month + '/' + day)
return this.verifyBirthday('19' + year, month, day, birthday)
}
// 身份证18位时,次序为省(3位)市(3位)年(4位)月(2位)日(2位)校验位(4位),校验位末尾可能为X
if (len === 18) {
let reEighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/
arrData = card.match(reEighteen)
year = arrData[2]
month = arrData[3]
day = arrData[4]
birthday = new Date(year + '/' + month + '/' + day)
return this.verifyBirthday(year, month, day, birthday)
}
return false
},
// 校验日期
verifyBirthday: function (year, month, day, birthday) {
// 年月日是否合理
return (birthday.getFullYear().toString() === year && ((birthday.getMonth() + 1) < 10 ? '0' + (birthday.getMonth() + 1) : (birthday.getMonth() + 1)) === month &&
birthday.getDate().toString() === day)
},
// 校验位的检测
checkParity (card) {
// 15位转18位
card = this.changeFivteenToEighteen(card)
var len = card.length
if (len === 18) {
let arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
let arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2')
let cardTemp = 0
for (let i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i]
}
let valnum = arrCh[cardTemp % 11]
if (valnum === card.substr(17, 1)) {
return true
}
return false
}
return false
},
// 15位转18位身份证号
changeFivteenToEighteen (card) {
if (card.length === 15) {
let arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
let arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2')
let cardTemp = 0
card = card.substr(0, 6) + '19' + card.substr(6, card.length - 6)
for (let i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i]
}
card += arrCh[cardTemp % 11]
return card
}
return card
},
/**
* 检验身份证号码
*/
isCardID (card) {
card = card.toUpperCase()
if (this.isCardNo(card) === false) {
return '你输入的身份证长度或格式错误'
}
// 检查省份
if (this.checkProvince(card) === false) {
return '你的身份证地区非法'
}
// 校验生日
if (this.checkBirthday(card) === false) {
return '身份证上的出生日期非法'
}
// 检验位的检测
if (this.checkParity(card) === false) {
return '你输入的身份证号非法'
}
return ''
},
// 银行卡号校验
isBankAccount: function (bankno) {
if (bankno.length < 16 || bankno.length > 19) {
/* 银行卡号长度必须在16到19之间 */
return '银行卡号长度必须在16到19之间'
}
let num = /^\d*$/// 全数字
if (!num.exec(bankno)) {
/* 银行卡号必须全为数字 */
return '银行卡号必须全为数字'
}
var strBin = '10,18,30,35,37,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,58,60,62,65,68,69,84,87,88,94,95,98,99'
if (strBin.indexOf(bankno.substring(0, 2)) === -1) {
/* 银行卡号开头6位不符合规范 */
return '银行卡号开头6位不符合规范'
}
// Luhn校验
if (!this.luhnCheck(bankno)) {
return '银行卡号有误,请从新输入'
}
// return true;
},
luhnCheck: function (bankno) {
let lastNum = bankno.substr(bankno.length - 1, 1)// 取出最后一位(与luhn进行比较)
let first15Num = bankno.substr(0, bankno.length - 1)// 前15或18位
let newArr = []
for (let i = first15Num.length - 1; i > -1; i--) { // 前15或18位倒序存进数组
newArr.push(first15Num.substr(i, 1))
}
let arrJiShu = [] // 奇数位*2的积 <9
let arrJiShu2 = [] // 奇数位*2的积 >9
let arrOuShu = [] // 偶数位数组
for (let j = 0; j < newArr.length; j++) {
if ((j + 1) % 2 === 1) { // 奇数位
if (parseInt(newArr[j]) * 2 < 9) { arrJiShu.push(parseInt(newArr[j]) * 2) } else { arrJiShu2.push(parseInt(newArr[j]) * 2) }
} else { arrOuShu.push(newArr[j]) }
}
let jishuChild1 = []// 奇数位*2 >9 的分割之后的数组个位数
let jishuChild2 = []// 奇数位*2 >9 的分割之后的数组十位数
for (let h = 0; h < arrJiShu2.length; h++) {
jishuChild1.push(parseInt(arrJiShu2[h]) % 10)
jishuChild2.push(parseInt(arrJiShu2[h]) / 10)
}
let sumJiShu = 0 // 奇数位*2 < 9 的数组之和
let sumOuShu = 0 // 偶数位数组之和
let sumJiShuChild1 = 0 // 奇数位*2 >9 的分割之后的数组个位数之和
let sumJiShuChild2 = 0 // 奇数位*2 >9 的分割之后的数组十位数之和
for (let m = 0; m < arrJiShu.length; m++) {
sumJiShu = sumJiShu + parseInt(arrJiShu[m])
}
for (let n = 0; n < arrOuShu.length; n++) {
sumOuShu = sumOuShu + parseInt(arrOuShu[n])
}
for (let p = 0; p < jishuChild1.length; p++) {
sumJiShuChild1 = sumJiShuChild1 + parseInt(jishuChild1[p])
sumJiShuChild2 = sumJiShuChild2 + parseInt(jishuChild2[p])
}
// 计算总和
let sumTotal = parseInt(sumJiShu) + parseInt(sumOuShu) + parseInt(sumJiShuChild1) + parseInt(sumJiShuChild2)
// 计算luhn值
let k = parseInt(sumTotal) % 10 === 0 ? 10 : parseInt(sumTotal) % 10
let luhn = 10 - k
if (lastNum === luhn) {
return true
} else {
/* 银行卡号必须符合luhn校验 */
return false
}
},
/**
* 判断输入是否为十一位电话号码
* @param str 字符串
* @returns {boolean}
*/
phoneNumber: function (str) {
// ^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$
let reg = /^((13[0-9]{1})|(14[0-9]{1})|(15[0-9]{1})|(17[0-9]{1})|(18[0-9]{1})|166|198|199|(147))+\d{8}$/
return reg.test(str)
},
/**
* 判断+86后11位电话号码
* @param str 字符串
* @returns {boolean}
*/
phoneNumber86: function (str) {
let reg = /^(\+86|\+86+\s)+(((13[0-9]{1})|(14[0-9]{1})|(15[0-9]{1})|(17[0-9]{1})|(18[0-9]{1})|166|198|199|(147))+\d{8})$/
return reg.test(str)
},
/**
* 是否是邮件格式
* @param str
* @returns {boolean|*}
*/
isEmailAddress: function (str) {
let pattern = /^([a-zA-Z0-9_.-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/
return pattern.test(str)
},
/**
*
* @param cameraoption 对象{quality:质量默认50,allowEdit:true||false,width:宽度,height:高度}
* @param onSuccess 成功回调函数
* @param onFail 失败回调函数
*/
/* eslint-disable */
openCamera: function (cameraoption, onSuccess, onFail) {
if (typeof onSuccess === 'function' && typeof onFail === 'function') {
let options = {
quality: cameraoption.quality || 50,
destinationType: Camera.DestinationType.FILE_URI,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: cameraoption.allowEdit || false,
targetWidth: cameraoption.width || 1024,
targetHeight: cameraoption.height || 768,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: window.localStorage.savePhoto || false,
correctOrientation: true,
}
navigator.camera.getPicture(onSuccess, onFail, options)
} else {
window.hlsPopup.showLongCenter('参数有误!')
}
},
/**
* 最多选取10张,返回图片的存储地址数组形式
* @param obj {quality:质量默认50,width:宽度,height:高度}
* @param successFunction 成功回调函数
* @param errorFunction 失败函数
*/
takePicture: function (obj, successFunction, errorFunction) {
if (typeof successFunction === 'function' && typeof errorFunction === 'function') {
window.imagePicker.getPictures(
successFunction, errorFunction, {
maximumImagesCount: obj.maxCount || 10,
quality: obj.quality || 50,
width: obj.width || 1024,
height: obj.height || 768,
}
)
} else {
window.hlsPopup.showLongBottom('参数有误!')
}
},
/**
* 拨打电话仅仅限制于手机
* @param number
*/
callPhone: function (number) {
window.open('tel:' + number)
},
/**
* 发邮件
* @param email
*/
callEmail: function (email) {
window.open('mailto:' + email)
},
/**
* 非ftp的上传方式
* @param filePath
* @param success
*/
fileUploadHls: function (file, success) {
let path = file.filePath
let name = path.substr(path.lastIndexOf('/') + 1)
let url = encodeURI(process.env.rootPath + '/app/fileUploadHls?sysName=HLS_APP&apiName=attment_file_upload')
let options = new FileUploadOptions() // eslint-disable-line
options.fileKey = 'file'
options.headers = {
'Authorization': 'Bearer ' + window.localStorage.access_token,
}
options.params = {
'table_name': file.table_name,
'table_pk_value': file.table_pk_value,
'user_id': window.localStorage.user_id,
'access_token': window.localStorage.access_token,
'filePath': path,
}
options.fileName = name
options.mimeType = 'multipart/form-date'
let ft = new FileTransfer() // eslint-disable-line
ft.onprogress = function (progressEvent) {
if (progressEvent.lengthComputable) {
loadingStatus.setPercentage(progressEvent.loaded / progressEvent.total) // eslint-disable-line
} else {
loadingStatus.increment() // eslint-disable-line
}
}
function uploadSuccess (result) {
success(JSON.parse(result.response))
}
function fileError(){
window.hlsPopup.hideLoading()
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
ft.upload(path, url, uploadSuccess, fileError, options)
},
/**
* 调用系统svc进行上传
* @param filePath
* @param success
*/
fileUploadSvc: function (file, success) {
let path = file.filePath
let name = path.substr(path.lastIndexOf('/') + 1)
let url = encodeURI(process.env.rootPath + '/app/fileUploadSvc?sysName=HLS_APP&apiName=attachment_upload')
let options = new FileUploadOptions() // eslint-disable-line
options.fileKey = 'file'
options.headers = {
'Authorization': 'Bearer ' + window.localStorage.access_token,
}
options.params = {
'source_type': file.table_name,
'pkvalue': file.table_pk_value,
'user_id': window.localStorage.user_id,
'access_token': window.localStorage.access_token,
'filePath': path,
'timestamp': file.timestamp,
'sequence': file.sequence,
}
options.fileName = name
options.mimeType = 'multipart/form-date'
let ft = new FileTransfer() // eslint-disable-line
function uploadSuccess (result) {
success(JSON.parse(result.response))
}
function fileError(){
window.hlsPopup.hideLoading()
console.log("upload error source " + error.source);
console.log("upload error target " + error.target);
}
ft.upload(path, url, uploadSuccess, fileError, options)
},
/**
* 汉王识别
* @param file
* @param url
* @param success
*/
hangwan: function (fileUrl, postUrl, success) {
if (!fileUrl) {
return
}
let path = fileUrl
let name = fileUrl.substr(fileUrl.lastIndexOf('/') + 1)
let url = encodeURI(postUrl)
let options = new FileUploadOptions() // eslint-disable-line
options.headers = {
'Authorization': 'Bearer ' + window.localStorage.access_token,
}
options.fileKey = 'file'
options.fileName = name
options.mimeType = 'multipart/form-date'
let ft = new FileTransfer() // eslint-disable-line
function uploadSuccess (message) {
let res = JSON.parse(message.response)
success(res)
}
function error (e) {
this.hlsPopup.showLongCenter('汉王识别失败')
}
ft.upload(path, url, uploadSuccess, error, options)
},
/**
*
* @param x 输入的数字
* @returns {Number} 返回数字
*/
toDecimal: function (x) {
// hlsPopup.showLongCenter(baseConfig.debug);
let f = parseFloat(x)
if (isNaN(f)) {
return 0
}
f = Math.round(x * 100) / 100
return f
},
formatFloat: function (f, digit) {
let m = Math.pow(100000, digit)
return parseInt(f * m, 100000) / m
},
/**
*
* @param ir interest rate per month
* @param np number of periods (months)
* @param pv present value
* @param fv future value (residual value)
* @returns {number} 计算结果;
* @constructor
*/
PMT: function (ir, np, pv, fv, type) {
/*
ir - interest rate per month
np - number of periods (months)
pv - present value
fv - future value (residual value)
type - 0 or 1 need to implement that
*/
if (!type) {
type = 0
}
if (ir === 0) {
return -pv / np
}
let r1 = 1 + ir
// let pmt = -( ir * ( pv * Math.pow((ir + 1), np) + fv ) ) / ( ( ir + 1 ) * ( Math.pow((ir + 1), np) - 1 ) );
let pmt = -(pv * Math.pow(r1, np) + fv) * ir / ((1 + ir * type) * (Math.pow(r1, np) - 1))
return this.toDecimal(pmt)
},
/**
*
* @param rate
* @param per
* @param nper
* @param pv
* @param fv
* @param type
* @returns {*}
* @constructor
*/
IPMT: function (rate, per, nper, pv, fv, type) {
let ipmt = 0
let r = rate
let R1 = 1 + r
let t = per
let n = nper
let ct
if (rate === 0) {
return 0
}
if (fv) {
fv = -fv
} else {
fv = 0
}
if (type) {
ct = type
} else {
ct = 0
}
if (type === 1 && per === 1) {
return ipmt
} else {
ipmt = -(pv * Math.pow(R1, n) + fv) * r /
((1 + r * ct) * (Math.pow(R1, n) - 1)) -
(pv / (1 + r * ct) - (pv * Math.pow(R1, n) + fv) /
((1 + r * ct) * (Math.pow(R1, n) - 1))) *
(Math.pow(R1, t) - Math.pow(R1, (t - 1)))
return this.toDecimal(ipmt)
}
},
/**
*
* @param p_rate
* @param p_nper
* @param p_pmt
* @param p_fv
* @param p_type
* @returns {number|*}
* @constructor
*/
PV: function (pRate, pNper, pPmt, pFv, pType) {
let pv
let r
let R1
let n
let pmt
let fv
let ct
r = pRate
R1 = 1 + r
n = pNper
if (pPmt) {
pmt = pPmt
} else {
pmt = 0
}
if (pFv) {
fv = pFv
} else {
fv = 0
}
if (pType) {
ct = pType
} else {
ct = 0
}
pv = -(fv + pmt * (1 + r * ct) * (Math.pow(R1, n) - 1) / r) /
Math.pow(R1, n)
return this.toDecimal(pv)
},
/**
*
* @param p_rate
* @param p_nper
* @param p_pmt
* @param p_pv
* @param p_type
* @returns {number|*}
* @constructor
*/
FV: function (pRate, pNper, pPmt, pPv, pType) {
let fv
let r
let R1
let n
let pmt
let pv
let ct
r = pRate
R1 = 1 + r
n = pNper
if (pPmt) {
pmt = pPmt
} else {
pmt = 0
}
if (pPv) {
pv = pPv
} else {
pv = 0
}
if (pType) {
ct = pType
} else {
ct = 0
}
fv = -pv * Math.pow(R1, n) - pmt * (1 + r * ct) * (Math.pow(R1, n) - 1) / r
return this.toDecimal(fv)
},
/**
*
* @param args
* @param rate
* @returns {*}
* @constructor
*/
NPV: function (args, rate) {
let rrate = (1 + rate / 100)
let npv = args[0]
for (let i = 1; i < args.length; i++) {
npv += (args[i] / Math.pow(rrate, i))
}
return npv
},
/**
*
* @param fn
* @returns {number}
*/
seekZero: function (fn) {
let x = 1
while (fn(x) > 0) {
x += 1
}
while (fn(x) < 0) {
x -= 0.01
}
return x + 0.01
},
/**
*
* @param array
* @returns {number}
* @constructor
*/
IRR: function (array) {
let args = array
let numberOfTries = 1
// Cash flow values must contain at least one positive value and one negative value
let positive, negative
Array.prototype.slice.call(args).forEach(function (value) {
if (value > 0) positive = true
if (value < 0) negative = true
})
if (!positive || !negative) throw new Error('IRR requires at least one positive value and one negative value')
function npv (rate) {
numberOfTries++
if (numberOfTries > 1000) {
throw new Error('IRR can\'t find a result')
}
let rrate = (1 + rate / 100)
let npv = args[0]
for (let i = 1; i < args.length; i++) {
npv += (args[i] / Math.pow(rrate, i))
}
return npv
}
return this.seekZero(npv)
},
// Returns Sum of f(x)/f'(x)
sumEq: function (cfs, durs, guess) {
let sumFx = 0
let sumFdx = 0
for (let i = 0; i < cfs.length; i++) {
sumFx = sumFx + (cfs[i] / Math.pow(1 + guess, durs[i]))
}
for (let i = 0; i < cfs.length; i++) {
sumFdx = sumFdx + (-cfs[i] * durs[i] * Math.pow(1 + guess, -1 - durs[i]))
}
return sumFx / sumFdx
},
durYear: function (first, last) {
return (Math.abs(last.getTime() - first.getTime()) / (1000 * 3600 * 24 * 365))
},
/**
*
* @param cfs
* @param dts
* @param guess
* @returns {number}
* @constructor
*/
XIRR: function (cfs, dts, guess) {
if (cfs.length !== dts.length) throw new Error('Number of cash flows and dates should match')
let positive, negative
Array.prototype.slice.call(cfs).forEach(function (value) {
if (value > 0) positive = true
if (value < 0) negative = true
})
if (!positive || !negative) throw new Error('XIRR requires at least one positive value and one negative value')
guess = guess || 0
let limit = 100 // loop limit
let guessLast
let durs = []
durs.push(0)
// Create Array of durations from First date
for (let i = 1; i < dts.length; i++) {
durs.push(this.durYear(dts[0], dts[i]))
}
do {
guessLast = guess
guess = guessLast - this.sumEq(cfs, durs, guessLast)
limit--
} while (guessLast.toFixed(5) !== guess.toFixed(5) && limit > 0)
let xirr = guessLast.toFixed(5) !== guess.toFixed(5) ? null : guess * 100
return Math.round(xirr * 100) / 100
},
// 指纹
fingerLogin: function () {
if (vum.Platform.isIOS()) {
return this.fingerLoginIos()
} else {
return this.fingerLoginAndroid()
}
},
// android
fingerLoginAndroid: function () {
let isSupportFinger = 'true'
return new Promise(function (resolve, reject) {
Fingerprint.isAvailable(function (res) { // eslint-disable-line
if (window.localStorage.isSupportFinger) {
window.localStorage.removeItem('isSupportFinger')
}
window.localStorage.setItem('isSupportFinger', isSupportFinger)
if (window.localStorage.isOpenFingerLogin && window.localStorage.username && window.localStorage.password) {
var successCallback = function (msg) {
resolve(msg)
}
var errorCallback = function (err) {
reject(err)
}
Fingerprint.show({ // eslint-disable-line
clientId: 'com.car.rental.easy',
clientSecret: 'a_very_secret_encryption_key', // Only necessary for Android
}, successCallback, errorCallback)
} else {
reject() // eslint-disable-line
}
}, function (error) {
isSupportFinger = false
window.localStorage.isSupportFinger = isSupportFinger
reject(error)
})
})
},
// ios
fingerLoginIos: function () {
return new Promise(function (resolve, reject) {
let isSupportFinger = true
window.plugins.touchid.isAvailable(
// 支持指纹
function () {
isSupportFinger = true
if (window.localStorage.isSupportFinger) {
window.localStorage.removeItem('isSupportFinger')
}
window.localStorage.setItem('isSupportFinger', isSupportFinger)
// window.localStorage.isSupportFinger = true;
// 判断是否开启了指纹登录
if (window.localStorage.isOpenFingerLogin && window.localStorage.username && window.localStorage.password) {
window.plugins.touchid.verifyFingerprint(
'通过Home键验证已有的手机指纹!', // this will be shown in the native scanner popup
function (msg) {
resolve(msg)
},
function (msg) {
reject(msg)
})
} else {
reject() // eslint-disable-line
}
}
// 不支持指纹
, function (msg) {
isSupportFinger = false
window.localStorage.isSupportFinger = isSupportFinger
reject(msg)
}
)
})
},
// 判断是否为首次登录
isFirstTimeLogin: function (name) {
if (window.localStorage.username) {
if (window.localStorage.username !== name) {
return true
} else {
return false
}
} else {
return true
}
},
// 打开指纹登陆
openFingerLogin: function () {
return new Promise(function (resolve, reject) {
if (vum.Platform.isIOS()) {
window.plugins.touchid.isAvailable(function () {
window.plugins.touchid.verifyFingerprint(
'通过Home键验证已有的手机指纹!',
function () {
resolve()
}, function () {
reject() // eslint-disable-line
}
)
}, function () {
this.hlsPopup.showLongCenter('您的设配暂不支持指纹')
reject() // eslint-disable-line
})
} else {
Fingerprint.isAvailable(function (res) { // eslint-disable-line
Fingerprint.show({ // eslint-disable-line
clientId: 'com.car.rental.easy',
clientSecret: 'a_very_secret_encryption_key', // Only necessary for Android
}, successCallback, errorCallback)
function successCallback (msg) {
resolve(msg)
}
function errorCallback (err) {
reject(err)
}
}, function (error) {
this.hlsPopup.showLongCenter('您的设配暂不支持指纹')
reject(error)
})
}
})
},
/**
* 判断平台
* @return {String} 平台
*/
detectOS: function () {
const ua = navigator.userAgent.toLowerCase()
if (/MicroMessenger/i.test(ua)) {
return 'weixin'
} else if (/iPhone|iPad|iPod|iOS/i.test(ua)) {
return 'ios'
} else if (/Android/i.test(ua)) {
return 'android'
} else {
return 'other'
}
},
}
/**
* Created by LJh on 2017/4/13.
*/
export default {
/**
* @param {object} params = {
* 'isOpenMessageRoaming': boolean // 是否开启消息漫游,不传默认关闭。
* }
*
* 打开消息漫游之后,用户多个设备之间登录时,SDK 会自动将当前登录用户的历史消息同步到本地。
*/
_init: function (params) {
if (process.env.isMobilePlatform) {
JMessagePlugin.init(params)
JMessagePlugin.setBadge({
badge: 0,
})
}
},
/**
* @param {object} params = {
* username:'username',
password:'password',
nickname: String,
...
* }
* @param {function} success = function () {}
* @param {function} error = function ({'code': '错误码', 'description': '错误信息'}) {}
*/
_register: function (params, success, error) {
JMessagePlugin.register(params, success, error)
},
/**
* @param {object} params = {
* username: 'username',
* password: 'password',
* }
* @param {function} success = function () {}
* @param {function} error = function ({'code': '错误码', 'description': '错误信息'}) {}
*/
_login: function (params, success, error) {
JMessagePlugin.login(params, success, error)
},
/**
* @param {object} params = {
* 'type': String, // 'single' / 'group' / 'chatRoom'
* 'username': String, // 当 type 为 'single' 时,username 不能为空
* 'appKey': String, // 当 type 为 'single' 时,用于指定对象所属应用的 appKey。如果为空,默认为当前应用
* 'text': String, // 消息内容
* }
* @param {function} success = function (msg) {} // 以参数形式返回消息对象。
* @param {function} error = function ({'code': '错误码', 'description': '错误信息'}) {}
*/
_sendTextMessage: function (params, success, error) {
JMessagePlugin.sendTextMessage(params, success, error)
},
/**
* 添加收到消息事件监听。
*
@param {function} listener = function (message) {} // 以参数形式返回消息对象。
* message = {
* 'id': String,
* 'from': object, // 消息发送者信息对象。
* 'target': object, // 消息接收方信息(可能为用户或者群组)。
* 'type': string // 'text' / 'image' / 'voice' / 'location' / 'file' / 'custom' / 'event'
* }
**/
_addReceiveMessageListener: function (listener) {
JMessagePlugin.addReceiveMessageListener(listener)
},
/**
*
* @param username
* @param password
* @private
*/
/* eslint handle-callback-err: "warn" */
_jmessage_config: function (username, password) {
if (process.env.isMobilePlatform) {
var login = function () {
JMessagePlugin.login({'username': username, 'password': password}, function () {
// alert("login success");
}, function (error) {
// alert("Login failed: " + error.description);
register()
})
}
/* eslint handle-callback-err: "warn" */
var register = function () {
JMessagePlugin.register({'username': username, 'password': password}, function () {
login()
}, function (error) {
// alert('Register failed: ' + error.description);
})
}
login()
}
},
}
/**
* Created by LJh on 2017/4/13.
*/
export default {
// 获取设备号
onGetRegistrationID: function (data) {
try {
// alert("JPushPlugin:registrationID is " + JSON.stringify(data));
if (data.length !== 0) {
window.localStorage.setItem('registrationID', data)
}
if (data.length === 0) {
window.setTimeout(this.getRegistrationID, 1000)
}
} catch (exception) {
// alert(angular.toJson(exception));
}
},
// 获取设备号
getRegistrationID: function () {
window.plugins.jPushPlugin.getRegistrationID(this.onGetRegistrationID)
},
onReceiveNotification: function (event) {
try {
let alertContent // eslint-disable-line
if (device.platform === 'Android') { // eslint-disable-line
alertContent = event.alert
} else {
alertContent = event.aps.alert
}
} catch (exception) {
console.log(exception)
}
},
onReceiveMessage: function (event) {
try {
let message // eslint-disable-line
if (device.platform === 'Android') { // eslint-disable-line
message = event.message
} else {
message = event.content
}
} catch (exception) {
// console.log("JPushPlugin:onReceiveMessage-->" + exception);
}
},
onOpenNotification: function (event) {
window.plugins.jPushPlugin.resetBadge()// 设置Badge
window.plugins.jPushPlugin.setApplicationIconBadgeNumber(0)
try {
let alertContent // eslint-disable-line
if (device.platform === 'Android') { // eslint-disable-line
alertContent = event.alert
} else {
alertContent = event.aps.alert
}
// alert("open Notification:" + JSON.stringify(event,'',2));
} catch (exception) {
// console.log("JPushPlugin:onOpenNotification" + exception);
}
},
// 启动极光推送
_init: function () {
if (process.env.isMobilePlatform) {
window.plugins.jPushPlugin.init()
window.plugins.jPushPlugin.setDebugMode(false)
window.plugins.jPushPlugin.getRegistrationID(this.onGetRegistrationID)
document.addEventListener('jpush.openNotification', this.onOpenNotification)
window.plugins.jPushPlugin.resetBadge()// 设置Badge
window.plugins.jPushPlugin.setApplicationIconBadgeNumber(0)
// document.addEventListener('jpush.receiveMessage', this.onReceiveMessage);
// document.addEventListener('jpush.receiveNotification', this.onReceiveNotification);
}
},
/*
* 获取状态
* */
_isPushStopped: function (fun) {
window.plugins.jPushPlugin.isPushStopped(fun)
},
/*
* 停止极光推送
* */
_stopPush: function () {
window.plugins.jPushPlugin.stopPush()
},
/*
* 重启极光推送
* */
_resumePush: function () {
window.plugins.jPushPlugin.resumePush()
},
/**
* 设置标签。
* 注意:该接口是覆盖逻辑,而不是增量逻辑。即新的调用会覆盖之前的设置。
*
* @param params = { 'sequence': number, 'tags': ['tag1', 'tag2'] }
*/
_setTags: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.setTags(params, successCallback, errorCallback)
},
/**
* 新增标签。
*
* @param params = { 'sequence': number, 'tags': ['tag1', 'tag2'] }
*/
_addTags: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.addTags(params, successCallback, errorCallback)
},
/**
* 删除指定标签。
*
* @param params = { 'sequence': number, 'tags': ['tag1', 'tag2'] }
*/
_deleteTags: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.deleteTags(params, successCallback, errorCallback)
},
/**
* 清除标签
* @param params
* @param successCallback
* @param errorCallback
* @private
*/
_cleanTags: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.cleanTags(params, successCallback, errorCallback)
},
/**
* 查询所有标签。
*
* @param params = { 'sequence': number }
*/
_getAllTags: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.getAllTags(params, successCallback, errorCallback)
},
/*
* 设置别名
* */
_setAlias: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.setAlias(params, successCallback, errorCallback)
},
/**
* 删除别名。
*
* @param params = { 'sequence': number }
*/
_deleteAlias: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.deleteAlias(params, successCallback, errorCallback)
},
/**
* 查询当前绑定的别名。
*
* @param params = { 'sequence': number }
*/
_getAlias: function (params, successCallback, errorCallback) {
window.plugins.jPushPlugin.getAlias(params, successCallback, errorCallback)
},
/**
* 设置角标
* @param value
* @private
*/
_setBadge: function (value) {
window.plugins.jPushPlugin.setBadge(value)
},
/*
* 清除角标
* */
_resetBadge: function () {
window.plugins.jPushPlugin.resetBadge()
window.plugins.jPushPlugin.setApplicationIconBadgeNumber(0)
},
_setLogOFF: function () {
window.plugins.jPushPlugin.setLogOFF()
},
// 极光推送
_jpush_config: function (tagOption) {
if (process.env.isMobilePlatform) {
let userId = window.localStorage.user_id
let tags = []
for (let key in tagOption) {
tags.push(tagOption[key])
}
/* if (userName) {
tags.push(userName.toUpperCase())
} */
window.plugins.jPushPlugin.setTags({sequence: Number(userId), tags: tags},
function (result) {
// alert(result.tags)
}, function (error) {
// alert(error.code)
})
}
},
}
/**
* hmap子应用登录逻辑
* @author momoko 2018/05/08
*/
import axios from 'axios'
import { getUrlParam } from './utils'
// 模拟登录
export async function analogLogin () {
const url = `${$config.baseURL}/oauth/token?client_id=a765ff3f-8d33-49b4-a9c9-48e991544242&client_secret=ec2a9a5d-8b21-40fb-b20b-fa846b944e7b&grant_type=password&authType=TEL&username=17700002674&password=123456`
const res = await axios.post(url)
return {
token: res.data.access_token,
tokenType: res.data.token_type,
expires: res.data.expires_in,
userId: res.data.userId,
organizationId: res.data.organizationId,
}
}
// 授权码登录
export async function authorizedLogin () {
const code = getUrlParam('code')
const url = `${$config.baseURL}/oauth/token?client_id=a765ff3f-8d33-49b4-a9c9-48e991544242&client_secret=ec2a9a5d-8b21-40fb-b20b-fa846b944e7b&grant_type=authorization_code&code=${encodeURIComponent(code)}`
const res = await axios.post(url)
return {
token: res.data.access_token,
tokenType: res.data.token_type,
expires: res.data.expires_in,
userId: res.data.userId,
organizationId: res.data.organizationId,
}
}
// 桥登录
export function bridgeLogin () {
return new Promise((resolve, reject) => {
// 登录成功回调
window.bridgeLoginSuccess = function (str) {
const res = JSON.parse(str)
const data = {
token: res.token,
tokenType: res.tokenType,
expires: res.expiresIn,
userId: res.userId,
organizationId: res.organizationId,
}
resolve(data)
}
// 登录失败回调
window.bridgeLoginFailure = function (res) {
console.error(res)
reject(res)
}
const dict = {
'className': 'BaseBridge',
'function': 'getBaseInfo',
'successCallBack': 'bridgeLoginSuccess',
'failureCallBack': 'bridgeLoginFailure',
}
HandBridge.postMessage(JSON.stringify(dict))
})
}
// 获取用户详细信息
export async function getUserInfo (userId) {
const url = `${$config.baseURL}/i/api/staff/customDetail`
const data = {
userId,
}
const options = {
headers: {
Authorization: `Bearer ${window.localStorage.token}`,
},
}
const res = await axios.post(url, data, options)
return res.data
}
/**
* 登录总成
* @param {String} [type] 可选:'online''local'
* @param {Boolean} [needInfo] 是否需要获取用户详细信息
* @return {Object.Promise} 若登录成功PromiseValue为数据对象/登录失败PromiseValue 为 false
*/
export default async function login (type = 'online', needInfo = true) { // 登录
const env = process.env.CONFIG_ENV // 环境
try {
let result = {}
if (env === 'prod' || env === 'uat') { // 真机
if (type === 'online') result = await authorizedLogin() // 在线子应用
if (type === 'local') result = await bridgeLogin() // 本地子应用
} else {
result = await analogLogin()
}
window.localStorage.token = result.token
if (needInfo) result.userInfo = await getUserInfo(result.userId)
return result
} catch (e) {
console.error(e)
return false
}
}
/**
*
* @param fmt
* @returns {*}
* @constructor
*/
Date.prototype.format = function (fmt) { // eslint-disable-line
var o = {
'M+': this.getMonth() + 1, // 月份
'd+': this.getDate(), // 日
'h+': this.getHours(), // 小时
'm+': this.getMinutes(), // 分
's+': this.getSeconds(), // 秒
'q+': Math.floor((this.getMonth() + 3) / 3), // 季度
'S': this.getMilliseconds(), // 毫秒
}
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length))
for (var k in o) { if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) }
return fmt
}
/**
* 移除数组的某个元素
* @param dx 下标
* @returns {boolean}
*/
Array.prototype.remove = function (dx) { // eslint-disable-line
if (isNaN(dx) || dx > this.length) {
return false
}
for (var i = 0, n = 0; i < this.length; i++) {
if (this[i] !== this[dx]) {
this[n++] = this[i]
}
}
this.length -= 1
}
/**
* 一些帮助函数
* @author momoko
*/
/**
* 取URL上的参数
* @param {String} param 参数名
* @return {String}
*/
export function getUrlParam (param) {
const result = window.location.href.match(new RegExp('(\\?|&)' + param + '(\\[\\])?=([^&#]*)'))
return result ? result[3] : undefined
}
/**
* 动态插入 script to html
* @param url
* @param callback
*/
export function createScript (url, callback) {
const oScript = document.createElement('script')
oScript.type = 'text/javascript'
oScript.async = true
oScript.src = url
/**
* IE6/7/8 -- onreadystatechange
* IE9/10 -- onreadystatechange, onload
* Firefox/Chrome/Opera -- onload
*/
const isIE = !-[1,] // eslint-disable-line
if (isIE) {
// 判断IE8及以下浏览器
oScript.onreadystatechange = function () {
if (this.readyState === 'loaded' || this.readyState === 'complete') {
callback && callback()
}
}
} else {
// IE9及以上浏览器,Firefox,Chrome,Opera
oScript.onload = function () {
callback && callback()
}
}
document.body.appendChild(oScript)
}
/**
* 判断平台
* @return {String} 平台
*/
export function detectOS () {
const ua = navigator.userAgent.toLowerCase()
if (/MicroMessenger/i.test(ua)) {
return 'weixin'
} else if (/iPhone|iPad|iPod|iOS/i.test(ua)) {
return 'ios'
} else if (/Android/i.test(ua)) {
return 'android'
} else {
return 'other'
}
}
/*!
* vum.bundle.js is a concatenation of:
* vum.js, angular.js, angular-animate.js,
* angular-sanitize.js, angular-ui-router.js,
* and vum-angular.js
*/
/*!
* Copyright 2015 Drifty Co.
* http://drifty.com/
*
* vum, v1.3.0
* A powerful HTML5 mobile app framework.
* http://vumframework.com/
*
* By @maxlynch, @benjsperry, @adamdbradley <3
*
* Licensed under the MIT license. Please see LICENSE for more information.
*
*/
/* eslint-disable */
(function () {
// Create global vum obj and its namespaces
// build processes may have already created an vum obj
window.vum = window.vum || {}
window.vum.version = '1.3.0';
(function (window, document, vum) {
var readyCallbacks = []
var isDomReady = document.readyState === 'complete' || document.readyState === 'interactive'
function domReady () {
isDomReady = true
for (var x = 0; x < readyCallbacks.length; x++) {
vum.requestAnimationFrame(readyCallbacks[x])
}
readyCallbacks = []
document.removeEventListener('DOMContentLoaded', domReady)
}
if (!isDomReady) {
document.addEventListener('DOMContentLoaded', domReady)
}
})(window, document, vum);
(function (window, document, vum) {
function getParameterByName (name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]')
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
results = regex.exec(location.search)
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '))
}
var IOS = 'ios'
var ANDROID = 'android'
var WINDOWS_PHONE = 'windowsphone'
var EDGE = 'edge'
var CROSSWALK = 'crosswalk'
var requestAnimationFrame = requestAnimationFrame // eslint-disable-line
// From the man himself, Mr. Paul Irish.
// The requestAnimationFrame polyfill
// Put it on window just to preserve its context
// without having to use .call
window._rAF = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 16)
}
})()
function requestAnimationFrame (cb) {
return window._rAF(cb)
}
/**
* @ngdoc utility
* @name vum.Platform
* @module vum
* @description
* A set of utility methods that can be used to retrieve the device ready state and
* various other information such as what kind of platform the app is currently installed on.
*
* @usage
* ```js
* angular.module('PlatformApp', ['vum'])
* .controller('PlatformCtrl', function($scope) {
*
* vum.Platform.ready(function(){
* // will execute when device is ready, or immediately if the device is already ready.
* });
*
* var deviceInformation = vum.Platform.device();
*
* var isWebView = vum.Platform.isWebView();
* var isIPad = vum.Platform.isIPad();
* var isIOS = vum.Platform.isIOS();
* var isAndroid = vum.Platform.isAndroid();
* var isWindowsPhone = vum.Platform.isWindowsPhone();
*
* var currentPlatform = vum.Platform.platform();
* var currentPlatformVersion = vum.Platform.version();
*
* vum.Platform.exitApp(); // stops the app
* });
* ```
*/
var self = vum.Platform = {
// Put navigator on platform so it can be mocked and set
// the browser does not allow window.navigator to be set
navigator: window.navigator,
/**
* @ngdoc property
* @name vum.Platform#isReady
* @returns {boolean} Whether the device is ready.
*/
isReady: false,
/**
* @ngdoc property
* @name vum.Platform#isFullScreen
* @returns {boolean} Whether the device is fullscreen.
*/
isFullScreen: false,
/**
* @ngdoc property
* @name vum.Platform#platforms
* @returns {Array(string)} An array of all platforms found.
*/
platforms: null,
/**
* @ngdoc property
* @name vum.Platform#grade
* @returns {string} What grade the current platform is.
*/
grade: null,
/**
* @ngdoc property
* @name vum.Platform#ua
* @returns {string} What User Agent is.
*/
ua: navigator.userAgent,
/**
* @ngdoc method
* @name vum.Platform#ready
* @description
* Trigger a callback once the device is ready, or immediately
* if the device is already ready. This method can be run from
* anywhere and does not need to be wrapped by any additonal methods.
* When the app is within a WebView (Cordova), it'll fire
* the callback once the device is ready. If the app is within
* a web browser, it'll fire the callback after `window.load`.
* Please remember that Cordova features (Camera, FileSystem, etc) still
* will not work in a web browser.
* @param {function} callback The function to call.
*/
ready: function (cb) {
// run through tasks to complete now that the device is ready
if (self.isReady) {
cb()
} else {
// the platform isn't ready yet, add it to this array
// which will be called once the platform is ready
readyCallbacks.push(cb)
}
},
/**
* @private
*/
detect: function () {
self._checkPlatforms()
requestAnimationFrame(function () {
// only add to the body class if we got platform info
for (var i = 0; i < self.platforms.length; i++) {
document.body.classList.add('platform-' + self.platforms[i])
}
})
},
/**
* @ngdoc method
* @name vum.Platform#setGrade
* @description Set the grade of the device: 'a', 'b', or 'c'. 'a' is the best
* (most css features enabled), 'c' is the worst. By default, sets the grade
* depending on the current device.
* @param {string} grade The new grade to set.
*/
setGrade: function (grade) {
var oldGrade = self.grade
self.grade = grade
requestAnimationFrame(function () {
if (oldGrade) {
document.body.classList.remove('grade-' + oldGrade)
}
document.body.classList.add('grade-' + grade)
})
},
/**
* @ngdoc method
* @name vum.Platform#device
* @description Return the current device (given by cordova).
* @returns {object} The device object.
*/
device: function () {
return window.device || {}
},
_checkPlatforms: function () {
self.platforms = []
var grade = 'a'
if (self.isWebView()) {
self.platforms.push('webview')
if (!(!window.cordova && !window.PhoneGap && !window.phonegap)) {
self.platforms.push('cordova')
} else if (typeof window.forge === 'object') {
self.platforms.push('trigger')
}
} else {
self.platforms.push('browser')
}
if (self.isIPad()) self.platforms.push('ipad')
var platform = self.platform()
if (platform) {
self.platforms.push(platform)
var version = self.version()
if (version) {
var v = version.toString()
if (v.indexOf('.') > 0) {
v = v.replace('.', '_')
} else {
v += '_0'
}
self.platforms.push(platform + v.split('_')[0])
self.platforms.push(platform + v)
if (self.isAndroid() && version < 4.4) {
grade = (version < 4 ? 'c' : 'b')
} else if (self.isWindowsPhone()) {
grade = 'b'
}
}
}
self.setGrade(grade)
},
/**
* @ngdoc method
* @name vum.Platform#isWebView
* @returns {boolean} Check if we are running within a WebView (such as Cordova).
*/
isWebView: function () {
return !(!window.cordova && !window.PhoneGap && !window.phonegap && window.forge !== 'object')
},
/**
* @ngdoc method
* @name vum.Platform#isIPad
* @returns {boolean} Whether we are running on iPad.
*/
isIPad: function () {
if (/iPad/i.test(self.navigator.platform)) {
return true
}
return /iPad/i.test(self.ua)
},
/**
* @ngdoc method
* @name vum.Platform#isIOS
* @returns {boolean} Whether we are running on iOS.
*/
isIOS: function () {
return self.is(IOS)
},
/**
* @ngdoc method
* @name vum.Platform#isAndroid
* @returns {boolean} Whether we are running on Android.
*/
isAndroid: function () {
return self.is(ANDROID)
},
/**
* @ngdoc method
* @name vum.Platform#isWindowsPhone
* @returns {boolean} Whether we are running on Windows Phone.
*/
isWindowsPhone: function () {
return self.is(WINDOWS_PHONE)
},
/**
* @ngdoc method
* @name vum.Platform#isEdge
* @returns {boolean} Whether we are running on MS Edge/Windows 10 (inc. Phone)
*/
isEdge: function () {
return self.is(EDGE)
},
isCrosswalk: function () {
return self.is(CROSSWALK)
},
/**
* @ngdoc method
* @name vum.Platform#platform
* @returns {string} The name of the current platform.
*/
platform: function () {
// singleton to get the platform name
if (platformName === null) self.setPlatform(self.device().platform)
return platformName
},
/**
* @private
*/
setPlatform: function (n) {
if (typeof n !== 'undefined' && n !== null && n.length) {
platformName = n.toLowerCase()
} else if (getParameterByName('vumplatform')) {
platformName = getParameterByName('vumplatform')
} else if (self.ua.indexOf('Edge') > -1) {
platformName = EDGE
} else if (self.ua.indexOf('Windows Phone') > -1) {
platformName = WINDOWS_PHONE
} else if (self.ua.indexOf('Android') > 0) {
platformName = ANDROID
} else if (/iPhone|iPad|iPod/.test(self.ua)) {
platformName = IOS
} else {
platformName = self.navigator.platform && navigator.platform.toLowerCase().split(' ')[0] || ''
}
},
/**
* @ngdoc method
* @name vum.Platform#version
* @returns {number} The version of the current device platform.
*/
version: function () {
// singleton to get the platform version
if (platformVersion === null) self.setVersion(self.device().version)
return platformVersion
},
/**
* @private
*/
setVersion: function (v) {
if (typeof v !== 'undefined' && v !== null) {
v = v.split('.')
v = parseFloat(v[0] + '.' + (v.length > 1 ? v[1] : 0))
if (!isNaN(v)) {
platformVersion = v
return
}
}
platformVersion = 0
// fallback to user-agent checking
var pName = self.platform()
var versionMatch = {
'android': /Android (\d+).(\d+)?/,
'ios': /OS (\d+)_(\d+)?/,
'windowsphone': /Windows Phone (\d+).(\d+)?/,
}
if (versionMatch[pName]) {
v = self.ua.match(versionMatch[pName])
if (v && v.length > 2) {
platformVersion = parseFloat(v[1] + '.' + v[2])
}
}
},
/**
* @ngdoc method
* @name vum.Platform#is
* @param {string} Platform name.
* @returns {boolean} Whether the platform name provided is detected.
*/
is: function (type) {
type = type.toLowerCase()
// check if it has an array of platforms
if (self.platforms) {
for (var x = 0; x < self.platforms.length; x++) {
if (self.platforms[x] === type) return true
}
}
// exact match
var pName = self.platform()
if (pName) {
return pName === type.toLowerCase()
}
// A quick hack for to check userAgent
return self.ua.toLowerCase().indexOf(type) >= 0
},
/**
* @ngdoc method
* @name vum.Platform#exitApp
* @description Exit the app.
*/
exitApp: function () {
self.ready(function () {
navigator.app && navigator.app.exitApp && navigator.app.exitApp()
})
},
/**
* @ngdoc method
* @name vum.Platform#showStatusBar
* @description Shows or hides the device status bar (in Cordova). Requires `cordova plugin add org.apache.cordova.statusbar`
* @param {boolean} shouldShow Whether or not to show the status bar.
*/
showStatusBar: function (val) {
// Only useful when run within cordova
self._showStatusBar = val
self.ready(function () {
// run this only when or if the platform (cordova) is ready
requestAnimationFrame(function () {
if (self._showStatusBar) {
// they do not want it to be full screen
window.StatusBar && window.StatusBar.show()
document.body.classList.remove('status-bar-hide')
} else {
// it should be full screen
window.StatusBar && window.StatusBar.hide()
document.body.classList.add('status-bar-hide')
}
})
})
},
/**
* @ngdoc method
* @name vum.Platform#fullScreen
* @description
* Sets whether the app is fullscreen or not (in Cordova).
* @param {boolean=} showFullScreen Whether or not to set the app to fullscreen. Defaults to true. Requires `cordova plugin add org.apache.cordova.statusbar`
* @param {boolean=} showStatusBar Whether or not to show the device's status bar. Defaults to false.
*/
fullScreen: function (showFullScreen, showStatusBar) {
// showFullScreen: default is true if no param provided
self.isFullScreen = (showFullScreen !== false)
// add/remove the fullscreen classname to the body
vum.DomUtil.ready(function () {
// run this only when or if the DOM is ready
requestAnimationFrame(function () {
if (self.isFullScreen) {
document.body.classList.add('fullscreen')
} else {
document.body.classList.remove('fullscreen')
}
})
// showStatusBar: default is false if no param provided
self.showStatusBar((showStatusBar === true))
})
},
}
var platformName = null, // just the name, like iOS or Android
platformVersion = null, // a float of the major and minor, like 7.1
readyCallbacks = [],
windowLoadListenderAttached,
platformReadyTimer = 2000 // How long to wait for platform ready before emitting a warning
verifyPlatformReady()
// Warn the user if deviceready did not fire in a reasonable amount of time, and how to fix it.
function verifyPlatformReady () {
setTimeout(function () {
if (!self.isReady && self.isWebView()) {
void 0
}
}, platformReadyTimer)
}
// setup listeners to know when the device is ready to go
function onWindowLoad () {
if (self.isWebView()) {
// the window and scripts are fully loaded, and a cordova/phonegap
// object exists then let's listen for the deviceready
document.addEventListener('deviceready', onPlatformReady, false)
} else {
// the window and scripts are fully loaded, but the window object doesn't have the
// cordova/phonegap object, so its just a browser, not a webview wrapped w/ cordova
onPlatformReady()
}
if (windowLoadListenderAttached) {
window.removeEventListener('load', onWindowLoad, false)
}
}
if (document.readyState === 'complete') {
onWindowLoad()
} else {
windowLoadListenderAttached = true
window.addEventListener('load', onWindowLoad, false)
}
function onPlatformReady () {
// the device is all set to go, init our own stuff then fire off our event
self.isReady = true
self.detect()
for (var x = 0; x < readyCallbacks.length; x++) {
// fire off all the callbacks that were added before the platform was ready
readyCallbacks[x]()
}
readyCallbacks = []
vum.trigger('platformready', {target: document})
requestAnimationFrame(function () {
document.body.classList.add('platform-ready')
})
}
// document.addEventListener('')
})(window, document, vum);
/**
* ion-events.js
*
* Author: Max Lynch <max@drifty.com>
*
* Framework events handles various mobile browser events, and
* detects special events like tap/swipe/etc. and emits them
* as custom events that can be used in an app.
*
* Portions lovingly adapted from github.com/maker/ratchet and github.com/alexgibson/tap.js - thanks guys!
*/
(function (vum) {
// Custom event polyfill
vum.CustomEvent = (function () {
if (typeof window.CustomEvent === 'function') return CustomEvent
var customEvent = function (event, params) {
var evt
params = params || {
bubbles: false,
cancelable: false,
detail: undefined,
}
try {
evt = document.createEvent('CustomEvent')
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
} catch (error) {
// fallback for browsers that don't support createEvent('CustomEvent')
evt = document.createEvent('Event')
for (var param in params) {
evt[param] = params[param]
}
evt.initEvent(event, params.bubbles, params.cancelable)
}
return evt
}
customEvent.prototype = window.Event.prototype
return customEvent
})()
/**
* @ngdoc utility
* @name vum.EventController
* @module vum
*/
vum.EventController = {
VIRTUALIZED_EVENTS: ['tap', 'swipe', 'swiperight', 'swipeleft', 'drag', 'hold', 'release'],
/**
* @ngdoc method
* @name vum.EventController#trigger
* @alias vum.trigger
* @param {string} eventType The event to trigger.
* @param {object} data The data for the event. Hint: pass in
* `{target: targetElement}`
* @param {boolean=} bubbles Whether the event should bubble up the DOM.
* @param {boolean=} cancelable Whether the event should be cancelable.
*/
// Trigger a new event
trigger: function (eventType, data, bubbles, cancelable) {
var event = new vum.CustomEvent(eventType, {
detail: data,
bubbles: !!bubbles,
cancelable: !!cancelable,
})
// Make sure to trigger the event on the given target, or dispatch it from
// the window if we don't have an event target
data && data.target && data.target.dispatchEvent && data.target.dispatchEvent(event) || window.dispatchEvent(event)
},
/**
* @ngdoc method
* @name vum.EventController#on
* @alias vum.on
* @description Listen to an event on an element.
* @param {string} type The event to listen for.
* @param {function} callback The listener to be called.
* @param {DOMElement} element The element to listen for the event on.
*/
on: function (type, callback, element) {
var e = element || window
// Bind a gesture if it's a virtual event
for (var i = 0, j = this.VIRTUALIZED_EVENTS.length; i < j; i++) {
if (type == this.VIRTUALIZED_EVENTS[i]) {
var gesture = new vum.Gesture(element)
gesture.on(type, callback)
return gesture
}
}
// Otherwise bind a normal event
e.addEventListener(type, callback)
},
/**
* @ngdoc method
* @name vum.EventController#off
* @alias vum.off
* @description Remove an event listener.
* @param {string} type
* @param {function} callback
* @param {DOMElement} element
*/
off: function (type, callback, element) {
element.removeEventListener(type, callback)
},
/**
* @ngdoc method
* @name vum.EventController#onGesture
* @alias vum.onGesture
* @description Add an event listener for a gesture on an element.
*
* Available eventTypes (from [hammer.js](http://eightmedia.github.io/hammer.js/)):
*
* `hold`, `tap`, `doubletap`, `drag`, `dragstart`, `dragend`, `dragup`, `dragdown`, <br/>
* `dragleft`, `dragright`, `swipe`, `swipeup`, `swipedown`, `swipeleft`, `swiperight`, <br/>
* `transform`, `transformstart`, `transformend`, `rotate`, `pinch`, `pinchin`, `pinchout`, <br/>
* `touch`, `release`
*
* @param {string} eventType The gesture event to listen for.
* @param {function(e)} callback The function to call when the gesture
* happens.
* @param {DOMElement} element The angular element to listen for the event on.
* @param {object} options object.
* @returns {vum.Gesture} The gesture object (use this to remove the gesture later on).
*/
onGesture: function (type, callback, element, options) {
var gesture = new vum.Gesture(element, options)
gesture.on(type, callback)
return gesture
},
/**
* @ngdoc method
* @name vum.EventController#offGesture
* @alias vum.offGesture
* @description Remove an event listener for a gesture created on an element.
* @param {vum.Gesture} gesture The gesture that should be removed.
* @param {string} eventType The gesture event to remove the listener for.
* @param {function(e)} callback The listener to remove.
*/
offGesture: function (gesture, type, callback) {
gesture && gesture.off(type, callback)
},
handlePopState: function () {
},
}
// Map some convenient top-level functions for event handling
vum.on = function () {
vum.EventController.on.apply(vum.EventController, arguments)
}
vum.off = function () {
vum.EventController.off.apply(vum.EventController, arguments)
}
vum.trigger = vum.EventController.trigger// function() { vum.EventController.trigger.apply(vum.EventController.trigger, arguments); };
vum.onGesture = function () {
return vum.EventController.onGesture.apply(vum.EventController.onGesture, arguments)
}
vum.offGesture = function () {
return vum.EventController.offGesture.apply(vum.EventController.offGesture, arguments)
}
})(window.vum);
(function (vum) {
vum.$vumPlatform = {
/**
* @ngdoc method
* @name $vumPlatform#onHardwareBackButton
* @description
* Some platforms have a hardware back button, so this is one way to
* bind to it.
* @param {function} callback the callback to trigger when this event occurs
*/
onHardwareBackButton: function (cb) {
vum.Platform.ready(function () {
document.addEventListener('backbutton', cb, false)
})
},
/**
* @ngdoc method
* @name $vumPlatform#offHardwareBackButton
* @description
* Remove an event listener for the backbutton.
* @param {function} callback The listener function that was
* originally bound.
*/
offHardwareBackButton: function (fn) {
vum.Platform.ready(function () {
document.removeEventListener('backbutton', fn)
})
},
/**
* @ngdoc method
* @name $vumPlatform#registerBackButtonAction
* @description
* Register a hardware back button action. Only one action will execute
* when the back button is clicked, so this method decides which of
* the registered back button actions has the highest priority.
*
* For example, if an actionsheet is showing, the back button should
* close the actionsheet, but it should not also go back a page view
* or close a modal which may be open.
*
* The priorities for the existing back button hooks are as follows:
* Return to previous view = 100
* Close side menu = 150
* Dismiss modal = 200
* Close action sheet = 300
* Dismiss popup = 400
* Dismiss loading overlay = 500
*
* Your back button action will override each of the above actions
* whose priority is less than the priority you provide. For example,
* an action assigned a priority of 101 will override the 'return to
* previous view' action, but not any of the other actions.
*
* @param {function} callback Called when the back button is pressed,
* if this listener is the highest priority.
* @param {number} priority Only the highest priority will execute.
* @param {*=} actionId The id to assign this action. Default: a
* random unique id.
* @returns {function} A function that, when called, will deregister
* this backButtonAction.
*/
$backButtonActions: {},
registerBackButtonAction: function (fn, priority, actionId) {
if (!vum.$vumPlatform._hasBackButtonHandler) {
// add a back button listener if one hasn't been setup yet
vum.$vumPlatform.$backButtonActions = {}
vum.$vumPlatform.onHardwareBackButton(vum.$vumPlatform.hardwareBackButtonClick)
vum.$vumPlatform._hasBackButtonHandler = true
}
var action = {
id: (actionId || vum.Utils.nextUid()),
priority: (priority || 0),
fn: fn,
}
vum.$vumPlatform.$backButtonActions[action.id] = action
// return a function to de-register this back button action
return function () {
delete vum.$vumPlatform.$backButtonActions[action.id]
}
},
/**
* @private
*/
hardwareBackButtonClick: function (e) {
// loop through all the registered back button actions
// and only run the last one of the highest priority
var priorityAction, actionId
for (actionId in vum.$vumPlatform.$backButtonActions) {
if (!priorityAction || vum.$vumPlatform.$backButtonActions[actionId].priority >= priorityAction.priority) {
priorityAction = vum.$vumPlatform.$backButtonActions[actionId]
}
}
if (priorityAction) {
priorityAction.fn(e)
return priorityAction
}
},
is: function (type) {
return vum.Platform.is(type)
},
/**
* @ngdoc method
* @name $vumPlatform#on
* @description
* Add Cordova event listeners, such as `pause`, `resume`, `volumedownbutton`, `batterylow`,
* `offline`, etc. More information about available event types can be found in
* [Cordova's event documentation](https://cordova.apache.org/docs/en/edge/cordova_events_events.md.html#Events).
* @param {string} type Cordova [event type](https://cordova.apache.org/docs/en/edge/cordova_events_events.md.html#Events).
* @param {function} callback Called when the Cordova event is fired.
* @returns {function} Returns a deregistration function to remove the event listener.
*/
on: function (type, cb) {
vum.Platform.ready(function () {
document.addEventListener(type, cb, false)
})
return function () {
vum.Platform.ready(function () {
document.removeEventListener(type, cb)
})
}
},
/**
* @ngdoc method
* @name $vumPlatform#ready
* @description
* Trigger a callback once the device is ready,
* or immediately if the device is already ready.
* @param {function=} callback The function to call.
*/
ready: function (cb) {
vum.Platform.ready(function () {
cb()
})
},
getWinSize: function () {
let winWidth
let winHeight
// 获取窗口宽度
if (window.innerWidth) { winWidth = window.innerWidth } else if ((document.body) && (document.body.clientWidth))
// 获取窗口高度
{ winWidth = document.body.clientWidth }
if (window.innerHeight) { winHeight = window.innerHeight } else if ((document.body) && (document.body.clientHeight)) { winHeight = document.body.clientHeight }
// 通过深入Document内部对body进行检测,获取窗口大小
if (document.documentElement && document.documentElement.clientHeight && document.documentElement.clientWidth) {
winHeight = document.documentElement.clientHeight
winWidth = document.documentElement.clientWidth
}
return {'width': winWidth, 'height': winHeight}
},
}
return vum.$vumPlatform
})(window.vum);
(function () {
var nextId = 0
vum.Utils = {
nextUid: function () {
return 'vue' + (nextId++)
},
}
var jqLite // delay binding since jQuery could be loaded after us.
var hasOwnProperty = Object.prototype.hasOwnProperty
/**
* @ngdoc function
* @name angular.isUndefined
* @module ng
* @kind function
*
* @description
* Determines if a reference is undefined.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is undefined.
*/
vum.isUndefined = function (value) {
return typeof value === 'undefined'
}
/**
* @ngdoc function
* @name angular.isDefined
* @module ng
* @kind function
*
* @description
* Determines if a reference is defined.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is defined.
*/
vum.isDefined = function (value) {
return typeof value !== 'undefined'
}
/**
* @ngdoc function
* @name angular.isObject
* @module ng
* @kind function
*
* @description
* Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
* considered to be objects. Note that JavaScript arrays are objects.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Object` but not `null`.
*/
vum.isObject = function (value) {
// http://jsperf.com/isobject4
return value !== null && typeof value === 'object'
}
/**
* Determine if a value is an object with a null prototype
*
* @returns {boolean} True if `value` is an `Object` with a null prototype
*/
vum.isBlankObject = function (value) {
return value !== null && typeof value === 'object' && !getPrototypeOf(value)
}
/**
* @ngdoc function
* @name angular.isString
* @module ng
* @kind function
*
* @description
* Determines if a reference is a `String`.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `String`.
*/
vum.isString = function (value) {
return typeof value === 'string'
}
/**
* @ngdoc function
* @name angular.isNumber
* @module ng
* @kind function
*
* @description
* Determines if a reference is a `Number`.
*
* This includes the "special" numbers `NaN`, `+Infinity` and `-Infinity`.
*
* If you wish to exclude these then you can use the native
* [`isFinite'](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isFinite)
* method.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Number`.
*/
vum.isNumber = function (value) {
return typeof value === 'number'
}
/**
* @ngdoc function
* @name angular.isDate
* @module ng
* @kind function
*
* @description
* Determines if a value is a date.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Date`.
*/
vum.isDate = function (value) {
return toString.call(value) === '[object Date]'
}
/**
* @ngdoc function
* @name angular.isArray
* @module ng
* @kind function
*
* @description
* Determines if a reference is an `Array`.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Array`.
*/
var isArray = Array.isArray
/**
* @ngdoc function
* @name angular.isFunction
* @module ng
* @kind function
*
* @description
* Determines if a reference is a `Function`.
*
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Function`.
*/
vum.isFunction = function (value) {
return typeof value === 'function'
}
/**
* Determines if a value is a regular expression object.
*
* @private
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `RegExp`.
*/
vum.isRegExp = function (value) {
return toString.call(value) === '[object RegExp]'
}
/**
* Checks if `obj` is a window object.
*
* @private
* @param {*} obj Object to check
* @returns {boolean} True if `obj` is a window obj.
*/
vum.isWindow = function (obj) {
return obj && obj.window === obj
}
vum.isScope = function (obj) {
return obj && obj.$evalAsync && obj.$watch
}
vum.isFile = function (obj) {
return toString.call(obj) === '[object File]'
}
vum.isFormData = function (obj) {
return toString.call(obj) === '[object FormData]'
}
vum.isBlob = function (obj) {
return toString.call(obj) === '[object Blob]'
}
vum.isBoolean = function (value) {
return typeof value === 'boolean'
}
vum.isPromiseLike = function (obj) {
return obj && isFunction(obj.then)
}
var TYPED_ARRAY_REGEXP = /^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array\]$/
vum.isTypedArray = function (value) {
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value))
}
vum.isArrayBuffer = function (obj) {
return toString.call(obj) === '[object ArrayBuffer]'
}
vum.toJsonReplacer = function (key, value) {
var val = value
if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
val = undefined
} else if (vum.isWindow(value)) {
val = '$WINDOW'
} else if (value && document === value) {
val = '$DOCUMENT'
} else if (vum.isScope(value)) {
val = '$SCOPE'
}
return val
}
/**
* @ngdoc function
* @name angular.toJson
* @module ng
* @kind function
*
* @description
* Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
* stripped since angular uses this notation internally.
*
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
* @param {boolean|number} [pretty=2] If set to true, the JSON output will contain newlines and whitespace.
* If set to an integer, the JSON output will contain that many spaces per indentation.
* @returns {string|undefined} JSON-ified string representing `obj`.
*/
vum.toJson = function (obj, pretty) {
if (vum.isUndefined(obj)) return undefined
if (!vum.isNumber(pretty)) {
pretty = pretty ? 2 : null
}
return JSON.stringify(obj, vum.toJsonReplacer, pretty)
}
function isArrayLike (obj) {
// `null`, `undefined` and `window` are not array-like
if (obj == null || isWindow(obj)) return false
// arrays, strings and jQuery/jqLite objects are array like
// * jqLite is either the jQuery or jqLite constructor function
// * we have to check the existence of jqLite first as this method is called
// via the forEach method when constructing the jqLite object in the first place
if (isArray(obj) || vum.isString(obj) || (jqLite && obj instanceof jqLite)) return true
// Support: iOS 8.2 (not reproducible in simulator)
// "length" in obj used to prevent JIT error (gh-11508)
var length = 'length' in Object(obj) && obj.length
// NodeList objects (with `item` method) and
// other objects with suitable length characteristics are array-like
return vum.isNumber(length) &&
(length >= 0 && ((length - 1) in obj || obj instanceof Array) || typeof obj.item === 'function')
}
/**
* @ngdoc function
* @name angular.forEach
* @module ng
* @kind function
*
* @description
* Invokes the `iterator` function once for each item in `obj` collection, which can be either an
* object or an array. The `iterator` function is invoked with `iterator(value, key, obj)`, where `value`
* is the value of an object property or an array element, `key` is the object property key or
* array element index and obj is the `obj` itself. Specifying a `context` for the function is optional.
*
* It is worth noting that `.forEach` does not iterate over inherited properties because it filters
* using the `hasOwnProperty` method.
*
* Unlike ES262's
* [Array.prototype.forEach](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.18),
* providing 'undefined' or 'null' values for `obj` will not throw a TypeError, but rather just
* return the value provided.
*
```js
var values = {name: 'misko', gender: 'male'};
var log = [];
angular.forEach(values, function(value, key) {
this.push(key + ': ' + value);
}, log);
expect(log).toEqual(['name: misko', 'gender: male']);
```
*
* @param {Object|Array} obj Object to iterate over.
* @param {Function} iterator Iterator function.
* @param {Object=} context Object to become context (`this`) for the iterator function.
* @returns {Object|Array} Reference to `obj`.
*/
vum.forEach = function (obj, iterator, context) {
var key, length
if (obj) {
if (vum.isFunction(obj)) {
for (key in obj) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
iterator.call(context, obj[key], key, obj)
}
}
} else if (isArray(obj) || isArrayLike(obj)) {
var isPrimitive = typeof obj !== 'object'
for (key = 0, length = obj.length; key < length; key++) {
if (isPrimitive || key in obj) {
iterator.call(context, obj[key], key, obj)
}
}
} else if (obj.forEach && obj.forEach !== forEach) {
obj.forEach(iterator, context, obj)
} else if (vum.isBlankObject(obj)) {
// createMap() fast path --- Safe to avoid hasOwnProperty check because prototype chain is empty
for (key in obj) {
iterator.call(context, obj[key], key, obj)
}
} else if (typeof obj.hasOwnProperty === 'function') {
// Slow path for objects inheriting Object.prototype, hasOwnProperty check needed
for (key in obj) {
if (obj.hasOwnProperty(key)) {
iterator.call(context, obj[key], key, obj)
}
}
} else {
// Slow path for objects which do not have a method `hasOwnProperty`
for (key in obj) {
if (hasOwnProperty.call(obj, key)) {
iterator.call(context, obj[key], key, obj)
}
}
}
}
return obj
}
vum.forEachSorted = function (obj, iterator, context) {
var keys = Object.keys(obj).sort()
for (var i = 0; i < keys.length; i++) {
iterator.call(context, obj[keys[i]], keys[i])
}
return keys
}
})(window.vum)
})()
/**
* 基础字体大小
*/
@font-size-big: 16px;
@font-size-middle: 14px;
@font-size-small: 12px;
@opacity-disabled: 0.4;
/**
* 颜色
*/
@theme-color:#5D98F6;
@font-color:#666666;
@mainColor: #000;
@baseColor: white;
@hintColor:rgb(181,181,181);
@headerColor: #5D98F6;
@background-color-gray: #fafafa;
@activated-color: #5D98F6;
@divider-color:#fafafa;
@check-box-bg:#48D2A0;
/**
* headbar的高度配置
*/
@headerHeight:44px;
@iosPaddingTop:20px;
@iosxPaddingTop:40px;
@hasHeader:44px;
@iosHasHeader:64px;
@iosxHasHeader:84px;
@paddingLength:15px;
@bottomSafeArea:34px;
/**
* Notify颜色
*/
@notifyFontColor:#fff;
@dialogWrapBackgroundColor:rgba(0,0,0,.7);
@dialogWrapWarningBackgroundColor:#f96f68;
@dialogWrapSuccessBackgroundColor:#48d2a0;
/**
* 覆盖vux自带的颜色
*/
@header-background-color:@theme-color;
@header-title-color:@baseColor;
@header-arrow-color:@baseColor;
@tabbar-text-active-color: #f96268;
@datetime-header-item-font-color:@theme-color;
@datetime-header-item-confirm-font-color:@theme-color;
@dialog-button-text-default-color:@font-color;
@dialog-button-text-primary-color:@theme-color;
/**
* popup-header
*/
@popup-header-height:44px;
@popup-header-bg-color:#fff;
@popup-header-font-size:16px;
@popup-header-right-text-color:@theme-color;
@popup-header-left-text-padding: 15px;
@popup-header-right-text-padding: 15px;
/**
* actionsheet
*/
/**
* en: primary type text color of menu item
* zh-CN: 菜单项primary类型的文本颜色
*/
@actionsheet-label-primary-color: @theme-color;
/**
* en: warn type text color of menu item
* zh-CN: 菜单项warn类型的文本颜色
*/
@actionsheet-label-warn-color: #f96268;
/**
* en: default type text color of menu item
* zh-CN: 菜单项default类型的文本颜色
*/
@actionsheet-label-default-color: #444;
/**
* en: disabled type text color of menu item
* zh-CN: 菜单项disabled类型的文本颜色
*/
@actionsheet-label-disabled-color: #ccc;
@swiper-indicator-active-color:@headerColor;
//swipout按钮的颜色定义
@swipeout-button-primary-bg-color:@headerColor;
@swipeout-button-warn-bg-color:#f96268;
@swipeout-button-default-bg-color:#c8c7cd;
.setTopLine(@c: rgba(0,0,0,.1)) {
content: " ";
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px; /*no*/
border-top: 1px solid @c; /*no*/
color: @c;
transform-origin: 0 0;
transform: scaleY(0.5);
}
.setBottomLine(@c: rgba(0,0,0,.1)) {
content: " ";
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px; /*no*/
border-bottom: 1px solid @c; /*no*/
color: @c;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.setLeftLine(@c: rgba(0,0,0,.1)) {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 1px; /*no*/
bottom: 0;
border-left: 1px solid @c; /*no*/
color: @c;
transform-origin: 0 0;
transform: scaleX(0.5);
}
.setRightLine(@c: rgba(0,0,0,.1)) {
content: " ";
position: absolute;
right: 0;
top: 0;
width: 1px; /*no*/
bottom: 0;
border-right: 1px solid @c; /*no*/
color: @c;
transform-origin: 100% 0;
transform: scaleX(0.5);
}
.setLine(@c: rgba(0,0,0,.1)) {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 200%;
border: 1px solid @c; /*no*/
color: @c;
height: 200%;
transform-origin: left top;
transform: scale(0.5);
}
This source diff could not be displayed because it is too large. You can view the blob instead.
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