提交 8224575b 作者: 刘贵生

init

上级
流水线 #88866 已失败 于阶段
in 1 分 23 秒
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"],
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": ["transform-vue-jsx", "istanbul"]
}
}
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/test/unit/coverage/
/test/e2e/reports/
selenium-debug.log
-lock
package-lock.json
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
// 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": {}
}
}
### 3. 项目结构
```
├─build·························webpack构建目录
├─config························webpack配置目录
├─examples······················网站相关
│ ├─components·················网站建设组件
│ ├─docs·······················使用文档
│ ├─json·······················网站配置文件
│ ├─router·····················路由配置文件
│ ├─App.vue····················根组件
│ └─js·························入口函数
├─packages······················需要向外抛出的组件
├─src···························开发目录
│ ├─assets·····················静态资源
│ │ ├─font····················字体图标
│ │ ├─images··················图片文件
│ │ └─js······················配置文件
│ ├─components·················组件
│ ├─mixins·····················混入文件
│ ├─style······················样式相关
│ ├─utils······················工具类
│ ├─index.js···················组件注册
│ ├─npm.js·····················打包工具
│ └─push.sh····················组件自动化发布
├─static························静态资源文件
├─types·························ts类型声明
│ .babelrc
│ .editorconfig
│ .gitignore
│ .postcssrc.js
│ index.html····················根页面
│ package.json··················包信息
│ README.md·····················项目介绍文件
```
'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'
))
})
})
const package = require('../package.json')
const webpack = require('webpack')
const ora = require('ora')
const path = require('path')
const chalk = require('chalk')
const spinner = ora('building for production...')
spinner.start()
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const webpackConfig = {
entry: "./src/npm.js",
output: {
filename: 'index.js',
chunkFilename: '[id].js',
libraryTarget: 'umd',
libraryExport: 'default',
library: 'form-making-rice',
umdNamedDefine: true,
path: path.resolve(__dirname, `../dist/libs@${package.version}`),
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src') }
},
externals: {
'vue': {
root: 'Vue',
commonjs: 'vue',
commonjs2: 'vue',
amd: 'vue'
},
'element-ui': 'element-ui'
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.(sass|scss)$/,
loaders: ['style', 'css', 'sass', "scss"]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
include: [resolve('examples'), resolve('src'),resolve('packages')]
},
{
test:/\.(ttf|eot|woff|woff2|svg)$/,
use:['file-loader']
},
{
test: /\.(css|scss)$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "sass-loader"}
],
},
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_debugger: true,
drop_console: true
},
sourceMap: true
})
]
}
webpack(webpackConfig, (err, stats) => {
spinner.stop()
console.log(chalk.cyan('sucess.\n'))
console.log(`
***********************************************************
打包成功
包名称: ${webpackConfig.output.library}
版本号: ${package.version}
***********************************************************
`)
});
'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)
}
}
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'first'
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.first.assetsRoot, config.first.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'lan'
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.lan.assetsRoot, config.lan.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'pred'
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.pred.assetsRoot, config.pred.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
const markdownRender = require('markdown-it')();
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
module.exports = {
externals: {
'vue': 'Vue',
'element-ui': 'ELEMENT'
},
context: path.resolve(__dirname, '../'),
entry: {
app: './examples/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('examples'), resolve('src')]
},
{
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]')
}
},
{
test: /\.sass$/,
loaders: ['style', 'css', 'sass',"scss"]
},
{
test: /\.md$/,
loader: 'vue-markdown-loader',
options: {
preventExtract: true,
use: [
[require('markdown-it-container'), 'demo', {
validate: function (params) {
return params.trim().match(/^demo\s+(.*)$/);
},
render: function (tokens, idx) {
if (tokens[idx].nesting === 1) {
// 1.获取第一行的内容使用markdown渲染html作为组件的描述
let demoInfo = tokens[idx].info.trim().match(/^demo\s+(.*)$/);
let description = (demoInfo && demoInfo.length > 1) ? demoInfo[1] : '';
let descriptionHTML = description ? markdownRender.render(description) : '';
// 2.获取代码块内的html和js代码
let content = tokens[idx + 1].content;
// 3.使用自定义开发组件【DemoBlock】来包裹内容并且渲染成案例和代码示例
return `<demo-block>
<div class="source" slot="source">${content}</div>
${descriptionHTML}
<div class="highlight" slot="highlight">`;
} else {
return '</div></demo-block>\n';
}
}
}]
]
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const 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)
}
})
})
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const ENV_MAP = {
'production': require('../config/prod.env'),
'lan': require('../config/lan.env'),
'pred': require('../config/pred.env'),
'first': require('../config/first.env')
}
const env = process.env.NODE_ENV = ENV_MAP[process.env.NODE_ENV];
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
'use strict'
module.exports = {
NODE_ENV: '"first"'
}
\ No newline at end of file
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
autoOpenBrowser:true,
proxyTable: {},
// Various Dev Server settings
host: '0.0.0.0', // can be overwritten by process.env.HOST
port: 7008, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: true, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
/**
* 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: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// 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
},
lan: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// 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
},
pred: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// 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
},
first: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// 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
}
}
'use strict'
module.exports = {
NODE_ENV: '"lan"'
}
\ No newline at end of file
'use strict'
module.exports = {
NODE_ENV: '"pred"'
}
\ No newline at end of file
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
<template>
<div id="app">
<!-- 头部 -->
<top-header></top-header>
<!-- 路由视图 -->
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</template>
<script>
// 头部组件引入
import TopHeader from "./components/Header.vue";
export default {
name: 'App',
components: {
TopHeader
}
}
</script>
<template>
<!-- 组件介绍页面(路由页)
@author: liuguisheng
@date: 2019-11-6
-->
<div class="main-">
<div class="main--left">
<ul>
<li v-for="(item, index) in webConfig.leftNav"
:key="index">
<router-link active-class="nav-left_active"
:to="item.path">{{item.name}}</router-link>
</li>
</ul>
</div>
<div class="main--right">
<router-view class="markdown"></router-view>
</div>
</div>
</template>
<script>
// 网站配置信息引入
import webConfig from "../json/web.config.json";
export default {
name: 'ComponentsMain',
data () {
return {
// 网站配置信息
webConfig: webConfig
}
}
}
</script>
<style>
.nav-left_active {
color: #1fb19e !important;
border-right: 2px solid #1fb19e!important;
}
.main- {
position: relative;
padding: 40px 0 0;
margin-left: 0;
margin-right: 0;
height: auto;
zoom: 1;
display: block;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.main- .main--left {
float: left;
-webkit-box-flex: 0;
-ms-flex: 0 0 auto;
flex: 0 0 auto;
}
.main- .main--left ul {
width: 250px;
margin: 0;
padding: 0;
}
.main- .main--left ul li {
margin: 0;
list-style: none;
padding: 0;
font-size: 14px;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
}
.main- .main--left ul li a {
font-size: 14px;
color: #333;
line-height: 40px;
height: 40px;
margin: 0;
padding: 4px 25px;
text-decoration: none;
display: block;
position: relative;
-webkit-transition: 0.15s ease-out;
transition: 0.15s ease-out;
font-weight: 600;
border-right: 1px solid #e8e8e8;
}
.main- .main--left ul li a:hover {
color: #1c9f8e;
}
.main- .main--left ul li.main--link-group {
height: auto;
}
.main- .main--left ul li.main--link-group a:hover {
color: #333;
cursor: default;
}
.main- .main--left ul li.main--link-group ul a {
display: block;
height: 40px;
color: #444;
line-height: 40px;
font-size: 14px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-weight: 400;
}
.main- .main--left ul li.main--link-group ul a:hover {
color: #41a259;
cursor: pointer;
}
.main- .main--right {
padding: 0 84px 140px 64px;
min-height: 500px;
overflow: hidden;
}
.main- .main--right a {
color: #41a259;
text-decoration: none;
}
</style>
\ No newline at end of file
<template>
<div
class="demo-block"
:class="[blockClass, { hover: hovering }]"
@mouseenter="hovering = true"
@mouseleave="hovering = false"
>
<!-- 源码运行 -->
<div class="source">
<slot name="source"></slot>
</div>
<!-- 源码 -->
<div class="meta" ref="meta">
<!-- 描述 -->
<div class="description" v-if="$slots.default">
<slot></slot>
</div>
<!-- 源码 -->
<div class="highlight">
<slot name="highlight"></slot>
</div>
</div>
<!-- 源码 显示或者隐藏 -->
<div
class="demo-block-control"
ref="control"
:class="{ 'is-fixed': fixedControl }"
@click="isExpanded = !isExpanded"
>
<transition name="arrow-slide">
<i :class="[iconClass, { hovering: hovering }]"></i>
</transition>
<transition name="text-slide">
<span v-show="hovering">{{ controlText }}</span>
</transition>
</div>
</div>
</template>
<style lang="scss">
.demo-block {
border: solid 1px #ebebeb;
border-radius: 3px;
transition: 0.2s;
&.hover {
box-shadow: 0 0 8px 0 rgba(232, 237, 250, 0.6),
0 2px 4px 0 rgba(232, 237, 250, 0.5);
}
code {
font-family: Menlo, Monaco, Consolas, Courier, monospace;
}
.demo-button {
float: right;
}
.source {
padding: 24px;
}
.meta {
background-color: #fafafa;
border-top: solid 1px #eaeefb;
overflow: hidden;
height: 0;
transition: height 0.2s;
}
.description {
padding: 20px;
box-sizing: border-box;
border: solid 1px #ebebeb;
border-radius: 3px;
font-size: 14px;
line-height: 22px;
color: #666;
word-break: break-word;
margin: 10px;
background-color: #fff;
p {
margin: 0;
line-height: 26px;
}
code {
color: #5e6d82;
background-color: #e6effb;
margin: 0 4px;
display: inline-block;
padding: 1px 5px;
font-size: 12px;
border-radius: 3px;
height: 18px;
line-height: 18px;
}
}
.highlight {
margin-left: 20px;
pre {
margin: 0;
}
code.hljs {
margin: 0;
border: none;
max-height: none;
border-radius: 0;
&::before {
content: none;
}
}
}
.demo-block-control {
border-top: solid 1px #eaeefb;
height: 44px;
box-sizing: border-box;
background-color: #fff;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
text-align: center;
margin-top: -1px;
color: #d3dce6;
cursor: pointer;
position: relative;
&.is-fixed {
position: fixed;
bottom: 0;
width: 868px;
}
i {
font-size: 16px;
line-height: 44px;
transition: 0.3s;
&.hovering {
transform: translateX(-40px);
}
}
> span {
position: absolute;
transform: translateX(-30px);
font-size: 14px;
line-height: 44px;
transition: 0.3s;
display: inline-block;
}
&:hover {
color: #1fb19e;
background-color: #f9fafc;
}
& .text-slide-enter,
& .text-slide-leave-active {
opacity: 0;
transform: translateX(10px);
}
.control-button {
line-height: 26px;
position: absolute;
top: 0;
right: 0;
font-size: 14px;
padding-left: 5px;
padding-right: 25px;
}
}
}
//doc table 样式
.element-doc table {
border-collapse: collapse;
width: 100%;
background-color: #fff;
font-size: 14px;
margin-bottom: 45px;
line-height: 1.5em;
strong {
font-weight: normal;
}
td,
th {
border-bottom: 1px solid #dcdfe6;
padding: 15px;
max-width: 250px;
}
th {
text-align: left;
white-space: nowrap;
color: #909399;
font-weight: normal;
}
td {
color: #606266;
}
th:first-child,
td:first-child {
padding-left: 10px;
}
}
</style>
<script type="text/babel">
export default {
data() {
return {
hovering: false,
isExpanded: false,
fixedControl: false,
scrollParent: null
};
},
computed: {
lang() {
return this.$route.path.split("/")[1];
},
blockClass() {
return `demo-${this.lang} demo-${this.$router.currentRoute.path
.split("/")
.pop()}`;
},
iconClass() {
return this.isExpanded ? "el-icon-caret-top" : "el-icon-caret-bottom";
},
controlText() {
return this.isExpanded ? "隐藏代码" : "显示代码";
},
codeArea() {
return this.$el.getElementsByClassName("meta")[0];
},
codeAreaHeight() {
if (this.$el.getElementsByClassName("description").length > 0) {
return (
this.$el.getElementsByClassName("description")[0].clientHeight +
this.$el.getElementsByClassName("highlight")[0].clientHeight +
20
);
}
return this.$el.getElementsByClassName("highlight")[0].clientHeight;
}
},
watch: {
isExpanded(val) {
this.codeArea.style.height = val ? `${this.codeAreaHeight + 1}px` : "0";
if (!val) {
this.fixedControl = false;
this.$refs.control.style.left = "0";
return;
}
}
}
};
</script>
\ No newline at end of file
<template>
<!-- 网站头部(组件)
@author: liuguisheng
@date: 2019-11-5
-->
<div class="header">
<!-- 头部 -->
<div class="main-header" :class="{'main-header_fixed': isHeaderFixed}">
<router-link to="/index" class="main-header_logo">
<img :src="logo" alt="RICE" />
<span>{{ webConfig.project.name }}</span>
</router-link>
<div class="main-header_nav">
<router-link
:to="el.path"
active-class="active"
v-for="(el, index) in webConfig.headNav"
:key="index"
>{{el.name}}</router-link>
<div class="version-wrap">v{{version}}</div>
</div>
</div>
<!-- 头部固定定位填充 -->
<div style="height: 65px" v-if="isHeaderFixed"></div>
</div>
</template>
<script>
// 网站配置信息引入
import webConfig from "../json/web.config.json";
// 导入项目配置
const packageConfig = require("../../package.json");
export default {
name: "Header",
data() {
return {
// 网站配置信息
webConfig,
// 头部是否固定
isHeaderFixed: false,
// 版本号
version: packageConfig.version,
// logo
logo: require("../../src/assets/images/logo.png")
};
},
methods: {
/**
* @name 跳转到首页
* @returns { void }
* @author liuguisheng
* @version 2019-11-6
*/
goToIndex() {
this.$router.push({ path: "/index" });
}
}
};
</script>
<style lang="scss" scoped>
a {
text-decoration: none;
}
.main-header_fixed {
position: fixed;
width: 100%;
box-sizing: border-box;
top: 0;
z-index: 99;
}
.main-header {
background-color: #fff;
padding: 0 50px 0 30px;
min-width: 700px;
height: 65px;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 8px #f0f1f2;
.main-header_logo {
display: flex;
align-items: center;
cursor: pointer;
&:hover {
img {
transform: rotate(-15deg);
transition: all 0.3s;
}
}
img {
width: 55px;
transition: all 0.6s;
}
span {
color: #4c4c4c;
font-size: 24px;
margin-left: 5px;
}
}
.main-header_nav {
display: flex;
font-size: 14px;
a {
color: #4c4c4c;
width: 80px;
text-align: center;
line-height: 65px;
transition: color 0.3s;
font-weight: 600;
opacity: .8;
letter-spacing: 1px;
&:hover {
color: #1fb19e;
transition: color 0.3s;
}
}
.active {
color: #1fb19e;
border-bottom: 2px solid #1fb19e;
}
.version-wrap {
color: #5c5c5c;
align-self: center;
margin-left: 20px;
padding-left: 40px;
border-left: 1px solid #ccc;
letter-spacing: 2px;
}
}
}
</style>
\ No newline at end of file
<template>
<div>
首页
</div>
</template>
<script>
export default {
}
</script>
\ No newline at end of file
<template>
<div>
体验
</div>
</template>
<script>
export default {
}
</script>
\ No newline at end of file
# 开发指南
## npm 安装
首先替换下载源
```shell
npm config set registry http://39.106.145.141:9000/repository/node-host/
```
下载依赖
```shell
npm install FormMakingRice -S
```
在 main.js 中写入如下内容
```shell
import FormMakingRice from "FormMakingRice";
Vue.use(FormMakingRice)
```
## cdn 引入
### 地址
> 200服务器
```shell
// 0.0.5 为表单编辑器的版本号, 应该替换为使用的正确版本号
<script src="https://192.168.10.200:7008/libs@0.0.5/index.js"></script>
```
> 测试环境
```shell
// 0.0.5 为表单编辑器的版本号, 应该替换为使用的正确版本号
<script src="https://dformmakingrice.allhome.com.cn/libs@0.0.5/index.js"></script>
```
> 正式环境
```shell
// 0.0.5 为表单编辑器的版本号, 应该替换为使用的正确版本号
<script src="https://formmakingrice.allhome.com.cn/libs@0.0.5/index.js"></script>
```
### 项目引入
webpack.base.config.js&emsp;externals配置项中添加如下:
```shell
formMakingRice': 'FormMakingRice
```
main.js 引入:
```shell
import formMakingRice from "formMakingRice";
Vue.use(formMakingRice);
```
# 首屏组件
## Attributes
| 参数名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| v-model | [String,Number] | - | 输入框v-model绑定 |
| placeholder | String | - | 默认提示
## Event
| 事件 | 返回值 | 描述 |
|---|---|---|
| change | input值 | 返回input输入值 |
## 基础用法
:::demo 代码展示
```html
<template>
<qj-input v-model="value"
:placeholder="placeholder"></qj-input>
</template>
<script>
export default {
data () {
return {
value: '',
placeholder: '请输入'
}
}
}
</script>
```
# 更新日志
## V0.0.1
1. 基本页面搭建
2. 组件拖拽
3. 属性设置实时响应
4. 表单项的增删复制
5. 预览表单
---
## V0.0.2
1. 增加关联设置
2. 打包成npm和cdn
3. 体验优化
---
## V0.0.3
1. 分块保存
2. 特殊字段提取
3. 交互优化
---
## V0.0.4
1. 动态渲染
2. 标签可单独设置
3. 新增面板组件
4. 拖拽优化
---
## V0.0.5
1. 事件添加禁用/解禁
2. 组件内容提取
3. 保存模块优化
4. 任意门优化
5. 渲染优化
---
## V0.0.6
1. 表单验证
2. 组件封装优化
---
## V0.0.7
1. 清空按钮加二次提示
2. 修改模块名称
3. 缩进占位问题
4. 下划线固定长度
5. 事件拆分
6. 选择类组件默认勾选
7. 变量对应
---
## V0.0.8
1. 新增文字占位设置
2. 修复选择类组件默认值设置异常bug
3. 按钮添加状态
4. 修复文字组件换行错误
5. 添加文字组件标题设置
6. 添加小写转大写实时预览
---
## V0.0.9
1. 添加对空值不渲染的配置
2. 调整渲染组件填写的值和下滑线之间的距离
3. 调整任意门中组件间的间距
4. 调整下划线两边空白位置
---
## V0.1.0
1. 更新网站排版,新主页,更优雅
2. 替换demoBlock组件,更改markdown渲染色调,更符合千家口味
3. 添加骨架屏,增加视觉体验
4. 目录结构调整.scss文件导入优化
---
> ## 组件备忘录
| 组件 | 组件名称 |
|------|--------
| 首页 | rice-index
| 表单动态渲染 | rice-preview-bridge
| 表单预览 | rice-preview-form
| 渲染预览 | rice-preview-render
\ No newline at end of file
{
"project": {
"name": "千家组件库"
},
"headNav": [
{
"name": "首页",
"path": "/index"
},
{
"name": "体验",
"path": "/start"
},
{
"name": "文档",
"path": "/component"
}
],
"leftNav": [
{
"name": "开发指南",
"path": "/component/guide"
},
{
"name": "更新日志",
"path": "/component/log"
},
{
"name": "输入框",
"path": "/component/input"
}
]
}
\ No newline at end of file
// vue
import Vue from 'vue';
// app.vue
import App from './App';
// router
import router from './router';
// component for code display
import DemoBlock from './components/DemoBlock.vue';
Vue.component('demo-block', DemoBlock);
// component
import Qj from "../packages/index";
Vue.use(Qj)
// plugin
import "../src/npm.js";
// productionTip
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
import Vue from 'vue';
import Router from 'vue-router';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
redirect: '/index'
},
{
path: '/index',
name: 'index',
component: () => import('../components/Index.vue'),
meta: {
title: '测试页面'
}
},
{
path: '/start',
name: 'start',
component: () => import('../components/Start.vue'),
meta: {
title: '快速体验'
}
},
{
path: '/component',
name: 'component',
component: () => import('../components/ComponentsMain.vue'),
redirect: '/component/guide',
meta: {
title: '开发文档'
},
children: [
{
path: '/component/guide',
name: 'guide',
component: r => require.ensure([], () => r(require('../docs/guide.md'))),
meta: {
title: '开发指南'
}
},
{
path: '/component/log',
name: 'log',
component: r => require.ensure([], () => r(require('../docs/log.md'))),
meta: {
title: '更新日志'
}
},
{
path: '/component/input',
name: 'input',
component: r => require.ensure([], () => r(require('../docs/input.md'))),
meta: {
title: '输入框'
}
}
]
},
]
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>表单设计器</title>
<link rel="shortcut icon" href="./static/favicon.ico" type="image/x-icon">
<!-- 引入样式(地址根据环境配置) -->
<link rel="stylesheet" href="https://web.allhome.com.cn/libs@1.1.2/theme-chalk/index.css">
</head>
<body>
<div id="app"></div>
<!-- 引入vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<!-- 引入组件库(地址根据环境配置) -->
<script src="https://web.allhome.com.cn/libs@1.1.2/index.js"></script>
</body>
</html>
\ No newline at end of file
{
"name": "form-making-rice",
"version": "0.1.2",
"description": "NPM package for new version of electronic contract, online examination, feedback and other test paper projects",
"author": "liuguisheng <codeliuguisheng@163.com> && wangrupeng <1107344708@qq.com>",
"main": "dist/libs@0.1.2/index.js",
"typings": "types/index.d.ts",
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"build": "node build/build.js",
"lan": "node build/lan.js",
"pred": "node build/pred.js",
"first": "node build/first.js",
"lib": "node build/build_bundle.js",
"host": "npm config set registry http://39.106.145.141:9000/repository/node-host/ && npm login",
"public": "npm config set registry http://39.106.145.141:9000/repository/node-public/",
"org": "npm config set registry https://registry.npmjs.org/",
"fast": "npm run lib && npm publish",
"bash": "sh src/push.sh"
},
"dependencies": {
"vue": "^2.5.2",
"vue-m-ace-editor": "^1.0.0",
"vue-router": "^3.0.1",
"vue2x-ace-editor": "^0.1.2",
"vuedraggable": "^2.23.0"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-istanbul": "^4.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",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"chromedriver": "^2.27.2",
"copy-webpack-plugin": "^4.0.1",
"cross-env": "^5.0.1",
"cross-spawn": "^5.0.1",
"css-loader": "^0.28.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"highlight.js": "^9.16.2",
"html-webpack-plugin": "^2.30.1",
"inject-loader": "^3.0.0",
"markdown-it-container": "^2.0.0",
"nightwatch": "^0.9.12",
"node-notifier": "^5.1.2",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"phantomjs-prebuilt": "^2.1.14",
"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.3.1",
"selenium-server": "^3.0.1",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"sinon": "^4.0.0",
"sinon-chai": "^2.8.0",
"style-loader": "^1.0.0",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-markdown-loader": "^2.4.1",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
import QjInput from './src/main.vue';
QjInput.install = function ( Vue ) {
Vue.component(QjInput.name,QjInput);
}
export default QjInput;
\ No newline at end of file
<template>
<div>
<input type="input"
class="qj-input"
:value="currentValue"
:placeholder="placeholder"
@input="onChange"/>
</div>
</template>
<script>
export default {
name: 'qj-input',
data () {
return {
currentValue: this.value
}
},
props: {
value: [String, Number],
placeholder: String
},
model: {
prop: 'value',
event: 'input'
},
methods: {
setCurrentValue ( val ) {
console.log(val)
if ( val === this.currentValue) return;
this.currentValue = value
},
onChange ( val ) {
this.$emit("input", val.target.value)
}
}
}
</script>
\ No newline at end of file
/**
* @name 组件注册
* @description 注册需要对外提供的组件
* @author liuguisheng
* @version 2019-12-9
*
*/
import QjInput from './QjInput/index.js';
const components = [
QjInput
];
export default function ( Vue ) {
components.map(component => {
Vue.component(component.name, component)
})
}
\ No newline at end of file
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1573606455596'); /* IE9 */
src: url('iconfont.eot?t=1573606455596#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'),
url('iconfont.woff?t=1573606455596') format('woff'),
url('iconfont.ttf?t=1573606455596') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1573606455596#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconcopy:before {
content: "\e612";
}
.iconmove:before {
content: "\e625";
}
.iconmokuai:before {
content: "\e601";
}
.iconbutton:before {
content: "\e600";
}
.icondelete:before {
content: "\e63e";
}
.icondomain:before {
content: "\e63f";
}
.iconslider:before {
content: "\e640";
}
.iconcascade:before {
content: "\e641";
}
.iconcounter:before {
content: "\e642";
}
.iconswitch:before {
content: "\e643";
}
.iconscore:before {
content: "\e644";
}
.icondropdown:before {
content: "\e645";
}
.iconline:before {
content: "\e646";
}
.iconsubform:before {
content: "\e647";
}
.iconwords:before {
content: "\e648";
}
.iconradio:before {
content: "\e649";
}
.iconcolor:before {
content: "\e64a";
}
.iconeditor:before {
content: "\e64b";
}
.iconfile:before {
content: "\e64c";
}
.iconlayout:before {
content: "\e64d";
}
.iconpicture:before {
content: "\e64e";
}
.icontext:before {
content: "\e64f";
}
.iconarea:before {
content: "\e650";
}
.iconcheckbox:before {
content: "\e651";
}
.icontime:before {
content: "\e652";
}
.iconpreview:before {
content: "\e654";
}
.iconcode:before {
content: "\e655";
}
.icondate:before {
content: "\e656";
}
.iconsave:before {
content: "\e653";
}
.iconcommit:before {
content: "\e657";
}
/**
* @name 组件渲染配置文件
* @description 每个组件都有其对应的渲染规则,例如单选框就按照实际渲染,
* 时间选择器需要转换成不同的时间格式,而按钮不需要渲染,
* 所以产生此文件,用来配置每个组件需要渲染的格式
* @param { String } key 组件类型
* @param { String } value 该类型组件需要渲染的组件名称
* @author liuguisheng
* @date 2019-11-21
*
*/
/**
* 目录
* (注意: 如果添加新的渲染类型,请及时更新此目录)
*
* render-none .........................不需要渲染 (例如按钮)
* render-text .........................文本类型
* render-boolean ......................布尔类型
* render-array ........................数组类型
* render-real .........................是什么样就长什么样(例如分割线)
* render-time .........................时间类型
* render-date .........................日期类型
* render-grid .........................栅格类型
*
*/
export const renderComponents = {
text: 'render-text',
button: 'render-none',
input: 'render-input',
textarea: 'render-input',
radio: 'render-input',
checkbox: 'render-array',
select: 'render-array',
switch: 'render-boolean',
datePicker: 'render-date',
timePicker: 'render-time',
uploadImage: 'render-image',
uploadFile: 'render-file',
grid: 'render-grid',
free: 'render-free',
line: 'render-none',
domain: 'render-domain'
}
\ No newline at end of file
/** 工具方法 :::
* @function produceNumber 随机数方法
* @function deepCopy 深拷贝方法
*/
import { deepCopy } from '@/utils/utils.js'
/** @name 模块组件编辑管理者混入
* @requires data {Object} domainEditProcess 编辑中模块数据
* @requires data {Array} formList 编辑区表单节点列表
* @requires data {Array} domainList 分组列表
* @requires data {Object} formMap 表单项字典
* @requires data {Object} eventMap 事件字典
* @requires data {Object} formSettingState 整个表单样式配置
* @requires data {Object} activeNode 激活表单节点
* @requires data {Array} activeList 激活表单节点所在列表
* @requires mixin @/mixins/common/mix_make_config_manager.js
* @requires mixin @/mixins/common/mix_domain_manager.js
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixDomainEditManager = {
methods: {
/** @name 分组组件编辑管理者
* @author 王汝鹏
* @version 2019-12-22
*/
domainEditManager() {
let that = this;
/** @name 判断是否为正在编辑的分组组件
* @param {Object} domain 分组组件
* @return {Boolean} 判断结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _isEqual = function(domain) {
if (that.domainEditManager().getStatus() === 'normal') return false;
let editDomainId = that.domainEditProcess.domain.node.id;
let compareDomainId = domain.node.id;
return editDomainId === compareDomainId;
}
/** @name 获取分组组件编辑状态
* @return {String} 编辑状态 { normal:"正常状态", editing:”修改中状态", changed:"已修改状态" }
* @author 王汝鹏
* @version 2019-12-22
*/
const _getStatus = function() {
return that.domainEditProcess.status;
}
/** @name 获取分组组件操作类型
* @return {String} 操作类型 { none:无操作, templates:模版操作, name:名称操作 }
* @author 王汝鹏
* @version 2020-01-05
*/
const _getOperation = function() {
return that.domainEditProcess.operation;
}
/** @name 获取编辑分组组件的名称
* @return {String} 分组组件名称
* @author 王汝鹏
* @version 2019-12-22
*/
const _getDomainName = function() {
if (that.domainEditManager().getStatus() === 'normal') return "";
let domain = that.domainEditProcess.domain;
return that.domainManager(domain).getName();
}
/** @name 设置分组组件的名称
* @param {String} name 分组组件名称
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2020-01-05
*/
const _setDomainName = function(name) {
if (that.domainEditManager().getStatus() === 'normal') throw new Error("没有模块处于编辑状态");
let domain = that.domainEditProcess.domain;
that.domainManager(domain).setName(name);
that.domainEditProcess.status = 'changed';
return true;
}
/** @name 准备编辑分组组件
* @param {Object} domain 分组组件
* @param {String} operation 操作类型 { none:无操作, templates:模版操作, name:名称操作 }
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _edit = function(domain, operation) {
if (that.domainEditManager().getStatus() === 'changed') throw new Error("有模块处于编辑状态,它的修改还没有保存");
if (['templates', 'name'].includes(operation) === false) throw new Error(`分组组件操作类型不正确: operation=${operation};`);
that.domainEditProcess.domain = domain;
that.domainEditProcess.original = {
formList: deepCopy(that.formList),
domainList: deepCopy(that.domainList),
formMap: deepCopy(that.formMap),
eventMap: deepCopy(that.eventMap),
formSettingState: deepCopy(that.formSettingState)
};
operation === 'templates'
? that.formList = that.domainManager(domain).getTemplates()
: that.formList = [];
that.domainEditProcess.operation = operation;
that.domainEditProcess.status = 'editing';
return true;
}
/** @name 更新分组组件模版数据
* @param {Object} templates 模版数据
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _setTemplates = function(templates) {
if (that.domainEditManager().getStatus() === 'normal') throw new Error("没有模块处于编辑状态");
if (that.domainEditManager().getOperation() !== 'templates') throw new Error("非模块组件模版编辑状态");
let domain = that.domainEditProcess.domain;
that.domainManager(domain).setTemplates(templates);
that.domainEditProcess.status = 'changed';
return true;
}
/** @name 提交分组组件改动
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _submitChanged = function() {
if (that.domainEditManager().getStatus() === 'normal') throw new Error("没有模块处于编辑状态");
that.domainEditProcess.domain = null;
that.domainEditProcess.original = {};
that.domainEditProcess.status = 'normal';
that.domainEditProcess.operation = "none";
that.domainList = [...that.domainList];
that.formList = [];
that.activeNode = {};
that.activeList = [];
return true;
}
/** @name 回退到编辑前
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _rollbackChanged = function() {
if (that.domainEditManager().getStatus() === 'normal') throw new Error("没有模块处于编辑状态");
let { formList, domainList, formMap, eventMap, formSettingState } = that.domainEditProcess.original;
that.formList = formList;
that.domainList = domainList;
that.formMap = formMap;
that.eventMap = eventMap;
that.formSettingState = formSettingState;
that.domainEditProcess.domain = null;
that.domainEditProcess.original = {};
that.domainEditProcess.status = 'normal';
that.domainEditProcess.operation = "none";
return true;
}
/** @name 将编辑中的分组另存为其它分组
* @param {String} domainName 模块名称
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _saveAs = function(domainName) {
if (that.domainEditManager().getStatus() === 'normal') throw new Error("没有模块处于编辑状态");
let copyList = that.formList.map(node => that.formNodeManager(node).copy());
let { formList, domainList, formMap, eventMap, formSettingState } = that.domainEditProcess.original;
that.formList = formList;
that.domainList = domainList;
that.formMap = { ...formMap, ...that.formMap };
that.eventMap = eventMap;
that.formSettingState = formSettingState;
let domainConfig = that.makeDomainConfig(domainName, copyList);
// 将新模块配置添加到模块组件列表
that.domainList.push(domainConfig);
that.domainEditProcess.domain = null;
that.domainEditProcess.original = {};
that.domainEditProcess.status = 'normal';
that.domainEditProcess.operation = "none";
return true;
}
return {
isEqual(domain) { return _isEqual(domain); },
getStatus() { return _getStatus(); },
getOperation() { return _getOperation(); },
edit(domain, operation) { return _edit(domain, operation); },
getDomainName() { return _getDomainName(); },
setDomainName(name) { return _setDomainName(name); },
setTemplates(templates) { return _setTemplates(templates); },
submitChanged() { _submitChanged(); },
rollbackChanged() { _rollbackChanged(); },
saveAs(domainName) { _saveAs(domainName); }
}
}
}
}
\ No newline at end of file
/** @name 分组组件管理者混入
* @requires data {Object} formMap 表单项字典
* @requires data {Array} domainList 分组列表
* @requires mixin @/mixins/common/mix_form_node_manager.js
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixDomainManager = {
methods: {
/** @name 分组组件管理者
* @param {Object} domain 表单分组配置
* @author 王汝鹏
* @version 2019-12-22
*/
domainManager(domain) {
let that = this;
/** @name 更新表单分组模版
* @param {Array} templates 分组模版
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _setTemplates = function(templates) {
domain.node.children = templates;
return true;
}
/** @name 获取分组模版
* @return {Array} 分组模版
* @author 王汝鹏
* @version 2019-12-22
*/
const _getTemplates = function() {
return domain.node.children;
}
/** @name 获取分组名称
* @return {String} 分组名称
* @author 王汝鹏
* @version 2019-12-22
*/
const _getName = function() {
return domain.exhibits.name;
}
/** @name 设置分组名称
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2020-01-05
*/
const _setName = function(name) {
domain.exhibits.name = name;
return true;
}
/** @name 获取分组图标
* @return {String} 分组图标
* @author 王汝鹏
* @version 2019-12-22
*/
const _getIcon = function() {
return domain.exhibits.icon;
}
/** @name 删除分组
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-22
*/
const _delete = function() {
let deleteIndex = that.domainList.findIndex(i => i.node.id === domain.node.id);
let domainTemplates = that.domainManager(domain).getTemplates();
for (let node of [...domainTemplates]) {
that.formNodeManager(node).deleteFrom(domainTemplates);
}
that.domainList.splice(deleteIndex, 1);
return true;
}
/** @name 获取模块组件节点
* @return {Object} 模块组件节点
* @author 王汝鹏
* @version 2019-12-23
*/
const _getNode = function() {
// 将模块注册到表单项字典中
let { node, config } = domain;
that.formMap[node.id] = config;
return node;
}
return {
getName() { return _getName(); },
setName(name) { return _setName(name); },
getIcon() { return _getIcon(); },
getTemplates() { return _getTemplates(); },
setTemplates(templates) { return _setTemplates(templates); },
getNode() { return _getNode(); },
delete() { return _delete(); }
}
},
}
}
/** @name 事件配置管理者混入
* @requires data {Object} eventMap 事件字典
* @requires data {Object} formMap 表单项字典
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixEventConfigManager = {
methods: {
/** @name 事件配置管理者
* @param {String} eventId 事件id
* @return {Object} 事件配置管理者
* @author 王汝鹏
* @version 2019-12-21
*/
eventConfigManager(eventId) {
let that = this;
/** @name 删除关联触发表单项
* @param {String} formId 表单id
* @return {Boolean} 删除操作结果
* @author 王汝鹏
* @version 2019-12-21
*/
const _deleteEmitRelated = function(formId) {
let eventConfig = that.eventMap[eventId];
if (!eventConfig) return false;
let { emit, on } = eventConfig;
eventConfig.emit = emit.filter(i => i.form !== formId);
if (eventConfig.emit.length === 0) {
let { form } = on;
let formConfig = that.formMap[form];
if (formConfig) formConfig.event.on = formConfig.event.on.filter(i => i !== eventId);
Reflect.deleteProperty(that.eventMap, eventId);
}
return true;
}
/** @name 删除事件
* @return {Boolean} 删除操作结果
* @author 王汝鹏
* @version 2019-12-21
*/
const _deleteEvent = function() {
let eventConfig = that.eventMap[eventId];
if (!eventConfig) return false;
let { emit, on } = eventConfig;
for (let { form } of emit) {
let formConfig = that.formMap[form];
if (formConfig) formConfig.event.emit = formConfig.event.emit.filter(i => i !== eventId);
}
let { form } = on;
let formConfig = that.formMap[form];
if (formConfig) formConfig.event.on = formConfig.event.on.filter(i => i !== eventId);
Reflect.deleteProperty(that.eventMap, eventId);
return true;
}
/** @name 创建/更新事件配置
* @param {Object} event 新事件配置
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-24
*/
const _upsertEvent = function(event) {
let {eventId, eventType, eventEmit, eventOn} = event;
let oldEventConfig = that.eventMap[eventId];
// 如果存在事件的历史配置,先删除历史配置
if (oldEventConfig) that.eventConfigManager(eventId).deleteEvent();
// 重新按照新的事件配置建立关系
// 建立新事件关系
// 遍历新事件配置中的 触发与监听 表单项
// 找到表单项,建立与当前事件的关系
for (let emitItem of eventEmit) {
let emitForm = that.formMap[emitItem.form];
emitForm.event.emit.push(eventId);
}
let onFrom = that.formMap[eventOn.form];
onFrom.event.on.push(eventId);
// 存储事件配置
that.eventMap[eventId] = {
type: eventType,
emit: eventEmit,
on: eventOn
};
}
/** @name 获取配置区事件格式配置
* @return {Object} 表单配置区事件配置
* @author 王汝鹏
* @version 2019-12-24
*/
const _transform = function(formId) {
let { type, emit, on } = that.eventMap[eventId];
let eventConfig = {
eventId: eventId, //当前事件id
eventType: type, //事件组合类型(并且、或者、...)
triggerForm: formId, //当前表单id
triggerType: "change", //当前表单项触发事件类型(值变化、点击、...)
triggerValue: undefined, //触发事件的值
emit: [], //关联其它表单项触发事件配置
on: {} //事件监听者配置
};
emit.forEach(e => {
// 触发者配置: { form:表单项id, type:事件类型, value:触发事件的值 }
let { form, type, value } = e;
// 如果触发者为当前表单项
// 更新当前表单项事件设置配置
if (form === formId) {
eventConfig.triggerForm = form;
eventConfig.triggerType = type;
eventConfig.triggerValue = value;
// 其它触发者配置,添加到关联触发者配置中
} else { eventConfig.emit.push({ form, type, value }); }
})
let { form, action } = on;
eventConfig.on = { form, action };
return eventConfig;
}
return {
deleteEmitRelated(formId) { return _deleteEmitRelated(formId); },
deleteEvent() { return _deleteEvent(); },
upsertEvent(event) { return _upsertEvent(event); },
transform(formId) { return _transform(formId); },
}
},
}
}
/** @name 事件编辑配置管理者混入
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixEventEditConfigManager = {
methods: {
/** @name 编辑事件配置管理者
* @param {Object} config 编辑事件配置
* @author 王汝鹏
* @version 2019-12-24
*/
eventEditConfigManager(config) {
let that = this;
/** @name 获取事件id
* @return {String} 事件id
* @author 王汝鹏
* @version 2019-12-24
*/
const _getId = function() {
return config.eventId;
}
/** @name 获取事件所有涉及的表单项id
* @return {Array} 表单项id集合
* @author 王汝鹏
* @version 2019-12-24
*/
const _getFormIds = function() {
let { emit, on } = config;
let formIdSet = new Set([on.form, ...emit.map(e => e.form)]);
formIdSet.delete(undefined);
return [...formIdSet];
}
/** @name 添加事件关联项
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-24
*/
const _addContact = function() {
config.emit.push({
form: undefined,
type: 'change',
value: undefined,
})
return true;
}
/** @name 移除事件关联项
* @param {Number} index 要删除的事件关联项索引
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-24
*/
const _removeContact = function(index) {
config.emit.splice(index, 1);
}
/** @name 转化为提交数据格式
* @return {Object} 提交的事件格式
* @author 王汝鹏
* @version 2019-12-24
*/
const _transform = function() {
// { eventId:事件Id, eventType:事件类型, triggerType:触发类型, triggerValue:触发事件值, emit:事件触发者列表, on:事件监听者 }
let {eventId, eventType, triggerForm, triggerType, triggerValue, emit, on} = config;
// 将当前表单项触发配置转换为事件触发者格式
let formEmitConfig = { form:triggerForm, type:triggerType, value:triggerValue };
// 转换为提交格式事件配置
let submitModel = { eventId, eventType, eventEmit:[...emit, formEmitConfig], eventOn:on };
return submitModel;
}
return {
getId() { return _getId(); },
getFormIds() { return _getFormIds(); },
addContact() { return _addContact(); },
removeContact(index) { return _removeContact(index); },
transform() { return _transform(); }
}
},
}
}
/** 配置数据 :::
* @param {Object} renderComponents 渲染组件字典数据
*/
import { renderComponents } from "@/assets/js/render_data.js";
/** 工具方法 :::
* @function cmToPx 厘米转像素
*/
import { cmToPx, measureFormat } from '@/utils/unit_format.js';
/** @name 表单项属性解构混入
* @requires data {Object} formMap 表单项字典
* @requires data {Object} formModels 表单填写数据
* @author 王汝鹏
* @version 2019-10-26
*/
export const mixFormConfig = {
props: {
formNode: {
type: Object,
required: true
}
},
computed: {
formConfig() { return this.formMap[this.formNode.id] || {} },
formNodeConfig() { return this.formConfig.node || {} },
formBaseOptionConfig() { return this.formConfig.baseOption || {} },
formStyleOptionConfig() { return this.formConfig.styleOption || {} },
formRenderOptionConfig() { return this.formConfig.renderOption || {} },
formEventConfig() { return this.formConfig.event || {} },
// node Config
formType() { return this.formNodeConfig.type },
selfId() { return this.formNodeConfig.selfId },
isCopied() { return this.formNodeConfig.isCopied },
copiedCount() { return this.formNodeConfig.copiedCount },
// baseOption Config
textLength () { return this.formBaseOptionConfig.textLength },
labelName() { return this.formBaseOptionConfig.labelName },
customName() { return this.formBaseOptionConfig.customName },
model() { return this.formBaseOptionConfig.model },
defaultValue() { return this.formBaseOptionConfig.defaultValue },
placeholder() { return this.formBaseOptionConfig.placeholder },
buttonType() { return this.formBaseOptionConfig.buttonType },
buttonSize() { return this.formBaseOptionConfig.buttonSize },
buttonBack() { return this.formBaseOptionConfig.buttonBack },
buttonLoading() { return this.formBaseOptionConfig.buttonLoading },
buttonThrottle() { return this.formBaseOptionConfig.buttonThrottle },
buttonText() { return this.formBaseOptionConfig.buttonText },
isDisplay() { return this.formBaseOptionConfig.isDisplay },
isClearable() { return this.formBaseOptionConfig.isClearable },
isDisabled() { return this.formBaseOptionConfig.isDisable },
isReadonly() { return this.formBaseOptionConfig.isReadonly },
isEditable() { return this.formBaseOptionConfig.isEditable },
isMultiple() { return this.formBaseOptionConfig.multiple },
displayType() { return this.formBaseOptionConfig.displayType || 'inline-block' },
dateType() { return this.formBaseOptionConfig.dateType },
dateFormat() { return this.formBaseOptionConfig.dateFormat },
lineText() { return this.formBaseOptionConfig.lineText },
textPosition() { return this.formBaseOptionConfig.textPosition },
lineStyle() { return this.formBaseOptionConfig.lineType },
uploadLimit () { return this.formBaseOptionConfig.limit },
uploadHost () { return this.formBaseOptionConfig.ossHost },
gridAlign() { return this.formBaseOptionConfig.align || 'top' },
gridGutter() { return this.formBaseOptionConfig.gutter || 0 },
gridJustify() { return this.formBaseOptionConfig.justify || 'start' },
autosizeMinRows() { return this.formBaseOptionConfig.autosizeMinRows },
autosizeMaxRows() { return this.formBaseOptionConfig.autosizeMaxRows },
autosize() { return { minRows:this.autosizeMinRows, maxRows:this.autosizeMaxRows } },
// styleOption Config
customClass() { return this.formStyleOptionConfig.customClass },
width() { return `${cmToPx(this.formStyleOptionConfig.width)}px` },
height() { return `${cmToPx(this.formStyleOptionConfig.height)}px`},
labelWidth() { return `${cmToPx(this.formStyleOptionConfig.labelWidth)}px` },
labelPosition() { return this.formStyleOptionConfig.labelPosition },
labelTextPosition() { return this.formStyleOptionConfig.labelTextPosition },
title() { return this.formStyleOptionConfig.title },
wordWeight () { return this.title === "12" ? 500 : 600 },
wordLineHeight () { return this.title === '12' ? "20px" : (this.title*1.5 + 'px');},
color () { return this.formStyleOptionConfig.color },
paddingLeft () { return `${cmToPx(this.formStyleOptionConfig.paddingLeft)}px` },
// renderOption Config
currentModel() { return this.formModels ? this.formModels[this.model] : undefined; },
renderType() { return renderComponents[this.formType]; },
strong() { return this.formRenderOptionConfig.strong },
underline() { return this.formRenderOptionConfig.underline },
isUnderline() { return this.formRenderOptionConfig.isUnderline },
showUnderline() { return this.underline > 0; },
showTextUnderline() { return this.underline; },
italic() { return this.formRenderOptionConfig.italic },
wrap() { return this.formRenderOptionConfig.wrap },
indent() { return this.formRenderOptionConfig.indent || 0 },
align() { return this.formRenderOptionConfig.align },
fontSize() { return measureFormat(this.formRenderOptionConfig.fontSize || 16); },
lineHeight() { return this.formRenderOptionConfig.lineHeight ? this.formRenderOptionConfig.lineHeight : 40 + 'px'; },
fullLine() { return (this.align && (this.align !== 'none')); },
showRule() { return this.formRenderOptionConfig.showRule },
seat() { return this.formRenderOptionConfig.seat || ''},
nullRender() { return this.formRenderOptionConfig.nullRender || '1'},
whereColor () { return this.formRenderOptionConfig.whereColor },
renderColor () { return this.formRenderOptionConfig.renderColor },
/** 特殊格式 **/
validator() { return this.formBaseOptionConfig.validator || {} },
options() { return this.formBaseOptionConfig.options },
dateFilter() { return this.formBaseOptionConfig.dateFilter },
gridColumns() { return this.formBaseOptionConfig.columns || [] }, // 类型已经变更
freeItemList: {
get() { return this.formBaseOptionConfig.list },
set(newValue) { this.formBaseOptionConfig.list = newValue; }
},
},
}
/** @name 表单项配置管理者混入
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixFormConfigManager = {
methods: {
/** @name 表单项配置管理者
* @param {Object} formConfig 表单项配置
* @return {Object} 表单配置操作
* @author 王汝鹏
* @version 2019-12-24
*/
formConfigManager(config) {
let that = this;
/** @name 更新表单项id
* @param {String} id 表单项id
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-24
*/
const _setId = function(id) {
config.node.selfId = id;
}
return {
setId(id) { return _setId(id); }
}
}
}
}
/** @name 展示表单项混入
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixFormExhibitsManager = {
methods: {
/** @name 展示表单项管理者
* @param {Object} config 展示表单项配置
* @return {Object} 展示表单项操作方法集合
* @author 王汝鹏
* @version 2019-12-24
*/
formExhibitsManager(config) {
let that = this;
/** @name 获取展示表单项名称
* @return {String} 展示表单项名称
* @author 王汝鹏
* @version 2019-12-24
*/
const _getName = function() {
return config.name;
}
/** @name 获取展示表单项图标
* @return {String} 展示表单项图标
* @author 王汝鹏
* @version 2019-12-24
*/
const _getIcon = function() {
return config.icon;
}
/** @name 获取展示表单项类型
* @return {String} 展示表单项类型
* @author 王汝鹏
* @version 2019-12-24
*/
const _getType = function() {
return config.type;
}
return {
getName() { return _getName(); },
getType() { return _getType(); },
getIcon() { return _getIcon(); }
}
},
}
}
/** @name 表单项列表管理者混入
* @requires data {Array} formList 表单项节点列表
* @requires data {Array} activeList 激活表单节点所在列表
* @requires data {Object} activeNode 激活表单节点
* @requires mixin @/mixins/common/mix_form_node_manager.js
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixFormListManager = {
methods: {
/** @name 表单列表管理者
* @author 王汝鹏
* @version 2019-12-21
*/
formListManager() {
let that = this;
/** @name 获取是否包含激活表单项节点
* @return {Boolean} 是否包含激活表单节点 { true:包含,false:不包含 }
* @author 王汝鹏
* @version 2019-12-24
*/
const _hasActiveNode = function() {
let activeIndex = that.activeList.findIndex(node => node.id === that.activeNode.id);
return activeIndex !== -1;
}
/** @name 获取激活节点索引
* @return {Number} 激活节点所在列表索引
* @author 王汝鹏
* @version 2019-12-24
*/
const _getActiveIndex = function() {
let activeIndex = that.activeList.findIndex(node => node.id === that.activeNode.id);
return activeIndex;
}
/** @name 激活表单项
* @param {Object} formNode 表单项节点
* @param {Array} formNodeList 表单项节点所在集合
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-21
*/
const _activeNode = function(formNode, formNodeList) {
that.activeList = formNodeList;
that.activeNode = formNode;
}
/** @name 刷新表单列表
* @author 王汝鹏
* @version 2019-12-21
*/
const _refreshList = function() {
that.formList = that.formList;
that.formMap = {...that.formMap};
}
/** @name 清空表单列表
* @author 王汝鹏
* @version 2019-12-21
* @updateInfo 2020-1-11 liuguisheng 添加变量设置删除
*/
const _emptyList = function() {
for (let node of [...that.formList]) {
that.formNodeManager(node).deleteFrom(that.formList);
}
that.formList = [];
that.activeNode = {};
that.activeList = [];
that.variableMap = {};
}
/** @name 获取列表节点数量
* @return {Number} 列表节点数量
* @author 王汝鹏
* @version 2019-12-22
*/
const _getLength = function() {
return that.formList.length;
}
return {
activeNode(formNode, formNodeList) { return _activeNode(formNode, formNodeList); },
refreshList() { return _refreshList(); },
emptyList() { return _emptyList(); },
getLength() { return _getLength(); },
hasActiveNode() { return _hasActiveNode(); },
getActiveIndex() { return _getActiveIndex(); }
}
},
}
}
/** 工具方法 :::
* @function deepCopy 深拷贝方法
*/
import { deepCopy, produceNumber } from '@/utils/utils.js'
/** 配置数据 :::
* @data {Map<String,Number>} allFormTypeIndex 表单类型序号字典
*/
import { allFormTypeIndex, formTypeNameDictionary } from "@/assets/js/form_dictionary.js";
/** @name 表单项节点管理者混入
* @requires data {Object} formMap 表单项字典
* @requires mixin @/mixins/common/mix_event_config_manager.js
* @requires mixin @/mixins/common/mix_make_config_manager.js
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixFormNodeManager = {
methods: {
formNodeManager(formNode) {
let that = this;
/** @name 判断节点配置是否相等
* @param {Object} compareConfig 要对比的节点配置
* @return {Boolean} 是否相等 {true:相等, false:不相等}
* @author 王汝鹏
* @version 2019-12-20
*/
const _isEqual = function(compareConfig) {
return formNode.id === compareConfig.id;
}
/** @name 删除当前节点
* @param {Array} list 表单节点所在列表
* @return {Boolean} 删除结果
* @author 王汝鹏
* @version 2019-12-21
*/
const _deleteFrom = function(list) {
let { id, children } = formNode;
for (let childNode of children) {
that.formNodeManager(childNode).deleteFrom(children);
}
// 删除表单项事件配置关系
let event = that.formMap[id].event;
let { emit, on } = event;
for (let eventId of emit) { that.eventConfigManager(eventId).deleteEmitRelated(id); }
for (let eventId of on) { that.eventConfigManager(eventId).deleteEvent(); }
// 删除变量设置
let { model } = that.formMap[id].baseOption;
delete that.variableMap[model]
// 删除表单项配置
Reflect.deleteProperty(that.formMap, id);
// 删除表单项
let deleteIndex = list.findIndex(i => i.id === id);
list.splice(deleteIndex, 1);
that.formMap = { ...that.formMap };
}
/** @name 复制当前节点
* @return {Object} 复制的表单项节点
* @author 王汝鹏
* @version 2019-12-21
*/
const _copy = function() {
let { id, children } = formNode;
let formConfig = that.formMap[id];
if (!formConfig) return;
// copy 表单项节点
let copyFormNode = that.makeFormNodeConfig();
// copy 表单项配置 重新分配表单项id、变量名、显示名称
let copyFormConfig = deepCopy(formConfig);
let { type } = copyFormConfig.node;
copyFormConfig.node.selfId = copyFormNode.id;
copyFormConfig.baseOption.model = `${type}_${produceNumber(6)}`;
allFormTypeIndex.set(type, allFormTypeIndex.get(type)+1);
copyFormConfig.baseOption.customName = `${formTypeNameDictionary.get(type)}_${String(allFormTypeIndex.get(type)).padStart(8, '0')}`;
copyFormConfig.event = { emit:[], on:[] };
// 表单项注册到表单字典中
that.formMap[copyFormNode.id] = copyFormConfig;
// 复制当前表单项的子级节点
copyFormNode.children = children.map(node => that.formNodeManager(node).copy());
return copyFormNode;
}
/** @name 复制当前节点到列表中
* @param {Array} list 表单项节点所在列表
* @return {Boolean} 复制结果
* @author 王汝鹏
* @version 2019-12-21
*/
const _copyTo = function(list) {
let { id } = formNode;
let formConfig = that.formMap[id];
if (!formConfig) return false;
let copyNode = that.formNodeManager(formNode).copy();
let copyNodeConfig = that.formMap[copyNode.id];
copyNodeConfig.node.isCopied = true;
formConfig.node.copiedCount = formConfig.node.copiedCount + 1;
let insertIndex = list.findIndex(node => node === formNode);
list.splice(insertIndex+1, 0, copyNode);
return true;
}
return {
isEqual(compareConfig) { return _isEqual(compareConfig); },
deleteFrom(list) { return _deleteFrom(list); },
copy() { return _copy(); },
copyTo(list) { return _copyTo(list); }
}
},
}
}
/** 工具方法 :::
* @function produceNumber 随机数方法
* @function deepCopy 深拷贝方法
*/
import { produceNumber, deepCopy } from '@/utils/utils.js'
/** 配置数据 :::
* @data {Map<String,String>} formTypeNameDictionary 表单类型名称字典
* @data {Map<String,Number>} allFormTypeIndex 表单类型序号字典
* @data {Object} formConfigMap 表单配置字典
*/
import { formTypeNameDictionary, allFormTypeIndex, formConfigMap } from "@/assets/js/form_dictionary.js";
/** @name 生成默认配置混入
* @requires
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixMakeConfigManager = {
methods: {
/** @name 生成表单项配置
* @param {String} type 表单项类型
* @return {Object} 表单项配置
* @author 王汝鹏
* @version 2019-12-24
*/
makeFormConfig(type) {
if (Reflect.has(formConfigMap, type) === false) throw new Error(`不存在 ${type} 类型表单配置.`);
allFormTypeIndex.set(type, allFormTypeIndex.get(type)+1);
// copy类型默认配置
let copyConfig = deepCopy(formConfigMap[type]);
// 分配表单项显示名称
copyConfig.baseOption.customName = `${formTypeNameDictionary.get(type)}_${String(allFormTypeIndex.get(type)).padStart(8, '0')}`;
// 分配表单项变量名
Reflect.has(copyConfig.baseOption, 'model') && (copyConfig.baseOption.model = `${type}_${produceNumber(6)}`);
return copyConfig;
},
/** @name 获取默认事件配置
* @param {String} formId 表单项id
* @reutrn {Object} 默认事件配置
* @author 王汝鹏
* @version 2019-12-24
*/
makeEventConfig(formId) {
return {
eventId: produceNumber(6), // 事件id
eventType: undefined, // 事件类型(并且、或者)
triggerForm: formId, // 触发表单项id
triggerType: "change", // 触发事件类型(默认值改变)
triggerValue: undefined, // 触发事件的值
emit: [], // 触发事件表单项配置列表
on: { form:undefined, action:undefined } // 监听事件表单项配置
}
},
/** @name 生成新表单项节点配置
* @return {Object} 表单项节点配置
* @author 王汝鹏
* @version 2019-12-21
*/
makeFormNodeConfig() {
return {
id: `${produceNumber(6)}`,
children: [],
}
},
/** @name 生成/获取 分组组件配置
* @param {String} domainName 模块名称
* @param {Array} templates 领域模版数据
* @return {Object} 模块组件数据
* @author 王汝鹏
* @version 2019-12-21
*/
makeDomainConfig(domainName, templates) {
let groupId = produceNumber(6)
return {
exhibits: {
type: "domain",
name: domainName,
icon: "iconmokuai",
},
node: {
id: groupId,
children: templates,
},
config: {
node: {
type: "domain",
selfId: groupId
},
baseOption: {},
styleOption: {},
renderOption: {},
event: {emit:[],on:[]},
}
}
},
}
}
\ No newline at end of file
/** @name 节点事件行为管理者混入
* @requires data {Object} formMap 表单项字典
* @requires mixin @/mixins/common/mix_form_node_manager.js
* @author 王汝鹏
* @version 2019-12-24
*/
export const mixNodeActionManager = {
methods: {
/** @name 节点事件行为管理者
* @param {Object} formNode 表单项节点
* @return {Object} 节点行为
* @author 王汝鹏
* @version 2019-12-23
*/
nodeActionManager(formNode) {
let that = this;
/** @name 表单节点显示行为
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-23
*/
const _display = function() {
let formConfig = that.formMap[formNode.id];
formConfig.baseOption.isDisplay = true;
}
/** @name 表单节点隐藏行为
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-23
*/
const _hide = function() {
let formConfig = that.formMap[formNode.id];
formConfig.baseOption.isDisplay = false;
}
/** @name 表单节点复制行为
* @param {Object} parent 节点父级
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-23
*/
const _copyTo = function(parent) {
that.formNodeManager(formNode).copyTo(parent);
}
/** @name 表单节点删除行为
* @param {Object} parent 节点父级
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-23
*/
const _deleteFrom = function(parent) {
that.formNodeManager(formNode).deleteFrom(parent);
}
/** @name 表单节点禁用行为
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-23
*/
const _disable = function() {
let formConfig = that.formMap[formNode.id];
formConfig.baseOption.isDisable = true;
}
/** @name 表单节点解禁行为
* @return {Boolean} 操作结果
* @author 王汝鹏
* @version 2019-12-23
*/
const _enable = function() {
let formConfig = that.formMap[formNode.id];
formConfig.baseOption.isDisable = false;
}
return {
display() { return _display(); },
hide() { return _hide(); },
copyTo(parent) { return _copyTo(parent); },
deleteFrom(parent) { return _deleteFrom(parent); },
disable() { return _disable(); },
enable() { return _enable(); }
}
}
}
}
/**
* @name 组件设置项通用混入文件
* @author liuguisheng
* @version 2019-11-13
*
*
*/
export default {
data () {
return {
// 计数器组件精度控制
precision: 2,
// 计数器组件步数
step: 0.01
}
},
}
\ No newline at end of file
// 导入上传工具
import { upload } from '@/utils/upload.js';
/**
* @name 上传混入文件
* @author 王汝鹏
* @version 2019-09-16
*/
export default {
data() {
return {
fileListData: [],
}
},
methods: {
/** @name 删除图片
* @description 删除后的文件地址存储到组件值中
* @param {Object} file 文件对象
* - {String} name 文件名称
* - {Number} size
* - {String} status
* - {String} url
* @param {Array} fileList 删除后的文件列表
* @author 王汝鹏
* @version 2019-09-16
*/
handleRemove(file, fileList) {
this.uploadFileList = fileList;
},
/** @name 上传图片到阿里云
* @description 读取组件配置,上传图片到阿里云,更新组件上传图片值
* @param {Object} file 文件对象
* @author 王汝鹏
* @version 2019-09-16
*/
async uploadImage({file}) {
try {
// 上传图片
let previewPath = await upload(file, this.ossConfig);
// 更新已上传文件列表
this.uploadFileList = [...this.uploadFileList, {
name: file.name,
url: `${previewPath}?name=${file.name}`
}];
} catch (err) { console.log('uploadImageError: ', err); }
},
/** @name 超出最大上传个数钩子
* @returns { void }
* @author liuguisheng
* @version 2019-11-13
*/
handleExceed () {
this.$message({type: 'warning', message: '超出最大上传个数!'})
}
},
computed: {
/** @name 已经上传的图片
* @return {Array}
* @author 王汝鹏
* @version 2019-09-16
*/
uploadFileList: {
get() {
let fileList = this.currentModel || [];
let result = fileList.map((url, index) => {
let query = url.split("?")[1];
let params = (query||"").split("&");
let paramMap = new Map();
for (let param of params) {
let [key, value] = param.split('=');
paramMap.set(key, value);
}
return { name: paramMap.get("name") || `${index}`, url };
})
return result;
},
set(newValue) {
this.currentModel = newValue.map(({name, url}) => url);
}
},
/** @name 展示的已上传文件列表
* @description 解决数据变化时,整个组件渲染图片列表跳动问题,缓存一份数据,对比数据判断是否刷新
* @author 王汝鹏
* @version 2019-12-02
*/
showFileListData() {
// 两个数据的长度不一样,说明数据肯定发生了变更
if (this.uploadFileList.length !== this.fileListData.length) {
this.fileListData = this.uploadFileList;
} else {
// 对比数据是否一致
let fileListMap = new Map(this.fileListData.map(({name, url}) => [url, name]))
for (let {name, url} of this.uploadFileList) {
if (fileListMap.get(url) !== name) {
this.fileListData = this.uploadFileList;
break;
}
}
}
return this.fileListData;
},
/** @name 阿里云配置
* @return {Object}
* @author 王汝鹏
* @version 2019-09-20
*/
ossConfig() {
let config = this.formBaseOptionConfig;
let ossConfig = {
uploadHost: config.ossHost,
region: config.ossRegion,
bucket: config.ossBucket,
fileDir: config.ossDir,
accessKeyId: config.accessKeyId,
accessKeySecret: config.accessKeySecret
}
return ossConfig;
}
}
}
\ No newline at end of file
/**************************************************************************************************************
@name v-model工具方法混入 + v-model数据解构计算属性方法
@description 主要方法说明
混入方法说明:
1. 在props中混入了value属性并限定类型为(Object|Array)
!!! required 如果在父组件没有绑定 v-model 或 value ???
2.1 methods :: valueRefresh
当父组件 v-model 或 value 值发生变化时会默认携带新值调用这个方法
这里声明了一个空方法防止自动调用报错,如果想获取更新值需要在组件中声明同名方法覆盖
2.2 methods :: refreshValue
主动调用该方法,用于强制刷新父组件的数据,在必要的时候使用
3. 在watch中混入value的监听, 值更新主动调用 valueRefresh 方法, 也可以在开发阶段在watch中检测值、调试值
计算属性映射方法说明:
功能效果: 根据配置生成 { example:{ get(){}, set(){} }, ... } 结构的数据
参数说明:
key: 计算属性变量名称
value :: parent: 用于查找计算属性变量父级的方法,方法参数为 v-model 或 value 绑定的值, 默认方法返回了 this.value
value :: attr: 当前映射计算属性的字段名称, 会在 get、set 方法中操作parent方法返回数据中attr字段
value :: getFormat: 在计算属性get方法返回值之前会调用getFormat方法对返回数据进行格式化后返回,默认方法没有做任何数据处理
value :: setFormat: 在计算属性set方法设置值之前会调用setFormat方法对设置数据进行格式化后赋值,默认方法没有做任何数据处理
@author 王汝鹏
@version 2019-09-26
**************************************************************************************************************/
/** @name 计算属性映射方法
* @description 使用例子:
* 参数: {
* example1:{ attr:"example1" },
* example2:{ parent:v=>v.e, attr:"example2", get:v => "hello "+v }
* }
* 结果: {
* example1:{ get(){ return this.value['example1']; },
* set(v){ this.value['example1']=v; this.$emit('input',{...this.value}); } }
* example2:{ get(){ return 'hello ' + this.value.e['example2']; },
* set(v){ this.value.e['example2']=v; this.$emit('input',{...this.value}); } }
* }
* @param {Object} items
* - {String} key 映射到计算属性中的计算属性名称
* - {Object} value 映射配置对象
* - {Function} parent 寻找属性父级方法,传入value变量,传出计算属性父级变量
* - {String} attr 变量名称
* - {Function} getFormat 读取数据格式化
* - {Function} setFormat 写入数据格式化
* @return {Object}
*/
export const mapComputed = function(items) {
let result = {};
for (let key in items) {
let defaultItem = {
parent: i => i,
attr: "",
getFormat: function(val) { return val; },
setFormat: function(val) { return val; }
}
let item = {...defaultItem, ...items[key]};
result[key] = {
get: function() {
let parent = item.parent(this.value);
let value = parent[item.attr];
value = item.getFormat(value);
return value;
},
set: function(newValue) {
let parent = item.parent(this.value);
parent[item.attr] = item.setFormat(newValue)
this.$emit('input', {...this.value});
}
}
}
return result;
}
/** @name v-model 观察者
* @param {Object|Array} value
* @function valueRefresh value值发生更新钩子方法
* @function refreshValue 刷新value值
* @author 王汝鹏
* @version 2019-09-26
*/
export default {
props: {
// v-model接收
value: {
type: [Object,Array],
required: true
}
},
methods: {
/** @name value值发生更新(值刷新))
* @author 王汝鹏
* @version 2019-09-26
*/
valueRefresh(newValue) {},
/** @name 刷新value值(刷新值)
* @author 王汝鹏
* @version 2019-09-26
*/
refreshValue () {
let model = (this.value instanceof Array) ? [...this.value] : {...this.value};
this.$emit('input', model);
}
},
watch: {
/** @name value值观察者
* @description 调用value刷新钩子方法
* @author 王汝鹏
* @version 2019-09-26
*/
value: {
handler(val) {
this.valueRefresh(val)
},
deep: true,
immediate: true
}
}
}
// Vue
import Vue from 'vue';
// element
import 'element-ui';
// icon
import "./assets/font/iconfont.css";
// markdowm
import "./style/markdowm.scss";
// style
import "./style/index.scss";
// component registry
import install from '../packages/index.js';
install(Vue);
export default { install };
#!/bin/sh
npm config set registry http://39.106.145.141:9000/repository/node-host/
echo "私有仓库地址设置成功"
npm login
echo "登录成功"
npm run lib
echo "打包成功"
npm publish
echo "已成功发布到私有仓库"
\ No newline at end of file
/**
* 公用样式
* @author liuguisheng
* @date 2019-9-8
*/
@import './var.scss';
// 去掉组件库按钮左边距
.el-button+.el-button {
margin-left: 0;
}
.el-popover {
text-align: center;
}
// 修改组件库表单校验错误提示的最小宽度
.el-form-item__error {
min-width: 28px;
}
// 去掉组件库表单项下边距并修改
.el-form-item {
margin-bottom: 0!important;
margin: 20px 0;
}
// 上传图片会闪一下,去掉过渡效果
.el-upload-list__item {
transition: none!important;
}
// 单选选项垂直对其方式
.el-radio-button__inner, .el-radio-group {
vertical-align: baseline!important;
}
.el-radio-group {
padding-top: 4px!important;
}
// 斜体
.italic {
font-style: italic;
}
// 加粗
.strong {
font-weight: 900;
}
// 换行
.wrap{
width: 100%;
}
// 下划线
.underline {
text-decoration: underline;
}
// 虚线框
.border-dashed {
border: 1px dashed $--border-color-base;
text-decoration: underline;
}
/**
* 样式混入文件
* @author liuguisheng
* @date 2019-9-8
*/
@import './var.scss';
// scrollbar
@mixin scrollbar ( $maxHeight ) {
max-height: $maxHeight;
overflow: scroll;
&::-webkit-scrollbar {
width: 8px;
background-color: $--color-icon-background;
border-radius: $--radius-middle;
}
&::-webkit-scrollbar-track {
background-color: $--color-icon-background;
}
&::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: $--radius-middle;
}
&::-webkit-scrollbar-button:start {
background-size: 12px 12px;
}
&::-webkit-scrollbar-button:end {
background-size: 12px 12px;
}
}
/** 文字溢出显示省略号 **/
@mixin TextOverflowEllipsis {
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
/**
* 样式初始化文件
* @author liuguisheng
* @date 2019-9-8
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
font-family: "Microsoft YaHei","SimSun","Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB",Arial,sans-serif;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
a, a:active {
text-decoration: none;
color: #000;
}
/**
* 基础变量定义
* @author liuguisheng
* @date 2019-9-8
*/
/** color **/
$--color-white: #fff !default;
$--color-black: #000 !default;
$--color-transparency: rgba(0, 0, 0, 0);
$--color-assist: #ff8b37 !default;
$--color-primary: #1fb19e !default;
$--color-primary-mix-white-1: mix($--color-white, $--color-primary, 10%) !default;
$--color-primary-mix-white-2: mix($--color-white, $--color-primary, 20%) !default; //#4cc1b1
$--color-primary-mix-white-3: mix($--color-white, $--color-primary, 30%) !default;
$--color-primary-mix-white-4: mix($--color-white, $--color-primary, 40%) !default;
$--color-primary-mix-white-5: mix($--color-white, $--color-primary, 50%) !default;
$--color-primary-mix-white-6: mix($--color-white, $--color-primary, 60%) !default;
$--color-primary-mix-white-7: mix($--color-white, $--color-primary, 70%) !default;
$--color-primary-mix-white-8: mix($--color-white, $--color-primary, 80%) !default;
$--color-primary-mix-white-9: mix($--color-white, $--color-primary, 90%) !default;
$--color-primary-mix-black-1: mix($--color-black, $--color-primary, 10%) !default;
$--color-primary-mix-black-2: mix($--color-black, $--color-primary, 20%) !default; //#1c9f8e
$--color-primary-mix-black-3: mix($--color-black, $--color-primary, 30%) !default;
$--color-primary-mix-black-4: mix($--color-black, $--color-primary, 40%) !default;
$--color-primary-mix-black-5: mix($--color-black, $--color-primary, 50%) !default;
$--color-primary-mix-black-6: mix($--color-black, $--color-primary, 60%) !default;
$--color-primary-mix-black-7: mix($--color-black, $--color-primary, 70%) !default;
$--color-primary-mix-black-8: mix($--color-black, $--color-primary, 80%) !default;
$--color-primary-mix-black-9: mix($--color-black, $--color-primary, 90%) !default;
$--color-success: #1fb19e !default;
$--color-success-mix-white: mix($--color-white, $--color-success, 20%) !default;
$--color-success-mix-black-2: mix($--color-black, $--color-success, 20%) !default;
$--color-warning: #ff8b37 !default;
$--color-warning-mix-white: mix($--color-white, $--color-warning, 20%) !default;
$--color-warning-mix-black-2: mix($--color-black, $--color-warning, 20%) !default;
$--color-danger: #eb4c44 !default;
$--color-danger-mix-white: mix($--color-white, $--color-danger, 20%) !default;
$--color-danger-mix-black-2: mix($--color-black, $--color-danger, 20%) !default;
$--color-link: #1e88e5 !default;
$--color-link-mix-white: mix($--color-white, $--color-link, 20%) !default;
$--color-link-mix-black-2: mix($--color-black, $--color-link, 20%) !default;
$--color-disable: #f3f3f3 !default;
$--color-disable-mix-white: mix($--color-white, $--color-disable, 20%) !default;
$--color-disable-mix-black-2: mix($--color-black, $--color-disable, 20%) !default;
$--color-text-secondary: #909399 !default;
$--color-text-primary: #5c5c5c !default;
$--color-text-placeholder: #999999 !default;
$--color-text-disabled: #cccccc !default;
$--color-icon-text: #4c4c4c !default;
$--color-icon-back: #ebeaed !default;
$--color-icon-background: #f7f7f7 !default;
/** Scrollbar **/
$--scrollbar-background-color: rgba($--color-text-secondary, .3) !default;
$--scrollbar-hover-background-color: rgba($--color-text-secondary, .5) !default;
/** Font **/
$--font-size-base: 14px !default;
$--font-size-small: 12px !default;
$--font-weight-normal: 400 !default;
$--font-weight-bold: 700 !default;
/** Button **/
$--button-font-size: 14px !default;
$--button-default-background-color: $--color-white !default;
/** Border **/
$--border-width-base: 1px !default;
$--border-style-base: solid !default;
$--border-color-base: #e2e2e2 !default;
$--border-color-hover: #1fb19e !default;
$--border-color-active: #1fb19e !default;
$--border-color-disable: #e2e2e2 !default;
/** Radius **/
$--radius-base: 3px !default;
$--radius-middle: 5px !default;
$--radius-large: 10px !default;
$--radius-progress: 100px !default;
$--radius-button-icon-base: 16px !default;
$--radius-button-icon-small: 14px !default;
/** Shadow **/
$--box-shadow-base: 1px 0px 10px rgba(0, 0, 0, .1), 1px 0px 1px rgba(238, 238, 238, .1) inset !default;
$--box-shadow-large: 5px 0px 20px rgba(0, 0, 0, .1), 5px 0px 1px rgba(238, 238, 238, .1) inset !default;
$--box-shadow-base-top: 1px 5px 5px rgba(0, 0, 0, .08), 1px 0px 1px rgba(238, 238, 238, .1) inset !default;
/** transition **/
$--transition-general: all .3s cubic-bezier(.25, .1, .25, 1) !default;
$--transition-solw: all .2s cubic-bezier(.25, .1, .25, 1) !default;
$--transition-fast: all .5s cubic-bezier(.25, .1, .25, 1) !default;
/** Select **/
$--select-border-color-base: $--border-color-base !default;
$--select-border-color-hover: $--border-color-hover !default;
$--select-border-color-active: $--border-color-active !default;
$--select-border-color-disable: $--border-color-disable !default;
$--select-input-font-color: $--color-text-primary !default;
$--select-font-size: $--font-size-small !default;
@import "./common/common.scss";
@import "./common/mixin.scss";
@import "./common/reset.scss";
@import "./common/var.scss";
@import "./packages//input.scss";
\ No newline at end of file
/**
* 首页样式
* @author liuguisheng
* @date 2019-11-6
*
*/
@import './common/var.scss';
.markdown hr {
margin-top: 33px;
}
.markdown h1 {
color: $--color-icon-text;
font-weight: 400;
margin-bottom: 20px;
margin-top: 8px;
line-height: 38px;
font-size: 28px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
margin: 1.6em 0 0.6em;
font-weight: 400;
clear: both;
font-size: 24px;
color: $--color-icon-text;
}
.markdown h3 {
font-size: 18px;
}
.markdown h4 {
font-size: 16px;
}
.markdown h5 {
font-size: 14px;
}
.markdown h6 {
font-size: 12px;
}
.markdown p,
.markdown pre {
font-size: 14px;
color: #5e6d82;
line-height: 1.5em;
}
.markdown ul > li > p,
.markdown ol > li > p {
margin: 0.2em 0;
}
.markdown ul {
padding: 0;
margin: 0;
}
.markdown ul > li {
list-style-type: circle;
margin-left: 20px;
padding-left: 4px;
padding-top: 15px;
color: $--color-icon-text;
}
.markdown ol > li {
list-style-type: decimal;
margin-left: 20px;
padding-left: 4px;
padding-top: 15px;
color: $--color-icon-text;
}
.markdown > table {
border-collapse: collapse;
border-spacing: 0;
empty-cells: show;
border: 1px solid #ebedf0;
width: 100%;
margin: 8px 0 16px;
}
.markdown > table th,
.markdown > table td {
color: #314659;
border: 1px solid #ebedf0;
text-align: left;
padding: 10px 15px;
}
.markdown > table th {
white-space: nowrap;
color: #5c6b77;
font-weight: 500;
background: rgba(0, 0, 0, 0.02);
}
.markdown strong,
.markdown b {
font-weight: 500;
}
.markdown .sh-markdown-permalink {
opacity: 0;
}
.markdown h1:hover .sh-markdown-permalink,
.markdown h2:hover .sh-markdown-permalink,
.markdown h3:hover .sh-markdown-permalink,
.markdown h4:hover .sh-markdown-permalink,
.markdown h5:hover .sh-markdown-permalink,
.markdown h6:hover .sh-markdown-permalink {
opacity: 1;
display: inline-block;
}
.markdown > br,
.markdown p > br {
clear: both;
}
.markdown blockquote {
font-size: 90%;
color: #0d1a26;
border-left: 4px solid #ebedf0;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown hr {
height: 1px;
border: 0;
background: #ebedf0;
clear: both;
}
.markdown code {
font-family: Microsoft YaHei;
margin: 0 1px;
border-radius: 3px;
font-size: 0.9em;
color: #5c5c5c;
font-size: 14px;
}
.markdown .language-html {
width: 100%;
padding: 10px 25px 10px 10px;
box-sizing: border-box;
}
.markdown pre {
line-height: 2.8em;
}
.markdown p {
line-height: 2em;
font-size: 15px;
}
.markdown .language-shell {
font-size: 13px;
background: $--color-primary;
width: 100%;
display: inline-block;
color: #fff;
}
/**
* @name 输入框样式
* @author liuguisheng
* @version 2020-10-21 10:26:46 星期三
*/
@import "../common/var.scss";
.qj-input {
border: 1px solid $--border-color-base;
outline: none;
padding: 10px 10px;
border-radius: $--radius-base;
transition: $--transition-general;
color: $--color-text-primary;
&:hover,&:focus {
transition: $--transition-general;
border-color: $--border-color-hover;
}
}
\ No newline at end of file
/************************************************
@function produceNumber 生成随机数方法
@function objTransformArr 对象转数组方法
@function objectEmptyCheck 校验对象的各个属性是否为空
@function deepCopy 对象深拷贝
************************************************/
/**
* @name 生成随机数方法
* @param {Number} length 随机字符串长度
* @param {Boolean} isDate 是否添加时间戳 (default: true)
* @return {String}
* @author liuguisheng
* @version 2019-9-11
*/
export const produceNumber = function(length, isDate=true) {
length = length || 32;
let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz23456789';
// 字符长度(maxLength)和随机数(randomNumber)定义
let maxLength = chars.length, randomNumber = '';
// 添加随机数
for (let i = 0; i < length; i++) {
randomNumber += chars.charAt(Math.floor(Math.random() * maxLength));
}
// 如果设置时间戳拼接到随机数后边,否则直接抛出
return isDate ? randomNumber + new Date().getTime() : randomNumber;
}
/**
* @name 对象转数组方法
* @params { Object } obj 需要转换的对象
* @return { Array } 转换后的数组
* @author liuguihsheng
* @version 2019-9-14
*
*/
export const objTransformArr = function(obj) {
let arr = [];
// 开始转换并抛出
for(let i in obj) arr.push(obj[i]);
return arr;
}
import Vue from 'vue'
export interface InstallationOptions {
locale: any,
i18n: any,
size: string
}
/** ElementUI component common definition */
export function install (vue: typeof Vue, options: InstallationOptions): void
export default {
install
}
// 表单编辑组件
export declare class RiceIndex {
readonly $el: Element;
value: Object;
}
// 联动预览组件
export declare class RicePreviewBridge {
readonly $el: Element;
value: Object;
formData: Object;
}
// 表单填写组件
export declare class RicePreviewForm {
readonly $el: Element;
value: Object;
formData: Object;
}
// 打印预览组件
export declare class RicePreviewRender {
readonly $el: Element;
value: Object;
formData: Object;
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论