初始化代码

This commit is contained in:
2025-12-22 17:13:05 +08:00
parent ed0de08e3a
commit 1f7e9d401b
2947 changed files with 526137 additions and 0 deletions

15
uniapp/uni-admin/.babelrc Normal file
View File

@@ -0,0 +1,15 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
// "ignore": [
// "./static/Ueditor/ueditor.all.js"
// ]
}

View File

@@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

View File

@@ -0,0 +1,4 @@
/build/
/config/
/dist/
/*.js

View File

@@ -0,0 +1,29 @@
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
}
}

15
uniapp/uni-admin/.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
.DS_Store
node_modules/
/dist/
/unpackage/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

View File

@@ -0,0 +1,10 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}

View File

@@ -0,0 +1,88 @@
# 后台管理系统开发规范
build js文件中替换
lbConfig.jsPath
## 命名规范
1、 JS命名规范: 请使用小驼峰命名法
> let userName = 'xxx'
2、CSS命名规范请使用小写 + 中划线拼接
> 如:.tab-bar
3、文件命名规范请使用语义化命名文件名必须和功能、项目的中文意思大致一致
> 如:商城 =》 shop、mall等
4、函数编写规范尽量表明函数的用途参数的说明
```code
/**
* @method 方法名
* @param {String | 参数类型} 参数1说明
* @param {Number | 参数类型} 参数2说明
* @return {String | 返回类型}
*/
```
## 目录结构
```
|--build vue自带的配置文件
|--config 本地环境与生产环境的配置
| |--dev.env.js 本地环境配置文件
| |--index.js 本地与开发的总配置文件
| |--prod.env.js 开发环境配置文件
|--dist 打包出来的文件 打包完后记得把static>js>manifest.js中的路径改了
|--src 开发的总目录
| |--api 接口api
| | |--modules 接口模块化(每个模块按模块名命名,每个接口请加上模块名的名字,以防全局污染)
| | |--index.js 接口的配置与接口统一处理异常错误
| |--assets 静态文件、图片
| |--components 通用组件和行业版的组件
| | |--basics 通用组件
| |--ad.vue 页面右侧帮助中心的组件
| |--footer.vue 页面底部组件
| |--header.vue 页面头部组件
| |--layout.vue 页面内容区域组件(以及把其他公用组件组装)
| |--sidebar.vue 页面菜单栏组件
| |--i18n 多语言包
| | |--langs 多语言模块
| | | |--en.json 英语
| | | |--zh.json 中文
| | |--index.js 多语言配置
| |--router 路由
| | |--_import_development.js 本地开发路由动态引入的方法
| | |--_import_production.js 生产环境路由动态引入的方法
| | |--index.js 白名单路由
| |--store 数据状态管理
| | |--modules 数据状态模块
| | |--index.js 数据状态管理集中处理
| |--style 全局的样式以及图标
| |--utils 全局的公共方法和工具
| |--view 所有的页面
| | |--404 找不到页面
| | |--custom 客户管理
| | |--examine 审核管理
| | |--finance 财务管理
| | |--login 登录
| | |--shop 订单管理
| | |--system 系统设置
| |--App.vue vue最外层组件
| |--Bus.js eventBus数据传递
| |--main.js vue入口文件
| |--permission.js 本地开发动态路由表
|--static 存放的Ueditor编辑器|
```
## 安装运行与打包
```找到文件【api/index.js】然后搜索【developmentURL】将其更改为您自己的域名
``` bash
# 安装依赖包
npm install
# 本地运行
npm run dev
# 打包上线
npm run build
```

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'
))
})
})

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)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,122 @@
'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
}
}
function generateSassResourceLoader() {
var loaders = [
cssLoader,
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
// 多个文件时用数组的形式传入,单个文件时可以直接使用 path.resolve(__dirname, '../static/style/common.scss'
resources: path.resolve(__dirname, '../src/style/theme.scss')
}
}
];
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader',
publicPath: '../../'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateSassResourceLoader('sass', { indentedSyntax: true }),
scss: generateSassResourceLoader('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')
})
}
}

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'
}
}

View File

@@ -0,0 +1,103 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
// app: './src/main.js'
app: ['babel-polyfill', './src/main.js']
},
externals: {
'vue': 'Vue',
'vuex': 'Vuex',
'element-ui': 'ElementUI',
'moment': 'moment'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.sass$/,
loaders: ['style', 'css', 'sass']
},
{
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'
}
}

View File

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

View File

@@ -0,0 +1,164 @@
'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 version = dateFtt("yyyyMMddhhmmss", new Date())
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].js?v=' + version), //js/[name].[chunkhash].js
chunkFilename: utils.assetsPath('js/[id].js?v=' + version) //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].css?v=' + version), // 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())
}
function dateFtt(fmt,date) {
var o = {
"M+" : date.getMonth()+1, //月份
"d+" : date.getDate(), //日
"h+" : date.getHours(), //小时
"m+" : date.getMinutes(), //分
"s+" : date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth()+3)/3), //季度
"S" : date.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt))
fmt=fmt.replace(RegExp.$1, (date.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;
}
module.exports = webpackConfig

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"'
})

View File

@@ -0,0 +1,90 @@
/*
* @Descripttion:
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-19 19:26:17
*/
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
// const buildPath = require('./dev.env')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api': {
target: 'https://apis.map.qq.com/',
changeOrigin: true,
secure: true,
pathRewrite: {
'^/api': ''
}
}
},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
// host: '192.168.1.5', // can be overwritten by process.env.HOST
port: 8000, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: true,
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',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: './', // 打包时配置路劲 声场环境路劲:/addons/longbing_card/core2/public/
/**
* Source Maps
*/
productionSourceMap: false,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#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
}
}

View File

@@ -0,0 +1,5 @@
'use strict'
module.exports = {
NODE_ENV: '"production"',
BASE_URL:'"/addons/longbing_card/core2/public/static/"'
}

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<meta name="renderer" content="webkit"/>
<meta name="force-rendering" content="webkit"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
<meta name="referrer" content="never">
<title>登录 - 后台管理中心</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.1.1/vuex.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.1/index.min.js"></script>
<!-- 引入样式 -->
<link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.1/theme-chalk/index.min.css" rel="stylesheet">
<link href="https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
</head>
<body>
<script>
var lbConfig = {
jsPath: '/addons/longbing_card/core2/public/'
}
</script>
<div id="app"></div>
<script charset="utf-8" src="https://map.qq.com/api/js?v=2.exp&key=2LNBZ-HT2R2-LENUE-CBNZK-QZ4VS-AQB5Z"></script>
</body>
</html>

View File

@@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>个人信息保护指引</title>
<style>
body {
padding: 20px 15px;
margin: 0;
}
p {
padding: 0px;
margin-block-start: 0px;
margin-block-end: 0px;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
img{
max-width: 100% !important;
height: auto !important;
display: block;
}
</style>
</head>
<body>
<div class="html-box"></div>
<script src="/js/jquery-3.5.1.min.js"></script>
<script>
let _href = window.location.href
let url = _href.split('/information.html')[0]
let ajax_url = `${url}/index.php?i=1&m=farm&s=index/getConfig`
$(function() {
$.ajax({
type: 'get',
url: `${ajax_url}`,
dataType: 'json',
async: false,
data: {},
success: function(res) {
let {
information_protection
} = res.data
$(".html-box").html(information_protection)
}
})
})
</script>
</body>
</html>

12511
uniapp/uni-admin/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
{
"name": "longbing_back",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "akang <815101207@qq.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"ali-oss": "^6.15.2",
"axios": "^0.19.0",
"babel-polyfill": "^6.26.0",
"cos-js-sdk-v5": "^1.2.15",
"crypto-js": "^4.0.0",
"element-china-area-data": "^4.1.2",
"element-ui": "^2.10.1",
"ezuikit-js": "^0.5.2",
"fundebug-javascript": "^2.0.0",
"fundebug-vue": "0.0.1",
"moment": "^2.24.0",
"qiniu-js": "^3.3.1",
"vue": "^2.5.2",
"vue-clipboard2": "^0.3.1",
"vue-i18n": "^8.12.0",
"vue-router": "^3.0.1",
"vuedraggable": "^2.23.2",
"vuex": "^3.1.1"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-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": "^3.2.0",
"echarts": "^4.3.0",
"eslint": "^4.19.1",
"eslint-friendly-formatter": "^4.0.1",
"eslint-loader": "^2.0.0",
"eslint-plugin-html": "^4.0.3",
"eslint-config-standard": "^10.2.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",
"moment": "^2.24.0",
"node-notifier": "^5.1.2",
"node-sass": "^4.12.0",
"nprogress": "^0.2.0",
"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": "^7.1.0",
"sass-resources-loader": "^2.0.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^2.2.0",
"uuid": "^3.3.2",
"vue-echarts": "^4.0.4",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"vuescroll": "^4.13.1",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0",
"xlsx": "^0.15.1"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

View File

@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户隐私协议</title>
<style>
body {
padding: 20px 15px;
margin: 0;
}
p {
padding: 0px;
margin-block-start: 0px;
margin-block-end: 0px;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
img {
max-width: 100% !important;
height: auto !important;
display: block;
}
</style>
</head>
<body>
<div class="html-box"></div>
<script src="/js/jquery-3.5.1.min.js"></script>
<script>
let _href = window.location.href
let url = _href.split('/protocol.html')[0]
let ajax_url = `${url}/index.php?i=1&m=farm&s=index/getConfig`
$(function() {
$.ajax({
type: 'get',
url: `${ajax_url}`,
dataType: 'json',
async: false,
data: {},
success: function(res) {
let {
login_protocol
} = res.data
$(".html-box").html(login_protocol)
}
})
})
</script>
</body>
</html>

View File

@@ -0,0 +1,102 @@
<!--
* @Description: App
* @Author: xiao li
* @Date: 2021-07-03 11:41:05
* @LastEditTime: 2022-08-24 11:05:34
* @LastEditors: xiao li
-->
<template>
<div id="app">
<router-view />
<prompt></prompt>
</div>
</template>
<script>
import axios from 'axios'
import { mapState, mapMutations } from 'vuex'
import prompt from './components/prompt.vue'
export default {
name: 'App',
components: {
prompt
},
data () {
return {
status: '',
isFirst: false,
name: 'App',
timer: null,
previous: null,
token: ''
}
},
// 监听器
watch: {
async $route (to, from) {
}
},
created () {
},
mounted () {
let that = this
window.onresize = () => {
that.fnThrottle(() => {
let clientWidth = document.documentElement.clientWidth
if (clientWidth < 1200) {
that.$store.commit('handleAdSwitch', false)
}
}, 300)()
}
},
computed: {
...mapState({
routesItem: state => state.routes
})
},
methods: {
...mapMutations([]),
fnThrottle (fn, delay, atleast) {
let that = this
return function () {
let now = +new Date()
if (!that.previous) that.previous = now
if (atleast && now - that.previous > atleast) {
fn()
that.previous = now
clearTimeout(that.timer)
} else {
clearTimeout(that.timer)
that.timer = setTimeout(function () {
fn()
that.previous = null
}, delay)
}
}
}
}
}
</script>
<style lang='scss'>
@import url('./style/reset.css');
@import url('./style/icon.css');
@import url('./style/base.css');
@import url('./style/diy.css');
@import url('./style/common.css');
.el-select__tags {
.el-tag--info:nth-child(1) {
max-width: 70%;
display: flex;
align-items: center;
.el-select__tags-text {
max-width: 90%;
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
</style>

View File

@@ -0,0 +1,3 @@
import Vue from 'vue'
const Bus = new Vue()
export default Bus

View File

@@ -0,0 +1,206 @@
import Vue from '@/main.js'
import axios from 'axios'
// import qs from 'qs'
import router from '../router'
// api 模块化
import apis from './modules'
let developmentURL = `https://https://stms.lyraiov.com`
axios.defaults.timeout = 300000
axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? developmentURL : getProCurrentHref()
// axios.defaults.baseURL = process.env.NODE_ENV === 'development' ? '/userApi/' : getProCurrentHref()
axios.interceptors.request.use(config => {
if (sessionStorage.getItem('minitk')) {
config.headers['token'] = sessionStorage.getItem('minitk')
// 'Content-Type': 'application/x-www-form-urlencoded' // application/json
}
return config
}, error => {
return Promise.reject(error)
})
axios.interceptors.response.use(res => {
// console.log(res, '====interceptors')
if (res.data.code === 401) { // token验证不合法或者没有
Vue.$message.error(res.data.error)
sessionStorage.removeItem('minitk') // 删除token
sessionStorage.removeItem('ms_username') // 删除用户名
router.push('/login')
} else if (res.data.code === 402) {
Vue.$message.error(res.data.error)
} else if (res.data.code === 400) {
Vue.$message.error(res.data.error)
}
return res
}, err => {
Vue.$message.error(err.message + ',请稍后再试')
return Promise.reject(err.response)
})
/**
* 封装get方法
* @param url
* @param data
* @returns {Promise}
*/
export function get (url, params = {}, type = 'application/json') {
// let headers = url.includes('qq/ws/geocoder/v1') ? {
// 'Content-Type': 'application/json; charset=utf-8',
// 'Access-Control-Allow-Origin': '*'
// } : {
// 'Content-Type': type
// }
return new Promise((resolve, reject) => {
axios.get(url, {
params,
headers: {
'Content-Type': type
}
})
.then(response => {
resolve(response.data)
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post请求
* @param url
* @param data
* @returns {Promise}
*/
export function post (url, data = {}, type = 'application/json') {
return new Promise((resolve, reject) => {
axios.post(url, data, {
headers: {
'Content-Type': type
}
}).then(response => {
resolve(response.data)
}, err => {
console.log(err)
reject(err)
})
})
}
/**
* 封装patch请求
* @param url
* @param data
* @returns {Promise}
*/
export function patch (url, data = {}, type = 'application/json') {
return new Promise((resolve, reject) => {
axios.patch(url, data)
.then(response => {
resolve(response.data)
}, err => {
reject(err)
})
})
}
/**
* 封装put请求
* @param url
* @param data
* @returns {Promise}
*/
export function put (url, data = {}, type = 'application/json') {
return new Promise((resolve, reject) => {
axios.put(url, data)
.then(response => {
resolve(response.data)
}, err => {
reject(err)
})
})
}
/**
* 封装del请求
* @param url
* @param data
* @returns {Promise}
*/
export function del (url, params = {}, type = 'application/json') {
return new Promise((resolve, reject) => {
console.log(params)
axios.delete(url, {
params: params,
headers: {
'Content-Type': type
}
})
.then(response => {
resolve(response.data)
})
.catch(err => {
reject(err)
})
})
}
/**
* 封装post上传图片、视频、音频、文件的接口
* @param url
* @param data
* @returns {Promise}
*/
export function postUpload (url, data = {}, progressCallback) {
return new Promise((resolve, reject) => {
axios.post(url, data, {
headers: {
'Content-Type': 'application/json'
},
onUploadProgress: progressCallback
}) // qs.stringify(data)
.then(response => {
resolve(response.data)
}, err => {
console.log(err)
reject(err)
})
})
}
/**
* @method 获取七牛token
* @param url
* @param data
* @returns {Promise}
*/
export function getQiniuToken (url, data = {}) {
return new Promise((resolve, reject) => {
axios.get(url, data)
.then(response => {
resolve(response.data)
}, err => {
reject(err)
})
})
}
/**
* 获取数据的接口
*/
export const api = {
...apis
}
function getProCurrentHref () {
let _href = window.location.href
let index = _href.indexOf('#')
let newHref = _href.slice(0, index)
newHref = window.lbConfig.isWe7 ? newHref + '&s=' : window.location.origin
return newHref
}

View File

@@ -0,0 +1,52 @@
/*
* @Descripttion: 权限管理
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-06-30 11:24:21
*/
import {
get, post
} from '../index'
export default {
// 角色列表
roleList (querys) {
return get('/farm/admin/AdminUser/roleList', querys)
},
// 角色下拉
roleSelect (querys) {
return get('/farm/admin/AdminUser/roleSelect', querys)
},
// 角色详情
roleInfo (querys) {
return get('/farm/admin/AdminUser/roleInfo', querys)
},
// 新增角色
roleAdd (querys) {
return post('/farm/admin/AdminUser/roleAdd', querys)
},
// 编辑角色
roleUpdate (querys) {
return post('/farm/admin/AdminUser/roleUpdate', querys)
},
// 账号列表
adminList (querys) {
return get('/farm/admin/AdminUser/adminList', querys)
},
// 账号详情
adminInfo (querys) {
return get('/farm/admin/AdminUser/adminInfo', querys)
},
// 新增账号
adminAdd (querys) {
return post('/farm/admin/AdminUser/adminAdd', querys)
},
// 编辑账号
adminUpdate (querys) {
return post('/farm/admin/AdminUser/adminUpdate', querys)
},
// 账号所匹配的角色的节点详情
adminNodeInfo (querys) {
return get('/farm/admin/AdminUser/adminNodeInfo', querys)
}
}

View File

@@ -0,0 +1,83 @@
/*
* @Descripttion:
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-19 20:17:04
*/
import {
get,
post
} from '../index'
export default {
// 登录
login (querys) {
return post('/farm/admin/admin/login', querys)
},
// 清除缓存
clearCache () {
return get('/admin/admin/config/clear')
},
// 修改自己的密码
updatePasswd (querys) {
return post('/farm/admin/AdminSetting/updatePass', querys)
},
// 基本信息
returnAdmin () {
return get('/card/Admin/returnAdmin')
},
// 获取可选商品列表
goodsSelect (querys) {
return post('/publics/someThing/goodsSelect', querys)
},
// 获取商品规格列表
goodsSpeList (querys) {
return post('/publics/someThing/goodsSpeList', querys)
},
// 图片中转用于canvas画图下载
handleImgSrc (querys) {
return new Promise(resolve => {
let { url, flag } = getProCurrentHref()
let $url = flag ? `${url}/card/getImage?path=${querys}` : `${url}/card/getImage&path=${querys}`
return resolve($url)
})
},
// 获取定地
getLocation (querys) {
let { lat, lng } = querys
let location = `${lat},${lng}`
location = '39.9843041172624,116.30564949558106'
querys = {
location,
key: '4IJBZ-DLACP-3QBDS-LI4FT-U2MZZ-5KFFA',
get_poi: 1
}
// return get(`/api/ws/geocoder/v1/`, querys)
// var ajax = new XMLHttpRequest();
// // get url 是不需要改变
// ajax.open("get", url);
// // 需要设置请求报文
// // ajax.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
// ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
// ajax.setRequestHeader('Access-Control-Allow-Origin', '*');
// ajax.send();
// // 注册事件
// ajax.onreadystatechange = function () {
// // 在事件中 获取数据 并修改界面显示
// if (ajax.readyState == 4 && ajax.status == 200) {
// console.log(JSON.parse(ajax.responseText),"======JSON.parse(ajax.responseText)")
// // 将 数据 让 外面可以使用
// callback && callback(JSON.parse(ajax.responseText));
// }
// };
}
}
function getProCurrentHref () {
let _href = window.location.href
let index = _href.indexOf('#')
let newHref = _href.slice(0, index)
let flag = !window.lbConfig.isWe7
newHref = window.lbConfig.isWe7 ? newHref + '&s=' : window.location.origin
return {url: newHref, flag}
}

View File

@@ -0,0 +1,121 @@
/*
* @Descripttion: 认养管理
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-13 12:58:39
*/
import {
get,
post
} from '../index'
export default {
// 分类列表
claimCateList (querys) {
return get('/farm/admin/AdminClaim/claimCateList', querys)
},
// 土地/认养分类下拉 type 1土地2认养
landAndClaimCate (querys) {
return get('farm/admin/AdminClaim/landAndClaimCate', querys)
},
// 分类详情
claimCateInfo (querys) {
return get('/farm/admin/AdminClaim/claimCateInfo', querys)
},
// 新增分类
claimCateAdd (querys) {
return post('/farm/admin/AdminClaim/claimCateAdd', querys)
},
// 编辑分类
claimCateUpdate (querys) {
return post('/farm/admin/AdminClaim/claimCateUpdate', querys)
},
// 认养列表
claimList (querys) {
return get('farm/admin/AdminClaim/claimList', querys)
},
// 认养详情
claimInfo (querys) {
return get('farm/admin/AdminClaim/claimInfo', querys)
},
// 新增认养
claimAdd (querys) {
return post('farm/admin/AdminClaim/claimAdd', querys)
},
// 编辑认养
claimUpdate (querys) {
return post('farm/admin/AdminClaim/claimUpdate', querys)
},
// 上下架/删除认养
claimStatusUpdate (querys) {
return post('farm/admin/AdminClaim/claimStatusUpdate', querys)
},
// 养殖列表
breedList (querys) {
return get('/farm/admin/AdminBreed/breedList', querys)
},
// 养殖详情
breedInfo (querys) {
return get('/farm/admin/AdminBreed/breedInfo', querys)
},
// 新增养殖
breedAdd (querys) {
return post('/farm/admin/AdminBreed/breedAdd', querys)
},
// 编辑养殖
breedUpdate (querys) {
return post('/farm/admin/AdminBreed/breedUpdate', querys)
},
// 拼团列表
collageList (querys) {
return get('/farm/admin/AdminClaim/collageList', querys)
},
// 拼团详情
collageInfo (querys) {
return get('/farm/admin/AdminClaim/collageInfo', querys)
},
// 新增拼团
collageAdd (querys) {
return post('/farm/admin/AdminClaim/collageAdd', querys)
},
// 编辑拼团
collageUpdate (querys) {
return post('/farm/admin/AdminClaim/collageUpdate', querys)
},
// 订单管理
orderList (querys) {
return get('/farm/admin/AdminClaim/orderList', querys)
},
// 订单详情
orderInfo (querys) {
return get('/farm/admin/AdminClaim/orderInfo', querys)
},
// 订单关联配送订单
userSendOrderList (querys) {
return get('/farm/admin/AdminClaim/userSendOrderList', querys)
},
// 配送订单列表
sendOrderList (querys) {
return get('/farm/admin/AdminClaim/sendOrderList', querys)
},
// 配送订单详情
sendOrderInfo (querys) {
return get('/farm/admin/AdminClaim/sendOrderInfo', querys)
},
// 配送订单收货
sendOrderReceiving (querys) {
return post('/farm/admin/AdminClaim/sendOrderReceiving', querys)
},
// 配送订单发货
sendOrderSend (querys) {
return post('/farm/admin/AdminClaim/sendOrderSend', querys)
},
// 评价管理
evaluateList (querys) {
return get('/farm/admin/AdminUser/evaluateList', querys)
},
// 编辑评价
evaluateUpdate (querys) {
return post('/farm/admin/AdminUser/evaluateUpdate', querys)
}
}

View File

@@ -0,0 +1,45 @@
/*
* @Description: 会员管理
* @Author: xiao li
* @Date: 2022-06-30 10:06:40
* @LastEditTime: 2022-07-20 17:09:46
* @LastEditors: xiao li
*/
import {
get, post
} from '../index'
export default {
// 会员列表
userList (querys) {
return get('/farm/admin/AdminUser/userList', querys)
},
// 编辑会员
userUpdate (querys) {
return post('/farm/admin/AdminUser/userUpdate', querys)
},
// 编辑会员积分
userIntegralUpdate (querys) {
return post('/farm/admin/AdminUser/userIntegralUpdate', querys)
},
// 会员等级列表
memberList (querys) {
return get('/shop/admin/AdminMember/memberList', querys)
},
// 会员等级下拉
memberSelect (querys) {
return get('/shop/admin/AdminMember/memberSelect', querys)
},
// 会员等级详情
memberInfo (querys) {
return get('/shop/admin/AdminMember/memberInfo', querys)
},
// 新增会员等级
memberAdd (querys) {
return post('/shop/admin/AdminMember/memberAdd', querys)
},
// 编辑会员等级
memberUpdate (querys) {
return post('/shop/admin/AdminMember/memberUpdate', querys)
}
}

View File

@@ -0,0 +1,42 @@
/*
* @Description: 营销管理
* @Author: xiao li
* @Date: 2021-07-06 18:32:16
* @LastEditTime: 2022-07-29 15:38:48
* @LastEditors: xiao li
*/
import {
get,
post
} from '../index'
export default {
// 审核列表
resellerList (querys) {
return get('/farm/admin/AdminReseller/resellerList', querys)
},
// 分销商详情
resellerInfo (querys) {
return get('/farm/admin/AdminReseller/resellerInfo', querys)
},
// 审核分销商
resellerUpdate (querys) {
return post('/farm/admin/AdminReseller/resellerUpdate', querys)
},
// 分销关系列表
userRelationshipList (querys) {
return get('/farm/admin/AdminReseller/userRelationshipList', querys)
},
// 分销关系查找
userRelationshipListFind (querys) {
return get('/farm/admin/AdminReseller/userRelationshipListFind', querys)
},
// 收益信息
userProfitList (querys) {
return get('/farm/admin/AdminReseller/userProfitList', querys)
},
// 佣金信息
cashList (querys) {
return get('/farm/admin/AdminReseller/cashList', querys)
}
}

View File

@@ -0,0 +1,46 @@
/*
* @Description: 农场主审核
* @Author: xiao li
* @Date: 2021-07-06 18:30:52
* @LastEditTime: 2022-07-19 14:56:49
* @LastEditors: xiao li
*/
import {
get,
post
} from '../index'
export default {
// 平台统计详情
statisticsCash (querys) {
return get('/farm/admin/AdminFarmer/statisticsCash', querys)
},
// 用户统计详情
statisticsUser (querys) {
return get('/farm/admin/AdminFarmer/statisticsUser', querys)
},
// 农场主列表
farmerList (querys) {
return get('/farm/admin/AdminFarmer/farmerList', querys)
},
// 农场主下拉
farmerSelectList (querys) {
return get('/farm/admin/AdminFarmer/farmerSelectList', querys)
},
// 店主下拉
storeSelect (querys) {
return get('/farm/admin/AdminFarmer/storeSelect', querys)
},
// 农场主详情
farmerInfo (querys) {
return get('/farm/admin/AdminFarmer/farmerInfo', querys)
},
// 新增农场主/店主
farmerAdd (querys) {
return post('/farm/admin/AdminFarmer/farmerAdd', querys)
},
// 农场主审核(status2通过,3拒绝,sh_text)
farmerUpdate (querys) {
return post('/farm/admin/AdminFarmer/farmerUpdate', querys)
}
}

View File

@@ -0,0 +1,34 @@
/*
* @Description: 财务管理
* @Author: xiao li
* @Date: 2021-11-12 16:30:33
* @LastEditTime: 2022-02-17 16:48:31
* @LastEditors: xiao li
*/
import {
get,
post
} from '../index'
export default {
// 财务管理
fincanceWaterList (querys) {
return get('/farm/admin/AdminFarmer/fincanceWaterList', querys)
},
// 财务管理详情
fincanceWaterInfo (querys) {
return get('/farm/admin/AdminFarmer/fincanceWaterInfo', querys)
},
// 提现申请
walletList (querys) {
return get('/farm/admin/AdminFarmer/walletList', querys)
},
// 同意打款id,status=2,online 1线上0线下
walletPass (querys) {
return post('/farm/admin/AdminFarmer/walletPass', querys)
},
// 拒绝打款id,status=3
walletNoPass (querys) {
return post('/farm/admin/AdminFarmer/walletNoPass', querys)
}
}

View File

@@ -0,0 +1,53 @@
/*
* @Description: 硬件设备
* @Author: xiao li
* @Date: 2022-04-11 14:32:24
* @LastEditTime: 2022-07-04 18:53:59
* @LastEditors: xiao li
*/
import {
get,
post
} from '../index'
export default {
// 仪器列表
machineList (querys) {
return get('/farm/admin/AdminFarmer/machineList', querys)
},
// 仪器下拉
machineSelect (querys) {
return get('farm/admin/AdminFarmer/machineSelect', querys)
},
// 仪器信息
machineInfo (querys) {
return get('/farm/admin/AdminFarmer/machineInfo', querys)
},
// 新增仪器
machineAdd (querys) {
return post('/farm/admin/AdminFarmer/machineAdd', querys)
},
// 编辑仪器
machineUpdate (querys) {
return post('/farm/admin/AdminFarmer/machineUpdate', querys)
},
// 监控列表
monitorList (querys) {
return get('/farm/admin/AdminFarmer/monitorList', querys)
},
// 监控下拉
monitorSelect (querys) {
return get('farm/admin/AdminFarmer/monitorSelect', querys)
},
// 监控信息
monitorInfo (querys) {
return get('/farm/admin/AdminFarmer/monitorInfo', querys)
},
// 新增监控
monitorAdd (querys) {
return post('/farm/admin/AdminFarmer/monitorAdd', querys)
},
// 编辑监控
monitorUpdate (querys) {
return post('/farm/admin/AdminFarmer/monitorUpdate', querys)
}
}

View File

@@ -0,0 +1,28 @@
/*
* @Descripttion: api
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-29 11:03:28
*/
import base from './base'
import upload from './upload'
import farmer from './farmer'
import land from './land'
import claim from './claim'
import shop from './shop'
import finance from './finance'
import distribution from './distribution'
import market from './market'
import stored from './stored'
import media from './media'
import hardware from './hardware'
import custom from './custom'
import account from './account'
import system from './system'
let modules = {
base, upload, farmer, land, claim, shop, finance, distribution, market, stored, media, hardware, account, custom, system
}
export default {
...modules
}

View File

@@ -0,0 +1,88 @@
/*
* @Descripttion: 土地管理
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-12 17:19:43
*/
import {
get, post
} from '../index'
export default {
// 土地列表
landList (querys) {
return get('farm/admin/AdminLand/landList', querys)
},
// 土地详情
landInfo (querys) {
return get('farm/admin/AdminLand/landInfo', querys)
},
// 新增土地
landAdd (querys) {
return post('farm/admin/AdminLand/landAdd', querys)
},
// 编辑土地
landUpdate (querys) {
return post('farm/admin/AdminLand/landUpdate', querys)
},
// 上下架/删除土地
landStatusUpdate (querys) {
return post('farm/admin/AdminLand/landStatusUpdate', querys)
},
// 地块列表
massifList (querys) {
return get('farm/admin/AdminMassif/massifList', querys)
},
// 地块下拉
massifSelect (querys) {
return get('farm/admin/AdminMassif/massifSelect', querys)
},
// 地块详情
massifInfo (querys) {
return get('farm/admin/AdminMassif/massifInfo', querys)
},
// 新增地块
massifAdd (querys) {
return post('farm/admin/AdminMassif/massifAdd', querys)
},
// 编辑地块
massifUpdate (querys) {
return post('farm/admin/AdminMassif/massifUpdate', querys)
},
// 种子列表
seedList (querys) {
return get('farm/admin/AdminSeed/seedList', querys)
},
// 种子下拉
seedSelect (querys) {
return get('farm/admin/AdminSeed/seedSelect', querys)
},
// 种子详情
seedInfo (querys) {
return get('farm/admin/AdminSeed/seedInfo', querys)
},
// 新增种子
seedAdd (querys) {
return post('farm/admin/AdminSeed/seedAdd', querys)
},
// 编辑种子
seedUpdate (querys) {
return post('farm/admin/AdminSeed/seedUpdate', querys)
},
// 上下架/删除种子
seedStatusUpdate (querys) {
return post('farm/admin/AdminSeed/seedStatusUpdate', querys)
},
// 订单管理
orderList (querys) {
return get('/farm/admin/AdminLand/orderList', querys)
},
// 订单详情
orderInfo (querys) {
return get('/farm/admin/AdminLand/orderInfo', querys)
},
// 配送订单
userSendOrderList (querys) {
return get('/farm/admin/AdminLand/userSendOrderList', querys)
}
}

View File

@@ -0,0 +1,122 @@
/*
* @Description: 营销管理
* @Author: xiao li
* @Date: 2021-07-06 18:32:16
* @LastEditTime: 2022-07-25 17:01:07
* @LastEditors: xiao li
*/
import {
get,
post
} from '../index'
export default {
// 优惠券列表
couponList (querys) {
return get('/farm/admin/AdminCoupon/couponList', querys)
},
// 优惠券下拉列表
couponSelect (querys) {
return get('/farm/admin/AdminCoupon/couponSelect', querys)
},
// 优惠券详情
couponInfo (querys) {
return get('/farm/admin/AdminCoupon/couponInfo', querys)
},
// 新增优惠券
couponAdd (querys) {
return post('/farm/admin/AdminCoupon/couponAdd', querys)
},
// 编辑优惠券
couponUpdate (querys) {
return post('/farm/admin/AdminCoupon/couponUpdate', querys)
},
// 上下架/删除
couponStatusUpdate (querys) {
return post('/farm/admin/AdminCoupon/couponStatusUpdate', querys)
},
// 派发卡券
couponRecordAdd (querys) {
return post('/farm/admin/AdminCoupon/couponRecordAdd', querys)
},
// 活动详情
couponAtvInfo (querys) {
return get('/farm/admin/AdminCoupon/couponAtvInfo', querys)
},
// 编辑活动
couponAtvUpdate (querys) {
return post('/farm/admin/AdminCoupon/couponAtvUpdate', querys)
},
// 积分列表
integralList (querys) {
return get('/shop/admin/AdminMark/integralList', querys)
},
// 积分详情
integralInfo (querys) {
return get('/shop/admin/AdminMark/integralInfo', querys)
},
// 新增积分
integralAdd (querys) {
return post('/shop/admin/AdminMark/integralAdd', querys)
},
// 编辑积分
integralUpdate (querys) {
return post('/shop/admin/AdminMark/integralUpdate', querys)
},
// 签到详情
signInfo (querys) {
return get('/shop/admin/AdminMark/signInfo', querys)
},
// 编辑签到
signUpdate (querys) {
return post('/shop/admin/AdminMark/signUpdate', querys)
},
// 抽奖列表
luckList (querys) {
return get('/shop/admin/AdminMark/luckList', querys)
},
// 抽奖详情
luckInfo (querys) {
return get('/shop/admin/AdminMark/luckInfo', querys)
},
// 新增抽奖
luckAdd (querys) {
return post('/shop/admin/AdminMark/luckAdd', querys)
},
// 编辑抽奖
luckUpdate (querys) {
return post('/shop/admin/AdminMark/luckUpdate', querys)
},
// 秒杀列表
killList (querys) {
return get('/shop/admin/AdminMark/killList', querys)
},
// 秒杀详情
killInfo (querys) {
return get('/shop/admin/AdminMark/killInfo', querys)
},
// 新增秒杀
killAdd (querys) {
return post('/shop/admin/AdminMark/killAdd', querys)
},
// 编辑秒杀
killUpdate (querys) {
return post('/shop/admin/AdminMark/killUpdate', querys)
},
// 秒杀商品列表
killGoodsList (querys) {
return get('/shop/admin/AdminMark/killGoodsList', querys)
},
// 秒杀商品详情
killGoodsInfo (querys) {
return get('/shop/admin/AdminMark/killGoodsInfo', querys)
},
// 新增秒杀商品
addKillGoods (querys) {
return post('/shop/admin/AdminMark/addKillGoods', querys)
},
// 删除秒杀商品
killGoodsDel (querys) {
return post('/shop/admin/AdminMark/killGoodsDel', querys)
}
}

View File

@@ -0,0 +1,85 @@
/*
* @Descripttion: 多媒体管理
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-01 14:45:08
*/
import {
get,
post
} from '../index'
export default {
// 轮播图列表
bannerList (querys) {
return post('/farm/admin/AdminSetting/bannerList', querys)
},
// 轮播图信息
bannerInfo (querys) {
return get('/farm/admin/AdminSetting/bannerInfo', querys)
},
// 新增轮播图
bannerAdd (querys) {
return post('/farm/admin/AdminSetting/bannerAdd', querys)
},
// 编辑轮播图
bannerUpdate (querys) {
return post('/farm/admin/AdminSetting/bannerUpdate', querys)
},
// 文章列表
articleList (querys) {
return get('/farm/admin/AdminSetting/articleList', querys)
},
// 文章下拉框
articleSelect (querys) {
return get('/farm/admin/AdminSetting/articleSelect', querys)
},
// 文章详情
articleInfo (querys) {
return get('/farm/admin/AdminSetting/articleInfo', querys)
},
// 新增文章
articleAdd (querys) {
return post('/farm/admin/AdminSetting/articleAdd', querys)
},
// 编辑文章
articleUpdate (querys) {
return post('/farm/admin/AdminSetting/articleUpdate', querys)
},
// 关于我们列表 type 0关于我们1认养2土地
aboutUsList (querys) {
return get('/farm/admin/AdminSetting/aboutUsList', querys)
},
// 根据type获取详情
aboutUsInfoType (querys) {
return get('/farm/admin/AdminSetting/aboutUsInfoType', querys)
},
// 关于我们详情
aboutUsInfo (querys) {
return get('/farm/admin/AdminSetting/aboutUsInfo', querys)
},
// 新增关于我们
aboutUsAdd (querys) {
return post('/farm/admin/AdminSetting/aboutUsAdd', querys)
},
// 编辑关于我们
aboutUsUpdate (querys) {
return post('/farm/admin/AdminSetting/aboutUsUpdate', querys)
},
// 公益栏目列表
welfareList (querys) {
return get('/farm/admin/AdminSetting/welfareList', querys)
},
// 公益栏目详情
welfareInfo (querys) {
return get('/farm/admin/AdminSetting/welfareInfo', querys)
},
// 新增公益栏目 type:1公益栏目 2系统公告 3运营公告
welfareAdd (querys) {
return post('/farm/admin/AdminSetting/welfareAdd', querys)
},
// 编辑公益栏目
welfareUpdate (querys) {
return post('/farm/admin/AdminSetting/welfareUpdate', querys)
}
}

View File

@@ -0,0 +1,117 @@
/*
* @Descripttion: 商城
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-08-24 11:13:07
*/
import {
get,
post
} from '../index'
export default {
// 分类列表
goodsCateList (querys) {
return get('/shop/admin/AdminGoods/goodsCateList', querys)
},
// 分类下拉
goodsCateSelect (querys) {
return get('/shop/admin/AdminGoods/goodsCateSelect', querys)
},
// 分类详情
goodsCateInfo (querys) {
return get('/shop/admin/AdminGoods/goodsCateInfo', querys)
},
// 新增分类
goodsCateAdd (querys) {
return post('/shop/admin/AdminGoods/goodsCateAdd', querys)
},
// 编辑分类
goodsCateUpdate (querys) {
return post('/shop/admin/AdminGoods/goodsCateUpdate', querys)
},
// 商品列表
goodsList (querys) {
return get('/shop/admin/AdminGoods/goodsList', querys)
},
// 商品详情
goodsInfo (querys) {
return get('/shop/admin/AdminGoods/goodsInfo', querys)
},
// 新增商品
goodsAdd (querys) {
return post('/shop/admin/AdminGoods/goodsAdd', querys)
},
// 编辑商品
goodsUpdate (querys) {
return post('/shop/admin/AdminGoods/goodsUpdate', querys)
},
// 复制商品
goodsCopy (querys) {
return post('/shop/admin/AdminGoods/goodsCopy', querys)
},
// 上下架商品status1,0和删除商品status-1
goodsStatusUpdate (querys) {
return post('/shop/admin/AdminGoods/goodsStatusUpdate', querys)
},
// 编辑商品库存
updateSpe (querys) {
return post('/shop/admin/AdminGoods/updateSpe', querys)
},
// 编辑商品信息
goodsBasicUpdate (querys) {
return post('/shop/admin/AdminGoods/goodsBasicUpdate', querys)
},
// 运费模版列表
tmplSelect (querys) {
return get('/shop/admin/AdminFreight/tmplSelect', querys)
},
// 运费模版列表
tmplList (querys) {
return get('/shop/admin/AdminFreight/tmplList', querys)
},
// 运费模版详情
tmplInfo (querys) {
return get('/shop/admin/AdminFreight/tmplInfo', querys)
},
// 新增运费模版
tmplAdd (querys) {
return post('/shop/admin/AdminFreight/tmplAdd', querys)
},
// 编辑运费模版
tmplUpdate (querys) {
return post('/shop/admin/AdminFreight/tmplUpdate', querys)
},
// 订单管理
orderList (querys) {
return get('/farm/admin/AdminOrder/orderList', querys)
},
// 订单详情
orderInfo (querys) {
return get('/farm/admin/AdminOrder/orderInfo', querys)
},
// 发货
shopOrderSend (querys) {
return post('/farm/admin/AdminOrder/shopOrderSend', querys)
},
// 上传视频
uploadVideo (querys) {
return post('/farm/admin/AdminOrder/uploadVideo', querys)
},
// 退款管理
refundOrderList (querys) {
return get('/farm/admin/AdminOrder/refundOrderList', querys)
},
// 退款详情
refundOrderInfo (querys) {
return get('/farm/admin/AdminOrder/refundOrderInfo', querys)
},
// 同意退款
passRefund (querys) {
return post('/farm/admin/AdminOrder/passRefund', querys)
},
// 拒绝退款
noPassRefund (querys) {
return post('/farm/admin/AdminOrder/noPassRefund', querys)
}
}

View File

@@ -0,0 +1,38 @@
/*
* @Description: 储值管理
* @Author: xiao li
* @Date: 2021-07-03 11:41:05
* @LastEditTime: 2021-09-15 13:33:20
* @LastEditors: xiao li
*/
import {
get,
post
} from '../index'
export default {
// 储值充值卡列表
cardList (querys) {
return get('/farm/admin/AdminBalance/cardList', querys)
},
// 储值充值卡详情
cardInfo (querys) {
return get('/farm/admin/AdminBalance/cardInfo', querys)
},
// 新增储值充值卡
cardAdd (querys) {
return post('/farm/admin/AdminBalance/cardAdd', querys)
},
// 编辑储值充值卡
cardUpdate (querys) {
return post('/farm/admin/AdminBalance/cardUpdate', querys)
},
// 储值订单列表
orderList (querys) {
return get('/farm/admin/AdminBalance/orderList', querys)
},
// 储值订单详情
orderInfo (querys) {
return get('/farm/admin/AdminBalance/orderInfo', querys)
}
}

View File

@@ -0,0 +1,57 @@
/*
* @Descripttion: 系统设置
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2022-07-12 13:42:58
*/
import {
get,
post
} from '../index'
export default {
// 获取上传配置信息
getOssConfig (querys) {
return get('/admin/admin/config/getOssConfig', querys)
},
// 设置上传配置信息
updateOssConfig (querys) {
return post('/admin/admin/config/updateOssConfig', querys)
},
// 获取系统配置信息
configInfo (querys) {
return post('/farm/admin/AdminSetting/configInfo', querys)
},
// 设置系统配置信息
configUpdate (querys) {
return post('/farm/admin/AdminSetting/configUpdate', querys)
},
// 获取支付配置信息
payConfigInfo (querys) {
return post('/farm/admin/AdminSetting/payConfigInfo', querys)
},
// 设置支付配置信息
payConfigUpdate (querys) {
return post('/farm/admin/AdminSetting/payConfigUpdate', querys)
},
// 获取配送信息
sendConfigInfo (querys) {
return get('/farm/admin/AdminSetting/sendConfigInfo', querys)
},
// 设置配送信息
sendConfigUpdate (querys) {
return post('/farm/admin/AdminSetting/sendConfigUpdate', querys)
},
// 获取订阅消息模板列表
tmpLists (querys) {
return post('/publics/tmpl/AdminTmpl/tmpLists', querys)
},
// 自动同步模板ID
getTmplId (querys) {
return post('/publics/tmpl/AdminTmpl/getTmplId', querys)
},
// 保存订阅消息模板
tmplUpdate (querys) {
return post('/publics/tmpl/AdminTmpl/tmplUpdate', querys)
}
}

View File

@@ -0,0 +1,50 @@
/*
* @Descripttion: 文件上传
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2021-09-10 16:36:24
*/
import { post, get, postUpload } from '../index'
export default {
// 新增分组
addGroup (querys) {
return post('/admin/admin/file/createGroup', querys)
},
// 修改分组
updateGroup (querys) {
return post('/admin/admin/file/updateGroup', querys)
},
// 移动分组
moveGroup (querys) {
return post('/admin/admin/file/moveGroup', querys)
},
// 删除单个分组
delGroup (querys) {
return post('/admin/admin/file/delGroup', querys)
},
delGroups (querys) {
return post('/admin/admin/file/delAllGroup', querys)
},
// 获取上传商品分组列表
getGroupsList () {
return get('/admin/admin/file/listGroup')
},
// 上传图片
uploadFiles (querys, fn) {
return postUpload('/admin/admin/file/uploadFiles', querys, fn)
},
// 上传文件到云存储后返回给后端
uploadAddFile (querys) {
return post('/admin/admin/file/addFile', querys)
},
// 获取图片,视频,音频等 1=>图片 2=>音频 3=>视频
getUploadFiles (querys) {
return get('/admin/admin/file/listFile', querys)
},
// 删除图片,视频,音乐等
delFiles (querys) {
return post('/admin/admin/file/delFile', querys)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,81 @@
<!--
* @Descripttion: 左侧边栏广告
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2021-03-15 13:22:26
-->
<template>
<div class="lb-ad" :class="!adSwitch ? 'ad-collapse' : ''">
<div class="ad-main">
<!-- <lb-image src="@/assets/icon/apps.png"/> -->
</div>
<div class="flod" @click="handleFold">{{adSwitch ? '折叠' : '展开'}}</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
data () {
return {
key: '广告'
}
},
created () {
},
methods: {
handleFold () {
let {adSwitch} = this
this.$store.commit('handleAdSwitch', !adSwitch)
}
},
computed: {
...mapGetters(['adSwitch'])
}
}
</script>
<style lang="scss" scoped>
.lb-ad{
width: 220px;
position: fixed;
transition: width 0.2s linear;
top: 70px;
right: 0;
height: 1000px;
z-index: 2;
.ad-main{
position: absolute;
top: 0;
left: 0;
width: 220px;
background: #fff;
height: 100%;
font-size: 14px;
padding: 10px;
}
.flod{
position: absolute;
top: 0;
bottom: 0;
left: -20px;
margin: auto;
width: 20px;
height: 80px;
background: #BFBFBF;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
cursor: pointer;
color: #fff;
font-size: 14px;
}
}
.ad-collapse{
width: 0px;
}
</style>

View File

@@ -0,0 +1,28 @@
import Vue from 'vue'
import TopNav from './topNav.vue'
import LbButton from './lbButton.vue'
import LbSwitch from './lbSwitch.vue'
import LbTips from './lbTips.vue'
import LbPage from './lbPage.vue'
import LbClassifyTitle from './lbClassifyTitle.vue'
import LbUpload from './lbUpload.vue'
import LbToolTips from './lbToolTips.vue'
import LbUploadCover from './lbUploadCover.vue'
import LbUeditor from './lbUeditor.vue'
import LbCover from './lbCover.vue'
import LbImage from './lbImage.vue'
import LbMap from './lbMap.vue'
Vue.component('top-nav', TopNav)
Vue.component('lb-button', LbButton)
Vue.component('lb-switch', LbSwitch)
Vue.component('lb-tips', LbTips)
Vue.component('lb-page', LbPage)
Vue.component('lb-classify-title', LbClassifyTitle)
Vue.component('lb-upload', LbUpload)
Vue.component('lb-tool-tips', LbToolTips)
Vue.component('lb-upload-cover', LbUploadCover)
Vue.component('lb-ueditor', LbUeditor)
Vue.component('lb-cover', LbCover)
Vue.component('lb-image', LbImage)
Vue.component('lb-map', LbMap)

View File

@@ -0,0 +1,79 @@
<template>
<el-button
:disabled="isDisabled"
:type="type"
:plain="plain"
:round="round"
:icon="icon"
:size="size"
:loading='loading'
@click="handleClick"
>
<slot></slot>
</el-button>
</template>
<script>
export default {
props: {
type: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
plain: {
type: Boolean,
default: false
},
round: {
type: Boolean,
default: false
},
icon: {
type: String,
default: ''
},
size: {
type: String,
default: 'medium'
},
opType: {
type: String,
default: ''
},
loading: {
type: Boolean,
default: false
}
},
data () {
return {
isDisabled: this.disabled,
currentIndex: this.$store.state.operate.currentIndex
}
},
created () {
let {isOnly, auth, pagePermission} = this.$route.meta
let {disabled} = this
if (disabled) {
this.isDisabled = disabled
} else if (this.opType) {
if (isOnly) {
this.isDisabled = auth.indexOf(this.opType) === -1
} else {
this.isDisabled = pagePermission[this.currentIndex].auth.indexOf(this.opType) === -1
}
}
},
methods: {
handleClick () {
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped></style>

View File

@@ -0,0 +1,39 @@
<!--
* @Description: 标题栏
* @Author: xiao li
* @Date: 2021-07-04 00:16:14
* @LastEditTime: 2021-09-10 16:31:28
* @LastEditors: xiao li
-->
<template>
<div class="lb-goods-edit-classify mb-lg">
<div class="title">{{ title }}</div>
<span v-if="tips" class="tips">{{ tips }}</span>
</div>
</template>
<script>
export default {
props: ['title', 'tips']
}
</script>
<style lang="scss" scoped>
.lb-goods-edit-classify {
width: 100%;
border-top: 1px solid $lineColor;
display: flex;
align-items: center;
.title {
display: inline-block;
padding: 6px 15px;
color: $themeColor;
background: $columnBgColor;
margin-right: 10px;
}
.tips {
color: $tipsColor;
font-size: 12px;
}
}
</style>

View File

@@ -0,0 +1,375 @@
<template>
<div class="lb-cover-wrap">
<div
class="lb-cover"
:class="[size]"
@click="showUploadModel"
v-if="type === 'single'"
>
<lb-image v-if="cover.length > 0" :src="cover[cover.length - 1].url" />
<i v-else class="el-icon-plus"></i>
<i
v-if="cover.length > 0"
@click.stop="deleteCover"
class="el-icon-circle-close"
></i>
</div>
<div v-else-if="type === 'more'" class="lb-upload-more">
<vuedraggable @change="dragChange" v-model="cover">
<transition-group class="flex-warp">
<div
class="more-item"
:class="[size]"
v-for="(item, index) in cover"
:key="`drag_${index}`"
>
<lb-image :src="item.url" />
<div class="mask">
<i
@click="lookBigImg(item.url)"
class="el-icon-zoom-in"
v-if="item.url"
></i>
<i
@click="delImg(index)"
class="el-icon-delete"
v-if="isToDel"
></i>
</div>
</div>
</transition-group>
</vuedraggable>
<div class="flex-warp" v-if="cover.length < fileSize">
<div class="up-item" :class="[size]" @click="showUploadModel">
<i class="el-icon-plus"></i>
</div>
<lb-tool-tips class="ml-sm" v-if="tips">{{
`图片建议尺寸${tips}`
}}</lb-tool-tips>
</div>
<el-dialog
:visible.sync="centerDialogVisible"
width="800px"
center
:append-to-body="true"
>
<div class="dialog-inner-img">
<lb-image class="dialog-img" :src="viewImg" />
</div>
</el-dialog>
</div>
<lb-button type="primary" size="mini" @click="showUploadModel" v-else
>选择</lb-button
>
<block v-if="isToDel">
<lb-upload
:paramData="paramData"
:filesLength="fileList.length"
:fileSize="fileSize"
:multilineType="type"
:visibles.sync="showUpload"
:fileType="fileType"
:fileAccept="fileAccept"
@selectedFiles="selectedFiles"
></lb-upload>
</block>
</div>
</template>
<script>
import vuedraggable from 'vuedraggable'
export default {
components: {
vuedraggable
},
props: {
type: {
type: String,
default () {
return 'single'
}
},
size: {
type: String,
default () {
return 'big'
}
},
tips: {
type: String,
default () {
return ''
}
},
fileType: {
type: String,
default () {
return 'image'
}
},
fileAccept: {
type: String,
default () {
return ''
}
},
fileSize: {
type: Number,
default () {
return 9
}
},
fileList: {
type: [Array, String],
default () {
return []
}
},
isToDel: {
type: Boolean,
default () {
return true
}
},
paramData: {
type: Object,
default () {
return {}
}
}
},
data () {
return {
showUpload: false,
cover: [],
centerDialogVisible: false,
viewImg: ''
}
},
created () {
if (this.fileList && this.fileList.length) {
this.cover = this.fileList
}
},
methods: {
selectedFiles (img) {
if (!img.length) return false
let selectedImgs = this.type === 'single' ? [img[img.length - 1]] : img
this.cover = selectedImgs
this.$emit('selectedFiles', selectedImgs)
},
dragChange (e) {
this.$emit('moveFiles', this.cover)
},
showUploadModel () {
this.showUpload = true
},
lookBigImg (url) {
this.viewImg = url
this.centerDialogVisible = true
},
delImg (index) {
this.cover.splice(index, 1)
},
deleteCover () {
this.cover = []
this.$emit('selectedFiles', [])
}
},
watch: {
fileList: {
deep: true,
handler (val) {
if (val && typeof val === 'object') {
this.cover = val
}
}
}
}
}
</script>
<style lang="scss" scoped>
.lb-cover-wrap {
display: inline-block;
.lb-cover.small {
width: 60px;
height: 60px;
.el-image {
width: 60px;
height: 60px;
}
i {
font-size: 20px;
line-height: 60px;
}
.el-icon-circle-close {
font-size: 18px;
line-height: 18px;
}
}
.lb-cover.middle {
width: 80px;
height: 80px;
.el-image {
width: 80px;
height: 80px;
}
i {
font-size: 20px;
line-height: 80px;
}
.el-icon-circle-close {
font-size: 22px;
line-height: 22px;
}
}
.lb-cover {
width: 100px;
height: 100px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
text-align: center;
overflow: hidden;
position: relative;
.el-image {
width: 100px;
height: 100px;
}
i {
font-size: 26px;
line-height: 100px;
}
&:hover {
border: 1px dashed #09f;
.el-icon-circle-close {
display: inline-block;
}
}
.el-icon-circle-close {
display: none;
z-index: 10;
position: absolute;
right: 5px;
top: 5px;
line-height: 1;
}
}
.lb-upload-more {
width: 100%;
display: flex;
flex-wrap: wrap;
.more-item.small {
width: 60px;
height: 60px;
.el-image {
width: 60px;
height: 60px;
z-index: 5;
}
}
.more-item.middle {
width: 80px;
height: 80px;
.el-image {
width: 80px;
height: 80px;
z-index: 5;
}
}
.more-item {
width: 100px;
height: 100px;
border: 1px solid #d9d9d9;
border-radius: 6px;
position: relative;
margin-right: 10px;
margin-bottom: 10px;
overflow: hidden;
.el-image {
width: 100px;
height: 100px;
z-index: 5;
}
.mask {
display: none;
position: absolute;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
font-size: 20px;
color: #fff;
justify-content: center;
align-items: center;
z-index: 10;
top: 0;
left: 0;
i {
margin: 0 10px;
cursor: pointer;
}
}
&:hover {
.mask {
display: flex;
}
}
}
.up-item {
width: 100px;
height: 100px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
text-align: center;
i {
font-size: 26px;
line-height: 100px;
}
&:hover {
border: 1px dashed #09f;
}
}
.up-item.small {
width: 60px;
height: 60px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
text-align: center;
i {
font-size: 18px;
line-height: 60px;
}
&:hover {
border: 1px dashed #09f;
}
}
.up-item.middle {
width: 80px;
height: 80px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
text-align: center;
i {
font-size: 22px;
line-height: 80px;
}
&:hover {
border: 1px dashed #09f;
}
}
}
.dialog-inner-img {
display: flex;
justify-content: center;
align-items: center;
.dialog-img {
width: 100%;
}
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<el-image :fit="fit" :src="src">
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</template>
<script>
export default {
props: {
fit: {
type: String,
default: 'cover'
},
src: {
type: String,
default: ''
}
}
}
</script>
<style lang="scss" scoped>
.el-image{
background: $bgThemeColor;
display: flex;
justify-content: center;
align-items: center;
.image-slot{
i{
font-size: 20px;
}
}
}
</style>

View File

@@ -0,0 +1,173 @@
<template>
<el-dialog
title="获取经纬度"
:visible.sync="centerDialogVisible"
width="600px"
center
:append-to-body="true"
>
<div class="dialog-inner">
<div class="map-search">
<el-input placeholder="输入地址" v-model="address"></el-input>
<lb-button size="mini" type="primary" @click="searchMapAddr"
> </lb-button
>
</div>
<div id="container"></div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible = false">{{
$t('action.cancel')
}}</el-button>
<el-button type="primary" @click="confirmLatLng">{{
$t('action.comfirm')
}}</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
props: {
dialogVisible: {
type: Boolean,
default: false
}
},
data () {
return {
centerDialogVisible: false,
map: null,
info: null,
address: '',
marker: '',
geocoder: null,
latLng: {
lat: 30.657535,
lng: 104.065783
}
}
},
methods: {
initMap () {
let that = this
let { lat, lng } = this.latLng
// 中心坐标
// eslint-disable-next-line no-undef
let center = new qq.maps.LatLng(lat, lng)
// eslint-disable-next-line no-undef
let map = new qq.maps.Map(
document.getElementById('container'),
{
center: center,
zoom: 12
}
)
that.map = map
// eslint-disable-next-line no-undef
that.info = new qq.maps.InfoWindow({
map: map
})
// eslint-disable-next-line no-undef
qq.maps.event.addListener(map, 'click', async function (val, el) {
if (that.marker) { that.marker.setMap(null) }
let { lat, lng } = val.latLng
that.latLng = val.latLng
// eslint-disable-next-line no-undef
that.marker = new qq.maps.Marker({
// 标记的位置
// eslint-disable-next-line no-undef
position: new qq.maps.LatLng(lat, lng),
map: map
})
that.info.open()
that.info.setContent(`<div style="margin:10px;">
<p>纬度:${lat}</p>
<p>经度:${lng}</p>
</div>`)
// eslint-disable-next-line no-undef
that.info.setPosition(new qq.maps.LatLng(lat, lng))
})
},
openQQMap () {
setTimeout(() => {
this.initMap()
this.initGeocoder()
}, 500)
},
/**
* @method 根据位置搜索坐标
*/
searchMapAddr () {
let { address } = this
this.geocoder.getLocation(address)
},
initGeocoder () {
let that = this
// eslint-disable-next-line no-undef
that.geocoder = new qq.maps.Geocoder()
// 设置服务请求成功的回调函数
that.geocoder.setComplete(function (result) {
let { lat, lng } = result.detail.location
that.latLng = result.detail.location
that.map.setCenter(result.detail.location)
// eslint-disable-next-line no-undef
that.marker = new qq.maps.Marker({
map: that.map,
position: result.detail.location
})
that.info.open()
that.info.setContent(`<div style="margin:10px;">
<p>纬度:${lat}</p>
<p>经度:${lng}</p>
</div>`)
// eslint-disable-next-line no-undef
that.info.setPosition(new qq.maps.LatLng(lat, lng))
})
// 若服务请求失败,则运行以下函数
that.geocoder.setError(function () {
that.$message.error('请输入包含市级的地址!')
})
},
/**
* @method 确定经纬度
*/
confirmLatLng () {
this.centerDialogVisible = false
this.$emit('selectedLatLng', this.latLng)
}
},
watch: {
dialogVisible (newValue, oldValue) {
if (newValue) {
this.centerDialogVisible = true
this.openQQMap()
}
},
centerDialogVisible (val) {
if (!val) {
this.$emit('update:dialogVisible', false)
}
}
}
}
</script>
<style lang="scss" scoped>
#container {
width: 500px;
height: 400px;
margin: 0 auto;
}
.dialog-inner {
.map-search {
display: flex;
justify-content: center;
margin-bottom: 20px;
.el-input {
width: 300px;
margin-right: 10px;
}
}
}
</style>

View File

@@ -0,0 +1,150 @@
<template>
<div class="lb-page">
<slot name="button">
<!-- 插入按钮 -->
</slot>
<div v-if="batch">
<div :class="[{ isShowBatch: isShowBatch }]">已选 {{ selected }} </div>
<div>
<span v-if="isShowBatch">批量</span>
<slot>
<!-- 插入按钮 -->
</slot>
</div>
</div>
<div v-if="slot">
<slot>
<!-- 插入按钮 -->
</slot>
</div>
<span v-else></span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[5, 10, 20]"
:page-size="currentPageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
v-if="isShowPage"
>
</el-pagination>
</div>
</template>
<script>
export default {
props: {
isShowPage: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
batch: {
type: Boolean,
default: true
},
slot: {
type: Boolean,
default: false
},
page: {
type: Number,
default: 1
},
pageSize: {
type: Number,
default: 10
},
total: {
type: Number,
default: 0
},
selected: {
type: Number,
default: 0
}
},
data () {
return {
currentPage: this.page,
currentPageSize: this.pageSize
}
},
methods: {
handleSizeChange (val) {
this.currentPageSize = val
this.$emit('handleSizeChange', val)
},
handleCurrentChange (val) {
this.currentPage = val
this.$emit('handleCurrentChange', val)
},
// 全选 反选
batchUpperAll (type) {
if (type === 1) {
this.$refs.multipleTable.clearSelection()
this.multipleSelection = this.tableData
this.tableData.map(item => {
this.$refs.multipleTable.toggleRowSelection(item)
})
} else {
let data = JSON.parse(JSON.stringify(this.multipleSelection))
let arr = []
data.map(item => {
arr.push(item.id)
})
this.$refs.multipleTable.clearSelection()
this.multipleSelection = []
this.tableData.map(item => {
if (!arr.includes(item.id)) {
this.multipleSelection.push(item)
this.$refs.multipleTable.toggleRowSelection(item)
}
})
}
}
},
watch: {
page (val) {
this.currentPage = val
},
pageSize (val) {
this.currentPageSize = val
}
}
}
</script>
<style lang="scss" scoped>
.lb-page {
width: 100%;
margin-top: 20px;
display: flex;
justify-content: space-between;
height: 40px;
font-size: 14px;
> div {
display: flex;
align-items: center;
white-space: nowrap;
> div.isShowBatch {
border-right: 1px solid #e8e8e8;
}
> div {
&:first-child {
height: 40px;
padding-right: 30px;
margin-right: 30px;
line-height: 40px;
}
.el-button {
margin-left: 10px;
}
}
}
}
</style>

View File

@@ -0,0 +1,109 @@
<template>
<el-switch
v-model="val"
:disabled='isDisabled'
:width='coreWidth'
:active-icon-class='activeIconClass'
:inactive-icon-class='inactiveIconClass'
:active-text='activeText'
:inactive-text='inactiveText'
:active-value='activeValue'
:inactive-value='inactiveValue'
:active-color='activeColor'
:inactive-color='inactiveColor'
:name='name'
@change="handleSwitchValue"
>
</el-switch>
</template>
<script>
export default {
props:
{
opType: {
type: String,
default: ''
},
value: {
type: [Boolean, String, Number],
default: false
},
disabled: {
type: Boolean,
default: false
},
width: {
type: Number,
default: 40
},
activeIconClass: {
type: String,
default: ''
},
inactiveIconClass: {
type: String,
default: ''
},
activeText: String,
inactiveText: String,
activeColor: {
type: String,
default: ''
},
inactiveColor: {
type: String,
default: ''
},
activeValue: {
type: [Boolean, String, Number],
default: true
},
inactiveValue: {
type: [Boolean, String, Number],
default: false
},
name: {
type: String,
default: ''
},
validateEvent: {
type: Boolean,
default: true
},
id: String
},
data () {
return {
val: this.value,
coreWidth: this.width,
isDisabled: this.disabled,
currentIndex: this.$store.state.operate.currentIndex
}
},
created () {
let {isOnly, auth, pagePermission} = this.$route.meta
if (this.opType) {
if (isOnly) {
this.isDisabled = auth.indexOf(this.opType) === -1
} else {
this.isDisabled = pagePermission[this.currentIndex].auth.indexOf(this.opType) === -1
}
}
},
computed: {
checked () {
return this.value === this.activeValue
}
},
methods: {
handleSwitchValue (val) {
this.$emit('change', val)
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,62 @@
<!--
* @Descripttion: 头部批注
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2021-04-15 14:21:09
-->
<template>
<div class="lb-tips" :class="[type]">
<i class="iconfont" :class="[icon]" v-if="isIcon"></i>
<div class="custom-item">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
props: {
icon: {
type: String,
default: 'icon-warn'
},
type: {
type: String,
default: 'danger'
},
isIcon: {
type: Boolean,
default: false
}
}
}
</script>
<style lang="scss" scoped>
.lb-tips {
width: 100%;
padding: 20px;
border-radius: 4px;
margin-bottom: 16px;
display: flex;
align-items: center;
justify-content: center;
border-left: 5px solid $primaryColor;
background: $primaryBgColor;
i{
color: $primaryColor;
margin-right: 10px;
}
.custom-item{
flex: 1;
}
}
.lb-tips.danger {
border-left: 5px solid $dangerColor;
background: $dangerBgColor;
i{
color: $dangerColor;
}
}
</style>

View File

@@ -0,0 +1,66 @@
<!--
* @Descripttion: 批注
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2021-09-10 16:31:43
-->
<template>
<block>
<div class="lb-tool-tips" :class="[type]" v-if="mode === 'text'">
<slot></slot>
</div>
<el-tooltip
class="tool-tips"
effect="dark"
placement="right"
:style="{ paddingTop: `${padding}px` }"
v-if="mode === 'tooltip'"
>
<div class="content" slot="content"><slot></slot></div>
<i class="el-icon-question"></i>
</el-tooltip>
</block>
</template>
<script>
export default {
props: {
mode: {
type: String,
default: 'tooltip'
},
type: {
type: String,
default: 'c-caption'
},
padding: {
type: Number,
default: 10
}
}
}
</script>
<style lang="scss" scoped>
.lb-tool-tips {
font-size: 12px;
line-height: 1.6;
padding-top: 10px;
}
.lb-tool-tips.c-link {
cursor: pointer;
}
.tool-tips {
margin-left: 5px;
vertical-align: top;
font-size: 18px;
color: #333;
.content {
max-width: 300px;
}
.el-icon-question {
cursor: pointer;
}
}
</style>

View File

@@ -0,0 +1,355 @@
<template>
<div>
<script ref="script" :name="name" type="text/plain"></script>
<lb-upload
type="more"
:fileType="fileType"
:visibles.sync="showDialog"
:isIframe="isIframe"
multilineType="more"
@selectedFiles="getChoiceFiles"
></lb-upload>
</div>
</template>
<script>
import LoadEvent from '@/utils/Event.js'
import Debounce from '@/utils/Debounce.js'
import Bus from '@/Bus'
import { mapGetters } from 'vuex'
export default {
name: 'VueUeditorWrap',
data () {
return {
showDialog: false,
fileType: 'image',
isIframe: false,
status: 0,
initValue: '',
defaultConfig: {
// VUE CLI 3 会添加 process.env.BASE_URL 的环境变量,而 VUE CLI 2 没有,所以借此设置 UEDITOR_HOME_URL能涵盖大部分 Vue 开发者的使用场景
UEDITOR_HOME_URL: process.env.NODE_ENV === 'production' ? window.lbConfig.jsPath + 'static/Ueditor/' : '/static/Ueditor/',
enableAutoSave: false,
// 编辑器不自动被内容撑高
autoHeightEnabled: false,
// 初始容器高度
initialFrameHeight: 500,
// 初始容器宽度
initialFrameWidth: 'auto',
// 上传文件接口(这个地址是我为了方便各位体验文件上传功能搭建的临时接口,请勿在生产环境使用!!!)
serverUrl: 'http://35.201.165.105:8000/controller.php',
// UEditor 资源文件的存放路径,如果你使用的是 vue-cli 生成的项目通常不需要设置该选项vue-ueditor-wrap 会自动处理常见的情况如果需要特殊配置参考下方的常见问题2
// UEDITOR_HOME_URL: '/static/Ueditor/',
zIndex: 5,
topOffset: false,
autoFloatEnabled: false,
toolbars: []
},
thatUeditor: {}
}
},
props: {
// v-model 实现方式
mode: {
type: String,
default: 'observer',
validator: function (value) {
// 1. observer 借助 MutationObserver API https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
// 2. listener 借助 UEditor 的 contentChange 事件 https://ueditor.baidu.com/doc/#UE.Editor:contentChange
return ['observer', 'listener'].indexOf(value) !== -1
}
},
value: {
type: String,
default: ''
},
config: {
type: Object,
default: function () {
return {}
}
},
init: {
type: Function,
default: function () {
return () => { }
}
},
destroy: {
type: Boolean,
default: false
},
ueditorType: {
type: Number,
default: 1
},
name: {
type: String,
default: ''
},
observerDebounceTime: {
type: Number,
default: 50,
validator: function (value) {
return value >= 20
}
},
observerOptions: {
type: Object,
default: function () {
// https://developer.mozilla.org/en-US/docs/Web/API/MutationObserverInit
return {
attributes: true, // 是否监听 DOM 元素的属性变化
attributeFilter: ['src', 'style', 'type', 'name'], // 只有在该数组中的属性值的变化才会监听
characterData: true, // 是否监听文本节点
childList: true, // 是否监听子节点
subtree: true // 是否监听后代元素
}
}
},
// 本组件提供对普通 Vue 项目和 Nuxt 项目开箱即 用的支持,但如果是自己搭建的 Vue SSR 项目,可能需要自行区分是客户端还是服务端环境并跳过环境检测,直接初始化
forceInit: {
type: Boolean,
default: false
}
},
created () {
Bus.$on('showLbUpload', (obj) => {
console.log(obj)
this.thatUeditor = obj.ueditor
let { uploadStatus } = this
if (uploadStatus) {
return false
} else {
this.showDialog = obj.val
this.isIframe = true
this.fileType = obj.fileType
this.$store.commit('handleUploadStatus', obj.val)
}
})
},
computed: {
mixedConfig () {
return Object.assign({}, this.defaultConfig, this.config)
},
...mapGetters(['uploadStatus'])
},
methods: {
// 添加自定义按钮(自定义按钮,自定义弹窗等操作从 2.2.0 版本 开始不再考虑直接集成,这会使得组件和 UEditor 过度耦合,但为了兼容一些老版用户的写法,这个方法依然保留)
registerButton ({ name, icon, tip, handler, index, UE = window.UE }) {
UE.registerUI(name, (editor, name) => {
editor.registerCommand(name, {
execCommand: () => {
handler(editor, name)
}
})
const btn = new UE.ui.Button({
name,
title: tip,
cssRules: `background-image: url(${icon}) !important;background-size: cover;`,
onclick () {
editor.execCommand(name)
}
})
editor.addListener('selectionchange', () => {
const state = editor.queryCommandState(name)
if (state === -1) {
btn.setDisabled(true)
btn.setChecked(false)
} else {
btn.setDisabled(false)
btn.setChecked(state)
}
})
return btn
}, index, this.id)
},
// 实例化编辑器
_initEditor () {
let toolbars = [
'fullscreen', 'source', '|',
'undo', 'redo', '|',
'bold', 'italic', 'underline', 'strikethrough', 'removeformat', 'formatmatch', 'autotypeset', 'pasteplain', '|',
// 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', '|',
'forecolor', 'backcolor', '|',
'fontfamily', 'fontsize', '|',
'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify'
]
let arr = {
1: ['|', 'lbinsertimage', 'lbinsertvideo', 'lbinsertmusic'],
2: [],
3: ['|', 'lbinsertimage']
}
if (arr[this.ueditorType].length > 0) {
arr[this.ueditorType].map(item => {
toolbars.push(item)
})
}
this.defaultConfig.toolbars = [toolbars]
this.$refs.script.id = this.id = 'editor_' + Math.random().toString(16).slice(-6) // 这么做是为了支持 Vue SSR因为如果把 id 属性放在 data 里会导致服务端和客户端分别计算该属性的值,而造成 id 不匹配无法初始化的 BUG
this.init()
this.$emit('beforeInit', this.id, this.mixedConfig)
this.editor = window.UE.getEditor(this.id, this.mixedConfig)
this.editor.addListener('ready', () => {
if (this.status === 2) { // 使用 keep-alive 组件会出现这种情况
this.editor.setContent(this.value)
} else {
this.status = 2
this.$emit('ready', this.editor)
this.editor.setContent(this.initValue)
}
if (this.mode === 'observer' && window.MutationObserver) {
this._observerChangeListener()
} else {
this._normalChangeListener()
}
})
},
// 检测依赖,确保 UEditor 资源文件已加载完毕
_checkDependencies () {
return new Promise((resolve, reject) => {
// 判断ueditor.config.js和ueditor.all.js是否均已加载(仅加载完ueditor.config.js时UE对象和UEDITOR_CONFIG对象存在,仅加载完ueditor.all.js时UEDITOR_CONFIG对象存在,但为空对象)
let scriptsLoaded = !!window.UE && !!window.UEDITOR_CONFIG && Object.keys(window.UEDITOR_CONFIG).length !== 0 && !!window.UE.getEditor
if (scriptsLoaded) {
resolve()
} else if (window['$loadEnv']) { // 利用订阅发布确保同时渲染多个组件时不会重复创建script标签
window['$loadEnv'].on('scriptsLoaded', () => {
resolve()
})
} else {
window['$loadEnv'] = new LoadEvent()
// 如果在其他地方只引用ueditor.all.min.js在加载ueditor.config.js之后仍需要重新加载ueditor.all.min.js所以必须确保ueditor.config.js已加载
this._loadConfig().then(() => this._loadCore()).then(() => {
resolve()
window['$loadEnv'].emit('scriptsLoaded')
})
}
})
},
_loadConfig () {
return new Promise((resolve, reject) => {
if (window.UE && window.UEDITOR_CONFIG && Object.keys(window.UEDITOR_CONFIG).length !== 0) {
resolve()
return
}
let configScript = document.createElement('script')
configScript.type = 'text/javascript'
configScript.src = this.mixedConfig.UEDITOR_HOME_URL + 'ueditor.config.js'
document.getElementsByTagName('head')[0].appendChild(configScript)
configScript.onload = function () {
if (window.UE && window.UEDITOR_CONFIG && Object.keys(window.UEDITOR_CONFIG).length !== 0) {
resolve()
} else {
console.warn('加载ueditor.config.js失败,请检查您的配置地址UEDITOR_HOME_URL填写是否正确!\n', configScript.src)
}
}
})
},
_loadCore () {
return new Promise((resolve, reject) => {
if (window.UE && window.UE.getEditor) {
resolve()
return
}
let coreScript = document.createElement('script')
coreScript.type = 'text/javascript'
coreScript.src = this.mixedConfig.UEDITOR_HOME_URL + 'ueditor.all.min.js'
document.getElementsByTagName('head')[0].appendChild(coreScript)
coreScript.onload = function () {
if (window.UE && window.UE.getEditor) {
resolve()
} else {
console.warn('加载ueditor.all.min.js失败,请检查您的配置地址UEDITOR_HOME_URL填写是否正确!\n', coreScript.src)
}
}
})
},
// 设置内容
_setContent (value) {
value === this.editor.getContent() || this.editor.setContent(value)
},
contentChangeHandler () {
this.$emit('input', this.editor.getContent())
},
// 基于 UEditor 的 contentChange 事件
_normalChangeListener () {
this.editor.addListener('contentChange', this.contentChangeHandler)
},
// 基于 MutationObserver API
_observerChangeListener () {
const changeHandle = (mutationsList) => {
if (this.editor.document.getElementById('baidu_pastebin')) {
return
}
this.$emit('input', this.editor.getContent())
}
// 函数防抖
this.observer = new MutationObserver(Debounce(changeHandle, this.observerDebounceTime))
this.observer.observe(this.editor.body, this.observerOptions)
},
getChoiceFiles (files) {
console.log(files)
for (let i = 0, len = files.length; i < len; i++) {
let insetHtml
if (files[i].type === 1) {
insetHtml = `<img src="${files[i].url}" style="box-sizing: border-box !important; overflow-wrap: break-word !important; visibility: visible !important;"/>`
} else if (files[i].type === 2) {
insetHtml = `<audio src="${files[i].url}" controls="controls"></audio>`
} else if (files[i].type === 3) {
insetHtml = `<img width='343' height='220' class='edui-upload-video vjs-default-skin video-js' _url='${files[i].url}' style="background:url(https://lbqny.migugu.com/admin/public/videologo.gif) no-repeat center center; border:1px solid gray;" />`
} else if (files[i].type === 5) { // iframe标签
insetHtml = files[i].url
}
this.thatUeditor.execCommand('insertHtml', insetHtml)
}
}
},
deactivated () {
this.editor && this.editor.removeListener('contentChange', this.contentChangeHandler)
this.observer && this.observer.disconnect()
},
beforeDestroy () {
if (this.destroy && this.editor && this.editor.destroy) {
this.editor.destroy()
}
if (this.observer && this.observer.disconnect) {
this.observer.disconnect()
}
this.$store.commit('handleUploadStatus', false)
Bus.$off('showLbUpload')
},
// v-model语法糖实现
watch: {
value: {
handler (value) {
// 0: 尚未初始化 1: 开始初始化但尚未ready 2 初始化完成并已ready
value = value.replace('font-family: &quot;Microsoft Yahei&quot;;', 'font-family: Microsoft Yahei;')
switch (this.status) {
case 0:
this.status = 1
this.initValue = value;
// 判断执行环境是服务端还是客户端,这里的 process.client 是 Nuxt 添加的环境变量
(this.forceInit || (typeof process !== 'undefined' && process.client) || typeof window !== 'undefined') && this._checkDependencies().then(() => {
this.$refs.script ? this._initEditor() : this.$nextTick(() => this._initEditor())
})
break
case 1:
this.initValue = value
break
case 2:
this._setContent(value)
break
default:
break
}
},
immediate: true
},
showDialog (val) {
if (!val) {
this.$store.commit('handleUploadStatus', val)
}
}
}
}
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
<!--
* @Description:
* @Author: xiao li
* @Date: 2022-06-30 10:06:40
* @LastEditTime: 2022-09-07 15:23:24
* @LastEditors: xiao li
-->
<template>
<el-upload
class="avatar-uploader"
action="https://jsonplaceholder.typicode.com/posts/"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<lb-image v-if="coverImg" :src="coverImg" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</template>
<script>
export default {
props: ['coverImg'],
methods: {
handleAvatarSuccess (response, file) {
let imageUrl = URL.createObjectURL(file.raw)
this.$emit('uploadImg', imageUrl)
},
beforeAvatarUpload (file) {
const isLt2M = file.size / 1024 / 1024 < 2
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isLt2M
}
}
}
</script>
<style lang="scss" scoped>
.avatar-uploader {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 128px;
height: 128px;
}
.avatar-uploader:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 128px;
height: 128px;
line-height: 128px;
text-align: center;
}
.avatar {
width: 128px;
height: 128px;
display: block;
}
</style>

View File

@@ -0,0 +1,99 @@
<template>
<div class="lb-top-nav">
<div @click="goBack" class="nav-item" v-if="title">
<i class="iconfont icon-left" v-if="isBack"></i> {{ title }}
</div>
<div @click="goBack" class="nav-item" v-else-if="nav.length === 1">
<i class="iconfont icon-left" v-if="isBack"></i>
{{ $t('menu.' + nav[0].title) }}
</div>
<router-link
v-else-if="nav.length > 1"
v-for="(item, index) in nav"
tag="div"
class="nav-item"
:key="index"
active-class="nav-item-active"
:to="item.url"
>
{{ $t('menu.' + item.title) }}
</router-link>
</div>
</template>
<script>
export default {
props: {
active: {
type: Number,
default: 0
},
isBack: {
type: Boolean,
default: false
},
title: {
type: String,
default: ''
}
},
data () {
return {
activeNav: this.active,
nav: []
}
},
created () {
let { pagePermission } = this.$route.meta
if (pagePermission) {
this.nav = pagePermission
this.activeNav = this.nav[0].index
}
},
methods: {
goBack () {
if (!this.isBack) return
this.$router.back(-1)
}
}
}
</script>
<style lang="scss" scoped>
.lb-top-nav {
width: 100%;
height: 60px;
border-bottom: 1px solid #e1e1e1;
display: flex;
align-items: center;
padding: 0 10px;
font-size: 14px;
white-space: nowrap;
.nav-item {
height: 60px;
padding: 0 20px;
line-height: 60px;
cursor: pointer;
&::after {
position: absolute;
content: '';
width: 0%;
bottom: 0;
left: 0;
right: 0;
margin: auto;
height: 0px;
background: $themeColor;
transform: all 0.3 linear;
}
}
.nav-item-active {
color: $themeColor;
position: relative;
&::after {
width: 90%;
height: 2px;
}
}
}
</style>

View File

@@ -0,0 +1,50 @@
<template>
<div class="lb-container">
<top-nav :nav='nav' @changNav='handleNav'></top-nav>
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</template>
<script>
export default {
data () {
return {
nav: []
}
},
created () {
this.nav = this.$route.meta.topMenu || []
},
methods: {
handleNav (index) {}
},
watch: {
$route: {
deep: true,
handler (val) {
this.nav = val.meta.topMenu || []
}
}
}
}
</script>
<style lang="scss" scoped>
.lb-container{
width: 100%;
height: 500px;
margin-left: 120px;
margin-top: 120px;
.fade-enter, .fade-leave-to {
opacity: 0
}
.fade-leave, .fade-enter-to {
opacity: 1
}
.fade-enter-active, .fade-leave-active {
transition: all .2s
}
}
</style>

View File

@@ -0,0 +1,46 @@
<!--
* @Descripttion:
* @Author: xiao li
* @Date: 2020-07-06 12:17:06
* @LastEditors: xiao li
* @LastEditTime: 2020-12-17 17:22:48
-->
<!-- 页面底部 -->
<template>
<div v-html="fHtml" class="lb-footer"></div>
</template>
<script>
export default {
data () {
return {
fHtml: ''
}
},
created () {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.lb-footer{
width: 100%;
height: 49px;
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid #ccc;
color: #ccc;
font-size: 12px;
z-index: 10;
background: #fff;
position: fixed;
bottom: 0;
left: 0;
right: 0;
margin: auto;
line-height: 1;
}
</style>

View File

@@ -0,0 +1,202 @@
<!-- 页面头部 -->
<template>
<div class="lb-header">
<div class="lb-left">
<div class="logo">
<!-- <el-image class="logo-img" :src="routesItem.logo" fit="cover" @click="$router.push('/')" ></el-image> -->
<div @click="$router.push('/')" class="flex-center logo-img c-base">
<img class="flex-center logo-img c-base" :src="banner" />
</div>
</div>
<div v-if="isIndex" class="admin-title"></div>
<div v-else class="menu-title">{{ $t('menu.' + title) }}</div>
</div>
<div class="lb-right">
<el-link :underline="false" @click="clearCache" :icon="icon">清除缓存</el-link>
<el-dropdown
v-if="!isWe7"
class="user-name"
trigger="click"
@command="handleCommand"
>
<span class="el-dropdown-link">
{{ username }}
<i class="el-icon-caret-bottom"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="myaccount">编辑账户</el-dropdown-item>
<el-dropdown-item command="loginout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
// import Bus from '@/Bus.js'
import { mapState, mapMutations } from 'vuex'
export default {
data () {
return {
isIndex: true,
title: '',
banner: require('@/./style/image/zhnc.png'),
icon: 'el-icon-s-open',
notice_list: { data: [] },
visible: false,
isAdmin: window.lbConfig.isWe7 && window.lbConfig.is_founder,
agentUrl: '',
username: window.sessionStorage.getItem('ms_username'),
isWe7: window.lbConfig.isWe7,
dialogVisible: false
}
},
created () {
this.handleTitle(this.$route.meta.title)
this.handleAgentUrl()
},
computed: {
...mapState({
routesItem: state => state.routes
})
},
methods: {
...mapMutations(['changeRoutesItem']),
// 用户名下拉菜单选择事件
handleCommand (command) {
if (command === 'myaccount') {
this.$emit('handleAccount', true)
} else if (command === 'loginout') {
// this.$api.userlogout().then(res => {
// if (res.code === 200) {
this.changeRoutesItem({ key: 'isAuth', val: false })
sessionStorage.removeItem('lbtk') // 删除token
sessionStorage.removeItem('ms_username')
this.$router.push('/login')
window.location.reload()
// }
// })
}
},
clearCache () {
this.icon = 'el-icon-loading'
this.$api.base.clearCache().then(res => {
this.icon = 'el-icon-s-open'
if (res.code === 200) {
this.$message.success('清除成功!')
}
})
},
handleTitle (title) {
this.isIndex = !title
this.title = title
},
handleAgentUrl () {
let currentUrl = window.location.href
let agentUrl = currentUrl.slice(0, currentUrl.indexOf('#')) + '&s=/agent/index'
this.agentUrl = agentUrl
}
},
watch: {
$route: {
handler (val, oldVal) {
this.handleTitle(val.meta.title)
},
// 深度观察监听
deep: true
}
}
}
</script>
<style lang="scss" scoped>
.lb-header {
width: 100%;
height: 70px;
position: fixed;
top: 0;
left: 0;
background: #ffffff;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 10;
.lb-left {
display: flex;
height: 71px;
background: #1c2c3c;
border-bottom: 1px solid #f0f0f0;
.logo {
width: 120px;
height: 70px;
display: flex;
justify-content: center;
align-items: center;
.logo-img {
width: 45px;
height: 45px;
margin-bottom: 0;
border-radius: 50%;
cursor: pointer;
}
}
.admin-title {
padding: 0 32px;
display: flex;
align-items: center;
background: #ffffff;
span {
margin-right: 5px;
}
}
.menu-title {
height: 71px !important;
width: 140px;
border-right: 1px solid #eeeeee;
border-bottom: 1px solid #eeeeee;
height: 100%;
display: flex;
font-size: 15px;
font-weight: bold;
color: #666;
align-items: center;
justify-content: center;
background: #ffffff;
}
}
.lb-right {
display: flex;
justify-content: center;
align-items: center;
padding: 0 30px;
cursor: pointer;
.notice-item {
margin: 0 20px;
}
.el-dropdown-link {
cursor: pointer;
}
.el-dropdown-menu__item {
text-align: center;
}
span {
margin: 0 5px 0 20px;
}
.el-link {
margin-left: 10px;
}
}
}
</style>

View File

@@ -0,0 +1,313 @@
<!-- 公共组件 -->
<template>
<div class="home">
<lb-header @handleAccount="handleAccount"></lb-header>
<sidebar></sidebar>
<div
class="container"
:style="{
'margin-right': adSwitch ? '220px' : '0px',
'margin-left': sideBarSwitch ? '260px' : '120px'
}"
>
<!-- 内容区域 -->
<div class="main">
<transition name="fade" mode="out-in">
<keep-alive :max="1">
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
</transition>
<transition name="fade" mode="out-in">
<router-view v-if="!$route.meta.keepAlive"></router-view>
</transition>
</div>
<!-- <div
class="home-footer"
v-html="fHtml"
></div> -->
</div>
<!-- 右侧展开折叠栏 ad -->
<!-- <ad></ad> -->
<!-- <lb-footer></lb-footer> -->
<!-- 编辑账户 -->
<el-dialog title="编辑账户" :visible.sync="dialogVisible" width="520px">
<el-form
@submit.native.prevent
:model="accountForm"
:rules="accountFormRules"
ref="accountForm"
label-width="130px"
class="basic-form"
style="padding-right: 30px"
>
<el-form-item label="账号" prop="account">
<el-input
v-model="accountForm.account"
:disabled="true"
placeholder="账号"
></el-input>
</el-form-item>
<!-- <el-form-item
label="原密码"
prop="old_passwd"
>
<el-input
v-model="accountForm.old_passwd"
placeholder="请输入原密码"
></el-input>
</el-form-item> -->
<el-form-item label="新密码" prop="new_passwd">
<el-input
v-model="accountForm.new_passwd"
placeholder="请输入新密码"
></el-input>
</el-form-item>
<el-form-item label="确认新密码" prop="again_passwd">
<el-input
v-model="accountForm.again_passwd"
placeholder="请确认新密码"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('accountForm')">{{
$t('action.submit')
}}</el-button>
</el-form-item>
</el-form>
</el-dialog>
</div>
</template>
<script>
import lbHeader from './header'
import lbFooter from './footer'
import sidebar from './sidebar'
import ad from './ad'
import { mapGetters, mapState, mapMutations } from 'vuex'
export default {
name: 'Home',
data () {
let validatePassword = (rule, value, callback) => {
if (!value) {
callback(new Error('请输入密码'))
} else if (!/^(\S){6,20}$/.test(value)) {
callback(new Error('请输入6-20位非空白符的字符!'))
} else {
callback()
}
}
let validateAgainPassword = (rule, value, callback) => {
if (!value) {
callback(new Error('请再次输入密码'))
} else if (value !== this.accountForm.new_passwd) {
callback(new Error('两次输入密码不一致'))
} else {
callback()
}
}
return {
isChangeRoutes: true,
fHtml: '',
dialogVisible: false,
accountForm: {
account: window.sessionStorage.getItem('ms_username'),
new_passwd: ''
},
accountFormRules: {
// old_passwd: {
// required: true,
// type: 'string',
// validator: validatePassword,
// trigger: 'blur'
// },
new_passwd: {
required: true,
type: 'string',
validator: validatePassword,
trigger: 'blur'
},
again_passwd: {
required: true,
type: 'string',
validator: validateAgainPassword,
trigger: 'blur'
}
},
authForm: {
pass: ''
},
authFormRules: {
pass: { required: true, type: 'string', message: '请输入获取到的激活口令', trigger: 'blur' }
},
modelAuthImg: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg',
modelAuthList: {
// https://lbqny.migugu.com/weixin/WechatIMG495.jpeg
longbing_card: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg',
longbing_radarstore: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg',
longbing_decorate: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg',
longbing_shortvideo: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg',
longbing_restaurant: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg',
longbing_member: 'https://lbqny.migugu.com/admin/card/WechatIMG322.jpeg'
}
}
},
components: {
lbHeader,
lbFooter,
sidebar,
ad
},
created () {
this.getCopyrightInfo()
},
computed: {
...mapGetters(['adSwitch', 'sideBarSwitch']),
...mapState({
routesItem: state => state.routes
})
},
methods: {
...mapMutations(['changeIsShowPrompt', 'changeRoutesItem']),
handleAccount (flag) {
this.dialogVisible = flag
},
submitForm (name) {
this.$refs[name].validate(valid => {
if (valid) {
let {
new_passwd: pass
} = JSON.parse(JSON.stringify(this.accountForm))
this.$api.base.updatePasswd({
pass
}).then(res => {
if (res.code === 200) {
this.$message.success(this.$t('tips.successRev'))
sessionStorage.removeItem('lbtk') // 删除token
sessionStorage.removeItem('ms_username') // 删除用户名
this.$router.push('/login')
}
})
}
})
},
submitAuthForm (name) {
this.$refs[name].validate(valid => {
if (valid) {
let { pass } = this.authForm
this.$api.baseGiveAuth({
pass
}).then(res => {
if (res.code === 200) {
this.$message.success(this.$t('tips.successSub'))
this.changeRoutesItem({ key: 'isFreeAuth', val: false })
}
})
}
})
},
getCopyrightInfo () {
let { systemCopyInfo } = this.routesItem
if (systemCopyInfo === 1) {
this.fHtml = ''
} else {
if (!systemCopyInfo.footerleft) {
this.fHtml =
`<div>Powered by <a class='el-link el-link--info' href="http://www.we7.cc"><b>微擎</b></a>
v${systemCopyInfo.version} © 2014-2015
<a class='el-link el-link--info' href="http://www.we7.cc">www.we7.cc</a></div>`
} else {
this.fHtml = systemCopyInfo.footerleft
}
if (systemCopyInfo.icp) {
this.fHtml = this.fHtml +
`<div>备案号:<a class='el-link el-link--info' href="http://www.miitbeian.gov.cn" target="_blank">${systemCopyInfo.icp}</a></div>`
}
}
}
}
}
</script>
<style lang="scss" scoped>
.home {
border: 1px solid transparent;
background: #f0f0f0;
.container {
margin: 70px 0 0 140px;
padding: 20px;
background: $bgThemeColor;
transition: margin 0.2s linear;
.main {
width: 100%;
background: #fff;
position: relative;
min-height: calc(100vh - 70px - 92px);
}
.home-footer {
height: 49px;
display: flex;
justify-content: center;
align-items: center;
color: #ccc;
font-size: 12px;
z-index: 10;
margin: 0 auto;
line-height: 1;
width: 50%;
}
}
}
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all 0.5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
.slide-fade-enter-active {
transition: all 2s ease;
}
.slide-fade-leave-active {
transition: all 0s ease;
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.fade-leave,
.fade-enter-to {
opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.2s;
}
.flex-center {
display: flex;
align-items: center;
justify-content: center;
}
</style>

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