Commit 2eb8ed26 authored by feifei's avatar feifei

客服后台

parents
Pipeline #221 failed with stages
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
root = true
# 匹配全部文件
[*]
# 缩进风格,可选"space"、"tab"
indent_style = space
# 缩进的空格数
indent_size = 2
# 结尾换行符,可选"lf"、"cr"、"crlf"
end_of_line = lf
# 在文件结尾插入新行
insert_final_newline = true
# 删除一行中的前后空格
trim_trailing_whitespace = true
[*.{js}]
# 设置字符集
charset = utf-8
/build/
/config/
/dist/
/*.js
/test/unit/coverage/
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: false,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: false,
},
extends: [
// 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.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
// 'vue/script-indent': [
// 'error',
// 4,
// {
// 'baseIndent': 1
// }
// ]
}
}
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
.idea
# testing
/coverage
# production
/dist
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}
# 后台管理系统
> A Vue.js project
## 编译步骤
``` bash
# 安装npm依赖包
npm install
# 热更新服务器,监听localhost:8080
npm run dev
# 编译打包
npm run build
# 查看打包编译情况,代码分析
npm run build --report
# 运行unit测试
npm run unit
# 运行e2e测试
npm run e2e
# 全部测试
npm test
```
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).
## 代码结构
## 业务功能模块
'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, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
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)
}
}
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})
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: () => {},
heartbeat: 2000
})
// 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 packageConfig = 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 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] : [cssLoader]
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 = () => {
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: packageConfig.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({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
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')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: isProd
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vendor': path.resolve(__dirname, '../src/vendor'),
'vue$': 'vue/dist/vue.esm.js',
'@components': resolve('src/components'),
'@': resolve('src'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
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]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const pkg = require('../package')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
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: {
rewrites: [
{from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html')},
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: 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')
}),
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({
title: pkg.title,
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
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://${devWebpackConfig.devServer.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 pkg = require('../package')
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')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const versiony = require('versiony')
const version = versiony.from('version.json')
const v = version.get()
console.log()
console.log(`###############当前版本${v}##############`)
console.log()
const versionAdd = function (oldVersion) {
let v = parseInt(oldVersion.replace(/\./g, '')) + 1
let varr = v.toString().split('')
return varr
}
const vNew = versionAdd(v)
version.major(vNew[0]).minor(vNew[1]).patch(vNew[2]).to('version.json').end()
/*当前是否是开发,测试环境*/
const isDev = process.env.NODE_ENV === 'testing'
const env = isDev
? require('../config/test.env')
: require('../config/prod.env')
/*具体配置*/
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
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
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? {safe: true, map: {inline: false}}
: {safe: true}
}),
// 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({
title: pkg.title,
filename: isDev ? 'index.html' : 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 vendor 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 (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.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
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"'
})
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path');
// 在这里做版本递增
const versiony = require('versiony');
const version = versiony.from('version.json');
const v = version.get();
module.exports = {
// 打包编译
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: `static`,
assetsPublicPath: `./`,
productionSourceMap: true,
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report
},
//阿里云测试环境
dev: {
env: require('./dev.env'),
port: 80,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
//生产环境
// target: 'http://116.62.244.103:8080/',
// target: 'http://localhost:8080/',
//测试环境
target: 'http://47.99.40.126:8080/',
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
}
},
// 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
}
}
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
'use strict'
const merge = require('webpack-merge')
const devEnv = require('./dev.env')
module.exports = merge(devEnv, {
NODE_ENV: '"testing"'
})
<!DOCTYPE html>
<html>
<head>
<title>系统</title>
<meta charset="utf-8">
<link type="favicon" rel="shortcut icon" href="/static/favicon.ico"/>
<!--引入呼叫系统需要的文件-->
<!-- <link href="/static/js/jsutils/jquery-ui.min.css" rel="stylesheet" type="text/css"/>
<script src="/static/js/jsutils/jquery.min.js"></script>
<script src="/static/js/jsutils/jquery-ui.min.js"></script>
<script src="/static/js/jsutils/jquery.tmpl.js"></script>
<script src="/static/js/jsutils/base64.js"></script>
<script src="/static/js/jsutils/md5.js"></script>
<script src="/static/js/sip-0.11.3.min.js"></script>
<script src="/static/js/zywl_sipclient.min.js"></script> -->
<!--接口配置-->
<script>
//本地测试
window.APIHOST = "http://192.168.0.50:8102";
//测试
//window.APIHOST ="http://47.99.245.36:8102";
//生产环境
//window.APIHOST = "https://loess.jqtianxia.com";
</script>
<link rel="stylesheet" href="./static/css/index.css">
</head>
<body>
<!-- 页面loading -->
<div id="loading" class="loading">
<div class="l-bg"></div>
<!-- <img src="/static/loading.gif"> -->
</div>
<!-- VUE渲染内容 -->
<div id="app"></div>
</body>
</html>
This diff is collapsed.
{
"name": "black_vue",
"title": "后台管理系统",
"version": "1.0.0",
"description": "black",
"author": "jinzhouhang <jinzhouhang@163.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"e2e": "node test/e2e/runner.js",
"test": "npm run unit && npm run e2e",
"lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.18.0",
"css-loader": "^0.28.11",
"echarts": "^4.1.0",
"element-ui": "^2.3.2",
"express": "^4.17.1",
"file-saver": "^2.0.0",
"js-cookie": "^2.2.0",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"moment": "^2.22.1",
"normalize.css": "^8.0.0",
"nprogress": "^0.2.0",
"style-loader": "^0.23.1",
"v-charts": "^1.18.0",
"versiony": "^2.0.1",
"vue": "^2.5.2",
"vue-canvas-nest": "^2.0.0",
"vue-iconfont": "^2.5.1",
"vue-json-excel": "^0.2.98",
"vue-router": "^3.0.1",
"vuex": "^3.0.1",
"xlsx": "^0.14.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "^21.0.2",
"babel-loader": "^7.1.1",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"chromedriver": "^2.27.2",
"copy-webpack-plugin": "^4.0.1",
"cross-spawn": "^5.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.19.1",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"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": "^3.14.0",
"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",
"jest": "^22.0.4",
"jest-serializer-vue": "^0.3.0",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"nightwatch": "^0.9.12",
"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",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"script-loader": "^0.7.2",
"selenium-server": "^3.0.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-jest": "^1.0.2",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
import vueCanvasNest from 'vue-canvas-nest'
export default {
name: 'app',
components: {vueCanvasNest},
mounted () {
this.$nextTick(() => {
document.getElementById('loading').innerHTML = ''
})
}
}
</script>
<style>
* {
margin: 0;
padding: 0;
}
#app {
width: 100%;
height: 100%;
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* overflow: auto; */
}
</style>
*{margin: 0;padding: 0;list-style: none;}
/*
KISSY CSS Reset
理念:1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。
2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。
3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。
特色:1. 适应中文;2. 基于最新主流浏览器。
维护:玉伯<lifesinger@gmail.com>, 正淳<ragecarrier@gmail.com>
*/
/** 清除内外边距 **/
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
pre, /* text formatting elements 文本格式元素 */
form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */
th, td /* table elements 表格元素 */ {
margin: 0;
padding: 0;
}
/** 设置默认字体 **/
body,
button, input, select, textarea /* for ie */ {
font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif;
}
h1, h2, h3, h4, h5, h6 { font-size: 100%; }
address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
/** 重置列表元素 **/
ul, ol { list-style: none; }
/** 重置文本格式元素 **/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
/** 重置表单元素 **/
legend { color: #000; } /* for ie6 */
fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */
button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */
/* 注:optgroup 无法扶正 */
/** 重置表格元素 **/
table { border-collapse: collapse; border-spacing: 0; }
/* 清除浮动 */
.ks-clear:after, .clear:after {
content: '\20';
display: block;
height: 0;
clear: both;
}
.ks-clear, .clear {
*zoom: 1;
}
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;}
.helps{margin-top:40px;}
.helps pre{
padding:20px;
margin:10px 0;
border:solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists{
width: 100% !important;
}
.icon_lists li{
float:left;
width: 100px;
height:180px;
text-align: center;
list-style: none !important;
}
.icon_lists .icon{
font-size: 42px;
line-height: 100px;
margin: 10px 0;
color:#333;
-webkit-transition: font-size 0.25s ease-out 0s;
-moz-transition: font-size 0.25s ease-out 0s;
transition: font-size 0.25s ease-out 0s;
}
.icon_lists .icon:hover{
font-size: 100px;
}
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p,
.markdown pre {
margin: 1em 0;
}
.markdown > p,
.markdown > blockquote,
.markdown > .highlight,
.markdown > ol,
.markdown > ul {
width: 80%;
}
.markdown ul > li {
list-style: circle;
}
.markdown > ul li,
.markdown blockquote ul > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown > ul li p,
.markdown > ol li p {
margin: 0.6em 0;
}
.markdown ol > li {
list-style: decimal;
}
.markdown > ol li,
.markdown blockquote ol > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown pre {
border-radius: 6px;
background: #f7f7f7;
padding: 20px;
}
.markdown pre code {
border: none;
background: #f7f7f7;
margin: 0;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown > table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown > table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown > table th,
.markdown > table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown > table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
font-style: italic;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown > br,
.markdown > p > br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
pre{
background: #fff;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont</title>
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
</head>
<body>
<div class="main markdown">
<h1>IconFont 图标</h1>
<ul class="icon_lists clear">
<li>
<i class="icon v-icon v-icon-shezhi"></i>
<div class="name">设置</div>
<div class="fontclass">.v-icon-shezhi</div>
</li>
<li>
<i class="icon v-icon v-icon-wxbzhuye"></i>
<div class="name">wxb主页</div>
<div class="fontclass">.v-icon-wxbzhuye</div>
</li>
<li>
<i class="icon v-icon v-icon-weibiaoti25"></i>
<div class="name">展开</div>
<div class="fontclass">.v-icon-weibiaoti25</div>
</li>
<li>
<i class="icon v-icon v-icon-gerenjiekuanjiekuan"></i>
<div class="name">个人借款 借款</div>
<div class="fontclass">.v-icon-gerenjiekuanjiekuan</div>
</li>
<li>
<i class="icon v-icon v-icon-yiyuqi"></i>
<div class="name">分期-已逾期</div>
<div class="fontclass">.v-icon-yiyuqi</div>
</li>
<li>
<i class="icon v-icon v-icon-feiyongjiesuandan"></i>
<div class="name">费用结算单</div>
<div class="fontclass">.v-icon-feiyongjiesuandan</div>
</li>
<li>
<i class="icon v-icon v-icon-xiangmushenbao"></i>
<div class="name">项目申报</div>
<div class="fontclass">.v-icon-xiangmushenbao</div>
</li>
<li>
<i class="icon v-icon v-icon-web-icon-"></i>
<div class="name">客户</div>
<div class="fontclass">.v-icon-web-icon-</div>
</li>
<li>
<i class="icon v-icon v-icon-zhankai"></i>
<div class="name">展开</div>
<div class="fontclass">.v-icon-zhankai</div>
</li>
<li>
<i class="icon v-icon v-icon-hanbaocaidanzhedie"></i>
<div class="name">汉堡菜单折叠</div>
<div class="fontclass">.v-icon-hanbaocaidanzhedie</div>
</li>
</ul>
<h2 id="font-class-">font-class引用</h2>
<hr>
<p>font-class是unicode使用方式的一种变种,主要是解决unicode书写不直观,语意不明确的问题。</p>
<p>与unicode使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持ie8+,及所有现代浏览器。</li>
<li>相比于unicode语意明确,书写更直观。可以很容易分辨这个icon是什么。</li>
<li>因为使用class来定义图标,所以当要替换图标时,只需要修改class里面的unicode引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的fontclass代码:</h3>
<pre><code class="lang-js hljs javascript"><span class="hljs-comment">&lt;link rel="stylesheet" type="text/css" href="./iconfont.css"&gt;</span></code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="lang-css hljs">&lt;<span class="hljs-selector-tag">i</span> <span class="hljs-selector-tag">class</span>="<span class="hljs-selector-tag">v-icon</span> <span class="hljs-selector-tag">v-icon-xxx</span>"&gt;&lt;/<span class="hljs-selector-tag">i</span>&gt;</code></pre>
<blockquote>
<p>"v-icon"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。</p>
</blockquote>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont</title>
<link rel="stylesheet" href="demo.css">
<script src="iconfont.js"></script>
<style type="text/css">
.icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em; height: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
</style>
</head>
<body>
<div class="main markdown">
<h1>IconFont 图标</h1>
<ul class="icon_lists clear">
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-shezhi"></use>
</svg>
<div class="name">设置</div>
<div class="fontclass">#v-icon-shezhi</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-wxbzhuye"></use>
</svg>
<div class="name">wxb主页</div>
<div class="fontclass">#v-icon-wxbzhuye</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-weibiaoti25"></use>
</svg>
<div class="name">展开</div>
<div class="fontclass">#v-icon-weibiaoti25</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-gerenjiekuanjiekuan"></use>
</svg>
<div class="name">个人借款 借款</div>
<div class="fontclass">#v-icon-gerenjiekuanjiekuan</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-yiyuqi"></use>
</svg>
<div class="name">分期-已逾期</div>
<div class="fontclass">#v-icon-yiyuqi</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-feiyongjiesuandan"></use>
</svg>
<div class="name">费用结算单</div>
<div class="fontclass">#v-icon-feiyongjiesuandan</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-xiangmushenbao"></use>
</svg>
<div class="name">项目申报</div>
<div class="fontclass">#v-icon-xiangmushenbao</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-web-icon-"></use>
</svg>
<div class="name">客户</div>
<div class="fontclass">#v-icon-web-icon-</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-zhankai"></use>
</svg>
<div class="name">展开</div>
<div class="fontclass">#v-icon-zhankai</div>
</li>
<li>
<svg class="icon" aria-hidden="true">
<use xlink:href="#v-icon-hanbaocaidanzhedie"></use>
</svg>
<div class="name">汉堡菜单折叠</div>
<div class="fontclass">#v-icon-hanbaocaidanzhedie</div>
</li>
</ul>
<h2 id="symbol-">symbol引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个svg的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过<code>font-size</code>,<code>color</code>来调整样式。</li>
<li>兼容性较差,支持 ie9+,及现代浏览器。</li>
<li>浏览器渲染svg的性能一般,还不如png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的symbol代码:</h3>
<pre><code class="lang-js hljs javascript"><span class="hljs-comment">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;</span></code></pre>
<h3 id="-css-">第二步:加入通用css代码(引入一次就行):</h3>
<pre><code class="lang-js hljs javascript">&lt;style type=<span class="hljs-string">"text/css"</span>&gt;
.icon {
width: <span class="hljs-number">1</span>em; height: <span class="hljs-number">1</span>em;
vertical-align: <span class="hljs-number">-0.15</span>em;
fill: currentColor;
overflow: hidden;
}
&lt;<span class="hljs-regexp">/style&gt;</span></code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="lang-js hljs javascript">&lt;svg <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"icon"</span> aria-hidden=<span class="hljs-string">"true"</span>&gt;<span class="xml"><span class="hljs-tag">
&lt;<span class="hljs-name">use</span> <span class="hljs-attr">xlink:href</span>=<span class="hljs-string">"#v-icon-xxx"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">use</span>&gt;</span>
</span>&lt;<span class="hljs-regexp">/svg&gt;
</span></code></pre>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont</title>
<link rel="stylesheet" href="demo.css">
<style type="text/css">
@font-face {font-family: "v-icon";
src: url('iconfont.eot'); /* IE9*/
src: url('iconfont.eot#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('iconfont.woff') format('woff'), /* chrome, firefox */
url('iconfont.ttf') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg#v-icon') format('svg'); /* iOS 4.1- */
}
.v-icon {
font-family:"v-icon" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
}
</style>
</head>
<body>
<div class="main markdown">
<h1>IconFont 图标</h1>
<ul class="icon_lists clear">
<li>
<i class="icon v-icon">&#xe624;</i>
<div class="name">设置</div>
<div class="code">&amp;#xe624;</div>
</li>
<li>
<i class="icon v-icon">&#xe61f;</i>
<div class="name">wxb主页</div>
<div class="code">&amp;#xe61f;</div>
</li>
<li>
<i class="icon v-icon">&#xe62b;</i>
<div class="name">展开</div>
<div class="code">&amp;#xe62b;</div>
</li>
<li>
<i class="icon v-icon">&#xe650;</i>
<div class="name">个人借款 借款</div>
<div class="code">&amp;#xe650;</div>
</li>
<li>
<i class="icon v-icon">&#xe665;</i>
<div class="name">分期-已逾期</div>
<div class="code">&amp;#xe665;</div>
</li>
<li>
<i class="icon v-icon">&#xe635;</i>
<div class="name">费用结算单</div>
<div class="code">&amp;#xe635;</div>
</li>
<li>
<i class="icon v-icon">&#xe6a6;</i>
<div class="name">项目申报</div>
<div class="code">&amp;#xe6a6;</div>
</li>
<li>
<i class="icon v-icon">&#xe70c;</i>
<div class="name">客户</div>
<div class="code">&amp;#xe70c;</div>
</li>
<li>
<i class="icon v-icon">&#xe60a;</i>
<div class="name">展开</div>
<div class="code">&amp;#xe60a;</div>
</li>
<li>
<i class="icon v-icon">&#xe62f;</i>
<div class="name">汉堡菜单折叠</div>
<div class="code">&amp;#xe62f;</div>
</li>
</ul>
<h2 id="unicode-">unicode引用</h2>
<hr>
<p>unicode是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持ie6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版iconfont支持多色图标,这些多色图标在unicode模式下将不能使用,如果有需求建议使用symbol的引用方式</p>
</blockquote>
<p>unicode使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的font-face</h3>
<pre><code class="lang-js hljs javascript">@font-face {
font-family: <span class="hljs-string">'v-icon'</span>;
src: url(<span class="hljs-string">'iconfont.eot'</span>);
src: url(<span class="hljs-string">'iconfont.eot?#iefix'</span>) format(<span class="hljs-string">'embedded-opentype'</span>),
url(<span class="hljs-string">'iconfont.woff'</span>) format(<span class="hljs-string">'woff'</span>),
url(<span class="hljs-string">'iconfont.ttf'</span>) format(<span class="hljs-string">'truetype'</span>),
url(<span class="hljs-string">'iconfont.svg#v-icon'</span>) format(<span class="hljs-string">'svg'</span>);
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用iconfont的样式</h3>
<pre><code class="lang-js hljs javascript">.v-icon{
font-family:<span class="hljs-string">"v-icon"</span> !important;
font-size:<span class="hljs-number">16</span>px;font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: <span class="hljs-number">0.2</span>px;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre><code class="lang-js hljs javascript">&lt;i <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"v-icon"</span>&gt;&amp;#x33;<span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span></span></code></pre>
<blockquote>
<p>"v-icon"是你项目下的font-family。可以通过编辑项目查看,默认是"iconfont"。</p>
</blockquote>
</div>
</body>
</html>
@font-face {font-family: "v-icon";
src: url('iconfont.eot?t=1540453552124'); /* IE9*/
src: url('iconfont.eot?t=1540453552124#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
url('iconfont.ttf?t=1540453552124') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1540453552124#v-icon') format('svg'); /* iOS 4.1- */
}
.v-icon {
font-family:"v-icon" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.v-icon-shezhi:before { content: "\e624"; }
.v-icon-wxbzhuye:before { content: "\e61f"; }
.v-icon-weibiaoti25:before { content: "\e62b"; }
.v-icon-gerenjiekuanjiekuan:before { content: "\e650"; }
.v-icon-yiyuqi:before { content: "\e665"; }
.v-icon-feiyongjiesuandan:before { content: "\e635"; }
.v-icon-xiangmushenbao:before { content: "\e6a6"; }
.v-icon-web-icon-:before { content: "\e70c"; }
.v-icon-zhankai:before { content: "\e60a"; }
.v-icon-hanbaocaidanzhedie:before { content: "\e62f"; }
This diff is collapsed.
This diff is collapsed.
.top {
width: 95%;
margin: auto
}
.top .search-input {
width: 300px
}
.top .close-btn {
margin-left: 10px
}
.top .btn {
float: right
}
.system-list {
width: 100%;
margin: 10px auto 15px auto
}
.page {
text-align: center
}
.important_text {
color: red;
font-weight: bolder
}
\ No newline at end of file
<template>
<el-dialog class="client-data-dialog" title="创建代扣还款单" width="30%" :visible.sync="visible"
:before-close="handleClose">
<span>确定要创建代扣还款单?</span>
<div slot="footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="submitForm('ruleForm')">确 定</el-button>
</div>
</el-dialog>
</template>
<script type="text/ecmascript-6">
export default {
name: 'AddByhRemindDialog',
props: {
dialogVisible: {
type: Boolean,
required: true
},
creator: {
type: String
},
orderNo: {
type: String
},
periodNo: {
type: Number
},
},
data() {
return {
ui: {
submitLoading: false
},
visible: this.$props.dialogVisible,
ruleForm: {
orderNo: '',
periodNo: '',
creator: '',
},
}
},
created() {
this.ruleForm = {
orderNo: this.orderNo,
periodNo: this.periodNo,
creator: this.creator,
}
},
methods: {
/** 提交点击 */
submitForm() {
this.$$post('/repayRemind/backedApplyByh', {
orderNo: this.ruleForm.orderNo, periodNo: this.ruleForm.periodNo, creator: this.ruleForm.creator
}).then(res => {
if (res.data.code != 1) {
this.$message.error(res.data.msg);
return
}
this.handleClose();
this.$message({message: '成功', type: 'success'});
window.location.reload();
})
.catch(err => {
this.$message.error("创建代扣还款单失败");
})
},
/** 关闭处理 */
handleClose() {
this.visible = false;
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 300);
},
}
}
</script>
<style scoped>
</style>
<template>
<el-dialog class="client-data-dialog" title="反馈新增" :visible.sync="visible" :before-close="handleClose">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="80px" class="demo-ruleForm">
<el-form-item label="功能点" prop="pointName">
<el-select v-model="ruleForm.pointName" label="功能点" placeholder="请选择" style="width:80%">
<el-option
v-for="item in optionsCustomer"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item >
<el-form-item label="问题标题" prop="pointTitle">
<el-input v-model="ruleForm.pointTitle" placeholder="请输入内容"></el-input>
</el-form-item>
<el-form-item label="问题描述" prop="problemDescription">
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="ruleForm.problemDescription" style="width:80%">
</el-input>
</el-form-item>
<el-form-item label="状态" prop="pointStatus">
<el-select v-model="ruleForm.pointStatus" label="功能点" placeholder="下拉选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="解决方式" prop="pointSolve">
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="ruleForm.pointSolve" style="width:80%">
</el-input>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<p>{{this.ruleForm.creator}}</p>
</el-form-item>
</el-form>
<div slot="footer" style="margin-right:30px">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="submitForm('ruleForm')">新 增</el-button>
</div>
</el-dialog>
</template>
<script type="text/ecmascript-6">
export default {
name: 'AddUserServiceDialog',
props: {
dialogVisible: {
type: Boolean,
required: true,
},
clientNo: {
type: String
},
},
data() {
/*请选择功能点*/
var validatepointFeatures = (rule, value, callback) => {
if (!value) {
return callback(new Error('请选择功能点'));
}
};
/*请输入问题描述*/
var validateqdescription = (rule, value, callback) => {
if (!value) {
return callback(new Error('请输入问题描述'));
}
};
var validatestatus = (rule, value, callback) => {
if (!value) {
return callback(new Error('请输入问题描述'));
}
};
var validatesolve = (rule, value, callback) => {
if (!value) {
return callback(new Error('请输入问题描述'));
}
};
return {
ui: {
submitLoading: false
},
visible: this.$props.dialogVisible,
operat: [],
restaurants: [],
loanoptions: [],
state: '',
ruleForm: {
pointName: '',
pointTitle: '',
clientNo: '',
problemDescription:'',
pointStatus:'FOLLOWEDUP',
pointSolve:'',
creator: ''
},
rules: {
pointName: [
{ validator: validatepointFeatures, trigger: 'blur' }
],
problemDescription: [
{ validator: validateqdescription, trigger: 'blur' }
],
pointStatus: [
{ validator: validatestatus, trigger: 'blur' }
],
pointSolve: [
{ validator: validatesolve, trigger: 'blur' }
]
},
options: [{
value: 'FOLLOWEDUP',
label: '待跟进'
}, {
value: 'FOLLOWEDING',
label: '跟进中'
}, {
value: 'FINISHED',
label: '已解决'
}],
optionsCustomer: [{
value: '内部投诉',
label: '内部投诉'
}, {
value: '还款问题',
label: '还款问题'
}, {
value: '系统问题',
label: '系统问题'
}, {
value: '借款咨询',
label: '借款咨询'
}, {
value: '账户问题',
label: '账户问题'
}, {
value: '其它',
label: '其它'
}],
}
},
created() {
this.ruleForm = {
clientNo: this.clientNo,
creator: localStorage.getItem("userName"),
}
},
methods: {
/** 提交点击 */
submitForm(formName) {
this.$$post('/customer/addQuestion', {
creator : localStorage.getItem("userName"),
pointName: this.ruleForm.pointName,
problemDescription : this.ruleForm.problemDescription ,
pointSolve: this.ruleForm.pointSolve,
pointStatus : this.ruleForm.pointStatus ,
pointTitle: this.ruleForm.pointTitle,
clientNo: this.ruleForm.clientNo
})
.then(res => {
if (res.data.code != 200) {
this.$message.error(res.data.message);
return
}
this.$message({message: '新增成功', type: 'success'});
this.handleClose();
})
.catch(err => {
alert("error!")
})
},
createFilter(queryString) {
return (restaurant) => {
return (restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
};
},
handleIconClick(ev) {
console.log(ev);
},
/** 关闭处理 */
handleClose() {
this.visible = false;
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 300);
}
},
// mounted: function () {
// this.loadOperate();
// },
}
</script>
<style>
</style>
<template>
<el-dialog class="client-data-dialog" title="创建提前结清" width="40%" :visible.sync="visible" :before-close="handleClose">
<div style="margin-left:50px">
<el-row :gutter="20" >
<el-col :span="8">
<div class="grid-content bg-purple">本金:{{ this.ruleForm.principleAmt }}</div>
</el-col>
<el-col :span="8">
<div class="grid-content bg-purple">起息日:{{ this.ruleForm.startDate | dateFilter}}</div>
</el-col>
<!-- <el-col :span="6">
<div class="grid-content bg-purple">还款日:{{ this.ruleForm.planAmt }}</div>
</el-col> -->
</el-row>
<br/>
<el-row :gutter="20" :center="true">
<el-col :span="8">
<div class="grid-content bg-purple">占用天数:{{ this.ruleForm.userDay }}</div>
</el-col>
<el-col :span="8">
<div class="grid-content bg-purple">占用期数:{{ this.ruleForm.userMonth }}</div>
</el-col>
</el-row>
<br/>
<el-row :gutter="20" >
<el-col :span="6">
<div class="grid-content bg-purple">总费用:{{ this.ruleForm.allAmt }}</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple">利息:{{ this.ruleForm.interestAmt }}</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple">服务费:{{ this.ruleForm.serviceAmt }}</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple">违约金:{{ this.ruleForm.breakAmt }}</div>
</el-col>
</el-row>
<br/>
<el-row :gutter="20" >
<el-col :span="16">
<div class="grid-content bg-purple">总计应还:{{ this.ruleForm.settleAmt }}</div>
</el-col>
</el-row>
</div>
<br/>
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="140px" class="demo-ruleForm">
<el-form-item label="还款银行账号" prop="bankAccount">
<el-col :span="20"><el-input v-model="ruleForm.bankAccount" placeholder="请输入还款银行账号"></el-input></el-col>
</el-form-item>
<el-form-item label="还款银行账户名称" prop="bankOwner">
<el-col :span="20"><el-input v-model="ruleForm.bankOwner" placeholder="请输入还款银行账户名称"></el-input></el-col>
</el-form-item>
<el-form-item label="转账金额" prop="settleAmt">
<el-col :span="20"><el-input v-model="ruleForm.settleAmt" placeholder="请输入转账金额" disabled></el-input></el-col>
</el-form-item>
<el-form-item label="减免金额" prop="derateAmt">
<el-col :span="20"><el-input v-model="ruleForm.derateAmt" placeholder="请输入转账金额" disabled></el-input></el-col>
</el-form-item>
<el-form-item label="还款凭证" prop="attach">
<el-upload
list-type="picture-card"
:multiple="oss.multiple"
:action="oss.action"
:data="oss.data"
accept=".jpeg,.jpg,.png"
:before-upload="handleBeforeApplyUpload"
:on-success="handleLoanApplySuccess"
:on-remove="handleLoanApplyRemove">
<i class="el-icon-plus"></i>
</el-upload>
</el-form-item>
<el-form-item label="还款备注" prop="memo">
<el-col :span="20"><el-input v-model="ruleForm.memo" placeholder="请输入还款备注"></el-input></el-col>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="backedTransfer('ruleForm')">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
import * as moment from "moment";
export default {
name: "advanceLoanAmt",
props: {
dialogVisible: {
type: Boolean,
required: true
},
loanNo: {
type: String
},
},
data() {
return {
ui: {
submitLoading: false
},
visible: this.$props.dialogVisible,
ruleForm: {
allAmt: '',
backedAmt: '',
loanNo: '',
breakAmt: '',
clientNo: '',
derateAmt: '',
interestAmt: '',
loanAmt: '',
overdueAmt: '',
principleAmt:'',
serviceAmt:'',
settleAmt: '',
startDate: '',
userDay:'',
userMonth:'',
memo:'',
attach:'',
bankAccount:'',
bankOwner:'',
},
rules: {
},
loginName:'',
oss: {
action: '',
data: {},
multiple: false,
},
}
},
filters: {
dateFilter: function (row) {
var date = row
if ( typeof(date)==undefined || typeof(date)==null) {
return ''
}
return moment(date).format("YYYY-MM-DD")
},
},
created() {
this.ruleForm = {
loanNo: this.loanNo,
}
// 查询当前的基础数据
this.$$get('/back/countSettle?loanNo='+this.loanNo).then(res => {
if (res.data.code !=200 ) {
this.$message.error(res.data.message);
return
} else {
this.ruleForm = res.data.result;
}
}).catch(error => {
this.$Message.error(error || '网络异常,请稍后。。。');
});
},
mounted() {
this.loginName = localStorage.getItem("loginName");
},
methods: {
/** 提交点击 */
backedTransfer() {
this.$$post(`/back/beforeSettle`, this.buildParam()).then(res => {
if (res.data.code != 200) {
this.$message.error(res.data.message);
return
}
this.$message({message: '操作成功', type: 'success'});
this.handleClose();
setTimeout(() => {
window.location.reload();
}, 1000);
})
.catch(err => {
alert("error!")
})
},
handleBeforeApplyUpload(file) {
var attachType = 'LOESS_TRANSFER_APPLY'
return this.$$get(`/oss/signature/?fileType=` + attachType + "&fileName=" + file.name).then(res => {
if (res.data.code != 200) {
this.$message.error(res.data.message);
return
}
const result = res.data.result.result;
const data = {};
const tempOss = {};
data.OSSAccessKeyId = result.accessId;
data.policy = result.policy;
data.Signature = result.signature;
data.key = result.dir;
tempOss.action = result.host;
tempOss.data = data;
this.oss = tempOss;
this.ruleForm.attach = result.dir
});
},
handleLoanApplySuccess(res, file, fileList) {
this.$notify({title: '成功', message: file.name + ",上传成功", type: 'success'});
},
handleLoanApplyRemove(res, file, fileList) {
},
//参数
buildParam() {
var return_hash = {
attach: this.ruleForm.attach ,
backAmt: this.ruleForm.settleAmt,
creater: localStorage.getItem("userName"),
bankAccount: this.ruleForm.bankAccount,
bankOwner: this.ruleForm.bankOwner,
derateAmt: this.ruleForm.derateAmt,
loanNo: this.ruleForm.loanNo,
memo: this.ruleForm.memo,
};
return return_hash;
},
/** 关闭处理 */
handleClose() {
this.visible = false;
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 300);
},
}
}
</script>
<style scoped>
</style>
This diff is collapsed.
<template>
<div>
<br>
<div class="top">
<el-form :inline="true" :model="searchInfo" class="demo-form-inline">
<el-form-item>
<el-input placeholder="坐席编号" v-model="searchInfo.extensionNumber"></el-input>
</el-form-item>
<el-form-item>
<!-- <el-input placeholder="业务人员" v-model="searchInfo.cellName"></el-input> -->
<el-autocomplete style="width: 80%"
v-model="searchInfo.cellNameStr"
:fetch-suggestions="querySearchAsync"
placeholder="请输入跟进人"
@select="handleSelect"
:clearable="true"
></el-autocomplete>
</el-form-item>
<el-form-item>
<el-input placeholder="主叫电话" v-model="searchInfo.caller"></el-input>
</el-form-item>
<el-form-item>
<el-input placeholder="客户手机号" v-model="searchInfo.callee"></el-input>
</el-form-item>
<el-form-item>
<el-date-picker v-model="searchInfo.date" type="daterange" range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期" :clearable="true"></el-date-picker>
</el-form-item>
<div class="btn">
<el-button @click="reset" type="primary">重置</el-button>
<el-button @click="querySearchRemind" type="primary">查询</el-button>
</div>
</el-form>
</div>
<div class="system-list">
<el-table :data="tablePlanRemindData" style="width: 100%" :default-sort="{prop: 'date', order: 'descending'}" :highlight-current-row="true" >
<el-table-column prop="extensionNumber" label="坐席编号" sortable ></el-table-column>
<el-table-column prop="cellNameStr" label="业务人员"></el-table-column>
<el-table-column prop="caller" label="主叫电话" >
</el-table-column>
<el-table-column prop="startTime" label="通话时间" :formatter="dateFormat" ></el-table-column>
<el-table-column prop="talkTime" label="通话时长" ></el-table-column>
<el-table-column prop="callee" label="客户手机号"></el-table-column>
<el-table-column label="操作" style="margin-right:15px">
<template slot-scope="scope">
<audio :src="scope.row.recordUrl" ref="audio"
@pause="onPause"
@play="onPlay"
controls="controls">
</audio>
</template>
</el-table-column>
<!-- 音频播放控件 -->
<div>
<el-button type="text" @click="startPlayOrPause">{{audio.playing | transPlayPause}}</el-button>
</div>
</el-table>
</div>
<div class="page">
<el-pagination
@current-change="handleCurrentChange"
:current-page.sync="page.current"
@size-change="handleSizeChange"
:page-sizes="[20, 50, 80, 100]"
:page-size="page.size"
layout="total, sizes, prev, pager, next, jumper"
:total="page.total">
</el-pagination>
</div>
<!--窗口组件-->
<template>
<!-- 通讯录 -->
<byhContactDialog
v-if="ui.byhContactDialog.visible"
:certNo="ui.byhContactDialog.certNo"
:clientCell="ui.byhContactDialog.clientCell"
:clientName="ui.byhContactDialog.clientName"
:dialogVisible.sync="ui.byhContactDialog.visible">
</byhContactDialog>
<!-- 通讯录 -->
<linkersDialog
v-if="ui.linkersDialog.visible"
:clientNo="ui.linkersDialog.clientNo"
:linkerType="ui.linkersDialog.linkerType"
:dialogVisible.sync="ui.linkersDialog.visible">
</linkersDialog>
</template>
</div>
</template>
<script>
import * as moment from "moment";
import byhContactDialog from './ByhContactDialog';
import linkersDialog from '../common/LinkersDialog'
export default {
name: "ByhPlanRemindList",
components: {
byhContactDialog,
linkersDialog,
},
data () {
return {
flag: false,
audio: {
// 该字段是音频是否处于播放状态的属性
playing: false
},
ui:
{
byhContactDialog: {
visible: false,
certNo: '',
clientName: ''
},
linkersDialog: {
visible: false,
clientNo: '',
linkerType: ''
}
},
page: {
current: 1,
size: 10,
total: 0
},
activeName: '',
searchInfo: {
date: [],
cellName: '',
callee: '',
caller: '',
cellNameStr: '',
extensionNumber: '',
},
tablePlanRemindData: [],
record: '',
}
},
created () {
},
mounted: function () {
this.tablePlanRemindData = this.remindData();
// 搜索的用户列表
this.$$get(`/user/select`)
.then(res => {
if (res.data.code < 1)
throw res.data.msg;
var array = []
res.data.data.forEach((item, index) => {
array[index] = {value: item.userName, lable: item.loginName,}
})
this.allUser = array;
})
.catch(err => this.$$msg.err(err))
},
filters: {
// 使用组件过滤器来动态改变按钮的显示
transPlayPause(value) {
return value ? '暂停' : '播放'
}
},
methods: {
// 搜索用户名接口
querySearchAsync(queryString, cb) {
var allUser = this.allUser;
var results = queryString ? allUser.filter(this.createStateFilter(queryString)) : allUser;
cb(results);
},
createStateFilter(queryString) {
return (state) => {
return (state.value.toLowerCase().search(queryString.toLowerCase()) >= 0);
};
},
handleSelect(item) {
console.log(item);
this.searchInfo.cellName = item.lable;
this.searchInfo.cellNameStr = item.value;
},
formatter (row, column) {
return row.address;
},
selected: function(gameName) {
this.activeName = gameName
},
/** 加载数据 */
remindData (params) {
var listsData = [];
this.$$post('/call/getCallPageList', this.buildParam()).then(res => {
if (res.data.code != 1) {
this.$message.error(res.data.msg);
return
}
listsData = res.data.data.records;
this.tablePlanRemindData = listsData;
this.page.total = res.data.data.total;
}).catch(error => {
this.$Message.error(error || '系统异常');
});
},
//搜索查询
querySearchRemind () {
this.remindData();
},
// 分页数据加载
handleSizeChange(row){
this.page.size=row
this.page.current=1;
this.remindData();
},
//参数
buildParam () {
var return_hash = {
size: this.page.size,
current: this.page.current,
};
if (this.searchInfo.extensionNumber != '') {
return_hash['extensionNumber'] = this.searchInfo.extensionNumber
}
if (this.searchInfo.cellName != '' && this.searchInfo.cellNameStr !='') {
return_hash['cellName'] = this.searchInfo.cellName
}
// 修改手机号查询为客户编号查询
if (this.searchInfo.caller != '') {
return_hash['caller'] = this.searchInfo.caller
}
if (this.searchInfo.callee != '') {
return_hash['callee'] = this.searchInfo.callee
}
if (!this.$permissionUtils.btnPermission('updateUser')) {
return_hash['handler'] = localStorage.getItem("loginName")
}
if (this.searchInfo.date != null) {
return_hash['recordStartTime'] = this.searchInfo.date[0];
return_hash['recordEndTime'] = this.searchInfo.date[1]
}
return return_hash;
},
//显示日期
dateFormat: function (row, column) {
var date = row[column.property];
if (date == undefined) {
return "";
}
return moment(date).format("YYYY-MM-DD HH:mm:ss");
},
//重置
reset () {
this.searchInfo.date = '';
this.searchInfo.extensionNumber = '';
this.searchInfo.cellName = '';
this.searchInfo.cellNameStr = '';
this.searchInfo.caller = '';
this.searchInfo.callee = '';
},
/** 处理分页操作*/
handleCurrentChange () {
this.tablePlanRemindData = this.remindData();
},
mergeDate (param1, param2) {
if (param1 == "") {
return ""
}
var array = new Array();
array[0] = new Date(param1)
array[1] = new Date(param2)
return array;
},
getDate (param, num) {
if (param && param[num] !== '') {
return moment(param[num]).format("YYYY-MM-DD")
}
return ""
},
// 控制音频的播放与暂停
startPlayOrPause () {
return this.audio.playing ? this.pause() : this.play()
},
// 播放音频
play () {
this.$refs.audio.play()
},
// 暂停音频
pause () {
this.$refs.audio.pause()
},
// 当音频播放
onPlay () {
this.audio.playing = true
},
// 当音频暂停
onPause () {
this.audio.playing = false
}
}
}
</script>
<style scoped>
</style>
<template>
<el-dialog class="client-data-dialog" :title="title" width="40%" :visible.sync="visible" :before-close="handleClose">
<el-form :model="ruleForm" ref="ruleForm" :rules="rules" label-width="80px" class="demo-ruleForm">
<el-form-item label="确认意见" prop="operaterDesc">
<el-col :span="20"><el-input v-model="ruleForm.operaterDesc" placeholder="请输入确认意见"></el-input></el-col>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" v-if="button.type == 'CONFIRM'" @click="confirmBacked('ruleForm')">确 定</el-button>
<el-button type="primary" v-if="button.type == 'REFUSE'" @click="refuseBacked('ruleForm')">驳 回</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: "ByhConfirmRefuseDailog",
props: {
dialogVisible: {
type: Boolean,
required: true
},
backedNo: {
type: String
},
btnType: {
type: String
},
},
data() {
return {
ui: {
submitLoading: false
},
visible: this.$props.dialogVisible,
ruleForm: {
backedNo: '',
operater: '',
operaterDesc: '',
},
rules: {
operaterDesc: [{required: true, message: '请输入确认意见', trigger: 'blur'}],
},
loginName:'',
button:{
type: '',
},
}
},
created() {
this.ruleForm = {
backedNo: this.backedNo,
}
},
computed: {
title() {
if (this.button.type === 'CONFIRM') return '还款单确认';
else if (this.button.type === 'REFUSE') return '还款单驳回'
}
},
mounted() {
this.loginName = localStorage.getItem("loginName");
this.button.type = this.btnType;
},
methods: {
/** 确认点击 */
confirmBacked() {
this.$refs['ruleForm'].validate((valid) => {
if (!valid) {
return false
}
this.$$post(`/back/pass`, {
backedNo: this.ruleForm.backedNo,
operater: this.loginName,
operaterDesc: this.ruleForm.operaterDesc,
}).then(res => {
if (res.data.code != 200) {
this.$message.error(res.data.message);
return
}
this.$message({message: '操作成功', type: 'success'});
this.handleClose();
window.location.reload();
})
.catch(err => {
alert("error!")
})
})
},
/** 驳回点击 */
refuseBacked() {
this.$refs['ruleForm'].validate((valid) => {
if (!valid) {
return false
}
this.$$post(`/back/fail`,{backedNo: this.ruleForm.backedNo, operater: this.loginName, operaterDesc:this.ruleForm.operaterDesc,
}).then(res => {
if (res.data.code < 200) {
this.$message.error(res.data.message);
return
}
this.$message({message: '操作成功', type: 'success'});
this.handleClose();
window.location.reload();
})
})
},
/** 关闭处理 */
handleClose() {
this.visible = false;
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 300);
},
}
}
</script>
<style scoped>
</style>
\ No newline at end of file
<template>
<el-dialog class="common-dialog"
title="客户通讯录" :visible.sync="dialogVisible" width="60%" :before-close="handleClose">
<div id="tableBody" class="content-table">
<el-table :data="records" stripe style="width: 100%">
<el-table-column prop="name" sortable label="联系人"></el-table-column>
<el-table-column prop="phone" sortable label="联系号码"></el-table-column>
</el-table>
</div>
<div slot="footer">
<el-button @click="handleClose">关 闭</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: "ByhContactDialog",
props: {
dialogVisible: {
type: Boolean
},
certNo: {
type: String
},
clientCell: {
type: String
},
clientName: {
type: String
}
},
data () {
return {
client: {},
records: [],
}
},
mounted: function () {
this.$$get(`/repayRemind/clientContact/${this.certNo}/${this.clientCell}/${this.clientName}`)
.then(res => {
if (res.data.code < 1) {
throw res.data.msg
}
this.records = res.data.data
})
.catch(err => this.$$msg.err(err))
this.$nextTick(() => {
const bg = localStorage.getItem('bg')
document.getElementById('tableBody').style.background = 'url("' + bg + '") 0 0 repeat';
});
},
methods: {
/** 关闭处理 */
handleClose () {
this.visible = false
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 100)
},
cellFormat: function (row, column) {
var cellFormat = row[column]
return cellFormat.substring(0, 3) + '-' + cellFormat.substring(3, 7) + '-' + cellFormat.substring(7, 11)
},
}
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
.contact-list table th {
color: #64656f;
text-align: center;
font-size: 16px;
}
.contact-list table td {
color: #64656f;
text-align: center;
font-size: 16px;
}
.content-table {
height 550px;
overflow auto;
}
/*表格*/
.el-table, .el-table__expanded-cell {
background transparent;
}
.el-table th, .el-table tr {
background transparent;
}
.el-table--striped .el-table__body tr.el-table__row--striped td {
background transparent;
}
.el-table--enable-row-hover .el-table__body tr:hover > td {
background transparent;
}
</style>
\ No newline at end of file
<template>
<el-dialog class="client-data-dialog" title="反馈新增" :visible.sync="visible" :before-close="handleClose" style="width:90%">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="140px" class="demo-ruleForm">
<el-form-item label="联系结果" prop="title">
<el-select v-model="ruleForm.title" label="联系结果" placeholder="请选择" @change="changeValue" style="width:80%">
<el-option
v-for="item in operat"
:key="item.name"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="备注信息" prop="content">
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="ruleForm.content" style="width:60%">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" style="margin-right:30px">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="submitForm('ruleForm')">确 定</el-button>
</div>
</el-dialog>
</template>
<script type="text/ecmascript-6">
export default {
name: 'ByhJumpUserDetail',
props: {
dialogVisible: {
type: Boolean,
required: true
},
bizNo: {
type: String
},
clientNo: {
type: String
},
},
data() {
return {
ui: {
submitLoading: false
},
visible: this.$props.dialogVisible,
operat: [],
ruleForm: {
bizNo : '',
title: '',
content :'',
clientCell:'',
handle: ''
},
rules: {
},
}
},
created() {
this.ruleForm = {
bizNo: this.bizNo,
clientNo: this.clientNo,
}
this.$$get('/client/getClientCell/'+this.clientNo)
.then(res => {
if (res.data.code == 1){
this.ruleForm.clientCell = res.data.data
}else{
this.$message({message: res.data.msg, type: 'error'});
}
})
.catch(err => this.$$msg.err(err))
},
methods: {
/** 提交点击 */
submitForm(ruleForm) {
this.$$post('/contact/create', {
bizNo : this.ruleForm.bizNo,
title : this.ruleForm.title,
clientCell : this.ruleForm.clientCell,
handle : localStorage.getItem("loginName") ,
content : this.ruleForm.content,
})
.then(res => {
if (res.data.code < 1) {
this.$message.error(res.data.msg);
return
}
this.$message({message: '新增成功', type: 'success'});
this.handleClose();
this.$emit('my-event',true)
})
.catch(err => {
alert("error!")
})
},
changeValue(value) {
let obj = {};
obj = this.operat.find((item)=>{
return item.value === value;
});
this.ruleForm.title = value;
},
loadOperate() {
this.$$get('/contact/getTitleEnum')
.then(res => {
if (res.data.code == 1){
let arr = []
Object.keys(res.data.data).forEach(function(key){
var a = new Object();
a.name = res.data.data[key]
a.value = key;
arr.push(a)
});
this.operat =arr;
}else{
this.$message({message: res.data.msg, type: 'error'});
}
})
.catch(err => this.$$msg.err(err))
},
handleSelect(item) {
this.ruleForm.title = item.value;
this.ruleForm.problemDescription = item.problemDescription;
this.ruleForm.solve = item.solve;
},
handleIconClick(ev) {
console.log(ev);
},
/** 关闭处理 */
handleClose() {
this.visible = false;
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 300);
}
},
mounted: function () {
this.loadOperate();
},
}
</script>
<style>
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<template>
<el-dialog title="绑卡记录" :visible.sync="dialogVisible" width="50%" :before-close="handleClose">
<div >
<el-table :data="records" stripe style="width: 100%;">
<el-table-column prop="gmtCreated" label="签约时间" :formatter="dateFormat" ></el-table-column>
<el-table-column prop="operaterDesc" label="备注" ></el-table-column>
</el-table>
</div>
</el-dialog>
</template>
<script>
import * as moment from "moment";
export default {
name: "ByhContactDialog",
props: {
dialogVisible: {
type: Boolean
},
cardLogList: {
type: Array
},
},
data () {
return {
records:[],
}
},
created() {
this.records = this.reverse(this.cardLogList);
},
methods: {
/** 关闭处理 */
handleClose () {
this.visible = false
setTimeout(() => {
this.$emit('update:dialogVisible', false)
}, 100)
},
/*日期*/
dateFormat: function (row, column) {
var date = row[column.property]
if (date == undefined) {
return ''
}
return moment(date).format("YYYY-MM-DD HH:mm:ss")
},
reverse(array){
var newArr = [];
for(var i=array.length-1;i>=0;i--){
newArr[newArr.length] = array[i];
}
return newArr;
},
submitMarket() {
},
},
mounted: function () {
this.submitMarket();
},
}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">
</style>
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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