初始提交

This commit is contained in:
wanyongkang
2020-10-04 10:30:08 +08:00
commit 3193537726
441 changed files with 171716 additions and 0 deletions

21
README.md Normal file
View File

@@ -0,0 +1,21 @@
# admin
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# 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).

21
admin.ps1 Normal file
View File

@@ -0,0 +1,21 @@
$workspace="C:\Program Files (x86)\Jenkins\workspace\hualian_admin"
$distFolder="C:\Program Files (x86)\Jenkins\workspace\hualian_admin\dist\*"
echo "cd "+$workspace
cd $workspace
echo "npm"
npm install
npm run build --prod
echo "npm ok"
C:\Windows\System32\inetsrv\appcmd.exe stop site "hualian_admin"
#$TargetFolder = "D:\www\hanniu\admin"
#$Files = get-childitem $TargetFolder -force
#Foreach ($File in $Files)
#{
##$FilePath=$File.FullName
#Write-Host $FilePath -NoNewline
#Remove-Item -Path $FilePath -Recurse -Force
#}
echo "copy start"
copy-item $distFolder -destination "D:\www\hualian\admin" -Recurse -Force
echo "copy ok"
C:\Windows\System32\inetsrv\appcmd.exe start site "hualian_admin"

41
build/build.js Normal file
View File

@@ -0,0 +1,41 @@
'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'
))
})
})

54
build/check-versions.js Normal file
View File

@@ -0,0 +1,54 @@
'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)
}
}

BIN
build/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

101
build/utils.js Normal file
View File

@@ -0,0 +1,101 @@
'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'
})
} 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')
})
}
}

22
build/vue-loader.conf.js Normal file
View File

@@ -0,0 +1,22 @@
'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'
}
}

101
build/webpack.base.conf.js Normal file
View File

@@ -0,0 +1,101 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const webpack = require('webpack')
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
}
})
module.exports = {
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'),
}
},
// 添加代码
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
jquery: "jquery",
"window.jQuery": "jquery"
})
],
module: {
rules: [
// ...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
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'
}
}

95
build/webpack.dev.conf.js Normal file
View File

@@ -0,0 +1,95 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
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({
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)
}
})
})

145
build/webpack.prod.conf.js Normal file
View File

@@ -0,0 +1,145 @@
'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')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const 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({
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 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

7
config/dev.env.js Normal file
View File

@@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

77
config/index.js Normal file
View File

@@ -0,0 +1,77 @@
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8081, // 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: 'cheap-module-eval-source-map',
devtool: '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: false,//true
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
//devtool: '#source-map',
devtool: 'cheap-module-eval-source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// 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
}
}

4
config/prod.env.js Normal file
View File

@@ -0,0 +1,4 @@
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

14
index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>华连云后台管理系统</title>
<!-- <link rel="stylesheet" href="https://at.alicdn.com/t/font_488037_mniwf800wz.css"> -->
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

13305
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

85
package.json Normal file
View File

@@ -0,0 +1,85 @@
{
"name": "admin",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"prod": "webpack-dev-server --inline --progress --config build/webpack.prod.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"axios": "^0.19.0",
"element-ui": "^2.12.0",
"jquery": "^3.4.1",
"nprogress": "^0.2.0",
"qrcodejs2": "0.0.2",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vue-ueditor-wrap": "^2.4.1",
"vuex": "^3.1.2"
},
"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-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.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",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.11",
"eslint": "^4.15.0",
"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": "^4.0.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",
"less": "^3.10.3",
"less-loader": "^5.0.0",
"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",
"sass-loader": "^8.0.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"style-loader": "^1.0.0",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"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"
]
}

14
src/App.vue Normal file
View File

@@ -0,0 +1,14 @@
<template>
<router-view ></router-view>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
#app {
}
</style>

View File

@@ -0,0 +1,125 @@
<template>
<div class="main_box screen1" v-loading="loading">
<el-form :model="articleModel" :rules="rules" ref="editor" label-width="100px">
<el-form-item prop="CatalogId" label="分类" size="small">
<el-select v-model="articleModel.CatalogId" placeholder="请选择">
<el-option label="华连头条" :value="1"></el-option>
<el-option label="优惠活动" :value="2"></el-option>
<el-option label="常见问题" :value="3"></el-option>
<el-option label="新手教程" :value="4"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="Title" label="标题">
<el-input placeholder="请填标题" v-model="articleModel.Title" size="small"></el-input>
</el-form-item>
<el-form-item prop="SubTitle" label="副标题">
<el-input placeholder="请填副标题" v-model="articleModel.SubTitle" size="small"></el-input>
</el-form-item>
<el-form-item prop="Keyword" label="关键字">
<el-input v-model="articleModel.Keyword" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="AccessCount" label="访问人数">
<el-input
placeholder="请填访问人数:"
v-model="articleModel.AccessCount"
type="number"
size="small"
></el-input>
</el-form-item>
<el-form-item prop="OnLine" label="发布状态">
<el-switch
v-model="articleModel.Publish"
:active-value="1"
:inactive-value="0"
size="small"
></el-switch>
</el-form-item>
</el-form>
<div class="editor-container">
<UE v-model="articleModel.Content" :config="config" ref="ue"></UE>
</div>
<div class="handel_box clr">
<el-button @click="$router.go(-1)" size="small"> </el-button>
<el-button type="primary" @click="save('editor')" size="small">确定</el-button>
</div>
</div>
</template>
<script>
let that;
export default {
components: {},
data() {
return {
articleModel: {
Publish: 0,
id: 0,
Thumb: "",
CatalogId:1,
},
loading: false,
rules: {
Title: [this.$vaild.required("标题")],
SubTitle: [this.$vaild.required("副标题")]
// Banner: [this.$vaild.required("课程主图")],
// Cover: [this.$vaild.required("课程封面")],
},
config: {
serverUrl: this.$api.baseURL + "ueditor",
UEDITOR_HOME_URL: "/static/ueditor/",
autoHeightEnabled: false,
initialFrameHeight: 500
},
options: []
};
},
created() {
this.$store.commit("setCurrentNav", "资讯管理>>添加资讯");
var query = this.$route.query;
if (query.optype == 2) {
this.getInfo(query.id);
}
},
methods: {
getInfo(id) {
this.$api.get("course/v1/article/Get", { id: id }).then(res => {
this.articleModel = res.Data;
});
},
save(formName) {
var that = this;
this.$refs[formName].validate(valid => {
if (valid) {
if (that.$route.query.optype == "1") {
that.add();
} else if (that.$route.query.optype == "2") {
that.edit();
}
}
});
},
add() {
this.$api.post("course/v1/article/post", this.articleModel).then(res => {
this.$router.push({ name: "articlelist" });
});
},
edit() {
this.$api.post("course/v1/article/put", this.articleModel).then(res => {
this.$router.push({ name: "articlelist" });
});
},
upload(callback) {
this.$api.upload("oss/v1/ImageCloud/upload").then(res => {
callback && callback(res.Data);
});
},
setCover(ret) {
this.articleModel.Thumb = ret.Url;
}
}
};
</script>
<style scoped>
.el-form {
width: 600px;
}
</style>

View File

@@ -0,0 +1,104 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-plus" v-href="'add?optype=1'">添加文章</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入名称/标题" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" size="medium" :height="$getHeight(100)" row-key="Id" border>
<!-- <el-table-column label="图片" width="80">
<template slot-scope="scope">
<img :src="scope.row.Thumb" style="width:50px;height:20px" />
</template>
</el-table-column> -->
<el-table-column prop="CatalogId" label="分类" width="180" :formatter="catalogFormat"></el-table-column>
<el-table-column prop="Title" label="标题" width="180"></el-table-column>
<el-table-column prop="SubTitle" label="子标题" width="180"></el-table-column>
<el-table-column prop="AccessCount" label="访问人数"></el-table-column>
<el-table-column prop="CreateTime" label="发布时间" aformatter="formatterTime"></el-table-column>
<el-table-column label="发布状态">
<template slot-scope="scope">
<el-switch
v-model="scope.row.Publish"
:active-value="1"
:inactive-value="0"
active-color="#13ce66"
inactive-color="#dcdfe6"
@change="audit(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span class="handel cursor edit" v-href="'add?optype=2&id='+scope.row.Id">编辑</span>
<span class="handel cursor del" @click="del(scope.row)">删除</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="20"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
catalogFormat(data) {
console.log(data)
return data.CatalogId==1?"华连头条":"使用技巧";
}
};
},
created() {
this.get();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api.get("course/v1/article/page", this.searchModel).then(res => {
this.retData = res;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api.post("course/v1/article/Delete?id=" + item.Id).then(res => {
that.get();
});
});
},
audit(item) {
this.$api.post("course/v1/article/Audit?id=" + item.Id).then(res => {
item.Publish = res.Data;
});
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,751 @@
<template>
<div>
<el-popover
v-if="showTip"
placement="top-start"
width="350"
trigger="click"
>
<div style="padding:20px;">
{{text}}
</div>
<span slot="reference">{{showText}}<i class="el-icon-arrow-down" style="padding-left:20px"></i></span>
</el-popover>
<span v-else>{{showText}}</span>
</div>
</template>
<script>
export default {
props: {
text: {
type: String,
default: function() {
return "";
}
},
length: {
type: Number,
default: function() {
return 10;
}
}
},
data() {
return {
showTip: false,
showText: ""
};
},
watch: {
text: function(newQuestion, oldQuestion) {
console.log(newQuestion);
this.init();
}
},
created() {
},
mounted(){
this.init();
},
methods: {
init() {
if (this.text.length > this.length) {
this.showText = this.text.substring(0, this.length);
this.showTip = true;
} else {
this.showText = this.text;
this.showTip = false;
}
return;
}
}
};
</script>
<style scoped>
#qrcode {
position: absolute;
right: 70px;
top: 16px;
}
.el-message-box__message p {
text-align: center !important;
}
.cur {
font-weight: normal;
}
.box {
overflow: hidden;
}
.main_right {
width: calc(100% - 300px);
height: 100%;
float: left;
border-left: 1px solid #dae1f2;
padding: 20px 20px 56px;
position: relative;
box-sizing: border-box;
}
.logo {
width: 33px;
height: 33px;
margin-top: 16.5px;
margin-right: 10px;
border-radius: 50%;
}
.popover_box span {
font-size: 14px;
color: #1a263c;
text-align: left;
width: calc(100% - 30px);
margin-left: 15px;
border-bottom: 1px solid #f0f3fa;
cursor: pointer;
}
.popover_box span:hover {
background: white;
}
.dialog_box {
width: 440px;
height: 210px;
}
.dialog_content {
height: auto;
padding-bottom: 20px;
min-height: 95px;
}
.right_top {
width: 100%;
height: 40px;
border-bottom: 1px solid #cccccc;
padding-bottom: 5px;
}
.right_top span {
border-left: 2px solid #4c82ff;
color: #17181a;
font-size: 16px;
padding-left: 10px;
}
.right_top .right {
float: right;
margin-left: 20px;
}
.right_top .right i {
color: #4c82ff;
}
.right_title {
width: 100%;
float: left;
margin-top: 25px;
margin-bottom: 10px;
position: relative;
}
.right_title .left span {
position: absolute;
top: 5px;
left: 32px;
}
.right_title .left i {
font-size: 22px;
color: rgb(184, 200, 240);
line-height: 30px;
}
.search_box {
background: #fafafa;
}
.search_box input {
background: #fafafa;
}
.handel_box {
width: calc(100% - 10px);
height: 50px;
background: #f7f8fc;
float: left;
margin: 0px;
max-width: 100%;
padding-left: 10px;
position: relative;
transform: translateX(0px);
}
.handel_box span {
width: 105px;
height: 36px;
text-align: center;
line-height: 36px;
border-radius: 3px;
border: 1px solid #dae1f2;
float: left;
background: white;
margin-top: 6px;
margin-right: 20px;
}
.handel_box span {
color: white;
border: 1px solid #4c82ff;
background: #4c82ff;
}
/* .handel_box span:last-child {
border: 1px solid #ff728d;
} */
.tbody td:last-child {
white-space: nowrap;
}
.tbody td:last-child span {
width: auto;
line-height: 22px;
display: inline-block;
margin-right: 10px;
border-radius: 7px;
cursor: pointer;
padding: 0px 5px;
}
.theader {
background: white;
}
.theader td:hover {
background: none;
}
table td {
border-right: 0px;
text-align: left;
}
.checkbox {
width: 16px;
height: 16px;
border: 1px solid #8c96ad;
display: block;
border-radius: 0px;
font-size: 14px;
}
.tbody .checkbox {
line-height: 16px;
}
.checkbox i {
font-size: 14px;
line-height: 16px;
color: #4c82ff;
display: none;
}
.checkbox_cur i {
display: block;
}
.ban {
padding-left: 10px;
width: 100%;
height: 25px;
border-left: 1px solid #dae1f2;
}
.span_box {
width: calc(100% - 40px);
margin: 5px 0 0 20px;
float: left;
}
.span_box span {
width: calc(50% - 15px);
height: 35px;
text-align: center;
line-height: 35px;
color: #1a1a1a;
font-size: 14px;
margin-left: 15px;
background: #fafbfc;
display: block;
float: left;
}
.span_box span:first-child {
margin-left: 0px;
margin-right: 15px;
}
.right_box {
width: 315px;
height: calc(100vh - 75px);
position: fixed;
right: 0px;
top: 70px;
background: #fafbfc;
box-shadow: 0px 5px 10px #cccccc;
margin-right: 0px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
overflow: hidden;
z-index: 9;
}
.title {
width: calc(100% - 20px);
line-height: 42px;
color: #363c4c;
font-size: 16px;
background: white;
padding-left: 20px;
}
.box_title {
width: calc(100% - 150px);
line-height: 49px;
text-align: left;
margin-left: 50px;
}
.checkbox {
width: 16px;
height: 16px;
border: 1px solid #979899;
text-align: center;
}
.checkbox i {
margin: 0px;
line-height: 16px;
font-size: 12px;
color: #4c82ff;
display: none;
}
.checkbox_cur i {
display: block;
}
.openstate {
font-size: 14px;
color: #4c82ff;
font-weight: bold;
line-height: 49px;
}
.menubox {
height: 710px;
overflow-y: auto;
}
.menuhandel {
width: calc(100% - 60px);
height: 60px;
background: white;
padding: 0px 30px;
}
.menuhandel span {
width: 102px;
height: 34px;
border: 5px;
text-align: center;
line-height: 34px;
box-sizing: border-box;
border: 1px solid #4c82ff;
color: #4c82ff;
float: left;
border-radius: 5px;
margin-top: 12px;
}
.menuhandel span:last-child {
color: white;
background: #4c82ff;
margin-left: 45px;
}
.route .icon-arrow-down {
transform: rotate(0deg);
}
.noroute .icon-arrow-down {
transform: rotate(-90deg);
}
table tr:first-child td {
padding-left: 0px;
}
table tr td {
min-width: 55px;
padding-left: 10px;
}
table tr td:first-child {
width: 15px;
min-width: 0px;
padding-right: 10px;
padding-left: 0px;
}
.ishead {
width: 12px;
height: 12px;
border-radius: 50%;
background: #edf1fa;
display: inline-block;
}
/* table .checkbox {
border: 2px solid #8c96ad;
box-sizing: border-box;
line-height: 15px;
text-align: center;
} */
.tbody {
height: 35px;
}
.theader {
height: 45px;
}
.third .icon-arrow-down {
transform: rotate(-90deg);
}
td .checkbox {
box-sizing: border-box;
border-width: 2px;
}
td .checkbox i {
font-size: 6px;
display: block;
line-height: 13px;
text-align: center;
transform: scale(0.8);
opacity: 0;
}
td .checkbox_cur i {
opacity: 1;
}
.tbody .short {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 128px;
}
.tbody td:last-child span {
margin-right: 5px;
}
.mt25 {
margin-top: 25px;
}
.dialog {
z-index: 2000;
}
.search_input {
float: right;
}
.el-input {
position: relative;
font-size: 14px;
display: inline-block;
height: 35px;
}
.search_btn {
background: #4c82ff;
width: 38px;
height: 38px;
border-radius: 3px;
margin: 1px 0;
float: left;
cursor: pointer;
padding-left: 0px !important;
}
.information {
text-align: center;
color: #919399;
margin-top: 96px;
}
.nd {
margin-top: 10px;
}
.liang {
width: 640px;
height: 160px;
background: url("/static/img/QRkuang.png");
background-repeat: no-repeat;
position: relative;
}
.num1,
.num2 {
font-size: 24px;
color: #409eff;
}
.num1 {
position: absolute;
left: 10px;
top: 10px;
}
.num2 {
position: absolute;
left: 340px;
top: 10px;
}
.fontSize {
font-size: 15px;
}
.stepText1 {
position: absolute;
top: 43px;
left: 10px;
}
.stepText2 {
position: absolute;
top: 43px;
left: 340px;
}
.guanzhu1 {
position: absolute;
top: 65px;
left: 10px;
}
.guanzhu2 {
position: absolute;
top: 65px;
left: 340px;
}
.weiyuQR {
width: 130px;
height: 130px;
position: absolute;
left: 110px;
top: 16px;
background: url("/static/img/weiyuQR.jpg");
background-size: 100%;
}
/* 人脸 */
.hang {
height: 50px;
padding-left: 60px;
}
.hang1 {
border: none;
}
.selectVIP {
height: 50px;
line-height: 50px;
}
.hangTip {
height: 35px;
font-size: 16px;
}
.img {
min-height: 50px;
padding-left: 60px;
padding-bottom: 46px;
padding-top: 5px;
display: flex;
}
.label {
width: 85px;
float: left;
height: 50px;
line-height: 55px;
}
.name {
float: left;
height: 30px;
line-height: 30px;
margin-top: 10px;
margin-left: 5px;
width: 250px;
border: 1px #ddd solid;
font-size: 12px;
text-indent: 5px;
border-radius: 4px;
}
.tel {
width: 330px;
}
.xing {
margin-top: 2px;
color: red;
float: right;
}
.xuanze {
width: 80px;
height: 30px;
line-height: 30px;
float: left;
border: 1px #4d82ff solid;
border-left: 0;
margin-top: 10px;
font-size: 12px;
text-align: center;
color: #fff;
cursor: pointer;
background: #4d82ff;
}
.el-radio {
height: 50px;
}
.imgBox {
width: 520px;
height: 100px;
margin-top: 20px;
position: relative;
}
.imgBox::after {
content: "请采集三张人脸图片";
position: absolute;
bottom: -35px;
left: 0;
}
.pic {
width: 100px;
height: 75px;
margin-right: 30px;
float: left;
border: 1px #ccc solid;
}
.close {
position: absolute;
top: 0;
right: 0;
font-size: 20px;
color: #fff;
cursor: pointer;
background: #409eff;
}
.face {
border: 0;
position: absolute;
left: 0;
top: 0;
}
.posi {
position: relative;
}
.addBox {
width: 100px;
height: 100px;
float: left;
border: 1px #ccc solid;
cursor: pointer;
}
.jia {
font-weight: 900;
font-size: 35px;
text-align: center;
margin-top: 25px;
}
.tip {
font-size: 12px;
text-align: center;
}
.cameraTip {
line-height: 150px;
margin-left: 28%;
font-size: 24px;
}
.cameraBox,
.faceFail {
width: 100%;
display: flex;
flex-direction: column;
padding-bottom: 10px;
position: relative;
}
.cameraBox .cameraBg {
position: absolute;
top: -15px;
left: 0;
right: 0;
height: 300px;
margin: 0 auto;
z-index: 100;
}
.faceFail {
padding: 100px 0;
}
.text {
font-size: 14px;
text-align: center;
margin-top: 10px;
}
.textFail {
font-size: 24px;
text-align: center;
}
.threepPic,
.toPic {
position: relative;
float: left;
}
.canvasBox {
width: 450px;
margin: 0 auto;
display: flex;
justify-content: space-around;
}
.threepPic {
width: 120px;
}
.el-radio {
margin-right: 0px;
}
.dialog_bind_wxbox {
width: 670px !important;
height: 330px !important;
}
</style>

View File

@@ -0,0 +1,21 @@
<template>
<div class="div_footer">
</div>
</template>
<script></script>
<style lang="less" scoped>
.div_footer {
width: 100%;
height: auto;
padding: 30px 0;
font-size: 12px;
color: #999999;
text-align: center;
&.pageAll {
box-sizing: border-box;
padding-left: 220px;
}
}
</style>

View File

@@ -0,0 +1,130 @@
<template>
<div class="base_topBarbox">
<div class="base_topBar editbase_topBar">
<div class="base_explain">
<span id="toolbar_title" class="edittopTittles">{{$store.state.currentNav}}</span>
<div class="base-top-bar">
<div class="base-top-bar__right">
<!-- <div class="base-top-bar__right">
<a href="/user_manage#/user_feedback" class="top-bar__text border-r">用户反馈</a>
</div> -->
<div><el-link type="danger" @click="logout">退出系统</el-link></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import QRCode from "qrcodejs2";
var that = null;
export default {
name: "headerBar",
data() {
return {
qrVisible: false,
qrCode: null
};
},
props: {},
created() {},
methods: {
open() {
console.log(open);
var url = "http://yk.hncore.net/store";
this.makeqrcode(url);
},
logout(){
localStorage.clear();
this.$router.replace('/login');
},
showQr() {
this.qrVisible = true;
},
makeqrcode(url) {
var that = this;
this.qrCode&&this.qrCode.clear();
var qr = document.getElementById("qrcode");
qr.innerHTML = "";
this.qrCode = new QRCode(qr, {
text: url,
width: 150,
height: 150,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
}
},
computed: {}
};
</script>
<style lang="less" scoped>
.base_topBarbox {
position: absolute;
margin-left: 180px;
top: 0;
left: 0;
width: calc(100% - 180px);
z-index: 1000;
background-color: #fff;
}
.edittopTittles {
-ms-flex: 0 0 auto;
flex: 0 0 auto;
line-height: 56px;
}
.base_topBar {
min-width: 1100px;
background-color: #fff;
padding: 0 20px;
}
.base_explain {
display: -ms-flexbox;
display: flex;
}
#toolbar_title,
.base_topBar.try_time .warn_info_box {
display: block;
}
.base-top-bar {
width: 100%;
height: 56px;
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row-reverse;
}
.base-top-bar__right {
display: flex;
align-items: center;
flex: 0 0 auto;
}
.base-top-bar__right {
display: flex;
align-items: center;
flex: 0 0 auto;
}
.top-bar__text {
width: 56px;
font-size: 14px;
color: #666666;
line-height: 20px;
margin: 0 16px;
position: relative;
cursor: pointer;
}
.top-bar__shop-view {
width: 81px;
height: 28px;
line-height: 26px;
text-align: center;
border-radius: 14px;
border: 1px solid #b2b2b2;
font-size: 12px;
color: #666666;
margin-right: 17px;
cursor: pointer;
}
</style>

View File

@@ -0,0 +1,60 @@
<template>
<page>
<Header></Header>
<Left></Left>
<div class="base_right">
<router-view class="page_main"></router-view>
</div>
</page>
</template>
<script>
let that;
export default {
name: "home",
components: {
Left: () => import("./left.vue"),
Header: () => import("./header.vue")
},
data() {
return {};
},
computed: {},
watch: {
$route: {
handler(val, oldVal) {
this.$nextTick(() => {
//页面加载完成后执行
//todo
// this.resetHandelBox();
});
},
deep: true // 深度观察监听
}
},
created() {},
updated() {},
methods: {}
};
</script>
<style lang="less" scoped>
.base_right {
margin-left: 180px;
padding-left: 10px;
height: 100%;
position: relative;
overflow-x: hidden;
overflow-y: auto;
background: #f5f7fa;
transition: padding ease 0.3s;
padding-right: 10px;
padding-top: 56px;
}
.page_main {
margin-top: 10px;
background-color: #fff;
padding: 15px;
padding-bottom: 15px !important;
}
</style>

View File

@@ -0,0 +1,210 @@
<template>
<div class="base_slide editbase_slide" id="base_slide">
<div class="base_logo_wrap">
<a href="/index">
<img src="../../../../static/logo.png" />
</a>
</div>
<div class="sidebarWrap">
<div class="leftsidebarWrap">
<div class="sideMenu_item" v-for="(item,index) in menus" :key="index">
<div class="firstindexMenuWrap MenuCursorpointer newsideMenu">
<i :class="'font_family theicon '+ item.Icon"></i>
<span
v-if="item.Permissionurl==''"
class="firstpri_name MenuText"
>{{item.Permissionlabel}}</span>
<router-link v-else :to="item.Permissionurl" :target="item.target">
<span class="firstpri_name MenuText">{{item.Permissionlabel}}</span>
</router-link>
<span class="font_family right_arrow icon-icon_pagination_left1" style="display: none;"></span>
</div>
<div class="ScedindexMenuWrap" v-if="item.Children&&item.Children.length>0">
<ul>
<li class="newsideMenu" v-for="(child,cindex) in item.Children" :key="cindex">
<router-link :to="item.Permissionurl+child.Permissionurl" :target="child.target">
<span class="sedMenuText MenuText">{{child.Permissionlabel}}</span>
</router-link>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
var that = null;
//import { menus } from "@/extend/js/newMenus.js";
export default {
name: "leftBar",
props: {},
data() {
return {
menus: [],
routerActive:"",
};
},
created() {
},
mounted() {
//this.getMenus();
this.menus=this.$store.state.menus;
if(!this.menus||this.menus.length==0){
this.menus=this.$local.getMenus(this.menus);
}
this.routerActive = this.$router.currentRoute.path
},
watch: {
$route: function (to, from) {
}
},
methods: {
goDefault() {
this.$router.push({
path: "/course/list"
});
},
getMenus() {
//this.loading=true;
// let loadingInstance1 =this.$loading({ fullscreen: true })
this.$api
.get("manage/v1/ManagerToPermission/GetPermissions")
.then(res => {
console.log(res);
// this.loading=false;
// loadingInstance1.close()
this.menus = res.Data;
});
},
active(item,child){
var res=window.location.pathname;
var url=item.Permissionurl;
if(child)url+=child.Permissionurl;
return res==url;
}
},
computed: {
}
};
</script>
<style lang="less" scoped>
@import url("../../../../static/css/font.css");
.base_slide {
top: 0;
float: left;
width: 180px;
height: 100%;
background-color: #fff;
overflow-x: hidden;
// overflow-y: auto;
color: #fff;
padding-top: 70px;
}
.base_logo_wrap {
position: absolute;
top: 0;
left: 0;
z-index: 1;
height: 70px;
background-color: #273043;
width: 180px;
}
.base_logo_wrap img {
height: 27px;
margin-left: 32px;
margin-top: 20px;
}
.sidebarWrap {
min-height: 100%;
background-color: #273043;
color: rgba(255, 255, 255, 0.9);
box-shadow: 0px 4px 0px 0px rgba(0, 0, 0, 0.05);
}
.sidebarWrap .leftsidebarWrap {
// padding-top: 20px;
width: 100%;
box-sizing: border-box;
padding-bottom: 100px;
}
.sidebarWrap .leftsidebarWrap .sideMenu_item {
width: 100%;
padding-bottom: 15px;
}
.firstindexMenuWrap {
padding: 0 24px;
height: 34px;
line-height: 34px;
}
.MenuCursorpointer {
cursor: pointer;
}
.firstindexMenuWrap .theicon {
position: relative;
top: -1px;
float: left;
font-size: 16px;
display: block;
vertical-align: middle;
margin-right: 6px;
}
.sideMenu_item .firstpri_name {
position: relative;
font-weight: 500;
font-size: 14px;
}
.sideMenu_item span {
display: inline-block;
}
.sideMenu_item .ScedindexMenuWrap {
width: 100%;
}
.ScedindexMenuWrap ul {
display: flex;
flex-wrap: wrap;
width: 100%;
padding-right: 2px;
padding-left: 20px;
}
.ScedindexMenuWrap ul li {
width: 50%;
margin-bottom: 2px;
margin-top: 8px;
}
.sidebarWrap li {
list-style: none;
}
.sidebarWrap li a {
height: 22px;
line-height: 22px;
text-align: center;
display: inline-block;
}
.sedMenuText {
height: 22px;
line-height: 22px;
padding: 0 4px;
text-align: center;
display: inline-block;
font-size: 12px;
color: rgba(255, 255, 255, 0.8);
cursor: pointer;
width: auto;
white-space: nowrap;
position: relative;
border-radius: 2px;
}
.icon-icon_pagination_left1:before {
content: "\e6b2";
}
.active {
background: #4b82ff;
}
.router-link-active{
background: #4b82ff;
}
</style>

View File

@@ -0,0 +1,5 @@
<template> <router-view></router-view></template>
<script></script>
<style lang="less" scoped>
</style>

View File

@@ -0,0 +1,75 @@
<template>
<div v-loading="loading">
<el-drawer title="选择员工" size="240" :visible.sync="drawer" direction="rtl">
<div class="search-box">
<el-input placeholder="输入关键字进行过滤" size="small" v-model="searchModel.keyWord">
<el-button slot="append" icon="el-icon-search" @click="getManager"></el-button>
</el-input>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" @row-click="select">
<el-table-column prop="LoginCode" label="账号" width="120"></el-table-column>
<el-table-column prop="RealName" label="名称" width="120"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="getManager"
:page-size="20"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</el-drawer>
</div>
</template>
<script>
export default {
props: [],
data() {
return {
loading:false,
drawer: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
}
}
},
watch: {
keyWord(val) {
this.$refs.tree.filter(val);
}
},
created() {
this.getManager();
},
methods: {
getManager() {
this.$api.get("manage/v1/Manager/Get",this.searchModel).then(res => {
this.retData=res;
})
},
select(item,node,_this) {
console.log(item)
this.drawer = false;
var item=JSON.parse( JSON.stringify(item))
this.$emit("select", item);
},
close() {
this.drawer = false;
this.$emit("close");
},
show() {
this.drawer = true;
}
}
};
</script>
<style scoped>
.search-box{
padding: 0 20px;
}
</style>

View File

@@ -0,0 +1,123 @@
<template>
<section :class="['grade'+grade,'grade']">
<section class="clr" :class="[{'bn':permissionObj.Children&&permissionObj.Children.length>0},{'show':permissionObj.show}]">
<div class="big" @click="showChild(permissionObj)" v-once>
<i v-if="permissionObj.Children&&permissionObj.Children.length>0"></i>
{{getName(permissionObj.Permissionlabel)}}
</div>
<div v-for="(a,i) in permissionObj.permission" :key="i">
<span :class="[{'choose':a.value==true},{'disabled':a.value== 'disabled' }]" @click="choose(permissionObj,i)"></span>
</div>
</section>
<section v-if="permissionObj.show" >
<permission :permissionObj="item" v-for="(item,index) in permissionObj.Children" :key="index" :parentStr="parentStr+'-'+permissionObj.Permissionlabel"
:grade="grade+1"></permission>
</section>
</section>
</template>
<script>
var that = null;
export default {
name: "permission",
props: {
permissionObj: {
type: Object,
require: true
},
grade: {
type: Number,
default: 0
},
parentStr: {
type: String,
default: ""
}
},
created() {
that = this;
},
methods: {
getName(str) {
return (that.parentStr + "-" + str).replace("-", "");
},
choose(obj, i) {
//更改当前选中目标状态
// console.log(obj, i);
if (typeof obj.permission[i].value == "boolean") {
obj.permission[i].value = !obj.permission[i].value;
that.chooseAll(obj, i, obj.permission[i].value);
that.chooseAll(obj.parent, i);
that.checkedisAll(obj, i, obj.permission[i].value);
}
},
chooseAll(obj, i, bol) {
//匹配当前菜单下子菜单选中状态
//
if (obj && obj.Children) {
if (bol != undefined) {
//匹配子集
obj.Children.forEach(el => {
if (el.permission[i].value != bol) {
if (el.permission[i].value != "disabled") el.permission[i].value = bol;
that.checkedisAll(el, i, bol);
}
that.chooseAll(el, i, bol);
});
} else {
//追溯父级
var bool = true;
obj.Children.forEach(el => {
if (el.permission[i].value == false) bool = true;
});
if (obj.permission[i].value != bool) {
if (obj.permission[i].value != "disabled") obj.permission[i].value = bool;
that.checkedisAll(obj, i, bool);
}
that.chooseAll(obj.parent, i);
}
}
},
showChild(permissionObj) {
permissionObj.show = !permissionObj.show;
},
checkedisAll(obj, i, bol) {
if (i == 4) {
for (var j = 0; j < 4; j++) {
if (obj.permission[j].value != "disabled") obj.permission[j].value = bol;
}
if (obj.permission[i].value) obj.chooseNum = 4;
else obj.chooseNum = 0;
} else {
if (obj.permission[i].value) {
obj.chooseNum++;
} else {
obj.chooseNum--;
}
}
if (obj.permission[4].value != "disabled") {
if (obj.chooseNum == 4) obj.permission[4].value = true;
else obj.permission[4].value = false;
}
}
},
computed: {}
};
</script>
<style scoped>
.grade .big{
width: 50%;
box-sizing: border-box;
}
.grade .grade1 .big{
padding-left: 10px;
}
.grade .grade1 .big i{
left: 30px;
}
.grade .grade2 .big{
padding-left: 20px;
}
</style>

View File

@@ -0,0 +1,68 @@
<template>
<div>
<span v-if="!showTip" @click="showTip=!showTip" class="cursor">{{showText}}</span>
<span v-else @click="showTip=show" class="cursor">{{text}}</span>
</div>
</template>
<script>
export default {
props: {
text: {
type: String,
default: function() {
return "";
}
},
show: {
type: Boolean,
default: function() {
return true;
}
},
length: {
type: Number,
default: function() {
return 10;
}
}
},
data() {
return {
showTip: false,
showText: "",
};
},
watch: {
text: function(newQuestion, oldQuestion) {
console.log(newQuestion);
this.init();
}
},
created() {
},
mounted(){
this.init();
},
methods: {
init() {
if (this.isMobile(this.text)) {
this.showText = this.text.substring(0, 3)+"****"+this.text.substring(7, 4);
}else{
this.showText=this.text
}
},
isMobile(phone){
let reg = /^1[345789]\d{9}$/;
return reg.test(phone)
}
}
};
</script>
<style scoped>
.cursor{
cursor:hand
}
</style>

View File

@@ -0,0 +1,11 @@
<template>
<router-view class="clr"></router-view>
</template>
<script>
</script>
<style>
</style>

View File

@@ -0,0 +1,15 @@
<template>
<router-view class="clr"></router-view>
</template>
<script>
export default {
name: "setting",
props: {
menusList: {
type: Array
}
}
};
</script>

View File

@@ -0,0 +1,150 @@
<template>
<section class="barContain">
<div class="slideBar" :style="getBarWidth"></div>
<div class="slideBlock" :style="getBlockPosition"></div>
<template v-if="showStops">
<span class="stops" :style="getStopsPosition(n)" v-for="n in stops" @click="changeValue(n)"></span>
<span class="stopsValue" :style="getStopsPosition(n)" v-for="n in stops" @click="changeValue(n)">
{{stopsValue(n)}}
</span>
</template>
</section>
</template>
<script>
var that = null;
export default {
name: "sliderBar",
props: {
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
showStops: {
type: Boolean,
default: false
},
unit: {
type: String
},
value: {
default: ''
}
},
created() {
that = this;
},
methods: {
stopsValue(n) {
return (this.min + this.step * (n - 1)) + this.unit
},
changeValue(n) {
var currentValue = this.min + this.step * (n - 1)
this.$emit('input', currentValue)
},
getStopsPosition(n) {
let left = (this.step * n - this.min) / (this.max - this.min) * 100 + "%";
let background, color, fontWeight;
if (this.value >= this.step * (n + 1) - this.min) background = "#4c82ff";
if (this.value == this.step * (n + 1) - this.min) {
color = "#4c82ff"
fontWeight = "bolder"
};
return {
left,
background,
color,
fontWeight
}
}
},
computed: {
stops() {
return parseInt((this.max - this.min) / this.step) + 1
},
getBarWidth() {
var currentValue = this.value || this.min;
return {
width: (currentValue - this.min) / (this.max - this.min) * 100 + "%"
}
},
getBlockPosition() {
var currentValue = this.value || this.min;
return {
left: (currentValue - this.min) / (this.max - this.min) * 100 + "%"
}
}
}
};
</script>
<style lang="less" scoped>
.barContain {
height: 4px;
border-radius: 4px;
background: #d0d6d8;
position: relative;
z-index: 10;
margin: 12px 0 29px;
.slideBar {
height: 4px;
border-radius: 4px;
background: #4c82ff;
width: 0;
transition: width ease 0.2s;
}
.slideBlock {
width: 15px;
height: 15px;
border: 2px solid #fafcfc;
background: #4c82ff;
border-radius: 50%;
position: absolute;
top: 50%;
left: 0;
transform: translate(-50%, -50%);
transition: all ease 0.2s;
transform-origin: center center;
z-index: 12;
cursor: pointer;
&:hover {
transform: translate(-50%, -50%) scale(1.2, 1.2);
}
}
.stops {
width: 6px;
height: 6px;
position: absolute;
border-radius: 50%;
border: 2px solid #fafcfc;
background: #d0d6d8;
top: 50%;
transform: translate(-50%, -50%);
transition: background ease 0.2s;
z-index: 11;
cursor: pointer;
}
.stopsValue {
position: absolute;
background: transparent !important;
top: 4px;
height: 29px;
line-height: 29px;
color: #3d424d;
font-size: 12px;
transform: translateX(-50%);
cursor: pointer;
&:first-of-type {
transform: translateX(0)
}
}
}
</style>

View File

@@ -0,0 +1,80 @@
<template>
<div v-loading="loading">
<el-drawer title="选择会员" size="240" :visible.sync="drawer" direction="rtl">
<div class="search-box">
<el-input placeholder="输入关键字进行过滤" size="small" v-model="searchModel.keyWord">
<el-button slot="append" icon="el-icon-search" @click="getUser"></el-button>
</el-input>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" @row-click="select" height="1000">
<el-table-column prop="LoginCode" label="账号" width="120"></el-table-column>
<el-table-column prop="Phone" label="手机" width="120">
<template slot-scope="scope">
<phoneHide :text="scope.row.Phone" show="false"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="Name" label="名称" width="120"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="getUser"
:page-size="20"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</el-drawer>
</div>
</template>
<script>
export default {
props: [],
data() {
return {
loading:false,
drawer: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
}
}
},
watch: {
keyWord(val) {
this.$refs.tree.filter(val);
}
},
created() {
this.getUser();
},
methods: {
getUser() {
this.$api.get("baseinfo/v1/user/Search",this.searchModel).then(res => {
this.retData=res;
})
},
select(item,node,_this) {
console.log(item)
this.drawer = false;
var item=JSON.parse( JSON.stringify(item))
this.$emit("select", item);
},
close() {
this.drawer = false;
this.$emit("close");
},
show() {
this.drawer = true;
}
}
};
</script>
<style scoped>
.search-box{
padding: 0 20px;
}
</style>

View File

@@ -0,0 +1,48 @@
<template>
<div id="app">
</div>
</template>
<script>
let that;
export default {
name: "home",
components: {
},
data() {
return {
// handelshow: false,
activeName: "",
selsecondindex: "",
menudata: [],
Navigation: {
secList: [],
show: false,
firsturl: "/",
loadMain: false
},
showGuide: false
};
},
computed: {
version: function() {
return this.$store.state.version;
}
},
created() {
},
methods: {
}
};
</script>
<style lang="less" scoped>
#app {
width: 100%;
height: 100%;
min-width: 1400px;
}
</style>

View File

@@ -0,0 +1,48 @@
<template>
<div id="app">
</div>
</template>
<script>
let that;
export default {
name: "home",
components: {
},
data() {
return {
// handelshow: false,
activeName: "",
selsecondindex: "",
menudata: [],
Navigation: {
secList: [],
show: false,
firsturl: "/",
loadMain: false
},
showGuide: false
};
},
computed: {
version: function() {
return this.$store.state.version;
}
},
created() {
this.$router.push("/order/statistics")
},
methods: {
}
};
</script>
<style lang="less" scoped>
#app {
width: 100%;
height: 100%;
min-width: 1400px;
}
</style>

View File

@@ -0,0 +1,46 @@
<template>
<el-carousel :interval="5000" arrow="always" height="700px">
<el-carousel-item v-for="item in 3" :key="item"></el-carousel-item>
</el-carousel>
</template>
<style scoped>
.el-carousel__item {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.el-carousel__item h3 {
color: #475669;
font-size: 18px;
opacity: 0.75;
line-height: 650px;
margin: 0;
}
.el-carousel__item:nth-child(2n) {
background-image: url("/static/img/login/banner1.png");
}
.el-carousel__item:nth-child(2n + 1) {
background-image: url("/static/img/login/banner1.png");
}
.el-carousel__item:nth-child(3n) {
background-image: url("/static/img/login/banner1.png");
}
@media screen and (min-width: 1280px) and (max-width:1812px) {
.el-carousel__item:nth-child(2n) {
background-image: url("/static/img/login/banner1.png");
}
.el-carousel__item:nth-child(2n + 1) {
background-image: url("/static/img/login/banner1.png");
}
.el-carousel__item:nth-child(3n) {
background-image: url("/static/img/login/banner1.png");
}
}
</style>

View File

@@ -0,0 +1,6 @@
<template>
<footer style="padding:50px;color:#8A9199;text-align:center;font-size:12px;">
<h2 style="font-size:18px;margin-bottom:.4em;font-weight:400;">让物业更智慧 让生活更便利</h2>
<p style=""> Copyright©2017-2019 &nbsp;楼小羽&nbsp;All&nbsp;Rights&nbsp;Reserved&nbsp;豫ICP备17018593号&nbsp;|&nbsp;客服电话:400&nbsp;871&nbsp;6696</p>
</footer>
</template>

View File

@@ -0,0 +1,29 @@
<template>
<div class="title_nav">
<div class="logo_pic">
<a style="display:inline-block;" href="#">
<img src="/static/logo.png">
<!-- src="/static/img/login/denglulogo1.png"> -->
</a>
</div>
</div>
</template>
<style scoped>
.title_nav {
height: 74px;
width: 100%;
background: #ffffff;
}
.logo_pic {
width: 140px;
height: 70px;
margin: -10px 0 0 56px;
}
.logo_pic img {
margin-top: 16px;
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,162 @@
<template>
<section class="login_box">
<h1 style="margin-bottom:30px;font-size:33px;font-weight:normal">登录</h1>
<el-form v-show="loginByNormal" ref="form" :model="data" :rules="rules" @submit.native="submit">
<el-form-item prop="Logincode">
<el-input style="width:310px;" type="text" v-model="data.Logincode" name="Logincode" placeholder="请输入账号"
:maxlength="11">
</el-input>
</el-form-item>
<!--密码-->
<el-form-item prop="Password">
<el-input style="width:310px;" type="password" v-model="data.Password" name="Password" placeholder="请输入密码">
</el-input>
</el-form-item>
<!--图片验证码-->
<el-form-item prop="Code">
<el-input style="width:310px;" type="text" v-model="data.Code" placeholder="请输入验证码">
<img slot="append" :src="vaildimg" @click="getvaild" style="height:34px;">
</el-input>
</el-form-item>
<el-form-item>
<el-button native-type="submit" style="display:block;width:100%;padding:12px 0;background:#409eff" :loading="disabled"
type="primary">登录
</el-button>
</el-form-item>
</el-form>
</section>
</template>
<script>
export default {
components: {
},
data: function() {
return {
loginByNormal: true,
disabled: false,
vaildimg: '',
data: {
Logincode: "",
Password: "",
Code: "",
CodeKey: "",
Appcpde: ""
},
rules: {
Logincode: [this.$vaild.required("账号")],
Password: [this.$vaild.required("密码")],
Code: [this.$vaild.required("验证码")]
},
menus:[]
}
},
created: function() {
this.getvaild();
},
beforeDestroy: function() {
clearTimeout(this.timerId);
},
methods: {
getMenus() {
this.$api
.get("manage/v1/ManagerToPermission/GetPermissions")
.then(res => {
var menus = res.Data;
this.$local.setMenus(menus);
this.$store.commit('setMnus', menus);
var defulat=this.getDefaultMenu(menus);
this.$router.replace(defulat);
});
},
getDefaultMenu(menus){
if(menus.length==0)return "/login"
var sumMenus;
for(var i=0;i<menus.length;i++){
sumMenus=menus[i].Children;
if(sumMenus) break;
}
if(sumMenus.length==0) return "/login";
return sumMenus[0].Permissionurl;
},
getvaild() {
this.$api.get('baseinfo/v1/manager/GetValidateCode').then(res=>{
var img = "data:image/jpg;base64," + res.Data.img;
this.vaildimg = img;
this.data.CodeKey = res.Data.key;
clearTimeout(this.timerId);
this.timerId = setTimeout(() => {
this.getvaild();
}, 10 * 60 * 1000)
})
},
submit: function(e) {
e.preventDefault();
this.$refs.form.validate(pass => {
if (!pass) return;
this.login();
})
},
loginSuccess: function(data) {
this.userInfo = data;
window.localStorage.clear(); //防止有未清理的缓存
this.$local.setUserCache(data)
this.$store.commit('updateUserInfo', data);
window.localStorage.setItem("loginType", "property");
this.getMenus();
// this.$router.replace('/user/index');
},
isNewUser(id) {
this.$api.get({
url: 'Manager/Account',
params: {
params: {
ID: id
}
},
success: (res) => {
if (res.Data.LoginCount <= 1) return this.$router.push({
name: "initlogin"
});
this.$router.push('/home');
},
failTip: '登录失败'
})
},
login() {
this.$api.post('baseinfo/v1/manager/Login',this.data).then(
res=>{
if (res.Data){
this.loginSuccess(res.Data);
return;
}
return this.$message({
type: "error",
message: "无此用户信息"
})
},err=>{
this.getvaild();
})
}
}
}
</script>
<style scoped>
.login_box {
position: absolute;
box-sizing: border-box;
height: 450px;
width: 410px;
padding: 50px 50px 30px 50px;
z-index: 999999;
top: 50%;
right: 10%;
transform: translateY(-50%);
background-color: #fff;
border-radius: 4px;
}
</style>

View File

@@ -0,0 +1,83 @@
<template>
<model-loading v-bind="loading" @relaoding="getwximg" style="text-align:center">
<div ref="container" class="layout-tr-center"></div>
<model-note>请使用微信扫描二维码登录</model-note>
</model-loading>
</template>
<script>
export default {
props:{
visible:Boolean
},
data: function () {
return {
id:'',
loading: {
code: -1,
message: ''
}
}
},
watch:{
visible:function(value){
if(value&&this.id) return this.time();
clearTimeout(this.timerId);
},
id:function(value){
if(value&&this.visible) return this.time();
clearTimeout(this.timerId);
}
},
mounted: function () {
this.getwximg();
},
methods: {
getwximg() {
this.$api.get({
url: 'baseinfo/v1/Manager/GetWxLoginQrc',
success: (res) => {
let data = res.Data;
let qrcode = new QRCode(this.$refs.container, {
text: data.image,
width: 225,
height: 225,
correctLevel: QRCode.CorrectLevel.L
});
this.$refs.container.setAttribute('title','二维码');
this.id=data.uuid;
}
}, this);
},
time(){
var that = this;
clearTimeout(this.timerId)
this.$api.get({
url: `baseinfo/v1/Manager/CheckScanLoginState`,
params:{
params:{
uuid:this.id
}
},
success: (res) => {
let data = res.Data;
if (data && data.State == 0) {
this.$emit('success',data)
} else {
this.timerId=setTimeout(() => {
this.time()
}, 3000)
}
},
fail: () => {
this.timerId=setTimeout(() => {
this.time()
}, 3000)
}
})
}
},
beforeDestroy:function(){
clearTimeout(this.timerId)
}
}
</script>

View File

@@ -0,0 +1,26 @@
<template>
<div>
<model-header></model-header>
<div style="position:relative;">
<model-carousel></model-carousel>
<login-by-account></login-by-account>
</div>
<!-- <model-footer></model-footer> -->
</div>
</template>
<script>
//components
import modelHeader from './components/header'
import modelCarousel from './components/carousel'
import modelFooter from './components/footer'
import loginByAccount from './components/login-by-account'
export default {
components: {
modelHeader: modelHeader,
modelCarousel:modelCarousel,
modelFooter:modelFooter,
loginByAccount:loginByAccount
}
}
</script>

View File

@@ -0,0 +1,51 @@
<template>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="用户" width="180"> </el-table-column>
<el-table-column prop="name" label="操作" width="180"> </el-table-column>
<el-table-column prop="address" label="操作内容"> </el-table-column>
<el-table-column prop="address" label="相关信息"> </el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
},
{
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄",
},
{
date: "2016-05-03",
name: "王小虎",
address: "上海市普陀区金沙江路 1516 弄",
},
],
};
},
created() {
this.$store.commit("setCurrentNav", "日志记录");
this.getData();
},
methods: {
getData(){
this.$api.get("baseinfo/v1/user/page", this.searchModel).then(res => {
console.log(res);
});
}
},
};
</script>

View File

@@ -0,0 +1,70 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入课程/订单号/订单名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(150)">
<el-table-column prop="OrderNo" label="订单号" width="180"></el-table-column>
<el-table-column prop="CourseName" label="课程" width="180"></el-table-column>
<el-table-column prop="UserName" label="用户" width="180"></el-table-column>
<el-table-column prop="PaymentAmount" label="金额"></el-table-column>
<el-table-column prop="PayType" label="支付类型">
<template slot-scope="scope">
<el-rate disabled v-model="scope.row.Star"></el-rate>
</template>
</el-table-column>
<el-table-column prop="OrderState" label="订单状态"></el-table-column>
<el-table-column prop="OrderState" label="过期日期"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="10"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: "",
Status: 0,
PayType: 0,
Btime: "",
Etime: ""
},
formatterTime(data) {
return data;
}
};
},
created() {
this.get();
},
methods: {
get() {
this.$api.get("courseOrder/v1/page", this.searchModel).then(res => {
this.retData = res;
});
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,240 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button
size="small"
type="primary"
icon="el-icon-sold-out"
@click="dataExport"
v-if="$local.isRoot()"
>导出</el-button>
<div class="search-box">
<el-cascader
placeholder="选择产品/套餐"
size="small"
v-model="searchModel.pModel"
:options="options"
:props="{ checkStrictly: true}"
clearable
></el-cascader>
<!-- <el-select v-model="searchModel.ProductId" placeholder="选择产品" clearable size="small">
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select> -->
<el-select
v-model="searchModel.OrderTypes"
multiple
collapse-tags
clearable
size="small"
placeholder="选择类型"
>
<el-option v-for="item in types" :key="item.text" :label="item.text" :value="item.value"></el-option>
</el-select>
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-input
v-model="searchModel.keyWord"
placeholder="请输入订单号、订单名称、用户名"
clearable
size="small"
>
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="CreateTime" label="创建日期" width="180"></el-table-column>
<el-table-column prop="UpdateTime" label="支付日期" width="180"></el-table-column>
<el-table-column prop="OrderNo" label="订单号" width="215"></el-table-column>
<el-table-column prop="OrderType" label="类型" :formatter="typeFormat"></el-table-column>
<el-table-column prop="UserName" label="用户" width="120">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserName"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="DayPrice" label="单价"></el-table-column>
<el-table-column prop="ConnectCount" label="连接数">
<template slot-scope="scope">{{scope.row.ConnectCount*scope.row.AccountCount}}</template>
</el-table-column>
<el-table-column prop="Accounts" label="账号">
<template slot-scope="scope">
<cutTip :text="scope.row.Accounts"></cutTip>
</template>
</el-table-column>
<el-table-column prop="OrderAmount" label="订单金额"></el-table-column>
<el-table-column prop="CouponAmount" label="优惠金额"></el-table-column>
<el-table-column prop="AccountPayAmount" label="余额支付"></el-table-column>
<el-table-column prop="OtherPayAmount" label="在线支付"></el-table-column>
<el-table-column prop="PaymentAmount" label="实付"></el-table-column>
<!-- <el-table-column prop="RefundAmount" label="退款"></el-table-column> -->
<el-table-column prop="PayType" label="付款方式" :formatter="payTypeFormat"></el-table-column>
<el-table-column prop="TradeNo" label="支付流水号" width="140">
<template slot-scope="scope">
<cutTip :text="scope.row.TradeNo"></cutTip>
</template>
</el-table-column>
<el-table-column prop="Remark" label="备注" width="140">
<template slot-scope="scope">
<cutTip :text="scope.row.Remark"></cutTip>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
cutTip: () => import("@/components/common/cutTip"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
options: [],
types: [
{ text: "新开", value: "1" },
{ text: "批量新开", value: "2" },
{ text: "续费", value: "3" },
{ text: "批量续费", value: "4" }
],
retData: { TotalCount: 0, Data: [] },
dateRange: [],
products: [],
searchModel: {
PageIndex: 1,
ProductId: null,
PackageId:null,
keyWord: "",
Status: 0,
PayType: 0,
OrderTypes: [],
Btime: "",
Etime: "",
pModel:[],
},
types: [
{ text: "新开", value: 1 },
{ text: "批量新开", value: 2 },
{ text: "续费", value: 3 },
{ text: "批量续费", value: 4 },
{ text: "老账号认证", value: 100 },
{ text: "测试", value: 200 }
],
typeFormat(row, column, cellValue, index) {
switch (cellValue) {
case 1:
return "新开";
case 2:
return "批量新开";
case 3:
return "续费";
case 4:
return "批量续费";
}
return "";
},
payTypeFormat(row, column, cellValue, index) {
switch (cellValue) {
case 10:
return "余额";
case 70:
return "微信";
case 100:
return "支付宝";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav", "订单管理>>订单明细");
this.get();
//this.getProduct();
this.getProductWithPackage();
},
methods: {
search() {
this.searchModel.PageIndex = 1;
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
if(this.searchModel.pModel.length>0)
this.searchModel.ProductId=this.searchModel.pModel[0];
if(this.searchModel.pModel.length>0)
this.searchModel.PackageId=this.searchModel.pModel[1];
this.$api.get("course/v1/order/page", this.searchModel).then(res => {
this.retData = res;
});
},
getProduct() {
this.loading = true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.products = res.Data;
this.loading = false;
});
},
getProductWithPackage() {
this.loading = true;
this.$api.get("course/v1/product/ProductWithPackage").then(res => {
this.options = res.Data;
var options = [];
res.Data.forEach(m => {
var product = {
label: m.Product.Name,
value: m.Product.Id,
children: []
};
m.Packages.forEach(p => {
var pkg = {
label: p.Name,
value: p.Id
}
product.children.push(pkg)
})
options.push(product);
});
this.options=options;
this.loading = false;
});
},
filterHandler(filters) {
console.log(filters);
var values = Object.values(filters);
console.log(...values);
values.forEach(m => {
this.searchModel.OrderTypes.push(...m);
});
this.get();
},
dataExport() {
this.$api.getDownloadFile("/course/v1/order/Export", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,73 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<span>
总营业额 <el-tag type="danger" effect="plain">{{retData.OrderAmount }} </el-tag>
总客户数<el-tag type="danger" effect="plain">{{retData.UserTotal }} </el-tag>
</span>
<div class="search-box">
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-button slot="append" icon="el-icon-search" @click="search" size="small">搜索</el-button>
</div>
</div>
<el-table :data="retData.List" border size="medium" :height="$getHeight(100)">
<el-table-column prop="Name" label="客户经理" width="180"></el-table-column>
<el-table-column prop="Amount" label="营业额" width="180"></el-table-column>
<el-table-column prop="UserCount" label="客户总数" ></el-table-column>
<el-table-column prop="NewUserCount" label="新增客户"></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
},
data() {
return {
loading: false,
options: [],
retData: { OrderAmount: 0,UserTotal:0, List: [] },
dateRange: [],
searchModel: {
Btime: "",
Etime: "",
}
};
},
created() {
this.$store.commit("setCurrentNav", "订单管理>>销售统计");
this.get();
},
methods: {
search() {
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}else{
this.searchModel.Btime =null;
this.searchModel.Etime =null;
}
this.$api.get("course/v1/order/UserCountStatistics", this.searchModel).then(res => {
this.retData = res.Data;
});
},
dataExport() {
this.$api.getDownloadFile("/baseinfo/v1/chargeorder/ExportOrder", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,96 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport">导出</el-button>
<div class="search-box">
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
@change=search
></el-date-picker>
<el-select v-model="searchModel.ProductIds" placeholder="选择产品" collapse-tags multiple clearable size="small" @change=search>
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="CreateTime" label="创建日期" width="180"></el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="ConnectCount" label="连接数"></el-table-column>
<el-table-column prop="Accounts" label="账号"></el-table-column>
<el-table-column prop="RefundRestTime" label="剩余时间"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
dateRange:[],
products:[],
searchModel: {
OrderTypes:[],
PageIndex: 1,
keyWord: "",
ProductIds:null,
}
}
},
created() {
this.$store.commit("setCurrentNav","订单管理>>退款订单")
this.get();
this.getProduct();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
this.$api.get("course/v1/order/OpenRefundOrders", this.searchModel).then(res => {
this.retData = res;
});
},
getProduct() {
this.loading = true;
this.$api.get("course/v1/product/OpenPage", this.searchModel).then(res => {
this.products = res.Data;
this.loading = false;
});
},
dataExport(){
this.$api.getDownloadFile("/course/v1/order/OpenExportRefundOrders", this.searchModel);
}
}
};
</script>
<style scoped>
.red{
color: red;
}
</style>

View File

@@ -0,0 +1,73 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入订单号/订单名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" size="medium" :height="$getHeight(150)" row-key="Id" border>
<el-table-column prop="OrderNo" label="订单号" width="180"></el-table-column>
<el-table-column prop="CourseName" label="课程" width="180"></el-table-column>
<el-table-column prop="UserName" label="用户" width="180"></el-table-column>
<el-table-column prop="PaymentAmount" label="金额"></el-table-column>
<el-table-column prop="PayType" label="支付类型">
<template slot-scope="scope">
<el-rate disabled v-model="scope.row.Star"></el-rate>
</template>
</el-table-column>
<el-table-column prop="OrderState" label="订单状态"></el-table-column>
<el-table-column prop="OrderState" label="过期日期"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="10"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: "",
Status: 0,
PayType: 0,
Btime: "",
Etime: ""
},
formatterTime(data) {
return data;
}
};
},
created() {
this.get();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api.get("courseOrder/v1/page", this.searchModel).then(res => {
this.retData = res;
});
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,201 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button>
<div class="search-box">
<el-select v-model="searchModel.ProductId" placeholder="选择产品" clearable size="small">
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select>
<el-select
v-model="searchModel.OrderTypes"
multiple
collapse-tags
clearable
size="small"
placeholder="选择类型"
>
<el-option v-for="item in types" :key="item.text" :label="item.text" :value="item.value"></el-option>
</el-select>
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-input v-model="searchModel.keyWord" placeholder="请输入订单号、订单名称、用户名" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" @filter-change="filterHandler" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="CreateTime" label="创建日期" width="180"></el-table-column>
<el-table-column prop="OrderNo" label="订单号" width="220"></el-table-column>
<!-- <el-table-column prop="OrderType" label="类型" :formatter="typeFormat"></el-table-column> -->
<el-table-column prop="UserName" label="用户" >
<template slot-scope="scope">
<phoneHide :text="scope.row.UserName"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<!-- <el-table-column prop="DayPrice" label="单价"></el-table-column> -->
<el-table-column prop="ConnectCount" label="连接数"></el-table-column>
<el-table-column prop="Accounts" label="账号"></el-table-column>
<el-table-column prop="PaymentAmount" label="实付金额"></el-table-column>
<el-table-column prop="RefundAmount" label="退款金额"></el-table-column>
<el-table-column prop="RefundRestTime" label="剩余时间"></el-table-column>
<el-table-column prop="IsAutoRefund" label="自动退款" :formatter="autoFormat"></el-table-column>
<el-table-column prop="BackAmount" label="返点"></el-table-column>
<el-table-column prop="OrderState" label="退款状态">
<template slot-scope="scope">
<span :class="{red:scope.row.OrderState==30}"> {{refundTypeFormat(scope.row.OrderState)}}</span>
<span v-if="scope.row.OrderState==30" class="handel cursor edit" @click="showRefund(scope.row)">处理</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="退款处理" :visible.sync="refundModel.Show" width="300px">
<el-form :model="refundModel" ref="inputForm" label-width="80px">
<el-form-item prop="Remark" label="备注说明">
<el-input v-model="refundModel.Remark" size="small"></el-input>
</el-form-item>
<el-form-item prop="BackAmount" label="返点">
<el-input v-model="refundModel.BackAmount" size="small" type="number"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputForm')"> </el-button>
<el-button type="primary" @click="doRefund('inputForm')">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
dateRange:[],
searchModel: {
PageIndex: 1,
keyWord: "",
Status: 0,
PayType: 0,
OrderTypes:[],
ProductId:null,
Btime: "",
Etime: ""
},
refundModel:{
Id:0,
BackAmount:0,
Remark:'',
Show:false,
},
types: [
{ text: "新开", value: 1 },
{ text: "批量新开", value: 2 },
{ text: "续费", value: 3 },
{ text: "批量续费", value: 4 },
{ text: "老账号认证", value: 100 },
{ text: "测试", value: 200 }
],
typeFormat(row, column, cellValue, index){
return "退款"
},
autoFormat(row, column, cellValue, index){
return cellValue&&cellValue==1?"是":"否";
},
refundTypeFormat(orderStatus){
switch (orderStatus) {
case 30:
return "未自动退款";
case 40:
return "已人工处理";
case 50:
return "已自动退款";
default:
return "";
}
return "";
},
}
},
created() {
this.$store.commit("setCurrentNav","订单管理>>退款订单")
this.get();
this.getProduct();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
this.$api.get("course/v1/order/RefundOrders", this.searchModel).then(res => {
this.retData = res;
});
},
getProduct() {
this.loading = true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.products = res.Data;
this.loading = false;
});
},
filterHandler(filters) {
console.log(filters)
var values=Object.values(filters);
console.log(...values)
values.forEach(m=>{
this.searchModel.OrderTypes.push(...m)
});
this.get();
},
dataExport(){
this.$api.getDownloadFile("/course/v1/order/ExportRefundOrders", this.searchModel);
},
showRefund(item){
this.refundModel.Show = true;
this.refundModel.Id=item.Id;
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.refundModel.Show = false;
},
doRefund(formName){
this.$api.post("course/v1/order/RefundProcess", this.refundModel).then(res => {
this.get();
this.resetForm(formName)
})
}
}
};
</script>
<style scoped>
.red{
color: red;
}
</style>

View File

@@ -0,0 +1,216 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="showDialog=true">认领</el-button>
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button>
<div class="search-box">
<el-select v-model="searchModel.ProductId" placeholder="选择产品" clearable size="small">
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select>
<el-select
v-model="searchModel.OrderTypes"
multiple
collapse-tags
clearable
size="small"
placeholder="选择类型"
>
<el-option v-for="item in types" :key="item.text" :label="item.text" :value="item.value"></el-option>
</el-select>
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-input v-model="searchModel.keyWord" placeholder="请输入订单号、订单名称、用户名" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="CreateTime" label="创建日期" width="180"></el-table-column>
<el-table-column prop="Channel" label="销售人" width="120"></el-table-column>
<el-table-column prop="OrderNo" label="订单号" width="215"></el-table-column>
<el-table-column prop="OrderType" label="类型" :formatter="typeFormat"></el-table-column>
<el-table-column prop="UserName" label="用户" width="120">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserName"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="DayPrice" label="单价"></el-table-column>
<el-table-column prop="ConnectCount" label="连接数">
<template slot-scope="scope">
{{scope.row.ConnectCount*scope.row.AccountCount}}
</template>
</el-table-column>
<el-table-column prop="Accounts" label="账号">
<template slot-scope="scope">
<cutTip :text="scope.row.Accounts"></cutTip>
</template>
</el-table-column>
<el-table-column prop="OrderAmount" label="订单金额"></el-table-column>
<el-table-column prop="CouponAmount" label="优惠金额"></el-table-column>
<el-table-column prop="AccountPayAmount" label="余额支付"></el-table-column>
<el-table-column prop="OtherPayAmount" label="在线支付"></el-table-column>
<el-table-column prop="PaymentAmount" label="实付"></el-table-column>
<!-- <el-table-column prop="RefundAmount" label="退款"></el-table-column> -->
<el-table-column prop="PayType" label="付款方式" :formatter="payTypeFormat"></el-table-column>
<el-table-column prop="TradeNo" label="支付流水号" width="140">
<template slot-scope="scope">
<cutTip :text="scope.row.TradeNo"></cutTip>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="认领订单" :visible.sync="showDialog" width="300px">
<el-form :model="takeModel" ref="inputForm" label-width="80px">
<el-form-item prop="phone" label="手机号">
<el-input v-model="takeModel.phone" size="small"></el-input>
</el-form-item>
<el-form-item prop="amount" label="订单金额">
<el-input v-model="takeModel.amount" size="small" type="number"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputForm')"> </el-button>
<el-button type="primary" @click="take()">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
cutTip:()=>import("@/components/common/cutTip"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
showDialog:false,
types:[
{text: '新开', value: '1'},
{text: '批量新开', value: '2'},
{text: '续费', value: '3'},
{text: '批量续费', value: '4'}],
retData: { TotalCount: 0, Data: [] },
dateRange:[],
products:[],
searchModel: {
PageIndex: 1,
ProductId:null,
keyWord: "",
Status: 0,
PayType: 0,
OrderTypes:[],
Btime: "",
Etime: ""
},
takeModel:{
phone:'',
amount:''
},
types: [
{ text: "新开", value: 1 },
{ text: "批量新开", value: 2 },
{ text: "续费", value: 3 },
{ text: "批量续费", value: 4 },
{ text: "老账号认证", value: 100 },
{ text: "测试", value: 200 }
],
typeFormat(row, column, cellValue, index){
switch (cellValue) {
case 1:
return "新开";
case 2:
return "批量新开";
case 3:
return "续费";
case 4:
return "批量续费";
}
return "";
},
payTypeFormat(row, column, cellValue, index){
switch (cellValue) {
case 10:
return "余额";
case 70:
return "微信";
case 100:
return "支付宝";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav","订单管理>>销售订单")
this.get();
this.getProduct();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
this.$api.get("course/v1/order/SellerOrders", this.searchModel).then(res => {
this.retData = res;
});
},
getProduct() {
this.loading = true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.products = res.Data;
this.loading = false;
});
},
filterHandler(filters) {
console.log(filters)
var values=Object.values(filters);
console.log(...values)
values.forEach(m=>{
this.searchModel.OrderTypes.push(...m)
});
this.get();
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.showDialog = false;
},
take(){
this.$api.get("course/v1/order/TakeOrder", this.takeModel).then(res => {
this.resetForm('inputForm')
this.get();
});
},
dataExport() {
this.$api.getDownloadFile("/course/v1/order/ExportSellerOrders", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,103 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-input v-model="searchModel.keyWord" placeholder="请输入产品名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table
:data="retData"
border
size="medium"
:height="$getHeight(100)"
:span-method="mergeSpan"
show-summary
>
<el-table-column prop="Channel" label="销售员"></el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="NewBuyCount" label="新开个数"></el-table-column>
<el-table-column prop="NewBuyAmount" label="新开金额"></el-table-column>
<el-table-column prop="AgainBuyCount" label="续费个数"></el-table-column>
<el-table-column prop="AgainBuyAmount" label="续费金额"></el-table-column>
<el-table-column prop="SellAmount" label="销售金额"></el-table-column>
<!-- <el-table-column prop="RefundCount" label="退货个数"></el-table-column>
<el-table-column prop="RefundAmount" label="退货金额"></el-table-column> -->
<!-- <el-table-column prop="PaymentAmount" label="换货个数"></el-table-column>
<el-table-column prop="PaymentAmount" label="换货金额"></el-table-column>-->
</el-table>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
retData:[],
searchModel: {
PageIndex: 1,
keyWord: "",
Status: 0,
PayType: 0,
Btime: "",
Etime: ""
},
dateRange:[],
flagMap:{}
};
},
created() {
this.$store.commit("setCurrentNav","销售管理>>销售员统计分析")
this.get();
},
methods: {
get() {
this.flagMap={};
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
this.$api.get("course/v1/order/SellerStatistics", this.searchModel).then(res => {
this.retData = res.Data;
this.retData.forEach(item=>{
var flag=this.flagMap[item.Channel];
if(!flag){
this.flagMap[item.Channel]=true;
var count=this.retData.filter(m=>m.Channel== item.Channel).length;
item.rSpan=count;
item.cSpan=1;
}else{
item.rSpan=0;
item.cSpan=0;
}
})
})
},
mergeSpan({row, column, rowIndex, columnIndex}){
if (columnIndex === 0) {
console.log(`${row.rSpan}-${row.cSpan}`)
return {
rowspan: row.rSpan,
colspan: row.cSpan
}
}
}
}
};
</script>
<style scoped>
.el-table{
overflow:visible !important;
}
</style>

View File

@@ -0,0 +1,102 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-input v-model="searchModel.keyWord" placeholder="请输入产品名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table
:data="retData"
border
size="medium"
:height="$getHeight(150)"
:span-method="mergeSpan"
show-summary
>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="NewBuyCount" label="新开个数"></el-table-column>
<el-table-column prop="NewBuyAmount" label="新开金额"></el-table-column>
<el-table-column prop="AgainBuyCount" label="续费个数"></el-table-column>
<el-table-column prop="AgainBuyAmount" label="续费金额"></el-table-column>
<el-table-column prop="RefundCount" label="退货个数"></el-table-column>
<el-table-column prop="RefundAmount" label="退货金额"></el-table-column>
<!-- <el-table-column prop="PaymentAmount" label="换货个数"></el-table-column>
<el-table-column prop="PaymentAmount" label="换货金额"></el-table-column>-->
</el-table>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
retData:[],
dateRange:[],
searchModel: {
PageIndex: 1,
keyWord: "",
Status: 0,
PayType: 0,
Btime: "",
Etime: ""
},
flagMap:{}
};
},
mounted(){
this.$store.commit("setCurrentNav","销售管理>>统计分析")
this.get();
},
methods: {
get() {
this.flagMap={};
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
this.$api.get("course/v1/order/Statistics", this.searchModel).then(res => {
this.retData = res.Data;
this.retData.forEach(item=>{
var flag=this.flagMap[item.ProductName];
if(!flag){
this.flagMap[item.ProductName]=true;
var count=this.retData.filter(m=>m.ProductName== item.ProductName).length;
item.rSpan=count;
item.cSpan=1;
}else{
item.rSpan=0;
item.cSpan=0;
}
})
})
},
mergeSpan({row, column, rowIndex, columnIndex}){
if (columnIndex === 0) {
console.log(`${row.rSpan}-${row.cSpan}`)
return {
rowspan: row.rSpan,
colspan: row.cSpan
}
}
}
}
};
</script>
<style scoped>
.el-table{
overflow:visible !important;
}
</style>

View File

@@ -0,0 +1,77 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入订单号、用户名" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="Created" label="创建日期" width="180"></el-table-column>
<el-table-column prop="Tid" label="订单号" width="180"></el-table-column>
<el-table-column prop="SellerNick" label="销售人" width="180"></el-table-column>
<el-table-column prop="BuyerNick" label="购买人" width="180"></el-table-column>
<el-table-column prop="Phone" label="购买人手机号">
<template slot-scope="scope">
<phoneHide :text="scope.row.Phone"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="Price" label="单价"></el-table-column>
<el-table-column prop="Num" label="数量"></el-table-column>
<el-table-column prop="TotalFee" label="订单金额"></el-table-column>
<el-table-column prop="Payment" label="实付金额"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: "",
Btime: "",
Etime: ""
},
};
},
created() {
this.$store.commit("setCurrentNav","订单管理>>淘宝订单")
this.get();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api.get("sells/v1/taobao/page", this.searchModel).then(res => {
this.retData = res;
});
},
dataExport(){
this.$api.getDownloadFile("/sells/v1/taobao/Export", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,361 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-edit" @click="batchSelectUser">批量修改归属</el-button>
<el-button size="small" type="primary" icon="el-icon-edit" @click="dels">批量删除</el-button>
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button>
<!-- <el-button size="small" type="primary" icon="el-icon-edit">检测</el-button> -->
<!-- <el-button size="small" type="primary" icon="el-icon-edit">老账号认证</el-button> -->
<div class="search-box">
<el-cascader
placeholder="选择产品/套餐"
size="small"
v-model="searchModel.pModel"
:options="options"
:props="{ checkStrictly: true}"
clearable
></el-cascader>
<!-- <el-select v-model="searchModel.ProductId" placeholder="选择产品" clearable size="small">
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select> -->
<el-select
v-model="searchModel.accountTypes"
multiple
collapse-tags
clearable
size="small"
placeholder="选择类型"
>
<el-option v-for="item in types" :key="item.text" :label="item.text" :value="item.value"></el-option>
</el-select>
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-select v-model="searchModel.ExpirdDay" placeholder="选择过期时间" clearable size="small">
<el-option
v-for="item in expirdtypes"
:key="item.text"
:label="item.text"
:value="item.value"
></el-option>
</el-select>
<el-input v-model="searchModel.keyWord" placeholder="请输入产品/套餐/会员/账号" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table
ref="multipleTable"
row-key="Id"
border
size="medium"
:data="retData.Data"
:height="$getHeight(100)"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="UserCode" label="会员">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserCode"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="AccountType" label="类型" :formatter="typeFormat"></el-table-column>
<el-table-column prop="Account" label="账号"></el-table-column>
<el-table-column prop="Pwd" label="密码"></el-table-column>
<el-table-column prop="ConnectCount" label="连接数"></el-table-column>
<el-table-column prop="StartTime" label="开通时间" width="160px"></el-table-column>
<el-table-column prop="EndTime" label="到期时间" width="160px"></el-table-column>
<el-table-column prop="RestTime" label="剩余时间" width="150px">
<template slot-scope="scope">
<span
v-if="scope.row.Status==1"
:class="{red:scope.row.RestTime=='已过期'}"
>{{scope.row.RestTime}}</span>
<span v-else class="red">已退款</span>
</template>
</el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="selectUser(scope.row)">归属</span>
<span class="handel cursor edit" @click="del(scope.row)">删除</span>
<span class="handel cursor edit" @click="online(scope.row)">查看在线</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<userDrawer ref="userDrawer" @select="onSelect"></userDrawer>
<el-dialog title="查看在线" :visible.sync="showOnlineDialog" width="900px" v-loading="loadingOnline">
<el-table
row-key="Id"
border
size="medium"
:data="onlineClient"
:height="$getHeight(300)"
>
<el-table-column prop="Account" label="账号"></el-table-column>
<el-table-column prop="LoginTime" label="登录时间"></el-table-column>
<el-table-column prop="OnlineTime" label="在线时间"></el-table-column>
<el-table-column prop="ServerIP" label="服务器Ip"></el-table-column>
<el-table-column prop="LoginIP" label="登录ip"></el-table-column>
<el-table-column prop="UpStream" label="上行" ></el-table-column>
<el-table-column prop="DownStream" label="下行"></el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="killout(scope.row)">强制离线</span>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
userDrawer: () => import("@/components/common/userDrawer"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
options: [],
showOnlineDialog:false,
loading: false,
loadingOnline:false,
retData: { TotalCount: 0, Data: [] },
products: [],
dateRange: [],
searchModel: {
ExpirdDay: -1,
UserId: 0,
PageIndex: 1,
keyWord: "",
ProductId: null,
PackageId:null,
accountTypes: null,
pModel:[],
Btime: "",
Etime: "",
},
onlineClient:[],
currentAccount: {},
account: [],
types: [
{ text: "新开", value: 1 },
{ text: "批量新开", value: 2 },
{ text: "续费", value: 3 },
{ text: "批量续费", value: 4 },
{ text: "老账号认证", value: 100 },
{ text: "测试", value: 200 }
],
expirdtypes: [
{ text: "全部", value: -1 },
{ text: "已过期", value: 0 },
{ text: "1天过期", value: 1 },
{ text: "3天过期", value: 3 },
{ text: "1周过期", value: 7 }
],
typeFormat(row, column, cellValue, index) {
switch (cellValue) {
case 1:
return "新开";
case 2:
return "批量新开";
case 3:
return "续费";
case 4:
return "批量续费";
case 100:
return "老账号认证";
case 200:
return "测试";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav", "会员管理>>账号管理");
var userId = this.$route.query.userId;
if (userId) this.searchModel.UserId = userId;
this.get();
this.getProductWithPackage();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
if(this.searchModel.pModel.length>0)
this.searchModel.ProductId=this.searchModel.pModel[0];
if(this.searchModel.pModel.length>0)
this.searchModel.PackageId=this.searchModel.pModel[1];
this.$api
.get("course/v1/productaccount/page", this.searchModel)
.then(res => {
this.retData = res;
});
},
getProduct() {
this.loading = true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.products = res.Data;
this.loading = false;
});
},
getProductWithPackage() {
this.loading = true;
this.$api.get("course/v1/product/ProductWithPackage").then(res => {
this.options = res.Data;
var options = [];
res.Data.forEach(m => {
var product = {
label: m.Product.Name,
value: m.Product.Id,
children: []
};
m.Packages.forEach(p => {
var pkg = {
label: p.Name,
value: p.Id
}
product.children.push(pkg)
})
options.push(product);
});
this.options=options;
this.loading = false;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api
.post("course/v1/productaccount/Delete?id=" + item.Id)
.then(res => {
that.get();
});
});
},
dels() {
var that = this;
if( this.account.length==0){
$this.$warn('请选账号')
return
}
var ids= this.account.map(m => m.Id)
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api
.post("course/v1/productaccount/Deletes",ids)
.then(res => {
that.searchModel.PageIndex=1;
that.get();
});
});
},
goAdd() {
this.$router.push({ name: "addPackage", query: { optype: 1 } });
},
goEdit(item) {
this.$router.push({
name: "addPackage",
query: { id: item.Id, optype: 2 }
});
},
batchSelectUser() {
if (this.account.length == 0) {
this.$warn("请选择账号");
return;
}
this.$refs["userDrawer"].show();
},
selectUser(row) {
this.$refs.multipleTable.clearSelection();
this.$refs.multipleTable.toggleRowSelection(row);
this.$refs["userDrawer"].show();
},
handleSelectionChange(val) {
this.account = val;
},
onSelect(item) {
var data = {
AccountIds: this.account.map(m => m.Id),
UserId: item.Id
};
this.$confirm("确定要迁移吗?").then(_ => {
this.$api.post("course/v1/productaccount/BindUser", data).then(res => {
this.get();
});
});
},
online(item){
this.showOnlineDialog=true;
this.loadingOnline=true;
var params={
productId:item.ProductId,
account:item.Account,
}
this.onlineClient=[];
this.$api
.get("course/v1/productaccount/OnLine", params)
.then(res => {
this.loadingOnline=false,
this.onlineClient = res.Data;
this.onlineClient.forEach(m=>m.info=item)
})
},
killout(item){
var params={
productId:item.info.ProductId,
id:item.Id,
}
this.$api
.get("course/v1/productaccount/KillOut",params)
.then(res => {
if(res.Data){
this.$info("离线成功");
}
this.online(item.info)
})
},
dataExport(){
this.$api.getDownloadFile("/course/v1/productaccount/Export");
}
}
};
</script>
<style scoped>
.red {
color: red;
}
</style>

View File

@@ -0,0 +1,274 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-edit" @click="batchSelectUser">批量修改归属</el-button>
<!-- <el-button size="small" type="primary" icon="el-icon-edit">检测</el-button> -->
<!-- <el-button size="small" type="primary" icon="el-icon-edit">老账号认证</el-button> -->
<div class="search-box">
<!-- <el-select v-model="searchModel.ProductId" placeholder="选择产品" clearable size="small">
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select>
<el-select
v-model="searchModel.accountTypes"
multiple
collapse-tags
clearable
size="small"
placeholder="选择类型"
>
<el-option v-for="item in types" :key="item.text" :label="item.text" :value="item.value"></el-option>
</el-select>
<el-select v-model="searchModel.ExpirdDay" placeholder="选择过期时间" clearable size="small">
<el-option
v-for="item in expirdtypes"
:key="item.text"
:label="item.text"
:value="item.value"
></el-option>
</el-select> -->
<el-input v-model="searchModel.keyWord" placeholder="会员/账号" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table
ref="multipleTable"
row-key="Id"
border
size="medium"
:data="retData.Data"
:height="$getHeight(100)"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="UserCode" label="会员">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserCode"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="AccountType" label="类型" :filters="types" :formatter="typeFormat"></el-table-column>
<el-table-column prop="Account" label="账号"></el-table-column>
<el-table-column prop="Pwd" label="密码"></el-table-column>
<el-table-column prop="ConnectCount" label="连接数"></el-table-column>
<el-table-column prop="StartTime" label="开通时间" width="160px"></el-table-column>
<el-table-column prop="EndTime" label="到期时间" width="160px"></el-table-column>
<el-table-column prop="RestTime" label="剩余时间" width="150px">
<template slot-scope="scope">
<span
v-if="scope.row.Status==1"
:class="{red:scope.row.RestTime=='已过期'}"
>{{scope.row.RestTime}}</span>
<span v-else class="red">已退款</span>
</template>
</el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="selectUser(scope.row)">归属</span>
<span class="handel cursor edit" @click="del(scope.row)">删除</span>
<span class="handel cursor edit" @click="online(scope.row)">查看在线</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<userDrawer ref="userDrawer" @select="onSelect"></userDrawer>
<el-dialog title="查看在线" :visible.sync="showOnlineDialog" width="900px" v-loading="loadingOnline">
<el-table
row-key="Id"
border
size="medium"
:data="onlineClient"
:height="$getHeight(300)"
>
<el-table-column prop="Account" label="账号"></el-table-column>
<el-table-column prop="LoginTime" label="登录时间"></el-table-column>
<el-table-column prop="OnlineTime" label="在线时间"></el-table-column>
<el-table-column prop="ServerIP" label="服务器Ip"></el-table-column>
<el-table-column prop="LoginIP" label="登录ip"></el-table-column>
<el-table-column prop="UpStream" label="上行" ></el-table-column>
<el-table-column prop="DownStream" label="下行"></el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="killout(scope.row)">强制离线</span>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
userDrawer: () => import("@/components/common/userDrawer"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
showOnlineDialog:false,
loading: false,
loadingOnline:false,
retData: { TotalCount: 0, Data: [] },
products: [],
searchModel: {
ExpirdDay: -1,
UserId: 0,
PageIndex: 1,
keyWord: "",
ProductId: null,
accountTypes: null
},
onlineClient:[],
currentAccount: {},
account: [],
types: [
{ text: "新开", value: 1 },
{ text: "批量新开", value: 2 },
{ text: "续费", value: 3 },
{ text: "批量续费", value: 4 },
{ text: "老账号认证", value: 100 },
{ text: "测试", value: 200 }
],
expirdtypes: [
{ text: "全部", value: -1 },
{ text: "已过期", value: 0 },
{ text: "1天过期", value: 1 },
{ text: "3天过期", value: 3 },
{ text: "1周过期", value: 7 }
],
typeFormat(row, column, cellValue, index) {
switch (cellValue) {
case 1:
return "新开";
case 2:
return "批量新开";
case 3:
return "续费";
case 4:
return "批量续费";
case 100:
return "老账号认证";
case 200:
return "测试";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav", "会员管理>>账号查询");
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api
.get("course/v1/productaccount/Search", this.searchModel)
.then(res => {
this.retData = res;
});
},
getProduct() {
this.loading = true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.products = res.Data;
this.loading = false;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api
.post("course/v1/productaccount/Delete?id=" + item.Id)
.then(res => {
that.get();
});
});
},
goAdd() {
this.$router.push({ name: "addPackage", query: { optype: 1 } });
},
goEdit(item) {
this.$router.push({
name: "addPackage",
query: { id: item.Id, optype: 2 }
});
},
batchSelectUser() {
if (this.account.length == 0) {
this.$warn("请选择账号");
return;
}
this.$refs["userDrawer"].show();
},
selectUser(row) {
this.$refs.multipleTable.clearSelection();
this.$refs.multipleTable.toggleRowSelection(row);
this.$refs["userDrawer"].show();
},
handleSelectionChange(val) {
this.account = val;
},
onSelect(item) {
var data = {
AccountIds: this.account.map(m => m.Id),
UserId: item.Id
};
this.$confirm("确定要迁移吗?").then(_ => {
this.$api.post("course/v1/productaccount/BindUser", data).then(res => {
this.get();
});
});
},
online(item){
this.showOnlineDialog=true;
this.loadingOnline=true;
var params={
productId:item.ProductId,
account:item.Account,
}
this.onlineClient=[];
this.$api
.get("course/v1/productaccount/OnLine", params)
.then(res => {
this.loadingOnline=false,
this.onlineClient = res.Data;
this.onlineClient.forEach(m=>m.info=item)
})
},
killout(item){
var params={
productId:item.info.ProductId,
id:item.Id,
}
this.$api
.get("course/v1/productaccount/KillOut",params)
.then(res => {
this.online(item.info)
})
}
}
};
</script>
<style scoped>
.red {
color: red;
}
</style>

View File

@@ -0,0 +1,187 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入产品名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)" :row-style="rowStyle">
<el-table-column prop="Name" label="产品名称" width="180"></el-table-column>
<el-table-column prop="Account" label="账号"></el-table-column>
<el-table-column label="密码">
<template>
<span>*********</span>
<!-- <span @click="goLook(scope.row)">
<i class="el-icon-view"></i>
</span> -->
</template>
</el-table-column>
<el-table-column prop="BaseUrl" label="接口地址"></el-table-column>
<el-table-column prop="Status" label="状态">
<template slot-scope="scope">
<span :class="{statusRed:scope.row.Status==0}">{{statusFormat(scope.row.Status)}}</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span class="handel cursor edit" @click="goLogin(scope.row)">检测</span>
<span class="handel cursor edit" @click="goEdit(scope.row)">编辑</span>
<!-- <span class="handel cursor del" @click="del(scope.row)">删除</span> -->
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="产品配置" :visible.sync="showDialog" width="400px">
<el-form :model="currentProduct" :rules="rules" ref="inputProductForm" label-width="80px">
<el-form-item prop="Account" label="账户">
<el-input v-model="currentProduct.Account" size="small"></el-input>
</el-form-item>
<el-form-item prop="Pwd" label="密码">
<el-input v-model="currentProduct.Pwd" show-password size="small"></el-input>
</el-form-item>
<el-form-item prop="LoginUrl" label="登录地址">
<el-input v-model="currentProduct.BaseUrl" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputProductForm')"> </el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
<el-dialog title="登录" :visible.sync="showLoginDialog" width="400px">
<el-form :model="loginModel" :rules="loginRules" ref="inputLoginForm" label-width="80px">
<el-form-item prop="Code" label="验证码" v-if="loginModel.LoginCodeUrl!=''">
<el-input v-model="loginModel.Code" size="small">
<img :src="loginModel.LoginCodeUrl" alt="" @click="getCode" slot="append"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputLoginForm')"> </el-button>
<el-button type="primary" @click="Login">检测</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
showDialog:false,
showLoginDialog:false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
loginModel:{
ProductId:0,
Code:"",
LoginCodeUrl:'',
Key:""
},
currentProduct: {
Id: 0,
Name: "",
Profile: "",
Image: ""
},
rules: {
Account: [this.$vaild.required("账户")],
Pwd: [this.$vaild.required("密码")],
LoginUrl: [this.$vaild.required("登录地址")]
},
loginRules:{
Code: [this.$vaild.required("验证码")],
}
};
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>产品配置");
this.get();
setInterval(this.get, 30*1000);
},
methods: {
get() {
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.retData = res;
});
},
goEdit(item) {
this.currentProduct = item;
this.showDialog = true;
},
goLogin(item) {
this.currentProduct=item;
// this.loginModel.LoginCodeUrl=item.LoginCodeUrl+"&="+(new Date()).getTime();
this.loginModel.ProductId= item.Id;
this.getCode()
this.showLoginDialog = true;
},
getCode(){
this.$api
.get("course/v1/agent/GetCode?productId="+this.currentProduct.Id, )
.then(res => {
if(res.Code==10000){
this.loginModel.LoginCodeUrl=res.Data.CodeImage;
this.loginModel.Key=res.Data.Key;
}else{
this.$error('验证码获取失败')
}
});
},
save() {
this.$api
.post("course/v1/product/putConfig", this.currentProduct)
.then(res => {
this.resetForm('inputProductForm');
this.get();
});
},
Login() {
this.$api
.post("course/v1/agent/Login",this.loginModel)
.then(res => {
this.resetForm('inputLoginForm');
this.get();
});
},
statusFormat(value) {
console.log(value)
if(value==1)return "在线";
return "离线"
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.showDialog = false;
this.showLoginDialog = false;
},
rowStyle({ row, rowIndex}) {
if (row.Status === 0) {
return 'color:red'
} else {
return ''
}
}
}
};
</script>
<style scoped>
.statusRed{
color: red;
}
</style>

View File

@@ -0,0 +1,163 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入产品名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="Image" label="产品图片" width="80px">
<template slot-scope="scope">
<img :src="scope.row.Image" style="width:32px;height:32px" alt />
</template>
</el-table-column>
<el-table-column prop="Name" label="产品名称" width="180"></el-table-column>
<el-table-column prop="RefundDayPrice" label="退款单价" width="180"></el-table-column>
<el-table-column prop="DayLimitPrice" label="最低价格" width="180"></el-table-column>
<el-table-column prop="Status" label="上下架" width="180">
<template slot-scope="scope">
<el-switch
v-model="scope.row.OnLine"
:active-value="1"
:inactive-value="0"
active-color="#13ce66"
inactive-color="#dcdfe6"
@change="changeLineStatus(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column prop="Profile" label="产品说明"></el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<span class="handel cursor edit" @click="goEdit(scope.row)">编辑</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="产品维护" :visible.sync="showDialog" width="400px">
<el-form :model="currentProduct" :rules="rules" ref="inputProductForm" label-width="80px">
<el-form-item prop="Name" label="产品名称">
<el-input v-model="currentProduct.Name" size="small"></el-input>
</el-form-item>
<el-form-item prop="RefundDayPrice" label="退款单价">
<el-input v-model="currentProduct.RefundDayPrice" size="small"></el-input>
</el-form-item>
<el-form-item prop="DayLimitPrice" label="最低价格">
<el-input v-model="currentProduct.DayLimitPrice" size="small"></el-input>
</el-form-item>
<el-form-item prop="Profile" label="产品说明">
<el-input type="textarea" :rows="3" v-model="currentProduct.Profile" size="small" ></el-input>
</el-form-item>
<!-- <el-form-item prop="Image" label="产品图标">
<span class="uploadimg_box">
<img
:src="currentProduct.Image"
v-if="currentProduct.Image!=''"
class="uploadimg"
@click="upload"
/>
<span class="ubloadbtn" v-else>
<img src="/static/img/common/imgadd.png" @click="upload" />
</span>
<p class="imgTip" @click="upload">点击更换</p>
</span>
</el-form-item> -->
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm"> </el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
showDialog:false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
currentProduct: {
Id:0,
Name:"",
Profile:"",
Image:""
},
rules:{
Name:[this.$vaild.required("产品名称")]
}
};
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>产品列表");
this.get();
},
methods: {
get() {
this.loading=true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.retData = res;
this.loading=false;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api.post("course/v1/product/Delete?id=" + item.Id).then(res => {
that.get();
});
});
},
goEdit(item) {
this.currentProduct=item;
this.showDialog=true;
},
save() {
this.$api.post("course/v1/product/put", this.currentProduct).then(res => {
this.resetForm()
this.get();
});
},
changeLineStatus(item) {
this.$api
.post("course/v1/product/SetProductLine?id=" + item.Id)
.then(res => {
item.Status = res.Data;
});
},
resetForm() {
this.$refs["inputProductForm"].resetFields();
this.showDialog = false;
},
upload(callback) {
this.$api.upload("oss/v1/ImageCloud/upload").then(res => {
this.courseModel.Cover = ret.Url;
});
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,153 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<!-- <el-button size="small" type="primary" icon="el-icon-plus" @click="goAdd">新建套餐</el-button> -->
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入套餐名称/标题" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<div>
<el-tabs tab-position="left" :style="$getStyleHeight(100)">
<el-tab-pane :label="item.Product.Name" v-for="(item,index) in product" :key="index">
<el-table
:data="item.Packages"
row-key="Id"
border
size="medium"
:height="$getHeight(100)"
>
<el-table-column prop="Name" label="套餐名称"></el-table-column>
<el-table-column prop="Title" label="套餐标题"></el-table-column>
<el-table-column prop="Price" label="价格"></el-table-column>
<el-table-column prop="LinePrice" label="划线价"></el-table-column>
<el-table-column prop="DayPrice" label="价格/天"></el-table-column>
<el-table-column prop="MinPrice" label="最低价"></el-table-column>
<el-table-column prop="Profile" label="期限说明"></el-table-column>
<el-table-column prop="Status" label="上架状态" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.Status"
:active-value="1"
:inactive-value="0"
active-color="#13ce66"
inactive-color="#dcdfe6"
@change="changeLineStatus(scope.row)"
></el-switch>
</template>
</el-table-column>
<!-- <el-table-column label="包含基本套餐">
<template slot-scope="scope">
<span class="handel cursor edit" @click="bindCourse(scope.row)">套餐</span>
</template>
</el-table-column>-->
<el-table-column label="操作">
<template slot-scope="scope">
<span class="handel cursor edit" @click="goEdit(scope.row)">编辑</span>
<!-- <span class="handel cursor del" @click="del(scope.row)">删除</span> -->
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
<el-dialog title="套餐维护" :visible.sync="showDialog" width="400px">
<el-form
:model="currentPackage"
:rules="rules"
ref="inputPackageForm"
label-width="80px"
>
<el-form-item prop="Name" label="套餐名称">
<el-input v-model="currentPackage.Name" size="small"></el-input>
</el-form-item>
<el-form-item prop="Price" label="套餐价格">
<el-input v-model="currentPackage.Price" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="LinePrice" label="划线价格">
<el-input v-model="currentPackage.LinePrice" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="MinPrice" label="最低价格">
<el-input v-model="currentPackage.MinPrice" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="Profile" label="说明">
<el-input v-model="currentPackage.Profile" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm"> </el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
showDialog:false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
product:[],
currentPackage: {},
rules:{}
};
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>套餐管理");
this.get();
},
methods: {
get() {
this.$api.get("course/v1/product/ProductWithPackage").then(res => {
this.product = res.Data;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api.post("course/v1/package/Delete?id=" + item.Id).then(res => {
this.get();
});
});
},
goEdit(item) {
this.currentPackage =clone(item);
this.showDialog = true;
},
save() {
this.$api
.post("course/v1/product/PutPackage", this.currentPackage)
.then(res => {
this.resetForm();
this.get();
// this.currentPackage = res.Data;
});
},
changeLineStatus(item) {
this.$api
.post("course/v1/product/SetPackageLine?id=" + item.Id)
.then(res => {
item.Status = res.Data;
});
},
resetForm() {
this.$refs["inputPackageForm"].resetFields();
this.showDialog = false;
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,139 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<!-- <el-button size="small" type="primary" icon="el-icon-plus" @click="goAdd">新建套餐</el-button> -->
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入套餐名称/标题" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<div>
<el-tabs tab-position="left" :style="$getStyleHeight(100)">
<el-tab-pane
:label="item.Product.Name"
v-for="(item,index) in productDiscount"
:key="index"
>
<el-table
:data="item.PackageDiscounts"
row-key="Id"
border
size="medium"
:height="$getHeight(100)"
>
<el-table-column prop="Package.Name" label="套餐名称"></el-table-column>
<el-table-column prop="Package.Price" label="原价格"></el-table-column>
<el-table-column prop="PriceDiscount.BuyPriceDiscount" label="购买折扣">
<template slot-scope="scope">{{scope.row.PriceDiscount.BuyPriceDiscount||'--'}}</template>
</el-table-column>
<el-table-column prop="PriceDiscount.RefundDayPriceDiscount" label="退款折扣">
<template slot-scope="scope">{{scope.row.PriceDiscount.RefundDayPriceDiscount||'--'}}</template>
</el-table-column>
<el-table-column prop="PriceDiscount.Remark" label="说明"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span class="handel cursor edit" @click="goEdit(scope.row)">编辑</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
<el-dialog title="折扣维护" :visible.sync="showDialog" width="400px">
<el-form :model="current" :rules="rules" ref="inputPackageForm" label-width="80px">
<el-form-item prop="Name" label="套餐名称">
<el-input v-model="current.Name" size="small" disabled></el-input>
</el-form-item>
<!-- <el-form-item prop="Price" label="原价格">
<el-input v-model="current.Price" type="number" size="small" disabled></el-input>
</el-form-item> -->
<el-form-item prop="MinPrice" label="购买折扣">
<el-input v-model="current.BuyPriceDiscount" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="RefundDayPriceDiscount" label="退款折扣">
<el-input v-model="current.RefundDayPriceDiscount" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="Remark" label="说明">
<el-input v-model="current.Remark" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm"> </el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
showDialog: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
productDiscount: [],
current: {
Remark: "",
BuyPriceDiscount: 0,
SchemeId: 0,
PackageId: 0,
ProductId: 0,
RefundDayPriceDiscount: 0
},
rules: {}
};
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>产品折扣");
this.current.SchemeId = this.$route.query.id;
this.get();
},
methods: {
get() {
this.$api
.get("course/v1/scheme/GetProductDiscount?id=" + this.current.SchemeId)
.then(res => {
this.productDiscount = res.Data;
});
},
goEdit(item) {
console.log(item);
this.showDialog = true;
this.current.Name = item.Package.Name;
this.current.ProductId = item.Package.ProductId;
this.current.PackageId = item.Package.Id;
this.current.BuyPriceDiscount = item.PriceDiscount.BuyPriceDiscount;
this.current.RefundDayPriceDiscount =
item.PriceDiscount.RefundDayPriceDiscount;
},
save() {
this.$api
.post("course/v1/scheme/PutProductDiscount", this.current)
.then(res => {
this.resetForm();
this.get();
});
},
changeStatus(item) {
this.$api
.post("course/v1/scheme/SetUserPriceStatus?id=" + item.UserPrice.Id)
.then(res => {
item.Status = res.Data;
});
},
resetForm() {
this.$refs["inputPackageForm"].resetFields();
this.showDialog = false;
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,149 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-edit" @click="add">添加</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入方案名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table
ref="multipleTable"
row-key="Id"
border
size="medium"
:data="retData.Data"
:height="$getHeight(100)"
>
<el-table-column prop="Name" label="方案名称"></el-table-column>
<el-table-column prop="Remark" label="方案说明"></el-table-column>
<el-table-column prop="CreateTime" label="创建时间"></el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="edit(scope.row)">编辑</span>
<router-link :to="{name:'pricediscount',query:{id:scope.row.Id}}">
<span class="handel cursor edit">折扣</span>
</router-link>
<span class="handel cursor edit" @click="del(scope.row)">删除</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="方案维护" :visible.sync="showDialog" width="500px">
<el-form :model="schemeModel" :rules="rules" ref="inputForm" label-width="80px">
<el-form-item prop="Name" label="方案名称">
<el-input v-model="schemeModel.Name" size="small"></el-input>
</el-form-item>
<el-form-item prop="Remark" label="方案说明">
<el-input v-model="schemeModel.Remark" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputForm')"> </el-button>
<el-button type="primary" @click="save('inputForm')">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
},
data() {
return {
loading: false,
showDialog:false,
optype:1,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: "",
},
schemeModel: {
Name:'',
Remark:'',
},
types: [
],
rules: {
Name: [this.$vaild.required("方案名称")]
},
}
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>价格方案");
this.get();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api
.get("course/v1/scheme/page", this.searchModel)
.then(res => {
this.retData = res;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api
.post("course/v1/scheme/Delete?id=" + item.Id)
.then(res => {
that.get();
});
});
},
add() {
this.showDialog = true;
this.optype = 1;
},
edit(item) {
this.showDialog = true;
this.optype = 2;
this.schemeModel = clone(item);
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.showDialog = false;
},
save(formName) {
var that=this;
this.$refs[formName].validate(valid => {
if (!valid) return;
if (that.optype == 1) {
that.$api.post("course/v1/scheme/post", that.schemeModel).then(res => {
that.resetForm('inputForm');
that.get();
});
} else {
that.$api.post("course/v1/scheme/put", that.schemeModel).then(res => {
that.resetForm('inputForm');
that.get();
});
}
})
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,217 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-edit" @click="add">添加</el-button>
<!-- <el-button size="small" type="primary" icon="el-icon-upload" @click="importExcel">导入</el-button>
<a href="http://www.ipkd.com/tpl.xlsx"><el-button size="small" type="primary" icon="el-icon-download" @click="importExcel">下载模板</el-button></a> -->
<div class="search-box">
<el-select v-model="searchModel.productId" placeholder="选择产品" clearable size="small">
<el-option v-for="item in products" :key="item.Name" :label="item.Name" :value="item.Id"></el-option>
</el-select>
<el-input v-model="searchModel.keyWord" placeholder="请输入城市或者运营商" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table
ref="multipleTable"
row-key="Id"
border
size="medium"
:data="retData.Data"
:height="$getHeight(100)"
@filter-change="filterHandler"
>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="Province" label="省份"></el-table-column>
<el-table-column prop="City" label="城市"></el-table-column>
<el-table-column prop="Name" label="运营商"></el-table-column>
<el-table-column prop="ServerUrl" label="服务器域名"></el-table-column>
<el-table-column prop="Status" label="运行状态"></el-table-column>
<el-table-column prop="LineType" label="支持方式"></el-table-column>
<el-table-column prop="BandWidth" label="实时带宽"></el-table-column>
<el-table-column prop="IpRemark" label="Ip量"></el-table-column>
<el-table-column prop="Sort" label="排序"></el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="edit(scope.row)">编辑</span>
<span class="handel cursor edit" @click="del(scope.row)">删除</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="线路维护" :visible.sync="showDialog" width="500px">
<el-form :model="routeModel" :rules="rules" ref="inputForm" label-width="80px">
<el-form-item prop="ProductId" label="产品">
<el-select size="small" v-model="routeModel.ProductId">
<el-option v-for="(item,index) in products" :key="index" :label="item.Name" :value="item.Id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="Province" label="省份">
<el-input v-model="routeModel.Province" size="small"></el-input>
</el-form-item>
<el-form-item prop="City" label="城市">
<el-input v-model="routeModel.City" size="small"></el-input>
</el-form-item>
<el-form-item prop="Name" label="运营商">
<el-input v-model="routeModel.Name" size="small"></el-input>
</el-form-item>
<el-form-item prop="ServerUrl" label="服务器域名">
<el-input v-model="routeModel.ServerUrl" size="small"></el-input>
</el-form-item>
<el-form-item prop="Status" label="运行状态">
<el-radio-group v-model="routeModel.Status" size="small">
<el-radio label="正常">正常</el-radio>
<el-radio label="离线">离线</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="Sort" label="排序">
<el-input v-model="routeModel.Sort" size="small" number ></el-input>
</el-form-item>
<el-form-item prop="LineType" label="支持方式">
<el-input v-model="routeModel.LineType" size="small"></el-input>
</el-form-item>
<el-form-item prop="BandWidth" label="带宽">
<el-input v-model="routeModel.BandWidth" size="small"></el-input>
</el-form-item>
<el-form-item prop="IpRemark" label="Ip">
<el-input v-model="routeModel.IpRemark" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputForm')"> </el-button>
<el-button type="primary" @click="save('inputForm')">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
},
data() {
return {
loading: false,
showDialog:false,
optype:1,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: "",
productId:"",
},
products:[],
routeModel: {
LineType:'L.P.T',
Status:'正常',
},
types: [
],
rules: {
ProductId: [this.$vaild.required("产品")],
Province: [this.$vaild.required("省份")],
City: [this.$vaild.required("城市")],
ServerUrl: [this.$vaild.required("服务器域名")],
Name: [this.$vaild.required("运营商")]
},
}
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>线路管理");
this.getProducts()
this.get();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
getProducts(){
this.$api
.get("course/v1/product/page", this.searchModel)
.then(res => {
this.products= res.Data;
//this.types=this.products.map(m=>{ return {text:m.Name,value:m.Id} })
});
},
get() {
this.$api
.get("course/v1/productroute/page", this.searchModel)
.then(res => {
this.retData = res;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api
.post("course/v1/productroute/Delete?id=" + item.Id)
.then(res => {
that.get();
});
});
},
add() {
this.showDialog = true;
this.optype = 1;
},
edit(item) {
this.showDialog = true;
this.optype = 2;
this.routeModel = clone(item);
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.showDialog = false;
},
filterHandler(filters) {
console.log(filters)
var values=Object.values(filters);
this.searchModel.productIds=values.join(',')
this.searchModel.PageIndex=1;
this.get();
},
save(formName) {
var that=this;
this.$refs[formName].validate(valid => {
if (!valid) return;
var [name]=that.products.filter(m=>m.Id==that.routeModel.ProductId).map(m=>m.Name);
that.routeModel.ProductName=name
if (that.optype == 1) {
that.$api.post("course/v1/productroute/post", that.routeModel).then(res => {
that.resetForm('inputForm');
that.get();
});
} else {
that.$api.post("course/v1/productroute/put", that.routeModel).then(res => {
that.resetForm('inputForm');
that.get();
});
}
})
},
importExcel(callback) {
this.$api.upload("course/v1/productroute/Import",{accept:"*/*"}).then(res => {
this.get()
})
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,127 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入产品名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="Name" label="产品名称" width="180"></el-table-column>
<el-table-column prop="PcClientDownloadUrl" label="电脑客户端">
<template slot-scope="scope">
<!-- <span><i class="el-icon-copy-document"></i>复制</span> -->
<cutTip :text="scope.row.PcClientDownloadUrl"></cutTip>
</template>
</el-table-column>
<el-table-column prop="SimulatorDownloadUrl" label="模拟器">
<template slot-scope="scope">
<cutTip :text="scope.row.SimulatorDownloadUrl"></cutTip>
</template>
</el-table-column>
<el-table-column prop="DroidDownloadUrl" label="安卓客户端">
<template slot-scope="scope">
<cutTip :text="scope.row.SimulatorDownloadUrl"></cutTip>
</template>
</el-table-column>
<el-table-column prop="IosDownloadUrl" label="Ios客户端">
<template slot-scope="scope">
<cutTip :text="scope.row.SimulatorDownloadUrl"></cutTip>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span class="handel cursor edit" @click="goEdit(scope.row)">编辑</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="软件下载配置" :visible.sync="showDialog" width="400px">
<el-form :model="currentProduct" :rules="rules" ref="inputProductForm" label-width="100px">
<el-form-item prop="PcClientDownloadUrl" label="电脑客户端">
<el-input v-model="currentProduct.PcClientDownloadUrl" size="small"></el-input>
</el-form-item>
<el-form-item prop="DroidDownloadUrl" label="安卓客户端">
<el-input v-model="currentProduct.DroidDownloadUrl" size="small"></el-input>
</el-form-item>
<el-form-item prop="IosDownloadUrl" label="Ios客户端">
<el-input v-model="currentProduct.IosDownloadUrl" size="small"></el-input>
</el-form-item>
<el-form-item prop="SimulatorDownloadUrl" label="模拟器">
<el-input v-model="currentProduct.SimulatorDownloadUrl" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm"> </el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
cutTip: () => import("@/components/common/cutTip")
},
data() {
return {
showDialog: false,
loading: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
currentProduct: {
Id: 0,
Name: "",
Profile: "",
Image: ""
},
rules: {}
};
},
created() {
this.$store.commit("setCurrentNav", "产品管理>>下载配置");
this.get();
},
methods: {
get() {
this.loading = true;
this.$api.get("course/v1/product/page", this.searchModel).then(res => {
this.retData = res;
this.loading = false;
});
},
goEdit(item) {
this.currentProduct = item;
this.showDialog = true;
},
save() {
this.$api
.post("course/v1/product/putSoft", this.currentProduct)
.then(res => {
this.resetForm();
this.get();
});
},
resetForm() {
this.$refs["inputProductForm"].resetFields();
this.showDialog = false;
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,250 @@
<template>
<div>
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-plus" @click="add">新建优惠券</el-button>
<div class="search-box">
<!-- <el-select v-model="value" placeholder="请选择" size="small">
<el-option label="全部状态" value="0"></el-option>
<el-option label="未开始" value="1"></el-option>
<el-option label="进行中" value="2"></el-option>
<el-option label="已结束" value="3"></el-option>
<el-option label="已失效" value="4"></el-option>
</el-select>-->
<el-input v-model="searchModel.keyWord" placeholder="请输入套餐名称/标题" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(110)">
<el-table-column prop="Name" label="优惠券名称"></el-table-column>
<el-table-column prop="CouponType" label="类型">
<template slot-scope="scope">{{scope.row.CouponType==1?"满减券":"折扣券"}}</template>
</el-table-column>
<el-table-column prop="CouponValue" label="优惠内容">
<template
slot-scope="scope"
>{{scope.row.CouponType==1?"减"+scope.row.CouponValue+"元":scope.row.CouponValue+"折"}}</template>
</el-table-column>
<el-table-column label="已领取">
<template slot-scope="scope">{{scope.row.GrantCount}}</template>
</el-table-column>
<!-- <el-table-column prop="UseCount" label="已使用" width="80"></el-table-column> -->
<el-table-column label="使用日期" width="240">
<template slot-scope="scope">
<div
v-if="scope.row.DateRule==1&&scope.row.StartDate&&scope.row.EndDate"
>{{scope.row.StartDate.DateFormat('yyyy-MM-dd')}}{{scope.row.EndDate.DateFormat('yyyy-MM-dd')}}</div>
<div v-else-if="scope.row.DateRule==2">领取当天起{{scope.row.ValidDay}}天内有效</div>
<div v-else>领取次日起{{scope.row.ValidDay}}天内有效</div>
</template>
</el-table-column>
<el-table-column label="操作" width="220">
<template slot-scope="scope">
<span class="handel cursor edit" @click="give(scope.row)">发放</span>
<span class="handel cursor edit" @click="edit(scope.row)">编辑</span>
<router-link :to="{name:'couponused',query:{couponId:scope.row.Id,couponName:scope.row.Name}}">
<span class="handel cursor edit">明细</span>
</router-link>
<!-- <span class="handel cursor edit" v-if="scope.row.Disabled==0" @click="disabled(scope.row)">使失效</span> -->
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="优惠券维护" :visible.sync="showDialog" width="680px">
<el-form :model="currentModel" :rules="rules" ref="inputForm" label-width="100px">
<el-form-item prop="CouponType" label="优惠券类型">
<el-radio-group v-model="currentModel.CouponType">
<el-radio :label="1">满减券</el-radio>
<el-radio :label="2">折扣券</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="Name" label="优惠券名称">
<el-input v-model="currentModel.Name" size="small"></el-input>
</el-form-item>
<el-form-item prop="CouponValue" label="优惠内容">
<div v-if="currentModel.CouponType==1">
<el-input v-model="currentModel.CouponValue" placeholder="请输入优惠券金额" size="small">
<el-button slot="append"></el-button>
</el-input>
</div>
<div class="discount-box" v-else>
<el-input v-model="currentModel.CouponValue" placeholder="请输入优惠券折扣1-10" size="small">
<el-button slot="append"></el-button>
</el-input>
</div>
</el-form-item>
<el-form-item prop="isLimitAmount" label="使用门槛">
<el-radio-group v-model="isLimitAmount">
<el-radio :label="0">无门槛</el-radio>
<el-radio :label="1">
<el-input
v-model="currentModel.AllowMinAmount"
size="small"
placeholder="请输入满xx元后方可使用"
></el-input>
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item prop="DateRule" label="使用时间">
<el-radio-group v-model="currentModel.DateRule">
<el-radio :label="1">
特定时间段
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-radio>
<el-radio :label="2">
领取当日起
<el-input v-model="currentModel.ValidDay" size="small" />天内可用
</el-radio>
<el-radio :label="3">
领取次日起
<el-input v-model="currentModel.ValidDay" size="small" />天内可用
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm"> </el-button>
<el-button type="primary" @click="save()">确定</el-button>
</span>
</el-dialog>
<userDrawer ref="userDrawer" @select="onSelect"></userDrawer>
</div>
</template>
<script>
var that = null;
export default {
components: {
userDrawer: () => import("@/components/common/userDrawer")
},
data() {
return {
showDialog: false,
optype: 1, //1:新建 2编辑
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
currentModel: {
CouponType: 1,
DateRule: 1,
ValidDay: 0,
CouponValue: 0,
AllowMinAmount: 0,
StartDate: null,
EndDate: null
},
giveModel:{
CouponId:0,
UserId:0
},
isLimitAmount: 0,
dateRange: [],
rules: {}
};
},
created() {
this.$store.commit("setCurrentNav", "优惠券管理");
this.get(1);
},
methods: {
get(page) {
if (Number.isInteger(page)) {
this.searchModel.PageIndex = page;
}
this.$api.get("sells/v1/coupon/Page", this.searchModel).then(res => {
this.retData = res;
});
},
add() {
this.optype = 1;
this.showDialog = true;
},
edit(item) {
this.optype = 2;
this.showDialog = true;
this.currentModel = clone(item);
if (item.AllowMinAmount > 0) this.isLimitAmount = 1;
else this.isLimitAmount = 0;
},
save() {
this.currentModel.StartDate = this.dateRange[0];
this.currentModel.EndDate = this.dateRange[1];
if (this.isLimitAmount == 0) this.currentModel.AllowMinAmount = 0;
if (this.optype == 1) {
this.$api.post("sells/v1/coupon/Post", this.currentModel).then(res => {
this.resetForm();
this.get();
});
} else {
this.$api.post("sells/v1/coupon/put", this.currentModel).then(res => {
this.resetForm();
this.get();
});
}
},
resetForm() {
this.$refs["inputForm"].resetFields();
this.showDialog = false;
},
disabled(item) {
this.$api.post("sells/v1/coupon/Disabled?id=" + item.Id).then(res => {
this.get();
});
},
give(row) {
this.giveModel.CouponId=row.Id;
this.$refs["userDrawer"].show();
},
onSelect(item) {
this.giveModel.UserId=item.Id;
this.$confirm("确定要赠送吗?").then(_ => {
this.$api.post("sells/v1/coupon/give", this.giveModel).then(res => {
this.get();
})
})
}
}
};
</script>
<style scoped>
.xeBtnDefault {
outline: medium;
color: #666;
background: #fafbfc;
border: 1px solid #e5e7eb;
}
.btnMid {
display: inline-block;
width: 90px;
height: 36px;
padding: 0;
text-align: center;
line-height: 36px;
border-radius: 2px;
cursor: pointer;
font-size: 14px;
}
.el-radio {
padding: 5px 0;
}
</style>

View File

@@ -0,0 +1,290 @@
<template>
<div class="couponbox">
<el-alert
title="优惠券说明"
type="info"
description=" 优惠券总量为用户领取、定向发放、兑换码兑换、支付有礼发放、运营计划发放所产生的优惠券数量,具体数量可在效果数据中查看。"
show-icon
></el-alert>
<div class="baseInfo">
<h2 class="title">基本信息</h2>
<section class="creat_item">
<label for="title" class="lable">
优惠券名称
<span class="star">*</span>
</label>
<input
type="text"
v-model="couponModel.Name"
placeholder="优惠券名称不超过10个字"
maxlength="10"
autocomplete="off"
/>
</section>
<section class="creat_item flex">
<div class="lable">
优惠券类型
<span class="star">*</span>
</div>
<div class="flex">
<el-radio v-model="couponModel.CouponType" :label="1">满减优惠券</el-radio>
<el-radio v-model="couponModel.CouponType" :label="2">折扣优惠券</el-radio>
</div>
</section>
<section class="creat_item flex">
<div class="lable">
使用门槛
<span class="star">*</span>
</div>
<div>
<el-radio v-model="limitAmount" :label="0">无门槛使用</el-radio>
<el-radio v-model="limitAmount" :label="1">
<span></span>
<input type="text" placeholder="输入金额" v-model="couponModel.AllowMinAmount" class="input_price" />
<span>元使用</span>
</el-radio>
</div>
</section>
<section class="creat_item flex">
<div class="lable">
优惠内容
<span class="star">*</span>
</div>
<div>
<div v-if="couponModel.CouponType==1">
<input type="text" v-model="couponModel.CouponValue" placeholder="请输入优惠券金额" />
</div>
<div class="discount-box" v-else >
<input type="text" v-model="couponModel.CouponValue" />
</div>
</div>
</section>
<section class="creat_item flex">
<label for="count" class="lable">
发行量
<span class="star">*</span>
</label>
<div>
<input
type="text"
v-model="couponModel.TotalCount"
autocomplete="off"
placeholder="最多多少张张"
/>
<br />
<div class="grayTip">优惠券创建后发行量只能增加不能减少请谨慎设置</div>
</div>
</section>
<section class="creat_item flex">
<label for="range" class="lable">
适用商品
<span class="star">*</span>
</label>
<div>
<el-radio v-model="couponModel.UseRange" :label="1">全部商品可用</el-radio>
<el-radio v-model="couponModel.UseRange" :label="2">指定商品可用</el-radio>
<div v-if="couponModel.UseRange==2">
<el-button type="primary" @click="$refs['productSelector'].show()">选择课程</el-button>
<el-table
:data="products"
style="width: 100%;margin-bottom: 20px;"
row-key="ResourceId"
border
>
<el-table-column label="课程图片" width="180">
<template slot-scope="scope">
<img :src="scope.row.ResourceImage" style="width:50px;height:25px;" />
</template>
</el-table-column>
<el-table-column prop="ResourceName" label="课程名称" width="180"></el-table-column>
<el-table-column prop="Price" label="价格"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-link type="primary" @click="remove(scope.row)">移除</el-link>
</template>
</el-table-column>
</el-table>
</div>
</div>
</section>
<section class="choose_time creat_item">
<div class="lable">
使用时间
<span class="star">*</span>
</div>
<div>
<div class="flex">
<el-radio v-model="couponModel.DateRule" :label="1">
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-radio>
</div>
<div class="up-down-margin">
<el-radio v-model="couponModel.DateRule" :label="2">
<label for="time_way_two">领取当日起</label>
<input type="text" v-model="couponModel.ValidDay" class="input_price" />
<span>天内可用</span>
</el-radio>
</div>
<div>
<el-radio v-model="couponModel.DateRule" :label="3">
<label for="time_way_three">领取次日起</label>
<input type="text" v-model="couponModel.ValidDay " class="input_price" />
<span>天内可用</span>
</el-radio>
</div>
</div>
</section>
</div>
<div class="popuInfo use-way-box">
<h2 class="title">领用规则</h2>
<section class="creat_item flex">
<div class="lable">
领取次数限制
<span class="star">*</span>
</div>
<div>
<el-radio v-model="isLimit" :label="0">不限次数</el-radio>
<el-radio v-model="isLimit" :label="1">每人限领</el-radio>
<el-input v-if="isLimit==1" v-model="couponModel.GetLimitCount"></el-input>
</div>
</section>
<!-- <section class="creat_item">
<label for="can_share" class="lable lable-top">分享设置</label>
<el-checkbox v-model="checked">优惠券允许分享给好友领取</el-checkbox>
</section>-->
<section class="creat_item">
<label for="can_use_activity" class="lable lable-top">活动叠加限制</label>
<el-checkbox v-model="couponModel.IsOverlay" :true-label="1" :false-label="0">优惠券仅原价购买商品时可用不可与其他营销活动叠加使用</el-checkbox>
</section>
<section class="creat_item activity-overlay">
<label for="can_use_activity" class="lable lable-top">公开设置</label>
<el-checkbox v-model="couponModel.IsOpen" :true-label="1" :false-label="0">用户可在商品详情页领取</el-checkbox>
</section>
</div>
<el-button @click="add">保存</el-button>
</div>
</template>
<script>
var that = null;
export default {
components: {
},
data() {
return {
isLimit: 0,
limitAmount:0,
dateRange: [],
couponModel: {
CouponType: 1,
DateRule: 1,
UseRange:1
},
products: []
};
},
watch: {
saoma: function() {}
},
created() {},
methods: {
get() {
this.$api.get("sells/v1/coupon/get").then(res => {
if (res.Data) this.couponModel = res.Data;
});
},
add() {
this.couponModel.StartDate = this.dateRange[0];
this.couponModel.EndDate = this.dateRange[1];
this.couponModel.Resource = this.products;
if (this.isLimit == 0) this.couponModel.LimitCount = -1;
this.$api.post("sells/v1/coupon/Post", this.couponModel).then(res => {
this.$router.push({ name: "coupon" });
});
},
selectCourse(data) {
var model = data.map(m => {
return {
ResourceId: m.Id,
ResourceImage: m.Cover,
ResourceName: m.Name,
ResourceType: 1,
Price: m.Price
};
});
this.products.push(...model);
},
selectLive(data) {
var model = data.map(m => {
return {
ResourceId: m.Id,
ResourceImage: m.Cover,
ResourceName: m.Name,
ResourceType: 2,
Price: m.Price
};
});
this.products.push(...model);
},
selectPackage(data) {
var model = data.map(m => {
return {
ResourceId: m.Id,
ResourceImage: m.Cover,
ResourceName: m.Name,
ResourceType: 3,
Price: m.Price
};
});
this.products.push(...model);
},
remove(item) {
var index = this.products.indexOf(item);
this.products.splice(index, 1);
}
}
};
</script>
<style scoped>
.couponbox {
padding: 20px;
}
.creat_item {
margin-bottom: 28px;
}
.lable {
width: 200px;
float: left;
}
.star {
color: red;
font-size: 20px;
}
input {
padding-left: 5px;
width: 240px;
height: 36px;
-webkit-border-radius: 2px;
border-radius: 2px;
border: 1px solid #eee;
margin-right: 10px;
}
.grayTip {
font-size: 12px;
color: #999999;
text-align: left;
margin-top: 10px;
}
</style>

View File

@@ -0,0 +1,97 @@
<template>
<div>
<div class="heior_box">
{{couponName}}
<div class="search-box"></div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="CreateTime" label="创建日期" width="180"></el-table-column>
<el-table-column prop="OrderNo" label="订单号" width="215"></el-table-column>
<el-table-column prop="UserName" label="用户" width="120"></el-table-column>
<el-table-column prop="ProductName" label="产品"></el-table-column>
<el-table-column prop="PackageName" label="套餐"></el-table-column>
<el-table-column prop="Accounts" label="账号">
<template slot-scope="scope">
<cutTip :text="scope.row.Accounts"></cutTip>
</template>
</el-table-column>
<el-table-column prop="OrderAmount" label="订单金额"></el-table-column>
<el-table-column prop="CouponAmount" label="优惠金额"></el-table-column>
<!-- <el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="Free(scope.row)">冻结</span>
</template>
</el-table-column> -->
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
var that = null;
export default {
components: {},
data() {
return {
retData: { TotalCount: 0, Data: [] },
couponName:'',
searchModel: {
PageIndex: 1,
keyWord: "",
CouponId: 0
}
}
},
created() {
this.$store.commit("setCurrentNav", "优惠券明细");
var couponId=this.$route.query.couponId;
this.couponName=this.$route.query.couponName;
this.get(couponId);
},
methods: {
get(couponId) {
if (Number.isInteger(couponId)) {
this.searchModel.CouponId = couponId;
}
this.$api
.get("course/v1/order/CouponOrders", this.searchModel)
.then(res => {
this.retData = res;
});
}
}
};
</script>
<style scoped>
.xeBtnDefault {
outline: medium;
color: #666;
background: #fafbfc;
border: 1px solid #e5e7eb;
}
.btnMid {
display: inline-block;
width: 90px;
height: 36px;
padding: 0;
text-align: center;
line-height: 36px;
border-radius: 2px;
cursor: pointer;
font-size: 14px;
}
.el-radio {
padding: 5px 0;
}
</style>

View File

@@ -0,0 +1,13 @@
<template>
<div>role</div>
</template>
<script>
export default {
name: "managers",
props: {
}
};
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,413 @@
<template>
<div>
<div class="heior_box">
<el-button
size="small"
type="primary"
icon="el-icon-plus"
v-href="'/user/addmanager'"
>添加子管理员</el-button>
<div class="search-box">
<el-input v-model="manageData.KeyWord" placeholder="用户名/姓名/联系方式" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="getmanagerlist(1)"></el-button>
</el-input>
</div>
</div>
<el-table :data="manegeList" size="medium" :height="$getHeight(100)" row-key="Id" border>
<el-table-column prop="LoginCode" label="账号"></el-table-column>
<el-table-column prop="RealName" label="姓名"></el-table-column>
<el-table-column prop="Phone" label="联系方式"></el-table-column>
<el-table-column prop="CreateTime" label="添加时间"></el-table-column>
<el-table-column prop="CreateTime" label="是否客户经理">
<template slot-scope="scope">
{{scope.row.roleid==100?"是":"否"}}
</template>
</el-table-column>
<el-table-column label="操作" width="140px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="setUser(scope.row)">分配用户</span>
<span class="handel cursor edit" @click="routerGo(scope.row)">编辑</span>
<span class="handel cursor del" @click="delmanagerData.ID=scope.row.Id;delmanager()">删除</span>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="manegeList.length>0"
@current-change="getmanagerlist"
:page-size="50"
:current-page.sync="manageData.PageIndex"
layout="total,prev, pager, next"
:total="manegeTotal"
></el-pagination>
</div>
<el-dialog title="选中用户" :visible.sync="showUserDialog" width="770px" v-loading="userLoading">
<div class="search-box">
<el-button size="small" type="primary" icon="el-icon-plus" @click="doSetUser()">分配用户</el-button>
<el-switch
active-value="1"
inactive-value="0"
v-model="searchUserModel.all"
active-text="全部用户">
</el-switch>
<el-input placeholder="输入关键字进行过滤" size="small" v-model="searchUserModel.keyWord">
<el-button slot="append" icon="el-icon-search" @click="getUser"></el-button>
</el-input>
</div>
<el-table :data="userRet.Data" row-key="Id" border size="medium" height="650px"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column prop="LoginCode" label="账号" ></el-table-column>
<el-table-column prop="CreateTime" label="注册时间"> </el-table-column>
<el-table-column prop="Name" label="名称"></el-table-column>
<el-table-column prop="ManagerName" label="客户经理"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="userRet.Data.length>0"
@current-change="getUser"
:page-size="500"
:current-page.sync="searchUserModel.PageIndex"
layout="total,prev, pager, next"
:total="userRet.TotalCount"
></el-pagination>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
userLoading:false,
showUserDialog:false,
allowAdd: true,
loading: false,
userdata: {}, //当前登录人信息
manegeList: [],
manageData: {
PageIndex: 1,
PageSize: 50,
TenantId: 0,
KeyWord: "",
RoleId: 0,
CurrentRoleId: 0,
IsRoot: 0
},
manegeTotal: 0,
checkEstate: false, //当前是否查看项目
delroleData: {
//删除角色
ID: "",
OwnerID: 1001,
OperaterID: 1,
ProjectCode: ""
},
delmanagerData: {
//删除管理员
ID: "",
OwnerID: 1001,
OperaterID: 1,
ProjectCode: ""
},
stateData: {
//更新关联项目
Managerid: 1,
Projectcodes: []
},
bindwx: false,
estateSelected: {
SelectedCodes: [],
SelectedNames: []
},
searchUserModel: {
PageIndex: 1,
keyWord: "",
PageSize:500,
all:0
},
userRet:{
TotalCount:0,
Data:[]
},
currentManager:null,
multipleSelection:null,
};
},
watch: {
bindwx: function() {
if (!this.bindwx) {
clearInterval(this.timer);
}
}
},
created() {
this.$store.commit("setCurrentNav","会员管理>>管理员")
this.userdata = JSON.parse(
window.localStorage.getItem("etorcurrentuser")
).Manager;
this.getmanagerlist();
this.getUser();
},
methods: {
handleSelectionChange(val){
this.multipleSelection = val;
console.log(val)
},
setUser(manage){
this.showUserDialog=true;
this.currentManager=manage;
},
getUser() {
this.$api.get("baseinfo/v1/user/Search",this.searchUserModel).then(res => {
this.userRet=res;
})
},
doSetUser() {
var data={
ManagerId:this.currentManager.Id,
ManagerName:this.currentManager.RealName,
UserIds:this.multipleSelection.map(m=>m.Id)
};
this.$api.post("baseinfo/v1/user/SetManager",data).then(res => {
this.getUser();
this.showUserDialog=false;
})
},
geturl(data) {
var that = this;
var id = data.Id;
var uuid = that.getguid();
var url =
this.$api.baseURL +
"Manager/ManageBindWx?data.Id=" +
id +
"&data.uuid=" +
uuid;
this.bindwx = true;
this.makeqrcode(url);
that.timer = setInterval(function() {
that.time(uuid, that.timer);
}, 1000);
},
// 获取uuid
getguid() {
return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
},
time(data, time) {
this.$api
.getscanbindwxstate(data)
.then(res => {
console.log(res);
if (res.Data.State == 0) {
clearInterval(time);
this.getmanagerlist(this.manageData.PageIndex);
this.bindwx = false;
}
})
.catch(res => {
clearInterval(time);
});
},
makeqrcode(url) {
document.getElementById("qrcode").innerHTML = "";
new QRCode(document.getElementById("qrcode"), {
text: url,
width: 127,
height: 127,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H
});
},
getmanagerlist(val) {
//获取管理员列表
var that = this;
this.loading = true;
typeof val === "number" && (this.manageData.PageIndex = val);
var roleid = this.userdata.Roleid;
this.manageData.CurrentRoleId = roleid;
this.manageData.IsRoot = 1;
this.$api
.get("manage/v1/Manager/Get", this.manageData)
.then(res => {
if (res.Code == 10000) {
this.manegeTotal = res.TotalCount;
this.manegeList = res.Data;
console.log(this.manegeList);
} else {
this.$message({
type: "error",
message: res.Message
});
}
this.loading = false;
})
.catch(res => {
//console.log(res);
});
},
putManagerdatadomain(e) {
//更改某管理员关联项目列表
this.stateData.Projectcodes = e.SelectedCodes;
//console.log(e);
this.$api
.putManagerdatadomain(this.stateData)
.then(res => {
if (res.Code == 10000) {
this.$message({
type: "success",
message: "修改关联项目成功!"
});
this.getmanagerlist();
} else {
this.$message({
type: "error",
message: res.Message
});
}
})
.catch(res => {
//console.log(res);
});
},
getManagerdatadomain(id) {
//获取管理员管理的楼宇编码
if (this.checkEstate) {
this.checkEstate = !this.checkEstate;
}
this.$api
.getManagerdatadomain({ ID: id })
.then(res => {
if (res.Code == 10000) {
this.stateData.Managerid = res.Data.Managerid;
this.estateSelected.SelectedCodes = res.Data.Projectcodes;
this.checkEstate = true;
} else {
this.$message({
type: "error",
message: res.Message
});
}
})
.catch(res => {
//console.log(res);
});
},
delmanager() {
//删除管理员
this.$confirm("确认删除该管理员吗?", "删除", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$api
.delmanager(this.delmanagerData)
.then(res => {
if (res.Code == 10000) {
this.$message({
type: "success",
message: "删除成功"
});
this.getmanagerlist(1);
} else {
this.$message({
type: "error",
message: res.Message
});
}
})
.catch(res => {
//console.log(res);
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除"
});
});
},
routerGo(item) {
this.$router.push({
name: "addmanager",
query: {
ID: item.Id
}
});
}
}
};
</script>
<style lang="less" scoped>
.basicsetting {
height: 100%;
.el-dialog {
.manager {
height: 210px;
p {
width: 165px;
}
.do img {
width: 150px;
height: 150px;
float: none;
margin-left: 50%;
transform: translateX(-50%);
}
}
/deep/ .el-dialog__footer {
height: 57px;
line-height: 57px;
p {
color: #2e2f33;
line-height: 57px;
text-align: left;
text-indent: 20px;
}
}
}
.blackList {
color: red;
border: 1px solid red;
}
}
#qrcode {
margin-left: calc(~"50% - 63.5px");
}
.dialog_box {
width: 440px;
height: 210px;
}
.dialog_content {
height: auto;
padding-bottom: 20px;
min-height: 95px;
}
.look {
color: #4c82ff;
}
.textm {
padding-left: 26px;
font-size: 14px;
color: #8f8f8f;
}
</style>

View File

@@ -0,0 +1,13 @@
<template>
<div>manager</div>
</template>
<script>
export default {
name: "managers",
props: {
}
};
</script>

View File

@@ -0,0 +1,13 @@
<template>
<div>roles</div>
</template>
<script>
export default {
name: "managers",
props: {
}
};
</script>

52
src/components/test.vue Normal file
View File

@@ -0,0 +1,52 @@
<template>
<page>
<hheader></hheader>
<left></left>
<div class="base_right editbase_right">
<router-view class="page_main"></router-view>
</div>
</page>
</template>
<script>
export default {
components: {
left: () => import('./common/layout/left.vue'),
hheader: () => import('./common/layout/header.vue'),
},
data() {
return {
mydata:{
name:'ff',
list:[1],
}
}
},
watch: {
saoma: function() {}
},
created() {},
methods: {
pp(){
this.mydata.list.push(2);
}
}
}
</script>
<style scoped>
.base_right {
margin-left: 180px;
height: 100%;
position: relative;
overflow-x: hidden;
overflow-y: auto;
background: #f5f7fa;
transition: padding ease .3s;
} body.help_doc_unfolding .base_right {
padding-right: 224px;
}.editbase_right {
padding-top: 56px;
}
</style>

132
src/components/user/add.vue Normal file
View File

@@ -0,0 +1,132 @@
<template>
<div class="main_box screen1" v-loading="loading">
<el-breadcrumb separator-class="el-icon-arrow-right" class="ml40 xw995">
<el-breadcrumb-item>资讯管理</el-breadcrumb-item>
<el-breadcrumb-item :to="{name:'course'}">资讯列表</el-breadcrumb-item>
<el-breadcrumb-item>新建课程</el-breadcrumb-item>
</el-breadcrumb>
<el-form :model="articleModel" :rules="rules" ref="editor" class="from_box clr">
<el-form-item prop="Title" class="from_item">
<label>标题</label>
<img src="/static/img/common/main.png">
<el-input placeholder="请填标题" v-model="articleModel.Title"></el-input>
</el-form-item>
<el-form-item prop="SubTitle" class="from_item">
<label>副标题</label>
<img src="/static/img/common/main.png">
<el-input placeholder="请填副标题" v-model="articleModel.SubTitle"></el-input>
</el-form-item>
<el-form-item prop="Keyword" class="from_item">
<label class="noimh">关键字</label>
<el-input v-model="articleModel.Keyword" type="number"></el-input>
</el-form-item>
<el-form-item prop="AccessCount" class="from_item">
<label>访问人数</label>
<img src="/static/img/common/main.png">
<el-input placeholder="请填访问人数::" v-model="articleModel.AccessCount" type="number"></el-input>
</el-form-item>
<el-form-item prop="OnLine" class="from_item">
<label>发布状态:</label>
<img src="/static/img/common/main.png">
<div>
<el-switch v-model="articleModel.Publish" :active-value="1" :inactive-value="0"> </el-switch>
</div>
</el-form-item>
<el-form :inline="true">
<el-form-item prop="Thumb" class="from_item">
<label>课程封面</label>
<div class="uploadimg_box ">
<img :src="articleModel.Thumb" v-if="articleModel.Thumb!=''" class="uploadimg" @click="upload(setCover)" />
<span class="ubloadbtn" v-else>
<img src="/static/img/common/imgadd.png" @click="upload(setCover)" >
</span>
<p class="imgTip" @click="upload(setCover)" >点击更换</p>
<p class="zhu">图片大小不可超过2M
</p>
</div>
</el-form-item>
</el-form>
</el-form>
<div class="editor-container">
<UE v-model="articleModel.Content" :config='config' ref="ue"></UE>
</div>
<div class="handel_box clr">
<router-link :to="{name:'course'}" tag="input" type="button" value="返回" class="cursor"></router-link>
<input type="button" value="保存" @click="save('editor')" class="small cursor">
</div>
</div>
</template>
<script>
let that;
export default {
components: {
},
data() {
return {
articleModel:{
Publish:0,
id:0,
Thumb:'',
},
loading: false,
rules: {
Title: [this.$vaild.required("标题")],
SubTitle: [this.$vaild.required("副标题")],
// Banner: [this.$vaild.required("课程主图")],
// Cover: [this.$vaild.required("课程封面")],
},
config:{
serverUrl:this.$api.baseURL+"ueditor",
UEDITOR_HOME_URL: "/static/ueditor/",
autoHeightEnabled: false,
initialFrameHeight: 500,
},
options:[]
}
},
created() {
var query=this.$route.query;
if(query.optype==2){
this.getInfo(query.id);
}
},
methods: {
getInfo(id){
this.$api.get("course/v1/article/Get",{id:id}).then(res=>{this.articleModel=res.Data});
},
save(formName) {
var that = this;
this.$refs[formName].validate(valid => {
if (valid) {
if (that.$route.query.optype=="1") {
that.add();
} else if(that.$route.query.optype=="2") {
that.edit();
}
}
})
},
add(){
this.$api.post("course/v1/article/post",this.articleModel).then(res=>{
this.$router.push({name:"course"})
})
},
edit(){
this.$api.post("course/v1/article/put",this.articleModel).then(res=>{
this.$router.push({name:"article"})
})
},
upload(callback) {
this.$api.upload('oss/v1/ImageCloud/upload').then(res=>{
callback&&callback(res.Data);
});
},
setCover(ret) {
this.articleModel.Thumb=ret.Url;
}
}
};
</script>

View File

@@ -0,0 +1,90 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入会员号/名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" size="medium" :height="$getHeight(300)" row-key="Id" border>
<el-table-column prop="CreateTime" label="日期"></el-table-column>
<el-table-column prop="UserName" label="用户">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserName"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="OperateUserName" label="操作人员"></el-table-column>
<el-table-column prop="ScoreTypeName" label="资金项目"></el-table-column>
<el-table-column prop="RestAmount1" label="操做前余额"></el-table-column>
<el-table-column prop="ScoreValue" label="金额"></el-table-column>
<el-table-column prop="RestAmount2" label="操做后余额"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="getAmountDetail"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "userIndex",
components: {
cutTip: () => import("@/components/common/cutTip"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
detailAmountData: [],
formatterCreateType(row, column, cellValue, index) {
switch (cellValue) {
case 1:
return "管理员添加";
case 2:
return "用户注册";
case 3:
return "淘宝注册";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav", "订单管理>>资金明细");
this.getAmountDetail();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.getAmountDetail();
},
getAmountDetail() {
this.loading = true;
this.$api
.get("baseinfo/v1/user/AmountDetails", this.searchModel)
.then(res => {
this.retData = res;
this.loading = false;
});
},
dataExport(){
this.$api.getDownloadFile("/baseinfo/v1/user/ExportAmount", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button
size="small"
type="primary"
icon="el-icon-sold-out"
@click="dataExport"
v-if="$local.isRoot()"
>导出</el-button>
<div class="search-box">
<el-date-picker
size="small"
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
<el-input
v-model="searchModel.keyWord"
placeholder="请输入订单号、用户名"
clearable
size="small"
>
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" row-key="Id" border size="medium" :height="$getHeight(100)">
<el-table-column prop="CreateTime" label="创建日期" width="180"></el-table-column>
<el-table-column prop="OrderNo" label="订单号" ></el-table-column>
<el-table-column prop="TradeNo" label="支付流水号"></el-table-column>
<el-table-column prop="UserName" label="用户" width="120">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserName"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="OrderAmount" label="充值金额" width="180"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:current-page.sync="searchModel.PageIndex"
:page-size="50"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {
cutTip: () => import("@/components/common/cutTip"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
options: [],
retData: { TotalCount: 0, Data: [] },
dateRange: [],
searchModel: {
PageIndex: 1,
keyWord: "",
Btime: "",
Etime: "",
}
};
},
created() {
this.$store.commit("setCurrentNav", "订单管理>>充值订单");
this.get();
},
methods: {
search() {
this.searchModel.PageIndex = 1;
this.get();
},
get() {
if (this.dateRange && this.dateRange.length == 2) {
this.searchModel.Btime = this.dateRange[0];
this.searchModel.Etime = this.dateRange[1];
}
this.$api.get("baseinfo/v1/chargeorder/page", this.searchModel).then(res => {
this.retData = res;
});
},
dataExport() {
this.$api.getDownloadFile("/baseinfo/v1/chargeorder/ExportOrder", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,314 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-plus" @click="add">添加会员</el-button>
<el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入会员号/名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" size="medium" :height="$getHeight(100)" row-key="Id" border>
<!-- <el-table-column prop="LoginCode" label="会员号" width="120px"></el-table-column> -->
<!-- <el-table-column prop="Name" label="名称"></el-table-column> -->
<el-table-column prop="LoginCode" label="会员号" width="120px">
<template slot-scope="scope">
<phoneHide :text="scope.row.LoginCode"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="CreateTime" label="注册时间" width="160px"></el-table-column>
<el-table-column prop="CreateType" label="注册方式" :formatter="formatterCreateType"></el-table-column>
<!-- <el-table-column prop="ProductAccountCount" label="账号总数"></el-table-column>
<el-table-column prop="ExpiredProductAccountCount" label="过期数"></el-table-column>
<el-table-column prop="ExpiredProductAccountCount" label="未过期数"></el-table-column>-->
<!-- <el-table-column prop="ConsumeAmount" label="消费总额"></el-table-column> -->
<el-table-column prop="RestAmount" label="余额"></el-table-column>
<el-table-column prop="RestAmount" label="测试限额/领用数">
<template slot-scope="scope">
{{scope.row.TestCountLimit==0?'3':scope.row.TestCountLimit}}/{{scope.row.UseTestCount==0?'--':scope.row.UseTestCount}}
</template>
</el-table-column>
<el-table-column prop="ManagerName" label="客户经理"></el-table-column>
<el-table-column label="操作" width="400px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="showUpdateTest(scope.row)">设置测试</span>
<span class="handel cursor edit" @click="showAmount(scope.row,1)" v-if="IsRoot">充值</span>
<span class="handel cursor edit" @click="showAmount(scope.row,2)">扣款</span>
<router-link :to="{name:'account',query:{userId:scope.row.Id}}">
<span class="handel cursor edit">账号</span>
</router-link>
<router-link :to="{name:'userprice',query:{id:scope.row.Id}}">
<span class="handel cursor edit">会员价</span>
</router-link>
<span class="handel cursor edit" @click="edit(scope.row)">编辑</span>
<span class="handel cursor edit" @click="showAmountDetail(scope.row)">明细</span>
<el-popover placement="bottom" trigger="hover" width="180">
<div class="popover_box">
<span>QQ号{{scope.row.QQ||'--'}}</span>
<span>微信{{scope.row.Wx||'--'}}</span>
<span>淘宝{{scope.row.TaoBao||'--'}}</span>
<span>邮箱:{{scope.row.Email||'--'}}</span>
</div>
<span class="handel cursor more" slot="reference">更多</span>
</el-popover>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="会员维护" :visible.sync="showDialog" width="400px">
<el-form :model="userModel" :rules="rules" ref="inputUserForm" label-width="80px">
<el-form-item prop="LoginCode" label="登录名称">
<el-input v-model="userModel.LoginCode" :disabled="optype==2" size="small"></el-input>
</el-form-item>
<el-form-item prop="Password" label="密码">
<el-input v-model="userModel.Password" show-password size="small"></el-input>
</el-form-item>
<el-form-item prop="Phone" label="手机号">
<el-input v-model="userModel.Phone" size="small"></el-input>
</el-form-item>
<el-form-item prop="QQ" label="QQ号">
<el-input v-model="userModel.QQ" size="small"></el-input>
</el-form-item>
<el-form-item prop="Wx" label="微信">
<el-input v-model="userModel.Wx" size="small"></el-input>
</el-form-item>
<el-form-item prop="TaoBao" label="淘宝">
<el-input v-model="userModel.TaoBao" size="small"></el-input>
</el-form-item>
<el-form-item prop="Email" label="邮箱">
<el-input v-model="userModel.Email" size="small"></el-input>
</el-form-item>
<el-form-item prop="Remark" label="备注">
<el-input v-model="userModel.Remark" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputUserForm')"> </el-button>
<el-button type="primary" @click="save('inputUserForm')">确定</el-button>
</span>
</el-dialog>
<el-dialog
:title="amountModel.opAmountType==1?'充值':'扣费'"
:visible.sync="amountModel.showAmountDialog"
width="300px"
>
<el-form :model="amountModel" :rules="amountRules" ref="inputAmountForm" label-width="80px">
<el-form-item prop="rest" label="当前余额">
<el-input v-model="amountModel.rest" size="small" disabled></el-input>
</el-form-item>
<el-form-item prop="amount" :label="amountModel.opAmountType==1?'充值金额':'扣费金额'">
<el-input v-model="amountModel.amount" size="small" type="number"></el-input>
</el-form-item>
<el-form-item prop="attchInfo" label="备注">
<el-input v-model="amountModel.attchInfo" size="small" type="number"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputAmountForm')"> </el-button>
<el-button type="primary" @click="updateAmount('inputAmountForm')">确定</el-button>
</span>
</el-dialog>
<el-dialog title="测试限额设置" :visible.sync="showTestDialog" width="300px">
<el-form :model="testLimitModel" ref="inputTestForm" label-width="80px">
<el-form-item prop="limit" label="限制次数">
<el-input v-model="testLimitModel.limit" size="small" type="number"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputTestForm')"> </el-button>
<el-button type="primary" @click="updateTestLimit()">确定</el-button>
</span>
</el-dialog>
<el-dialog title="资金明细" :visible.sync="showDetailDialog" width="500px">
<el-table
:data="detailAmountData"
size="medium"
:height="$getHeight(300)"
row-key="Id"
border
>
<el-table-column prop="ScoreTypeName" label="资金项目"></el-table-column>
<el-table-column prop="ScoreValue" label="金额"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
export default {
name: "userIndex",
components: {
cutTip: () => import("@/components/common/cutTip"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
isRoot:false,
loading: false,
showDialog: false,
showTestDialog: false,
showDetailDialog: false,
optype: 1, //1:添加 2编辑
userModel: {
LoginCode: "",
Phone: "",
Password: "",
Remark: ""
},
amountModel: {
rest: 0,
amount: 0,
opAmountType: 1, ////1:充值 2扣款
showAmountDialog: false,
attchInfo:''
},
testLimitModel: {
userId: 0,
limit: 3
},
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
rules: {
LoginCode: [this.$vaild.required("登录名称")],
Phone: [this.$vaild.required("手机号")],
// Password: [this.$vaild.required("密码")]
},
amountRules: {
// amount: [{ type: 'number', message: '金额必须为数字值'}],
},
detailAmountData: [],
formatterCreateType(row, column, cellValue, index) {
switch (cellValue) {
case 1:
return "管理员添加";
case 2:
return "用户注册";
case 3:
return "淘宝注册";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav", "用户管理>>会员管理");
var currentUser=this.$local.getUserByCache();
this.IsRoot=currentUser.Manager.IsRootUser;
this.get();
},
methods: {
search(){
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api.get("baseinfo/v1/user/page", this.searchModel).then(res => {
this.retData = res;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api.post("baseinfo/v1/user/Delete?id=" + item.Id).then(res => {
that.get();
});
});
},
add() {
this.showDialog = true;
this.optype = 1;
},
edit(item) {
this.showDialog = true;
this.optype = 2;
this.userModel = clone(item);
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.showDialog = false;
this.amountModel.showAmountDialog = false;
this.showTestDialog = false;
},
save(formName) {
this.$refs[formName].validate(valid => {
if (!valid) return;
if (this.optype == 1) {
this.$api.post("baseinfo/v1/user/post", this.userModel).then(res => {
this.resetForm("inputUserForm");
this.get();
});
} else {
this.$api.post("baseinfo/v1/user/put", this.userModel).then(res => {
this.resetForm("inputUserForm");
this.get();
});
}
});
},
showAmount(item, type) {
this.amountModel.rest = item.RestAmount;
this.amountModel.opAmountType = type;
this.amountModel.showAmountDialog = true;
this.amountModel.UserId = item.Id;
},
updateAmount(formName) {
this.$refs[formName].validate(valid => {
if (!valid) return;
this.$api
.post("baseinfo/v1/user/UpdateAmount", this.amountModel)
.then(res => {
this.resetForm("inputAmountForm");
this.get();
});
});
},
showUpdateTest(item) {
this.showTestDialog = true;
this.testLimitModel.UserId = item.Id;
this.testLimitModel.limit = item.TestCountLimit;
},
updateTestLimit() {
this.$api
.post("baseinfo/v1/user/UpdateTestCount", this.testLimitModel)
.then(res => {
this.resetForm("inputTestForm");
this.get();
});
},
showAmountDetail(item) {
this.showDetailDialog = true;
this.$api
.get("baseinfo/v1/user/AmountDetail?userId=" + item.Id)
.then(res => {
this.detailAmountData = res.Data;
});
},
dataExport(){
this.$api.getDownloadFile("/baseinfo/v1/user/Export");
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,302 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-plus" @click="add">添加会员</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入会员号/名称" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" size="medium" :height="$getHeight(100)" row-key="Id" border>
<el-table-column prop="LoginCode" label="会员号" width="120px">
<template slot-scope="scope">
<phoneHide :text="scope.row.LoginCode"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="CreateTime" label="注册时间" width="160px"></el-table-column>
<el-table-column prop="CreateType" label="注册方式" :formatter="formatterCreateType"></el-table-column>
<el-table-column prop="RestAmount" label="余额"></el-table-column>
<el-table-column prop="RestAmount" label="测试限额/领用数">
<template slot-scope="scope">
{{scope.row.TestCountLimit==0?'3':scope.row.TestCountLimit}}/{{scope.row.UseTestCount==0?'--':scope.row.UseTestCount}}
</template>
</el-table-column>
<el-table-column label="操作" width="400px">
<template slot-scope="scope">
<span class="handel cursor edit" @click="showUpdateTest(scope.row)">设置测试</span>
<router-link :to="{name:'account',query:{userId:scope.row.Id}}">
<span class="handel cursor edit">账号</span>
</router-link>
<router-link :to="{name:'userprice',query:{id:scope.row.Id}}">
<span class="handel cursor edit">会员价</span>
</router-link>
<span class="handel cursor edit" @click="edit(scope.row)">编辑</span>
<span class="handel cursor edit" @click="showAmountDetail(scope.row)">明细</span>
<el-popover placement="bottom" trigger="hover" width="180">
<div class="popover_box">
<span>QQ号{{scope.row.QQ||'--'}}</span>
<span>微信{{scope.row.Wx||'--'}}</span>
<span>淘宝{{scope.row.TaoBao||'--'}}</span>
<span>邮箱:{{scope.row.Email||'--'}}</span>
</div>
<span class="handel cursor more" slot="reference">更多</span>
</el-popover>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
<el-dialog title="会员维护" :visible.sync="showDialog" width="400px">
<el-form :model="userModel" :rules="rules" ref="inputUserForm" label-width="80px">
<el-form-item prop="LoginCode" label="登录名称">
<el-input v-model="userModel.LoginCode" :disabled="optype==2" size="small"></el-input>
</el-form-item>
<el-form-item prop="Password" label="密码">
<el-input v-model="userModel.Password" show-password size="small"></el-input>
</el-form-item>
<el-form-item prop="Phone" label="手机号">
<el-input v-model="userModel.Phone" size="small"></el-input>
</el-form-item>
<el-form-item prop="QQ" label="QQ号">
<el-input v-model="userModel.QQ" size="small"></el-input>
</el-form-item>
<el-form-item prop="Wx" label="微信">
<el-input v-model="userModel.Wx" size="small"></el-input>
</el-form-item>
<el-form-item prop="TaoBao" label="淘宝">
<el-input v-model="userModel.TaoBao" size="small"></el-input>
</el-form-item>
<el-form-item prop="Email" label="邮箱">
<el-input v-model="userModel.Email" size="small"></el-input>
</el-form-item>
<el-form-item prop="Remark" label="备注">
<el-input v-model="userModel.Remark" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputUserForm')"> </el-button>
<el-button type="primary" @click="save('inputUserForm')">确定</el-button>
</span>
</el-dialog>
<el-dialog
:title="amountModel.opAmountType==1?'充值':'扣费'"
:visible.sync="amountModel.showAmountDialog"
width="300px"
>
<el-form :model="amountModel" :rules="amountRules" ref="inputAmountForm" label-width="80px">
<el-form-item prop="rest" label="当前余额">
<el-input v-model="amountModel.rest" size="small" disabled></el-input>
</el-form-item>
<el-form-item prop="amount" :label="amountModel.opAmountType==1?'充值金额':'扣费金额'">
<el-input v-model="amountModel.amount" size="small" type="number"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputAmountForm')"> </el-button>
<el-button type="primary" @click="updateAmount('inputAmountForm')">确定</el-button>
</span>
</el-dialog>
<el-dialog title="测试限额设置" :visible.sync="showTestDialog" width="300px">
<el-form :model="testLimitModel" ref="inputTestForm" label-width="80px">
<el-form-item prop="limit" label="限制次数">
<el-input v-model="testLimitModel.limit" size="small" type="number"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm('inputTestForm')"> </el-button>
<el-button type="primary" @click="updateTestLimit()">确定</el-button>
</span>
</el-dialog>
<el-dialog title="资金明细" :visible.sync="showDetailDialog" width="500px">
<el-table
:data="detailAmountData"
size="medium"
:height="$getHeight(300)"
row-key="Id"
border
>
<el-table-column prop="ScoreTypeName" label="资金项目"></el-table-column>
<el-table-column prop="ScoreValue" label="金额"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
export default {
name: "userIndex",
components: {
cutTip: () => import("@/components/common/cutTip"),
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
isRoot:false,
loading: false,
showDialog: false,
showTestDialog: false,
showDetailDialog: false,
optype: 1, //1:添加 2编辑
userModel: {
LoginCode: "",
Phone: "",
Password: "",
Remark: ""
},
amountModel: {
rest: 0,
amount: 0,
opAmountType: 1, ////1:充值 2扣款
showAmountDialog: false
},
testLimitModel: {
userId: 0,
limit: 3
},
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
rules: {
LoginCode: [this.$vaild.required("登录名称")],
Phone: [this.$vaild.required("手机号")],
Password: [this.$vaild.required("密码")]
},
amountRules: {
// amount: [{ type: 'number', message: '金额必须为数字值'}],
},
detailAmountData: [],
formatterCreateType(row, column, cellValue, index) {
switch (cellValue) {
case 1:
return "管理员添加";
case 2:
return "用户注册";
case 3:
return "淘宝注册";
}
return "";
}
};
},
created() {
this.$store.commit("setCurrentNav", "用户管理>>用户查询");
var currentUser=this.$local.getUserByCache();
this.IsRoot=currentUser.Manager.IsRootUser;
},
methods: {
search(){
if(this.searchModel.keyWord==''){
this.$warn("请输入查询关键字");
return;
}
this.searchModel.PageIndex=1;
this.get();
},
get() {
this.$api.get("baseinfo/v1/user/SearchInfo", this.searchModel).then(res => {
this.retData = res;
});
},
del(item) {
var that = this;
this.$confirm("确定删除?", "", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(_ => {
this.$api.post("baseinfo/v1/user/Delete?id=" + item.Id).then(res => {
that.get();
});
});
},
add() {
this.showDialog = true;
this.optype = 1;
},
edit(item) {
this.showDialog = true;
this.optype = 2;
this.userModel = clone(item);
},
resetForm(formName) {
this.$refs[formName].resetFields();
this.showDialog = false;
this.amountModel.showAmountDialog = false;
this.showTestDialog = false;
},
save(formName) {
this.$refs[formName].validate(valid => {
if (!valid) return;
if (this.optype == 1) {
this.$api.post("baseinfo/v1/user/post", this.userModel).then(res => {
this.resetForm("inputUserForm");
// this.get();
});
} else {
this.$api.post("baseinfo/v1/user/put", this.userModel).then(res => {
this.resetForm("inputUserForm");
// this.get();
});
}
});
},
showAmount(item, type) {
this.amountModel.rest = item.RestAmount;
this.amountModel.opAmountType = type;
this.amountModel.showAmountDialog = true;
this.amountModel.UserId = item.Id;
},
updateAmount(formName) {
this.$refs[formName].validate(valid => {
if (!valid) return;
this.$api
.post("baseinfo/v1/user/UpdateAmount", this.amountModel)
.then(res => {
this.resetForm("inputAmountForm");
this.get();
});
});
},
showUpdateTest(item) {
this.showTestDialog = true;
this.testLimitModel.UserId = item.Id;
this.testLimitModel.limit = item.TestCountLimit;
},
updateTestLimit() {
this.$api
.post("baseinfo/v1/user/UpdateTestCount", this.testLimitModel)
.then(res => {
this.resetForm("inputTestForm");
this.get();
});
},
showAmountDetail(item) {
this.showDetailDialog = true;
this.$api
.get("baseinfo/v1/user/AmountDetail?userId=" + item.Id)
.then(res => {
this.detailAmountData = res.Data;
});
},
dataExport(){
this.$api.getDownloadFile("/baseinfo/v1/user/Export");
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,188 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button
size="small"
type="primary"
icon="el-icon-sold-out"
v-if="$local.isRoot()"
@click="dataExport"
>导出</el-button>
<!-- <el-button size="small" type="primary" icon="el-icon-sold-out" @click="dataExport" v-if="$local.isRoot()">导出</el-button> -->
<div class="search-box">
<el-date-picker
size="small"
v-model="dateRange1"
type="daterange"
range-separator=""
start-placeholder="A开始日期"
end-placeholder="A结束日期"
></el-date-picker>
<el-date-picker
size="small"
v-model="dateRange2"
type="daterange"
range-separator=""
start-placeholder="B开始日期"
end-placeholder="B结束日期"
></el-date-picker>
<el-select
v-model="searchModel.profile"
clearable
size="small"
placeholder="状态"
>
<el-option v-for="item in types" :key="item.label" :label="item.label" :value="item.value"></el-option>
</el-select>
<el-input v-model="searchModel.keyWord" placeholder="请输入会员号" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="search"></el-button>
</el-input>
</div>
</div>
<el-table :data="retData.Data" size="medium" :height="$getHeight(300)"
@sort-change="sort"
row-key="Id" border>
<el-table-column prop="Profile" label="状态" width="240">
<template slot-scope="scope">
<el-dropdown size="small" split-button type="primary">
{{scope.row.UserInfo.Profile}}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="changeProfile(scope.row,'已完成')">已完成</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'高意向客户')">高意向客户</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'待跟进-消费减少')">待跟进-消费减少</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'待跟进-未购买')">待跟进-未购买</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'跟进超时-消费减少')">跟进超时-消费减少</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'跟进超时-未购买')">跟进超时-未购买</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'流失-需求减少')">流失-需求减少</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'流失-暂时不用')">流失-暂时不用</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'流失-价格问题')">流失-价格问题</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'流失-产品问题')">流失-产品问题</el-dropdown-item>
<el-dropdown-item @click.native="changeProfile(scope.row,'跟进超时')">跟进超时</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
<el-table-column prop="UserName" label="用户">
<template slot-scope="scope">
<phoneHide :text="scope.row.UserName"></phoneHide>
</template>
</el-table-column>
<el-table-column prop="UserName" label="联系信息">
<template slot-scope="scope">
<p v-if="scope.row.UserInfo.Wx">微信:{{scope.row.UserInfo.Wx}}</p>
<p v-if="scope.row.UserInfo.QQ">QQ:{{scope.row.UserInfo.QQ}}</p>
<p v-if="scope.row.UserInfo.TaoBao">淘宝:{{scope.row.UserInfo.TaoBao}}</p>
<p v-if="scope.row.UserInfo.WangWang">旺旺:{{scope.row.UserInfo.WangWang}}</p>
</template>
</el-table-column>
<el-table-column prop="CreateTime" label="注册时间"></el-table-column>
<el-table-column prop="PrevMonthAmount" label="消费金额A" sortable="custom"></el-table-column>
<el-table-column prop="MonthAmount" label="消费金额B" sortable="custom"></el-table-column>
<el-table-column prop="AddAmount" label="对比增长金额" sortable="custom">
<!-- <template slot-scope="scope">
{{scope.row.MonthAmount-scope.row.PrevMonthAmount}}
</template> -->
</el-table-column>
<el-table-column prop="TotalAccountCount" label="账户总数" sortable="custom"></el-table-column>
<el-table-column prop="UsingAccountCount" label="使用中个数" sortable="custom"></el-table-column>
<el-table-column prop="ExpirdAccountCount" label="过期个数" sortable="custom"></el-table-column>
</el-table>
<div class="block">
<el-pagination
v-if="retData.Data.length>0"
@current-change="get"
:page-size="50"
:current-page.sync="searchModel.PageIndex"
layout="total,prev, pager, next"
:total="retData.TotalCount"
></el-pagination>
</div>
</div>
</template>
<script>
import * as dateUtil from '@/extend/js/dateFormatUtil';
export default {
name: "userIndex",
components: {
phoneHide: () => import("@/components/common/phonehide")
},
data() {
return {
loading: false,
retData: { TotalCount: 0, Data: [] },
dateRange1: [],
dateRange2: [],
searchModel: {
PageIndex: 1,
keyWord: "",
sortLable:"",
sortOrder:0,
profile:"",
},
types:[{ value: '已完成', label: '已完成'},
{ value: '高意向客户', label: '高意向客户'},
{ value: '待跟进-消费减少', label: '待跟进-消费减少'},
{ value: '待跟进-未购买', label: '待跟进-未购买'},
{ value: '跟进超时-消费减少', label: '跟进超时-消费减少'},
{ value: '跟进超时-未购买', label: '跟进超时-未购买'},
{ value: '流失-需求减少', label: '流失-需求减少'},
{ value: '流失-暂时不用', label: '流失-暂时不用'},
{ value: '流失-价格问题', label: '流失-价格问题'},
{ value: '流失-产品问题', label: '流失-产品问题'},
{ value: '跟进超时', label: '跟进超时'},
]
}
},
created() {
this.$store.commit("setCurrentNav", "用户管理>>消费统计");
this.dateRange1[0]=dateUtil.getLastMonthStartDate();
this.dateRange1[1]=dateUtil.getLastMonthCurrentDate();
this.dateRange2[0]=dateUtil.getMonthStartDate();
this.dateRange2[1]=dateUtil.getMonthCurrentDate();
this.get();
},
methods: {
sort({column, prop, order }){
console.log(column)
console.log(prop)
console.log(order)
this.searchModel.sortLable=prop;
this.searchModel.sortOrder=order=="ascending"?0:1;
this.search()
},
changeProfile(row,command){
row.UserInfo.Profile=command;
this.$api
.post("baseinfo/v1/user/UpdateProfile",{UserId:row.UserInfo.Id,Profile:command})
.then(res => {});
},
search() {
this.searchModel.PageIndex = 1;
this.get();
},
get() {
this.loading = true;
if (this.dateRange1 && this.dateRange1.length == 2) {
this.searchModel.bTime1 = this.dateRange1[0];
this.searchModel.eTime1 = this.dateRange1[1];
}
if (this.dateRange2 && this.dateRange2.length == 2) {
this.searchModel.bTime2 = this.dateRange2[0];
this.searchModel.eTime2 = this.dateRange2[1];
}
this.$api
.get("course/v1/order/UserConsumeStatistics", this.searchModel)
.then(res => {
this.retData = res;
this.loading = false;
});
},
dataExport() {
this.$api.getDownloadFile("/course/v1/order/ExportUserConsumeStatistics", this.searchModel);
}
}
};
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,197 @@
<template>
<div v-loading="loading">
<div class="heior_box">
<el-button size="small" type="primary" icon="el-icon-plus" @click="showDialogDiscount=true">折扣价格</el-button>
<div class="search-box">
<el-input v-model="searchModel.keyWord" placeholder="请输入套餐名称/标题" clearable size="small">
<el-button slot="append" icon="el-icon-search" @click="get"></el-button>
</el-input>
</div>
</div>
<div>
<el-tabs tab-position="left" :style="$getStyleHeight(100)">
<el-tab-pane :label="item.Product.Name" v-for="(item,index) in product" :key="index">
<el-table
:data="item.PackageUserPrices"
row-key="Id"
border
size="medium"
:height="$getHeight(100)"
>
<el-table-column prop="Package.Name" label="套餐名称"></el-table-column>
<el-table-column prop="Package.Price" label="原价格"></el-table-column>
<el-table-column prop="UserPrice.UserPrice" label="会员价格">
<template slot-scope="scope">
{{scope.row.UserPrice.UserPrice||'--'}}
</template></el-table-column>
<el-table-column prop="UserPrice.RefundDayPrice" label="退款单价"></el-table-column>
<el-table-column prop="UserPrice.Remark" label="说明"></el-table-column>
<el-table-column prop="UserPrice.Status" label="启用状态" width="100">
<template slot-scope="scope">
<el-switch
v-model="scope.row.UserPrice.Status"
:active-value="1"
:inactive-value="0"
active-color="#13ce66"
inactive-color="#dcdfe6"
@change="changeStatus(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<span class="handel cursor edit" @click="goEdit(scope.row)">编辑</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
<el-dialog title="会员价格" :visible.sync="showDialog" width="400px">
<el-form
:model="current"
:rules="rules"
ref="inputPackageForm"
label-width="80px"
>
<el-form-item prop="Name" label="套餐名称">
<el-input v-model="current.Name" size="small" disabled=""></el-input>
</el-form-item>
<el-form-item prop="Price" label="原价格">
<el-input v-model="current.Price" type="number" size="small" disabled=""></el-input>
</el-form-item>
<el-form-item prop="MinPrice" label="会员价格">
<el-input v-model="current.UserPrice" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="RefundDayPrice" label="退款单价">
<el-input v-model="current.RefundDayPrice" type="number" size="small"></el-input>
</el-form-item>
<el-form-item prop="Remark" label="说明">
<el-input v-model="current.Remark" size="small"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="resetForm"> </el-button>
<el-button type="primary" @click="save">确定</el-button>
</span>
</el-dialog>
<el-dialog title="价格折扣" :visible.sync="showDialogDiscount" width="300px">
<el-form
:model="current"
:rules="rules"
ref="inputPackageForm"
label-width="80px"
>
<el-form-item prop="Name" label="折扣方案">
<el-select size="small" v-model="currentDiscount.schemeId">
<el-option v-for="(item,index) in productDiscounts" :key="index" :label="item.Name" :value="item.Id"></el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="showDialogDiscount=false"> </el-button>
<el-button type="primary" @click="setDiscount">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "treeTable",
components: {},
data() {
return {
loading: false,
showDialog:false,
showDialogDiscount:false,
retData: { TotalCount: 0, Data: [] },
searchModel: {
PageIndex: 1,
keyWord: ""
},
product:[],
current: {
Name:"",
Remark:'',
Price:0,
UserPrice:0,
UserId:0,
PackageId:0,
ProductId:0,
RefundDayPrice:0,
},
rules:{},
currentDiscount:{
schemeId:null,
userId:null,
},
productDiscounts:[]
};
},
created() {
this.$store.commit("setCurrentNav", "用户管理>>会员价");
this.current.UserId=this.$route.query.id;
this.currentDiscount.userId=this.$route.query.id;
this.get();
this.getProductDiscounts();
},
methods: {
get() {
this.$api.get("course/v1/product/ProductUserPrice?userId="+this.current.UserId).then(res => {
this.product = res.Data;
});
},
getProductDiscounts(){
this.$api
.get("course/v1/scheme/page")
.then(res => {
this.productDiscounts= res.Data;
});
},
goEdit(item) {
console.log(item)
this.showDialog = true;
this.current.Name =item.Package.Name;
this.current.Price =item.Package.Price;
this.current.ProductId =item.Package.ProductId;
this.current.PackageId =item.Package.Id;
this.current.UserPrice =item.UserPrice.UserPrice;
this.current.RefundDayPrice =item.UserPrice.RefundDayPrice;
},
save() {
this.$api
.post("course/v1/product/PutUserPrice", this.current)
.then(res => {
this.resetForm();
this.get();
});
},
changeStatus(item) {
this.$api
.post("course/v1/product/SetUserPriceStatus?id=" + item.UserPrice.Id)
.then(res => {
item.Status = res.Data;
});
},
setDiscount() {
if(!this.currentDiscount.schemeId){
this.$warn('请选择方案')
return ;
}
this.$api
.post("course/v1/scheme/SetUserDiscount",this.currentDiscount)
.then(res => {
this.showDialogDiscount=false;
this.get();
});
},
resetForm() {
this.$refs["inputPackageForm"].resetFields();
this.showDialog = false;
}
}
};
</script>
<style scoped>
</style>

338
src/extend/api/api.js Normal file
View File

@@ -0,0 +1,338 @@
import axios from "axios";
import qs from 'qs';
import router from "../../router";
import { Message } from "element-ui";
import saveAs from "./../lib/filesaver";
import NProgress from 'nprogress';
import './../../../static/css/nprogress.css';
var http = require("./httpurl");
function getUserToken(){
var data = window.localStorage.getItem("etorcurrentuser");
if(data)
return JSON.parse(data).Token;
return "";
}
var bmsAxios = axios.create({
// timeout: 120000,
withCredentials: true,
baseURL: http.baseURL,
headers: {
post: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
}
}
});
bmsAxios.interceptors.request.use(
config => {
var data = "";
if (window.localStorage.getItem("etorcurrentuser")) {
data = window.localStorage.getItem("etorcurrentuser");
}
if (data == "") {
config.headers.token = "";
config.headers.sid = sid || 0;
} else {
config.headers.token = JSON.parse(data).Token;
//var TenantId = JSON.parse(data).Manager.TenantId;
//var OperaterID = JSON.parse(data).Manager.ID;
}
var sid = window.localStorage.getItem("sid");
config.headers.sid = sid || 0;
removeNullAndUndefinedProperty(config.data)//没用的参数不要传
removeNullAndUndefinedProperty(config.params)//没用的参数不要传
if (config.url != "Permission/AgainGetToken") {
window.localStorage.setItem(
"lastrequesttime",
JSON.stringify(Date.now())
); //记录用户最后请求时间
}
//debugger
return config;
},
error => {
return Promise.reject(error);
}
);
// 返回状态
let onceMessage = false;
bmsAxios.interceptors.response.use(
res => {
return res;
},
error => {
//有异常
if (error.response) {
switch (error.response.status) {
case 401:
if (onceMessage) return;
onceMessage = true;
// Message.error("信息过期,请重新登陆");
router.replace({
path: "/login",
query: {
redirect: router.currentRoute.fullPath
}
});
break;
case 204:
Message.error("暂无数据");
break;
}
}
return Promise.reject(error);
}
);
export function get(url, config) {
return new Promise((resolve, reject) => {
bmsAxios.get(url, {
params: config,
paramsSerializer: function (params) {
return qs.stringify(params, { arrayFormat: 'repeat' })
}
}).then(
response => {
if (response.data.Code == 10000) {
return resolve(response.data);
} else {
Message.error(response.data.Message||"数据异常")
}
},
err => {
reject(err);
}
)
.catch(error => {
reject(error);
});
});
}
export function post(url, params) {
return new Promise((resolve, reject) => {
bmsAxios.post(url, params).then(
response => {
if (response.data.Code == 10000) {
Message.success("操作成功")
return resolve(response.data);
} else {
Message.error(response.data.Message)
}
},
err => {
Message.error("操作失败")
reject(err);
}
)
.catch(error => {
Message.error("操作异常")
reject(error);
});
});
}
export function put(url, params) {
return new Promise((resolve, reject) => {
bmsAxios.put(url, params).then(
response => {
resolve(response.data);
},
err => {
reject(err);
}
)
.catch(error => {
reject(error);
});
});
}
export function del(url, config) {
return new Promise((resolve, reject) => {
bmsAxios.delete(url, { params: config }).then(
response => {
resolve(response.data);
},
err => {
reject(err);
}
)
.catch(error => {
reject(error);
});
});
}
/** 使用 get HTTP Method 下载文件 */
export function getDownloadFile(url, params, name) {
NProgress.start();
return new Promise((resolve, reject) => {
bmsAxios
.get(url, {
params: {
...params,
params: params
},
responseType: "blob"
})
.then(response => {
//确定最终文件名
const fileNameHeader = "x-suggested-filename";
let suggestedFileName = response.headers[fileNameHeader] || name;
if (suggestedFileName)
suggestedFileName = decodeURIComponent(suggestedFileName);
const effectiveFileName =
suggestedFileName === undefined ? "untitled" : suggestedFileName;
//长度为零给出提示,扔出错误
if (response.data.size == 0) throw new Error("文件长度为0");
//返回json进行解析获取Message扔出错误
if (response.data.type == "application/json") {
let reader = new FileReader();
reader.onload = function (event) {
var message = JSON.parse(event.target.result);
reject(new Error(message.Message)); //拒绝
};
reader.readAsText(response.data);
} else {
saveAs(response.data, effectiveFileName);
resolve(); //解决
}
})
.catch(e => reject(e)).finally(function () {
NProgress.done();
}); //拒绝
});
}
export function all(urlArr) { //并发请求
if (urlArr.length > 6) {
throw '当前不支持数量大于6个的并发请求';
}
return new Promise((resolve, reject) => {
axios.all(urlArr).then(
axios.spread((v0, v1, v2, v3, v4, v5) => {
let ret = {};
arguments.forEach((item, idx) => {
if (item)
ret[`ret${idx}`] = item
})
resolve(item);
}),
err => {
reject(err);
}
)
.catch(error => {
reject(error);
});
});
}
export function axiosHttp(url, params, type = 'get') {
return new Promise((resolve, reject) => {
axios[type](url, { params: params }).then(
response => {
resolve(response.data);
},
err => {
reject(err);
}
).catch(error => {
reject(error);
});
});
}
function removeNullAndUndefinedProperty(model) {//移除对象中值为null、undefined的属性
if (model) {
for (let key in model) {
if (model[key] === null || typeof (model[key]) === 'undefined') {
delete model[key]
}
}
}
}
function createFileInput(accept, onSelect) {
var lastFileInput = document.getElementById("f1_id");
if (lastFileInput != null) {
document.body.removeChild(lastFileInput);
}
lastFileInput = document.createElement("input");
lastFileInput.type = "file";
lastFileInput.name = "f1";
lastFileInput.id = "f1_id";
accept && (lastFileInput.accept = accept);
lastFileInput.setAttribute("style", "display:none;");
document.body.appendChild(lastFileInput);
lastFileInput.onchange = function (e) {
var f = lastFileInput.files[0];
onSelect && onSelect(f)
}
return lastFileInput;
}
export function getUuid(length) {
return Number(Math.random().toString().substr(3, length) + Date.now()).toString(36);
}
//通过axios上传文件
export function upload(url, uconfig) {
var uconfig = uconfig || {};
var params = uconfig.params || {};
var accept = uconfig.accept || "image/gif, image/jpeg,image/jpg,image/png,image/*";
var onProgress = uconfig.onProgress || function () { };
var onStart = uconfig.onStart || function () { };
var uuid = uconfig.uuid || getUuid(10);
let config = {
headers: {
"Content-Type": "multipart/form-data",
"token":getUserToken(),
"sid":0
},
transformRequest: [function (data) {
return data
}],
onUploadProgress: e => {
var completeProgress = ((e.loaded / e.total * 100) | 0);
onProgress && onProgress(uuid, completeProgress);
console.log("onUploadProgress:" + completeProgress);
}
}
let formData = new FormData();
for (let key of Object.keys(params)) {
formData.append(key, params[key] !== null ? params[key] : '')
}
return new Promise((resolve, reject) => {
var lastFileInput = createFileInput(accept, file => {
if (!file)
reject("没有选择文件")
formData.append(file.name, file);
onStart && onStart(uuid, file);
var uploadAxios = axios.create({
withCredentials: true,
baseURL: http.baseURL
});
uploadAxios.post(url, formData, config).then(
response => { resolve(response.data) },
err => { reject(err) }
).catch(error => { reject(error) })
})
lastFileInput.click();
});
}
export default {
baseURL: http.baseURL,
get,
post,
del,
put,
upload,//:httpfile.upload,
getDownloadFile,
all(urlArr) { //并发请求
return all(urlArr);
}
};

224
src/extend/api/httpfile.js Normal file
View File

@@ -0,0 +1,224 @@
function then(onthen) {
this._then_callback = function (p) { };
this._error_callback = function (p) { };
this._on_then = onthen;
}
function JsFormData() {
this.boundry = "";
this.formName = "";
this.formValue = "";
}
JsFormData.prototype.constructor = JsFormData;
JsFormData.prototype.getFormString = function () {
return "--" + this.boundry + "\r\nContent-Disposition:form-data; name=" + this.formName + "\r\n\r\n" + this.formValue + "\r\n";
};
JsFormData.prototype.toString = function () {
return this.getFormString();
};
function JsFileFormData() {
this.formFileName = "";
this.contentType = "";
JsFormData.call(this);
}
JsFileFormData.prototype = new JsFileFormData();
JsFileFormData.prototype.constructor = JsFileFormData;
JsFileFormData.prototype.getFormString = function () {
return "--" + this.boundry + "\r\nContent-Disposition:form-data; name=" + this.formName + "; filename=" + this.formFileName + "\r\nContent-Type: " + this.contentType + "\r\n\r\n" + this.formValue + "\r\n";
};
JsFileFormData.prototype.toString = function () {
return this.getFormString();
};
then.prototype.constructor = then;
then.prototype = new then();
then.prototype.then = function (p) {
this._then_callback = p;
this._on_then();
return this;
};
then.prototype.error = function (p) {
this._error_callback = p;
return this;
}
then.prototype.invoke_then = function (p) {
this._then_callback(p);
return this;
}
then.prototype.invoke_error = function (p) {
this._error_callback(p);
return this;
}
function JsHttpHelper() {
this.formData = new Array();
}
JsHttpHelper.prototype.boundry = Math.random().toString().substr(2),
JsHttpHelper.prototype.addFormValue = function (key, value) {
var f = new JsFormData();
f.formName = key;
f.formValue = value;
f.boundry = this.boundry;
this.formData.push(f);
};
JsHttpHelper.prototype.addFileFormValue = function (key, fname, fcontent) {
var f = new JsFileFormData();
f.formName = key;
f.formValue = fcontent;
f.contentType = "application/octet-stream";
f.formFileName = fname;
f.boundry = this.boundry;
this.formData.push(f);
};
JsHttpHelper.prototype.postMultipartFormData = function (url, postCallBack, updateProgress, errorFunc) {
var xhr = new XMLHttpRequest();
// xhr.onloadend = function (e) {
// if (e.total > 0)
// postCallBack(e, xhr);
// };
xhr.onload = function (e) {
if((e.status >= 200 && e.status < 300) || e.status == 304){
postCallBack(e, xhr);
}
};
xhr.onabort = errorFunc;
xhr.onerror = errorFunc;
xhr.ontimeout = errorFunc;
if (updateProgress != null) {
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
updateProgress((e.loaded / e.total) * 100);
}
}
};
xhr.open("POST", url, true);
xhr.setRequestHeader("content-type", "multipart/form-data; charset=utf-8; boundary=" + this.boundry);
var postBody = "";
// console.log(this.formData);
for (var s = 0; s < this.formData.length; s++) {
postBody += this.formData[s].getFormString();
}
postBody += "--" + this.boundry + "--\r\n";
xhr.send(postBody);
this.formData = new Array();
console.log(this.formData);
};
JsHttpHelper.prototype.constructor = JsHttpHelper;
var lastFileInput;
function compress_image(base64Image, callback, wd) {
if (wd == null || wd == undefined) {
wd = 200;
}
var image = document.createElement("img");
image.onload = function () {
var square = wd;
var canvas = document.createElement('canvas');
var HoverW = this.height / this.width;
var hNew = wd * HoverW;
var wNew = wd;
canvas.width = wNew;
canvas.height = hNew;
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(this, 0, 0, this.width, this.height, 0, 0, wNew, hNew);
var data = canvas.toDataURL('image/jpeg');
//console.log("compress_image raw " + base64Image.length + " now " + data.length + " decrease rate " + (base64Image.length - data.length) / base64Image.length);
callback(data);
};
image.setAttribute('src', base64Image);
}
function read_file_base64String(funcReadOver, funcReadOutoffLimit, sizeLimit) {
if (sizeLimit == null || sizeLimit == undefined) {
sizeLimit = 200;
}
lastFileInput = document.getElementById("f1_id");
if (lastFileInput != null) {
document.body.removeChild(lastFileInput);
lastFileInput = null;
}
if (lastFileInput == null) {
lastFileInput = document.createElement("input");
lastFileInput.type = "file";
lastFileInput.name = "f1";
lastFileInput.id = "f1_id";
lastFileInput.setAttribute("style", "display:none;");
document.body.appendChild(lastFileInput);
}
lastFileInput.onchange = null;
lastFileInput.onchange = function (e) {
var f = lastFileInput.files[0];
var reader = new FileReader();
var sz = ((f.size / 1024) / 1024);
//console.log(sz + "m");
reader.onloadend = function (e) {
compress_image(e.target.result, function (bs64) {
funcReadOver(bs64);
}, sizeLimit);
//1M == 1398211
};
reader.readAsDataURL(f);
};
lastFileInput.click();
}
function upload(url,func, keyValues, isfile, accept) {
// var proc = progressBar.start();
lastFileInput = document.getElementById("f1_id");
if (lastFileInput != null) {
document.body.removeChild(lastFileInput);
lastFileInput = null;
}
if (lastFileInput == null) {
lastFileInput = document.createElement("input");
lastFileInput.type = "file";
lastFileInput.name = "f1";
lastFileInput.id = "f1_id";
accept && (lastFileInput.accept = accept);
lastFileInput.setAttribute("style", "display:none;");
document.body.appendChild(lastFileInput);
}
lastFileInput.onchange = null;
lastFileInput.onchange = function (e) {
var f = lastFileInput.files[0];
var reader = new FileReader();
reader.onloadend = function (e) {
var sz = ((f.size / 1024) / 1024);
if (isfile != undefined && isfile!=='') {
var http = new JsHttpHelper();
http.addFileFormValue("f2", f.name, e.target.result);
if(keyValues){
for (var key in keyValues) {
http.addFormValue(keyValues[key].key, keyValues[key].value);
}
}
http.postMultipartFormData(url, func, null, function (e, xhr) {
});
} else {
compress_image(e.target.result, function (bs64) {
var http = new JsHttpHelper();
http.addFileFormValue("f2", f.name, bs64);
if(keyValues){
for (var key in keyValues) {
http.addFormValue(keyValues[key].key, keyValues[key].value);
}
}
http.postMultipartFormData(url, func, null, function (e, xhr) {
});
});
}
//1M == 1398211
};
reader.readAsDataURL(f);
};
lastFileInput.click();
}
export default{
compress_image,
read_file_base64String,
upload
}

23
src/extend/api/httpurl.js Normal file
View File

@@ -0,0 +1,23 @@
//npm run build -- dev
//npm run build -- test
//npm run build -- prod
const devUrlNew ='http://localhost:5000/api/'
const testUrlNew = "http://localhost:5000/api/"
const prodUrlNew ="http://www.juip.com/api/";// "http://api.yk.hncore.net/api/"/"http://hapi.hncore.net/api"
var baseURL= devUrlNew
switch (process.env.NODE_ENV) {
case "development":
baseURL =devUrlNew
break;
case "test":
baseURL =testUrlNew
break;
case "production":
baseURL = prodUrlNew
break;
}
export {
baseURL
};

View File

@@ -0,0 +1,35 @@
<template>
<nav class="model-breadcrumbs">
<ol>
<li style="display:inline-block;" v-for="(item,index) in routes" :key="index">
<router-link style="color:#333" v-if="item.link" :to="item.link">{{item.name}}<span style="margin:0 .4em;">></span></router-link>
<span v-else>{{item.name}}</span>
</li>
</ol>
</nav>
</template>
<script>
export default {
props:{
routes:{
type:Array,
default:function(){
return []
}
}
}
}
</script>
<style scoped>
.model-breadcrumbs{
padding:15px;
border: 1px solid #dae1f2;
font-size:16px;
background: white;
border-radius: 5px;
width: 100%;
box-sizing: border-box;
color:#333;
}
</style>

View File

@@ -0,0 +1,38 @@
<template>
<el-dropdown @command="assignValue">
<el-button size="mini">
{{value.name}}<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="item" v-for="(item,index) in list" :key="item.code||index">{{item.name||1111}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
props: {
title: {
type: String,
default: 'drop down'
},
list: {
type: Array,
default: function () {
return [];
}
},
value:{
type:Object,
default:function(){
return {};
}
}
},
methods:{
assignValue:function(value){
this.$emit('input',value)
}
}
}
</script>

View File

@@ -0,0 +1,32 @@
<template>
<section class="model-empty" style="padding:30px;text-align:center;">
<figure :class="`model-empty-figure ${type}`"></figure>
<h2 style="font-size:14px;color:#999;font-weight:400;">{{title}}</h2>
<slot></slot>
</section>
</template>
<script>
export default {
props:{
type:{
type:String
},
title:{
type:String,
default:'还没有任何数据'
}
}
}
</script>
<style scoped>
.model-empty-figure{
height:100px;
background-repeat: no-repeat;
background-position:center top;
background-size:auto 100%;
background-image: url('/static/img/nodata.png');
}
.model-empty-figure.call{
background-image:url('/static/img/no-call.png');
}
</style>

View File

@@ -0,0 +1,10 @@
<template>
<div data-v-1aadaada="" class="table_tabs" style="justify-content: start;"><span data-v-1aadaada="">{{title}}</span></div>
</template>
<script>
export default {
props:{
title:String
}
}
</script>

View File

@@ -0,0 +1,23 @@
<template>
<div v-if="init||visible">
<slot></slot>
</div>
</template>
<script>
export default {
props:{
visible:{
type:Boolean,
default:true
}
},
data:function(){
init:false
},
watch:{
visible:function(value){
if(value) this.init=true;
}
}
}
</script>

View File

@@ -0,0 +1,83 @@
<template>
<div style="position:relative;" :is="tag" v-if="successCode.indexOf(code-0)!==-1||code==-1"
v-loading="animation?code==-1?true:false:false">
<slot></slot>
</div>
<div :is="tag" v-else :class="`${position} model-loading`" style="background-color:#fff;">
<div class="layout-td">
<h2 style="font-size:16px;margin-bottom:.6em"><span>错误({{code}})</span></h2>
<p>{{errorMessage}},
<span class="cursor" style="color:#6896ff" @click="reload">刷新页面</span>
或者<span class="cursor" style="color:#6896ff" @click="$emit('reloading')">重新加载</span>
</p>
</div>
</div>
</template>
<script>
export default {
props: {
position: {
type: String,
default: ''
},
tag: {
type: String,
default: 'div'
},
code: {
type: [String, Number],
default: -1
},
successCode: {
type: Array,
default: function () {
return [200, 10000, 304]
}
},
message: {
type: String,
default: '服务器繁忙'
},
animation:{
type:Boolean,
default:true
}
},
computed: {
errorMessage: function () {
return navigator.onLine ? '服务器繁忙' : '网络错误'
}
},
data: function () {
return {
product: process.env.NODE_ENV === 'production'
}
},
methods: {
reload: function () {
location.reload();
}
}
}
</script>
<style scoped>
.model-loading {
position: relative;
flex-wrap: wrap;
margin: 15px auto;
padding: 15px;
min-height: 50px;
color: #999;
font-size: 14px;
text-align: center;
background-color: #fff;
}
.model-loading.middle {
display: flex;
align-items: center;
justify-content: center;
}
</style>

View File

@@ -0,0 +1,3 @@
<template>
<p style="font-size:12px;color:#999;margin:.4em auto;"><slot></slot></p>
</template>

View File

@@ -0,0 +1,92 @@
<template>
<el-pagination
:style="[style.original,style[type]]"
:current-page.sync="currentPageSelf"
:page-sizes="pageSizes" :page-size.sync="pageSizeSelf" :layout="layout" :total="total">
</el-pagination>
</template>
<script>
const pageSize =20;
let style={
original:{
position:'static',
transform:'translate(0,0)',
textAlign:'center'
},
primary:{
backgroundColor:'#fff',
padding:'15px',
border:'1px solid #EBEEF5',
borderTop:0
}
};
export default {
props: {
type:{
type:String,
default:'primary'
},
pageSizes: {
type: Array,
default: function () {
return [1.5*pageSize, 2 * pageSize, 3 * pageSize, 5 * pageSize,10*pageSize]
}
},
pageSize: {
type: Number,
default:1.5*pageSize
},
layout: {
type: String,
default: 'total,sizes,prev, pager, next, jumper'
},
total: {
type: Number,
default: 0
},
currentPage:{
type: Number,
default:1
}
},
data:function(){
return {
style:style
}
},
computed: {
currentPageSelf: {
get: function () {
return this.currentPage
},
set: function (value){
this.$emit('update:currentPage', value);
}
},
pageSizeSelf:{
get:function(){
return this.pageSize
},
set:function(value){
this.$emit('update:pageSize',value);
}
}
},
watch:{
pageSize:function(){
this.emitChange()
},
currentPage:function(){
this.emitChange()
}
},
methods:{
emitChange:function(){
clearTimeout(this.timerId);
setTimeout(()=>{
this.$emit('change',[this.currentPage,this.pageSize]);
},80)
}
}
}
</script>

View File

@@ -0,0 +1,22 @@
<template>
<el-form style="background-color:#fdfdfe;padding:10px;" :inline="inline" :label-width="labelWidth">
<slot></slot>
<div class="layout-tr-between" style="width:100%;">
<div><slot name="left"></slot></div>
<div><slot name="right"></slot></div>
</div>
</el-form>
</template>
<script>
export default {
props:{
labelWidth:{
type:String
},
inline:{
type:Boolean,
default:true
}
}
}
</script>

View File

@@ -0,0 +1,99 @@
// Thanks to: https://github.com/calebroseland/vue-dom-portal
/**
* Get target DOM Node
* @param {(Node|string|Boolean)} [node=document.body] DOM Node, CSS selector, or Boolean
* @return {Node} The target that the el will be appended to
*/
function getTarget (node) {
if (node === void 0) {
return document.body
}
if (typeof node === 'string' && node.indexOf('?') === 0) {
return document.body
} else if (typeof node === 'string' && node.indexOf('?') > 0) {
node = node.split('?')[0]
}
if (node === 'body' || node === true) {
return document.body
}
return node instanceof window.Node ? node : document.querySelector(node)
}
function getShouldUpdate (node) {
// do not updated by default
if (!node) {
return false
}
if (typeof node === 'string' && node.indexOf('?') > 0) {
try {
const config = JSON.parse(node.split('?')[1])
return config.autoUpdate || false
} catch (e) {
return false
}
}
return false
}
const directive = {
inserted (el, { value }, vnode) {
el.className = el.className ? el.className + ' v-transfer-dom' : 'v-transfer-dom'
const parentNode = el.parentNode
var home = document.createComment('')
var hasMovedOut = false
if (value !== false) {
parentNode.replaceChild(home, el) // moving out, el is no longer in the document
getTarget(value).appendChild(el) // moving into new place
hasMovedOut = true
}
if (!el.__transferDomData) {
el.__transferDomData = {
parentNode: parentNode,
home: home,
target: getTarget(value),
hasMovedOut: hasMovedOut
}
}
},
componentUpdated (el, { value }) {
const shouldUpdate = getShouldUpdate(value)
if (!shouldUpdate) {
return
}
// need to make sure children are done updating (vs. `update`)
var ref$1 = el.__transferDomData
// homes.get(el)
var parentNode = ref$1.parentNode
var home = ref$1.home
var hasMovedOut = ref$1.hasMovedOut // recall where home is
if (!hasMovedOut && value) {
// remove from document and leave placeholder
parentNode.replaceChild(home, el)
// append to target
getTarget(value).appendChild(el)
el.__transferDomData = Object.assign({}, el.__transferDomData, { hasMovedOut: true, target: getTarget(value) })
} else if (hasMovedOut && value === false) {
// previously moved, coming back home
parentNode.replaceChild(el, home)
el.__transferDomData = Object.assign({}, el.__transferDomData, { hasMovedOut: false, target: getTarget(value) })
} else if (value) {
// already moved, going somewhere else
getTarget(value).appendChild(el)
}
},
unbind: function unbind (el, binding) {
el.className = el.className.replace('v-transfer-dom', '')
if (el.__transferDomData && el.__transferDomData.hasMovedOut === true) {
el.__transferDomData.parentNode && el.__transferDomData.parentNode.appendChild(el)
}
el.__transferDomData = null
}
}
export default directive

View File

@@ -0,0 +1,49 @@
function getTarget (node = document.body) {
if (node === true) return document.body
return node instanceof window.Node ? node : document.querySelector(node)
}
const homes = new Map()
const directive = {
inserted (el, { value }, vnode) {
console.log('v-transfer-dom:inserted')
const { parentNode } = el
const home = document.createComment('')
let hasMovedOut = false
if (value !== false) {
parentNode&&parentNode.replaceChild(home, el) // moving out, el is no longer in the document
getTarget(value).appendChild(el) // moving into new place
hasMovedOut = true
}
if (!homes.has(el)) homes.set(el, { parentNode, home, hasMovedOut }) // remember where home is or should be
},
componentUpdated (el, { value }) { // need to make sure children are done updating (vs. `update`)
console.log('v-transfer-dom:componentUpdated')
const { parentNode, home, hasMovedOut } = homes.get(el) // recall where home is
if (!hasMovedOut && value) {
// remove from document and leave placeholder
parentNode.replaceChild(home, el)
// append to target
getTarget(value).appendChild(el)
homes.set(el, Object.assign({}, homes.get(el), { hasMovedOut: true }))
} else if (hasMovedOut && value === false) {
// previously moved, coming back home
parentNode.replaceChild(el, home)
homes.set(el, Object.assign({}, homes.get(el), { hasMovedOut: false }))
} else if (value) {
// already moved, going somewhere else
getTarget(value).appendChild(el)
}
},
unbind (el, binding) {
console.log('v-transfer-dom:unbind')
el.parentNode.removeChild(el);
homes.delete(el)
}
}
export default directive

56
src/extend/index.js Normal file
View File

@@ -0,0 +1,56 @@
import vue from 'vue';
// element-ui
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
vue.use(ElementUI);
import './js/utils';
import './js/filter';
//api
import api from './api/api';
vue.prototype.$api = api;
//message
import './js/messageTip';
//localStorage
import local from './js/localStorage';
vue.prototype.$local = local;
import vaild from './../../static/js/vaild.js'
vue.prototype.$vaild = vaild;
// echarts from baidu
//import echarts from 'echarts';
//vue.prototype.$echarts = echarts;
// components
import loading from './components/loading';
import dropDown from './components/drop-down';
import empty from './components/empty';
import pagination from './components/pagination';
import ScrollBar from 'element-ui/lib/scrollbar';
import modelNote from './components/note';
// import '../../static/umeditor/themes/default/css/umeditor.css';
// import '../../static/umeditor/umeditor.config.js'
// import '../../static/umeditor/umeditor.js'
// import '../../static/umeditor/lang/zh-cn/zh-cn.js'
// import UE from '../../static/umeditor/umeditor.vue';
import UE from "vue-ueditor-wrap";
vue.component("model-loading", loading);
vue.component("model-drop-down", dropDown);
vue.component("model-empty", empty);
vue.component("model-pagination", pagination);
vue.component("ScrollBar",ScrollBar);
vue.component("model-note", modelNote);
vue.component("UE",UE);

View File

@@ -0,0 +1,137 @@
// 当前日期
let now = new Date();
// 今天本周的第几天
let nowDayOfWeek = now.getDay();
// 当前日
let nowDay = now.getDate();
// 当前月
let nowMonth = now.getMonth();
// 当前年
let nowYear = now.getFullYear();
nowYear += (nowYear < 2000) ? 1900 : 0;
// 上月日期
let lastMonthDate = new Date();
lastMonthDate.setDate(1);
lastMonthDate.setMonth(lastMonthDate.getMonth() - 1);
let lastMonth = lastMonthDate.getMonth();
// 日期格式化,时间戳 时分秒 hh:mm:ss
export function formatTimeStamp(date, fmt = 'yyyy-MM-dd hh:mm:ss') {
if(!date) {
return '-';
}
date = new Date(date);
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
}
let o = {
'M+': date.getMonth() + 1,
'd+': date.getDate(),
'h+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds()
};
for (let k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
let str = o[k] + '';
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? str : padLeftZero(str));
}
}
return fmt;
}
function padLeftZero(str) {
return ('00' + str).substr(str.length);
}
// 获取当前时间
export function getNowDate() {
return formatTimeStamp(new Date());
}
// 获得某月的天数
export function getMonthDays(myMonth) {
let monthStartDate = new Date(nowYear, myMonth, 1);
let monthEndDate = new Date(nowYear, myMonth + 1, 1);
let days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24);
return days;
}
// 获得本季度的开始月份
export function getQuarterStartMonth() {
let quarterStartMonth = 0;
if (nowMonth < 3) {
quarterStartMonth = 0;
}
if (2 < nowMonth && nowMonth < 6) {
quarterStartMonth = 3;
}
if (5 < nowMonth && nowMonth < 9) {
quarterStartMonth = 6;
}
if (nowMonth > 8) {
quarterStartMonth = 9;
}
return quarterStartMonth;
}
// 获得本周的开始日期
export function getWeekStartDate() {
let weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek);
return formatTimeStamp(weekStartDate);
}
// 获得本周的结束日期
export function getWeekEndDate() {
let weekEndDate = new Date(nowYear, nowMonth, nowDay + (6 - nowDayOfWeek));
return formatTimeStamp(weekEndDate);
}
// 获得上周的开始日期
export function getLastWeekStartDate() {
let weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek - 6);
return formatTimeStamp(weekStartDate);
}
// 获得上周的结束日期
export function getLastWeekEndDate() {
let weekEndDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek);
return formatTimeStamp(weekEndDate);
}
// 获得本月的开始日期
export function getMonthStartDate() {
let monthStartDate = new Date(nowYear, nowMonth, 1);
return formatTimeStamp(monthStartDate);
}
// 获得本月的当前日期
export function getMonthCurrentDate() {
let monthEndDate = new Date(nowYear, nowMonth, now.getDate());
return formatTimeStamp(monthEndDate);
}
// 获得本月的结束日期
export function getMonthEndDate() {
let monthEndDate = new Date(nowYear, nowMonth, getMonthDays(nowMonth));
return formatTimeStamp(monthEndDate);
}
// 获得上月开始时间
export function getLastMonthStartDate() {
let lastMonthStartDate = new Date(nowYear, lastMonth, 1);
return formatTimeStamp(lastMonthStartDate);
}
// 获得上月结束时间
export function getLastMonthEndDate() {
let lastMonthEndDate = new Date(nowYear, lastMonth, getMonthDays(lastMonth));
return formatTimeStamp(lastMonthEndDate);
}
// 获得上月当前时间
export function getLastMonthCurrentDate() {
let lastMonthCurrentDate = new Date(nowYear, lastMonth, now.getDate());
return formatTimeStamp(lastMonthCurrentDate);
}
// 获得本季度的开始日期
export function getQuarterStartDate() {
let quarterStartDate = new Date(nowYear, getQuarterStartMonth(), 1);
return formatTimeStamp(quarterStartDate);
}
// 或的本季度的结束日期
export function getQuarterEndDate() {
let quarterEndMonth = getQuarterStartMonth() + 2;
let quarterStartDate = new Date(nowYear, quarterEndMonth, getMonthDays(quarterEndMonth));
return formatTimeStamp(quarterStartDate);
}
// 当时时间减去天数
export function getNowDateSubtraction(day) {
let nowDateSubtraction = new Date().setDate((new Date().getDate() - day));
return formatTimeStamp(nowDateSubtraction);
}

116
src/extend/js/filter.js Normal file
View File

@@ -0,0 +1,116 @@
import vue from 'vue';
vue.filter("upcase", function (value) {
var arr = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
// value = arr[value];
if (value <= 9) {
value = arr[value];
} else if (value == 19) {
value = '二十'
} else if (9 < value <= 18) {
value = '十' + arr[value % 10]
}
// if (value >= 10) {
// if (value % 10 == 0) {
// value = arr[(value / 10) - 1] + '十'
// } else {
// value = arr[(value / 10) - 1] + '十' + arr[(value % 10) - 1]
// }
// }
return value;
});
vue.filter('week', function (value) { // 时间转星期
if (!value) return ''
let date = new Date(value).getDay();
//let weeks = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
let weeks = new Array("周日", "周一", "周二", "周三", "周四", "周五", "周六");
return weeks[date];
})
//yyyy-MM-dd HH:mm:ss
vue.filter("dateFormat", function (value) {
if (value == null || value == '') return '-';
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "-" : "-0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "-" : "-0") + value.getDate() + " " + (value.getHours() > 9 ? "" : "0") + value.getHours() + (value.getMinutes() > 9 ? ":" : ":0") + value.getMinutes() + (value.getSeconds() > 9 ? ":" : ":0") + value.getSeconds();
});
//yyyyMMddHHmmss
vue.filter("dateFormat1", function (value) {
if (value == null) return null;
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "" : "0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "" : "0") + value.getDate() + "" + (value.getHours() > 9 ? "" : "0") + value.getHours() + (value.getMinutes() > 9 ? "" : "0") + value.getMinutes() + (value.getSeconds() > 9 ? "" : "0") + value.getSeconds();
});
//yyyy-MM-dd HH:mm
vue.filter("dateMinuteFormat", function (value) {
if (value == null) return null;
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "-" : "-0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "-" : "-0") + value.getDate() + " " + (value.getHours() > 9 ? "" : "0") + value.getHours() + (value.getMinutes() > 9 ? ":" : ":0") + value.getMinutes();
});
//yyyy-MM-dd
vue.filter("dateFormat2", function (value) {
if (value == null) return null;
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "-" : "-0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "-" : "-0") + value.getDate();
});
//yyyy-MM
vue.filter("dateFormat3", function (value) {
if (value == null) return null;
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "-" : "-0") + (value.getMonth() + 1);
});
//yyyy年MM月dd日
vue.filter("dateFormat4", function (value) {
if (value == null) return null;
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "年" : "年0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "月" : "月0") + value.getDate() + "日";
});
//null??"-"
vue.filter("nullFormat", function (value) {
return (value == null || value == undefined || value == '') ? "-" : value;
});
//0.00
vue.filter("roundFormat", function (value) {
if (value == null || isNaN(value)) return null;
return value.toFixed(2);
});
//yyyy-MM-dd
vue.filter("shortDateFormat", function (value) {
if (value == null || value == '') return '-';
value = new Date(value);
return value.getFullYear() + (value.getMonth() + 1 > 9 ? "-" : "-0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "-" : "-0") + value.getDate();
});
//00:00:00
vue.filter("shortTimeFormat", function (value) {
if (value == null) return null;
value = new Date(value);
return (value.getHours() > 9 ? "" : "0") + value.getHours() + (value.getMinutes() > 9 ? ":" : ":0") + value.getMinutes() + (value.getSeconds() > 9 ? ":" : ":0") + value.getSeconds();
});
//字数太多显示不全...
vue.filter("partStringFormat", function (value, count = 10) {
if (value == null) return null;
if (value.length <= count) {
return value;
}
if (value.length > count) {
return value.substring(0, count) + '...'
}
});
//判断是否初始化时间字段,若是则返回空串
vue.filter("iNitStringFormat", function (value) {
if (value == "null") return null;
if (value == "0001-01-01T00:00:00+08:00") {
value = "";
} else {
value = new Date(value);
value = value.getFullYear() + (value.getMonth() + 1 > 9 ? "-" : "-0") + (value.getMonth() + 1) + (value.getDate() > 9 ? "-" : "-0") + value.getDate() + " " + (value.getHours() > 9 ? "" : "0") + value.getHours() + (value.getMinutes() > 9 ? ":" : ":0") + value.getMinutes() + (value.getSeconds() > 9 ? ":" : ":0") + value.getSeconds();
}
return value;
});
vue.filter("phoneHide", function (value) {
if (isNaN(Number(value))) return value;
if (!value) return '-';
var rega = new RegExp("(\\w{3})\\w{" + (value.trim().length - 7) + "}(\\w{4})", "ig");
return value = value.replace(rega, '$1****$2');
});

View File

@@ -0,0 +1,173 @@
var _setCache=(str)=> {//1支持多用户登录同端2处理个别浏览器缓存未清理干净
let _managerId = 0
_managerId=window.localStorage.getItem('unique_login');//唯一登录标识
return `${str}_${_managerId}`
};
export default {
setUserCache(data){//设置登录用户信息缓存
let _unique_login=data.Manager.ID+data.Manager.Logincode
let _cacheName=`etorcurrentuser_${_unique_login}`
window.localStorage.setItem( _cacheName, JSON.stringify(data));
window.localStorage.setItem('unique_login', _unique_login);
window.localStorage.setItem("etorcurrentuser",JSON.stringify(data));//兼容未使用公共方法的页面
},
getUserByCache: function () {//获取用户信息缓存
let _cacheName=_setCache("etorcurrentuser")
var str= window.localStorage.getItem(_cacheName);
return JSON.parse(str);
},
setMenus(data){
let _cacheName="pmenus"
window.localStorage.setItem( _cacheName, JSON.stringify(data));
},
getMenus(){
let _cacheName="pmenus"
var str= window.localStorage.getItem(_cacheName);
return JSON.parse(str);
},
isRoot: function () {//是否超级管理员
var currentUser=this.getUserByCache();
var isRoot=currentUser.Manager.IsRootUser;
return isRoot;
},
freshToken(type) {
//刷新token
// 0刷新过期时间1刷新管理小区
let etorcurrentuser=this.getUserByCache()
newapi
.AgainGetToken({ Token: etorcurrentuser.Token, Type: type })
.then(res => {
if (res.Code == 10000) {
console.log(`刷新token成功`);
etorcurrentuser.Token = res.Data;
this.setUserCache(etorcurrentuser)
}
})
.catch(res => { });
},
arr: [],
dbclick: function (tag) {
var img_obj = document.getElementsByClassName(tag);
var body = document.getElementsByTagName("body")[0];
var obj_arr = new Array();
var img_arr = new Array();
var nowindex = 0;
for (var i = 0; i < img_obj.length; i++) {
obj_arr.push(img_obj[i]);
img_arr.push(img_obj[i].getAttribute("src"));
img_obj[i].ondblclick = function () {
var nowurl = this.getAttribute("src");
//获取到当前点击是第几个元素
for (var t = 0; t < img_arr.length; t++) {
if (img_arr[t] == nowurl) nowindex = t;
}
var cover_div = document.createElement("div");
var center_div = document.createElement("div");
var img_box = document.createElement("div");
var leftspan = document.createElement("span");
var rightspan = document.createElement("span");
cover_div.className = "cover-div";
center_div.className = "center-div";
img_box.className = "readimg_box";
leftspan.className = "leftspan";
rightspan.className = "rightspan";
center_div.appendChild(img_box);
body.appendChild(cover_div);
body.appendChild(center_div);
body.appendChild(leftspan);
body.appendChild(rightspan);
//外层div点击的时候删除
cover_div.onclick = function () {
body.removeChild(cover_div);
body.removeChild(leftspan);
body.removeChild(rightspan);
body.removeChild(center_div);
center_div.removeChild(img_box);
};
//添加图片
for (var n = 0; n < img_arr.length; n++) {
var oimg = document.createElement("img");
oimg.className = "img_cover";
oimg.src = img_arr[n];
img_box.appendChild(oimg);
}
img_box.style.marginLeft = -nowindex * 500 + "px";
rightspan.onclick = function () {
nowindex++;
if (nowindex >= img_arr.length - 1) {
nowindex = img_arr.length - 1;
}
img_box.style.marginLeft = -nowindex * 500 + "px";
};
leftspan.onclick = function () {
//console.log(img_arr.length - 1);
//console.log(nowindex);
nowindex--;
if (nowindex <= 0) {
nowindex = 0;
}
img_box.style.marginLeft = -nowindex * 500 + "px";
};
};
}
},
uploadimg: function () {
var input = document.createElement("input");
input.setAttribute("type", "file");
var event = document.createEvent("MouseEvents");
event.initMouseEvent(
"click",
false,
true,
window,
0,
0,
0,
0,
0,
false,
false,
true,
false,
0,
null
);
input.dispatchEvent(event);
// this.makebase64()
var that = this;
// console.log(that.makebase64)
input.onchange = function (e) {
var f = input.files[0];
console.log("e");
console.log(e);
console.log("input.files");
console.log(f.name);
console.log(f.size / 1024);
// if(f.name)
if (f.size / 1024 > 2048) {
// alert('图片大小不能超过2m')
// Message({
// type: 'error',
// message: '图片大小不能超过2m'
// })
return;
}
var reader = new FileReader();
console.log("reader1");
console.log(reader);
reader.readAsDataURL(f);
console.log("reader");
console.log(reader);
reader.onloadend = function (e) {
e = window.event || e;
var imgbase = e.target.result;
};
};
}
};

2149
src/extend/js/menus.js Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
import vue from 'vue';
vue.prototype.$error = function(text){
this.$message({
type: "error",
message: text
})
}
vue.prototype.$info = function(text){
this.$message({
type: "info",
message: text
})
}
vue.prototype.$warn = function(text){
this.$message({
type: "warning",
message: text
})
}
vue.prototype.$success = function(text){
this.$message({
type: "success",
message: text
})
}

234
src/extend/js/newMenus.js Normal file
View File

@@ -0,0 +1,234 @@
export var menus = [
{
"Id": 1,
"Permissionlabel": "概况总览",
"Permissionurl": "/store/index",
"Icon": "icon-gaikuang",
},
{
"Id": 2,
"Permissionlabel": "店铺管理",
"Permissionurl": "",
"Icon": "icon-zhuangxiu",
"Children": [
{
"Id": 23,
"Permissionlabel": "设计",
"Permissionurl": "/d",
"target":"_blank"
},
{
"Id": 23,
"Permissionlabel": "设置",
"Permissionurl": "/store/setting",
}]
},
{
"Id": 5,
"Permissionlabel": "课程管理",
"Permissionurl": "",
"Icon": "icon-kecheng" ,
"Children": [
{
"Id": 23,
"Permissionlabel": "录播课程",
"Permissionurl": "/course/list",
},
{
"Id": 23,
"Permissionlabel": "直播课程",
"Permissionurl": "/course/live",
},
{
"Id": 23,
"Permissionlabel": "课程套餐",
"Permissionurl": "/course/package",
},
{
"Id": 10049,
"Permissionlabel": "音视频库",
"Permissionurl": "/course/asset",
},
{
"Id": 10093,
"Permissionlabel": "课程评论",
"Permissionurl": "/course/comment",
"Icon": "icon-fuwuguanli",
"Iconactivate": "icon-fuwuguanli_xuanzhong",
},
{
"Id": 10050,
"Permissionlabel": "学习记录",
"Permissionurl": "/course/learn",
},
]
},
{
"Id": 5,
"Permissionlabel": "题库管理",
"Permissionurl": "",
"Icon": "icon-zhuxue",
"Children": [
{
"Id": 23,
"Permissionlabel": "科目",
"Permissionurl": "/questions/subject",
},
{
"Id": 23,
"Permissionlabel": "考点",
"Permissionurl": "/questions/examsite",
},
{
"Id": 10049,
"Permissionlabel": "试题",
"Permissionurl": "/questions/question",
},
{
"Id": 10093,
"Permissionlabel": "试卷",
"Permissionurl": "/questions/paper",
"Icon": "icon-fuwuguanli",
"Iconactivate": "icon-fuwuguanli_xuanzhong",
},
{
"Id": 10050,
"Permissionlabel": "考试",
"Permissionurl": "/questions/exam",
},
]
},
{
"Id": 30001,
"Permissionlabel": "订单管理",
"Permissionurl": "",
"Icon": "icon-shuju",
"Children": [
{
"Id": 10099,
"Permissionlabel": "订单概况",
"Permissionurl": "/order/index",
"Icon": "icon-shebeiguanli",
"Iconactivate": "icon-shebeiguanli_xuanzhong",
},
{
"Id": 10099,
"Permissionlabel": "课程订单",
"Permissionurl": "/order/courseorder",
"Icon": "icon-shebeiguanli",
"Iconactivate": "icon-shebeiguanli_xuanzhong",
},
{
"Id": 10053,
"Permissionlabel": "套餐订单",
"Permissionurl": "/order/packageorder",
"Icon": null,
},
{
"Id": 10054,
"Permissionlabel": "拼团订单",
"Permissionurl": "/order/grouporder",
},
{
"Id": 10100,
"Permissionlabel": "直播订单",
"Permissionurl": "/order/liveorder",
},
{
"Id": 10100,
"Permissionlabel": "题库订单",
"Permissionurl": "/order/questionorder",
}
]
},
{
"Id": 3,
"Permissionlabel": "营销中心",
"Permissionurl": "",
"Icon": "icon-zhuxue",
"Children": [
{
"Id": 138,
"Permissionlabel": "推销员",
"Permissionurl": "/sell/seller",
},
{
"Id": 10159,
"Permissionlabel": "兑换码",
"Permissionurl": "/sell/redeemcode",
},
{
"Id": 12,
"Permissionlabel": "优惠券",
"Permissionurl": "/sell/coupon",
},
{
"Id": 12,
"Permissionlabel": "吸粉器",
"Permissionurl": "/sell/fans",
},
{
"Id": 10056,
"Permissionlabel": "支付有礼",
"Permissionurl": "/sell/payaward",
},
{
"Id": 138,
"Permissionlabel": "弹窗广告",
"Permissionurl": "/sell/popad",
},
{
"Id": 138,
"Permissionlabel": "好友助力",
"Permissionurl": "/sell/help",
},
{
"Id": 138,
"Permissionlabel": "限时折扣",
"Permissionurl": "/sell/timediscount",
} ,
{
"Id": 138,
"Permissionlabel": "裂变海报",
"Permissionurl": "/sell/fission",
} ,
{
"Id": 10159,
"Permissionlabel": "工具",
"Permissionurl": "/sell/index",
},
]
},
{
"Id": 9999,
"Permissionlabel": "设置",
"Permissionurl": "",
"Icon": "icon-shezhi",
"Children": [
{
"Id": 10042,
"Permissionlabel": "员工管理",
"Permissionurl": "/setting/managerlist",
},
{
"Id": 22,
"Permissionlabel": "系统通知",
"Permissionurl": "/setting/sysNotice",
}
]
},
{
"Id": 3,
"Permissionlabel": "资讯管理",
"Permissionurl": "/article/list",
"Icon": "icon-jiaoyi"
},
{
"Id": 10000,
"Permissionlabel": "用户中心",
"Permissionurl": "users",
"Icon": "icon-yonghu",
}
]

View File

@@ -0,0 +1,25 @@
import Vue from 'vue';
function getPermission(permission, permissionObj) {
if (!permissionObj) return true;
if (permission instanceof Array) return permission.find(item => {
return permissionObj[item]
});
return permissionObj[permission];
}
function permissionInit(value) {
let items = ['AllowView', 'AllowAdd', 'AllowEdit', 'AllowDel'];
let _items = ['allowView', 'allowAdd', 'allowEdit', 'allowDel'];
let permission = [];
items.forEach(function (item) {
permission.push(getPermission(item,value));
});
permission.forEach(function (item, index) {
Vue.prototype[_items[index]] = item;
// console.log(_items[index], item);
});
}
export default permissionInit

View File

@@ -0,0 +1,15 @@
export default function convertTree(root) {
var that=this;
var newRoot=root.Data;
if(root.Children&&root.Children.length>0){
var children=[];
root.Children.forEach(function (child){
var newChild=convertTree(child);
children.push(newChild);
});
newRoot.children=children
}else{
newRoot.children=[];
}
return newRoot;
}

156
src/extend/js/utils.js Normal file
View File

@@ -0,0 +1,156 @@
import vue from "vue";
import {
MessageBox
} from 'element-ui';
vue.prototype.$makeSure = function (fn, message, title) {
try {
message = message || '您确定要执行此操作吗';
title = title || '温馨提示';
MessageBox.confirm(message, title).then(() => {
fn();
}).catch(() => {});
} catch (e) {
debugger
}
};
//vue.prototype.$upload = http_upload_picture; //global variable
vue.prototype.$getPageSize = function (num) {
var winHeight = document.documentElement.clientHeight;
// 菜单高62 分页72 page_content的上下padding合30 表头高44 其他内容占据高度num
var size = parseInt((winHeight - 62 - 44 - 72 - 30 - num) / 44);
size = size <= 1 ? 1 : size
//三目运算的判断
return size;
};
vue.prototype.$getStyleHeight = function (num, flag=true) {
var winHeight = document.documentElement.clientHeight;
// 菜单高62 page_content的上下padding合30 其他内容占据高度num
var size = parseInt(winHeight - 56 - 15 - num)
if (flag) {
return {
'height': size + 'px',
}
} else {
return {
'min-height': size + 'px',
}
}
};
vue.prototype.$getHeight = function (num, flag) {
var winHeight = document.documentElement.clientHeight;
var size = parseInt(winHeight - 62 - 30 - num)
size < 0 && (size = 0);
return size + 'px';
};
vue.prototype.$addstyle = function (arr, id) {
arr.forEach(element => {
var link = document.createElement('link');
link.setAttribute("rel", "stylesheet");
link.setAttribute("id", id);
link.href = element;
document.getElementsByTagName("head")[0].appendChild(link)
}, this);
};
vue.prototype.$addscript = function (url, callback) {
var head = document.getElementsByTagName("head")[0];
// arr.forEach(element => {
var script = document.createElement('script');
script.setAttribute('style', 'type/javascript');
script.setAttribute('id', 'echarts2');
script.src = url;
head.appendChild(script)
if (typeof (callback) != "undefined") {
if (script.readyState) {
script.onreadystatechange = function () {
if (script.readyState == "loaded" || script.readyState == "complete") {
script.onreadystatechange = null;
callback();
}
};
} else {
script.onload = function () {
callback();
};
}
}
// }, this)
};
//获取本日、本周、本月、本年的时间
vue.prototype.$getTime = (idx) => {
!idx && (idx = 0);
let date = new Date(new Date().setHours(23, 59, 59, 0));
let year = date.getFullYear(),
month = date.getMonth() + 1,
day = date.getDate();
switch (idx) {
case 0: //本日
return [new Date(year, month, day), date]
case 1: //本周
let week = date.getDay();
week == 0 && (week = 7);
let time = new Date(new Date().setHours(0, 0, 0, 0));
time.setDate(day - week + 1);
return [new Date(time), date]
case 2: //本月
return [new Date(year, month, '1'), date]
case 3: //本年
return [new Date(year + '-01-01'), date]
}
};
vue.prototype.empty = '--';
vue.prototype.maxPageSize = 2000;
vue.prototype.camelCase=function(str='none',smallCamelCase=true){
str=str.toString();
if(str.toLowerCase()=='id') return smallCamelCase?'id':'ID';
return smallCamelCase?str[0].toLowerCase()+str.slice(1):str[0].toUpperCase()+str.slice(1);
};
vue.prototype.camelCaseData=function(data,smallCamelCase=true){
let agent={};
let that=this;
Object.keys(data).forEach(function(key){
agent[that.camelCase(key,smallCamelCase)]=data[key];
});
return agent;
}
vue.prototype.$uuid=function(length){
return Number(Math.random().toString().substr(3,length) + Date.now()).toString(36);
}
String.prototype.toJson = function () {
return JSON.parse(this);
}
String.prototype.isEmpty = function () {
if (this == null || this == undefined || this.trim() == "") {
return true;
}
return false;
}
String.prototype.DateFormat = function (fmt) {
var dt = new Date(this);
return dt.Format(fmt);
}
Date.prototype.Format = function (fmt) { //author: meizz
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;
}
Window.prototype.clone=function(data){
return JSON.parse(JSON.stringify(data));
}

Some files were not shown because too many files have changed in this diff Show More