Compare commits

..

No commits in common. 'master' and 'V1.0.2' have entirely different histories.

  1. 4
      .env
  2. 2
      .env.production
  3. 5
      .eslintrc.js
  4. 346
      package-lock.json
  5. 8
      package.json
  6. 462
      public/tinymce/langs/zh_CN.js
  7. 419
      public/tinymce/langs/zh_TW.js
  8. 7
      public/tinymce/skins/content/dark/content.min.css
  9. 7
      public/tinymce/skins/content/default/content.min.css
  10. 7
      public/tinymce/skins/content/document/content.min.css
  11. 7
      public/tinymce/skins/content/writer/content.min.css
  12. 7
      public/tinymce/skins/ui/oxide-dark/content.inline.min.css
  13. 7
      public/tinymce/skins/ui/oxide-dark/content.min.css
  14. 7
      public/tinymce/skins/ui/oxide-dark/content.mobile.min.css
  15. BIN
      public/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff
  16. 7
      public/tinymce/skins/ui/oxide-dark/skin.min.css
  17. 7
      public/tinymce/skins/ui/oxide-dark/skin.mobile.min.css
  18. 7
      public/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css
  19. 7
      public/tinymce/skins/ui/oxide/content.inline.min.css
  20. 7
      public/tinymce/skins/ui/oxide/content.min.css
  21. 7
      public/tinymce/skins/ui/oxide/content.mobile.min.css
  22. BIN
      public/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff
  23. 7
      public/tinymce/skins/ui/oxide/skin.min.css
  24. 7
      public/tinymce/skins/ui/oxide/skin.mobile.min.css
  25. 7
      public/tinymce/skins/ui/oxide/skin.shadowdom.min.css
  26. 1
      src/api/bank.ts
  27. 164
      src/api/model.ts
  28. 1
      src/api/system.ts
  29. 31
      src/api/user.ts
  30. 1
      src/assets/svgs/preview.svg
  31. 2
      src/components/AliOss/upload.ts
  32. 10
      src/components/Back.vue
  33. 381
      src/components/Panel/index.vue
  34. 9
      src/components/Search.vue
  35. 34
      src/components/StrategyConfirm.vue
  36. 5
      src/components/Tinymce/index.vue
  37. 21
      src/layout/components/AppHeader.vue
  38. 3
      src/layout/components/AppMain.vue
  39. 142
      src/layout/components/AppSidebar/Menu.vue
  40. 31
      src/layout/components/AppSidebar/index.vue
  41. 3
      src/layout/components/Logo.vue
  42. 16
      src/layout/index.vue
  43. 3
      src/permission.ts
  44. 2
      src/router/index.ts
  45. 2
      src/store/useCurrentUser.ts
  46. 24
      src/store/useProduct.ts
  47. 33
      src/styles/index.scss
  48. 1
      src/utils/auth.ts
  49. 11
      src/utils/common.ts
  50. 27
      src/utils/request.ts
  51. 4
      src/views/403.vue
  52. 17
      src/views/404.vue
  53. 89
      src/views/Home.vue
  54. 90
      src/views/Role.vue
  55. 55
      src/views/bankProduct/index.vue
  56. 139
      src/views/config/level/Index.vue
  57. 110
      src/views/config/param/Buyer.vue
  58. 40
      src/views/config/param/Financial.vue
  59. 15
      src/views/config/param/Index.vue
  60. 27
      src/views/finance/Account.vue
  61. 87
      src/views/finance/Bank.vue
  62. 117
      src/views/finance/BankDetail.vue
  63. 96
      src/views/finance/Fund.vue
  64. 80
      src/views/finance/Insurance.vue
  65. 68
      src/views/finance/Order.vue
  66. 92
      src/views/finance/Publish.vue
  67. 173
      src/views/product/afterLoan/1029.vue
  68. 194
      src/views/product/afterLoan/1029/Detail.vue
  69. 157
      src/views/product/afterLoan/1029/Index.vue
  70. 186
      src/views/product/afterLoan/1030.vue
  71. 219
      src/views/product/afterLoan/1030/Detail.vue
  72. 157
      src/views/product/afterLoan/1030/Index.vue
  73. 344
      src/views/product/afterLoan/1031.vue
  74. 336
      src/views/product/afterLoan/1031/Detail.vue
  75. 157
      src/views/product/afterLoan/1031/Index.vue
  76. 130
      src/views/product/afterLoan/1032.vue
  77. 169
      src/views/product/afterLoan/1032/Detail.vue
  78. 157
      src/views/product/afterLoan/1032/Index.vue
  79. 195
      src/views/product/afterLoan/1033.vue
  80. 229
      src/views/product/afterLoan/1033/Detail.vue
  81. 157
      src/views/product/afterLoan/1033/Index.vue
  82. 89
      src/views/product/afterLoan/CardList.vue
  83. 502
      src/views/product/bank/Add.vue
  84. 55
      src/views/product/bank/Approve.vue
  85. 92
      src/views/product/bank/CardList.vue
  86. 1474
      src/views/product/bank/Config.vue
  87. 3
      src/views/product/bank/Detail.vue
  88. 273
      src/views/product/bank/Info.vue
  89. 147
      src/views/product/bank/List.vue
  90. 276
      src/views/product/fund/Add.vue
  91. 64
      src/views/product/fund/CardList.vue
  92. 3
      src/views/product/fund/Detail.vue
  93. 23
      src/views/product/fund/Info.vue
  94. 107
      src/views/product/fund/List.vue
  95. 113
      src/views/product/insurance/Add.vue
  96. 72
      src/views/product/insurance/CardList.vue
  97. 3
      src/views/product/insurance/Detail.vue
  98. 35
      src/views/product/insurance/Info.vue
  99. 118
      src/views/product/insurance/List.vue
  100. 304
      src/views/product/interestRate/772.vue
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,8 +2,8 @@ VITE_APP_TITLE=金融产品设计及数字化营销沙盘
VITE_PORT=9520
# VITE_PROXY=http://192.168.31.125:8080
VITE_PUBLIC_PATH=./
# VITE_BASE_API=http://192.168.31.217:9000
VITE_BASE_API=http://121.37.12.51
VITE_BASE_API=http://192.168.31.217:9000
# VITE_BASE_API=http://121.37.12.51
# VITE_BASE_API=https://www.occupationlab.com
VITE_I18N_LOCALE=zh-cn
VITE_I18N_FALLBACK_LOCALE=zh-cn

@ -1 +1 @@
VITE_BASE_API=https://izhixinyun.com
VITE_BASE_API=https://www.occupationlab.com

@ -17,11 +17,6 @@ module.exports = {
// '@typescript-eslint/camelcase': 'off',
'import/extensions': 'off',
'no-nested-ternary': 'off',
'no-use-before-define': 'off',
'no-unused-expressions': 'off',
'no-empty': 'off',
'no-console': 'off'
},
settings: {
'import/resolver': {

346
package-lock.json generated

@ -52,9 +52,9 @@
}
},
"@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
"integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA=="
"version": "3.4.0",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz",
"integrity": "sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ=="
},
"@element-plus/icons-vue": {
"version": "0.2.7",
@ -85,28 +85,6 @@
"integrity": "sha512-8HqW8EVqjnCmWXVpqAOZf+EGESdkR27odcMMMGefgKXtar00SoYNSryGv//TELI4T3QFsECo78p+0lmalk/CFA==",
"dev": true
},
"@floating-ui/core": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.1.tgz",
"integrity": "sha512-42UH54oPZHPdRHdw6BgoBD6cg/eVTmVrFcgeRDM3jbO7uxSoipVcmcIGFcA5jmOHO5apcyvBhkSKES3fQJnu7A==",
"requires": {
"@floating-ui/utils": "^0.2.0"
}
},
"@floating-ui/dom": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz",
"integrity": "sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==",
"requires": {
"@floating-ui/core": "^1.0.0",
"@floating-ui/utils": "^0.2.0"
}
},
"@floating-ui/utils": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw=="
},
"@intlify/bundle-utils": {
"version": "2.2.0",
"resolved": "https://registry.npmmirror.com/@intlify/bundle-utils/-/bundle-utils-2.2.0.tgz",
@ -229,9 +207,9 @@
}
},
"@popperjs/core": {
"version": "npm:@sxzz/popperjs-es@2.11.7",
"resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz",
"integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ=="
"version": "2.11.2",
"resolved": "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.2.tgz",
"integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA=="
},
"@rollup/pluginutils": {
"version": "4.1.2",
@ -307,15 +285,8 @@
"@types/lodash": {
"version": "4.14.178",
"resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.14.178.tgz",
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
},
"@types/lodash-es": {
"version": "4.17.12",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
"integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
"requires": {
"@types/lodash": "*"
}
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw==",
"dev": true
},
"@types/node": {
"version": "17.0.17",
@ -344,11 +315,6 @@
"@types/node": "*"
}
},
"@types/web-bluetooth": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz",
"integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ=="
},
"@typescript-eslint/eslint-plugin": {
"version": "4.33.0",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz",
@ -616,16 +582,16 @@
}
},
"@vue/compiler-sfc": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.34.tgz",
"integrity": "sha512-I+vT4soKJtdsoREBDYAcz56+yGpZ5T3GUigvBFgC2yTeTtBtREOPzYw8kZyMuD2ZlryPYBkbV8D9xxcvU0j/aw==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.25.tgz",
"integrity": "sha512-PminuOYIcFI7UZn+mdy2OPbogyAb0IHkVuqwmLDJiSRFhc/QAXQnO9KdS4nez3bQ9XlQmoAveQzcZuekHzdb5w==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/compiler-core": "3.2.34",
"@vue/compiler-dom": "3.2.34",
"@vue/compiler-ssr": "3.2.34",
"@vue/reactivity-transform": "3.2.34",
"@vue/shared": "3.2.34",
"@vue/compiler-core": "3.2.25",
"@vue/compiler-dom": "3.2.25",
"@vue/compiler-ssr": "3.2.25",
"@vue/reactivity-transform": "3.2.25",
"@vue/shared": "3.2.25",
"estree-walker": "^2.0.2",
"magic-string": "^0.25.7",
"postcss": "^8.1.10",
@ -633,65 +599,65 @@
},
"dependencies": {
"@vue/compiler-core": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.34.tgz",
"integrity": "sha512-Y53lv04ZhDfqflhk4yEgBZrCL1RipbxqmqJFfl1PRkjOzt0bvJpf1sCNN81QNfXohVwFGf+Hng2ztwLwOZgbuA==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.25.tgz",
"integrity": "sha512-FlffKezIqztTCTyG0klkYRwhdyL6b1PTTCIerPb4p2R9qQaczccTX5g9ysi9w6tpLQ48a1WiXnFDJhWD7XoqwA==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/shared": "3.2.34",
"@vue/shared": "3.2.25",
"estree-walker": "^2.0.2",
"source-map": "^0.6.1"
}
},
"@vue/compiler-dom": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.34.tgz",
"integrity": "sha512-MFLUYDgy0aES9x1goU/pgxpzgT9IZOndO8qwQVSyVfUvl/CywEBtfBi5+8fsiBDhoGIT7g8qcsUUF1NYViU2vQ==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.25.tgz",
"integrity": "sha512-4JrburkRg4VWbc8AKpzKFWbNY4MDXshqjFl53+vINq7zaw3Z7aSqnLv0EkKh8B8ynf/MYsAdygGutyVbEWYxOw==",
"requires": {
"@vue/compiler-core": "3.2.34",
"@vue/shared": "3.2.34"
"@vue/compiler-core": "3.2.25",
"@vue/shared": "3.2.25"
}
},
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
"@vue/compiler-ssr": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.34.tgz",
"integrity": "sha512-zyaMdGJhxoA34ibWsXF7VH1PO5yrNB1MZg/ByRfXGM8JefGQaz+PpHvBy/5OI0ehEyhAyCb7279JdhYHacMZbw==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.25.tgz",
"integrity": "sha512-+BAl8U5D3JkGR6086PFx1BQQ5km3z9fT88hy/7lzf8i3vEDdPQodadnX2t6tndFjIux05MEKg43DeocOojT0mw==",
"requires": {
"@vue/compiler-dom": "3.2.34",
"@vue/shared": "3.2.34"
"@vue/compiler-dom": "3.2.25",
"@vue/shared": "3.2.25"
},
"dependencies": {
"@vue/compiler-core": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.34.tgz",
"integrity": "sha512-Y53lv04ZhDfqflhk4yEgBZrCL1RipbxqmqJFfl1PRkjOzt0bvJpf1sCNN81QNfXohVwFGf+Hng2ztwLwOZgbuA==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.25.tgz",
"integrity": "sha512-FlffKezIqztTCTyG0klkYRwhdyL6b1PTTCIerPb4p2R9qQaczccTX5g9ysi9w6tpLQ48a1WiXnFDJhWD7XoqwA==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/shared": "3.2.34",
"@vue/shared": "3.2.25",
"estree-walker": "^2.0.2",
"source-map": "^0.6.1"
}
},
"@vue/compiler-dom": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.34.tgz",
"integrity": "sha512-MFLUYDgy0aES9x1goU/pgxpzgT9IZOndO8qwQVSyVfUvl/CywEBtfBi5+8fsiBDhoGIT7g8qcsUUF1NYViU2vQ==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.25.tgz",
"integrity": "sha512-4JrburkRg4VWbc8AKpzKFWbNY4MDXshqjFl53+vINq7zaw3Z7aSqnLv0EkKh8B8ynf/MYsAdygGutyVbEWYxOw==",
"requires": {
"@vue/compiler-core": "3.2.34",
"@vue/shared": "3.2.34"
"@vue/compiler-core": "3.2.25",
"@vue/shared": "3.2.25"
}
},
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
@ -728,89 +694,89 @@
}
},
"@vue/reactivity-transform": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.34.tgz",
"integrity": "sha512-OtsrL4/i6Md279pMhZ8wRijeDhPSdnXrH9wmqAcKDhVcp1L2kSWlgVVLa1jGIyyFYE806YiJNJiGBvXPGXMzxw==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.25.tgz",
"integrity": "sha512-fOiW67PUalicMfMr4Sc9l8mUtkN7ZD+G1/zJV8blzQ8GEZSeRcJm11gqve6Ps623ju5YORu7V/Q1gZoOJ9WO4g==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/compiler-core": "3.2.34",
"@vue/shared": "3.2.34",
"@vue/compiler-core": "3.2.25",
"@vue/shared": "3.2.25",
"estree-walker": "^2.0.2",
"magic-string": "^0.25.7"
},
"dependencies": {
"@vue/compiler-core": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.34.tgz",
"integrity": "sha512-Y53lv04ZhDfqflhk4yEgBZrCL1RipbxqmqJFfl1PRkjOzt0bvJpf1sCNN81QNfXohVwFGf+Hng2ztwLwOZgbuA==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.25.tgz",
"integrity": "sha512-FlffKezIqztTCTyG0klkYRwhdyL6b1PTTCIerPb4p2R9qQaczccTX5g9ysi9w6tpLQ48a1WiXnFDJhWD7XoqwA==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/shared": "3.2.34",
"@vue/shared": "3.2.25",
"estree-walker": "^2.0.2",
"source-map": "^0.6.1"
}
},
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
"@vue/runtime-core": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.34.tgz",
"integrity": "sha512-GtaHqYiuEb56OA0cbMh20UPpDiXGRX+NS1buKif4OL341JJ3NtmNOIchCzknaN76oN6KqrLiO82/+TEZXl2Xtw==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.25.tgz",
"integrity": "sha512-2+fo5+lofT4xr8W2rtjyz+AM+UB1U/UNLH6ISFdHWNWuveSWxF+vkCQaATmhp6O3XA7QJAbHoRqIZor20EWSfQ==",
"requires": {
"@vue/reactivity": "3.2.34",
"@vue/shared": "3.2.34"
"@vue/reactivity": "3.2.25",
"@vue/shared": "3.2.25"
},
"dependencies": {
"@vue/reactivity": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.34.tgz",
"integrity": "sha512-xbRIOPqxdNOr0zS47moRS6zf4BKd0z+55R85UJlo4r5ezqCktk6fYy1atY4tGzo7Maqh6QoKw3LtIKvpz8d7WA==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.25.tgz",
"integrity": "sha512-Dxc/u/dxoneIDqyfmuwPVBR0G3OQJqe3Dtz4z3NGt+CGj4UuOZQfN5raJPmp6xGYgrtC6PAWoCgHhyrgr1qCtg==",
"requires": {
"@vue/shared": "3.2.34"
"@vue/shared": "3.2.25"
}
},
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
"@vue/runtime-dom": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.34.tgz",
"integrity": "sha512-uqizbaJqmNH3O4TRr+8cM1tid5ODWHyQYZ3CLWcjn3dLkf0N7wvNuhUELQUZU/wQLvVMhJUQNrmOqckHLm6Xpw==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.25.tgz",
"integrity": "sha512-3gGeyHnygn4yG6bssRKhQIxnE8vgB8FtYUUwoYoA/Pm0vZ+bGPoZax4TbtZD9eW9rvs8CY8boNp4t/sJaPJrRQ==",
"requires": {
"@vue/runtime-core": "3.2.34",
"@vue/shared": "3.2.34",
"@vue/runtime-core": "3.2.25",
"@vue/shared": "3.2.25",
"csstype": "^2.6.8"
},
"dependencies": {
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
"@vue/server-renderer": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.34.tgz",
"integrity": "sha512-PMnBAq1BexPFXBxuLngp4lQvc0XQD1CBDIHtEsG0pRusGWVJddBUKlR/EnnSvGaJ34YmKkAl9kdvczOz0kddew==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.25.tgz",
"integrity": "sha512-qFRmcyeyyhWbnTPn6cbCZ4bjeuPLSkUpFa98p4LEJtFBFbxjGnrHXHOjYxCY3Lznmxe0kMM3qG4t3GnjcXP12w==",
"requires": {
"@vue/compiler-ssr": "3.2.34",
"@vue/shared": "3.2.34"
"@vue/compiler-ssr": "3.2.25",
"@vue/shared": "3.2.25"
},
"dependencies": {
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
@ -830,25 +796,18 @@
}
},
"@vueuse/core": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz",
"integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==",
"version": "7.6.1",
"resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-7.6.1.tgz",
"integrity": "sha512-492y7R9HRu6TXzcGBMVG5qg5o9CHjrWLfOHh+TEknJeLe3LIYHsIBi1IlUN5s/yP3OHlBynjrzMMUm4gEyBmQg==",
"requires": {
"@types/web-bluetooth": "^0.0.16",
"@vueuse/metadata": "9.13.0",
"@vueuse/shared": "9.13.0",
"@vueuse/shared": "7.6.1",
"vue-demi": "*"
}
},
"@vueuse/metadata": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz",
"integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ=="
},
"@vueuse/shared": {
"version": "9.13.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz",
"integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==",
"version": "7.6.1",
"resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-7.6.1.tgz",
"integrity": "sha512-VhURBjuyELYLW94TLqwyM+tUZ0uyWAOjp8zDnJts5wwyHZlGt/yabLbuEl70cKmt0zR9psVyAyHC+LTgRrA1Zw==",
"requires": {
"vue-demi": "*"
}
@ -1080,9 +1039,9 @@
"dev": true
},
"async-validator": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
"version": "4.0.7",
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.0.7.tgz",
"integrity": "sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ=="
},
"autoprefixer": {
"version": "10.4.2",
@ -1236,9 +1195,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001620",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz",
"integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==",
"version": "1.0.30001311",
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001311.tgz",
"integrity": "sha512-mleTFtFKfykEeW34EyfhGIFjGCqzhh38Y0LhdQ9aWF+HorZTtdgKV/1hEE0NlFkG2ubvisPV6l400tlbPys98A==",
"dev": true
},
"capital-case": {
@ -1761,42 +1720,21 @@
"dev": true
},
"element-plus": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.4.3.tgz",
"integrity": "sha512-b3q26j+lM4SBqiyzw8HybybGnP2pk4MWgrnzzzYW5qKQUgV6EG1Zg7nMCfgCVccI8tNvZoTiUHb2mFaiB9qT8w==",
"requires": {
"@ctrl/tinycolor": "^3.4.1",
"@element-plus/icons-vue": "^2.3.1",
"@floating-ui/dom": "^1.0.1",
"@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7",
"@types/lodash": "^4.14.182",
"@types/lodash-es": "^4.17.6",
"@vueuse/core": "^9.1.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.3",
"escape-html": "^1.0.3",
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.0.2.tgz",
"integrity": "sha512-URjC0HwwiqtlLxqTmHXQ31WXrdAq4ChWyyn52OcQs3PRsnMPfahGVq2AWnfzzlzlhVeI5lY3HQiuB1zDathS+g==",
"requires": {
"@ctrl/tinycolor": "^3.4.0",
"@element-plus/icons-vue": "^0.2.6",
"@popperjs/core": "^2.11.2",
"@vueuse/core": "^7.6.0",
"async-validator": "^4.0.7",
"dayjs": "^1.10.7",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash-unified": "^1.0.2",
"lodash-unified": "^1.0.1",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"
},
"dependencies": {
"@element-plus/icons-vue": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
"integrity": "sha512-XxVUZv48RZAd87ucGS48jPf6pKu0yV5UCg9f4FFwtrYxXOwWuVJo6wOvSLKEoMQKjv8GsX/mhP6UsC1lRwbUWg=="
},
"@types/lodash": {
"version": "4.17.1",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.1.tgz",
"integrity": "sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q=="
},
"dayjs": {
"version": "1.11.11",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz",
"integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg=="
}
"normalize-wheel-es": "^1.1.1"
}
},
"emmet": {
@ -3431,13 +3369,13 @@
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash-unified": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz",
"integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ=="
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.1.tgz",
"integrity": "sha512-Py+twfpWn+2dFQWCuGcp21WiQRwZwnm1cyE3piSt/VtBVKVyxlR58WgOVRzXtmdmDRGJKH8F8GPaA29WK/yK8g=="
},
"lodash.clonedeep": {
"version": "4.5.0",
@ -3575,7 +3513,7 @@
},
"memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
},
"merge-descriptors": {
@ -3880,9 +3818,9 @@
"dev": true
},
"normalize-wheel-es": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw=="
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.1.tgz",
"integrity": "sha512-157VNH4CngrcsvF8xOVOe22cwniIR3nxSltdctvQeHZj8JttEeOXffK28jucWfWBXs0QNetAumjc1GiInnwX4w=="
},
"nprogress": {
"version": "0.2.0",
@ -5800,48 +5738,48 @@
}
},
"vue": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.2.34.tgz",
"integrity": "sha512-gXRg5v8OSmGT4ZiQ/X/Pcz6Fr2igHQx/wvRH/pLnt0VvjfGGqrwhnwjYZilLP4HBcO211rMD9PpU6lfWfIv3wg==",
"requires": {
"@vue/compiler-dom": "3.2.34",
"@vue/compiler-sfc": "3.2.34",
"@vue/runtime-dom": "3.2.34",
"@vue/server-renderer": "3.2.34",
"@vue/shared": "3.2.34"
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.2.25.tgz",
"integrity": "sha512-jU3t7fyQDHoCWCqhmRrnSmYZvHC35tOJTP704di7HGfq5EcFA1cU/1ZPjUV1eCxJev65Khjyfni+vk9oa+eTtw==",
"requires": {
"@vue/compiler-dom": "3.2.25",
"@vue/compiler-sfc": "3.2.25",
"@vue/runtime-dom": "3.2.25",
"@vue/server-renderer": "3.2.25",
"@vue/shared": "3.2.25"
},
"dependencies": {
"@vue/compiler-core": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.34.tgz",
"integrity": "sha512-Y53lv04ZhDfqflhk4yEgBZrCL1RipbxqmqJFfl1PRkjOzt0bvJpf1sCNN81QNfXohVwFGf+Hng2ztwLwOZgbuA==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.25.tgz",
"integrity": "sha512-FlffKezIqztTCTyG0klkYRwhdyL6b1PTTCIerPb4p2R9qQaczccTX5g9ysi9w6tpLQ48a1WiXnFDJhWD7XoqwA==",
"requires": {
"@babel/parser": "^7.16.4",
"@vue/shared": "3.2.34",
"@vue/shared": "3.2.25",
"estree-walker": "^2.0.2",
"source-map": "^0.6.1"
}
},
"@vue/compiler-dom": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.34.tgz",
"integrity": "sha512-MFLUYDgy0aES9x1goU/pgxpzgT9IZOndO8qwQVSyVfUvl/CywEBtfBi5+8fsiBDhoGIT7g8qcsUUF1NYViU2vQ==",
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.25.tgz",
"integrity": "sha512-4JrburkRg4VWbc8AKpzKFWbNY4MDXshqjFl53+vINq7zaw3Z7aSqnLv0EkKh8B8ynf/MYsAdygGutyVbEWYxOw==",
"requires": {
"@vue/compiler-core": "3.2.34",
"@vue/shared": "3.2.34"
"@vue/compiler-core": "3.2.25",
"@vue/shared": "3.2.25"
}
},
"@vue/shared": {
"version": "3.2.34",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.34.tgz",
"integrity": "sha512-zhEeB8TrFmTXmTXmu/wcjEhgrjO4xqdDQrCdPhjX7NxfoLqoBVKguOm8qyihWNLbP+41svYY4za9mqXyqFLzNg=="
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.25.tgz",
"integrity": "sha512-DkHJFV2gw9WBRmUCa21eyG0WvlF0l1QFOgTkWj29O4mt2Tv3BSE5PQOKhUruZIym4bBYCqx9ZGtoD1WohDprow=="
}
}
},
"vue-demi": {
"version": "0.14.7",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
"integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA=="
"version": "0.12.1",
"resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.12.1.tgz",
"integrity": "sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw=="
},
"vue-eslint-parser": {
"version": "7.11.0",

@ -6,8 +6,8 @@
"dev": "vite",
"test": "vite build --mode test",
"build": "vite build",
"lint": "eslint --ext .vue,.ts src/",
"lint:fix": "eslint --ext .vue,.ts src/ --fix"
"preview": "vite preview",
"plop": "plop"
},
"dependencies": {
"@element-plus/icons-vue": "^0.2.7",
@ -17,14 +17,14 @@
"core-js": "^3.21.0",
"cropperjs": "^1.5.12",
"dayjs": "^1.10.7",
"element-plus": "^2.4.3",
"element-plus": "^2.0.2",
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
"mavon-editor": "^2.10.4",
"nprogress": "^0.2.0",
"path-to-regexp": "^6.2.0",
"tinymce": "^5.9.2",
"vue": "^3.2.34",
"vue": "^3.2.25",
"vue-i18n": "^9.2.0-beta.30",
"vue-router": "^4.0.12",
"vuedraggable": "^4.1.0"

@ -0,0 +1,462 @@
tinymce.addI18n('zh_CN',{
"Redo": "\u91cd\u505a",
"Undo": "\u64a4\u9500",
"Cut": "\u526a\u5207",
"Copy": "\u590d\u5236",
"Paste": "\u7c98\u8d34",
"Select all": "\u5168\u9009",
"New document": "\u65b0\u6587\u4ef6",
"Ok": "\u786e\u5b9a",
"Cancel": "\u53d6\u6d88",
"Visual aids": "\u7f51\u683c\u7ebf",
"Bold": "\u7c97\u4f53",
"Italic": "\u659c\u4f53",
"Underline": "\u4e0b\u5212\u7ebf",
"Strikethrough": "\u5220\u9664\u7ebf",
"Superscript": "\u4e0a\u6807",
"Subscript": "\u4e0b\u6807",
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
"Align left": "\u5de6\u8fb9\u5bf9\u9f50",
"Align center": "\u4e2d\u95f4\u5bf9\u9f50",
"Align right": "\u53f3\u8fb9\u5bf9\u9f50",
"Justify": "\u4e24\u7aef\u5bf9\u9f50",
"Bullet list": "\u9879\u76ee\u7b26\u53f7",
"Numbered list": "\u7f16\u53f7\u5217\u8868",
"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
"Close": "\u5173\u95ed",
"Formats": "\u683c\u5f0f",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u6253\u5f00\u526a\u8d34\u677f\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u7b49\u5feb\u6377\u952e\u3002",
"Headers": "\u6807\u9898",
"Header 1": "\u6807\u98981",
"Header 2": "\u6807\u98982",
"Header 3": "\u6807\u98983",
"Header 4": "\u6807\u98984",
"Header 5": "\u6807\u98985",
"Header 6": "\u6807\u98986",
"Headings": "\u6807\u9898",
"Heading 1": "\u6807\u98981",
"Heading 2": "\u6807\u98982",
"Heading 3": "\u6807\u98983",
"Heading 4": "\u6807\u98984",
"Heading 5": "\u6807\u98985",
"Heading 6": "\u6807\u98986",
"Preformatted": "\u9884\u5148\u683c\u5f0f\u5316\u7684",
"Div": "Div",
"Pre": "Pre",
"Code": "\u4ee3\u7801",
"Paragraph": "\u6bb5\u843d",
"Blockquote": "\u5f15\u6587\u533a\u5757",
"Inline": "\u6587\u672c",
"Blocks": "\u57fa\u5757",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
"Fonts": "\u5b57\u4f53",
"Font Sizes": "\u5b57\u53f7",
"Class": "\u7c7b\u578b",
"Browse for an image": "\u6d4f\u89c8\u56fe\u50cf",
"OR": "\u6216",
"Drop an image here": "\u62d6\u653e\u4e00\u5f20\u56fe\u50cf\u81f3\u6b64",
"Upload": "\u4e0a\u4f20",
"Block": "\u5757",
"Align": "\u5bf9\u9f50",
"Default": "\u9ed8\u8ba4",
"Circle": "\u7a7a\u5fc3\u5706",
"Disc": "\u5b9e\u5fc3\u5706",
"Square": "\u65b9\u5757",
"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
"Anchor...": "\u951a\u70b9...",
"Name": "\u540d\u79f0",
"Id": "\u6807\u8bc6\u7b26",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
"Special character...": "\u7279\u6b8a\u5b57\u7b26...",
"Source code": "\u6e90\u4ee3\u7801",
"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
"Language": "\u8bed\u8a00",
"Code sample...": "\u793a\u4f8b\u4ee3\u7801...",
"Color Picker": "\u9009\u8272\u5668",
"R": "R",
"G": "G",
"B": "B",
"Left to right": "\u4ece\u5de6\u5230\u53f3",
"Right to left": "\u4ece\u53f3\u5230\u5de6",
"Emoticons": "\u8868\u60c5",
"Emoticons...": "\u8868\u60c5\u7b26\u53f7...",
"Metadata and Document Properties": "\u5143\u6570\u636e\u548c\u6587\u6863\u5c5e\u6027",
"Title": "\u6807\u9898",
"Keywords": "\u5173\u952e\u8bcd",
"Description": "\u63cf\u8ff0",
"Robots": "\u673a\u5668\u4eba",
"Author": "\u4f5c\u8005",
"Encoding": "\u7f16\u7801",
"Fullscreen": "\u5168\u5c4f",
"Action": "\u64cd\u4f5c",
"Shortcut": "\u5feb\u6377\u952e",
"Help": "\u5e2e\u52a9",
"Address": "\u5730\u5740",
"Focus to menubar": "\u79fb\u52a8\u7126\u70b9\u5230\u83dc\u5355\u680f",
"Focus to toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u5de5\u5177\u680f",
"Focus to element path": "\u79fb\u52a8\u7126\u70b9\u5230\u5143\u7d20\u8def\u5f84",
"Focus to contextual toolbar": "\u79fb\u52a8\u7126\u70b9\u5230\u4e0a\u4e0b\u6587\u83dc\u5355",
"Insert link (if link plugin activated)": "\u63d2\u5165\u94fe\u63a5 (\u5982\u679c\u94fe\u63a5\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Save (if save plugin activated)": "\u4fdd\u5b58(\u5982\u679c\u4fdd\u5b58\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Find (if searchreplace plugin activated)": "\u67e5\u627e(\u5982\u679c\u67e5\u627e\u66ff\u6362\u63d2\u4ef6\u5df2\u6fc0\u6d3b)",
"Plugins installed ({0}):": "\u5df2\u5b89\u88c5\u63d2\u4ef6 ({0}):",
"Premium plugins:": "\u4f18\u79c0\u63d2\u4ef6\uff1a",
"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
"You are using {0}": "\u4f60\u6b63\u5728\u4f7f\u7528 {0}",
"Plugins": "\u63d2\u4ef6",
"Handy Shortcuts": "\u5feb\u6377\u952e",
"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
"Alternative description": "\u66ff\u4ee3\u63cf\u8ff0",
"Accessibility": "\u8f85\u52a9\u529f\u80fd",
"Image is decorative": "\u56fe\u50cf\u662f\u88c5\u9970\u6027\u7684",
"Source": "\u5730\u5740",
"Dimensions": "\u5927\u5c0f",
"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
"General": "\u666e\u901a",
"Advanced": "\u9ad8\u7ea7",
"Style": "\u6837\u5f0f",
"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
"Border": "\u8fb9\u6846",
"Insert image": "\u63d2\u5165\u56fe\u7247",
"Image...": "\u56fe\u7247...",
"Image list": "\u56fe\u7247\u5217\u8868",
"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
"Edit image": "\u7f16\u8f91\u56fe\u7247",
"Image options": "\u56fe\u7247\u9009\u9879",
"Zoom in": "\u653e\u5927",
"Zoom out": "\u7f29\u5c0f",
"Crop": "\u88c1\u526a",
"Resize": "\u8c03\u6574\u5927\u5c0f",
"Orientation": "\u65b9\u5411",
"Brightness": "\u4eae\u5ea6",
"Sharpen": "\u9510\u5316",
"Contrast": "\u5bf9\u6bd4\u5ea6",
"Color levels": "\u989c\u8272\u5c42\u6b21",
"Gamma": "\u4f3d\u9a6c\u503c",
"Invert": "\u53cd\u8f6c",
"Apply": "\u5e94\u7528",
"Back": "\u540e\u9000",
"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
"Text to display": "\u663e\u793a\u6587\u5b57",
"Url": "\u5730\u5740",
"Open link in...": "\u94fe\u63a5\u6253\u5f00\u4f4d\u7f6e...",
"Current window": "\u5f53\u524d\u7a97\u53e3",
"None": "\u65e0",
"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
"Open link": "\u6253\u5f00\u94fe\u63a5",
"Remove link": "\u5220\u9664\u94fe\u63a5",
"Anchors": "\u951a\u70b9",
"Link...": "\u94fe\u63a5...",
"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
"The URL you entered seems to be an external link. Do you want to add the required https:\/\/ prefix?": "\u60a8\u8f93\u5165\u7684 URL \u4f3c\u4e4e\u662f\u4e00\u4e2a\u5916\u90e8\u94fe\u63a5\u3002\u60a8\u60f3\u6dfb\u52a0\u6240\u9700\u7684 https:\/\/ \u524d\u7f00\u5417\uff1f",
"Link list": "\u94fe\u63a5\u5217\u8868",
"Insert video": "\u63d2\u5165\u89c6\u9891",
"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
"Alternative source": "\u955c\u50cf",
"Alternative source URL": "\u66ff\u4ee3\u6765\u6e90\u7f51\u5740",
"Media poster (Image URL)": "\u5c01\u9762(\u56fe\u7247\u5730\u5740)",
"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
"Embed": "\u5185\u5d4c",
"Media...": "\u591a\u5a92\u4f53...",
"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
"Page break": "\u5206\u9875\u7b26",
"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
"Preview": "\u9884\u89c8",
"Print...": "\u6253\u5370...",
"Save": "\u4fdd\u5b58",
"Find": "\u67e5\u627e",
"Replace with": "\u66ff\u6362\u4e3a",
"Replace": "\u66ff\u6362",
"Replace all": "\u5168\u90e8\u66ff\u6362",
"Previous": "\u4e0a\u4e00\u4e2a",
"Next": "\u4e0b\u4e00\u4e2a",
"Find and Replace": "\u67e5\u627e\u548c\u66ff\u6362",
"Find and replace...": "\u67e5\u627e\u5e76\u66ff\u6362...",
"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
"Find whole words only": "\u5168\u5b57\u5339\u914d",
"Find in selection": "\u5728\u9009\u533a\u4e2d\u67e5\u627e",
"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
"Spellcheck Language": "\u62fc\u5199\u68c0\u67e5\u8bed\u8a00",
"No misspellings found.": "\u6ca1\u6709\u53d1\u73b0\u62fc\u5199\u9519\u8bef",
"Ignore": "\u5ffd\u7565",
"Ignore all": "\u5168\u90e8\u5ffd\u7565",
"Finish": "\u5b8c\u6210",
"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
"Insert table": "\u63d2\u5165\u8868\u683c",
"Table properties": "\u8868\u683c\u5c5e\u6027",
"Delete table": "\u5220\u9664\u8868\u683c",
"Cell": "\u5355\u5143\u683c",
"Row": "\u884c",
"Column": "\u5217",
"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
"Delete row": "\u5220\u9664\u884c",
"Row properties": "\u884c\u5c5e\u6027",
"Cut row": "\u526a\u5207\u884c",
"Copy row": "\u590d\u5236\u884c",
"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
"Delete column": "\u5220\u9664\u5217",
"Cols": "\u5217",
"Rows": "\u884c",
"Width": "\u5bbd",
"Height": "\u9ad8",
"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
"Caption": "\u6807\u9898",
"Show caption": "\u663e\u793a\u6807\u9898",
"Left": "\u5de6\u5bf9\u9f50",
"Center": "\u5c45\u4e2d",
"Right": "\u53f3\u5bf9\u9f50",
"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
"Scope": "\u8303\u56f4",
"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
"H Align": "\u6c34\u5e73\u5bf9\u9f50",
"V Align": "\u5782\u76f4\u5bf9\u9f50",
"Top": "\u9876\u90e8\u5bf9\u9f50",
"Middle": "\u5782\u76f4\u5c45\u4e2d",
"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
"Header cell": "\u8868\u5934\u5355\u5143\u683c",
"Row group": "\u884c\u7ec4",
"Column group": "\u5217\u7ec4",
"Row type": "\u884c\u7c7b\u578b",
"Header": "\u8868\u5934",
"Body": "\u8868\u4f53",
"Footer": "\u8868\u5c3e",
"Border color": "\u8fb9\u6846\u989c\u8272",
"Insert template...": "\u63d2\u5165\u6a21\u677f...",
"Templates": "\u6a21\u677f",
"Template": "\u6a21\u677f",
"Text color": "\u6587\u5b57\u989c\u8272",
"Background color": "\u80cc\u666f\u8272",
"Custom...": "\u81ea\u5b9a\u4e49...",
"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
"No color": "\u65e0",
"Remove color": "\u79fb\u9664\u989c\u8272",
"Table of Contents": "\u5185\u5bb9\u5217\u8868",
"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
"Word count": "\u5b57\u6570",
"Count": "\u8ba1\u6570",
"Document": "\u6587\u6863",
"Selection": "\u9009\u62e9",
"Words": "\u5355\u8bcd",
"Words: {0}": "\u5b57\u6570\uff1a{0}",
"{0} words": "{0} \u5b57",
"File": "\u6587\u4ef6",
"Edit": "\u7f16\u8f91",
"Insert": "\u63d2\u5165",
"View": "\u89c6\u56fe",
"Format": "\u683c\u5f0f",
"Table": "\u8868\u683c",
"Tools": "\u5de5\u5177",
"Powered by {0}": "\u7531{0}\u9a71\u52a8",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9",
"Image title": "\u56fe\u7247\u6807\u9898",
"Border width": "\u8fb9\u6846\u5bbd\u5ea6",
"Border style": "\u8fb9\u6846\u6837\u5f0f",
"Error": "\u9519\u8bef",
"Warn": "\u8b66\u544a",
"Valid": "\u6709\u6548",
"To open the popup, press Shift+Enter": "\u6309Shitf+Enter\u952e\u6253\u5f00\u5bf9\u8bdd\u6846",
"Rich Text Area. Press ALT-0 for help.": "\u7f16\u8f91\u533a\u3002\u6309Alt+0\u952e\u6253\u5f00\u5e2e\u52a9\u3002",
"System Font": "\u7cfb\u7edf\u5b57\u4f53",
"Failed to upload image: {0}": "\u56fe\u7247\u4e0a\u4f20\u5931\u8d25: {0}",
"Failed to load plugin: {0} from url {1}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25: {0} \u6765\u81ea\u94fe\u63a5 {1}",
"Failed to load plugin url: {0}": "\u63d2\u4ef6\u52a0\u8f7d\u5931\u8d25 \u94fe\u63a5: {0}",
"Failed to initialize plugin: {0}": "\u63d2\u4ef6\u521d\u59cb\u5316\u5931\u8d25: {0}",
"example": "\u793a\u4f8b",
"Search": "\u641c\u7d22",
"All": "\u5168\u90e8",
"Currency": "\u8d27\u5e01",
"Text": "\u6587\u5b57",
"Quotations": "\u5f15\u7528",
"Mathematical": "\u6570\u5b66",
"Extended Latin": "\u62c9\u4e01\u8bed\u6269\u5145",
"Symbols": "\u7b26\u53f7",
"Arrows": "\u7bad\u5934",
"User Defined": "\u81ea\u5b9a\u4e49",
"dollar sign": "\u7f8e\u5143\u7b26\u53f7",
"currency sign": "\u8d27\u5e01\u7b26\u53f7",
"euro-currency sign": "\u6b27\u5143\u7b26\u53f7",
"colon sign": "\u5192\u53f7",
"cruzeiro sign": "\u514b\u9c81\u8d5b\u7f57\u5e01\u7b26\u53f7",
"french franc sign": "\u6cd5\u90ce\u7b26\u53f7",
"lira sign": "\u91cc\u62c9\u7b26\u53f7",
"mill sign": "\u5bc6\u5c14\u7b26\u53f7",
"naira sign": "\u5948\u62c9\u7b26\u53f7",
"peseta sign": "\u6bd4\u585e\u5854\u7b26\u53f7",
"rupee sign": "\u5362\u6bd4\u7b26\u53f7",
"won sign": "\u97e9\u5143\u7b26\u53f7",
"new sheqel sign": "\u65b0\u8c22\u514b\u5c14\u7b26\u53f7",
"dong sign": "\u8d8a\u5357\u76fe\u7b26\u53f7",
"kip sign": "\u8001\u631d\u57fa\u666e\u7b26\u53f7",
"tugrik sign": "\u56fe\u683c\u91cc\u514b\u7b26\u53f7",
"drachma sign": "\u5fb7\u62c9\u514b\u9a6c\u7b26\u53f7",
"german penny symbol": "\u5fb7\u56fd\u4fbf\u58eb\u7b26\u53f7",
"peso sign": "\u6bd4\u7d22\u7b26\u53f7",
"guarani sign": "\u74dc\u62c9\u5c3c\u7b26\u53f7",
"austral sign": "\u6fb3\u5143\u7b26\u53f7",
"hryvnia sign": "\u683c\u91cc\u592b\u5c3c\u4e9a\u7b26\u53f7",
"cedi sign": "\u585e\u5730\u7b26\u53f7",
"livre tournois sign": "\u91cc\u5f17\u5f17\u5c14\u7b26\u53f7",
"spesmilo sign": "spesmilo\u7b26\u53f7",
"tenge sign": "\u575a\u6208\u7b26\u53f7",
"indian rupee sign": "\u5370\u5ea6\u5362\u6bd4",
"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9",
"nordic mark sign": "\u5317\u6b27\u9a6c\u514b",
"manat sign": "\u9a6c\u7eb3\u7279\u7b26\u53f7",
"ruble sign": "\u5362\u5e03\u7b26\u53f7",
"yen character": "\u65e5\u5143\u5b57\u6837",
"yuan character": "\u4eba\u6c11\u5e01\u5143\u5b57\u6837",
"yuan character, in hong kong and taiwan": "\u5143\u5b57\u6837\uff08\u6e2f\u53f0\u5730\u533a\uff09",
"yen\/yuan character variant one": "\u5143\u5b57\u6837\uff08\u5927\u5199\uff09",
"Loading emoticons...": "\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7...",
"Could not load emoticons": "\u4e0d\u80fd\u52a0\u8f7d\u8868\u60c5\u7b26\u53f7",
"People": "\u4eba\u7c7b",
"Animals and Nature": "\u52a8\u7269\u548c\u81ea\u7136",
"Food and Drink": "\u98df\u7269\u548c\u996e\u54c1",
"Activity": "\u6d3b\u52a8",
"Travel and Places": "\u65c5\u6e38\u548c\u5730\u70b9",
"Objects": "\u7269\u4ef6",
"Flags": "\u65d7\u5e1c",
"Characters": "\u5b57\u7b26",
"Characters (no spaces)": "\u5b57\u7b26(\u65e0\u7a7a\u683c)",
"{0} characters": "{0} \u4e2a\u5b57\u7b26",
"Error: Form submit field collision.": "\u9519\u8bef: \u8868\u5355\u63d0\u4ea4\u5b57\u6bb5\u51b2\u7a81\u3002",
"Error: No form element found.": "\u9519\u8bef: \u6ca1\u6709\u8868\u5355\u63a7\u4ef6\u3002",
"Update": "\u66f4\u65b0",
"Color swatch": "\u989c\u8272\u6837\u672c",
"Turquoise": "\u9752\u7eff\u8272",
"Green": "\u7eff\u8272",
"Blue": "\u84dd\u8272",
"Purple": "\u7d2b\u8272",
"Navy Blue": "\u6d77\u519b\u84dd",
"Dark Turquoise": "\u6df1\u84dd\u7eff\u8272",
"Dark Green": "\u6df1\u7eff\u8272",
"Medium Blue": "\u4e2d\u84dd\u8272",
"Medium Purple": "\u4e2d\u7d2b\u8272",
"Midnight Blue": "\u6df1\u84dd\u8272",
"Yellow": "\u9ec4\u8272",
"Orange": "\u6a59\u8272",
"Red": "\u7ea2\u8272",
"Light Gray": "\u6d45\u7070\u8272",
"Gray": "\u7070\u8272",
"Dark Yellow": "\u6697\u9ec4\u8272",
"Dark Orange": "\u6df1\u6a59\u8272",
"Dark Red": "\u6df1\u7ea2\u8272",
"Medium Gray": "\u4e2d\u7070\u8272",
"Dark Gray": "\u6df1\u7070\u8272",
"Light Green": "\u6d45\u7eff\u8272",
"Light Yellow": "\u6d45\u9ec4\u8272",
"Light Red": "\u6d45\u7ea2\u8272",
"Light Purple": "\u6d45\u7d2b\u8272",
"Light Blue": "\u6d45\u84dd\u8272",
"Dark Purple": "\u6df1\u7d2b\u8272",
"Dark Blue": "\u6df1\u84dd\u8272",
"Black": "\u9ed1\u8272",
"White": "\u767d\u8272",
"Switch to or from fullscreen mode": "\u5207\u6362\u5168\u5c4f\u6a21\u5f0f",
"Open help dialog": "\u6253\u5f00\u5e2e\u52a9\u5bf9\u8bdd\u6846",
"history": "\u5386\u53f2",
"styles": "\u6837\u5f0f",
"formatting": "\u683c\u5f0f\u5316",
"alignment": "\u5bf9\u9f50",
"indentation": "\u7f29\u8fdb",
"Font": "\u5b57\u4f53",
"Size": "\u5b57\u53f7",
"More...": "\u66f4\u591a...",
"Select...": "\u9009\u62e9...",
"Preferences": "\u9996\u9009\u9879",
"Yes": "\u662f",
"No": "\u5426",
"Keyboard Navigation": "\u952e\u76d8\u6307\u5f15",
"Version": "\u7248\u672c",
"Code view": "\u4ee3\u7801\u89c6\u56fe",
"Open popup menu for split buttons": "\u6253\u5f00\u5f39\u51fa\u5f0f\u83dc\u5355\uff0c\u7528\u4e8e\u62c6\u5206\u6309\u94ae",
"List Properties": "\u5217\u8868\u5c5e\u6027",
"List properties...": "\u6807\u9898\u5b57\u4f53\u5c5e\u6027",
"Start list at number": "\u4ee5\u6570\u5b57\u5f00\u59cb\u5217\u8868",
"Line height": "\u884c\u9ad8",
"comments": "\u5907\u6ce8",
"Format Painter": "\u683c\u5f0f\u5237",
"Insert\/edit iframe": "\u63d2\u5165\/\u7f16\u8f91\u6846\u67b6",
"Capitalization": "\u5927\u5199",
"lowercase": "\u5c0f\u5199",
"UPPERCASE": "\u5927\u5199",
"Title Case": "\u9996\u5b57\u6bcd\u5927\u5199",
"permanent pen": "\u8bb0\u53f7\u7b14",
"Permanent Pen Properties": "\u6c38\u4e45\u7b14\u5c5e\u6027",
"Permanent pen properties...": "\u6c38\u4e45\u7b14\u5c5e\u6027...",
"case change": "\u6848\u4f8b\u66f4\u6539",
"page embed": "\u9875\u9762\u5d4c\u5165",
"Advanced sort...": "\u9ad8\u7ea7\u6392\u5e8f...",
"Advanced Sort": "\u9ad8\u7ea7\u6392\u5e8f",
"Sort table by column ascending": "\u6309\u5217\u5347\u5e8f\u8868",
"Sort table by column descending": "\u6309\u5217\u964d\u5e8f\u8868",
"Sort": "\u6392\u5e8f",
"Order": "\u6392\u5e8f",
"Sort by": "\u6392\u5e8f\u65b9\u5f0f",
"Ascending": "\u5347\u5e8f",
"Descending": "\u964d\u5e8f",
"Column {0}": "\u5217{0}",
"Row {0}": "\u884c{0}",
"Spellcheck...": "\u62fc\u5199\u68c0\u67e5...",
"Misspelled word": "\u62fc\u5199\u9519\u8bef\u7684\u5355\u8bcd",
"Suggestions": "\u5efa\u8bae",
"Change": "\u66f4\u6539",
"Finding word suggestions": "\u67e5\u627e\u5355\u8bcd\u5efa\u8bae",
"Success": "\u6210\u529f",
"Repair": "\u4fee\u590d",
"Issue {0} of {1}": "\u5171\u8ba1{1}\u95ee\u9898{0}",
"Images must be marked as decorative or have an alternative text description": "\u56fe\u50cf\u5fc5\u987b\u6807\u8bb0\u4e3a\u88c5\u9970\u6027\u6216\u5177\u6709\u66ff\u4ee3\u6587\u672c\u63cf\u8ff0",
"Images must have an alternative text description. Decorative images are not allowed.": "\u56fe\u50cf\u5fc5\u987b\u5177\u6709\u66ff\u4ee3\u6587\u672c\u63cf\u8ff0\u3002\u4e0d\u5141\u8bb8\u4f7f\u7528\u88c5\u9970\u56fe\u50cf\u3002",
"Or provide alternative text:": "\u6216\u63d0\u4f9b\u5907\u9009\u6587\u672c\uff1a",
"Make image decorative:": "\u4f7f\u56fe\u50cf\u88c5\u9970\uff1a",
"ID attribute must be unique": "ID \u5c5e\u6027\u5fc5\u987b\u662f\u552f\u4e00\u7684",
"Make ID unique": "\u4f7f ID \u72ec\u4e00\u65e0\u4e8c",
"Keep this ID and remove all others": "\u4fdd\u7559\u6b64 ID \u5e76\u5220\u9664\u6240\u6709\u5176\u4ed6",
"Remove this ID": "\u5220\u9664\u6b64 ID",
"Remove all IDs": "\u6e05\u9664\u5168\u90e8IDs",
"Checklist": "\u6e05\u5355",
"Anchor": "\u951a\u70b9",
"Special character": "\u7279\u6b8a\u7b26\u53f7",
"Code sample": "\u4ee3\u7801\u793a\u4f8b",
"Color": "\u989c\u8272",
"Document properties": "\u6587\u6863\u5c5e\u6027",
"Image description": "\u56fe\u7247\u63cf\u8ff0",
"Image": "\u56fe\u7247",
"Insert link": "\u63d2\u5165\u94fe\u63a5",
"Target": "\u6253\u5f00\u65b9\u5f0f",
"Link": "\u94fe\u63a5",
"Poster": "\u5c01\u9762",
"Media": "\u5a92\u4f53",
"Print": "\u6253\u5370",
"Prev": "\u4e0a\u4e00\u4e2a",
"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
"Whole words": "\u5168\u5b57\u5339\u914d",
"Insert template": "\u63d2\u5165\u6a21\u677f"
});

@ -0,0 +1,419 @@
tinymce.addI18n('zh_TW',{
"Redo": "\u91cd\u505a",
"Undo": "\u64a4\u92b7",
"Cut": "\u526a\u4e0b",
"Copy": "\u8907\u88fd",
"Paste": "\u8cbc\u4e0a",
"Select all": "\u5168\u9078",
"New document": "\u65b0\u6587\u4ef6",
"Ok": "\u78ba\u5b9a",
"Cancel": "\u53d6\u6d88",
"Visual aids": "\u5c0f\u5e6b\u624b",
"Bold": "\u7c97\u9ad4",
"Italic": "\u659c\u9ad4",
"Underline": "\u4e0b\u5283\u7dda",
"Strikethrough": "\u522a\u9664\u7dda",
"Superscript": "\u4e0a\u6a19",
"Subscript": "\u4e0b\u6a19",
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
"Align left": "\u5de6\u908a\u5c0d\u9f4a",
"Align center": "\u4e2d\u9593\u5c0d\u9f4a",
"Align right": "\u53f3\u908a\u5c0d\u9f4a",
"Justify": "\u5de6\u53f3\u5c0d\u9f4a",
"Bullet list": "\u9805\u76ee\u6e05\u55ae",
"Numbered list": "\u6578\u5b57\u6e05\u55ae",
"Decrease indent": "\u6e1b\u5c11\u7e2e\u6392",
"Increase indent": "\u589e\u52a0\u7e2e\u6392",
"Close": "\u95dc\u9589",
"Formats": "\u683c\u5f0f",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u60a8\u7684\u700f\u89bd\u5668\u4e0d\u652f\u63f4\u5b58\u53d6\u526a\u8cbc\u7c3f\uff0c\u53ef\u4ee5\u4f7f\u7528\u5feb\u901f\u9375 Ctrl + X\/C\/V \u4ee3\u66ff\u526a\u4e0b\u3001\u8907\u88fd\u8207\u8cbc\u4e0a\u3002",
"Headers": "\u6a19\u984c",
"Header 1": "\u6a19\u984c 1",
"Header 2": "\u6a19\u984c 2",
"Header 3": "\u6a19\u984c 3",
"Header 4": "\u6a19\u984c 4",
"Header 5": "\u6a19\u984c 5",
"Header 6": "\u6a19\u984c 6",
"Headings": "\u6a19\u984c",
"Heading 1": "\u6a19\u984c1",
"Heading 2": "\u6a19\u984c2",
"Heading 3": "\u6a19\u984c3",
"Heading 4": "\u6a19\u984c4",
"Heading 5": "\u6a19\u984c5",
"Heading 6": "\u6a19\u984c6",
"Preformatted": "\u9810\u5148\u683c\u5f0f\u5316\u7684",
"Div": "Div",
"Pre": "Pre",
"Code": "\u4ee3\u78bc",
"Paragraph": "\u6bb5\u843d",
"Blockquote": "\u5f15\u6587\u5340\u584a",
"Inline": "\u5167\u806f",
"Blocks": "\u57fa\u584a",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u76ee\u524d\u5c07\u4ee5\u7d14\u6587\u5b57\u7684\u6a21\u5f0f\u8cbc\u4e0a\uff0c\u60a8\u53ef\u4ee5\u518d\u9ede\u9078\u4e00\u6b21\u53d6\u6d88\u3002",
"Fonts": "\u5b57\u578b",
"Font Sizes": "\u5b57\u578b\u5927\u5c0f",
"Class": "\u985e\u578b",
"Browse for an image": "\u5f9e\u5716\u7247\u4e2d\u700f\u89bd",
"OR": "\u6216",
"Drop an image here": "\u62d6\u66f3\u5716\u7247\u81f3\u6b64",
"Upload": "\u4e0a\u50b3",
"Block": "\u5340\u584a",
"Align": "\u5c0d\u9f4a",
"Default": "\u9810\u8a2d",
"Circle": "\u7a7a\u5fc3\u5713",
"Disc": "\u5be6\u5fc3\u5713",
"Square": "\u6b63\u65b9\u5f62",
"Lower Alpha": "\u5c0f\u5beb\u82f1\u6587\u5b57\u6bcd",
"Lower Greek": "\u5e0c\u81d8\u5b57\u6bcd",
"Lower Roman": "\u5c0f\u5beb\u7f85\u99ac\u6578\u5b57",
"Upper Alpha": "\u5927\u5beb\u82f1\u6587\u5b57\u6bcd",
"Upper Roman": "\u5927\u5beb\u7f85\u99ac\u6578\u5b57",
"Anchor...": "\u9328\u9ede...",
"Name": "\u540d\u7a31",
"Id": "Id",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "Id\u61c9\u4ee5\u5b57\u6bcd\u958b\u982d\uff0c\u5f8c\u9762\u63a5\u8457\u5b57\u6bcd\uff0c\u6578\u5b57\uff0c\u7834\u6298\u865f\uff0c\u9ede\u6578\uff0c\u5192\u865f\u6216\u4e0b\u5283\u7dda\u3002",
"You have unsaved changes are you sure you want to navigate away?": "\u7de8\u8f2f\u5c1a\u672a\u88ab\u5132\u5b58\uff0c\u4f60\u78ba\u5b9a\u8981\u96e2\u958b\uff1f",
"Restore last draft": "\u8f09\u5165\u4e0a\u4e00\u6b21\u7de8\u8f2f\u7684\u8349\u7a3f",
"Special character...": "\u7279\u6b8a\u5b57\u5143......",
"Source code": "\u539f\u59cb\u78bc",
"Insert\/Edit code sample": "\u63d2\u5165\/\u7de8\u8f2f \u7a0b\u5f0f\u78bc\u7bc4\u4f8b",
"Language": "\u8a9e\u8a00",
"Code sample...": "\u7a0b\u5f0f\u78bc\u7bc4\u4f8b...",
"Color Picker": "\u9078\u8272\u5668",
"R": "\u7d05",
"G": "\u7da0",
"B": "\u85cd",
"Left to right": "\u5f9e\u5de6\u5230\u53f3",
"Right to left": "\u5f9e\u53f3\u5230\u5de6",
"Emoticons...": "\u8868\u60c5\u7b26\u865f\u2026",
"Metadata and Document Properties": "\u5f8c\u8a2d\u8cc7\u6599\u8207\u6587\u4ef6\u5c6c\u6027",
"Title": "\u6a19\u984c",
"Keywords": "\u95dc\u9375\u5b57",
"Description": "\u63cf\u8ff0",
"Robots": "\u6a5f\u5668\u4eba",
"Author": "\u4f5c\u8005",
"Encoding": "\u7de8\u78bc",
"Fullscreen": "\u5168\u87a2\u5e55",
"Action": "\u52d5\u4f5c",
"Shortcut": "\u5feb\u901f\u9375",
"Help": "\u5e6b\u52a9",
"Address": "\u5730\u5740",
"Focus to menubar": "\u8df3\u81f3\u9078\u55ae\u5217",
"Focus to toolbar": "\u8df3\u81f3\u5de5\u5177\u5217",
"Focus to element path": "\u8df3\u81f3HTML\u5143\u7d20\u5217",
"Focus to contextual toolbar": "\u8df3\u81f3\u5feb\u6377\u9078\u55ae",
"Insert link (if link plugin activated)": "\u65b0\u589e\u6377\u5f91 (\u6377\u5f91\u5916\u639b\u555f\u7528\u6642)",
"Save (if save plugin activated)": "\u5132\u5b58 (\u5132\u5b58\u5916\u639b\u555f\u7528\u6642)",
"Find (if searchreplace plugin activated)": "\u5c0b\u627e (\u5c0b\u627e\u53d6\u4ee3\u5916\u639b\u555f\u7528\u6642)",
"Plugins installed ({0}):": "({0}) \u500b\u5916\u639b\u5df2\u5b89\u88dd\uff1a",
"Premium plugins:": "\u52a0\u503c\u5916\u639b\uff1a",
"Learn more...": "\u4e86\u89e3\u66f4\u591a...",
"You are using {0}": "\u60a8\u6b63\u5728\u4f7f\u7528 {0}",
"Plugins": "\u5916\u639b",
"Handy Shortcuts": "\u5feb\u901f\u9375",
"Horizontal line": "\u6c34\u5e73\u7dda",
"Insert\/edit image": "\u63d2\u5165\/\u7de8\u8f2f \u5716\u7247",
"Image description": "\u5716\u7247\u63cf\u8ff0",
"Source": "\u5716\u7247\u7db2\u5740",
"Dimensions": "\u5c3a\u5bf8",
"Constrain proportions": "\u7b49\u6bd4\u4f8b\u7e2e\u653e",
"General": "\u4e00\u822c",
"Advanced": "\u9032\u968e",
"Style": "\u6a23\u5f0f",
"Vertical space": "\u9ad8\u5ea6",
"Horizontal space": "\u5bec\u5ea6",
"Border": "\u908a\u6846",
"Insert image": "\u63d2\u5165\u5716\u7247",
"Image...": "\u5716\u7247......",
"Image list": "\u5716\u7247\u6e05\u55ae",
"Rotate counterclockwise": "\u9006\u6642\u91dd\u65cb\u8f49",
"Rotate clockwise": "\u9806\u6642\u91dd\u65cb\u8f49",
"Flip vertically": "\u5782\u76f4\u7ffb\u8f49",
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f49",
"Edit image": "\u7de8\u8f2f\u5716\u7247",
"Image options": "\u5716\u7247\u9078\u9805",
"Zoom in": "\u653e\u5927",
"Zoom out": "\u7e2e\u5c0f",
"Crop": "\u88c1\u526a",
"Resize": "\u8abf\u6574\u5927\u5c0f",
"Orientation": "\u65b9\u5411",
"Brightness": "\u4eae\u5ea6",
"Sharpen": "\u92b3\u5316",
"Contrast": "\u5c0d\u6bd4",
"Color levels": "\u984f\u8272\u5c64\u6b21",
"Gamma": "\u4f3d\u99ac\u503c",
"Invert": "\u53cd\u8f49",
"Apply": "\u61c9\u7528",
"Back": "\u5f8c\u9000",
"Insert date\/time": "\u63d2\u5165 \u65e5\u671f\/\u6642\u9593",
"Date\/time": "\u65e5\u671f\/\u6642\u9593",
"Insert\/Edit Link": "\u63d2\u5165\/\u7de8\u8f2f\u9023\u7d50",
"Insert\/edit link": "\u63d2\u5165\/\u7de8\u8f2f\u9023\u7d50",
"Text to display": "\u986f\u793a\u6587\u5b57",
"Url": "\u7db2\u5740",
"Open link in...": "\u958b\u555f\u9023\u7d50\u65bc...",
"Current window": "\u76ee\u524d\u8996\u7a97",
"None": "\u7121",
"New window": "\u53e6\u958b\u8996\u7a97",
"Remove link": "\u79fb\u9664\u9023\u7d50",
"Anchors": "\u52a0\u5165\u9328\u9ede",
"Link...": "\u9023\u7d50...",
"Paste or type a link": "\u8cbc\u4e0a\u6216\u8f38\u5165\u9023\u7d50",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5beb\u7684URL\u70ba\u96fb\u5b50\u90f5\u4ef6\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7db4\u55ce\uff1f",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5beb\u7684URL\u5c6c\u65bc\u5916\u90e8\u93c8\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7db4\u55ce\uff1f",
"Link list": "\u9023\u7d50\u6e05\u55ae",
"Insert video": "\u63d2\u5165\u5f71\u97f3",
"Insert\/edit video": "\u63d2\u4ef6\/\u7de8\u8f2f \u5f71\u97f3",
"Insert\/edit media": "\u63d2\u5165\/\u7de8\u8f2f \u5a92\u9ad4",
"Alternative source": "\u66ff\u4ee3\u5f71\u97f3",
"Alternative source URL": "\u66ff\u4ee3\u4f86\u6e90URL",
"Media poster (Image URL)": "\u5a92\u9ad4\u6d77\u5831\uff08\u5f71\u50cfImage URL\uff09",
"Paste your embed code below:": "\u8acb\u5c07\u60a8\u7684\u5d4c\u5165\u5f0f\u7a0b\u5f0f\u78bc\u8cbc\u5728\u4e0b\u9762:",
"Embed": "\u5d4c\u5165\u78bc",
"Media...": "\u5a92\u9ad4...",
"Nonbreaking space": "\u4e0d\u5206\u884c\u7684\u7a7a\u683c",
"Page break": "\u5206\u9801",
"Paste as text": "\u4ee5\u7d14\u6587\u5b57\u8cbc\u4e0a",
"Preview": "\u9810\u89bd",
"Print...": "\u5217\u5370...",
"Save": "\u5132\u5b58",
"Find": "\u641c\u5c0b",
"Replace with": "\u66f4\u63db",
"Replace": "\u66ff\u63db",
"Replace all": "\u66ff\u63db\u5168\u90e8",
"Previous": "\u4e0a\u4e00\u500b",
"Next": "\u4e0b\u4e00\u500b",
"Find and replace...": "\u5c0b\u627e\u53ca\u53d6\u4ee3...",
"Could not find the specified string.": "\u7121\u6cd5\u67e5\u8a62\u5230\u6b64\u7279\u5b9a\u5b57\u4e32",
"Match case": "\u76f8\u5339\u914d\u6848\u4ef6",
"Find whole words only": "\u50c5\u627e\u51fa\u5b8c\u6574\u5b57\u532f",
"Spell check": "\u62fc\u5beb\u6aa2\u67e5",
"Ignore": "\u5ffd\u7565",
"Ignore all": "\u5ffd\u7565\u6240\u6709",
"Finish": "\u5b8c\u6210",
"Add to Dictionary": "\u52a0\u5165\u5b57\u5178\u4e2d",
"Insert table": "\u63d2\u5165\u8868\u683c",
"Table properties": "\u8868\u683c\u5c6c\u6027",
"Delete table": "\u522a\u9664\u8868\u683c",
"Cell": "\u5132\u5b58\u683c",
"Row": "\u5217",
"Column": "\u884c",
"Cell properties": "\u5132\u5b58\u683c\u5c6c\u6027",
"Merge cells": "\u5408\u4f75\u5132\u5b58\u683c",
"Split cell": "\u5206\u5272\u5132\u5b58\u683c",
"Insert row before": "\u63d2\u5165\u5217\u5728...\u4e4b\u524d",
"Insert row after": "\u63d2\u5165\u5217\u5728...\u4e4b\u5f8c",
"Delete row": "\u522a\u9664\u5217",
"Row properties": "\u5217\u5c6c\u6027",
"Cut row": "\u526a\u4e0b\u5217",
"Copy row": "\u8907\u88fd\u5217",
"Paste row before": "\u8cbc\u4e0a\u5217\u5728...\u4e4b\u524d",
"Paste row after": "\u8cbc\u4e0a\u5217\u5728...\u4e4b\u5f8c",
"Insert column before": "\u63d2\u5165\u6b04\u4f4d\u5728...\u4e4b\u524d",
"Insert column after": "\u63d2\u5165\u6b04\u4f4d\u5728...\u4e4b\u5f8c",
"Delete column": "\u522a\u9664\u884c",
"Cols": "\u6b04\u4f4d\u6bb5",
"Rows": "\u5217",
"Width": "\u5bec\u5ea6",
"Height": "\u9ad8\u5ea6",
"Cell spacing": "\u5132\u5b58\u683c\u5f97\u9593\u8ddd",
"Cell padding": "\u5132\u5b58\u683c\u7684\u908a\u8ddd",
"Show caption": "\u986f\u793a\u6a19\u984c",
"Left": "\u5de6\u908a",
"Center": "\u4e2d\u9593",
"Right": "\u53f3\u908a",
"Cell type": "\u5132\u5b58\u683c\u7684\u985e\u578b",
"Scope": "\u7bc4\u570d",
"Alignment": "\u5c0d\u9f4a",
"H Align": "\u6c34\u5e73\u4f4d\u7f6e",
"V Align": "\u5782\u76f4\u4f4d\u7f6e",
"Top": "\u7f6e\u9802",
"Middle": "\u7f6e\u4e2d",
"Bottom": "\u7f6e\u5e95",
"Header cell": "\u6a19\u982d\u5132\u5b58\u683c",
"Row group": "\u5217\u7fa4\u7d44",
"Column group": "\u6b04\u4f4d\u7fa4\u7d44",
"Row type": "\u884c\u7684\u985e\u578b",
"Header": "\u6a19\u982d",
"Body": "\u4e3b\u9ad4",
"Footer": "\u9801\u5c3e",
"Border color": "\u908a\u6846\u984f\u8272",
"Insert template...": "\u63d2\u5165\u6a23\u7248...",
"Templates": "\u6a23\u7248",
"Template": "\u6a23\u677f",
"Text color": "\u6587\u5b57\u984f\u8272",
"Background color": "\u80cc\u666f\u984f\u8272",
"Custom...": "\u81ea\u8a02",
"Custom color": "\u81ea\u8a02\u984f\u8272",
"No color": "No color",
"Remove color": "\u79fb\u9664\u984f\u8272",
"Table of Contents": "\u76ee\u9304",
"Show blocks": "\u986f\u793a\u5340\u584a\u8cc7\u8a0a",
"Show invisible characters": "\u986f\u793a\u96b1\u85cf\u5b57\u5143",
"Word count": "\u8a08\u7b97\u5b57\u6578",
"Count": "\u8a08\u7b97",
"Document": "\u6587\u4ef6",
"Selection": "\u9078\u9805",
"Words": "\u5b57\u6578",
"Words: {0}": "\u5b57\u6578\uff1a{0}",
"{0} words": "{0} \u5b57\u5143",
"File": "\u6a94\u6848",
"Edit": "\u7de8\u8f2f",
"Insert": "\u63d2\u5165",
"View": "\u6aa2\u8996",
"Format": "\u683c\u5f0f",
"Table": "\u8868\u683c",
"Tools": "\u5de5\u5177",
"Powered by {0}": "\u7531 {0} \u63d0\u4f9b",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u8c50\u5bcc\u7684\u6587\u672c\u5340\u57df\u3002\u6309ALT-F9\u524d\u5f80\u4e3b\u9078\u55ae\u3002\u6309ALT-F10\u547c\u53eb\u5de5\u5177\u6b04\u3002\u6309ALT-0\u5c0b\u6c42\u5e6b\u52a9",
"Image title": "\u5716\u7247\u6a19\u984c",
"Border width": "\u6846\u7dda\u5bec\u5ea6",
"Border style": "\u6846\u7dda\u6a23\u5f0f",
"Error": "\u932f\u8aa4",
"Warn": "\u8b66\u544a",
"Valid": "\u6709\u6548",
"To open the popup, press Shift+Enter": "\u8981\u958b\u555f\u5f48\u51fa\u8996\u7a97\uff0c\u8acb\u6309Shift+Enter",
"Rich Text Area. Press ALT-0 for help.": "\u5bcc\u6587\u672c\u5340\u57df\u3002\u8acb\u6309ALT-0\u5c0b\u6c42\u5354\u52a9\u3002",
"System Font": "\u7cfb\u7d71\u5b57\u578b",
"Failed to upload image: {0}": "\u7121\u6cd5\u4e0a\u50b3\u5f71\u50cf\uff1a{0}",
"Failed to load plugin: {0} from url {1}": "\u7121\u6cd5\u4e0a\u50b3\u63d2\u4ef6\uff1a{0}\u81eaurl{1}",
"Failed to load plugin url: {0}": "\u7121\u6cd5\u4e0a\u50b3\u63d2\u4ef6\uff1a{0}",
"Failed to initialize plugin: {0}": "\u7121\u6cd5\u555f\u52d5\u63d2\u4ef6\uff1a{0}",
"example": "\u7bc4\u4f8b",
"Search": "\u641c\u7d22",
"All": "\u5168\u90e8",
"Currency": "\u8ca8\u5e63",
"Text": "\u6587\u672c",
"Quotations": "\u5f15\u7528",
"Mathematical": "\u6578\u5b78",
"Extended Latin": "\u62c9\u4e01\u5b57\u6bcd\u64f4\u5145",
"Symbols": "\u7b26\u865f",
"Arrows": "\u7bad\u982d",
"User Defined": "\u4f7f\u7528\u8005\u5df2\u5b9a\u7fa9",
"dollar sign": "\u7f8e\u5143\u7b26\u865f",
"currency sign": "\u8ca8\u5e63\u7b26\u865f",
"euro-currency sign": "\u6b50\u5143\u7b26\u865f",
"colon sign": "\u79d1\u6717\u7b26\u865f",
"cruzeiro sign": "\u514b\u9b6f\u8cfd\u7f85\u7b26\u865f",
"french franc sign": "\u6cd5\u6717\u7b26\u865f",
"lira sign": "\u91cc\u62c9\u7b26\u865f",
"mill sign": "\u6587\u7b26\u865f",
"naira sign": "\u5948\u62c9\u7b26\u865f",
"peseta sign": "\u6bd4\u585e\u5854\u7b26\u865f",
"rupee sign": "\u76e7\u6bd4\u7b26\u865f",
"won sign": "\u97d3\u571c\u7b26\u865f",
"new sheqel sign": "\u65b0\u8b1d\u514b\u723e\u7b26\u865f",
"dong sign": "\u8d8a\u5357\u76fe\u7b26\u865f",
"kip sign": "\u8001\u64be\u5e63\u7b26\u865f",
"tugrik sign": "\u8499\u53e4\u5e63\u7b26\u865f",
"drachma sign": "\u5fb7\u514b\u62c9\u99ac\u7b26\u865f",
"german penny symbol": "\u5fb7\u570b\u5206\u7b26\u865f",
"peso sign": "\u62ab\u7d22\u7b26\u865f",
"guarani sign": "\u5df4\u62c9\u572d\u5e63\u7b26\u865f",
"austral sign": "\u963f\u6839\u5ef7\u5e63\u7b26\u865f",
"hryvnia sign": "\u70cf\u514b\u862d\u5e63\u7b26\u865f",
"cedi sign": "\u8fe6\u7d0d\u5e63\u7b26\u865f",
"livre tournois sign": "\u91cc\u5f17\u723e\u7b26\u865f",
"spesmilo sign": "\u570b\u969b\u5e63\u7b26\u865f",
"tenge sign": "\u54c8\u85a9\u514b\u5e63\u7b26\u865f",
"indian rupee sign": "\u5370\u5ea6\u76e7\u6bd4\u7b26\u865f",
"turkish lira sign": "\u571f\u8033\u5176\u91cc\u62c9\u7b26\u865f",
"nordic mark sign": "\u5317\u6b50\u99ac\u514b\u7b26\u865f",
"manat sign": "\u4e9e\u585e\u62dc\u7136\u5e63\u7b26\u865f",
"ruble sign": "\u76e7\u5e03\u7b26\u865f",
"yen character": "\u65e5\u5713\u7b26\u865f",
"yuan character": "\u4eba\u6c11\u5e63\u7b26\u865f",
"yuan character, in hong kong and taiwan": "\u6e2f\u5143\u8207\u53f0\u5e63\u7b26\u865f",
"yen\/yuan character variant one": "\u65e5\u5713\/\u4eba\u6c11\u5e63\u7b26\u865f\u8b8a\u5316\u578b",
"Loading emoticons...": "\u8f09\u5165\u8868\u60c5\u7b26\u865f\u2026",
"Could not load emoticons": "\u7121\u6cd5\u8f09\u5165\u8868\u60c5\u7b26\u865f",
"People": "\u4eba",
"Animals and Nature": "\u52d5\u7269\u8207\u81ea\u7136",
"Food and Drink": "\u98f2\u98df",
"Activity": "\u6d3b\u52d5",
"Travel and Places": "\u65c5\u884c\u8207\u5730\u9ede",
"Objects": "\u7269\u4ef6",
"Flags": "\u65d7\u6a19",
"Characters": "\u5b57\u5143",
"Characters (no spaces)": "\u5b57\u5143\uff08\u7121\u7a7a\u683c\uff09",
"{0} characters": "{0}\u5b57\u5143",
"Error: Form submit field collision.": "\u932f\u8aa4\uff1a\u8868\u683c\u905e\u4ea4\u6b04\u4f4d\u885d\u7a81\u3002",
"Error: No form element found.": "\u932f\u8aa4\uff1a\u627e\u4e0d\u5230\u8868\u683c\u5143\u7d20\u3002",
"Update": "\u66f4\u65b0",
"Color swatch": "\u8272\u5f69\u6a23\u672c",
"Turquoise": "\u571f\u8033\u5176\u85cd",
"Green": "\u7da0\u8272",
"Blue": "\u85cd\u8272",
"Purple": "\u7d2b\u8272",
"Navy Blue": "\u6df1\u85cd\u8272",
"Dark Turquoise": "\u6df1\u571f\u8033\u5176\u85cd",
"Dark Green": "\u6df1\u7da0\u8272",
"Medium Blue": "\u4e2d\u85cd\u8272",
"Medium Purple": "\u4e2d\u7d2b\u8272",
"Midnight Blue": "\u9ed1\u85cd\u8272",
"Yellow": "\u9ec3\u8272",
"Orange": "\u6a59\u8272",
"Red": "\u7d05\u8272",
"Light Gray": "\u6dfa\u7070\u8272",
"Gray": "\u7070\u8272",
"Dark Yellow": "\u6df1\u9ec3\u8272",
"Dark Orange": "\u6df1\u6a59\u8272",
"Dark Red": "\u6697\u7d05\u8272",
"Medium Gray": "\u4e2d\u7070\u8272",
"Dark Gray": "\u6df1\u7070\u8272",
"Light Green": "\u6de1\u7da0\u8272",
"Light Yellow": "\u6dfa\u9ec3\u8272",
"Light Red": "\u6dfa\u7d05\u8272",
"Light Purple": "\u6dfa\u7d2b\u8272",
"Light Blue": "\u6dfa\u85cd\u8272",
"Dark Purple": "\u6df1\u7d2b\u8272",
"Dark Blue": "\u6df1\u85cd\u8272",
"Black": "\u9ed1\u8272",
"White": "\u767d\u8272",
"Switch to or from fullscreen mode": "\u8f49\u63db\u81ea\/\u81f3\u5168\u87a2\u5e55\u6a21\u5f0f",
"Open help dialog": "\u958b\u555f\u5354\u52a9\u5c0d\u8a71",
"history": "\u6b77\u53f2",
"styles": "\u6a23\u5f0f",
"formatting": "\u683c\u5f0f",
"alignment": "\u5c0d\u9f4a",
"indentation": "\u7e2e\u6392",
"permanent pen": "\u6c38\u4e45\u6027\u7b46",
"comments": "\u8a3b\u89e3",
"Format Painter": "\u8907\u88fd\u683c\u5f0f",
"Insert\/edit iframe": "\u63d2\u5165\/\u7de8\u8f2fiframe",
"Capitalization": "\u5927\u5beb",
"lowercase": "\u5c0f\u5beb",
"UPPERCASE": "\u5927\u5beb",
"Title Case": "\u5b57\u9996\u5927\u5beb",
"Permanent Pen Properties": "\u6c38\u4e45\u6a19\u8a18\u5c6c\u6027",
"Permanent pen properties...": "\u6c38\u4e45\u6a19\u8a18\u5c6c\u6027......",
"Font": "\u5b57\u578b",
"Size": "\u5b57\u5f62\u5927\u5c0f",
"More...": "\u66f4\u591a\u8cc7\u8a0a......",
"Spellcheck Language": "\u62fc\u5beb\u8a9e\u8a00",
"Select...": "\u9078\u64c7......",
"Preferences": "\u9996\u9078\u9805",
"Yes": "\u662f",
"No": "\u5426",
"Keyboard Navigation": "\u9375\u76e4\u5c0e\u822a",
"Version": "\u7248\u672c",
"Anchor": "\u52a0\u5165\u9328\u9ede",
"Special character": "\u7279\u6b8a\u5b57\u5143",
"Code sample": "\u7a0b\u5f0f\u78bc\u7bc4\u4f8b",
"Color": "\u984f\u8272",
"Emoticons": "\u8868\u60c5",
"Document properties": "\u6587\u4ef6\u7684\u5c6c\u6027",
"Image": "\u5716\u7247",
"Insert link": "\u63d2\u5165\u9023\u7d50",
"Target": "\u958b\u555f\u65b9\u5f0f",
"Link": "\u9023\u7d50",
"Poster": "\u9810\u89bd\u5716\u7247",
"Media": "\u5a92\u9ad4",
"Print": "\u5217\u5370",
"Prev": "\u4e0a\u4e00\u500b",
"Find and replace": "\u5c0b\u627e\u53ca\u53d6\u4ee3",
"Whole words": "\u6574\u500b\u55ae\u5b57",
"Spellcheck": "\u62fc\u5b57\u6aa2\u67e5",
"Caption": "\u8868\u683c\u6a19\u984c",
"Insert template": "\u63d2\u5165\u6a23\u7248"
});

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
body{background-color:#2f3742;color:#dfe0e4;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}a{color:#4099ff}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#6d737b}figure{display:table;margin:1rem auto}figure figcaption{color:#8a8f97;display:block;margin-top:.25rem;text-align:center}hr{border-color:#6d737b;border-style:solid;border-width:1px 0 0 0}code{background-color:#6d737b;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #6d737b;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #6d737b;margin-right:1.5rem;padding-right:1rem}

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
@media screen{html{background:#f4f4f4;min-height:100%}}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif}@media screen{body{background-color:#fff;box-shadow:0 0 4px rgba(0,0,0,.15);box-sizing:border-box;margin:1rem auto 0;max-width:820px;min-height:calc(100vh - 1rem);padding:4rem 6rem 6rem 6rem}}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure figcaption{color:#999;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem auto;max-width:900px}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;left:0;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;position:fixed;top:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox.tox-tinymce.tox-fullscreen{background-color:transparent;z-index:1200}.tox-shadowhost.tox-fullscreen{z-index:1200}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
.tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{background-color:green;display:inline-block;opacity:.5;position:absolute}body{-webkit-text-size-adjust:none}body img{max-width:96vw}body table img{max-width:95%}body{font-family:sans-serif}table{border-collapse:collapse}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,7 @@
/**
* Copyright (c) Tiny Technologies, Inc. All rights reserved.
* Licensed under the LGPL or a commercial license.
* For LGPL see License.txt in the project root for license information.
* For commercial licenses see https://www.tiny.cloud/
*/
body.tox-dialog__disable-scroll{overflow:hidden}.tox-fullscreen{border:0;height:100%;left:0;margin:0;overflow:hidden;-ms-scroll-chaining:none;overscroll-behavior:none;padding:0;position:fixed;top:0;touch-action:pinch-zoom;width:100%}.tox.tox-tinymce.tox-fullscreen .tox-statusbar__resize-handle{display:none}.tox.tox-tinymce.tox-fullscreen{background-color:transparent;z-index:1200}.tox-shadowhost.tox-fullscreen{z-index:1200}.tox-fullscreen .tox.tox-tinymce-aux,.tox-fullscreen~.tox.tox-tinymce-aux{z-index:1201}

@ -15,6 +15,7 @@ export const elementDetail = async (id: number): Promise<any> => (await axios.po
export const save = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/product/bank/products/save`, data)).data;
export const riskSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/managerOfRiskControl/bankRiskControlAllocation/save`, data)).data;
export const riskUpdate = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/managerOfRiskControl/bankRiskControlAllocation/update`, data)).data;
export const riskById = async (id: number): Promise<any> => (await axios.post(`/product/managerOfRiskControl/bankRiskControlAllocation/findById?id=${id}`)).data;
export const riskControlDetailsAreDisplayed = async (id: number): Promise<any> =>
(await axios.post(`/product/managerOfRiskControl/bankRiskControlAllocation/riskControlDetailsAreDisplayed?id=${id}`)).data;
export const examineAndApprove = async (id: number | string, opinionDescription: string, status: number, approvalTime: string): Promise<any> =>

@ -3,103 +3,35 @@ import { getIds } from '@/utils/common';
const host = `http://192.168.31.51:9000`;
export const accessStrategyGovernmentBlacklistList = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyGovernmentBlacklist/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyGovernmentBlacklistFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyGovernmentBlacklist/details`, {}, { params })).data;
export const accessStrategyGovernmentBlacklistFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyGovernmentBlacklist/details`, getIds())).data;
export const accessStrategyGovernmentBlacklistSave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyGovernmentBlacklist/saveOrUpdate`, data)).data;
export const accessStrategyGovernmentBlacklistDel = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyGovernmentBlacklist/delete`, data)).data;
export const accessStrategyEnterpriseBlacklist = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyEnterpriseBlacklist/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyEnterpriseBlacklistFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/details`, {}, { params })).data;
export const accessStrategyEnterpriseBlacklistFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyEnterpriseBlacklist/details`, getIds())).data;
export const accessStrategyEnterpriseBlacklistSave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/saveOrUpdate`, data)).data;
export const accessStrategyEnterpriseBlacklistDel = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/delete`, data)).data;
export const accessStrategyAntiFraudStrategy = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyAntiFraudStrategy/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyAntiFraudStrategyFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyAntiFraudStrategy/details`, {}, { params })).data;
export const accessStrategyAntiFraudStrategyFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyAntiFraudStrategy/details`, getIds())).data;
export const accessStrategyAntiFraudStrategySave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyAntiFraudStrategy/saveOrUpdate`, data)).data;
export const accessStrategyAntiFraudStrategyDel = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyAntiFraudStrategy/delete`, data)).data;
export const accessStrategyBusinessBlacklist = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyBusinessBlacklist/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyBusinessBlacklistFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyBusinessBlacklist/details`, {}, { params })).data;
export const accessStrategyBusinessBlacklistFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyBusinessBlacklist/details`, getIds())).data;
export const accessStrategyBusinessBlacklistSave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyBusinessBlacklist/saveOrUpdate`, data)).data;
export const accessStrategyBusinessBlacklistDel = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyBusinessBlacklist/delete`, data)).data;
export const accessStrategyCreditBlacklist = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyCreditBlacklist/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyCreditBlacklistFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyCreditBlacklist/details`, {}, { params })).data;
export const accessStrategyCreditBlacklistFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyCreditBlacklist/details`, getIds())).data;
export const accessStrategyCreditBlacklistSave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyCreditBlacklist/saveOrUpdate`, data)).data;
export const accessStrategyCreditBlacklistDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/accessStrategyCreditBlacklist/delete`, data)).data;
export const accessStrategyInlineBlacklist = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyInlineBlacklist/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyInlineBlacklistFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyInlineBlacklist/details`, {}, { params })).data;
export const accessStrategyInlineBlacklistFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyInlineBlacklist/details`, getIds())).data;
export const accessStrategyInlineBlacklistSave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyInlineBlacklist/saveOrUpdate`, data)).data;
export const accessStrategyInlineBlacklistDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/accessStrategyInlineBlacklist/delete`, data)).data;
export const accessStrategyNegativeIndustryStrategy = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/accessStrategyNegativeIndustryStrategy/list`, {
...getIds(),
...data,
})
).data;
export const accessStrategyNegativeIndustryStrategyFind = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/details`, {}, { params })).data;
export const accessStrategyNegativeIndustryStrategyFind = async (): Promise<any> => (await axios.post(`/product/accessStrategyNegativeIndustryStrategy/details`, getIds())).data;
export const accessStrategyNegativeIndustryStrategySave = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/saveOrUpdate`, data)).data;
export const accessStrategyNegativeIndustryStrategyDel = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/delete`, data)).data;
export const delCredit = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/creditScoringStrategy/delete`, data)).data;
export const delCredit = async (id: number): Promise<any> => (await axios.post(`/product/creditScoringStrategy/delete?strategyId=${id}`)).data;
export const findCredit = async (id: number): Promise<any> => (await axios.post(`/product/creditScoringStrategy/details?strategyId=${id}`)).data;
export const listCredit = async (data: Record<string, any>): Promise<any> =>
(
@ -119,95 +51,31 @@ export const detailRick = async (type: number): Promise<any> =>
).data;
export const saveRick = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/riskDegreeStrategy/saveOrUpdate`, data)).data;
export const interestRateModelList = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/interestRateModel/list`, {
...getIds(),
...data,
})
).data;
export const businessInterestRateDetails = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/interestRateModel/businessInterestRateDetails`, {}, { params })).data;
export const businessInterestRateDetails = async (): Promise<any> => (await axios.post(`/product/interestRateModel/businessInterestRateDetails`, getIds())).data;
export const businessInterestRateSaveOrUpdate = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/interestRateModel/businessInterestRateSaveOrUpdate`, data)).data;
export const personalInterestRateDetails = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/interestRateModel/personalInterestRateDetails`, {}, { params })).data;
export const personalInterestRateDetails = async (): Promise<any> => (await axios.post(`/product/interestRateModel/personalInterestRateDetails`, getIds())).data;
export const personalInterestRateSaveOrUpdate = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/interestRateModel/personalInterestRateSaveOrUpdate`, data)).data;
export const deleteBusinessInterestRate = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/interestRateModel/deleteBusinessInterestRate`, data)).data;
export const deletePersonalInterestRate = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/interestRateModel/deletePersonalInterestRate`, data)).data;
export const quotaModelList = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/quotaModel/list`, {
...getIds(),
...data,
})
).data;
export const quotaModelDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/quotaModel/delete`, data)).data;
export const businessQuotaModelDetails = async (): Promise<any> => (await axios.post(`/product/quotaModel/businessQuotaModelDetails`, getIds())).data;
export const businessQuotaModelSaveOrUpdate = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/quotaModel/businessQuotaModelSaveOrUpdate`, data)).data;
export const personalCreditModelDetails = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/quotaModel/personalCreditModelDetails`, {}, { params })).data;
export const personalCreditModelDetails = async (): Promise<any> => (await axios.post(`/product/quotaModel/personalCreditModelDetails`, getIds())).data;
export const personalCreditModelSaveOrUpdate = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/quotaModel/personalCreditModelSaveOrUpdate`, data)).data;
export const fiveLevelClassification = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/fiveLevelClassification/list`, {
...getIds(),
...data,
})
).data;
export const fiveLevelClassificationDetails = async (params: Record<string, any>): Promise<any> =>
(await axios.post(`/product/fiveLevelClassification/details`, {}, { params })).data;
export const fiveLevelClassificationDetails = async (): Promise<any> => (await axios.post(`/product/fiveLevelClassification/details`, getIds())).data;
export const fiveLevelClassificationSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/fiveLevelClassification/saveOrUpdate`, data)).data;
export const fiveLevelClassificationDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/fiveLevelClassification/delete`, data)).data;
export const postLoanInspection = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/postLoanInspection/list`, {
...getIds(),
...data,
})
).data;
export const postLoanInspectionDetails = async (params: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanInspection/details`, {}, { params })).data;
export const postLoanInspectionDetails = async (): Promise<any> => (await axios.post(`/product/postLoanInspection/details`, getIds())).data;
export const postLoanInspectionSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanInspection/saveOrUpdate`, data)).data;
export const postLoanInspectionDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanInspection/delete`, data)).data;
export const postCreditScore = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/postCreditScore/list`, {
...getIds(),
...data,
})
).data;
export const postCreditScoreDetails = async (params: Record<string, any>): Promise<any> => (await axios.post(`/product/postCreditScore/details`, {}, { params })).data;
export const postCreditScoreDetails = async (): Promise<any> => (await axios.post(`/product/postCreditScore/details`, getIds())).data;
export const postCreditScoreSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postCreditScore/saveOrUpdate`, data)).data;
export const postCreditScoreDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postCreditScore/delete`, data)).data;
export const postLoanWarning = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/postLoanWarning/list`, {
...getIds(),
...data,
})
).data;
export const postLoanWarningDetails = async (params: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanWarning/details`, {}, { params })).data;
export const postLoanWarningDetails = async (): Promise<any> => (await axios.post(`/product/postLoanWarning/details`, getIds())).data;
export const postLoanWarningSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanWarning/saveOrUpdate`, data)).data;
export const postLoanWarningDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanWarning/delete`, data)).data;
export const collectionAfterLoan = async (data: Record<string, any>): Promise<any> =>
(
await axios.post(`/product/collectionAfterLoan/list`, {
...getIds(),
...data,
})
).data;
export const collectionAfterLoanDetails = async (params: Record<string, any>): Promise<any> => (await axios.post(`/product/collectionAfterLoan/details`, {}, { params })).data;
export const collectionAfterLoanDetails = async (): Promise<any> => (await axios.post(`/product/collectionAfterLoan/details`, getIds())).data;
export const collectionAfterLoanSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/collectionAfterLoan/saveOrUpdate`, data)).data;
export const collectionAfterLoanDel = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/collectionAfterLoan/delete`, data)).data;
export const isTheStrategyRelatedToTheProduct = async (data: Record<string, any>): Promise<any> =>
(await axios.post(`/product/managerOfRiskControl/bankRiskControlAllocation/isTheStrategyRelatedToTheProduct`, data)).data;

@ -17,4 +17,3 @@ export const editExperimentalData = async (data: Record<string, any>): Promise<a
export const getStartTime = async (params: Record<string, any>): Promise<any> => (await axios.get('/python/python/getStartTime', { params })).data;
export const getCurrentTime = async (): Promise<any> => (await axios.get('/competition/competition/management/getCurrentTime')).data;
export const heartbeatDetection = async (): Promise<any> => (await axios.get('/nakadai/message/heartbeatDetection')).data;
export const initData = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/product/bank/operation/initData`, data)).data;

@ -0,0 +1,31 @@
import axios from '@/utils/request';
export const queryOrgList = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/org', { params })).data;
export const queryOrg = async (id: number): Promise<any> => (await axios.get(`/backend/core/org/${id}`)).data;
export const createOrg = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/org', data)).data;
export const updateOrg = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/org?_method=put', data)).data;
export const updateOrgOrder = async (data: number[]): Promise<any> => (await axios.post('/backend/core/org/order?_method=put', data)).data;
export const deleteOrg = async (data: number[]): Promise<any> => (await axios.post('/backend/core/org?_method=delete', data)).data;
export const queryRoleList = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/role', { params })).data;
export const queryRole = async (id: number): Promise<any> => (await axios.get(`/backend/core/role/${id}`)).data;
export const createRole = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/role', data)).data;
export const updateRole = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/role?_method=put', data)).data;
export const updateRoleOrder = async (data: number[]): Promise<any> => (await axios.post('/backend/core/role/order?_method=put', data)).data;
export const deleteRole = async (data: number[]): Promise<any> => (await axios.post('/backend/core/role?_method=delete', data)).data;
export const queryGroupList = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/group', { params })).data;
export const queryGroup = async (id: number): Promise<any> => (await axios.get(`/backend/core/group/${id}`)).data;
export const createGroup = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/group', data)).data;
export const updateGroup = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/group?_method=put', data)).data;
export const updateGroupOrder = async (data: number[]): Promise<any> => (await axios.post('/backend/core/group/order?_method=put', data)).data;
export const deleteGroup = async (data: number[]): Promise<any> => (await axios.post('/backend/core/group?_method=delete', data)).data;
export const queryUserPage = async (params?: Record<string, any>): Promise<any> => (await axios.get('/backend/core/user', { params })).data;
export const queryUser = async (id: number): Promise<any> => (await axios.get(`/backend/core/user/${id}`)).data;
export const createUser = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/user', data)).data;
export const updateUser = async (data: Record<string, any>): Promise<any> => (await axios.post('/backend/core/user?_method=put', data)).data;
export const deleteUser = async (data: number[]): Promise<any> => (await axios.post('/backend/core/user?_method=delete', data)).data;
export const usernameValidation = async (username?: string): Promise<any> => (await axios.get('/backend/core/user/username-validation', { params: { username } })).data;
export const emailValidation = async (email?: string): Promise<any> => (await axios.get('/backend/core/user/email-validation', { params: { email } })).data;
export const mobileValidation = async (mobile?: string): Promise<any> => (await axios.get('/backend/core/user/mobile-validation', { params: { mobile } })).data;

@ -1 +0,0 @@
<?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="1713852488689" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2030" width="20" height="20" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M900.896 240.832c-21.344-29.024-51.04-63.04-83.584-95.552s-66.528-62.304-95.552-83.552c-49.44-36.256-73.376-40.384-87.136-40.384l-475.296 0c-42.336 0-76.704 34.336-76.704 76.672l0 827.968c0 42.336 34.368 76.704 76.704 76.704l705.248 0c42.208 0 76.768-34.336 76.768-76.704l0-597.952c-0.032-13.792-4.256-37.792-40.48-87.168l0 0 0 0zM773.856 188.672c29.504 29.472 52.544 55.968 69.568 77.984l-147.552 0 0-147.552c22.016 17.056 48.544 40.16 77.984 69.536l0 0 0 0 0 0zM880.032 925.952c0 8.384-7.008 15.392-15.392 15.392l-705.248 0c-8.384 0-15.392-7.008-15.392-15.392l0-827.936c0-8.288 7.008-15.328 15.392-15.328l475.296 0 0 214.688c0 16.864 13.728 30.688 30.688 30.688l214.688 0 0.032 597.92zM779.872 823.296l-172.928-172.96c29.024-36.384 46.432-82.464 46.432-132.704 0-117.6-95.328-212.896-212.896-212.896-117.632 0-212.896 95.296-212.896 212.896s95.328 212.896 212.896 212.896c46.304 0 83.744-9.344 118.688-34.496l173.984 173.984c6.56 6.56 17.088 6.56 23.584 0l23.136-23.072c6.432-6.528 6.432-17.12 0-23.648l0 0 0 0zM440.448 656.832c-76.896 0-139.232-62.336-139.232-139.232s62.336-139.232 139.232-139.232 139.232 62.336 139.232 139.232-62.304 139.232-139.232 139.232l0 0 0 0z" fill="#006bff" p-id="2031"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@ -17,7 +17,7 @@ export default {
return new Promise(async (resolve, reject) => {
try {
// 上传到阿里云oss
const res = await client.multipartUpload(`${Date.now()}.${getFileExt(file.name)}`, file);
const res = await client.multipartUpload(Date.now() + '.' + getFileExt(file.name), file);
resolve({
format: getFileExt(file.name),
name: file.name,

@ -1,7 +1,10 @@
<template>
<div class="flex items-center p-3 mb-5 bg-white rounded-[10px]">
<div class="inline-flex items-center cursor-pointer" @click="back">
<img src="@/assets/images/back.png" alt="" class="" />
<div class="inline-flex items-center cursor-pointer"
@click="back">
<img src="@/assets/images/back.png"
alt=""
class="" />
<span class="ml-[6px] text-sm text-[#3C65FF]">返回</span>
</div>
<span class="mx-5 text-sm text-[#999]">|</span>
@ -9,7 +12,8 @@
</div>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router';
import { onMounted, ref } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import { logout } from '@/store/useCurrentUser';
const props = defineProps({

@ -1,48 +1,83 @@
<template>
<div v-if="!hidePanel" :class="['panel', { active: visible }]" id="panel" ref="container" :style="style" v-loading="loading">
<el-container class="scrollbar" id="container" v-show="visible">
<el-header class="panel-header" id="panelHeader">
<div class="project">
<div class="inline-flex items-center">
<p class="whitespace-nowrap">实训项目</p>
<el-tooltip effect="dark" content="点击右侧“下三角”按钮可切换实验项目" placement="bottom">
<i class="info el-icon-warning" style="margin-left: 10px"></i>
</el-tooltip>
<div v-if="!hidePanel"
:class="['panel', { active: visible }]"
id="panel"
ref="container"
:style="style">
<el-container class="scrollbar"
id="container"
v-show="visible">
<el-header id="header">
<div class="panel-header"
id="panelHeader">
<div class="project">
<div class="inline-flex items-center">
<p>实训项目</p>
<el-tooltip effect="dark"
content="点击右侧“下三角”按钮可切换实验项目"
placement="bottom">
<i class="info el-icon-warning"
style="margin-left: 10px"></i>
</el-tooltip>
</div>
<el-select v-model="param.projectId"
placeholder="请选择"
class="select"
:disabled="per != 0"
@change="getCache(1)">
<el-option v-for="(item, i) in projectList"
:key="item.projectId"
:label="i + 1 + '. ' + item.projectName"
:value="item.projectId"></el-option>
</el-select>
</div>
<el-select v-model="param.projectId" placeholder="请选择" class="select" :disabled="per != 0" @change="getCache(1)">
<el-option v-for="(item, i) in projectList" :key="item.projectId" :label="i + 1 + '. ' + item.projectName" :value="item.projectId"></el-option>
</el-select>
</div>
<div class="item">
<div class="count">
实训{{ text }}时间 <span>{{ day }}</span
> <span>{{ hour }}</span
>小时 <span>{{ minutes }}</span
> <span>{{ seconds }}</span
>
<div class="item">
<div class="count">
实训{{ text }}时间 <span>{{ day }}</span> <span>{{ hour }}</span>小时 <span>{{ minutes }}</span> <span>{{ seconds }}</span>
</div>
</div>
<div class="item">
<div>
总得分
<span class="total-score">{{ grade }}</span>
</div>
</div>
<div>
<el-button class="h-[40px]"
@click="toReport"
v-if="isSubmit">查看实验报告</el-button>
<el-button class="reload h-[40px]"
@click="reload(1)"
v-show="per == 0">重新开始</el-button>
<el-button type="primary"
class="submit btn h-[40px]"
:loading="submiting"
@click="confirmSubmit"
:disabled="isSubmit || !projectList.length">提交</el-button>
</div>
</div>
<div v-if="per !== 2" class="item">
总得分
<span class="total-score">{{ grade }}</span>
</div>
<div class="actions">
<el-button class="h-[40px]" @click="toReport" v-if="isSubmit">查看实验报告</el-button>
<el-button class="reload h-[40px]" @click="reloadConfirm" v-show="per == 0">重新开始</el-button>
<el-button type="primary" class="submit btn h-[40px]" :loading="submiting" @click="confirmSubmit" :disabled="isSubmit || !projectList.length">提交</el-button>
</div>
</el-header>
<el-container id="infoContainer">
<el-aside id="aside" width="30%">
<el-aside id="aside"
width="30%">
<div class="aside-header">
<div class="p-title">
<i class="el-icon-s-order"></i>
<p>实验目标</p>
</div>
<div class="goal">
<div v-if="pd.experimentTargetType == 0 || !pd.experimentTargetType" class="ql-editor" v-html="pd.experimentTarget"></div>
<div v-if="pd.experimentTargetType == 0 || !pd.experimentTargetType"
class="ql-editor"
v-html="pd.experimentTarget"></div>
<mavon-editor v-else class="md" v-model="pd.experimentTarget" :ishljs="true" :subfield="false" :editable="false" :toolbarsFlag="false" :boxShadowStyle="none" />
<mavon-editor v-else
class="md"
v-model="pd.experimentTarget"
:ishljs="true"
:subfield="false"
:editable="false"
:toolbarsFlag="false"
:boxShadowStyle="none" />
</div>
</div>
<div class="aside-footer">
@ -53,20 +88,35 @@
<div>
<el-row>
<el-col :span="24">
<el-card shadow="never" :border="false">
<el-table class="task-table" :data="taskList" :stripe="true">
<el-card shadow="never"
:border="false">
<el-table class="task-table"
:data="taskList"
:stripe="true">
<el-table-column type="index"></el-table-column>
<el-table-column prop="name" label="判分点" align="center"></el-table-column>
<el-table-column prop="score" label="分值" width="60" align="center"></el-table-column>
<el-table-column prop="name"
label="判分点"
align="center"></el-table-column>
<el-table-column prop="score"
label="分值"
width="60"
align="center"></el-table-column>
<template v-if="!param.competitionId">
<el-table-column label="结果" width="60" align="center">
<template #default="{ row }">
<el-table-column label="结果"
width="60"
align="center">
<template v-slot="scope">
<template v-if="isSubmit">
<div v-if="!param.competitionId" class="flex justify-center items-center">
<el-icon v-if="row.finishedResult" color="#15d500" :size="16">
<div v-if="!param.competitionId"
class="flex justify-center items-center">
<el-icon v-if="scope.row.finishedResult"
color="#15d500"
:size="16">
<Check />
</el-icon>
<el-icon v-else color="#f00" :size="16">
<el-icon v-else
color="#f00"
:size="16">
<Close />
</el-icon>
</div>
@ -74,9 +124,12 @@
</template>
</template>
</el-table-column>
<el-table-column label="得分" width="60" align="center">
<template #default="{ row }">
<template v-if="isSubmit">{{ param.competitionId ? '-' : row.examScore }}</template>
<el-table-column prop="score"
label="得分"
width="60"
align="center">
<template v-slot="scope">
<template v-if="isSubmit">{{ param.competitionId ? '-' : scope.row.examScore }}</template>
</template>
</el-table-column>
</template>
@ -88,38 +141,65 @@
</div>
</el-aside>
<el-main id="main">
<el-tabs class="info-tab" v-model="pannelTab" type="card">
<el-tab-pane label="项目背景" name="first">
<div v-if="pd.experimentDescriptionType == 0 || !pd.experimentDescriptionType" class="ql-editor" v-html="pd.experimentDescription"></div>
<el-tabs class="info-tab"
v-model="pannelTab"
type="card">
<el-tab-pane label="项目背景"
name="first">
<div v-if="pd.experimentDescriptionType == 0 || !pd.experimentDescriptionType"
class="ql-editor"
v-html="pd.experimentDescription"></div>
<mavon-editor v-else class="md" v-model="pd.experimentDescription" :ishljs="true" :subfield="false" :editable="false" :toolbarsFlag="false" :boxShadowStyle="none" />
<mavon-editor v-else
class="md"
v-model="pd.experimentDescription"
:ishljs="true"
:subfield="false"
:editable="false"
:toolbarsFlag="false"
:boxShadowStyle="none" />
</el-tab-pane>
<el-tab-pane label="实验要求" name="second">
<el-tab-pane label="实验要求"
name="second">
<el-collapse v-model="curReq">
<el-collapse-item v-for="item in points" :name="item.judgmentId" :key="item.judgmentId">
<el-collapse-item v-for="item in points"
:name="item.judgmentId"
:key="item.judgmentId">
<template v-slot:title>
<i class="el-icon-s-ticket"></i>
<div class="break-all des" v-html="item.name"></div>
<div class="break-all des"
v-html="item.name"></div>
</template>
<div v-if="item.experimentalRequirementsType == 0 || !item.experimentalRequirementsType" class="ql-editor" v-html="item.experimentalRequirements"></div>
<div v-if="item.experimentalRequirementsType == 0 || !item.experimentalRequirementsType"
class="ql-editor"
v-html="item.experimentalRequirements"></div>
<mavon-editor
v-else
class="md"
v-model="item.experimentalRequirements"
:ishljs="true"
:subfield="false"
:editable="false"
:toolbarsFlag="false"
:boxShadowStyle="none"
/>
<mavon-editor v-else
class="md"
v-model="item.experimentalRequirements"
:ishljs="true"
:subfield="false"
:editable="false"
:toolbarsFlag="false"
:boxShadowStyle="none" />
</el-collapse-item>
</el-collapse>
</el-tab-pane>
<el-tab-pane label="实验提示" name="third" v-if="hintOpen">
<div v-if="pd.experimentHintType == 0 || !pd.experimentHintType" class="ql-editor" v-html="pd.experimentHint"></div>
<el-tab-pane label="实验提示"
name="third"
v-if="hintOpen">
<div v-if="pd.experimentHintType == 0 || !pd.experimentHintType"
class="ql-editor"
v-html="pd.experimentHint"></div>
<mavon-editor v-else class="md" v-model="pd.experimentHint" :ishljs="true" :subfield="false" :editable="false" :toolbarsFlag="false" :boxShadowStyle="none" />
<mavon-editor v-else
class="md"
v-model="pd.experimentHint"
:ishljs="true"
:subfield="false"
:editable="false"
:toolbarsFlag="false"
:boxShadowStyle="none" />
</el-tab-pane>
</el-tabs>
</el-main>
@ -127,19 +207,25 @@
</el-container>
<div :class="['toggle absolute top-[200px] text-center', visible ? 'top-[35%] left-[100%]' : '']">
<el-icon class="cursor-pointer" color="#f1772b" :size="24">
<el-icon class="cursor-pointer"
color="#f1772b"
:size="24">
<Rank id="toggle" />
</el-icon>
<div class="toggle-panel w-[40px] h-[175px] bg-[length:100%_100%] bg-no-repeat cursor-pointer" :class="{ active: visible }" ref="handle" @click="pannelToggle"></div>
<div class="toggle-panel w-[40px] h-[175px] bg-[length:100%_100%] bg-no-repeat cursor-pointer"
:class="{ active: visible }"
ref="handle"
@click="visible = !visible"></div>
</div>
</div>
<div v-if="isSubmit && !isReport" class="z-[199] fixed top-[64px] right-0 bottom-0 left-0 bg-[rgba(0,0,0,.3)]"></div>
<div v-if="isSubmit && !isReport"
class="z-[199] fixed top-[64px] right-0 bottom-0 left-0 bg-[rgba(0,0,0,.3)]"></div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, inject, computed, watch, onUnmounted } from 'vue';
import { submitOpe } from '@/api/bank';
import { getSandTableLastCache, deleteOperationData } from '@/api/judgment';
import { getProjectBySystemId, getProjectDetail, getDetailById, getCompetition, getStartTime, heartbeatDetection, initData } from '@/api/system';
import { getProjectBySystemId, getProjectDetail, getDetailById, getCompetition, getStartTime, heartbeatDetection } from '@/api/system';
import Settings from '@/settings';
import { useRouter, useRoute, beforeRouteLeave } from 'vue-router';
import type { Action } from 'element-plus';
@ -150,9 +236,9 @@ import Cookies from 'js-cookie';
import { mavonEditor } from 'mavon-editor';
import 'mavon-editor/dist/css/index.css';
import '@vueup/vue-quill/dist/vue-quill.snow.css';
import { useDraggable, useWindowSize, Position } from '@vueuse/core';
import { useDraggable } from '@vueuse/core';
import { logout } from '@/store/useCurrentUser';
import { getNow } from '@/utils/common';
import { getIds, getNow } from '@/utils/common';
const router = useRouter();
const route = useRoute();
@ -180,23 +266,20 @@ const judgmentId = ref<string | number>('');
const curReq = ref<Record<string, any>[]>([]);
const taskList = ref<Record<string, any>[]>([]);
const pannelTab = ref<string>('first');
const loading = ref<boolean>(false);
const submiting = ref<boolean>(false);
const reportId = ref<string | number>('');
const countVal = ref<any>('');
const getLevel = ref();
const container = ref<HTMLElement | null>(null);
const handle = ref<HTMLElement | null>(null);
const { width, height } = useWindowSize();
//
const { x, y, style } = useDraggable(container, {
initialValue: { x: 0, y: 200 },
stopPropagation: true,
handle: handle.value,
onStart: (p: Position, e: PointerEvent): boolean => {
onStart(position, e) {
const { id } = e.target;
if (id !== 'panelHeader' && id !== 'toggle') return false;
return true;
},
});
@ -411,18 +494,8 @@ let setNewProject = (reloadPage?: number) => {
}
}
};
//
const initBuiltInData = async () => {
await initData({
assessmentId: param.assessmentId,
cid: param.cid,
competitionId: param.competitionId,
projectId: param.projectId,
});
};
//
let getCache = async (reloadPage?: number) => {
initBuiltInData();
//
const res = await getSandTableLastCache({
cid: param.cid,
@ -462,7 +535,7 @@ let getCache = async (reloadPage?: number) => {
});
} else {
Cookies.remove('sand-level');
setNewProject(reloadPage);
setNewProject();
}
};
let handleCache = () => {
@ -474,10 +547,15 @@ let handleCache = () => {
};
//
const toReport = () => {
router.replace('/report');
router.push('/report');
};
//
let reload = async () => {
let reload = async (fromReload?: number) => {
if (fromReload) {
getEntryTime(1);
await delCache(); //
Cookies.remove('sand-level');
}
if (!per.value) {
reloadCount();
startCount();
@ -487,34 +565,6 @@ let reload = async () => {
router.push('/');
}
};
//
let reloadConfirm = async () => {
if (isSubmit.value) {
reload();
} else {
ElMessageBox.confirm('<p class="text-danger">点击重新开始,之前操作会清空。</p><p>确定重新开始吗?</p>', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false,
dangerouslyUseHTMLString: true,
})
.then(() => {
getEntryTime(1);
delCache().then(); //
Cookies.remove('sand-level');
reload();
})
.catch(() => {
submiting.value = false;
});
}
};
let pannelToggle = () => {
visible.value = !visible.value;
x.value = 0;
y.value = 200;
};
//
let submit = async () => {
if (!submiting.value) {
@ -560,7 +610,7 @@ let submit = async () => {
} catch (e) {}
});
const score = retMap.totalScore;
grade.value = score < 10 && !(score % 1) ? `0${score}` : score;
grade.value = score < 10 && !(score % 1) ? '0' + score : score;
reportId.value = retMap.reportId;
Cookies.set('sand-reportId', retMap.reportId);
Cookies.set('sand-score', grade.value);
@ -605,42 +655,38 @@ let confirmSubmit = () => {
//
let getProDetail = async () => {
loading.value = true;
try {
const res = await getProjectDetail({
projectId: param.projectId,
stuAssessent: 1,
});
const pointsList = res.projectJudgmentVos;
const project = res.projectManage;
Cookies.set('sand-projectId', param.projectId);
// /
if (per.value) {
projectList.value = [
{
projectId: param.projectId,
projectName: project.projectName,
},
];
}
curReq.value = pointsList.map((e) => e.judgmentId); // judgmentIditem
points.value = pointsList;
taskList.value = isSubmit.value ? JSON.parse(localStorage.getItem('sand-taskList')) : pointsList; //
grade.value = isSubmit.value ? Cookies.get('sand-score') : '00';
judgmentId.value = pointsList[0].judgmentId; //
pd.value = project;
curSystemId.value = project.systemId;
hintOpen.value = project.founder ? !project.hintOpenBySchool : !project.hintOpen; // 01
const isPrac = per.value === 0; //
text.value = isPrac ? '已用' : '剩余';
//
if (!param.competitionId && !isSubmit.value) {
const now = await getNow();
countVal.value = (isPrac ? now - entryTime.value : new Date(param.stopTime).getTime() - now) / 1000; //
startCount();
}
} finally {
loading.value = false;
const res = await getProjectDetail({
projectId: param.projectId,
stuAssessent: 1,
});
const pointsList = res.projectJudgmentVos;
const project = res.projectManage;
Cookies.set('sand-projectId', param.projectId);
// /
if (per.value) {
projectList.value = [
{
projectId: param.projectId,
projectName: project.projectName,
},
];
// Cookies.set('sand-projectName', project.projectName);
}
curReq.value = pointsList.map((e) => e.judgmentId); // judgmentIditem
points.value = pointsList;
taskList.value = isSubmit.value ? JSON.parse(localStorage.getItem('sand-taskList')) : pointsList; //
grade.value = isSubmit.value ? Cookies.get('sand-score') : '00';
judgmentId.value = pointsList[0].judgmentId; //
pd.value = project;
curSystemId.value = project.systemId;
hintOpen.value = project.founder ? !project.hintOpenBySchool : !project.hintOpen; // 01
const isPrac = per.value === 0; //
text.value = isPrac ? '已用' : '剩余';
//
if (!param.competitionId && !isSubmit.value) {
const now = await getNow();
countVal.value = (isPrac ? now - entryTime.value : new Date(param.stopTime).getTime() - now) / 1000; //
startCount();
}
};
@ -735,7 +781,6 @@ onMounted(init);
onUnmounted(() => {
counter = null;
submit = null;
pannelToggle = null;
setHeartbeatDetection = null;
getProDetail = null;
getCache = null;
@ -750,25 +795,30 @@ onUnmounted(() => {
delCache = null;
setNewProject = null;
reload = null;
reloadConfirm = null;
startCount = null;
setSubmit = null;
clearInterval(counterTimer.value);
clearInterval(heartBeatTimer.value);
console.log('onUnmounted');
// next();
});
</script>
<style lang="scss" scoped>
.el-main {
@apply w-[60%] p-0 mr-5 mb-2 ml-2 text-[#333] text-base whitespace-pre-wrap bg-white overflow-hidden;
width: 60%;
background-color: #fff;
color: #333;
padding: 0;
font-size: 16px;
margin: 0px 20px 10px 10px;
white-space: pre-wrap;
overflow: hidden;
}
.panel-header {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
height: auto !important;
.project {
display: inline-flex;
align-items: center;
@ -909,7 +959,7 @@ onUnmounted(() => {
font-size: 14px;
}
:deep(.select) {
@apply flex-1 min-w-[180px];
@apply flex-1;
.el-select__caret:before {
// content: '\e78f';
padding: 3px;
@ -924,7 +974,7 @@ onUnmounted(() => {
.el-input {
padding: 10px 0;
}
.el-input--suffix .el-input__wrapper {
.el-input--suffix .el-input__inner {
height: 40px !important;
padding-right: 50px;
margin-left: 15px;
@ -936,7 +986,6 @@ onUnmounted(() => {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
box-shadow: none;
}
}
.panel {
@ -983,14 +1032,4 @@ onUnmounted(() => {
.ql-editor {
@apply text-sm;
}
@media (max-width: 1450px) {
.panel-header {
.actions {
z-index: 10;
position: absolute;
top: 70px;
right: 30px;
}
}
}
</style>

@ -1,7 +1,12 @@
<template>
<div class="search">
<input type="text" placeholder="搜索" maxlength="20" v-model="val" />
<img src="@/assets/images/search.png" alt="" class="icon" />
<input type="text"
placeholder="搜索"
maxlength="20"
v-model="val" />
<img src="@/assets/images/search.png"
alt=""
class="icon" />
</div>
</template>

@ -1,34 +0,0 @@
<template>
<!-- 保存策略时的confirm询问 -->
<el-dialog v-model="visible" width="500px">
<p>修改后的策略同步已关联这条策略的贷款产品会导致关联产品下架并重新配置风控</p>
<p class="my-3 text-[#006BFF]">确定修改这条策略吗</p>
<el-checkbox v-model="syncCheck" label="策略修改同步之前关联的产品" />
<template #footer>
<div class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
const props = defineProps({
modelValue: { type: Boolean, default: false },
});
const emit = defineEmits(['update:modelValue', 'submit']);
const visible = computed({
get: () => props.modelValue,
set: (value) => {
emit('update:modelValue', value);
},
});
const syncCheck = ref<boolean>(false);
const submit = () => {
visible.value = false;
emit('submit', +syncCheck.value);
};
</script>

@ -1,6 +1,7 @@
<template>
<div>
<textarea :id="elementId" ref="element"></textarea>
<textarea :id="elementId"
ref="element"></textarea>
</div>
</template>
@ -54,8 +55,8 @@ import 'tinymce/plugins/visualblocks';
import 'tinymce/plugins/visualchars';
// import 'tinymce/plugins/wordcount';
import Oss from '@/components/AliOss/upload.ts';
import { isTextarea, uuid, initEditor } from './utils';
import Oss from '@/components/AliOss/upload.ts';
export default defineComponent({
name: 'Tinymce',

@ -1,12 +1,23 @@
<template>
<div class="width-[100%] flex justify-between items-center w-full py-6 lg:py-4 px-5 overflow-hidden bg-transparent">
<logo />
<div v-if="!hidePanel" class="inline-flex items-center">
<el-tooltip effect="light" content="退出实训" placement="bottom">
<img class="mr-3 cursor-pointer" src="@/assets/images/11.png" alt="" @click="logout" />
<div v-if="!hidePanel"
class="inline-flex items-center">
<el-tooltip effect="light"
content="退出实训"
placement="bottom">
<img class="mr-3 cursor-pointer"
src="@/assets/images/11.png"
alt=""
@click="logout" />
</el-tooltip>
<el-tooltip effect="light" content="返回选择角色" placement="bottom">
<img class="cursor-pointer" src="@/assets/images/4.png" alt="" @click="toRole" />
<el-tooltip effect="light"
content="返回选择角色"
placement="bottom">
<img class="cursor-pointer"
src="@/assets/images/4.png"
alt=""
@click="toRole" />
</el-tooltip>
</div>
</div>

@ -1,7 +1,8 @@
<template>
<section class="px-3">
<router-view v-slot="{ Component }">
<transition name="fade-transform" mode="out-in">
<transition name="fade-transform"
mode="out-in">
<component :is="Component" />
</transition>
</router-view>

@ -2,74 +2,124 @@
<ul class="switch px-7 lg:px-2">
<!-- 产品经理 -->
<template v-if="role == 41">
<el-badge :value="productState.stat1">
<li :class="{ active: active == 1 }" @click="toPage('/product/bank?type=0&i=1&role=41')">
<img class="icon" src="@/assets/images/icon5.png" alt="" />
<img class="icon-1" src="@/assets/images/icon5-1.png" alt="" />
<el-badge :value="num1">
<li :class="{ active: active == 1 }"
@click="toPage('/product/bank?type=0&i=1&role=41')">
<img class="icon"
src="@/assets/images/icon5.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon5-1.png"
alt="" />
<p class="text">个人产品</p>
</li>
</el-badge>
<el-badge :value="productState.stat2">
<li :class="{ active: active == 2 }" @click="toPage('/product/bank?type=1&i=2&role=41')">
<img class="icon" src="@/assets/images/icon6.png" alt="" />
<img class="icon-1" src="@/assets/images/icon6-1.png" alt="" />
<el-badge :value="num2">
<li :class="{ active: active == 2 }"
@click="toPage('/product/bank?type=1&i=2&role=41')">
<img class="icon"
src="@/assets/images/icon6.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon6-1.png"
alt="" />
<p class="text">企业产品</p>
</li>
</el-badge>
</template>
<!-- 风控经理 -->
<template v-else-if="role == 42">
<el-badge :value="productState.stat1">
<li :class="{ active: active == 1 }" @click="toPage('/product/bank?type=&i=1&role=42')">
<img class="icon" src="@/assets/images/icon1.png" alt="" />
<img class="icon-1" src="@/assets/images/icon1-1.png" alt="" />
<el-badge :value="num1">
<li :class="{ active: active == 1 }"
@click="toPage('/product/bank?type=&i=1&role=42')">
<img class="icon"
src="@/assets/images/icon1.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon1-1.png"
alt="" />
<p class="text">产品风控配置</p>
</li>
</el-badge>
<li :class="{ active: active == 2 }" @click="toPage('/product/strategy?i=2&role=42&id=150')">
<img class="icon" src="@/assets/images/icon2.png" alt="" />
<img class="icon-1" src="@/assets/images/icon2-1.png" alt="" />
<li :class="{ active: active == 2 }"
@click="toPage('/product/strategy?i=2&role=42&id=150')">
<img class="icon"
src="@/assets/images/icon2.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon2-1.png"
alt="" />
<p class="text">贷前准入模型</p>
</li>
<li :class="{ active: active == 3 }" @click="toPage('/product/interestRate?&i=3&role=42&id=772')">
<img class="icon" src="@/assets/images/icon3.png" alt="" />
<img class="icon-1" src="@/assets/images/icon3-1.png" alt="" />
<li :class="{ active: active == 3 }"
@click="toPage('/product/interestRate/tab1?&i=3&role=42&id=772')">
<img class="icon"
src="@/assets/images/icon3.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon3-1.png"
alt="" />
<p class="text">利率定价模型</p>
</li>
<li :class="{ active: active == 4 }" @click="toPage('/product/afterLoan?&i=4&role=42&id=1029')">
<img class="icon" src="@/assets/images/icon4.png" alt="" />
<img class="icon-1" src="@/assets/images/icon4-1.png" alt="" />
<li :class="{ active: active == 4 }"
@click="toPage('/product/afterLoan?&i=4&role=42&id=1029')">
<img class="icon"
src="@/assets/images/icon4.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon4-1.png"
alt="" />
<p class="text">贷后管理模型</p>
</li>
</template>
<!-- 专家委员会 -->
<el-badge v-else-if="role == 43" :value="productState.stat1">
<el-badge v-else-if="role == 43"
:value="num1">
<li class="active">
<img class="icon-1" src="@/assets/images/icon7-1.png" alt="" />
<img class="icon-1"
src="@/assets/images/icon7-1.png"
alt="" />
<p class="text">审批产品</p>
</li>
</el-badge>
<!-- 保险 -->
<li v-else-if="route.path.includes('insurance')" class="active">
<img class="icon-1" src="@/assets/images/icon4-1.png" alt="" />
<li v-else-if="route.path.includes('insurance')"
class="active">
<img class="icon-1"
src="@/assets/images/icon4-1.png"
alt="" />
<p class="text">保险产品</p>
</li>
<!-- 基金 -->
<li v-else-if="route.path.includes('fund')" class="active">
<img class="icon-1" src="@/assets/images/icon3-1.png" alt="" />
<li v-else-if="route.path.includes('fund')"
class="active">
<img class="icon-1"
src="@/assets/images/icon3-1.png"
alt="" />
<p class="text">基金产品</p>
</li>
<!-- 配置 -->
<template v-else>
<li :class="{ active: route.path === '/config/index' }" @click="toPage('/config/index')">
<img class="icon" src="@/assets/images/icon4.png" alt="" />
<img class="icon-1" src="@/assets/images/icon4-1.png" alt="" />
<li :class="{ active: route.path === '/config/index' }"
@click="toPage('/config/index')">
<img class="icon"
src="@/assets/images/icon4.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon4-1.png"
alt="" />
<p class="text">参数配置</p>
</li>
<!-- 中台进来的才需要显示关卡配置 -->
<li v-if="isAdmin" :class="{ active: route.path === '/config/level' }" @click="toPage('/config/level')">
<img class="icon" src="@/assets/images/icon1.png" alt="" />
<img class="icon-1" src="@/assets/images/icon1-1.png" alt="" />
<li v-if="isAdmin"
:class="{ active: route.path === '/config/level' }"
@click="toPage('/config/level')">
<img class="icon"
src="@/assets/images/icon1.png"
alt="" />
<img class="icon-1"
src="@/assets/images/icon1-1.png"
alt="" />
<p class="text">关卡配置</p>
</li>
</template>
@ -80,24 +130,42 @@
import { onMounted, computed, ref } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import Cookies from 'js-cookie';
import { productState, getStat } from '@/store/useProduct';
import { statistics } from '@/api/bank';
const router = useRouter();
const route = useRoute();
const active = computed(() => route.query.i);
const role = computed(() => route.query.role);
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const isAdmin = ref<number | string>(route.query.admin ?? Cookies.get('sand-admin')); //
const num1 = ref<number | string>('');
const num2 = ref<number>(0);
//
const toPage = (path: string) => {
router.push(path);
};
//
const getNum = async (status?: number, type?: number) => {
const { data } = await statistics({
checkpointId: levelId,
projectId,
status,
productType: type,
});
if (type === 1) {
// -
num2.value = data || '';
} else {
num1.value = data || '';
}
};
onMounted(() => {
const status = role.value === '41' ? 299 : role.value === '42' ? 295 : role.value === '43' ? 296 : ''; // (1- 2-3-4-5-
if (status) {
getStat(status, role.value === '41' ? 0 : '');
role.value === '41' && getStat(status, 1);
getNum(status, role.value === '41' ? 0 : '');
role.value === '41' && getNum(status, 1);
}
});
</script>

@ -1,8 +1,11 @@
<template>
<div>
<el-scrollbar wrap-style="height: calc(100% - 85px)">
<div v-if="!isConfig" class="avatar py-3 mx-auto mb-5 text-center">
<img class="mx-auto" src="@/assets/images/6.png" alt="" />
<div v-if="!isConfig"
class="avatar py-3 mx-auto mb-5 text-center">
<img class="mx-auto"
src="@/assets/images/6.png"
alt="" />
<p class="text-white text-base lg:text-sm">{{ roleName }}</p>
<p class="my-2 text-white text-sm lg:text-xs">产品部门</p>
<div class="flex justify-center items-center text-white text-xs lg:text-[10px]">
@ -16,14 +19,22 @@
<menus></menus>
</el-scrollbar>
<el-dialog v-model="dateVisible" title="选择交易日期" width="400px" center>
<el-dialog v-model="dateVisible"
title="选择交易日期"
width="400px"
center>
<div class="text-center">
<el-date-picker v-model="diaDate" format="YYYY/MM/DD" value-format="YYYY-MM-DD" type="date" />
<el-date-picker v-model="diaDate"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
type="date" />
</div>
<template #footer>
<span class="flex justify-center">
<div class="dia-btn cancel" @click="dateVisible = false">取消</div>
<div class="dia-btn" @click="submitDate">确定</div>
<div class="dia-btn mr-3 cancel"
@click="dateVisible = false">取消</div>
<div class="dia-btn"
@click="submitDate">确定</div>
</span>
</template>
</el-dialog>
@ -33,11 +44,11 @@
<script setup lang="ts">
import { onMounted, ref, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router';
import Menus from './Menu.vue';
import { getOperationTime, saveOperationTime } from '@/api/config';
import Cookies from 'js-cookie';
import dayjs from 'dayjs';
import { getNow } from '@/utils/common';
import Menus from './Menu.vue';
const router = useRouter();
const route = useRoute();
@ -56,11 +67,9 @@ const roleIds = {
const roleName = computed(() => {
if (route.query.role) {
return roleIds[+route.query.role];
}
if (route.path.includes('insurance')) {
} else if (route.path.includes('insurance')) {
return '保险产品经理';
}
if (route.path.includes('fund')) {
} else if (route.path.includes('fund')) {
return '基金产品经理';
}
});

@ -1,6 +1,7 @@
<template>
<div class="flex items-center justify-center overflow-hidden">
<router-link class="whitespace-nowrap text-center" to="/">
<router-link class="whitespace-nowrap text-center"
to="/">
<h1 class="ml-1 text-[22px] lg:text-lg leading-[1] font-bold text-[#333]">{{ title }}</h1>
</router-link>
</div>

@ -1,9 +1,15 @@
<template>
<div class="min-h-full bg-[url('@/assets/images/1.png')] bg-[length:100%_100%] bg-no-repeat">
<app-header />
<Back v-if="hidePanel" class="mx-3" name="金融产品设计及数字化营销沙盘系统后台管理系统" :isLogout="true" />
<app-sidebar v-if="!hideNav" class="sidebar fixed h-full px-5 overflow-hidden transition-width duration-300" />
<div class="main h-[calc(100vh-86px)] transition-margin duration-300 overflow-auto" :class="{ ml: !hideNav }" id="appMain">
<Back v-if="hidePanel"
class="mx-3"
name="金融产品设计及数字化营销沙盘系统后台管理系统"
:isLogout="true" />
<app-sidebar v-if="!hideNav"
class="sidebar fixed h-full px-5 overflow-hidden transition-width duration-300 z-40" />
<div class="main h-[calc(100vh-86px)] transition-margin duration-300 overflow-auto"
:class="{ 'ml': !hideNav }"
id="appMain">
<app-main />
</div>
<Panel />
@ -14,10 +20,10 @@
import { defineComponent, computed } from 'vue';
import { useRoute } from 'vue-router';
import Settings from '@/settings';
import Panel from '@/components/Panel/index.vue';
import Back from '@/components/Back.vue';
import { AppSidebar, AppHeader, AppMain } from './components';
import useResizeHandler from './composables/useResizeHandler';
import Panel from '@/components/Panel/index.vue';
import Back from '@/components/Back.vue';
export default defineComponent({
name: 'Layout',

@ -2,11 +2,12 @@ import NProgress from 'nprogress'; // progress bar
import 'nprogress/nprogress.css'; // progress bar style
import { RouteLocationNormalized } from 'vue-router';
import getPageTitle from '@/utils/getPageTitle';
import { getAccessToken } from '@/utils/auth'; // get token from cookie
import router from './router';
NProgress.configure({ showSpinner: false }); // NProgress Configuration
router.beforeEach(async () => {
router.beforeEach(async (to: RouteLocationNormalized) => {
NProgress.start();
return true;
});

@ -37,7 +37,7 @@ export const routes: Array<RouteRecordRaw> = [
{ path: 'strategy', component: () => import('@/views/product/strategy/CardList.vue'), meta: { title: '产品列表' } },
{ path: 'insurance', component: () => import('@/views/product/insurance/List.vue'), meta: { title: '保险产品' } },
{ path: 'insurance/:action', component: () => import('@/views/product/insurance/CardList.vue'), meta: { title: '保险产品' } },
{ path: 'interestRate', component: () => import('@/views/product/interestRate/CardList.vue'), meta: { title: '利率定价模型' } },
{ path: 'interestRate/:action', component: () => import('@/views/product/interestRate/CardList.vue'), meta: { title: '利率定价模型' } },
{ path: 'fund', component: () => import('@/views/product/fund/List.vue'), meta: { title: '基金产品' } },
{ path: 'fund/:action', component: () => import('@/views/product/fund/CardList.vue'), meta: { title: '基金产品' } },
{ path: 'afterLoan', component: () => import('@/views/product/afterLoan/CardList.vue'), meta: { title: '贷后管理' } },

@ -1,4 +1,4 @@
import { reactive } from 'vue';
import { reactive, readonly } from 'vue';
import { RouteRecordRaw } from 'vue-router';
import { removeAccessToken, removeParam } from '@/utils/auth';
import Cookies from 'js-cookie';

@ -1,11 +1,7 @@
import { reactive, readonly } from 'vue';
import { statistics } from '@/api/bank';
import Cookies from 'js-cookie';
export interface Product {
status?: Record<string, any>;
stat1?: number | string;
stat2?: number | string;
}
const state = reactive<Product>({
@ -36,12 +32,9 @@ const state = reactive<Product>({
name: '审批打回',
},
],
// 左侧菜单项的右上角badge统计
stat1: '',
stat2: '',
});
export const productState = state;
export const productState = readonly(state);
// 专家委员会产品进度(去除配置风控)
export const getExpertStatus = (): Record<string, any>[] => {
const newStatus = JSON.parse(JSON.stringify(state.status));
@ -52,18 +45,3 @@ export const getExpertStatus = (): Record<string, any>[] => {
export const getStatus = (id: number | string): string => {
return state.status.find((e) => e.id === id)?.name;
};
// 获取产品数量
export const getStat = async (status?: number, type?: number): Promise<void> => {
const { data } = await statistics({
checkpointId: Cookies.get('sand-level'),
projectId: Cookies.get('sand-projectId'),
status,
productType: type,
});
if (type === 1) {
// 产品经理-企业
state.stat2 = data || '';
} else {
state.stat1 = data || '';
}
};

@ -49,7 +49,9 @@ body {
// global css
.block {
@apply p-5 rounded-lg bg-white;
@apply p-5;
@apply rounded-lg;
@apply bg-white;
}
.inline-form .el-form-item {
@ -100,21 +102,11 @@ body {
@apply flex-1 w-[calc(100vw-533px)] max-h-[calc(100vh-100px)] overflow-auto px-5 pt-2;
}
}
.menu-card {
@apply flex;
.left {
@apply mr-4 rounded-lg border-r-0;
}
.right {
@apply flex-1 w-[calc(100vw-533px)] max-h-[calc(100vh-100px)] overflow-auto p-4 bg-white rounded-lg;
}
}
// .c-auto {
// @apply w-[calc(100vw-533px)] max-h-[calc(100vh-160px)] overflow-auto;
// }
.c-table {
@apply rounded-[10px];
th.el-table__cell {
@apply bg-[#F8FBFC];
}
@ -125,7 +117,7 @@ body {
.el-input {
@apply lg:text-xs;
}
.el-input__wrapper {
.el-input__inner {
@apply px-2;
}
}
@ -138,7 +130,7 @@ body {
}
.el-select {
@apply w-[170px];
.el-input__wrapper {
.el-input__inner {
@apply pl-[41px] rounded-[18px] border-[#dfe9f8];
}
}
@ -157,18 +149,19 @@ body {
}
}
.dia-btn {
@apply py-[11px] px-[26px] text-sm leading-[1] text-white rounded-[18px] cursor-pointer;
padding: 11px 26px;
font-size: 14px;
line-height: 1;
color: #fff;
background: linear-gradient(-36deg, #006bff, #2ab1ff);
border-radius: 18px;
cursor: pointer;
&.cancel {
@apply mr-3 font-semibold text-[#333];
font-size: 600;
color: #333;
background: #f4f8fc;
}
}
.model-drawer {
.el-drawer__header > :first-child {
@apply text-[#333] text-xl font-semibold text-center;
}
}
@media screen and (-webkit-min-device-pixel-ratio: 1.5), screen and (min-resolution: 144dpi) {
body {

@ -24,7 +24,6 @@ export const removeParam = (): void => {
Cookies.remove('sand-systemId');
Cookies.remove('sand-level');
Cookies.remove('sand-submit');
Cookies.remove('sand-loaded');
};
export const getAuthHeaders = (): any => {

@ -273,14 +273,3 @@ export const whethers = [
name: '不启用',
},
];
export const opt1 = [
{
id: 345,
name: '是',
},
{
id: 346,
name: '否',
},
];

@ -5,9 +5,9 @@ import { logout } from '@/store/useCurrentUser';
const service = axios.create({
baseURL: import.meta.env.VITE_BASE_API,
timeout: 60 * 1000,
timeout: 10000,
});
let logouted = 0;
let loaded = 0;
service.interceptors.request.use(
(config) => {
config.headers = { ...config.headers, ...getAuthHeaders() };
@ -18,27 +18,12 @@ service.interceptors.request.use(
service.interceptors.response.use(
(res) => {
const { message, status, code, msg } = res.data;
const { message, status } = res.data;
if (status) {
if (status === 200) {
return res;
}
ElMessage.error(message);
} else if (code === 401) {
// 账号互踢
if (!logouted) {
ElMessageBox.alert(msg.includes('顶') ? '您的账号已在其他设备登录,您已被迫下线!' : '登录过期,请重新登录!', {
confirmButtonText: '重新登录',
type: 'warning',
closeOnClickModal: false,
showClose: false,
}).then(() => {
// 未登录
logout();
});
logouted = 1;
}
message === '无缓存' || ElMessage.error(message);
} else {
return res;
}
@ -51,12 +36,12 @@ service.interceptors.response.use(
},
} = e;
if (status === 401) {
logouted ||
loaded ||
ElMessageBox.alert('登录状态已过期,请重新登录', { confirmButtonText: '重新登录', type: 'warning', closeOnClickModal: false, showClose: false }).then(() => {
// 未登录
logout();
});
logouted = 1;
loaded = 1;
} else if (message) {
ElMessage.error(message);
}

@ -4,7 +4,9 @@
<h1 class="font-bold text-3xl">403</h1>
<p class="mt-4">对不起您没有该页面的访问权限</p>
<p class="mt-4">
<el-button type="primary" @click="handleLogout()" plain>退出</el-button>
<el-button type="primary"
@click="handleLogout()"
plain>退出</el-button>
</p>
</div>
</div>

@ -2,16 +2,15 @@
<div class="wscn-http404-container">
<div class="wscn-http404">
<div class="pic-404">
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404" />
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404" />
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404" />
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404" />
<img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
<img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
<img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
<img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
</div>
<div class="bullshit">
<div class="bullshit__oops">OOPS!</div>
<div class="bullshit__info">
All rights reserved
<a style="color: #20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
<div class="bullshit__info">All rights reserved
<a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
</div>
<div class="bullshit__headline">{{ message }}</div>
<div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
@ -35,8 +34,8 @@ export default defineComponent({
</script>
<style lang="scss" scoped>
.wscn-http404-container {
transform: translate(-50%, -50%);
.wscn-http404-container{
transform: translate(-50%,-50%);
position: absolute;
top: 40%;
left: 50%;

@ -2,40 +2,64 @@
<div class="flex justify-between items-center h-[64px] px-5 bg-white">
<h1>金融产品设计及数字化营销沙盘系统</h1>
<div class="inline-flex items-center">
<el-tooltip effect="light" content="退出实训" placement="bottom">
<img class="mr-3 cursor-pointer" src="@/assets/images/11.png" alt="" @click="logout" />
<el-tooltip effect="light"
content="退出实训"
placement="bottom">
<img class="mr-3 cursor-pointer"
src="@/assets/images/11.png"
alt=""
@click="logout" />
</el-tooltip>
</div>
</div>
<div class="relative h-[calc(100vh-64px)] pt-5 pl-5 bg-[url('@/assets/images/level/4.png')] bg-[length:100%_100%] bg-no-repeat bg-fixed overflow-auto" id="wrap">
<div class="relative h-[calc(100vh-64px)] pt-5 pl-5 bg-[url('@/assets/images/level/4.png')] bg-[length:100%_100%] bg-no-repeat bg-fixed overflow-auto"
id="wrap">
<div class="fixed z-10">
<div class="w-[354px] h-[68px] bg-[url('@/assets/images/level/5.png')] bg-[length:100%_100%] bg-no-repeat"></div>
<div class="absolute top-5 left-40 flex items-center cursor-pointer" @click="getLevel(1)">
<img v-if="collected" src="@/assets/images/level/7.png" alt="" />
<img v-else src="@/assets/images/level/6.png" alt="" />
<div class="absolute top-5 left-40 flex items-center cursor-pointer"
@click="getLevel(1)">
<img v-if="collected"
src="@/assets/images/level/7.png"
alt="" />
<img v-else
src="@/assets/images/level/6.png"
alt="" />
<span class="ml-2 text-sm text-[#999]">仅显示已收藏的关卡</span>
</div>
</div>
<div class="relative mt-20">
<div v-for="(item, i) in levels" :key="i" :class="['item', { active: curLevel === item.checkpointId, disabled: !item.enableOrNot }]" @click="selecLevel(item)">
<span class="num">LV.{{ i + 1 }}</span>
<div v-for="(item, i) in levels"
:key="i"
:class="['item', { active: curLevel === item.checkpointId }]"
@click="selecLevel(item)">
<span class="num">LV.{{ item.serialNumber }}</span>
<div class="texts">
<h6>{{ numToChinese(i + 1) }}</h6>
<h6>{{ numToChinese(item.serialNumber) }}</h6>
<p class="des mul-ellipsis2">{{ item.customsPassName }}</p>
<img v-if="item.collect" class="icon" src="@/assets/images/level/star2.png" alt="" @click.stop="collectItem(item)" />
<img v-else class="icon" src="@/assets/images/level/star1.png" alt="" @click.stop="collectItem(item)" />
<img v-if="item.collect"
class="icon"
src="@/assets/images/level/star2.png"
alt=""
@click.stop="collectItem(item)" />
<img v-else
class="icon"
src="@/assets/images/level/star1.png"
alt=""
@click.stop="collectItem(item)" />
</div>
</div>
</div>
<div class="arrow top-[68px] left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-up.png')]" @click="move('up')"></div>
<div class="arrow right-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-right.png')]" @click="move('right')"></div>
<div class="arrow bottom-0 left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-down.png')]" @click="move('down')"></div>
<div class="arrow left-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-left.png')]" @click="move('left')"></div>
<div
class="fixed bottom-2 right-1 w-[262px] h-[74px] bg-[url('@/assets/images/level/submit.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer hover:bg-[url('@/assets/images/level/submit-hover.png')]"
@click="toRole"
></div>
<div class="arrow top-[68px] left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-up.png')]"
@click="move('up')"></div>
<div class="arrow right-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-right.png')]"
@click="move('right')"></div>
<div class="arrow bottom-0 left-[50%] translate-x-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-down.png')]"
@click="move('down')"></div>
<div class="arrow left-0 top-[50%] translate-y-[-50%] w-[64px] h-[64px] bg-[url('@/assets/images/level/arrow-left.png')]"
@click="move('left')"></div>
<div class="fixed bottom-2 right-1 w-[262px] h-[74px] bg-[url('@/assets/images/level/submit.png')] bg-[length:100%_100%] bg-no-repeat cursor-pointer hover:bg-[url('@/assets/images/level/submit-hover.png')]"
@click="toRole"></div>
</div>
<Panel />
</template>
@ -66,21 +90,19 @@ const getLevel = async (only: any = '') => {
provide('getLevel', getLevel);
//
const selecLevel = (item: Record<string, any>) => {
if (item.enableOrNot) curLevel.value = item.checkpointId;
curLevel.value = item.checkpointId;
};
//
const collectItem = async (item: Record<string, any>) => {
if (item.enableOrNot) {
if (item.collect) {
await cancelCollection(item.favoriteId);
} else {
await collect({
checkpointId: item.checkpointId,
projectId,
});
}
getLevel();
if (item.collect) {
await cancelCollection(item.favoriteId);
} else {
await collect({
checkpointId: item.checkpointId,
projectId,
});
}
getLevel();
};
//
const toRole = () => {
@ -105,7 +127,9 @@ const move = (dir: string) => {
if (dir === 'up' || dir === 'down') param.top = el.scrollTop + (dir === 'up' ? -150 : 150);
el.scrollTo(param);
};
onMounted(getLevel);
onMounted(() => {
getLevel();
});
</script>
<style lang="scss" scoped>
@ -161,9 +185,6 @@ onMounted(getLevel);
-webkit-text-fill-color: #fff;
}
}
&.disabled {
@apply opacity-30 cursor-not-allowed;
}
&:nth-child(2) {
@apply top-[var(--line2)] left-[160px];

@ -41,50 +41,49 @@
<p class="text">今日渠道订单</p>
</div>
</div>
<el-tooltip effect="light" content="退出实训" placement="bottom">
<img class="mr-3 cursor-pointer" src="@/assets/images/11.png" alt="" @click="logout" />
<el-tooltip effect="light"
content="退出实训"
placement="bottom">
<img class="mr-3 cursor-pointer"
src="@/assets/images/11.png"
alt=""
@click="logout" />
</el-tooltip>
<el-tooltip effect="light" content="返回关卡" placement="bottom">
<img class="mr-3 cursor-pointer" src="@/assets/images/2.png" alt="" @click="toLevel" />
<el-tooltip effect="light"
content="返回关卡"
placement="bottom">
<img class="mr-3 cursor-pointer"
src="@/assets/images/2.png"
alt=""
@click="toLevel" />
</el-tooltip>
</div>
</div>
<div class="relative h-[calc(100vh-64px)] overflow-hidden bg-[#e5eafe]">
<img class="w-full h-full" src="@/assets/images/role/bg.png" alt="" />
<img class="w-full h-full"
src="@/assets/images/role/bg.png"
alt="">
<div class="absolute top-5 left-[18px] w-[204px] h-[68px] bg-[url('@/assets/images/role/2.png')] bg-[length:100%_100%] bg-no-repeat"></div>
<div class="date absolute top-[70px] left-[54%] w-[198px] h-[46px] pt-[10px] pl-[56px] text-base text-white bg-[url('@/assets/images/role/date.png')] bg-no-repeat transition">
{{ date }}
</div>
<div
class="role top-[30%] left-[17%] xl:top-[31%] lg:top-[32%] lg:left-[15%] bg-[url('@/assets/images/role/product.png')] hover:bg-[url('@/assets/images/role/product1.png')]"
@click="selectRole(41)"
></div>
<div
class="role top-[22%] left-[25%] xl:top-[24%] lg:top-[25%] lg:left-[23%] bg-[url('@/assets/images/role/committee.png')] hover:bg-[url('@/assets/images/role/committee1.png')]"
@click="selectRole(43)"
></div>
<div
class="role top-[17%] left-[31.5%] xl:top-[16%] xl:left-[31%] lg:left-[30%] bg-[url('@/assets/images/role/riskControl.png')] hover:bg-[url('@/assets/images/role/riskControl1.png')]"
@click="selectRole(42)"
></div>
<div
class="role bottom-[200px] left-[100px] xl:bottom-[150px] lg:bottom-[120px] bg-[url('@/assets/images/role/insurance.png')] hover:bg-[url('@/assets/images/role/insurance1.png')]"
@click="selectRole(275)"
></div>
<div class="role relative bottom-[70px] left-[25%] bg-[url('@/assets/images/role/fund.png')] hover:bg-[url('@/assets/images/role/fund1.png')]" @click="selectRole(1161)"></div>
<div
class="role relative bottom-[220px] left-[41%] bg-[url('@/assets/images/role/market-bank.png')] hover:bg-[url('@/assets/images/role/market-bank1.png')]"
@click="selectRole('bank')"
></div>
<div
class="role relative bottom-[360px] left-[52%] bg-[url('@/assets/images/role/market-insurance.png')] hover:bg-[url('@/assets/images/role/market-insurance1.png')]"
@click="selectRole('insurance')"
></div>
<div
class="role relative bottom-[490px] left-[63%] bg-[url('@/assets/images/role/market-fund.png')] hover:bg-[url('@/assets/images/role/market-fund1.png')]"
@click="selectRole('fund')"
></div>
<div class="role top-[30%] left-[17%] xl:top-[31%] lg:top-[32%] lg:left-[15%] bg-[url('@/assets/images/role/product.png')] hover:bg-[url('@/assets/images/role/product1.png')]"
@click="selectRole(41)"></div>
<div class="role top-[22%] left-[25%] xl:top-[24%] lg:top-[25%] lg:left-[23%] bg-[url('@/assets/images/role/committee.png')] hover:bg-[url('@/assets/images/role/committee1.png')]"
@click="selectRole(43)"></div>
<div class="role top-[17%] left-[31.5%] xl:top-[16%] xl:left-[31%] lg:left-[30%] bg-[url('@/assets/images/role/riskControl.png')] hover:bg-[url('@/assets/images/role/riskControl1.png')]"
@click="selectRole(42)"></div>
<div class="role bottom-[200px] left-[100px] xl:bottom-[150px] lg:bottom-[120px] bg-[url('@/assets/images/role/insurance.png')] hover:bg-[url('@/assets/images/role/insurance1.png')]"
@click="selectRole(275)"></div>
<div class="role relative bottom-[70px] left-[25%] bg-[url('@/assets/images/role/fund.png')] hover:bg-[url('@/assets/images/role/fund1.png')]"
@click="selectRole(1161)"></div>
<div class="role relative bottom-[220px] left-[41%] bg-[url('@/assets/images/role/market-bank.png')] hover:bg-[url('@/assets/images/role/market-bank1.png')]"
@click="selectRole('bank')"></div>
<div class="role relative bottom-[360px] left-[52%] bg-[url('@/assets/images/role/market-insurance.png')] hover:bg-[url('@/assets/images/role/market-insurance1.png')]"
@click="selectRole('insurance')"></div>
<div class="role relative bottom-[490px] left-[63%] bg-[url('@/assets/images/role/market-fund.png')] hover:bg-[url('@/assets/images/role/market-fund1.png')]"
@click="selectRole('fund')"></div>
</div>
<!-- <div class="fixed top-[80px] right-[80px]">
<div class="flex items-center h-[60px] px-4 rounded-tl-[20px] rounded-tr-[20px]"
@ -125,14 +124,20 @@
<Panel />
<el-dialog v-model="dateVisible" title="选择交易日期" width="400px" center>
<el-dialog v-model="dateVisible"
title="选择交易日期"
width="400px"
center>
<div class="text-center">
<el-date-picker v-model="diaDate" type="date" />
<el-date-picker v-model="diaDate"
type="date" />
</div>
<template #footer>
<span class="flex justify-center">
<div class="dia-btn cancel" @click="dateVisible = false">取消</div>
<div class="dia-btn" @click="submitDate">确定</div>
<div class="dia-btn mr-3 cancel"
@click="dateVisible = false">取消</div>
<div class="dia-btn"
@click="submitDate">确定</div>
</span>
</template>
</el-dialog>
@ -150,8 +155,11 @@ import dayjs from 'dayjs';
import { getNow } from '@/utils/common';
const router = useRouter();
const route = useRoute();
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const collected = ref<boolean>(false);
const curLevel = ref<number | string>('');
const dateVisible = ref<boolean>(false);
const date = ref<string>(dayjs(new Date()).format('YYYY-MM-DD'));
const diaDate = ref<string>(dayjs(new Date()).format('YYYY-M-D'));
@ -220,7 +228,11 @@ const ranks = ref<Record<string, any>[]>([
money: '沙盘名称',
},
]);
//
const getLevel = async () => {
const { data } = await checkPointList(1);
levels.value = data;
};
//
const selectRole = (id: number) => {
let path = `/product/bank?type=0&i=1&role=${id}`;

@ -4,37 +4,54 @@
<dl>
<dt>担保方式</dt>
<div class="vals">
<dd v-for="(item, i) in methods" :key="i" :class="{ active: method === item.id }" @click="filterClick(item, 'method')">{{ item.name }}</dd>
<dd v-for="(item, i) in methods"
:key="i"
:class="{ active: method === item.id }"
@click="filterClick(item, 'method')">{{ item.name }}</dd>
</div>
</dl>
<dl>
<dt>产品进度</dt>
<div class="vals">
<dd v-for="(item, i) in methods" :key="i" :class="{ active: method === item.id }" @click="filterClick(item, 'method')">{{ item.name }}</dd>
<dd v-for="(item, i) in methods"
:key="i"
:class="{ active: method === item.id }"
@click="filterClick(item, 'method')">{{ item.name }}</dd>
</div>
</dl>
</div>
<div class="block mt-3">
<div class="search">
<input type="text" placeholder="搜索" maxlength="20" />
<img src="@/assets/images/search.png" alt="" class="icon" />
<input type="text"
placeholder="搜索"
maxlength="20" />
<img src="@/assets/images/search.png"
alt=""
class="icon" />
</div>
<el-table ref="table" v-loading="loading" :data="data" @selection-change="(rows) => (selection = rows)" @sort-change="handleSort">
<el-table-column type="selection" :selectable="deletable" width="50"></el-table-column>
<el-table-column property="id" label="ID" width="64" sortable="custom"></el-table-column>
<el-table ref="table"
v-loading="loading"
:data="data"
@selection-change="(rows) => (selection = rows)"
@sort-change="handleSort">
<el-table-column type="selection"
:selectable="deletable"
width="50"></el-table-column>
<el-table-column property="id"
label="ID"
width="64"
sortable="custom"></el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="fetchData()"
@current-change="fetchData()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="fetchData()"
@current-change="fetchData()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</div>
</template>

@ -1,18 +1,30 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="params.customsPassName" @change="getList"></search>
<search v-model="params.customsPassName"
@change="getList"></search>
<div class="filter">
<div class="select">
<el-select v-model="params.isEnable" placeholder="启用状态" size="large" clearable>
<el-option v-for="item in enables" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="params.isEnable"
placeholder="启用状态"
size="large"
clearable>
<el-option v-for="item in enables"
:key="item.id"
:label="item.name"
:value="item.id" />
</el-select>
<img src="@/assets/images/7.png" alt="" class="icon" />
<img src="@/assets/images/7.png"
alt=""
class="icon" />
</div>
<el-popconfirm :title="delTitle" :disabled="!multipleSelection.length" @confirm.stop="delAll">
<el-popconfirm :title="delTitle"
:disabled="!multipleSelection.length"
@confirm.stop="delAll">
<template #reference>
<div :class="['add-btn mr-2', { 'cursor-not-allowed': !multipleSelection.length }]">
<el-icon :size="24" color="#fff">
<div :class="['add-btn mr-2', {'cursor-not-allowed': !multipleSelection.length}]">
<el-icon :size="24"
color="#fff">
<Delete />
</el-icon>
删除关卡
@ -20,73 +32,120 @@
</template>
</el-popconfirm>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
<div class="add-btn"
@click="toAdd">
<img src="@/assets/images/plus.png"
alt=""
class="icon" />
新增关卡
</div>
</div>
</div>
<div class="h-[calc(100vh-310px)] overflow-auto" id="tableWrap">
<el-table v-loading="loading" :data="list" @sort-change="handleSort" @selection-change="handleSelectionChange">
<el-table-column label="移动" width="80">
<div class="h-[calc(100vh-310px)] overflow-auto"
id="tableWrap">
<el-table v-loading="loading"
:data="list"
@sort-change="handleSort"
@selection-change="handleSelectionChange">
<el-table-column label="移动"
width="80">
<template #default="{ row, $index }">
<el-popover placement="right" trigger="hover">
<el-popover placement="right"
trigger="hover">
<template #reference>
<el-icon class="rotate-90 cursor-pointer" :size="16" color="#877c7c">
<el-icon class="rotate-90 cursor-pointer"
:size="16"
color="#877c7c">
<MoreFilled />
</el-icon>
</template>
<div class="flex items-center mb-2">
<el-input class="w-[80px]" placeholder="请输入" v-model.number="row.serial"></el-input>
<el-icon class="ml-2 cursor-pointer" :size="16" color="#877c7c" @click.stop="submitSerial(row, $index, row.serial)">
<el-input class="w-[80px]"
placeholder="请输入"
v-model.number="row.serial"></el-input>
<el-icon class="ml-2 cursor-pointer"
:size="16"
color="#877c7c"
@click.stop="submitSerial(row, $index, row.serial)">
<Check />
</el-icon>
</div>
<p class="my-2 cursor-pointer" @click="submitSerial(row, $index, 1)">置顶</p>
<p class="cursor-pointer" @click="submitSerial(row, $index, list.length)">置底</p>
<p class="my-2 cursor-pointer"
@click="submitSerial(row, $index, 1)">置顶</p>
<p class="cursor-pointer"
@click="submitSerial(row, $index, list.length)">置底</p>
</el-popover>
</template>
</el-table-column>
<el-table-column type="selection" width="55" />
<el-table-column label="序号" width="80" align="center">
<el-table-column type="selection"
width="55" />
<el-table-column label="序号"
width="80"
align="center">
<template #default="{ row, $index }">
{{ $index + 1 }}
</template>
</el-table-column>
<el-table-column prop="customsPassName" min-width="200" label="关卡名称">
<el-table-column prop="customsPassName"
min-width="200"
label="关卡名称">
<template #default="{ row }">
<div class="flex items-center">
<el-input v-if="row.editing" class="w-[250px]" placeholder="请输入关卡名称" v-model="row.customsPassName"></el-input>
<el-input v-if="row.editing"
class="w-[250px]"
placeholder="请输入关卡名称"
v-model="row.customsPassName"></el-input>
<span v-else>{{ row.customsPassName }}</span>
<el-icon v-if="!row.editing" class="mx-2 cursor-pointer" :size="16" color="#877c7c" @click="edit(row)">
<el-icon v-if="!row.editing"
class="mx-2 cursor-pointer"
:size="16"
color="#877c7c"
@click="edit(row)">
<Edit />
</el-icon>
<el-icon v-if="row.editing" class="ml-2 cursor-pointer" :size="16" color="#877c7c" @click="cancel(row)">
<el-icon v-if="row.editing"
class="ml-2 cursor-pointer"
:size="16"
color="#877c7c"
@click="cancel(row)">
<Close />
</el-icon>
</div>
</template>
</el-table-column>
<el-table-column prop="creator" min-width="170" label="创建人"></el-table-column>
<el-table-column prop="createTime" label="创建时间" width="180" sortable="custom"></el-table-column>
<el-table-column label="启用关卡" width="140" align="center">
<el-table-column prop="creator"
min-width="170"
label="创建人"></el-table-column>
<el-table-column prop="createTime"
label="创建时间"
width="180"
sortable="custom"></el-table-column>
<el-table-column label="启用关卡"
width="140"
align="center">
<template #default="{ row }">
<el-popconfirm
v-if="row.checkpointId"
:title="row.isEnable ? '禁用关卡后,已关联该关卡的判分点将被禁用,确定禁用吗?' : '启用关卡后,已关联该关卡的判分点将被启用,确定启用吗?'"
@confirm.stop="enableSubmit(row)"
>
<el-popconfirm v-if="row.checkpointId"
:title="row.isEnable ? '禁用关卡后,已关联该关卡的判分点将被禁用,确定禁用吗?' : '启用关卡后,已关联该关卡的判分点将被启用,确定启用吗?'"
@confirm.stop="enableSubmit(row)">
<template #reference>
<el-switch v-if="row.checkpointId" v-model="row.isEnable" :active-value="1" :inactive-value="0" @change="enableChange(row)" />
<el-switch v-if="row.checkpointId"
v-model="row.isEnable"
:active-value="1"
:inactive-value="0"
@change="enableChange(row)" />
</template>
</el-popconfirm>
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<el-table-column label="操作"
width="120">
<template #default="{ row }">
<el-popconfirm v-if="row.checkpointId" :title="delTitle" @confirm.stop="handleDelete([row])">
<el-popconfirm v-if="row.checkpointId"
:title="delTitle"
@confirm.stop="handleDelete([row])">
<template #reference>
<el-button type="text" size="small">删除</el-button>
<el-button type="text"
size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
@ -94,7 +153,11 @@
</el-table>
</div>
<div class="filter flex justify-end mt-3">
<div :class="['add-btn', { 'not-allow': !hadChange }]" @click="save" v-loading="saveLoading">保存</div>
<div :class="['add-btn', {'not-allow': !hadChange}]"
@click="save"
v-loading="saveLoading">
保存
</div>
</div>
</div>
</template>
@ -113,7 +176,7 @@ const route = useRoute();
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const hadChange = ref<number>(0);
const delTitle = '删除关卡后,已关联该关卡的判分点将被禁用,确定删除吗?';
const delTitle: string = '删除关卡后,已关联该关卡的判分点将被禁用,确定删除吗?';
const params = reactive({
createDateSort: '',
platformId: 3,

@ -1,71 +1,123 @@
<template>
<div class="max-h-[calc(100vh-290px)] overflow-auto">
<h6 class="title">城市人口及年龄参数</h6>
<el-table class="c-table" :data="form.ageAduRatioList" :span-method="ageSpan" border>
<el-table-column prop="productName" label="城市总人口 (人)" align="center">
<el-table class="c-table"
:data="form.ageAduRatioList"
:span-method="ageSpan"
border>
<el-table-column prop="productName"
label="城市总人口 (人)"
align="center">
<template #default="{ row }">
<el-input v-model.number="row.totalPopulation" placeholder="请输入" type="number" min="0"></el-input>
<el-input v-model.number="row.totalPopulation"
placeholder="请输入"
type="number"
min="0"></el-input>
</template>
</el-table-column>
<el-table-column prop="ageStage" label="年龄 (岁)" align="center"></el-table-column>
<el-table-column prop="ageRatio" label="年龄占比 (%)" align="center">
<el-table-column prop="ageStage"
label="年龄 (岁)"
align="center"></el-table-column>
<el-table-column prop="ageRatio"
label="年龄占比 (%)"
align="center">
<template #default="{ row }">
<el-input v-model="row.ageRatio" placeholder="请输入"></el-input>
<el-input v-model="row.ageRatio"
placeholder="请输入"></el-input>
</template>
</el-table-column>
</el-table>
<h6 class="title mt-7">学历参数</h6>
<el-table class="c-table" :data="edus" :span-method="eduSpan" border>
<el-table-column prop="ageStage" label="年龄 (岁)" align="center"> </el-table-column>
<el-table-column prop="education" label="学历" align="center"></el-table-column>
<el-table-column prop="parentIds" label="学历占比 (%)" align="center">
<el-table class="c-table"
:data="edus"
:span-method="eduSpan"
border>
<el-table-column prop="ageStage"
label="年龄 (岁)"
align="center"> </el-table-column>
<el-table-column prop="education"
label="学历"
align="center"></el-table-column>
<el-table-column prop="parentIds"
label="学历占比 (%)"
align="center">
<template #default="{ row }">
<el-input v-model="row.eduRatio" placeholder="请输入"></el-input>
<el-input v-model="row.eduRatio"
placeholder="请输入"></el-input>
</template>
</el-table-column>
</el-table>
<h6 class="title mt-7">企业数量配置</h6>
<el-table class="c-table" :data="form.enterpriseNumList" border>
<el-table-column prop="productName" label="企业类型" align="center">
<el-table class="c-table"
:data="form.enterpriseNumList"
border>
<el-table-column prop="productName"
label="企业类型"
align="center">
<template #default="{ row }">
{{ row.enterpriseType == 1 ? '小微企业' : '创业企业' }}
</template>
</el-table-column>
<el-table-column prop="parentIds" label="企业数量(家)" align="center">
<el-table-column prop="parentIds"
label="企业数量(家)"
align="center">
<template #default="{ row }">
<el-input v-model.number="row.number" placeholder="请输入" maxlength="3" type="number" min="0"></el-input>
<el-input v-model.number="row.number"
placeholder="请输入"
maxlength="3"
type="number"
min="0"></el-input>
</template>
</el-table-column>
</el-table>
<h6 class="title mt-7">单个商品每日需求量</h6>
<el-table class="c-table" :data="form.commodityDemandList" border>
<el-table-column prop="typeName" label="买家类型" min-width="100" align="center"> </el-table-column>
<el-table-column prop="parentIds" label="买家总占比 (%)" min-width="100" align="center">
<el-table class="c-table"
:data="form.commodityDemandList"
border>
<el-table-column prop="typeName"
label="买家类型"
min-width="100"
align="center"> </el-table-column>
<el-table-column prop="parentIds"
label="买家总占比 (%)"
min-width="100"
align="center">
<template #default="{ row }">
<el-input v-model="row.buyerRatio" placeholder="请输入"></el-input>
<el-input v-model="row.buyerRatio"
placeholder="请输入"></el-input>
</template>
</el-table-column>
<el-table-column prop="parentIds" label="每次需求人数占比 (%)" min-width="130" align="center">
<el-table-column prop="parentIds"
label="每次需求人数占比 (%)"
min-width="130"
align="center">
<template #default="{ row }">
<el-input v-model="row.peopleNumRatio" placeholder="请输入"></el-input>
<el-input v-model="row.peopleNumRatio"
placeholder="请输入"></el-input>
</template>
</el-table-column>
<el-table-column prop="parentIds" label="单个买家单次需求" min-width="200" align="center">
<el-table-column prop="parentIds"
label="单个买家单次需求"
min-width="200"
align="center">
<template #default="{ row }">
<div class="flex items-center">
<template v-if="row.typeId == 7 || row.typeId == 8">
<span class="mr-2 whitespace-nowrap">一个保险产品一次最多购买</span>
<el-input v-model="row.buyerSingleDemand" placeholder="请输入"></el-input>
<el-input v-model="row.buyerSingleDemand"
placeholder="请输入"></el-input>
<span class="ml-2"></span>
</template>
<template v-else>
<span class="mr-2 whitespace-nowrap">{{ row.typeId == 9 ? '投入' : '贷款' }}</span>
<el-input v-model="row.buyerSingleDemandMin" placeholder="请输入"></el-input>
<el-input v-model="row.buyerSingleDemandMin"
placeholder="请输入"></el-input>
<span class="mx-2">~</span>
<el-input v-model="row.buyerSingleDemandMax" placeholder="请输入"></el-input>
<el-input v-model="row.buyerSingleDemandMax"
placeholder="请输入"></el-input>
<span class="ml-2 whitespace-nowrap">万元</span>
</template>
</div>
@ -74,7 +126,10 @@
</el-table>
<h6 class="title mt-7">系统账户起始金额</h6>
<el-form v-if="form.moneyAllocationList.length" class="w-[300px]" label-width="120px" label-suffix=":">
<el-form v-if="form.moneyAllocationList.length"
class="w-[300px]"
label-width="120px"
label-suffix=":">
<el-form-item label="银行账户">
<el-input v-model="form.moneyAllocationList[0].startingAmount">
<template #suffix> 万元 </template>
@ -94,7 +149,8 @@
</div>
<div class="flex justify-end">
<div class="submit" @click="submit">保存修改</div>
<div class="submit"
@click="submit">保存修改</div>
</div>
</template>

@ -1,19 +1,24 @@
<template>
<div class="max-h-[calc(100vh-290px)] overflow-auto">
<el-form ref="formRef" label-width="100px" label-suffix="" class="form" status-icon>
<el-form ref="formRef"
label-width="100px"
label-suffix=":"
class="form"
status-icon>
<h6 class="title">单个银行账户</h6>
<el-form-item label="收益计算">
<div>
<p class="text leading-[32px]">收入 = 收回的本金 + 利息</p>
<p class="text leading-[32px]">成本 = 贷出去未收回的本金 + 购买渠道金额</p>
<p class="text leading-[32px]">收益 = 收入 - 成本</p>
<p class="text leading-[32px] ">收入 = 收回的本金 + 利息</p>
<p class="text leading-[32px] ">成本 = 贷出去未收回的本金 + 购买渠道金额</p>
<p class="text leading-[32px] ">收益 = 收入 - 成本</p>
</div>
</el-form-item>
<el-form-item label="银行资产">
<div class="flex-1">
<div class="flex items-center">
<span class="text">起始金额</span>
<el-input class="w-[140px] mx-2" v-model="form[0].startingAmount"></el-input>
<el-input class="w-[140px] mx-2"
v-model="form[0].startingAmount"></el-input>
<span class="text">万元</span>
</div>
<p class="text mt-4">银行账户金额 = 起始金额 + 累计收益</p>
@ -23,16 +28,17 @@
<h6 class="title">单个保险账户</h6>
<el-form-item label="收益计算">
<div>
<p class="text leading-[32px]">收入 = 收到的保费</p>
<p class="text leading-[32px]">成本 = 赔偿金 + 购买渠道金额</p>
<p class="text leading-[32px]">收益 = 收入 - 成本</p>
<p class="text leading-[32px] ">收入 = 收到的保费</p>
<p class="text leading-[32px] ">成本 = 赔偿金 + 购买渠道金额</p>
<p class="text leading-[32px] ">收益 = 收入 - 成本</p>
</div>
</el-form-item>
<el-form-item label="保险资产">
<div class="flex-1">
<div class="flex items-center">
<span class="text">起始金额</span>
<el-input class="w-[140px] mx-2" v-model="form[1].startingAmount"></el-input>
<el-input class="w-[140px] mx-2"
v-model="form[1].startingAmount"></el-input>
<span class="text">万元</span>
</div>
<p class="text mt-4">保险账户金额 = 起始金额 + 累计收益</p>
@ -42,22 +48,23 @@
<h6 class="title">单个基金账户</h6>
<el-form-item label="冻结账户">
<div>
<p class="text leading-[32px]">冻结账户金额 = 申购金额 + 赎回金额</p>
<p class="text leading-[32px]">基金申购以及赎回确认份额期间</p>
<p class="text leading-[32px] ">冻结账户金额 = 申购金额 + 赎回金额</p>
<p class="text leading-[32px] ">基金申购以及赎回确认份额期间</p>
</div>
</el-form-item>
<el-form-item label="收益计算">
<div>
<p class="text leading-[32px]">收入 = 申购费用 + 管理费用 + 托管费用 + 销售服务费用 + 赎回费用</p>
<p class="text leading-[32px]">成本 = 购买渠道金额</p>
<p class="text leading-[32px]">收益 = 申购费用 + 管理费用 + 托管费用 + 销售服务费用 + 赎回费用</p>
<p class="text leading-[32px] ">收入 = 申购费用 + 管理费用 + 托管费用 + 销售服务费用 + 赎回费用</p>
<p class="text leading-[32px] ">成本 = 购买渠道金额</p>
<p class="text leading-[32px] ">收益 = 申购费用 + 管理费用 + 托管费用 + 销售服务费用 + 赎回费用</p>
</div>
</el-form-item>
<el-form-item label="基金资产:">
<div class="flex-1">
<div class="flex items-center">
<span class="text">起始金额</span>
<el-input class="w-[140px] mx-2" v-model="form[2].startingAmount"></el-input>
<el-input class="w-[140px] mx-2"
v-model="form[2].startingAmount"></el-input>
<span class="text">万元</span>
</div>
<p class="text mt-4">基金账户金额 = 所有基金资产净值+起始金额 + 累计收益 - 购买渠道金额</p>
@ -67,7 +74,8 @@
</div>
<div class="flex justify-end">
<div class="submit" @click="submit">保存修改</div>
<div class="submit"
@click="submit">保存修改</div>
</div>
</template>

@ -1,14 +1,19 @@
<template>
<div class="block">
<el-tabs v-model="curTab" @tab-click="tabChange">
<el-tab-pane label="系统买方" name="tab1">
<el-tabs v-model="curTab"
@tab-click="tabChange">
<el-tab-pane label="系统买方"
name="tab1">
<buyer />
</el-tab-pane>
<el-tab-pane label="金融市场" name="tab2">
<el-tab-pane label="金融市场"
name="tab2">
<Financial />
</el-tab-pane>
<el-tab-pane label="扫单配置" name="tab3"> </el-tab-pane>
<el-tab-pane label="渠道广告" name="tab4"> </el-tab-pane>
<el-tab-pane label="扫单配置"
name="tab3"> </el-tab-pane>
<el-tab-pane label="渠道广告"
name="tab4"> </el-tab-pane>
</el-tabs>
</div>
</template>

@ -9,17 +9,23 @@
<li>
<h6 class="title mb-[10px]">收入总额</h6>
<p class="text-lg text-[#F08B14]">696,652,660,000.00</p>
<img src="@/assets/images/account/1.png" alt="" class="bg" />
<img src="@/assets/images/account/1.png"
alt=""
class="bg" />
</li>
<li>
<h6 class="title mb-[10px]">支出总额</h6>
<p class="text-lg text-[#4488F4]">696,652,660,000.00</p>
<img src="@/assets/images/account/2.png" alt="" class="bg" />
<img src="@/assets/images/account/2.png"
alt=""
class="bg" />
</li>
<li>
<h6 class="title mb-[10px]">累计收益</h6>
<p class="text-lg text-[#FE4953]">696,652,660,000.00</p>
<img src="@/assets/images/account/3.png" alt="" class="bg" />
<img src="@/assets/images/account/3.png"
alt=""
class="bg" />
</li>
</ul>
</div>
@ -34,7 +40,8 @@
<div>
<div class="flex items-center mb-[75px]">
<div class="icon mr-2">
<img src="@/assets/images/account/6.png" alt="" />
<img src="@/assets/images/account/6.png"
alt="" />
</div>
<div class="">
<h6 class="mb-2 text-base text-[#333]">银行账户</h6>
@ -43,7 +50,8 @@
</div>
<div class="flex items-center mb-[75px]">
<div class="icon mr-2">
<img src="@/assets/images/account/7.png" alt="" />
<img src="@/assets/images/account/7.png"
alt="" />
</div>
<div class="">
@ -53,7 +61,8 @@
</div>
<div class="flex items-center">
<div class="icon mr-2">
<img src="@/assets/images/account/8.png" alt="" />
<img src="@/assets/images/account/8.png"
alt="" />
</div>
<div class="">
<h6 class="mb-2 text-base text-[#333]">基金账户</h6>
@ -72,7 +81,8 @@
<p class="text-[#448ACA] font-semibold">3656631.00</p>
</div>
<div class="icon blue ml-2">
<img src="@/assets/images/account/9.png" alt="" />
<img src="@/assets/images/account/9.png"
alt="" />
</div>
</div>
<div class="flex items-center">
@ -81,7 +91,8 @@
<p class="text-[#448ACA] font-semibold">3656631.00</p>
</div>
<div class="icon blue ml-2">
<img src="@/assets/images/account/10.png" alt="" />
<img src="@/assets/images/account/10.png"
alt="" />
</div>
</div>
</div>

@ -5,42 +5,77 @@
<dl>
<dt>担保方式</dt>
<div class="vals">
<dd v-for="(item, i) in productTypes" :key="i" :class="{ active: params.productType === item.id }" @click="filterClick(item, 'productType')">{{ item.name }}</dd>
<dd v-for="(item, i) in productTypes"
:key="i"
:class="{ active: params.productType === item.id }"
@click="filterClick(item, 'productType')">{{ item.name }}</dd>
</div>
</dl>
<dl>
<dt>担保方式</dt>
<div class="vals">
<dd v-for="(item, i) in guarantees" :key="i" :class="{ active: params.guarantyStyleId === item.id }" @click="filterClick(item, 'guarantyStyleId')">{{ item.name }}</dd>
<dd v-for="(item, i) in guarantees"
:key="i"
:class="{ active: params.guarantyStyleId === item.id }"
@click="filterClick(item, 'guarantyStyleId')">{{ item.name }}</dd>
</div>
</dl>
<dl>
<dt>贷款期限</dt>
<div class="vals">
<dd v-for="(item, i) in times" :key="i" :class="{ active: params.loanPeriod === item.name }" @click="filterClick(item, 'loanPeriod')">{{ item.name }}</dd>
<dd v-for="(item, i) in times"
:key="i"
:class="{ active: params.loanPeriod === item.name }"
@click="filterClick(item, 'loanPeriod')">{{ item.name }}</dd>
</div>
</dl>
<dl>
<dt>贷款额度</dt>
<div class="vals">
<dd v-for="(item, i) in moneys" :key="i" :class="{ active: params.loanLimit === item.name }" @click="filterClick(item, 'loanLimit')">{{ item.name }}</dd>
<dd v-for="(item, i) in moneys"
:key="i"
:class="{ active: params.loanLimit === item.name }"
@click="filterClick(item, 'loanLimit')">{{ item.name }}</dd>
</div>
</dl>
</div>
<div class="block mt-3">
<div class="search mb-2">
<input type="text" v-model="params.keyWord" placeholder="搜索" maxlength="20" />
<img src="@/assets/images/search.png" alt="" class="icon" />
<input type="text"
v-model="params.keyWord"
placeholder="搜索"
maxlength="20" />
<img src="@/assets/images/search.png"
alt=""
class="icon" />
</div>
<el-table ref="table" v-loading="loading" :data="list">
<el-table-column prop="productName" label="贷款名称" min-width="110"></el-table-column>
<el-table-column prop="productTypeText" label="贷款对象" min-width="80"></el-table-column>
<el-table-column prop="guarantyStyle" label="担保方式" min-width="80"></el-table-column>
<el-table-column prop="loanPeriod" label="贷款期限" min-width="80"></el-table-column>
<el-table-column prop="loanLimit" label="贷款额度" min-width="80"></el-table-column>
<el-table-column prop="rateStandard" label="参考利率范围" min-width="80"></el-table-column>
<el-table-column prop="userName" label="产品经理" min-width="80"></el-table-column>
<el-table-column prop="operationTime" label="发布日期" min-width="80"></el-table-column>
<el-table ref="table"
v-loading="loading"
:data="list">
<el-table-column prop="productName"
label="贷款名称"
min-width="110"></el-table-column>
<el-table-column prop="productTypeText"
label="贷款对象"
min-width="80"></el-table-column>
<el-table-column prop="guarantyStyle"
label="担保方式"
min-width="80"></el-table-column>
<el-table-column prop="loanPeriod"
label="贷款期限"
min-width="80"></el-table-column>
<el-table-column prop="loanLimit"
label="贷款额度"
min-width="80"></el-table-column>
<el-table-column prop="rateStandard"
label="参考利率范围"
min-width="80"></el-table-column>
<el-table-column prop="userName"
label="产品经理"
min-width="80"></el-table-column>
<el-table-column prop="operationTime"
label="发布日期"
min-width="80"></el-table-column>
<!-- <el-table-column prop="id"
label="操作"
width="100">
@ -50,18 +85,16 @@
@click="toDetail(row)">查看详情</el-button>
</template></el-table-column> -->
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</div>
</template>

@ -49,21 +49,19 @@
</div>
<div class="line">
<span class="label">贷款用途</span>
<div class="val">
{{
info.loanPurpose === '购房'
? '可用于住房按揭贷款、二手房住房按揭贷款。'
: info.loanPurpose === '消费'
? '贷款用途可用于除购房之外的合法个人消费支出,不得用于投资经营,不得用于无指定用途的个人支出。'
: info.loanPurpose === '经营' && !info.productType
? '可用于个人或其企业生产和经营活动中临时性、季节性等流动资金周转以及购置、安装或修理小型设备和装潢经营性场所所需的人民币贷款业务。'
: info.loanPurpose === '创业'
? '用于创业或再创业过程中的资金需求。'
: info.loanPurpose === '经营' && info.productType
? '用于短期生产经营周转的可循环的人民币信用贷款业务。'
: info.otherPurposesOfLoan
}}
</div>
<div class="val">{{
info.loanPurpose === '购房'
? '可用于住房按揭贷款、二手房住房按揭贷款。'
: info.loanPurpose === '消费'
? '贷款用途可用于除购房之外的合法个人消费支出,不得用于投资经营,不得用于无指定用途的个人支出。'
: info.loanPurpose === '经营' && !info.productType
? '可用于个人或其企业生产和经营活动中临时性、季节性等流动资金周转以及购置、安装或修理小型设备和装潢经营性场所所需的人民币贷款业务。'
: info.loanPurpose === '创业'
? '用于创业或再创业过程中的资金需求。'
: info.loanPurpose === '经营' && info.productType
? '用于短期生产经营周转的可循环的人民币信用贷款业务。'
: info.otherPurposesOfLoan
}}</div>
</div>
<div class="line">
<span class="label">还款方式</span>
@ -83,43 +81,71 @@
<span class="label">材料要求</span>
<div class="val">
<p class="text">办理账户-提供材料{{ riskInfo?.accountMaterials }}</p>
<p v-if="riskInfo?.sendingAccount" class="text">办理账户-发放账户借记卡或放款专户</p>
<p v-if="riskInfo?.loanApplicationMethod" class="text">贷款申请-申请方式{{ riskInfo?.loanApplicationMethod }}</p>
<p v-if="riskInfo?.borrowerMaterial" class="text">贷款申请-提供材料-借款人材料{{ riskInfo?.borrowerMaterial }}</p>
<p v-if="riskInfo?.sendingAccount"
class="text">办理账户-发放账户借记卡或放款专户</p>
<p v-if="riskInfo?.loanApplicationMethod"
class="text">贷款申请-申请方式{{ riskInfo?.loanApplicationMethod }}</p>
<p v-if="riskInfo?.borrowerMaterial"
class="text">贷款申请-提供材料-借款人材料{{ riskInfo?.borrowerMaterial }}</p>
<template v-if="info.productType">
<p v-if="riskInfo?.enterpriseMaterial" class="text">贷款申请-提供材料-企业材料{{ riskInfo?.enterpriseMaterial }}</p>
<p v-if="riskInfo?.collateral" class="text">贷款申请-提供材料-抵押物{{ riskInfo?.collateral }}</p>
<p v-if="riskInfo?.enterpriseMaterial"
class="text">贷款申请-提供材料-企业材料{{ riskInfo?.enterpriseMaterial }}</p>
<p v-if="riskInfo?.collateral"
class="text">贷款申请-提供材料-抵押物{{ riskInfo?.collateral }}</p>
</template>
<template v-else>
<p v-if="riskInfo?.mateMaterial" class="text">贷款申请-提供材料-配偶材料{{ riskInfo?.mateMaterial }}</p>
<p v-if="riskInfo?.businessMaterials" class="text">贷款申请-提供材料-经营类材料{{ riskInfo?.businessMaterials }}</p>
<p v-if="riskInfo?.mateMaterial"
class="text">贷款申请-提供材料-配偶材料{{ riskInfo?.mateMaterial }}</p>
<p v-if="riskInfo?.businessMaterials"
class="text">贷款申请-提供材料-经营类材料{{ riskInfo?.businessMaterials }}</p>
</template>
<p v-if="riskInfo?.supplementaryMaterials" class="text">贷款申请-提供材料-补充材料{{ riskInfo?.supplementaryMaterials }}</p>
<p v-if="riskInfo?.runBatchObject" class="text">系统跑批准入风控策略-跑批对象{{ riskInfo?.runBatchObject }}</p>
<p v-if="riskInfo?.accessStrategy" class="text">系统跑批准入风控策略-准入策略{{ riskInfo?.accessStrategy }}</p>
<p v-if="riskInfo?.personalCreditScoringStrategies" class="text">系统跑批准入风控策略-信用评分策略{{ riskInfo?.personalCreditScoringStrategies }}</p>
<p v-if="riskInfo?.riskDegreeStrategy" class="text">系统跑批准入风控策略-风险度策略{{ riskInfo?.riskDegreeStrategy }}</p>
<p v-if="riskInfo?.interestRatePricingModel" class="text">系统跑批准入风控策略-利率定价模型-个人额度模型{{ riskInfo?.interestRatePricingModel }}</p>
<p v-if="riskInfo?.individualInterestRateModel" class="text">系统跑批准入风控策略-利率定价模型-个人利率模型</p>
<p v-if="riskInfo?.dueDiligenceMode" class="text">尽职调查-尽调方式{{ riskInfo?.dueDiligenceMode }}</p>
<p v-if="riskInfo?.dueDiligenceContent" class="text">尽职调查-尽调内容{{ riskInfo?.dueDiligenceContent }}</p>
<p v-if="riskInfo?.reviewContent" class="text">贷款审查-审查内容{{ riskInfo?.reviewContent }}</p>
<p v-if="riskInfo?.reviewSignature" class="text">贷款审查-审查签字{{ riskInfo?.reviewSignature }}</p>
<p v-if="riskInfo?.reviewApproveContent" class="text">贷款审批-审批内容{{ riskInfo?.reviewApproveContent }}</p>
<p v-if="riskInfo?.approvalSignature" class="text">贷款审批-审批签字{{ riskInfo?.approvalSignature }}</p>
<p v-if="riskInfo?.contractMaterials" class="text">签订合同-提供的材料{{ riskInfo?.contractMaterials }}</p>
<p v-if="riskInfo?.loanContract" class="text">签订合同-合同模板-借贷合同{{ riskInfo?.loanContract }}</p>
<p v-if="riskInfo?.mortgageContract" class="text">签订合同-合同模板-抵押合同{{ riskInfo?.mortgageContract }}</p>
<p v-if="riskInfo?.pledgeContract" class="text">签订合同-合同模板-质押合同{{ riskInfo?.pledgeContract }}</p>
<p v-if="riskInfo?.guaranteeContract" class="text">签订合同-合同模板-担保合同{{ riskInfo?.guaranteeContract }}</p>
<p v-if="riskInfo?.selectionStrategy" class="text">贷后管理-选择策略{{ riskInfo?.selectionStrategy }}</p>
<p v-if="riskInfo?.supplementaryMaterials"
class="text">贷款申请-提供材料-补充材料{{ riskInfo?.supplementaryMaterials }}</p>
<p v-if="riskInfo?.runBatchObject"
class="text">系统跑批准入风控策略-跑批对象{{ riskInfo?.runBatchObject }}</p>
<p v-if="riskInfo?.accessStrategy"
class="text">系统跑批准入风控策略-准入策略{{ riskInfo?.accessStrategy }}</p>
<p v-if="riskInfo?.personalCreditScoringStrategies"
class="text">系统跑批准入风控策略-信用评分策略{{ riskInfo?.personalCreditScoringStrategies }}</p>
<p v-if="riskInfo?.riskDegreeStrategy"
class="text">系统跑批准入风控策略-风险度策略{{ riskInfo?.riskDegreeStrategy }}</p>
<p v-if="riskInfo?.interestRatePricingModel"
class="text">系统跑批准入风控策略-利率定价模型-个人额度模型{{ riskInfo?.interestRatePricingModel }}</p>
<p v-if="riskInfo?.individualInterestRateModel"
class="text">系统跑批准入风控策略-利率定价模型-个人利率模型</p>
<p v-if="riskInfo?.dueDiligenceMode"
class="text">尽职调查-尽调方式{{ riskInfo?.dueDiligenceMode }}</p>
<p v-if="riskInfo?.dueDiligenceContent"
class="text">尽职调查-尽调内容{{ riskInfo?.dueDiligenceContent }}</p>
<p v-if="riskInfo?.reviewContent"
class="text">贷款审查-审查内容{{ riskInfo?.reviewContent }}</p>
<p v-if="riskInfo?.reviewSignature"
class="text">贷款审查-审查签字{{ riskInfo?.reviewSignature }}</p>
<p v-if="riskInfo?.reviewApproveContent"
class="text">贷款审批-审批内容{{ riskInfo?.reviewApproveContent }}</p>
<p v-if="riskInfo?.approvalSignature"
class="text">贷款审批-审批签字{{ riskInfo?.approvalSignature }}</p>
<p v-if="riskInfo?.contractMaterials"
class="text">签订合同-提供的材料{{ riskInfo?.contractMaterials }}</p>
<p v-if="riskInfo?.loanContract"
class="text">签订合同-合同模板-借贷合同{{ riskInfo?.loanContract }}</p>
<p v-if="riskInfo?.mortgageContract"
class="text">签订合同-合同模板-抵押合同{{ riskInfo?.mortgageContract }}</p>
<p v-if="riskInfo?.pledgeContract"
class="text">签订合同-合同模板-质押合同{{ riskInfo?.pledgeContract }}</p>
<p v-if="riskInfo?.guaranteeContract"
class="text">签订合同-合同模板-担保合同{{ riskInfo?.guaranteeContract }}</p>
<p v-if="riskInfo?.selectionStrategy"
class="text">贷后管理-选择策略{{ riskInfo?.selectionStrategy }}</p>
</div>
</div>
</div>
<div class="user m-4">
<h6 class="mb-4 text-lg font-semibold text-[#01305B]">产品经理</h6>
<div class="text-center">
<img src="@/assets/images/bankDetail/4.png" alt="" class="mx-auto" />
<img src="@/assets/images/bankDetail/4.png"
alt=""
class="mx-auto" />
<p class="mt-2 font-semibold text-[#114575]">{{ userName }}</p>
</div>
<p class="mt-2 text-[#114575]">财经学院 金融2班</p>
@ -131,6 +157,7 @@
<script setup lang="ts">
import { ref, computed, watch, onMounted } from 'vue';
import { findById } from '@/api/bank';
import { getTheCurrentUserName } from '@/api/config';
import { useRouter, useRoute } from 'vue-router';
import Back from '@/components/Back.vue';
@ -152,8 +179,14 @@ const getDetail = async () => {
}
}
};
//
const getName = async () => {
const res = await getTheCurrentUserName();
userName.value = res.userName;
};
onMounted(() => {
getDetail();
getName();
});
</script>

@ -5,41 +5,77 @@
<dl>
<dt>申购费率</dt>
<div class="vals">
<dd v-for="(item, i) in rates" :key="i" :class="{ active: params.subscriptionRate === item.id }" @click="filterClick(item, 'subscriptionRate')">{{ item.name }}</dd>
<dd v-for="(item, i) in rates"
:key="i"
:class="{ active: params.subscriptionRate === item.id }"
@click="filterClick(item, 'subscriptionRate')">{{ item.name }}</dd>
</div>
</dl>
<dl>
<dt>成立年限</dt>
<div class="vals">
<dd v-for="(item, i) in times" :key="i" :class="{ active: params.establishmentPeriod === item.name }" @click="filterClick(item, 'establishmentPeriod')">
{{ item.name }}
</dd>
<dd v-for="(item, i) in times"
:key="i"
:class="{ active: params.establishmentPeriod === item.name }"
@click="filterClick(item, 'establishmentPeriod')">{{ item.name }}</dd>
</div>
</dl>
<dl>
<dt>基金规模</dt>
<div class="vals">
<dd v-for="(item, i) in scales" :key="i" :class="{ active: params.fundraisingScale === item.name }" @click="filterClick(item, 'fundraisingScale')">{{ item.name }}</dd>
<dd v-for="(item, i) in scales"
:key="i"
:class="{ active: params.fundraisingScale === item.name }"
@click="filterClick(item, 'fundraisingScale')">{{ item.name }}</dd>
</div>
</dl>
</div>
<div class="block mt-3">
<div class="search mb-2">
<input type="text" v-model="params.fundName" placeholder="搜索" maxlength="20" />
<img src="@/assets/images/search.png" alt="" class="icon" />
<input type="text"
v-model="params.fundName"
placeholder="搜索"
maxlength="20" />
<img src="@/assets/images/search.png"
alt=""
class="icon" />
</div>
<el-table ref="table" v-loading="loading" :data="list">
<el-table-column prop="fundCode" label="基金代码" min-width="80"></el-table-column>
<el-table-column prop="fundName" label="基金名称" min-width="110"></el-table-column>
<el-table-column prop="dailyNetAssetValue" label="最新单位净值" min-width="80"></el-table-column>
<el-table-column prop="dailyGrowthRate" label="日增长率(%)" min-width="80"></el-table-column>
<el-table-column prop="weeklyGrowthRate" label="近1周(%)" min-width="80"></el-table-column>
<el-table-column prop="monthlyGrowthRate" label="近1月(%)" min-width="80"></el-table-column>
<el-table-column prop="growthRateInRecentMarch" label="近3月(%)" min-width="80"></el-table-column>
<el-table-column prop="growthRateSinceInception" label="成立来(%)" min-width="80"></el-table-column>
<el-table-column prop="fundraisingScale" label="基金规模(万元)" min-width="80"></el-table-column>
<el-table-column prop="userName" label="产品经理" min-width="80"></el-table-column>
<el-table-column prop="operationTime" label="发布日期" min-width="80"></el-table-column>
<el-table ref="table"
v-loading="loading"
:data="list">
<el-table-column prop="fundCode"
label="基金代码"
min-width="80"></el-table-column>
<el-table-column prop="fundName"
label="基金名称"
min-width="110"></el-table-column>
<el-table-column prop="dailyNetAssetValue"
label="最新单位净值"
min-width="80"></el-table-column>
<el-table-column prop="dailyGrowthRate"
label="日增长率(%)"
min-width="80"></el-table-column>
<el-table-column prop="weeklyGrowthRate"
label="近1周(%)"
min-width="80"></el-table-column>
<el-table-column prop="monthlyGrowthRate"
label="近1月(%)"
min-width="80"></el-table-column>
<el-table-column prop="growthRateInRecentMarch"
label="近3月(%)"
min-width="80"></el-table-column>
<el-table-column prop="growthRateSinceInception"
label="成立来(%)"
min-width="80"></el-table-column>
<el-table-column prop="fundraisingScale"
label="基金规模(万元)"
min-width="80"></el-table-column>
<el-table-column prop="userName"
label="产品经理"
min-width="80"></el-table-column>
<el-table-column prop="operationTime"
label="发布日期"
min-width="80"></el-table-column>
<!-- <el-table-column prop="id"
label="操作"
width="100">
@ -49,18 +85,16 @@
@click="toDetail(row)">查看详情</el-button>
</template></el-table-column> -->
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</div>
</template>

@ -5,39 +5,71 @@
<dl>
<dt>险种分类</dt>
<div class="vals">
<dd v-for="(item, i) in insuranceTypes" :key="i" :class="{ active: params.insuranceType === item.id }" @click="filterClick(item, 'insuranceType')">{{ item.name }}</dd>
<dd v-for="(item, i) in insuranceTypes"
:key="i"
:class="{ active: params.insuranceType === item.id }"
@click="filterClick(item, 'insuranceType')">{{ item.name }}</dd>
</div>
</dl>
<dl v-if="params.insuranceType !== 311">
<dt>承保年龄</dt>
<div class="vals">
<dd v-for="(item, i) in ages" :key="i" :class="{ active: params.coverageAge === item.id }" @click="filterClick(item, 'coverageAge')">{{ item.id }}</dd>
<dd v-for="(item, i) in ages"
:key="i"
:class="{ active: params.coverageAge === item.id }"
@click="filterClick(item, 'coverageAge')">{{ item.id }}</dd>
</div>
</dl>
<dl>
<dt>保险期限</dt>
<div class="vals">
<dd v-for="(item, i) in times" :key="i" :class="{ active: params.protectionPeriod === item.id }" @click="filterClick(item, 'protectionPeriod')">{{ item.id }}</dd>
<dd v-for="(item, i) in times"
:key="i"
:class="{ active: params.protectionPeriod === item.id }"
@click="filterClick(item, 'protectionPeriod')">{{ item.id }}</dd>
</div>
</dl>
</div>
<div class="block mt-3">
<div class="search mb-2">
<input type="text" v-model="params.insuranceName" placeholder="搜索" maxlength="20" />
<img src="@/assets/images/search.png" alt="" class="icon" />
<input type="text"
v-model="params.insuranceName"
placeholder="搜索"
maxlength="20" />
<img src="@/assets/images/search.png"
alt=""
class="icon" />
</div>
<el-table ref="table" v-loading="loading" :data="list">
<el-table-column prop="insuranceName" label="保险名称" min-width="110"></el-table-column>
<el-table-column prop="insuranceTypeText" label="险种分类" min-width="80"></el-table-column>
<el-table-column v-if="params.insuranceType !== 311" prop="guarantyStyle" label="承保年龄" min-width="80">
<el-table ref="table"
v-loading="loading"
:data="list">
<el-table-column prop="insuranceName"
label="保险名称"
min-width="110"></el-table-column>
<el-table-column prop="insuranceTypeText"
label="险种分类"
min-width="80"></el-table-column>
<el-table-column v-if="params.insuranceType !== 311"
prop="guarantyStyle"
label="承保年龄"
min-width="80">
<template #default="{ row }">
{{ row.minimumAge ? row.minimumAge + '-' + row.maximumAge + '周岁' : '-' }}
</template>
</el-table-column>
<el-table-column prop="insuranceDeadline" label="保险期限" min-width="80"></el-table-column>
<el-table-column prop="premiumAmount" label="保费(元)" min-width="80"></el-table-column>
<el-table-column prop="userName" label="产品经理" min-width="80"></el-table-column>
<el-table-column prop="operationTime" label="发布日期" min-width="80"></el-table-column>
<el-table-column prop="insuranceDeadline"
label="保险期限"
min-width="80"></el-table-column>
<el-table-column prop="premiumAmount"
label="保费(元)"
min-width="80"></el-table-column>
<el-table-column prop="userName"
label="产品经理"
min-width="80"></el-table-column>
<el-table-column prop="operationTime"
label="发布日期"
min-width="80"></el-table-column>
<!-- <el-table-column prop="id"
label="操作"
width="100">
@ -47,18 +79,16 @@
@click="toDetail(row)">查看详情</el-button>
</template></el-table-column> -->
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</div>
</template>

@ -8,37 +8,55 @@
<h6 class="title mb-5">订单列表</h6>
<div class="flex justify-between mb-5">
<div class="search">
<input type="text" placeholder="搜索" maxlength="20" />
<img src="@/assets/images/search.png" alt="" class="icon" />
<input type="text"
placeholder="搜索"
maxlength="20" />
<img src="@/assets/images/search.png"
alt=""
class="icon" />
</div>
<div>
<el-select v-model="form.status" placeholder="订单类型" size="large">
<el-option v-for="item in paces" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="form.status"
placeholder="订单类型"
size="large">
<el-option v-for="item in paces"
:key="item.id"
:label="item.name"
:value="item.id" />
</el-select>
</div>
</div>
<el-table ref="table" v-loading="loading" :data="data">
<el-table-column type="selection" :selectable="deletable" width="50"></el-table-column>
<el-table-column prop="parentIds" label="订单号"></el-table-column>
<el-table-column prop="parentIds" label="产品名称"></el-table-column>
<el-table-column prop="parentIds" label="订单类型"></el-table-column>
<el-table-column prop="parentIds" label="成交情况"></el-table-column>
<el-table-column prop="parentIds" label="成交日期"></el-table-column>
<el-table-column prop="parentIds" label="订单情况 "></el-table-column>
<el-table-column prop="parentIds" label="备注"></el-table-column>
<el-table ref="table"
v-loading="loading"
:data="data">
<el-table-column type="selection"
:selectable="deletable"
width="50"></el-table-column>
<el-table-column prop="parentIds"
label="订单号"></el-table-column>
<el-table-column prop="parentIds"
label="产品名称"></el-table-column>
<el-table-column prop="parentIds"
label="订单类型"></el-table-column>
<el-table-column prop="parentIds"
label="成交情况"></el-table-column>
<el-table-column prop="parentIds"
label="成交日期"></el-table-column>
<el-table-column prop="parentIds"
label="订单情况 "></el-table-column>
<el-table-column prop="parentIds"
label="备注"></el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="fetchData()"
@current-change="fetchData()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="fetchData()"
@current-change="fetchData()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</div>
</template>

@ -6,25 +6,34 @@
<div class="line">
<label class="label">产品类型</label>
<div class="fields">
<el-input value="银行产品" disabled></el-input>
<el-input value="银行产品"
disabled></el-input>
</div>
</div>
<div class="line">
<label class="label">选择产品</label>
<div class="fields flex items-center">
<el-input class="mr-5" placeholder="点击选择需要发布的产品"></el-input>
<div class="btn" @click="showProduct">新增</div>
<el-input class="mr-5"
placeholder="点击选择需要发布的产品"></el-input>
<div class="btn"
@click="showProduct">新增</div>
</div>
</div>
<div class="line">
<label class="label">产品图标</label>
<div class="fields">
<p class="tips">上传产品LOGO图片</p>
<div class="avatar-uploader" action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15" :show-file-list="false">
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<div v-else class="upload">
<div class="avatar-uploader"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
:show-file-list="false">
<img v-if="imageUrl"
:src="imageUrl"
class="avatar" />
<div v-else
class="upload">
<el-icon :size="20">
<Plus :size="20" color="#DFE9F8" />
<Plus :size="20"
color="#DFE9F8" />
</el-icon>
</div>
</div>
@ -43,11 +52,15 @@
<p class="tips">选择需要购买的投放渠道</p>
<div class="route">
<p class="text">{百度广告类型}单次广告价格为{}适用于{}次扫单</p>
<el-input-number v-model="num" :min="1" :max="10" />
<el-input-number v-model="num"
:min="1"
:max="10" />
</div>
<div class="route">
<p class="text">{百度广告类型}单次广告价格为{}适用于{}次扫单</p>
<el-input-number v-model="num" :min="1" :max="10" />
<el-input-number v-model="num"
:min="1"
:max="10" />
</div>
</div>
</div>
@ -64,37 +77,50 @@
</div>
</div>
<el-dialog v-model="productVisible" title="选择需要发布的银行产品" width="1000px" center>
<el-dialog v-model="productVisible"
title="选择需要发布的银行产品"
width="1000px"
center>
<div class="flex justify-between mb-4">
<search v-model="keyword"></search>
<el-checkbox label="仅查看未发布的产品" />
</div>
<el-table ref="table" v-loading="loading" :data="list">
<el-table-column prop="productNumber" label="产品名称"></el-table-column>
<el-table-column prop="productNumber" label="产品编号"></el-table-column>
<el-table-column prop="productNumber" label="产品对象"></el-table-column>
<el-table-column prop="parentIds" label="担保方式"></el-table-column>
<el-table-column prop="parentIds" label="贷款用途"></el-table-column>
<el-table-column prop="loanCeiling" label="最高额度/年利率/期限"></el-table-column>
<el-table-column prop="createTime" label="创建日期"></el-table-column>
<el-table-column prop="status" label="状态"></el-table-column>
<el-table ref="table"
v-loading="loading"
:data="list">
<el-table-column prop="productNumber"
label="产品名称"></el-table-column>
<el-table-column prop="productNumber"
label="产品编号"></el-table-column>
<el-table-column prop="productNumber"
label="产品对象"></el-table-column>
<el-table-column prop="parentIds"
label="担保方式"></el-table-column>
<el-table-column prop="parentIds"
label="贷款用途"></el-table-column>
<el-table-column prop="loanCeiling"
label="最高额度/年利率/期限"></el-table-column>
<el-table-column prop="createTime"
label="创建日期"></el-table-column>
<el-table-column prop="status"
label="状态"></el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="fetchData()"
@current-change="fetchData()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="fetchData()"
@current-change="fetchData()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
<template #footer>
<span class="flex justify-center">
<div class="dia-btn cancel" @click="productVisible = false">取消</div>
<div class="dia-btn" @click="productVisible = false">确定</div>
<div class="dia-btn mr-3 cancel"
@click="productVisible = false">取消</div>
<div class="dia-btn"
@click="productVisible = false">确定</div>
</span>
</template>
</el-dialog>

@ -0,0 +1,173 @@
<template>
<!-- 五级分类 -->
<el-table class="c-table"
:data="form"
:span-method="span"
:cell-style="{background:'#fff'}"
border>
<el-table-column prop="recordName"
label="产品类别"
min-width="150"
align="center">
</el-table-column>
<el-table-column label="逾期时间"
align="center">
<el-table-column label="未逾期"
align="center">
<template #default="{ row }">
<el-select clearable
v-model="row.notOverdue">
<el-option v-for="item in row.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template>
</el-table-column>
<el-table-column label="1~30天"
align="center">
<template #default="{ row }">
<el-select clearable
v-model="row.thirtyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template></el-table-column>
<el-table-column label="31~90天"
align="center">
<template #default="{ row }">
<el-select clearable
v-model="row.ninetyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template></el-table-column>
<el-table-column label="91~180天"
align="center">
<template #default="{ row }">
<el-select clearable
v-model="row.oneHundredAndEightyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template></el-table-column>
<el-table-column label="181~360天"
align="center">
<template #default="{ row }">
<el-select clearable
v-model="row.threeHundredAndSixtyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template></el-table-column>
<el-table-column label="360天以上"
align="center">
<template #default="{ row }">
<el-select clearable
v-model="row.threeHundredAndSixtyDaysAbove">
<el-option v-for="item in row.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template></el-table-column>
</el-table-column>
</el-table>
<div class="flex justify-end">
<div class="submit"
@click="submit">确认完成配置</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { fiveLevelClassificationDetails, fiveLevelClassificationSave } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1029);
const result = [];
process.map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
result.push({
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
ninetyDays: +cur.ninetyDays || '',
notOverdue: +cur.notOverdue || '',
oneHundredAndEightyDays: +cur.oneHundredAndEightyDays || '',
thirtyDays: +cur.thirtyDays || '',
threeHundredAndSixtyDays: +cur.threeHundredAndSixtyDays || '',
threeHundredAndSixtyDaysAbove: +cur.threeHundredAndSixtyDaysAbove || '',
id: cur.id || '',
stRecordId: e.id,
});
});
form.value = result;
};
//
const getDetail = async () => {
try {
const { data } = await fiveLevelClassificationDetails();
info.value = data;
getConfig();
} finally {
}
};
const fieldKeys = ['notOverdue', 'thirtyDays', 'ninetyDays', 'oneHundredAndEightyDays', 'threeHundredAndSixtyDays', 'threeHundredAndSixtyDaysAbove'];
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${levelId},42,69,1029`; // 1id
const rule = [];
data.map((e) => {
e.recordChildren.forEach((n, i) => {
e[fieldKeys[i]] && rule.push(handleId(n.id, n.subjectId, e[fieldKeys[i]], `${preIds},${e.stRecordId},${n.id}`, 1));
});
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
};
//
const submit = async () => {
let param = JSON.parse(JSON.stringify(form.value));
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await fiveLevelClassificationSave({ fiveLevelClassificationList: param });
addRecord(recordParam);
getDetail();
ElMessage.success('提交成功!');
};
onMounted(() => {
getDetail();
});
</script>
<style lang="scss" scoped>
@import url(../../../styles/form.scss);
</style>

@ -1,194 +0,0 @@
<template>
<!-- 五级分类 -->
<el-form label-width="90px" label-suffix="" class="form" :disabled="disabled" v-loading="loading">
<el-form-item label="策略名称">
<div>
<el-input class="w-[320px]" placeholder="请输入20以内字符" maxlength="20" clearable v-model="strategyName" />
<p v-if="bankIds.length" class="text-danger">不同步已关联产品请修改策略名称</p>
</div>
</el-form-item>
<el-form-item label="策略规则">
<el-table class="c-table" :data="form" :cell-style="{ background: '#fff' }" border>
<el-table-column prop="recordName" label="产品类别" min-width="150" align="center"> </el-table-column>
<el-table-column label="逾期时间" align="center">
<el-table-column label="未逾期" align="center">
<template #default="{ row }">
<el-select clearable v-model="row.notOverdue">
<el-option v-for="item in row.recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</template>
</el-table-column>
<el-table-column label="1~30天" align="center">
<template #default="{ row }">
<el-select clearable v-model="row.thirtyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select> </template
></el-table-column>
<el-table-column label="31~90天" align="center">
<template #default="{ row }">
<el-select clearable v-model="row.ninetyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select> </template
></el-table-column>
<el-table-column label="91~180天" align="center">
<template #default="{ row }">
<el-select clearable v-model="row.oneHundredAndEightyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select> </template
></el-table-column>
<el-table-column label="181~360天" align="center">
<template #default="{ row }">
<el-select clearable v-model="row.threeHundredAndSixtyDays">
<el-option v-for="item in row.recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select> </template
></el-table-column>
<el-table-column label="360天以上" align="center">
<template #default="{ row }">
<el-select clearable v-model="row.threeHundredAndSixtyDaysAbove">
<el-option v-for="item in row.recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select> </template
></el-table-column>
</el-table-column>
</el-table>
</el-form-item>
<div v-if="!disabled" class="flex justify-end mt-3">
<div class="dia-btn cancel" @click="emit('close')">取消</div>
<div class="dia-btn" @click="confirmSubmit">确定</div>
</div>
</el-form>
<Confirm v-model="syncVisible" @submit="submit" />
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent, onMounted, toRefs } from 'vue';
import { ElMessage } from 'element-plus';
import { fiveLevelClassificationDetails, fiveLevelClassificationSave, isTheStrategyRelatedToTheProduct } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
import { getStat } from '@/store/useProduct';
const Confirm = defineAsyncComponent(() => import('@/components/StrategyConfirm.vue'));
const props = defineProps({
disabled: { type: Boolean, default: false },
row: { type: Object },
});
const emit = defineEmits(['close']);
const { strategyId, strategyName } = toRefs(props.row);
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const syncVisible = ref<boolean>(false);
const bankIds = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1029);
const result = [];
process.slice(1).map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
result.push({
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
ninetyDays: +cur.ninetyDays || '',
notOverdue: +cur.notOverdue || '',
oneHundredAndEightyDays: +cur.oneHundredAndEightyDays || '',
thirtyDays: +cur.thirtyDays || '',
threeHundredAndSixtyDays: +cur.threeHundredAndSixtyDays || '',
threeHundredAndSixtyDaysAbove: +cur.threeHundredAndSixtyDaysAbove || '',
id: cur.id || '',
stRecordId: e.id,
});
});
form.value = result;
loading.value = false;
};
//
const getDetail = async () => {
loading.value = true;
try {
if (strategyId.value) {
const { data } = await fiveLevelClassificationDetails({
strategyId: strategyId.value,
});
info.value = data;
}
getConfig();
//
if (strategyId.value && !props.disabled) {
const res = await isTheStrategyRelatedToTheProduct({
tacticsId: strategyId.value,
strategyType: 14,
});
if (res.isRelated) bankIds.value = res.bankIds;
}
} finally {
}
};
onMounted(getDetail);
const fieldKeys = ['notOverdue', 'thirtyDays', 'ninetyDays', 'oneHundredAndEightyDays', 'threeHundredAndSixtyDays', 'threeHundredAndSixtyDaysAbove'];
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${Cookies.get('sand-level')},42,69,1029`; // 1id
const rule = [handleId(140, 28, strategyName.value, `${preIds},140`, 3)];
data.map((e) => {
e.recordChildren.forEach((n, i) => {
e[fieldKeys[i]] && rule.push(handleId(n.id, n.subjectId, e[fieldKeys[i]], `${preIds},${e.stRecordId},${n.id}`, 1));
});
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
loading.value = false;
ElMessage.success('提交成功!');
syncVisible.value = false;
emit('close', 1);
};
//
const submit = async (synchronizeUpdate?: number) => {
loading.value = true;
try {
const param = JSON.parse(JSON.stringify(form.value));
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await fiveLevelClassificationSave({
...getIds(),
strategyId: strategyId.value,
strategyName: strategyName.value,
synchronizeUpdate,
fiveLevelClassificationList: param,
bankIds: bankIds.value,
});
getStat(295);
addRecord(recordParam);
} catch (e) {
loading.value = false;
}
};
const confirmSubmit = async () => {
if (!strategyName.value) return ElMessage.error('请输入策略名称!');
//
if (bankIds.value.length) {
syncVisible.value = true;
} else {
submit();
}
};
</script>
<style lang="scss" scoped>
@import url(../../../../styles/form.scss);
</style>

@ -1,157 +0,0 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="keyWord" @change="initList"></search>
<div class="filter">
<el-popconfirm title="确定删除选中策略吗?" :disabled="!multipleSelection.length" @confirm.stop="delAll">
<template #reference>
<div :class="['add-btn mr-2', { 'cursor-not-allowed': !multipleSelection.length }]">
<el-icon :size="24" color="#fff">
<Delete />
</el-icon>
批量删除
</div>
</template>
</el-popconfirm>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
新增
</div>
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="handleDisable" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column prop="strategyName" label="五级分类策略名称" min-width="180" />
<el-table-column prop="createTime" label="新增日期" min-width="140" />
<el-table-column label="操作" width="140">
<template #default="{ row }">
<el-button type="primary" link @click="toDetail(row, true)" size="small">查看</el-button>
<template v-if="!row.builtIn">
<el-button type="primary" link @click="toDetail(row)" size="small">编辑</el-button>
<el-popconfirm title="确定删除这条策略吗?" @confirm.stop="handleDelete([row.strategyId])">
<template #reference>
<el-button type="primary" link size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-drawer v-model="visible" :title="(isDetail ? '查看' : curRow.strategyId ? '编辑' : '新增') + '五级分类策略'" size="100%" :z-index="10" class="model-drawer">
<Detail v-model:row="curRow" :disabled="isDetail" :key="i" @close="closeDrawer" />
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, defineAsyncComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { pageSizes, pageLayout } from '@/utils/common';
import { fiveLevelClassification, fiveLevelClassificationDel } from '@/api/model';
import Search from '@/components/Search.vue';
const Detail = defineAsyncComponent(() => import('./Detail.vue'));
const keyWord = ref<string>();
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
const table = ref<any>();
const multipleSelection = ref<Record<string, any>[]>([]);
const list = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const visible = ref<boolean>(false);
const curRow = ref<Record<string, any>>({
strategyId: '',
strategyName: '',
});
const isDetail = ref<boolean>(false);
const i = ref<number>(0);
//
const getList = async () => {
loading.value = true;
try {
const { page } = await fiveLevelClassification({ pageNum: currentPage.value, pageSize: pageSize.value, keyWord: keyWord.value });
list.value = page.records;
total.value = page.total;
} finally {
loading.value = false;
}
};
//
const initList = async () => {
currentPage.value = 1;
getList();
};
watch(keyWord, initList);
onMounted(getList);
//
const handleDisable = (row: Record<string, any>) => {
//
if (row.builtIn) return false;
return true;
};
//
const handleSelectionChange = (val: Record<string, any>[]) => {
multipleSelection.value = val;
};
const handleDelete = async (ids: number[]) => {
try {
const res = await fiveLevelClassificationDel({ ids });
//
if (res.tip) {
ElMessageBox.alert(res.message, '提示', {
confirmButtonText: '确定',
});
} else {
getList();
ElMessage.success('删除成功!');
}
} catch (e) {}
};
//
const delAll = async () => {
handleDelete(multipleSelection.value.map((e) => e.strategyId));
};
//
const toAdd = () => {
i.value++;
isDetail.value = false;
curRow.value = {
strategyId: '',
strategyName: '',
};
visible.value = true;
};
//
const toDetail = async (row: Record<string, any>, detail = false) => {
i.value++;
isDetail.value = detail;
curRow.value = row;
visible.value = true;
};
//
const closeDrawer = (refresh?: number) => {
visible.value = false;
refresh && initList();
};
</script>

@ -0,0 +1,186 @@
<template>
<!-- 贷后检查 -->
<div class="c-auto">
<el-table class="c-table"
:data="form"
:cell-style="{background:'#fff'}"
border>
<el-table-column prop="name"
label="选用"
width="100"
align="center">
<template #default="{ row }">
<el-checkbox v-model="row.isChoose"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="recordName"
label="检查方式"
min-width="150"
align="center"></el-table-column>
<el-table-column label="检查对象"
min-width="200"
align="center">
<template #default="{ row }">
<el-select v-if="row.recordChildren"
clearable
v-model="row.checkObject">
<el-option v-for="item in row?.recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template>
</el-table-column>
<el-table-column label="检查时间"
min-width="270"
align="center">
<template #default="{ row, $index }">
<span v-if="$index === 4">点击后触发</span>
<div v-else
class="flex items-center">
<el-select v-if="row.recordChildren"
clearable
v-model="row.checkTimeType">
<el-option v-for="item in row?.recordChildren[2].recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
<el-input class="w-[100px] mx-2"
placeholder="请输入"
v-model="row.timeDays"></el-input>
</div>
</template>
</el-table-column>
<el-table-column label="检查内容"
min-width="230"
align="center">
<template #default="{ row }">
<el-checkbox v-model="row.governmentData">政务数据</el-checkbox>
<el-checkbox v-model="row.creditData">征信数据</el-checkbox>
</template>
</el-table-column>
</el-table>
</div>
<div class="flex justify-end">
<div class="submit"
@click="submit">确认完成配置</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { postLoanInspectionDetails, postLoanInspectionSave } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import type { TableColumnCtx } from 'element-plus';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1030);
const result = [];
process.map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
let temp = {
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
checkObject: +cur.checkObject || '',
checkTimeType: +cur.checkTimeType || '',
creditData: info.value.length ? !!cur.creditData : false,
governmentData: info.value.length ? !!cur.governmentData : false,
isChoose: info.value.length ? !!cur.isChoose : false,
timeDays: cur.timeDays || '',
id: cur.id || '',
stRecordId: e.id,
};
result.push(temp);
});
form.value = result;
};
//
const getDetail = async () => {
try {
const { data } = await postLoanInspectionDetails();
info.value = data;
getConfig();
} finally {
}
};
interface SpanMethodProps {
row: Record<string, any>;
column: TableColumnCtx<Record<string, any>>;
rowIndex: number;
columnIndex: number;
}
//
const span = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
if (columnIndex < 2) {
if (rowIndex === 1) {
return {
rowspan: 2,
colspan: 1,
};
} else if (rowIndex === 2) {
return {
rowspan: 0,
colspan: 0,
};
}
}
};
//
const addRecord = async (data: Record<string, any>) => {
console.log('🚀 ~ addRecord ~ data:', data);
const preIds = `1,${Cookies.get('sand-level')},42,69,1030`; // 1id
const rule = [];
data.forEach((e, i) => {
e.isChoose && rule.push(handleId(1052, '', '', preIds + ',' + e.stRecordId + ',1052', ''));
e.checkObject && rule.push(handleId(1053, 282, e.checkObject, preIds + ',' + e.stRecordId + ',1053', 1));
i !== 4 && e.checkTimeType && rule.push(handleId(1054, 283, e.checkTimeType, preIds + ',' + e.stRecordId + ',1054,1056', 1));
e.timeDays && rule.push(handleId(1057, 284, e.timeDays, preIds + ',' + e.stRecordId + ',1054,1057', 3));
const ids = [];
e.governmentData && ids.push(778);
e.creditData && ids.push(793);
e.governmentData && rule.push(handleId(1055, 323, ids.join(), preIds + ',' + e.stRecordId + ',1055', 1));
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
};
//
const submit = async () => {
let param = JSON.parse(JSON.stringify(form.value));
param.map((e, i) => {
e.creditData = +e.creditData;
e.governmentData = +e.governmentData;
e.isChoose = +e.isChoose;
});
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await postLoanInspectionSave({ postLoanInspectionList: param });
addRecord(recordParam);
getDetail();
ElMessage.success('提交成功!');
};
onMounted(() => {
getDetail();
});
</script>
<style lang="scss" scoped>
@import url(../../../styles/form.scss);
</style>

@ -1,219 +0,0 @@
<template>
<!-- 贷后检查 -->
<el-form label-width="90px" label-suffix="" class="form" :disabled="disabled" v-loading="loading">
<el-form-item label="策略名称">
<div>
<el-input class="w-[320px]" placeholder="请输入20以内字符" maxlength="20" clearable v-model="strategyName" />
<p v-if="bankIds.length" class="text-danger">不同步已关联产品请修改策略名称</p>
</div>
</el-form-item>
<el-form-item label="策略规则">
<el-table class="c-table" :data="form" :cell-style="{ background: '#fff' }" border>
<el-table-column prop="name" label="选用" width="130" align="center">
<template #default="{ row }">
<el-radio-group v-model="row.isChoose">
<el-radio v-for="(item, i) in opt1" :key="i" :label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</template>
</el-table-column>
<el-table-column prop="recordName" label="检查方式" min-width="150" align="center"></el-table-column>
<el-table-column label="检查对象" min-width="200" align="center">
<template #default="{ row }">
<el-select v-if="row.recordChildren" clearable v-model="row.checkObject">
<el-option v-for="item in row?.recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</template>
</el-table-column>
<el-table-column label="检查时间" min-width="270" align="center">
<template #default="{ row, $index }">
<span v-if="$index === 4">点击后触发</span>
<div v-else class="flex items-center">
<el-select v-if="row.recordChildren" clearable v-model="row.checkTimeType">
<el-option v-for="item in row?.recordChildren[2].recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
<el-input class="w-[100px] mx-2" placeholder="请输入" v-model="row.timeDays"></el-input>
</div>
</template>
</el-table-column>
<el-table-column label="检查内容" min-width="230" align="center">
<template #default="{ row }">
<el-checkbox v-model="row.governmentData">政务数据</el-checkbox>
<el-checkbox v-model="row.creditData">征信数据</el-checkbox>
</template>
</el-table-column>
</el-table>
</el-form-item>
<div v-if="!disabled" class="flex justify-end mt-3">
<div class="dia-btn cancel" @click="emit('close')">取消</div>
<div class="dia-btn" @click="confirmSubmit">确定</div>
</div>
</el-form>
<Confirm v-model="syncVisible" @submit="submit" />
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent, onMounted, toRefs } from 'vue';
import { ElMessage } from 'element-plus';
import { postLoanInspectionDetails, postLoanInspectionSave, isTheStrategyRelatedToTheProduct } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import type { TableColumnCtx } from 'element-plus';
import { handleId, getIds, opt1 } from '@/utils/common';
import Cookies from 'js-cookie';
import { getStat } from '@/store/useProduct';
const Confirm = defineAsyncComponent(() => import('@/components/StrategyConfirm.vue'));
const props = defineProps({
disabled: { type: Boolean, default: false },
row: { type: Object },
});
const emit = defineEmits(['close']);
const { strategyId, strategyName } = toRefs(props.row);
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const syncVisible = ref<boolean>(false);
const bankIds = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1030);
const result = [];
process.slice(1).map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
const temp = {
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
checkObject: +cur.checkObject || '',
checkTimeType: +cur.checkTimeType || '',
creditData: info.value.length ? !!cur.creditData : false,
governmentData: info.value.length ? !!cur.governmentData : false,
isChoose: info.value.length ? cur.isChoose : '',
timeDays: cur.timeDays || '',
id: cur.id || '',
stRecordId: e.id,
};
result.push(temp);
});
form.value = result;
loading.value = false;
};
//
const getDetail = async () => {
loading.value = true;
try {
if (strategyId.value) {
const { data } = await postLoanInspectionDetails({
strategyId: strategyId.value,
});
info.value = data;
}
getConfig();
//
if (strategyId.value && !props.disabled) {
const res = await isTheStrategyRelatedToTheProduct({
tacticsId: strategyId.value,
strategyType: 15,
});
if (res.isRelated) bankIds.value = res.bankIds;
}
} finally {
}
};
onMounted(getDetail);
interface SpanMethodProps {
row: Record<string, any>;
column: TableColumnCtx<Record<string, any>>;
rowIndex: number;
columnIndex: number;
}
//
const span = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
if (columnIndex < 2) {
if (rowIndex === 1) {
return {
rowspan: 2,
colspan: 1,
};
}
if (rowIndex === 2) {
return {
rowspan: 0,
colspan: 0,
};
}
}
};
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${Cookies.get('sand-level')},42,69,1030`; // 1id
const rule = [handleId(140, 28, strategyName.value, `${preIds},140`, 3)];
data.forEach((e, i) => {
e.isChoose && rule.push(handleId(1052, 140, e.isChoose, `${preIds},${e.stRecordId},1052`, 1));
e.checkObject && rule.push(handleId(1053, 282, e.checkObject, `${preIds},${e.stRecordId},1053`, 1));
i !== 4 && e.checkTimeType && rule.push(handleId(1054, 283, e.checkTimeType, `${preIds},${e.stRecordId},1054,1056`, 1));
e.timeDays && rule.push(handleId(1057, 284, e.timeDays, `${preIds},${e.stRecordId},1054,1057`, 3));
const ids = [];
e.governmentData && ids.push(778);
e.creditData && ids.push(793);
e.governmentData && rule.push(handleId(1055, 323, ids.join(), `${preIds},${e.stRecordId},1055`, 1));
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
loading.value = false;
ElMessage.success('提交成功!');
syncVisible.value = false;
emit('close', 1);
};
//
const submit = async (synchronizeUpdate?: number) => {
loading.value = true;
try {
const param = JSON.parse(JSON.stringify(form.value));
param.map((e, i) => {
e.creditData = +e.creditData;
e.governmentData = +e.governmentData;
});
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await postLoanInspectionSave({
...getIds(),
strategyId: strategyId.value,
strategyName: strategyName.value,
synchronizeUpdate,
postLoanInspectionList: param,
bankIds: bankIds.value,
});
getStat(295);
addRecord(recordParam);
} catch (e) {
loading.value = false;
}
};
const confirmSubmit = async () => {
if (!strategyName.value) return ElMessage.error('请输入策略名称!');
//
if (bankIds.value.length) {
syncVisible.value = true;
} else {
submit();
}
};
</script>
<style lang="scss" scoped>
@import url(../../../../styles/form.scss);
</style>

@ -1,157 +0,0 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="keyWord" @change="initList"></search>
<div class="filter">
<el-popconfirm title="确定删除选中策略吗?" :disabled="!multipleSelection.length" @confirm.stop="delAll">
<template #reference>
<div :class="['add-btn mr-2', { 'cursor-not-allowed': !multipleSelection.length }]">
<el-icon :size="24" color="#fff">
<Delete />
</el-icon>
批量删除
</div>
</template>
</el-popconfirm>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
新增
</div>
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="handleDisable" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column prop="strategyName" label="贷后检查策略名称" min-width="180" />
<el-table-column prop="createTime" label="新增日期" min-width="140" />
<el-table-column label="操作" width="140">
<template #default="{ row }">
<el-button type="primary" link @click="toDetail(row, true)" size="small">查看</el-button>
<template v-if="!row.builtIn">
<el-button type="primary" link @click="toDetail(row)" size="small">编辑</el-button>
<el-popconfirm title="确定删除这条策略吗?" @confirm.stop="handleDelete([row.strategyId])">
<template #reference>
<el-button type="primary" link size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-drawer v-model="visible" :title="(isDetail ? '查看' : curRow.strategyId ? '编辑' : '新增') + '贷后检查策略'" size="100%" :z-index="10" class="model-drawer">
<Detail v-model:row="curRow" :disabled="isDetail" :key="i" @close="closeDrawer" />
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, defineAsyncComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { pageSizes, pageLayout } from '@/utils/common';
import { postLoanInspection, postLoanInspectionDel } from '@/api/model';
import Search from '@/components/Search.vue';
const Detail = defineAsyncComponent(() => import('./Detail.vue'));
const keyWord = ref<string>();
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
const table = ref<any>();
const multipleSelection = ref<Record<string, any>[]>([]);
const list = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const visible = ref<boolean>(false);
const curRow = ref<Record<string, any>>({
strategyId: '',
strategyName: '',
});
const isDetail = ref<boolean>(false);
const i = ref<number>(0);
//
const getList = async () => {
loading.value = true;
try {
const { page } = await postLoanInspection({ pageNum: currentPage.value, pageSize: pageSize.value, keyWord: keyWord.value });
list.value = page.records;
total.value = page.total;
} finally {
loading.value = false;
}
};
//
const initList = async () => {
currentPage.value = 1;
getList();
};
watch(keyWord, initList);
onMounted(getList);
//
const handleDisable = (row: Record<string, any>) => {
//
if (row.builtIn) return false;
return true;
};
//
const handleSelectionChange = (val: Record<string, any>[]) => {
multipleSelection.value = val;
};
const handleDelete = async (ids: number[]) => {
try {
const res = await postLoanInspectionDel({ ids });
//
if (res.tip) {
ElMessageBox.alert(res.message, '提示', {
confirmButtonText: '确定',
});
} else {
getList();
ElMessage.success('删除成功!');
}
} catch (e) {}
};
//
const delAll = async () => {
handleDelete(multipleSelection.value.map((e) => e.strategyId));
};
//
const toAdd = () => {
i.value++;
isDetail.value = false;
curRow.value = {
strategyId: '',
strategyName: '',
};
visible.value = true;
};
//
const toDetail = async (row: Record<string, any>, detail = false) => {
i.value++;
isDetail.value = detail;
curRow.value = row;
visible.value = true;
};
//
const closeDrawer = (refresh?: number) => {
visible.value = false;
refresh && initList();
};
</script>

@ -0,0 +1,344 @@
<template>
<!-- 贷后评分 -->
<el-table class="c-table"
:data="form"
:span-method="span"
:cell-style="{background:'#fff'}"
border>
<el-table-column prop="recordName"
label="指标"
min-width="80"
align="center"></el-table-column>
<el-table-column prop="recordName"
label="公式/取值"
min-width="200"
align="center">
<template #default="{ row, $index }">
<div class="flex items-center">
<template v-if="$index === 1">
存贷比 =
<div class="inline-flex flex-col justify-center mx-2">
<el-select v-if="row.recordChildren"
class="w-[140px]"
clearable
v-model="row.formulaOne">
<el-option v-for="item in row?.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
<p class="h-[1px] my-2 bg-[#cdcdcd]"></p>
<el-select v-if="row.recordChildren"
class="w-[140px]"
clearable
v-model="row.formulaTwo">
<el-option v-for="item in row?.recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</div>
x 100%
</template>
<template v-if="$index === 6">
房屋净值 =
<el-select v-if="row.recordChildren"
class="w-[140px] mx-2"
clearable
v-model="row.formulaOne">
<el-option v-for="item in row?.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
-
<el-select v-if="row.recordChildren"
class="w-[140px] ml-2"
clearable
v-model="row.formulaTwo">
<el-option v-for="item in row?.recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</template>
<template v-if="$index === 9">
<el-input class="w-[80px] mx-2"
placeholder="请输入"
v-model="row.formulaOne"></el-input>
<el-select v-if="row.recordChildren"
class="w-[140px] mr-2"
clearable
v-model="row.formulaTwo">
<el-option v-for="item in row?.recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
内逾期次数
</template>
<template v-if="$index === 12">
<el-select v-if="row.recordChildren"
class="w-[140px] mx-2"
clearable
v-model="row.formulaOne">
<el-option v-for="item in row?.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
开始算还款当天不计算利息
</template>
<template v-if="$index === 15">当前尚未偿还的贷款总额</template>
<template v-if="$index === 18">
平均额度使用率 =
<div class="inline-flex flex-col justify-center mx-2">
<el-select v-if="row.recordChildren"
class="w-[140px]"
clearable
v-model="row.formulaOne">
<el-option v-for="item in row?.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
<p class="h-[1px] my-2 bg-[#cdcdcd]"></p>
<el-select v-if="row.recordChildren"
class="w-[140px]"
clearable
v-model="row.formulaTwo">
<el-option v-for="item in row?.recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</div>
x 100%
</template>
<template v-if="$index === 22">
最大用信率 =
<div class="inline-flex flex-col justify-center mx-2">
<el-select v-if="row.recordChildren"
class="w-[140px]"
clearable
v-model="row.formulaOne">
<el-option v-for="item in row?.recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
<p class="h-[1px] my-2 bg-[#cdcdcd]"></p>
<el-select v-if="row.recordChildren"
class="w-[140px]"
clearable
v-model="row.formulaTwo">
<el-option v-for="item in row?.recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</div>
x 100%
</template>
<template v-if="$index === 26">到目前为止使用额度的次数</template>
<template v-if="$index === 30">到目前为止客户可以使用的最大额度</template>
<template v-if="$index === 35">客户贷记卡已经逾期的总月数</template>
<template v-if="$index === 37">客户在行所有贷款已经逾期的总月数</template>
</div>
</template>
</el-table-column>
<el-table-column prop="ruleName"
label="取值"
min-width="100"
align="center"></el-table-column>
<el-table-column label="分数"
min-width="80"
align="center">
<template #default="{ row }">
<el-select v-if="row.subject"
clearable
v-model="row.score">
<el-option v-for="item in row.subject.itemList.sort((a, b) => +a.options - +b.options)"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
<span v-else>600</span>
</template>
</el-table-column>
</el-table>
<div class="flex justify-end">
<div class="submit"
@click="submit">确认完成配置</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { postCreditScoreDetails, postCreditScoreSave } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import type { TableColumnCtx } from 'element-plus';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1031);
const result = [
{
recordName: '基准分',
},
];
process.map((e, i) => {
let temp = {
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
formulaOne: '',
formulaTwo: '',
score: '',
id: '',
stRecordId: e.id,
middleId: e.recordChildren[e.recordChildren.length - 1]?.id,
};
//
e.recordChildren[e.recordChildren.length - 1]?.recordChildren?.map((n, j) => {
temp = JSON.parse(JSON.stringify(temp));
temp.index = j;
temp.ruleName = n.name;
temp.subject = n.subject;
temp.ruleId = n.id;
result.push(temp);
});
});
if (info.value.length) {
result.forEach((e, i) => {
if (i) {
e.formulaOne = info.value[i - 1].formulaOne ? +info.value[i - 1].formulaOne : '';
e.indexId = info.value[i - 1].indexId;
e.formulaTwo = info.value[i - 1].formulaTwo ? +info.value[i - 1].formulaTwo : '';
e.score = info.value[i - 1].score ? +info.value[i - 1].score : '';
}
});
}
form.value = result;
console.log('🚀 ~ file: 1031.vue:83 ~ getConfig ~ result:', result);
};
//
const getDetail = async () => {
try {
const { data } = await postCreditScoreDetails();
info.value = data;
getConfig();
} finally {
}
};
interface SpanMethodProps {
row: Record<string, any>;
column: TableColumnCtx<Record<string, any>>;
rowIndex: number;
columnIndex: number;
}
const rowMerge1 = [1, 30];
const rowMerge2 = [6, 9, 12, 15];
const rowMerge3 = [9, 18, 22, 26];
const rowMerge4 = [35, 37];
//
const span = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
if (!rowIndex) {
if (!columnIndex) {
return {
rowspan: 1,
colspan: 3,
};
} else if (columnIndex === 3) {
return {
rowspan: 1,
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
if (columnIndex < 2) {
if (rowMerge1.includes(rowIndex)) {
return {
rowspan: 5,
colspan: 1,
};
} else if (rowMerge2.includes(rowIndex)) {
return {
rowspan: 3,
colspan: 1,
};
} else if (rowMerge3.includes(rowIndex)) {
return {
rowspan: 4,
colspan: 1,
};
} else if (rowMerge4.includes(rowIndex)) {
return {
rowspan: 2,
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
};
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${Cookies.get('sand-level')},42,69,1031`; // 1id
const rule = [];
data.forEach((e, i) => {
e.score && rule.push(handleId(e.ruleId, e.subject.subjectId, e.score, `${preIds},${e.stRecordId},${e.middleId},${e.ruleId}`, 1));
if (i === 1 || i === 6 || i === 18 || i === 22) {
e.formulaOne && rule.push(handleId(1061, 285, e.formulaOne, `${preIds},${e.stRecordId},1061`, 1));
e.formulaTwo && rule.push(handleId(1062, 285, e.formulaTwo, `${preIds},${e.stRecordId},1062`, 1));
}
});
data[9].formulaOne && rule.push(handleId(1075, 288, data[9].formulaOne, `${preIds},1074,1075`, 3));
data[9].formulaTwo && rule.push(handleId(1076, 289, data[9].formulaTwo, `${preIds},1074,1076`, 1));
data[12].formulaOne && rule.push(handleId(1083, 291, data[12].formulaOne, `${preIds},1082,1083`, 1));
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
};
//
const submit = async () => {
let param = JSON.parse(JSON.stringify(form.value));
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await postCreditScoreSave({ postCreditScoreList: param });
addRecord(recordParam);
getDetail();
ElMessage.success('提交成功!');
};
onMounted(() => {
getDetail();
});
</script>
<style lang="scss" scoped>
@import url(../../../styles/form.scss);
</style>

@ -1,336 +0,0 @@
<template>
<!-- 贷后评分 -->
<el-form label-width="90px" label-suffix="" class="form" :disabled="disabled" v-loading="loading">
<el-form-item label="策略名称">
<div>
<el-input class="w-[320px]" placeholder="请输入20以内字符" maxlength="20" clearable v-model="strategyName" />
<p v-if="bankIds.length" class="text-danger">不同步已关联产品请修改策略名称</p>
</div>
</el-form-item>
<el-form-item label="策略规则">
<el-table class="c-table" :data="form" :span-method="span" :cell-style="{ background: '#fff' }" border>
<el-table-column prop="name" label="选用" width="130" align="center">
<template #default="{ row, $index }">
<el-radio-group v-if="$index" v-model="row.isChoose">
<el-radio v-for="(item, i) in opt1" :key="i" :label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
<span v-else>基准分</span>
</template>
</el-table-column>
<el-table-column prop="recordName" label="指标" min-width="80" align="center"></el-table-column>
<el-table-column prop="recordName" label="公式/取值" min-width="200" align="center">
<template #default="{ row, $index }">
<div class="flex items-center">
<template v-if="$index === 1">
存贷比 =
<div class="inline-flex flex-col justify-center mx-2">
<el-select v-if="row.recordChildren" class="w-[140px]" clearable v-model="row.formulaOne" disabled>
<el-option v-for="item in row?.recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
<p class="h-[1px] my-2 bg-[#cdcdcd]"></p>
<el-select v-if="row.recordChildren" class="w-[140px]" clearable v-model="row.formulaTwo" disabled>
<el-option v-for="item in row?.recordChildren[2].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</div>
x 100%
</template>
<template v-if="$index === 6">
房屋净值 =
<el-select v-if="row.recordChildren" class="w-[140px] mx-2" clearable v-model="row.formulaOne" disabled>
<el-option v-for="item in row?.recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
-
<el-select v-if="row.recordChildren" class="w-[140px] ml-2" clearable v-model="row.formulaTwo" disabled>
<el-option v-for="item in row?.recordChildren[2].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</template>
<template v-if="$index === 9">
<el-input class="w-[80px] mx-2" placeholder="请输入" v-model="row.formulaOne" disabled></el-input>
<el-select v-if="row.recordChildren" class="w-[140px] mr-2" clearable v-model="row.formulaTwo" disabled>
<el-option v-for="item in row?.recordChildren[2].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
内逾期次数
</template>
<template v-if="$index === 12">
<el-select v-if="row.recordChildren" class="w-[140px] mx-2" clearable v-model="row.formulaOne" disabled>
<el-option v-for="item in row?.recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
开始算还款当天不计算利息
</template>
<template v-if="$index === 15">当前尚未偿还的贷款总额</template>
<template v-if="$index === 18">
平均额度使用率 =
<div class="inline-flex flex-col justify-center mx-2">
<el-select v-if="row.recordChildren" class="w-[140px]" clearable v-model="row.formulaOne" disabled>
<el-option v-for="item in row?.recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
<p class="h-[1px] my-2 bg-[#cdcdcd]"></p>
<el-select v-if="row.recordChildren" class="w-[140px]" clearable v-model="row.formulaTwo" disabled>
<el-option v-for="item in row?.recordChildren[2].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</div>
x 100%
</template>
<template v-if="$index === 22">
最大用信率 =
<div class="inline-flex flex-col justify-center mx-2">
<el-select v-if="row.recordChildren" class="w-[140px]" clearable v-model="row.formulaOne" disabled>
<el-option v-for="item in row?.recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
<p class="h-[1px] my-2 bg-[#cdcdcd]"></p>
<el-select v-if="row.recordChildren" class="w-[140px]" clearable v-model="row.formulaTwo" disabled>
<el-option v-for="item in row?.recordChildren[2].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</div>
x 100%
</template>
<template v-if="$index === 26">到目前为止使用额度的次数</template>
<template v-if="$index === 30">到目前为止客户可以使用的最大额度</template>
<template v-if="$index === 35">客户贷记卡已经逾期的总月数</template>
<template v-if="$index === 37">客户在行所有贷款已经逾期的总月数</template>
</div>
</template>
</el-table-column>
<el-table-column prop="ruleName" label="取值" min-width="100" align="center"></el-table-column>
<el-table-column label="分数" min-width="80" align="center">
<template #default="{ row }">
<el-select v-if="row.subject" clearable v-model="row.score">
<el-option v-for="item in row.subject.itemList.sort((a, b) => +a.options - +b.options)" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
<span v-else>600</span>
</template>
</el-table-column>
</el-table>
</el-form-item>
<div v-if="!disabled" class="flex justify-end mt-3">
<div class="dia-btn cancel" @click="emit('close')">取消</div>
<div class="dia-btn" @click="confirmSubmit">确定</div>
</div>
</el-form>
<Confirm v-model="syncVisible" @submit="submit" />
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent, onMounted, toRefs } from 'vue';
import { ElMessage } from 'element-plus';
import { postCreditScoreDetails, postCreditScoreSave, isTheStrategyRelatedToTheProduct } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import type { TableColumnCtx } from 'element-plus';
import { handleId, getIds, opt1 } from '@/utils/common';
import Cookies from 'js-cookie';
import { getStat } from '@/store/useProduct';
const Confirm = defineAsyncComponent(() => import('@/components/StrategyConfirm.vue'));
const props = defineProps({
disabled: { type: Boolean, default: false },
row: { type: Object },
});
const emit = defineEmits(['close']);
const { strategyId, strategyName } = toRefs(props.row);
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
//
const answer = [[697, 693], [698, 691], [1, 707], [716], [], [695, 696], [696, 694]];
const loading = ref<boolean>(false);
const syncVisible = ref<boolean>(false);
const bankIds = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1031);
const result = [
{
recordName: '基准分',
},
];
process.slice(1).map((e, i) => {
let temp = {
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
formulaOne: i < 7 ? answer[i][0] || '' : '',
formulaTwo: i < 7 ? answer[i][1] || '' : '',
score: '',
id: '',
stRecordId: e.id,
middleId: e.recordChildren[e.recordChildren.length - 1]?.id,
};
//
e.recordChildren[e.recordChildren.length - 1]?.recordChildren?.map((n, j) => {
temp = JSON.parse(JSON.stringify(temp));
temp.index = j;
temp.ruleName = n.name;
temp.subject = n.subject;
temp.ruleId = n.id;
temp.isChoose = '';
result.push(temp);
});
});
if (info.value.length) {
result.forEach((e, i) => {
if (i) {
e.indexId = info.value[i - 1].indexId;
e.isChoose = info.value[i - 1].isChoose;
e.score = info.value[i - 1].score ? +info.value[i - 1].score : '';
}
});
}
form.value = result;
loading.value = false;
};
//
const getDetail = async () => {
loading.value = true;
try {
if (strategyId.value) {
const { data } = await postCreditScoreDetails({
strategyId: strategyId.value,
});
info.value = data.slice(1);
}
getConfig();
//
if (strategyId.value && !props.disabled) {
const res = await isTheStrategyRelatedToTheProduct({
tacticsId: strategyId.value,
strategyType: 16,
});
if (res.isRelated) bankIds.value = res.bankIds;
}
} finally {
}
};
onMounted(getDetail);
interface SpanMethodProps {
row: Record<string, any>;
column: TableColumnCtx<Record<string, any>>;
rowIndex: number;
columnIndex: number;
}
const rowMerge1 = [1, 30];
const rowMerge2 = [6, 9, 12, 15];
const rowMerge3 = [9, 18, 22, 26];
const rowMerge4 = [35, 37];
//
const span = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
if (!rowIndex) {
if (!columnIndex) {
return {
rowspan: 1,
colspan: 4,
};
}
if (columnIndex === 4) {
return {
rowspan: 1,
colspan: 1,
};
}
return {
rowspan: 0,
colspan: 0,
};
}
if (columnIndex < 3) {
if (rowMerge1.includes(rowIndex)) {
return {
rowspan: 5,
colspan: 1,
};
}
if (rowMerge2.includes(rowIndex)) {
return {
rowspan: 3,
colspan: 1,
};
}
if (rowMerge3.includes(rowIndex)) {
return {
rowspan: 4,
colspan: 1,
};
}
if (rowMerge4.includes(rowIndex)) {
return {
rowspan: 2,
colspan: 1,
};
}
return {
rowspan: 0,
colspan: 0,
};
}
};
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${Cookies.get('sand-level')},42,69,1031`; // 1id
const rule = [handleId(140, 28, strategyName.value, `${preIds},140`, 3)];
data.forEach((e, i) => {
e.isChoose && rule.push(handleId(1052, 140, e.isChoose, `${preIds},${e.stRecordId},1052`, 1));
e.score && rule.push(handleId(e.ruleId, e.subject.subjectId, e.score, `${preIds},${e.stRecordId},${e.middleId},${e.ruleId}`, 1));
if (i === 1 || i === 6 || i === 18 || i === 22) {
e.formulaOne && rule.push(handleId(1061, 285, e.formulaOne, `${preIds},${e.stRecordId},1061`, 1));
e.formulaTwo && rule.push(handleId(1062, 285, e.formulaTwo, `${preIds},${e.stRecordId},1062`, 1));
}
});
data[9].formulaOne && rule.push(handleId(1075, 288, data[9].formulaOne, `${preIds},1074,1075`, 3));
data[9].formulaTwo && rule.push(handleId(1076, 289, data[9].formulaTwo, `${preIds},1074,1076`, 1));
data[12].formulaOne && rule.push(handleId(1083, 291, data[12].formulaOne, `${preIds},1082,1083`, 1));
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
loading.value = false;
ElMessage.success('提交成功!');
syncVisible.value = false;
emit('close', 1);
};
//
const submit = async (synchronizeUpdate?: number) => {
loading.value = true;
try {
const param = JSON.parse(JSON.stringify(form.value));
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await postCreditScoreSave({
...getIds(),
strategyId: strategyId.value,
strategyName: strategyName.value,
synchronizeUpdate,
postCreditScoreList: param,
bankIds: bankIds.value,
});
getStat(295);
addRecord(recordParam);
} catch (e) {
loading.value = false;
}
};
const confirmSubmit = async () => {
if (!strategyName.value) return ElMessage.error('请输入策略名称!');
//
if (bankIds.value.length) {
syncVisible.value = true;
} else {
submit();
}
};
</script>
<style lang="scss" scoped>
@import url(../../../../styles/form.scss);
</style>

@ -1,157 +0,0 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="keyWord" @change="initList"></search>
<div class="filter">
<el-popconfirm title="确定删除选中策略吗?" :disabled="!multipleSelection.length" @confirm.stop="delAll">
<template #reference>
<div :class="['add-btn mr-2', { 'cursor-not-allowed': !multipleSelection.length }]">
<el-icon :size="24" color="#fff">
<Delete />
</el-icon>
批量删除
</div>
</template>
</el-popconfirm>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
新增
</div>
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="handleDisable" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column prop="strategyName" label="贷后评分策略名称" min-width="180" />
<el-table-column prop="createTime" label="新增日期" min-width="140" />
<el-table-column label="操作" width="140">
<template #default="{ row }">
<el-button type="primary" link @click="toDetail(row, true)" size="small">查看</el-button>
<template v-if="!row.builtIn">
<el-button type="primary" link @click="toDetail(row)" size="small">编辑</el-button>
<el-popconfirm title="确定删除这条策略吗?" @confirm.stop="handleDelete([row.strategyId])">
<template #reference>
<el-button type="primary" link size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-drawer v-model="visible" :title="(isDetail ? '查看' : curRow.strategyId ? '编辑' : '新增') + '贷后评分策略'" size="100%" :z-index="10" class="model-drawer">
<Detail v-model:row="curRow" :disabled="isDetail" :key="i" @close="closeDrawer" />
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, defineAsyncComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { pageSizes, pageLayout } from '@/utils/common';
import { postCreditScore, postCreditScoreDel } from '@/api/model';
import Search from '@/components/Search.vue';
const Detail = defineAsyncComponent(() => import('./Detail.vue'));
const keyWord = ref<string>();
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
const table = ref<any>();
const multipleSelection = ref<Record<string, any>[]>([]);
const list = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const visible = ref<boolean>(false);
const curRow = ref<Record<string, any>>({
strategyId: '',
strategyName: '',
});
const isDetail = ref<boolean>(false);
const i = ref<number>(0);
//
const getList = async () => {
loading.value = true;
try {
const { page } = await postCreditScore({ pageNum: currentPage.value, pageSize: pageSize.value, keyWord: keyWord.value });
list.value = page.records;
total.value = page.total;
} finally {
loading.value = false;
}
};
//
const initList = async () => {
currentPage.value = 1;
getList();
};
watch(keyWord, initList);
onMounted(getList);
//
const handleDisable = (row: Record<string, any>) => {
//
if (row.builtIn) return false;
return true;
};
//
const handleSelectionChange = (val: Record<string, any>[]) => {
multipleSelection.value = val;
};
const handleDelete = async (ids: number[]) => {
try {
const res = await postCreditScoreDel({ ids });
//
if (res.tip) {
ElMessageBox.alert(res.message, '提示', {
confirmButtonText: '确定',
});
} else {
getList();
ElMessage.success('删除成功!');
}
} catch (e) {}
};
//
const delAll = async () => {
handleDelete(multipleSelection.value.map((e) => e.strategyId));
};
//
const toAdd = () => {
i.value++;
isDetail.value = false;
curRow.value = {
strategyId: '',
strategyName: '',
};
visible.value = true;
};
//
const toDetail = async (row: Record<string, any>, detail = false) => {
i.value++;
isDetail.value = detail;
curRow.value = row;
visible.value = true;
};
//
const closeDrawer = (refresh?: number) => {
visible.value = false;
refresh && initList();
};
</script>

@ -0,0 +1,130 @@
<template>
<!-- 贷后预警 -->
<el-table class="c-table"
:data="form"
:cell-style="{background:'#fff'}"
border>
<el-table-column label="选用"
width="80"
align="center">
<template #default="{ row }">
<el-checkbox v-model="row.isChoose"></el-checkbox>
</template>
</el-table-column>
<el-table-column prop="recordName"
label="风险类型"
align="center"></el-table-column>
<el-table-column label="风险等级"
align="center">
<template #default="{ row }">
<div class="flex">
<el-select v-if="row.recordChildren"
class="mr-2"
clearable
v-model="row.riskGradeType">
<el-option v-for="item in row?.recordChildren[1].recordChildren[0].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
<el-select v-if="row.recordChildren"
clearable
v-model="row.riskGrade">
<el-option v-for="item in row?.recordChildren[1].recordChildren[1].subject.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</div>
</template></el-table-column>
</el-table>
<div class="flex justify-end">
<div class="submit"
@click="submit">确认完成配置</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage } from 'element-plus';
import { postLoanWarningDetails, postLoanWarningSave } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1032);
const result = [];
process.map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
result.push({
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
riskGrade: +cur.riskGrade || '',
riskGradeType: +cur.riskGradeType || '',
isChoose: info.value.length ? !!cur.isChoose : false,
id: cur.id || '',
stRecordId: e.id,
});
});
form.value = result;
};
//
const getDetail = async () => {
try {
const { data } = await postLoanWarningDetails();
info.value = data;
getConfig();
} finally {
}
};
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${levelId},42,69,1032`; // 1id
const rule = [];
data.map((e) => {
e.isChoose && rule.push(handleId(1052, '', '', `${preIds},${e.stRecordId},1052`, ''));
e.riskGradeType && rule.push(handleId(1147, 299, e.riskGradeType, `${preIds},${e.stRecordId},1146,1147`, 1));
e.riskGrade && rule.push(handleId(1148, 300, e.riskGrade, `${preIds},${e.stRecordId},1146,1148`, 1));
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
};
//
const submit = async () => {
let param = JSON.parse(JSON.stringify(form.value));
param.forEach((e) => {
e.isChoose = +e.isChoose;
});
const recordParam = JSON.parse(JSON.stringify(param));
param.forEach((e) => {
delete e.recordChildren;
});
await postLoanWarningSave({ postLoanWarningList: param });
addRecord(recordParam);
getDetail();
ElMessage.success('提交成功!');
};
onMounted(() => {
getDetail();
});
</script>
<style lang="scss" scoped>
@import url(../../../styles/form.scss);
</style>

@ -1,169 +0,0 @@
<template>
<!-- 贷后预警 -->
<el-form label-width="90px" label-suffix="" class="form" :disabled="disabled" v-loading="loading">
<el-form-item label="策略名称">
<div>
<el-input class="w-[320px]" placeholder="请输入20以内字符" maxlength="20" clearable v-model="strategyName" />
<p v-if="bankIds.length" class="text-danger">不同步已关联产品请修改策略名称</p>
</div>
</el-form-item>
<el-form-item label="策略规则">
<el-table class="c-table" :data="form" :cell-style="{ background: '#fff' }" border>
<el-table-column label="选用" width="130" align="center">
<template #default="{ row }">
<el-radio-group v-model="row.isChoose">
<el-radio v-for="(item, i) in opt1" :key="i" :label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</template>
</el-table-column>
<el-table-column prop="recordName" label="风险类型" align="center"></el-table-column>
<el-table-column label="风险等级" align="center">
<template #default="{ row }">
<div class="flex">
<el-select v-if="row.recordChildren" class="mr-2" clearable v-model="row.riskGradeType">
<el-option v-for="item in row?.recordChildren[1].recordChildren[0].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
<el-select v-if="row.recordChildren" clearable v-model="row.riskGrade">
<el-option v-for="item in row?.recordChildren[1].recordChildren[1].subject.itemList" :key="item" :label="item.options" :value="item.itemId" />
</el-select>
</div> </template
></el-table-column>
</el-table>
</el-form-item>
<div v-if="!disabled" class="flex justify-end mt-3">
<div class="dia-btn cancel" @click="emit('close')">取消</div>
<div class="dia-btn" @click="confirmSubmit">确定</div>
</div>
</el-form>
<Confirm v-model="syncVisible" @submit="submit" />
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent, onMounted, toRefs } from 'vue';
import { ElMessage } from 'element-plus';
import { postLoanWarningDetails, postLoanWarningSave, isTheStrategyRelatedToTheProduct } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { handleId, getIds, opt1 } from '@/utils/common';
import Cookies from 'js-cookie';
import { getStat } from '@/store/useProduct';
const Confirm = defineAsyncComponent(() => import('@/components/StrategyConfirm.vue'));
const props = defineProps({
disabled: { type: Boolean, default: false },
row: { type: Object },
});
const emit = defineEmits(['close']);
const { strategyId, strategyName } = toRefs(props.row);
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const syncVisible = ref<boolean>(false);
const bankIds = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1032);
const result = [];
process.slice(1).map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
result.push({
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
riskGrade: +cur.riskGrade || '',
riskGradeType: +cur.riskGradeType || '',
isChoose: info.value.length ? cur.isChoose : '',
id: cur.id || '',
stRecordId: e.id,
});
});
form.value = result;
loading.value = false;
};
//
const getDetail = async () => {
loading.value = true;
try {
if (strategyId.value) {
const { data } = await postLoanWarningDetails({
strategyId: strategyId.value,
});
info.value = data;
}
getConfig();
//
if (strategyId.value && !props.disabled) {
const res = await isTheStrategyRelatedToTheProduct({
tacticsId: strategyId.value,
strategyType: 17,
});
if (res.isRelated) bankIds.value = res.bankIds;
}
} finally {
}
};
onMounted(getDetail);
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${Cookies.get('sand-level')},42,69,1032`; // 1id
const rule = [handleId(140, 28, strategyName.value, `${preIds},140`, 3)];
data.map((e) => {
e.isChoose && rule.push(handleId(1052, 140, e.isChoose, `${preIds},${e.stRecordId},1052`, 1));
e.riskGradeType && rule.push(handleId(1147, 299, e.riskGradeType, `${preIds},${e.stRecordId},1146,1147`, 1));
e.riskGrade && rule.push(handleId(1148, 300, e.riskGrade, `${preIds},${e.stRecordId},1146,1148`, 1));
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
loading.value = false;
ElMessage.success('提交成功!');
syncVisible.value = false;
emit('close', 1);
};
//
const submit = async (synchronizeUpdate?: number) => {
loading.value = true;
try {
const param = JSON.parse(JSON.stringify(form.value));
param.forEach((e) => {
delete e.recordChildren;
});
await postLoanWarningSave({
...getIds(),
strategyId: strategyId.value,
strategyName: strategyName.value,
synchronizeUpdate,
postLoanWarningList: param,
bankIds: bankIds.value,
});
getStat(295);
addRecord(param);
} catch (e) {
loading.value = false;
}
};
const confirmSubmit = async () => {
if (!strategyName.value) return ElMessage.error('请输入策略名称!');
//
if (bankIds.value.length) {
syncVisible.value = true;
} else {
submit();
}
};
</script>
<style lang="scss" scoped>
@import url(../../../../styles/form.scss);
</style>

@ -1,157 +0,0 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="keyWord" @change="initList"></search>
<div class="filter">
<el-popconfirm title="确定删除选中策略吗?" :disabled="!multipleSelection.length" @confirm.stop="delAll">
<template #reference>
<div :class="['add-btn mr-2', { 'cursor-not-allowed': !multipleSelection.length }]">
<el-icon :size="24" color="#fff">
<Delete />
</el-icon>
批量删除
</div>
</template>
</el-popconfirm>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
新增
</div>
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="handleDisable" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column prop="strategyName" label="贷后预警策略名称" min-width="180" />
<el-table-column prop="createTime" label="新增日期" min-width="140" />
<el-table-column label="操作" width="140">
<template #default="{ row }">
<el-button type="primary" link @click="toDetail(row, true)" size="small">查看</el-button>
<template v-if="!row.builtIn">
<el-button type="primary" link @click="toDetail(row)" size="small">编辑</el-button>
<el-popconfirm title="确定删除这条策略吗?" @confirm.stop="handleDelete([row.strategyId])">
<template #reference>
<el-button type="primary" link size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-drawer v-model="visible" :title="(isDetail ? '查看' : curRow.strategyId ? '编辑' : '新增') + '贷后预警策略'" size="100%" :z-index="10" class="model-drawer">
<Detail v-model:row="curRow" :disabled="isDetail" :key="i" @close="closeDrawer" />
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, defineAsyncComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { pageSizes, pageLayout } from '@/utils/common';
import { postLoanWarning, postLoanWarningDel } from '@/api/model';
import Search from '@/components/Search.vue';
const Detail = defineAsyncComponent(() => import('./Detail.vue'));
const keyWord = ref<string>();
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
const table = ref<any>();
const multipleSelection = ref<Record<string, any>[]>([]);
const list = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const visible = ref<boolean>(false);
const curRow = ref<Record<string, any>>({
strategyId: '',
strategyName: '',
});
const isDetail = ref<boolean>(false);
const i = ref<number>(0);
//
const getList = async () => {
loading.value = true;
try {
const { page } = await postLoanWarning({ pageNum: currentPage.value, pageSize: pageSize.value, keyWord: keyWord.value });
list.value = page.records;
total.value = page.total;
} finally {
loading.value = false;
}
};
//
const initList = async () => {
currentPage.value = 1;
getList();
};
watch(keyWord, initList);
onMounted(getList);
//
const handleDisable = (row: Record<string, any>) => {
//
if (row.builtIn) return false;
return true;
};
//
const handleSelectionChange = (val: Record<string, any>[]) => {
multipleSelection.value = val;
};
const handleDelete = async (ids: number[]) => {
try {
const res = await postLoanWarningDel({ ids });
//
if (res.tip) {
ElMessageBox.alert(res.message, '提示', {
confirmButtonText: '确定',
});
} else {
getList();
ElMessage.success('删除成功!');
}
} catch (e) {}
};
//
const delAll = async () => {
handleDelete(multipleSelection.value.map((e) => e.strategyId));
};
//
const toAdd = () => {
i.value++;
isDetail.value = false;
curRow.value = {
strategyId: '',
strategyName: '',
};
visible.value = true;
};
//
const toDetail = async (row: Record<string, any>, detail = false) => {
i.value++;
isDetail.value = detail;
curRow.value = row;
visible.value = true;
};
//
const closeDrawer = (refresh?: number) => {
visible.value = false;
refresh && initList();
};
</script>

@ -0,0 +1,195 @@
<template>
<!-- 贷后催收 -->
<el-table class="c-table"
:data="form"
:span-method="span"
:cell-style="{background:'#fff'}"
border>
<el-table-column prop="recordName"
label="逾期时长"
width="150"
align="center">
</el-table-column>
<el-table-column label="选择催收方式"
width="440"
align="center">
<template #default="{ row }">
<el-checkbox v-model="row.shortMessageCollection">短信催收</el-checkbox>
<el-checkbox v-model="row.appCollection">APP催收</el-checkbox>
<el-checkbox v-model="row.automaticOutboundCall">自动外呼</el-checkbox>
<el-checkbox v-model="row.manualCollection">人工催收</el-checkbox>
</template>
</el-table-column>
<el-table-column label="短信/APP/自动外呼 话术"
min-width="310"
align="center">
<template #default="{ row }">
<p v-if="row.recordChildren && row.verbalTrick">{{ row?.recordChildren[0]?.subject?.itemList.find(e => e.itemId === row.verbalTrick)?.options }}</p>
<el-button type="primary"
:icon="Plus"
@click="showDia(row)">选择</el-button>
<!-- <el-select v-if="row.recordChildren"
class="w-full type-select"
v-model="row.verbalTrick">
<el-option v-for="item in row?.recordChildren[0]?.subject?.itemList"
:key="item"
:label="item.options"
:value="item.itemId">
<span>{{ item.options }}</span>
</el-option>
</el-select> -->
</template></el-table-column>
</el-table>
<div class="flex justify-end">
<div class="submit"
@click="submit">确认完成配置</div>
</div>
<el-dialog v-model="selectDia"
custom-class="select-dia">
<div class="selects"
v-if="curRow.recordChildren">
<div v-for="item in
curRow?.recordChildren[0]?.subject?.itemList"
:key="item"
class="line"
@click="curRow.verbalTrick = item.itemId">
<el-radio v-model="curRow.verbalTrick"
:label="item.itemId"></el-radio>
<span>{{ item.options }}</span>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary"
@click="selectDia = false">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { collectionAfterLoanDetails, collectionAfterLoanSave } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
const curRow = ref<Record<string, any>>({});
const selectDia = ref<boolean>(false);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1033);
const result = [];
process[0].recordChildren.map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
result.push({
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
appCollection: info.value.length ? !!cur.appCollection : false,
automaticOutboundCall: info.value.length ? !!cur.automaticOutboundCall : false,
shortMessageCollection: info.value.length ? !!cur.shortMessageCollection : false,
manualCollection: info.value.length ? !!cur.manualCollection : false,
verbalTrick: cur.verbalTrick ? +cur.verbalTrick : '',
id: cur.id || '',
stRecordId: e.id,
});
});
form.value = result;
console.log('🚀 ~ getConfig ~ result:', result);
};
//
const getDetail = async () => {
try {
const { data } = await collectionAfterLoanDetails();
info.value = data;
getConfig();
} finally {
}
};
//
const showDia = (row: Record<string, any>) => {
selectDia.value = true;
curRow.value = row;
};
//
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${levelId},42,69,1033,1149`; // 1id
const rule = [];
data.map((e) => {
e.recordChildren.forEach((n, i) => {
if (i) {
const ids = [];
e.shortMessageCollection && ids.push(774);
e.appCollection && ids.push(775);
e.automaticOutboundCall && ids.push(776);
e.manualCollection && ids.push(777);
ids.length && rule.push(handleId(n.id, n.subjectId, ids.join(), `${preIds},${e.stRecordId},${n.id}`, 1));
} else {
e.verbalTrick && rule.push(handleId(n.id, n.subjectId, e.verbalTrick, `${preIds},${e.stRecordId},${n.id}`, 1));
}
});
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
};
//
const submit = async () => {
let param = JSON.parse(JSON.stringify(form.value));
param.map((e) => {
e.appCollection = +e.appCollection;
e.automaticOutboundCall = +e.automaticOutboundCall;
e.shortMessageCollection = +e.shortMessageCollection;
e.manualCollection = +e.manualCollection;
});
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await collectionAfterLoanSave({ collectionAfterLoanList: param });
addRecord(recordParam);
getDetail();
ElMessage.success('提交成功!');
};
onMounted(() => {
getDetail();
});
</script>
<style lang="scss" scoped>
@import url(../../../styles/form.scss);
.select-dia {
.selects {
margin-top: 20px;
}
.line {
display: flex;
align-items: flex-start;
margin-bottom: 10px;
cursor: pointer;
}
background-color: #fff;
.el-radio {
height: 20px;
margin-right: 10px;
:deep(.el-radio__label) {
display: none;
}
}
}
</style>

@ -1,229 +0,0 @@
<template>
<!-- 贷后催收 -->
<el-form label-width="90px" label-suffix="" class="form" :disabled="disabled">
<el-form-item label="策略名称">
<div>
<el-input class="w-[320px]" placeholder="请输入20以内字符" maxlength="20" clearable v-model="strategyName" />
<p v-if="bankIds.length" class="text-danger">不同步已关联产品请修改策略名称</p>
</div>
</el-form-item>
<el-form-item label="策略规则">
<el-table class="c-table" :data="form" :span-method="span" :cell-style="{ background: '#fff' }" border>
<el-table-column prop="name" label="选用" width="130" align="center">
<template #default="{ row }">
<el-radio-group v-model="row.isChoose">
<el-radio v-for="(item, i) in opt1" :key="i" :label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</template>
</el-table-column>
<el-table-column prop="recordName" label="逾期时长" width="150" align="center"> </el-table-column>
<el-table-column label="选择催收方式" width="440" align="center">
<template #default="{ row }">
<el-checkbox v-model="row.shortMessageCollection">短信催收</el-checkbox>
<el-checkbox v-model="row.appCollection">APP催收</el-checkbox>
<el-checkbox v-model="row.automaticOutboundCall">自动外呼</el-checkbox>
<el-checkbox v-model="row.manualCollection">人工催收</el-checkbox>
</template>
</el-table-column>
<el-table-column label="短信/APP/自动外呼 话术" min-width="310" align="center">
<template #default="{ row }">
<p v-if="row.recordChildren && row.verbalTrick">{{ row?.recordChildren[1]?.subject?.itemList.find((e) => e.itemId === row.verbalTrick)?.options }}</p>
<el-button type="primary" :icon="Plus" @click="showDia(row)">选择</el-button>
</template></el-table-column
>
</el-table>
</el-form-item>
</el-form>
<div v-if="!disabled" class="flex justify-end mt-3">
<div class="dia-btn cancel" @click="emit('close')">取消</div>
<div class="dia-btn" @click="confirmSubmit">确定</div>
</div>
<Confirm v-model="syncVisible" @submit="submit" />
<el-dialog v-model="selectDia" custom-class="select-dia">
<div class="selects" v-if="curRow.recordChildren">
<div v-for="item in curRow?.recordChildren[1]?.subject?.itemList" :key="item" class="line" @click="curRow.verbalTrick = item.itemId">
<el-radio v-model="curRow.verbalTrick" :label="item.itemId"></el-radio>
<span>{{ item.options }}</span>
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="selectDia = false">关闭</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, defineAsyncComponent, onMounted, toRefs } from 'vue';
import { Plus } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { collectionAfterLoanDetails, collectionAfterLoanSave, isTheStrategyRelatedToTheProduct } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { handleId, getIds, opt1 } from '@/utils/common';
import Cookies from 'js-cookie';
import { getStat } from '@/store/useProduct';
const Confirm = defineAsyncComponent(() => import('@/components/StrategyConfirm.vue'));
const props = defineProps({
disabled: { type: Boolean, default: false },
row: { type: Object },
});
const emit = defineEmits(['close']);
const { strategyId, strategyName } = toRefs(props.row);
const form = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
const curRow = ref<Record<string, any>>({});
const selectDia = ref<boolean>(false);
const syncVisible = ref<boolean>(false);
const bankIds = ref<Record<string, any>[]>([]);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(1033);
const result = [];
process[1].recordChildren.map((e, i) => {
const cur = info.value.length ? info.value[i] : {};
result.push({
...getIds(),
recordName: e.name,
recordChildren: e.recordChildren,
isChoose: info.value.length ? cur.isChoose : '',
appCollection: info.value.length ? !!cur.appCollection : false,
automaticOutboundCall: info.value.length ? !!cur.automaticOutboundCall : false,
shortMessageCollection: info.value.length ? !!cur.shortMessageCollection : false,
manualCollection: info.value.length ? !!cur.manualCollection : false,
verbalTrick: cur.verbalTrick ? +cur.verbalTrick : '',
id: cur.id || '',
stRecordId: e.id,
});
});
form.value = result;
};
//
const getDetail = async () => {
try {
if (strategyId.value) {
const { data } = await collectionAfterLoanDetails({
strategyId: strategyId.value,
});
info.value = data;
}
getConfig();
//
if (strategyId.value && !props.disabled) {
const res = await isTheStrategyRelatedToTheProduct({
tacticsId: strategyId.value,
strategyType: 18,
});
if (res.isRelated) bankIds.value = res.bankIds;
}
} finally {
}
};
onMounted(getDetail);
//
const showDia = (row: Record<string, any>) => {
selectDia.value = true;
curRow.value = row;
};
//
const addRecord = async (data: Record<string, any>) => {
let preIds = `1,${Cookies.get('sand-level')},42,69,1033`; // 1id
const rule = [handleId(140, 28, strategyName.value, `${preIds},140`, 3)];
preIds += ',1149';
data.map((e) => {
e.recordChildren.forEach((n, i) => {
if (i === 2) {
//
const ids = [];
e.shortMessageCollection && ids.push(774);
e.appCollection && ids.push(775);
e.automaticOutboundCall && ids.push(776);
e.manualCollection && ids.push(777);
ids.length && rule.push(handleId(n.id, n.subjectId, ids.join(), `${preIds},${e.stRecordId},${n.id}`, 1));
} else if (i === 1) {
//
e.verbalTrick && rule.push(handleId(n.id, n.subjectId, e.verbalTrick, `${preIds},${e.stRecordId},${n.id}`, 1));
} else {
//
e.isChoose && rule.push(handleId(1052, 140, e.isChoose, `${preIds},${e.stRecordId},1052`, 1));
}
});
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
ElMessage.success('提交成功!');
syncVisible.value = false;
emit('close', 1);
};
//
const submit = async (synchronizeUpdate?: number) => {
try {
const param = JSON.parse(JSON.stringify(form.value));
param.map((e) => {
e.appCollection = +e.appCollection;
e.automaticOutboundCall = +e.automaticOutboundCall;
e.shortMessageCollection = +e.shortMessageCollection;
e.manualCollection = +e.manualCollection;
});
const recordParam = JSON.parse(JSON.stringify(param));
param.map((e) => {
delete e.recordChildren;
});
await collectionAfterLoanSave({
...getIds(),
strategyId: strategyId.value,
strategyName: strategyName.value,
synchronizeUpdate,
collectionAfterLoanList: param,
bankIds: bankIds.value,
});
getStat(295);
addRecord(recordParam);
} catch (e) {}
};
const confirmSubmit = async () => {
if (!strategyName.value) return ElMessage.error('请输入策略名称!');
//
if (bankIds.value.length) {
syncVisible.value = true;
} else {
submit();
}
};
</script>
<style lang="scss" scoped>
@import url(../../../../styles/form.scss);
.select-dia {
.selects {
margin-top: 20px;
}
.line {
display: flex;
align-items: flex-start;
margin-bottom: 10px;
cursor: pointer;
}
background-color: #fff;
.el-radio {
height: 20px;
margin-right: 10px;
:deep(.el-radio__label) {
display: none;
}
}
}
</style>

@ -1,157 +0,0 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="keyWord" @change="initList"></search>
<div class="filter">
<el-popconfirm title="确定删除选中策略吗?" :disabled="!multipleSelection.length" @confirm.stop="delAll">
<template #reference>
<div :class="['add-btn mr-2', { 'cursor-not-allowed': !multipleSelection.length }]">
<el-icon :size="24" color="#fff">
<Delete />
</el-icon>
批量删除
</div>
</template>
</el-popconfirm>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
新增
</div>
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="handleDisable" />
<el-table-column label="序号" type="index" width="60" align="center" />
<el-table-column prop="strategyName" label="贷后催收策略名称" min-width="180" />
<el-table-column prop="createTime" label="新增日期" min-width="140" />
<el-table-column label="操作" width="140">
<template #default="{ row }">
<el-button type="primary" link @click="toDetail(row, true)" size="small">查看</el-button>
<template v-if="!row.builtIn">
<el-button type="primary" link @click="toDetail(row)" size="small">编辑</el-button>
<el-popconfirm title="确定删除这条策略吗?" @confirm.stop="handleDelete([row.strategyId])">
<template #reference>
<el-button type="primary" link size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</template>
</el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-drawer v-model="visible" :title="(isDetail ? '查看' : curRow.strategyId ? '编辑' : '新增') + '贷后催收策略'" size="100%" :z-index="10" class="model-drawer">
<Detail v-model:row="curRow" :disabled="isDetail" :key="i" @close="closeDrawer" />
</el-drawer>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, watch, defineAsyncComponent } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Delete } from '@element-plus/icons-vue';
import { pageSizes, pageLayout } from '@/utils/common';
import { collectionAfterLoan, collectionAfterLoanDel } from '@/api/model';
import Search from '@/components/Search.vue';
const Detail = defineAsyncComponent(() => import('./Detail.vue'));
const keyWord = ref<string>();
const currentPage = ref<number>(1);
const pageSize = ref<number>(10);
const total = ref<number>(0);
const table = ref<any>();
const multipleSelection = ref<Record<string, any>[]>([]);
const list = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
const visible = ref<boolean>(false);
const curRow = ref<Record<string, any>>({
strategyId: '',
strategyName: '',
});
const isDetail = ref<boolean>(false);
const i = ref<number>(0);
//
const getList = async () => {
loading.value = true;
try {
const { page } = await collectionAfterLoan({ pageNum: currentPage.value, pageSize: pageSize.value, keyWord: keyWord.value });
list.value = page.records;
total.value = page.total;
} finally {
loading.value = false;
}
};
//
const initList = async () => {
currentPage.value = 1;
getList();
};
watch(keyWord, initList);
onMounted(getList);
//
const handleDisable = (row: Record<string, any>) => {
//
if (row.builtIn) return false;
return true;
};
//
const handleSelectionChange = (val: Record<string, any>[]) => {
multipleSelection.value = val;
};
const handleDelete = async (ids: number[]) => {
try {
const res = await collectionAfterLoanDel({ ids });
//
if (res.tip) {
ElMessageBox.alert(res.message, '提示', {
confirmButtonText: '确定',
});
} else {
getList();
ElMessage.success('删除成功!');
}
} catch (e) {}
};
//
const delAll = async () => {
handleDelete(multipleSelection.value.map((e) => e.strategyId));
};
//
const toAdd = () => {
i.value++;
isDetail.value = false;
curRow.value = {
strategyId: '',
strategyName: '',
};
visible.value = true;
};
//
const toDetail = async (row: Record<string, any>, detail = false) => {
i.value++;
isDetail.value = detail;
curRow.value = row;
visible.value = true;
};
//
const closeDrawer = (refresh?: number) => {
visible.value = false;
refresh && initList();
};
</script>

@ -1,71 +1,64 @@
<template>
<div v-if="list.length">
<div class="menu-card">
<el-menu class="left" :default-active="curMenu" @select="handleSelect">
<el-menu-item v-for="(item, i) in list" :key="i" :index="String(item.id)">{{ item.name }}</el-menu-item>
</el-menu>
<div class="right">
<component v-if="loadedComponents[activeComponent]" :is="loadedComponents[activeComponent]" />
</div>
<div class="block card-list flex py-0">
<div class="left">
<ul class="products">
<li v-for="(item, i) in list"
:key="i"
:class="{ active: item.id === id }"
@click="switchProduct(item.id)">
<h6>{{ item.name }}</h6>
<p class="meta">{{ item.remark }}</p>
</li>
</ul>
</div>
<div class="right">
<Com1 v-if="id == 1029" />
<Com2 v-else-if="id == 1030" />
<Com3 v-else-if="id == 1031" />
<Com4 v-else-if="id == 1032" />
<Com5 v-else-if="id == 1033" />
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, defineAsyncComponent, markRaw } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { getProcessInformationBasedOnRoles } from '@/api/judgment';
import { useRouter, useRoute } from 'vue-router';
import Cookies from 'js-cookie';
import Com1 from './1029.vue';
import Com2 from './1030.vue';
import Com3 from './1031.vue';
import Com4 from './1032.vue';
import Com5 from './1033.vue';
const router = useRouter();
const route = useRoute();
const projectId = +Cookies.get('sand-projectId');
const levelId = +Cookies.get('sand-level');
const list = ref<Array<Record<string, any>>>([]);
const curMenu = computed({
get() {
return route.query.id;
},
set() {},
});
const id = computed(() => +route.query.id);
const asyncComponents = {
'1029': defineAsyncComponent(() => import('./1029/Index.vue')),
'1030': defineAsyncComponent(() => import('./1030/Index.vue')),
'1031': defineAsyncComponent(() => import('./1031/Index.vue')),
'1032': defineAsyncComponent(() => import('./1032/Index.vue')),
'1033': defineAsyncComponent(() => import('./1033/Index.vue')),
};
const loadedComponents = markRaw({});
const activeComponent = ref<string>('');
//
const loadComponent = async (componentName: string) => {
if (!loadedComponents[componentName]) {
try {
loadedComponents[componentName] = asyncComponents[componentName];
activeComponent.value = componentName;
} catch (error) {
console.error(`Failed to load component ${componentName}`, error);
}
} else {
activeComponent.value = componentName;
}
};
const handleSelect = async (key: string) => {
curMenu.value = key;
await loadComponent(key);
router.push(`/product/afterLoan?i=${route.query.i}&role=${route.query.role}&id=${key}`);
//
const switchProduct = (productId: number | string) => {
router.push(`/product/afterLoan?i=4&role=42&id=${productId}`);
};
//
const getList = async () => {
const getList = async (refresh?: number) => {
const { process } = await getProcessInformationBasedOnRoles(69);
// eslint-disable-next-line no-unused-expressions
!id.value && switchProduct(process[0].id);
list.value = process;
handleSelect(curMenu.value || process[0].recordChildren[0].id);
};
onMounted(getList);
onMounted(() => {
getList();
});
</script>
<style lang="scss" scoped>
.left {
@apply w-[200px];
.card-list {
.left {
@apply max-h-[calc(100vh-120px)];
}
}
</style>

@ -1,46 +1,61 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane :label="id ? '配置要素' : '新增产品'" name="tab1">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-suffix="" class="form" status-icon>
<el-tabs v-model="curTab"
@tab-click="tabChange">
<el-tab-pane :label="id ? '配置要素' : '新增产品'"
name="tab1">
<el-form ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
label-suffix=":"
class="form"
status-icon>
<div class="h-[calc(100vh-230px)] pr-1 overflow-auto">
<el-form-item label="产品定义" prop="productDefinition">
<el-input
type="textarea"
placeholder="用一段话简单介绍一下这个产品或者描述产品的设计理念。例如:本产品根据个人客户的信用状况,为其提供的一种短期融资便利产品,借款人可在额度金额内可循环周转使用贷款。"
maxlength="200"
v-model="form.productDefinition"
></el-input>
<el-form-item label="产品定义"
prop="productDefinition">
<el-input type="textarea"
placeholder="用一段话简单介绍一下这个产品或者描述产品的设计理念。例如:本产品根据个人客户的信用状况,为其提供的一种短期融资便利产品,借款人可在额度金额内可循环周转使用贷款。"
maxlength="200"
v-model="form.productDefinition"></el-input>
</el-form-item>
<el-form-item label="产品名称" prop="productName">
<el-input placeholder="取个有吸引力的产品名,限20字。" maxlength="20" v-model="form.productName"></el-input>
<el-form-item label="产品名称"
prop="productName">
<el-input placeholder="取个有吸引力的产品名,限20字。"
maxlength="20"
v-model="form.productName"></el-input>
</el-form-item>
<el-form-item label="产品币种" prop="productCurrency">
<el-select v-model="form.productCurrency" placeholder="请选择">
<el-option label="人民币" :value="1" />
<el-form-item label="产品币种"
prop="productCurrency">
<el-select v-model="form.productCurrency"
placeholder="请选择">
<el-option label="人民币"
:value="1" />
</el-select>
</el-form-item>
<el-form-item label="贷款对象" required>
<el-form-item label="贷款对象"
required>
<div class="flex-1">
<!-- 企业 -->
<template v-if="productType">
<template v-if="form.productType">
<div class="flex items-center">
<span class="mr-3 text-[#333] text-sm">企业类型</span>
<el-select v-model="form.productObject" placeholder="请选择">
<el-option
v-for="(item, i) in config.find((e) => e.name === '企业产品-贷款对象')?.recordChildren[0]?.subject?.itemList"
:key="i"
:label="item.options"
:value="item.itemId"
/>
<el-select v-model="form.productObject"
placeholder="请选择">
<el-option v-for="(item, i) in config.find((e) => e.name === '企业产品-贷款对象')?.recordChildren[0]?.subject?.itemList"
:key="i"
:label="item.options"
:value="item.itemId" />
</el-select>
</div>
<div class="flex items-center mt-4">
<span class="mr-3 text-[#333] text-sm">借款人年龄</span>
<div class="num-inputs ml-7">
<el-input placeholder="最小年龄" v-model.number="form.minimumAge"></el-input>
<el-input placeholder="最小年龄"
v-model.number="form.minimumAge"></el-input>
<span class="split">-</span>
<el-input placeholder="最大年龄" v-model.number="form.maximumAge"></el-input>
<el-input placeholder="最大年龄"
v-model.number="form.maximumAge"></el-input>
<span class="unit">周岁</span>
</div>
</div>
@ -53,14 +68,19 @@
<span class="label">1年龄</span>
<span class="whether">是否启用</span>
<el-radio-group v-model="form.ageSelectedState">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<div v-if="form.ageSelectedState === 795" class="num-inputs ml-7">
<el-input placeholder="最小年龄" v-model.number="form.minimumAge"></el-input>
<div v-if="form.ageSelectedState === 795"
class="num-inputs ml-7">
<el-input placeholder="最小年龄"
v-model.number="form.minimumAge"></el-input>
<span class="split">-</span>
<el-input placeholder="最大年龄" v-model.number="form.maximumAge"></el-input>
<el-input placeholder="最大年龄"
v-model.number="form.maximumAge"></el-input>
</div>
</div>
<div class="flex items-center h-[47px] mb-2">
@ -68,17 +88,18 @@
<span class="label">2学历要求</span>
<span class="whether">是否启用</span>
<el-radio-group v-model="form.degreeSelectedStatus">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<el-checkbox-group v-if="form.degreeSelectedStatus === 795" class="mt-2 ml-5" v-model="form.educationalRequirements">
<el-checkbox
v-for="(item, i) in config.find((e) => e.name === '个人产品-贷款对象')?.recordChildren[1]?.recordChildren[1]?.subject?.itemList"
:key="i"
:label="item.itemId"
>{{ item.options }}</el-checkbox
>
<el-checkbox-group v-if="form.degreeSelectedStatus === 795"
class="mt-2 ml-5"
v-model="form.educationalRequirements">
<el-checkbox v-for="(item, i) in config.find((e) => e.name === '个人产品-贷款对象')?.recordChildren[1]?.recordChildren[1]?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-checkbox>
</el-checkbox-group>
</div>
@ -87,17 +108,18 @@
<span class="label">3工作年限</span>
<span class="whether">是否启用</span>
<el-radio-group v-model="form.workingLifeSelectedState">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<el-checkbox-group v-if="form.workingLifeSelectedState === 795" class="mt-2 ml-5" v-model="form.currentWorkingLife">
<el-checkbox
v-for="(item, i) in config.find((e) => e.name === '个人产品-贷款对象')?.recordChildren[2]?.recordChildren[1]?.subject?.itemList"
:key="i"
:label="item.itemId"
>{{ item.options }}</el-checkbox
>
<el-checkbox-group v-if="form.workingLifeSelectedState === 795"
class="mt-2 ml-5"
v-model="form.currentWorkingLife">
<el-checkbox v-for="(item, i) in config.find((e) => e.name === '个人产品-贷款对象')?.recordChildren[2]?.recordChildren[1]?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-checkbox>
</el-checkbox-group>
</div>
@ -105,152 +127,179 @@
<span class="label">4公积金/社保</span>
<span class="whether">是否启用</span>
<el-radio-group v-model="form.providentFundAndSocialSecurity">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
</template>
</div>
</el-form-item>
<el-form-item
label="贷款用途"
prop="loanPurpose"
:rules="[
{ required: true, message: '请选择贷款用途', trigger: 'change' },
{
asyncValidator: async (rule, value, callback) => {
if (value === 107 && !form.otherPurposesOfLoan) {
callback('请输入其他贷款用途');
} else {
callback();
}
},
<el-form-item label="贷款用途"
prop="loanPurpose"
:rules="[
{ required: true, message: '请选择贷款用途', trigger: 'change' },
{
asyncValidator: async (rule, value, callback) => {
if (value === 107 && !form.otherPurposesOfLoan) {
callback('请输入其他贷款用途')
} else {
callback()
}
},
]"
>
},
]">
<div class="flex-1">
<p class="field-name">选择本产品贷款资金的用途</p>
<el-radio-group v-model="form.loanPurpose">
<template v-if="productType">
<el-radio v-for="(item, i) in config.find((e) => e.name === '企业产品-贷款用途')?.subject?.itemList" :key="i" :label="item.itemId">{{ item.options }}</el-radio>
<template v-if="form.productType">
<el-radio v-for="(item, i) in config.find((e) => e.name === '企业产品-贷款用途')?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-radio>
</template>
<template v-else>
<el-radio v-for="(item, i) in config.find((e) => e.name === '个人产品-贷款用途')?.recordChildren[0]?.subject?.itemList" :key="i" :label="item.itemId">{{
item.options
}}</el-radio>
<el-radio v-for="(item, i) in config.find(e => e.name === '个人产品-贷款用途')?.recordChildren[0]?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-radio>
</template>
</el-radio-group>
<el-input
v-if="form?.loanPurpose === 822"
class="w-[300px] ml-5"
placeholder="请描述其他贷款用途可用于哪些方面。"
maxlength="10"
v-model="form.otherPurposesOfLoan"
></el-input>
<el-input v-if="form?.loanPurpose === 822"
class="w-[300px] ml-5"
placeholder="请描述其他贷款用途可用于哪些方面。"
maxlength="10"
v-model="form.otherPurposesOfLoan"></el-input>
</div>
</el-form-item>
<el-form-item
label="担保方式"
prop="bankGuaranteeTypeIds"
:rules="[
{
asyncValidator: async (rule, value, callback) => {
if (form.mortgageSelectedStatus === 795 && !value.find((e) => e > 22 && e < 33)) {
callback('请选择抵押物');
} else if (form.hypothecatedSelectedStatus === 795 && !value.find((e) => e > 32 && e < 38)) {
callback('请选择质押贷');
} else {
callback();
}
},
<el-form-item label="担保方式"
prop="bankGuaranteeTypeIds"
:rules="[
{
asyncValidator: async (rule, value, callback) => {
if (form.mortgageSelectedStatus === 795 && !value.find(e => e > 22 && e < 33)) {
callback('请选择抵押物')
} else if (form.hypothecatedSelectedStatus === 795 && !value.find(e => e > 32 && e < 38)) {
callback('请选择质押贷')
} else {
callback()
}
},
]"
>
},
]">
<div class="flex-1">
<p class="field-name">选择本产品的担保种类</p>
<div class="radio-wrap">
<span class="label">信用贷</span>
<el-radio-group v-model="form.creditSelectedStatus">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<div class="radio-wrap my-1">
<span class="label">保证贷</span>
<el-radio-group v-model="form.guaranteeLoanSelectedStatus">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<div class="radio-wrap">
<span class="label">抵押贷</span>
<el-radio-group v-model="form.mortgageSelectedStatus">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<el-checkbox-group v-if="form.mortgageSelectedStatus === 795" v-model="form.bankGuaranteeTypeIds">
<el-checkbox
v-for="(child, j) in config.find((e) => e.name === '担保方式')?.recordChildren[2]?.recordChildren[0]?.subject?.itemList"
:key="j"
:label="child.itemId"
>{{ child.options }}</el-checkbox
>
<el-checkbox-group v-if="form.mortgageSelectedStatus === 795"
v-model="form.bankGuaranteeTypeIds">
<el-checkbox v-for="(child, j) in config.find((e) => e.name === '担保方式')?.recordChildren[2]?.recordChildren[0]?.subject?.itemList"
:key="j"
:label="child.itemId">{{ child.options }}</el-checkbox>
</el-checkbox-group>
<div class="radio-wrap mt-1">
<span class="label">质押贷</span>
<el-radio-group v-model="form.hypothecatedSelectedStatus">
<el-radio v-for="(item, i) in whethers" :key="i" :label="item.id">{{ item.name }}</el-radio>
<el-radio v-for="(item, i) in whethers"
:key="i"
:label="item.id">{{ item.name }}</el-radio>
</el-radio-group>
</div>
<el-checkbox-group v-if="form.hypothecatedSelectedStatus === 795" v-model="form.bankGuaranteeTypeIds">
<el-checkbox
v-for="(child, j) in config.find((e) => e.name === '担保方式')?.recordChildren[3]?.recordChildren[0]?.subject?.itemList"
:key="j"
:label="child.itemId"
>{{ child.options }}</el-checkbox
>
<el-checkbox-group v-if="form.hypothecatedSelectedStatus === 795"
v-model="form.bankGuaranteeTypeIds">
<el-checkbox v-for="(child, j) in config.find((e) => e.name === '担保方式')?.recordChildren[3]?.recordChildren[0]?.subject?.itemList"
:key="j"
:label="child.itemId">{{ child.options }}</el-checkbox>
</el-checkbox-group>
</div>
</el-form-item>
<el-form-item label="贷款额度" prop="minimumLoan" :rules="[{ required: true, message: '请输入贷款额度', trigger: 'blur' }]">
<el-form-item label="贷款额度"
prop="minimumLoan"
:rules="[
{ required: true, message: '请输入贷款额度', trigger: 'blur' },
]">
<div class="flex-1">
<div class="num-inputs">
<el-input placeholder="最小额度" v-model="form.minimumLoan"></el-input>
<el-input placeholder="最小额度"
v-model="form.minimumLoan"></el-input>
<span class="split">-</span>
<el-input placeholder="最高额度" v-model="form.loanCeiling"></el-input>
<el-input placeholder="最高额度"
v-model="form.loanCeiling"></el-input>
<span class="unit">万元</span>
</div>
</div>
</el-form-item>
<el-form-item label="贷款利率" prop="minimumAprOnLoan" :rules="[{ required: true, message: '请输入贷款利率', trigger: 'blur' }]">
<el-form-item label="贷款利率"
prop="minimumAprOnLoan"
:rules="[
{ required: true, message: '请输入贷款利率', trigger: 'blur' },
]">
<div class="flex-1">
<div class="num-inputs">
<el-input placeholder="最小年利率" min="0" v-model="form.minimumAprOnLoan"></el-input>
<el-input placeholder="最小年利率"
min="0"
v-model="form.minimumAprOnLoan"></el-input>
<span class="split">-</span>
<el-input placeholder="最高年利率" min="0" v-model="form.maximumAnnualInterestRate"></el-input>
<el-input placeholder="最高年利率"
min="0"
v-model="form.maximumAnnualInterestRate"></el-input>
<span class="unit">%</span>
</div>
</div>
</el-form-item>
<el-form-item label="贷款期限" prop="minimumTermOfLoan" :rules="[{ required: true, message: '请输入贷款期限', trigger: 'blur' }]">
<el-form-item label="贷款期限"
prop="minimumTermOfLoan"
:rules="[
{ required: true, message: '请输入贷款期限', trigger: 'blur' },
]">
<div class="flex-1">
<div class="num-inputs">
<el-input placeholder="最小期限" v-model="form.minimumTermOfLoan"></el-input>
<el-input placeholder="最小期限"
v-model="form.minimumTermOfLoan"></el-input>
<span class="split">-</span>
<el-input placeholder="最大期限" v-model="form.maximumTermOfLoan"></el-input>
<el-input placeholder="最大期限"
v-model="form.maximumTermOfLoan"></el-input>
<span class="unit"></span>
</div>
</div>
</el-form-item>
<el-form-item label="还款方式" prop="modeRepayment">
<el-form-item label="还款方式"
prop="modeRepayment">
<div class="flex-1">
<p class="field-name">选择本产品可以选择的还款方式</p>
<el-checkbox-group v-model="form.modeRepayment">
<el-checkbox v-for="(item, i) in config.find((e) => e.name === '还款方式')?.subject?.itemList" :key="i" :label="item.itemId">{{ item.options }}</el-checkbox>
<el-checkbox v-for="(item, i) in config.find((e) => e.name === '还款方式')?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-checkbox>
</el-checkbox-group>
</div>
</el-form-item>
<el-form-item label="提前还款" prop="whetherToSupportEarlyRepayment">
<el-form-item label="提前还款"
prop="whetherToSupportEarlyRepayment">
<div class="flex-1 flex items-center">
<el-switch v-model="form.whetherToSupportEarlyRepayment" />
<p class="tips ml-4">本产品是否支持提前还款</p>
@ -258,13 +307,16 @@
</el-form-item>
</div>
<div class="flex justify-end">
<div class="submit" @click="submit(formRef)">完成提交风控经理</div>
<div class="submit"
@click="submit(formRef)">完成提交风控经理</div>
</div>
</el-form>
</el-tab-pane>
<el-tab-pane v-if="id" label="产品详情" name="tab2">
<el-tab-pane v-if="id"
label="产品详情"
name="tab2">
<div class="h-[calc(100vh-170px)] pr-1 overflow-auto">
<info />
<info v-model:tab="curTab" />
</div>
</el-tab-pane>
</el-tabs>
@ -274,14 +326,14 @@
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted, defineEmits } from 'vue';
import { ElMessage } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
import type { TabsPaneContext, FormInstance, FormRules } from 'element-plus';
import { findById, save, update, elementDetail } from '@/api/bank';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import { useRouter, useRoute } from 'vue-router';
import { handleId, isIllegalNum, getIds, whethers, getUsername } from '@/utils/common';
import Cookies from 'js-cookie';
import { getStat } from '@/store/useProduct';
import { getStatus } from '@/store/useProduct';
import Info from './Info.vue';
import Cookies from 'js-cookie';
const emit = defineEmits(['getList']);
interface RuleForm {
@ -306,7 +358,7 @@ interface RuleForm {
modeRepayment?: number[];
otherPurposesOfLoan: string;
productObject?: number;
productType?: number;
productType: number;
providentFundAndSocialSecurity: number | string;
whetherToSupportEarlyRepayment: boolean;
creditSelectedStatus?: number;
@ -318,15 +370,13 @@ interface RuleForm {
const router = useRouter();
const route = useRoute();
const id = computed(() => route.query.id);
const productType = +route.query.type;
const curTab = ref<string>(route.query.show ? 'tab2' : 'tab1');
const config = ref<any[]>([]);
const info = ref<Record<string, any>>(null);
const formRef = ref<FormInstance>();
const userName = ref<string>();
const form = reactive<RuleForm>({
let form = reactive<RuleForm>({
...getIds(),
productDefinition: '',
productName: '',
@ -349,7 +399,7 @@ const form = reactive<RuleForm>({
modeRepayment: [],
otherPurposesOfLoan: '',
productObject: '',
productType: '',
productType: computed(() => +route.query.type),
providentFundAndSocialSecurity: '',
whetherToSupportEarlyRepayment: false,
creditSelectedStatus: '',
@ -364,117 +414,56 @@ const rules = reactive<FormRules<RuleForm>>({
modeRepayment: [{ required: true, message: '请选择还款方式', trigger: 'change' }],
});
// tab
const tabChange = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event);
};
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(productType === 1 ? 45 : 44);
const { process } = await getProcessInformationBasedOnRoles(form.productType === 1 ? 45 : 44);
config.value = process;
};
//
const getDetail = async () => {
if (!Cookies.get('sand-submit')) {
if (!route.query.show) curTab.value = 'tab1';
userName.value = await getUsername();
info.value = null;
if (id.value) {
try {
// name
const { data } = await findById(id.value);
info.value = data;
// id
const res = await elementDetail(id.value);
if (res) {
const e = res.data.bankProducts;
e.currentWorkingLife = e.currentWorkingLife.split(',').map((n) => +n);
e.educationalRequirements = e.educationalRequirements.split(',').map((n) => +n);
e.modeRepayment = e.modeRepayment.split(',').map((n) => +n);
e.whetherToSupportEarlyRepayment = !!e.whetherToSupportEarlyRepayment;
e.bankGuaranteeTypeIds = [];
if (e.bankGuaranteeAllocationList) {
e.bankGuaranteeAllocationList.map((n) => {
n.guaranteeTypeId && e.bankGuaranteeTypeIds.push(n.guaranteeTypeId);
});
}
for (const i in e) {
if (e.hasOwnProperty(i)) {
form[i] = e[i];
}
}
if (!route.query.show) curTab.value = 'tab1';
userName.value = await getUsername();
info.value = null;
if (id.value) {
try {
// name
const { data } = await findById(id.value);
info.value = data;
// id
const res = await elementDetail(id.value);
if (res) {
const e = res.data.bankProducts;
e.currentWorkingLife = e.currentWorkingLife.split(',').map((n) => +n);
e.educationalRequirements = e.educationalRequirements.split(',').map((n) => +n);
e.modeRepayment = e.modeRepayment.split(',').map((n) => +n);
e.whetherToSupportEarlyRepayment = !!e.whetherToSupportEarlyRepayment;
e.bankGuaranteeTypeIds = [];
if (e.bankGuaranteeAllocationList) {
e.bankGuaranteeAllocationList.map((n) => {
n.guaranteeTypeId && e.bankGuaranteeTypeIds.push(n.guaranteeTypeId);
});
}
} finally {
form = Object.assign(form, e);
}
} finally {
}
}
};
watch(
() => route.query,
() => {
route.params.action === 'add' && getDetail();
getDetail();
},
{
immediate: true,
},
);
//
const addRecord = async (data: Record<string, any>) => {
getStat(299);
const isEnterprise = productType === 1;
const preIds = `1,${Cookies.get('sand-level')},41,${productType ? 45 : 44}`; // 1id/44/45
const lcRule: Array<Record<string, any>> = [
handleId(48, 1, data.productDefinition, `${preIds},48`, 3),
handleId(49, 2, data.productName, `${preIds},49`, 3),
handleId(50, 3, 1, `${preIds},50`, 1),
];
//
if (isEnterprise) {
//
lcRule.push(
handleId(62, 7, data.productObject, `${preIds},61,62`, 1),
handleId(63, 8, `${data.minimumAge}~${data.maximumAge}`, `${preIds},61,63`, 5),
handleId(65, 19, data.loanPurpose, `${preIds},65`, 1),
);
} else {
//
data.ageSelectedState && lcRule.push(handleId(1235, 324, data.ageSelectedState, `${preIds},51,1234,1235`, 1));
data.ageSelectedState === 795 && lcRule.push(handleId(1236, 41, `${data.minimumAge}~${data.maximumAge}`, `${preIds},51,1234,1236`, 5));
data.degreeSelectedStatus && lcRule.push(handleId(1238, 324, data.degreeSelectedStatus, `${preIds},51,1237,1238`, 1));
data.degreeSelectedStatus === 795 && lcRule.push(handleId(1239, 42, data.educationalRequirements, `${preIds},51,1237,1239`, 1));
data.workingLifeSelectedState && lcRule.push(handleId(1241, 324, data.workingLifeSelectedState, `${preIds},51,1240,1241`, 1));
data.workingLifeSelectedState === 795 && lcRule.push(handleId(1242, 43, data.currentWorkingLife, `${preIds},51,1240,1242`, 1));
data.providentFundAndSocialSecurity && lcRule.push(handleId(1244, 324, data.providentFundAndSocialSecurity, `${preIds},51,1243,1244`, 1)); //
lcRule.push(handleId(1316, 328, data.loanPurpose, `${preIds},52,1316`, 1));
data.loanPurpose === 822 && lcRule.push(handleId(1317, 11, data.otherPurposesOfLoan, `${preIds},52,1317`, 3));
}
//
data.creditSelectedStatus && lcRule.push(handleId(108, 324, data.creditSelectedStatus, `${preIds},53,108`, 1));
data.guaranteeLoanSelectedStatus && lcRule.push(handleId(109, 324, data.guaranteeLoanSelectedStatus, `${preIds},53,109`, 1));
data.mortgageSelectedStatus && lcRule.push(handleId(1277, 324, data.mortgageSelectedStatus, `${preIds},53,110,1277`, 1));
data.hypothecatedSelectedStatus && lcRule.push(handleId(1278, 324, data.hypothecatedSelectedStatus, `${preIds},53,111,1278`, 1));
data.mortgageSelectedStatus === 795 && lcRule.push(handleId(1275, 13, data.bankGuaranteeTypeIds.filter((e: number) => e > 22 && e < 33).join(), `${preIds},53,110,1275`, 1));
data.hypothecatedSelectedStatus === 795 && lcRule.push(handleId(1276, 14, data.bankGuaranteeTypeIds.filter((e: number) => e > 32 && e < 38).join(), `${preIds},53,111,1276`, 1));
lcRule.push(
handleId(54, 15, `${data.minimumLoan}~${data.loanCeiling}`, `${preIds},54`, 5),
handleId(55, 16, `${data.minimumAprOnLoan}~${data.maximumAnnualInterestRate}`, `${preIds},55`, 5),
handleId(56, 17, `${data.minimumTermOfLoan}~${data.maximumTermOfLoan}`, `${preIds},56`, 5),
handleId(57, 18, data.modeRepayment, `${preIds},57`, 1),
);
lcRule.push(handleId(58, 140, data.whetherToSupportEarlyRepayment ? 345 : 346, `${preIds},58`, 1));
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: lcRule,
});
};
//
const submit = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
@ -482,11 +471,12 @@ const submit = async (formEl: FormInstance | undefined) => {
if (valid) {
try {
const param = JSON.parse(JSON.stringify(form));
//
if (productType) {
if (param.productType) {
if (!param.productObject) return ElMessage.error('请选择企业类型');
}
if ((!param.productType && param.ageSelectedState === 795) || productType) {
if ((!param.productType && param.ageSelectedState === 795) || param.productType) {
if (!param.minimumAge) return ElMessage.error('请输入最小年龄');
if (!param.maximumAge) return ElMessage.error('请输入最大年龄');
if (isIllegalNum(param.minimumAge) || isIllegalNum(param.maximumAge)) return ElMessage.error('请输入合理的年龄');
@ -494,7 +484,7 @@ const submit = async (formEl: FormInstance | undefined) => {
}
//
if (!productType) {
if (!param.productType) {
if (param.degreeSelectedStatus === 795 && !param.educationalRequirements.length) return ElMessage.error('请选择学历要求');
if (param.workingLifeSelectedState === 795 && !param.currentWorkingLife.length) return ElMessage.error('请选择工作年限');
}
@ -504,7 +494,7 @@ const submit = async (formEl: FormInstance | undefined) => {
if (isIllegalNum(param.minimumTermOfLoan) || isIllegalNum(param.maximumTermOfLoan) || +param.minimumTermOfLoan > +param.maximumTermOfLoan)
return ElMessage.error('请输入合理的贷款期限');
if (!productType && param.ageSelectedState !== 795) {
if (!param.productType && param.ageSelectedState !== 795) {
param.minimumAge = '';
param.maximumAge = '';
}
@ -547,7 +537,6 @@ const submit = async (formEl: FormInstance | undefined) => {
}
});
param.addBankProductsGuarantyStyleReqList = graIds;
param.productType = productType;
let res;
if (id.value) {
param.id = id.value;
@ -569,6 +558,63 @@ const submit = async (formEl: FormInstance | undefined) => {
}
});
};
//
const addRecord = async (data: Record<string, any>) => {
const isEnterprise = data.productType === 1;
const preIds = `1,${Cookies.get('sand-level')},41,${data.productType ? 45 : 44}`; // 1id/44/45
const lcRule: Array<Record<string, any>> = [
handleId(48, 1, data.productDefinition, preIds + ',48', 3),
handleId(49, 2, data.productName, preIds + ',49', 3),
handleId(50, 3, 1, preIds + ',50', 1),
];
//
if (isEnterprise) {
//
lcRule.push(
handleId(62, 7, data.productObject, preIds + ',61,62', 1),
handleId(63, 8, data.minimumAge + '~' + data.maximumAge + '', preIds + ',61,63', 5),
handleId(65, 19, data.loanPurpose, preIds + ',65', 1),
);
} else {
//
data.ageSelectedState && lcRule.push(handleId(1235, 324, data.ageSelectedState, preIds + ',51,1234,1235', 1));
data.ageSelectedState === 795 && lcRule.push(handleId(1236, 41, data.minimumAge + '~' + data.maximumAge, preIds + ',51,1234,1236', 5));
data.degreeSelectedStatus && lcRule.push(handleId(1238, 324, data.degreeSelectedStatus, preIds + ',51,1237,1238', 1));
data.degreeSelectedStatus === 795 && lcRule.push(handleId(1239, 42, data.educationalRequirements, preIds + ',51,1237,1239', 1));
data.workingLifeSelectedState && lcRule.push(handleId(1241, 324, data.workingLifeSelectedState, preIds + ',51,1240,1241', 1));
data.workingLifeSelectedState === 795 && lcRule.push(handleId(1242, 43, data.currentWorkingLife, preIds + ',51,1240,1242', 1));
data.providentFundAndSocialSecurity && lcRule.push(handleId(1244, 324, data.providentFundAndSocialSecurity, preIds + ',51,1243,1244', 1)); //
lcRule.push(handleId(1316, 328, data.loanPurpose, preIds + ',52,1316', 1));
data.loanPurpose === 822 && lcRule.push(handleId(1317, 11, data.otherPurposesOfLoan, preIds + ',52,1317', 3));
}
//
data.creditSelectedStatus && lcRule.push(handleId(108, 324, data.creditSelectedStatus, preIds + ',53,108', 1));
data.guaranteeLoanSelectedStatus && lcRule.push(handleId(109, 324, data.guaranteeLoanSelectedStatus, preIds + ',53,109', 1));
data.mortgageSelectedStatus && lcRule.push(handleId(1277, 324, data.mortgageSelectedStatus, preIds + ',53,110,1277', 1));
data.hypothecatedSelectedStatus && lcRule.push(handleId(1278, 324, data.hypothecatedSelectedStatus, preIds + ',53,111,1278', 1));
data.mortgageSelectedStatus === 795 && lcRule.push(handleId(1275, 13, data.bankGuaranteeTypeIds.filter((e: number) => e > 22 && e < 33).join(), preIds + ',53,110,1275', 1));
data.hypothecatedSelectedStatus === 795 && lcRule.push(handleId(1276, 14, data.bankGuaranteeTypeIds.filter((e: number) => e > 32 && e < 38).join(), preIds + ',53,111,1276', 1));
lcRule.push(
handleId(54, 15, data.minimumLoan + '~' + data.loanCeiling, preIds + ',54', 5),
handleId(55, 16, data.minimumAprOnLoan + '~' + data.maximumAnnualInterestRate, preIds + ',55', 5),
handleId(56, 17, data.minimumTermOfLoan + '~' + data.maximumTermOfLoan, preIds + ',56', 5),
handleId(57, 18, data.modeRepayment, preIds + ',57', 1),
);
lcRule.push(handleId(58, 140, data.whetherToSupportEarlyRepayment ? 345 : 346, preIds + ',58', 1));
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: lcRule,
});
};
onMounted(() => {
getConfig();
});

@ -1,17 +1,34 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane label="审批" name="tab1">
<el-tab-pane label="审批"
name="tab1">
<div class="h-[calc(100vh-170px)] pr-1 overflow-auto">
<info ref="infoRef" @updateAudits="updateAudits" />
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-suffix="" class="form pt-5 mt-5 border-t border-t-solid border-t-[#EDF1F5]" status-icon>
<el-form-item label="审批意见" prop="status">
<el-select v-model="form.status" placeholder="请选择">
<el-option v-for="(item, i) in autids" :key="i" :label="item.name" :value="item.id" />
<info ref="infoRef"
@updateAudits="updateAudits" />
<el-form ref="formRef"
:model="form"
:rules="rules"
label-width="100px"
label-suffix=":"
class="form pt-5 mt-5 border-t border-t-solid border-t-[#EDF1F5]"
status-icon>
<el-form-item label="审批意见"
prop="status">
<el-select v-model="form.status"
placeholder="请选择">
<el-option v-for="(item, i) in autids"
:key="i"
:label="item.name"
:value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="意见描述" prop="opinionDescription">
<el-input type="textarea" placeholder="审批意见500字以内。" maxlength="500" v-model="form.opinionDescription"></el-input>
<el-form-item label="意见描述"
prop="opinionDescription">
<el-input type="textarea"
placeholder="审批意见500字以内。"
maxlength="500"
v-model="form.opinionDescription"></el-input>
</el-form-item>
<div class="flex flex-col items-end">
<div class="mb-[18px] text-sm leading-[1.6]">
@ -20,12 +37,16 @@
</div>
<div class="inline-flex items-center mb-[18px] text-sm leading-[1.6]">
<span class="text-sm font-semibold">审批员</span>
<span v-if="signed" class="text-lg text-[#f00]">{{ signed }}</span>
<span v-else class="py-2 px-5 ml-1 text-sm text-white bg-[#006BFF] cursor-pointer" @click="sign">签章</span>
<span v-if="signed"
class="text-lg text-[#f00]">{{ signed }}</span>
<span v-else
class="py-2 px-5 ml-1 text-sm text-white bg-[#006BFF] cursor-pointer"
@click="sign">签章</span>
</div>
</div>
<div class="flex justify-end">
<div class="submit" @click="submit(formRef)">审批</div>
<div class="submit"
@click="submit(formRef)">审批</div>
</div>
</el-form>
</div>
@ -37,16 +58,16 @@
<script setup lang="ts">
import { ref, computed, reactive, onMounted, watch } from 'vue';
import { ElMessage } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
import type { TabsPaneContext, FormInstance, FormRules } from 'element-plus';
import { useRouter, useRoute } from 'vue-router';
import Info from './Info.vue';
import { handleId, getIds, getNow, getUsername } from '@/utils/common';
import { examineAndApprove } from '@/api/bank';
import { getOperationTime } from '@/api/config';
import { addOperation } from '@/api/judgment';
import dayjs from 'dayjs';
import Cookies from 'js-cookie';
import { productState, getStat } from '@/store/useProduct';
import Info from './Info.vue';
import { productState } from '@/store/useProduct';
const emit = defineEmits(['getList']);
interface RuleForm {
@ -77,7 +98,7 @@ const signed = ref<string>();
//
const updateAudits = (count: number) => {
if (count >= 9) {
if (count >= 2) {
autids.value.pop();
}
};
@ -95,7 +116,7 @@ const sign = async () => {
};
//
const addRecord = async (data: Record<string, any>) => {
const approved = data.status !== 299; // id
const approved = !!infoRef.value.info.approvalTime; // id
const preIds = `1,${levelId},43,${approved ? 1219 : 1218}`; // 1id
const lcRule = [
handleId(approved ? 1215 : 145, 69, data.status, `${preIds},${approved ? '1215' : '145'}`, 1),
@ -119,7 +140,6 @@ const submit = async (formEl: FormInstance | undefined) => {
await examineAndApprove(param.id, param.opinionDescription, param.status, param.approvalTime);
router.push(`/product/bank/detail?type=${route.query.type || ''}&i=${route.query.i}&role=${route.query.role}&id=${id.value}`);
getStat(296);
addRecord(param);
ElMessage.success('提交成功!');
emit('getList');
@ -129,6 +149,7 @@ const submit = async (formEl: FormInstance | undefined) => {
});
};
onMounted(async () => {
console.log(11);
date.value = dayjs(await getNow()).format('YYYY-MM-DD');
});
watch(

@ -1,24 +1,34 @@
<template>
<div class="block card-list flex py-0">
<div class="left">
<div
v-if="role == 41"
class="flex justify-center items-center py-2 mb-3 text-sm text-[#006BFF] bg-[rgba(0,107,255,0.1)] border border-solid border-[#006BFF] rounded-[10px] cursor-pointer"
@click="toAdd"
>
<el-icon class="mr-1" :size="16" color="#006BFF">
<div v-if="role == 41"
class="flex justify-center items-center py-2 mb-3 text-sm text-[#006BFF] bg-[rgba(0,107,255,0.1)] border border-solid border-[#006BFF] rounded-[10px] cursor-pointer"
@click="toAdd">
<el-icon class="mr-1"
:size="16"
color="#006BFF">
<Plus />
</el-icon>
新增产品
</div>
<div class="flex justify-end mb-4">
<img src="@/assets/images/fold.png" alt="" class="cursor-pointer" @click="toList" />
<img src="@/assets/images/fold.png"
alt=""
class="cursor-pointer"
@click="toList" />
</div>
<ul class="products">
<li v-for="(item, i) in list" :key="i" :class="{ active: item.id === id }" @click="switchProduct(item)">
<el-popconfirm v-if="role == 41" title="您确定删除吗?" @confirm="handleDelete(item.id)">
<li v-for="(item, i) in list"
:key="i"
:class="{ active: item.id === id }"
@click="switchProduct(item)">
<el-popconfirm v-if="role == 41"
title="您确定删除吗?"
@confirm="handleDelete(item.id)">
<template #reference>
<img src="@/assets/images/trash.png" alt="" class="del" />
<img src="@/assets/images/trash.png"
alt=""
class="del" />
</template>
</el-popconfirm>
@ -30,32 +40,42 @@
</ul>
</div>
<div class="right">
<config v-if="action === 'config'" :key="actionKey" @getList="getList"></config>
<!-- <component :is="currentSubApp"
@getList="getList"></component> -->
<config v-if="action === 'config'"
:key="actionKey"
@getList="getList"></config>
<detail v-if="action === 'detail'"></detail>
<add v-else-if="action === 'add'" :key="actionKey" @getList="getList"></add>
<approve v-else-if="action === 'approve'" :key="actionKey" @getList="getList"></approve>
<add v-else-if="action === 'add'"
:key="actionKey"
@getList="getList"></add>
<approve v-else-if="action === 'approve'"
:key="actionKey"
@getList="getList"></approve>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue';
import { computed, onMounted, ref, watch, defineAsyncComponent } from 'vue';
import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
import { bankingProductsList, batchDeletion } from '@/api/bank';
import { useRouter, useRoute } from 'vue-router';
import { getStatus } from '@/store/useProduct';
import { getIds } from '@/utils/common';
import Cookies from 'js-cookie';
import Config from './Config.vue';
import Detail from './Detail.vue';
import Add from './Add.vue';
import Approve from './Approve.vue';
import Cookies from 'js-cookie';
import { getIds } from '@/utils/common';
const router = useRouter();
const route = useRoute();
const action = ref<any>('');
// const modules: any = import.meta.glob('./*.vue');
// let currentSubApp = defineAsyncComponent(modules[`./${route.params.action}.vue`]);
const list = ref<Array<any>>([]);
const loading = ref<boolean>(false);
const productType = computed(() => route.query.type); // /
@ -64,28 +84,28 @@ const id = computed(() => +route.query.id);
const actionKey = ref<number>(1);
//
const getList = async (refresh?: number) => {
if (!Cookies.get('sand-submit')) {
loading.value = true;
try {
const { data } = await bankingProductsList({
...getIds(),
pageNum: 1,
pageSize: 1000,
productType: productType.value,
roleId: route.query.role,
keyWord: route.query.name ?? '',
createDateSort: route.query.createDateSort ?? '',
guarantyStyleId: route.query.guarantyStyleId ?? '',
status: route.query.status ?? '',
});
list.value = data.message.records;
((route.path !== '/product/bank/add' && list.value.length && !id.value) || refresh) && switchProduct(list.value[0], refresh);
} finally {
loading.value = false;
}
loading.value = true;
try {
const { data } = await bankingProductsList({
...getIds(),
pageNum: 1,
pageSize: 1000,
productType: productType.value,
roleId: route.query.role,
keyWord: route.query.name ?? '',
createDateSort: route.query.createDateSort ?? '',
guarantyStyleId: route.query.guarantyStyleId ?? '',
status: route.query.status ?? '',
});
list.value = data.message.records;
((route.path !== '/product/bank/add' && list.value.length && !id.value) || refresh) && switchProduct(list.value[0], refresh);
} finally {
loading.value = false;
}
};
onMounted(getList);
onMounted(() => {
getList();
});
watch(
route,

File diff suppressed because it is too large Load Diff

@ -1,7 +1,8 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane :label="status" name="tab1">
<el-tab-pane :label="status"
name="tab1">
<div class="h-[calc(100vh-170px)] pr-1 overflow-auto">
<info />
</div>

@ -1,12 +1,14 @@
<template>
<div class="info my-2">
<h1 v-if="riskInfo" class="mb-3 text-xl font-semibold text-center">{{ info.productName }}产品手册</h1>
<h1 v-if="riskInfo"
class="mb-3 text-xl font-semibold text-center">{{ info.productName }}产品手册</h1>
<h6 class="step-name">{{ route.params.action !== 'config' ? '一、' : '' }}产品定义</h6>
<p class="text">{{ info.productDefinition }}</p>
<h6 class="step-name mt-5">{{ route.params.action !== 'config' ? '二、' : '' }}产品要素</h6>
<p class="text">产品名称{{ info.productName }}</p>
<p class="text">贷款币种人民币</p>
<p v-if="info.loanPurpose" class="text">
<p v-if="info.loanPurpose"
class="text">
贷款用途{{
info.loanPurpose === '购房'
? '可用于住房按揭贷款、二手房住房按揭贷款。'
@ -21,9 +23,11 @@
: info.otherPurposesOfLoan
}}
</p>
<div v-if="info.guarantyStyle" class="flex my-2">
<div v-if="info.guarantyStyle"
class="flex my-2">
<p class="text whitespace-nowrap">担保方式</p>
<p v-html="info.guarantyStyle" class="text"></p>
<p v-html="info.guarantyStyle"
class="text"></p>
</div>
<p class="text">贷款期限{{ info.minimumTermOfLoan }} - {{ info.maximumTermOfLoan }}</p>
@ -31,88 +35,73 @@
<p class="text">贷款利率{{ info.minimumAprOnLoan }}% - {{ info.maximumAnnualInterestRate }}%</p>
<p class="text">还款方式{{ info.modeRepayment }}</p>
<div v-if="info.prospectiveBorrowerText" class="flex my-2">
<div v-if="info.prospectiveBorrowerText"
class="flex my-2">
<p class="text whitespace-nowrap">适用条件</p>
<div class="text" v-html="info.prospectiveBorrowerText"></div>
<div class="text"
v-html="info.prospectiveBorrowerText"></div>
</div>
<template v-if="riskInfo">
<h6 class="step-name mt-5">{{ route.params.action !== 'add' ? '三、' : '' }}材料要求</h6>
<p v-if="riskInfo?.accountMaterials" class="text">办理账户-提供材料{{ riskInfo?.accountMaterials }}</p>
<p v-if="riskInfo?.sendingAccount" class="text">办理账户-发放账户借记卡或放款专户</p>
<p v-if="riskInfo?.loanApplicationMethod" class="text">贷款申请-申请方式{{ riskInfo?.loanApplicationMethod }}</p>
<p v-if="riskInfo?.borrowerMaterial" class="text">贷款申请-提供材料-借款人材料{{ riskInfo?.borrowerMaterial }}</p>
<p v-if="riskInfo?.accountMaterials"
class="text">办理账户-提供材料{{ riskInfo?.accountMaterials }}</p>
<p v-if="riskInfo?.sendingAccount"
class="text">办理账户-发放账户借记卡或放款专户</p>
<p v-if="riskInfo?.loanApplicationMethod"
class="text">贷款申请-申请方式{{ riskInfo?.loanApplicationMethod }}</p>
<p v-if="riskInfo?.borrowerMaterial"
class="text">贷款申请-提供材料-借款人材料{{ riskInfo?.borrowerMaterial }}</p>
<template v-if="info.productType">
<p v-if="riskInfo?.enterpriseMaterial" class="text">贷款申请-提供材料-企业材料{{ riskInfo?.enterpriseMaterial }}</p>
<p v-if="riskInfo?.collateral" class="text">贷款申请-提供材料-抵押物{{ riskInfo?.collateral }}</p>
<p v-if="riskInfo?.enterpriseMaterial"
class="text">贷款申请-提供材料-企业材料{{ riskInfo?.enterpriseMaterial }}</p>
<p v-if="riskInfo?.collateral"
class="text">贷款申请-提供材料-抵押物{{ riskInfo?.collateral }}</p>
</template>
<template v-else>
<p v-if="riskInfo?.mateMaterial" class="text">贷款申请-提供材料-配偶材料{{ riskInfo?.mateMaterial }}</p>
<p v-if="riskInfo?.businessMaterials" class="text">贷款申请-提供材料-经营类材料{{ riskInfo?.businessMaterials }}</p>
</template>
<p v-if="riskInfo?.supplementaryMaterials" class="text">贷款申请-提供材料-补充材料{{ riskInfo?.supplementaryMaterials }}</p>
<p v-if="riskInfo?.runBatchObject" class="text">系统跑批准入风控策略-跑批对象{{ riskInfo?.runBatchObject }}</p>
<template v-if="info.bankRiskControlAllocationTacticsList && info.bankRiskControlAllocationTacticsList.length">
<template v-for="(item, i) in info.bankRiskControlAllocationTacticsList">
<p v-if="item.tacticsSelectedStatus" :key="i" class="text flex">
系统跑批{{ item.pointName }}{{ item.tacticsName || '无需跑批' }}
<img v-if="item.tacticsName" src="@/assets/svgs/preview.svg" alt="" class="cursor-pointer ml-2" @click="preview(item, i)" />
</p>
</template>
</template>
<template v-if="info.creditScoringStrategyList && info.creditScoringStrategyList.length">
<template v-for="(item, i) in info.creditScoringStrategyList">
<p v-if="item.tacticsSelectedStatus" :key="i" class="text flex">
系统跑批{{ item.pointName }}{{ item.tacticsName || '无需跑批' }}
<img v-if="item.tacticsName" src="@/assets/svgs/preview.svg" alt="" class="cursor-pointer ml-2" @click="previewCredits(item, i)" />
</p>
</template>
</template>
<p v-if="info?.personalRiskDegreeStrategySelectedStatus === 803 || info?.enterpriseRiskDegreeStrategySelectedStatus === 803" class="text">
系统跑批风险度策略
{{ info?.personalRiskDegreeStrategySelectedStatus === 803 ? '个人风险度策略' : '' }}
{{ info?.personalRiskDegreeStrategySelectedStatus === 803 && info?.enterpriseRiskDegreeStrategySelectedStatus === 803 ? ',' : '' }}
{{ info?.enterpriseRiskDegreeStrategySelectedStatus === 803 ? '企业风险度策略' : '' }}
</p>
<template v-if="info.interestRatePricingModelList && info.interestRatePricingModelList.length">
<template v-for="(item, i) in info.interestRatePricingModelList">
<p v-if="item.tacticsSelectedStatus" :key="i" class="text flex">
系统跑批{{ item.pointName }}{{ item.tacticsName || '无需跑批' }}
<img v-if="item.tacticsName" src="@/assets/svgs/preview.svg" alt="" class="cursor-pointer ml-2" @click="previewRate(item, i)" />
</p>
</template>
</template>
<p v-if="info?.enterpriseQuotaModelStr" class="text">系统跑批企业额度模型{{ info?.enterpriseQuotaModelStr }}</p>
<p v-if="riskInfo?.dueDiligenceMode" class="text">尽职调查-尽调方式{{ riskInfo?.dueDiligenceMode }}</p>
<p v-if="riskInfo?.dueDiligenceContent" class="text">尽职调查-尽调内容{{ riskInfo?.dueDiligenceContent }}</p>
<p v-if="riskInfo?.reviewContent" class="text">贷款审查-审查内容{{ riskInfo?.reviewContent }}</p>
<p v-if="riskInfo?.reviewSignature" class="text">贷款审查-审查签字{{ riskInfo?.reviewSignature }}</p>
<p v-if="riskInfo?.reviewApproveContent" class="text">贷款审批-审批内容{{ riskInfo?.reviewApproveContent }}</p>
<p v-if="riskInfo?.approvalSignature" class="text">贷款审批-审批签字{{ riskInfo?.approvalSignature }}</p>
<p v-if="riskInfo?.contractMaterials" class="text">签订合同-提供的材料{{ riskInfo?.contractMaterials }}</p>
<p v-if="riskInfo?.loanContract" class="text">需要签订借贷合同{{ riskInfo?.loanContract }}</p>
<p v-if="riskInfo?.mortgageContract" class="text">需要签订抵押合同{{ riskInfo?.mortgageContract }}</p>
<p v-if="riskInfo?.pledgeContract" class="text">需要签订质押合同{{ riskInfo?.pledgeContract }}</p>
<p v-if="riskInfo?.guaranteeContract" class="text">需要签订担保合同{{ riskInfo?.guaranteeContract }}</p>
<template v-if="info.postLoanSelectionStrategyList && info.postLoanSelectionStrategyList.length">
<template v-for="(item, i) in info.postLoanSelectionStrategyList">
<p v-if="item.tacticsSelectedStatus" :key="i" class="text flex">
系统跑批{{ item.pointName }}{{ item.tacticsName || '无需跑批' }}
<img v-if="item.tacticsName" src="@/assets/svgs/preview.svg" alt="" class="cursor-pointer ml-2" @click="previewAfter(item, i)" />
</p>
</template>
<p v-if="riskInfo?.mateMaterial"
class="text">贷款申请-提供材料-配偶材料{{ riskInfo?.mateMaterial }}</p>
<p v-if="riskInfo?.businessMaterials"
class="text">贷款申请-提供材料-经营类材料{{ riskInfo?.businessMaterials }}</p>
</template>
<p v-if="riskInfo?.supplementaryMaterials"
class="text">贷款申请-提供材料-补充材料{{ riskInfo?.supplementaryMaterials }}</p>
<p v-if="riskInfo?.runBatchObject"
class="text">系统跑批准入风控策略-跑批对象{{ riskInfo?.runBatchObject }}</p>
<p v-if="riskInfo?.accessStrategy"
class="text">系统跑批准入风控策略-准入策略{{ riskInfo?.accessStrategy }}</p>
<p v-if="riskInfo?.personalCreditScoringStrategies"
class="text">系统跑批准入风控策略-信用评分策略{{ riskInfo?.personalCreditScoringStrategies }}</p>
<p v-if="riskInfo?.riskDegreeStrategy"
class="text">系统跑批准入风控策略-风险度策略{{ riskInfo?.riskDegreeStrategy }}</p>
<p v-if="riskInfo?.interestRatePricingModel"
class="text">系统跑批准入风控策略-利率定价模型-{{ info.productType ? '企业' : '个人' }}额度模型{{ riskInfo?.interestRatePricingModel }}</p>
<p v-if="riskInfo?.individualInterestRateModel === '需要跑批'"
class="text">系统跑批准入风控策略-利率定价模型-{{ info.productType ? '企业' : '个人' }}利率模型</p>
<p v-if="riskInfo?.dueDiligenceMode"
class="text">尽职调查-尽调方式{{ riskInfo?.dueDiligenceMode }}</p>
<p v-if="riskInfo?.dueDiligenceContent"
class="text">尽职调查-尽调内容{{ riskInfo?.dueDiligenceContent }}</p>
<p v-if="riskInfo?.reviewContent"
class="text">贷款审查-审查内容{{ riskInfo?.reviewContent }}</p>
<p v-if="riskInfo?.reviewSignature"
class="text">贷款审查-审查签字{{ riskInfo?.reviewSignature }}</p>
<p v-if="riskInfo?.reviewApproveContent"
class="text">贷款审批-审批内容{{ riskInfo?.reviewApproveContent }}</p>
<p v-if="riskInfo?.approvalSignature"
class="text">贷款审批-审批签字{{ riskInfo?.approvalSignature }}</p>
<p v-if="riskInfo?.contractMaterials"
class="text">签订合同-提供的材料{{ riskInfo?.contractMaterials }}</p>
<p v-if="riskInfo?.loanContract"
class="text">签订合同-合同模板-借贷合同{{ riskInfo?.loanContract }}</p>
<p v-if="riskInfo?.mortgageContract"
class="text">签订合同-合同模板-抵押合同{{ riskInfo?.mortgageContract }}</p>
<p v-if="riskInfo?.pledgeContract"
class="text">签订合同-合同模板-质押合同{{ riskInfo?.pledgeContract }}</p>
<p v-if="riskInfo?.guaranteeContract"
class="text">签订合同-合同模板-担保合同{{ riskInfo?.guaranteeContract }}</p>
<p v-if="riskInfo?.selectionStrategy"
class="text">贷后管理-选择策略{{ riskInfo?.selectionStrategy }}</p>
<h6 class="step-name mt-5">{{ route.params.action !== 'add' ? '四、' : '' }}业务流程</h6>
<p class="text">1贷款人APP向智信银行公司业务部门提交借款申请同时提交贷款用途证明文件以及有关资料</p>
@ -129,8 +118,11 @@
</template>
</div>
<div v-if="approvals.length" class="mt-10">
<div v-for="(item, i) in approvals" :key="i" class="audit">
<div v-if="approvals.length"
class="mt-10">
<div v-for="(item, i) in approvals"
:key="i"
class="audit">
<div class="line">
<span class="field">审批意见</span>
<span class="status">{{ getStatus(item?.status) }}</span>
@ -140,24 +132,23 @@
{{ item.opinionDescription }}
</div>
<p class="mb-2 text-sm text-[#333] text-right">审查日期{{ item.approvalTime }}</p>
<p class="mb-2 text-sm text-[#333] text-right">{{ i === 10 ? '' : '审查员:' }}{{ item.examinationApprovalOfficer }}</p>
<p class="mb-2 text-sm text-[#333] text-right">审查员{{ userName }}</p>
</div>
</div>
<el-drawer v-model="visible" :title="curPreviewTitle" size="100%" :z-index="10" class="model-drawer">
<component v-if="loadedComponents[activeComponent]" :is="loadedComponents[activeComponent]" v-model:row="curRow" disabled :key="curRow.strategyId" />
</el-drawer>
</template>
<script setup lang="ts">
import { ref, computed, watch, defineExpose, defineAsyncComponent, markRaw } from 'vue';
import { ref, computed, watch, defineExpose } from 'vue';
import { findById, approvalRecord } from '@/api/bank';
import { useRoute } from 'vue-router';
import { useRouter, useRoute } from 'vue-router';
import { getStatus } from '@/store/useProduct';
import { getUsername } from '@/utils/common';
import Cookies from 'js-cookie';
// const props = defineProps({
// tab: String,
// });
const emit = defineEmits(['updateAudits']);
const router = useRouter();
const route = useRoute();
const id = computed(() => +route.query.id);
const info = ref<Record<string, any>>({});
@ -165,115 +156,35 @@ const riskInfo = ref<Record<string, any>>(null);
const approvals = ref<Record<string, any>[]>([]);
const userName = ref<string>();
const visible = ref<boolean>(false);
const curRow = ref<Record<string, any>>();
const curPreviewTitle = ref<string>();
const asyncComponents = {
'150': defineAsyncComponent(() => import('../strategy/150/Detail.vue')),
'151': defineAsyncComponent(() => import('../strategy/151/Detail.vue')),
'152': defineAsyncComponent(() => import('../strategy/152/Detail.vue')),
'153': defineAsyncComponent(() => import('../strategy/153/Detail.vue')),
'154': defineAsyncComponent(() => import('../strategy/154/Detail.vue')),
'155': defineAsyncComponent(() => import('../strategy/155/Detail.vue')),
'156': defineAsyncComponent(() => import('../strategy/156/Detail.vue')),
'512': defineAsyncComponent(() => import('../strategy/512/Detail.vue')),
'513': defineAsyncComponent(() => import('../strategy/513/Detail.vue')),
'772': defineAsyncComponent(() => import('../interestRate/772/Detail.vue')),
'935': defineAsyncComponent(() => import('../interestRate/935/Detail.vue')),
'936': defineAsyncComponent(() => import('../interestRate/936/Detail.vue')),
'1029': defineAsyncComponent(() => import('../afterLoan/1029/Detail.vue')),
'1030': defineAsyncComponent(() => import('../afterLoan/1030/Detail.vue')),
'1031': defineAsyncComponent(() => import('../afterLoan/1031/Detail.vue')),
'1032': defineAsyncComponent(() => import('../afterLoan/1032/Detail.vue')),
'1033': defineAsyncComponent(() => import('../afterLoan/1033/Detail.vue')),
};
const loadedComponents = markRaw({});
const activeComponent = ref<string>('');
//
const loadComponent = async (componentName: string) => {
if (!loadedComponents[componentName]) {
try {
loadedComponents[componentName] = asyncComponents[componentName];
activeComponent.value = componentName;
} catch (error) {
console.error(`Failed to load component ${componentName}`, error);
}
} else {
activeComponent.value = componentName;
}
};
//
const getDetail = async () => {
if (!Cookies.get('sand-submit')) {
userName.value = await getUsername();
userName.value = await getUsername();
if (id.value) {
try {
const { data } = await findById(id.value);
info.value = data;
if (info.value.riskControlDetails) riskInfo.value = data.riskControlDetails;
const res = await approvalRecord({
id: id.value,
});
approvals.value = res.list;
emit('updateAudits', res.list.length);
} catch (e) {}
if (id.value) {
try {
const { data } = await findById(id.value);
info.value = data;
emit('updateAudits', data.rejectCount);
if (info.value.riskControlDetails) riskInfo.value = data.riskControlDetails;
const res = await approvalRecord({
id: id.value,
});
approvals.value = res.list;
} finally {
}
}
};
watch(
() => route.query,
() => {
route.path.startsWith('/product/bank') && getDetail();
getDetail();
},
{
immediate: true,
},
);
//
const preview = async (row: Record<string, any>, i: number) => {
curRow.value = {
strategyId: row.tacticsId,
strategyName: row.tacticsName,
};
await loadComponent(Object.keys(asyncComponents)[i]);
curPreviewTitle.value = `查看${row.pointName}`;
visible.value = true;
};
//
const previewCredits = async (row: Record<string, any>, i: number) => {
curRow.value = {
id: row.tacticsId,
};
await loadComponent(i ? '513' : '512');
curPreviewTitle.value = `查看${row.pointName}`;
visible.value = true;
};
//
const previewRate = async (row: Record<string, any>, i: number) => {
curRow.value = {
id: row.tacticsId,
modelName: row.tacticsName,
};
await loadComponent(i === 2 ? '936' : i ? '772' : '935');
curPreviewTitle.value = `查看${row.pointName}`;
visible.value = true;
};
//
const previewAfter = async (row: Record<string, any>, i: number) => {
curRow.value = {
strategyId: row.tacticsId,
strategyName: row.tacticsName,
};
await loadComponent(Object.keys(asyncComponents)[i + 12]);
curPreviewTitle.value = `查看${row.pointName}`;
visible.value = true;
};
defineExpose({
info,
});

@ -1,79 +1,138 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="params.keyWord" @change="initList"></search>
<search v-model="params.keyWord"
@change="initList"></search>
<div class="filter">
<el-checkbox-group v-if="params.roleId == 42" class="mr-5" v-model="productTypes">
<el-checkbox-group v-if="params.roleId == 42"
class="mr-5"
v-model="productTypes">
<el-checkbox :label="0">个人</el-checkbox>
<el-checkbox :label="1">企业</el-checkbox>
</el-checkbox-group>
<div class="select">
<el-select v-model="params.guarantyStyleId" placeholder="担保方式" size="large">
<el-option label="担保方式" value="" />
<el-option v-for="item in guarantees" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="params.guarantyStyleId"
placeholder="担保方式"
size="large">
<el-option label="担保方式"
value="" />
<el-option v-for="item in guarantees"
:key="item.id"
:label="item.name"
:value="item.id" />
</el-select>
<img src="@/assets/images/7.png" alt="" class="icon" />
<img src="@/assets/images/7.png"
alt=""
class="icon" />
</div>
<div class="select">
<el-select v-model="params.status" placeholder="产品进度" size="large">
<el-option v-for="item in params.roleId == 43 ? getExpertStatus() : productState.status" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="params.status"
placeholder="产品进度"
size="large">
<el-option v-for="item in params.roleId == 43 ? getExpertStatus() : productState.status"
:key="item.id"
:label="item.name"
:value="item.id" />
</el-select>
<img src="@/assets/images/8.png" alt="" class="icon" />
<img src="@/assets/images/8.png"
alt=""
class="icon" />
</div>
<div v-if="params.roleId == 41" class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
<div v-if="params.roleId == 41"
class="add-btn"
@click="toAdd">
<img src="@/assets/images/plus.png"
alt=""
class="icon" />
新增产品
</div>
<img src="@/assets/images/9.png" alt="" class="ml-4 cursor-pointer" @click="toCardList" />
<img src="@/assets/images/9.png"
alt=""
class="ml-4 cursor-pointer"
@click="toCardList" />
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @sort-change="handleSort">
<el-table-column prop="productName" label="产品名称" min-width="110"></el-table-column>
<el-table-column prop="productNumber" label="产品编号" min-width="80"></el-table-column>
<el-table-column v-if="params.roleId != 41" prop="loanCeiling" :label="params.roleId == 42 ? '贷款对象' : '产品对象'" min-width="80">
<el-table ref="table"
v-loading="loading"
:data="list"
@sort-change="handleSort">
<el-table-column prop="productName"
label="产品名称"
min-width="110"></el-table-column>
<el-table-column prop="productNumber"
label="产品编号"
min-width="80"></el-table-column>
<el-table-column v-if="params.roleId != 41"
prop="loanCeiling"
:label="params.roleId == 42 ? '贷款对象' : '产品对象'"
min-width="80">
<template #default="{ row }">
{{ row.productType ? '企业' : '个人' }}
</template>
</el-table-column>
<el-table-column prop="guarantyStyle" label="担保方式" min-width="80"></el-table-column>
<el-table-column prop="loanCeiling" label="最高额度/年利率/期限" min-width="110">
<el-table-column prop="guarantyStyle"
label="担保方式"
min-width="80"></el-table-column>
<el-table-column prop="loanCeiling"
label="最高额度/年利率/期限"
min-width="110">
<template #default="{ row }">
{{ row.loanCeiling + '万元/' + row.maximumAnnualInterestRate + '%/' + row.maximumTermOfLoan + '个月' }}
</template>
</el-table-column>
<el-table-column prop="operationTime" label="创建日期" sortable="custom" min-width="80"></el-table-column>
<el-table-column prop="status" label="产品进度" min-width="80">
<el-table-column prop="operationTime"
label="创建日期"
sortable="custom"
min-width="80"></el-table-column>
<el-table-column prop="status"
label="产品进度"
min-width="80">
<template #default="{ row }">
{{ getStatus(row.status) }}
</template>
</el-table-column>
<el-table-column prop="id" label="操作" min-width="110">
<el-table-column prop="id"
label="操作"
min-width="110">
<template #default="{ row }">
<el-button v-if="row.showDetailsOrNot" type="primary" link @click="toDetail(`/product/bank/detail`, row)" size="small">产品详情</el-button>
<el-button v-if="row.showElementsOrNot" type="primary" link size="small" @click="toDetail(`/product/bank/add`, row)">配置要素</el-button>
<el-button v-if="row.showRiskControlOrNot" type="primary" link size="small" @click="toDetail(`/product/bank/config`, row)">配置风控</el-button>
<el-popconfirm v-if="row.showDeleteOrNot" title="您确定删除吗?" @confirm.stop="handleDelete(row.id)">
<el-button v-if="row.showDetailsOrNot"
type="text"
@click="toDetail(`/product/bank/detail`, row)"
size="small">产品详情</el-button>
<el-button v-if="row.showElementsOrNot"
type="text"
size="small"
@click="toDetail(`/product/bank/add`, row)">配置要素</el-button>
<el-button v-if="row.showRiskControlOrNot"
type="text"
size="small"
@click="toDetail(`/product/bank/config`, row)">配置风控</el-button>
<el-popconfirm v-if="row.showDeleteOrNot"
title="您确定删除吗?"
@confirm.stop="handleDelete(row)">
<template #reference>
<el-button type="primary" link size="small" @click.stop="stop">删除</el-button>
<el-button type="text"
size="small"
@click.stop="stop">删除</el-button>
</template>
</el-popconfirm>
<el-button v-if="row.showApprovalOrNot" type="primary" link size="small" @click="toDetail(`/product/bank/approve`, row)">审批</el-button>
</template></el-table-column
>
<el-button v-if="row.showApprovalOrNot"
type="text"
size="small"
@click="toDetail(`/product/bank/approve`, row)">审批</el-button>
</template></el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</template>
@ -143,10 +202,8 @@ const initList = async () => {
getList();
};
onMounted(() => {
if (!Cookies.get('sand-submit')) {
getGuarantee();
getList();
}
getGuarantee();
getList();
});
watch([params, () => route.query], initList);

@ -1,26 +1,44 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane :label="id ? '产品要素' : '新增产品'" name="tab1">
<el-form label-width="100px" label-suffix="" class="max-w-[calc(100vw-540px)] lg:max-w-[calc(100vw-423px)] overflow-auto form" status-icon>
<el-form-item label="基金名称" prop="fundName">
<el-input placeholder="取个有吸引力的产品名,限20字。" maxlength="20" v-model="form.fundName"></el-input>
<el-tab-pane :label="id ? '产品要素' : '新增产品'"
name="tab1">
<el-form label-width="100px"
label-suffix=":"
class="max-w-[calc(100vw-540px)] overflow-auto form"
status-icon>
<el-form-item label="基金名称"
prop="fundName">
<el-input placeholder="取个有吸引力的产品名,限20字。"
maxlength="20"
v-model="form.fundName"></el-input>
</el-form-item>
<el-form-item label="基金类型" prop="fundType">
<el-select v-model="form.fundType" placeholder="请选择">
<el-option v-for="item in config[1]?.subject?.itemList" :key="item" :label="item.options" :value="item.itemId" />
<el-form-item label="基金类型"
prop="fundType">
<el-select v-model="form.fundType"
placeholder="请选择">
<el-option v-for="item in config[1]?.subject?.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</el-form-item>
<el-form-item label="募集规模">
<div>
<el-input placeholder="请输入" v-model="form.fundraisingScale">
<el-input placeholder="请输入"
v-model="form.fundraisingScale">
<template #append>万元</template>
</el-input>
</div>
</el-form-item>
<el-form-item label="运作方式" prop="modeOfOperation">
<el-select v-model="form.modeOfOperation" placeholder="请选择">
<el-option v-for="item in config[3]?.subject?.itemList" :key="item" :label="item.options" :value="item.itemId" />
<el-form-item label="运作方式"
prop="modeOfOperation">
<el-select v-model="form.modeOfOperation"
placeholder="请选择">
<el-option v-for="item in config[3]?.subject?.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</el-form-item>
<el-form-item label="持股配置">
@ -30,30 +48,37 @@
<p class="field-name w-[300px] mr-32">股票</p>
<p class="field-name w-[100px] mr-32">比重(%)</p>
<div class="field-name">
<el-icon class="cursor-pointer" :size="16" color="#333" @click="addStock">
<el-icon class="cursor-pointer"
:size="16"
color="#333"
@click="addStock">
<Plus />
</el-icon>
</div>
</div>
<div v-for="(item, i) in form.shareholdingAllocationsList" :key="i" class="flex items-center mb-2">
<div v-for="(item, i) in form.shareholdingAllocationsList"
:key="i"
class="flex items-center mb-2">
<div class="w-[300px] mr-32">
<el-select-v2
class="w-full"
v-model="item.stockCode"
filterable
remote
:remote-method="(val) => remoteMethod(val, item)"
clearable
:options="item.stocks"
:loading="loading"
placeholder="请输入A股代码或者名称"
/>
<el-select-v2 class="w-full"
v-model="item.stockCode"
filterable
remote
:remote-method="val => remoteMethod(val, item)"
clearable
:options="item.stocks"
:loading="loading"
placeholder="请输入A股代码或者名称" />
</div>
<div class="w-[100px] mr-32">
<el-input placeholder="请输入" v-model="item.proportion"></el-input>
<el-input placeholder="请输入"
v-model="item.proportion"></el-input>
</div>
<div>
<el-icon class="cursor-pointer" :size="16" color="#333" @click="delStock(i)">
<el-icon class="cursor-pointer"
:size="16"
color="#333"
@click="delStock(i)">
<Minus />
</el-icon>
</div>
@ -66,17 +91,29 @@
<!-- 份额时长 -->
<div class="flex items-center mb-3">
客户T时买入T+
<el-input class="w-[100px] mx-2" placeholder="请输入" v-model="form.buyingDuration"></el-input>
<el-select class="w-[100px] mr-2" v-model="form.buyingUnit" placeholder="请选择">
<el-option v-for="item in config[5]?.recordChildren[0]?.recordChildren[1]?.subject?.itemList" :key="item" :value="item.options" />
<el-input class="w-[100px] mx-2"
placeholder="请输入"
v-model="form.buyingDuration"></el-input>
<el-select class="w-[100px] mr-2"
v-model="form.buyingUnit"
placeholder="请选择">
<el-option v-for="item in config[5]?.recordChildren[0]?.recordChildren[1]?.subject?.itemList"
:key="item"
:value="item.options" />
</el-select>
确认申购份额期间资金进入冻结账户
</div>
<div class="flex items-center">
客户T时卖出T+
<el-input class="w-[90px] mx-2" placeholder="请输入" v-model="form.sellingTime"></el-input>
<el-select class="w-[90px] mr-2" v-model="form.soldUnit" placeholder="请选择">
<el-option v-for="item in config[5]?.recordChildren[0]?.recordChildren[1]?.subject?.itemList" :key="item" :value="item.options" />
<el-input class="w-[100px] mx-2"
placeholder="请输入"
v-model="form.sellingTime"></el-input>
<el-select class="w-[100px] mr-2"
v-model="form.soldUnit"
placeholder="请选择">
<el-option v-for="item in config[5]?.recordChildren[0]?.recordChildren[1]?.subject?.itemList"
:key="item"
:value="item.options" />
</el-select>
确认赎回金额期间资金进入冻结账户
</div>
@ -85,35 +122,60 @@
<p class="mt-10 mb-2 text-xs text-[#ef3838]">买入费率单笔费率应小于5.00%5000</p>
<div class="flex">
<p class="field-name w-[400px] mr-32">金额</p>
<p class="field-name w-[90px] mr-32 xl:mr-10">费率</p>
<p class="field-name w-[100px] mr-32">费率</p>
<div class="field-name">
<el-icon class="cursor-pointer" :size="16" color="#333" @click="addRatio(0)">
<el-icon class="cursor-pointer"
:size="16"
color="#333"
@click="addRatio(0)">
<Plus />
</el-icon>
</div>
</div>
<div v-for="(item, i) in form.buySellRatioList0" :key="i" class="flex items-center mb-2">
<div class="w-[390px] mr-10">
<el-input v-if="i" class="w-[90px] mr-2" placeholder="请输入" disabled v-model="form.buySellRatioList0[i - 1].input2"></el-input>
<el-input v-else class="w-[90px] mr-2" placeholder="请输入" disabled v-model="item.input1"></el-input>
<div v-for="(item, i) in form.buySellRatioList0"
:key="i"
class="flex items-center mb-2">
<div class="w-[400px] mr-10">
<el-input v-if="i"
class="w-[100px] mr-2"
placeholder="请输入"
disabled
v-model="form.buySellRatioList0[i - 1].input2"></el-input>
<el-input v-else
class="w-[100px] mr-2"
placeholder="请输入"
disabled
v-model="item.input1"></el-input>
{{ i ? '万' : '&emsp;' }}
<span class="mx-2"> &lt;= 买入金额</span>
<span class="mx-2">
&lt;= 买入金额</span>
<template v-if="i !== form.buySellRatioList0.length - 1">
&lt;
<el-input class="w-[90px] mx-2" placeholder="请输入" v-model="item.input2"></el-input>
<el-input class="w-[100px] mx-2"
placeholder="请输入"
v-model="item.input2"></el-input>
</template>
</div>
<div class="mr-32 xl:mr-10">
<el-input class="w-[90px] mr-2" placeholder="请输入" v-model="item.rate"></el-input>
<el-select class="w-[90px]" v-model="item.rateUnit" placeholder="请选择">
<el-option v-for="item in units" :key="item" :value="item" />
<div class="mr-32">
<el-input class="w-[100px] mr-2"
placeholder="请输入"
v-model="item.rate"></el-input>
<el-select class="w-[90px]"
v-model="item.rateUnit"
placeholder="请选择">
<el-option v-for="item in units"
:key="item"
:value="item" />
</el-select>
</div>
<div v-if="i">
<el-icon class="cursor-pointer" :size="16" color="#333" @click="delRatio(0, i)">
<el-icon class="cursor-pointer"
:size="16"
color="#333"
@click="delRatio(0, i)">
<Minus />
</el-icon>
</div>
@ -129,15 +191,21 @@
<p class="mt-10 mb-2 text-xs text-[#ef3838]">运作费率单笔费率应小于5.00%</p>
<div class="flex">
<span class="w-[140px]">管理费</span>
<el-input class="w-[100px] mr-2" placeholder="请输入" v-model="form.operationManagementRate"></el-input>%
<el-input class="w-[100px] mr-2"
placeholder="请输入"
v-model="form.operationManagementRate"></el-input>%
</div>
<div class="flex my-2">
<span class="w-[140px]">托管费</span>
<el-input class="w-[100px] mr-2" placeholder="请输入" v-model="form.operatingEscrowRate"></el-input>%
<el-input class="w-[100px] mr-2"
placeholder="请输入"
v-model="form.operatingEscrowRate"></el-input>%
</div>
<div class="flex">
<span class="w-[140px]">销售服务费</span>
<el-input class="w-[100px] mr-2" placeholder="请输入" v-model="form.operatingSalesServiceRates"></el-input>%
<el-input class="w-[100px] mr-2"
placeholder="请输入"
v-model="form.operatingSalesServiceRates"></el-input>%
</div>
<div class="mt-5 text-xs text-[#7a7a7a]">
<p>运作费计算</p>
@ -149,43 +217,78 @@
<!-- 赎回费率 -->
<p class="mt-10 mb-2 text-xs text-[#ef3838]">赎回费率单笔费率应小于5.00%5000</p>
<div class="flex">
<p class="field-name w-[600px] mr-32 xl:w-[540px] xl:mr-20">持有时长</p>
<p class="field-name w-[90px] mr-20 xl:mr-10">费率</p>
<p class="field-name w-[600px] mr-32">持有时长</p>
<p class="field-name w-[100px] mr-32">费率</p>
<div class="field-name">
<el-icon class="cursor-pointer" :size="16" color="#333" @click="addRatio(1)">
<el-icon class="cursor-pointer"
:size="16"
color="#333"
@click="addRatio(1)">
<Plus />
</el-icon>
</div>
</div>
<div v-for="(item, i) in form.buySellRatioList1" :key="i" class="flex items-center mb-2">
<div class="w-[590px] mr-10 xl:w-[538px] xl:mr-0">
<el-input v-if="i" class="w-[90px] mr-2" placeholder="请输入" disabled v-model="form.buySellRatioList1[i - 1].input2"></el-input>
<el-input v-else class="w-[90px] mr-[98px]" placeholder="请输入" disabled v-model="item.input1"></el-input>
<div v-for="(item, i) in form.buySellRatioList1"
:key="i"
class="flex items-center mb-2">
<div class="w-[600px] mr-10">
<el-input v-if="i"
class="w-[100px] mr-2"
placeholder="请输入"
disabled
v-model="form.buySellRatioList1[i - 1].input2"></el-input>
<el-input v-else
class="w-[100px] mr-[108px]"
placeholder="请输入"
disabled
v-model="item.input1"></el-input>
<el-select v-if="i" class="w-[90px]" v-model="form.buySellRatioList1[i - 1].soldUnit2" placeholder="请选择" disabled>
<el-option v-for="item in times" :key="item" :value="item" />
<el-select v-if="i"
class="w-[100px]"
v-model="form.buySellRatioList1[i - 1].soldUnit2"
placeholder="请选择"
disabled>
<el-option v-for="item in times"
:key="item"
:value="item" />
</el-select>
<span class="mx-2"> &lt;= 持有时长</span>
<span class="mx-2">
&lt;= 持有时长</span>
<template v-if="i !== form.buySellRatioList1.length - 1">
&lt;
<el-input class="w-[90px] mx-2" placeholder="请输入" v-model="item.input2"></el-input>
<el-input class="w-[100px] mx-2"
placeholder="请输入"
v-model="item.input2"></el-input>
<el-select class="w-[90px]" v-model="item.soldUnit2" placeholder="请选择">
<el-option v-for="item in times" :key="item" :value="item" />
<el-select class="w-[100px]"
v-model="item.soldUnit2"
placeholder="请选择">
<el-option v-for="item in times"
:key="item"
:value="item" />
</el-select>
</template>
</div>
<div class="min-w-[190px] mr-20 xl:mr-6">
<el-input class="w-[90px] mr-2" placeholder="请输入" v-model="item.rate"></el-input>
<el-select class="w-[90px]" v-model="item.rateUnit" placeholder="请选择">
<el-option v-for="item in units" :key="item" :value="item" />
<div class="mr-32">
<el-input class="w-[100px] mr-2"
placeholder="请输入"
v-model="item.rate"></el-input>
<el-select class="w-[90px]"
v-model="item.rateUnit"
placeholder="请选择">
<el-option v-for="item in units"
:key="item"
:value="item" />
</el-select>
</div>
<div v-if="i">
<el-icon class="cursor-pointer" :size="16" color="#333" @click="delRatio(1, i)">
<el-icon class="cursor-pointer"
:size="16"
color="#333"
@click="delRatio(1, i)">
<Minus />
</el-icon>
</div>
@ -198,7 +301,8 @@
</div>
</el-form-item>
<div class="flex justify-end">
<div class="submit" @click="submit">完成</div>
<div class="submit"
@click="submit">完成</div>
</div>
</el-form>
</el-tab-pane>
@ -207,7 +311,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, defineEmits } from 'vue';
import { ref, reactive, computed, watch, onMounted, defineEmits } from 'vue';
import { ElMessage } from 'element-plus';
import { Plus, Minus } from '@element-plus/icons-vue';
import { getAListOfAShares, saveFund } from '@/api/fund';
@ -333,7 +437,7 @@ const remoteMethod = (query: string, item: Record<string, any>) => {
//
const addRatio = (type: number) => {
if (form[`buySellRatioList${type}`].length === 5) {
if (form['buySellRatioList' + type].length === 5) {
ElMessage.error('规则最多只能添加5条!');
} else {
const temp = {
@ -347,12 +451,12 @@ const addRatio = (type: number) => {
temp.soldUnit1 = '';
temp.soldUnit2 = '';
}
form[`buySellRatioList${type}`].push(temp);
form['buySellRatioList' + type].push(temp);
}
};
//
const delRatio = (type: number, i: number) => {
form[`buySellRatioList${type}`].length > 1 && form[`buySellRatioList${type}`].splice(i, 1);
form['buySellRatioList' + type].length > 1 && form['buySellRatioList' + type].splice(i, 1);
};
const getId = (str: string): string | number => {
@ -363,10 +467,10 @@ const getId = (str: string): string | number => {
const addRecord = async (data: Record<string, any>) => {
const preIds = `1,${levelId},1161`; // 1id
const rule = [
handleId(1162, 308, data.fundName, `${preIds},1162`, 3),
handleId(1163, 309, 764, `${preIds},1163`, 1),
handleId(1164, 310, data.fundraisingScale, `${preIds},1164`, 3),
handleId(1165, 311, 765, `${preIds},1165`, 1),
handleId(1162, 308, data.fundName, preIds + ',1162', 3),
handleId(1163, 309, 764, preIds + ',1163', 1),
handleId(1164, 310, data.fundraisingScale, preIds + ',1164', 3),
handleId(1165, 311, 765, preIds + ',1165', 1),
];
const stockId = 1167;
@ -375,10 +479,10 @@ const addRecord = async (data: Record<string, any>) => {
rule.push(handleId(1178, 313, e.proportion, `${preIds},1166,${stockId + i},1178`, 3));
});
rule.push(
handleId(1181, 314, data.buyingDuration, `${preIds},1179,1180,1181`, 3),
handleId(1182, 315, getId(data.buyingUnit), `${preIds},1179,1180,1182`, 1),
handleId(1184, 314, data.sellingTime, `${preIds},1179,1183,1184`, 3),
handleId(1185, 315, getId(data.soldUnit), `${preIds},1179,1183,1185`, 1),
handleId(1181, 314, data.buyingDuration, preIds + ',1179,1180,1181', 3),
handleId(1182, 315, getId(data.buyingUnit), preIds + ',1179,1180,1182', 1),
handleId(1184, 314, data.sellingTime, preIds + ',1179,1183,1184', 3),
handleId(1185, 315, getId(data.soldUnit), preIds + ',1179,1183,1185', 1),
);
//
@ -396,9 +500,9 @@ const addRecord = async (data: Record<string, any>) => {
});
rule.push(
handleId(1196, 319, data.operationManagementRate, `${preIds},1179,1195,1196`, 3),
handleId(1197, 320, data.operatingEscrowRate, `${preIds},1179,1195,1197`, 3),
handleId(1198, 321, data.operatingSalesServiceRates, `${preIds},1179,1195,1198`, 3),
handleId(1196, 319, data.operationManagementRate, preIds + ',1179,1195,1196', 3),
handleId(1197, 320, data.operatingEscrowRate, preIds + ',1179,1195,1197', 3),
handleId(1198, 321, data.operatingSalesServiceRates, preIds + ',1179,1195,1198', 3),
);
await addOperation({
@ -441,7 +545,7 @@ const submit = async () => {
//
param.buySellRatioList0.forEach((e, i) => {
e.amountOrDuration = `${i ? param.buySellRatioList0[i - 1].input2 : e.input1}${i !== param.buySellRatioList0.length - 1 ? `~${e.input2}` : ''}`;
e.amountOrDuration = (i ? param.buySellRatioList0[i - 1].input2 : e.input1) + `${i !== param.buySellRatioList0.length - 1 ? '~' + e.input2 : ''}`;
});
param.buySellRatioList1.forEach((e, i) => {
e.amountOrDuration = i ? param.buySellRatioList1[i - 1].input2 + param.buySellRatioList1[i - 1].soldUnit2 : e.input1;
@ -453,7 +557,7 @@ const submit = async () => {
delete param.buySellRatioList0;
delete param.buySellRatioList1;
const res = await saveFund(param);
router.push(`/product/fund/detail?id=${res.message}`);
router.push(`/product/fund/detail?id=` + res.message);
addRecord(recordParam);
ElMessage.success('提交成功!');
emit('getList');
@ -461,9 +565,7 @@ const submit = async () => {
}
};
onMounted(() => {
if (!Cookies.get('sand-submit')) {
getConfig();
}
getConfig();
});
</script>

@ -1,23 +1,32 @@
<template>
<div class="block card-list flex py-0">
<div class="left">
<div
class="flex justify-center items-center py-2 mb-3 text-sm text-[#006BFF] bg-[rgba(0,107,255,0.1)] border border-solid border-[#006BFF] rounded-[10px] cursor-pointer"
@click="toAdd"
>
<el-icon class="mr-1" :size="16" color="#006BFF">
<div class="flex justify-center items-center py-2 mb-3 text-sm text-[#006BFF] bg-[rgba(0,107,255,0.1)] border border-solid border-[#006BFF] rounded-[10px] cursor-pointer"
@click="toAdd">
<el-icon class="mr-1"
:size="16"
color="#006BFF">
<Plus />
</el-icon>
新增产品
</div>
<div class="flex justify-end mb-4">
<img src="@/assets/images/fold.png" alt="" class="cursor-pointer" @click="toList" />
<img src="@/assets/images/fold.png"
alt=""
class="cursor-pointer"
@click="toList" />
</div>
<ul class="products">
<li v-for="(item, i) in list" :key="i" :class="{ active: item.id === id }" @click="switchProduct(item.id)">
<el-popconfirm title="您确定删除吗?" @confirm="handleDelete(item.id)">
<li v-for="(item, i) in list"
:key="i"
:class="{ active: item.id === id }"
@click="switchProduct(item.id)">
<el-popconfirm title="您确定删除吗?"
@confirm="handleDelete(item.id)">
<template #reference>
<img src="@/assets/images/trash.png" alt="" class="del" />
<img src="@/assets/images/trash.png"
alt=""
class="del" />
</template>
</el-popconfirm>
@ -30,7 +39,8 @@
</div>
<div class="right">
<detail v-if="action === 'detail'"></detail>
<add v-else-if="action === 'add'" @getList="getList"></add>
<add v-else-if="action === 'add'"
@getList="getList"></add>
</div>
</div>
</template>
@ -41,10 +51,10 @@ import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
import { fundProductList, batchDeletion } from '@/api/fund';
import { useRouter, useRoute } from 'vue-router';
import Cookies from 'js-cookie';
import { getIds } from '@/utils/common';
import Detail from './Detail.vue';
import Add from './Add.vue';
import Cookies from 'js-cookie';
import { getIds } from '@/utils/common';
const router = useRouter();
const route = useRoute();
@ -55,21 +65,19 @@ const loading = ref<boolean>(false);
const id = computed(() => +route.query.id);
//
const getList = async (refresh?: number) => {
if (!Cookies.get('sand-submit')) {
loading.value = true;
try {
const { data } = await fundProductList({
...getIds(),
pageNum: 1,
pageSize: 1000,
fundName: route.query.name ?? '',
createDateSort: route.query.createDateSort ?? '',
});
list.value = data.data.records;
refresh && list.value.length && switchProduct(list.value[0].id);
} finally {
loading.value = false;
}
loading.value = true;
try {
const { data } = await fundProductList({
...getIds(),
pageNum: 1,
pageSize: 1000,
fundName: route.query.name ?? '',
createDateSort: route.query.createDateSort ?? '',
});
list.value = data.data.records;
refresh && list.value.length && switchProduct(list.value[0].id);
} finally {
loading.value = false;
}
};
onMounted(() => {
@ -87,7 +95,7 @@ watch(
);
//
const switchProduct = (fundId: number) => {
router.push(`/product/fund/detail?id=${fundId}`);
router.push(`/product/fund/detail?id=` + fundId);
};
//
const toAdd = () => {

@ -1,7 +1,8 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane label="产品详情" name="tab1">
<el-tab-pane label="产品详情"
name="tab1">
<info />
</el-tab-pane>
</el-tabs>

@ -10,7 +10,9 @@
<p class="w-[130px] mr-32">股票</p>
<p class="">比重(%)</p>
</div>
<div v-for="(item, i) in info.shareholdingAllocationsList" :key="item" class="flex">
<div v-for="(item, i) in info.shareholdingAllocationsList"
:key="item"
class="flex">
<p class="w-[130px] mr-32">{{ item.stockName }}({{ item.stockCode }})</p>
<p class="">{{ item.proportion }}</p>
</div>
@ -25,9 +27,12 @@
<p class="w-[130px] mr-32">金额</p>
<p class="">费率</p>
</div>
<div v-for="(item, i) in info.purchaseRateList" :key="item" class="flex">
<div v-for="(item, i) in info.purchaseRateList"
:key="item"
class="flex">
<p class="w-[130px] mr-32">{{ item.amountOrDuration }}</p>
<p class="">{{ item.rate }}{{ item.rateUnit }}</p>
<p class="">{{ item.rate }}{{ item.rateUnit
}}</p>
</div>
</div>
@ -41,7 +46,9 @@
<p class="w-[130px] mr-32">持有时长</p>
<p class="">费率</p>
</div>
<div v-for="(item, i) in info.sellingRateList" :key="item" class="flex">
<div v-for="(item, i) in info.sellingRateList"
:key="item"
class="flex">
<p class="w-[130px] mr-32">{{ item.amountOrDuration }}</p>
<p class="">{{ item.rate }}{{ item.rateUnit }}</p>
</div>
@ -50,18 +57,18 @@
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { ref, computed, watch, onMounted } from 'vue';
import { findById } from '@/api/fund';
import { useRoute } from 'vue-router';
import Cookies from 'js-cookie';
import { useRouter, useRoute } from 'vue-router';
const router = useRouter();
const route = useRoute();
const id = computed(() => +route.query.id);
const info = ref<Record<string, any>>({});
//
const getDetail = async () => {
if (id.value && !Cookies.get('sand-submit')) {
if (id.value) {
try {
const { data } = await findById(id.value);
info.value = data;

@ -1,47 +1,76 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="params.fundName" @change="initList"></search>
<search v-model="params.fundName"
@change="initList"></search>
<div class="filter">
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
<div class="add-btn"
@click="toAdd">
<img src="@/assets/images/plus.png"
alt=""
class="icon" />
新增产品
</div>
<img src="@/assets/images/9.png" alt="" class="ml-4 cursor-pointer" @click="toCardList" />
<img src="@/assets/images/9.png"
alt=""
class="ml-4 cursor-pointer"
@click="toCardList" />
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @sort-change="handleSort">
<el-table-column prop="fundName" label="基金名称" min-width="150"></el-table-column>
<el-table-column prop="fundCode" label="基金代码" min-width="100"></el-table-column>
<el-table-column prop="fundType" label="基金类型" min-width="100"></el-table-column>
<el-table-column prop="fundraisingScale" label="募集规模" min-width="100"></el-table-column>
<el-table-column prop="modeOfOperation" label="运作方式" min-width="100"></el-table-column>
<el-table-column prop="buying" label="买入费率" min-width="120"></el-table-column>
<el-table-column prop="sale" label="赎回费率" min-width="120"></el-table-column>
<el-table-column prop="operationTime" label="创建日期" width="180" sortable="custom"></el-table-column>
<el-table-column label="操作" width="140">
<el-table ref="table"
v-loading="loading"
:data="list"
@sort-change="handleSort">
<el-table-column prop="fundName"
label="基金名称"
min-width="150"></el-table-column>
<el-table-column prop="fundCode"
label="基金代码"
min-width="100"></el-table-column>
<el-table-column prop="fundType"
label="基金类型"
min-width="100"></el-table-column>
<el-table-column prop="fundraisingScale"
label="募集规模"
min-width="100"></el-table-column>
<el-table-column prop="modeOfOperation"
label="运作方式"
min-width="100"></el-table-column>
<el-table-column prop="buying"
label="买入费率"
min-width="120"></el-table-column>
<el-table-column prop="sale"
label="赎回费率"
min-width="120"></el-table-column>
<el-table-column prop="operationTime"
label="创建日期"
width="180"
sortable="custom"></el-table-column>
<el-table-column label="操作"
width="140">
<template #default="{ row }">
<el-popconfirm title="您确定删除吗?" @confirm.stop="handleDelete(row.id)">
<el-popconfirm title="您确定删除吗?"
@confirm.stop="handleDelete(row.id)">
<template #reference>
<el-button type="primary" link size="small">删除</el-button>
<el-button type="text"
size="small">删除</el-button>
</template>
</el-popconfirm>
<el-button type="primary" link @click="toDetail(`/product/fund/detail`, row.id)" size="small">产品详情</el-button>
</template></el-table-column
>
<el-button type="text"
@click="toDetail(`/product/fund/detail`, row.id)"
size="small">产品详情</el-button>
</template></el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</template>
@ -72,15 +101,13 @@ const list = ref<Record<string, any>[]>([]);
const loading = ref<boolean>(false);
//
const getList = async () => {
if (!Cookies.get('sand-submit')) {
loading.value = true;
try {
const { data } = await fundProductList({ pageNum: currentPage.value, pageSize: pageSize.value, ...toParams(params) });
list.value = data.data.records;
total.value = data.data.total;
} finally {
loading.value = false;
}
loading.value = true;
try {
const { data } = await fundProductList({ pageNum: currentPage.value, pageSize: pageSize.value, ...toParams(params) });
list.value = data.data.records;
total.value = data.data.total;
} finally {
loading.value = false;
}
};
//

@ -1,22 +1,37 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane :label="id ? '产品要素' : '新增产品'" name="tab1">
<el-form label-width="100px" label-suffix="" class="max-w-[calc(100vw-540px)] lg:max-w-[calc(100vw-423px)] overflow-auto form" status-icon>
<el-form-item label="保险名称" prop="insuranceName">
<el-input placeholder="取个有吸引力的产品名,限20字。" maxlength="20" v-model="form.insuranceName"></el-input>
<el-tab-pane :label="id ? '产品要素' : '新增产品'"
name="tab1">
<el-form label-width="100px"
label-suffix=":"
class="max-w-[calc(100vw-540px)] overflow-auto form"
status-icon>
<el-form-item label="保险名称"
prop="insuranceName">
<el-input placeholder="取个有吸引力的产品名,限20字。"
maxlength="20"
v-model="form.insuranceName"></el-input>
</el-form-item>
<el-form-item label="险种分类" prop="insuranceType">
<el-select v-model="form.insuranceType" placeholder="请选择">
<el-option v-for="item in config[0]?.recordChildren[1]?.subject?.itemList" :key="item" :label="item.options" :value="item.itemId" />
<el-form-item label="险种分类"
prop="insuranceType">
<el-select v-model="form.insuranceType"
placeholder="请选择">
<el-option v-for="item in config[0]?.recordChildren[1]?.subject?.itemList"
:key="item"
:label="item.options"
:value="item.itemId" />
</el-select>
</el-form-item>
<el-form-item v-if="form.insuranceType === 310" label="承保年龄">
<el-form-item v-if="form.insuranceType === 310"
label="承保年龄">
<div class="flex items-center">
<div class="num-inputs">
<el-input placeholder="最小年龄" v-model.number="form.minimumAge"></el-input>
<el-input placeholder="最小年龄"
v-model.number="form.minimumAge"></el-input>
<span class="split">-</span>
<el-input placeholder="最大年龄" v-model.number="form.maximumAge"></el-input>
<el-input placeholder="最大年龄"
v-model.number="form.maximumAge"></el-input>
<span class="unit">周岁</span>
</div>
</div>
@ -27,50 +42,68 @@
<p class="field-name w-[130px] mr-32">保险责任</p>
<p class="field-name">保额</p>
</div>
<div v-for="(item, i) in config[form.insuranceType === 310 ? 0 : 1]?.recordChildren[2]?.recordChildren" :key="i" class="flex items-center mb-2">
<div v-for="(item, i) in config[form.insuranceType === 310 ? 0 : 1]?.recordChildren[2]?.recordChildren"
:key="i"
class="flex items-center mb-2">
<div class="w-[130px] mr-32">
<el-checkbox :key="item.id" v-model="item.check" :label="item.name" />
<el-checkbox :key="item.id"
v-model="item.check"
:label="item.name" />
</div>
<div v-if="item.check">
<el-input placeholder="请输入" v-model="item.sumInsured">
<el-input placeholder="请输入"
v-model="item.sumInsured">
<template #append>{{ item.id === 764 || item.id === 765 ? '元' : '万' }}</template>
</el-input>
</div>
</div>
</div>
</el-form-item>
<el-form-item label="保费金额" prop="minimumLoan">
<el-form-item label="保费金额"
prop="minimumLoan">
<div>
<el-input placeholder="请输入" v-model="form.premiumAmount">
<el-input placeholder="请输入"
v-model="form.premiumAmount">
<template #append></template>
</el-input>
</div>
</el-form-item>
<el-form-item label="缴纳形式">
<el-radio :label="312" v-model="form.formOfPayment">趸交</el-radio>
<el-radio :label="312"
v-model="form.formOfPayment">趸交</el-radio>
</el-form-item>
<el-form-item label="保险期限">
<div class="flex">
<el-input class="mr-2" placeholder="请输入" v-model="form.insuranceDeadline"></el-input>
<el-select v-model="form.insuranceDeadlineUnit" placeholder="请选择" clearable>
<el-option v-for="item in units" :key="item" :label="item" :value="item" />
<el-input class="mr-2"
placeholder="请输入"
v-model="form.insuranceDeadline"></el-input>
<el-select v-model="form.insuranceDeadlineUnit"
placeholder="请选择"
clearable>
<el-option v-for="item in units"
:key="item"
:label="item"
:value="item" />
</el-select>
</div>
</el-form-item>
<el-form-item label="申请材料">
<el-checkbox-group v-model="form.applicationMaterial">
<el-checkbox v-for="(item, i) in config[form.insuranceType === 310 ? 0 : 1]?.recordChildren[6]?.subject?.itemList" :key="i" :label="item.itemId">{{
item.options
}}</el-checkbox>
<el-checkbox v-for="(item, i) in config[form.insuranceType === 310 ? 0 : 1]?.recordChildren[6]?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="责任免除">
<el-checkbox-group v-model="form.exemptionFromLiability">
<el-checkbox v-for="(item, i) in config[0]?.recordChildren[7]?.subject?.itemList" :key="i" :label="item.itemId">{{ item.options }}</el-checkbox>
<el-checkbox v-for="(item, i) in config[0]?.recordChildren[7]?.subject?.itemList"
:key="i"
:label="item.itemId">{{ item.options }}</el-checkbox>
</el-checkbox-group>
</el-form-item>
<div class="flex justify-end">
<div class="submit" @click="submit">完成</div>
<div class="submit"
@click="submit">完成</div>
</div>
</el-form>
</el-tab-pane>
@ -113,14 +146,12 @@ const form = reactive({
//
const getConfig = async () => {
if (!Cookies.get('sand-submit')) {
const { process } = await getProcessInformationBasedOnRoles(275);
config.value = process;
}
const { process } = await getProcessInformationBasedOnRoles(275);
config.value = process;
};
//
const getDetail = async () => {
if (id.value && !Cookies.get('sand-submit')) {
if (id.value) {
try {
const { data } = await insuranceProductDetails(id.value);
info.value = data;
@ -141,30 +172,30 @@ watch(
const addRecord = async (data: Record<string, any>) => {
const isAcci = data.insuranceType === 310; //
const preIds = `1,${Cookies.get('sand-level')},275,${isAcci ? 276 : 277}`; // 1id
const rule: Array<Record<string, any>> = [handleId(278, 118, data.insuranceName, `${preIds},278`, 3), handleId(279, 119, data.insuranceType, `${preIds},279`, 1)];
data.minimumAge && rule.push(handleId(680, 219, data.minimumAge, `${preIds},678,680`, 3));
data.maximumAge && rule.push(handleId(679, 218, data.maximumAge, `${preIds},678,679`, 3));
const rule: Array<Record<string, any>> = [handleId(278, 118, data.insuranceName, preIds + ',278', 3), handleId(279, 119, data.insuranceType, preIds + ',279', 1)];
data.minimumAge && rule.push(handleId(680, 219, data.minimumAge, preIds + ',678,680', 3));
data.maximumAge && rule.push(handleId(679, 218, data.maximumAge, preIds + ',678,679', 3));
//
config.value[form.insuranceType === 310 ? 0 : 1]?.recordChildren[2]?.recordChildren?.map((e) => {
rule.push(handleId(isAcci ? 766 : 768, 140, e.check ? 345 : 346, `${preIds},${isAcci ? 280 : 288},${e.id},${isAcci ? 766 : 768}`, 1));
e.check && e.sumInsured && rule.push(handleId(isAcci ? 767 : 769, 234, e.sumInsured, `${preIds},${isAcci ? 280 : 288},${e.id},${isAcci ? 767 : 769}`, 3));
});
data.premiumAmount && rule.push(handleId(296, 134, data.premiumAmount, `${preIds},296`, 3));
data.formOfPayment && rule.push(handleId(297, 135, data.formOfPayment, `${preIds},297`, 1));
data.premiumAmount && rule.push(handleId(296, 134, data.premiumAmount, preIds + ',296', 3));
data.formOfPayment && rule.push(handleId(297, 135, data.formOfPayment, preIds + ',297', 1));
form.insuranceDeadline && rule.push(handleId(770, 136, form.insuranceDeadline, `${preIds},298,770`, 3));
form.insuranceDeadline && rule.push(handleId(770, 136, form.insuranceDeadline, preIds + ',298,770', 3));
form.insuranceDeadlineUnit &&
rule.push(
handleId(
771,
235,
config.value[form.insuranceType === 310 ? 0 : 1]?.recordChildren[5]?.recordChildren[1]?.subject?.itemList?.find((e) => e.options === form.insuranceDeadlineUnit)?.itemId,
`${preIds},298,771`,
preIds + ',298,771',
1,
),
);
data.applicationMaterial && rule.push(handleId(isAcci ? 299 : 300, isAcci ? 137 : 138, data.applicationMaterial, `${preIds},${isAcci ? 299 : 300}`, 1));
data.exemptionFromLiability && rule.push(handleId(301, 139, data.exemptionFromLiability, `${preIds},301`, 1));
data.exemptionFromLiability && rule.push(handleId(301, 139, data.exemptionFromLiability, preIds + ',301', 1));
await addOperation({
...getIds(),
@ -203,19 +234,19 @@ const submit = async () => {
if (!param.insuranceCoverageConfigList.length) return ElMessage.error('请至少输入一项保险额度');
if (isIllegalNum(param.premiumAmount)) {
return ElMessage.error('请输入合理的保费金额');
} else {
param.premiumAmount = Math.round(Number(param.premiumAmount) * 100) / 100;
}
param.premiumAmount = Math.round(Number(param.premiumAmount) * 100) / 100;
if (!param.formOfPayment) return ElMessage.error('请选择缴纳形式');
if (isIllegalNum(param.insuranceDeadline)) return ElMessage.error('请输入合理的保险期限');
if (!param.insuranceDeadlineUnit) return ElMessage.error('请选择保险期限');
param.insuranceDeadline += param.insuranceDeadlineUnit;
param.insuranceDeadline = param.insuranceDeadline + param.insuranceDeadlineUnit;
if (!param.applicationMaterial.length) return ElMessage.error('请至少选择一项申请材料');
if (!param.exemptionFromLiability.length) return ElMessage.error('请至少选择一项责任免除');
param.applicationMaterial = param.applicationMaterial.join();
param.exemptionFromLiability = param.exemptionFromLiability.join();
const res = await addInsuranceProducts(param);
router.push(`/product/insurance/detail?id=${res.message}`);
router.push(`/product/insurance/detail?id=` + res.message);
addRecord(param);
ElMessage.success('提交成功!');
emit('getList');

@ -1,36 +1,48 @@
<template>
<div class="block card-list flex py-0">
<div class="left">
<div
class="flex justify-center items-center py-2 mb-3 text-sm text-[#006BFF] bg-[rgba(0,107,255,0.1)] border border-solid border-[#006BFF] rounded-[10px] cursor-pointer"
@click="toAdd"
>
<el-icon class="mr-1" :size="16" color="#006BFF">
<div class="flex justify-center items-center py-2 mb-3 text-sm text-[#006BFF] bg-[rgba(0,107,255,0.1)] border border-solid border-[#006BFF] rounded-[10px] cursor-pointer"
@click="toAdd">
<el-icon class="mr-1"
:size="16"
color="#006BFF">
<Plus />
</el-icon>
新增产品
</div>
<div class="flex justify-end mb-4">
<img src="@/assets/images/fold.png" alt="" class="cursor-pointer" @click="toList" />
<img src="@/assets/images/fold.png"
alt=""
class="cursor-pointer"
@click="toList" />
</div>
<ul class="products">
<li v-for="(item, i) in list" :key="i" :class="{ active: item.insuranceId === id }" @click="switchProduct(item.insuranceId)">
<el-popconfirm title="您确定删除吗?" @confirm="handleDelete(item.insuranceId)">
<li v-for="(item, i) in list"
:key="i"
:class="{ active: item.insuranceId === id }"
@click="switchProduct(item.insuranceId)">
<el-popconfirm title="您确定删除吗?"
@confirm="handleDelete(item.insuranceId)">
<template #reference>
<img src="@/assets/images/trash.png" alt="" class="del" />
<img src="@/assets/images/trash.png"
alt=""
class="del" />
</template>
</el-popconfirm>
<h6>{{ item.insuranceName }}</h6>
<p v-if="item.minimumAge && item.maximumAge" class="type">{{ item.minimumAge + '-' + item.maximumAge + '周岁' }}</p>
<p v-if="item.insuranceCoverageConfig" class="type">{{ item.insuranceCoverageConfig }}万保额</p>
<p v-if="item.minimumAge && item.maximumAge"
class="type">{{ item.minimumAge + '-' + item.maximumAge + '周岁' }}</p>
<p v-if="item.insuranceCoverageConfig"
class="type">{{ item.insuranceCoverageConfig }}万保额</p>
<p class="meta">创建日期{{ item.operationTime }}</p>
</li>
</ul>
</div>
<div class="right">
<detail v-if="action === 'detail'"></detail>
<add v-else-if="action === 'add'" @getList="getList"></add>
<add v-else-if="action === 'add'"
@getList="getList"></add>
</div>
</div>
</template>
@ -41,10 +53,10 @@ import { ElMessage } from 'element-plus';
import { Plus } from '@element-plus/icons-vue';
import { insuranceList, batchDeletion } from '@/api/insurance';
import { useRouter, useRoute } from 'vue-router';
import Cookies from 'js-cookie';
import { getIds } from '@/utils/common';
import Detail from './Detail.vue';
import Add from './Add.vue';
import Cookies from 'js-cookie';
import { getIds } from '@/utils/common';
const router = useRouter();
const route = useRoute();
@ -57,22 +69,20 @@ const loading = ref<boolean>(false);
const id = computed(() => +route.query.id);
//
const getList = async (first: any) => {
if (!Cookies.get('sand-submit')) {
loading.value = true;
try {
const { data } = await insuranceList({
...getIds(),
pageNum: 1,
pageSize: 1000,
insuranceName: route.query.name ?? '',
createDateSort: route.query.createDateSort ?? '',
insuranceType: route.query.insuranceType ?? '',
});
list.value = data.records;
first && list.value.length && switchProduct(list.value[0].insuranceId);
} finally {
loading.value = false;
}
loading.value = true;
try {
const { data } = await insuranceList({
...getIds(),
pageNum: 1,
pageSize: 1000,
insuranceName: route.query.name ?? '',
createDateSort: route.query.createDateSort ?? '',
insuranceType: route.query.insuranceType ?? '',
});
list.value = data.records;
first && list.value.length && switchProduct(list.value[0].insuranceId);
} finally {
loading.value = false;
}
};
onMounted(() => {
@ -90,7 +100,7 @@ watch(
);
//
const switchProduct = (insId: number) => {
router.push(`/product/insurance/detail?id=${insId}`);
router.push(`/product/insurance/detail?id=` + insId);
};
//
const toAdd = () => {

@ -1,7 +1,8 @@
<template>
<div>
<el-tabs v-model="curTab">
<el-tab-pane label="产品详情" name="tab1">
<el-tab-pane label="产品详情"
name="tab1">
<info />
</el-tab-pane>
</el-tabs>

@ -1,37 +1,46 @@
<template>
<div class="info my-2">
<h2 class="text-center text-lg">{{ info.insuranceName }}</h2>
<h2 class="text-center text-lg">{{info.insuranceName}}</h2>
<p class="text">险种分类{{ info.insuranceType }}</p>
<p v-if="info.minimumAge && info.maximumAge" class="text">承保年龄{{ info.minimumAge + '-' + info.maximumAge + '周岁' }}</p>
<p v-if="info.insuranceDeadline" class="text">保险期限{{ info.insuranceDeadline }}</p>
<p v-if="info.minimumAge && info.maximumAge"
class="text">承保年龄{{ info.minimumAge + '-' + info.maximumAge + '周岁' }}</p>
<p v-if="info.insuranceDeadline"
class="text">保险期限{{ info.insuranceDeadline }}</p>
<div class="text">
<div class="flex">
<p class="w-[130px] mr-32">保险责任</p>
<p class="">保额</p>
</div>
<div v-for="(item, i) in info.insuranceCoverageConfigList" :key="item" class="flex">
<div v-for="(item, i) in info.insuranceCoverageConfigList"
:key="item"
class="flex">
<p class="w-[130px] mr-32">{{ item.insuranceCoverage }}</p>
<p>{{ Number(item.sumInsured * (item.insuredLiabilityId === 764 || item.insuredLiabilityId === 765 ? 1 : 10000)).toFixed(2) }}</p>
</div>
</div>
<p v-if="info.premiumAmount" class="text">保费金额{{ Number(info.premiumAmount).toFixed(2) }}</p>
<p v-if="info.formOfPayment" class="text">缴纳形式{{ info.formOfPayment }}</p>
<div v-if="info.applicationMaterialList?.length" class="text">
<p v-if="info.premiumAmount"
class="text">保费金额{{ Number(info.premiumAmount).toFixed(2) }}</p>
<p v-if="info.formOfPayment"
class="text">缴纳形式{{ info.formOfPayment }}</p>
<div v-if="info.applicationMaterialList?.length"
class="text">
申请材料
<p v-for="(item, i) in info.applicationMaterialList" :key="item">{{ i + 1 }}{{ item }}</p>
<p v-for="(item, i) in info.applicationMaterialList"
:key="item">{{ i + 1 }}{{item}}</p>
</div>
<div v-if="info.exemptionFromLiabilityList?.length" class="text">
<div v-if="info.exemptionFromLiabilityList?.length"
class="text">
责任免除
<p v-for="(item, i) in info.exemptionFromLiabilityList" :key="item">{{ i + 1 }}{{ item }}</p>
<p v-for="(item, i) in info.exemptionFromLiabilityList"
:key="item">{{ i + 1 }}{{item}}</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { ref, computed, watch, onMounted } from 'vue';
import { insuranceProductDetails } from '@/api/insurance';
import { useRouter, useRoute } from 'vue-router';
import Cookies from 'js-cookie';
const router = useRouter();
const route = useRoute();
@ -40,7 +49,7 @@ const info = ref<Record<string, any>>({});
//
const getDetail = async () => {
if (id.value && !Cookies.get('sand-submit')) {
if (id.value) {
try {
const { data } = await insuranceProductDetails(id.value);
info.value = data;

@ -1,68 +1,104 @@
<template>
<div class="block">
<div class="flex justify-between items-center mb-5">
<search v-model="params.insuranceName" @change="initList"></search>
<search v-model="params.insuranceName"
@change="initList"></search>
<div class="filter">
<div class="select">
<el-select v-model="params.insuranceType" placeholder="险种分类" size="large" clearable>
<el-option v-for="item in insuranceTypes" :key="item.id" :label="item.name" :value="item.id" />
<el-select v-model="params.insuranceType"
placeholder="险种分类"
size="large"
clearable>
<el-option v-for="item in insuranceTypes"
:key="item.id"
:label="item.name"
:value="item.id" />
</el-select>
<img src="@/assets/images/7.png" alt="" class="icon" />
<img src="@/assets/images/7.png"
alt=""
class="icon" />
</div>
<div class="add-btn" @click="toAdd">
<img src="@/assets/images/plus.png" alt="" class="icon" />
<div class="add-btn"
@click="toAdd">
<img src="@/assets/images/plus.png"
alt=""
class="icon" />
新增产品
</div>
<img src="@/assets/images/9.png" alt="" class="ml-4 cursor-pointer" @click="toCardList" />
<img src="@/assets/images/9.png"
alt=""
class="ml-4 cursor-pointer"
@click="toCardList" />
</div>
</div>
<el-table ref="table" v-loading="loading" :data="list" @sort-change="handleSort">
<el-table-column prop="insuranceName" label="保险名称" min-width="150"></el-table-column>
<el-table-column prop="insuranceTypeName" label="险种分类" min-width="100"></el-table-column>
<el-table-column prop="minimumAge" label="承保年龄" min-width="100">
<el-table ref="table"
v-loading="loading"
:data="list"
@sort-change="handleSort">
<el-table-column prop="insuranceName"
label="保险名称"
min-width="150"></el-table-column>
<el-table-column prop="insuranceTypeName"
label="险种分类"
min-width="100"></el-table-column>
<el-table-column prop="minimumAge"
label="承保年龄"
min-width="100">
<template #default="{ row }">
{{ row.minimumAge && row.maximumAge ? row.minimumAge + ' - ' + row.maximumAge + '周岁' : '-' }}
</template>
</el-table-column>
<el-table-column prop="insuranceCoverageConfig" label="保险额度(元)" min-width="300">
<el-table-column prop="insuranceCoverageConfig"
label="保险额度(元)"
min-width="300">
<template #default="{ row }">
{{ row.insuranceCoverageConfig ? row.insuranceCoverageConfig + '万' : '-' }}
</template>
</el-table-column>
<el-table-column prop="insuranceDeadline" label="保险期限" min-width="100">
<el-table-column prop="insuranceDeadline"
label="保险期限"
min-width="100">
<template #default="{ row }">
{{ row.insuranceDeadline || '-' }}
</template>
</el-table-column>
<el-table-column prop="premiumAmount" label="保费金额(元)" min-width="140">
<el-table-column prop="premiumAmount"
label="保费金额(元)"
min-width="140">
<template #default="{ row }">
{{ row.premiumAmount?.toFixed(2) || '-' }}
</template>
</el-table-column>
<el-table-column prop="operationTime" label="创建日期" width="180" sortable="custom"></el-table-column>
<el-table-column label="操作" width="140">
<el-table-column prop="operationTime"
label="创建日期"
width="180"
sortable="custom"></el-table-column>
<el-table-column label="操作"
width="140">
<template #default="{ row }">
<el-popconfirm title="您确定删除吗?" @confirm.stop="handleDelete(row.insuranceId)">
<el-popconfirm title="您确定删除吗?"
@confirm.stop="handleDelete(row.insuranceId)">
<template #reference>
<el-button type="primary" link size="small" @click.stop="stop">删除</el-button>
<el-button type="text"
size="small"
@click.stop="stop">删除</el-button>
</template>
</el-popconfirm>
<el-button type="primary" link @click="toDetail(`/product/insurance/detail`, row.insuranceId)" size="small">产品详情</el-button>
</template></el-table-column
>
<el-button type="text"
@click="toDetail(`/product/insurance/detail`, row.insuranceId)"
size="small">产品详情</el-button>
</template></el-table-column>
</el-table>
<el-pagination
v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"
></el-pagination>
<el-pagination v-model:currentPage="currentPage"
v-model:pageSize="pageSize"
:total="total"
:page-sizes="pageSizes"
:layout="pageLayout"
@size-change="getList()"
@current-change="getList()"
small
background
class="px-3 py-2 justify-end"></el-pagination>
</div>
</template>
@ -104,15 +140,13 @@ const loading = ref<boolean>(false);
const stop = () => {};
//
const getList = async () => {
if (!Cookies.get('sand-submit')) {
loading.value = true;
try {
const { data } = await insuranceList({ pageNum: currentPage.value, pageSize: pageSize.value, ...toParams(params) });
list.value = data.records;
total.value = data.total;
} finally {
loading.value = false;
}
loading.value = true;
try {
const { data } = await insuranceList({ pageNum: currentPage.value, pageSize: pageSize.value, ...toParams(params) });
list.value = data.records;
total.value = data.total;
} finally {
loading.value = false;
}
};
//

@ -0,0 +1,304 @@
<template>
<!-- 个人额度模型 -->
<el-form label-width="80px"
class="form"
status-icon>
<h6 class="step-name mb-2">{{ formProcess[0]?.name }}</h6>
<el-form-item label="不超过">
<el-select v-model="form.firstMode">
<el-option v-for="item in formProcess[0]?.recordChildren[0]?.subject?.itemList"
:key="item"
:value="item.options" />
</el-select>
</el-form-item>
<h6 class="step-name mt-4 mb-2">{{ formProcess[1]?.name }}</h6>
<el-form-item label="不超过">
<el-select v-model="form.secondMode">
<el-option v-for="item in formProcess[1]?.recordChildren[0]?.subject?.itemList"
:key="item"
:value="item.options" />
</el-select>
</el-form-item>
<h6 class="step-name mt-4 mb-2">{{ formProcess[2]?.name }}</h6>
<el-form-item label="不超过">
<el-select v-model="form.thirdMode">
<el-option v-for="item in formProcess[2]?.recordChildren[0]?.subject?.itemList"
:key="item"
:value="item.options" />
</el-select>
</el-form-item>
<el-form-item label="且"></el-form-item>
<el-form-item label="不超过">
<el-select v-model="form.andThird">
<el-option v-for="item in formProcess[2]?.recordChildren[1]?.subject?.itemList"
:key="item"
:value="item.options" />
</el-select>
</el-form-item>
<el-form-item label="额度模型">
<el-table class="c-table"
:data="form.individualCreditModels"
:span-method="span"
:cell-style="{background:'#fff'}"
border>
<el-table-column prop="indexName"
label="指标名称"
min-width="100"
align="center">
<template #default="{ row, $index }">
<span :class="{'text-[#006bff]': !$index || $index === len}">{{ row?.indexName }}</span>
</template>
</el-table-column>
<el-table-column label="描述"
min-width="150">
<template #default="{ row, $index }">
<span :class="{'text-[#006bff]': !$index || $index === len}">{{ row?.description }}</span>
</template>
</el-table-column>
<el-table-column label="分值"
min-width="150">
<template #default="{ row, $index }">
<div v-if="$index !== len"
class="flex items-center">
<span v-if="!$index"
class="mr-2 whitespace-nowrap">{{ row?.subject?.name }}</span>
<el-select v-if="row.subject"
v-model="row.score">
<el-option v-for="item in row?.subject?.itemList.sort((a, b) => +(a.options.replace(/[^\d-]/, '')) - +(b.options.replace(/[^\d-]/, '')))"
:key="item"
:value="item.options" />
</el-select>
</div>
<span v-else
class="text-[#006bff]">以上分值合计</span>
</template>
</el-table-column>
</el-table>
</el-form-item>
</el-form>
<div class="flex justify-end">
<div class="submit"
@click="submit">确认完成配置</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ElMessage, ElLoading } from 'element-plus';
import { personalCreditModelDetails, personalCreditModelSaveOrUpdate } from '@/api/model';
import { getProcessInformationBasedOnRoles, addOperation } from '@/api/judgment';
import type { TableColumnCtx } from 'element-plus';
import { useRouter, useRoute } from 'vue-router';
import { handleId, getIds } from '@/utils/common';
import Cookies from 'js-cookie';
const router = useRouter();
const route = useRoute();
let loading = null;
const form = ref<Record<string, any>>({
...getIds(),
andThird: '',
firstMode: '',
secondMode: '',
thirdMode: '',
type: 1,
individualCreditModels: [],
});
const formProcess = ref<Record<string, any>[]>([]);
const info = ref<Record<string, any>[]>([]);
const len = ref<number>(0);
//
const getConfig = async () => {
const { process } = await getProcessInformationBasedOnRoles(772);
formProcess.value = process.slice(0, 3);
const list = process[3]?.recordChildren;
let cur = info.value.length ? info.value[0] : {};
const result = [
{
modelId: cur?.modelId || '',
id: cur?.id || '',
indexName: list[0]?.name,
description: list[0]?.remark,
subject: list[0]?.recordChildren[0]?.subject,
score: cur?.score || '',
},
];
const length = list.length - 1;
list?.forEach((e, i) => {
if (i && i !== length) {
cur = info.value.length ? info.value[i] : {};
let temp = {
indexName: e.name,
recordChildren: e.recordChildren,
stRecordId: e.id,
ruleId: e?.recordChildren[0]?.id || '',
description: e?.recordChildren[0]?.name || '',
subject: e?.recordChildren[0]?.subject || [],
score: '',
};
result.push(temp);
e?.recordChildren.forEach((n, j) => {
if (j) {
temp = JSON.parse(JSON.stringify(temp));
temp.description = n.name;
temp.subject = n.subject;
temp.ruleId = n.id;
result.push(temp);
}
});
}
});
cur = info.value.length ? info.value[info.value.length - 1] : {};
result.push({
indexName: list[length]?.name,
description: list[length]?.remark,
subject: list[length]?.subject,
score: '',
});
len.value = result.length - 1;
if (info.value.length) {
result.forEach((e, i) => {
result[i].score = info.value[i].score;
result[i].id = info.value[i].id;
result[i].modelId = info.value[i].modelId;
});
}
form.value.individualCreditModels = result;
loading.close();
};
//
const getDetail = async (load?: number) => {
if (load) loading = ElLoading.service();
try {
const { data } = await personalCreditModelDetails();
if (data) {
form.value = data;
info.value = data.individualCreditModels;
}
getConfig();
} finally {
}
};
onMounted(() => {
getDetail(1);
});
interface SpanMethodProps {
row: Record<string, any>;
column: TableColumnCtx<Record<string, any>>;
rowIndex: number;
columnIndex: number;
}
const rowMerge1 = [1, 7, 16, 23, 71, 75, 87, 98];
const rowMerge2 = [5, 30, 59, 61, 63, 79];
const rowMerge3 = [11, 38, 45];
const rowMerge4 = [20, 27, 50, 53, 56, 65, 68, 81, 84, 102, 105, 108];
const rowMerge5 = [0, 43, 44, 111];
//
const span = ({ row, column, rowIndex, columnIndex }: SpanMethodProps) => {
if (columnIndex === 0) {
if (rowMerge1.includes(rowIndex)) {
return {
rowspan: 4,
colspan: 1,
};
} else if (rowMerge2.includes(rowIndex)) {
return {
rowspan: 2,
colspan: 1,
};
} else if (rowMerge3.includes(rowIndex)) {
return {
rowspan: 5,
colspan: 1,
};
} else if (rowMerge4.includes(rowIndex)) {
return {
rowspan: 3,
colspan: 1,
};
} else if (rowIndex === 32) {
return {
rowspan: 6,
colspan: 1,
};
} else if (rowIndex === 91) {
return {
rowspan: 7,
colspan: 1,
};
} else if (rowMerge5.includes(rowIndex)) {
return {
rowspan: 1,
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
};
const getItemId = (name: string): number | string => {
if (!name) return '';
return formProcess.value[0]?.recordChildren[0]?.subject?.itemList.find((e) => e.options === name)?.itemId;
};
//
const addRecord = async (data: Record<string, any>) => {
let preIds = `1,${Cookies.get('sand-level')},42,68,756,772`; // 1id
const rule: Array<Record<string, any>> = [];
data.firstMode && rule.push(handleId(777, 236, getItemId(data.firstMode), preIds + ',774,777', 1));
data.secondMode && rule.push(handleId(777, 236, getItemId(data.secondMode), preIds + ',775,777', 1));
data.thirdMode && rule.push(handleId(777, 236, getItemId(data.thirdMode), preIds + ',776,777', 1));
data.andThird && rule.push(handleId(778, 236, getItemId(data.andThird), preIds + ',776,778', 1));
preIds += `,788`;
form.value.individualCreditModels[0].score &&
rule.push(
handleId(
790,
238,
form.value?.individualCreditModels[0]?.subject?.itemList.find((e) => e.options === form.value.individualCreditModels[0].score)?.itemId,
preIds + ',789,790',
1,
),
);
form.value.individualCreditModels.forEach((e, i) => {
if (i && i !== len.value && e.subject) {
e.score && rule.push(handleId(e.ruleId, e.subject.subjectId, e?.subject?.itemList?.find((n) => n.options === e.score)?.itemId, `${preIds},${e.stRecordId},${e.ruleId}`, 1));
}
});
await addOperation({
...getIds(),
parentId: preIds,
lcJudgmentRuleReq: rule,
});
};
//
const submit = async () => {
const param = JSON.parse(JSON.stringify(form.value));
param?.individualCreditModels.forEach((e, i) => {
delete e.recordChildren;
delete e.subject;
});
loading = ElLoading.service();
await personalCreditModelSaveOrUpdate(param);
addRecord(param);
getDetail();
ElMessage.success('提交成功!');
};
</script>
<style lang="scss" scoped>
@import url(../../../styles/form.scss);
.c-table {
:deep(.el-input__inner) {
@apply px-2;
}
}
</style>

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

Loading…
Cancel
Save