Browse Source

faster-demo同步暂存

master
安虹睿 1 year ago
parent
commit
9bbc8bed72
  1. 14
      Code/Fe/.editorconfig
  2. 8
      Code/Fe/.env.development
  3. 14
      Code/Fe/.env.production
  4. 8
      Code/Fe/.env.staging
  5. 5
      Code/Fe/.eslintignore
  6. 198
      Code/Fe/.eslintrc.js
  7. 116
      Code/Fe/.gitignore
  8. 1
      Code/Fe/.npmrc
  9. 5
      Code/Fe/.travis.yml
  10. 21
      Code/Fe/LICENSE
  11. 126
      Code/Fe/README.md
  12. 14
      Code/Fe/babel.config.js
  13. 35
      Code/Fe/build/index.js
  14. 24
      Code/Fe/jest.config.js
  15. 9
      Code/Fe/jsconfig.json
  16. 116
      Code/Fe/mock/article.js
  17. 60
      Code/Fe/mock/index.js
  18. 84
      Code/Fe/mock/mock-server.js
  19. 51
      Code/Fe/mock/remote-search.js
  20. 98
      Code/Fe/mock/role/index.js
  21. 530
      Code/Fe/mock/role/routes.js
  22. 84
      Code/Fe/mock/user.js
  23. 48
      Code/Fe/mock/utils.js
  24. 42623
      Code/Fe/package-lock.json
  25. 122
      Code/Fe/package.json
  26. 26
      Code/Fe/plop-templates/component/index.hbs
  27. 55
      Code/Fe/plop-templates/component/prompt.js
  28. 16
      Code/Fe/plop-templates/store/index.hbs
  29. 62
      Code/Fe/plop-templates/store/prompt.js
  30. 2
      Code/Fe/plop-templates/utils.js
  31. 26
      Code/Fe/plop-templates/view/index.hbs
  32. 55
      Code/Fe/plop-templates/view/prompt.js
  33. 9
      Code/Fe/plopfile.js
  34. 5
      Code/Fe/postcss.config.js
  35. 1
      Code/Fe/public/WMS.svg
  36. 33
      Code/Fe/public/config.js
  37. BIN
      Code/Fe/public/favicon.ico
  38. BIN
      Code/Fe/public/img_login_bg.jpg
  39. 30
      Code/Fe/public/index.html
  40. 3
      Code/Fe/public/version.json
  41. 84
      Code/Fe/src/App.vue
  42. 604
      Code/Fe/src/api/wms-api.js
  43. 320
      Code/Fe/src/api/wms-auth.js
  44. 56
      Code/Fe/src/api/wms-core.js
  45. 159
      Code/Fe/src/api/wms-interface.js
  46. 237
      Code/Fe/src/api/wms-job.js
  47. BIN
      Code/Fe/src/assets/401_images/401.gif
  48. BIN
      Code/Fe/src/assets/404_images/404.png
  49. BIN
      Code/Fe/src/assets/404_images/404_cloud.png
  50. BIN
      Code/Fe/src/assets/custom-theme/fonts/element-icons.ttf
  51. BIN
      Code/Fe/src/assets/custom-theme/fonts/element-icons.woff
  52. 1
      Code/Fe/src/assets/custom-theme/index.css
  53. 2
      Code/Fe/src/assets/img/Profile.svg
  54. BIN
      Code/Fe/src/assets/img/drawerHeader.png
  55. BIN
      Code/Fe/src/assets/img/menuLogo.png
  56. 85
      Code/Fe/src/components/Breadcrumb/index.vue
  57. 78
      Code/Fe/src/components/ErrorLog/index.vue
  58. 44
      Code/Fe/src/components/Hamburger/index.vue
  59. 190
      Code/Fe/src/components/HeaderSearch/index.vue
  60. 337
      Code/Fe/src/components/News/dialogIndex.vue
  61. 64
      Code/Fe/src/components/News/index.vue
  62. 82
      Code/Fe/src/components/Pagination/index.vue
  63. 142
      Code/Fe/src/components/PanThumb/index.vue
  64. 149
      Code/Fe/src/components/RightPanel/index.vue
  65. 60
      Code/Fe/src/components/Screenfull/index.vue
  66. 58
      Code/Fe/src/components/SizeSelect/index.vue
  67. 654
      Code/Fe/src/components/StepsCountPlanForm/_index.vue
  68. 723
      Code/Fe/src/components/StepsCountPlanForm/index.vue
  69. 86
      Code/Fe/src/components/StepsCountPlanForm/style/index.scss
  70. 459
      Code/Fe/src/components/StepsForm/_index.vue
  71. 551
      Code/Fe/src/components/StepsForm/index.vue
  72. 134
      Code/Fe/src/components/StepsForm/style/index.scss
  73. 213
      Code/Fe/src/components/StepsFormAlone/index.vue
  74. 44
      Code/Fe/src/components/StepsFormAlone/style/index.scss
  75. 62
      Code/Fe/src/components/SvgIcon/index.vue
  76. 173
      Code/Fe/src/components/ThemePicker/index.vue
  77. 380
      Code/Fe/src/components/UploadExcel/index.vue
  78. 77
      Code/Fe/src/components/batchButton/index.vue
  79. 559
      Code/Fe/src/components/commonTabel-drawer/index.vue
  80. 122
      Code/Fe/src/components/commonTabel-drawer/style/index.scss
  81. 349
      Code/Fe/src/components/conditionFilters/index.vue
  82. 46
      Code/Fe/src/components/conditionFilters/style/index.scss
  83. 107
      Code/Fe/src/components/currenButton/index.vue
  84. 60
      Code/Fe/src/components/currenButton/innerButton.vue
  85. 165
      Code/Fe/src/components/currenDescriptions/index.vue
  86. 888
      Code/Fe/src/components/currenForm/index.vue
  87. 761
      Code/Fe/src/components/currenTable/index.vue
  88. 309
      Code/Fe/src/components/currenTableFlex/index.vue
  89. 12
      Code/Fe/src/components/currenTableFlex/style/index.scss
  90. 57
      Code/Fe/src/components/currenTabs/index.vue
  91. 82
      Code/Fe/src/components/currenUpload/index.vue
  92. 72
      Code/Fe/src/components/currenUploadList/index.vue
  93. 100
      Code/Fe/src/components/currenUploadPictureCard/index.vue
  94. 306
      Code/Fe/src/components/filterForDetailPage/index.vue
  95. 214
      Code/Fe/src/components/filterSelect/index.vue
  96. 206
      Code/Fe/src/components/handelFrom/index.vue
  97. 298
      Code/Fe/src/components/importFile/index.vue
  98. 298
      Code/Fe/src/components/newAndEdiDialog/index.vue
  99. 354
      Code/Fe/src/components/newAndEdiDialogForDetail/index.vue
  100. 81
      Code/Fe/src/components/pdf/index.vue

14
Code/Fe/.editorconfig

@ -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

8
Code/Fe/.env.development

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

14
Code/Fe/.env.production

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

8
Code/Fe/.env.staging

@ -0,0 +1,8 @@
NODE_ENV = production
# just a flag
ENV = 'staging'
# base api
VUE_APP_BASE_API = '/stage-api'

5
Code/Fe/.eslintignore

@ -0,0 +1,5 @@
# build/*.js
# src/assets
# public
# dist
*

198
Code/Fe/.eslintrc.js

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

116
Code/Fe/.gitignore

@ -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.*

1
Code/Fe/.npmrc

@ -0,0 +1 @@
registry=https://registry.npm.taobao.org/

5
Code/Fe/.travis.yml

@ -0,0 +1,5 @@
language: node_js
node_js: 10
script: npm run test
notifications:
email: false

21
Code/Fe/LICENSE

@ -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.

126
Code/Fe/README.md

@ -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 主列表-操作列按钮点击事件
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},

14
Code/Fe/babel.config.js

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

35
Code/Fe/build/index.js

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

24
Code/Fe/jest.config.js

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

9
Code/Fe/jsconfig.json

@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

116
Code/Fe/mock/article.js

@ -0,0 +1,116 @@
const Mock = require('mockjs')
const List = []
const count = 100
const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
for (let i = 0; i < count; i++) {
List.push(Mock.mock({
id: '@increment',
timestamp: +Mock.Random.date('T'),
author: '@first',
reviewer: '@first',
title: '@title(5, 10)',
content_short: 'mock data',
content: baseContent,
forecast: '@float(0, 100, 2, 2)',
importance: '@integer(1, 3)',
'type|1': ['CN', 'US', 'JP', 'EU'],
'status|1': ['published', 'draft'],
display_time: '@datetime',
comment_disabled: true,
pageviews: '@integer(300, 5000)',
image_uri,
platforms: ['a-platform']
}))
}
module.exports = [
{
url: '/vue-element-admin/article/list',
type: 'get',
response: config => {
const { importance, type, title, page = 1, limit = 20, sort } = config.query
let mockList = List.filter(item => {
if (importance && item.importance !== +importance) return false
if (type && item.type !== type) return false
if (title && item.title.indexOf(title) < 0) return false
return true
})
if (sort === '-id') {
mockList = mockList.reverse()
}
const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
return {
code: 20000,
data: {
total: mockList.length,
items: pageList
}
}
}
},
{
url: '/vue-element-admin/article/detail',
type: 'get',
response: config => {
const { id } = config.query
for (const article of List) {
if (article.id === +id) {
return {
code: 20000,
data: article
}
}
}
}
},
{
url: '/vue-element-admin/article/pv',
type: 'get',
response: _ => {
return {
code: 20000,
data: {
pvData: [
{ key: 'PC', pv: 1024 },
{ key: 'mobile', pv: 1024 },
{ key: 'ios', pv: 1024 },
{ key: 'android', pv: 1024 }
]
}
}
}
},
{
url: '/vue-element-admin/article/create',
type: 'post',
response: _ => {
return {
code: 20000,
data: 'success'
}
}
},
{
url: '/vue-element-admin/article/update',
type: 'post',
response: _ => {
return {
code: 20000,
data: 'success'
}
}
}
]

60
Code/Fe/mock/index.js

@ -0,0 +1,60 @@
const Mock = require('mockjs')
const { param2Obj } = require('./utils')
const user = require('./user')
const role = require('./role')
const article = require('./article')
const search = require('./remote-search')
const mocks = [
...user,
...role,
...article,
...search
]
// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
function mockXHR() {
// mock patch
// https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
Mock.XHR.prototype.send = function() {
if (this.custom.xhr) {
this.custom.xhr.withCredentials = this.withCredentials || false
if (this.responseType) {
this.custom.xhr.responseType = this.responseType
}
}
this.proxy_send(...arguments)
}
function XHR2ExpressReqWrap(respond) {
return function(options) {
let result = null
if (respond instanceof Function) {
const { body, type, url } = options
// https://expressjs.com/en/4x/api.html#req
result = respond({
method: type,
body: JSON.parse(body),
query: param2Obj(url)
})
} else {
result = respond
}
return Mock.mock(result)
}
}
for (const i of mocks) {
Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
}
}
module.exports = {
mocks,
mockXHR
}

84
Code/Fe/mock/mock-server.js

@ -0,0 +1,84 @@
const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
const path = require('path')
const Mock = require('mockjs')
const mockDir = path.join(process.cwd(), 'mock')
function registerRoutes(app) {
let mockLastIndex
const { mocks } = require('./index.js')
const mocksForServer = mocks.map(route => {
return responseFake(route.url, route.type, route.response)
})
for (const mock of mocksForServer) {
// app[mock.type](mock.url, mock.response)
app[mock.type](mock.url, bodyParser.json(),bodyParser.urlencoded({ //添加
extended:true
}),mock.response)
mockLastIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocksForServer).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength
}
}
function unregisterRoutes() {
Object.keys(require.cache).forEach(i => {
if (i.includes(mockDir)) {
delete require.cache[require.resolve(i)]
}
})
}
// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || 'get',
response(req, res) {
console.log('request invoke:' + req.path)
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
}
}
}
module.exports = app => {
// parse app.body
// https://expressjs.com/en/4x/api.html#req.body
// app.use(bodyParser.json())
// app.use(bodyParser.urlencoded({
// extended: true
// }))
const mockRoutes = registerRoutes(app)
var mockRoutesLength = mockRoutes.mockRoutesLength
var mockStartIndex = mockRoutes.mockStartIndex
// watch files, hot reload mock server
chokidar.watch(mockDir, {
ignored: /mock-server/,
ignoreInitial: true
}).on('all', (event, path) => {
if (event === 'change' || event === 'add') {
try {
// remove mock routes stack
app._router.stack.splice(mockStartIndex, mockRoutesLength)
// clear routes cache
unregisterRoutes()
const mockRoutes = registerRoutes(app)
mockRoutesLength = mockRoutes.mockRoutesLength
mockStartIndex = mockRoutes.mockStartIndex
console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
} catch (error) {
console.log(chalk.redBright(error))
}
}
})
}

51
Code/Fe/mock/remote-search.js

@ -0,0 +1,51 @@
const Mock = require('mockjs')
const NameList = []
const count = 100
for (let i = 0; i < count; i++) {
NameList.push(Mock.mock({
name: '@first'
}))
}
NameList.push({ name: 'mock-Pan' })
module.exports = [
// username search
{
url: '/vue-element-admin/search/user',
type: 'get',
response: config => {
const { name } = config.query
const mockNameList = NameList.filter(item => {
const lowerCaseName = item.name.toLowerCase()
return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
})
return {
code: 20000,
data: { items: mockNameList }
}
}
},
// transaction list
{
url: '/vue-element-admin/transaction/list',
type: 'get',
response: _ => {
return {
code: 20000,
data: {
total: 20,
'items|20': [{
order_no: '@guid()',
timestamp: +Mock.Random.date('T'),
username: '@name()',
price: '@float(1000, 15000, 0, 2)',
'status|1': ['success', 'pending']
}]
}
}
}
}
]

98
Code/Fe/mock/role/index.js

@ -0,0 +1,98 @@
const Mock = require('mockjs')
const { deepClone } = require('../utils')
const { asyncRoutes, constantRoutes } = require('./routes.js')
const routes = deepClone([...constantRoutes, ...asyncRoutes])
const roles = [
{
key: 'admin',
name: 'admin',
description: 'Super Administrator. Have access to view all pages.',
routes: routes
},
{
key: 'editor',
name: 'editor',
description: 'Normal Editor. Can see all pages except permission page',
routes: routes.filter(i => i.path !== '/permission')// just a mock
},
{
key: 'visitor',
name: 'visitor',
description: 'Just a visitor. Can only see the home page and the document page',
routes: [{
path: '',
redirect: 'dashboard',
children: [
{
path: 'dashboard',
name: 'Dashboard',
meta: { title: 'dashboard', icon: 'dashboard' }
}
]
}]
}
]
module.exports = [
// mock get all routes form server
{
url: '/vue-element-admin/routes',
type: 'get',
response: _ => {
return {
code: 20000,
data: routes
}
}
},
// mock get all roles form server
{
url: '/vue-element-admin/roles',
type: 'get',
response: _ => {
return {
code: 20000,
data: roles
}
}
},
// add role
{
url: '/vue-element-admin/role',
type: 'post',
response: {
code: 20000,
data: {
key: Mock.mock('@integer(300, 5000)')
}
}
},
// update role
{
url: '/vue-element-admin/role/[A-Za-z0-9]',
type: 'put',
response: {
code: 20000,
data: {
status: 'success'
}
}
},
// delete role
{
url: '/vue-element-admin/role/[A-Za-z0-9]',
type: 'delete',
response: {
code: 20000,
data: {
status: 'success'
}
}
}
]

530
Code/Fe/mock/role/routes.js

@ -0,0 +1,530 @@
// Just a mock data
const constantRoutes = [
{
path: '/redirect',
component: 'layout/Layout',
hidden: true,
children: [
{
path: '/redirect/:path*',
component: 'views/redirect/index'
}
]
},
{
path: '/login',
component: 'views/login/index',
hidden: true
},
{
path: '/auth-redirect',
component: 'views/login/auth-redirect',
hidden: true
},
{
path: '/404',
component: 'views/error-page/404',
hidden: true
},
{
path: '/401',
component: 'views/error-page/401',
hidden: true
},
{
path: '',
component: 'layout/Layout',
redirect: 'dashboard',
children: [
{
path: 'dashboard',
component: 'views/dashboard/index',
name: 'Dashboard',
meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
}
]
},
{
path: '/documentation',
component: 'layout/Layout',
children: [
{
path: 'index',
component: 'views/documentation/index',
name: 'Documentation',
meta: { title: 'Documentation', icon: 'documentation', affix: true }
}
]
},
{
path: '/guide',
component: 'layout/Layout',
redirect: '/guide/index',
children: [
{
path: 'index',
component: 'views/guide/index',
name: 'Guide',
meta: { title: 'Guide', icon: 'guide', noCache: true }
}
]
}
]
const asyncRoutes = [
{
path: '/permission',
component: 'layout/Layout',
redirect: '/permission/index',
alwaysShow: true,
meta: {
title: 'Permission',
icon: 'lock',
roles: ['admin', 'editor']
},
children: [
{
path: 'page',
component: 'views/permission/page',
name: 'PagePermission',
meta: {
title: 'Page Permission',
roles: ['admin']
}
},
{
path: 'directive',
component: 'views/permission/directive',
name: 'DirectivePermission',
meta: {
title: 'Directive Permission'
}
},
{
path: 'role',
component: 'views/permission/role',
name: 'RolePermission',
meta: {
title: 'Role Permission',
roles: ['admin']
}
}
]
},
{
path: '/icon',
component: 'layout/Layout',
children: [
{
path: 'index',
component: 'views/icons/index',
name: 'Icons',
meta: { title: 'Icons', icon: 'icon', noCache: true }
}
]
},
{
path: '/components',
component: 'layout/Layout',
redirect: 'noRedirect',
name: 'ComponentDemo',
meta: {
title: 'Components',
icon: 'component'
},
children: [
{
path: 'tinymce',
component: 'views/components-demo/tinymce',
name: 'TinymceDemo',
meta: { title: 'Tinymce' }
},
{
path: 'markdown',
component: 'views/components-demo/markdown',
name: 'MarkdownDemo',
meta: { title: 'Markdown' }
},
{
path: 'json-editor',
component: 'views/components-demo/json-editor',
name: 'JsonEditorDemo',
meta: { title: 'Json Editor' }
},
{
path: 'split-pane',
component: 'views/components-demo/split-pane',
name: 'SplitpaneDemo',
meta: { title: 'SplitPane' }
},
{
path: 'avatar-upload',
component: 'views/components-demo/avatar-upload',
name: 'AvatarUploadDemo',
meta: { title: 'Avatar Upload' }
},
{
path: 'dropzone',
component: 'views/components-demo/dropzone',
name: 'DropzoneDemo',
meta: { title: 'Dropzone' }
},
{
path: 'sticky',
component: 'views/components-demo/sticky',
name: 'StickyDemo',
meta: { title: 'Sticky' }
},
{
path: 'count-to',
component: 'views/components-demo/count-to',
name: 'CountToDemo',
meta: { title: 'Count To' }
},
{
path: 'mixin',
component: 'views/components-demo/mixin',
name: 'ComponentMixinDemo',
meta: { title: 'componentMixin' }
},
{
path: 'back-to-top',
component: 'views/components-demo/back-to-top',
name: 'BackToTopDemo',
meta: { title: 'Back To Top' }
},
{
path: 'drag-dialog',
component: 'views/components-demo/drag-dialog',
name: 'DragDialogDemo',
meta: { title: 'Drag Dialog' }
},
{
path: 'drag-select',
component: 'views/components-demo/drag-select',
name: 'DragSelectDemo',
meta: { title: 'Drag Select' }
},
{
path: 'dnd-list',
component: 'views/components-demo/dnd-list',
name: 'DndListDemo',
meta: { title: 'Dnd List' }
},
{
path: 'drag-kanban',
component: 'views/components-demo/drag-kanban',
name: 'DragKanbanDemo',
meta: { title: 'Drag Kanban' }
}
]
},
{
path: '/charts',
component: 'layout/Layout',
redirect: 'noRedirect',
name: 'Charts',
meta: {
title: 'Charts',
icon: 'chart'
},
children: [
{
path: 'keyboard',
component: 'views/charts/keyboard',
name: 'KeyboardChart',
meta: { title: 'Keyboard Chart', noCache: true }
},
{
path: 'line',
component: 'views/charts/line',
name: 'LineChart',
meta: { title: 'Line Chart', noCache: true }
},
{
path: 'mixchart',
component: 'views/charts/mixChart',
name: 'MixChart',
meta: { title: 'Mix Chart', noCache: true }
}
]
},
{
path: '/nested',
component: 'layout/Layout',
redirect: '/nested/menu1/menu1-1',
name: 'Nested',
meta: {
title: 'Nested',
icon: 'nested'
},
children: [
{
path: 'menu1',
component: 'views/nested/menu1/index',
name: 'Menu1',
meta: { title: 'Menu1' },
redirect: '/nested/menu1/menu1-1',
children: [
{
path: 'menu1-1',
component: 'views/nested/menu1/menu1-1',
name: 'Menu1-1',
meta: { title: 'Menu1-1' }
},
{
path: 'menu1-2',
component: 'views/nested/menu1/menu1-2',
name: 'Menu1-2',
redirect: '/nested/menu1/menu1-2/menu1-2-1',
meta: { title: 'Menu1-2' },
children: [
{
path: 'menu1-2-1',
component: 'views/nested/menu1/menu1-2/menu1-2-1',
name: 'Menu1-2-1',
meta: { title: 'Menu1-2-1' }
},
{
path: 'menu1-2-2',
component: 'views/nested/menu1/menu1-2/menu1-2-2',
name: 'Menu1-2-2',
meta: { title: 'Menu1-2-2' }
}
]
},
{
path: 'menu1-3',
component: 'views/nested/menu1/menu1-3',
name: 'Menu1-3',
meta: { title: 'Menu1-3' }
}
]
},
{
path: 'menu2',
name: 'Menu2',
component: 'views/nested/menu2/index',
meta: { title: 'Menu2' }
}
]
},
{
path: '/example',
component: 'layout/Layout',
redirect: '/example/list',
name: 'Example',
meta: {
title: 'Example',
icon: 'example'
},
children: [
{
path: 'create',
component: 'views/example/create',
name: 'CreateArticle',
meta: { title: 'Create Article', icon: 'edit' }
},
{
path: 'edit/:id(\\d+)',
component: 'views/example/edit',
name: 'EditArticle',
meta: { title: 'Edit Article', noCache: true },
hidden: true
},
{
path: 'list',
component: 'views/example/list',
name: 'ArticleList',
meta: { title: 'Article List', icon: 'list' }
}
]
},
{
path: '/tab',
component: 'layout/Layout',
children: [
{
path: 'index',
component: 'views/tab/index',
name: 'Tab',
meta: { title: 'Tab', icon: 'tab' }
}
]
},
{
path: '/error',
component: 'layout/Layout',
redirect: 'noRedirect',
name: 'ErrorPages',
meta: {
title: 'Error Pages',
icon: '404'
},
children: [
{
path: '401',
component: 'views/error-page/401',
name: 'Page401',
meta: { title: 'Page 401', noCache: true }
},
{
path: '404',
component: 'views/error-page/404',
name: 'Page404',
meta: { title: 'Page 404', noCache: true }
}
]
},
{
path: '/error-log',
component: 'layout/Layout',
redirect: 'noRedirect',
children: [
{
path: 'log',
component: 'views/error-log/index',
name: 'ErrorLog',
meta: { title: 'Error Log', icon: 'bug' }
}
]
},
{
path: '/excel',
component: 'layout/Layout',
redirect: '/excel/export-excel',
name: 'Excel',
meta: {
title: 'Excel',
icon: 'excel'
},
children: [
{
path: 'export-excel',
component: 'views/excel/export-excel',
name: 'ExportExcel',
meta: { title: 'Export Excel' }
},
{
path: 'export-selected-excel',
component: 'views/excel/select-excel',
name: 'SelectExcel',
meta: { title: 'Select Excel' }
},
{
path: 'export-merge-header',
component: 'views/excel/merge-header',
name: 'MergeHeader',
meta: { title: 'Merge Header' }
},
{
path: 'upload-excel',
component: 'views/excel/upload-excel',
name: 'UploadExcel',
meta: { title: 'Upload Excel' }
}
]
},
{
path: '/zip',
component: 'layout/Layout',
redirect: '/zip/download',
alwaysShow: true,
meta: { title: 'Zip', icon: 'zip' },
children: [
{
path: 'download',
component: 'views/zip/index',
name: 'ExportZip',
meta: { title: 'Export Zip' }
}
]
},
{
path: '/pdf',
component: 'layout/Layout',
redirect: '/pdf/index',
children: [
{
path: 'index',
component: 'views/pdf/index',
name: 'PDF',
meta: { title: 'PDF', icon: 'pdf' }
}
]
},
{
path: '/pdf/download',
component: 'views/pdf/download',
hidden: true
},
{
path: '/theme',
component: 'layout/Layout',
redirect: 'noRedirect',
children: [
{
path: 'index',
component: 'views/theme/index',
name: 'Theme',
meta: { title: 'Theme', icon: 'theme' }
}
]
},
{
path: '/clipboard',
component: 'layout/Layout',
redirect: 'noRedirect',
children: [
{
path: 'index',
component: 'views/clipboard/index',
name: 'ClipboardDemo',
meta: { title: 'Clipboard Demo', icon: 'clipboard' }
}
]
},
{
path: '/i18n',
component: 'layout/Layout',
children: [
{
path: 'index',
component: 'views/i18n-demo/index',
name: 'I18n',
meta: { title: 'I18n', icon: 'international' }
}
]
},
{
path: 'external-link',
component: 'layout/Layout',
children: [
{
path: 'https://github.com/PanJiaChen/vue-element-admin',
meta: { title: 'External Link', icon: 'link' }
}
]
},
{ path: '*', redirect: '/404', hidden: true }
]
module.exports = {
constantRoutes,
asyncRoutes
}

84
Code/Fe/mock/user.js

@ -0,0 +1,84 @@
const tokens = {
admin: {
token: 'admin-token'
},
editor: {
token: 'editor-token'
}
}
const users = {
'admin-token': {
roles: ['admin'],
introduction: 'I am a super administrator',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Super Admin'
},
'editor-token': {
roles: ['editor'],
introduction: 'I am an editor',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor'
}
}
module.exports = [
// user login
{
url: '/vue-element-admin/user/login',
type: 'post',
response: config => {
const { username } = config.body
const token = tokens[username]
// mock error
if (!token) {
return {
code: 60204,
message: 'Account and password are incorrect.'
}
}
return {
code: 20000,
data: token
}
}
},
// get user info
{
url: '/vue-element-admin/user/info\.*',
type: 'get',
response: config => {
const { token } = config.query
const info = users[token]
// mock error
if (!info) {
return {
code: 50008,
message: 'Login failed, unable to get user details.'
}
}
return {
code: 20000,
data: info
}
}
},
// user logout
{
url: '/vue-element-admin/user/logout',
type: 'post',
response: _ => {
return {
code: 20000,
data: 'success'
}
}
}
]

48
Code/Fe/mock/utils.js

@ -0,0 +1,48 @@
/**
* @param {string} url
* @returns {Object}
*/
function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
module.exports = {
param2Obj,
deepClone
}

42623
Code/Fe/package-lock.json

File diff suppressed because it is too large

122
Code/Fe/package.json

@ -0,0 +1,122 @@
{
"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",
"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"
}
}

26
Code/Fe/plop-templates/component/index.hbs

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

55
Code/Fe/plop-templates/component/prompt.js

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

16
Code/Fe/plop-templates/store/index.hbs

@ -0,0 +1,16 @@
{{#if state}}
const state = {}
{{/if}}
{{#if mutations}}
const mutations = {}
{{/if}}
{{#if actions}}
const actions = {}
{{/if}}
export default {
namespaced: true,
{{options}}
}

62
Code/Fe/plop-templates/store/prompt.js

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

2
Code/Fe/plop-templates/utils.js

@ -0,0 +1,2 @@
exports.notEmpty = name => v =>
!v || v.trim() === '' ? `${name} is required` : true

26
Code/Fe/plop-templates/view/index.hbs

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

55
Code/Fe/plop-templates/view/prompt.js

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

9
Code/Fe/plopfile.js

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

5
Code/Fe/postcss.config.js

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

1
Code/Fe/public/WMS.svg

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1642571135328" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2046" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M935.808 330.752c10.624 18.176 16.128 26.112 16.768 48.64V840.96c-1.152 35.712-7.296 59.264-30.848 82.944-23.552 23.68-46.976 29.952-82.432 30.976H184.704c-35.584-1.152-59.008-7.424-82.432-30.976C78.72 900.224 72.576 876.8 71.424 840.96V379.392c0-22.528 5.76-30.464 17.152-48.64 11.52-18.176 20.608-27.392 39.552-40.064L449.152 88.064c19.456-12.672 41.472-19.072 65.792-19.072s46.336 6.272 65.792 19.072l321.152 202.624c16.128 12.672 23.296 21.888 33.92 40.064z" fill="#319EEC" p-id="2047"></path><path d="M447.616 833.28H261.504c-27.52 0-50.048-22.528-50.048-50.048V595.584c0-27.52 22.528-50.048 50.048-50.048h186.112c27.52 0 50.048 22.528 50.048 50.048v187.648c0.128 27.52-22.4 50.048-50.048 50.048zM640.896 823.936h-80.896c-12.032 0-21.76-9.856-21.76-21.76V720.64c0-12.032 9.856-21.76 21.76-21.76h80.896c12.032 0 21.76 9.856 21.76 21.76v81.536c0 12.032-9.728 21.76-21.76 21.76zM640.896 670.72h-80.896c-12.032 0-21.76-9.856-21.76-21.76v-81.536c0-12.032 9.856-21.76 21.76-21.76h80.896c12.032 0 21.76 9.856 21.76 21.76V648.96c0 11.904-9.728 21.76-21.76 21.76zM802.944 823.936h-80.896c-12.032 0-21.76-9.856-21.76-21.76V720.64c0-12.032 9.856-21.76 21.76-21.76h80.896c12.032 0 21.76 9.856 21.76 21.76v81.536c0 12.032-9.728 21.76-21.76 21.76z" fill="#FFFFFF" p-id="2048"></path></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

33
Code/Fe/public/config.js

@ -0,0 +1,33 @@
// dev_win
window.SITE_CONFIG['base'] = 'http://dev.ccwin-in.com:60069'
window.SITE_CONFIG['columnsApiNames'] = '/api/abp/application-configuration'
window.SITE_CONFIG['isAutoLogin'] = false
window.SITE_CONFIG['isSinglePage'] = false
window.SITE_CONFIG['userNameOrEmailAddress'] = 'admin'
window.SITE_CONFIG['client_secret'] = '1q2w3E*'
// window.SITE_CONFIG['user'] = 'http://dev.ccwin-in.com:60069/api'
// // window.SITE_CONFIG['print'] = 'print'21384
// window.SITE_CONFIG['print'] = 'http://dev.ccwin-in.com:60074'
// window.SITE_CONFIG['largeScreen'] = 'http://dev.ccwin-in.com:60073'
// window.SITE_CONFIG['warehouseCode'] = 'T8'
// window.SITE_CONFIG['company'] = 'DongYang'
// window.SITE_CONFIG['client_secret'] = '1q2w3E*'
// window.SITE_CONFIG['reportsUrl'] = 'http://dev.ccwin-in.com:60074/#/reports/'
// window.SITE_CONFIG['versionUrl'] = 'http://dev.ccwin-in.com:60070'
// window.SITE_CONFIG['companyName'] = '长春一汽富维东阳汽车塑料零部件(安徽)有限公司'
// 接口看板地址
// window.SITE_CONFIG['interfaceBoardUrl'] = 'http://dev.ccwin-in.com:60090/'
// window.SITE_CONFIG['interfaceBoardUrl'] = 'http://dev.ccwin-in.com:60069/'
// 接口看板表头获取地址
// window.SITE_CONFIG['interfaceBoardColumnsApi'] = 'api/abp/application-configuration'
// mock
// window.SITE_CONFIG['apifoxToken'] = 'NXHNi5mp0dnUHGt0wkCrjvfcidsFKV33'
// window.SITE_CONFIG['base'] = 'https://mock.apifox.cn/m1/1773588-0-default'
// window.SITE_CONFIG['user'] = 'http://dev.ccwin-in.com:60099/api/auth'
// window.SITE_CONFIG['print'] = 'print'
// window.SITE_CONFIG['largeScreen'] = 'http://dev.ccwin-in.com:60073'
// window.SITE_CONFIG['warehouseCode'] = 'T8'
// window.SITE_CONFIG['company'] = 'DongYang'
// window.SITE_CONFIG['client_secret'] = '1q2w3E*'
// window.SITE_CONFIG['reportsUrl'] = 'http://10.164.0.227:59091/#/reports/'

BIN
Code/Fe/public/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
Code/Fe/public/img_login_bg.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

30
Code/Fe/public/index.html

@ -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>

3
Code/Fe/public/version.json

@ -0,0 +1,3 @@
{
"version": "1.0.45"
}

84
Code/Fe/src/App.vue

@ -0,0 +1,84 @@
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
localStorage.setItem('base',window.SITE_CONFIG['base'])
localStorage.setItem('columnsApiNames',window.SITE_CONFIG['columnsApiNames'])
localStorage.setItem('isAutoLogin',window.SITE_CONFIG['isAutoLogin'])
localStorage.setItem('isSinglePage',window.SITE_CONFIG['isSinglePage'])
localStorage.setItem('userNameOrEmailAddress',window.SITE_CONFIG['userNameOrEmailAddress'])
localStorage.setItem('client_secret',window.SITE_CONFIG['client_secret'])
// localStorage.setItem('user',window.SITE_CONFIG['user'])
// localStorage.setItem('print',window.SITE_CONFIG['print'])
// localStorage.setItem('warehouseCode',window.SITE_CONFIG['warehouseCode'])
// localStorage.setItem('company',window.SITE_CONFIG['company'])
// localStorage.setItem('largeScreen',window.SITE_CONFIG['largeScreen'])
// localStorage.setItem('apifoxToken',window.SITE_CONFIG['apifoxToken'])
// localStorage.setItem('reportsUrl',window.SITE_CONFIG['reportsUrl'])
// localStorage.setItem('companyName',window.SITE_CONFIG['companyName'])
// // localStorage.setItem('interfaceBoardUrl',window.SITE_CONFIG['interfaceBoardUrl'])
// localStorage.setItem('interfaceBoardColumnsApi',window.SITE_CONFIG['interfaceBoardColumnsApi'])
</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>

604
Code/Fe/src/api/wms-api.js

@ -0,0 +1,604 @@
import request from '@/utils/request'
import store from '@/store'
// let baseURL = process.env.VUE_APP_BASE_API + '/'
let baseURL = localStorage.getItem('base') + '/api/'
let printURL = localStorage.getItem('print') + '/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.name.userName
}
return request({
url: baseURL + url,
method: 'post',
data
})
}
//编辑
export function postUpdate(data, id, url) {
return request({
url: baseURL + url + '/' + id,
method: 'put',
data
})
}
//申请流程
export function processRequest(id, url) {
return request({
url: baseURL + url + id,
method: 'post',
})
}
//子表编辑
export function postDetailUpdate(data, id, UrlData, url) {
return request({
url: baseURL + url + '/detail/' + id,
method: 'put',
params: UrlData,
data
})
}
//删除
export function postDelete(id, url) {
return request({
url: baseURL + url + '/' + id,
method: 'delete',
})
}
//子表删除
// export function postDetailDelete(id, UrlData, url) {
// return request({
// url: baseURL + url + '/detail/' + id,
// method: 'delete',
// params: UrlData
// })
// }
//分页+筛选【列表】
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,
})
}
//导入-新-创建文件
export function fileStorageCreate(data) {
return request({
url: baseURL + 'filestore/file/create',
method: 'post',
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 planHandle(id, url, data) {
return request({
url: baseURL + url + '/handle/' + id,
method: 'post',
params: data
})
}
// 取消计划(生产计划为关闭) | 盘点计划
export function postCancel(id, url) {
return request({
url: baseURL + url + '/cancel/' + id,
method: 'post'
})
}
// 中止 | 盘点计划
export function postAbort(id, url) {
return request({
url: baseURL + url + '/abort/' + id,
method: 'post'
})
}
//完成 | 盘点计划
export function postComplete(id,data,url) {
return request({
url: baseURL + url + '/complete-by-type/' + id,
method: 'post',
params:data
})
}
//阶段 - 校正库存 | 盘点计划
export function ChangeStage(data, url) {
return request({
url: baseURL + url + '/change-stage',
method: 'post',
params:data
})
}
//拆分 | 盘点计划
export function postCreateWithCondition(data, url) {
if (Object.keys(data).includes('company')) {
data.company = localStorage.getItem('company')
}
if (Object.keys(data).includes('warehouseCode')) {
data.warehouseCode =localStorage.getItem('warehouseCode')
}
return request({
url: baseURL + url + '/create-with-condition',
method: 'post',
data
})
}
//更新可用容量
export function postUpdateAvailableCapacity(data, url) {
return request({
url: baseURL + url + '/recalculate',
method: 'post',
params: data
})
}
// 执行调整 | 盘点调整申请
// export function ExecuteAdjusted(id) {
// return request({
// url: baseURL + 'wms/store/count-adjust-note/ExecuteAdjusted/' + id,
// method: 'post',
// })
// }
// 生成盘点调整申请 | 盘点记录
export function StartAdjust(id) {
return request({
// url: baseURL + 'wms/store/count-note/StartAdjust/' + id,
url: baseURL + 'wms/store/count-note/'+ id +'/generate-adjust-request',
method: 'post'
})
}
//---------------------------通用---------------------------
//获取详情
export function getDetailed(id, url) {
return request({
url: baseURL + url + '/' + id,
method: 'get',
})
}
//获取子表详情
export function getDetailedSon(id, UrlData, url) {
return request({
url: baseURL + url + '/detail/' + id,
method: 'get',
params: UrlData
})
}
//---------------------------只查询-------------------------
//获取分页+筛选
export function getPage(data, url) {
return request({
url: baseURL + url,
method: 'get',
params: data
})
}
//打印标签
export function PrintServices(data) {
return request({
url: printURL + 'reporting/PrintServices',
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
transformRequest: [
function (data) {
var ret = ''
for (var it in data) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
}
ret = ret.substring(0, ret.lastIndexOf('&'))
return ret
}
],
data
})
}
// 修改库存余额过期日期 | 库存余额
export function updateExpireDate(data, url) {
return request({
url: baseURL + url + '/update/expire-date',
method: 'post',
params: data
})
}
// 详情tabs页 通过code 获取列表
export function getListByItemcode(data, url ){
return request({
url: baseURL + url + '/get-list-by-itemcode',
method: 'get',
params: data
})
}
// 详情tabs页 通过code 获取列表
export function byItem(itemCode, url ){
return request({
url: baseURL + url + '/list/by-item/' + itemCode,
method: 'get'
})
}
// 详情tabs页 通过父物品号 获取列表
export function byProduct(product, url ){
return request({
url: baseURL + url + '/get-list-by-product',
method: 'get',
params: product
})
}
// 详情tabs页 通过子物品号 获取列表
export function byComponent(component, url ){
return request({
url: baseURL + url + '/get-list-by-component',
method: 'get',
params: component
})
}
// 详情tabs页 通过供应商 获取列表
export function bySupplierCode(supplierCode, url ){
return request({
url: baseURL + url + '/get-list-by-supplier-code',
method: 'get',
params: supplierCode
})
}
// 详情tabs页 通过库位 获取列表
export function byLocation(locationCode, url ){
return request({
url: baseURL + url + '/list/by-location/' + locationCode,
method: 'get',
})
}
// 详情tabs页 通过库位 获取列表
export function byLocationCode(locationCode, url ){
return request({
url: baseURL + url + '/get-by-location-code',
method: 'get',
params: locationCode
})
}
// 详情tabs页 通过库位-零件关系 获取列表
export function relationByLocationCode(locationCode, url ){
return request({
url: baseURL + url + '/by-location',
method: 'get',
params: locationCode
})
}
// 详情tabs页 通过子物品号 获取子层级列表
export function byComponentCJ(component, url ){
return request({
url: baseURL + url + '/get-list-by-component-with-tree',
method: 'get',
params: component
})
}
//消息管理——用户消息类型关系——获取用户已有消息类型
export function messageTypeSubscribe(id) {
return request({
url: baseURL + 'message/message-type-subscribe/list/' + id,
method: 'get',
// params:id
})
}
//消息管理——用户消息类型关系——保存用户与消息类型关系
export function messageTypeSubscribeCreateMany(data,id) {
return request({
url: baseURL + 'message/message-type-subscribe/create-many',
method: 'post',
params:id,
data
})
}
//首页——获取当前用户未读消息
export function userNotifyNotReadList(userId) {
return request({
url: baseURL + 'message/user-notify-message/not-read-list/' + userId,
method: 'get'
})
}
//首页——获取当前用户已读消息
export function userNotifyHasRead(userId) {
return request({
url: baseURL + 'message/user-notify-message/has-read-list/' + userId,
method: 'get'
})
}
//首页——修改当前用户消息状态
export function userNotifyMessageUpdate(id) {
return request({
url: baseURL + 'message/user-notify-message/read/' + id,
method: 'post'
})
}
//首页——获取当前用户消息详情
export function notifyMessage(params, id) {
return request({
url: baseURL + 'message/notify-message/' + id,
method: 'get',
params: params,
})
}
// 库存-启用 | 库存余额
// export function inventoryBalanceActive(id) {
// return request({
// url: baseURL + 'wms/inventory/inventory-balance/active?id=' + id,
// method: 'post',
// })
// }
// 库存列表
export function inventoryBalanceList(data) {
return request({
url: baseURL + 'wms/inventory/Inventory-Balance/list',
method: 'post',
data
})
}
// 库存-启用 | 库存余额 改
export function inventoryBalanceActive(params) {
return request({
url: baseURL + 'wms/inventory/inventory-balance/' + params.id + '/active',
method: 'post',
params: params,
})
}
//库移——查询 | 库存转移日志
export function byBalancesRequestManyParameter(data) {
return request({
url: baseURL + 'wms/inventory/inventory-balance/by-balances-request-many-parameter',
method: 'post',
data
})
}
//库移——提交 | 库存转移日志
export function inventoryTransferNote(data) {
return request({
url: baseURL + 'wms/store/inventory-transfer-note',
method: 'post',
data
})
}
//库存管理——已占用库存——删除
//库存管理——预填充库存——删除
export function remove(id, url) {
return request({
url: baseURL + url + '/remove/' + id,
method: 'post',
params: id
})
}
//发料任务——新增 | 自动发料任务 | 人工发料任务
export function createAndHandle(data) {
return request({
url: baseURL + 'wms/store/material-request/create-and-handle',
method: 'post',
data
})
}
// 人工叫料申请 | 人工发料任务 | 人工发料记录 | 自动叫料申请 | 自动发料任务 | 自动发料记录 | 直接发料记录
// 完工收货缴库申请 | 线边仓缴库申请 | 线边仓缴库记录 | 线边仓报废申请 | 线边仓报废记录 | 原料报废记录
export function materialRequestByType(data, url, params) {
let _type = params.type?params.type:params.requestType
return request({
url: baseURL + url + '/' + _type,
method: 'post',
params: params,
data
})
}
// 采购收货——供应商发货通知——导入——确定(【批量创建】供应商发货通知)
export function supplierAsnCreateMany(data) {
return request({
url: baseURL + 'wms/store/supplier-asn/create-many',
method: 'post',
data
})
}
// 调拨作废
// export function transferRequestCancel(url, data ) {
// return request({
// url: baseURL + url + '/cancel/' + data.id,
// method: 'post',
// params: data
// })
// }
// 打印之后调用 记录打印次数 | 原料直发客户记录
export function sumPrint(number, url ) {
return request({
url: baseURL + url + '/sum-print/' + number,
method: 'post'
})
}
// 线边仓调拨列表 | 上架前退货记录 | 采购上架记录 | 半成品上架记录 | 原料直发
export function getPageListWip(data, url) {
return request({
url: baseURL + url,
method: 'post',
data
})
}
// 线边仓调拨确认按钮 | 客户调拨确认按钮 | 自动发料记录
export function confirm(id, url) {
return request({
url: baseURL + url + '/confirm/' + id,
method: 'post',
})
}
// 采购收货记录-详情页TAB-不合格品收货明细/合格品收货明细/收货缺料明细
export function purRecNoteCustomInfo( url,id ){
return request({
url: baseURL + 'wms/store/purchase-receipt-note/' + url + id,
method: 'get',
})
}
// 质检-不合格转合格
export function convertOk(data) {
return request({
url: baseURL + 'wms/store/no-ok-convert-ok-notes',
method: 'post',
data
})
}
// 获取全部供应商(codes)| 上架前退货记录 | 上架后退货记录 | 采购上架记录
export function allSupplierByCodes(data) {
return request({
url: baseURL + 'basedata/supplier/by-codes',
method: 'post',
data
})
}
// 根据code获取当前供应商信息 打印需要获取供应商信息(供应商简称等)相关位置
export function getOneSupplierInfoByCode(code) {
return request({
url: baseURL + 'basedata/supplier/by-code/' + code,
method: 'get'
})
}
// 根据code获取当前客户信息 打印需要获取供应商信息(客户地址等)相关位置
export function getOneCustomerInfoByCode(code) {
return request({
url: baseURL + 'basedata/customer/by-code/' + code,
method: 'get'
})
}
// 获取版本编号
export function getVsersion() {
return request({
url: window.SITE_CONFIG['versionUrl'] + `/version.json?t=${new Date().getTime()}`,
method: 'get'
})
}
// 安全库存预警
export function getListPageSafety(data, url) {
return request({
url: baseURL + url,
method: 'post',
data
})
}
// 根据编号获取字典信息
// export function getDictByCode(code) {
// return request({
// url: baseURL + 'basedata/dict/by-code/' + code,
// method: 'get',
// })
// }

320
Code/Fe/src/api/wms-auth.js

@ -0,0 +1,320 @@
import request from '@/utils/request'
let baseURL = localStorage.getItem('base') + '/api'
import axios from 'axios'
export function login(data) {
return request({
url: baseURL + '/account/login',
method: 'post',
data
})
}
export function getUsersByUserName(name) {
return request({
url: baseURL + '/identity/users/by-username/'+name,
method: 'get',
})
}
export function token(data) {
return request({
// url: baseURL + '/token',
url: baseURL + '/connect/token',
method: 'post',
data
})
}
export function getInfo() {
return request({
url: baseURL + '/abp/application-configuration',
method: 'get',
})
}
export function logout() {
return request({
url: baseURL + '/account/logout',
method: 'get'
})
}
//获取PC菜单
export function getWebMenu(params) {
return request({
url: baseURL + '/auth/user-menu/web-menu/' + params.userId,
method: 'get',
params: params
})
}
//新建
export function postCreate(data) {
return request({
url: baseURL + '/identity/users',
method: 'post',
data
})
}
//获取全部角色 | 用户信息维护
export function usersroles() {
return request({
url: baseURL + '/identity/users/assignable-roles',
method: 'get'
})
}
//获取当前角色 | 用户信息维护
export function getusersID(data) {
return request({
url: baseURL + '/identity/users/' + data + '/roles',
method: 'get'
})
}
//编辑
export function postUpdate(data, id) {
return request({
url: baseURL + '/identity/users/' + id,
method: 'put',
data
})
}
//删除
export function postDelete(id) {
return request({
url: baseURL + '/identity/users/' + id,
method: 'delete',
})
}
//分页+筛选
export function getPageList(data) {
return request({
url: baseURL + '/identity/users',
method: 'get',
params: data
})
}
//重置密码功能 | 用户信息维护
export function putpassword(id) {
return request({
url: baseURL + '/identity/users/reset-password/' + id,
method: 'post'
})
}
//获取全部权限(包含PDA+pc) | PC菜单信息维护 | PDA菜单信息维护 | PDA用户权限维护 | PC角色权限维护
export function menuPermissions(data) {
return request({
url: baseURL + '/auth/menu/list',
method: 'post',
data
})
}
//新建菜单 | PC菜单信息维护 | PDA菜单信息维护
export function postCreateMenu(data) {
return request({
url: baseURL + '/auth/menu',
method: 'post',
data
})
}
//编辑菜单 | PC菜单信息维护 | PDA菜单信息维护
export function postUpdateMenu(data, id) {
return request({
url: baseURL + '/auth/menu/' + id,
method: 'put',
data
})
}
//删除菜单 | PC菜单信息维护 | PDA菜单信息维护
export function postDeleteMenu(id) {
return request({
url: baseURL + '/auth/menu/' + id,
method: 'delete',
})
}
//获取菜单详情 | PC菜单信息维护 | PDA菜单信息维护
export function getDetailedMenu(id) {
return request({
url: baseURL + '/auth/menu/' + id,
method: 'get',
})
}
//获取用户全部工作组 | 用户工作组对应关系
// export function workgroupPermissions() {
// return request({
// url: baseURL + '/auth/user-workgroup/get-list',
// method: 'get',
// params:{
// SkipCount:0,
// MaxResultCount:100
// }
// })
// }
//获取已有权限 | PDA用户权限维护
export function UserPermissions(id, url) {
return request({
url: baseURL + '/' + url + '/' + id.userId,
method: 'get',
params:id
})
}
//保存权限 | PDA用户权限维护
export function SetUserPermissions(data, id, url) {
return request({
url: baseURL + '/' + url + '/' + id.userId,
method: 'put',
params:id,
data
})
}
//获取用户已有工作组 | 用户工作组对应关系
export function userWorkgroupPermissions(id) {
return request({
url: baseURL + '/auth/user-workgroup/get-user-work-group-by-user-id',
method: 'get',
params:id
})
}
//保存用户与工作组关系 | 用户工作组对应关系
export function SetUserWorkgroupPermissions(data,id) {
return request({
url: baseURL + '/auth/user-workgroup/add-many',
method: 'post',
params:id,
data
})
}
//加载用户登录信息
export function loadLoginUserInfo(id) {
return request({
url: baseURL + '/identity/users/' + id,
method: 'get'
})
}
//修改登录用户基本信息
export function putLoginUserInfo(data) {
return request({
url: baseURL + '/identity/my-profile',
method: 'put',
data
})
}
//修改登录用户的密码-强密码规则
export function postLoginUserInfo(data, id) {
return request({
url: baseURL + '/identity/users/change-password/' + id,
method: 'post',
data
})
}
//获取部门列表 | 用户信息维护 | 部门信息维护
export function departmentList(data) {
return request({
url: baseURL + '/auth/department/list',
method: 'post',
data
})
}
//获取明细列表
export function getDetailed(id, url) {
return request({
url: baseURL + url + id,
method: 'get'
})
}
//新建 | 部门信息维护
export function authCreate(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.name.userName
}
return request({
url: baseURL + '/' + url,
method: 'post',
data
})
}
//编辑 | 部门信息维护
export function authUpdate(data, id, url) {
return request({
url: baseURL + '/' + url + '/' + id,
method: 'put',
data
})
}
//删除 | 部门信息维护
export function authDelete(id, url) {
return request({
url: baseURL + '/' + url + '/' + id,
method: 'delete',
})
}
//-------------------------------------
// 创建 | PC角色权限维护
export function postCreateRoles(data) {
return request({
url: baseURL + '/identity/roles',
method: 'post',
data
})
}
//编辑 | PC角色权限维护
export function postUpdateRoles(data, id) {
return request({
url: baseURL+'/identity/roles/' + id,
method: 'put',
data
})
}
//删除 | PC角色权限维护
export function postDeleteRoles(id) {
return request({
url: baseURL + '/identity/roles/' + id,
method: 'delete',
})
}
// 描述修改 | PC角色权限维护
export function saveOrUpdateDescribe(params,id) {
return request({
url: baseURL + '/identity/roles/' + id + '/description',
method: 'post',
params: params
})
}
//分页+筛选 | PC角色权限维护
export function getPageListRoles(data) {
return request({
url: baseURL + '/identity/roles',
method: 'get',
params: data
})
}
//获取权限模板 | PC角色权限维护
export function getpermissionsRoles(data) {
return request({
url: baseURL +'/permission-management/permissions',
method: 'get',
params: data
})
}
//保存权限模板 | PC角色权限维护
export function putpermissionsRoles(url, data) {
return request({
url: baseURL+ url,
method: 'put',
data
})
}

56
Code/Fe/src/api/wms-core.js

@ -0,0 +1,56 @@
import request from '@/utils/request'
// let baseURL = localStorage.getItem('print') + '/api/'
let baseURL = localStorage.getItem('base') + '/api/'
// 根据箱码获取标签相关信息 | 补打标签
export function getOneInventoryLabelByCode(code) {
return request({
url: baseURL + 'label/inventory-label/by-code/' + code,
method: 'get'
})
}
// 批量获取箱标签信息 | 到货请求
export function getInventoryLabelByCodes(data) {
return request({
url: baseURL + 'label/inventory-label/by-codes',
method: 'post',
data
})
}
//生产、采购生成标签(批量)| 标签管理模块
export function postInventoryLabelCode(data) {
return request({
url: baseURL + 'label/Inventory-label/generate-and-create/many',
method: 'post',
data
})
}
//生产、采购生成标签(一次多个)| 标签管理模块
export function postInventoryLabelCode_count(params,data) {
return request({
url: baseURL + 'label/inventory-label/generate-and-create/many/'+params.count,
method: 'post',
data
})
}
// 拆箱 | 标签管理-拆分箱标签
export function postSplitPacking(data) {
return request({
url: baseURL + 'wms/store/transfer-note/split-packing',
method: 'post',
data
})
}
// 拆箱记录列表
export function splitPackingList(data) {
return request({
url: baseURL + 'wms/store/transfer-note/get-split-packing-list',
method: 'post',
data
})
}

159
Code/Fe/src/api/wms-interface.js

@ -0,0 +1,159 @@
// 接口监控看板相关api
import request from '@/utils/request'
let base_api = localStorage.getItem('base')
let colum_url = localStorage.getItem('columnsApiNames')
// 转义传参
const initParams = (data) => {
return {
skipCount:data.SkipCount,
maxResultCount:data.MaxResultCount,
sorting:data.Sorting
}
}
// 获取表头数据
export function getInterfaceBoard() {
return request({
method:'get',
url: base_api + colum_url
})
}
// 获取导出配置信息接口
// export function getExportConfigList(name) {
// return request({
// url: base_api + '/get-by-user-and-table-name',
// method: 'post',
// params:{
// userId:JSON.parse(localStorage.getItem("currentUserInfo")).id,
// exportTableName:name
// },
// })
// }
//外部数据转换
// export function dataExchangeFromOut(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'outgoing-to-external',
// params:initParams(data)
// })
// }
// //归档外部数据转换
// export function dataExchangeFromOut_file(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'archived-outgoing-to-external',
// params:initParams(data)
// })
// }
// //wms数据接收
// export function comingToWms(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'incoming-to-wms',
// params:initParams(data)
// })
// }
// //归档wms数据接收
// export function comingToWms_file(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'archived-incoming-to-wms',
// params:initParams(data)
// })
// }
// //wms数据转换
// export function dataExchangeFromWms(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'data-exchange_Outgoing-from-wms',
// params:initParams(data)
// })
// }
// // 归档wms数据转换
// export function dataExchangeFromWms_file(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'data-exchange_Archived-outgoing-from-wms',
// params:initParams(data)
// })
// }
// //外部数据接收
// export function comingFromOut(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'data-exchange_Incoming-from-external',
// params:initParams(data)
// })
// }
// //归档外部数据接收
// export function comingFromOut_file(data) {
// return axios({
// method:'get',
// url: interfaceBoard_api + 'data-exchange_Archived-incoming-from-external',
// params:initParams(data)
// })
// }
// 测试数据-列表
// export function TestSchool(data, includeDetails) {
// return request({
// method:'post',
// url: base_api + '/api/TestSchool/base/get-list-page-by-filter?includeDetails='+Boolean(includeDetails),
// data
// })
// }
// // 测试数据-列表-根据id获取详情
// export function TestSchoolItemById(id) {
// return request({
// method:'get',
// url: base_api + '/api/app/test-school/'+id,
// })
// }
// // 测试数据-列表-新增、编辑
// export function TestSchool_save(data,isAdd) {
// let _type = isAdd ? 'create' : 'update-by-id'
// return request({
// method:'post',
// url: base_api + '/api/TestSchool/base/'+_type,
// data:data,
// params:{id:data.id}
// })
// }
// // 测试数据-列表-删除
// export function TestSchool_delete(id) {
// return request({
// method:'DELETE',
// url: base_api + '/api/TestSchool/base/delete-by-id',
// params:{id:id}
// })
// }
// // 测试数据-明细-列表
// export function TestSchoolDetailList(data,includeDetails) {
// return request({
// method:'post',
// url: base_api + '/api/TestStudentDetail/base/get-list-page-by-filter?includeDetails='+Boolean(includeDetails),
// data
// })
// }
// // 测试数据-明细-删除
// export function TestSchoolDetailList_delete(id) {
// return request({
// method:'DELETE',
// url: base_api + '/api/TestStudentDetail/base/delete-by-id',
// params:{id:id}
// })
// }

237
Code/Fe/src/api/wms-job.js

@ -0,0 +1,237 @@
import request from '@/utils/request'
// let baseURL = process.env.VUE_APP_BASE_API + '/'
let baseURL = localStorage.getItem('base') + '/api/'
//分页+筛选
export function getPageList(data, url) {
return request({
url: baseURL + url + '/list',
method: 'post',
data
})
}
//分页+筛选
export function getPage(data, url) {
return request({
url: baseURL + url + '/count',
method: 'post',
data
})
}
//---------------------------通用---------------------------
//任务流程——承接
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 handle(data, params, url) {
return request({
url: baseURL + url + '/handle/'+params.id,
method: 'post',
// params: params,
data
})
}
//任务流程——打开
export function open(url, data) {
return request({
url: baseURL + url + '/open/'+data.id,
method: 'post',
// params: data
})
}
//获取详情
export function getDetailed(id, url) {
return request({
url: baseURL + url + '/' + id,
method: 'get',
})
}
//获取子表详情
export function getDetailedSon(id, UrlData, url) {
return request({
url: baseURL + url + '/detail/' + id,
method: 'get',
params: UrlData
})
}
//收货任务-执行 - 目检
export function visualInspection( params,data) {
return request({
url: baseURL + 'wms/job/purchase-receipt-job/save-detail-inspect/' + params.id,
method: 'post',
data
})
}
// 收货任务-执行-待处理全部转合格
export function AllPendingToQualified( id,params) {
return request({
// url: baseURL + 'wms/job/purchase-receipt-job/set-inspect-status-with-not-inspect/' + id,
url: baseURL + 'wms/job/purchase-receipt-job/set-inspect-status-ok-by-inspect/' + id,
method: 'post',
params: params,
})
}
// 收货任务-执行-重置目检状态
export function resetSelectToInspect( id,data) {
return request({
url: baseURL + 'wms/job/purchase-receipt-job/reset-many-detail-inspect/' + id,
method: 'post',
data: data,
})
}
//作废任务
export function Invalid(url, id) {
return request({
url: baseURL + url + '/invalid',
method: 'post',
params: id,
})
}
//检查任务
export function Check(url, id, data) {
return request({
url: baseURL + url + '/check',
method: 'post',
params: id,
data
})
}
//上架任务——执行
export function HandleJob(data, id, url) {
return request({
url: baseURL + url + '/handle-job',
method: 'post',
params: id,
data
})
}
//质检执行任务
export function InspectJobHandle(data, params, url) {
return request({
url: baseURL + url + '/handle',
method: 'post',
params: params,
data
})
}
// //发料任务——执行
// export function issueJobHandle(data, params, url) {
// return request({
// url: baseURL + url + '/handle',
// method: 'post',
// params: params,
// data
// })
// }
//人工发料任务 | 自动发料任务
export function materialRequestByType(data, url, params,includeDetails) {
let _type = params.type?params.type:params.requestType
return request({
url: baseURL + url + '/' + _type + '?includeDetails=' + (includeDetails || false),
method: 'post',
params: params,
data
})
}
//生产计划——更新备料计划
export function productionPlanUpdate(data, detailId, id) {
return request({
url: baseURL + 'wms/store/preparation-plan/details/' + id,
method: 'put',
params: detailId,
data
})
}
//生产计划——生产备料计划后查询乐观锁
export function preparationPlanByNumber(params) {
return request({
url: baseURL + 'wms/store/preparation-plan/by-number',
method: 'get',
params: params,
})
}
//质检——完成质检
export function completeSummaryDetailStatus(params, data) {
return request({
url: baseURL + 'wms/store/inspect-job/complete-summary-detail-status/' + params.id,
method: 'post',
params: params,
data
})
}
//质检——设置默认状态(清除质检)
export function setDetailDefaultOkStatus(params, id, data) {
return request({
url: baseURL + 'wms/store/inspect-job/set-detail-default-ok-status/' + id,
method: 'post',
params: params,
data
})
}
//质检——设置详情为合格
export function setDetailOkStatus(params, id, data) {
return request({
url: baseURL + 'wms/store/inspect-job/set-detail-ok-status/' + id,
method: 'post',
params: params,
data
})
}
//质检——设置详情为不合格
export function setDetailNookStatus(params, id, data) {
return request({
url: baseURL + 'wms/store/inspect-job/set-detail-nook-status/' + id,
method: 'post',
params: params,
data
})
}

BIN
Code/Fe/src/assets/401_images/401.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
Code/Fe/src/assets/404_images/404.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

BIN
Code/Fe/src/assets/404_images/404_cloud.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
Code/Fe/src/assets/custom-theme/fonts/element-icons.ttf

Binary file not shown.

BIN
Code/Fe/src/assets/custom-theme/fonts/element-icons.woff

Binary file not shown.

1
Code/Fe/src/assets/custom-theme/index.css

File diff suppressed because one or more lines are too long

2
Code/Fe/src/assets/img/Profile.svg

@ -0,0 +1,2 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1648694852408" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="64325" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); }
</style></defs><path d="M509.952 10.24C232.448 10.24 8.192 234.496 8.192 512s224.256 501.76 501.76 501.76 501.76-224.256 501.76-501.76-224.256-501.76-501.76-501.76z m0 152.576c84.992 0 153.6 68.608 153.6 153.6s-68.608 153.6-153.6 153.6-153.6-68.608-153.6-153.6 68.608-153.6 153.6-153.6z m-1.024 698.368c-177.152 0-320.512-80.896-320.512-168.96S331.776 532.48 509.952 532.48c177.152 0 321.536 71.68 321.536 159.744S686.08 861.184 508.928 861.184z" p-id="64326" fill="#1296db"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
Code/Fe/src/assets/img/drawerHeader.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Code/Fe/src/assets/img/menuLogo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

85
Code/Fe/src/components/Breadcrumb/index.vue

@ -0,0 +1,85 @@
<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)
// matched = [{ path: '/inventoryManage/InventoryBalance', 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>

78
Code/Fe/src/components/ErrorLog/index.vue

@ -0,0 +1,78 @@
<template>
<div v-if="errorLogs.length>0">
<el-badge :is-dot="true" style="line-height: 25px;margin-top: -5px;" @click.native="dialogTableVisible=true">
<el-button style="padding: 8px 10px;" size="small" type="danger">
<svg-icon icon-class="bug" />
</el-button>
</el-badge>
<el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
<div slot="title">
<span style="padding-right: 10px;">Error Log</span>
<el-button size="mini" type="primary" icon="el-icon-delete" @click="clearAll">Clear All</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>

44
Code/Fe/src/components/Hamburger/index.vue

@ -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>

190
Code/Fe/src/components/HeaderSearch/index.vue

@ -0,0 +1,190 @@
<template>
<div :class="{ show: show }" class="header-search">
<svg-icon
class-name="search-icon"
icon-class="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>

337
Code/Fe/src/components/News/dialogIndex.vue

@ -0,0 +1,337 @@
<template>
<!-- v-if="errorLogs.length>0" -->
<div>
<el-dialog :visible.sync="dialogVisible" width="80%" top="8vh" append-to-body>
<div slot="title">
<span style="padding-right: 10px;">消息列表</span>
</div>
<el-row :gutter="20">
<el-col :span="12">
<el-table
v-loading="hasReadLoading"
:data="tableDataHasRead"
height="400"
style="width: 100%"
@sort-change="sortChange"
@row-click="handleRowHasReadClick"
>
<el-table-column
prop="title"
label="标题"
width="180"
align="center"
sortable="custom"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="hasRead"
label="状态"
align="center"
sortable="custom"
>
<template slot-scope="scope" >
<span v-if="scope.row.hasRead == true">已读</span>
<span v-else-if="scope.row.hasRead == false">未读</span>
</template>
</el-table-column>
<el-table-column
prop="readTime"
label="已读时间"
width="180"
align="center"
sortable="custom"
:show-overflow-tooltip="true"
/>
</el-table>
</el-col>
<el-col :span="12">
<el-table
v-loading="notReadLoading"
:data="tableData"
height="400"
style="width: 100%"
@sort-change="sortChange"
@row-click="handleRowClick"
>
<el-table-column
prop="title"
label="标题"
width="180"
align="center"
sortable="custom"
:show-overflow-tooltip="true"
/>
<el-table-column
prop="hasRead"
label="状态"
align="center"
sortable="custom"
>
<template slot-scope="scope" >
<span v-if="scope.row.hasRead == true">已读</span>
<span v-else-if="scope.row.hasRead == false">未读</span>
</template>
</el-table-column>
<el-table-column
prop="creationTime"
label="创建时间"
width="180"
align="center"
sortable="custom"
:show-overflow-tooltip="true"
/>
</el-table>
</el-col>
</el-row>
<!-- <div class="Footer">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryInfo.currentPage"
:page-sizes="[10, 15, 20]"
:page-size="queryInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
<el-button
type="primary"
size="mini"
style="margin-left: 10px; background-color: #409eff"
>确定</el-button
>
</div> -->
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="close"> </el-button>
<!-- <el-button type="primary" @click="dialogVisible = false"> </el-button> -->
</span>
<el-dialog
width="30%"
:title="details.titleDialog"
:visible.sync="innerVisible"
append-to-body>
<el-descriptions direction="vertical" :column="2" border v-loading="DialogLoading">
<el-descriptions-item label="消息标题">{{details.title}}</el-descriptions-item>
<el-descriptions-item label="内容">{{details.content}}</el-descriptions-item>
<el-descriptions-item label="消息类别">{{details.messageType}}</el-descriptions-item>
<el-descriptions-item label="创建时间">{{details.sendTime}}</el-descriptions-item>
</el-descriptions>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="innerVisible = false"> </el-button>
</span>
</el-dialog>
</el-dialog>
</div>
</template>
<script>
import { userNotifyNotReadList, userNotifyHasRead, userNotifyMessageUpdate, notifyMessage, getPageList } from "@/api/wms-api"
import { formatTimeStrToStr } from "@/utils/formatTime"
export default {
name: 'News',
data() {
return {
userId: '',
innerVisible: false,
details: {
titleDialog: '',
title: '',
content: '',
messageType: '',
sendTime: ''
},
hasReadLoading: false,
notReadLoading: false,
DialogLoading: false,
//
total: 0,
//
queryInfo: {
//
currentPage: 1,
//
pagesize: 20,
Sorting: "",
},
tableData: [],
tableDataHasRead:[],
}
},
props:{
dialogVisible: {
type: Boolean,
default: () => {
return false
}
},
},
computed: {
errorLogs() {
return this.$store.getters.errorLogs
}
},
mounted () {
this.userId = this.$store.getters.name.id
// todo-new:
// this.getList()
},
methods: {
getList(){
// ---------------
this.notReadLoading = true
userNotifyNotReadList(this.userId).then(res => {
this.tableData = res
this.tableData.forEach(item => {
if (item.creationTime) {
item.creationTime = formatTimeStrToStr(item.creationTime)
}
})
this.notReadLoading = false
}).catch(err => {
console.log(err)
this.notReadLoading = false
})
// ---------------
this.hasReadLoading = true
userNotifyHasRead(this.userId).then(res => {
this.tableDataHasRead = res
this.tableDataHasRead.forEach(item => {
if (item.readTime) {
item.readTime = formatTimeStrToStr(item.readTime)
}
})
this.hasReadLoading = false
}).catch(err => {
console.log(err)
this.hasReadLoading = false
})
},
//
handleSizeChange(val) {
this.queryInfo.pagesize = val;
this.getList();
},
//
handleCurrentChange(val) {
this.queryInfo.currentPage = val;
this.getList();
},
//
sortChange(data) {
const { prop, order } = data;
if (!prop || !order) {
this.queryInfo.Sorting = "";
this.handleFilter();
return;
}
this.queryInfo.Sorting = prop + " " + order;
this.handleFilter();
},
//table
handleRowClick(row, column, event) {
let that = this
this.innerVisible = true
this.details.titleDialog = row.title
this.DialogLoading = true
notifyMessage({id: row.messageId}, row.messageId).then(res => {
this.details.title = res.title
this.details.content = res.content
this.details.messageType = res.messageType
this.details.sendTime = formatTimeStrToStr(res.sendTime)
//
let params = {
sorting: null,
maxResultCount: 1000,
skipCount: 0,
condition: {
filters: null
}
}
getPageList(params,'message/message-type').then(resType => {
resType.items.forEach(item => {
if (item.messageTypeCode == res.messageType) {
that.details.messageType = item.messageTypeName
}
})
this.DialogLoading = false
}).catch(err => {
this.DialogLoading = false
console.log(err)
})
userNotifyMessageUpdate(row.id).then(res => {
that.getList();
that.$emit('getNoReadCount', that.userId)
}).catch(err => {
this.notReadLoading = false
console.log(err)
})
}).catch(err => {
console.log(err)
this.DialogLoading = false
})
// this.$router.push('/taskManage/InspectJob')
},
handleRowHasReadClick(row, column, event) {
let that = this
this.innerVisible = true
this.details.titleDialog = row.title
this.DialogLoading = true
notifyMessage({id: row.messageId}, row.messageId).then(res => {
this.details.title = res.title
this.details.content = res.content
this.details.messageType = res.messageType
this.details.sendTime = formatTimeStrToStr(res.sendTime)
//
let params = {
sorting: null,
maxResultCount: 1000,
skipCount: 0,
condition: {
filters: null
}
}
getPageList(params,'message/message-type').then(resType => {
resType.items.forEach(item => {
if (item.messageTypeCode == res.messageType) {
that.details.messageType = item.messageTypeName
}
})
this.DialogLoading = false
}).catch(err => {
console.log(err)
this.DialogLoading = false
})
}).catch(err => {
console.log(err)
this.DialogLoading = false
})
},
close() {
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.message-title {
font-size: 16px;
color: #333;
font-weight: bold;
padding-right: 8px;
}
.Footer {
padding: 40px 40px;
display: flex;
justify-content: flex-end;
::v-deep button {
background-color: #fff;
}
::v-deep .number {
background-color: #fff;
}
}
</style>

64
Code/Fe/src/components/News/index.vue

@ -0,0 +1,64 @@
<template>
<!-- v-if="errorLogs.length>0" -->
<div>
<el-badge v-if="this.noReadCount > 0" :value="this.noReadCount" :max="99" style="line-height: 10px;margin-right:10px" @click.native="dialogClick">
<svg-icon icon-class="email" />
</el-badge>
<svg-icon icon-class="email" v-if="this.noReadCount == 0" @click.native="dialogClick"/>
<dialogIndex :dialogVisible="dialogVisible" @close="close" @getNoReadCount="getNoReadCount"></dialogIndex>
</div>
</template>
<script>
import { userNotifyHasRead, userNotifyNotReadList, userNotifyMessageUpdate, notifyMessage, getPageList } from "@/api/wms-api"
import dialogIndex from "@/components/News/dialogIndex"
import { updateVersion } from '@/utils/upDateVersion'
export default {
name: 'News',
data() {
return {
dialogVisible: false,
noReadCount: 0
}
},
components: {
dialogIndex
},
mounted () {
this.userId = this.$store.getters.name.id
this.getNoReadCount(this.userId)
this.getSetInterval()
//
updateVersion()
},
methods: {
getSetInterval() {
let that = this
setInterval(function () {
that.getNoReadCount(that.userId)
//
updateVersion()
},120000)
},
getNoReadCount(userId) {
let that = this
// todo-new:
that.noReadCount = 0
// userNotifyNotReadList(userId).then(res => {
// that.noReadCount = res.length
// }).catch(err => {
// console.log(err)
// })
},
dialogClick(){
this.dialogVisible=true
},
close() {
this.dialogVisible = false
}
}
}
</script>
<style lang="scss" scoped>
</style>

82
Code/Fe/src/components/Pagination/index.vue

@ -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>

142
Code/Fe/src/components/PanThumb/index.vue

@ -0,0 +1,142 @@
<template>
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
<div class="pan-info">
<div class="pan-info-roles-container">
<slot />
</div>
</div>
<!-- eslint-disable-next-line -->
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
</div>
</template>
<script>
export default {
name: 'PanThumb',
props: {
image: {
type: String,
required: true
},
zIndex: {
type: Number,
default: 1
},
width: {
type: String,
default: '150px'
},
height: {
type: String,
default: '150px'
}
}
}
</script>
<style scoped>
.pan-item {
width: 200px;
height: 200px;
border-radius: 50%;
display: inline-block;
position: relative;
cursor: default;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.pan-info-roles-container {
padding: 20px;
text-align: center;
}
.pan-thumb {
width: 100%;
height: 100%;
background-position: center center;
background-size: cover;
border-radius: 50%;
overflow: hidden;
position: absolute;
transform-origin: 95% 40%;
transition: all 0.3s ease-in-out;
}
/* .pan-thumb:after {
content: '';
width: 8px;
height: 8px;
position: absolute;
border-radius: 50%;
top: 40%;
left: 95%;
margin: -4px 0 0 -4px;
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
} */
.pan-info {
position: absolute;
width: inherit;
height: inherit;
border-radius: 50%;
overflow: hidden;
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
}
.pan-info h3 {
color: #fff;
text-transform: uppercase;
position: relative;
letter-spacing: 2px;
font-size: 18px;
margin: 0 60px;
padding: 22px 0 0 0;
height: 85px;
font-family: 'Open Sans', Arial, sans-serif;
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
}
.pan-info p {
color: #fff;
padding: 10px 5px;
font-style: italic;
margin: 0 30px;
font-size: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.5);
}
.pan-info p a {
display: block;
color: #333;
width: 80px;
height: 80px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
color: #fff;
font-style: normal;
font-weight: 700;
text-transform: uppercase;
font-size: 9px;
letter-spacing: 1px;
padding-top: 24px;
margin: 7px auto 0;
font-family: 'Open Sans', Arial, sans-serif;
opacity: 0;
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
transform: translateX(60px) rotate(90deg);
}
.pan-info p a:hover {
background: rgba(255, 255, 255, 0.5);
}
.pan-item:hover .pan-thumb {
transform: rotate(-110deg);
}
.pan-item:hover .pan-info p a {
opacity: 1;
transform: translateX(0px) rotate(0deg);
}
</style>

149
Code/Fe/src/components/RightPanel/index.vue

@ -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>

60
Code/Fe/src/components/Screenfull/index.vue

@ -0,0 +1,60 @@
<template>
<div>
<svg-icon
:icon-class="isFullscreen?'exit-fullscreen':'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>

58
Code/Fe/src/components/SizeSelect/index.vue

@ -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>

654
Code/Fe/src/components/StepsCountPlanForm/_index.vue

@ -0,0 +1,654 @@
<template>
<el-dialog
:title="formTitle"
v-if="displayDialog.newDialog"
:visible="true"
:fullscreen="true"
:append-to-body="false"
:modal="false"
:modal-append-to-body="false"
:show-close="false"
>
<div id="stepsForm">
<el-steps
:active="active"
process-status="finish"
finish-status="success"
:align-center="true"
>
<el-step
v-for="(item, index) in stepFilters"
:key="index"
:title="item"
></el-step>
</el-steps>
<!-- "总体信息" -->
<curren-Form
v-if="active == 0"
class="page1"
size="medium"
ref="page1"
:searchData="CreateFormData"
:searchForm="CreateForm"
:searchOptions="Options"
:searchHandle="editHandle"
:rules="Rules"
:loading="loading"
@push="DataPush(arguments)"
@submitForm="editFormClick(arguments)"
>
</curren-Form>
<!-- "物品参数" -->
<searchPage
ref="searchTable"
:tableLoading="tableLoading"
:advancedFilter="advancedFilter(
'basedata/item-basic',
pageListItemBasic,
'totalCountItemBasic',
'itemBasicData',
oldSkipCountItemBasic
)"
:filterPageListParams="[]"
:formTitle="''"
:displayDialog="active == 1"
:selectionTable="false"
:editHandle="editHandle"
:searchTableData="locationData"
:searchTableColumns="$isTableColumns.Location"
:searchTotalCount="totalCountLocation"
:supplierItemPage="pageListLocation"
@SizeChange="AddNewAlterResultCount(
$event,
'basedata/item-basic',
pageListItemBasic,
'totalCountItemBasic',
'itemBasicData',
oldSkipCountItemBasic
)"
@CurrentChange="AddNewAlertoldSkipCount(
$event,
'basedata/item-basic',
pageListItemBasic,
'totalCountItemBasic',
'itemBasicData',
oldSkipCountItemBasic
)"
@tableButtonClick="addFormData(arguments)"
></searchPage>
<!-- "库位参数" -->
<searchPage
ref="searchTable"
:tableLoading="tableLoading"
:advancedFilter="advancedFilter(
'basedata/location',
pageListLocation,
'totalCountLocation',
'locationData',
oldSkipCountLocation
)"
:filterPageListParams="[]"
:formTitle="''"
:displayDialog="active == 2"
:selectionTable="false"
:editHandle="editHandle"
:searchTableData="locationData"
:searchTableColumns="$isTableColumns.Location"
:searchTotalCount="totalCountLocation"
:supplierItemPage="pageListLocation"
@SizeChange="AddNewAlterResultCount(
$event,
'basedata/location',
pageListLocation,
'totalCountLocation',
'locationData',
oldSkipCountLocation
)"
@CurrentChange="AddNewAlertoldSkipCount(
$event,
'basedata/location',
pageListLocation,
'totalCountLocation',
'locationData',
oldSkipCountLocation
)"
@tableButtonClick="addFormData(arguments)"
></searchPage>
<!-- "其他参数" -->
<curren-Form
v-loading="loading"
v-if="active == 3"
class="page1"
size="medium"
ref="page1"
:searchData="other"
:searchForm="otherForm"
:searchOptions="Options"
:searchHandle="editHandle"
:rules="Rules"
:loading="loading"
@push="DataPush(arguments)"
@submitForm="editFormClick(arguments)"
>
</curren-Form>
<!-- <curren-Form
v-if="active === 4"
size="medium"
class="page3"
:searchData="previewFormData"
:searchForm="CreateForm | formData"
:searchHandle="editHandle"
:rules="Rules"
:loading="loading"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item class="formTable-box" prop="details">
<currenTable
:tableData="previewFormData.details"
:tableColumns="detailsTableColumns | formDataDetails"
:selectionTable="false"
>
</currenTable>
</el-form-item>
</template>
</curren-Form> -->
<!-- "结果" -->
<div
v-if="active === step.length - 1 && pageStatus === 'success'"
class="page4"
>
<el-result icon="success" title="成功提示" subTitle="新增成功">
<template slot="extra">
<!-- <el-button type="primary" size="medium" @click="tuoFormPrint"
>打印托标签</el-button
>
<el-button type="primary" size="medium" @click="xbqFormPrint"
>打印箱标签</el-button
> -->
<el-button
v-for="item in successHandle"
:key="item.label"
:type="item.type"
size="medium"
@click="item.click()"
>{{ item.label }}</el-button
>
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
<div
v-if="active === step.length - 1 && pageStatus === 'error'"
class="page4"
>
<el-result icon="error" title="错误提示" subTitle="新增失败">
<template slot="extra">
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
</div>
</el-dialog>
</template>
<script>
import currenForm from "@/components/currenForm";
import currenTable from "@/components/currenTable";
import {
getPageList,
postCreateWithCondition,
postCreate,
} from "@/api/wms-api";
export default {
name: "stepsForm",
components: {
currenForm,
currenTable,
},
watch: {
active(val) {
if (val != 0) {
this.editHandle[0].label = "上一步";
} else {
this.editHandle[0].label = "取消";
}
},
},
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") {
data[index].type = "input";
} else if (key.type == "objectAutocomplete") {
data[index].type = "objectInput";
} else if (key.prop == "containerCode") data[index].disabled = "false";
});
return data;
},
},
props: {
//
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 [];
},
},
},
computed: {
stepFilters() {
let stepFilters = [];
const routeName = this.$route.meta.title;
this.step.forEach((key) => {
stepFilters.push(routeName.concat(key));
});
return stepFilters;
},
// autoAdvanced () {
// if (this.active == 1) {
// return this.advancedFilter(
// 'item-basic',
// this.pageListItemBasic,
// 'totalCountItemBasic',
// 'itemBasicData',
// this.oldSkipCountItemBasic
// )
// } else if (this.active == 2) {
// return this.advancedFilter(
// 'location',
// this.pageListLocation,
// 'totalCountLocation',
// 'locationData',
// this.oldSkipCountLocation
// )
// }
// },
},
data() {
return {
active: 0,
formReveal: 1,
pageStatus: "",
filterListParams: [],
itemBasicData: [],
isItemBasicData: [],
previewFormData: [],
totalCountItemBasic: 0,
oldSkipCountItemBasic: 1,
pageListItemBasic: {
condition: {
filters: [],
},
Sorting: "",
SkipCount: 0,
MaxResultCount: 100,
},
locationData: [],
isLocationData: [],
totalCountLocation: 0,
oldSkipCountLocation: 1,
pageListLocation: {
condition: {
filters: [],
},
Sorting: "",
SkipCount: 0,
MaxResultCount: 100,
},
other: {
otherParam: [],
},
otherForm: [
{
label: "状态",
prop: "otherParam",
type: "checkbox",
indeterminate:"true",
checkboxs: "radios",
},
],
otherFormData: {
countMethod: 0,
// type: 0,//
company: null,
description: null,
// beginTime: null,
// endTime: null,
planTime: null,
partCondition: {},
locCondition: {},
statusList: [],
worker: null,
warehouseCode: null,
remark: null,
},
loading: false,
tableLoading: false,
session: null,
step: ["总体信息", "物品参数", "库位参数", "其他参数", "结果"],
editHandle: [
{ label: "取消", name: "cancel" },
{ label: "下一步", type: "primary", name: "determine" },
],
};
},
mounted() {
this.session = JSON.parse(JSON.stringify(this.CreateFormData));
},
methods: {
//退
close(val) {
this.active = 0;
const filter ={
condition: {
filters: [],
},
Sorting: "",
SkipCount: 0,
MaxResultCount: 100,
}
this.pageListItemBasic = JSON.parse(JSON.stringify(filter))
this.pageListLocation = JSON.parse(JSON.stringify(filter))
const data = JSON.parse(JSON.stringify(this.session));
this.itemBasicData = []
this.locationData = []
this.$emit("close", data, val);
},
//autoComplete
DataPush(val) {
this.$emit("DataPush", val);
},
//autoComplete
detailsDataPush(val) {
this.$emit("detailsDataPush", val);
},
//
advancedFilter(url, list, TotalCount, data, oldSkipCount) {
return () => {
list.SkipCount = (oldSkipCount - 1) * list.MaxResultCount;
this.tableLoading = true;
getPageList(list, url)
.then((res) => {
this[data] = res.items;
this[TotalCount] = res.totalCount;
this.tableLoading = false;
})
.catch(() => {
this.tableLoading = false;
});
};
},
//(emit)
AddNewAlterResultCount(val, url, list, TotalCount, data, oldSkipCount) {
list.MaxResultCount = val;
const Function = this.advancedFilter(
url,
list,
TotalCount,
data,
oldSkipCount
);
Function();
},
//(emit)
AddNewAlertoldSkipCount(val, url, list, TotalCount, data, oldSkipCount) {
oldSkipCount = val;
const Function = this.advancedFilter(
url,
list,
TotalCount,
data,
oldSkipCount
);
Function();
},
//
tuoFormPrint() {
this.$emit("tuoFormPrint");
},
//
xbqFormPrint() {
this.$emit("xbqFormPrint");
},
// //
// addNew (url, list, TotalCount, data, MaxResultItem) {
// list.SkipCount = 0
// list.MaxResultCount = JSON.parse(TotalCount)
// getPageList(list, url).then((res) => {
// this[data] = res.items
// list.MaxResultCount = MaxResultItem
// })
// },
//
addFormData(val) {
if (val[0] == "cancel") {
this.active--;
} else {
if (this.active == 1) {
const MaxResultItem = JSON.parse(
this.pageListItemBasic.MaxResultCount
);
// this.addNew('item-basic', this.pageListItemBasic, this.totalCountItemBasic, 'isItemBasicData', MaxResultItem)
// this.pageListItemBasic.MaxResultCount = MaxResultItem
const Function = this.advancedFilter(
"basedata/location",
this.pageListLocation,
"totalCountLocation",
"locationData",
this.oldSkipCountLocation
);
Function();
this.$nextTick(()=>{
this.active++;
})
} else if (this.active == 2) {
const MaxResultLocation = JSON.parse(
this.pageListLocation.MaxResultCount
);
// this.addNew('location', this.pageListLocation, this.totalCountLocation, 'isLocationData', MaxResultLocation)
// this.pageListLocation.MaxResultCount = MaxResultLocation
this.active++;
}
}
},
//
splitFormData(val) {
return new Promise((resolve, reject) => {
postCreateWithCondition(val, "wms/store/count-plan")
.then((res) => {
this.previewFormData = JSON.parse(
JSON.stringify(this.CreateFormData)
);
// delete this.previewFormData.details
this.$listAssign(this.previewFormData, res);
this.previewFormData.details = [];
res.details.forEach((item) => {
const details = JSON.parse(
JSON.stringify(...this.childTableData)
);
this.$listAssign(details, item);
this.previewFormData.details.push(details);
});
resolve();
})
.catch((err) => {
reject();
});
});
},
editFormClick(val) {
// Moment(this.CreateFormData.arriveTime).format()
if (val[0] == 0) {
if (this.active == 0) {
this.close(0);
} else {
this.active--;
}
} else {
val[1].validate((valid) => {
if (valid) {
if (this.active == 0) {
const Function = this.advancedFilter(
"basedata/item-basic",
this.pageListItemBasic,
"totalCountItemBasic",
"itemBasicData",
this.oldSkipCountItemBasic
);
Function();
this.active++;
} else if (this.active == 3) {
this.$listAssign(this.otherFormData, this.CreateFormData);
this.otherFormData.partCondition =
this.pageListItemBasic.condition;
this.otherFormData.locCondition = this.pageListLocation.condition;
this.otherFormData.statusList = [];
let checkboxArray = []
this.other.otherParam.forEach(item => {
if (item == '待检') {
checkboxArray.push(1)
} else if (item == '合格') {
checkboxArray.push(2)
} else if (item == '不合格') {
checkboxArray.push(3)
} else if (item == '隔离') {
checkboxArray.push(4)
} else if (item == '破坏') {
checkboxArray.push(5)
} else if (item == '冻结') {
checkboxArray.push(6)
}
})
// ', '', '', '', '', ''
this.otherFormData.statusList = checkboxArray;
this.otherFormData.vendCondition = {
filters:[]
}
this.loading = true;
this.otherFormData.requestType = 2
this.splitFormData(this.otherFormData).then(
(resolve) => {
this.pageStatus = "success";
this.active++;
this.loading = false;
},
(reject) => {
this.pageStatus = "error";
this.active++;
this.loading = false;
}
);
}
// else if (this.active == 4) {
// postCreate(this.previewFormData, 'count-plan').then(res => {
// this.pageStatus = 'success'
// this.active++
// this.loading = false
// }).catch(err => {
// this.pageStatus = 'error'
// this.active++
// this.loading = false
// })
// }
else {
this.$errorMsg("请检查表单");
}
}
});
}
},
},
};
</script>
<style lang="scss" scoped>
@import "./style/index.scss";
</style>
<style lang="scss">
#stepsForm{
.formButton{
text-align: right;
}
}
</style>

723
Code/Fe/src/components/StepsCountPlanForm/index.vue

@ -0,0 +1,723 @@
<template>
<el-dialog
:title="formTitle"
v-if="displayDialog.newDialog"
:visible="true"
:fullscreen="true"
:append-to-body="false"
:modal="false"
:modal-append-to-body="false"
:show-close="false"
>
<div id="stepsForm">
<el-steps
:active="active"
process-status="finish"
finish-status="success"
:align-center="true"
>
<el-step
v-for="(item, index) in stepFilters"
:key="index"
:title="item"
></el-step>
</el-steps>
<!-- 总体信息 -->
<curren-Form
v-if="active == 0"
class="page1"
size="medium"
ref="page1"
:searchData="CreateFormData"
:searchForm="CreateForm"
:searchOptions="Options"
:searchHandle="editHandle"
:rules="Rules"
:loading="loading"
@push="DataPush(arguments)"
@submitForm="editFormClick(arguments)"
>
</curren-Form>
<!-- 库位参数 -->
<!-- 搜索按钮窗体组件LocationForPADPlan -->
<searchPage
v-if="active == 1"
@sxBtnClickHandle="sxBtnClickHandle"
ref="searchTable"
:tableLoading="tableLoading"
:filterActionOptions="filterActionOptions"
:advancedFilter="advancedFilter(
'basedata/location',
pageListLocation,
'totalCountLocation',
'locationData',
oldSkipCountLocation
)"
:setUTableHeight="355"
:filterPageListParams="[]"
:formTitle="''"
:displayDialog="active == 1"
:selectionTable="false"
:editHandle="editHandle"
:buttonsAllIsRight="true"
:searchTableData="locationData"
:searchTableColumns="initSearchPageTableColums()"
:searchTotalCount="totalCountLocation"
:supplierItemPage="pageListLocation"
@SizeChange="AddNewAlterResultCount(
$event,
'basedata/location',
pageListLocation,
'totalCountLocation',
'locationData',
oldSkipCountLocation
)"
@CurrentChange="AddNewAlertoldSkipCount(
$event,
'basedata/location',
pageListLocation,
'totalCountLocation',
'locationData',
oldSkipCountLocation
)"
@tableButtonClick="addFormData(arguments)"
></searchPage>
<!-- @filterBtnClickHandle="filterBtnClickHandle" -->
<!-- 其他参数 -->
<curren-Form
v-loading="loading"
v-if="active == 2"
class="page1"
size="medium"
ref="page1"
:searchData="other"
:searchForm="otherForm"
:searchOptions="Options"
:searchHandle="editHandle"
:rules="Rules"
:loading="loading"
@push="DataPush(arguments)"
@submitForm="editFormClick(arguments)"
>
</curren-Form>
<!-- <curren-Form
v-if="active === 4"
size="medium"
class="page3"
:searchData="previewFormData"
:searchForm="CreateForm | formData"
:searchHandle="editHandle"
:rules="Rules"
:loading="loading"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item class="formTable-box" prop="details">
<currenTable
:tableData="previewFormData.details"
:tableColumns="detailsTableColumns | formDataDetails"
:selectionTable="false"
>
</currenTable>
</el-form-item>
</template>
</curren-Form> -->
<div
v-if="active === step.length - 1 && pageStatus === 'success'"
class="page4"
>
<el-result icon="success" title="成功提示" subTitle="新增成功">
<template slot="extra">
<!-- <el-button type="primary" size="medium" @click="tuoFormPrint"
>打印托标签</el-button
>
<el-button type="primary" size="medium" @click="xbqFormPrint"
>打印箱标签</el-button
> -->
<el-button
v-for="item in successHandle"
:key="item.label"
:type="item.type"
size="medium"
@click="item.click()"
>{{ item.label }}</el-button
>
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
<div
v-if="active === step.length - 1 && pageStatus === 'error'"
class="page4"
>
<el-result icon="error" title="错误提示" subTitle="新增失败">
<template slot="extra">
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
</div>
</el-dialog>
</template>
<script>
import currenForm from "@/components/currenForm";
import currenTable from "@/components/currenTable";
import {
getPageList,
postCreateWithCondition,
postCreate,
} from "@/api/wms-api";
export default {
name: "stepsForm",
components: {
currenForm,
currenTable,
},
watch: {
active(val) {
if (val != 0) {
this.editHandle[0].label = "上一步";
} else {
this.editHandle[0].label = "取消";
}
},
},
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") {
data[index].type = "input";
} else if (key.type == "objectAutocomplete") {
data[index].type = "objectInput";
} else if (key.prop == "containerCode") data[index].disabled = "false";
});
return data;
},
},
props: {
//
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 [];
},
},
},
computed: {
stepFilters() {
let stepFilters = [];
const routeName = this.$route.meta.title;
this.step.forEach((key) => {
stepFilters.push(routeName.concat(key));
});
return stepFilters;
},
// autoAdvanced () {
// if (this.active == 1) {
// return this.advancedFilter(
// 'item-basic',
// this.pageListItemBasic,
// 'totalCountItemBasic',
// 'itemBasicData',
// this.oldSkipCountItemBasic
// )
// } else if (this.active == 2) {
// return this.advancedFilter(
// 'location',
// this.pageListLocation,
// 'totalCountLocation',
// 'locationData',
// this.oldSkipCountLocation
// )
// }
// },
},
data() {
return {
active: 0,
formReveal: 1,
pageStatus: "",
filterListParams: [],
itemBasicData: [],
isItemBasicData: [],
previewFormData: [],
totalCountItemBasic: 0,
oldSkipCountItemBasic: 1,
pageListItemBasic: {
condition: {
filters: [],
},
Sorting: "",
SkipCount: 0,
MaxResultCount: 100,
},
locationData: [],
isLocationData: [],
totalCountLocation: 0,
oldSkipCountLocation: 1,
pageListLocation: {
condition: {
filters: [],
},
Sorting: "",
SkipCount: 0,
MaxResultCount: 100,
},
other: {
otherParam: [],
},
otherForm: [
{
label: "状态",
prop: "otherParam",
type: "checkbox",
indeterminate:"true",
checkboxs: "radios",
},
],
otherFormData: {
countMethod: 0,
// type: 0,//
company: null,
description: null,
// beginTime: null,
// endTime: null,
planTime: null,
partCondition: {},
locCondition: {},
statusList: [],
worker: null,
warehouseCode: null,
remark: null,
requestType: null,
},
loading: false,
tableLoading: false,
session: null,
// step: ["", "", "", "", ""],
step: ["总体信息", "库位参数", "其他参数", "结果"],
editHandle: [
{ label: "取消", name: "cancel" },
{ label: "下一步", type: "primary", name: "determine" },
],
filterActionOptions:[{
value: '==',
label: '等于'
}, {
value: '!=',
label: '不等于'
}],
// (codevalue)
filterOptionCopyForMutiple:[],
//
filterCodeExclude:'INSPECT,HOLD,TRANSFERONTHEWAY',
};
},
mounted() {
this.session = JSON.parse(JSON.stringify(this.CreateFormData));
},
methods: {
// pda线
initSearchPageTableColums(){
// let _list = JSON.parse(JSON.stringify(this.$isTableColumns.Location));
let _list = JSON.parse(JSON.stringify(this.$isTableColumns.CountPlanByAddLocation));
_list.forEach(item => {
// pda 使 locationTypeForPADPlan 线
// Excel 使 locationTypeForExcelPlan
if(item.prop == 'type'){
item.filters = this.CreateFormData.requestType == 2 ? 'locationTypeForPADPlan' : 'locationTypeForExcelPlan'
}
});
return _list
},
//退
close(val) {
this.active = 0;
const filter ={
condition: {
filters: [],
},
Sorting: "",
SkipCount: 0,
MaxResultCount: 100,
}
this.pageListItemBasic = JSON.parse(JSON.stringify(filter))
this.pageListLocation = JSON.parse(JSON.stringify(filter))
const data = JSON.parse(JSON.stringify(this.session));
this.itemBasicData = []
this.locationData = []
this.$emit("close", data, val);
},
//autoComplete
DataPush(val) {
this.$emit("DataPush", val);
},
//autoComplete
detailsDataPush(val) {
this.$emit("detailsDataPush", val);
},
// 20230704
sxBtnClickHandle(data){
// code 20230705
this.$refs.searchTable.setScreenDataFilters(this.filterOptionCopyForMutiple)
},
//
advancedFilter(url, list, TotalCount, data, oldSkipCount) {
return () => {
list.SkipCount = (oldSkipCount - 1) * list.MaxResultCount;
this.tableLoading = true;
// 线 20230703
// Excel(this.CreateFormData.requestType == 1)2
// Excel(this.CreateFormData.requestType != 1)线5
let type_value = this.CreateFormData.requestType == 1 ? '2' : '5'
let _filter = {
action: "!=",
column: "type",
logic: "And",
value: type_value,
hide:true
}
//
let _filter_code = {
action: "!=",
column: "code",
logic: "And",
value: this.filterCodeExclude,
hide: true
}
if(this.pageListLocation.condition.filters.length <= 0){
this.pageListLocation.condition.filters.push(_filter)
this.pageListLocation.condition.filters.push(_filter_code)
}
// code 20230705
this.filterOptionCopyForMutiple = JSON.parse(JSON.stringify(list.condition.filters))
let _filters = []
// code
this.filterOptionCopyForMutiple.forEach((option)=>{
if(option.column == 'code'){
option.value.split(',').forEach((val,val_index)=>{
// != (And) == Or
let _logic = val_index == 0 ? option.logic : (option.action == '!=' ? 'And' : 'Or')
if((val || val == 0) && val.length > 0){
let _item = {
action: option.action,
column: option.column,
logic: _logic,
value: val,
}
_filters.push(_item)
}
})
}else{
_filters.push(option)
}
})
list.condition.filters = _filters
getPageList(list, url)
.then((res) => {
this[data] = res.items;
this[TotalCount] = res.totalCount;
this.tableLoading = false;
})
.catch(() => {
this.tableLoading = false;
});
};
},
//(emit)
AddNewAlterResultCount(val, url, list, TotalCount, data, oldSkipCount) {
list.MaxResultCount = val;
const Function = this.advancedFilter(
url,
list,
TotalCount,
data,
oldSkipCount
);
Function();
},
//(emit)
AddNewAlertoldSkipCount(val, url, list, TotalCount, data, oldSkipCount) {
oldSkipCount = val;
const Function = this.advancedFilter(
url,
list,
TotalCount,
data,
oldSkipCount
);
Function();
},
//
tuoFormPrint() {
this.$emit("tuoFormPrint");
},
//
xbqFormPrint() {
this.$emit("xbqFormPrint");
},
// //
// addNew (url, list, TotalCount, data, MaxResultItem) {
// list.SkipCount = 0
// list.MaxResultCount = JSON.parse(TotalCount)
// getPageList(list, url).then((res) => {
// this[data] = res.items
// list.MaxResultCount = MaxResultItem
// })
// },
//
addFormData(val) {
if (val[0] == "cancel") {
this.active--;
} else {
//
// if (this.active == 1) {
// const MaxResultItem = JSON.parse(
// this.pageListItemBasic.MaxResultCount
// );
// // this.addNew('item-basic', this.pageListItemBasic, this.totalCountItemBasic, 'isItemBasicData', MaxResultItem)
// // this.pageListItemBasic.MaxResultCount = MaxResultItem
// const Function = this.advancedFilter(
// "basedata/location",
// this.pageListLocation,
// "totalCountLocation",
// "locationData",
// this.oldSkipCountLocation
// );
// Function();
// this.$nextTick(()=>{
// this.active++;
// })
// }
//
if (this.active == 1) {
const MaxResultLocation = JSON.parse(
this.pageListLocation.MaxResultCount
);
// this.addNew('location', this.pageListLocation, this.totalCountLocation, 'isLocationData', MaxResultLocation)
// this.pageListLocation.MaxResultCount = MaxResultLocation
this.active++;
}
}
},
//
splitFormData(val) {
return new Promise((resolve, reject) => {
postCreateWithCondition(val, "wms/store/count-plan")
.then((res) => {
this.previewFormData = JSON.parse(
JSON.stringify(this.CreateFormData)
);
// delete this.previewFormData.details
this.$listAssign(this.previewFormData, res);
this.previewFormData.details = [];
res.details.forEach((item) => {
const details = JSON.parse(
JSON.stringify(...this.childTableData)
);
this.$listAssign(details, item);
this.previewFormData.details.push(details);
});
resolve();
})
.catch((err) => {
reject();
});
});
},
//
editFormClick(val) {
// Moment(this.CreateFormData.arriveTime).format()
if (val[0] == 0) {
if (this.active == 0) {
this.close(0);
} else {
this.active--;
}
} else {
val[1].validate((valid) => {
if (valid) {
//
if (this.active == 0) {
this.pageListLocation.condition.filters = []
const Function = this.advancedFilter(
// "basedata/item-basic",
// this.pageListItemBasic,
// "totalCountItemBasic",
// "itemBasicData",
// this.oldSkipCountItemBasic
'basedata/location',
this.pageListLocation,
'totalCountLocation',
'locationData',
this.oldSkipCountLocation
);
Function();
this.active++;
}
//
else if (this.active == 2) {
this.$listAssign(this.otherFormData, this.CreateFormData);
this.otherFormData.partCondition =
this.pageListItemBasic.condition;
this.otherFormData.locCondition = this.pageListLocation.condition;
this.otherFormData.statusList = [];
let checkboxArray = []
this.other.otherParam.forEach(item => {
if (item == '待检') {
checkboxArray.push(1)
} else if (item == '合格') {
checkboxArray.push(2)
} else if (item == '不合格') {
checkboxArray.push(3)
} else if (item == '隔离') {
checkboxArray.push(4)
} else if (item == '破坏') {
checkboxArray.push(5)
} else if (item == '冻结') {
checkboxArray.push(6)
}
})
// ', '', '', '', '', ''
this.otherFormData.statusList = checkboxArray;
this.otherFormData.vendCondition = {
filters:[]
}
if(this.otherFormData.statusList.length <= 0){
this.$warningMsg("请选择状态");
return
}
this.loading = true;
// this.otherFormData.requestType = 2
this.splitFormData(this.otherFormData).then(
(resolve) => {
this.pageStatus = "success";
this.active++;
this.loading = false;
},
(reject) => {
this.pageStatus = "error";
this.active++;
this.loading = false;
}
);
}
// else if (this.active == 4) {
// postCreate(this.previewFormData, 'count-plan').then(res => {
// this.pageStatus = 'success'
// this.active++
// this.loading = false
// }).catch(err => {
// this.pageStatus = 'error'
// this.active++
// this.loading = false
// })
// }
else {
this.$errorMsg("请检查表单");
}
}
});
}
},
},
};
</script>
<style lang="scss" scoped>
@import "./style/index.scss";
</style>
<style lang="scss">
#stepsForm{
.formButton{
text-align: right;
}
.searchPageComponents{
top: 130px !important;
}
.el-dialog__wrapper{
height: unset;
}
}
</style>

86
Code/Fe/src/components/StepsCountPlanForm/style/index.scss

@ -0,0 +1,86 @@
#stepsForm {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
::v-deep .el-steps {
padding-bottom: 15px;
.el-step__main {
.el-step__title {
line-height: 24px;
font-size: 14px;
}
}
}
.page1 {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.page2 {
flex: 1;
overflow: hidden;
position: relative;
::v-deep & >.el-dialog {
width: 100%;
height: 100%;
& >.el-dialog__header {
padding: 0 !important;
}
& > .el-dialog__body {
padding-top: 0;
}
}
}
.page3 {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-bottom: 54px;
overflow: hidden;
overflow-y: auto;
::v-deep .el-form {
flex: 1;
display: flex;
flex-direction: column;
.el-row {
flex: 1;
flex-wrap: wrap;
overflow: hidden;
overflow-y: auto;
}
.formTable-box {
flex: 1;
overflow: hidden;
overflow-y: auto;
.el-form-item__content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
margin: 0 !important;
}
}
}
::v-deep .formButton {
position: absolute;
bottom: 0;
right: 0;
z-index: 3;
}
}
}

459
Code/Fe/src/components/StepsForm/_index.vue

@ -0,0 +1,459 @@
<template>
<el-dialog
:title="formTitle"
v-loading="loading"
v-if="displayDialog.newDialog"
:visible="true"
:fullscreen="true"
:append-to-body="false"
:modal="false"
:modal-append-to-body="false"
:show-close="false"
>
<div id="stepsForm">
<el-steps
:active="active"
process-status="finish"
finish-status="success"
:align-center="true"
>
<el-step
v-for="(item, index) in stepFilters"
:key="index"
:title="item"
></el-step>
</el-steps>
<curren-Form
v-if="active == 0"
class="page1"
size="medium"
ref="page1"
:searchData="CreateFormData"
:searchForm="CreateForm"
:searchOptions="Options"
:searchHandle="editHandle"
:rules="Rules"
@changeInput="changeInput"
@changeSelect="changeSelect"
@push="DataPush(arguments)"
@submitForm="editFormClick(arguments)"
>
</curren-Form>
<curren-Form
v-if="active === 1"
class="page2"
size="medium"
:searchData="CreateFormData"
:searchHandle="editHandle"
:rules="Rules"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item class="formTable-box" prop="details" v-if="active == 1">
<div class="heder" v-if="addClick">
<span @click="openAddNew">添加一行</span>
</div>
<currenTable
:tableData="CreateFormData.details"
:searchOptions="Options"
:tableColumns="detailsTableColumns"
:selectionTable="false"
@push="detailsDataPush(arguments)"
>
<template v-if="showDeleteButton">
<el-table-column
label="操作"
align="center"
fixed="right"
width="100px"
>
<template slot-scope="scope">
<div class="childTable" @click="childTable($event, scope)">
<span>删除</span>
</div>
</template>
</el-table-column>
</template>
</currenTable>
</el-form-item>
</template>
</curren-Form>
<curren-Form
v-if="active === 2"
size="medium"
class="page3"
:searchData="previewFormData"
:searchForm="CreateForm | formData"
:searchHandle="editHandle"
:rules="Rules"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item class="formTable-box" prop="details">
<currenTable
:tableData="previewFormData.details"
:tableColumns="detailsTableColumns | formDataDetails"
:selectionTable="false"
>
</currenTable>
</el-form-item>
</template>
</curren-Form>
<div
v-if="active === step.length - 1 && pageStatus === 'success'"
class="page4"
>
<el-result
icon="success"
title="成功提示"
:subTitle="formTitle + '成功'"
>
<template slot="extra">
<!-- <el-button type="primary" size="medium" @click="tuoFormPrint"
>打印托标签</el-button
>
<el-button type="primary" size="medium" @click="xbqFormPrint"
>打印箱标签</el-button
> -->
<el-button
v-for="item in successHandle"
:key="item.label"
:type="item.type"
size="medium"
@click="successClick(item.click())"
>{{ item.label }}</el-button
>
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
<div
v-if="active === step.length - 1 && pageStatus === 'error'"
class="page4"
>
<el-result icon="error" title="错误提示" :subTitle="formTitle + '失败'">
<template slot="extra">
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
</div>
</el-dialog>
</template>
<script>
import currenForm from "@/components/currenForm"
import currenTable from "@/components/currenTable"
export default {
name: 'stepsForm',
components: {
currenForm,
currenTable
},
watch: {
active (val) {
if (val != 0) {
this.editHandle[0].label = '上一步'
} else {
this.editHandle[0].label = '取消'
}
},
stepArray(newVal, oldVal){
this.step = newVal
}
},
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: {
//
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
}
}
},
computed: {
stepFilters () {
let stepFilters = []
const routeName = this.$route.meta.title
this.step.forEach(key => {
stepFilters.push(routeName.concat(key))
})
return stepFilters
},
},
data () {
return {
active: 0,
formReveal: 1,
activeStep: 1,
pageStatus: '',
addClick: this.addClickButton,
showDeleteButton: this.isShowDeleteButton,
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))
},
methods: {
//退
close (val) {
this.active = 0
// const pageRef = this.Refs[1]
const data = JSON.parse(JSON.stringify(this.session))
this.$emit('close', data, val)
},
//autoComplete
DataPush (val) {
this.$emit("DataPush", val)
},
//autoComplete
detailsDataPush (val) {
this.$emit("detailsDataPush", val)
},
// //
// tuoFormPrint () {
// this.$emit('tuoFormPrint')
// },
// //
// xbqFormPrint () {
// this.$emit('xbqFormPrint')
// },
successClick (val) {
this.loading = true
val.then(res => {
this.loading = false
}, reason => {
this.loading = false
})
},
editFormClick (val) {
// Moment(this.CreateFormData.arriveTime).format()
if (val[0] == 0) {
if (this.active == 0) {
// debugger
// this.active = ''
this.close(0)
} else {
if (this.active == 2) {
this.active = this.active - this.activeStep
} else {
this.active--
}
}
} else {
val[1].validate((valid) => {
if (valid) {
const parent = this.$parent
if (this.active < this.step.length - 1) {
this.loading = true
if (this.active == this.step.length - 2) {
parent.stepsSubmit().then(res => {
if (res == '质检校验返回') {
this.loading = false
} else {
this.pageStatus = 'success'
this.active++
this.loading = false
}
}, reason => {
this.pageStatus = 'error'
this.active++
this.loading = false
}).catch(err=>{
this.loading = false
})
} else if (this.active == this.step.length - 3) {
parent.PalletlFunction().then(res => {
//
if (res == '质检任务跳过详情') {
parent.stepsSubmit().then(res => {
this.pageStatus = 'success'
this.active = this.active + 2
this.loading = false
}, reason => {
this.pageStatus = 'error'
this.active = this.active + 2
this.loading = false
}).catch(err=>{
this.loading = false
})
} else {
this.active++
}
this.loading = false
}, reason => {
this.loading = false
}).catch(err=>{
this.loading = false
})
} else {
parent.stepsHandelOne().then(res => {
if (res) {
this.addClick = res.open
this.active = this.active + res.index
this.activeStep = res.index
} else {
this.activeStep = 1
this.active++
}
this.loading = false
}, reason => {
this.loading = false
}).catch(err=>{
this.loading = false
})
}
}
} else {
this.$errorMsg('请检查表单')
}
})
}
},
//
openAddNew () {
const parent = this.$parent
parent.openAddNew()
},
childTable (e, val) {
const parent = this.$parent
parent.childTable(e, val)
},
changeInput(prop,val){
this.$emit("changeInput", prop, val)
},
changeSelect(prop,val){
this.$emit("changeSelect", prop, val)
},
}
}
</script>
<style lang="scss" scoped>
@import "./style/index.scss";
</style>

551
Code/Fe/src/components/StepsForm/index.vue

@ -0,0 +1,551 @@
<template>
<el-dialog
:title="formTitle"
v-loading="loading"
v-if="displayDialog.newDialog"
:visible="true"
:fullscreen="true"
:append-to-body="false"
:modal="false"
:modal-append-to-body="false"
:show-close="false"
>
<div id="stepsForm">
<el-steps
:active="active"
process-status="finish"
finish-status="success"
:align-center="true"
>
<el-step
v-for="(item, index) in stepFilters"
:key="index"
:title="item"
></el-step>
</el-steps>
<curren-Form
v-if="active == 0"
class="page1"
size="medium"
ref="page1"
:searchData="CreateFormData"
:searchForm="CreateForm"
:searchOptions="Options"
:searchHandle="editHandle"
:rules="Rules"
@changeInput="changeInput"
@changeSelect="changeSelect"
@push="DataPush(arguments)"
@submitForm="editFormClick(arguments)"
>
</curren-Form>
<curren-Form
v-if="active === 1"
class="page2"
size="medium"
:searchData="CreateFormData"
:searchHandle="editHandle"
:rules="Rules"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item class="formTable-box" prop="details" v-if="active == 1">
<div class="heder">
<el-button
v-if="addClick"
type="primary"
@click="openAddNew"
icon="el-icon-plus"
size="mini"
>添加一行</el-button>
<el-button
v-if="importFormButton"
type="success"
icon="el-icon-download"
@click="openImportForm"
size="mini"
>导入</el-button>
</div>
<currenTable
:tableData="CreateFormData.details"
:searchOptions="Options"
:tableColumns="detailsTableColumns"
:selectionTable="false"
@push="detailsDataPush(arguments)"
>
<template v-if="showDeleteButton">
<el-table-column
label="操作"
align="center"
fixed="right"
width="100px"
>
<template slot-scope="scope">
<div class="childTable" @click="childTable($event, scope)">
<span>删除</span>
</div>
</template>
</el-table-column>
</template>
</currenTable>
</el-form-item>
</template>
</curren-Form>
<curren-Form
v-if="active === 2"
size="medium"
class="page3"
:searchData="previewFormData"
:searchForm="CreateForm | formData"
:searchHandle="editHandle"
:rules="Rules"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item class="formTable-box" prop="details">
<currenTable
:tableData="previewFormData.details"
:tableColumns="detailsTableColumns | formDataDetails"
:selectionTable="false"
>
<template v-if="showPreviewFormDeleteButton">
<el-table-column
label="操作"
align="center"
fixed="right"
width="100px"
>
<template slot-scope="scope">
<div @click="previewChildRemove($event, scope)">
<span style="color:red">删除</span>
</div>
</template>
</el-table-column>
</template>
</currenTable>
</el-form-item>
</template>
</curren-Form>
<div
v-if="active === step.length - 1 && pageStatus === 'success'"
class="page4"
>
<el-result
icon="success"
title="成功提示"
:subTitle="formTitle + '成功'"
>
<template slot="extra">
<!-- <el-button type="primary" size="medium" @click="tuoFormPrint"
>打印托标签</el-button
>
<el-button type="primary" size="medium" @click="xbqFormPrint"
>打印箱标签</el-button
> -->
<el-button
v-for="item in successHandle"
:key="item.label"
:type="item.type"
size="medium"
@click="successClick(item.click())"
>{{ item.label }}</el-button
>
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
<div
v-if="active === step.length - 1 && pageStatus === 'error'"
class="page4"
>
<el-result icon="error" title="错误提示" :subTitle="formTitle + '失败'">
<template slot="extra">
<el-button type="primary" size="medium" @click="close(1)"
>退出</el-button
>
</template>
</el-result>
</div>
</div>
</el-dialog>
</template>
<script>
import currenForm from "@/components/currenForm"
import currenTable from "@/components/currenTable"
export default {
name: 'stepsForm',
components: {
currenForm,
currenTable
},
watch: {
active (val) {
if (val != 0) {
this.editHandle=[
{ label: "上一步", name: "cancel" },
{ label: "下一步", type: "primary", name: "determine" },
];
} else {
if(this.hideFirstActiveCancel){
this.editHandle=[
{ label: "下一步", type: "primary", name: "determine" },
];
}else{
this.editHandle=[
{ label: "取消", name: "cancel" },
{ label: "下一步", type: "primary", name: "determine" },
];
}
}
},
stepArray(newVal, oldVal){
this.step = newVal
}
},
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: {
//
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
}
},
//
importFormButton: {
type: Boolean,
default: () => {
return false
}
},
//
isShowDeleteButton: {
type: Boolean,
default: () => {
return true
}
},
//
isHideFirstActiveCancel:{
type: Boolean,
default: () => {
return false
}
},
//
showPreviewFormDeleteButton:{
type: Boolean,
default: () => {
return false
}
}
},
computed: {
stepFilters () {
let stepFilters = []
const routeName = this.$route.meta.title
this.step.forEach(key => {
stepFilters.push(routeName.concat(key))
})
return stepFilters
},
},
data () {
return {
active: 0,
formReveal: 1,
activeStep: 1,
pageStatus: '',
addClick: this.addClickButton,//
importForm:this.importFormButton,//
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: {
//退
close (val) {
this.active = 0
// const pageRef = this.Refs[1]
const data = JSON.parse(JSON.stringify(this.session))
this.$emit('close', data, val)
},
//autoComplete
DataPush (val) {
this.$emit("DataPush", val)
},
//autoComplete
detailsDataPush (val) {
this.$emit("detailsDataPush", val)
},
// //
// tuoFormPrint () {
// this.$emit('tuoFormPrint')
// },
// //
// xbqFormPrint () {
// this.$emit('xbqFormPrint')
// },
successClick (val) {
this.loading = true
val.then(res => {
this.loading = false
}, reason => {
this.loading = false
}).catch(err=>{
this.loading = false
})
},
editFormClick (val) {
// Moment(this.CreateFormData.arriveTime).format()
// if (val[0] == 0) {
if (val[2].name == "cancel") {
if (this.active == 0) {
// debugger
// this.active = ''
this.close(0)
} else {
if (this.active == 2) {
this.active = this.active - this.activeStep
} else {
this.active--
}
}
} else {
val[1].validate((valid) => {
if (valid) {
const parent = this.$parent
if (this.active < this.step.length - 1) {
this.loading = true
if (this.active == this.step.length - 2) {
parent.stepsSubmit().then(res => {
if (res == '质检校验返回') {
this.loading = false
} else {
this.pageStatus = 'success'
this.active++
this.loading = false
}
}, reason => {
this.loading = false
if(reason=="return")return
this.pageStatus = 'error'
this.active++
this.loading = false
}).catch(err=>{
this.loading = false
})
} else if (this.active == this.step.length - 3) {
parent.PalletlFunction().then(res => {
//
if (res == '质检任务跳过详情') {
parent.stepsSubmit().then(res => {
this.pageStatus = 'success'
this.active = this.active + 2
this.loading = false
}, reason => {
this.pageStatus = 'error'
this.active = this.active + 2
this.loading = false
}).catch(err=>{
this.loading = false
})
} else {
this.active++
}
this.loading = false
}, reason => {
this.loading = false
}).catch(err=>{
this.loading = false
})
} else {
parent.stepsHandelOne().then(res => {
if (res) {
this.addClick = res.open
this.active = this.active + res.index
this.activeStep = res.index
} else {
this.activeStep = 1
this.active++
}
this.loading = false
}, reason => {
this.loading = false
}).catch(err=>{
this.loading = false
})
}
}
} else {
this.$errorMsg('请检查表单')
}
})
}
},
//
openAddNew () {
const parent = this.$parent
parent.openAddNew()
},
//
openImportForm(){
const parent = this.$parent
parent.openImportFormHandle()
// this.displayDialog.importDialog = true
},
childTable (e, val) {
const parent = this.$parent
parent.childTable(e, val)
},
changeInput(prop,val){
this.$emit("changeInput", prop, val)
},
changeSelect(prop,val){
this.$emit("changeSelect", prop, val)
},
//
previewChildRemove(e, val) {
this.$confirm('您确定删除吗, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.previewFormData.details.splice(val.$index, 1)
// this.$emit("removePreviewFormRow",this.previewFormData)
}).catch(() => {
});
},
}
}
</script>
<style lang="scss" scoped>
@import "./style/index.scss";
</style>

134
Code/Fe/src/components/StepsForm/style/index.scss

@ -0,0 +1,134 @@
#stepsForm {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
::v-deep .el-steps {
padding-bottom: 15px;
.el-step__main {
.el-step__title {
line-height: 24px;
font-size: 14px;
}
}
}
.page1 {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
overflow-y: auto;
}
.page2 {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
padding-bottom: 54px;
overflow: hidden;
overflow-y: auto;
::v-deep .el-form {
flex: 1;
display: flex;
.el-row {
display: none;
}
.formTable-box {
flex: 1;
overflow: hidden;
overflow-y: auto;
.el-form-item__content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
margin: 0 !important;
.heder {
padding: 5px 0;
text-align: center;
font-size: 18px;
button{
margin: 0 10px;
}
}
.el-table {
flex: 1;
.childTable {
display: flex;
justify-content: space-around;
span {
cursor: pointer;
&:nth-child(1) {
color: red;
}
&:nth-child(2) {
color: green;
}
}
}
}
}
}
}
::v-deep .formButton {
position: absolute;
bottom: 0;
right: 0;
z-index: 3;
}
}
.page3 {
flex: 1;
display: flex;
flex-direction: column;
padding-bottom: 54px;
overflow: hidden;
overflow-y: auto;
::v-deep .el-form {
flex: 1;
display: flex;
flex-direction: column;
.el-row {
flex: 1;
flex-wrap: wrap;
}
.formTable-box {
flex: 1;
.el-form-item__content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
margin: 0 !important;
}
}
}
::v-deep .formButton {
position: absolute;
bottom: 0;
right: 0;
z-index: 3;
}
}
}

213
Code/Fe/src/components/StepsFormAlone/index.vue

@ -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},
]
}
},
// verticalstepsAlignCenter=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>

44
Code/Fe/src/components/StepsFormAlone/style/index.scss

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

62
Code/Fe/src/components/SvgIcon/index.vue

@ -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>

173
Code/Fe/src/components/ThemePicker/index.vue

@ -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>

380
Code/Fe/src/components/UploadExcel/index.vue

@ -0,0 +1,380 @@
<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"
import { postInventoryLabelCode } from "@/api/wms-core"
import { supplierAsnExcel } from "@/filters/excelOrReportsOption";
import {SupplierAsnCtypeStaBack} from "@/filters/status"
export default {
name:"UploadExcel",
mixins:[mixins],
watch: {
show () {
this.reset()
}
},
props: {
//
fixedArr:{
type:Array,
default: () => {
return [ {name:supplierAsnExcel.details.packingCode,value:"right"} ]
}
},
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
// }
//
// this.getPackingCode(arr)
// },
//
getPackingCode(header, results){
let createManyParams = [];
results.forEach(item => {
let _item = {
itemCode: item[supplierAsnExcel.details.itemCode] || "",
lot: item[supplierAsnExcel.details.lot] || "",
labelType:1,
qty: Number(item[supplierAsnExcel.details.qty]),
uom: item[supplierAsnExcel.details.uom],
stdPackQty:0,
company:localStorage.getItem("company"),
// poNumber:item[supplierAsnExcel.poNumber],
// number:item[supplierAsnExcel.number],
supplierCode:item[supplierAsnExcel.supplierCode],
planUserCode:item[supplierAsnExcel.planUserCode],
contactUserName:item[supplierAsnExcel.planUserCode],
planArriveDate:item[supplierAsnExcel.planArriveDate],
shipDate:item[supplierAsnExcel.shipDate],
remark:item[supplierAsnExcel.remark],
ctype:SupplierAsnCtypeStaBack(item[supplierAsnExcel.details.ctype]),
projectCode:item[supplierAsnExcel.details.projectCode],
itemCode:item[supplierAsnExcel.details.itemCode],
recommendErpCode:item[supplierAsnExcel.details.recommendErpCode],
qty:item[supplierAsnExcel.details.qty],
uom:item[supplierAsnExcel.details.uom],
lot:item[supplierAsnExcel.details.lot],
produceDate:item[supplierAsnExcel.details.produceDate],
expireDate:item[supplierAsnExcel.details.expireDate],
};
createManyParams.push(_item)
});
postInventoryLabelCode(createManyParams)
.then((res,a) => {
let _header = JSON.parse(JSON.stringify(header))
_header.push(supplierAsnExcel.details.packingCode)
res.forEach((v,k)=>{
this.$set(results[k],supplierAsnExcel.details.packingCode, res[k].code)
})
this.successShowExcel(_header, results)
}).catch(err => {
console.log(err)
this.loading = false
this.$message.error('导入失败,请重新导入');
// this.reset()
})
},
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)
// this.getPackingCode(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>

77
Code/Fe/src/components/batchButton/index.vue

@ -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>

559
Code/Fe/src/components/commonTabel-drawer/index.vue

@ -0,0 +1,559 @@
<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="heder-img">
<img
src="@/assets/img/drawerHeader.png"
alt=""
style="width: 100%; height: 100%"
/>
</div> -->
<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>
<!-- currenTableDetails 组件 明细中带分页功能 -->
<umyTable
v-if="scope.value == 'mx'"
:tableBorder="true"
:tableData="propsData.details"
:propsData="propsData"
:tableColumns="tableColumns"
:selectionTable="selectionTable"
:requiredRules="false"
:setUTableHeight="260"
@sortChange="sortChange"
@handleSelectionChange="handleSelectionChange"
@inlineDialog="inlineDialog"
@buttonClick="buttonClick"
>
<template>
<slot></slot>
</template>
</umyTable>
<!-- 明细页码 -->
<pagination
v-if="scope.value == 'mx'"
:totalCount="totalCount"
:pagesizeProps="MaxResultCount"
@SizeChange="alterResultCountDetails"
@CurrentChange="alertoldSkipCountDetails"
:currentPageProps="currentPage"
></pagination>
<!-- 新增汇总 表头 区分明细表头使用 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>
<!-- 自定义扩展tree的形式 目前使用位置物品清单信息-子物品层级 todo:待优化-->
<currenTable
v-if="
scope.value == zdyValue &&
scope.value == 'zwlcj'
"
:tableLoading="tableLoading"
:tableData="otherData"
:tableColumns="zdyTableColumns"
:selectionTable="selectionTable"
:requiredRules="false"
@sortChange="sortChange"
@handleSelectionChange="handleSelectionChange"
@inlineDialog="inlineDialog"
:treeProps="{children: 'children', hasChildren: 'hasChildren'}"
@buttonClick="buttonClick"
>
<template>
<slot></slot>
</template>
</currenTable>
</template>
</curren-tabs>
</div>
<div class="drawer-Shut" @click="drawerShut">
<el-button type="danger" size="mini">关闭</el-button>
</div>
</el-drawer>
</template>
<script>
import { getListByItemcode,byItem,byProduct,byComponent,bySupplierCode,byLocation,byLocationCode,
relationByLocationCode,byComponentCJ,purRecNoteCustomInfo,EnumPurchaseReceiptInspect
} from "@/api/wms-api"
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"
export default {
name: 'currenTabel-drawer',
components: {
pagination,
currenButton,
currenDescriptions,
currenTabs,
currenTable,
},
props: {
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) {
this.initDropdownTabsData = [{
label: "详情",
name: 'xq'
},
{
label: "明细",
name: 'mx'
},
{
label: "汇总",
name: 'hz'
}]
if (this.propsData.details == undefined || !this.propsData.details.length) {
this.initDropdownTabsData = [{
label: "详情",
name: 'xq'
}]
return this.initDropdownTabsData
}
if (this.propsData.summaryDetails == undefined || !this.propsData.summaryDetails.length ) {
this.initDropdownTabsData = [{
label: "详情",
name: 'xq'
},
{
label: "明细",
name: 'mx'
}]
return this.initDropdownTabsData
}
}
return this.initDropdownTabsData
}
},
},
mounted () {
},
data () {
return {
otherData:[], // tabs
zdyTableColumns:[], //
zdyValue:'', //
// firstTabs:'xq',
initDropdownTabsData:[
{
label: "详情",
name: 'xq'
},
{
label: "明细",
name: 'mx'
},
{
label: "汇总",
name: 'hz'
}
]
}
},
methods: {
handleCommand (command) {
this.$emit('handleCommand', command)
},
drawerShut () {
this.$emit('drawerShut', false)
},
tableButtonClick (val) {
this.$emit('drawerbutton', val)
},
//
sortChange (data) {
this.$emit('sortChange', data)
},
//selection
handleSelectionChange (val) {
this.$emit("handleSelectionChange", val)
},
//nameemit
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);
},
// 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 == 'byItem') {
byItem(this.propsData.code, 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 == 'byProduct') {
byProduct({product:this.propsData.product}, 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 == 'byComponent') {
byComponent({component:this.propsData.component}, 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 == 'byComponentCJ') {
this.otherData = []
byComponentCJ({component:this.propsData.component}, item.url).then(res => {
let zdyTableColumnsJSON = JSON.parse(JSON.stringify(this.$isTableColumns[item.tableColumns]));
delete zdyTableColumnsJSON[0].type
this.zdyTableColumns = zdyTableColumnsJSON
this.otherData = res
this.recursion(this.otherData)
parent.tableLoading = false
}).catch(err => {
console.log(err)
parent.tableLoading = false
})
} else if (item.functionName == 'bySupplierCode') {
bySupplierCode({supplierCode:this.propsData.code}, 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 == 'byLocation') {
byLocation(this.propsData.code==null?this.propsData.locationCode:this.propsData.code, item.url).then(res => {
let zdyTableColumnsJSON = JSON.parse(JSON.stringify(this.$isTableColumns[item.tableColumns]));
delete zdyTableColumnsJSON[0].type
this.zdyTableColumns = zdyTableColumnsJSON
this.otherData = res
this.o
parent.tableLoading = false
}).catch(err => {
console.log(err)
parent.tableLoading = false
})
} else if (item.functionName == 'byLocationCode') {
byLocationCode({locationCode: this.propsData.code}, item.url).then(res => {
let itemData = []
itemData.push(res)
let zdyTableColumnsJSON = JSON.parse(JSON.stringify(this.$isTableColumns[item.tableColumns]));
delete zdyTableColumnsJSON[0].type
this.zdyTableColumns = zdyTableColumnsJSON
this.otherData = itemData
parent.tableLoading = false
}).catch(err => {
console.log(err)
parent.tableLoading = false
})
}
// ---
else if (item.functionName == 'relationByLocationCode') {
relationByLocationCode({locationCode: this.propsData.code}, 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 == "purRecNoteCustomInfo"){
parent.Loading.DrawerLoading = true
purRecNoteCustomInfo( item.url,this.propsData.id).then(res => {
let zdyTableColumnsJSON = JSON.parse(JSON.stringify(this.$isTableColumns[item.tableColumns]));
delete zdyTableColumnsJSON[0].type
this.zdyTableColumns = zdyTableColumnsJSON
this.otherData = res
parent.Loading.DrawerLoading = false
}).catch(err => {
console.log(err)
parent.Loading.DrawerLoading = false
})
}
// 退-TAB-
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
}
}
}
})
},
//
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>

122
Code/Fe/src/components/commonTabel-drawer/style/index.scss

@ -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;
}

349
Code/Fe/src/components/conditionFilters/index.vue

@ -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>

46
Code/Fe/src/components/conditionFilters/style/index.scss

@ -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;
}
}

107
Code/Fe/src/components/currenButton/index.vue

@ -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>

60
Code/Fe/src/components/currenButton/innerButton.vue

@ -0,0 +1,60 @@
<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)"
>{{ 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>

165
Code/Fe/src/components/currenDescriptions/index.vue

@ -0,0 +1,165 @@
<template>
<el-descriptions
: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/index"
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>

888
Code/Fe/src/components/currenForm/index.vue

@ -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) ||
searchOptions['options']"
: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)
}
}
},
// inputonkeyup
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);
},
// filterSelectoption
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>

761
Code/Fe/src/components/currenTable/index.vue

@ -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)
}
}
},
// inputonkeyup
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);
},
//nameemit
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>

309
Code/Fe/src/components/currenTableFlex/index.vue

@ -0,0 +1,309 @@
<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 -->
<currenTable
class="flexTable"
:tableData="flexTableData"
:searchOptions="flexSearchOptions"
:tableColumns="flexTableColumns"
:selectionTable="selectionTable"
:isShowIndex="isShowIndex"
@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>
</currenTable>
</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: {
//
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>

12
Code/Fe/src/components/currenTableFlex/style/index.scss

@ -0,0 +1,12 @@
.currenTableFlex{
height: 100%;
display: flex;
flex-direction: column;
.flexTable{
height: 100%;
}
.headerButtons{
text-align: center;
margin-bottom: 20px;
}
}

57
Code/Fe/src/components/currenTabs/index.vue

@ -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>

82
Code/Fe/src/components/currenUpload/index.vue

@ -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>

72
Code/Fe/src/components/currenUploadList/index.vue

@ -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>

100
Code/Fe/src/components/currenUploadPictureCard/index.vue

@ -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>

306
Code/Fe/src/components/filterForDetailPage/index.vue

@ -0,0 +1,306 @@
<template>
<div class="filterForDetailPage">
<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)"
>
<div
class="filterForDetailPage-list"
v-loading="Loading.tableLoading"
>
<!-- 列表 -->
<tablePagination
v-if="dialogShow"
:currenButtonData="currenButtonData"
:tableData="tableData"
:tableLoading="Loading.tableLoading"
:tableColumns="listColumns"
:totalCount="totalCount"
:multipleSelection="multipleSelection"
:MaxResultCount="PageListParams.MaxResultCount"
:setUTableHeight="setUTableHeight"
@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"
>
<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"
:show-close="true"
>
<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 { TestSchoolDetailList,TestSchoolDetailList_delete } from "@/api/wms-interface"
import * as interfaceApi from "@/api/wms-interface"
import {getListDesById,getPageListForDetail} from "@/api/wms-api"
import * as allUrlOption from '@/utils/baseData/urlOption'
export default {
name: 'filterForDetailPage',
mixins: [
tableMixins,
TableHeaderMixins,
mixins,
filterSelectMixins,
LoadingMixins
],
components:{
currenDescriptions
},
props: {
// app-main100%
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: true,
},
// api
DeleteApi: {
type: String,
default: null
},
// -
listColumns:{
type: Array,
default: null
},
// -
parentColumns:{
type: Array,
default: null
},
showHandleButtons:{
type:Array,
default:() => {
return ['showParent','fresh','filter'];//'add','edit' 'delete'
}
},
// 2
column: {
type: Number,
default: 2
},
//
direction: {
type: String,
default: 'horizontal'
},
},
data () {
return {
dialogShow:true,
URLOption_detailList:allUrlOption[this.$route.name].detailListURL,//-
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,//-
}
},
mounted(){
this.paging()
this.initHandleButtons()
},
methods: {
//
initHandleButtons(){
//
let _arr_header = []
if(this.showHandleButtons.indexOf('add') >= 0){_arr_header.push(this.defaultAddBtn())}
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)
// interfaceApi[this.URLOption_detailList](this.PageListParams)
.then(result => {
this.Loading.tableLoading = false
this.tableData = []
result.items.forEach(item=>{
item.deleteTipVisible = false
this.tableData.push(item)
})
this.totalCount = result.totalCount
this.pagingCallback(callback)
})
.catch(err => {
this.Loading.tableLoading = false
this.$message.error("数据获取失败")
})
},
//
showParentHandleForDetail(data){
this.showParentTitle = `[${data.studentName}] 主表信息`
this.showParentDialog = true
this.showParentLoading = true
getListDesById(this.URLOption_parent,data.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 {
.el-dialog__body{
padding-bottom: 20px !important;
}
.fullPageCover{
height: calc(100% - 380px) !important;
}
}
.filterForDetailPage-list{
height: calc(100% - 320px);
overflow: auto;
}
</style>

214
Code/Fe/src/components/filterSelect/index.vue

@ -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:[],
//filterableremotetrueremote-methodremote-method
// getPageList
// truefalsetruefalse
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="正在加载"
// apigetPageList
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})
}
}
// apigetPagegetFilterList 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){
// 100A
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>

206
Code/Fe/src/components/handelFrom/index.vue

@ -0,0 +1,206 @@
<template>
<el-dialog
:title="formTitle"
v-loading="loading"
v-if="displayDialog"
:visible="true"
:fullscreen="true"
:modal="false"
:modal-append-to-body="false"
:show-close="false"
style="z-index:11111"
>
<curren-Form
class="handleForm"
size="medium"
:searchData="CreateFormData"
:searchForm="CreateForm"
:searchHandle="editHandle"
:searchOptions="Options"
:rules="Rules"
@submitForm="editFormClick(arguments)"
>
<template>
<el-form-item
class="formTable-box"
prop="details"
v-if="CreateFormData.details"
>
<currenTable
:tableData="CreateFormData.details"
:searchOptions="Options"
:tableColumns="detailsTableColumns"
:selectionTable="selectionTable"
:isShowIndex="isShowIndex"
@handleSelectionChange="handleSelectionChange"
@buttonClick="buttonClick"
>
<template>
<slot></slot>
</template>
</currenTable>
</el-form-item>
</template>
</curren-Form>
</el-dialog>
</template>
<script>
export default {
props: {
//
formTitle: {
type: String,
default: ''
},
//
displayDialog: {
type: Boolean,
default: () => {
return false
}
},
//
CreateFormData: {
type: Object,
default: () => {
return {}
}
},
//form
CreateForm: {
type: Array,
default: () => {
return []
}
},
//
Rules: {
type: Object,
default: () => {
return {}
}
},
//
Options: {
type: Object,
default: () => {
return {}
}
},
//table
detailsTableColumns: {
type: Array,
default: () => {
return []
}
},
selectionTable:{
type: Boolean,
default: () => {
return false
}
},
//
isShowIndex: {
type: Boolean,
default: false,
},
editHandle: {
type: Array,
default: () => {
return [
{ label: "取消", name: "cancel" },
{ label: "确定", type: "primary", name: "determine" },
];
},
},
// loading: {
// type: Boolean,
// default: false
// },
},
data () {
return {
loading: false,
// editHandle: [
// { label: "", name: "cancel" },
// { label: "", type: "primary", name: "determine" },
// ],
}
},
methods: {
//
editFormClick (val) {
if (val[0] == 0) {
//
this.$emit('update:displayDialog', false)
if(val[2].handleEvent)val[2].handleEvent()
} else if(val[0] == 1){
//
val[1].validate((valid) => {
if (valid) {
const parent = this.$parent
this.loading = true
parent.handleFormSubmit().then(res => {
this.loading = false
}, err => {
this.loading = false
})
} else {
this.$errorMsg('请检查表单')
return false;
}
});
} else {
//
if(val[2].handleEvent)val[2].handleEvent()
}
},
handleSelectionChange(val){
this.$emit("handleSelectionChange", val);
},
//
buttonClick(row,index) {
this.$emit("buttonClick", row,index);
},
}
}
</script>
<style lang="scss" scoped>
.handleForm {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
::v-deep .el-form {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
.el-row {
flex: 2;
flex-wrap: wrap;
overflow: hidden;
overflow-y: auto;
}
.formTable-box {
flex: 2;
overflow: hidden;
.el-form-item__content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0 !important;
}
}
}
.el-table {
height: 500px !important;
}
}
</style>

298
Code/Fe/src/components/importFile/index.vue

@ -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>

298
Code/Fe/src/components/newAndEdiDialog/index.vue

@ -0,0 +1,298 @@
<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);
},
// formchange
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;
}
.dialogOuterTitle{
position: relative;
padding: 20px 0;
font-size: 18px;
height: 60px;
overflow: hidden;
color: #333;
font-weight: bold;
padding-left: 18px;
&::before{
content: "";
position: absolute;
left: 0;
top: 22px;
width: 5px;
height: 22px;
background: #1890ff;
}
}
::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>

354
Code/Fe/src/components/newAndEdiDialogForDetail/index.vue

@ -0,0 +1,354 @@
<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>
<div v-if="active === 0" class="currentFormAndTable">
<curren-Form
size="medium"
class="newAndEdiDialogForDetail"
:searchData="FormData"
:searchForm="Form"
:searchOptions="Options"
:searchHandle="Handle"
:rules="Rules"
@changeInput="changeInput"
@push="DataPush(arguments)"
@submitForm="FormClick(arguments)"
@radioChange="radioChange"
@changeSelect="changeSelect"
>
<!-- <template>
<div class="addDetailsContent">
<div class="title">添加明细数据</div>
<div class="tableBox">
<currenTableFlex
:flexTableData="flexTableData"
:flexSearchOptions="Options"
:flexTableColumns="flexTableColumns"
:showAddBtn="true"
:showAllDeleteButton="true"
></currenTableFlex>
</div>
</div>
</template> -->
<!-- <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 class="addDetailsContent" v-if="active === 0">
<div class="title">添加明细数据</div>
<currenTableFlex
:flexTableData="flexTableData"
:flexSearchOptions="editOptions"
:flexTableColumns="flexTableColumns"
:showAddBtn="true"
:showAllDeleteButton="true"
></currenTableFlex>
</div>
</div>
<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>
import currenTableFlex from "@/components/currenTableFlex"
export default {
components: {
currenTableFlex,
},
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,
},
// detail
flexTableColumns:{
type: Array,
default: () => {
return []
}
}
},
data () {
return {
session: null,
flexTableData: null,//detail
editOptions: {},
}
},
mounted () {
this.session = JSON.parse(JSON.stringify(this.FormData))
this.flexTableData = this.FormData.details || []
console.log(190,this.flexTableData,this.flexTableColumns)
},
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);
},
// formchange
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;
}
.dialogOuterTitle{
position: relative;
padding: 20px 0;
font-size: 18px;
height: 60px;
overflow: hidden;
color: #333;
font-weight: bold;
padding-left: 18px;
&::before{
content: "";
position: absolute;
left: 0;
top: 22px;
width: 5px;
height: 22px;
background: #1890ff;
}
}
.currentFormAndTable{
display: flex;
height: calc(100% - 120px);
}
::v-deep .newAndEdiDialogForDetail {
display: flex;
flex-direction: column;
width: 70%;
height: calc(100% - 10px);
.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 {
position: fixed;
right: 60px;
bottom: 40px;
}
.formTable-box {
height: 40%;
.el-form-item__content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
margin: 0 !important;
}
}
}
.addDetailsContent{
background: #f8f8f8;
padding: 20px;
height: calc(100% - 10px);
.currenTableFlex{
height: calc(100% - 20px);
}
}
</style>

81
Code/Fe/src/components/pdf/index.vue

@ -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>

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

Loading…
Cancel
Save