@ -0,0 +1,14 @@ |
|||
# https://editorconfig.org |
|||
root = true |
|||
|
|||
[*] |
|||
charset = utf-8 |
|||
indent_style = space |
|||
indent_size = 2 |
|||
end_of_line = lf |
|||
insert_final_newline = true |
|||
trim_trailing_whitespace = true |
|||
|
|||
[*.md] |
|||
insert_final_newline = false |
|||
trim_trailing_whitespace = false |
@ -0,0 +1,8 @@ |
|||
# just a flag |
|||
ENV = 'development' |
|||
|
|||
# base api |
|||
#VUE_APP_BASE_API = '/dev-api' |
|||
VUE_APP_BASE_API = '/base' |
|||
VUE_APP_USER_API = '/user' |
|||
VUE_APP_PRINT_API='http://dev.cd-top.com:9097' |
@ -0,0 +1,14 @@ |
|||
# just a flag |
|||
ENV = 'production' |
|||
|
|||
# base api |
|||
#VUE_APP_BASE_API = '/prod-api' |
|||
VUE_APP_BASE_API = '/base' |
|||
VUE_APP_USER_API = '/user' |
|||
VUE_APP_PRINT_API='http://dev.cd-top.com:9097' |
|||
# 杭州 |
|||
#VUE_APP_PRINT_API='http://10.74.150.81:9082' |
|||
# 天津 |
|||
#VUE_APP_PRINT_API='http://10.74.160.70:9082' |
|||
|
|||
|
@ -0,0 +1,8 @@ |
|||
NODE_ENV = production |
|||
|
|||
# just a flag |
|||
ENV = 'staging' |
|||
|
|||
# base api |
|||
VUE_APP_BASE_API = '/stage-api' |
|||
|
@ -0,0 +1,5 @@ |
|||
# build/*.js |
|||
# src/assets |
|||
# public |
|||
# dist |
|||
* |
@ -0,0 +1,198 @@ |
|||
module.exports = { |
|||
root: true, |
|||
parserOptions: { |
|||
parser: 'babel-eslint', |
|||
sourceType: 'module' |
|||
}, |
|||
env: { |
|||
browser: true, |
|||
node: true, |
|||
es6: true, |
|||
}, |
|||
extends: ['plugin:vue/recommended', 'eslint:recommended'], |
|||
|
|||
// add your custom rules here
|
|||
//it is base on https://github.com/vuejs/eslint-config-vue
|
|||
rules: { |
|||
"vue/max-attributes-per-line": [2, { |
|||
"singleline": 10, |
|||
"multiline": { |
|||
"max": 1, |
|||
"allowFirstLine": false |
|||
} |
|||
}], |
|||
"vue/singleline-html-element-content-newline": "off", |
|||
"vue/multiline-html-element-content-newline":"off", |
|||
"vue/name-property-casing": ["error", "PascalCase"], |
|||
"vue/no-v-html": "off", |
|||
'accessor-pairs': 2, |
|||
'arrow-spacing': [2, { |
|||
'before': true, |
|||
'after': true |
|||
}], |
|||
'block-spacing': [2, 'always'], |
|||
'brace-style': [2, '1tbs', { |
|||
'allowSingleLine': true |
|||
}], |
|||
'camelcase': [0, { |
|||
'properties': 'always' |
|||
}], |
|||
'comma-dangle': [2, 'never'], |
|||
'comma-spacing': [2, { |
|||
'before': false, |
|||
'after': true |
|||
}], |
|||
'comma-style': [2, 'last'], |
|||
'constructor-super': 2, |
|||
'curly': [2, 'multi-line'], |
|||
'dot-location': [2, 'property'], |
|||
'eol-last': 2, |
|||
'eqeqeq': ["error", "always", {"null": "ignore"}], |
|||
'generator-star-spacing': [2, { |
|||
'before': true, |
|||
'after': true |
|||
}], |
|||
'handle-callback-err': [2, '^(err|error)$'], |
|||
'indent': [2, 2, { |
|||
'SwitchCase': 1 |
|||
}], |
|||
'jsx-quotes': [2, 'prefer-single'], |
|||
'key-spacing': [2, { |
|||
'beforeColon': false, |
|||
'afterColon': true |
|||
}], |
|||
'keyword-spacing': [2, { |
|||
'before': true, |
|||
'after': true |
|||
}], |
|||
'new-cap': [2, { |
|||
'newIsCap': true, |
|||
'capIsNew': false |
|||
}], |
|||
'new-parens': 2, |
|||
'no-array-constructor': 2, |
|||
'no-caller': 2, |
|||
'no-console': 'off', |
|||
'no-class-assign': 2, |
|||
'no-cond-assign': 2, |
|||
'no-const-assign': 2, |
|||
'no-control-regex': 0, |
|||
'no-delete-var': 2, |
|||
'no-dupe-args': 2, |
|||
'no-dupe-class-members': 2, |
|||
'no-dupe-keys': 2, |
|||
'no-duplicate-case': 2, |
|||
'no-empty-character-class': 2, |
|||
'no-empty-pattern': 2, |
|||
'no-eval': 2, |
|||
'no-ex-assign': 2, |
|||
'no-extend-native': 2, |
|||
'no-extra-bind': 2, |
|||
'no-extra-boolean-cast': 2, |
|||
'no-extra-parens': [2, 'functions'], |
|||
'no-fallthrough': 2, |
|||
'no-floating-decimal': 2, |
|||
'no-func-assign': 2, |
|||
'no-implied-eval': 2, |
|||
'no-inner-declarations': [2, 'functions'], |
|||
'no-invalid-regexp': 2, |
|||
'no-irregular-whitespace': 2, |
|||
'no-iterator': 2, |
|||
'no-label-var': 2, |
|||
'no-labels': [2, { |
|||
'allowLoop': false, |
|||
'allowSwitch': false |
|||
}], |
|||
'no-lone-blocks': 2, |
|||
'no-mixed-spaces-and-tabs': 2, |
|||
'no-multi-spaces': 2, |
|||
'no-multi-str': 2, |
|||
'no-multiple-empty-lines': [2, { |
|||
'max': 1 |
|||
}], |
|||
'no-native-reassign': 2, |
|||
'no-negated-in-lhs': 2, |
|||
'no-new-object': 2, |
|||
'no-new-require': 2, |
|||
'no-new-symbol': 2, |
|||
'no-new-wrappers': 2, |
|||
'no-obj-calls': 2, |
|||
'no-octal': 2, |
|||
'no-octal-escape': 2, |
|||
'no-path-concat': 2, |
|||
'no-proto': 2, |
|||
'no-redeclare': 2, |
|||
'no-regex-spaces': 2, |
|||
'no-return-assign': [2, 'except-parens'], |
|||
'no-self-assign': 2, |
|||
'no-self-compare': 2, |
|||
'no-sequences': 2, |
|||
'no-shadow-restricted-names': 2, |
|||
'no-spaced-func': 2, |
|||
'no-sparse-arrays': 2, |
|||
'no-this-before-super': 2, |
|||
'no-throw-literal': 2, |
|||
'no-trailing-spaces': 2, |
|||
'no-undef': 2, |
|||
'no-undef-init': 2, |
|||
'no-unexpected-multiline': 2, |
|||
'no-unmodified-loop-condition': 2, |
|||
'no-unneeded-ternary': [2, { |
|||
'defaultAssignment': false |
|||
}], |
|||
'no-unreachable': 2, |
|||
'no-unsafe-finally': 2, |
|||
'no-unused-vars': [2, { |
|||
'vars': 'all', |
|||
'args': 'none' |
|||
}], |
|||
'no-useless-call': 2, |
|||
'no-useless-computed-key': 2, |
|||
'no-useless-constructor': 2, |
|||
'no-useless-escape': 0, |
|||
'no-whitespace-before-property': 2, |
|||
'no-with': 2, |
|||
'one-var': [2, { |
|||
'initialized': 'never' |
|||
}], |
|||
'operator-linebreak': [2, 'after', { |
|||
'overrides': { |
|||
'?': 'before', |
|||
':': 'before' |
|||
} |
|||
}], |
|||
'padded-blocks': [2, 'never'], |
|||
'quotes': [2, 'single', { |
|||
'avoidEscape': true, |
|||
'allowTemplateLiterals': true |
|||
}], |
|||
'semi': [2, 'never'], |
|||
'semi-spacing': [2, { |
|||
'before': false, |
|||
'after': true |
|||
}], |
|||
'space-before-blocks': [2, 'always'], |
|||
'space-before-function-paren': [2, 'never'], |
|||
'space-in-parens': [2, 'never'], |
|||
'space-infix-ops': 2, |
|||
'space-unary-ops': [2, { |
|||
'words': true, |
|||
'nonwords': false |
|||
}], |
|||
'spaced-comment': [2, 'always', { |
|||
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] |
|||
}], |
|||
'template-curly-spacing': [2, 'never'], |
|||
'use-isnan': 2, |
|||
'valid-typeof': 2, |
|||
'wrap-iife': [2, 'any'], |
|||
'yield-star-spacing': [2, 'both'], |
|||
'yoda': [2, 'never'], |
|||
'prefer-const': 2, |
|||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, |
|||
'object-curly-spacing': [2, 'always', { |
|||
objectsInObjects: false |
|||
}], |
|||
'array-bracket-spacing': [2, 'never'] |
|||
} |
|||
} |
@ -0,0 +1,116 @@ |
|||
# Logs |
|||
logs |
|||
*.log |
|||
npm-debug.log* |
|||
yarn-debug.log* |
|||
yarn-error.log* |
|||
lerna-debug.log* |
|||
|
|||
# Diagnostic reports (https://nodejs.org/api/report.html) |
|||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json |
|||
|
|||
# Runtime data |
|||
pids |
|||
*.pid |
|||
*.seed |
|||
*.pid.lock |
|||
|
|||
# Directory for instrumented libs generated by jscoverage/JSCover |
|||
lib-cov |
|||
|
|||
# Coverage directory used by tools like istanbul |
|||
coverage |
|||
*.lcov |
|||
|
|||
# nyc test coverage |
|||
.nyc_output |
|||
|
|||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) |
|||
.grunt |
|||
|
|||
# Bower dependency directory (https://bower.io/) |
|||
bower_components |
|||
|
|||
# node-waf configuration |
|||
.lock-wscript |
|||
|
|||
# Compiled binary addons (https://nodejs.org/api/addons.html) |
|||
build/Release |
|||
|
|||
# Dependency directories |
|||
node_modules/ |
|||
jspm_packages/ |
|||
|
|||
# Snowpack dependency directory (https://snowpack.dev/) |
|||
web_modules/ |
|||
|
|||
# TypeScript cache |
|||
*.tsbuildinfo |
|||
|
|||
# Optional npm cache directory |
|||
.npm |
|||
|
|||
# Optional eslint cache |
|||
.eslintcache |
|||
|
|||
# Microbundle cache |
|||
.rpt2_cache/ |
|||
.rts2_cache_cjs/ |
|||
.rts2_cache_es/ |
|||
.rts2_cache_umd/ |
|||
|
|||
# Optional REPL history |
|||
.node_repl_history |
|||
|
|||
# Output of 'npm pack' |
|||
*.tgz |
|||
|
|||
# Yarn Integrity file |
|||
.yarn-integrity |
|||
|
|||
# dotenv environment variables file |
|||
.env |
|||
.env.test |
|||
|
|||
# parcel-bundler cache (https://parceljs.org/) |
|||
.cache |
|||
.parcel-cache |
|||
|
|||
# Next.js build output |
|||
.next |
|||
out |
|||
|
|||
# Nuxt.js build / generate output |
|||
.nuxt |
|||
dist |
|||
|
|||
# Gatsby files |
|||
.cache/ |
|||
# Comment in the public line in if your project uses Gatsby and not Next.js |
|||
# https://nextjs.org/blog/next-9-1#public-directory-support |
|||
# public |
|||
|
|||
# vuepress build output |
|||
.vuepress/dist |
|||
|
|||
# Serverless directories |
|||
.serverless/ |
|||
|
|||
# FuseBox cache |
|||
.fusebox/ |
|||
|
|||
# DynamoDB Local files |
|||
.dynamodb/ |
|||
|
|||
# TernJS port file |
|||
.tern-port |
|||
|
|||
# Stores VSCode versions used for testing VSCode extensions |
|||
.vscode-test |
|||
|
|||
# yarn v2 |
|||
|
|||
.yarn/cache |
|||
.yarn/unplugged |
|||
.yarn/build-state.yml |
|||
.pnp.* |
@ -0,0 +1 @@ |
|||
registry=https://registry.npm.taobao.org/ |
@ -0,0 +1,5 @@ |
|||
language: node_js |
|||
node_js: 10 |
|||
script: npm run test |
|||
notifications: |
|||
email: false |
@ -0,0 +1,21 @@ |
|||
MIT License |
|||
|
|||
Copyright (c) 2017-present PanJiaChen |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in all |
|||
copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|||
SOFTWARE. |
@ -0,0 +1,126 @@ |
|||
|
|||
## websocket: |
|||
|
|||
import { sendWebsocket, closeWebsocket } from '@/utils/websocket' |
|||
|
|||
beforeDestroy () { |
|||
// 页面销毁时关闭ws。因为有可能ws连接接收数据尚未完成,用户就跳转了页面 |
|||
// 在需要主动关闭ws的地方都可以调用该方法 |
|||
closeWebsocket() |
|||
}, |
|||
// ws连接成功,后台返回的ws数据,组件要拿数据渲染页面等操作 |
|||
wsMessage (data) { |
|||
const dataJson = data |
|||
console.log(dataJson) |
|||
// 这里写拿到数据后的业务代码 |
|||
}, |
|||
// ws连接失败,组件要执行的代码 |
|||
wsError () { |
|||
// 比如取消页面的loading |
|||
}, |
|||
requstWs () { |
|||
// 防止用户多次连续点击发起请求,所以要先关闭上次的ws请求。 |
|||
closeWebsocket() |
|||
// 跟后端协商,需要什么参数数据给后台 |
|||
const obj = { |
|||
monitorUrl: 'xxxxxxxxxxxxx', |
|||
userName: 'xxxxxxxxxx' |
|||
} |
|||
// 发起ws请求 |
|||
sendWebsocket('ws://test.ws.com', obj, this.wsMessage, this.wsError) |
|||
} |
|||
|
|||
## 组件: |
|||
[主列表:tablePagination] |
|||
currenButtonData 主列表按钮 |
|||
tableData 主列表数据 |
|||
tableLoading 主列表loading |
|||
tableColumns 主列表表头 |
|||
totalCount 主列表数据总条数 |
|||
multipleSelection 主列表选择行数据 |
|||
MaxResultCount 主列表当前页最大条数 |
|||
topbutton 主列表按钮方法 tablePagination ==> TableHeaderMixins.js |
|||
inlineDialog 主列表抽屉展现 tablePagination ==> currenTable |
|||
sortChange 主列表排序 tablePagination ==> currenTable |
|||
alertoldSkipCount 主列表-分页-当前页条数 |
|||
alterResultCount 主列表-分页-每页最大页数 |
|||
handleSelectionChange 主列表-选择-行数据方法 tablePagination ==> currenTable |
|||
<----20230207添加 begin----> |
|||
buttonOperationClick_left 主列表-操作列按钮点击事件 |
|||
currentPageProps 主列表-当前页码值 |
|||
使用的是@/mixins/TableMixins的oldSkipCount值 |
|||
quicklySearchOption 主表查询-快速搜索数据配置 ==> 通用配置在@/utils/quicklySearchOption/index |
|||
quicklySearchClick 主表查询-快速搜索按钮点击事件(回车事件通用) |
|||
quicklySearchClear 主表查询-快速搜索清除点击事件 |
|||
<----20230207添加 end----> |
|||
<----20230215添加 [全面搜索相关配置] begin----> |
|||
:primarySearchOption 普通查询表单配置项 |
|||
(@utils/primarySearchOption/index.js) |
|||
:primarySearchButton 普通查询表单自定义按钮 |
|||
:showMoreSearch 是否显示高级筛选(默认true) |
|||
:tableColumns 高级筛选数据配置(tableColumns.js) |
|||
@overallSearchFormClick 全面搜索中所有按钮的点击事件汇总,包括普通和高级 |
|||
:httpOverallSearchData 全面筛选组件中当前数据的筛选项 |
|||
(参数目的:使回显与当前接口筛选项同步) |
|||
<----20230215添加 end----> |
|||
<----20230321添加 [字段设置] begin----> |
|||
rowDrop 主表字段设置事件(排序及显隐) |
|||
<----20230321添加 end----> |
|||
|
|||
[普通搜索:searchPrimaryComponent] |
|||
:primarySearchOption 查询表单配置项 |
|||
(@utils/primarySearchOption/index.js) |
|||
具体配置方法见上述文件的示例配置:primarySearchOptionExample |
|||
:primarySearchButton 查询表单自定义按钮(业务线页面内定义) |
|||
@primarySearchButtonClick 普通搜索自定义按钮事件(与primarySearchButton共同设置) |
|||
@primarySearchBaseHandle 普通查询基础按钮点击事件 |
|||
|
|||
|
|||
|
|||
[全面筛选:searchOverall] |
|||
:showSearchOverall 显示全面筛选组件 |
|||
@getShowSearchOverall 全面筛选组件内部显示/隐藏更改触发, |
|||
同步当前业务showSearchOverall与筛选内部是否显示 |
|||
:primarySearchOption 查询表单配置项 |
|||
(@utils/primarySearchOption/index.js) |
|||
:primarySearchButton 其他普通搜索按钮位置配置 |
|||
@overallSearchFormClick 所有按钮操作 |
|||
(包含primarySearchButton设置的按钮) |
|||
:showMoreSearch 是否显示高级筛选(默认true) |
|||
:httpOverallSearchData 全面筛选组件中当前数据的筛选项 |
|||
(参数目的:使回显与当前接口筛选项同步),格式: |
|||
{ |
|||
<!-- 普通数据 --> |
|||
"params": {"code": "12","status": 1}, |
|||
<!-- 高级数据 --> |
|||
"moreList": { |
|||
"filters": [ |
|||
{"logic": "And","column": "abcClass","action": "==","value": "A"}, |
|||
{"logic": "And","column": "Name","action": "Like","value": "A45415"}, |
|||
] |
|||
} |
|||
} |
|||
|
|||
新增编辑:《newAndEdiDialog》 |
|||
loading 抽屉loading |
|||
active 步骤控制 |
|||
pageStatus 结合active控制返回结果 |
|||
|
|||
[字段设置:rowDrop] |
|||
@radio="rowDrop" 数据更新方法 |
|||
:tableColumns="tableColumns" 表头数据 |
|||
:visible="visible" 是否显示 |
|||
@closeRowDrop="closeRowDrop" 关闭方法 |
|||
|
|||
[表单组件补充:currenForm] |
|||
validType type仅等于input时:实时keyUp校验,类型如下: |
|||
1、 number:正整数, |
|||
2、 pointNumber:数字+带小数点(只能输入一个小数点, 小数点后方保留位数见<pointNumberFixed>), |
|||
3、 numberLetter: 数字+字母, |
|||
4、 letter:纯字母, |
|||
5、 letterCn:字母+中文 |
|||
6、 numberLetterBar:字母+中文+横杠(-) |
|||
pointNumberFixed 组合上方validType值仅等于pointNumber时: |
|||
小数点后方保留位数,如不填写默认为100位 |
|||
<validType>+<pointNumberFixed>示例: |
|||
{ type:"input", label:"金额", prop:"money", validType:'pointNumber',pointNumberFixed:2}, |
@ -0,0 +1,14 @@ |
|||
module.exports = { |
|||
presets: [ |
|||
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
|
|||
'@vue/cli-plugin-babel/preset' |
|||
], |
|||
'env': { |
|||
'development': { |
|||
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
|
|||
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
|
|||
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
|
|||
'plugins': ['dynamic-import-node'] |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,35 @@ |
|||
const { run } = require('runjs') |
|||
const chalk = require('chalk') |
|||
const config = require('../vue.config.js') |
|||
const rawArgv = process.argv.slice(2) |
|||
const args = rawArgv.join(' ') |
|||
|
|||
if (process.env.npm_config_preview || rawArgv.includes('--preview')) { |
|||
const report = rawArgv.includes('--report') |
|||
|
|||
run(`vue-cli-service build ${args}`) |
|||
|
|||
const port = 9526 |
|||
const publicPath = config.publicPath |
|||
|
|||
var connect = require('connect') |
|||
var serveStatic = require('serve-static') |
|||
const app = connect() |
|||
|
|||
app.use( |
|||
publicPath, |
|||
serveStatic('./dist', { |
|||
index: ['index.html', '/'] |
|||
}) |
|||
) |
|||
|
|||
app.listen(port, function () { |
|||
console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) |
|||
if (report) { |
|||
console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) |
|||
} |
|||
|
|||
}) |
|||
} else { |
|||
run(`vue-cli-service build ${args}`) |
|||
} |
@ -0,0 +1,24 @@ |
|||
module.exports = { |
|||
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], |
|||
transform: { |
|||
'^.+\\.vue$': 'vue-jest', |
|||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': |
|||
'jest-transform-stub', |
|||
'^.+\\.jsx?$': 'babel-jest' |
|||
}, |
|||
moduleNameMapper: { |
|||
'^@/(.*)$': '<rootDir>/src/$1' |
|||
}, |
|||
snapshotSerializers: ['jest-serializer-vue'], |
|||
testMatch: [ |
|||
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' |
|||
], |
|||
collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], |
|||
coverageDirectory: '<rootDir>/tests/unit/coverage', |
|||
// 'collectCoverage': true,
|
|||
'coverageReporters': [ |
|||
'lcov', |
|||
'text-summary' |
|||
], |
|||
testURL: 'http://localhost/' |
|||
} |
@ -0,0 +1,9 @@ |
|||
{ |
|||
"compilerOptions": { |
|||
"baseUrl": "./", |
|||
"paths": { |
|||
"@/*": ["src/*"] |
|||
} |
|||
}, |
|||
"exclude": ["node_modules", "dist"] |
|||
} |
@ -0,0 +1,123 @@ |
|||
{ |
|||
"name": "vue-element-admin", |
|||
"version": "4.4.1", |
|||
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features", |
|||
"author": "Pan <panfree23@gmail.com>", |
|||
"scripts": { |
|||
"dev": "vue-cli-service serve", |
|||
"lint": "eslint --ext .js,.vue src", |
|||
"build": "vue-cli-service build", |
|||
"build:stage": "vue-cli-service build --mode staging", |
|||
"preview": "node build/index.js --preview", |
|||
"new": "plop", |
|||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml", |
|||
"test:unit": "jest --clearCache && vue-cli-service test:unit", |
|||
"test:ci": "npm run lint && npm run test:unit" |
|||
}, |
|||
"dependencies": { |
|||
"af-table-column": "^1.0.3", |
|||
"axios": "0.18.1", |
|||
"clipboard": "2.0.4", |
|||
"codemirror": "5.45.0", |
|||
"core-js": "3.6.5", |
|||
"driver.js": "0.9.5", |
|||
"dropzone": "5.5.1", |
|||
"echarts": "4.2.1", |
|||
"element-ui": "^2.15.13", |
|||
"file-saver": "2.0.1", |
|||
"fuse.js": "3.4.4", |
|||
"js-cookie": "2.2.0", |
|||
"jsonlint": "1.6.3", |
|||
"jszip": "3.2.1", |
|||
"lodash": "^4.17.21", |
|||
"moment": "^2.29.1", |
|||
"normalize.css": "7.0.0", |
|||
"nprogress": "0.2.0", |
|||
"oidc-client": "^1.11.5", |
|||
"path-to-regexp": "2.4.0", |
|||
"qs": "^6.10.3", |
|||
"screenfull": "4.2.0", |
|||
"script-loader": "0.7.2", |
|||
"sortable.js": "^0.3.0", |
|||
"sortablejs": "^1.8.4", |
|||
"tui-editor": "1.3.3", |
|||
"umy-ui": "^1.1.6", |
|||
"v-fit-columns": "^0.2.0", |
|||
"vue": "2.6.10", |
|||
"vue-count-to": "1.0.13", |
|||
"vue-grid-layout": "^2.4.0", |
|||
"vue-i18n": "^8.28.2", |
|||
"vue-pdf": "^4.3.0", |
|||
"vue-router": "3.0.2", |
|||
"vue-splitpane": "1.0.4", |
|||
"vuedraggable": "2.20.0", |
|||
"vuex": "3.1.0", |
|||
"xlsx": "0.14.1" |
|||
}, |
|||
"devDependencies": { |
|||
"@vue/cli-plugin-babel": "4.4.4", |
|||
"@vue/cli-plugin-eslint": "4.4.4", |
|||
"@vue/cli-plugin-unit-jest": "4.4.4", |
|||
"@vue/cli-service": "4.4.4", |
|||
"@vue/test-utils": "1.0.0-beta.29", |
|||
"autoprefixer": "9.5.1", |
|||
"babel-eslint": "10.1.0", |
|||
"babel-jest": "23.6.0", |
|||
"babel-plugin-component": "^1.1.1", |
|||
"babel-plugin-dynamic-import-node": "2.3.3", |
|||
"chalk": "2.4.2", |
|||
"chokidar": "2.1.5", |
|||
"connect": "3.6.6", |
|||
"eslint": "6.7.2", |
|||
"eslint-plugin-vue": "6.2.2", |
|||
"html-webpack-plugin": "3.2.0", |
|||
"husky": "1.3.1", |
|||
"lint-staged": "8.1.5", |
|||
"mockjs": "1.0.1-beta3", |
|||
"plop": "2.3.0", |
|||
"runjs": "4.3.2", |
|||
"sass": "~1.26.5", |
|||
"sass-loader": "10.1.0", |
|||
"script-ext-html-webpack-plugin": "2.1.3", |
|||
"serve-static": "1.13.2", |
|||
"svg-sprite-loader": "4.1.3", |
|||
"svgo": "1.2.0", |
|||
"vue-template-compiler": "2.6.10" |
|||
}, |
|||
"browserslist": [ |
|||
"> 1%", |
|||
"last 2 versions" |
|||
], |
|||
"bugs": { |
|||
"url": "https://github.com/PanJiaChen/vue-element-admin/issues" |
|||
}, |
|||
"engines": { |
|||
"node": ">=8.9", |
|||
"npm": ">= 3.0.0" |
|||
}, |
|||
"keywords": [ |
|||
"vue", |
|||
"admin", |
|||
"dashboard", |
|||
"element-ui", |
|||
"boilerplate", |
|||
"admin-template", |
|||
"management-system" |
|||
], |
|||
"license": "MIT", |
|||
"lint-staged": { |
|||
"src/**/*.{js,vue}": [ |
|||
"eslint --fix", |
|||
"git add" |
|||
] |
|||
}, |
|||
"husky": { |
|||
"hooks": { |
|||
"pre-commit": "lint-staged" |
|||
} |
|||
}, |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git" |
|||
} |
|||
} |
@ -0,0 +1,26 @@ |
|||
{{#if template}} |
|||
<template> |
|||
<div /> |
|||
</template> |
|||
{{/if}} |
|||
|
|||
{{#if script}} |
|||
<script> |
|||
export default { |
|||
name: '{{ properCase name }}', |
|||
props: {}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
created() {}, |
|||
mounted() {}, |
|||
methods: {} |
|||
} |
|||
</script> |
|||
{{/if}} |
|||
|
|||
{{#if style}} |
|||
<style lang="scss" scoped> |
|||
|
|||
</style> |
|||
{{/if}} |
@ -0,0 +1,55 @@ |
|||
const { notEmpty } = require('../utils.js') |
|||
|
|||
module.exports = { |
|||
description: 'generate vue component', |
|||
prompts: [{ |
|||
type: 'input', |
|||
name: 'name', |
|||
message: 'component name please', |
|||
validate: notEmpty('name') |
|||
}, |
|||
{ |
|||
type: 'checkbox', |
|||
name: 'blocks', |
|||
message: 'Blocks:', |
|||
choices: [{ |
|||
name: '<template>', |
|||
value: 'template', |
|||
checked: true |
|||
}, |
|||
{ |
|||
name: '<script>', |
|||
value: 'script', |
|||
checked: true |
|||
}, |
|||
{ |
|||
name: 'style', |
|||
value: 'style', |
|||
checked: true |
|||
} |
|||
], |
|||
validate(value) { |
|||
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) { |
|||
return 'Components require at least a <script> or <template> tag.' |
|||
} |
|||
return true |
|||
} |
|||
} |
|||
], |
|||
actions: data => { |
|||
const name = '{{properCase name}}' |
|||
const actions = [{ |
|||
type: 'add', |
|||
path: `src/components/${name}/index.vue`, |
|||
templateFile: 'plop-templates/component/index.hbs', |
|||
data: { |
|||
name: name, |
|||
template: data.blocks.includes('template'), |
|||
script: data.blocks.includes('script'), |
|||
style: data.blocks.includes('style') |
|||
} |
|||
}] |
|||
|
|||
return actions |
|||
} |
|||
} |
@ -0,0 +1,16 @@ |
|||
{{#if state}} |
|||
const state = {} |
|||
{{/if}} |
|||
|
|||
{{#if mutations}} |
|||
const mutations = {} |
|||
{{/if}} |
|||
|
|||
{{#if actions}} |
|||
const actions = {} |
|||
{{/if}} |
|||
|
|||
export default { |
|||
namespaced: true, |
|||
{{options}} |
|||
} |
@ -0,0 +1,62 @@ |
|||
const { notEmpty } = require('../utils.js') |
|||
|
|||
module.exports = { |
|||
description: 'generate store', |
|||
prompts: [{ |
|||
type: 'input', |
|||
name: 'name', |
|||
message: 'store name please', |
|||
validate: notEmpty('name') |
|||
}, |
|||
{ |
|||
type: 'checkbox', |
|||
name: 'blocks', |
|||
message: 'Blocks:', |
|||
choices: [{ |
|||
name: 'state', |
|||
value: 'state', |
|||
checked: true |
|||
}, |
|||
{ |
|||
name: 'mutations', |
|||
value: 'mutations', |
|||
checked: true |
|||
}, |
|||
{ |
|||
name: 'actions', |
|||
value: 'actions', |
|||
checked: true |
|||
} |
|||
], |
|||
validate(value) { |
|||
if (!value.includes('state') || !value.includes('mutations')) { |
|||
return 'store require at least state and mutations' |
|||
} |
|||
return true |
|||
} |
|||
} |
|||
], |
|||
actions(data) { |
|||
const name = '{{name}}' |
|||
const { blocks } = data |
|||
const options = ['state', 'mutations'] |
|||
const joinFlag = `,
|
|||
` |
|||
if (blocks.length === 3) { |
|||
options.push('actions') |
|||
} |
|||
|
|||
const actions = [{ |
|||
type: 'add', |
|||
path: `src/store/modules/${name}.js`, |
|||
templateFile: 'plop-templates/store/index.hbs', |
|||
data: { |
|||
options: options.join(joinFlag), |
|||
state: blocks.includes('state'), |
|||
mutations: blocks.includes('mutations'), |
|||
actions: blocks.includes('actions') |
|||
} |
|||
}] |
|||
return actions |
|||
} |
|||
} |
@ -0,0 +1,2 @@ |
|||
exports.notEmpty = name => v => |
|||
!v || v.trim() === '' ? `${name} is required` : true |
@ -0,0 +1,26 @@ |
|||
{{#if template}} |
|||
<template> |
|||
<div /> |
|||
</template> |
|||
{{/if}} |
|||
|
|||
{{#if script}} |
|||
<script> |
|||
export default { |
|||
name: '{{ properCase name }}', |
|||
props: {}, |
|||
data() { |
|||
return {} |
|||
}, |
|||
created() {}, |
|||
mounted() {}, |
|||
methods: {} |
|||
} |
|||
</script> |
|||
{{/if}} |
|||
|
|||
{{#if style}} |
|||
<style lang="scss" scoped> |
|||
|
|||
</style> |
|||
{{/if}} |
@ -0,0 +1,55 @@ |
|||
const { notEmpty } = require('../utils.js') |
|||
|
|||
module.exports = { |
|||
description: 'generate a view', |
|||
prompts: [{ |
|||
type: 'input', |
|||
name: 'name', |
|||
message: 'view name please', |
|||
validate: notEmpty('name') |
|||
}, |
|||
{ |
|||
type: 'checkbox', |
|||
name: 'blocks', |
|||
message: 'Blocks:', |
|||
choices: [{ |
|||
name: '<template>', |
|||
value: 'template', |
|||
checked: true |
|||
}, |
|||
{ |
|||
name: '<script>', |
|||
value: 'script', |
|||
checked: true |
|||
}, |
|||
{ |
|||
name: 'style', |
|||
value: 'style', |
|||
checked: true |
|||
} |
|||
], |
|||
validate(value) { |
|||
if (value.indexOf('script') === -1 && value.indexOf('template') === -1) { |
|||
return 'View require at least a <script> or <template> tag.' |
|||
} |
|||
return true |
|||
} |
|||
} |
|||
], |
|||
actions: data => { |
|||
const name = '{{name}}' |
|||
const actions = [{ |
|||
type: 'add', |
|||
path: `src/views/${name}/index.vue`, |
|||
templateFile: 'plop-templates/view/index.hbs', |
|||
data: { |
|||
name: name, |
|||
template: data.blocks.includes('template'), |
|||
script: data.blocks.includes('script'), |
|||
style: data.blocks.includes('style') |
|||
} |
|||
}] |
|||
|
|||
return actions |
|||
} |
|||
} |
@ -0,0 +1,9 @@ |
|||
const viewGenerator = require('./plop-templates/view/prompt') |
|||
const componentGenerator = require('./plop-templates/component/prompt') |
|||
const storeGenerator = require('./plop-templates/store/prompt.js') |
|||
|
|||
module.exports = function(plop) { |
|||
plop.setGenerator('view', viewGenerator) |
|||
plop.setGenerator('component', componentGenerator) |
|||
plop.setGenerator('store', storeGenerator) |
|||
} |
@ -0,0 +1,5 @@ |
|||
module.exports = { |
|||
plugins: { |
|||
autoprefixer: {} |
|||
} |
|||
} |
After Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,26 @@ |
|||
// dev_win
|
|||
window.SITE_CONFIG['baseApi'] = 'http://dev.ccwin-in.com:60024' |
|||
window.SITE_CONFIG['authApi'] = 'http://dev.ccwin-in.com:60020' |
|||
// window.SITE_CONFIG['baseApi'] = 'http://192.168.0.190:60078'//http://dev.ccwin-in.com:60022
|
|||
// window.SITE_CONFIG['authApi'] = 'http://192.168.0.190:60065'//http://dev.ccwin-in.com:60020
|
|||
window.SITE_CONFIG['businessApi'] = 'http://dev.ccwin-in.com:10097' |
|||
//是否登录配置信息【loginName】
|
|||
window.SITE_CONFIG['isConfigLogin'] = false |
|||
//如果【isConfigLogin】为true则使用【loginName】登录
|
|||
window.SITE_CONFIG['configLoginName'] = 'admin' |
|||
// 默认登录密码(isConfigLogin为true或者链接参数存在loginName使用)
|
|||
window.SITE_CONFIG['configLoginPass'] = '1q2w3E*' |
|||
// 是否单页面(不显示菜单头部等部分)
|
|||
window.SITE_CONFIG['isSinglePage'] = false |
|||
// 项目配置
|
|||
window.SITE_CONFIG['appClientId'] = 'Z_App' |
|||
// 项目配置内部名称
|
|||
window.SITE_CONFIG['appClientScope'] = 'Inventory' |
|||
// 浏览器名称
|
|||
window.SITE_CONFIG['browserTitle'] = 'Inventory-QAD&WMS' |
|||
// 单点登录使用数据
|
|||
window.SITE_CONFIG['oidcLogin_url'] = 'http://dev.ccwin-in.com:60065', |
|||
window.SITE_CONFIG['oidcLogin_clientId'] = 'InterfaceDash_App' |
|||
window.SITE_CONFIG['oidcLogin_scopes'] = 'offline_access Z profile' |
|||
// 隐藏的页面
|
|||
window.SITE_CONFIG['menuHiddenConfig'] = [] |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 303 KiB |
@ -0,0 +1,30 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
|
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
|||
<meta name="renderer" content="webkit"> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> |
|||
<!-- <meta http-equiv="pragram" content="no-cache"> |
|||
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate"> --> |
|||
<link rel="icon" href="<%= BASE_URL %>WMS.svg"> |
|||
<script> |
|||
// 初始化 |
|||
window.SITE_CONFIG = {}; |
|||
window.SITE_CONFIG['base'] = '' |
|||
window.SITE_CONFIG['user'] = '' |
|||
window.SITE_CONFIG['print'] = '' |
|||
window.SITE_CONFIG['warehouseCode'] = '' |
|||
window.SITE_CONFIG['company'] = '' |
|||
</script> |
|||
<title><%= webpackConfig.name %></title> |
|||
<script src="./config.js"></script> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"></div> |
|||
<!-- built files will be auto injected --> |
|||
</body> |
|||
|
|||
</html> |
@ -0,0 +1,3 @@ |
|||
{ |
|||
"version": "1.0.45" |
|||
} |
@ -0,0 +1,98 @@ |
|||
<template> |
|||
<div id="app"> |
|||
<router-view /> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'App' |
|||
} |
|||
localStorage.setItem('baseApi',window.SITE_CONFIG['baseApi']) |
|||
localStorage.setItem('authApi',window.SITE_CONFIG['authApi']) |
|||
// localStorage.setItem('userApi',window.SITE_CONFIG['userApi']) |
|||
localStorage.setItem('businessApi',window.SITE_CONFIG['businessApi']) |
|||
localStorage.setItem('isConfigLogin',window.SITE_CONFIG['isConfigLogin']) |
|||
localStorage.setItem('configLoginName',window.SITE_CONFIG['configLoginName']) |
|||
localStorage.setItem('configLoginPass',window.SITE_CONFIG['configLoginPass']) |
|||
localStorage.setItem('isSinglePage',window.SITE_CONFIG['isSinglePage']) |
|||
localStorage.setItem('appClientId',window.SITE_CONFIG['appClientId']) |
|||
localStorage.setItem('appClientScope',window.SITE_CONFIG['appClientScope']) |
|||
localStorage.setItem('browserTitle',window.SITE_CONFIG['browserTitle']) |
|||
// 单点登录使用数据 |
|||
localStorage.setItem('oidcLogin_url',window.SITE_CONFIG['oidcLogin_url']) |
|||
localStorage.setItem('oidcLogin_clientId',window.SITE_CONFIG['oidcLogin_clientId']) |
|||
localStorage.setItem('oidcLogin_scopes',window.SITE_CONFIG['oidcLogin_scopes']) |
|||
// 隐藏菜单 |
|||
localStorage.setItem('menuHiddenConfig',window.SITE_CONFIG['menuHiddenConfig']) |
|||
|
|||
// localStorage.setItem('isAutoLogin',window.SITE_CONFIG['isAutoLogin']) |
|||
// localStorage.setItem('userNameOrEmailAddress',window.SITE_CONFIG['userNameOrEmailAddress']) |
|||
// localStorage.setItem('client_secret',window.SITE_CONFIG['client_secret']) |
|||
|
|||
// 获取浏览器语言 |
|||
const language_brow = (navigator.language || navigator.browserLanguage) |
|||
console.log(21,language_brow) |
|||
if(language_brow.indexOf('zh') >= 0){ |
|||
localStorage.setItem('browserLanguage','zh-Hans') |
|||
}else{ |
|||
localStorage.setItem('browserLanguage','en') |
|||
} |
|||
|
|||
</script> |
|||
<style lang="scss"> |
|||
/* 滚动条 */ |
|||
::-webkit-scrollbar { |
|||
width: 7px; |
|||
height: 7px; |
|||
background: transparent; |
|||
border-radius: 5px; |
|||
} |
|||
|
|||
/* 滚动条两端按钮 */ |
|||
::-webkit-scrollbar-button { |
|||
width: 0; |
|||
height: 0; |
|||
} |
|||
|
|||
/* 外层轨道 */ |
|||
::-webkit-scrollbar-track { |
|||
border-radius: 5px; |
|||
} |
|||
|
|||
/* 内层轨道,它会覆盖外层轨道的样式 */ |
|||
::-webkit-scrollbar-track-piece { |
|||
// background-color: #f3f3f3; |
|||
height: 7px; |
|||
width: 7px; |
|||
margin: 0 -2px 0; |
|||
} |
|||
|
|||
/* 滑块 */ |
|||
::-webkit-scrollbar-thumb { |
|||
background-color: #ccc; |
|||
min-height: 60px; |
|||
min-width: 60px; |
|||
border-radius: 5px; |
|||
} |
|||
|
|||
/* 纵向滑块悬浮 */ |
|||
::-webkit-scrollbar-thumb:vertical:hover { |
|||
background-color: #ccc; |
|||
} |
|||
|
|||
/* 横向滑块悬浮 */ |
|||
::-webkit-scrollbar-thumb:horizontal:hover { |
|||
background-color: #ccc; |
|||
} |
|||
/*横竖滚动条交角图案*/ |
|||
// ::-webkit-resizer { |
|||
// /*background-image: url(/public/img/resizer-inactive.png);*/ |
|||
// background-repeat: no-repeat; |
|||
// background-position: bottom right; |
|||
// } |
|||
/*横竖滚动条交角*/ |
|||
// ::-webkit-scrollbar-corner { |
|||
// background-color: #f3f3f3; |
|||
// } |
|||
</style> |
@ -0,0 +1,177 @@ |
|||
import request from '@/utils/request' |
|||
import store from '@/store' |
|||
// let baseURL = process.env.VUE_APP_BASE_API + '/'
|
|||
let baseAPI = localStorage.getItem('baseApi') + '/' |
|||
let baseURL = localStorage.getItem('baseApi') + '/api/' |
|||
|
|||
//新建
|
|||
export function postCreate(data, url) { |
|||
if (Object.keys(data).includes('company')) { |
|||
data.company = localStorage.getItem('company') |
|||
} |
|||
if (Object.keys(data).includes('warehouseCode')) { |
|||
data.warehouseCode = localStorage.getItem('warehouseCode') |
|||
} |
|||
if(Object.keys(data).includes('worker')) { |
|||
data.worker = store.getters.currentUserInfo.userName |
|||
} |
|||
return request({ |
|||
url: baseURL + url, |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
|||
//编辑
|
|||
export function postUpdate(data, id, url) { |
|||
return request({ |
|||
// url: baseURL + url + '/' + id,
|
|||
url: baseURL + url, |
|||
method: 'put', |
|||
data, |
|||
params:{id:id} |
|||
}) |
|||
} |
|||
//删除
|
|||
export function postDelete(id, url) { |
|||
return request({ |
|||
// url: baseURL + url + '/' + id,
|
|||
url: baseURL + url, |
|||
method: 'delete', |
|||
params:{id:id} |
|||
}) |
|||
} |
|||
//分页+筛选【列表】
|
|||
export function getPageList(data, url, includeDetails) { |
|||
let _url = includeDetails ? baseURL + url + '/get-list-page-by-filter?includeDetails='+ includeDetails : baseURL + url + '/get-list-page-by-filter' |
|||
return request({ |
|||
url: _url, |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
|||
//分页+筛选【明细列表】
|
|||
export function getPageListForDetail(data, url, includeDetails) { |
|||
return request({ |
|||
method:'post', |
|||
url: baseURL + url + '/get-list-page-by-filter?includeDetails='+Boolean(includeDetails), |
|||
data |
|||
}) |
|||
} |
|||
// 根据id获取主表信息
|
|||
export function getListDesById(url,id) { |
|||
return request({ |
|||
method:'get', |
|||
url: baseURL + url + '/' + id |
|||
}) |
|||
} |
|||
//导出-获取文件 blobName
|
|||
/** |
|||
* @param {*} data |
|||
* @param {*} url 地址 |
|||
* @param {*} special 是否为特殊,如果是特殊,则直接用url |
|||
* @returns |
|||
*/ |
|||
export function postExport(params,data, url, special) { |
|||
let _url = special ? baseURL + url : baseURL + url + '/export-to-excel' |
|||
return request({ |
|||
url: _url, |
|||
method: 'post', |
|||
data, |
|||
params:params, |
|||
responseType: 'blob' |
|||
}) |
|||
} |
|||
//导出(详情内)-获取文件 blobName
|
|||
/** |
|||
* @param {*} data |
|||
* @param {*} url 地址 |
|||
* @param {*} params |
|||
* @returns |
|||
*/ |
|||
export function postExportForDetail(data, url,params) { |
|||
return request({ |
|||
url: baseURL + url, |
|||
method: 'post', |
|||
data, |
|||
params: params, |
|||
responseType: 'blob' |
|||
}) |
|||
} |
|||
//导出-文件
|
|||
export function fileStorage(data) { |
|||
return request({ |
|||
url: baseURL + 'filestore/file', |
|||
method: 'get', |
|||
params: data, |
|||
}) |
|||
} |
|||
//导入 isSpecial 是否为特殊接口
|
|||
export function postImport(data, url,isSpecial) { |
|||
let _url = isSpecial ? url : url + '/import' |
|||
return request({ |
|||
url: baseURL + _url, |
|||
method: 'post', |
|||
headers: { |
|||
'Content-Type': 'multipart/form-data;' |
|||
}, |
|||
responseType: 'blob', |
|||
data |
|||
}) |
|||
} |
|||
//导入模板下载
|
|||
export function postImportDown(url) { |
|||
return request({ |
|||
url: baseURL + url + '/import-template', |
|||
method: 'post', |
|||
responseType: 'blob' |
|||
}) |
|||
} |
|||
//获取详情
|
|||
export function getDetailed(id, url) { |
|||
return request({ |
|||
url: baseURL + url + '/' + id, |
|||
method: 'get', |
|||
}) |
|||
} |
|||
//获取分页+筛选(只查询)
|
|||
export function getPage(data, url) { |
|||
return request({ |
|||
url: baseURL + url, |
|||
method: 'get', |
|||
params: data |
|||
}) |
|||
} |
|||
// 获取版本编号
|
|||
export function getVsersion() { |
|||
return request({ |
|||
url: window.SITE_CONFIG['versionUrl'] + `/version.json?t=${new Date().getTime()}`, |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
// fast-new
|
|||
//API-POST
|
|||
export function ApiTypePost(data, url) { |
|||
return request({ |
|||
url: baseAPI + url, |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
|||
//API-PUT
|
|||
export function ApiTypePut(data, id, url) { |
|||
return request({ |
|||
url: baseAPI + url, |
|||
method: 'put', |
|||
data, |
|||
params:{id:id} |
|||
}) |
|||
} |
|||
//API-DELETE
|
|||
export function ApiTypeDelete(id, url) { |
|||
return request({ |
|||
url: baseAPI + url, |
|||
method: 'delete', |
|||
params:{id:id} |
|||
}) |
|||
} |
@ -0,0 +1,207 @@ |
|||
import request from '@/utils/request' |
|||
let baseApi = localStorage.getItem('baseApi') + '/api' |
|||
let authUrl = localStorage.getItem('authApi') |
|||
let authApi = authUrl + '/api' |
|||
|
|||
export function logout() { |
|||
return request({ |
|||
url: authApi + '/account/logout', |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
|
|||
// faster-new
|
|||
// 登录
|
|||
export function login(data) { |
|||
return request({ |
|||
url: authUrl + '/CustAccount/login', |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
// 获取token
|
|||
export function token(data) { |
|||
return request({ |
|||
url: authApi + '/connect/token', |
|||
method: 'post', |
|||
headers: { |
|||
'Content-Type': 'application/x-www-form-urlencoded' |
|||
}, |
|||
data |
|||
}) |
|||
} |
|||
|
|||
// 通过token获取用户信息(单点登录)
|
|||
export function getUsersByToken(token) { |
|||
return request({ |
|||
url: authUrl + '/connect/userinfo', |
|||
method: 'get', |
|||
Token:token |
|||
}) |
|||
} |
|||
|
|||
// 通过用户名获取用户信息
|
|||
export function getUsersByUserName(name) { |
|||
return request({ |
|||
url: authApi + '/identity/users/by-username/'+name, |
|||
method: 'get', |
|||
}) |
|||
} |
|||
|
|||
// 获取表头zh转义数据
|
|||
export function getInterfaceBoard() { |
|||
return request({ |
|||
method:'get', |
|||
url: baseApi + '/abp/application-localization', |
|||
params:{ |
|||
CultureName:localStorage.getItem('browserLanguage'), |
|||
OnlyDynamics:false |
|||
} |
|||
// params:{IncludeLocalizationResources:true}
|
|||
}) |
|||
} |
|||
|
|||
// 获取菜单数据
|
|||
export function getDefinitionMenu(IncludeTypes) { |
|||
return request({ |
|||
method:'get', |
|||
url: baseApi + '/abp/application-configuration', |
|||
params:{IncludeLocalizationResources:true} |
|||
}) |
|||
} |
|||
|
|||
// 获取枚举数据/dto列类型等所有配置
|
|||
export async function getApiDefinition() { |
|||
return request({ |
|||
method:'get', |
|||
url: baseApi + '/abp/api-definition', |
|||
params:{IncludeTypes:true} |
|||
}) |
|||
} |
|||
|
|||
// *************权限Roles页面维护*************
|
|||
//获取列表
|
|||
export function getPageListRoles(data) { |
|||
return request({ |
|||
url: authApi + '/identity/roles', |
|||
// url: 'http://192.168.0.190:44330/Identity/Roles',
|
|||
method: 'get', |
|||
params: data |
|||
}) |
|||
} |
|||
|
|||
//获取权限模板
|
|||
export function getPermissionsRoles(data) { |
|||
return request({ |
|||
url: authApi +'/permission-management/permissions', |
|||
method: 'get', |
|||
params: data |
|||
}) |
|||
} |
|||
|
|||
// 创建角色
|
|||
export function postCreateRoles(data) { |
|||
return request({ |
|||
url: authApi + '/identity/roles', |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
//编辑角色
|
|||
export function postUpdateRoles(data, id) { |
|||
return request({ |
|||
url: authApi+'/identity/roles/' + id, |
|||
method: 'put', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
//删除角色
|
|||
export function postDeleteRoles(id) { |
|||
return request({ |
|||
url: authApi + '/identity/roles/' + id, |
|||
method: 'delete', |
|||
}) |
|||
} |
|||
|
|||
//保存权限模板
|
|||
export function savePermissionsRoles(URL, data) { |
|||
return request({ |
|||
url: authApi + URL, |
|||
method: 'put', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
// 更新权限
|
|||
export function updatePermissionsGranted(pname,pkey) { |
|||
return request({ |
|||
url: authApi + `/permissions/get-isGranted?name=demox&providerName=${pname}&providerKey=${pkey}`, |
|||
method: 'post', |
|||
}) |
|||
} |
|||
|
|||
// *************用户Users页面维护*************
|
|||
|
|||
//获取全部用户信息
|
|||
export function getPageListUsers(data) { |
|||
return request({ |
|||
url: authApi + '/identity/users', |
|||
method: 'get', |
|||
params: data |
|||
}) |
|||
} |
|||
|
|||
//新建用户
|
|||
export function postCreateUser(data) { |
|||
return request({ |
|||
url: authApi + '/identity/users', |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
//编辑用户
|
|||
export function postUpdateUser(data, id) { |
|||
return request({ |
|||
url: authApi + '/identity/users/' + id, |
|||
method: 'put', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
//删除用户
|
|||
export function postDeleteUser(id) { |
|||
return request({ |
|||
url: authApi + '/identity/users/' + id, |
|||
method: 'delete', |
|||
}) |
|||
} |
|||
|
|||
// 获取当前用户的角色
|
|||
export function usersroles() { |
|||
return request({ |
|||
url: authApi + '/identity/users/assignable-roles', |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
//获取当前角色
|
|||
export function getusersID(data) { |
|||
return request({ |
|||
url: authApi + '/identity/users/' + data + '/roles', |
|||
method: 'get' |
|||
}) |
|||
} |
|||
|
|||
//修改登录用户的密码-强密码规则
|
|||
export function postLoginUserInfo(data, id) { |
|||
return request({ |
|||
url: authApi + '/identity/users/change-password/' + id, |
|||
method: 'post', |
|||
data |
|||
}) |
|||
} |
@ -0,0 +1,49 @@ |
|||
import request from '@/utils/request' |
|||
// let baseURL = process.env.VUE_APP_BASE_API + '/'
|
|||
let baseURL = localStorage.getItem('base') + '/api/' |
|||
|
|||
//---------------------------通用---------------------------
|
|||
//任务流程——承接
|
|||
export function accept(url, data) { |
|||
return request({ |
|||
url: baseURL + url + '/accept/'+data.id, |
|||
method: 'post', |
|||
// params: data
|
|||
}) |
|||
} |
|||
|
|||
//任务流程——关闭
|
|||
export function close(url, data) { |
|||
return request({ |
|||
url: baseURL + url + '/close/'+data.id, |
|||
method: 'post', |
|||
// params: data
|
|||
}) |
|||
} |
|||
|
|||
//任务流程——取消
|
|||
export function cancel(url, data) { |
|||
return request({ |
|||
url: baseURL + url + '/cancel/'+data.id, |
|||
method: 'post', |
|||
// params: data
|
|||
}) |
|||
} |
|||
|
|||
//任务流程——取消承接 | 采购收货任务
|
|||
export function cancelAccept(url, data) { |
|||
return request({ |
|||
url: baseURL + url + '/cancel-accept/'+data.id, |
|||
method: 'post', |
|||
// params: data
|
|||
}) |
|||
} |
|||
|
|||
//任务流程——打开
|
|||
export function open(url, data) { |
|||
return request({ |
|||
url: baseURL + url + '/open/'+data.id, |
|||
method: 'post', |
|||
// params: data
|
|||
}) |
|||
} |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,84 @@ |
|||
<template> |
|||
<el-breadcrumb class="app-breadcrumb" separator="/"> |
|||
<transition-group name="breadcrumb"> |
|||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> |
|||
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span> |
|||
<a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> |
|||
</el-breadcrumb-item> |
|||
</transition-group> |
|||
</el-breadcrumb> |
|||
</template> |
|||
|
|||
<script> |
|||
import pathToRegexp from 'path-to-regexp' |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
levelList: null |
|||
} |
|||
}, |
|||
watch: { |
|||
$route(route) { |
|||
// if you go to the redirect page, do not update the breadcrumbs |
|||
if (route.path.startsWith('/redirect/')) { |
|||
return |
|||
} |
|||
this.getBreadcrumb() |
|||
} |
|||
}, |
|||
created() { |
|||
this.getBreadcrumb() |
|||
}, |
|||
methods: { |
|||
getBreadcrumb() { |
|||
// only show routes with meta.title |
|||
let matched = this.$route.matched.filter(item => item.meta && item.meta.title) |
|||
const first = matched[0] |
|||
|
|||
if (!this.isDashboard(first)) { |
|||
matched = [].concat(matched) |
|||
// matched = [{ path: '/dashboard', meta: { title: '系统首页' }}].concat(matched) |
|||
} |
|||
|
|||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) |
|||
}, |
|||
isDashboard(route) { |
|||
const name = route && route.name |
|||
if (!name) { |
|||
return false |
|||
} |
|||
return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase() |
|||
}, |
|||
pathCompile(path) { |
|||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561 |
|||
const { params } = this.$route |
|||
var toPath = pathToRegexp.compile(path) |
|||
return toPath(params) |
|||
}, |
|||
handleLink(item) { |
|||
const { redirect, path } = item |
|||
if (redirect) { |
|||
this.$router.push(redirect) |
|||
return |
|||
} |
|||
this.$router.push(this.pathCompile(path)) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import '../../styles/variables.scss'; |
|||
.app-breadcrumb.el-breadcrumb { |
|||
display: inline-block; |
|||
font-size: 14px; |
|||
line-height: $navHeight; |
|||
margin-left: 8px; |
|||
|
|||
.no-redirect { |
|||
color: #97a8be; |
|||
cursor: text; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,94 @@ |
|||
<template> |
|||
<div v-if="errorLogs.length>0"> |
|||
<el-badge |
|||
:is-dot="true" |
|||
style="line-height: 10px;" |
|||
@click.native="dialogTableVisible=true" |
|||
> |
|||
<el-button style="padding: 4px" size="small" type="danger"> |
|||
<svg-icon icon-class="svg_bug" style="font-size: 16px;"/> |
|||
</el-button> |
|||
</el-badge> |
|||
|
|||
<el-dialog |
|||
:visible.sync="dialogTableVisible" |
|||
width="80%" |
|||
append-to-body |
|||
:close-on-click-modal="true" |
|||
:show-close="true" |
|||
> |
|||
<div slot="title"> |
|||
<span style="padding-right: 10px;">Error Log</span> |
|||
<el-button |
|||
size="mini" |
|||
type="primary" |
|||
icon="el-icon-delete" |
|||
@click="clearAll" |
|||
style="float: right;margin-right: 30px;" |
|||
>清除全部</el-button> |
|||
</div> |
|||
<el-table :data="errorLogs" border> |
|||
<el-table-column label="Message"> |
|||
<template slot-scope="{row}"> |
|||
<div> |
|||
<span class="message-title">Msg:</span> |
|||
<el-tag type="danger"> |
|||
{{ row.err.message }} |
|||
</el-tag> |
|||
</div> |
|||
<br> |
|||
<div> |
|||
<span class="message-title" style="padding-right: 10px;">Info: </span> |
|||
<el-tag type="warning"> |
|||
{{ row.vm.$vnode.tag }} error in {{ row.info }} |
|||
</el-tag> |
|||
</div> |
|||
<br> |
|||
<div> |
|||
<span class="message-title" style="padding-right: 16px;">Url: </span> |
|||
<el-tag type="success"> |
|||
{{ row.url }} |
|||
</el-tag> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column label="Stack"> |
|||
<template slot-scope="scope"> |
|||
{{ scope.row.err.stack }} |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'ErrorLog', |
|||
data() { |
|||
return { |
|||
dialogTableVisible: false |
|||
} |
|||
}, |
|||
computed: { |
|||
errorLogs() { |
|||
return this.$store.getters.errorLogs |
|||
} |
|||
}, |
|||
methods: { |
|||
clearAll() { |
|||
this.dialogTableVisible = false |
|||
this.$store.dispatch('errorLog/clearErrorLog') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.message-title { |
|||
font-size: 16px; |
|||
color: #333; |
|||
font-weight: bold; |
|||
padding-right: 8px; |
|||
} |
|||
</style> |
@ -0,0 +1,44 @@ |
|||
<template> |
|||
<div style="padding: 0 15px;" @click="toggleClick"> |
|||
<svg |
|||
:class="{'is-active':isActive}" |
|||
class="hamburger" |
|||
viewBox="0 0 1024 1024" |
|||
xmlns="http://www.w3.org/2000/svg" |
|||
width="64" |
|||
height="64" |
|||
> |
|||
<path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" /> |
|||
</svg> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'Hamburger', |
|||
props: { |
|||
isActive: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
methods: { |
|||
toggleClick() { |
|||
this.$emit('toggleClick') |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.hamburger { |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
width: 20px; |
|||
height: 20px; |
|||
} |
|||
|
|||
.hamburger.is-active { |
|||
transform: rotate(180deg); |
|||
} |
|||
</style> |
@ -0,0 +1,190 @@ |
|||
<template> |
|||
<div :class="{ show: show }" class="header-search"> |
|||
<svg-icon |
|||
class-name="search-icon" |
|||
icon-class="svg_search" |
|||
@click.stop="click" |
|||
/> |
|||
<el-select |
|||
ref="headerSearchSelect" |
|||
v-model="search" |
|||
:remote-method="querySearch" |
|||
filterable |
|||
default-first-option |
|||
remote |
|||
placeholder="搜索导航栏" |
|||
class="header-search-select" |
|||
@change="change" |
|||
> |
|||
<el-option |
|||
v-for="item in options" |
|||
:key="item.path" |
|||
:value="item" |
|||
:label="item.title.join(' > ')" |
|||
/> |
|||
</el-select> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
// fuse is a lightweight fuzzy-search module |
|||
// make search results more in line with expectations |
|||
import Fuse from 'fuse.js' |
|||
import path from 'path' |
|||
|
|||
export default { |
|||
name: 'HeaderSearch', |
|||
data () { |
|||
return { |
|||
search: '', |
|||
options: [], |
|||
searchPool: [], |
|||
show: false, |
|||
fuse: undefined |
|||
} |
|||
}, |
|||
computed: { |
|||
routes () { |
|||
return this.$store.getters.permission_routes |
|||
} |
|||
}, |
|||
watch: { |
|||
routes () { |
|||
this.searchPool = this.generateRoutes(this.routes) |
|||
}, |
|||
searchPool (list) { |
|||
this.initFuse(list) |
|||
}, |
|||
show (value) { |
|||
if (value) { |
|||
document.body.addEventListener('click', this.close) |
|||
} else { |
|||
document.body.removeEventListener('click', this.close) |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.searchPool = this.generateRoutes(this.routes) |
|||
}, |
|||
methods: { |
|||
click () { |
|||
this.show = !this.show |
|||
if (this.show) { |
|||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus() |
|||
} |
|||
}, |
|||
close () { |
|||
this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur() |
|||
this.options = [] |
|||
this.show = false |
|||
}, |
|||
change (val) { |
|||
this.$router.push(val.path) |
|||
this.search = '' |
|||
this.options = [] |
|||
this.$nextTick(() => { |
|||
this.show = false |
|||
}) |
|||
}, |
|||
initFuse (list) { |
|||
this.fuse = new Fuse(list, { |
|||
shouldSort: true, |
|||
threshold: 0.4, |
|||
location: 0, |
|||
distance: 100, |
|||
maxPatternLength: 32, |
|||
minMatchCharLength: 1, |
|||
keys: [{ |
|||
name: 'title', |
|||
weight: 0.7 |
|||
}, { |
|||
name: 'path', |
|||
weight: 0.3 |
|||
}] |
|||
}) |
|||
}, |
|||
// Filter out the routes that can be displayed in the sidebar |
|||
// And generate the internationalized title |
|||
generateRoutes (routes, basePath = '/', prefixTitle = []) { |
|||
let res = [] |
|||
|
|||
for (const router of routes) { |
|||
// skip hidden router |
|||
if (router.hidden) { continue } |
|||
|
|||
const data = { |
|||
path: path.resolve(basePath, router.path), |
|||
title: [...prefixTitle] |
|||
} |
|||
|
|||
if (router.meta && router.meta.title) { |
|||
data.title = [...data.title, router.meta.title] |
|||
|
|||
if (router.redirect !== 'noRedirect') { |
|||
// only push the routes with title |
|||
// special case: need to exclude parent router without redirect |
|||
res.push(data) |
|||
} |
|||
} |
|||
|
|||
// recursive child routes |
|||
if (router.children) { |
|||
const tempRoutes = this.generateRoutes(router.children, data.path, data.title) |
|||
if (tempRoutes.length >= 1) { |
|||
res = [...res, ...tempRoutes] |
|||
} |
|||
} |
|||
} |
|||
return res |
|||
}, |
|||
querySearch (query) { |
|||
if (query !== '') { |
|||
this.options = this.fuse.search(query) |
|||
} else { |
|||
this.options = [] |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.header-search { |
|||
font-size: 0 !important; |
|||
|
|||
.search-icon { |
|||
cursor: pointer; |
|||
font-size: 18px; |
|||
vertical-align: middle; |
|||
} |
|||
|
|||
.header-search-select { |
|||
font-size: 18px; |
|||
transition: width 0.2s; |
|||
width: 0; |
|||
overflow: hidden; |
|||
background: transparent; |
|||
border-radius: 0; |
|||
display: inline-block; |
|||
vertical-align: middle; |
|||
|
|||
::v-deep .el-input__inner { |
|||
border-radius: 0; |
|||
border: 0; |
|||
padding-left: 0; |
|||
padding-right: 0; |
|||
box-shadow: none !important; |
|||
border-bottom: 1px solid #d9d9d9; |
|||
vertical-align: middle; |
|||
background: transparent; |
|||
} |
|||
} |
|||
|
|||
&.show { |
|||
.header-search-select { |
|||
width: 210px; |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,82 @@ |
|||
<template> |
|||
<div class="pagination elPaginationOuter"> |
|||
<el-pagination |
|||
background |
|||
@size-change="handleSizeChange" |
|||
@current-change="handleCurrentChange" |
|||
:current-page="currentPage" |
|||
:page-sizes="trendTotalCount" |
|||
:page-size="pagesize" |
|||
layout="total, sizes, prev, pager, next, jumper" |
|||
:total="totalCount" |
|||
> |
|||
</el-pagination> |
|||
<el-button |
|||
class="goPageBtn" |
|||
type="primary" |
|||
size="mini" |
|||
>跳转</el-button> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
// import { setResultCount } from "@/utils/auth" |
|||
export default { |
|||
name: 'pagination', |
|||
props: { |
|||
totalCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
pagesizeProps: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
currentPageProps: { |
|||
type: Number, |
|||
default: 1 |
|||
} |
|||
}, |
|||
computed:{ |
|||
trendTotalCount(){ |
|||
return [20,50,100] |
|||
} |
|||
}, |
|||
watch:{ |
|||
currentPageProps(n,o){ |
|||
this.currentPage = n |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
currentPage: 1, |
|||
pagesize: 0 |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.pagesize = this.pagesizeProps |
|||
this.currentPage = this.currentPageProps |
|||
}, |
|||
methods: { |
|||
//每页最大条数改变提交emit |
|||
handleSizeChange (val) { |
|||
// setResultCount(val) |
|||
this.pagesize = val |
|||
this.$emit('SizeChange', val) |
|||
}, |
|||
//当前页改变提交emit |
|||
handleCurrentChange (val) { |
|||
this.currentPage = val |
|||
this.$emit('CurrentChange', val) |
|||
}, |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
<style scoped> |
|||
.goPageBtn{ |
|||
margin-left: 20px; |
|||
background: #e8f4ff; |
|||
color:#409EFF; |
|||
border:none |
|||
} |
|||
</style> |
@ -0,0 +1,149 @@ |
|||
<template> |
|||
<div ref="rightPanel" :class="{ show: show }" class="rightPanel-container"> |
|||
<div class="rightPanel-background" /> |
|||
<div class="rightPanel"> |
|||
<div |
|||
class="handle-button" |
|||
:style="{ top: buttonTop + 'px', 'background-color': theme }" |
|||
@click="show = !show" |
|||
> |
|||
<i :class="show?'el-icon-close':'el-icon-setting'" /> |
|||
</div> |
|||
<div class="rightPanel-items"> |
|||
<slot /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import { addClass, removeClass } from '@/utils' |
|||
|
|||
export default { |
|||
name: 'RightPanel', |
|||
props: { |
|||
clickNotClose: { |
|||
default: false, |
|||
type: Boolean |
|||
}, |
|||
buttonTop: { |
|||
default: 250, |
|||
type: Number |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
show: false |
|||
} |
|||
}, |
|||
computed: { |
|||
theme () { |
|||
return this.$store.state.settings.theme |
|||
} |
|||
}, |
|||
watch: { |
|||
show (value) { |
|||
if (value && !this.clickNotClose) { |
|||
this.addEventClick() |
|||
} |
|||
if (value) { |
|||
addClass(document.body, 'showRightPanel') |
|||
} else { |
|||
removeClass(document.body, 'showRightPanel') |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.insertToBody() |
|||
}, |
|||
beforeDestroy () { |
|||
const elx = this.$refs.rightPanel |
|||
elx.remove() |
|||
}, |
|||
methods: { |
|||
addEventClick () { |
|||
window.addEventListener('click', this.closeSidebar) |
|||
}, |
|||
closeSidebar (evt) { |
|||
const parent = evt.target.closest('.rightPanel') |
|||
if (!parent) { |
|||
this.show = false |
|||
window.removeEventListener('click', this.closeSidebar) |
|||
} |
|||
}, |
|||
insertToBody () { |
|||
const elx = this.$refs.rightPanel |
|||
const body = document.querySelector('body') |
|||
body.insertBefore(elx, body.firstChild) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.showRightPanel { |
|||
overflow: hidden; |
|||
position: relative; |
|||
width: calc(100% - 15px); |
|||
} |
|||
</style> |
|||
|
|||
<style lang="scss" scoped> |
|||
.rightPanel-background { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
opacity: 0; |
|||
transition: opacity 0.3s cubic-bezier(0.7, 0.3, 0.1, 1); |
|||
background: rgba(0, 0, 0, 0.2); |
|||
z-index: -1; |
|||
} |
|||
|
|||
.rightPanel { |
|||
width: 100%; |
|||
max-width: 260px; |
|||
height: 100vh; |
|||
position: fixed; |
|||
top: 0; |
|||
right: 0; |
|||
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.05); |
|||
transition: all 0.25s cubic-bezier(0.7, 0.3, 0.1, 1); |
|||
transform: translate(100%); |
|||
background: #fff; |
|||
z-index: 40000; |
|||
} |
|||
|
|||
.show { |
|||
transition: all 0.3s cubic-bezier(0.7, 0.3, 0.1, 1); |
|||
|
|||
.rightPanel-background { |
|||
z-index: 20000; |
|||
opacity: 1; |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
|
|||
.rightPanel { |
|||
transform: translate(0); |
|||
} |
|||
} |
|||
|
|||
.handle-button { |
|||
width: 48px; |
|||
height: 48px; |
|||
position: absolute; |
|||
left: -48px; |
|||
text-align: center; |
|||
font-size: 24px; |
|||
border-radius: 6px 0 0 6px !important; |
|||
z-index: 0; |
|||
pointer-events: auto; |
|||
cursor: pointer; |
|||
color: #fff; |
|||
line-height: 48px; |
|||
i { |
|||
font-size: 24px; |
|||
line-height: 48px; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,60 @@ |
|||
<template> |
|||
<div> |
|||
<svg-icon |
|||
:icon-class="isFullscreen?'svg_exitFullscreen':'svg_fullscreen'" |
|||
@click="click" |
|||
/> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import screenfull from 'screenfull' |
|||
|
|||
export default { |
|||
name: 'Screenfull', |
|||
data () { |
|||
return { |
|||
isFullscreen: false |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.init() |
|||
}, |
|||
beforeDestroy () { |
|||
this.destroy() |
|||
}, |
|||
methods: { |
|||
click () { |
|||
if (!screenfull.enabled) { |
|||
this.$warningMsg('you browser can not work') |
|||
return false |
|||
} |
|||
screenfull.toggle() |
|||
}, |
|||
change () { |
|||
this.isFullscreen = screenfull.isFullscreen |
|||
}, |
|||
init () { |
|||
if (screenfull.enabled) { |
|||
screenfull.on('change', this.change) |
|||
} |
|||
}, |
|||
destroy () { |
|||
if (screenfull.enabled) { |
|||
screenfull.off('change', this.change) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.screenfull-svg { |
|||
display: inline-block; |
|||
cursor: pointer; |
|||
fill: #5a5e66; |
|||
width: 20px; |
|||
height: 20px; |
|||
vertical-align: 10px; |
|||
} |
|||
</style> |
@ -0,0 +1,58 @@ |
|||
<template> |
|||
<el-dropdown trigger="click" @command="handleSetSize"> |
|||
<div> |
|||
<svg-icon class-name="size-icon" icon-class="size" /> |
|||
</div> |
|||
<el-dropdown-menu slot="dropdown"> |
|||
<el-dropdown-item |
|||
v-for="item of sizeOptions" |
|||
:key="item.value" |
|||
:disabled="size === item.value" |
|||
:command="item.value" |
|||
> |
|||
{{ item.label }} |
|||
</el-dropdown-item> |
|||
</el-dropdown-menu> |
|||
</el-dropdown> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data () { |
|||
return { |
|||
sizeOptions: [ |
|||
{ label: 'Default', value: 'default' }, |
|||
{ label: 'Medium', value: 'medium' }, |
|||
{ label: 'Small', value: 'small' }, |
|||
{ label: 'Mini', value: 'mini' } |
|||
] |
|||
} |
|||
}, |
|||
computed: { |
|||
size () { |
|||
return this.$store.getters.size |
|||
} |
|||
}, |
|||
methods: { |
|||
handleSetSize (size) { |
|||
this.$ELEMENT.size = size |
|||
this.$store.dispatch('app/setSize', size) |
|||
this.refreshView() |
|||
this.$successMsg('Switch Size Success') |
|||
}, |
|||
refreshView () { |
|||
// In order to make the cached page re-rendered |
|||
this.$store.dispatch('tagsView/delAllCachedViews', this.$route) |
|||
|
|||
const { fullPath } = this.$route |
|||
|
|||
this.$nextTick(() => { |
|||
this.$router.replace({ |
|||
path: '/redirect' + fullPath |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
@ -0,0 +1,213 @@ |
|||
<template> |
|||
<div class="StepsFormAloneComponents"> |
|||
<div |
|||
class="pageMainContain" |
|||
:class="stepsDirection && stepsDirection == 'vertical' ? 'pageMainContainVertical' : ''" |
|||
> |
|||
<!-- 步骤流程图 --> |
|||
<div class="stepsContain"> |
|||
<el-steps |
|||
:active="active" |
|||
:process-status="processStatus" |
|||
:finish-status="finishStatus" |
|||
:direction="stepsDirection" |
|||
:space="stepsSpace" |
|||
:align-center="stepsAlignCenter" |
|||
:simple="stepsSimple" |
|||
:style="stepsStyle" |
|||
> |
|||
<el-step |
|||
v-for="(item, index) in steps" |
|||
:key="index" |
|||
:title="item.title" |
|||
:description="item.description" |
|||
:icon="item.icon" |
|||
></el-step> |
|||
</el-steps> |
|||
</div> |
|||
|
|||
<!-- 步骤对应页面内容 --> |
|||
<div class="allStepPages"> |
|||
<div |
|||
v-for="(item,index) in steps" |
|||
:key="index" |
|||
v-show="active == index" |
|||
class="stepBottomPage" |
|||
:class="'stepBottomPage'+(index+1)" |
|||
> |
|||
<slot :name="'stepSlot'+(index+1)"></slot> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 操作按钮 --> |
|||
<div class="stepsHandleBtns" v-if="(!((active == stepArray.length - 1) && hideLastBtsn))"> |
|||
<!-- 组件内已有按钮【前面】其他按钮位置插槽 --> |
|||
<slot name="stepOtherBeforeButton"></slot> |
|||
<!-- 组件内按钮 --> |
|||
<el-button |
|||
v-for="(item,index) in handleBtns" |
|||
:key="index" |
|||
v-show="!(active == 0 && item.name == 'cancle')" |
|||
:type="item.type" |
|||
@click="stepsHandleClick(item,index)" |
|||
:class="'stepsAloneBtn-'+item.name" |
|||
>{{item.label}}</el-button> |
|||
<!-- 组件内已有按钮【后面】其他按钮位置插槽 --> |
|||
<slot name="stepOtherAfterButton"></slot> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'StepsFormAlone', |
|||
props: { |
|||
stepsStyle:{ |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
// 结束状态 |
|||
finishStatus:{ |
|||
type: String, |
|||
default: 'success' |
|||
}, |
|||
// 当前步骤的状态 |
|||
processStatus:{ |
|||
type: String, |
|||
default: 'success' |
|||
}, |
|||
// 单独设置步骤名称 |
|||
stepNames: { |
|||
type: Array, |
|||
default: () => { |
|||
return null |
|||
} |
|||
}, |
|||
//步骤options |
|||
stepArray: { |
|||
type: Array, |
|||
default: () => { |
|||
return [ |
|||
{title:"步骤一",description:"",icon:"",status:null}, |
|||
{title:"步骤二",description:"",icon:"",status:null}, |
|||
{title:"步骤三",description:"",icon:"",status:null}, |
|||
] |
|||
} |
|||
}, |
|||
// 显示方向 如果更改为vertical:最好与stepsAlignCenter=false同步赋值 |
|||
stepsDirection:{ |
|||
type: String, |
|||
default: 'horizontal' |
|||
}, |
|||
//居中对齐 |
|||
stepsAlignCenter: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return true |
|||
} |
|||
}, |
|||
// 每个 step 的间距 |
|||
stepsSpace:{ |
|||
type: Number, |
|||
default: null |
|||
}, |
|||
//简洁风格 |
|||
stepsSimple: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
// 步骤操作 |
|||
stepHandleFuncs:{ |
|||
type: Object, |
|||
default: () => {} |
|||
}, |
|||
// 最后一步是否隐藏按钮 |
|||
hideLastBtsn:{ |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
active: 0, |
|||
steps: null,//步骤标头 |
|||
// 操作按钮 |
|||
handleBtns:[ |
|||
{name:"cancle",label:"上一步"}, |
|||
{name:"next",label:"下一步",type:"primary"}, |
|||
] |
|||
} |
|||
}, |
|||
created(){ |
|||
this.initStepsOption() |
|||
}, |
|||
mounted () { |
|||
}, |
|||
methods: { |
|||
// 设置步骤标头 |
|||
initStepsOption(){ |
|||
this.steps = Object.assign([], this.stepArray); |
|||
if(!this.stepNames)return; |
|||
this.stepNames.forEach((item,key)=>{ |
|||
if(key < this.steps.length) |
|||
this.steps[key].title = item |
|||
}) |
|||
}, |
|||
// 操作按钮 |
|||
stepsHandleClick(item,index){ |
|||
// 上一步 |
|||
if(item.name == 'cancle'){ |
|||
if(this.steps[this.active].cancle){ |
|||
this.steps[this.active].cancle().then((data) => { |
|||
this.active -- |
|||
}).catch((err) => { |
|||
console.log('cancle-err',err) |
|||
}) |
|||
}else{ |
|||
this.active -- |
|||
} |
|||
} |
|||
// 下一步 |
|||
if(item.name == 'next'){ |
|||
// 非最后一步 |
|||
if(this.active < this.steps.length - 1){ |
|||
if(this.steps[this.active].next){ |
|||
this.steps[this.active].next().then(res => { |
|||
this.active ++ |
|||
}).catch((err) => { |
|||
console.log('next-err',err) |
|||
}) |
|||
}else{ |
|||
this.active ++ |
|||
} |
|||
} |
|||
// 最后一步 |
|||
else{ |
|||
if(this.steps[this.active].next){ |
|||
this.steps[this.active].next() |
|||
// .then(res => { |
|||
// // 回到第一步 |
|||
// this.returnFirstActive() |
|||
// console.log('res',res) |
|||
// }).catch((err) => { |
|||
// console.log('next-err',err) |
|||
// }) |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
returnFirstActive(){ |
|||
this.active = 0 |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,44 @@ |
|||
.StepsFormAloneComponents{ |
|||
padding: 30px 30px 20px; |
|||
width: 100%; |
|||
height: 100%; |
|||
box-sizing: border-box; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.allStepPages{ |
|||
height: calc(100% - 110px); |
|||
margin-top: 30px; |
|||
|
|||
.stepBottomPage{ |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
} |
|||
|
|||
.stepsHandleBtns{ |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
} |
|||
|
|||
.pageMainContain{ |
|||
height: 100%; |
|||
|
|||
// 竖排列 |
|||
&.pageMainContainVertical{ |
|||
display: flex; |
|||
|
|||
.stepsContain{ |
|||
min-width: 260px; |
|||
flex-shrink: 0; |
|||
padding: 30px 0; |
|||
} |
|||
|
|||
.allStepPages{ |
|||
width: 100%; |
|||
height: calc(100% - 50px); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,62 @@ |
|||
<template> |
|||
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> |
|||
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> |
|||
<use :xlink:href="iconName" /> |
|||
</svg> |
|||
</template> |
|||
|
|||
<script> |
|||
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage |
|||
import { isExternal } from '@/utils/validate' |
|||
|
|||
export default { |
|||
name: 'SvgIcon', |
|||
props: { |
|||
iconClass: { |
|||
type: String, |
|||
required: true |
|||
}, |
|||
className: { |
|||
type: String, |
|||
default: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
isExternal() { |
|||
return isExternal(this.iconClass) |
|||
}, |
|||
iconName() { |
|||
return `#icon-${this.iconClass}` |
|||
}, |
|||
svgClass() { |
|||
if (this.className) { |
|||
return 'svg-icon ' + this.className |
|||
} else { |
|||
return 'svg-icon' |
|||
} |
|||
}, |
|||
styleExternalIcon() { |
|||
return { |
|||
mask: `url(${this.iconClass}) no-repeat 50% 50%`, |
|||
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.svg-icon { |
|||
width: 1em; |
|||
height: 1em; |
|||
vertical-align: -0.15em; |
|||
fill: currentColor; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.svg-external-icon { |
|||
background-color: currentColor; |
|||
mask-size: cover!important; |
|||
display: inline-block; |
|||
} |
|||
</style> |
@ -0,0 +1,173 @@ |
|||
<template> |
|||
<el-color-picker |
|||
v-model="theme" |
|||
:predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]" |
|||
class="theme-picker" |
|||
popper-class="theme-picker-dropdown" |
|||
/> |
|||
</template> |
|||
|
|||
<script> |
|||
const version = require('element-ui/package.json').version // element-ui version from node_modules |
|||
const ORIGINAL_THEME = '#409EFF' // default color |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
chalk: '', // content of theme-chalk css |
|||
theme: '' |
|||
} |
|||
}, |
|||
computed: { |
|||
defaultTheme() { |
|||
return this.$store.state.settings.theme |
|||
} |
|||
}, |
|||
watch: { |
|||
defaultTheme: { |
|||
handler: function(val, oldVal) { |
|||
this.theme = val |
|||
}, |
|||
immediate: true |
|||
}, |
|||
async theme(val) { |
|||
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME |
|||
if (typeof val !== 'string') return |
|||
const themeCluster = this.getThemeCluster(val.replace('#', '')) |
|||
const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) |
|||
const $message = this.$message({ |
|||
message: ' Compiling the theme', |
|||
customClass: 'theme-message', |
|||
type: 'success', |
|||
duration: 0, |
|||
iconClass: 'el-icon-loading' |
|||
}) |
|||
|
|||
const getHandler = (variable, id) => { |
|||
return () => { |
|||
const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) |
|||
const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) |
|||
|
|||
let styleTag = document.getElementById(id) |
|||
if (!styleTag) { |
|||
styleTag = document.createElement('style') |
|||
styleTag.setAttribute('id', id) |
|||
document.head.appendChild(styleTag) |
|||
} |
|||
styleTag.innerText = newStyle |
|||
} |
|||
} |
|||
|
|||
if (!this.chalk) { |
|||
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` |
|||
await this.getCSSString(url, 'chalk') |
|||
} |
|||
|
|||
const chalkHandler = getHandler('chalk', 'chalk-style') |
|||
|
|||
chalkHandler() |
|||
|
|||
const styles = [].slice.call(document.querySelectorAll('style')) |
|||
.filter(style => { |
|||
const text = style.innerText |
|||
return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) |
|||
}) |
|||
styles.forEach(style => { |
|||
const { innerText } = style |
|||
if (typeof innerText !== 'string') return |
|||
style.innerText = this.updateStyle(innerText, originalCluster, themeCluster) |
|||
}) |
|||
|
|||
this.$emit('change', val) |
|||
|
|||
$message.close() |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
updateStyle(style, oldCluster, newCluster) { |
|||
let newStyle = style |
|||
oldCluster.forEach((color, index) => { |
|||
newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) |
|||
}) |
|||
return newStyle |
|||
}, |
|||
|
|||
getCSSString(url, variable) { |
|||
return new Promise(resolve => { |
|||
const xhr = new XMLHttpRequest() |
|||
xhr.onreadystatechange = () => { |
|||
if (xhr.readyState === 4 && xhr.status === 200) { |
|||
this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') |
|||
resolve() |
|||
} |
|||
} |
|||
xhr.open('GET', url) |
|||
xhr.send() |
|||
}) |
|||
}, |
|||
|
|||
getThemeCluster(theme) { |
|||
const tintColor = (color, tint) => { |
|||
let red = parseInt(color.slice(0, 2), 16) |
|||
let green = parseInt(color.slice(2, 4), 16) |
|||
let blue = parseInt(color.slice(4, 6), 16) |
|||
|
|||
if (tint === 0) { // when primary color is in its rgb space |
|||
return [red, green, blue].join(',') |
|||
} else { |
|||
red += Math.round(tint * (255 - red)) |
|||
green += Math.round(tint * (255 - green)) |
|||
blue += Math.round(tint * (255 - blue)) |
|||
|
|||
red = red.toString(16) |
|||
green = green.toString(16) |
|||
blue = blue.toString(16) |
|||
|
|||
return `#${red}${green}${blue}` |
|||
} |
|||
} |
|||
|
|||
const shadeColor = (color, shade) => { |
|||
let red = parseInt(color.slice(0, 2), 16) |
|||
let green = parseInt(color.slice(2, 4), 16) |
|||
let blue = parseInt(color.slice(4, 6), 16) |
|||
|
|||
red = Math.round((1 - shade) * red) |
|||
green = Math.round((1 - shade) * green) |
|||
blue = Math.round((1 - shade) * blue) |
|||
|
|||
red = red.toString(16) |
|||
green = green.toString(16) |
|||
blue = blue.toString(16) |
|||
|
|||
return `#${red}${green}${blue}` |
|||
} |
|||
|
|||
const clusters = [theme] |
|||
for (let i = 0; i <= 9; i++) { |
|||
clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) |
|||
} |
|||
clusters.push(shadeColor(theme, 0.1)) |
|||
return clusters |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.theme-message, |
|||
.theme-picker-dropdown { |
|||
z-index: 99999 !important; |
|||
} |
|||
|
|||
.theme-picker .el-color-picker__trigger { |
|||
height: 26px !important; |
|||
width: 26px !important; |
|||
padding: 2px; |
|||
} |
|||
|
|||
.theme-picker-dropdown .el-color-dropdown__link-btn { |
|||
display: none; |
|||
} |
|||
</style> |
@ -0,0 +1,324 @@ |
|||
<template> |
|||
<el-dialog |
|||
title="导入" |
|||
element-loading-text="正在导入..." |
|||
:visible.sync="show" |
|||
:append-to-body="false" |
|||
:modal-append-to-body="false" |
|||
:fullscreen="true" |
|||
v-loading="loading" |
|||
:modal="false" |
|||
> |
|||
<!-- v-loading.fullscreen.lock="loading" --> |
|||
<el-button |
|||
type="success" |
|||
size="mini" |
|||
icon="el-icon-download" |
|||
@click="postImportDown" |
|||
>获取模板</el-button |
|||
> |
|||
<!-- <el-button |
|||
type="warning" |
|||
size="mini" |
|||
icon="el-icon-upload" |
|||
@click="postImportDown" |
|||
>导入数据</el-button |
|||
> --> |
|||
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick"> |
|||
<el-button |
|||
:loading="loading" |
|||
style="margin-left:16px;" |
|||
size="mini" |
|||
type="primary" |
|||
@click="handleUpload" |
|||
icon="el-icon-download" |
|||
> |
|||
导入数据 |
|||
</el-button> |
|||
<!-- <el-button |
|||
:loading="loading" |
|||
style="margin-left:16px;" |
|||
size="mini" |
|||
type="warning" |
|||
@click="handlePrint()" |
|||
icon="el-icon-printer" |
|||
> |
|||
全部打印 |
|||
</el-button> --> |
|||
<!-- <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover"> |
|||
Drop excel file here or |
|||
<el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload"> |
|||
Browse |
|||
</el-button> |
|||
</div> --> |
|||
<div style="height:calc(100% - 60px)" id="tableOuter"> |
|||
<el-table |
|||
:data="excelData.results" |
|||
border |
|||
highlight-current-row |
|||
style="width: 100%;margin-top:20px;" |
|||
:max-height="tableMaxHeight" |
|||
> |
|||
<!-- @selection-change="handleSelectionPrint" --> |
|||
<!-- <el-table-column type="selection" width="55"></el-table-column> --> |
|||
<el-table-column |
|||
v-if="excelData.header.length > 0" |
|||
type="index" |
|||
fixed="left" |
|||
label="序号" |
|||
width="50" |
|||
/> |
|||
<el-table-column |
|||
v-for="(item,index) of excelData.header" |
|||
:key="index" |
|||
:prop="item" |
|||
:label="item" |
|||
:fixed="headerFixed(item)" |
|||
/> |
|||
<!-- <el-table-column v-if="excelData.header.length > 0" label="明细-箱标签" fixed="right" width="100"> |
|||
<template slot-scope="scope"> |
|||
{{scope.row['明细-箱标签']}} |
|||
</template> |
|||
</el-table-column> --> |
|||
<!-- <el-table-column label="操作" fixed="right"> |
|||
<template slot-scope="scope"> |
|||
<el-button type="text" @click="handlePrint([scope.row])">打印</el-button> |
|||
</template> |
|||
</el-table-column> --> |
|||
</el-table> |
|||
</div> |
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="submitForm(0)">取 消</el-button> |
|||
<el-button type="primary" @click="submitForm(1)">确 定</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</template> |
|||
|
|||
<script> |
|||
import XLSX from 'xlsx' |
|||
import { mixins } from "@/mixins/mixins" |
|||
|
|||
export default { |
|||
name:"UploadExcel", |
|||
mixins:[mixins], |
|||
watch: { |
|||
show () { |
|||
this.reset() |
|||
} |
|||
}, |
|||
props: { |
|||
//表头浮动项 |
|||
fixedArr:{ |
|||
type:Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
fixedLeftArr:{ |
|||
type:Array, |
|||
default:null |
|||
}, |
|||
show: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
beforeUpload: Function, // eslint-disable-line |
|||
onSuccess: Function// eslint-disable-line |
|||
}, |
|||
data() { |
|||
return { |
|||
loading: false, |
|||
excelData: { |
|||
header: [], |
|||
results: [] |
|||
}, |
|||
// printSelection:[],//已选打印 |
|||
tableMaxHeight:null,//表格流体最大高度 |
|||
} |
|||
}, |
|||
methods: { |
|||
// 数据重置 |
|||
reset(){ |
|||
this.excelData = { |
|||
header:[], |
|||
results:[] |
|||
} |
|||
this.loading = false |
|||
// this.printSelection = []; |
|||
}, |
|||
headerFixed(item){ |
|||
let _fix = false |
|||
this.fixedArr.forEach(fix=>{ |
|||
if(fix.name == item){ |
|||
_fix = fix.value |
|||
} |
|||
}) |
|||
return _fix |
|||
}, |
|||
/** |
|||
* 按钮操作 |
|||
* index 0:取消,1:确定 |
|||
*/ |
|||
submitForm(index) { |
|||
this.$emit("submitForm", index,this.excelData); |
|||
}, |
|||
// 多选 |
|||
// handleSelectionPrint(val) { |
|||
// this.printSelection = val; |
|||
// }, |
|||
/** |
|||
* 打印 |
|||
* arr 有参数为单独打印,无参数为批量打印 |
|||
*/ |
|||
// handlePrint(arr){ |
|||
// let rdlx = "xiangbq.rdlx"; |
|||
// let params = { |
|||
// "boxlabel":[] |
|||
// } |
|||
// // let printArr = arr ? arr : this.printSelection; |
|||
// let printArr = arr ? arr : this.excelData.results; |
|||
// if(!printArr || printArr.length <= 0){ |
|||
// this.$message({ |
|||
// message: '请选择要打印的数据', |
|||
// type: 'error' |
|||
// }); |
|||
// return |
|||
// } |
|||
// }, |
|||
postImportDown () { |
|||
this.$emit('postImportDown') |
|||
}, |
|||
// 成功后回显及渲染 |
|||
successShowExcel(header, results){ |
|||
this.excelData.header = header |
|||
this.excelData.results = results |
|||
this.tableMaxHeight = document.getElementById("tableOuter").clientHeight |
|||
this.loading = false |
|||
}, |
|||
generateData({ header, results }) { |
|||
// this.excelData.header = header |
|||
// this.excelData.results = results |
|||
// this.tableMaxHeight = document.getElementById("tableOuter").clientHeight |
|||
if(this.onSuccess){ |
|||
this.onSuccess(header, results).then((res_header, res_results)=>{ |
|||
let _header = res_header ? res_header : header; |
|||
let _results = res_results ? res_results : results; |
|||
this.successShowExcel(_header, _results) |
|||
}).catch(err=>{ |
|||
this.loading = false |
|||
}) |
|||
}else{ |
|||
this.successShowExcel(header, results) |
|||
} |
|||
}, |
|||
handleDrop(e) { |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
if (this.loading) return |
|||
const files = e.dataTransfer.files |
|||
if (files.length !== 1) { |
|||
this.$message.error('Only support uploading one file!') |
|||
return |
|||
} |
|||
const rawFile = files[0] // only use files[0] |
|||
|
|||
if (!this.isExcel(rawFile)) { |
|||
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files') |
|||
return false |
|||
} |
|||
this.upload(rawFile) |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
}, |
|||
handleDragover(e) { |
|||
e.stopPropagation() |
|||
e.preventDefault() |
|||
e.dataTransfer.dropEffect = 'copy' |
|||
}, |
|||
handleUpload() { |
|||
this.$refs['excel-upload-input'].click() |
|||
}, |
|||
handleClick(e) { |
|||
const files = e.target.files |
|||
const rawFile = files[0] // only use files[0] |
|||
if (!rawFile) return |
|||
this.upload(rawFile) |
|||
}, |
|||
upload(rawFile) { |
|||
this.loading = true |
|||
this.$refs['excel-upload-input'].value = null // fix can't select the same excel |
|||
|
|||
if (!this.beforeUpload) { |
|||
this.readerData(rawFile) |
|||
this.loading = false |
|||
return |
|||
} |
|||
const before = this.beforeUpload(rawFile) |
|||
if (before) { |
|||
this.readerData(rawFile) |
|||
} |
|||
}, |
|||
readerData(rawFile) { |
|||
return new Promise((resolve, reject) => { |
|||
const reader = new FileReader() |
|||
reader.onload = e => { |
|||
const data = e.target.result |
|||
// const workbook = XLSX.read(data, { type: 'array',cellText:false,cellDates:true }) |
|||
const workbook = XLSX.read(data, { type: 'array'}) |
|||
const firstSheetName = workbook.SheetNames[0] |
|||
const worksheet = workbook.Sheets[firstSheetName] |
|||
const header = this.getHeaderRow(worksheet) |
|||
const results = XLSX.utils.sheet_to_json(worksheet,{raw:false}) |
|||
// const results = XLSX.utils.sheet_to_json(worksheet) |
|||
if(results.length <= 0){ |
|||
this.$message.error('导入表格内无数据,请确认后重新导入'); |
|||
this.loading = false |
|||
return |
|||
} |
|||
this.generateData({ header, results }) |
|||
resolve() |
|||
this.tab |
|||
} |
|||
reader.readAsArrayBuffer(rawFile) |
|||
}) |
|||
}, |
|||
getHeaderRow(sheet) { |
|||
const headers = [] |
|||
const range = XLSX.utils.decode_range(sheet['!ref']) |
|||
let C |
|||
const R = range.s.r |
|||
/* start in the first row */ |
|||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ |
|||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] |
|||
/* find the cell in the first row */ |
|||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default |
|||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell) |
|||
headers.push(hdr) |
|||
} |
|||
return headers |
|||
}, |
|||
isExcel(file) { |
|||
return /\.(xlsx|xls|csv)$/.test(file.name) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.excel-upload-input{ |
|||
display: none; |
|||
z-index: -9999; |
|||
} |
|||
.drop{ |
|||
border: 2px dashed #bbb; |
|||
width: 600px; |
|||
height: 160px; |
|||
line-height: 160px; |
|||
margin: 0 auto; |
|||
font-size: 24px; |
|||
border-radius: 5px; |
|||
text-align: center; |
|||
color: #bbb; |
|||
position: relative; |
|||
} |
|||
</style> |
@ -0,0 +1,367 @@ |
|||
<template> |
|||
<!-- 组件功能:普通新增编辑(目前只有主表)参数配置从api获取 --> |
|||
<el-dialog |
|||
:visible.sync="show" |
|||
:modal="false" |
|||
:modal-append-to-body="false" |
|||
:show-close="true" |
|||
@close="close" |
|||
class="searchPageComponents" |
|||
:fullscreen="true" |
|||
style="width:calc(100% - 28px);left:14px;top:14px;height:calc(100% - 28px)" |
|||
v-loading="Loading.addEditApiLoading" |
|||
> |
|||
<!-- 数据填写 --> |
|||
<div v-if="active === 0" style="height: 100%;"> |
|||
<div class="centerInnerContent" :class="{'hasDetails' : flexTableData}"> |
|||
<!-- 左侧主表 --> |
|||
<div class="leftMainForm"> |
|||
<div class="dialogOuterTitle">{{formTitle}} 【主表信息】</div> |
|||
<!-- 表单 --> |
|||
<el-form |
|||
class="addEditFrom" |
|||
ref="addEditFrom_Ref" |
|||
v-if="formData" |
|||
:model="formData" |
|||
:rules="formRules" |
|||
> |
|||
<el-row :gutter="40"> |
|||
<el-col |
|||
:span="item.colSpan || 12" |
|||
v-for="(item, index) in formItemData" |
|||
:key="index" |
|||
> |
|||
<el-form-item |
|||
:label="item.label" |
|||
:prop="item.prop" |
|||
v-if="item.label.toUpperCase() != 'DETAILS'" |
|||
> |
|||
<!-- 数值 --> |
|||
<el-input-number |
|||
v-if="item.apiBaseType === 'number'" |
|||
v-model="formData[item.prop]" |
|||
:min="item.minimum || undefined" |
|||
:max="item.maximum || undefined" |
|||
:maxlength="item.maxLength || undefined" |
|||
:minlength="item.minLength || undefined" |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@change="changeValue(item.prop,item,$event)" |
|||
@clear="clearValue(item.prop,$event)" |
|||
></el-input-number> |
|||
|
|||
<!-- 时间转换 --> |
|||
<el-date-picker |
|||
v-else-if="item.apiBaseType === 'datetime'" |
|||
v-model="formData[item.prop]" |
|||
type="datetime" |
|||
placeholder="选择日期时间" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
|
|||
<!-- 布尔、枚举 --> |
|||
<el-select |
|||
v-else-if="item.isEnums || item.apiBaseType === 'boolean'" |
|||
v-model="formData[item.prop]" |
|||
:placeholder="item.placeholder || '请选择' + item.label" |
|||
:disabled="Boolean(item.disabled)" |
|||
> |
|||
<el-option |
|||
v-for="item in item.enums_list" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
></el-option> |
|||
</el-select> |
|||
|
|||
<!-- 文本框 --> |
|||
<!-- <el-input |
|||
v-else |
|||
type="textarea" |
|||
autosize |
|||
resize="none" |
|||
v-model="formData[item.prop]" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-input> --> |
|||
<el-input |
|||
v-else |
|||
v-model="formData[item.prop]" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
</el-form> |
|||
</div> |
|||
<!-- 右侧子表 --> |
|||
<div class="rightDetailTable" v-if="flexTableData"> |
|||
<div class="dialogOuterTitle">{{formTitle}} 【子表信息】</div> |
|||
<currenTableFlex |
|||
ref="currenTableFlex_Ref" |
|||
:isShowIndex="true" |
|||
:isEditable="true" |
|||
:setUTableHeight="230" |
|||
class="currenTableFlex" |
|||
:flexTableData="flexTableData" |
|||
:flexTableColumns="flexTableColumns" |
|||
></currenTableFlex> |
|||
</div> |
|||
</div> |
|||
<!-- 操作按钮 --> |
|||
<div slot="footer" class="dialog-footer"> |
|||
<el-button @click="show = false">取 消</el-button> |
|||
<el-button type="primary" @click="submitHandle()">确 定</el-button> |
|||
</div> |
|||
</div> |
|||
<!-- 成功提示 --> |
|||
<div v-if="active === 1"> |
|||
<el-result icon="success" title="成功提示" :subTitle="formTitle + '成功'"> |
|||
<template slot="extra"> |
|||
<el-button type="primary" size="medium" @click="exitHandle" |
|||
>退出</el-button |
|||
> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
<!-- 错误提示 --> |
|||
<div v-if="active === 2"> |
|||
<el-result icon="error" title="错误提示" :subTitle="formTitle + '失败'"> |
|||
<template slot="extra"> |
|||
<el-button type="primary" size="medium" @click="changeActive(0)" |
|||
>返回</el-button |
|||
> |
|||
<el-button type="primary" size="medium" @click="exitHandle" |
|||
>退出</el-button |
|||
> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
</el-dialog> |
|||
</template> |
|||
<script> |
|||
import { ApiTypePost, ApiTypePut } from "@/api/wms-api" |
|||
import { LoadingMixins } from "@/mixins/LoadingMixins"; |
|||
import currenTableFlex from "@/components/currenTableFlex" |
|||
import * as allUrlOption from '@/utils/baseData/urlOption' |
|||
export default { |
|||
name:"addEditFromApiPop", |
|||
mixins:[ LoadingMixins ], |
|||
components: { currenTableFlex }, |
|||
props: { |
|||
// 编辑行数据 |
|||
editRowData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 操作类型:add/edit |
|||
handleType:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 提交事件 |
|||
submitForm:{ |
|||
type:Function, |
|||
default:null |
|||
}, |
|||
// 特殊的【新增】接口,如果没有就走路由下的配置文件 |
|||
addSubmitUrl:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 特殊的【编辑】接口,如果没有就走路由下的配置文件 |
|||
editSubmitUrl:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
//明细-列表 |
|||
URLOption_detailList:allUrlOption[this.$route.name].detailListURL, |
|||
// 当前的dto |
|||
currentDtos:this.$store.getters.dtoColumnTypes[this.$route.name], |
|||
active:0,//显示内容:0表单 1成功 2失败 |
|||
show:true, |
|||
formTitle:null,//form名称 |
|||
formData:{},//表单数据 |
|||
formItemData:null,//表单item配置 |
|||
formRules: {},//表单验证 |
|||
flexTableData:null,//子表table |
|||
// flexTableColumns:null,//子表table列 |
|||
flexTableColumns: null, |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.initTitle() |
|||
this.initFormItems() |
|||
}, |
|||
methods: { |
|||
// 初始化form名称 |
|||
initTitle(){ |
|||
if(this.handleType){ |
|||
this.formTitle = this.handleType == 'add' ? '新增'+this.$route.name : '编辑'+this.$route.name |
|||
} |
|||
}, |
|||
// 初始化表单配置、rules |
|||
initFormItems(){ |
|||
let _dtoList_type = this.handleType == 'add' ? 'C' : 'U' |
|||
let _dtoList = this.currentDtos[_dtoList_type].dtoList |
|||
// 除去子表信息 |
|||
let _formItems = _dtoList.filter(item=>{ |
|||
return item.prop.toUpperCase() != 'DETAILS' |
|||
}) |
|||
if(_formItems)this.formItemData = _formItems |
|||
// 编辑格式:特殊处理默认值 |
|||
if(this.handleType == 'edit' && this.editRowData){ |
|||
this.formData = JSON.parse(JSON.stringify(this.editRowData)) |
|||
}else{ |
|||
this.formData = {} |
|||
} |
|||
// 子表数据 |
|||
let _list = _dtoList.filter(item=>{ |
|||
return item.prop.toUpperCase() == 'DETAILS' |
|||
}) |
|||
if(_list && _list.length > 0){ |
|||
if(this.handleType == 'edit'){ |
|||
this.flexTableData = this.formData[_list[0].prop] |
|||
}else{ |
|||
this.flexTableData = [] |
|||
} |
|||
} |
|||
// 子表数据列 |
|||
if(this.URLOption_detailList){ |
|||
let _detailApi = this.URLOption_detailList.slice(0,this.URLOption_detailList.lastIndexOf('/')) |
|||
let _detailDtos = this.$store.getters.dtoColumnTypes[_detailApi].S.dtoList |
|||
this.flexTableColumns = _detailDtos |
|||
} |
|||
|
|||
// 表单验证格式化 |
|||
this.formRules={} |
|||
_dtoList.forEach(item=>{ |
|||
if(item.isRequired){ |
|||
this.formRules[item.prop] = [{ required: true, trigger: "blur", message: "不可为空" }] |
|||
} |
|||
}) |
|||
}, |
|||
// 关闭弹窗 |
|||
close() { |
|||
this.show = false |
|||
this.$emit("closePop") |
|||
}, |
|||
// 提交表单 |
|||
submitHandle(){ |
|||
this.$refs.addEditFrom_Ref.validate((valid) => { |
|||
if(this.submitForm){ |
|||
this.submitForm(valid,this.formData,this.handleType,this.formItemData,this.formRules) |
|||
return |
|||
} |
|||
this.formData.details = this.flexTableData |
|||
this.Loading.addEditApiLoading = true |
|||
if (valid) { |
|||
// 新增 |
|||
if(this.handleType == 'add'){ |
|||
ApiTypePost( |
|||
this.formData, |
|||
this.currentDtos.C.actionsUrl |
|||
).then(res => { |
|||
this.changeActive(1) |
|||
}).catch(err => { |
|||
this.changeActive(2) |
|||
}) |
|||
} |
|||
// 编辑 |
|||
else{ |
|||
ApiTypePut( |
|||
this.formData, |
|||
this.formData.id, |
|||
this.currentDtos.U.actionsUrl |
|||
).then(res => { |
|||
this.changeActive(1) |
|||
}).catch(err => { |
|||
this.changeActive(2) |
|||
}) |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
}); |
|||
}, |
|||
// 结果页退出 |
|||
exitHandle(){ |
|||
this.close() |
|||
if(this.active == '1')this.oldSkipCount = 1; |
|||
this.show = false |
|||
this.$emit("exitAfterHandle") |
|||
this.$nextTick(()=>{ |
|||
this.active = 0 |
|||
}) |
|||
}, |
|||
// 更改页面步骤 |
|||
changeActive(sta){ |
|||
this.active = sta |
|||
this.Loading.addEditApiLoading = false |
|||
}, |
|||
// 值更改函数 |
|||
changeValue(prop,item,val) { |
|||
this.$emit("changeValue", prop, item, val) |
|||
}, |
|||
// 值清除函数 |
|||
clearValue(prop,item,val) { |
|||
this.$emit("clearValue", prop, item, val) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
::v-deep .el-dialog__header{ |
|||
padding: 0 !important; |
|||
} |
|||
::v-deep .el-row{ |
|||
width: 100%; |
|||
} |
|||
::v-deep .addEditFrom{ |
|||
height: calc(100%); |
|||
overflow: auto; |
|||
} |
|||
::v-deep .el-form-item__label{ |
|||
float: unset; |
|||
} |
|||
|
|||
::v-deep .el-input,.el-select,.el-input-number{ |
|||
width: 100% !important; |
|||
} |
|||
|
|||
.dialog-footer{ |
|||
padding-top: 15px; |
|||
text-align: right; |
|||
} |
|||
.centerInnerContent{ |
|||
height: calc(100% - 60px); |
|||
overflow: auto; |
|||
|
|||
.leftMainForm{ |
|||
height: calc(100% - 60px); |
|||
} |
|||
|
|||
&.hasDetails{ |
|||
display: flex; |
|||
|
|||
.leftMainForm{ |
|||
width: 50%; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.rightDetailTable{ |
|||
height: calc(100% - 60px); |
|||
width: calc(50%); |
|||
padding-left:40px; |
|||
border-left: #ddd solid 1px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,312 @@ |
|||
<template> |
|||
<!-- 组件功能:普通新增编辑(目前只有主表)参数配置从api获取 --> |
|||
<el-dialog |
|||
:visible.sync="show" |
|||
:modal="false" |
|||
:modal-append-to-body="false" |
|||
:show-close="true" |
|||
@close="close" |
|||
class="searchPageComponents" |
|||
:fullscreen="true" |
|||
style="width:calc(100% - 28px);left:14px;top:14px;height:calc(100% - 28px)" |
|||
v-loading="Loading.addEditApiLoading" |
|||
> |
|||
<!-- 表单 --> |
|||
<div v-if="active === 0" style="height: 100%;"> |
|||
<!-- 标题 --> |
|||
<div class="dialogOuterTitle">{{formTitle}}</div> |
|||
<!-- 表单 --> |
|||
<el-form |
|||
class="addEditFrom" |
|||
ref="addEditFrom_Ref" |
|||
v-if="formData" |
|||
:model="formData" |
|||
:rules="formRules" |
|||
> |
|||
<el-row :gutter="40"> |
|||
<el-col |
|||
:span="item.colSpan || 12" |
|||
v-for="(item, index) in formItemData" |
|||
:key="index" |
|||
> |
|||
<el-form-item |
|||
:label="item.label" |
|||
:prop="item.prop" |
|||
> |
|||
<!-- 数值 --> |
|||
<el-input-number |
|||
v-if="item.apiBaseType === 'number'" |
|||
v-model="formData[item.prop]" |
|||
:min="item.minimum || undefined" |
|||
:max="item.maximum || undefined" |
|||
:maxlength="item.maxLength || undefined" |
|||
:minlength="item.minLength || undefined" |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@change="changeValue(item.prop,item,$event)" |
|||
@clear="clearValue(item.prop,$event)" |
|||
></el-input-number> |
|||
|
|||
<!-- 时间转换 --> |
|||
<el-date-picker |
|||
v-else-if="item.apiBaseType === 'datetime'" |
|||
v-model="formData[item.prop]" |
|||
type="datetime" |
|||
placeholder="选择日期时间" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
|
|||
<!-- 布尔、枚举 --> |
|||
<el-select |
|||
v-else-if="item.isEnums || item.apiBaseType === 'boolean'" |
|||
v-model="formData[item.prop]" |
|||
:placeholder="item.placeholder || '请选择' + item.label" |
|||
:disabled="Boolean(item.disabled)" |
|||
> |
|||
<el-option |
|||
v-for="item in getItemEnums(item)" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
></el-option> |
|||
</el-select> |
|||
|
|||
<!-- 文本框 --> |
|||
<!-- <el-input |
|||
v-else |
|||
type="textarea" |
|||
autosize |
|||
resize="none" |
|||
v-model="formData[item.prop]" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-input> --> |
|||
<el-input |
|||
v-else |
|||
v-model="formData[item.prop]" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
</el-form> |
|||
<!-- 操作按钮 --> |
|||
<div slot="footer" class="dialog-footer"> |
|||
<el-button @click="show = false">取 消</el-button> |
|||
<el-button type="primary" @click="submitHandle()">确 定</el-button> |
|||
</div> |
|||
</div> |
|||
<!-- 成功提示 --> |
|||
<div v-if="active === 1"> |
|||
<el-result icon="success" title="成功提示" :subTitle="formTitle + '成功'"> |
|||
<template slot="extra"> |
|||
<el-button type="primary" size="medium" @click="exitHandle" |
|||
>退出</el-button |
|||
> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
<!-- 错误提示 --> |
|||
<div v-if="active === 2"> |
|||
<el-result icon="error" title="错误提示" :subTitle="formTitle + '失败'"> |
|||
<template slot="extra"> |
|||
<el-button type="primary" size="medium" @click="changeActive(0)" |
|||
>返回</el-button |
|||
> |
|||
<el-button type="primary" size="medium" @click="exitHandle" |
|||
>退出</el-button |
|||
> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
</el-dialog> |
|||
</template> |
|||
<script> |
|||
import { ApiTypePost, ApiTypePut } from "@/api/wms-api" |
|||
import { LoadingMixins } from "@/mixins/LoadingMixins"; |
|||
import { tableMixins } from "@/mixins/TableMixins" |
|||
export default { |
|||
name:"addEditFromApiPop", |
|||
mixins:[ LoadingMixins,tableMixins ], |
|||
props: { |
|||
// 编辑行数据 |
|||
editRowData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 操作类型:add/edit |
|||
handleType:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 提交事件 |
|||
submitForm:{ |
|||
type:Function, |
|||
default:null |
|||
}, |
|||
// 特殊的【新增】接口,如果没有就走路由下的配置文件 |
|||
addSubmitUrl:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 特殊的【编辑】接口,如果没有就走路由下的配置文件 |
|||
editSubmitUrl:{ |
|||
type: String, |
|||
default: null |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
currentDtos:this.$store.getters.dtoColumnTypes[this.$route.name], |
|||
active:0,//显示内容:0表单 1成功 2失败 |
|||
show:true, |
|||
formTitle:null,//form名称 |
|||
formData:{},//表单数据 |
|||
formItemData:null,//表单item配置 |
|||
formRules: {},//表单验证 |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.initTitle() |
|||
this.initFormItems() |
|||
}, |
|||
methods: { |
|||
// 初始化form名称 |
|||
initTitle(){ |
|||
if(this.handleType){ |
|||
this.formTitle = this.handleType == 'add' ? '新增'+this.$route.name : '编辑'+this.$route.name |
|||
} |
|||
}, |
|||
// 初始化表单配置、rules |
|||
initFormItems(){ |
|||
let _dtoList_type = this.handleType == 'add' ? 'C' : 'U' |
|||
let _dtoList = this.currentDtos[_dtoList_type].dtoList |
|||
this.formItemData = JSON.parse(JSON.stringify(_dtoList)) |
|||
// 编辑格式:特殊处理默认值 |
|||
if(this.handleType == 'edit' && this.editRowData){ |
|||
this.formData = JSON.parse(JSON.stringify(this.editRowData)) |
|||
}else{ |
|||
this.formData = {} |
|||
} |
|||
// 表单验证格式化 |
|||
this.formRules={} |
|||
_dtoList.forEach(item=>{ |
|||
if(item.isRequired){ |
|||
this.formRules[item.prop] = [{ required: true, trigger: "blur", message: "不可为空" }] |
|||
} |
|||
}) |
|||
}, |
|||
// 获取枚举、布尔 |
|||
getItemEnums(item){ |
|||
let _option = [] |
|||
// 布尔 |
|||
if(item.apiBaseType == 'boolean'){ |
|||
_option = [{ |
|||
value: true, |
|||
label: '是' |
|||
},{ |
|||
value: false, |
|||
label: '否' |
|||
},] |
|||
} |
|||
if(item.isEnums){ |
|||
_option = item.enums_list |
|||
} |
|||
return _option |
|||
}, |
|||
// 关闭弹窗 |
|||
close() { |
|||
this.show = false |
|||
this.$emit("closePop") |
|||
}, |
|||
// 提交表单 |
|||
submitHandle(){ |
|||
this.$refs.addEditFrom_Ref.validate((valid) => { |
|||
if(this.submitForm){ |
|||
this.submitForm(valid,this.formData,this.handleType,this.formItemData,this.formRules) |
|||
return |
|||
} |
|||
this.Loading.addEditApiLoading = true |
|||
if (valid) { |
|||
// 新增 |
|||
if(this.handleType == 'add'){ |
|||
ApiTypePost( |
|||
this.formData, |
|||
this.currentDtos.C.actionsUrl |
|||
).then(res => { |
|||
this.changeActive(1) |
|||
}).catch(err => { |
|||
this.changeActive(2) |
|||
}) |
|||
} |
|||
// 编辑 |
|||
else{ |
|||
ApiTypePut( |
|||
this.formData, |
|||
this.formData.id, |
|||
this.currentDtos.U.actionsUrl |
|||
).then(res => { |
|||
this.changeActive(1) |
|||
}).catch(err => { |
|||
this.changeActive(2) |
|||
}) |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
}); |
|||
}, |
|||
// 结果页退出 |
|||
exitHandle(){ |
|||
this.close() |
|||
if(this.active == '1')this.oldSkipCount = 1; |
|||
this.show = false |
|||
this.paging() |
|||
this.$nextTick(()=>{ |
|||
this.active = 0 |
|||
}) |
|||
}, |
|||
// 更改页面步骤 |
|||
changeActive(sta){ |
|||
this.active = sta |
|||
this.Loading.addEditApiLoading = false |
|||
}, |
|||
// 值更改函数 |
|||
changeValue(prop,item,val) { |
|||
this.$emit("changeValue", prop, item, val) |
|||
}, |
|||
// 值清除函数 |
|||
clearValue(prop,item,val) { |
|||
this.$emit("clearValue", prop, item, val) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
::v-deep .el-dialog__header{ |
|||
padding: 0 !important; |
|||
} |
|||
::v-deep .el-row{ |
|||
width: 100%; |
|||
} |
|||
::v-deep .addEditFrom{ |
|||
height: calc(100% - 120px); |
|||
overflow: auto; |
|||
} |
|||
::v-deep .el-form-item__label{ |
|||
float: unset; |
|||
} |
|||
|
|||
::v-deep .el-input,.el-select,.el-input-number{ |
|||
width: 100% !important; |
|||
} |
|||
|
|||
.dialog-footer{ |
|||
padding-top: 15px; |
|||
text-align: right; |
|||
} |
|||
</style> |
@ -0,0 +1,77 @@ |
|||
<template> |
|||
<div class="batchButton"> |
|||
<div class="query-box" v-if="!checkButton.length"> |
|||
<el-input |
|||
v-model="input" |
|||
:placeholder="placeholder" |
|||
@keyup.enter.native="filtrate" |
|||
/> |
|||
<el-button type="primary" @click.native.prevent="filtrate" |
|||
>搜索</el-button |
|||
> |
|||
</div> |
|||
<div class="button-box" v-else> |
|||
<curren-Button |
|||
:Butttondata="Butttondata" |
|||
@tableButtonClick="tableButtonClick" |
|||
></curren-Button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenButton from "@/components/currenButton" |
|||
export default { |
|||
name: 'batchButton', |
|||
components: { |
|||
currenButton, |
|||
}, |
|||
props: { |
|||
Butttondata: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
placeholder: { |
|||
type: String, |
|||
default: '搜索...' |
|||
}, |
|||
checkButton: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
} |
|||
}, |
|||
computed: { |
|||
|
|||
}, |
|||
data () { |
|||
return { |
|||
input: '' |
|||
} |
|||
}, |
|||
methods: { |
|||
//搜索字段变化时 |
|||
filtrate () { |
|||
this.$emit('filtrate', this.input) |
|||
}, |
|||
tableButtonClick (val) { |
|||
this.$emit('tableButtonClick', val) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.batchButton { |
|||
display: flex; |
|||
align-items: center; |
|||
height: 50px; |
|||
.query-box { |
|||
display: flex; |
|||
.el-button { |
|||
margin: 0 0 0 10px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,634 @@ |
|||
<template> |
|||
<el-drawer |
|||
v-loading="DrawerLoading" |
|||
v-if="drawer" |
|||
:visible="true" |
|||
:close-on-press-escape="false" |
|||
:wrapperClosable="false" |
|||
:with-header="false" |
|||
:modal="false" |
|||
size="100%" |
|||
> |
|||
<!-- <div class="drawer-heder"> |
|||
<div class="heder-left"> |
|||
<div class="header-text"> |
|||
<span>{{ propsData[title[0].prop] }}</span> |
|||
<span>{{ title[0].label }}</span> |
|||
</div> |
|||
</div> |
|||
<div class="heder-right"> |
|||
<curren-Button |
|||
:Butttondata="Butttondata" |
|||
@tableButtonClick="tableButtonClick" |
|||
> |
|||
<template> |
|||
<el-dropdown |
|||
trigger="click" |
|||
@command="handleCommand" |
|||
v-if="JSON.stringify(dropdownData) != '{}'" |
|||
> |
|||
<el-button size="mini" icon="el-icon-more"></el-button> |
|||
<el-dropdown-menu slot="dropdown"> |
|||
<el-dropdown-item |
|||
v-for="(item, index) in dropdownData" |
|||
:key="index" |
|||
:command="item.command" |
|||
>{{ item.label }}</el-dropdown-item |
|||
> |
|||
</el-dropdown-menu> |
|||
</el-dropdown> |
|||
</template> |
|||
</curren-Button> |
|||
</div> |
|||
</div> --> |
|||
<div class="drawer-main"> |
|||
<curren-tabs |
|||
:tabsData="dropdownTabs" |
|||
:activeName="firstTabs" |
|||
type="border-card" |
|||
@handleClick="handleClick" |
|||
> |
|||
<template slot-scope="scope"> |
|||
<curren-descriptions |
|||
border |
|||
v-if="scope.value == 'xq'" |
|||
:column="column" |
|||
:direction="direction" |
|||
:colon="false" |
|||
:tabsDesTions="tabsDesTions" |
|||
:propsData="propsData" |
|||
> |
|||
</curren-descriptions> |
|||
<!-- 明细 包含分页 头部按钮等 --> |
|||
<tablePagination |
|||
ref="tablePaginationForMX_Ref" |
|||
v-if="scope.value == 'mx'" |
|||
:currenButtonData="detailHeaderButton" |
|||
:tableData="propsData.details" |
|||
:tableColumns="tableColumns" |
|||
:setUTableHeight="showDetailColumnsSet || showDetailFilters ? 220 : 180" |
|||
@rowDrop="rowDrop" |
|||
:searchOverallCoverHeight="'calc(100vh - 345px)'" |
|||
:rowSource="'detail_api'" |
|||
:selectMaxHeight="'116px'" |
|||
:rowMaxHeight="rowMaxHeight" |
|||
:totalCount="totalCountForDetail" |
|||
:MaxResultCount="MaxResultCount" |
|||
@sortChange="sortChangeForDetail" |
|||
@alertoldSkipCount="alertoldSkipCountForDetail" |
|||
@alterResultCount="alterResultCountForDetail" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
:currentPageProps="oldSkipCount" |
|||
@overallSearchFormClick="overallSearchClickForDetail" |
|||
:httpOverallSearchData="httpOverallSearchData" |
|||
@buttonOperationClick_left="buttonOperationClick_left" |
|||
:buttonOperationList_left="buttonOperationList_left" |
|||
:tableLoading="Loading.tableLoading" |
|||
></tablePagination> |
|||
<!-- 新增汇总 表头 区分明细表头使用 summaryTableColumns --> |
|||
<umyTable |
|||
v-if="scope.value == 'hz'" |
|||
:tableBorder="true" |
|||
:tableData="propsData.summaryDetails" |
|||
:tableColumns="summaryTableColumns.length == 0 ? tableColumns : summaryTableColumns" |
|||
:selectionTable="selectionTable" |
|||
:requiredRules="false" |
|||
@sortChange="sortChange" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
@inlineDialog="inlineDialog" |
|||
@buttonClick="buttonClick" |
|||
:setUTableHeight="210" |
|||
> |
|||
<template> |
|||
<slot></slot> |
|||
</template> |
|||
</umyTable> |
|||
<!-- 自定义扩展 --> |
|||
<umyTable |
|||
v-if=" |
|||
scope.value == zdyValue && |
|||
scope.value != 'xq' && |
|||
scope.value != 'mx' && |
|||
scope.value != 'hz' && |
|||
scope.value != 'zwlcj' |
|||
" |
|||
:tableBorder="true" |
|||
:tableLoading="tableLoading" |
|||
:tableData="otherData" |
|||
:tableColumns="zdyTableColumns" |
|||
:selectionTable="selectionTable" |
|||
:requiredRules="false" |
|||
@sortChange="sortChange" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
@inlineDialog="inlineDialog" |
|||
@buttonClick="buttonClick" |
|||
:setUTableHeight="210" |
|||
> |
|||
<template> |
|||
<slot></slot> |
|||
</template> |
|||
</umyTable> |
|||
</template> |
|||
</curren-tabs> |
|||
</div> |
|||
<div class="drawer-Shut" @click="drawerShut"> |
|||
<el-button type="danger" size="mini">关闭</el-button> |
|||
</div> |
|||
<!-- 明细-查看详情 --> |
|||
<el-dialog |
|||
width="90%" |
|||
:modal-append-to-body="false" |
|||
:append-to-body="false" |
|||
:title="detailInfoTitle" |
|||
:visible.sync="displayDialog.detailInfoDialog" |
|||
:show-close="true" |
|||
:close-on-click-modal="true" |
|||
:close-on-press-escape="true" |
|||
> |
|||
<div> |
|||
<curren-descriptions |
|||
v-if="detailInfoTableData" |
|||
border |
|||
:column="column" |
|||
:direction="direction" |
|||
:colon="false" |
|||
:tabsDesTions="tableColumns" |
|||
:propsData="detailInfoTableData" |
|||
style="padding-bottom: 20px;" |
|||
></curren-descriptions> |
|||
</div> |
|||
</el-dialog> |
|||
</el-drawer> |
|||
</template> |
|||
<script> |
|||
import { getPageListForDetail } from "@/api/wms-api" |
|||
import searchOverall from "@/components/searchOverall" |
|||
import currenButton from "@/components/currenButton" |
|||
import currenDescriptions from "@/components/currenDescriptions" |
|||
import currenTabs from "@/components/currenTabs" |
|||
import currenTable from "@/components/currenTable" |
|||
import pagination from "@/components/Pagination" |
|||
import rowDrop from "@/components/rowDrop/index.vue" |
|||
import * as allUrlOption from '@/utils/baseData/urlOption' |
|||
import { LoadingMixins } from "@/mixins/LoadingMixins"; |
|||
export default { |
|||
name: 'currenTabel-drawer', |
|||
components: { |
|||
pagination, |
|||
currenButton, |
|||
currenDescriptions, |
|||
currenTabs, |
|||
currenTable, |
|||
searchOverall, |
|||
rowDrop |
|||
}, |
|||
mixins: [ |
|||
LoadingMixins, |
|||
], |
|||
props: { |
|||
rowMaxHeight:{ |
|||
type:String, |
|||
default:'calc(90vh - 450px)' |
|||
}, |
|||
// 操作列按钮 |
|||
buttonOperationList_left:{ |
|||
type: Array, |
|||
default: null, |
|||
}, |
|||
// 是否显示明细-字段设置 |
|||
showDetailColumnsSet:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 是否显示明细-筛选 |
|||
showDetailFilters:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
title: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
DrawerLoading: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
drawer: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
dropdownData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
propsData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
tabsDesTions: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
dropdownTabsData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
tableLoading: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
summaryTableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
Butttondata: { |
|||
type: Array, |
|||
default: () => { |
|||
return [{ |
|||
type: 'warning', |
|||
icon: 'el-icon-edit', |
|||
label: '编辑', |
|||
name: 'edit', |
|||
size: 'mini' |
|||
}] |
|||
} |
|||
}, |
|||
selectionTable: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
MaxResultCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
totalCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
currentPage: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
// 详情展现列数,默认为2列展现 |
|||
column: { |
|||
type: Number, |
|||
default: 2 |
|||
}, |
|||
// 详情展示方式,默认水平分布 |
|||
direction: { |
|||
type: String, |
|||
default: 'horizontal' |
|||
}, |
|||
// 详情tabs排序默认 |
|||
firstTabs: { |
|||
type: String, |
|||
default: 'xq' |
|||
} |
|||
|
|||
}, |
|||
computed: { |
|||
dropdownTabs () { |
|||
// 带有特殊扩展tabs页的 |
|||
if (this.dropdownTabsData.length !== 0) { |
|||
return this.dropdownTabsData |
|||
} else { |
|||
// 正常普通 详情,明细,汇总 |
|||
// if (Object.keys(this.propsData).length != 0) { |
|||
if (Object.keys(this.propsData)) { |
|||
this.initDropdownTabsData = [{ |
|||
label: "详情", |
|||
name: 'xq' |
|||
}] |
|||
// 明细可以为空数组,前端分页使用 |
|||
if(this.propsData.details){ |
|||
this.initDropdownTabsData.push({ |
|||
label: "明细", |
|||
name: 'mx' |
|||
}) |
|||
} |
|||
if(this.propsData.summaryDetails && this.propsData.summaryDetails.length > 0){ |
|||
this.initDropdownTabsData.push({ |
|||
label: "汇总", |
|||
name: 'hz' |
|||
}) |
|||
} |
|||
} |
|||
return this.initDropdownTabsData |
|||
} |
|||
}, |
|||
}, |
|||
mounted () { |
|||
this.initDetailHeaderButton() |
|||
}, |
|||
data () { |
|||
return { |
|||
detailHeaderButton:null,//明细-上方按钮 |
|||
detailInfoTableData:null,//明细-查看详情弹窗数据 |
|||
detailInfoTitle:null,//明细-查看详情弹窗title |
|||
otherData:[], // 切换tabs页赋值 |
|||
zdyTableColumns:[], // 自定义表头 |
|||
zdyValue:'', // 自定义展现值 |
|||
// firstTabs:'xq', |
|||
initDropdownTabsData:[ |
|||
{ |
|||
label: "详情", |
|||
name: 'xq' |
|||
}, |
|||
{ |
|||
label: "明细", |
|||
name: 'mx' |
|||
}, |
|||
{ |
|||
label: "汇总", |
|||
name: 'hz' |
|||
} |
|||
], |
|||
//明细列表- 改变当前页 |
|||
oldSkipCount: 1, |
|||
// 明细列表- 全面搜索:当前列表数据请求接口的筛选条件 |
|||
httpOverallSearchData:null, |
|||
//明细列表- 分页参数 |
|||
PageListParams: { |
|||
condition: { |
|||
filters: [] |
|||
}, |
|||
Sorting: "", |
|||
SkipCount: 0, |
|||
MaxResultCount: 20, |
|||
}, |
|||
totalCountForDetail:0, |
|||
//明细-查看主表的连接id |
|||
URLOption_masterId:allUrlOption[this.$route.name].masterId || 'masterId', |
|||
//明细-列表 |
|||
URLOption_detailList:allUrlOption[this.$route.name].detailListURL, |
|||
} |
|||
}, |
|||
methods: { |
|||
// 明细列表 - 获取明细列表(后端分页) |
|||
getDetailList(data,successFn,errorFn){ |
|||
if(data)this.PageListParams.condition.filters = [] |
|||
// 获取明细分页信息 |
|||
let _hasId = false |
|||
this.PageListParams.condition.filters.forEach(item=>{ |
|||
if(item.column == this.URLOption_masterId){ |
|||
_hasId = true |
|||
} |
|||
}) |
|||
if(!_hasId || data){ |
|||
this.PageListParams.condition.filters.push({ |
|||
logic: "And", |
|||
column: this.URLOption_masterId, |
|||
action: "==", |
|||
value: data ? data.id : this.propsData.id |
|||
}) |
|||
} |
|||
this.PageListParams.SkipCount = (this.oldSkipCount - 1) * this.PageListParams.MaxResultCount |
|||
this.Loading.tableLoading = true |
|||
getPageListForDetail(this.PageListParams,this.URLOption_detailList) |
|||
.then(result => { |
|||
this.propsData.details = result.items |
|||
this.totalCountForDetail = result.totalCount |
|||
this.Loading.tableLoading = false |
|||
if(successFn)successFn() |
|||
}) |
|||
.catch(err => { |
|||
this.Loading.tableLoading = false |
|||
if(errorFn)errorFn() |
|||
this.$message.error("数据获取失败") |
|||
}) |
|||
}, |
|||
// 明细列表 - 全面筛选组件查询 |
|||
overallSearchForDetailHandle(options){ |
|||
let _data_primary = options.data_primary, |
|||
_data_moreList = options.data_moreList, |
|||
_option_primary = options.option_primary, |
|||
_vm_quickly = options.vm_quickly, |
|||
_vm_moreList = options.vm_moreList |
|||
|
|||
//普通筛选数据集合 |
|||
let _primary_filters = [] |
|||
_option_primary.forEach(item=>{ |
|||
if(_data_primary[item.prop] && String(_data_primary[item.prop]).length > 0){ |
|||
let _item = { |
|||
action:item.action || '==', |
|||
column:item.prop, |
|||
logic:'And', |
|||
value:String(_data_primary[item.prop]) |
|||
} |
|||
_primary_filters.push(_item) |
|||
} |
|||
}) |
|||
//高级筛选数据集合 |
|||
let _moreList_filters = [] |
|||
_data_moreList.filters.forEach(item=>{ |
|||
if(String(item.column).length > 0 && String(item.value).length > 0){ |
|||
_moreList_filters.push(item) |
|||
} |
|||
}) |
|||
// 全部筛选数据集合 |
|||
let _all_filters = [] |
|||
_all_filters = _primary_filters.concat(_moreList_filters) |
|||
// 调用接口数据配置 |
|||
this.oldSkipCount = 1 |
|||
this.Loading.tableLoading = true; |
|||
this.PageListParams.SkipCount = (this.oldSkipCount - 1) * this.PageListParams.MaxResultCount; |
|||
this.PageListParams.condition = {filters:_all_filters} |
|||
this.getDetailList(null,()=>{ |
|||
//快速搜索清空 |
|||
if(_vm_quickly){_vm_quickly.searchNormalClear(true)} |
|||
//关闭高级筛选 |
|||
if(_vm_moreList){_vm_moreList.changeMoreListShow(false)} |
|||
// 同步当前列表数据请求接口的筛选条件 |
|||
this.httpOverallSearchData = {} |
|||
this.httpOverallSearchData.params = JSON.parse(JSON.stringify(_data_primary)) |
|||
this.httpOverallSearchData.moreList = JSON.parse(JSON.stringify(_data_moreList)) |
|||
},()=>{ |
|||
//快速搜索清空 |
|||
if(_vm_quickly){_vm_quickly.searchNormalClear(true)} |
|||
//关闭高级筛选 |
|||
if(_vm_moreList){_vm_moreList.changeMoreListShow(false)} |
|||
}) |
|||
}, |
|||
// 明细列表 - 全面筛选所有按钮操作集 |
|||
overallSearchClickForDetail(options){ |
|||
let _item = options.item; |
|||
// 普通搜索 + 高级搜索 + 普通重置 + 高级重置 |
|||
if( |
|||
_item.name == 'search' || _item.name == 'moreList-search' || |
|||
_item.name == 'reset' || _item.name == 'moreList-reset' |
|||
){ |
|||
this.overallSearchForDetailHandle(options) |
|||
} |
|||
}, |
|||
// 明细列表 -接收分页组件emit改变当前页 |
|||
alertoldSkipCountForDetail(val) { |
|||
this.oldSkipCount = val; |
|||
this.getDetailList(); |
|||
}, |
|||
// 明细列表 -接收分页组件emit改变每页最大页数 |
|||
alterResultCountForDetail(val) { |
|||
this.PageListParams.MaxResultCount = val; |
|||
this.getDetailList(); |
|||
}, |
|||
// 明细列表 - 排序查询 |
|||
sortChangeForDetail(val) { |
|||
const { |
|||
prop, |
|||
order |
|||
} = val; |
|||
if (!prop || !order) { |
|||
this.PageListParams.Sorting = ""; |
|||
this.oldSkipCount = 1; |
|||
this.getDetailList(); |
|||
return; |
|||
} |
|||
let orderdata = order.substr(0, order.indexOf("c") + 1); |
|||
const props = prop.charAt(0).toUpperCase() + prop.slice(1) |
|||
this.PageListParams.Sorting = props + " " + orderdata.toUpperCase(); |
|||
this.oldSkipCount = 1; |
|||
this.getDetailList(); |
|||
}, |
|||
// 初始化明细-上方按钮 |
|||
initDetailHeaderButton(){ |
|||
this.detailHeaderButton = [] |
|||
if(this.showDetailColumnsSet){this.detailHeaderButton.push(this.defaultFieldSettingBtn())} |
|||
if(this.showDetailFilters){this.detailHeaderButton.push(this.defaultFilterBtn())} |
|||
}, |
|||
// 关闭明细-详情弹窗 |
|||
closeDetailInfo(val){ |
|||
this.displayDialog.detailInfoDialog = val || false |
|||
}, |
|||
// 明细-操作列事件 |
|||
buttonOperationClick_left(row, item, index){ |
|||
// 查看详情 |
|||
if(item.name == "info"){ |
|||
this.displayDialog.detailInfoDialog = true |
|||
this.detailInfoTableData = row |
|||
let _name = allUrlOption[this.$route.name].detailInfoName |
|||
this.detailInfoTitle = _name ? row[_name] + ' 详情' : '详情' |
|||
} |
|||
this.$emit('buttonOperationClick_left',row, item, index) |
|||
}, |
|||
rowDrop(data,type) { |
|||
this.$emit('rowDrop',data,type) |
|||
}, |
|||
handleCommand (command) { |
|||
this.$emit('handleCommand', command) |
|||
}, |
|||
drawerShut () { |
|||
this.closeDetailInfo(false) |
|||
this.$emit('drawerShut', false) |
|||
}, |
|||
tableButtonClick (val) { |
|||
this.$emit('drawerbutton', val) |
|||
}, |
|||
//排序 |
|||
sortChange (data) { |
|||
this.$emit('sortChange', data) |
|||
}, |
|||
//点击selection框 |
|||
handleSelectionChange (val) { |
|||
this.$emit("handleSelectionChange", val) |
|||
}, |
|||
//点击name提交emit打开编辑页面 |
|||
inlineDialog (row) { |
|||
this.$emit("inlineDialog", row) |
|||
}, |
|||
//接收分页组件emit改变每页最大页数 |
|||
alterResultCountDetails (val) { |
|||
this.$emit('alterResultCountDetails', val) |
|||
}, |
|||
//接收分页组件emit改变当前页 |
|||
alertoldSkipCountDetails (val) { |
|||
this.$emit('alertoldSkipCountDetails', val) |
|||
}, |
|||
buttonClick(row) { |
|||
this.$emit("buttonClick", row); |
|||
}, |
|||
// 重新渲染表格 |
|||
doFreshTableLayout(){ |
|||
this.$nextTick(() => { |
|||
if(this.$refs.tablePaginationForMX_Ref && this.$refs.tablePaginationForMX_Ref.doFreshTableLayout){ |
|||
this.$refs.tablePaginationForMX_Ref.doFreshTableLayout() |
|||
} |
|||
}) |
|||
}, |
|||
// tabs 切换页 |
|||
handleClick (val) { |
|||
this.$emit("currenTabsChange", val);//父级获取当前的tab内容 |
|||
this.zdyValue = val.name |
|||
this.dropdownTabsData.forEach( item => { |
|||
if (item.name == val.name) { |
|||
let parent = this.$parent |
|||
parent.tableLoading = true |
|||
// 详情 明细 汇总 |
|||
parent.firstTabs = val.name |
|||
if (val.name == 'xq' || val.name == 'mx' || val.name == 'hz') { |
|||
this.zdyTableColumns = [] |
|||
this.otherData = [] |
|||
parent.tableLoading = false |
|||
} else { |
|||
this.zdyTableColumns = [] |
|||
this.otherData = [] |
|||
// this.firstTabs = val.name |
|||
// 其他自定义tab页 |
|||
// if (item.functionName == 'getListByItemcode') { |
|||
// let params = { |
|||
// itemCode: this.propsData.code |
|||
// } |
|||
// getListByItemcode(params, item.url).then(res => { |
|||
// let zdyTableColumnsJSON = JSON.parse(JSON.stringify(this.$isTableColumns[item.tableColumns])); |
|||
// delete zdyTableColumnsJSON[0].type |
|||
// this.zdyTableColumns = zdyTableColumnsJSON |
|||
// this.otherData = res |
|||
// parent.tableLoading = false |
|||
// }).catch(err => { |
|||
// console.log(err) |
|||
// parent.tableLoading = false |
|||
// }) |
|||
// } |
|||
// else if(item.functionName == "customerDismantleBackFlushNote"){ |
|||
// let zdyTableColumnsJSON = JSON.parse(JSON.stringify(this.$isTableColumns[item.tableColumns])); |
|||
// delete zdyTableColumnsJSON[0].type |
|||
// this.zdyTableColumns = zdyTableColumnsJSON |
|||
// this.otherData = this.propsData.noteAndBackFlushDetails |
|||
// } |
|||
} |
|||
} |
|||
}) |
|||
this.doFreshTableLayout() |
|||
}, |
|||
// 递归 子级层级 |
|||
recursion(val){ |
|||
val.forEach(item => { |
|||
if(item.componentDTOs) { |
|||
item.children = item.componentDTOs |
|||
this.recursion(item.componentDTOs) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
// el-drawer |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,122 @@ |
|||
.el-drawer__wrapper { |
|||
z-index: 10 !important; |
|||
position: absolute; |
|||
left: 32%; |
|||
overflow: visible; |
|||
// height:calc(100% - 28px); |
|||
// top: 14px; |
|||
// right:14px |
|||
|
|||
::v-deep .el-drawer { |
|||
height: 100%; |
|||
overflow: visible; |
|||
box-shadow: 0 8px 10px -5px rgb(0 0 0 / 15%), 0 16px 24px 2px rgb(0 0 0 / 9%), 0 6px 30px 5px rgb(0 0 0 / 7%); |
|||
|
|||
.el-drawer__body { |
|||
width: 100%; |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.drawer-heder { |
|||
display: flex; |
|||
padding: 15px 10px; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
|
|||
.heder-left { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
|
|||
.heder-img { |
|||
width: 40px; |
|||
height: 40px; |
|||
margin-right: 10px; |
|||
} |
|||
|
|||
.header-text { |
|||
padding:0 20px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-between; |
|||
|
|||
span:nth-child(1) { |
|||
color: #333; |
|||
font-size: 22px; |
|||
} |
|||
|
|||
span:nth-child(2) { |
|||
color: #999; |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.Descriptions { |
|||
padding: 0 10px; |
|||
} |
|||
|
|||
.drawer-main { |
|||
// padding-top: 20px; |
|||
flex: 1; |
|||
overflow: hidden; |
|||
// background-color: #efefef; |
|||
padding: 10px 20px 20px 30px; |
|||
border-top: solid 5px #f6f6f6; |
|||
|
|||
.el-tabs { |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
.el-tabs__header{ |
|||
// padding-bottom: 5px ; |
|||
.el-tabs__nav{ |
|||
z-index: auto !important; |
|||
} |
|||
} |
|||
|
|||
.el-tabs__content { |
|||
flex: 1; |
|||
|
|||
.el-tab-pane { |
|||
width: 100%; |
|||
height: 100%; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.el-descriptions-item__label { |
|||
padding-right: 40px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.drawer-Shut { |
|||
width: 35px; |
|||
height: 100px; |
|||
position: absolute; |
|||
top: 200px; |
|||
left: -35px; |
|||
|
|||
.el-button { |
|||
width: 100%; |
|||
height: 100%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
|
|||
::v-deep span { |
|||
font-size: 12px; |
|||
letter-spacing: 10px; |
|||
writing-mode: tb-rl; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
::v-deep .el-tabs__nav-wrap::after{ |
|||
content: unset !important; |
|||
} |
@ -0,0 +1,349 @@ |
|||
<template> |
|||
<el-dialog |
|||
title="高级筛选" |
|||
v-if="displayDialog.screenDialog" |
|||
:visible="true" |
|||
:modal="false" |
|||
top="5vh" |
|||
width="950px" |
|||
> |
|||
<curren-Form |
|||
class="navFilter" |
|||
size="medium" |
|||
labelWidth="0" |
|||
:searchData="screenData" |
|||
:searchOptions="editOptions" |
|||
:searchHandle="editHandle" |
|||
@submitForm="screenFormClick(arguments)" |
|||
> |
|||
<template> |
|||
<el-row :gutter="20"> |
|||
<el-form-item |
|||
v-for="(item, index) in screenData.filters" |
|||
:key="index" |
|||
> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.column'" |
|||
:rules="{ |
|||
required: true, |
|||
message: '请选择筛选对象', |
|||
trigger: 'change', |
|||
}" |
|||
> |
|||
<el-select |
|||
v-model="item.column" |
|||
placeholder="请选择筛选对象" |
|||
:disabled="item.hide" |
|||
:filterable="true" |
|||
@change="filterColumnChange(item)" |
|||
> |
|||
<el-option |
|||
v-for="(item, index) in tableColumnsOptions(tableColumns)" |
|||
:key="index" |
|||
:label="item.label" |
|||
:value=" |
|||
item.showProp |
|||
? item.prop + '.' + item.showProp |
|||
: item.prop |
|||
" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.action'" |
|||
:rules="{ |
|||
required: true, |
|||
message: '请选择条件', |
|||
trigger: 'change', |
|||
}" |
|||
> |
|||
<el-select |
|||
v-model="item.action" |
|||
placeholder="请选择条件" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
> |
|||
<el-option |
|||
v-for="item in options.action" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="7"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.value'" |
|||
:rules="{ |
|||
required: true, |
|||
message: '请输入内容', |
|||
trigger: 'blur', |
|||
}" |
|||
> |
|||
<el-select |
|||
v-if="Object.keys(inputOrSelect(item.column)).length > 0" |
|||
v-model="item.value" |
|||
placeholder="请选择内容" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
:filterable="true" |
|||
@change="inputOrSelect(item.column)" |
|||
clearable |
|||
> |
|||
<el-option |
|||
v-for="item in $staticOptions[ |
|||
inputOrSelect(item.column).filters |
|||
]()" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:disabled="item.disabled" |
|||
:value=" |
|||
typeof item.value == 'string' |
|||
? item.value |
|||
: String(item.value) |
|||
" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
<el-input |
|||
v-else |
|||
v-model="item.value" |
|||
placeholder="请输入内容" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
clearable |
|||
></el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.logic'" |
|||
:rules="{ |
|||
required: true, |
|||
message: '请选择关系', |
|||
trigger: 'change', |
|||
}" |
|||
> |
|||
<el-select |
|||
v-model="item.logic" |
|||
placeholder="请选择关系" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
> |
|||
<el-option |
|||
v-for="item in options.logic" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="1" v-if="!item.hide"> |
|||
<el-button |
|||
type="danger" |
|||
icon="el-icon-minus" |
|||
circle |
|||
size="mini" |
|||
@click="screenDelete(index)" |
|||
></el-button> |
|||
</el-col> |
|||
</el-form-item> |
|||
</el-row> |
|||
</template> |
|||
<div class="screen-push"> |
|||
<span @click="screenPush">+ 添加筛选条件</span> |
|||
</div> |
|||
</curren-Form> |
|||
</el-dialog> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
props: { |
|||
//displayDialog显示 |
|||
displayDialog: { |
|||
type: Object, |
|||
default: () => { |
|||
return { |
|||
screenDialog: false |
|||
} |
|||
} |
|||
}, |
|||
// 筛选数据 |
|||
screenData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
} |
|||
}, |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//验证规则 |
|||
editOptions: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
//挂载到body |
|||
modalAppendToBody: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return true |
|||
} |
|||
}, |
|||
// 筛选条件自定义(等于/不等于/大于/小于等数据) |
|||
filterActionOptions:{ |
|||
type: Array, |
|||
default: null |
|||
} |
|||
// //按钮 |
|||
// editHandle: { |
|||
// type: Array, |
|||
// default: () => { |
|||
// return [] |
|||
// } |
|||
// } |
|||
}, |
|||
watch: { |
|||
// InputOrSelect (val) { |
|||
// if (val) { |
|||
// this.InputOrSelectHide = val |
|||
// } |
|||
// } |
|||
}, |
|||
computed: { |
|||
}, |
|||
data() { |
|||
return { |
|||
editHandle: [ |
|||
{ float: 'left', label: '重置', type: 'danger', name: 'reset' }, |
|||
{ label: "取消", name: "cancel" }, |
|||
{ label: "确定", type: "primary", name: "determine" }, |
|||
], |
|||
options: { |
|||
action: [{ |
|||
value: '==', |
|||
label: '等于' |
|||
}, { |
|||
value: '!=', |
|||
label: '不等于' |
|||
}, { |
|||
value: '>', |
|||
label: '大于' |
|||
}, { |
|||
value: '<', |
|||
label: '小于' |
|||
}, { |
|||
value: '>=', |
|||
label: '大于等于' |
|||
}, { |
|||
value: '<=', |
|||
label: '小于等于' |
|||
}, { |
|||
value: 'Like', |
|||
label: '包含' |
|||
}, { |
|||
value: 'NotLike', |
|||
label: '不包含' |
|||
}, |
|||
// { |
|||
// value: 'In', |
|||
// label: '包含' |
|||
// }, { |
|||
// value: 'NotIn', |
|||
// label: '不包含' |
|||
// } |
|||
], |
|||
logic: [ |
|||
{ |
|||
value: 'And', |
|||
label: '并且' |
|||
}, |
|||
{ |
|||
value: 'Or', |
|||
label: '或者' |
|||
} |
|||
], |
|||
}, |
|||
rules: |
|||
{ |
|||
column: [ |
|||
{ required: true, message: '请选择筛选对象', trigger: 'change' } |
|||
], |
|||
// value: [ |
|||
// { required: true, message: '请输入内容', trigger: 'change' } |
|||
// ], |
|||
action: [ |
|||
{ required: true, message: '请选择条件', trigger: 'change' } |
|||
], |
|||
logic: [ |
|||
{ required: true, message: '请选择关系', trigger: 'change' } |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
created() { |
|||
// this.form.exerciseType = this.typeOptions[0].value |
|||
|
|||
}, |
|||
mounted() { |
|||
if(this.filterActionOptions)this.options.action = this.filterActionOptions |
|||
}, |
|||
methods: { |
|||
// 选择对象更改 |
|||
filterColumnChange(item){ |
|||
// 筛选对象更改时候,清空value值 |
|||
item.value = "" |
|||
}, |
|||
tableColumnsOptions(val) { |
|||
const data = JSON.parse(JSON.stringify(val)); |
|||
let num = 0 |
|||
val.forEach((item, index) => { |
|||
if (item.showProp) { |
|||
data.splice(index - num, 1) |
|||
num++ |
|||
} |
|||
}) |
|||
return data |
|||
}, |
|||
inputOrSelect(val) { |
|||
let data |
|||
if (val) { |
|||
this.tableColumns.forEach((key) => { |
|||
if (val == key.prop) { |
|||
if (key.filters) { |
|||
data = key |
|||
} else { |
|||
data = {} |
|||
} |
|||
} |
|||
}) |
|||
} else { |
|||
data = {} |
|||
} |
|||
return data |
|||
}, |
|||
screenFormClick(val) { |
|||
this.$emit("screenFormClick", val) |
|||
}, |
|||
screenDelete(val) { |
|||
this.$emit("screenDelete", val) |
|||
}, |
|||
screenPush() { |
|||
this.$emit("screenPush") |
|||
} |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,46 @@ |
|||
.el-dialog__wrapper { |
|||
width:100% !important; |
|||
} |
|||
|
|||
::v-deep .el-dialog { |
|||
overflow: hidden; |
|||
overflow-x: auto; |
|||
} |
|||
|
|||
::v-deep .navFilter { |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 100%; |
|||
height: 100%; |
|||
max-height: 50vh; |
|||
|
|||
.el-form { |
|||
flex: 1; |
|||
padding-left: 100px; |
|||
padding-right: 100px; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-content: flex-start; |
|||
flex-wrap: wrap; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
.screen-push { |
|||
width: 100%; |
|||
padding-left: 5px; |
|||
color: rgb(64, 158, 255); |
|||
|
|||
span { |
|||
cursor: pointer; |
|||
|
|||
&:hover { |
|||
color: blue; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.formButton { |
|||
padding: 20px 20px 20px 0; |
|||
} |
|||
} |
@ -0,0 +1,107 @@ |
|||
<template> |
|||
<div class="tableNavBtnsContent"> |
|||
<div class="tableNavLeftBtns"> |
|||
<!-- 左侧按钮 --> |
|||
<innerButton :Butttondata="buttonsLeft" @tableButtonClick="tableButtonClick"></innerButton> |
|||
</div> |
|||
<div class="tableNavRightBtns"> |
|||
<!-- 快速搜索 --> |
|||
<searchNormal |
|||
ref="quicklySearchDomRef" |
|||
v-if="quicklySearchOption" |
|||
:searchNormalOption="quicklySearchOption" |
|||
@searchNormalClick="quicklySearchClick" |
|||
@searchNormalClear="quicklySearchClear" |
|||
></searchNormal> |
|||
<!-- 右侧按钮 --> |
|||
<innerButton :Butttondata="buttonsRight" @tableButtonClick="tableButtonClick"></innerButton> |
|||
</div> |
|||
<slot></slot> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import innerButton from "./innerButton.vue" |
|||
import searchNormal from "@/components/searchNormal/index.vue" |
|||
import permission from "@/directive/permission/index" |
|||
export default { |
|||
directives: { permission }, |
|||
components:{ |
|||
innerButton, |
|||
searchNormal |
|||
}, |
|||
props: { |
|||
Butttondata: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
quicklySearchOption: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 按钮整体靠右 |
|||
buttonsAllIsRight:{ |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
buttonsLeft:null,//左侧按钮数据 |
|||
buttonsRight:null,//右侧按钮数据 |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.initButtonsData() |
|||
}, |
|||
methods:{ |
|||
// 按钮数据处理(左右分开处理) |
|||
initButtonsData(){ |
|||
this.buttonsLeft = [] |
|||
this.buttonsRight = [] |
|||
if(this.buttonsAllIsRight){ |
|||
this.buttonsRight = this.Butttondata |
|||
return |
|||
} |
|||
this.Butttondata.forEach(item=>{ |
|||
if(item.float && item.float == 'right'){ |
|||
this.buttonsRight.push(item) |
|||
}else{ |
|||
this.buttonsLeft.push(item) |
|||
} |
|||
}) |
|||
}, |
|||
// 按钮事件 |
|||
tableButtonClick (val,item) { |
|||
this.$emit('tableButtonClick', val,item) |
|||
}, |
|||
// 搜索 |
|||
quicklySearchClick(val,option){ |
|||
this.$emit('quicklySearchClick', val,option) |
|||
}, |
|||
// 清除搜索 |
|||
quicklySearchClear(val,option){ |
|||
this.$emit('quicklySearchClear', val,option) |
|||
}, |
|||
// 获取快速搜索的节点,便于其他组件清空搜索值 |
|||
getQuicklySearchDom(){ |
|||
return this.$refs.quicklySearchDomRef |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
.tableNavBtnsContent{ |
|||
display: flex; |
|||
justify-content: space-between; |
|||
|
|||
.tableNavRightBtns{ |
|||
display: flex; |
|||
margin-left: 10px; |
|||
.currenButton .el-button { |
|||
margin-left: 10px !important; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,66 @@ |
|||
<template> |
|||
<div class="currenButton clearfix"> |
|||
<el-button |
|||
v-for="(item, index) in Butttondata" :key="index" |
|||
v-show="typeof item.hide == 'function' ? !item.hide() : !item.hide" |
|||
:type="item.type" |
|||
:icon="item.icon" |
|||
:plain="item.plain" |
|||
:round="item.round" |
|||
:circle="item.circle" |
|||
:size="item.size" |
|||
:style="{ |
|||
float:item.float, |
|||
background:item.background, |
|||
borderColor:item.background, |
|||
}" |
|||
:class="item.class" |
|||
@click="tableButtonClick(item.name,item)" |
|||
v-permission="item.permission || []" |
|||
>{{ item.label }}</el-button> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import permission from "@/directive/permission/index" |
|||
export default { |
|||
directives: { permission }, |
|||
props: { |
|||
Butttondata: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
}, |
|||
mounted(){ |
|||
window.addEventListener('setItemEvent', (item) => { |
|||
if (item.key.indexOf('tableColumns') > -1) { |
|||
this.initButtonType(item) |
|||
} |
|||
}) |
|||
}, |
|||
methods:{ |
|||
initButtonType(changeItem){ |
|||
let _num = 0 |
|||
let _new = JSON.parse(changeItem.newValue) |
|||
_new.forEach((item) => { |
|||
if(item.istrue)_num ++ |
|||
}) |
|||
this.Butttondata.forEach(item=>{ |
|||
// 监听本地缓存【字段配置】缓存,更改按钮type |
|||
if(item.name == 'field'){ |
|||
return item.type = (_num >= _new.length) ? '' : 'warning'; |
|||
} |
|||
}) |
|||
}, |
|||
tableButtonClick (val,item) { |
|||
this.$emit('tableButtonClick', val,item) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.el-button{ |
|||
margin-left: 10px; |
|||
} |
|||
</style> |
@ -0,0 +1,181 @@ |
|||
<template> |
|||
<el-descriptions |
|||
class="currenDescriptionsPage" |
|||
:title="title" |
|||
:column="column" |
|||
:direction="direction" |
|||
:colon="colon" |
|||
:border="border" |
|||
v-loading="currenDescriptionsLoading" |
|||
> |
|||
<template> |
|||
<el-descriptions-item |
|||
:label="item.label" |
|||
v-for="(item, index) in tabsDesTions" |
|||
:key="index" |
|||
:labelStyle="{'text-align': 'right','padding-right':'10px'}" |
|||
> |
|||
<span v-if="item.type && item.type == 'date'">{{ |
|||
propsData[item.prop] | formatOnlyDate |
|||
}}</span> |
|||
<span v-else-if="item.type && item.type == 'dateTime'">{{ |
|||
propsData[item.prop] | formatDate |
|||
}}</span> |
|||
<span v-else-if="item.type && item.type == 'objectDateTime'">{{ |
|||
propsData[item.prop]?propsData[item.prop][item.showProp]:"" | formatDate |
|||
}}</span> |
|||
<span v-else-if="item.type && item.type == 'object'"> |
|||
{{ propsData[item.prop]?propsData[item.prop][item.showProp]:"" }} |
|||
</span> |
|||
<span v-else-if="item.type && item.type == 'filter'"> |
|||
{{ propsData[item.prop] | trigger(item.filters,"label", item.dictType) }} |
|||
</span> |
|||
<span v-else-if="item.type && item.type == 'objectFilter'"> |
|||
{{ propsData[item.prop]?propsData[item.prop][item.showProp]:false | trigger(item.filters,"label") }} |
|||
</span> |
|||
<span v-else-if="item.type && item.type == 'percent'"> |
|||
{{ propsData[item.prop] +'%' }} |
|||
</span> |
|||
<span v-else-if="item.type && item.type == 'uploadPictureCard'"> |
|||
<div id="uploadPictureCardRef">{{propsData[item.prop] | formatDatePicture}}</div> |
|||
</span> |
|||
<span v-else-if="item.type == 'filterList'" > |
|||
{{ propsData[item.prop] | triggerList(item.filters, "label") }} |
|||
</span> |
|||
<!-- 文本域 --> |
|||
<span v-else-if="item.type == 'textarea'"> |
|||
<template> |
|||
<el-input |
|||
:type="item.type" |
|||
v-model="propsData[item.prop]" |
|||
:rows="item.rows" |
|||
:readonly="item.readonly" |
|||
></el-input> |
|||
</template> |
|||
</span> |
|||
<span v-else>{{ propsData[item.prop] ? propsData[item.prop] + "" : propsData[item.prop] }}</span> |
|||
</el-descriptions-item> |
|||
</template> |
|||
<el-descriptions-item |
|||
v-for="item in descriptionsData" |
|||
:label="item.label" |
|||
:key="item.label" |
|||
>{{ item.data }}</el-descriptions-item |
|||
> |
|||
<slot></slot> |
|||
</el-descriptions> |
|||
</template> |
|||
<script> |
|||
import { parseTime } from "@/utils/formatTime" |
|||
import { formatTimeStrToStr } from "@/utils/formatTime" |
|||
import { fileStorage } from "@/api/wms-api" |
|||
|
|||
let that |
|||
export default { |
|||
name:'curren-descriptions', |
|||
data () { |
|||
return { |
|||
// 临时存储文件编号 防止重复请求图片 |
|||
blobName: '', |
|||
currenDescriptionsLoading: false |
|||
} |
|||
}, |
|||
beforeCreate () { |
|||
that = this; |
|||
}, |
|||
filters: { |
|||
formatDate (time) { |
|||
if (time == null) { |
|||
return '-' |
|||
} |
|||
return formatTimeStrToStr(time) |
|||
}, |
|||
formatOnlyDate (time) { |
|||
var date = new Date(time); |
|||
return parseTime(date).substring(0,10) |
|||
}, |
|||
formatDatePicture(val) { |
|||
if (val !== undefined && that.blobName !== val) { |
|||
that.blobName = val |
|||
that.currenDescriptionsLoading = true |
|||
fileStorage({blobName: val}).then(res => { |
|||
var byteString = atob(res.bytes) |
|||
var arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组 |
|||
var intArray = new Uint8Array(arrayBuffer) // 创建视图 |
|||
for (var i = 0; i < byteString.length; i++) { |
|||
intArray[i] = byteString.charCodeAt(i) |
|||
} |
|||
const blob = new Blob([intArray], { type: '' }) |
|||
var img = new Image() |
|||
img.width="100" |
|||
img.height="100" |
|||
img.src = URL.createObjectURL(blob) |
|||
var otest = document.getElementById("uploadPictureCardRef") |
|||
otest.innerHTML = '' |
|||
otest.appendChild(img) |
|||
that.currenDescriptionsLoading = false |
|||
}).catch(err => { |
|||
console.log(err) |
|||
that.currenDescriptionsLoading = false |
|||
}) |
|||
} |
|||
} |
|||
}, |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
colon: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
column: { |
|||
type: Number, |
|||
default: 1 |
|||
}, |
|||
border: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
descriptionsData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
direction: { |
|||
type: String, |
|||
default: 'horizontal' |
|||
}, |
|||
tabsDesTions: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
propsData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
} |
|||
|
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
.currenDescriptionsPage{ |
|||
th{ |
|||
min-width: 200px !important; |
|||
width: auto; |
|||
} |
|||
td{ |
|||
span{ |
|||
display: inline-block; |
|||
max-height: 150px; |
|||
overflow: auto; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,174 @@ |
|||
<template> |
|||
<el-descriptions |
|||
class="currenDescriptionsPage" |
|||
:title="title" |
|||
:column="column" |
|||
:direction="direction" |
|||
:colon="colon" |
|||
:border="border" |
|||
v-loading="currenDescriptionsLoading" |
|||
> |
|||
<template> |
|||
<el-descriptions-item |
|||
:label="item.label" |
|||
v-for="(item, index) in tabsDesTions" |
|||
:key="index" |
|||
:labelStyle="{'text-align': 'right','padding-right':'10px'}" |
|||
> |
|||
<!-- 时间转换 --> |
|||
<span v-if="item.apiBaseType && item.apiBaseType == 'datetime'">{{ |
|||
propsData[item.prop] | formatDate |
|||
}}</span> |
|||
<!-- 枚举 --> |
|||
<span v-else-if="item.isEnums"> |
|||
{{ initApiEnumList(item,propsData[item.prop]) }} |
|||
</span> |
|||
<!-- 布尔 --> |
|||
<span v-else-if="item.apiBaseType == 'boolean'"> |
|||
{{ propsData[item.prop] ? '是' : '否' }} |
|||
</span> |
|||
<!-- 数值 --> |
|||
<span v-else-if="item.apiBaseType == 'number'"> |
|||
{{ propsData[item.prop] }} |
|||
</span> |
|||
<span v-else> |
|||
{{ propsData[item.prop] ? propsData[item.prop] + "" : propsData[item.prop] }} |
|||
</span> |
|||
</el-descriptions-item> |
|||
</template> |
|||
<el-descriptions-item |
|||
v-for="item in descriptionsData" |
|||
:label="item.label" |
|||
:key="item.label" |
|||
>{{ item.data }}</el-descriptions-item |
|||
> |
|||
<slot></slot> |
|||
</el-descriptions> |
|||
</template> |
|||
<script> |
|||
import { parseTime } from "@/utils/formatTime" |
|||
import { formatTimeStrToStr } from "@/utils/formatTime" |
|||
import { fileStorage } from "@/api/wms-api" |
|||
|
|||
let that |
|||
export default { |
|||
name:'curren-descriptions', |
|||
data () { |
|||
return { |
|||
// 临时存储文件编号 防止重复请求图片 |
|||
blobName: '', |
|||
currenDescriptionsLoading: false |
|||
} |
|||
}, |
|||
beforeCreate () { |
|||
that = this; |
|||
}, |
|||
filters: { |
|||
formatDate (time) { |
|||
if (time == null) { |
|||
return '-' |
|||
} |
|||
return formatTimeStrToStr(time) |
|||
}, |
|||
formatOnlyDate (time) { |
|||
var date = new Date(time); |
|||
return parseTime(date).substring(0,10) |
|||
}, |
|||
formatDatePicture(val) { |
|||
if (val !== undefined && that.blobName !== val) { |
|||
that.blobName = val |
|||
that.currenDescriptionsLoading = true |
|||
fileStorage({blobName: val}).then(res => { |
|||
var byteString = atob(res.bytes) |
|||
var arrayBuffer = new ArrayBuffer(byteString.length) // 创建缓冲数组 |
|||
var intArray = new Uint8Array(arrayBuffer) // 创建视图 |
|||
for (var i = 0; i < byteString.length; i++) { |
|||
intArray[i] = byteString.charCodeAt(i) |
|||
} |
|||
const blob = new Blob([intArray], { type: '' }) |
|||
var img = new Image() |
|||
img.width="100" |
|||
img.height="100" |
|||
img.src = URL.createObjectURL(blob) |
|||
var otest = document.getElementById("uploadPictureCardRef") |
|||
otest.innerHTML = '' |
|||
otest.appendChild(img) |
|||
that.currenDescriptionsLoading = false |
|||
}).catch(err => { |
|||
console.log(err) |
|||
that.currenDescriptionsLoading = false |
|||
}) |
|||
} |
|||
} |
|||
}, |
|||
props: { |
|||
title: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
colon: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
column: { |
|||
type: Number, |
|||
default: 1 |
|||
}, |
|||
border: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
descriptionsData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
direction: { |
|||
type: String, |
|||
default: 'horizontal' |
|||
}, |
|||
tabsDesTions: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
propsData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
} |
|||
|
|||
}, |
|||
methods:{ |
|||
// 转义枚举值 |
|||
initApiEnumList(item,data){ |
|||
let _item_enumList = {} |
|||
if(item.enums_list){ |
|||
item.enums_list.forEach((item,key)=>{ |
|||
_item_enumList[item.value] = item.label |
|||
}) |
|||
} |
|||
return _item_enumList[data] || '未定义' |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
.currenDescriptionsPage{ |
|||
th{ |
|||
min-width: 200px !important; |
|||
width: auto; |
|||
} |
|||
td{ |
|||
span{ |
|||
display: inline-block; |
|||
max-height: 150px; |
|||
overflow: auto; |
|||
min-width: 200px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,888 @@ |
|||
<template> |
|||
<div class="currenForm"> |
|||
<!-- @submit.native.prevent 阻止form只有一个input输入框回车触发提交事件 --> |
|||
<el-form |
|||
ref="form" |
|||
:size="size" |
|||
:label-position="labelPosition" |
|||
:inline="inline" |
|||
:label-width="labelWidth" |
|||
:rules="rules" |
|||
:model="searchData" |
|||
@submit.native.prevent |
|||
v-if="!hide ? true : false" |
|||
> |
|||
<el-row :gutter="40"> |
|||
<el-col |
|||
:span="item.colSpan" |
|||
v-for="(item, index) in searchForm" |
|||
:key="index" |
|||
> |
|||
<el-form-item |
|||
:label="item.label" |
|||
:prop="item.showProp ? item.prop + '.' + item.showProp : item.prop" |
|||
v-if="!item.hide ? true : false" |
|||
> |
|||
<!-- 输入框 onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<!-- :onkeyup="item.onkeyup" --> |
|||
<el-input |
|||
v-if="item.type === 'input'" |
|||
v-model="searchData[item.prop]" |
|||
:maxlength="item.maxlength" |
|||
:onkeyup="itemOnKeyUp(item,searchData[item.prop])" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@change="changeInput(item.prop,$event)" |
|||
@clear="clearInput(item.prop,$event)" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
<!-- 输入框(有上下增加按钮框) onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<el-input-number |
|||
v-if="item.type === 'number'" |
|||
v-model="searchData[item.prop]" |
|||
:onkeyup="item.onkeyup" |
|||
:disabled="Boolean(item.disabled)" |
|||
@change="changeInput(item.prop,$event)" |
|||
@clear="clearInput(item.prop,$event)" |
|||
:min="item.min" |
|||
:max="item.max" |
|||
:precision="item.precision" |
|||
class="inputNameberClass" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input-number> |
|||
<!-- 输入框(只能输入数字) onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<!-- oninput="value=value.replace(/[^\d]/g,'')" --> |
|||
<el-input |
|||
v-if="item.type === 'inputNumber'" |
|||
v-model="searchData[item.prop]" |
|||
:maxlength="item.maxlength" |
|||
:onkeyup="typeNumberOnkeyup(item,searchData[item.prop])" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@change="changeInput(item.prop,$event)" |
|||
@clear="clearInput(item.prop,$event)" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
<!-- 对象输入框 --> |
|||
<el-input |
|||
v-if="item.type === 'objectInput'" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:maxlength="item.maxlength" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
<!-- 对象富文本框 --> |
|||
<el-input |
|||
v-if="item.type === 'objectTextarea'" |
|||
type="textarea" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
></el-input> |
|||
<!--查询下拉--> |
|||
<el-autocomplete |
|||
v-if="item.type === 'autocomplete'" |
|||
class="inline-input" |
|||
style="width: 100%" |
|||
v-model="searchData[item.prop]" |
|||
:disabled="Boolean(item.disabled)" |
|||
:fetch-suggestions=" |
|||
(queryString, cb) => { |
|||
querySearch(queryString, cb, item); |
|||
} |
|||
" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@select="handleSelect($event, item)" |
|||
> |
|||
<el-button |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
v-if="item.click" |
|||
@click="item.click(item)" |
|||
style="color: #1890ff; background-color: #ffffff" |
|||
></el-button> |
|||
</el-autocomplete> |
|||
<!--对象查询下拉--> |
|||
<el-autocomplete |
|||
v-if="item.type === 'objectAutocomplete'" |
|||
class="inline-input" |
|||
style="width: 100%" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:fetch-suggestions=" |
|||
(queryString, cb) => { |
|||
querySearch(queryString, cb, item); |
|||
} |
|||
" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@select="handleSelect($event, item)" |
|||
> |
|||
<el-button |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
v-if="item.click" |
|||
@click="item.click(item)" |
|||
style="color: #1890ff; background-color: #ffffff" |
|||
></el-button> |
|||
</el-autocomplete> |
|||
<!-- 文本框 --> |
|||
<el-input |
|||
v-if="item.type === 'textarea'" |
|||
:type="item.type" |
|||
v-model="searchData[item.prop]" |
|||
:rows="item.rows" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:maxlength="item.maxlength" |
|||
show-word-limit |
|||
></el-input> |
|||
<!-- 下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'select'" |
|||
v-model="searchData[item.prop]" |
|||
:loading="selectLoading" |
|||
:clearable="item.clearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled)" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
style="width: 100%" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@change="changeSelect(item.prop,$event)" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
item.userOptions" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- 链接接口filter下拉框 --> |
|||
<filterSelect |
|||
v-if="item.type === 'filterSelect'" |
|||
:selectModel="searchData[item.prop]" |
|||
:selectItem="item" |
|||
@filterOptionSelectHandle="filterOptionSelectHandle" |
|||
@filterClearHandle="filterClearHandle(item)" |
|||
></filterSelect> |
|||
<!--对象下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'objectSelect'" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:loading="selectLoading" |
|||
:clearable="item.clearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled)" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
style="width: 100%" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
searchOptions['options']" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- 下拉框多选 --> |
|||
<el-select |
|||
v-if="item.type === 'selectArray'" |
|||
v-model="searchData[item.prop]" |
|||
multiple |
|||
:placeholder="item.placeholder || '请选择' + item.label" |
|||
style="width: 100%" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
item.searchOptions" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- 单选 --> |
|||
<el-radio-group |
|||
v-if="item.type === 'radio'" |
|||
v-model="searchData[item.prop]" |
|||
:disabled="Boolean(item.disabled)" |
|||
@change="radioChange(item.prop,$event)" |
|||
> |
|||
<el-radio |
|||
v-for="ra in searchOptions[item.radio]" |
|||
:label="ra.id" |
|||
:key="ra.value" |
|||
>{{ ra.label }}</el-radio |
|||
> |
|||
</el-radio-group> |
|||
<!-- 单选按钮 --> |
|||
<el-radio-group |
|||
v-if="item.type === 'radioButton'" |
|||
v-model="searchData[item.prop]" |
|||
@change="item.change && item.change(searchData[item.prop])" |
|||
> |
|||
<el-radio-button |
|||
v-for="ra in searchOptions[item.radios]" |
|||
:label="ra.value" |
|||
:key="ra.value" |
|||
>{{ ra.label }}</el-radio-button |
|||
> |
|||
</el-radio-group> |
|||
<!-- 复选框 --> |
|||
<el-checkbox v-if="item.type === 'checkbox'" :indeterminate="indeterminate" v-model="item.checkAll" @change="handleCheckAllChange($event,item)">全选</el-checkbox> |
|||
<el-checkbox-group |
|||
v-if="item.type === 'checkbox'" |
|||
v-model="searchData[item.prop]" |
|||
@change="handleCheckedCitiesChange($event,item)" |
|||
> |
|||
<el-checkbox |
|||
v-for="ch in searchOptions[item.checkboxs]" |
|||
:label="ch" |
|||
:key="ch" |
|||
>{{ ch }}</el-checkbox |
|||
> |
|||
</el-checkbox-group> |
|||
<!-- 日期 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'date'" |
|||
v-model="searchData[item.prop]" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '选择日期'" |
|||
value-format="yyyy-MM-dd" |
|||
></el-date-picker> |
|||
<!-- 时间 --> |
|||
<el-time-picker |
|||
v-if="item.type === 'time'" |
|||
v-model="searchData[item.prop]" |
|||
:placeholder="item.placeholder || '选择时间'" |
|||
style="width: 100%" |
|||
:picker-options="{ |
|||
selectableRange: '00:00:00 - 23:59:00', |
|||
}" |
|||
:disabled="Boolean(item.disabled)" |
|||
format="HH:mm" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
></el-time-picker> |
|||
<!-- 日期时间 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'dateTime'" |
|||
type="datetime" |
|||
v-model="searchData[item.prop]" |
|||
:placeholder="item.placeholder || '选择日期时间'" |
|||
style="width: 100%" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
<!-- 日期时间 日期有限制 选择范围:当前天及以后--> |
|||
<el-date-picker |
|||
v-if="item.type === 'dateTimelimit'" |
|||
type="datetime" |
|||
v-model="searchData[item.prop]" |
|||
:placeholder="item.placeholder || '选择日期时间'" |
|||
style="width: 100%" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
:pickerOptions="endDateTimeLimitPickerOptions()" |
|||
></el-date-picker> |
|||
<!-- 对象日期时间 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'objectDateTime'" |
|||
type="datetime" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:placeholder="item.placeholder || '选择日期'" |
|||
style="width: 100%" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
<!--开始时间结束时间--> |
|||
<div |
|||
class="RangeDateTime" |
|||
v-if="item.type === 'rangeDateTime'" |
|||
style="width: 100%; height: 100%" |
|||
> |
|||
<el-col :span="10"> |
|||
<el-form-item :prop="item.prop + '.' + item.startDate"> |
|||
<el-date-picker |
|||
type="datetime" |
|||
:placeholder="item.placeholder || '开始日期'" |
|||
v-model="searchData[item.prop][item.startDate]" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled)" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:pickerOptions=" |
|||
startPickerOptions(searchData[item.prop][item.endDate]) |
|||
" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col class="line" :span="4">-</el-col> |
|||
<el-col :span="10"> |
|||
<el-form-item :prop="item.prop + '.' + item.endDate"> |
|||
<el-date-picker |
|||
type="datetime" |
|||
:placeholder="item.placeholder || '结束日期'" |
|||
v-model="searchData[item.prop][item.endDate]" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled)" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:pickerOptions=" |
|||
endPickerOptions(searchData[item.prop][item.startDate]) |
|||
" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
</el-col> |
|||
</div> |
|||
<!-- 开关 --> |
|||
<el-switch |
|||
v-if="item.type === 'switch'" |
|||
v-model="searchData[item.prop]" |
|||
></el-switch> |
|||
<!--文件上传--> |
|||
<currenUpload |
|||
v-if="item.type === 'upload'" |
|||
:limit="item.limit" |
|||
:beforeUpload="beforeAvatarUpload" |
|||
:searchData="searchData[item.prop]" |
|||
@httpRequestfiles="httpRequestfiles($event, item.prop)" |
|||
@handleRemove="handleRemove($event, item.prop)" |
|||
> |
|||
</currenUpload> |
|||
<!--文件上传——列表形式--> |
|||
<currenUploadList |
|||
v-if="item.type === 'uploadList'" |
|||
:limit="item.limit" |
|||
:picExt="item.picExt" |
|||
:searchData="searchData[item.prop]" |
|||
@uploadListView="uploadListView" |
|||
@changeUpload="changeUpload($event, item)" |
|||
@handleRemove="handleRemove($event, item.prop)" |
|||
> |
|||
</currenUploadList> |
|||
<!-- 缩略图上传 --> |
|||
<currenUploadPictureCard |
|||
v-if="item.type === 'uploadPictureCard'" |
|||
:limit="item.limit" |
|||
:multiple="item.multiple" |
|||
:picExt="item.picExt" |
|||
:searchData="searchData[item.prop]" |
|||
@changeUpload="changeUpload($event, item)" |
|||
@handleRemove="handleRemove($event, item.prop)" |
|||
> |
|||
</currenUploadPictureCard> |
|||
<el-button |
|||
v-if="item.type === 'button'" |
|||
type="primary" |
|||
size="mini" |
|||
@click="item.click(item)" |
|||
> |
|||
{{item.buttonText}} |
|||
</el-button> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
<slot></slot> |
|||
</el-form> |
|||
<div v-if="isHandle" class="formButton"> |
|||
<!-- :style="{float:item.float}" 自定义按钮显示位置 --> |
|||
<el-button |
|||
v-for="(item, index) in searchHandle" |
|||
:key="item.label" |
|||
:type="item.type" |
|||
:size="item.size || size" |
|||
:loading="loading" |
|||
:style="{float:item.float}" |
|||
@click="submitForm(index,item)" |
|||
>{{ item.label }}</el-button |
|||
> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenUpload from "@/components/currenUpload"; |
|||
import currenUploadList from "@/components/currenUploadList"; |
|||
import currenUploadPictureCard from "@/components/currenUploadPictureCard"; |
|||
import filterSelect from "@/components/filterSelect" |
|||
import { getMatchRegConformValue } from "@/utils/index" |
|||
export default { |
|||
name: "currenForm", |
|||
components: { |
|||
currenUpload, |
|||
currenUploadList, |
|||
currenUploadPictureCard, |
|||
filterSelect |
|||
}, |
|||
props: { |
|||
loading: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
labelPosition: { |
|||
type: String, |
|||
default: "right", |
|||
}, |
|||
isHandle: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
inline: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
labelWidth: { |
|||
type: String, |
|||
default: "140px", |
|||
}, |
|||
size: { |
|||
type: String, |
|||
default: "mini", |
|||
}, |
|||
searchForm: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
searchHandle: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
searchData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
searchOptions: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
rules: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
formSpan: { |
|||
type: Number, |
|||
default: 24, |
|||
}, |
|||
hide: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
restaurants: [], |
|||
indeterminate: false, |
|||
selectLoading: false, |
|||
}; |
|||
}, |
|||
computed: { |
|||
startPickerOptions() { |
|||
return function (val) { |
|||
return { |
|||
disabledDate(time) { |
|||
if (val) { |
|||
return ( |
|||
// time.getTime() > Date.now() || |
|||
// time.getTime() > new Date(that.CreateFormData.endDate).getTime() |
|||
time.getTime() > val |
|||
); |
|||
} |
|||
// return time.getTime() > Date.now(); //实现1效果 |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
endPickerOptions() { |
|||
// const that = this; |
|||
return function (val) { |
|||
return { |
|||
disabledDate(time) { |
|||
if (val) { |
|||
return ( |
|||
// time.getTime() > Date.now() || |
|||
// time.getTime() < new Date(that.CreateFormData.startDate).getTime() |
|||
time.getTime() < val |
|||
); |
|||
} |
|||
// return time.getTime() > Date.now(); //实现1效果 |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
// 日期时间组件,选择范围:当前天及以后 |
|||
endDateTimeLimitPickerOptions() { |
|||
return function () { |
|||
return { |
|||
disabledDate(time) { |
|||
return ( |
|||
time.getTime() < Date.now() - 8.64e7 |
|||
); |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
selectOptions() { |
|||
return (val) => { |
|||
if (val) { |
|||
let options = this.$staticOptions[val]; |
|||
if (options) { |
|||
return options(); |
|||
} else { |
|||
return []; |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
}; |
|||
}, |
|||
}, |
|||
mounted() { |
|||
// 单选 , 默认设置 |
|||
this.searchForm.forEach(item => { |
|||
if (item.type === 'radio') { |
|||
this.searchData[item.prop] = item.value + '' |
|||
} |
|||
if (item.type === 'checkbox') { |
|||
this.searchData[item.prop].push(item.value) |
|||
} |
|||
}) |
|||
}, |
|||
methods: { |
|||
// type=input情况下,框实时校验 |
|||
itemOnKeyUp(item,value){ |
|||
if(item.onkeyup){ |
|||
return item.onkeyup() |
|||
}else{ |
|||
if(value && item.validType){ |
|||
this.searchData[item.prop]=getMatchRegConformValue(item.validType,value,item.pointNumberFixed) |
|||
} |
|||
} |
|||
}, |
|||
// 数字类型input框onkeyup最大最小值处理 |
|||
typeNumberOnkeyup(item,value){ |
|||
if(value){ |
|||
// 添加pointNumberFixed 可以输入小数 |
|||
if (item.pointNumberFixed) { |
|||
let _fixed = item.pointNumberFixed ? Number(item.pointNumberFixed) : 100 |
|||
let reg = new RegExp(`\\d+\\.?\\d{0,${_fixed}}`); |
|||
let _match = String(value).match(reg) |
|||
this.searchData[item.prop] = _match ? _match[0] : _match |
|||
} else { |
|||
let _match = String(value).match(/\d+/)//正整数 |
|||
this.searchData[item.prop] = _match?_match[0]:_match |
|||
} |
|||
} |
|||
if(this.searchData[item.prop] > item.max){ |
|||
this.searchData[item.prop] = item.max |
|||
} |
|||
if(this.searchData[item.prop] && this.searchData[item.prop] < item.min){ |
|||
this.searchData[item.prop] = item.min |
|||
} |
|||
if(item.onkeyup)item.onkeyup() |
|||
}, |
|||
//复选框全选 |
|||
handleCheckAllChange(val,item) { |
|||
const options = [] |
|||
if(val){ |
|||
this.searchOptions[item.checkboxs].forEach(items=>{ |
|||
options.push(items) |
|||
}) |
|||
} |
|||
this.searchData[item.prop] = val ? options : []; |
|||
this.indeterminate = false; |
|||
}, |
|||
//取消全选 |
|||
handleCheckedCitiesChange(value,item) { |
|||
let checkedCount = value.length; |
|||
item.checkAll = checkedCount === this.searchOptions[item.checkboxs].length; |
|||
this.indeterminate = checkedCount > 0 && checkedCount < this.searchOptions[item.checkboxs].length; |
|||
}, |
|||
inputPlaceholder(val, item, type, func) { |
|||
if (item.valueType) { |
|||
if (type == "focus") { |
|||
console.log("focus") |
|||
//影响必填项,2023-1-3 placeholder不处理 |
|||
// val.target.placeholder = '0'; |
|||
// if (val.target.value != "") { |
|||
// val.target.placeholder = val.target.value; |
|||
// val.target.value = ""; |
|||
// } |
|||
} else if (type == "blur") { |
|||
console.log("blur") |
|||
// val.target.value = "0" |
|||
val.target.value = val.target.value.toString().replace(/[^\d.]/g,'') |
|||
// if (val.target.value == "") { |
|||
// // if (val.target.placeholder.indexOf('请输入') == -1) { |
|||
// val.target.value = val.target.placeholder; |
|||
// // } |
|||
// } |
|||
if(item.showProp){ |
|||
if(val.target.value != ""){func[item.prop][item.showProp]= Number(val.target.value)} |
|||
}else{ |
|||
if(val.target.value != ""){func[item.prop]= Number(val.target.value)} |
|||
} |
|||
// item.valueType |
|||
// ? (this.searchData[item.prop] = item.valueType( |
|||
// this.searchData[item.prop] |
|||
// )) |
|||
// : () => { |
|||
// return; |
|||
// } |
|||
} |
|||
} |
|||
}, |
|||
querySearch(queryString, cb, val) { |
|||
const { options, optionsValue, optionsLabel } = val; |
|||
let func = val.focus; |
|||
let data = {}; |
|||
if (queryString) { |
|||
data.filter = [ |
|||
{ |
|||
logic: "And", |
|||
column: optionsValue, |
|||
action: "Like", |
|||
value: queryString, |
|||
}, |
|||
// { |
|||
// logic: "Or", |
|||
// column: optionsLabel, |
|||
// action: "Like", |
|||
// value: queryString |
|||
// } |
|||
]; |
|||
} |
|||
func(data).then((res) => { |
|||
var restaurants = this.searchOptions["options"]; |
|||
var results = queryString |
|||
? restaurants.filter( |
|||
this.createFilter(queryString, optionsValue, optionsLabel) |
|||
) |
|||
: restaurants; |
|||
results.forEach((key) => { |
|||
if (typeof optionsValue === "string") { |
|||
key.value = key[optionsValue] + "----" + key[optionsLabel]; |
|||
} else { |
|||
key.value = |
|||
key[optionsValue[0]][optionsValue[1]] + |
|||
"----" + |
|||
key[optionsLabel]; |
|||
} |
|||
}); |
|||
// 调用 callback 返回建议列表的数据 |
|||
cb(results); |
|||
}); |
|||
}, |
|||
createFilter(queryString, optionsValue, optionsLabel) { |
|||
return (restaurant) => { |
|||
if (typeof optionsValue === "string") { |
|||
restaurant.value = |
|||
restaurant[optionsValue] + "----" + restaurant[optionsLabel]; |
|||
} else { |
|||
restaurant.value = |
|||
restaurant[optionsValue[0]][optionsValue[1]] + |
|||
"----" + |
|||
restaurant[optionsLabel]; |
|||
} |
|||
return ( |
|||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) != |
|||
-1 |
|||
); |
|||
}; |
|||
}, |
|||
handleSelect(item, val) { |
|||
let data = this.searchData; |
|||
if (!val.showProp) { |
|||
if (typeof val.optionsValue === "string") { |
|||
data[val.prop] = item[val.optionsValue]; |
|||
} else { |
|||
data[val.prop] = item[val.optionsValue[0]][val.optionsValue[1]]; |
|||
} |
|||
} else { |
|||
if (typeof val.optionsValue === "string") { |
|||
data[val.prop][val.showProp] = item[val.optionsValue]; |
|||
} else { |
|||
data[val.prop][val.showProp] = |
|||
item[val.optionsValue[0]][val.optionsValue[1]]; |
|||
} |
|||
} |
|||
this.$emit("push", item, val); |
|||
}, |
|||
// filterSelect点击option事件 |
|||
filterOptionSelectHandle(item,props,val){ |
|||
this.searchData[props['prop']] = val |
|||
this.$emit("push", item, props); |
|||
}, |
|||
// filterSelect点击清除事件 |
|||
filterClearHandle(item){ |
|||
this.searchData[item['prop']] = "" |
|||
this.$emit("clear",item) |
|||
}, |
|||
// selectFocus (val, item) { |
|||
// this.selectLoading = true; |
|||
// let func = item.focus |
|||
// func({}).then(res => { |
|||
// this.selectLoading = false; |
|||
// }) |
|||
// }, |
|||
// dataFilter (query, item) { |
|||
// const { options, optionsValue, optionsLabel } = item |
|||
// let func = item.focus |
|||
// let data = {} |
|||
// this.selectLoading = true; |
|||
// if (query) { |
|||
// data.filter = { |
|||
// logic: "And", |
|||
// column: optionsLabel, |
|||
// action: "Like", |
|||
// value: query |
|||
// } |
|||
// } |
|||
// setTimeout(() => { |
|||
// func(data).then(res => { |
|||
// this.selectLoading = false; |
|||
// }) |
|||
// }, 200); |
|||
// // this.options = []; |
|||
// }, |
|||
submitForm(val,item) { |
|||
this.$emit("submitForm", val, this.$refs.form,item); |
|||
}, |
|||
getDom(){ |
|||
return this.$refs.form |
|||
}, |
|||
handleClick(val) { |
|||
this.$emit("handleClick", val); |
|||
}, |
|||
httpRequestfiles(val, item) { |
|||
this.searchData[item].push(val); |
|||
}, |
|||
beforeAvatarUpload(val, data) { |
|||
const repeat = data.filter((item) => { |
|||
return item.name == val.name; |
|||
}); |
|||
if (repeat.length != 0) { |
|||
this.$errorMsg("文件重复"); |
|||
return false; |
|||
} else { |
|||
return true; |
|||
} |
|||
}, |
|||
handleRemove(val, item) { |
|||
this.searchData[item] = val |
|||
}, |
|||
changeUpload(val, item){ |
|||
// 判断上传文件是否满足类型 |
|||
let suffix = val.name.substring(val.name.lastIndexOf('.') + 1) |
|||
if (item.picExt.indexOf(suffix) === -1) { |
|||
this.$warningMsg('上传文件只能是 ' + item.picExt + '格式!') |
|||
this.searchData[item.prop] = [] |
|||
return false |
|||
} else { |
|||
this.searchData[item.prop].push(val); |
|||
} |
|||
}, |
|||
uploadListView() { |
|||
this.$emit('uploadListView') |
|||
}, |
|||
radioChange(prop, val) { |
|||
this.$emit("radioChange", prop, val) |
|||
}, |
|||
changeInput(prop, val) { |
|||
this.$emit("changeInput", prop, val) |
|||
}, |
|||
clearInput(prop, val) { |
|||
this.$emit("clearInput", prop, val) |
|||
}, |
|||
changeSelect(prop, val) { |
|||
this.$emit("changeSelect", prop, val) |
|||
}, |
|||
|
|||
restrictionRule(item, prop) { |
|||
|
|||
if(prop) { |
|||
console.log('item',item) |
|||
console.log('prop', prop) |
|||
console.log('this.searchData', this.searchData) |
|||
console.log(this.searchData[prop]) |
|||
if (this.searchData[prop]) { |
|||
return false |
|||
} else { |
|||
return true |
|||
} |
|||
} else { |
|||
return true |
|||
} |
|||
} |
|||
|
|||
// 单一文件上传输入框——上传文件提示 |
|||
// handleExceed (val) { |
|||
// this.$warningMsg('最多上传1个文件') |
|||
// } |
|||
// //自定义select搜索 |
|||
// dataFilter (val, data) { |
|||
// if (!data) { |
|||
// return; |
|||
// } else { |
|||
// this.$emit(data, val); |
|||
// } |
|||
// }, |
|||
}, |
|||
}; |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
// .formButton { |
|||
// text-align: right; |
|||
// } |
|||
.inputNameberClass { |
|||
width: 100%; |
|||
} |
|||
.el-row { |
|||
::v-deep .el-form-item__content { |
|||
position: relative; |
|||
font-size: 14px; |
|||
} |
|||
.RangeDateTime { |
|||
::v-deep .el-col { |
|||
padding: 0 !important; |
|||
} |
|||
.line { |
|||
text-align: center; |
|||
} |
|||
} |
|||
} |
|||
::v-deep .el-form-item__label{ |
|||
color: #999 !important; |
|||
font-weight: normal !important; |
|||
} |
|||
</style> |
@ -0,0 +1,888 @@ |
|||
<template> |
|||
<div class="currenForm"> |
|||
<!-- @submit.native.prevent 阻止form只有一个input输入框回车触发提交事件 --> |
|||
<el-form |
|||
ref="form" |
|||
:size="size" |
|||
:label-position="labelPosition" |
|||
:inline="inline" |
|||
:label-width="labelWidth" |
|||
:rules="rules" |
|||
:model="searchData" |
|||
@submit.native.prevent |
|||
v-if="!hide ? true : false" |
|||
> |
|||
<el-row :gutter="40"> |
|||
<el-col |
|||
:span="item.colSpan" |
|||
v-for="(item, index) in searchForm" |
|||
:key="index" |
|||
> |
|||
<el-form-item |
|||
:label="item.label" |
|||
:prop="item.showProp ? item.prop + '.' + item.showProp : item.prop" |
|||
v-if="!item.hide ? true : false" |
|||
> |
|||
<!-- 输入框 onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<!-- :onkeyup="item.onkeyup" --> |
|||
<el-input |
|||
v-if="item.type === 'input'" |
|||
v-model="searchData[item.prop]" |
|||
:maxlength="item.maxlength" |
|||
:onkeyup="itemOnKeyUp(item,searchData[item.prop])" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@change="changeInput(item.prop,$event)" |
|||
@clear="clearInput(item.prop,$event)" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
<!-- 输入框(有上下增加按钮框) onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<el-input-number |
|||
v-if="item.type === 'number'" |
|||
v-model="searchData[item.prop]" |
|||
:onkeyup="item.onkeyup" |
|||
:disabled="Boolean(item.disabled)" |
|||
@change="changeInput(item.prop,$event)" |
|||
@clear="clearInput(item.prop,$event)" |
|||
:min="item.min" |
|||
:max="item.max" |
|||
:precision="item.precision" |
|||
class="inputNameberClass" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input-number> |
|||
<!-- 输入框(只能输入数字) onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<!-- oninput="value=value.replace(/[^\d]/g,'')" --> |
|||
<el-input |
|||
v-if="item.type === 'inputNumber'" |
|||
v-model="searchData[item.prop]" |
|||
:maxlength="item.maxlength" |
|||
:onkeyup="typeNumberOnkeyup(item,searchData[item.prop])" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@change="changeInput(item.prop,$event)" |
|||
@clear="clearInput(item.prop,$event)" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
<!-- 对象输入框 --> |
|||
<el-input |
|||
v-if="item.type === 'objectInput'" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:maxlength="item.maxlength" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',searchData) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
<!-- 对象富文本框 --> |
|||
<el-input |
|||
v-if="item.type === 'objectTextarea'" |
|||
type="textarea" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
></el-input> |
|||
<!--查询下拉--> |
|||
<el-autocomplete |
|||
v-if="item.type === 'autocomplete'" |
|||
class="inline-input" |
|||
style="width: 100%" |
|||
v-model="searchData[item.prop]" |
|||
:disabled="Boolean(item.disabled)" |
|||
:fetch-suggestions=" |
|||
(queryString, cb) => { |
|||
querySearch(queryString, cb, item); |
|||
} |
|||
" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@select="handleSelect($event, item)" |
|||
> |
|||
<el-button |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
v-if="item.click" |
|||
@click="item.click(item)" |
|||
style="color: #1890ff; background-color: #ffffff" |
|||
></el-button> |
|||
</el-autocomplete> |
|||
<!--对象查询下拉--> |
|||
<el-autocomplete |
|||
v-if="item.type === 'objectAutocomplete'" |
|||
class="inline-input" |
|||
style="width: 100%" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:fetch-suggestions=" |
|||
(queryString, cb) => { |
|||
querySearch(queryString, cb, item); |
|||
} |
|||
" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@select="handleSelect($event, item)" |
|||
> |
|||
<el-button |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
v-if="item.click" |
|||
@click="item.click(item)" |
|||
style="color: #1890ff; background-color: #ffffff" |
|||
></el-button> |
|||
</el-autocomplete> |
|||
<!-- 文本框 --> |
|||
<el-input |
|||
v-if="item.type === 'textarea'" |
|||
:type="item.type" |
|||
v-model="searchData[item.prop]" |
|||
:rows="item.rows" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:maxlength="item.maxlength" |
|||
show-word-limit |
|||
></el-input> |
|||
<!-- 下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'select'" |
|||
v-model="searchData[item.prop]" |
|||
:loading="selectLoading" |
|||
:clearable="item.clearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled)" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
style="width: 100%" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
@change="changeSelect(item.prop,$event)" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
item.userOptions" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- 链接接口filter下拉框 --> |
|||
<filterSelect |
|||
v-if="item.type === 'filterSelect'" |
|||
:selectModel="searchData[item.prop]" |
|||
:selectItem="item" |
|||
@filterOptionSelectHandle="filterOptionSelectHandle" |
|||
@filterClearHandle="filterClearHandle(item)" |
|||
></filterSelect> |
|||
<!--对象下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'objectSelect'" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:loading="selectLoading" |
|||
:clearable="item.clearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled)" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
style="width: 100%" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
searchOptions['options']" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- 下拉框多选 --> |
|||
<el-select |
|||
v-if="item.type === 'selectArray'" |
|||
v-model="searchData[item.prop]" |
|||
multiple |
|||
:placeholder="item.placeholder || '请选择' + item.label" |
|||
style="width: 100%" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
item.searchOptions" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- 单选 --> |
|||
<el-radio-group |
|||
v-if="item.type === 'radio'" |
|||
v-model="searchData[item.prop]" |
|||
:disabled="Boolean(item.disabled)" |
|||
@change="radioChange(item.prop,$event)" |
|||
> |
|||
<el-radio |
|||
v-for="ra in searchOptions[item.radio]" |
|||
:label="ra.id" |
|||
:key="ra.value" |
|||
>{{ ra.label }}</el-radio |
|||
> |
|||
</el-radio-group> |
|||
<!-- 单选按钮 --> |
|||
<el-radio-group |
|||
v-if="item.type === 'radioButton'" |
|||
v-model="searchData[item.prop]" |
|||
@change="item.change && item.change(searchData[item.prop])" |
|||
> |
|||
<el-radio-button |
|||
v-for="ra in searchOptions[item.radios]" |
|||
:label="ra.value" |
|||
:key="ra.value" |
|||
>{{ ra.label }}</el-radio-button |
|||
> |
|||
</el-radio-group> |
|||
<!-- 复选框 --> |
|||
<el-checkbox v-if="item.type === 'checkbox'" :indeterminate="indeterminate" v-model="item.checkAll" @change="handleCheckAllChange($event,item)">全选</el-checkbox> |
|||
<el-checkbox-group |
|||
v-if="item.type === 'checkbox'" |
|||
v-model="searchData[item.prop]" |
|||
@change="handleCheckedCitiesChange($event,item)" |
|||
> |
|||
<el-checkbox |
|||
v-for="ch in searchOptions[item.checkboxs]" |
|||
:label="ch" |
|||
:key="ch" |
|||
>{{ ch }}</el-checkbox |
|||
> |
|||
</el-checkbox-group> |
|||
<!-- 日期 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'date'" |
|||
v-model="searchData[item.prop]" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '选择日期'" |
|||
value-format="yyyy-MM-dd" |
|||
></el-date-picker> |
|||
<!-- 时间 --> |
|||
<el-time-picker |
|||
v-if="item.type === 'time'" |
|||
v-model="searchData[item.prop]" |
|||
:placeholder="item.placeholder || '选择时间'" |
|||
style="width: 100%" |
|||
:picker-options="{ |
|||
selectableRange: '00:00:00 - 23:59:00', |
|||
}" |
|||
:disabled="Boolean(item.disabled)" |
|||
format="HH:mm" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
></el-time-picker> |
|||
<!-- 日期时间 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'dateTime'" |
|||
type="datetime" |
|||
v-model="searchData[item.prop]" |
|||
:placeholder="item.placeholder || '选择日期时间'" |
|||
style="width: 100%" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
<!-- 日期时间 日期有限制 选择范围:当前天及以后--> |
|||
<el-date-picker |
|||
v-if="item.type === 'dateTimelimit'" |
|||
type="datetime" |
|||
v-model="searchData[item.prop]" |
|||
:placeholder="item.placeholder || '选择日期时间'" |
|||
style="width: 100%" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
:pickerOptions="endDateTimeLimitPickerOptions()" |
|||
></el-date-picker> |
|||
<!-- 对象日期时间 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'objectDateTime'" |
|||
type="datetime" |
|||
v-model="searchData[item.prop][item.showProp]" |
|||
:placeholder="item.placeholder || '选择日期'" |
|||
style="width: 100%" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
<!--开始时间结束时间--> |
|||
<div |
|||
class="RangeDateTime" |
|||
v-if="item.type === 'rangeDateTime'" |
|||
style="width: 100%; height: 100%" |
|||
> |
|||
<el-col :span="10"> |
|||
<el-form-item :prop="item.prop + '.' + item.startDate"> |
|||
<el-date-picker |
|||
type="datetime" |
|||
:placeholder="item.placeholder || '开始日期'" |
|||
v-model="searchData[item.prop][item.startDate]" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled)" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:pickerOptions=" |
|||
startPickerOptions(searchData[item.prop][item.endDate]) |
|||
" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col class="line" :span="4">-</el-col> |
|||
<el-col :span="10"> |
|||
<el-form-item :prop="item.prop + '.' + item.endDate"> |
|||
<el-date-picker |
|||
type="datetime" |
|||
:placeholder="item.placeholder || '结束日期'" |
|||
v-model="searchData[item.prop][item.endDate]" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled)" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:pickerOptions=" |
|||
endPickerOptions(searchData[item.prop][item.startDate]) |
|||
" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
</el-col> |
|||
</div> |
|||
<!-- 开关 --> |
|||
<el-switch |
|||
v-if="item.type === 'switch'" |
|||
v-model="searchData[item.prop]" |
|||
></el-switch> |
|||
<!--文件上传--> |
|||
<currenUpload |
|||
v-if="item.type === 'upload'" |
|||
:limit="item.limit" |
|||
:beforeUpload="beforeAvatarUpload" |
|||
:searchData="searchData[item.prop]" |
|||
@httpRequestfiles="httpRequestfiles($event, item.prop)" |
|||
@handleRemove="handleRemove($event, item.prop)" |
|||
> |
|||
</currenUpload> |
|||
<!--文件上传——列表形式--> |
|||
<currenUploadList |
|||
v-if="item.type === 'uploadList'" |
|||
:limit="item.limit" |
|||
:picExt="item.picExt" |
|||
:searchData="searchData[item.prop]" |
|||
@uploadListView="uploadListView" |
|||
@changeUpload="changeUpload($event, item)" |
|||
@handleRemove="handleRemove($event, item.prop)" |
|||
> |
|||
</currenUploadList> |
|||
<!-- 缩略图上传 --> |
|||
<currenUploadPictureCard |
|||
v-if="item.type === 'uploadPictureCard'" |
|||
:limit="item.limit" |
|||
:multiple="item.multiple" |
|||
:picExt="item.picExt" |
|||
:searchData="searchData[item.prop]" |
|||
@changeUpload="changeUpload($event, item)" |
|||
@handleRemove="handleRemove($event, item.prop)" |
|||
> |
|||
</currenUploadPictureCard> |
|||
<el-button |
|||
v-if="item.type === 'button'" |
|||
type="primary" |
|||
size="mini" |
|||
@click="item.click(item)" |
|||
> |
|||
{{item.buttonText}} |
|||
</el-button> |
|||
</el-form-item> |
|||
</el-col> |
|||
</el-row> |
|||
<slot></slot> |
|||
</el-form> |
|||
<div v-if="isHandle" class="formButton"> |
|||
<!-- :style="{float:item.float}" 自定义按钮显示位置 --> |
|||
<el-button |
|||
v-for="(item, index) in searchHandle" |
|||
:key="item.label" |
|||
:type="item.type" |
|||
:size="item.size || size" |
|||
:loading="loading" |
|||
:style="{float:item.float}" |
|||
@click="submitForm(index,item)" |
|||
>{{ item.label }}</el-button |
|||
> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenUpload from "@/components/currenUpload"; |
|||
import currenUploadList from "@/components/currenUploadList"; |
|||
import currenUploadPictureCard from "@/components/currenUploadPictureCard"; |
|||
import filterSelect from "@/components/filterSelect" |
|||
import { getMatchRegConformValue } from "@/utils/index" |
|||
export default { |
|||
name: "currenForm", |
|||
components: { |
|||
currenUpload, |
|||
currenUploadList, |
|||
currenUploadPictureCard, |
|||
filterSelect |
|||
}, |
|||
props: { |
|||
loading: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
labelPosition: { |
|||
type: String, |
|||
default: "right", |
|||
}, |
|||
isHandle: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
inline: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
labelWidth: { |
|||
type: String, |
|||
default: "140px", |
|||
}, |
|||
size: { |
|||
type: String, |
|||
default: "mini", |
|||
}, |
|||
searchForm: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
searchHandle: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
searchData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
searchOptions: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
rules: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
formSpan: { |
|||
type: Number, |
|||
default: 24, |
|||
}, |
|||
hide: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
restaurants: [], |
|||
indeterminate: false, |
|||
selectLoading: false, |
|||
}; |
|||
}, |
|||
computed: { |
|||
startPickerOptions() { |
|||
return function (val) { |
|||
return { |
|||
disabledDate(time) { |
|||
if (val) { |
|||
return ( |
|||
// time.getTime() > Date.now() || |
|||
// time.getTime() > new Date(that.CreateFormData.endDate).getTime() |
|||
time.getTime() > val |
|||
); |
|||
} |
|||
// return time.getTime() > Date.now(); //实现1效果 |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
endPickerOptions() { |
|||
// const that = this; |
|||
return function (val) { |
|||
return { |
|||
disabledDate(time) { |
|||
if (val) { |
|||
return ( |
|||
// time.getTime() > Date.now() || |
|||
// time.getTime() < new Date(that.CreateFormData.startDate).getTime() |
|||
time.getTime() < val |
|||
); |
|||
} |
|||
// return time.getTime() > Date.now(); //实现1效果 |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
// 日期时间组件,选择范围:当前天及以后 |
|||
endDateTimeLimitPickerOptions() { |
|||
return function () { |
|||
return { |
|||
disabledDate(time) { |
|||
return ( |
|||
time.getTime() < Date.now() - 8.64e7 |
|||
); |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
selectOptions() { |
|||
return (val) => { |
|||
if (val) { |
|||
let options = this.$staticOptions[val]; |
|||
if (options) { |
|||
return options(); |
|||
} else { |
|||
return []; |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
}; |
|||
}, |
|||
}, |
|||
mounted() { |
|||
// 单选 , 默认设置 |
|||
this.searchForm.forEach(item => { |
|||
if (item.type === 'radio') { |
|||
this.searchData[item.prop] = item.value + '' |
|||
} |
|||
if (item.type === 'checkbox') { |
|||
this.searchData[item.prop].push(item.value) |
|||
} |
|||
}) |
|||
}, |
|||
methods: { |
|||
// type=input情况下,框实时校验 |
|||
itemOnKeyUp(item,value){ |
|||
if(item.onkeyup){ |
|||
return item.onkeyup() |
|||
}else{ |
|||
if(value && item.validType){ |
|||
this.searchData[item.prop]=getMatchRegConformValue(item.validType,value,item.pointNumberFixed) |
|||
} |
|||
} |
|||
}, |
|||
// 数字类型input框onkeyup最大最小值处理 |
|||
typeNumberOnkeyup(item,value){ |
|||
if(value){ |
|||
// 添加pointNumberFixed 可以输入小数 |
|||
if (item.pointNumberFixed) { |
|||
let _fixed = item.pointNumberFixed ? Number(item.pointNumberFixed) : 100 |
|||
let reg = new RegExp(`\\d+\\.?\\d{0,${_fixed}}`); |
|||
let _match = String(value).match(reg) |
|||
this.searchData[item.prop] = _match ? _match[0] : _match |
|||
} else { |
|||
let _match = String(value).match(/\d+/)//正整数 |
|||
this.searchData[item.prop] = _match?_match[0]:_match |
|||
} |
|||
} |
|||
if(this.searchData[item.prop] > item.max){ |
|||
this.searchData[item.prop] = item.max |
|||
} |
|||
if(this.searchData[item.prop] && this.searchData[item.prop] < item.min){ |
|||
this.searchData[item.prop] = item.min |
|||
} |
|||
if(item.onkeyup)item.onkeyup() |
|||
}, |
|||
//复选框全选 |
|||
handleCheckAllChange(val,item) { |
|||
const options = [] |
|||
if(val){ |
|||
this.searchOptions[item.checkboxs].forEach(items=>{ |
|||
options.push(items) |
|||
}) |
|||
} |
|||
this.searchData[item.prop] = val ? options : []; |
|||
this.indeterminate = false; |
|||
}, |
|||
//取消全选 |
|||
handleCheckedCitiesChange(value,item) { |
|||
let checkedCount = value.length; |
|||
item.checkAll = checkedCount === this.searchOptions[item.checkboxs].length; |
|||
this.indeterminate = checkedCount > 0 && checkedCount < this.searchOptions[item.checkboxs].length; |
|||
}, |
|||
inputPlaceholder(val, item, type, func) { |
|||
if (item.valueType) { |
|||
if (type == "focus") { |
|||
console.log("focus") |
|||
//影响必填项,2023-1-3 placeholder不处理 |
|||
// val.target.placeholder = '0'; |
|||
// if (val.target.value != "") { |
|||
// val.target.placeholder = val.target.value; |
|||
// val.target.value = ""; |
|||
// } |
|||
} else if (type == "blur") { |
|||
console.log("blur") |
|||
// val.target.value = "0" |
|||
val.target.value = val.target.value.toString().replace(/[^\d.]/g,'') |
|||
// if (val.target.value == "") { |
|||
// // if (val.target.placeholder.indexOf('请输入') == -1) { |
|||
// val.target.value = val.target.placeholder; |
|||
// // } |
|||
// } |
|||
if(item.showProp){ |
|||
if(val.target.value != ""){func[item.prop][item.showProp]= Number(val.target.value)} |
|||
}else{ |
|||
if(val.target.value != ""){func[item.prop]= Number(val.target.value)} |
|||
} |
|||
// item.valueType |
|||
// ? (this.searchData[item.prop] = item.valueType( |
|||
// this.searchData[item.prop] |
|||
// )) |
|||
// : () => { |
|||
// return; |
|||
// } |
|||
} |
|||
} |
|||
}, |
|||
querySearch(queryString, cb, val) { |
|||
const { options, optionsValue, optionsLabel } = val; |
|||
let func = val.focus; |
|||
let data = {}; |
|||
if (queryString) { |
|||
data.filter = [ |
|||
{ |
|||
logic: "And", |
|||
column: optionsValue, |
|||
action: "Like", |
|||
value: queryString, |
|||
}, |
|||
// { |
|||
// logic: "Or", |
|||
// column: optionsLabel, |
|||
// action: "Like", |
|||
// value: queryString |
|||
// } |
|||
]; |
|||
} |
|||
func(data).then((res) => { |
|||
var restaurants = this.searchOptions["options"]; |
|||
var results = queryString |
|||
? restaurants.filter( |
|||
this.createFilter(queryString, optionsValue, optionsLabel) |
|||
) |
|||
: restaurants; |
|||
results.forEach((key) => { |
|||
if (typeof optionsValue === "string") { |
|||
key.value = key[optionsValue] + "----" + key[optionsLabel]; |
|||
} else { |
|||
key.value = |
|||
key[optionsValue[0]][optionsValue[1]] + |
|||
"----" + |
|||
key[optionsLabel]; |
|||
} |
|||
}); |
|||
// 调用 callback 返回建议列表的数据 |
|||
cb(results); |
|||
}); |
|||
}, |
|||
createFilter(queryString, optionsValue, optionsLabel) { |
|||
return (restaurant) => { |
|||
if (typeof optionsValue === "string") { |
|||
restaurant.value = |
|||
restaurant[optionsValue] + "----" + restaurant[optionsLabel]; |
|||
} else { |
|||
restaurant.value = |
|||
restaurant[optionsValue[0]][optionsValue[1]] + |
|||
"----" + |
|||
restaurant[optionsLabel]; |
|||
} |
|||
return ( |
|||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) != |
|||
-1 |
|||
); |
|||
}; |
|||
}, |
|||
handleSelect(item, val) { |
|||
let data = this.searchData; |
|||
if (!val.showProp) { |
|||
if (typeof val.optionsValue === "string") { |
|||
data[val.prop] = item[val.optionsValue]; |
|||
} else { |
|||
data[val.prop] = item[val.optionsValue[0]][val.optionsValue[1]]; |
|||
} |
|||
} else { |
|||
if (typeof val.optionsValue === "string") { |
|||
data[val.prop][val.showProp] = item[val.optionsValue]; |
|||
} else { |
|||
data[val.prop][val.showProp] = |
|||
item[val.optionsValue[0]][val.optionsValue[1]]; |
|||
} |
|||
} |
|||
this.$emit("push", item, val); |
|||
}, |
|||
// filterSelect点击option事件 |
|||
filterOptionSelectHandle(item,props,val){ |
|||
this.searchData[props['prop']] = val |
|||
this.$emit("push", item, props); |
|||
}, |
|||
// filterSelect点击清除事件 |
|||
filterClearHandle(item){ |
|||
this.searchData[item['prop']] = "" |
|||
this.$emit("clear",item) |
|||
}, |
|||
// selectFocus (val, item) { |
|||
// this.selectLoading = true; |
|||
// let func = item.focus |
|||
// func({}).then(res => { |
|||
// this.selectLoading = false; |
|||
// }) |
|||
// }, |
|||
// dataFilter (query, item) { |
|||
// const { options, optionsValue, optionsLabel } = item |
|||
// let func = item.focus |
|||
// let data = {} |
|||
// this.selectLoading = true; |
|||
// if (query) { |
|||
// data.filter = { |
|||
// logic: "And", |
|||
// column: optionsLabel, |
|||
// action: "Like", |
|||
// value: query |
|||
// } |
|||
// } |
|||
// setTimeout(() => { |
|||
// func(data).then(res => { |
|||
// this.selectLoading = false; |
|||
// }) |
|||
// }, 200); |
|||
// // this.options = []; |
|||
// }, |
|||
submitForm(val,item) { |
|||
this.$emit("submitForm", val, this.$refs.form,item); |
|||
}, |
|||
getDom(){ |
|||
return this.$refs.form |
|||
}, |
|||
handleClick(val) { |
|||
this.$emit("handleClick", val); |
|||
}, |
|||
httpRequestfiles(val, item) { |
|||
this.searchData[item].push(val); |
|||
}, |
|||
beforeAvatarUpload(val, data) { |
|||
const repeat = data.filter((item) => { |
|||
return item.name == val.name; |
|||
}); |
|||
if (repeat.length != 0) { |
|||
this.$errorMsg("文件重复"); |
|||
return false; |
|||
} else { |
|||
return true; |
|||
} |
|||
}, |
|||
handleRemove(val, item) { |
|||
this.searchData[item] = val |
|||
}, |
|||
changeUpload(val, item){ |
|||
// 判断上传文件是否满足类型 |
|||
let suffix = val.name.substring(val.name.lastIndexOf('.') + 1) |
|||
if (item.picExt.indexOf(suffix) === -1) { |
|||
this.$warningMsg('上传文件只能是 ' + item.picExt + '格式!') |
|||
this.searchData[item.prop] = [] |
|||
return false |
|||
} else { |
|||
this.searchData[item.prop].push(val); |
|||
} |
|||
}, |
|||
uploadListView() { |
|||
this.$emit('uploadListView') |
|||
}, |
|||
radioChange(prop, val) { |
|||
this.$emit("radioChange", prop, val) |
|||
}, |
|||
changeInput(prop, val) { |
|||
this.$emit("changeInput", prop, val) |
|||
}, |
|||
clearInput(prop, val) { |
|||
this.$emit("clearInput", prop, val) |
|||
}, |
|||
changeSelect(prop, val) { |
|||
this.$emit("changeSelect", prop, val) |
|||
}, |
|||
|
|||
restrictionRule(item, prop) { |
|||
|
|||
if(prop) { |
|||
console.log('item',item) |
|||
console.log('prop', prop) |
|||
console.log('this.searchData', this.searchData) |
|||
console.log(this.searchData[prop]) |
|||
if (this.searchData[prop]) { |
|||
return false |
|||
} else { |
|||
return true |
|||
} |
|||
} else { |
|||
return true |
|||
} |
|||
} |
|||
|
|||
// 单一文件上传输入框——上传文件提示 |
|||
// handleExceed (val) { |
|||
// this.$warningMsg('最多上传1个文件') |
|||
// } |
|||
// //自定义select搜索 |
|||
// dataFilter (val, data) { |
|||
// if (!data) { |
|||
// return; |
|||
// } else { |
|||
// this.$emit(data, val); |
|||
// } |
|||
// }, |
|||
}, |
|||
}; |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
// .formButton { |
|||
// text-align: right; |
|||
// } |
|||
.inputNameberClass { |
|||
width: 100%; |
|||
} |
|||
.el-row { |
|||
::v-deep .el-form-item__content { |
|||
position: relative; |
|||
font-size: 14px; |
|||
} |
|||
.RangeDateTime { |
|||
::v-deep .el-col { |
|||
padding: 0 !important; |
|||
} |
|||
.line { |
|||
text-align: center; |
|||
} |
|||
} |
|||
} |
|||
::v-deep .el-form-item__label{ |
|||
color: #999 !important; |
|||
font-weight: normal !important; |
|||
} |
|||
</style> |
@ -0,0 +1,761 @@ |
|||
<template> |
|||
<!-- <div> --> |
|||
<el-table |
|||
:id="_uid" |
|||
v-loading="tableLoading" |
|||
element-loading-text="拼命加载中..." |
|||
@sort-change="sortChange" |
|||
@selection-change="handleSelectionChange" |
|||
ref="multipleTable" |
|||
:data="tableData" |
|||
height="85%" |
|||
row-key="id" |
|||
stripe |
|||
border |
|||
style="width: 100%" |
|||
:tree-props="treeProps" |
|||
:cell-style="cellStyle" |
|||
> |
|||
<el-table-column v-if="selectionTable" fixed="left" type="selection" /> |
|||
<el-table-column v-if="isShowIndex" type="index" fixed="left" label="序号" width="50" /> |
|||
<el-table-column |
|||
v-for="(item, index) in TableSize" |
|||
:key="index" |
|||
:prop="item.showProp ? item.prop + '.' + item.showProp : item.prop" |
|||
:sortable="item.sortable" |
|||
:fixed="item.fixed" |
|||
:show-overflow-tooltip="true" |
|||
:width="item.width" |
|||
align="center" |
|||
> |
|||
<template #header> |
|||
<span>{{ item.label }}</span> |
|||
<i style="color: #f56c6c" v-if="item.rules && requiredRules">*</i> |
|||
</template> |
|||
<template slot-scope="scope"> |
|||
<el-form> |
|||
<el-form-item |
|||
v-if="item.type == 'input'" |
|||
:onkeyup="itemOnKeyUp(item,item.prop,scope.$index)" |
|||
:prop="'details.' + scope.$index + '.' + item.prop" |
|||
:rules="item.rules" |
|||
> |
|||
<el-input |
|||
:placeholder="'请输入' + item.label" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
v-model="scope.row[item.prop]" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',scope.row) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
clearable |
|||
> |
|||
</el-input> |
|||
</el-form-item> |
|||
<!-- 输入框(数字) onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<el-form-item |
|||
v-if="item.type == 'inputNumber'" |
|||
:prop="'details.' + scope.$index + '.' + item.prop" |
|||
:rules="item.rules" |
|||
> |
|||
<el-input |
|||
v-model="scope.row[item.prop]" |
|||
:maxlength="item.maxlength" |
|||
:onkeyup="typeNumberOnkeyup(item,item.prop,scope.$index)" |
|||
clearable |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="'请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
@clear="clearInput(item.prop,$event)" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur',scope.row) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
></el-input> |
|||
</el-form-item> |
|||
<el-form-item |
|||
v-if="item.type == 'objectInput'" |
|||
:prop=" |
|||
'details.' + scope.$index + '.' + item.prop + '.' + item.showProp |
|||
" |
|||
:rules="item.rules" |
|||
> |
|||
<el-input |
|||
:placeholder="'请输入' + item.label" |
|||
v-model="scope.row[item.prop][item.showProp]" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
@blur=" |
|||
inputPlaceholder($event, item, 'blur', scope.row) |
|||
" |
|||
@focus="inputPlaceholder($event, item, 'focus')" |
|||
clearable |
|||
> |
|||
</el-input> |
|||
</el-form-item> |
|||
<!-- 下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'select'" |
|||
v-model="scope.row[item.prop]" |
|||
:loading="selectLoading" |
|||
:clearable="item.clearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
style="width: 100%" |
|||
:placeholder="'请输入' + item.label" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
searchOptions['options']" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!--对象下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'objectSelect'" |
|||
v-model="scope.row[item.prop][item.showProp]" |
|||
:loading="selectLoading" |
|||
:clearable="item.clearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
style="width: 100%" |
|||
:placeholder="'请输入' + item.label" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
searchOptions['options']" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!--查询下拉--> |
|||
<el-form-item |
|||
v-if="item.type === 'autocomplete'" |
|||
:prop="'details.' + scope.$index + '.' + item.prop" |
|||
:rules="item.rules" |
|||
> |
|||
<el-autocomplete |
|||
class="inline-input" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
v-model="scope.row[item.prop]" |
|||
:fetch-suggestions=" |
|||
(queryString, cb) => { |
|||
querySearch(queryString, cb, item, scope); |
|||
} |
|||
" |
|||
:placeholder="'请输入' + item.label" |
|||
@select="handleSelect($event, item, scope)" |
|||
> |
|||
<!-- <template slot-scope="{item}"> |
|||
<div class="name" style="color:green">{{item.value = item.name}}</div> |
|||
<div class="name" >{{item.address = item.code}}</div> |
|||
</template> --> |
|||
<el-button |
|||
v-if="item.click" |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
@click="item.click({ scope, item })" |
|||
style="color: #1890ff; background-color: #ffffff" |
|||
></el-button> |
|||
</el-autocomplete> |
|||
</el-form-item> |
|||
<!-- 对象查询下拉 --> |
|||
<el-form-item |
|||
v-if="item.type === 'objectAutocomplete'" |
|||
:prop=" |
|||
'details.' + scope.$index + '.' + item.prop + '.' + item.showProp |
|||
" |
|||
:rules="item.rules" |
|||
> |
|||
<el-autocomplete |
|||
class="inline-input" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
v-model="scope.row[item.prop][item.showProp]" |
|||
:fetch-suggestions=" |
|||
(queryString, cb) => { |
|||
querySearch(queryString, cb, item, scope); |
|||
} |
|||
" |
|||
:placeholder="'请输入' + item.label" |
|||
@select="handleSelect($event, item, scope)" |
|||
> |
|||
<!-- <template slot-scope="{item}"> |
|||
<div class="name" style="color:green">{{item.value = item.name}}</div> |
|||
<div class="name" >{{item.address = item.code}}</div> |
|||
</template> --> |
|||
<el-button |
|||
v-if="item.click" |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
@click="item.click({ scope, item })" |
|||
style="color: #1890ff; background-color: #ffffff" |
|||
></el-button> |
|||
</el-autocomplete> |
|||
</el-form-item> |
|||
<!-- <el-form-item v-if="item.type == 'inputEnum'" :prop="item.prop"> |
|||
<el-input |
|||
placeholder="请输入内容" |
|||
v-model="scope.row[item.prop]" |
|||
clearable |
|||
> |
|||
</el-input> |
|||
</el-form-item> --> |
|||
|
|||
<el-form-item |
|||
v-if="item.type == 'dateTimeInput'" |
|||
:prop="'details.' + scope.$index + '.' + item.prop" |
|||
:rules="item.rules" |
|||
> |
|||
<el-date-picker |
|||
type="datetime" |
|||
v-model="scope.row[item.prop]" |
|||
placeholder="选择日期" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
value-format="yyyy-MM-ddTHH:mm:ss.sssZ" |
|||
format="yyyy-MM-dd" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
<el-form-item |
|||
v-if="item.type == 'objectDateTimeInput'" |
|||
:prop="'details.' + scope.$index + '.' + item.prop + '.' + item.showProp" |
|||
:rules="item.rules" |
|||
> |
|||
<el-date-picker |
|||
type="datetime" |
|||
v-model="scope.row[item.prop][item.showProp]" |
|||
placeholder="选择日期" |
|||
style="width: 100%" |
|||
:disabled="Boolean(item.disabled) || Boolean(scope.row['disabled'])" |
|||
value-format="yyyy-MM-ddTHH:mm:ss.sssZ" |
|||
format="yyyy-MM-dd" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
<!-- table表添加按钮事件 v-show="scope.row.number == 'PRJ202210060001'" --> |
|||
<el-form-item v-if="item.type == 'button'" > |
|||
<el-button |
|||
v-show="scope.row[item.prop]==undefined?true:false" |
|||
type="primary" |
|||
size="mini" |
|||
@click="buttonClick(scope.row, scope.$index, item.label)" |
|||
>{{item.label}}</el-button> |
|||
</el-form-item> |
|||
|
|||
<span v-if="item.type == 'object'"> |
|||
{{ scope.row[item.prop] ? scope.row[item.prop][item.showProp] : "" }} |
|||
</span> |
|||
<span v-if="item.type == 'objectDateTime'"> |
|||
{{ scope.row[item.prop]? scope.row[item.prop][item.showProp]: "" | formatDate }} |
|||
</span> |
|||
<span v-if="item.type == 'dateTime'"> |
|||
{{ scope.row[item.prop] | formatDate }} |
|||
</span> |
|||
<!-- 调用主表信息 --> |
|||
<span v-else-if="item.type && item.type == 'outerMainFilter'"> |
|||
{{ propsData[item.showProp] }} |
|||
</span> |
|||
<el-tag |
|||
v-if="item.type == 'tagFilter'" |
|||
:effect="'dark'" |
|||
size="medium" |
|||
class="tagFilterTypeDarkItem" |
|||
:color="scope.row[item.prop] | trigger(item.filters, 'background')" |
|||
> |
|||
{{ scope.row[item.prop] | trigger(item.filters, "label") }} |
|||
</el-tag> |
|||
<span |
|||
v-if="item.type == 'filter'" |
|||
:style="scope.row[item.prop]" |
|||
> |
|||
{{ scope.row[item.prop] | trigger(item.filters, "label", item.dictType) }} |
|||
</span> |
|||
<span |
|||
v-if="item.type == 'objectFilter'" |
|||
:style="scope.row[item.prop][item.showProp]" |
|||
> |
|||
{{ scope.row[item.prop][item.showProp] | trigger(item.filters, "label") }} |
|||
</span> |
|||
<span |
|||
v-if="item.type == 'name' || !item.type" |
|||
@click="item.type == 'name' && inlineDialog(scope.row)" |
|||
:class="{ spamHover: item.type == 'name' }" |
|||
>{{ scope.row[item.prop] }}</span |
|||
> |
|||
</el-form> |
|||
</template> |
|||
</el-table-column> |
|||
<slot></slot> |
|||
</el-table> |
|||
<!-- <pre style="text-align: left"> |
|||
{{ tableColumns }} |
|||
</pre> |
|||
<hr /> |
|||
<pre style="text-align: left"> |
|||
{{ tableData }} |
|||
</pre> --> |
|||
<!-- </div> --> |
|||
</template> |
|||
<script> |
|||
import Sortable from "sortablejs"; |
|||
import { formatTimeStrToStr } from "@/utils/formatTime"; |
|||
import { getMatchRegConformValue } from "@/utils/index" |
|||
import _ from "lodash"; |
|||
export default { |
|||
name: "currenTable", |
|||
filters: { |
|||
formatDate(time) { |
|||
if (time == null) { |
|||
return '-' |
|||
} |
|||
return formatTimeStrToStr(time) |
|||
}, |
|||
}, |
|||
props: { |
|||
propsData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
tableData: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
tableLoading: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
selectionTable: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
requiredRules: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
searchOptions: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
treeProps: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
} |
|||
}, |
|||
isShowIndex: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
cellStyle: { |
|||
type: Function, |
|||
default: () => { |
|||
return Function; |
|||
} |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
dropCol: null, |
|||
selectLoading: false, |
|||
// TableSize: [], |
|||
random: '' |
|||
}; |
|||
}, |
|||
computed: { |
|||
selectOptions() { |
|||
return (val) => { |
|||
if (val) { |
|||
let options = this.$staticOptions[val]; |
|||
if (options) { |
|||
return options(); |
|||
} else { |
|||
return []; |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
}; |
|||
}, |
|||
TableSize(){ |
|||
return this.tableColumnsFilter() |
|||
} |
|||
}, |
|||
watch: { |
|||
tableData: { |
|||
handler(val, oldVal) { |
|||
this.$nextTick(() => { |
|||
this.$refs.multipleTable.doLayout(); |
|||
// this.$forceUpdate() |
|||
}); |
|||
}, |
|||
immediate: false, |
|||
} |
|||
}, |
|||
activated() { |
|||
this.$refs.multipleTable.doLayout(); |
|||
}, |
|||
created() { |
|||
|
|||
}, |
|||
// beforeUpdate () { |
|||
// this.$nextTick(() => { |
|||
// this.$refs.multipleTable.doLayout() |
|||
// }) |
|||
// }, |
|||
mounted() { |
|||
// this.tableColumnsFilter() |
|||
this.random = this._uid |
|||
// this.rowDrop() |
|||
// this.columnDrop(); |
|||
// this.tableColumns.forEach(item => { |
|||
// if (item.focus) { |
|||
// item.focus() |
|||
// } |
|||
// }) |
|||
}, |
|||
methods: { |
|||
// type=input情况下,框实时校验 |
|||
itemOnKeyUp(item,value,index){ |
|||
if(item.onkeyup){ |
|||
return item.onkeyup() |
|||
}else{ |
|||
if(this.tableData[index][value] && item.validType){ |
|||
this.tableData[index][value]=getMatchRegConformValue(item.validType,this.tableData[index][value],item.pointNumberFixed) |
|||
} |
|||
} |
|||
}, |
|||
// 数字类型input框onkeyup最大最小值处理 |
|||
typeNumberOnkeyup(item,value,index){ |
|||
if(this.tableData[index][value]){ |
|||
let _match = String(this.tableData[index][value]).match(/\d+/)//正整数 |
|||
this.tableData[index][value] = _match?_match[0]:_match |
|||
} |
|||
if(this.tableData[index][value] > item.max){ |
|||
this.tableData[index][value] = item.max |
|||
} |
|||
if(this.tableData[index][value] && this.tableData[index][value] < item.min){ |
|||
this.tableData[index][value] = item.min |
|||
} |
|||
if(item.onkeyup)item.onkeyup() |
|||
}, |
|||
tableColumnsFilter() { |
|||
let widthSize = _.cloneDeep(this.tableColumns); |
|||
for(let i = 0;i<widthSize.length;i++){ |
|||
let item = widthSize[i] |
|||
if (item.type == "autocomplete" || item.type == "objectAutocomplete") { |
|||
item.width = item.width ? item.width: "300px"; |
|||
} else if (item.type == "input" || item.type == "objectInput") { |
|||
if (item.width == '100%') { |
|||
item.width = '' |
|||
} else { |
|||
item.width = item.width ? item.width: "200px"; |
|||
} |
|||
} else if ( |
|||
item.type == "dateTimeInput" || |
|||
item.type == "objectDateTimeInput" |
|||
) { |
|||
item.width =item.width ? item.width: "200px"; |
|||
} else if (item.type == "objectDateTime" || item.type == "dateTime") { |
|||
item.width =item.width ? item.width: "200px"; |
|||
} else if (item.width == '100%') { |
|||
item.width = '' |
|||
} else { |
|||
item.width =item.width ? item.width: "150px"; |
|||
} |
|||
} |
|||
// this.TableSize = widthSize; |
|||
return widthSize |
|||
}, |
|||
inputPlaceholder(val, item, type, func) { |
|||
if (item.valueType) { |
|||
if (type == "focus") { |
|||
val.target.placeholder = "请输入" + item.label; |
|||
if (val.target.value != "") { |
|||
val.target.placeholder = val.target.value; |
|||
val.target.value = ""; |
|||
} |
|||
} else if (type == "blur") { |
|||
// val.target.value = "0" |
|||
val.target.value = val.target.value.toString().replace(/[^\d.]/g,'') |
|||
if (val.target.value == "") { |
|||
// if (val.target.placeholder.indexOf('请输入') == -1) { |
|||
val.target.value = val.target.placeholder; |
|||
// } |
|||
} |
|||
if(item.showProp){ |
|||
func[item.prop][item.showProp]= Number(val.target.value) |
|||
}else{ |
|||
func[item.prop]= Number(val.target.value) |
|||
} |
|||
// item.valueType |
|||
// ? (this.tableData[index][value] = item.valueType( |
|||
// this.tableData[index][value] |
|||
// )) |
|||
// : () => { |
|||
// return; |
|||
// } |
|||
} |
|||
} |
|||
}, |
|||
// handeleInput (et, item) { |
|||
// const { optionsValue } = item |
|||
// let func = item.focus |
|||
// let filter = { |
|||
// logic: "And", |
|||
// column: optionsValue, |
|||
// action: "Like", |
|||
// value: et |
|||
// } |
|||
// debounce(func(filter), 2000,true) |
|||
// }, |
|||
//autocomplete下拉 |
|||
querySearch(queryString, cb, val, row) { |
|||
const { options, optionsValue, optionsLabel } = val; |
|||
let func = val.focus; |
|||
let data = { |
|||
scope: row, |
|||
}; |
|||
if (queryString) { |
|||
data.filter = [ |
|||
{ |
|||
logic: "And", |
|||
column: optionsValue, |
|||
action: "Like", |
|||
value: queryString, |
|||
}, |
|||
// { |
|||
// logic: "Or", |
|||
// column: optionsLabel, |
|||
// action: "Like", |
|||
// value: queryString |
|||
// } |
|||
]; |
|||
} |
|||
func(data).then((res) => { |
|||
var restaurants = this.searchOptions["options"]; |
|||
let results = queryString |
|||
? restaurants.filter( |
|||
this.createFilter(queryString, optionsValue, optionsLabel) |
|||
) |
|||
: restaurants; |
|||
results.forEach((key) => { |
|||
if (typeof optionsValue === "string") { |
|||
key.value = key[optionsValue] + "----" + key[optionsLabel]; |
|||
} else { |
|||
key.value = |
|||
key[optionsValue[0]][optionsValue[1]] + |
|||
"----" + |
|||
key[optionsLabel]; |
|||
} |
|||
}); |
|||
// 调用 callback 返回建议列表的数据 |
|||
cb(results); |
|||
}); |
|||
}, |
|||
createFilter(queryString, optionsValue, optionsLabel) { |
|||
return (restaurant) => { |
|||
if (typeof optionsValue === "string") { |
|||
restaurant.value = |
|||
restaurant[optionsValue] + "----" + restaurant[optionsLabel]; |
|||
} else { |
|||
restaurant.value = |
|||
restaurant[optionsValue[0]][optionsValue[1]] + |
|||
"----" + |
|||
restaurant[optionsLabel]; |
|||
} |
|||
return ( |
|||
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) != |
|||
-1 |
|||
); |
|||
}; |
|||
}, |
|||
handleSelect(item, val, scope) { |
|||
let data = this.tableData[scope.$index]; |
|||
if (!val.showProp) { |
|||
if (typeof val.optionsValue === "string") { |
|||
data[val.prop] = item[val.optionsValue]; |
|||
} else { |
|||
data[val.prop] = item[val.optionsValue[0]][val.optionsValue[1]]; |
|||
} |
|||
} else { |
|||
if (typeof val.optionsValue === "string") { |
|||
data[val.prop][val.showProp] = item[val.optionsValue]; |
|||
} else { |
|||
data[val.prop][val.showProp] = |
|||
item[val.optionsValue[0]][val.optionsValue[1]]; |
|||
} |
|||
} |
|||
this.$emit("push", item, scope, val); |
|||
}, |
|||
// selectFocus (val, item) { |
|||
// this.selectLoading = true; |
|||
// let func = item.focus |
|||
// func({}).then(res => { |
|||
// this.selectLoading = false; |
|||
// }) |
|||
// }, |
|||
// dataFilter (query, item, row) { |
|||
// const { options, optionsValue, optionsLabel } = item |
|||
// let func = item.focus |
|||
// let data = { |
|||
// scope: row |
|||
// } |
|||
// this.selectLoading = true; |
|||
// if (query) { |
|||
// data.filter = { |
|||
// logic: "And", |
|||
// column: optionsLabel, |
|||
// action: "Like", |
|||
// value: query |
|||
// } |
|||
// } |
|||
// setTimeout(() => { |
|||
// func(data).then(res => { |
|||
// this.selectLoading = false; |
|||
// }) |
|||
// }, 200); |
|||
// }, |
|||
getMaxLength(arr) { |
|||
return arr.reduce((acc, item) => { |
|||
if (item) { |
|||
const calcLen = this.getTexWidth(item); |
|||
if (acc < calcLen) { |
|||
acc = calcLen; |
|||
} |
|||
} |
|||
return acc; |
|||
}, 0); |
|||
}, |
|||
getTexWidth(str) { |
|||
let width = 0; |
|||
const html = document.createElement("span"); |
|||
html.innerText = str; |
|||
html.className = "getTextWidth"; |
|||
document.querySelector("body").appendChild(html); |
|||
width = document.querySelector(".getTextWidth").offsetWidth; |
|||
document.querySelector(".getTextWidth").remove(); |
|||
return width; |
|||
}, |
|||
flexColumnWidth(label, prop) { |
|||
const arr = this.tableData.map((x) => { |
|||
if (typeof prop !== "string") { |
|||
return x[prop[0]][prop[1]]; |
|||
} else { |
|||
return x[prop]; |
|||
} |
|||
}); |
|||
arr.push(label); |
|||
return this.getMaxLength(arr) + 60 + "px"; |
|||
}, |
|||
//排序 |
|||
sortChange(data) { |
|||
this.$emit("sortChange", data); |
|||
}, |
|||
//点击selection框 |
|||
handleSelectionChange(val) { |
|||
this.$emit("handleSelectionChange", val); |
|||
}, |
|||
//点击name提交emit打开编辑页面 |
|||
inlineDialog(row) { |
|||
this.$emit("inlineDialog", row); |
|||
}, |
|||
//点击按钮打开自定义弹窗 |
|||
buttonClick(row, index, label) { |
|||
this.$emit("buttonClick", row, index, label); |
|||
}, |
|||
rowDrop() { |
|||
const tbody = this.$refs.multipleTable.$el.querySelector( |
|||
".el-table__body-wrapper tbody" |
|||
); |
|||
const _this = this; |
|||
Sortable.create(tbody, { |
|||
onEnd({ newIndex, oldIndex }) { |
|||
const currRow = _this.tableData.splice(oldIndex, 1)[0]; |
|||
_this.tableData.splice(newIndex, 0, currRow); |
|||
}, |
|||
}); |
|||
}, |
|||
//列拖拽 |
|||
columnDrop() { |
|||
const wrapperTr = this.$refs.multipleTable.$el.querySelector( |
|||
".el-table__header-wrapper tr" |
|||
); |
|||
let bomIndex = this.selectionTable ? 1 : 0; |
|||
this.sortable = Sortable.create(wrapperTr, { |
|||
animation: 180, |
|||
delay: 0, |
|||
onEnd: (evt) => { |
|||
const oldItem = this.TableSize[evt.oldIndex - bomIndex]; |
|||
this.TableSize.splice(evt.oldIndex - bomIndex, 1); |
|||
this.TableSize.splice(evt.newIndex - bomIndex, 0, oldItem); |
|||
}, |
|||
}); |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
::v-deep .el-form-item__error{ |
|||
position: relative; |
|||
} |
|||
::v-deep .el-table__fixed { |
|||
display: block-inline !important; |
|||
height: auto !important; |
|||
bottom: 13px !important; |
|||
.el-table__fixed-header-wrapper { |
|||
z-index: auto !important; |
|||
} |
|||
.el-table__fixed-body-wrapper { |
|||
z-index: auto !important; |
|||
} |
|||
} |
|||
::v-deep .el-table__fixed::before, |
|||
.el-table__fixed-right::before { |
|||
z-index: auto !important; |
|||
} |
|||
.spamHover { |
|||
color: #409eff; |
|||
cursor: pointer; |
|||
} |
|||
.spamHover:hover { |
|||
border-bottom: 1px solid #409eff; |
|||
color: blue; |
|||
} |
|||
span { |
|||
white-space: pre; |
|||
} |
|||
::v-deep .el-select { |
|||
.el-input__inner { |
|||
padding: 0 30px 0 15px; |
|||
} |
|||
.el-input__prefix { |
|||
width: 100% !important; |
|||
left: 0; |
|||
.el-button { |
|||
position: absolute; |
|||
top: 0; |
|||
right: 0; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,322 @@ |
|||
<template> |
|||
<div class="currenTableFlex"> |
|||
<div class="headerButtons"> |
|||
<el-button |
|||
type="primary" |
|||
v-if="showAddBtn" |
|||
@click="flexOpenAddNew" |
|||
icon="el-icon-plus" |
|||
size="mini" |
|||
>添加一行</el-button> |
|||
<slot name="headerBtns"></slot> |
|||
</div> |
|||
<!-- todo:多选处理【selectionTable】 --> |
|||
<umyTable |
|||
:isEditable="isEditable" |
|||
class="flexTable" |
|||
:tableData="flexTableData" |
|||
:searchOptions="flexSearchOptions" |
|||
:tableColumns="flexTableColumns" |
|||
:selectionTable="selectionTable" |
|||
:isShowIndex="isShowIndex" |
|||
:setUTableHeight="setUTableHeight" |
|||
@push="detailsDataPush(arguments)" |
|||
> |
|||
<template v-if="showAllDeleteButton"> |
|||
<el-table-column |
|||
label="操作" |
|||
align="center" |
|||
fixed="right" |
|||
width="100px" |
|||
> |
|||
<template slot-scope="scope"> |
|||
<div |
|||
v-if="!scope.row.hide" |
|||
class="childTable" |
|||
@click="flexRowRemove($event, scope)" |
|||
> |
|||
<span style="color:red">删除</span> |
|||
</div> |
|||
</template> |
|||
</el-table-column> |
|||
</template> |
|||
</umyTable> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenTable from "@/components/currenTable" |
|||
import { mixins } from "@/mixins/mixins" |
|||
export default { |
|||
name: 'currenTableFlex', |
|||
components: { |
|||
currenTable |
|||
}, |
|||
mixins: [ |
|||
mixins, |
|||
], |
|||
filters: { |
|||
// formData (val) { |
|||
// let data = JSON.parse(JSON.stringify(val)) |
|||
// val.forEach((key, index) => { |
|||
// data[index].disabled = "true" |
|||
// delete data[index].focus |
|||
// if (key.type == "autocomplete" || key.type == "import") { |
|||
// data[index].type = "input" |
|||
// } |
|||
// }); |
|||
// return data |
|||
// }, |
|||
// formDataDetails (val) { |
|||
// let data = JSON.parse(JSON.stringify(val)) |
|||
// val.forEach((key, index) => { |
|||
// data[index].disabled = true |
|||
// delete data[index].focus |
|||
// delete data[index].rules |
|||
// if (key.type == "autocomplete" || key.type == "import") { |
|||
// delete data[index].type |
|||
// } else if (key.type == "objectAutocomplete") { |
|||
// data[index].type = "object" |
|||
// } else if (key.prop == "containerCode" && key.type == "input") { |
|||
// data[index].disabled = false |
|||
// } else if (key.isChange) { |
|||
// // 针对第三步预览特殊情况处理 |
|||
// data[index].disabled = false |
|||
// } |
|||
// }); |
|||
// return data |
|||
// } |
|||
}, |
|||
props: { |
|||
// table内表单数据是否可编辑 |
|||
isEditable:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 已app-main高度为100% 需要减掉的高度 |
|||
setUTableHeight: { |
|||
type: Number, |
|||
default: () => { |
|||
return 280; |
|||
} |
|||
}, |
|||
// 是否显示添加一行按钮 |
|||
showAddBtn:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 是否显示删除按钮(控制全部列) |
|||
showAllDeleteButton:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 是否禁止编辑行(控制全部行) |
|||
disableAllRow:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
flexTableData: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
flexSearchOptions: { |
|||
type: Object, |
|||
default: () => { |
|||
return {}; |
|||
}, |
|||
}, |
|||
flexTableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
// 是否显示多选 |
|||
selectionTable: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
// 是否显示序号列 |
|||
isShowIndex: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
//名称 |
|||
// formTitle: { |
|||
// type: String, |
|||
// default: '' |
|||
// }, |
|||
// //是否弹窗 |
|||
// displayDialog: { |
|||
// type: Object, |
|||
// default: () => { |
|||
// return { |
|||
// newDialog: false |
|||
// } |
|||
// } |
|||
// }, |
|||
// //主表提交数据 |
|||
// CreateFormData: { |
|||
// type: Object, |
|||
// default: () => { |
|||
// return {} |
|||
// } |
|||
// }, |
|||
// //主表显示form |
|||
// CreateForm: { |
|||
// type: Array, |
|||
// default: () => { |
|||
// return [] |
|||
// } |
|||
// }, |
|||
// //预览数据 |
|||
// previewFormData: { |
|||
// type: Object, |
|||
// default: () => { |
|||
// return {} |
|||
// } |
|||
// }, |
|||
// Rules: { |
|||
// type: Object, |
|||
// default: () => { |
|||
// return {} |
|||
// } |
|||
// }, |
|||
// //下拉选择 |
|||
// Options: { |
|||
// type: Object, |
|||
// default: () => { |
|||
// return {} |
|||
// } |
|||
// }, |
|||
// //子表table显示 |
|||
// detailsTableColumns: { |
|||
// type: Array, |
|||
// default: () => { |
|||
// return [] |
|||
// } |
|||
// }, |
|||
// //子表提交数据 |
|||
// childTableData: { |
|||
// type: Array, |
|||
// default: () => { |
|||
// return [] |
|||
// } |
|||
// }, |
|||
// //成功后的操作 |
|||
// successHandle: { |
|||
// type: Array, |
|||
// default: () => { |
|||
// return [] |
|||
// } |
|||
// }, |
|||
// //步骤标题 |
|||
// stepArray: { |
|||
// type: Array, |
|||
// default: () => { |
|||
// return ["总体信息", "明细", "预览", "结果"] |
|||
// } |
|||
// }, |
|||
// //添加一行 |
|||
// addClickButton: { |
|||
// type: Boolean, |
|||
// default: () => { |
|||
// return true |
|||
// } |
|||
// }, |
|||
// //删除行记录 |
|||
// isShowDeleteButton: { |
|||
// type: Boolean, |
|||
// default: () => { |
|||
// return true |
|||
// } |
|||
// }, |
|||
// // 隐藏第一步骤的取消按钮 |
|||
// isHideFirstActiveCancel:{ |
|||
// type: Boolean, |
|||
// default: () => { |
|||
// return false |
|||
// } |
|||
// }, |
|||
// // 预览视图显示删除按钮 |
|||
// showPreviewFormDeleteButton:{ |
|||
// type: Boolean, |
|||
// default: () => { |
|||
// return false |
|||
// } |
|||
// } |
|||
}, |
|||
data () { |
|||
return { |
|||
// 添加一行的空置 |
|||
addEmptyRow:null, |
|||
// active: 0, |
|||
// formReveal: 1, |
|||
// activeStep: 1, |
|||
// pageStatus: '', |
|||
// addClick: this.addClickButton,//添加一行按钮 |
|||
// showDeleteButton: this.isShowDeleteButton,//操作-删除按钮 |
|||
// hideFirstActiveCancel:this.isHideFirstActiveCancel,// 隐藏第一步骤的取消按钮 |
|||
// loading: false, |
|||
// session: null, |
|||
// step: this.stepArray, |
|||
// editHandle: [ |
|||
// { label: "取消", name: "cancel" }, |
|||
// { label: "下一步", type: "primary", name: "determine" }, |
|||
// ], |
|||
} |
|||
}, |
|||
mounted () { |
|||
// this.session = JSON.parse(JSON.stringify(this.CreateFormData)) |
|||
// if(this.hideFirstActiveCancel){ |
|||
// this.editHandle=[ |
|||
// { label: "下一步", type: "primary", name: "determine" }, |
|||
// ]; |
|||
// } |
|||
}, |
|||
methods: { |
|||
//添加行 |
|||
flexOpenAddNew() { |
|||
let _oneRow = Object.assign({}, this.flexTableData[0]) |
|||
for(let key in _oneRow){ |
|||
_oneRow[key] = null |
|||
} |
|||
this.flexTableData.push(_oneRow) |
|||
// if(this.flexTableData.length <= 0)return |
|||
// if(!this.addEmptyRow){ |
|||
// let _oneRow = Object.assign({}, this.flexTableData[0]) |
|||
// for(let key in _oneRow){ |
|||
// _oneRow[key] = null |
|||
// } |
|||
// this.addEmptyRow = _oneRow |
|||
// this.addEmptyRow['disabled']=false |
|||
// } |
|||
// this.flexTableData.push(this.addEmptyRow) |
|||
}, |
|||
//删除行 |
|||
flexRowRemove(e, val) { |
|||
this.$confirm('您确定删除吗, 是否继续?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.flexTableData.splice(val.$index, 1) |
|||
}).catch(() => { |
|||
|
|||
}); |
|||
}, |
|||
//点击selection框 |
|||
handleSelectionChange(val) { |
|||
this.$emit("handleSelectionChange", val); |
|||
}, |
|||
// //autoComplete子表 |
|||
detailsDataPush (val) { |
|||
this.$emit("detailsDataPush", val) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,12 @@ |
|||
.currenTableFlex{ |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
.flexTable{ |
|||
height: 100%; |
|||
} |
|||
.headerButtons{ |
|||
text-align: center; |
|||
margin-bottom: 20px; |
|||
} |
|||
} |
@ -0,0 +1,57 @@ |
|||
<template> |
|||
<el-tabs |
|||
v-model="tabsName" |
|||
@tab-click="handleClick" |
|||
:tab-position="tabPosition" |
|||
> |
|||
<el-tab-pane |
|||
v-for="(item, index) in tabsData" |
|||
:key="index" |
|||
:label="item.label" |
|||
:name="item.name" |
|||
> |
|||
<span slot="label"><i :class="item.icon"></i>{{ item.label }}</span> |
|||
<slot :value="item.name"></slot> |
|||
</el-tab-pane> |
|||
</el-tabs> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'currenTabs', |
|||
watch: { |
|||
activeName(newVal, oldVal){ |
|||
this.tabsName = newVal |
|||
} |
|||
}, |
|||
props: { |
|||
activeName: { |
|||
type: String, |
|||
default: 'first' |
|||
}, |
|||
tabsData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
type: { |
|||
type: String, |
|||
default: 'border-card' //card/border-card |
|||
}, |
|||
tabPosition: { |
|||
type: String, |
|||
default: 'top' |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
tabsName: this.activeName |
|||
} |
|||
}, |
|||
methods: { |
|||
handleClick (val) { |
|||
this.$emit("handleClick", val) |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,82 @@ |
|||
<template> |
|||
<div class="curren-upload"> |
|||
<el-upload |
|||
ref="upload" |
|||
class="avatar-uploader" |
|||
drag |
|||
action="#" |
|||
:http-request="httpRequestfiles" |
|||
:file-list="searchData" |
|||
:before-upload="beforeAvatarUpload" |
|||
:before-remove="beforeRemove" |
|||
:on-remove="handleRemove" |
|||
:on-exceed="handleExceed" |
|||
multiple |
|||
:limit="limit" |
|||
:accept="picExt" |
|||
> |
|||
<i class="el-icon-upload"></i> |
|||
<div class="el-upload__text"> |
|||
将文件拖到此处,或 |
|||
<em>点击上传</em> |
|||
</div> |
|||
</el-upload> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: "currenUpload", |
|||
props: { |
|||
limit: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
searchData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
beforeUpload: { |
|||
type: Function, |
|||
default: () => { |
|||
return Function |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
isFileType: '', |
|||
picExt:'.xlsx' |
|||
} |
|||
}, |
|||
methods: { |
|||
httpRequestfiles (val) { |
|||
let rd = new FileReader(); // 创建文件读取对象 |
|||
let file = val.file; |
|||
this.$emit('httpRequestfiles', file) |
|||
rd.readAsDataURL(file); // 文件读取装换为base64类型 |
|||
}, |
|||
beforeAvatarUpload (val) { |
|||
let suffix = val.name.substring(val.name.lastIndexOf('.') + 1) |
|||
if (this.picExt.indexOf(suffix) === -1) { |
|||
this.$warningMsg('上传文件只能是 ' + this.picExt + '格式!') |
|||
return false |
|||
} |
|||
return this.beforeUpload(val, this.searchData) |
|||
|
|||
}, |
|||
beforeRemove (val) { |
|||
// if (val && val.status === "success") { |
|||
// return this.$confirm(`确定移除 ${val.name}?`); |
|||
// } |
|||
}, |
|||
handleRemove (file, fileList) { |
|||
this.$emit('handleRemove', fileList) |
|||
}, |
|||
handleExceed (val) { |
|||
this.$warningMsg('最多上传' + this.limit + '个文件') |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,72 @@ |
|||
<template> |
|||
<div> |
|||
<el-upload |
|||
ref="uploadPicture" |
|||
class="upload-demo" |
|||
action="#" |
|||
:file-list="searchData" |
|||
:on-remove="handleRemove" |
|||
:on-exceed="handleExceed" |
|||
:on-change="changeUpload" |
|||
multiple |
|||
:limit="limit" |
|||
:accept="picExt" |
|||
:auto-upload="false" |
|||
> |
|||
<el-button slot="trigger" size="mini" type="primary">上传</el-button> |
|||
<el-button style="margin-left: 10px;" size="mini" type="info" @click="uploadListView">查看</el-button> |
|||
</el-upload> |
|||
|
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: "currenUploadList", |
|||
props: { |
|||
limit: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
searchData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
picExt: { |
|||
type: String, |
|||
default: "", |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
isFileType: '', |
|||
} |
|||
}, |
|||
methods: { |
|||
changeUpload (val) { |
|||
// let suffix = val.name.substring(val.name.lastIndexOf('.') + 1) |
|||
// if (this.picExt.indexOf(suffix) === -1) { |
|||
// this.$warningMsg('上传文件只能是 ' + this.picExt + '格式!') |
|||
// return false |
|||
// } |
|||
let rd = new FileReader(); // 创建文件读取对象 |
|||
let file = val.raw; |
|||
this.$emit('changeUpload', file) |
|||
rd.readAsDataURL(file); // 文件读取装换为base64类型 |
|||
}, |
|||
handleRemove (file, fileList) { |
|||
this.$emit('handleRemove', fileList) |
|||
}, |
|||
handleExceed (val) { |
|||
this.$warningMsg('最多上传' + this.limit + '个文件') |
|||
}, |
|||
uploadListView() { |
|||
this.$emit('uploadListView') |
|||
}, |
|||
submitUpload() { |
|||
this.$refs.upload.submit(); |
|||
}, |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,100 @@ |
|||
<template> |
|||
<div class="curren-upload"> |
|||
<el-upload |
|||
action="#" |
|||
list-type="picture-card" |
|||
:auto-upload="false" |
|||
:multiple="multiple" |
|||
:limit="limit" |
|||
:accept="picExt" |
|||
:file-list="searchData" |
|||
:on-exceed="handleExceed" |
|||
:on-remove="handleRemove" |
|||
:on-preview="handlePictureCardPreview" |
|||
:on-change="changeUpload" |
|||
> |
|||
<i slot="default" class="el-icon-plus"></i> |
|||
<!-- <div slot="file" slot-scope="{file}"> |
|||
<img |
|||
class="el-upload-list__item-thumbnail" |
|||
:src="file.url" alt="" |
|||
> |
|||
<span class="el-upload-list__item-actions"> |
|||
<span |
|||
class="el-upload-list__item-preview" |
|||
@click="handlePictureCardPreview(file)" |
|||
> |
|||
<i class="el-icon-zoom-in"></i> |
|||
</span> |
|||
<span |
|||
v-if="!disabled" |
|||
class="el-upload-list__item-delete" |
|||
@click="handleRemove(file)" |
|||
> |
|||
<i class="el-icon-delete"></i> |
|||
</span> |
|||
</span> |
|||
</div> --> |
|||
</el-upload> |
|||
<el-dialog |
|||
:visible.sync="dialogVisible" |
|||
top="1vh" |
|||
width="35%" |
|||
:modal-append-to-body="false" |
|||
:append-to-body="true" |
|||
:show-close="true" |
|||
> |
|||
<img width="100%" :src="dialogImageUrl" alt=""> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: "currenUploadPictureCard", |
|||
props: { |
|||
limit: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
multiple:{ |
|||
type: Boolean, |
|||
default:false |
|||
}, |
|||
searchData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
picExt: { |
|||
type: String, |
|||
default: "", |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
dialogImageUrl: '', |
|||
dialogVisible: false, |
|||
disabled: false |
|||
} |
|||
}, |
|||
methods: { |
|||
handlePictureCardPreview(file) { |
|||
this.dialogImageUrl = file.url; |
|||
this.dialogVisible = true; |
|||
}, |
|||
// handleDownload(file) { |
|||
// console.log(file); |
|||
// }, |
|||
changeUpload (val) { |
|||
this.$emit('changeUpload', val) |
|||
}, |
|||
handleRemove (file, fileList) { |
|||
this.$emit('handleRemove', fileList) |
|||
}, |
|||
handleExceed (val) { |
|||
this.$warningMsg('最多上传' + this.limit + '个文件') |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div> |
|||
<el-dialog |
|||
title="导出" |
|||
:visible.sync="show" |
|||
:append-to-body="true" |
|||
:modal-append-to-body="false" |
|||
width="800px" |
|||
:show-close="true" |
|||
@close="close" |
|||
> |
|||
<div class="formItem"> |
|||
<span class="title">是否显示明细:</span> |
|||
<el-radio-group v-model="form.isDetail" > |
|||
<el-radio :label="true">是</el-radio> |
|||
<el-radio :label="false">否</el-radio> |
|||
</el-radio-group> |
|||
</div> |
|||
<div class="formItem"> |
|||
<span class="title">是否冗余主表数据:</span> |
|||
<el-radio-group v-model="form.isRedundance" > |
|||
<el-radio :label="true">是</el-radio> |
|||
<el-radio :label="false">否</el-radio> |
|||
</el-radio-group> |
|||
</div> |
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="submit('page')">本页导出</el-button> |
|||
<el-button |
|||
:spinner="'el-icon-loading'" |
|||
type="primary" |
|||
@click="submit('all')" |
|||
>全部导出</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
name: 'exportDrop', |
|||
props: { |
|||
// 导出是【否冗余主表数据】配置 |
|||
isDetail:{ |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
// 导出是【显示明细】配置 |
|||
isRedundance:{ |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
show:true, |
|||
form:{ |
|||
isDetail:null, |
|||
isRedundance:null, |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.form={ |
|||
isDetail:this.isDetail, |
|||
isRedundance:this.isRedundance, |
|||
} |
|||
}, |
|||
methods: { |
|||
close() { |
|||
this.show = false |
|||
this.$emit("closeDialog") |
|||
}, |
|||
submit(type){ |
|||
this.$emit("exportDropSubmit",type,this.form) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.formItem{ |
|||
padding-bottom: 15px; |
|||
display: flex; |
|||
.title{ |
|||
width: 180px; |
|||
text-align: right; |
|||
padding-right: 10px; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,338 @@ |
|||
<template> |
|||
<div class="filterForDetailPage" v-if="dialogShow"> |
|||
<el-dialog |
|||
title="明细查询" |
|||
:visible.sync="dialogShow" |
|||
top="5vh" |
|||
width="96%" |
|||
:modal-append-to-body="false" |
|||
:append-to-body="false" |
|||
:show-close="true" |
|||
@close="closeDialog(false)" |
|||
class="mainTable-dialog" |
|||
> |
|||
<div |
|||
class="filterForDetailPage-list" |
|||
v-loading="Loading.tableLoading" |
|||
> |
|||
<!-- 列表 --> |
|||
<tablePagination |
|||
v-if="dialogShow && listColumns && listColumns.length > 0" |
|||
:currenButtonData="currenButtonData" |
|||
:tableData="tableData" |
|||
:tableLoading="Loading.tableLoading" |
|||
@rowDrop="rowDropForDetail" |
|||
:rowSource="'detailPage_api'" |
|||
:searchOverallCoverHeight="'calc(100vh - 380px)'" |
|||
:rowMaxHeight="rowMaxHeight" |
|||
:tableColumns="listColumns" |
|||
:totalCount="totalCount" |
|||
:multipleSelection="multipleSelection" |
|||
:MaxResultCount="PageListParams.MaxResultCount" |
|||
:setUTableHeight="setUTableHeight" |
|||
:selectMaxHeight="'116px'" |
|||
@topbutton="topbutton" |
|||
@inlineDialog="inlineDialog" |
|||
@sortChange="sortChange" |
|||
@alertoldSkipCount="alertoldSkipCount" |
|||
@alterResultCount="alterResultCount" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
:currentPageProps="oldSkipCount" |
|||
:quicklySearchOption="quicklySearchOption" |
|||
@quicklySearchClick="quicklySearchClick" |
|||
@quicklySearchClear="quicklySearchClear" |
|||
:primarySearchOption="primarySearchOption" |
|||
@overallSearchFormClick="overallSearchFormClick" |
|||
:httpOverallSearchData="httpOverallSearchData" |
|||
> |
|||
<template> |
|||
<!-- todo:width处理 --> |
|||
<el-table-column |
|||
v-if="operaButtons && operaButtons.length > 0" |
|||
label="操作" |
|||
:align="'center'" |
|||
width="150" |
|||
fixed="left" |
|||
> |
|||
<template slot-scope="scope"> |
|||
<span v-for="item in operaButtons" style="margin: 0 10px;"> |
|||
<!-- 查看主表信息 --> |
|||
<el-button |
|||
v-if="item == 'showParent'" |
|||
type="text" |
|||
@click="showParentHandleForDetail(scope.row)" |
|||
>查看主表信息</el-button> |
|||
<!-- 编辑 --> |
|||
<el-button |
|||
v-if="item == 'edit'" |
|||
type="text" |
|||
style="color: #ff9000;" |
|||
@click="editHandleForDetail(scope.row)" |
|||
>编辑</el-button> |
|||
<!-- 删除 --> |
|||
<el-popover |
|||
v-if="item == 'delete'" |
|||
placement="left" |
|||
width="260" |
|||
v-model="scope.row.deleteTipVisible" |
|||
> |
|||
<p>此操作将永久删除该消息, 是否继续?</p> |
|||
<div style="text-align: right; margin: 0"> |
|||
<el-button size="mini" type="text" style="margin-right: 20px;" @click="scope.row.deleteTipVisible = false">取消</el-button> |
|||
<el-button type="primary" size="mini" @click="deleteHandleForDetail(scope.row)">确定</el-button> |
|||
</div> |
|||
<el-button type="text" slot="reference" style="color: red;">删除</el-button> |
|||
</el-popover> |
|||
</span> |
|||
</template> |
|||
</el-table-column> |
|||
</template> |
|||
</tablePagination> |
|||
</div> |
|||
</el-dialog> |
|||
<!-- 主表信息 --> |
|||
<el-dialog |
|||
:modal-append-to-body="false" |
|||
:append-to-body="false" |
|||
:title="showParentTitle" |
|||
:visible.sync="showParentDialog" |
|||
:close-on-click-modal="true" |
|||
:close-on-press-escape="true" |
|||
:show-close="true" |
|||
width="70%" |
|||
> |
|||
<div v-loading="showParentLoading"> |
|||
<curren-descriptions |
|||
v-if="showParentTableData" |
|||
border |
|||
:column="column" |
|||
:direction="direction" |
|||
:colon="false" |
|||
:tabsDesTions="parentColumns" |
|||
:propsData="showParentTableData" |
|||
style="padding-bottom: 20px;" |
|||
></curren-descriptions> |
|||
</div> |
|||
<!-- <el-table :data="showParentTableData"> |
|||
<el-table-column property="date" label="日期" width="150"></el-table-column> |
|||
<el-table-column property="name" label="姓名" width="200"></el-table-column> |
|||
<el-table-column property="address" label="地址"></el-table-column> |
|||
</el-table> --> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenDescriptions from "@/components/currenDescriptions" |
|||
import { tableMixins } from "@/mixins/TableMixins"; |
|||
import { TableHeaderMixins } from "@/mixins/TableHeaderMixins"; |
|||
import { LoadingMixins } from "@/mixins/LoadingMixins"; |
|||
import { mixins } from "@/mixins/mixins"; |
|||
import { filterSelectMixins } from '@/mixins/filter-Select' |
|||
import {getListDesById,getPageListForDetail} from "@/api/wms-api" |
|||
export default { |
|||
name: 'filterForDetailPage', |
|||
mixins: [ |
|||
tableMixins, |
|||
TableHeaderMixins, |
|||
mixins, |
|||
filterSelectMixins, |
|||
LoadingMixins |
|||
], |
|||
components:{ |
|||
currenDescriptions |
|||
}, |
|||
props: { |
|||
// 已app-main高度为100% 需要减掉的高度 |
|||
setUTableHeight: { |
|||
type: Number, |
|||
default: 340 |
|||
}, |
|||
// 是否显示序号 |
|||
isShowIndex:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 复选框 |
|||
tableSelection: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
cellStyle: { |
|||
type: Function, |
|||
default: () => { |
|||
return Function; |
|||
} |
|||
}, |
|||
// 超出内容是否提示 |
|||
showOverflowTooltip:{ |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
// 删除api |
|||
DeleteApi: { |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 主表数据-表头 |
|||
parentColumns:{ |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
showHandleButtons:{ |
|||
type:Array, |
|||
default:() => { |
|||
//'add','edit'暂未处理操作 'delete'暂时隐藏 |
|||
// showParent查看主表信息,fresh刷新,filter筛选,field字段设置 |
|||
return ['showParent','fresh','filter','field']; |
|||
} |
|||
}, |
|||
// 父级展现列数,默认为2列展现 |
|||
column: { |
|||
type: Number, |
|||
default: 2 |
|||
}, |
|||
// 父级展示方式,默认水平分布 |
|||
direction: { |
|||
type: String, |
|||
default: 'horizontal' |
|||
}, |
|||
rowMaxHeight:{ |
|||
type:String, |
|||
default:'calc(90vh - 450px)' |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
dialogShow:true, |
|||
// URLOption_detailList:allUrlOption[this.$route.name].detailListURL,//明细-列表 |
|||
// URLOption_masterId:allUrlOption[this.$route.name].masterId || 'masterId',//明细-查看主表的连接id |
|||
// URLOption_masterName:allUrlOption[this.$route.name].masterName,//明细-列表//明细-查看主表的连接title名称 |
|||
// URLOption_parent:allUrlOption[this.$route.name].parentURL ? allUrlOption[this.$route.name].parentURL : allUrlOption[this.$route.name].detailURL,//明细-查看主表 |
|||
currenButtonData: [],//头部按钮 |
|||
operaButtons:[],//操作列按钮 |
|||
showParentDialog:false,//显示父级数据弹窗 |
|||
showParentTitle:null,//显示父级数据弹窗-title |
|||
showParentTableData:null,//显示父级数据弹窗-数据 |
|||
showParentLoading:false,//显示父级数据弹窗-加载 |
|||
listColumns:[],//表头数据 |
|||
} |
|||
}, |
|||
activated(){ |
|||
// 解决切换页面的时候,遮罩层消失的问题 |
|||
this.dialogShow = false |
|||
this.$nextTick(() => { |
|||
this.dialogShow = true |
|||
}); |
|||
}, |
|||
mounted(){ |
|||
this.paging() |
|||
this.initHandleButtons() |
|||
}, |
|||
methods: { |
|||
rowDropForDetail(data,type){ |
|||
this.listColumns = data |
|||
this.$emit("rowDropForDetail", data,type) |
|||
}, |
|||
// 初始化显示按钮 |
|||
initHandleButtons(){ |
|||
// 头部按钮 |
|||
let _arr_header = [] |
|||
if(this.showHandleButtons.indexOf('add') >= 0){_arr_header.push(this.defaultAddBtn())} |
|||
if(this.showHandleButtons.indexOf('field') >= 0){_arr_header.push(this.defaultFieldSettingBtn())} |
|||
if(this.showHandleButtons.indexOf('fresh') >= 0){_arr_header.push(this.defaultFreshBtn())} |
|||
if(this.showHandleButtons.indexOf('filter') >= 0){_arr_header.push(this.defaultFilterBtn())} |
|||
this.currenButtonData = _arr_header |
|||
|
|||
// 操作列按钮 |
|||
let _arr_op = [] |
|||
if(this.showHandleButtons.indexOf('edit') >= 0){_arr_op.push('edit')} |
|||
if(this.showHandleButtons.indexOf('delete') >= 0){_arr_op.push('delete')} |
|||
if(this.showHandleButtons.indexOf('showParent') >= 0){_arr_op.push('showParent')} |
|||
this.operaButtons = _arr_op |
|||
}, |
|||
// 关闭明细查询弹窗 |
|||
closeDialog(data){ |
|||
this.dialogShow = false |
|||
this.$emit("closeDialog", data) |
|||
}, |
|||
// 获取列表 |
|||
paging(callback){ |
|||
this.Loading.tableLoading = true; |
|||
this.PageListParams.SkipCount = (this.oldSkipCount - 1) * this.PageListParams.MaxResultCount |
|||
getPageListForDetail(this.PageListParams,this.URLOption_detailList) |
|||
.then(res=>{ |
|||
// 表头处理 |
|||
let _parentName = this.URLOption_detailList.substr(0,this.URLOption_detailList.indexOf('/')) |
|||
let _Columns = this.initApiColumnsForDto(res.items[0],_parentName) |
|||
this.listColumns = this.initTableColumns(_Columns,'detailPage_api') |
|||
// 页面数据处理 |
|||
if(res){ |
|||
this.Loading.tableLoading = false |
|||
this.tableData = [] |
|||
res.items.forEach(item=>{ |
|||
item.deleteTipVisible = false |
|||
this.tableData.push(item) |
|||
}) |
|||
this.totalCount = res.totalCount |
|||
} |
|||
this.pagingCallback(callback) |
|||
}) |
|||
.catch(err=>{ |
|||
this.Loading.tableLoading = false |
|||
this.$message.error("数据获取失败") |
|||
}) |
|||
}, |
|||
// 查看主表信息 |
|||
showParentHandleForDetail(data){ |
|||
this.showParentTitle = `${data[this.URLOption_masterName] || ''} 主表信息` |
|||
this.showParentDialog = true |
|||
this.showParentLoading = true |
|||
getListDesById(this.URLOption_parent,data[this.URLOption_masterId]) |
|||
.then(res => { |
|||
this.showParentTableData = res |
|||
this.showParentLoading = false |
|||
}) |
|||
.catch(err => { |
|||
this.showParentLoading = false |
|||
this.$message.error("主表信息获取失败!") |
|||
}) |
|||
}, |
|||
// 编辑 |
|||
editHandleForDetail(data){ |
|||
console.log(data) |
|||
}, |
|||
// 删除 |
|||
deleteHandleForDetail(data){ |
|||
this.Loading.appMainLoading = true |
|||
data.deleteTipVisible = false |
|||
// interfaceApi[this.DeleteApi](data.id).then(res => { |
|||
// this.$successMsg('删除成功!') |
|||
// this.oldSkipCount = 1 |
|||
// this.Loading.appMainLoading = false |
|||
// this.paging() |
|||
// }).catch(err => { |
|||
// this.Loading.appMainLoading = false |
|||
// this.$message.error("删除失败!") |
|||
// }) |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
.filterForDetailPage { |
|||
|
|||
.mainTable-dialog{ |
|||
.el-dialog{ |
|||
height: calc(100% - 100px); |
|||
} |
|||
} |
|||
.el-dialog__body{ |
|||
min-height: 200px; |
|||
padding-bottom: 20px !important; |
|||
} |
|||
} |
|||
.filterForDetailPage-list{ |
|||
height: calc(100%); |
|||
overflow: auto; |
|||
} |
|||
</style> |
@ -0,0 +1,214 @@ |
|||
<template> |
|||
<div class="filterSelectComponents"> |
|||
<el-select |
|||
ref="filterSelect" |
|||
v-model="value" |
|||
:placeholder="'请选择'+selectItem.label" |
|||
:disabled="selectItem.disabled" |
|||
:clearable="true" |
|||
:multiple="selectItem.multiple" |
|||
:multiple-limit="selectItem.multipleLimit" |
|||
:collapse-tags="selectItem.collapseTags" |
|||
:filterable="!selectItem.noFilter" |
|||
:remote="isRemote" |
|||
:remote-method="inputChangeHandle" |
|||
:style="{width:selectItem.width || '100%'}" |
|||
@visible-change="visibleChangeHandle(arguments)" |
|||
@clear="clearHandle()" |
|||
:loading="loading" |
|||
:loading-text="loadingText" |
|||
@change="changeHandle(arguments)" |
|||
:class="[selectItem.searchButton ? 'hasSearchButton' : '']" |
|||
> |
|||
<el-option |
|||
v-for="item in options" |
|||
:key="item.value" |
|||
:label="item[selectItem.optionsValue] || item.value" |
|||
:value="item[selectItem.optionsValue] || item.value" |
|||
:disabled="item.disabled" |
|||
> |
|||
<div class="optionsRow clearfix" > |
|||
<div class="left">{{item[selectItem.optionsValue] || item.value}}</div> |
|||
<div class="right" v-if="selectItem.optionsLabel">{{item[selectItem.optionsLabel]}}</div> |
|||
</div> |
|||
</el-option> |
|||
</el-select> |
|||
<!-- 搜索按钮 --> |
|||
<div class="filterSelectButton"> |
|||
<el-button |
|||
:disabled=selectItem.disabled |
|||
slot="append" |
|||
icon="el-icon-search" |
|||
v-if="selectItem.searchButton" |
|||
@click="selectItem.searchButton(selectItem)" |
|||
></el-button> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
watch: { |
|||
selectModel (val) { |
|||
this.value = val |
|||
} |
|||
}, |
|||
props: { |
|||
// 数据类型基础配置 |
|||
selectModel: { |
|||
type: String, |
|||
default: "" |
|||
}, |
|||
// 数据类型基础配置 |
|||
selectItem: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
loading:false, |
|||
loadingText:"正在加载", |
|||
options:[], |
|||
value:"", |
|||
optionsCopy:[], |
|||
//控制是否远程,filterable、remote都为true时候,remote-method才生效(搜索时候走remote-method方法,否则走下拉内容搜索) |
|||
// 【目前getPageList方式为远程】 |
|||
// 显示差异:为true时候加载显示加载false显示无数据,true时候无数据无下拉,false出下拉 |
|||
isRemote:false, |
|||
} |
|||
}, |
|||
created () { |
|||
if(this.selectItem){ |
|||
this.value = this.selectModel |
|||
this.options = this.selectItem.options |
|||
this.isRemoteReset() |
|||
} |
|||
}, |
|||
methods: { |
|||
changeHandle(value){ |
|||
if(!value[0] || value[0].length <= 0)return |
|||
let _options = JSON.parse(JSON.stringify(this.selectItem)) |
|||
let _item = {} |
|||
let _prop = this.selectItem.optionsValue || this.selectItem.prop |
|||
this.options.forEach(item=>{ |
|||
if(item[_prop] == value[0])_item = item |
|||
}) |
|||
this.$emit("filterOptionSelectHandle",_item,_options,value[0]) |
|||
}, |
|||
isRemoteReset(){ |
|||
this.isRemote = (!this.selectItem.noFilter && (!this.selectItem.getType || this.selectItem.getType== 'getPageList')) |
|||
}, |
|||
clearHandle(){ |
|||
this.$emit("filterClearHandle",JSON.parse(JSON.stringify(this.selectItem))) |
|||
}, |
|||
// 给focus返回参数操作 |
|||
getHttpData(query){ |
|||
if(this.selectItem.beforeFocus && !this.selectItem.beforeFocus()){ |
|||
return |
|||
} |
|||
if(this.selectItem.focus){ |
|||
// 当前项的搜索条件 |
|||
let _value = query ? query : this.value || "" |
|||
let _params = null; |
|||
this.loading = true |
|||
this.loadingText="正在加载" |
|||
// api中《getPageList》方式: |
|||
if(!this.selectItem.getType || this.selectItem.getType== "getPageList"){ |
|||
_params = { |
|||
SkipCount: 0, |
|||
MaxResultCount: 100, |
|||
condition: { |
|||
filters: [] |
|||
} |
|||
} |
|||
if(_value.length > 0 && !this.selectItem.noFilter){ |
|||
let _column = this.selectItem.optionsValue || this.selectItem.prop |
|||
_params.condition.filters.push({logic:"And",column:_column,action:"Like",value:_value}) |
|||
} |
|||
} |
|||
// api中《getPage》方式:在业务页面调用getFilterList时候 自行传第二个val值 |
|||
// 执行方法并传参 |
|||
this.selectItem.focus(this.selectItem.getType,_params) |
|||
.then(res=>{ |
|||
this.options = res |
|||
if(!res || res.length <= 0){ |
|||
this.isRemoteReset() |
|||
this.loadingText="无数据" |
|||
}else{ |
|||
this.loading = false |
|||
this.isRemoteReset() |
|||
if(!this.selectItem.filterShowEmpty){ |
|||
// 为空的值去掉 |
|||
let _noEmpty = [] |
|||
this.options.forEach((item,key)=>{ |
|||
let _key = this.selectItem.optionsValue || this.selectItem.prop |
|||
if(item[_key] && item[_key].length > 0){ |
|||
_noEmpty.push(item) |
|||
} |
|||
}) |
|||
this.options = _noEmpty |
|||
} |
|||
} |
|||
this.optionsCopy = this.options |
|||
}) |
|||
.catch((err)=>{ |
|||
this.loading = false |
|||
}) |
|||
} |
|||
}, |
|||
inputChangeHandle(query){ |
|||
// 目的:假设防止前100个中没有包含A的字符,再次输入时候从后台重新获取 |
|||
if(!this.selectItem.getType || this.selectItem.getType== "getPageList"){ |
|||
this.getHttpData(query) |
|||
} |
|||
}, |
|||
visibleChangeHandle(val){ |
|||
// 展开/focus |
|||
if(val[0]){ |
|||
this.isRemote = true |
|||
this.getHttpData() |
|||
} |
|||
// 隐藏 |
|||
else{ |
|||
this.options = [] |
|||
this.loading = false |
|||
if(this.selectItem.hide){ |
|||
this.selectItem.hide(this.$refs.filterSelect) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
.filterSelectComponents{ |
|||
position: relative; |
|||
.filterSelectButton{ |
|||
position: absolute; |
|||
right: 0; |
|||
top: 0; |
|||
button{ |
|||
display: block; |
|||
} |
|||
} |
|||
.hasSearchButton .el-input__suffix{ |
|||
right: 65px !important; |
|||
} |
|||
.el-input--medium .el-input__icon{ |
|||
height: 30px !important; |
|||
line-height: 30px !important; |
|||
} |
|||
} |
|||
.optionsRow{ |
|||
.left{ |
|||
float: left; |
|||
} |
|||
.right{ |
|||
float: right; |
|||
padding-left: 20px; |
|||
color: #C0C4CC; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,298 @@ |
|||
<template> |
|||
<div> |
|||
<el-dialog |
|||
title="导入" |
|||
v-loading="loading" |
|||
element-loading-text="正在导入..." |
|||
:visible.sync="show" |
|||
:append-to-body="true" |
|||
:modal-append-to-body="false" |
|||
width="800px" |
|||
:show-close="false" |
|||
> |
|||
<div class="body_header"> |
|||
<span>上传模板下载:</span> |
|||
<el-button |
|||
type="success" |
|||
size="mini" |
|||
icon="el-icon-download" |
|||
@click="postImportDown" |
|||
>获取模板</el-button |
|||
> |
|||
</div> |
|||
<div class="body_header"> |
|||
<span> 导 入 模 式:</span> |
|||
<el-radio-group v-model="method" > |
|||
<el-radio label="1" :disabled="disabledMethod.method2">追加式</el-radio> |
|||
<el-radio label="0" :disabled="disabledMethod.method1">更新式</el-radio> |
|||
<el-radio label="2" :disabled="disabledMethod.method3">覆盖式</el-radio> |
|||
</el-radio-group> |
|||
</div> |
|||
<div class="body_header"> |
|||
<span>是否部分导入:</span> |
|||
<el-radio-group v-model="isAllowPartImport" > |
|||
<el-radio label="0" :disabled="disabledIsAllowPartImport.isAllowPartImport1">是</el-radio> |
|||
<el-radio label="1" :disabled="disabledIsAllowPartImport.isAllowPartImport2">否</el-radio> |
|||
</el-radio-group> |
|||
</div> |
|||
<curren-Form |
|||
class="importFile" |
|||
size="medium" |
|||
:searchData="FormData" |
|||
:searchForm="Form" |
|||
:searchHandle="editHandle" |
|||
:rules="Rules" |
|||
@submitForm="formClick(arguments)" |
|||
> |
|||
</curren-Form> |
|||
</el-dialog> |
|||
<!-- 导入预览 --> |
|||
<el-dialog |
|||
class="previewClass" |
|||
title="导入预览" |
|||
:visible.sync="previewShow" |
|||
:append-to-body="true" |
|||
:modal-append-to-body="false" |
|||
:show-close="false" |
|||
width="70%" |
|||
> |
|||
<div > |
|||
<el-table |
|||
:data="excelData.results" |
|||
:border="true" |
|||
highlight-current-row |
|||
style="width: 100%; |
|||
margin-top:10px;" |
|||
max-height="400" |
|||
> |
|||
<el-table-column |
|||
v-if="excelData.header.length > 0" |
|||
type="index" |
|||
fixed="left" |
|||
label="序号" |
|||
width="50" |
|||
/> |
|||
<el-table-column |
|||
v-for="(item,index) of excelData.header" |
|||
:key="index" |
|||
:prop="item" |
|||
:label="item" |
|||
/> |
|||
</el-table> |
|||
</div> |
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="submitForm(0)">取 消</el-button> |
|||
<el-button type="primary" @click="submitForm(1)">确 定</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
|
|||
<script> |
|||
import XLSX from 'xlsx' |
|||
import currenForm from "@/components/currenForm" |
|||
export default { |
|||
name: 'importFile', |
|||
components: { |
|||
currenForm |
|||
}, |
|||
props: { |
|||
loading: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
show: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
url: { |
|||
type: String |
|||
}, |
|||
postImport: { |
|||
type: Function, |
|||
default: () => { } |
|||
}, |
|||
disabledMethod:{ |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
disabledIsAllowPartImport:{ |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
methodValue:{ |
|||
type: String, |
|||
default:'1' |
|||
}, |
|||
isAllowPartImportValue:{ |
|||
type: String |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
previewShow: false, |
|||
// exel表头及数据 |
|||
excelData: { |
|||
header: [], |
|||
results: [] |
|||
}, |
|||
//表格流体最大高度 |
|||
tableMaxHeight:null, |
|||
// 临时存储提交数据 |
|||
submitDataLS: null, |
|||
method: '1', |
|||
isAllowPartImport: '1', |
|||
editHandle: [ |
|||
{ label: "取消", name: "cancel" }, |
|||
{ label: "确定", type: "primary", name: "determine" }, |
|||
], |
|||
FormData: { |
|||
formFile: [] |
|||
}, |
|||
Form: [ |
|||
{ type: "upload", label: "文件导入", prop: "formFile", limit: 1, colSpan: 24 } |
|||
], |
|||
Rules: { |
|||
formFile: { required: true, trigger: "change", message: "不可为空" } |
|||
} |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.method = this.methodValue |
|||
this.isAllowPartImport = this.isAllowPartImportValue |
|||
}, |
|||
methods: { |
|||
postImportDown () { |
|||
this.$emit('postImportDown') |
|||
}, |
|||
// postImport () { |
|||
// this.$emit('postImport') |
|||
// }, |
|||
// methodValueChane() { |
|||
// this.$emit("methodChange", this.methodValue); // 用 $emit 通知父组件去修改 |
|||
// }, |
|||
// isAllowPartImportValueChane() { |
|||
// this.$emit("isAllowPartImportChange", this.isAllowPartImportValue); // 用 $emit 通知父组件去修改 |
|||
// }, |
|||
readerData(rawFile) { |
|||
if (rawFile) { |
|||
return new Promise((resolve, reject) => { |
|||
const reader = new FileReader() |
|||
reader.onload = e => { |
|||
const data = e.target.result |
|||
// const workbook = XLSX.read(data, { type: 'array',cellText:false,cellDates:true }) |
|||
const workbook = XLSX.read(data, { type: 'array'}) |
|||
const firstSheetName = workbook.SheetNames[0] |
|||
const worksheet = workbook.Sheets[firstSheetName] |
|||
const header = this.getHeaderRow(worksheet) |
|||
const results = XLSX.utils.sheet_to_json(worksheet,{raw:false}) |
|||
// const results = XLSX.utils.sheet_to_json(worksheet,{raw:false,dateNF:'yyyy-mm-dd'}) //yyyy-MM-dd HH:mm:ss |
|||
if(results.length <= 0){ |
|||
this.$message.error('导入表格内无数据,请确认后重新导入'); |
|||
this.loading = false |
|||
return |
|||
} |
|||
// this.generateData({ header, results }) |
|||
this.excelData.header = header |
|||
this.excelData.results = results |
|||
// this.tableMaxHeight = document.getElementById("tableOuter").clientHeight |
|||
resolve() |
|||
this.tab |
|||
} |
|||
reader.readAsArrayBuffer(rawFile) |
|||
}) |
|||
} |
|||
}, |
|||
getHeaderRow(sheet) { |
|||
const headers = [] |
|||
const range = XLSX.utils.decode_range(sheet['!ref']) |
|||
let C |
|||
const R = range.s.r |
|||
/* start in the first row */ |
|||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */ |
|||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] |
|||
/* find the cell in the first row */ |
|||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default |
|||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell) |
|||
headers.push(hdr) |
|||
} |
|||
return headers |
|||
}, |
|||
// 文件预览 |
|||
submitForm(val) { |
|||
if (val == 0) { |
|||
this.previewShow = false |
|||
} else { |
|||
this.submiData(this.submitDataLS) |
|||
this.previewShow = false |
|||
} |
|||
}, |
|||
// formClick(val) { |
|||
// this.FormData.method = this.method |
|||
// this.FormData.isAllowPartImport = this.isAllowPartImport |
|||
// this.$emit('importClick', val, this.FormData) |
|||
// } |
|||
formClick (val) { |
|||
if (val[0] == 0) { |
|||
this.submiData(val) |
|||
} else { |
|||
// 显示预览页 |
|||
// 没上传文件时 不显示预览界面 |
|||
if (val[1].fields[0].fieldValue[0]) { |
|||
this.previewShow = true |
|||
this.submitDataLS = val |
|||
// 文件数据展示 |
|||
this.readerData(val[1].fields[0].fieldValue[0]) |
|||
} else { |
|||
this.$message.error('请上传文件!'); |
|||
} |
|||
} |
|||
}, |
|||
// 提交数据 |
|||
submiData(val) { |
|||
this.FormData.method = this.method |
|||
this.FormData.isAllowPartImport = this.isAllowPartImport |
|||
this.$emit('importClick', val, this.FormData) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
::v-deep .el-dialog__body { |
|||
max-height: 100vh; |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
.body_header { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 0 0 20px 100px; |
|||
} |
|||
::v-deep .importFile { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
overflow: hidden; |
|||
|
|||
.el-form { |
|||
flex: 1; |
|||
padding-left: 70px; |
|||
padding-right: 70px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
overflow-y: auto; |
|||
.el-row { |
|||
flex: 2; |
|||
padding-left: 30px; |
|||
padding-right: 30px; |
|||
} |
|||
} |
|||
.formButton { |
|||
padding: 20px 20px 20px 0; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,278 @@ |
|||
<template> |
|||
<el-dialog |
|||
v-loading="loading" |
|||
element-loading-text="加载中..." |
|||
v-if="displayDialog" |
|||
:visible="true" |
|||
:fullscreen="true" |
|||
:modal="false" |
|||
:modal-append-to-body="false" |
|||
:show-close="false" |
|||
style="width:calc(100% - 28px);left:14px;top:14px;height:calc(100% - 28px)" |
|||
> |
|||
<div class="dialogOuterTitle">{{formTitle}}</div> |
|||
<curren-Form |
|||
v-if="active === 0" |
|||
size="medium" |
|||
class="newAndEdiDialog" |
|||
:searchData="FormData" |
|||
:searchForm="Form" |
|||
:searchOptions="Options" |
|||
:searchHandle="Handle" |
|||
:rules="Rules" |
|||
@changeInput="changeInput" |
|||
@push="DataPush(arguments)" |
|||
@submitForm="FormClick(arguments)" |
|||
@radioChange="radioChange" |
|||
@changeSelect="changeSelect" |
|||
> |
|||
<template v-if="showmyTable"> |
|||
<el-form-item class="formTable-box" prop="details"> |
|||
<currenTable |
|||
:tableData="FormData.details" |
|||
:tableColumns="myTableColumns" |
|||
:selectionTable="selectionTable" |
|||
:tableLoading="tableLoading" |
|||
:isShowIndex="isShowIndex" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
> |
|||
<template> |
|||
<el-table-column |
|||
fixed="right" |
|||
label="操作" |
|||
width="120"> |
|||
<template slot-scope="scope"> |
|||
<el-button |
|||
@click.native.prevent="deleteRow(scope.$index, FormData.details)" |
|||
type="text" |
|||
size="small"> |
|||
删除 |
|||
</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</template> |
|||
</currenTable> |
|||
</el-form-item> |
|||
</template> |
|||
</curren-Form> |
|||
<div v-if="active === 1 && pageStatus == 'success'" class="page4"> |
|||
<el-result icon="success" title="成功提示" :subTitle="formTitle + '成功'"> |
|||
<template slot="extra"> |
|||
<el-button type="primary" size="medium" @click="close" |
|||
>退出</el-button |
|||
> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
<div v-if="active === 2 && pageStatus == 'error'" class="page4"> |
|||
<el-result icon="error" title="错误提示" :subTitle="formTitle + '失败'"> |
|||
<template slot="extra"> |
|||
<el-button type="primary" size="medium" @click="goBack" |
|||
>返回</el-button |
|||
> |
|||
<el-button type="primary" size="medium" @click="close" |
|||
>退出</el-button |
|||
> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
</el-dialog> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
props: { |
|||
loading: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//控制步骤 |
|||
active: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
//结合active控制返回结果 |
|||
pageStatus: { |
|||
type: String, |
|||
default: "" |
|||
}, |
|||
//显示返回结果 |
|||
formReveal: { |
|||
type: Boolean, |
|||
}, |
|||
//dialog标题 |
|||
formTitle: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
//dialog是否显示 |
|||
displayDialog: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
//表单数据 |
|||
FormData: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
//绑定表单数据 |
|||
Form: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//下拉框数据 |
|||
Options: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
//表单按钮 |
|||
Handle: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//表单验证 |
|||
Rules: { |
|||
type: Object, |
|||
default: () => { |
|||
return {} |
|||
} |
|||
}, |
|||
// 列表字段 |
|||
myTableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
showmyTable: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
selectionTable: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
tableLoading: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
isShowIndex: { |
|||
type: Boolean, |
|||
default: false, |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
session: null |
|||
} |
|||
}, |
|||
mounted () { |
|||
this.session = JSON.parse(JSON.stringify(this.FormData)) |
|||
}, |
|||
methods: { |
|||
//点击表单提交(新增或编辑) |
|||
FormClick (val) { |
|||
if (val[0] == 0) { |
|||
this.close() |
|||
} else { |
|||
val[1].validate((valid) => { |
|||
if (valid) { |
|||
this.$emit('FormSubmit', val); |
|||
} else { |
|||
this.$errorMsg('请按照提示继续操作') |
|||
return false; |
|||
} |
|||
}); |
|||
} |
|||
}, |
|||
close () { |
|||
const data = JSON.parse(JSON.stringify(this.session)) |
|||
this.$emit('close', data) |
|||
}, |
|||
goBack () { |
|||
this.$emit('goBack') |
|||
}, |
|||
DataPush (val) { |
|||
this.$emit('push', val) |
|||
}, |
|||
deleteRow(index, tableData) { |
|||
this.$emit('deleteRow', index, tableData) |
|||
}, |
|||
radioChange(prop,val){ |
|||
this.$emit('radioChange', prop, val) |
|||
}, |
|||
changeInput(prop, val) { |
|||
this.$emit("changeInput", prop, val) |
|||
}, |
|||
//点击selection框 |
|||
handleSelectionChange(val) { |
|||
this.$emit("handleSelectionChange", val); |
|||
}, |
|||
// form表单下拉框change事件 |
|||
changeSelect(prop,val ) { |
|||
this.$emit("changeSelect", prop, val) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
::v-deep .el-dialog__header{ |
|||
padding: 0 !important; |
|||
} |
|||
::v-deep .el-dialog__body{ |
|||
padding-top: 0; |
|||
} |
|||
::v-deep .newAndEdiDialog { |
|||
display: flex; |
|||
flex-direction: column; |
|||
width: 100%; |
|||
height: calc(100% - 60px); |
|||
.el-form { |
|||
flex: 1; |
|||
display: flex; |
|||
justify-content: flex-start; |
|||
align-content: flex-start; |
|||
flex-wrap: wrap; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
padding-right: 40px; |
|||
} |
|||
.screen-push { |
|||
color: rgb(64, 158, 255); |
|||
span { |
|||
cursor: pointer; |
|||
&:hover { |
|||
color: blue; |
|||
} |
|||
} |
|||
} |
|||
.formButton { |
|||
padding: 20px 20px 20px 0; |
|||
} |
|||
.formTable-box { |
|||
height: 40%; |
|||
|
|||
.el-form-item__content { |
|||
width: 100%; |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
overflow: hidden; |
|||
margin: 0 !important; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,81 @@ |
|||
<template> |
|||
<el-dialog |
|||
:title="title" |
|||
:v-loading="loadingPDF" |
|||
:visible.sync="isShowPDF" |
|||
:modal-append-to-body="false" |
|||
:append-to-body="true" |
|||
top="1vh" |
|||
> |
|||
<div> |
|||
<el-button-group> |
|||
<el-button type="primary" icon="el-icon-arrow-left" size="mini" @click="prePage">上一页</el-button> |
|||
<el-button type="primary" size="mini" @click="nextPage">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button> |
|||
</el-button-group> |
|||
<div style="marginTop: 10px; color: #409EFF">{{ pageNum }} / {{ pageTotalNum }}</div> |
|||
<pdf |
|||
:page="pageNum" |
|||
:src="urlPDF" |
|||
@progress="loadedRatio = $event" |
|||
@num-pages="pageTotalNum=$event" |
|||
></pdf> |
|||
</div> |
|||
<span slot="footer" class="dialog-footer"> |
|||
<el-button @click="close">取 消</el-button> |
|||
</span> |
|||
</el-dialog> |
|||
</template> |
|||
<script> |
|||
|
|||
import pdf from 'vue-pdf' |
|||
|
|||
export default { |
|||
name: 'Pdf', |
|||
components: { |
|||
pdf, |
|||
}, |
|||
data() { |
|||
return { |
|||
// urlPDF: 'http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf', |
|||
pageNum: 1, |
|||
pageTotalNum: 1, //总页数 |
|||
loadedRatio: 0, // 当前页面的加载进度,范围是0-1 ,等于1的时候代表当前页已经完全加载完成了 |
|||
} |
|||
}, |
|||
props: { |
|||
urlPDF: { |
|||
type: String, |
|||
default: '', |
|||
}, |
|||
title: { |
|||
type: String, |
|||
default: '', |
|||
}, |
|||
isShowPDF: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
loadingPDF: { |
|||
type: Boolean, |
|||
default: false |
|||
} |
|||
}, |
|||
methods: { |
|||
// 上一页 |
|||
prePage() { |
|||
let page = this.pageNum |
|||
page = page > 1 ? page - 1 : this.pageTotalNum |
|||
this.pageNum = page |
|||
}, |
|||
// 下一页 |
|||
nextPage() { |
|||
let page = this.pageNum |
|||
page = page < this.pageTotalNum ? page + 1 : 1 |
|||
this.pageNum = page |
|||
}, |
|||
close(){ |
|||
this.$emit('closePDF') |
|||
} |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,43 @@ |
|||
<template> |
|||
<div class="resultStatusComponents"> |
|||
<!-- // todo-An icon插槽组件化 --> |
|||
<el-result |
|||
:icon="status" |
|||
:title="title" |
|||
:subTitle="subTitle" |
|||
> |
|||
<template slot="extra"> |
|||
<slot></slot> |
|||
</template> |
|||
</el-result> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: 'resultStatus', |
|||
props: { |
|||
// 状态 success / warning / info / error |
|||
status: { |
|||
type: String, |
|||
default: 'success' |
|||
}, |
|||
// 主标题 |
|||
title:{ |
|||
type: String, |
|||
default: '成功' |
|||
}, |
|||
//次标题 |
|||
subTitle:{ |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
|
|||
} |
|||
}, |
|||
methods: { |
|||
} |
|||
} |
|||
</script> |
@ -0,0 +1,265 @@ |
|||
<template> |
|||
<el-popover |
|||
placement="top" |
|||
v-model="visible" |
|||
class="rowDropContain rowDropNotHideItem" |
|||
width="270" |
|||
> |
|||
<div class="test_wrapper" @dragover="dragover($event)"> |
|||
<div class="text" >字段设置</div> |
|||
<el-divider></el-divider> |
|||
<!-- 全选 --> |
|||
<div class="allSelectContent" @click="redioAllChange()"> |
|||
<i class="el-icon-success icon" v-if="allSeletType == 'allSelect'"></i> |
|||
<i class="el-icon-remove icon" v-if="allSeletType == 'hasSelect'"></i> |
|||
<i class="el-icon-success icon" v-if="allSeletType == 'NoSelect'" style="color:#999" ></i> |
|||
全选 |
|||
</div> |
|||
<transition-group class="transition-wrapper" :style="{maxHeight:innerMaxHeight}" name="sort"> |
|||
<div |
|||
v-for="(item,index) in dataList" |
|||
:key='index+item.label' |
|||
class="sort-item" |
|||
:draggable="true" |
|||
@dragstart="dragstart(item)" |
|||
@dragenter="dragenter(item,$event)" |
|||
@dragend="dragend(item,$event)" |
|||
@dragover="dragover($event)" |
|||
> |
|||
<svg-icon |
|||
class="checkbox-svg" |
|||
:class="{'show': dataList[index].istrue}" |
|||
@click="rediochange(index)" |
|||
:icon-class="dataList[index].istrue ? 'svg_show' : 'svg_hide'" |
|||
/> |
|||
<div class="lable">{{ item.label }}</div> |
|||
</div> |
|||
</transition-group> |
|||
</div> |
|||
<div class="buttonsBox"> |
|||
<el-button size="mini" @click="reset">重置</el-button> |
|||
<el-button size="mini" @click="close">关闭</el-button> |
|||
<!-- <el-button type="primary" size="mini" @click="save">保存</el-button> --> |
|||
</div> |
|||
</el-popover> |
|||
|
|||
</template> |
|||
<script> |
|||
import draggable from "vuedraggable"; |
|||
import Sortable from "sortablejs"; |
|||
import { getLoginName } from "@/utils/auth" |
|||
export default { |
|||
components: { |
|||
draggable, |
|||
Sortable, |
|||
}, |
|||
data() { |
|||
return { |
|||
historyTableColumns:null, |
|||
name: null, |
|||
oldData: null, |
|||
newData: null, |
|||
dataList: [], |
|||
// 全选 allSelect hasSelect NoSelect |
|||
allSeletType:'NoSelect', |
|||
userName: getLoginName() |
|||
} |
|||
}, |
|||
props: { |
|||
innerMaxHeight:{ |
|||
type:String, |
|||
default:'calc(90vh - 280px)' |
|||
}, |
|||
visible: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
// list_api detail_api detailPage_api list detail detailPage |
|||
source:{ |
|||
type:String, |
|||
default:'list_api' |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.historyTableColumns = JSON.parse(JSON.stringify(this.tableColumns)) |
|||
this.formatData(this.tableColumns) |
|||
this.initSelectSta() |
|||
}, |
|||
methods: { |
|||
reset() { |
|||
this.$confirm('重置后,字段设置将恢复初始设置,是否继续?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning', |
|||
cancelButtonClass:'rowDropNotHideItem' |
|||
}).then(() => { |
|||
// 先set是为了字段设置按钮可以监听到缓存变化,之后在移除缓存 |
|||
localStorage.setItem('file_Columns_' + this.source + '_' + this.userName + '_' + this.$route.name, JSON.stringify([])) |
|||
localStorage.removeItem('file_Columns_' + this.source + '_' +this.userName + '_' + this.$route.name) |
|||
// let _resetCol = this.$isTableColumns[this.$route.name] |
|||
let _resetCol = this.historyTableColumns |
|||
_resetCol.forEach(item => { |
|||
item.istrue = true |
|||
}) |
|||
this.dataList = _resetCol |
|||
this.initSelectSta() |
|||
this.$emit('radio',_resetCol,this.source) |
|||
this.close() |
|||
}).catch(() => { |
|||
|
|||
}); |
|||
}, |
|||
close() { |
|||
this.$emit('closeRowDrop') |
|||
}, |
|||
// 格式化表头数据 |
|||
formatData (val) { |
|||
this.dataList = JSON.parse(JSON.stringify(val)) |
|||
this.dataList.forEach(item => { |
|||
if (item.istrue == undefined) { |
|||
item.istrue = true |
|||
} |
|||
}) |
|||
}, |
|||
save () { |
|||
this.$forceUpdate() |
|||
this.$emit('radio',this.dataList,this.source) |
|||
// 本地缓存 当前用户名 + 路由名称 |
|||
localStorage.setItem('file_Columns_' + this.source + '_' + this.userName + '_' + this.$route.name, JSON.stringify(this.dataList)) |
|||
}, |
|||
dragstart(value) { |
|||
this.oldData = value |
|||
}, |
|||
// 记录移动过程中信息 |
|||
dragenter(value, e) { |
|||
this.newData = value |
|||
e.preventDefault() |
|||
}, |
|||
// 拖拽最终操作 |
|||
dragend(value, e) { |
|||
if (this.oldData !== this.newData) { |
|||
let oldIndex = this.dataList.indexOf(this.oldData) |
|||
let newIndex = this.dataList.indexOf(this.newData) |
|||
let newItems = [...this.dataList] |
|||
// 删除老的节点 |
|||
newItems.splice(oldIndex, 1) |
|||
// 在列表中目标位置增加新的节点 |
|||
newItems.splice(newIndex, 0, this.oldData) |
|||
this.dataList = [...newItems] |
|||
this.save() |
|||
} |
|||
}, |
|||
// 拖动事件(主要是为了拖动时鼠标光标不变为禁止) |
|||
dragover(e) { |
|||
e.preventDefault() |
|||
}, |
|||
// item元素点击眼睛事件 |
|||
rediochange(index){ |
|||
// this.dataList[index].istrue = !this.dataList[index].istrue |
|||
this.$set(this.dataList[index],'istrue', !this.dataList[index].istrue) |
|||
this.initSelectSta() |
|||
this.$nextTick(()=>{ |
|||
this.save() |
|||
}) |
|||
}, |
|||
// 初始化当前全选状态 |
|||
initSelectSta(){ |
|||
let _num = 0 |
|||
this.dataList.forEach(item=>{ |
|||
if(item.istrue){ |
|||
_num ++ |
|||
} |
|||
}) |
|||
if(_num == 0){this.allSeletType = 'NoSelect'} |
|||
if(_num == this.dataList.length){this.allSeletType = 'allSelect'} |
|||
if(_num > 0 && _num != this.dataList.length){this.allSeletType = 'hasSelect'} |
|||
}, |
|||
// 全选点击事件 |
|||
redioAllChange(){ |
|||
let isSelectAll = !(this.allSeletType == 'allSelect') |
|||
this.allSeletType = isSelectAll ? 'allSelect' : 'NoSelect'; |
|||
this.dataList.forEach(item=>{ |
|||
return item.istrue = isSelectAll |
|||
}) |
|||
this.save() |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
$paddingSize:20px; |
|||
.rowDropContain{ |
|||
.el-popover{ |
|||
position: fixed; |
|||
right: 30px; |
|||
padding: 0; |
|||
} |
|||
.transition-wrapper { |
|||
display: block; |
|||
// max-height: calc(90vh - 280px); |
|||
overflow: auto; |
|||
padding: 0 0 $paddingSize $paddingSize; |
|||
|
|||
.sort-item{ |
|||
margin-bottom: 6px; |
|||
display: flex; |
|||
cursor: grab; |
|||
align-items: center; |
|||
|
|||
&:last-child{ |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
.lable{ |
|||
padding: 0 15px 0 10px; |
|||
} |
|||
} |
|||
} |
|||
.el-divider--horizontal { |
|||
margin: $paddingSize; |
|||
width: calc(100% - 40px); |
|||
} |
|||
.text { |
|||
color: #333; |
|||
font-weight: bold; |
|||
padding: $paddingSize 0 0 $paddingSize; |
|||
} |
|||
.allSelectContent{ |
|||
user-select: none; |
|||
cursor: pointer; |
|||
padding:0 0 10px $paddingSize; |
|||
.icon{ |
|||
font-size:18px; |
|||
vertical-align: middle; |
|||
color: #409EFF; |
|||
margin-right: 5px; |
|||
} |
|||
} |
|||
.buttonsBox{ |
|||
text-align: center; |
|||
margin: 0; |
|||
padding: 15px; |
|||
border-top: #eee solid 1px; |
|||
} |
|||
.checkbox-svg{ |
|||
width: 20px; |
|||
flex-shrink: 0; |
|||
fill:currentColor; |
|||
color:#999; |
|||
font-size: 18px; |
|||
cursor: pointer; |
|||
|
|||
&.show{ |
|||
color: #409EFF; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,66 @@ |
|||
<template> |
|||
<!-- 组件功能:普通搜索(列表中的快速搜索) --> |
|||
<div class="normalSearchComponentsContain"> |
|||
<div class="leftInputBox"> |
|||
<i class="el-icon-search searchIcon"></i> |
|||
<el-input |
|||
v-model="searchValue" |
|||
:placeholder="searchNormalOption && searchNormalOption.placeholder ? searchNormalOption.placeholder : '这里是快速搜索'" |
|||
clearable |
|||
@keyup.enter.native="searchNormalClick" |
|||
@clear="searchNormalClear" |
|||
></el-input> |
|||
</div> |
|||
<el-button |
|||
class="searchButton" |
|||
size="mini" |
|||
@click="searchNormalClick" |
|||
>搜索</el-button> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
props: { |
|||
// 格式:{ |
|||
// prop:'asnNumber',//查询的接口过滤数据 |
|||
// placeholder:'请输入发货单号',//placeholder |
|||
// }, |
|||
searchNormalOption: { |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
searchValue:null,//搜索内容数据 |
|||
} |
|||
}, |
|||
methods:{ |
|||
// 搜索 |
|||
searchNormalClick(){ |
|||
this.$emit('searchNormalClick', this.searchValue, this.searchNormalOption) |
|||
}, |
|||
// 清除搜索 |
|||
searchNormalClear(noflesh){ |
|||
this.searchValue = "" |
|||
if(!noflesh){ |
|||
this.$emit('searchNormalClear',this.searchValue, this.searchNormalOption) |
|||
} |
|||
}, |
|||
// 设置值 |
|||
setSearchNormalValue(val,noflesh){ |
|||
this.searchValue = val |
|||
if(!noflesh){ |
|||
this.searchNormalClick() |
|||
} |
|||
}, |
|||
// 获取值 |
|||
getSearchNormalValue(){ |
|||
return this.searchValue |
|||
}, |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss"> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,63 @@ |
|||
$searchWidth:60px; |
|||
.normalSearchComponentsContain{ |
|||
min-height: 29px; |
|||
width: 230px; |
|||
overflow: hidden; |
|||
position: relative; |
|||
caret-color:#ccc; |
|||
background: #fff; |
|||
|
|||
.leftInputBox{ |
|||
position: absolute; |
|||
left: 0; |
|||
right: $searchWidth; |
|||
top: 0; |
|||
bottom: 0; |
|||
border: #e8e8e8 solid 1px; |
|||
overflow: hidden; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.searchIcon{ |
|||
display: block; |
|||
position: absolute; |
|||
left: 10px; |
|||
top: 0; |
|||
height: 100%; |
|||
line-height: 28px; |
|||
text-align: center; |
|||
color: #ccc; |
|||
} |
|||
|
|||
.el-input{ |
|||
position: absolute; |
|||
left: 30px; |
|||
right: 0; |
|||
height: 100%; |
|||
width: auto; |
|||
|
|||
input{ |
|||
border: none; |
|||
height: 100%; |
|||
padding: 0 30px 0 0; |
|||
} |
|||
|
|||
.el-input__icon{ |
|||
line-height: 28px; |
|||
} |
|||
} |
|||
|
|||
.searchButton{ |
|||
position: absolute; |
|||
right: 0; |
|||
top: 0; |
|||
width: $searchWidth + 3px; |
|||
border-radius: 0 4px 4px 0; |
|||
border: none; |
|||
color: #1890ff; |
|||
height: 100%; |
|||
background: #d5eaff; |
|||
font-size: 13px; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,611 @@ |
|||
<template> |
|||
<!-- 全面的筛选组件:初级普通筛选 + 高级筛选(按照配置来判断显示情况)--> |
|||
<!-- todo:使用v-if每次重新赋值,与接口查询保持一致 --> |
|||
<div |
|||
class="searchOverallComponent" |
|||
:style="{height:componentsHeight+'px',overflow:isShowMoreList ? 'unset' : 'hidden'}" |
|||
v-show="isShow" |
|||
> |
|||
<div |
|||
class="border-outer" |
|||
> |
|||
<!-- 整体背景遮罩 --> |
|||
<div |
|||
v-if="isShow && isShowMoreList" |
|||
class="fullPageCover" |
|||
:style="{height:searchOverallCoverHeight}" |
|||
></div> |
|||
<div class="title" v-if="isShowMoreList">高级筛选</div> |
|||
<!-- 普通筛选界面 --> |
|||
<searchPrimary |
|||
v-if="primarySearchOption && primarySearchOption.length > 0" |
|||
ref="searchPrimaryRef" |
|||
:showBaseButton="!isShowMoreList" |
|||
:primarySearchOption="primarySearchOption" |
|||
:primarySearchButton="isShowMoreList ? primarySearchButton : primarySearchAllButton" |
|||
@primarySearchButtonClick="primarySearchButtonClick" |
|||
@primarySearchBaseHandle="primarySearchBaseHandle" |
|||
> |
|||
<slot></slot> |
|||
</searchPrimary> |
|||
<!-- 高级筛选界面 --> |
|||
<div v-if="isShow && isShowMoreList" class="moreListOuter"> |
|||
<curren-Form |
|||
class="navFilter" |
|||
size="medium" |
|||
labelWidth="0" |
|||
:searchData="moreListData" |
|||
> |
|||
<el-row :gutter="20"> |
|||
<el-form-item |
|||
v-for="(item, index) in moreListData.filters" |
|||
:key="index" |
|||
> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.column'" |
|||
:rules="rules && rules.column ? rules.column : []" |
|||
> |
|||
<el-select |
|||
v-model="item.column" |
|||
placeholder="请选择筛选对象" |
|||
:disabled="item.hide" |
|||
:filterable="true" |
|||
@change="resetSelect(item)" |
|||
> |
|||
<el-option |
|||
v-for="(item, index) in tableColumnsOptions(tableColumns)" |
|||
:key="index" |
|||
:label="item.label" |
|||
:value=" |
|||
item.showProp |
|||
? item.prop + '.' + item.showProp |
|||
: item.prop |
|||
" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.action'" |
|||
> |
|||
<el-select |
|||
v-model="item.action" |
|||
placeholder="请选择条件" |
|||
:disabled="disabledAction || item.column == '' || item.hide ? true : false" |
|||
> |
|||
<!-- moreListOptions.action --> |
|||
<el-option |
|||
v-for="item in formatMoreListOptions(item.column) " |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="7"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.value'" |
|||
:rules="rules && rules.value ? rules.value : []" |
|||
> |
|||
<el-select |
|||
v-if="Object.keys(inputOrSelect(item.column)).length > 0" |
|||
v-model="item.value" |
|||
placeholder="请选择内容" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
:filterable="true" |
|||
@change="inputOrSelect(item.column)" |
|||
clearable |
|||
> |
|||
<el-option |
|||
v-for="item in $staticOptions[ |
|||
inputOrSelect(item.column).filters |
|||
]()" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value=" |
|||
typeof item.value == 'string' |
|||
? item.value |
|||
: String(item.value) |
|||
" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
<!-- 日期时间 --> |
|||
<el-date-picker |
|||
v-else-if="getColumnType(item.column) == 'dateTime'" |
|||
type="datetime" |
|||
v-model="item.value" |
|||
:placeholder="'选择日期时间'" |
|||
style="width: 100%" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
></el-date-picker> |
|||
<el-input |
|||
v-else |
|||
v-model="item.value" |
|||
placeholder="请输入内容" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
clearable |
|||
></el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.logic'" |
|||
> |
|||
<el-select |
|||
v-model="item.logic" |
|||
placeholder="请选择关系" |
|||
:disabled="disabledLogic || item.column == '' || item.hide ? true : false" |
|||
> |
|||
<el-option |
|||
v-for="item in moreListOptions.logic" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="1" v-if="!item.hide"> |
|||
<!-- 删除条件按钮 --> |
|||
<el-button |
|||
type="danger" |
|||
icon="el-icon-minus" |
|||
circle |
|||
size="mini" |
|||
@click="moreListDelete(index,item)" |
|||
></el-button> |
|||
</el-col> |
|||
</el-form-item> |
|||
</el-row> |
|||
</curren-Form> |
|||
<!-- 添加筛选条件 --> |
|||
<div class="moreListPush-btn"> |
|||
<span @click="moreListPush">+ 添加筛选条件</span> |
|||
</div> |
|||
<!-- 按钮 --> |
|||
<div class="moreListBaseBts" v-if="moreListbuttons && moreListbuttons.length > 0" > |
|||
<el-button |
|||
v-for="(item,index) in moreListbuttons" |
|||
:key="index" |
|||
:type="item.type" |
|||
:size="item.size || 'medium'" |
|||
@click="moreListButtonHandle(item)" |
|||
:icon="item.iconRight ? '' : item.icon" |
|||
> |
|||
{{ item.label }} |
|||
<!-- 自定义右侧图标 --> |
|||
<i |
|||
style="margin-left:0" |
|||
v-if="item.iconRight" |
|||
:class="['el-icon--right',item.icon]" |
|||
></i> |
|||
</el-button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import searchPrimary from "@/components/searchPrimary" |
|||
export default { |
|||
name:'searchOverallComponent', |
|||
components: { |
|||
searchPrimary, |
|||
}, |
|||
watch:{ |
|||
// 监听显示切换 |
|||
showSearchOverall(n){ |
|||
// 控制是否显示 + 动画效果处理 |
|||
// 没有普通查询配置 |
|||
if(this.primarySearchOption.length <= 0){ |
|||
this.changeSearchOverallShow(n) |
|||
this.changeMoreListShow(n) |
|||
return |
|||
} |
|||
// 有普通查询配置 |
|||
if(n){ |
|||
this.changeSearchOverallShow(n) |
|||
this.changeMoreListShow(false) |
|||
} |
|||
this.$nextTick(()=>{ |
|||
if(n){ |
|||
this.componentsHeight = this.getSearchPrimaryHeight() + 20 |
|||
}else{ |
|||
this.componentsHeight = 0 |
|||
this.changeMoreListShow(false) |
|||
// setTimeout(()=>{ |
|||
// this.changeSearchOverallShow(n) |
|||
// },500) |
|||
} |
|||
}) |
|||
this.setOverallSearchData(this.httpOverallSearchData) |
|||
}, |
|||
// 监听接口搜索的筛选数据 |
|||
httpOverallSearchData(n,o){ |
|||
this.setOverallSearchData(n) |
|||
}, |
|||
isShowMoreList(){ |
|||
this.setOverallSearchData(this.httpOverallSearchData) |
|||
} |
|||
}, |
|||
props: { |
|||
// 筛选遮罩高度 |
|||
searchOverallCoverHeight:{ |
|||
type: String, |
|||
default: 'calc(100vh - 200px)' |
|||
}, |
|||
// 禁用选择条件 |
|||
disabledAction:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 禁用选择关系 |
|||
disabledLogic:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 是否显示全面筛选组件 |
|||
showSearchOverall:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 是否显示高级筛选 |
|||
showMoreSearch:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
//普通筛选绑定表单数据 |
|||
primarySearchOption: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//普通筛选自定义按钮 |
|||
primarySearchButton:{ |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 显示数据配置 |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 当前接口中的筛选数据(用于同步全面筛选的数据) |
|||
httpOverallSearchData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 自定义配置条件 |
|||
filterActionOptions:{ |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
// 普通筛选自定义所有按钮(包括高级筛选) |
|||
primarySearchAllButton:[], |
|||
// 高级筛选列表是否显示 |
|||
isShowMoreList:false, |
|||
// 组件高度(用于动画效果) |
|||
componentsHeight:0, |
|||
// 是否显示总组件,与showSearchOverall相通(重新定义一遍目的是为了动画效果) |
|||
isShow:false, |
|||
// 高级筛选列表内部按钮 |
|||
moreListbuttons: [ |
|||
{ label: "搜索", type: "primary", name: "moreList-search" }, |
|||
{ label: '重置', name: 'moreList-reset' }, |
|||
{ label:'收起筛选', name:'moreList-up', type: 'text', icon:'el-icon-arrow-up', iconRight:true} |
|||
], |
|||
// 高级筛选数据列表/值 |
|||
moreListData: {filters:[]}, |
|||
// 高级筛选条件列表配置 |
|||
moreListOptions: { |
|||
action: [{ |
|||
value: '==', |
|||
label: '等于' |
|||
}, { |
|||
value: '!=', |
|||
label: '不等于' |
|||
}, { |
|||
value: '>', |
|||
label: '大于' |
|||
}, { |
|||
value: '<', |
|||
label: '小于' |
|||
}, { |
|||
value: '>=', |
|||
label: '大于等于' |
|||
}, { |
|||
value: '<=', |
|||
label: '小于等于' |
|||
}, { |
|||
value: 'Like', |
|||
label: '包含' |
|||
}, { |
|||
value: 'NotLike', |
|||
label: '不包含' |
|||
}, |
|||
// { |
|||
// value: 'In', |
|||
// label: '包含' |
|||
// }, { |
|||
// value: 'NotIn', |
|||
// label: '不包含' |
|||
// } |
|||
], |
|||
logic: [ |
|||
{ |
|||
value: 'And', |
|||
label: '并且' |
|||
}, |
|||
{ |
|||
value: 'Or', |
|||
label: '或者' |
|||
} |
|||
], |
|||
}, |
|||
// 高级筛选rules暂未使用验证,但是不能删除rules定义 |
|||
// todo:优化后放开,优化内容:如果选择了筛选对象【column】,则验证【value】,否则都不验证 |
|||
rules:{ |
|||
// column: [ |
|||
// { required: true, message: '请选择筛选对象', trigger: 'change' } |
|||
// ], |
|||
// value: [ |
|||
// { required: true, message: '请输入内容', trigger: 'blur' } |
|||
// ], |
|||
}, |
|||
} |
|||
}, |
|||
created() { |
|||
this.moreListPush() |
|||
}, |
|||
mounted() { |
|||
// 配置普通筛选默认按钮(是否包含高级筛选按钮) |
|||
this.setPrimarySearchAllButton() |
|||
}, |
|||
methods: { |
|||
// 获取普通筛选的高度,外部也有使用,用于动画样式 |
|||
getSearchPrimaryHeight(){ |
|||
return document.getElementsByClassName('searchPrimaryComponent')[0].clientHeight |
|||
}, |
|||
// 配置普通筛选自定义按钮 |
|||
setPrimarySearchAllButton(){ |
|||
let _more_btn = [{ |
|||
label:'高级筛选', |
|||
name:'more', |
|||
type: 'text', |
|||
icon:'el-icon-arrow-down', |
|||
iconRight:true |
|||
}] |
|||
if(this.showMoreSearch){ |
|||
this.primarySearchAllButton = _more_btn.concat(this.primarySearchButton) |
|||
}else{ |
|||
this.primarySearchAllButton= this.primarySearchButton |
|||
} |
|||
}, |
|||
// 普通查询基础按钮点击事件 |
|||
primarySearchBaseHandle(item,data, option, that){ |
|||
this.overallSearchFormClick(item,data, option, that) |
|||
}, |
|||
// 普通筛选自定义按钮点击事件 |
|||
primarySearchButtonClick( item,data, option,that){ |
|||
// 点击[高级筛选]按钮 |
|||
if(item.name == 'more'){ |
|||
this.changeMoreListShow(true) |
|||
} |
|||
this.overallSearchFormClick(item,data, option, that) |
|||
}, |
|||
// 高级筛选基础按钮点击事件 |
|||
moreListButtonHandle(item){ |
|||
this.overallSearchFormClick(item) |
|||
}, |
|||
// 设置moreList的列表值(默认按tableColumns设置) |
|||
tableColumnsOptions(val) { |
|||
const data = JSON.parse(JSON.stringify(val)); |
|||
let num = 0 |
|||
val.forEach((item, index) => { |
|||
if (item.showProp) { |
|||
data.splice(index - num, 1) |
|||
num++ |
|||
} |
|||
}) |
|||
return data |
|||
}, |
|||
// 判断筛选类型是否是时间格式 |
|||
getColumnType(val) { |
|||
var columnsType = this.tableColumns.filter(item => item.prop == val) |
|||
if (columnsType.length > 0) { |
|||
if (columnsType[0].type) { |
|||
return columnsType[0].type |
|||
} |
|||
} else { |
|||
return '' |
|||
} |
|||
}, |
|||
// 筛选条件改变重置其他项 |
|||
resetSelect(val) { |
|||
val.action = "==" |
|||
val.value = "" |
|||
}, |
|||
// 根据数据内容约束条件选项 |
|||
formatMoreListOptions(val) { |
|||
// 自定义配置条件filterActionOptions |
|||
if(this.filterActionOptions){ |
|||
this.moreListOptions.action = this.filterActionOptions |
|||
return this.moreListOptions.action |
|||
} |
|||
if (val) { |
|||
for(var i =0; i< this.tableColumns.length; i++) { |
|||
if (val == this.tableColumns[i].prop) { |
|||
if (this.tableColumns[i].filters) { |
|||
return this.moreListOptions.action.filter(item => item.value == '==' || item.value == '!=') |
|||
} else if (this.tableColumns[i].type == 'dateTime') { |
|||
return this.moreListOptions.action.filter(item => |
|||
item.value == '==' || |
|||
item.value == '!=' || |
|||
item.value == '>' || |
|||
item.value == '<' || |
|||
item.value == '>=' || |
|||
item.value == '<=' ) |
|||
} else { |
|||
return this.moreListOptions.action |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return this.moreListOptions.action |
|||
}, |
|||
// 设置moreList列表的内容项是input还是select |
|||
inputOrSelect(val) { |
|||
let data |
|||
if (val) { |
|||
this.tableColumns.forEach((key) => { |
|||
if (val == key.prop) { |
|||
if (key.filters) { |
|||
data = key |
|||
} else { |
|||
data = {} |
|||
} |
|||
} |
|||
}) |
|||
} else { |
|||
data = {} |
|||
} |
|||
return data |
|||
}, |
|||
// 高级筛选列表-删除筛选条件行 |
|||
moreListDelete(val,item) { |
|||
if (this.moreListData.filters.length == 1) { |
|||
this.$warningMsg('必须保留一条筛选条件!') |
|||
} else { |
|||
this.$confirm('您确定删除吗, 是否继续?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.moreListData.filters.splice(val, 1) |
|||
}).catch(() => { |
|||
// this.modalAppendToBody = false |
|||
}); |
|||
} |
|||
this.overallSearchFormClick({name:'moreList-deleteRow'}) |
|||
}, |
|||
// 高级筛选列表-添加筛选条件行 |
|||
moreListPush() { |
|||
let data = { |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
} |
|||
this.moreListData.filters.push(data) |
|||
this.overallSearchFormClick({name:'moreList-addRow'}) |
|||
}, |
|||
// 重置数据,高级(单纯节点显示数据,不重新查询接口) |
|||
resetMoreListData(){ |
|||
this.moreListData = {filters:[]} |
|||
this.moreListPush() |
|||
}, |
|||
// 设置数据值,高级(单纯节点显示数据,不重新查询接口) |
|||
setMoreListData(val){ |
|||
this.moreListData = JSON.parse(JSON.stringify(val)) |
|||
}, |
|||
// 重置数据,普通+高级(单纯节点显示数据,不重新查询接口) |
|||
resetOverallSearchData(){ |
|||
if(this.$refs.searchPrimaryRef)this.$refs.searchPrimaryRef.resetPrimarySearchData(); |
|||
this.resetMoreListData() |
|||
}, |
|||
// 设置数据,普通+高级(单纯节点显示数据,不重新查询接口) |
|||
setOverallSearchData(data){ |
|||
// 普通筛选数据同步 |
|||
if(data && data.params){ |
|||
if(this.$refs.searchPrimaryRef)this.$refs.searchPrimaryRef.setPrimarySearchData(data.params) |
|||
}else{ |
|||
if(this.$refs.searchPrimaryRef)this.$refs.searchPrimaryRef.resetPrimarySearchData() |
|||
} |
|||
// 高级筛选数据同步 |
|||
if(data && data.moreList){ |
|||
let _list = {filters:[]} |
|||
data.moreList.filters.forEach(item=>{ |
|||
if(String(item.column).length > 0 && String(item.value).length > 0){ |
|||
_list.filters.push(item) |
|||
} |
|||
}) |
|||
if(_list.filters.length <= 0){ |
|||
_list.filters.push({ |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
}) |
|||
} |
|||
this.setMoreListData(_list) |
|||
}else{ |
|||
this.resetMoreListData() |
|||
} |
|||
}, |
|||
// 展开-收缩高级筛选 |
|||
changeMoreListShow(val){ |
|||
this.isShowMoreList = val || false |
|||
// 如果没有初级筛选 |
|||
if(!this.primarySearchOption || this.primarySearchOption.length <= 0){ |
|||
// 关闭时候直接整个全面筛选组件 |
|||
if(!this.isShowMoreList){ |
|||
this.isShow = false |
|||
this.$emit("getShowSearchOverall",this.isShow) |
|||
} |
|||
} |
|||
}, |
|||
// 关闭整个全面组件 |
|||
changeSearchOverallShow(val){ |
|||
if(!val){ |
|||
this.changeMoreListShow(false) |
|||
} |
|||
this.isShow = val || false |
|||
this.$emit("getShowSearchOverall",this.isShow) |
|||
}, |
|||
// 全面筛选组件所有按钮事件 |
|||
overallSearchFormClick(item,data, option) { |
|||
// 页面功能 |
|||
// 收缩筛选 |
|||
if(item.name == 'moreList-up'){ |
|||
this.changeMoreListShow(false) |
|||
} |
|||
// 高级筛选内-重置 || 普通格式-重置 |
|||
else if(item.name == "moreList-reset" || item.name == "reset"){ |
|||
this.resetOverallSearchData() |
|||
} |
|||
// 抛出函数传参 |
|||
let _searchPrimaryRef = this.$refs.searchPrimaryRef |
|||
let _options = { |
|||
item:item, |
|||
data_primary:_searchPrimaryRef ? _searchPrimaryRef.getPrimarySearchData() : null, |
|||
data_moreList:this.moreListData, |
|||
option_primary:this.primarySearchOption, |
|||
option_moreList:this.tableColumns, |
|||
vm_primary:_searchPrimaryRef, |
|||
vm_moreList:this |
|||
} |
|||
this.$emit("overallSearchFormClick",_options) |
|||
}, |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,647 @@ |
|||
<template> |
|||
<!-- 全面的筛选组件:初级普通筛选 + 高级筛选(按照配置来判断显示情况)--> |
|||
<!-- todo:使用v-if每次重新赋值,与接口查询保持一致 --> |
|||
<div |
|||
class="searchOverallComponent" |
|||
:style="{height:componentsHeight+'px',overflow:isShowMoreList ? 'unset' : 'hidden'}" |
|||
v-show="isShow" |
|||
> |
|||
<div |
|||
class="border-outer" |
|||
ref="searchOverallComponent_inner" |
|||
> |
|||
<!-- 整体背景遮罩 --> |
|||
<!-- <div |
|||
v-if="isShow && isShowMoreList" |
|||
class="fullPageCover" |
|||
:style="{height:searchOverallCoverHeight}" |
|||
></div> --> |
|||
<!-- <div class="title" v-if="isShowMoreList">高级筛选</div> --> |
|||
<!-- 普通筛选界面 --> |
|||
<searchPrimary |
|||
v-if="primarySearchOption && primarySearchOption.length > 0" |
|||
ref="searchPrimaryRef" |
|||
:showBaseButton="!isShowMoreList" |
|||
:primarySearchOption="primarySearchOption" |
|||
:primarySearchButton="isShowMoreList ? primarySearchButton : primarySearchAllButton" |
|||
@primarySearchButtonClick="primarySearchButtonClick" |
|||
@primarySearchBaseHandle="primarySearchBaseHandle" |
|||
> |
|||
<slot></slot> |
|||
</searchPrimary> |
|||
<!-- 高级筛选界面 --> |
|||
<div v-if="isShow && isShowMoreList" class="moreListOuter"> |
|||
<curren-Form |
|||
:style="`--navFilterMaxHeight: ${selectMaxHeight};`" |
|||
class="navFilter" |
|||
size="medium" |
|||
labelWidth="0" |
|||
:searchData="moreListData" |
|||
> |
|||
<el-row :gutter="20"> |
|||
<el-form-item |
|||
v-for="(item, index) in moreListData.filters" |
|||
:key="index" |
|||
> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.column'" |
|||
:rules="rules && rules.column ? rules.column : []" |
|||
> |
|||
<el-select |
|||
v-model="item.column" |
|||
placeholder="请选择筛选对象" |
|||
:disabled="item.hide" |
|||
:filterable="true" |
|||
@change="resetSelect(item)" |
|||
> |
|||
<el-option |
|||
v-for="(item, index) in tableColumnsOptions(tableColumns)" |
|||
:key="index" |
|||
:label="item.label" |
|||
:value=" |
|||
item.showProp |
|||
? item.prop + '.' + item.showProp |
|||
: item.prop |
|||
" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.action'" |
|||
> |
|||
<el-select |
|||
v-model="item.action" |
|||
placeholder="请选择条件" |
|||
:disabled="disabledAction || item.column == '' || item.hide ? true : false" |
|||
> |
|||
<!-- moreListOptions.action --> |
|||
<el-option |
|||
v-for="item in formatMoreListOptions(item.column) " |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="7"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.value'" |
|||
:rules="rules && rules.value ? rules.value : []" |
|||
> |
|||
<el-select |
|||
v-if="inputOrSelect(item.column)" |
|||
v-model="item.value" |
|||
placeholder="请选择内容" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
:filterable="true" |
|||
@change="inputOrSelect(item.column)" |
|||
clearable |
|||
> |
|||
<el-option |
|||
v-for="item in inputOrSelect(item.column)" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value=" |
|||
typeof item.value == 'string' |
|||
? item.value |
|||
: String(item.value) |
|||
" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
<!-- 日期时间 --> |
|||
<el-date-picker |
|||
v-else-if="getColumnType(item.column) == 'datetime'" |
|||
type="datetime" |
|||
v-model="item.value" |
|||
:placeholder="'选择日期时间'" |
|||
style="width: 100%" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
></el-date-picker> |
|||
<el-input |
|||
v-else |
|||
v-model="item.value" |
|||
placeholder="请输入内容" |
|||
:disabled="item.column == '' || item.hide ? true : false" |
|||
clearable |
|||
></el-input> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="5"> |
|||
<el-form-item |
|||
:prop="'filters.' + index + '.logic'" |
|||
> |
|||
<el-select |
|||
v-model="item.logic" |
|||
placeholder="请选择关系" |
|||
:disabled="disabledLogic || item.column == '' || item.hide ? true : false" |
|||
> |
|||
<el-option |
|||
v-for="item in moreListOptions.logic" |
|||
:key="item.value" |
|||
:label="item.label" |
|||
:value="item.value" |
|||
> |
|||
</el-option> |
|||
</el-select> |
|||
</el-form-item> |
|||
</el-col> |
|||
<el-col :span="1" v-if="!item.hide"> |
|||
<!-- 删除条件按钮 --> |
|||
<el-button |
|||
type="danger" |
|||
icon="el-icon-minus" |
|||
circle |
|||
size="mini" |
|||
@click="moreListDelete(index,item)" |
|||
></el-button> |
|||
</el-col> |
|||
</el-form-item> |
|||
</el-row> |
|||
</curren-Form> |
|||
<div class="buttonsContent"> |
|||
<div class="leftButtons"> |
|||
<!-- 添加筛选条件 --> |
|||
<el-button size="small" @click="moreListPush(true)">+ 添加筛选条件</el-button> |
|||
<!-- 收起 --> |
|||
<el-button |
|||
type="text" |
|||
size="small" |
|||
@click="moreListButtonHandle({ label:'收起筛选', name:'moreList-up', type: 'text', icon:'el-icon-arrow-up', iconRight:true})" |
|||
> |
|||
收起筛选 |
|||
<i |
|||
style="margin-left:0" |
|||
:class="['el-icon--right','el-icon-arrow-up']" |
|||
></i> |
|||
</el-button> |
|||
</div> |
|||
<!-- 按钮 --> |
|||
<div class="rightButtons" v-if="moreListbuttons && moreListbuttons.length > 0" > |
|||
<el-button |
|||
v-for="(item,index) in moreListbuttons" |
|||
:key="index" |
|||
:type="item.type" |
|||
:size="item.size || 'small'" |
|||
@click="moreListButtonHandle(item)" |
|||
:icon="item.iconRight ? '' : item.icon" |
|||
> |
|||
{{ item.label }} |
|||
<!-- 自定义右侧图标 --> |
|||
<i |
|||
style="margin-left:0" |
|||
v-if="item.iconRight" |
|||
:class="['el-icon--right',item.icon]" |
|||
></i> |
|||
</el-button> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import searchPrimary from "@/components/searchPrimary" |
|||
export default { |
|||
name:'searchOverallComponent', |
|||
components: { |
|||
searchPrimary, |
|||
}, |
|||
watch:{ |
|||
// 监听显示切换 |
|||
showSearchOverall(n){ |
|||
// 控制是否显示 + 动画效果处理 |
|||
// 没有普通查询配置 |
|||
if(this.primarySearchOption.length <= 0){ |
|||
this.changeSearchOverallShow(n) |
|||
this.changeMoreListShow(n) |
|||
this.$nextTick(()=>{ |
|||
this.componentsHeight = this.getAllSearchInnerHeight() + 20 |
|||
// 收起 |
|||
if(!n && this.$parent.changeTableHeight){ |
|||
this.$parent.changeTableHeight() |
|||
} |
|||
}) |
|||
return |
|||
} |
|||
// 有普通查询配置 |
|||
if(n){ |
|||
this.changeSearchOverallShow(n) |
|||
this.changeMoreListShow(false) |
|||
} |
|||
this.$nextTick(()=>{ |
|||
if(n){ |
|||
this.componentsHeight = this.getSearchPrimaryHeight() + 20 |
|||
}else{ |
|||
this.componentsHeight = 0 |
|||
this.changeMoreListShow(false) |
|||
// setTimeout(()=>{ |
|||
// this.changeSearchOverallShow(n) |
|||
// },500) |
|||
} |
|||
}) |
|||
this.setOverallSearchData(this.httpOverallSearchData) |
|||
}, |
|||
// 监听接口搜索的筛选数据 |
|||
httpOverallSearchData(n,o){ |
|||
this.setOverallSearchData(n) |
|||
}, |
|||
isShowMoreList(){ |
|||
this.setOverallSearchData(this.httpOverallSearchData) |
|||
} |
|||
}, |
|||
props: { |
|||
// 筛选条件最大高度 |
|||
selectMaxHeight:{ |
|||
type: String, |
|||
default: '174px' |
|||
}, |
|||
// 筛选遮罩高度 |
|||
searchOverallCoverHeight:{ |
|||
type: String, |
|||
default: 'calc(100vh - 200px)' |
|||
}, |
|||
// 禁用选择条件 |
|||
disabledAction:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 禁用选择关系 |
|||
disabledLogic:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 是否显示全面筛选组件 |
|||
showSearchOverall:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 是否显示高级筛选 |
|||
showMoreSearch:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
//普通筛选绑定表单数据 |
|||
primarySearchOption: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//普通筛选自定义按钮 |
|||
primarySearchButton:{ |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 显示数据配置 |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 当前接口中的筛选数据(用于同步全面筛选的数据) |
|||
httpOverallSearchData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 自定义配置条件 |
|||
filterActionOptions:{ |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
// 普通筛选自定义所有按钮(包括高级筛选) |
|||
primarySearchAllButton:[], |
|||
// 高级筛选列表是否显示 |
|||
isShowMoreList:false, |
|||
// 组件高度(用于动画效果) |
|||
componentsHeight:0, |
|||
// 是否显示总组件,与showSearchOverall相通(重新定义一遍目的是为了动画效果) |
|||
isShow:false, |
|||
// 高级筛选列表内部按钮 |
|||
moreListbuttons: [ |
|||
{ label: "搜索", type: "primary", name: "moreList-search" }, |
|||
{ label: '重置', name: 'moreList-reset' }, |
|||
// { label:'收起筛选', name:'moreList-up', type: 'text', icon:'el-icon-arrow-up', iconRight:true} |
|||
], |
|||
// 高级筛选数据列表/值 |
|||
moreListData: {filters:[]}, |
|||
// 高级筛选条件列表配置 |
|||
moreListOptions: { |
|||
action: [{ |
|||
value: '==', |
|||
label: '等于' |
|||
}, { |
|||
value: '!=', |
|||
label: '不等于' |
|||
}, { |
|||
value: '>', |
|||
label: '大于' |
|||
}, { |
|||
value: '<', |
|||
label: '小于' |
|||
}, { |
|||
value: '>=', |
|||
label: '大于等于' |
|||
}, { |
|||
value: '<=', |
|||
label: '小于等于' |
|||
}, { |
|||
value: 'Like', |
|||
label: '包含' |
|||
}, { |
|||
value: 'NotLike', |
|||
label: '不包含' |
|||
}, |
|||
// { |
|||
// value: 'In', |
|||
// label: '包含' |
|||
// }, { |
|||
// value: 'NotIn', |
|||
// label: '不包含' |
|||
// } |
|||
], |
|||
logic: [ |
|||
{ |
|||
value: 'And', |
|||
label: '并且' |
|||
}, |
|||
{ |
|||
value: 'Or', |
|||
label: '或者' |
|||
} |
|||
], |
|||
}, |
|||
// 高级筛选rules暂未使用验证,但是不能删除rules定义 |
|||
// todo:优化后放开,优化内容:如果选择了筛选对象【column】,则验证【value】,否则都不验证 |
|||
rules:{ |
|||
// column: [ |
|||
// { required: true, message: '请选择筛选对象', trigger: 'change' } |
|||
// ], |
|||
// value: [ |
|||
// { required: true, message: '请输入内容', trigger: 'blur' } |
|||
// ], |
|||
}, |
|||
} |
|||
}, |
|||
created() { |
|||
this.moreListPush() |
|||
}, |
|||
mounted() { |
|||
// 配置普通筛选默认按钮(是否包含高级筛选按钮) |
|||
this.setPrimarySearchAllButton() |
|||
}, |
|||
methods: { |
|||
// 获取普通筛选的高度,外部也有使用,用于动画样式 |
|||
getSearchPrimaryHeight(){ |
|||
return document.getElementsByClassName('searchPrimaryComponent')[0].clientHeight |
|||
}, |
|||
// 获取普高级筛选的高度,外部也有使用,用于动画样式 |
|||
getAllSearchInnerHeight(){ |
|||
return this.$refs.searchOverallComponent_inner ? this.$refs.searchOverallComponent_inner.clientHeight : 0 |
|||
}, |
|||
// 配置普通筛选自定义按钮 |
|||
setPrimarySearchAllButton(){ |
|||
let _more_btn = [{ |
|||
label:'高级筛选', |
|||
name:'more', |
|||
type: 'text', |
|||
icon:'el-icon-arrow-down', |
|||
iconRight:true |
|||
}] |
|||
if(this.showMoreSearch){ |
|||
this.primarySearchAllButton = _more_btn.concat(this.primarySearchButton) |
|||
}else{ |
|||
this.primarySearchAllButton= this.primarySearchButton |
|||
} |
|||
}, |
|||
// 普通查询基础按钮点击事件 |
|||
primarySearchBaseHandle(item,data, option, that){ |
|||
this.overallSearchFormClick(item,data, option, that) |
|||
}, |
|||
// 普通筛选自定义按钮点击事件 |
|||
primarySearchButtonClick( item,data, option,that){ |
|||
// 点击[高级筛选]按钮 |
|||
if(item.name == 'more'){ |
|||
this.changeMoreListShow(true) |
|||
} |
|||
this.overallSearchFormClick(item,data, option, that) |
|||
}, |
|||
// 高级筛选基础按钮点击事件 |
|||
moreListButtonHandle(item){ |
|||
this.overallSearchFormClick(item) |
|||
}, |
|||
// 设置moreList的列表值(默认按tableColumns设置) |
|||
tableColumnsOptions(val) { |
|||
const data = JSON.parse(JSON.stringify(val)); |
|||
let num = 0 |
|||
val.forEach((item, index) => { |
|||
if (item.showProp) { |
|||
data.splice(index - num, 1) |
|||
num++ |
|||
} |
|||
}) |
|||
return data |
|||
}, |
|||
// 判断筛选类型是否是时间格式 |
|||
getColumnType(val) { |
|||
var columnsType = this.tableColumns.filter(item => item.prop == val) |
|||
if (columnsType.length > 0) { |
|||
if (columnsType[0].apiBaseType) { |
|||
return columnsType[0].apiBaseType |
|||
} |
|||
} else { |
|||
return '' |
|||
} |
|||
}, |
|||
// 筛选条件改变重置其他项 |
|||
resetSelect(val) { |
|||
val.action = "==" |
|||
val.value = "" |
|||
}, |
|||
// 根据数据内容约束条件选项 |
|||
formatMoreListOptions(val) { |
|||
// 自定义配置条件filterActionOptions |
|||
if(this.filterActionOptions){ |
|||
this.moreListOptions.action = this.filterActionOptions |
|||
return this.moreListOptions.action |
|||
} |
|||
if (val) { |
|||
for(var i =0; i< this.tableColumns.length; i++) { |
|||
if (val == this.tableColumns[i].prop) { |
|||
if (this.tableColumns[i].filters) { |
|||
return this.moreListOptions.action.filter(item => item.value == '==' || item.value == '!=') |
|||
} else if (this.tableColumns[i].type == 'dateTime') { |
|||
return this.moreListOptions.action.filter(item => |
|||
item.value == '==' || |
|||
item.value == '!=' || |
|||
item.value == '>' || |
|||
item.value == '<' || |
|||
item.value == '>=' || |
|||
item.value == '<=' ) |
|||
} else { |
|||
return this.moreListOptions.action |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return this.moreListOptions.action |
|||
}, |
|||
// 设置moreList列表的内容项是input还是select |
|||
inputOrSelect(val) { |
|||
let data = null |
|||
if (val) { |
|||
this.tableColumns.forEach((key) => { |
|||
if (val == key.prop) { |
|||
if (key.enums_list && key.enums_list.length > 0) { |
|||
data = key.enums_list |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
return data |
|||
}, |
|||
// 高级筛选列表-删除筛选条件行 |
|||
moreListDelete(val,item) { |
|||
if (this.moreListData.filters.length == 1) { |
|||
this.$warningMsg('必须保留一条筛选条件!') |
|||
} else { |
|||
this.$confirm('您确定删除吗, 是否继续?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.moreListData.filters.splice(val, 1) |
|||
this.$nextTick(()=>{ |
|||
this.componentsHeight = this.getAllSearchInnerHeight() + 20 |
|||
this.$parent.changeTableHeight(this.getAllSearchInnerHeight()) |
|||
}) |
|||
}).catch(() => { |
|||
// this.modalAppendToBody = false |
|||
}); |
|||
} |
|||
this.overallSearchFormClick({name:'moreList-deleteRow'}) |
|||
}, |
|||
// 高级筛选列表-添加筛选条件行 |
|||
moreListPush(handle) { |
|||
let data = { |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
} |
|||
this.moreListData.filters.push(data) |
|||
this.overallSearchFormClick({name:'moreList-addRow'}) |
|||
if(handle){ |
|||
this.$nextTick(()=>{ |
|||
this.componentsHeight = this.getAllSearchInnerHeight() + 20 |
|||
this.$parent.changeTableHeight(this.getAllSearchInnerHeight()) |
|||
}) |
|||
} |
|||
}, |
|||
// 重置数据,高级(单纯节点显示数据,不重新查询接口) |
|||
resetMoreListData(){ |
|||
this.moreListData = {filters:[]} |
|||
this.moreListPush() |
|||
}, |
|||
// 设置数据值,高级(单纯节点显示数据,不重新查询接口) |
|||
setMoreListData(val){ |
|||
this.moreListData = JSON.parse(JSON.stringify(val)) |
|||
}, |
|||
// 重置数据,普通+高级(单纯节点显示数据,不重新查询接口) |
|||
resetOverallSearchData(){ |
|||
if(this.$refs.searchPrimaryRef)this.$refs.searchPrimaryRef.resetPrimarySearchData(); |
|||
this.resetMoreListData() |
|||
}, |
|||
// 设置数据,普通+高级(单纯节点显示数据,不重新查询接口) |
|||
setOverallSearchData(data){ |
|||
// 普通筛选数据同步 |
|||
if(data && data.params){ |
|||
if(this.$refs.searchPrimaryRef)this.$refs.searchPrimaryRef.setPrimarySearchData(data.params) |
|||
}else{ |
|||
if(this.$refs.searchPrimaryRef)this.$refs.searchPrimaryRef.resetPrimarySearchData() |
|||
} |
|||
// 高级筛选数据同步 |
|||
if(data && data.moreList){ |
|||
let _list = {filters:[]} |
|||
data.moreList.filters.forEach(item=>{ |
|||
if(String(item.column).length > 0 && String(item.value).length > 0){ |
|||
_list.filters.push(item) |
|||
} |
|||
}) |
|||
if(_list.filters.length <= 0){ |
|||
_list.filters.push({ |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
}) |
|||
} |
|||
this.setMoreListData(_list) |
|||
}else{ |
|||
this.resetMoreListData() |
|||
} |
|||
}, |
|||
// 展开-收缩高级筛选 |
|||
changeMoreListShow(val){ |
|||
this.isShowMoreList = val || false |
|||
// 如果没有初级筛选 |
|||
if(!this.primarySearchOption || this.primarySearchOption.length <= 0){ |
|||
// 关闭时候直接整个全面筛选组件 |
|||
if(!this.isShowMoreList){ |
|||
this.isShow = false |
|||
this.$emit("getShowSearchOverall",this.isShow) |
|||
} |
|||
} |
|||
}, |
|||
// 关闭整个全面组件 |
|||
changeSearchOverallShow(val){ |
|||
if(!val){ |
|||
this.changeMoreListShow(false) |
|||
} |
|||
this.isShow = val || false |
|||
this.$emit("getShowSearchOverall",this.isShow) |
|||
}, |
|||
// 全面筛选组件所有按钮事件 |
|||
overallSearchFormClick(item,data, option) { |
|||
// 页面功能 |
|||
// 收缩筛选 |
|||
if(item.name == 'moreList-up'){ |
|||
this.changeMoreListShow(false) |
|||
} |
|||
// 高级筛选内-重置 || 普通格式-重置 |
|||
else if(item.name == "moreList-reset" || item.name == "reset"){ |
|||
this.resetOverallSearchData() |
|||
} |
|||
// 抛出函数传参 |
|||
let _searchPrimaryRef = this.$refs.searchPrimaryRef |
|||
let _options = { |
|||
item:item, |
|||
data_primary:_searchPrimaryRef ? _searchPrimaryRef.getPrimarySearchData() : null, |
|||
data_moreList:this.moreListData, |
|||
option_primary:this.primarySearchOption, |
|||
option_moreList:this.tableColumns, |
|||
vm_primary:_searchPrimaryRef, |
|||
vm_moreList:this |
|||
} |
|||
this.$emit("overallSearchFormClick",_options) |
|||
}, |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,83 @@ |
|||
.searchOverallComponent{ |
|||
height: 0; |
|||
transition:all 0.5s; |
|||
z-index: 1; |
|||
overflow: hidden; |
|||
|
|||
.border-outer{ |
|||
position: relative; |
|||
background: #f8f9fb; |
|||
padding: 10px 20px 0; |
|||
border: #eff0f2 solid 1px; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
.fullPageCover{ |
|||
position: absolute; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
left: 0; |
|||
right: 0; |
|||
// height: calc(100vh - 200px); |
|||
cursor: no-drop; |
|||
} |
|||
|
|||
.moreListOuter{ |
|||
margin-top: 10px; |
|||
position: relative; |
|||
} |
|||
|
|||
::v-deep .navFilter { |
|||
// display: flex; |
|||
// flex-direction: column; |
|||
// width: 100%; |
|||
// height: 100%; |
|||
max-height: 30vh; |
|||
overflow: auto; |
|||
|
|||
.el-form { |
|||
// flex: 1; |
|||
// padding-left: 100px; |
|||
// padding-right: 100px; |
|||
display: flex; |
|||
align-content: flex-start; |
|||
flex-wrap: wrap; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
|
|||
.el-row{ |
|||
margin: 0 !important; |
|||
margin-left: -5px !important; |
|||
} |
|||
|
|||
|
|||
.el-select{ |
|||
width: 100%; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.title{ |
|||
padding: 10px 0 15px 0; |
|||
font-weight: bold; |
|||
color: #333; |
|||
} |
|||
|
|||
.moreListPush-btn { |
|||
width: 100%; |
|||
padding-left: 5px; |
|||
color: rgb(64, 158, 255); |
|||
|
|||
span { |
|||
cursor: pointer; |
|||
|
|||
&:hover { |
|||
color: blue; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.moreListBaseBts{ |
|||
padding: 20px 0; |
|||
} |
|||
|
|||
} |
@ -0,0 +1,89 @@ |
|||
.searchOverallComponent{ |
|||
height: 0; |
|||
transition:all 0.5s; |
|||
z-index: 1; |
|||
overflow: hidden; |
|||
|
|||
.border-outer{ |
|||
position: relative; |
|||
background: #f8f9fb; |
|||
padding: 10px 20px 0; |
|||
border: #eff0f2 solid 1px; |
|||
margin-bottom: 10px; |
|||
} |
|||
|
|||
.fullPageCover{ |
|||
position: absolute; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
left: 0; |
|||
right: 0; |
|||
// height: calc(100vh - 200px); |
|||
cursor: no-drop; |
|||
} |
|||
|
|||
.moreListOuter{ |
|||
margin-top: 10px; |
|||
position: relative; |
|||
} |
|||
|
|||
::v-deep .navFilter { |
|||
// display: flex; |
|||
// flex-direction: column; |
|||
// width: 100%; |
|||
// height: 100%; |
|||
max-height: var(--navFilterMaxHeight); |
|||
overflow: auto; |
|||
|
|||
.el-form { |
|||
// flex: 1; |
|||
// padding-left: 100px; |
|||
// padding-right: 100px; |
|||
display: flex; |
|||
align-content: flex-start; |
|||
flex-wrap: wrap; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
|
|||
.el-row{ |
|||
margin: 0 !important; |
|||
margin-left: -5px !important; |
|||
} |
|||
|
|||
|
|||
.el-select{ |
|||
width: 100%; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.title{ |
|||
padding: 10px 0 15px 0; |
|||
font-weight: bold; |
|||
color: #333; |
|||
} |
|||
|
|||
.buttonsContent{ |
|||
justify-content: space-between; |
|||
display: flex; |
|||
padding-bottom: 20px; |
|||
width: 890px; |
|||
} |
|||
// .moreListPush-btn { |
|||
// width: 100%; |
|||
// padding-left: 5px; |
|||
// color: rgb(64, 158, 255); |
|||
|
|||
// span { |
|||
// cursor: pointer; |
|||
|
|||
// &:hover { |
|||
// color: blue; |
|||
// } |
|||
// } |
|||
// } |
|||
|
|||
// .moreListBaseBts{ |
|||
// padding: 20px 0; |
|||
// } |
|||
|
|||
} |
@ -0,0 +1,336 @@ |
|||
<template> |
|||
<!-- 组件功能:搜索页面,filterSelect后面放大镜页面 --> |
|||
<el-dialog |
|||
class="searchPageComponents" |
|||
:title="formTitle" |
|||
v-if="displayDialog" |
|||
:visible="true" |
|||
:fullscreen="true" |
|||
:modal="false" |
|||
:modal-append-to-body="false" |
|||
:show-close="false" |
|||
> |
|||
<div class="searchDialog"> |
|||
<div class="searchSXButton"> |
|||
<el-button |
|||
type="primary" |
|||
icon="el-icon-finished" |
|||
size="mini" |
|||
@click="handleSubmit" |
|||
style="width:180px" |
|||
>筛选 |
|||
</el-button> |
|||
</div> |
|||
<umyTable |
|||
ref="searchTable" |
|||
:tableLoading="tableLoading" |
|||
:tableData="searchTableData" |
|||
:selectionTable="selectionTable" |
|||
:tableColumns="searchTableColumns | DialogTable" |
|||
:setUTableHeight="setUTableHeight" |
|||
@handleSelectionChange="prepareFormData" |
|||
></umyTable> |
|||
<pagination |
|||
:totalCount="searchTotalCount" |
|||
:pagesizeProps="supplierItemPage.MaxResultCount" |
|||
@SizeChange="SizeChange" |
|||
@CurrentChange="CurrentChange" |
|||
></pagination> |
|||
<div class="formButton"> |
|||
<currenButton |
|||
:buttonsAllIsRight="buttonsAllIsRight" |
|||
:Butttondata="editHandle" |
|||
@tableButtonClick="tableButtonClick" |
|||
></currenButton> |
|||
</div> |
|||
</div> |
|||
<div class="filterPage" v-if="modal"> |
|||
<!-- 筛选 --> |
|||
<conditionFilters |
|||
:displayDialog="dialog" |
|||
:screenData="screenData" |
|||
:tableColumns="searchTableColumns" |
|||
@screenFormClick="screenFormClick" |
|||
@screenDelete="screenDelete" |
|||
@screenPush="screenPush" |
|||
:filterActionOptions="filterActionOptions" |
|||
></conditionFilters> |
|||
</div> |
|||
</el-dialog> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
props: { |
|||
//是否需要遮罩层 |
|||
// modal: { |
|||
// type: Boolean, |
|||
// default: () => { |
|||
// return true |
|||
// } |
|||
// }, |
|||
//loading |
|||
tableLoading: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
// 已app-main高度为100% 需要减掉的高度 |
|||
setUTableHeight: { |
|||
type: Number, |
|||
default: () => { |
|||
return 220; |
|||
} |
|||
}, |
|||
// 按钮整体靠右 |
|||
buttonsAllIsRight:{ |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//名称 |
|||
formTitle: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
//是否弹窗 |
|||
displayDialog: { |
|||
type: Boolean, |
|||
default: () => { |
|||
return false |
|||
} |
|||
}, |
|||
//Table表头数据 |
|||
searchTableData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//Table表身绑定 |
|||
searchTableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//Table总数 |
|||
searchTotalCount: { |
|||
type: Number, |
|||
default: () => { |
|||
return 0 |
|||
} |
|||
}, |
|||
//Table每页显示数量 |
|||
supplierItemPage: { |
|||
type: Object, |
|||
default: () => { |
|||
return { |
|||
MaxResultCount: 20, |
|||
SkipCount: 0 |
|||
} |
|||
} |
|||
}, |
|||
//Table选中数据 |
|||
selectionTable: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
//Table是否支持多选 |
|||
isMoreSelectTable: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// 筛选条件自定义(等于/不等于/大于/小于等数据) |
|||
filterActionOptions:{ |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
//确认筛选后续操作 |
|||
advancedFilter: { |
|||
type: Function, |
|||
default: () => { |
|||
return () => { |
|||
return {} |
|||
} |
|||
} |
|||
}, |
|||
//初始化筛选数据 |
|||
filterPageListParams: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
editHandle: { |
|||
type: Array, |
|||
default: () => { |
|||
return [ |
|||
{ label: "取消", name: "cancel" }, |
|||
{ label: "确定", type: "primary", name: "determine" }, |
|||
] |
|||
} |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
modal: false, |
|||
dialog: { |
|||
screenDialog: false |
|||
}, |
|||
//筛选 |
|||
screenData: { |
|||
filters: [{ |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
}] |
|||
}, |
|||
} |
|||
}, |
|||
methods: { |
|||
//table选择当前行数据 |
|||
prepareFormData (val) { |
|||
this.$parent.isMoreSelectTable = this.isMoreSelectTable |
|||
this.$emit('handleSelectionChange', val) |
|||
}, |
|||
//改变每页最大数 |
|||
SizeChange (val) { |
|||
this.$emit('SizeChange', val) |
|||
}, |
|||
//改变当前页 |
|||
CurrentChange (val) { |
|||
this.$emit('CurrentChange', val) |
|||
}, |
|||
//table按钮点击事件 |
|||
tableButtonClick (val) { |
|||
this.$emit('tableButtonClick', val, this.$refs.searchTable) |
|||
}, |
|||
//点击筛选按钮 |
|||
handleSubmit () { |
|||
let filter = JSON.parse(JSON.stringify(this.filterPageListParams)) |
|||
let newFilter = this.supplierItemPage.condition.filters |
|||
this.dialog.screenDialog = true |
|||
this.screenData.filters = [] |
|||
if (newFilter.length != 0) { |
|||
filter.forEach((element, index) => { |
|||
newFilter[index].hide = true |
|||
}); |
|||
this.screenData.filters.push(...newFilter) |
|||
} else { |
|||
let data = [{ |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
}] |
|||
this.screenData.filters = data |
|||
} |
|||
this.$emit('sxBtnClickHandle',this.screenData.filters) |
|||
this.modal = true |
|||
}, |
|||
// 设置this.screenData.filters的值 |
|||
setScreenDataFilters (data){ |
|||
this.screenData.filters = data |
|||
}, |
|||
//筛选 |
|||
screenFormClick (val) { |
|||
let filter = JSON.parse(JSON.stringify(this.filterPageListParams)) |
|||
if (val[0] == 0) { |
|||
if (filter.length != 0) { |
|||
this.supplierItemPage.condition.filters = filter |
|||
} else { |
|||
this.supplierItemPage.condition.filters = [] |
|||
} |
|||
this.dialog.screenDialog = false; |
|||
this.advancedFilter() |
|||
} else if (val[0] == 1) { |
|||
val[1].clearValidate() |
|||
this.dialog.screenDialog = false; |
|||
} else { |
|||
val[1].validate((valid, newFilter) => { |
|||
if (valid) { |
|||
this.supplierItemPage.condition.filters = [] |
|||
this.screenData.filters.forEach((element, index) => { |
|||
this.supplierItemPage.condition.filters.push(element) |
|||
}) |
|||
this.dialog.screenDialog = false; |
|||
this.advancedFilter() |
|||
} else { |
|||
this.$errorMsg('请按照提示继续操作') |
|||
return false; |
|||
} |
|||
}); |
|||
} |
|||
this.modal = false |
|||
}, |
|||
//添加筛选条件 |
|||
screenPush () { |
|||
let data = { |
|||
logic: "And", |
|||
column: "", |
|||
action: "==", |
|||
value: "" |
|||
} |
|||
// if (this.screenData.filters.length <= this.searchTableColumns.length) { |
|||
this.screenData.filters.push(data) |
|||
// } else { |
|||
// this.$errorMsg('筛选条件数不足!') |
|||
// } |
|||
}, |
|||
//删除筛选条件 |
|||
screenDelete (val) { |
|||
if (this.screenData.filters.length == 1) { |
|||
this.$warningMsg('必须保留一条筛选条件!') |
|||
} else { |
|||
this.$confirm('您确定删除吗, 是否继续?', '提示', { |
|||
confirmButtonText: '确定', |
|||
cancelButtonText: '取消', |
|||
type: 'warning' |
|||
}).then(() => { |
|||
this.screenData.filters.splice(val, 1) |
|||
}).catch((err) => { |
|||
console.log(err) |
|||
}); |
|||
} |
|||
}, |
|||
} |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.searchPageComponents { |
|||
.el-dialog__body{ |
|||
height: calc(100% - 55px) !important; |
|||
padding: 0 20px; |
|||
} |
|||
.currenButton{ |
|||
padding: 0; |
|||
} |
|||
.searchDialog{ |
|||
height: 100%; |
|||
} |
|||
.pagination{ |
|||
padding: 30px 10px 20px 10px; |
|||
} |
|||
.formButton{ |
|||
padding-top: 0 !important; |
|||
} |
|||
.el-dialog__header{ |
|||
padding-top: 10px; |
|||
} |
|||
.currenButton .el-button{ |
|||
margin: 0; |
|||
margin-left: 10px; |
|||
} |
|||
} |
|||
</style> |
|||
<style lang="scss" scoped> |
|||
.searchSXButton { |
|||
padding-bottom: 10px |
|||
} |
|||
.el-dialog__wrapper{ |
|||
position: absolute !important; |
|||
} |
|||
</style> |
@ -0,0 +1,242 @@ |
|||
<template> |
|||
<!-- 普通筛选:列表点击筛选下的普通筛选 --> |
|||
<div class="searchPrimaryComponent" > |
|||
<!-- @submit.native.prevent 阻止form只有一个input输入框回车触发提交事件 --> |
|||
<el-form |
|||
class="searchPrimaryForm" |
|||
ref="searchPrimaryForm" |
|||
:size="primarySearchSize" |
|||
:inline="true" |
|||
:model="primarySearchData_inner" |
|||
@submit.native.prevent |
|||
> |
|||
<el-form-item |
|||
v-for="(item, index) in primarySearchOption" |
|||
:key="index" |
|||
:label="item.label" |
|||
:prop="item.showProp ? item.prop + '.' + item.showProp : item.prop" |
|||
v-show="!item.hide ? true : false" |
|||
> |
|||
<!-- type === 'input' 输入框 onkeyup: 正则表达式,用于前端输入校验工作--> |
|||
<el-input |
|||
v-if="item.type === 'input'" |
|||
v-model="primarySearchData_inner[item.prop]" |
|||
:maxlength="item.maxlength" |
|||
:onkeyup="item.onkeyup" |
|||
:clearable="!item.noClearable" |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
:prefix-icon="item.icon" |
|||
:show-password="item.showPassword" |
|||
></el-input> |
|||
<!-- item.type === 'select' 下拉框 --> |
|||
<el-select |
|||
v-if="item.type === 'select'" |
|||
v-model="primarySearchData_inner[item.prop]" |
|||
:clearable="!item.noClearable" |
|||
:multiple="item.multiple" |
|||
:disabled="Boolean(item.disabled)" |
|||
:filterable="item.filterable" |
|||
:allow-create="item.allowCreate" |
|||
:placeholder="item.placeholder || '请输入' + item.label" |
|||
> |
|||
<el-option |
|||
v-for="(op, index) in selectOptions(item.options) || |
|||
item.userOptions" |
|||
:label="op[item.optionsLabel] || op.label" |
|||
:value="op[item.optionsValue] || op.value" |
|||
:key="index" |
|||
></el-option> |
|||
</el-select> |
|||
<!-- item.type === 'date' 日期 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'date'" |
|||
v-model="primarySearchData_inner[item.prop]" |
|||
:disabled="Boolean(item.disabled)" |
|||
:placeholder="item.placeholder || '选择日期'" |
|||
value-format="yyyy-MM-dd" |
|||
></el-date-picker> |
|||
<!-- item.type === 'time' 时间 --> |
|||
<el-time-picker |
|||
v-if="item.type === 'time'" |
|||
v-model="primarySearchData_inner[item.prop]" |
|||
:placeholder="item.placeholder || '选择时间'" |
|||
:picker-options="{ |
|||
selectableRange: '00:00:00 - 23:59:00', |
|||
}" |
|||
:disabled="Boolean(item.disabled)" |
|||
format="HH:mm" |
|||
value-format="HH:mm" |
|||
></el-time-picker> |
|||
<!-- item.type === 'dateTime' 日期时间 --> |
|||
<el-date-picker |
|||
v-if="item.type === 'dateTime'" |
|||
type="datetime" |
|||
v-model="primarySearchData_inner[item.prop]" |
|||
:placeholder="item.placeholder || '选择日期时间'" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
></el-date-picker> |
|||
<!-- item.type === 'dateTimelimit' 日期时间 日期有限制 选择范围:当前天及以后--> |
|||
<el-date-picker |
|||
v-if="item.type === 'dateTimelimit'" |
|||
type="datetime" |
|||
v-model="primarySearchData_inner[item.prop]" |
|||
:placeholder="item.placeholder || '选择日期时间'" |
|||
format="yyyy-MM-dd HH:mm:ss" |
|||
value-format="yyyy-MM-ddTHH:mm:ss" |
|||
:disabled="Boolean(item.disabled)" |
|||
:pickerOptions="endDateTimeLimitPickerOptions()" |
|||
></el-date-picker> |
|||
</el-form-item> |
|||
<!-- 自定义插槽 --> |
|||
<slot></slot> |
|||
<!-- 基础按钮 --> |
|||
<el-form-item v-if="showBaseButton" class="el-form-item__buttonbox"> |
|||
<el-button |
|||
v-for="(item,index) in baseButton" |
|||
:key="index" |
|||
:type="item.type" |
|||
:size="primarySearchSize" |
|||
@click="primarySearchBaseHandle(item)" |
|||
>{{item.label}}</el-button> |
|||
</el-form-item> |
|||
<!-- 自定义按钮 --> |
|||
<el-form-item |
|||
class="el-form-item__buttonbox" |
|||
v-for="(item,index) in primarySearchButton" |
|||
:key="item.name + '' + index" |
|||
> |
|||
<el-button |
|||
:type="item.type" |
|||
:size="item.size || primarySearchSize" |
|||
@click="primarySearchButtonClick(item)" |
|||
:icon="item.iconRight ? '' : item.icon" |
|||
> |
|||
{{ item.label }} |
|||
<!-- 自定义右侧图标 --> |
|||
<i |
|||
style="margin-left:0" |
|||
v-if="item.iconRight" |
|||
:class="['el-icon--right',item.icon]" |
|||
></i> |
|||
</el-button> |
|||
</el-form-item> |
|||
</el-form> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
export default { |
|||
name: "searchPrimaryComponent", |
|||
props: { |
|||
// 查询表单配置(@utils/primarySearchOption/index.js) |
|||
primarySearchOption: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
// 是否显示基础按钮(查询、重置) |
|||
showBaseButton:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 查询表单自定义按钮(业务线页面内定义) |
|||
primarySearchButton: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
}, |
|||
}, |
|||
}, |
|||
data() { |
|||
return { |
|||
// 最初记录的值,(用于普通筛选自带默认值) |
|||
initialPrimarySearchData:null, |
|||
// 绑定的值 |
|||
primarySearchData_inner:{}, |
|||
// 初级筛选内容大小 |
|||
primarySearchSize:'medium', |
|||
// 默认基础按钮配置(同【高级筛选】等按钮,与初级筛选内部无关,属于自定义按钮,在primarySearchButton中配置) |
|||
baseButton:[ |
|||
{label:"搜索",name:"search",type: "primary"}, |
|||
{label:"重置",name:"reset"}, |
|||
], |
|||
}; |
|||
}, |
|||
computed: { |
|||
// 日期时间组件,选择范围:当前天及以后 |
|||
endDateTimeLimitPickerOptions() { |
|||
return function () { |
|||
return { |
|||
disabledDate(time) { |
|||
return ( |
|||
time.getTime() < Date.now() - 8.64e7 |
|||
); |
|||
}, |
|||
}; |
|||
}; |
|||
}, |
|||
// 获取statu.js中配置的options |
|||
selectOptions() { |
|||
return (val) => { |
|||
if (val) { |
|||
let options = this.$staticOptions[val]; |
|||
if (options) { |
|||
return options(); |
|||
} else { |
|||
return []; |
|||
} |
|||
} else { |
|||
return false; |
|||
} |
|||
}; |
|||
}, |
|||
}, |
|||
created(){ |
|||
// 默认设置值 initialPrimarySearchData + primarySearchData_inner |
|||
this.initialPrimarySearchData = {} |
|||
this.primarySearchOption.forEach(item => { |
|||
this.initialPrimarySearchData[item.prop] = item.value || null |
|||
}) |
|||
this.setPrimarySearchData(this.initialPrimarySearchData) |
|||
}, |
|||
methods: { |
|||
// 基础按钮操作 |
|||
primarySearchBaseHandle(item){ |
|||
this.$emit("primarySearchBaseHandle", item,this.primarySearchData_inner, this.primarySearchOption, this ) |
|||
}, |
|||
// 重置数据(单纯节点显示数据,不重新查询接口) |
|||
resetPrimarySearchData(){ |
|||
this.primarySearchData_inner = JSON.parse(JSON.stringify(this.initialPrimarySearchData)) |
|||
}, |
|||
// 获取普通搜索数据值 |
|||
getPrimarySearchData(){ |
|||
return this.primarySearchData_inner |
|||
}, |
|||
// 设置普通搜索数据值 |
|||
setPrimarySearchData(data){ |
|||
this.primarySearchData_inner = JSON.parse(JSON.stringify(data)) |
|||
}, |
|||
// 自定义按钮点击事件 |
|||
primarySearchButtonClick(item){ |
|||
this.$emit("primarySearchButtonClick", item,this.primarySearchData_inner, this.primarySearchOption,this) |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.searchPrimaryComponent{ |
|||
.el-input{ |
|||
width: auto !important; |
|||
} |
|||
.el-form-item{ |
|||
margin-bottom: 10px !important; |
|||
|
|||
&:not(.el-form-item__buttonbox){ |
|||
margin-right: 30px !important; |
|||
} |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,284 @@ |
|||
<template> |
|||
<!-- 组件功能:查看json及复制 --> |
|||
<div class="showCopyJsonPop"> |
|||
|
|||
<!-- 点开查看Json转换后table弹窗 --> |
|||
<el-dialog |
|||
top="50px" |
|||
:visible.sync="JsonTableShow" |
|||
:modal-append-to-body="true" |
|||
:append-to-body="true" |
|||
:show-close="true" |
|||
:close-on-click-modal="true" |
|||
:close-on-press-escape="true" |
|||
width="90%" |
|||
@close="closePop" |
|||
> |
|||
<template #title> |
|||
内容详情 |
|||
<el-button |
|||
size="mini" |
|||
@click="copyJsonHandle()" |
|||
type="primary" |
|||
style="margin-right: 30px;float: right;" |
|||
>复制JSON</el-button> |
|||
</template> |
|||
<el-table |
|||
height="calc(100vh - 220px)" |
|||
:data="JsonTableData" |
|||
:border="true" |
|||
style="width: 100%"> |
|||
<el-table-column |
|||
prop="name" |
|||
width="220" |
|||
label="属性" |
|||
> |
|||
<template slot-scope="scope"> |
|||
{{ scope.row.name }} |
|||
<el-button |
|||
type="primary" |
|||
v-if="(scope.row.name).toUpperCase() == 'DETAILS'" |
|||
size="mini" |
|||
style="margin-left: 20px;" |
|||
@click="showDetailTableHandle(scope.row)" |
|||
>查看详情</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column |
|||
label="值" |
|||
> |
|||
<template slot-scope="scope"> |
|||
<!-- DETAILS todo:DETAILS判断条件需要优化,使用传参的方式 --> |
|||
<span v-if="(scope.row.name).toUpperCase() != 'DETAILS'">{{scope.row.value}}</span> |
|||
<el-table |
|||
v-else |
|||
:data="scope.row.value" |
|||
stripe |
|||
:border="true" |
|||
style="width: 100%" |
|||
height="300" |
|||
> |
|||
<el-table-column |
|||
label="序号" |
|||
fixed="left" |
|||
type="index" |
|||
width="50"> |
|||
</el-table-column> |
|||
<el-table-column |
|||
v-for="(head,h_key) in detailTableHeader" |
|||
:key="h_key" |
|||
min-width="120" |
|||
> |
|||
<template #header> |
|||
<span :title="head">{{ head }}</span> |
|||
</template> |
|||
<template slot-scope="scope2"> |
|||
<div v-if="typeof scope2.row[head] == 'object'"> |
|||
<div v-for="(o,o_key) in scope2.row[head]"> |
|||
{{ o_key }}:{{ o }} |
|||
<div style="border-bottom: dashed 1px #ddd;"></div> |
|||
</div> |
|||
</div> |
|||
<div v-else>{{ scope2.row[head] }}</div> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
</el-dialog> |
|||
|
|||
<!-- json复制内容弹窗 --> |
|||
<el-dialog |
|||
top="50px" |
|||
:visible.sync="JsonCopyShow" |
|||
:modal-append-to-body="false" |
|||
:append-to-body="true" |
|||
:show-close="true" |
|||
:close-on-click-modal="true" |
|||
:close-on-press-escape="true" |
|||
:title="'JSON详情'" |
|||
> |
|||
<el-input |
|||
class="copyJsonTextarea" |
|||
ref="copyJsonTextarea_ref" |
|||
type="textarea" |
|||
readonly |
|||
autosize |
|||
resize="none" |
|||
v-model="JsonCopyData" |
|||
></el-input> |
|||
</el-dialog> |
|||
|
|||
<!-- details的table --> |
|||
<el-dialog |
|||
top="80px" |
|||
width="86%" |
|||
v-if="detailTableRow" |
|||
:visible.sync="detailsTableShow" |
|||
:modal-append-to-body="true" |
|||
:append-to-body="true" |
|||
:show-close="true" |
|||
:close-on-click-modal="true" |
|||
:close-on-press-escape="true" |
|||
:title="detailTableRow.name+' 详情'" |
|||
> |
|||
<!-- row-key 默认不处理,解决id可能重复问题,此处没有选择框,可以这么处理 --> |
|||
<umyTable |
|||
:isShowIndex="true" |
|||
:tableBorder="true" |
|||
:setUTableHeight="170" |
|||
:row-key="null" |
|||
:tableData="detailTableRow.value" |
|||
:tableColumns="detailTableColumns" |
|||
:selectionTable="false" |
|||
></umyTable> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import { LoadingMixins } from "@/mixins/LoadingMixins"; |
|||
import { tableMixins } from "@/mixins/TableMixins" |
|||
export default { |
|||
name:"showCopyJsonPop", |
|||
mixins:[ LoadingMixins,tableMixins ], |
|||
props: { |
|||
// Json数据 |
|||
JsonData:{ |
|||
type: Object, |
|||
default: null, |
|||
}, |
|||
}, |
|||
data () { |
|||
return { |
|||
JsonTableShow:true,//点开查看Json转换后table弹窗 |
|||
JsonTableData:null,//表格转义的json数据 |
|||
JsonCopyData:null,//复制的Json字符串 |
|||
JsonCopyShow:false,//复制json的Dialog显隐控制 |
|||
detailTableHeader:null,//details表格的Header |
|||
detailTableRow:null,//details的相关信息 |
|||
detailsTableShow:false,//details的详情 |
|||
detailTableColumns:false,//details的详情header表头 |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.initJsonData() |
|||
}, |
|||
methods: { |
|||
// 关闭整个弹窗 |
|||
closePop() { |
|||
this.JsonTableShow = false |
|||
this.$emit("closePop") |
|||
}, |
|||
// json数据转义 |
|||
initJsonData(){ |
|||
let _arr = [] |
|||
let __initJson = (data) => { |
|||
let _init = [] |
|||
for(let item in data){ |
|||
_init.push({name:item,value:data[item]}) |
|||
} |
|||
return _init |
|||
} |
|||
let _json = this.JsonData |
|||
for(let item in _json){ |
|||
// 直接输出 |
|||
if(!_json[item]){ |
|||
_arr.push({name:item,value:_json[item]}) |
|||
}else{ |
|||
if(typeof _json[item] != 'object'){ |
|||
_arr.push({name:item,value:_json[item] + ""}) |
|||
}else{ |
|||
// 如果是数组 |
|||
if(Array.isArray(_json[item])){ |
|||
// 如果是 DETAILS todo:DETAILS判断条件需要优化,使用传参的方式 |
|||
// let _value = (item).toUpperCase() == 'DETAILS' ? __initJson(_json[item][0]) : (_json[item]).join(",") |
|||
this.detailTableHeader = [] |
|||
for(let h in _json[item][0]){ |
|||
this.detailTableHeader.push(h) |
|||
} |
|||
let _value = (item).toUpperCase() == 'DETAILS' ? _json[item] : (_json[item]).join(",") |
|||
_arr.push({name:item,value:_value}) |
|||
} |
|||
// 如果是对象 |
|||
else{ |
|||
let _obj_arr = __initJson(_json[item]) |
|||
// 对象有数据 |
|||
if(_obj_arr.length > 0){ |
|||
_arr = [..._obj_arr] |
|||
}else{ |
|||
// 空对象 |
|||
_arr.push({name:item,value:""}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
this.JsonTableData = _arr |
|||
this.JsonCopyData = JSON.stringify(_json, null, '\t')//复制使用 |
|||
}, |
|||
// 复制后选择框处理 |
|||
copyJsonInputHandle(type){ |
|||
if(type == 'error')this.$message.error('复制失败'); |
|||
if(type == 'success')this.$message.success('复制成功'); |
|||
if(this.$refs.copyJsonTextarea_ref){ |
|||
this.$refs.copyJsonTextarea_ref.focus() |
|||
this.$refs.copyJsonTextarea_ref.$refs.textarea.scrollTop = 0 |
|||
} |
|||
}, |
|||
// 复制Json按钮 |
|||
copyJsonHandle(){ |
|||
this.JsonCopyShow = true |
|||
if (navigator.clipboard && window.isSecureContext) { |
|||
navigator.clipboard.writeText(this.JsonCopyData) |
|||
.then(() => { |
|||
this.copyJsonInputHandle('success') |
|||
}) |
|||
.catch(err => { |
|||
this.copyJsonInputHandle('error') |
|||
}); |
|||
}else { |
|||
// 创建text area |
|||
const textArea = document.createElement('textarea') |
|||
textArea.value = this.JsonCopyData |
|||
// 使text area不在viewport,同时设置不可见 |
|||
document.body.appendChild(textArea) |
|||
textArea.focus() |
|||
textArea.select() |
|||
return new Promise((resolve, reject) => { |
|||
// 执行复制命令并移除文本框 |
|||
document.execCommand('copy') ? resolve() : reject(new Error('出错了')) |
|||
textArea.remove() |
|||
}).then(() => { |
|||
this.$nextTick(()=>{ |
|||
this.copyJsonInputHandle('success') |
|||
}) |
|||
},() => { |
|||
this.copyJsonInputHandle('error') |
|||
}) |
|||
} |
|||
|
|||
}, |
|||
// detail的table详情 |
|||
showDetailTableHandle(row){ |
|||
this.detailTableRow = row |
|||
this.detailTableColumns = [] |
|||
this.detailTableHeader.forEach(item=>{ |
|||
this.detailTableColumns.push({ |
|||
prop:item, |
|||
label:item |
|||
}) |
|||
}) |
|||
this.detailsTableShow = true |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
::v-deep .copyJsonTextarea{ |
|||
textarea{ |
|||
max-height: calc(100vh - 220px) !important; |
|||
overflow: auto !important; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,402 @@ |
|||
<template> |
|||
<div class="tablePagination"> |
|||
<!-- 头部按钮 --> |
|||
<div class="table-nav"> |
|||
<curren-Button |
|||
ref="tablePagination_topNav" |
|||
:Butttondata="currenButtonData" |
|||
@tableButtonClick="topbutton" |
|||
@quicklySearchClick="quicklySearchClick" |
|||
@quicklySearchClear="quicklySearchClear" |
|||
:quicklySearchOption="quicklySearchOption" |
|||
> |
|||
</curren-Button> |
|||
<slot name="tableTopSlot"></slot> |
|||
</div> |
|||
<!-- 全面搜索(普通+高级整合) --> |
|||
<searchOverall |
|||
ref="searchOverallRef" |
|||
:searchOverallCoverHeight="searchOverallCoverHeight" |
|||
:showSearchOverall="showSearchOverall" |
|||
@getShowSearchOverall="getShowSearchOverall" |
|||
:primarySearchOption="primarySearchOption" |
|||
:primarySearchButton="primarySearchButton" |
|||
:showMoreSearch="showMoreSearch" |
|||
:tableColumns="tableColumns" |
|||
@overallSearchFormClick="overallSearchFormClick" |
|||
:httpOverallSearchData="httpOverallSearchData" |
|||
> |
|||
<!-- 插槽预留 --> |
|||
<slot name="searchPrimarySlot"></slot> |
|||
</searchOverall> |
|||
<!-- 字段设置弹窗 --> |
|||
<rowDrop |
|||
@radio="rowDrop" |
|||
:tableColumns="tableColumns" |
|||
:visible="rowDropVisible" |
|||
@closeRowDrop="closeRowDrop" |
|||
:source="rowSource" |
|||
:innerMaxHeight="rowMaxHeight" |
|||
></rowDrop> |
|||
<!-- 列表 --> |
|||
<div class="uTableOuter" ref="uTableOuterRef" :style="{height:uTableOuterHeight + 'px',overflow:'hidden'}"> |
|||
<umyTable |
|||
ref="tablePaginationTableRef" |
|||
:isUpdate="isUpdate" |
|||
:tableLoading="tableLoading" |
|||
:tableData="tableData" |
|||
:tableColumns="tableColumns | isTableColumns" |
|||
:isShowIndex="isShowIndex" |
|||
:selectionTable="tableSelection" |
|||
:setUTableHeight="setUTableHeight || uTableTopHeight" |
|||
@sortChange="sortChange" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
@inlineDialog="inlineDialog" |
|||
:buttonOperationList_left="buttonOperationList_left" |
|||
@buttonOperationClick_left="buttonOperationClick_left" |
|||
:buttonOperationList_right="buttonOperationList_right" |
|||
@buttonOperationClick_right="buttonOperationClick_right" |
|||
:tableBorder="true" |
|||
:firstFixed="true" |
|||
:cellStyle = "cellStyle" |
|||
:showOverflowTooltip="showOverflowTooltip" |
|||
> |
|||
<template> |
|||
<slot></slot> |
|||
</template> |
|||
</umyTable> |
|||
</div> |
|||
<!-- 页码 --> |
|||
<pagination |
|||
:totalCount="totalCount" |
|||
:pagesizeProps="MaxResultCount" |
|||
:currentPageProps="currentPageProps" |
|||
@SizeChange="alterResultCount" |
|||
@CurrentChange="alertoldSkipCount" |
|||
></pagination> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenButton from "@/components/currenButton" |
|||
import pagination from "@/components/Pagination" |
|||
import searchOverall from "@/components/searchOverall" |
|||
import rowDrop from "@/components/rowDrop/index.vue" |
|||
import { getParentNode } from '@/utils' |
|||
export default { |
|||
name: 'tablePagination', |
|||
components: { |
|||
pagination, |
|||
currenButton, |
|||
searchOverall, |
|||
rowDrop |
|||
}, |
|||
props: { |
|||
rowMaxHeight:{ |
|||
type:String, |
|||
default:'calc(90vh - 280px)' |
|||
}, |
|||
// 筛选高度 |
|||
searchOverallCoverHeight:{ |
|||
type: String, |
|||
default: 'calc(100vh - 200px)' |
|||
}, |
|||
// 已app-main高度为100% 需要减掉的高度 |
|||
setUTableHeight: { |
|||
type: Number, |
|||
default: null |
|||
}, |
|||
// 超出内容是否提示 |
|||
showOverflowTooltip:{ |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
// 显示搜索配置 |
|||
quicklySearchOption:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 表格上方头部按钮配置 |
|||
currenButtonData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 操作列按钮(左侧) |
|||
buttonOperationList_left:{ |
|||
type: Array, |
|||
default: null, |
|||
}, |
|||
// 操作列按钮(右侧) |
|||
buttonOperationList_right:{ |
|||
type: Function, |
|||
default: null, |
|||
}, |
|||
// 列表数据 |
|||
tableData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 列表列配置 + 高级筛选配置 |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 复选框 |
|||
tableSelection: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// table页码总数 |
|||
totalCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
// table组件上的loading |
|||
tableLoading: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 页码每页显示数 |
|||
MaxResultCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
// 页码当前页配置 |
|||
currentPageProps: { |
|||
type: Number, |
|||
default: 1 |
|||
}, |
|||
// 是否显示序号 |
|||
isShowIndex: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
// 选择当前行数据 |
|||
multipleSelection: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 以下为全面筛选组件配置 |
|||
//初级筛选绑定表单配置 |
|||
primarySearchOption: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//初级筛选表单自定义按钮 |
|||
primarySearchButton: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 是否显示高级筛选 |
|||
showMoreSearch:{ |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
// 当前接口中的筛选数据(用于同步全面筛选的数据) |
|||
httpOverallSearchData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
cellStyle: { |
|||
type: Function, |
|||
default: () => { |
|||
return Function; |
|||
} |
|||
}, |
|||
// 字段设置来源(列表、列表-明细、明细页面) |
|||
rowSource:{ |
|||
type:String, |
|||
default:'list_api' |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
// 字段设置是否显示 |
|||
rowDropVisible: false, |
|||
// table 重新渲染所需key |
|||
isUpdate: false, |
|||
// 除去table的高度 |
|||
uTableTopHeight:165, |
|||
// table外部高度控制,用于点击筛选动画处理 |
|||
uTableOuterHeight:null, |
|||
// table外部最初始化高度,用于点击筛选动画处理 |
|||
uTableOuterHeight_init:null, |
|||
//table操作按钮 |
|||
Butttondata: [ |
|||
{ |
|||
type: 'danger', |
|||
icon: 'el-icon-delete', |
|||
label: '批量删除', |
|||
size: 'mini' |
|||
}, |
|||
{ |
|||
type: 'warning', |
|||
icon: 'el-icon-edit', |
|||
label: '批量修改状态', |
|||
size: 'mini' |
|||
}, |
|||
{ |
|||
type: 'success', |
|||
icon: 'el-icon-upload2', |
|||
label: '批量导出', |
|||
size: 'mini' |
|||
}, |
|||
{ |
|||
type: 'info', |
|||
icon: 'el-icon-printer', |
|||
label: '批量打印', |
|||
size: 'mini' |
|||
}, |
|||
], |
|||
// 全面筛选组件配置 |
|||
// 显示全面筛选组件 |
|||
showSearchOverall:false, |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.uTableOuterHeight = this.$refs.tablePaginationTableRef.getTableHeight() |
|||
this.uTableOuterHeight_init = Number(JSON.stringify(this.uTableOuterHeight)) |
|||
|
|||
// 点击外部,字段设置弹窗隐藏 |
|||
document.addEventListener('click',(e)=>{ |
|||
if(!this.rowDropVisible)return |
|||
let _class = "rowDropNotHideItem" |
|||
let _hasParent = getParentNode(e.target,_class) |
|||
let _current_class = e.target._prevClass || e.target.className |
|||
let _hasCurrent = _current_class ? String(_current_class).includes(_class) : false |
|||
if(!_hasParent && !_hasCurrent){ |
|||
this.closeRowDrop() |
|||
} |
|||
}) |
|||
}, |
|||
methods: { |
|||
rowDrop(data,type) { |
|||
this.$emit('rowDrop',data,type) |
|||
this.$nextTick(()=>{ |
|||
this.isUpdate = !this.isUpdate |
|||
}) |
|||
}, |
|||
//点击常用按钮 |
|||
topbutton (val,item) { |
|||
// 筛选按钮 + table高度变化 + 动画效果(勿动顺序) |
|||
if(val=="filter"){ |
|||
this.showSearchOverall = !this.showSearchOverall |
|||
// 有普通查询配置 |
|||
if(this.primarySearchOption && this.primarySearchOption.length > 0){ |
|||
this.$nextTick(()=>{ |
|||
let _search_height = this.$refs.searchOverallRef.getSearchPrimaryHeight() |
|||
if(this.showSearchOverall){ |
|||
let _margin = 20 |
|||
this.uTableOuterHeight = this.uTableOuterHeight_init - _search_height - _margin |
|||
setTimeout(()=>{ |
|||
this.uTableTopHeight += _search_height + _margin |
|||
},0) |
|||
}else{ |
|||
this.uTableOuterHeight = this.uTableOuterHeight_init |
|||
setTimeout(()=>{ |
|||
this.uTableTopHeight = 165 |
|||
},0) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
// 字段设置 |
|||
else if (val == 'field') { |
|||
this.rowDropVisible = !this.rowDropVisible |
|||
} |
|||
this.$emit("topbutton", val,item) |
|||
}, |
|||
// 快速搜索 - 搜索按钮 |
|||
quicklySearchClick (val,option) { |
|||
this.$emit("quicklySearchClick", val,option,this.$refs.searchOverallRef) |
|||
}, |
|||
// 快速搜索 - 清除搜索 |
|||
quicklySearchClear (val,option) { |
|||
// 判断是否有筛选按钮 |
|||
let hasSearch = false |
|||
this.currenButtonData.forEach(item=>{ |
|||
if(item.name == 'filter'){ |
|||
hasSearch = true |
|||
return |
|||
} |
|||
}) |
|||
this.$emit("quicklySearchClear", val,option,this.$refs.searchOverallRef,hasSearch ) |
|||
}, |
|||
//接收分页组件emit改变每页最大页数 |
|||
alterResultCount (val) { |
|||
this.$emit('alterResultCount', val) |
|||
}, |
|||
//接收分页组件emit改变当前页 |
|||
alertoldSkipCount (val) { |
|||
this.$emit('alertoldSkipCount', val) |
|||
}, |
|||
//点击name提交emit打开编辑页面 |
|||
inlineDialog (row) { |
|||
this.$emit("inlineDialog", row) |
|||
}, |
|||
//点击selection框 |
|||
handleSelectionChange (val) { |
|||
this.$emit("handleSelectionChange", val) |
|||
}, |
|||
//排序 |
|||
sortChange (data) { |
|||
this.$emit('sortChange', data) |
|||
}, |
|||
//点击table操作列(左侧)按钮 |
|||
buttonOperationClick_left(row, item, index) { |
|||
this.$emit("buttonOperationClick_left", row, item, index); |
|||
}, |
|||
//点击table操作列(右侧)按钮 |
|||
buttonOperationClick_right(row, item, index) { |
|||
this.$emit("buttonOperationClick_right", row, item, index); |
|||
}, |
|||
// 全面筛选组件配置 |
|||
// 全面筛选组件内部显示/隐藏更改触发,同步当前的showSearchOverall值 |
|||
getShowSearchOverall(val){ |
|||
this.showSearchOverall = val || false |
|||
}, |
|||
// 全面筛选组件所有按钮事件 |
|||
overallSearchFormClick(options){ |
|||
//增加快速搜索实体 |
|||
options.vm_quickly = this.$refs.tablePagination_topNav.getQuicklySearchDom() |
|||
this.$emit("overallSearchFormClick", options) |
|||
}, |
|||
// 关闭字段设置 |
|||
closeRowDrop() { |
|||
this.rowDropVisible = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.uTableOuter{ |
|||
transition:all 0.5s; |
|||
overflow: hidden; |
|||
} |
|||
.tablePagination { |
|||
width: 100%; |
|||
height: 100%; |
|||
background-color: #fff; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.table-nav { |
|||
padding-bottom: 15px; |
|||
} |
|||
|
|||
.el-table { |
|||
flex: 1; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,464 @@ |
|||
<template> |
|||
<div class="tablePagination"> |
|||
<!-- 头部按钮 --> |
|||
<div class="table-nav"> |
|||
<curren-Button |
|||
v-if="headerButttondata" |
|||
ref="tablePagination_topNav" |
|||
:Butttondata="headerButttondata" |
|||
@tableButtonClick="topbutton" |
|||
@quicklySearchClick="quicklySearchClick" |
|||
@quicklySearchClear="quicklySearchClear" |
|||
:quicklySearchOption="quicklySearchOption" |
|||
> |
|||
</curren-Button> |
|||
<slot name="tableTopSlot"></slot> |
|||
</div> |
|||
<!-- 全面搜索(普通+高级整合) --> |
|||
<searchOverall |
|||
ref="searchOverallRef" |
|||
:searchOverallCoverHeight="searchOverallCoverHeight" |
|||
:showSearchOverall="showSearchOverall" |
|||
@getShowSearchOverall="getShowSearchOverall" |
|||
:primarySearchOption="primarySearchOption" |
|||
:primarySearchButton="primarySearchButton" |
|||
:showMoreSearch="showMoreSearch" |
|||
:tableColumns="tableColumns" |
|||
@overallSearchFormClick="overallSearchFormClick" |
|||
:httpOverallSearchData="httpOverallSearchData" |
|||
:selectMaxHeight="selectMaxHeight" |
|||
> |
|||
<!-- 插槽预留 --> |
|||
<slot name="searchPrimarySlot"></slot> |
|||
</searchOverall> |
|||
<!-- 字段设置弹窗 --> |
|||
<rowDrop |
|||
@radio="rowDrop" |
|||
:tableColumns="tableColumns" |
|||
:visible="rowDropVisible" |
|||
@closeRowDrop="closeRowDrop" |
|||
:source="rowSource" |
|||
:innerMaxHeight="rowMaxHeight" |
|||
></rowDrop> |
|||
<!-- 列表 --> |
|||
<div class="uTableOuter" ref="uTableOuterRef" :style="{height:uTableOuterHeight + 'px',overflow:'hidden'}"> |
|||
<umyTable |
|||
ref="tablePaginationTableRef" |
|||
:isUpdate="isUpdate" |
|||
:tableLoading="tableLoading" |
|||
:tableData="tableData" |
|||
:tableColumns="tableColumns | isTableColumns" |
|||
:isShowIndex="isShowIndex" |
|||
:selectionTable="tableSelection" |
|||
:setUTableHeight="uTableTopHeight" |
|||
@sortChange="sortChange" |
|||
@handleSelectionChange="handleSelectionChange" |
|||
@inlineDialog="inlineDialog" |
|||
:buttonOperationList_left="buttonOperationList_left" |
|||
@buttonOperationClick_left="buttonOperationClick_left" |
|||
:buttonOperationList_right="buttonOperationList_right" |
|||
@buttonOperationClick_right="buttonOperationClick_right" |
|||
:tableBorder="true" |
|||
:firstFixed="true" |
|||
:cellStyle = "cellStyle" |
|||
:showOverflowTooltip="showOverflowTooltip" |
|||
> |
|||
<template> |
|||
<slot></slot> |
|||
</template> |
|||
</umyTable> |
|||
</div> |
|||
<!-- 页码 --> |
|||
<pagination |
|||
:totalCount="totalCount" |
|||
:pagesizeProps="MaxResultCount" |
|||
:currentPageProps="currentPageProps" |
|||
@SizeChange="alterResultCount" |
|||
@CurrentChange="alertoldSkipCount" |
|||
></pagination> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import currenButton from "@/components/currenButton" |
|||
import pagination from "@/components/Pagination" |
|||
import searchOverall from "@/components/searchOverall" |
|||
import rowDrop from "@/components/rowDrop/index.vue" |
|||
import { getParentNode } from '@/utils' |
|||
export default { |
|||
name: 'tablePagination', |
|||
components: { |
|||
pagination, |
|||
currenButton, |
|||
searchOverall, |
|||
rowDrop |
|||
}, |
|||
props: { |
|||
// 不使用权限的按钮 |
|||
noUsePermissionBtn:{ |
|||
type: Array, |
|||
default: () => { |
|||
return ['refresh','field','filterForDetail','export','filter']//刷新,字段设置,明细查询,导出,筛选 |
|||
} |
|||
}, |
|||
rowMaxHeight:{ |
|||
type:String, |
|||
default:'calc(90vh - 280px)' |
|||
}, |
|||
// 筛选条件最大高度 |
|||
selectMaxHeight:{ |
|||
type: String, |
|||
default: '174px' |
|||
}, |
|||
// 筛选高度 |
|||
searchOverallCoverHeight:{ |
|||
type: String, |
|||
default: 'calc(100vh - 200px)' |
|||
}, |
|||
// 已app-main高度为100% 需要减掉的高度 |
|||
setUTableHeight: { |
|||
type: Number, |
|||
default: null |
|||
}, |
|||
// 超出内容是否提示 |
|||
showOverflowTooltip:{ |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
// 显示搜索配置 |
|||
quicklySearchOption:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 表格上方头部按钮配置 |
|||
currenButtonData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 操作列按钮(左侧) |
|||
buttonOperationList_left:{ |
|||
type: Array, |
|||
default: null, |
|||
}, |
|||
// 操作列按钮(右侧) |
|||
buttonOperationList_right:{ |
|||
type: Function, |
|||
default: null, |
|||
}, |
|||
// 列表数据 |
|||
tableData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 列表列配置 + 高级筛选配置 |
|||
tableColumns: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 复选框 |
|||
tableSelection: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
// table页码总数 |
|||
totalCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
// table组件上的loading |
|||
tableLoading: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 页码每页显示数 |
|||
MaxResultCount: { |
|||
type: Number, |
|||
default: 0 |
|||
}, |
|||
// 页码当前页配置 |
|||
currentPageProps: { |
|||
type: Number, |
|||
default: 1 |
|||
}, |
|||
// 是否显示序号 |
|||
isShowIndex: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
// 选择当前行数据 |
|||
multipleSelection: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 以下为全面筛选组件配置 |
|||
//初级筛选绑定表单配置 |
|||
primarySearchOption: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
//初级筛选表单自定义按钮 |
|||
primarySearchButton: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 是否显示高级筛选 |
|||
showMoreSearch:{ |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
// 当前接口中的筛选数据(用于同步全面筛选的数据) |
|||
httpOverallSearchData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
cellStyle: { |
|||
type: Function, |
|||
default: () => { |
|||
return Function; |
|||
} |
|||
}, |
|||
// 字段设置来源(列表、列表-明细、明细页面) |
|||
rowSource:{ |
|||
type:String, |
|||
default:'list_api' |
|||
} |
|||
}, |
|||
data () { |
|||
return { |
|||
headerButttondata:null, |
|||
// 字段设置是否显示 |
|||
rowDropVisible: false, |
|||
// table 重新渲染所需key |
|||
isUpdate: false, |
|||
appRemoveHeight:165, |
|||
// 除去table的高度 |
|||
uTableTopHeight:165, |
|||
// table外部高度控制,用于点击筛选动画处理 |
|||
uTableOuterHeight:null, |
|||
// table外部最初始化高度,用于点击筛选动画处理 |
|||
uTableOuterHeight_init:null, |
|||
//table操作按钮 |
|||
Butttondata: [ |
|||
{ |
|||
type: 'danger', |
|||
icon: 'el-icon-delete', |
|||
label: '批量删除', |
|||
size: 'mini' |
|||
}, |
|||
{ |
|||
type: 'warning', |
|||
icon: 'el-icon-edit', |
|||
label: '批量修改状态', |
|||
size: 'mini' |
|||
}, |
|||
{ |
|||
type: 'success', |
|||
icon: 'el-icon-upload2', |
|||
label: '批量导出', |
|||
size: 'mini' |
|||
}, |
|||
{ |
|||
type: 'info', |
|||
icon: 'el-icon-printer', |
|||
label: '批量打印', |
|||
size: 'mini' |
|||
}, |
|||
], |
|||
// 全面筛选组件配置 |
|||
// 显示全面筛选组件 |
|||
showSearchOverall:false, |
|||
} |
|||
}, |
|||
mounted(){ |
|||
this.appRemoveHeight = this.setUTableHeight || 165 |
|||
this.uTableTopHeight = this.appRemoveHeight |
|||
this.uTableOuterHeight = this.$refs.tablePaginationTableRef.getTableHeight() |
|||
this.uTableOuterHeight_init = Number(JSON.stringify(this.uTableOuterHeight)) |
|||
this.initButttondata() |
|||
|
|||
// 点击外部,字段设置弹窗隐藏 |
|||
document.addEventListener('click',(e)=>{ |
|||
if(!this.rowDropVisible)return |
|||
let _class = "rowDropNotHideItem" |
|||
let _hasParent = getParentNode(e.target,_class) |
|||
let _current_class = e.target._prevClass || e.target.className |
|||
let _hasCurrent = _current_class ? String(_current_class).includes(_class) : false |
|||
if(!_hasParent && !_hasCurrent){ |
|||
this.closeRowDrop() |
|||
} |
|||
}) |
|||
}, |
|||
methods: { |
|||
initButttondata(){ |
|||
let _list = [] |
|||
this.currenButtonData.forEach(item=>{ |
|||
if(item.permission){ |
|||
_list.push(item) |
|||
}else{ |
|||
if(this.noUsePermissionBtn.indexOf(item.name) < 0){ |
|||
let _scope = item.clientScope || localStorage.getItem('appClientScope') |
|||
item.permission = [_scope + '.' +this.$route.name+'.'+(item.permissionName || item.name)] |
|||
}else{ |
|||
item.permission = [] |
|||
} |
|||
_list.push(item) |
|||
} |
|||
}) |
|||
this.headerButttondata = _list |
|||
}, |
|||
// 重新渲染表格 |
|||
doFreshTableLayout(){ |
|||
if(this.$refs.tablePaginationTableRef && this.$refs.tablePaginationTableRef.doFreshLayout){ |
|||
this.$refs.tablePaginationTableRef.doFreshLayout() |
|||
} |
|||
}, |
|||
rowDrop(data,type) { |
|||
this.$emit('rowDrop',data,type) |
|||
this.$nextTick(()=>{ |
|||
this.isUpdate = !this.isUpdate |
|||
}) |
|||
}, |
|||
//点击常用按钮 |
|||
topbutton (val,item) { |
|||
// 筛选按钮 + table高度变化 + 动画效果(勿动顺序) |
|||
if(val=="filter"){ |
|||
this.showSearchOverall = !this.showSearchOverall |
|||
// 有普通查询配置 |
|||
if(this.primarySearchOption && this.primarySearchOption.length > 0){ |
|||
this.$nextTick(()=>{ |
|||
let _search_height = this.$refs.searchOverallRef.getSearchPrimaryHeight() |
|||
this.changeTableHeight(_search_height) |
|||
// if(this.showSearchOverall){ |
|||
// let _margin = 20 |
|||
// this.uTableOuterHeight = this.uTableOuterHeight_init - _search_height - _margin |
|||
// setTimeout(()=>{ |
|||
// this.uTableTopHeight += _search_height + _margin |
|||
// },0) |
|||
// }else{ |
|||
// this.uTableOuterHeight = this.uTableOuterHeight_init |
|||
// setTimeout(()=>{ |
|||
// this.uTableTopHeight = 165 |
|||
// },0) |
|||
// } |
|||
}) |
|||
} |
|||
this.$nextTick(()=>{ |
|||
let _search_height = this.$refs.searchOverallRef.getAllSearchInnerHeight() |
|||
this.changeTableHeight(_search_height) |
|||
}) |
|||
} |
|||
// 字段设置 |
|||
else if (val == 'field') { |
|||
this.rowDropVisible = !this.rowDropVisible |
|||
} |
|||
this.$emit("topbutton", val,item) |
|||
}, |
|||
// 更改筛选时候的table高度问题 |
|||
changeTableHeight(minusHeight=0){ |
|||
if(this.showSearchOverall){ |
|||
let _margin = 20 |
|||
this.uTableOuterHeight = this.uTableOuterHeight_init - minusHeight - _margin |
|||
setTimeout(()=>{ |
|||
this.uTableTopHeight = minusHeight + this.appRemoveHeight + _margin |
|||
},0) |
|||
}else{ |
|||
this.uTableOuterHeight = this.uTableOuterHeight_init |
|||
setTimeout(()=>{ |
|||
this.uTableTopHeight = this.appRemoveHeight |
|||
},0) |
|||
} |
|||
}, |
|||
// 快速搜索 - 搜索按钮 |
|||
quicklySearchClick (val,option) { |
|||
this.$emit("quicklySearchClick", val,option,this.$refs.searchOverallRef) |
|||
}, |
|||
// 快速搜索 - 清除搜索 |
|||
quicklySearchClear (val,option) { |
|||
// 判断是否有筛选按钮 |
|||
let hasSearch = false |
|||
this.currenButtonData.forEach(item=>{ |
|||
if(item.name == 'filter'){ |
|||
hasSearch = true |
|||
return |
|||
} |
|||
}) |
|||
this.$emit("quicklySearchClear", val,option,this.$refs.searchOverallRef,hasSearch ) |
|||
}, |
|||
//接收分页组件emit改变每页最大页数 |
|||
alterResultCount (val) { |
|||
this.$emit('alterResultCount', val) |
|||
}, |
|||
//接收分页组件emit改变当前页 |
|||
alertoldSkipCount (val) { |
|||
this.$emit('alertoldSkipCount', val) |
|||
}, |
|||
//点击name提交emit打开编辑页面 |
|||
inlineDialog (row) { |
|||
this.$emit("inlineDialog", row) |
|||
}, |
|||
//点击selection框 |
|||
handleSelectionChange (val) { |
|||
this.$emit("handleSelectionChange", val) |
|||
}, |
|||
//排序 |
|||
sortChange (data) { |
|||
this.$emit('sortChange', data) |
|||
}, |
|||
//点击table操作列(左侧)按钮 |
|||
buttonOperationClick_left(row, item, index) { |
|||
this.$emit("buttonOperationClick_left", row, item, index); |
|||
}, |
|||
//点击table操作列(右侧)按钮 |
|||
buttonOperationClick_right(row, item, index) { |
|||
this.$emit("buttonOperationClick_right", row, item, index); |
|||
}, |
|||
// 全面筛选组件配置 |
|||
// 全面筛选组件内部显示/隐藏更改触发,同步当前的showSearchOverall值 |
|||
getShowSearchOverall(val){ |
|||
this.showSearchOverall = val || false |
|||
}, |
|||
// 全面筛选组件所有按钮事件 |
|||
overallSearchFormClick(options){ |
|||
//增加快速搜索实体 |
|||
if(this.$refs.tablePagination_topNav)options.vm_quickly = this.$refs.tablePagination_topNav.getQuicklySearchDom() |
|||
this.$emit("overallSearchFormClick", options) |
|||
}, |
|||
// 关闭字段设置 |
|||
closeRowDrop() { |
|||
this.rowDropVisible = false |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
.uTableOuter{ |
|||
transition:all 0.5s; |
|||
overflow: hidden; |
|||
} |
|||
.tablePagination { |
|||
width: 100%; |
|||
height: 100%; |
|||
background-color: #fff; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.table-nav { |
|||
padding-bottom: 15px; |
|||
} |
|||
|
|||
.el-table { |
|||
flex: 1; |
|||
} |
|||
} |
|||
</style> |
@ -0,0 +1,542 @@ |
|||
<template> |
|||
<div class="tableTreeComponents"> |
|||
<div class="table-tree-search" v-if="showQueryHeader"> |
|||
<div class="bttton-box"> |
|||
<!-- 左侧按钮 --> |
|||
<el-button |
|||
v-for="(item,index) in leftButtons" |
|||
v-show="queryHeaderBtn.indexOf(item.name) >= 0" |
|||
:key="index" |
|||
:type="item.type" |
|||
:icon="item.icon" |
|||
:size="item.size" |
|||
@click="headerButtonsHandle(item)" |
|||
v-permission="item.permission || []" |
|||
>{{item.label}}</el-button> |
|||
</div> |
|||
<div class="query-box"> |
|||
<!-- 搜索 --> |
|||
<searchNormal |
|||
v-if="queryHeaderBtn.indexOf('search') >= 0" |
|||
ref="searchNormalRef" |
|||
@searchNormalClick="headerButtonsHandle({name:'search'})" |
|||
@searchNormalClear="headerButtonsHandle({name:'reset'})" |
|||
></searchNormal> |
|||
<!-- 右侧其他按钮 --> |
|||
<el-button |
|||
v-for="(item,index) in rightButtons" |
|||
v-show="queryHeaderBtn.indexOf(item.name) >= 0 && item.name != 'search'" |
|||
:key="index" |
|||
:type="item.type" |
|||
:icon="item.icon" |
|||
:size="item.size" |
|||
@click="headerButtonsHandle(item)" |
|||
v-permission="item.permission || []" |
|||
>{{item.label}}</el-button> |
|||
</div> |
|||
</div> |
|||
<el-table |
|||
ref="treeTableRef" |
|||
:data="tableData" |
|||
:row-key="rowkey" |
|||
style="width: 100%" |
|||
height="calc(100%)" |
|||
border |
|||
> |
|||
<el-table-column |
|||
v-for="(item,index) in treeColumn" |
|||
:key="index" |
|||
:label="item.label" |
|||
:width="item.width" |
|||
:align="item.align || 'left'" |
|||
:header-align="item.headerAlign || 'left'" |
|||
:show-overflow-tooltip="!item.hideTooltip" |
|||
:fixed="item.fixed" |
|||
> |
|||
<template slot-scope="scope"> |
|||
<span v-if="!item.filters">{{scope.row[item.prop]}}</span> |
|||
<span v-else>{{item.filters[scope.row[item.prop]]}}</span> |
|||
</template> |
|||
</el-table-column> |
|||
<el-table-column |
|||
label="操作" |
|||
header-align="center" |
|||
:align="treeAlign" |
|||
:width="handleBtnsWidth || Number(btnsData.length) * 55" |
|||
fixed="right" |
|||
> |
|||
<template slot-scope="scope"> |
|||
<el-button |
|||
v-for="(item,index) in btnsData" |
|||
:key="index" |
|||
:type="item.type" |
|||
:size="item.size" |
|||
@click="btnHandle(item,scope.row)" |
|||
:style="item.style" |
|||
v-show="typeof item.hide == 'function' ? !item.hide(scope.row) : !item.hide" |
|||
:icon="item.icon" |
|||
v-permission="item.permission || []" |
|||
>{{item.label}}</el-button> |
|||
</template> |
|||
</el-table-column> |
|||
</el-table> |
|||
|
|||
<!-- 新增/编辑弹窗 --> |
|||
<el-dialog |
|||
:title="treeEditTitle" |
|||
:visible.sync="treeEditDialog" |
|||
width="600px" |
|||
:close-on-click-modal="false" |
|||
> |
|||
<curren-Form |
|||
v-if="treeEditDialog" |
|||
v-loading="dialogLoading" |
|||
size="medium" |
|||
ref="treeEditDialogRef" |
|||
:searchData="treeEditFormData" |
|||
:searchForm="treeEditForm" |
|||
:rules="treeEditRules" |
|||
:searchHandle="treeEditHandle" |
|||
@push="DataPush(arguments)" |
|||
@submitForm="treeEditFormClick(arguments)" |
|||
></curren-Form> |
|||
<!-- @changeInput="changeInput" |
|||
@radioChange="radioChange" --> |
|||
<!-- :searchOptions="treeEditOptions" --> |
|||
</el-dialog> |
|||
</div> |
|||
</template> |
|||
<script> |
|||
import permission from "@/utils/permission/index"; |
|||
import { treeDefalutButton,formatDefalutConfig,queryDefalutButtons } from "@/utils/tableTree" |
|||
import searchNormal from "@/components/searchNormal/index.vue" |
|||
export default { |
|||
name: 'tableTreeComponents', |
|||
directives: { permission }, |
|||
components:{ |
|||
searchNormal |
|||
}, |
|||
watch:{ |
|||
treeData(n,o){ |
|||
if(n){ |
|||
this.init() |
|||
} |
|||
}, |
|||
treeEditData:{ |
|||
handler(n,o){ |
|||
this.treeEditFormData = n |
|||
}, |
|||
deep:true |
|||
} |
|||
}, |
|||
props: { |
|||
// 是否显示Query头部 |
|||
showQueryHeader:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
// 查询参数 |
|||
searchParam:{ |
|||
type: Object, |
|||
default: ()=>{ |
|||
return {name:'name',label:'菜单名称'} |
|||
} |
|||
}, |
|||
// Query头部显示按钮 |
|||
queryHeaderBtn:{ |
|||
type: Array, |
|||
default: () => { |
|||
return ['addFirst','fresh','search'] |
|||
} |
|||
}, |
|||
// 搜索栏左侧按钮(默认【创建一级菜单】、【刷新】) |
|||
queryLeftButtons: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
// 头部创建一级菜单按钮显示名称 |
|||
headerAddName:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 搜索栏左侧按钮(默认【搜索框】、【搜索】、【重置】) |
|||
queryRightButtons: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
// 搜索栏按钮操作 |
|||
queryButtonsHandle:Function, |
|||
|
|||
// 刷新table数据 |
|||
rowkey:{ |
|||
type: String, |
|||
default: 'id' |
|||
}, |
|||
// 操作栏宽度 |
|||
handleBtnsWidth:{ |
|||
type: String, |
|||
default: null |
|||
}, |
|||
// 默认展开类型 all:全部 first:第一层 |
|||
expandedType:{ |
|||
type:String, |
|||
default:null |
|||
}, |
|||
// tree数据 |
|||
treeData: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// tree配置 |
|||
treeColumn: { |
|||
type: Array, |
|||
default: () => { |
|||
return [] |
|||
} |
|||
}, |
|||
// 是否需要格式化数据 |
|||
needFormatData:{ |
|||
type: Boolean, |
|||
default:false |
|||
}, |
|||
// 格式化数据配置 |
|||
formatDataConfig:{ |
|||
type: Object, |
|||
default: () => { |
|||
return formatDefalutConfig() |
|||
} |
|||
}, |
|||
// table操作按钮 |
|||
treeButtons: { |
|||
type: Array, |
|||
default: null |
|||
}, |
|||
// table操作居中 |
|||
treeAlign:{ |
|||
type: String, |
|||
default: 'right' |
|||
}, |
|||
// 新增/操作数据 |
|||
treeEditData:{ |
|||
type: Object, |
|||
default: null |
|||
}, |
|||
// 新增/编辑显示 |
|||
treeEditForm:{ |
|||
type: Array, |
|||
default: ()=>{ |
|||
return [] |
|||
} |
|||
}, |
|||
// 新增/编辑Rules |
|||
treeEditRules:{ |
|||
type: Object, |
|||
default: ()=>{ |
|||
return {} |
|||
} |
|||
}, |
|||
// 新增/编辑Rules |
|||
treeEditHandle:{ |
|||
type: Array, |
|||
default: ()=>{ |
|||
return [ |
|||
{ label: "取消", name: "cancel" }, |
|||
{ label: "确认", name: "sure", type:"primary" }, |
|||
] |
|||
} |
|||
}, |
|||
// 点击编辑前 |
|||
treeEditBefore:Function, |
|||
// 取消提交前 |
|||
treeEditCancle:Function, |
|||
// 提交事件 |
|||
treeEditSubmit:Function, |
|||
// 删除事件 |
|||
treeEditDelete:Function, |
|||
}, |
|||
data () { |
|||
return { |
|||
leftButtons:[],//左侧按钮 |
|||
rightButtons:[],//右侧按钮 |
|||
|
|||
tableData: [],//table渲染 |
|||
tableDataCopy: [],//用于查询存储所有数据 |
|||
btnsData:[],//table中的按钮 |
|||
|
|||
treeEditDialog:false,//新增编辑弹窗显示 |
|||
dialogLoading:false,//编辑弹窗加载 |
|||
treeEditTitle:"",//新增编辑弹窗title |
|||
isEdit:false,//false:编辑 true:新建 |
|||
treeEditFormData:[],//编辑弹窗内数据 |
|||
} |
|||
}, |
|||
activated(){ |
|||
// 解决切换导航后,页面table窜行问题 |
|||
this.$refs.treeTableRef.doLayout(); |
|||
}, |
|||
created(){ |
|||
this.init() |
|||
}, |
|||
methods: { |
|||
init(){ |
|||
// 头部左侧的按钮 |
|||
if(this.queryLeftButtons){ |
|||
this.leftButtons = this.queryLeftButtons |
|||
}else{ |
|||
this.leftButtons = [ |
|||
...queryDefalutButtons("left",this.headerAddName) |
|||
] |
|||
} |
|||
// 头部右侧的按钮 |
|||
if(this.queryRightButtons){ |
|||
this.rightButtons = this.queryRightButtons |
|||
}else{ |
|||
this.rightButtons = [ |
|||
...queryDefalutButtons("right") |
|||
] |
|||
} |
|||
|
|||
// 数据 |
|||
if(this.treeData){ |
|||
if(!this.needFormatData){ |
|||
this.tableData = this.treeData |
|||
}else{ |
|||
let _tree = this.initTreeData(this.treeData).sort(this.sortData(this.formatDataConfig.sort)) |
|||
this.tableData = _tree |
|||
} |
|||
this.tableDataCopy = JSON.parse(JSON.stringify(this.tableData)) |
|||
// 展开情况 |
|||
this.$nextTick(()=>{ |
|||
this.initTreeExpanded() |
|||
}) |
|||
} |
|||
// table中的按钮 |
|||
if(this.treeButtons){ |
|||
this.btnsData = this.treeButtons |
|||
}else{ |
|||
this.btnsData = [ |
|||
...treeDefalutButton() |
|||
] |
|||
} |
|||
|
|||
// 新增/编辑数据 |
|||
this.treeEditFormData = this.treeEditData |
|||
}, |
|||
// 展开情况处理 |
|||
initTreeExpanded(type){ |
|||
let _type = type || this.expandedType |
|||
let _this = this |
|||
function __changHandle(exp){ |
|||
_this.tableData.forEach(item=>{ |
|||
item.children.forEach(item_c=>{ |
|||
_this.$refs.treeTableRef.toggleRowExpansion(item_c,Boolean(exp)); |
|||
}) |
|||
_this.$refs.treeTableRef.toggleRowExpansion(item,Boolean(exp)); |
|||
}) |
|||
} |
|||
if(!_type){ |
|||
__changHandle(false) |
|||
} |
|||
else if(_type == "all"){ |
|||
__changHandle(true) |
|||
} |
|||
else if(_type == "first"){ |
|||
this.tableData.forEach((item,key)=>{ |
|||
let _exp = key == 0 ? true : false |
|||
item.children.forEach(item_c=>{ |
|||
this.$refs.treeTableRef.toggleRowExpansion(item_c,_exp); |
|||
}) |
|||
this.$refs.treeTableRef.toggleRowExpansion(item,_exp); |
|||
}) |
|||
} |
|||
}, |
|||
// 刷新新增/查询显示配置,如何时更改disabled属性等 |
|||
freshTreeEditForm(item,row){ |
|||
this.$emit("freshTreeEditForm",item,row); |
|||
}, |
|||
// 树状图格式化数据 |
|||
initTreeData(list,code = ""){ |
|||
const children = [] |
|||
// 对于list,每个元素.如果他的parentCode==code,他就是当前的children |
|||
list.forEach(item => { |
|||
if (item[this.formatDataConfig.parentCode] == code) { |
|||
children.push(item) |
|||
//排序 |
|||
item.children=this.initTreeData(list,item[this.formatDataConfig.code]).sort(this.sortData(this.formatDataConfig.sort)) |
|||
} |
|||
}) |
|||
return children |
|||
}, |
|||
// table排序 |
|||
/** |
|||
* sort 按照排序字段(现在为数字) 默认sort |
|||
*/ |
|||
sortData(sort){ |
|||
return function(a,b){ |
|||
const val1 = a[sort]; |
|||
const val2 = b[sort]; |
|||
return val1 - val2; |
|||
} |
|||
}, |
|||
// 头部创建一级菜单 |
|||
createFirstTreeHandle(item) { |
|||
this.treeEditDialog = true |
|||
this.treeEditTitle = item.label |
|||
this.isEdit = false; |
|||
this.freshTreeEditForm(item) |
|||
}, |
|||
// 获取search的值 |
|||
getSearchValue(){ |
|||
return this.$refs.searchNormalRef.getSearchNormalValue() |
|||
}, |
|||
// 清除search的值 |
|||
clearSearchValue(){ |
|||
this.$refs.searchNormalRef.searchNormalClear(true) |
|||
}, |
|||
//头部刷新 |
|||
createView(){ |
|||
this.resetView() |
|||
this.$emit("freshTreeData",this.getSearchValue()); |
|||
}, |
|||
// 头部搜索 |
|||
querySearchHandle(data){ |
|||
this.tableData=[]; |
|||
let newarr = []; |
|||
let _data = data || this.tableDataCopy; |
|||
_data.forEach(element => { |
|||
if (String(element[this.searchParam.name]).indexOf(this.getSearchValue()) >= 0) { |
|||
newarr.push(element); |
|||
} |
|||
else { |
|||
if (element.children && element.children.length > 0) { |
|||
const newObj = this.querySearchHandle(element.children); |
|||
const obj = { |
|||
...element, |
|||
children: newObj |
|||
}; |
|||
if (newObj && newObj.length > 0) { |
|||
newarr.push(obj); |
|||
} |
|||
} |
|||
} |
|||
}); |
|||
this.tableData=newarr; |
|||
return newarr |
|||
}, |
|||
//头部重置 |
|||
resetView(){ |
|||
this.clearSearchValue() |
|||
this.querySearchHandle() |
|||
this.initTreeExpanded(null) |
|||
}, |
|||
// table中操作按钮 |
|||
btnHandle(item,row){ |
|||
// 创建子菜单 |
|||
if(item.name == "add"){ |
|||
this.treeEditDialog = true |
|||
this.treeEditTitle = item.label |
|||
this.isEdit = false; |
|||
this.freshTreeEditForm(item,row) |
|||
} |
|||
// 编辑 |
|||
if(item.name == "edit"){ |
|||
this.freshTreeEditForm(item,row) |
|||
this.treeEditDialog = true |
|||
this.treeEditTitle = item.label |
|||
this.isEdit = true; |
|||
if(this.treeEditBefore){ |
|||
this.dialogLoading = true |
|||
this.treeEditBefore(row) |
|||
.then((data)=>{ |
|||
this.dialogLoading = false |
|||
this.treeEditFormData = data; |
|||
row = data |
|||
}) |
|||
.catch(err=>{ |
|||
this.dialogLoading = false |
|||
}) |
|||
}else{ |
|||
this.treeEditFormData = JSON.parse(JSON.stringify(row)); |
|||
} |
|||
} |
|||
// 删除 |
|||
if(item.name == "delete"){ |
|||
this.$emit("treeEditDelete",row); |
|||
} |
|||
}, |
|||
// 头部查询按钮操作 |
|||
headerButtonsHandle(item){ |
|||
let _goon = true |
|||
if(this.queryButtonsHandle){ |
|||
_goon = this.queryButtonsHandle(item,this.getSearchValue()) |
|||
} |
|||
if(!_goon)return |
|||
if(item.name == "addFirst"){ |
|||
this.createFirstTreeHandle(item) |
|||
} |
|||
if(item.name == "fresh"){ |
|||
this.createView(item) |
|||
} |
|||
if(item.name == "search"){ |
|||
this.querySearchHandle() |
|||
let _exp = this.getSearchValue() && this.getSearchValue().length > 0 ? 'all' : null |
|||
this.initTreeExpanded(_exp) |
|||
} |
|||
if(item.name == "reset"){ |
|||
this.resetView(item) |
|||
} |
|||
}, |
|||
// 重置表单 |
|||
treeEditResetFields(){ |
|||
this.$refs.treeEditDialogRef.getDom().resetFields(); |
|||
this.$nextTick(()=>{ |
|||
this.treeEditDialog = false; |
|||
this.dialogLoading = false |
|||
}) |
|||
}, |
|||
// 新增/修改按钮事件 |
|||
treeEditFormClick(val,row){ |
|||
// 取消 |
|||
if(val[2].name == "cancel"){ |
|||
if(this.treeEditCancle){ |
|||
this.dialogLoading = true |
|||
this.treeEditCancle(this.isEdit,this.treeEditFormData,val) |
|||
.then(()=>{ |
|||
this.treeEditResetFields() |
|||
}) |
|||
.catch(err=>{ |
|||
this.dialogLoading = false |
|||
}) |
|||
}else{ |
|||
this.treeEditResetFields() |
|||
} |
|||
} |
|||
// 确定 |
|||
if(val[2].name == "sure"){ |
|||
this.$refs.treeEditDialogRef.getDom().validate((valid) => { |
|||
if(valid){ |
|||
if(this.treeEditSubmit){ |
|||
this.dialogLoading = true |
|||
this.treeEditSubmit(this.isEdit,this.treeEditFormData,val) |
|||
.then(()=>{ |
|||
this.clearSearchValue() |
|||
this.treeEditResetFields() |
|||
}) |
|||
.catch(err=>{ |
|||
this.dialogLoading = false |
|||
}) |
|||
}else{ |
|||
this.treeEditResetFields() |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
<style lang="scss" scoped> |
|||
@import "./style/index.scss"; |
|||
</style> |
@ -0,0 +1,24 @@ |
|||
.tableTreeComponents{ |
|||
height: 100%; |
|||
// background-color: #f2f2f2; |
|||
|
|||
.table-tree-search { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 20px 0; |
|||
|
|||
.bttton-box { |
|||
display: flex; |
|||
} |
|||
|
|||
.query-box { |
|||
display: flex; |
|||
|
|||
.el-input { |
|||
margin: 0 5px; |
|||
} |
|||
} |
|||
} |
|||
} |