Compare commits
No commits in common. 'master' and 'V1.0.1' have entirely different histories.
166 changed files with 11546 additions and 11920 deletions
@ -1,9 +1,8 @@ |
|||||||
VITE_APP_TITLE=金融产品设计及数字化营销沙盘 |
VITE_APP_TITLE=金融产品设计及数字化营销沙盘 |
||||||
VITE_PORT=9520 |
VITE_PORT=9520 |
||||||
# VITE_PROXY=http://192.168.31.125:8080 |
VITE_PROXY=http://192.168.31.125:8080 |
||||||
VITE_PUBLIC_PATH=./ |
VITE_PUBLIC_PATH=./ |
||||||
# VITE_BASE_API=http://192.168.31.217:9000 |
VITE_BASE_API=http://192.168.31.217:9000 |
||||||
VITE_BASE_API=http://121.37.12.51 |
# VITE_BASE_API=http://121.37.12.51 |
||||||
# VITE_BASE_API=https://www.occupationlab.com |
|
||||||
VITE_I18N_LOCALE=zh-cn |
VITE_I18N_LOCALE=zh-cn |
||||||
VITE_I18N_FALLBACK_LOCALE=zh-cn |
VITE_I18N_FALLBACK_LOCALE=zh-cn |
||||||
|
@ -1 +1 @@ |
|||||||
VITE_BASE_API=https://izhixinyun.com |
VITE_BASE_API=https://www.occupationlab.com |
@ -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} |
Binary file not shown.
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} |
Binary file not shown.
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} |
@ -1,213 +1,84 @@ |
|||||||
import axios from '@/utils/request'; |
import axios from '@/utils/request'; |
||||||
import { getIds } from '@/utils/common'; |
|
||||||
|
export const accessStrategyGovernmentBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
const host = `http://192.168.31.51:9000`; |
(await axios.post(`/product/accessStrategyGovernmentBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
|
||||||
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 accessStrategyGovernmentBlacklistSave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyGovernmentBlacklistSave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyGovernmentBlacklist/saveOrUpdate`, data)).data; |
(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 accessStrategyEnterpriseBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).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 accessStrategyEnterpriseBlacklistSave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyEnterpriseBlacklistSave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyEnterpriseBlacklist/saveOrUpdate`, data)).data; |
(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 accessStrategyAntiFraudStrategyFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyAntiFraudStrategy/details?checkpointId=${checkpointId}&projectId=${projectId}`)).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 accessStrategyAntiFraudStrategySave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyAntiFraudStrategySave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyAntiFraudStrategy/saveOrUpdate`, data)).data; |
(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 accessStrategyBusinessBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyBusinessBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).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 accessStrategyBusinessBlacklistSave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyBusinessBlacklistSave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyBusinessBlacklist/saveOrUpdate`, data)).data; |
(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 accessStrategyCreditBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/accessStrategyCreditBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).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 accessStrategyCreditBlacklistSave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyCreditBlacklistSave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyCreditBlacklist/saveOrUpdate`, data)).data; |
(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 accessStrategyInlineBlacklistFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
export const accessStrategyInlineBlacklist = async (data: Record<string, any>): Promise<any> => |
(await axios.post(`/product/accessStrategyInlineBlacklist/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
( |
|
||||||
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 accessStrategyInlineBlacklistSave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyInlineBlacklistSave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyInlineBlacklist/saveOrUpdate`, data)).data; |
(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 accessStrategyNegativeIndustryStrategyFind = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
export const accessStrategyNegativeIndustryStrategy = async (data: Record<string, any>): Promise<any> => |
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
( |
|
||||||
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 accessStrategyNegativeIndustryStrategySave = async (data: Record<string, any>): Promise<any> => |
export const accessStrategyNegativeIndustryStrategySave = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/accessStrategyNegativeIndustryStrategy/saveOrUpdate`, data)).data; |
(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 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> => |
export const listCredit = async (data: Record<string, any>): Promise<any> => |
||||||
( |
(await axios.post(`/product/creditScoringStrategy/list?checkpointId=${data.checkpointId}&projectId=${data.projectId}&pageNum=${data.pageNum}&pageSize=${data.pageSize}`)).data; |
||||||
await axios.post(`/product/creditScoringStrategy/list`, { |
|
||||||
...data, |
|
||||||
...getIds(), |
|
||||||
}) |
|
||||||
).data; |
|
||||||
export const saveCredit = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/creditScoringStrategy/saveOrUpdate`, data)).data; |
export const saveCredit = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/creditScoringStrategy/saveOrUpdate`, data)).data; |
||||||
|
|
||||||
export const detailRick = async (type: number): Promise<any> => |
export const detailRick = async (data: Record<string, any>): Promise<any> => |
||||||
( |
(await axios.post(`/product/riskDegreeStrategy/details?checkpointId=${data.checkpointId}&projectId=${data.projectId}&type=${data.type}`)).data; |
||||||
await axios.post(`/product/riskDegreeStrategy/details`, { |
|
||||||
...getIds(), |
|
||||||
type, |
|
||||||
}) |
|
||||||
).data; |
|
||||||
export const saveRick = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/riskDegreeStrategy/saveOrUpdate`, data)).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> => |
export const businessInterestRateDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
( |
(await axios.post(`/product/interestRateModel/businessInterestRateDetails?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
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 businessInterestRateSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
export const businessInterestRateSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/interestRateModel/businessInterestRateSaveOrUpdate`, data)).data; |
(await axios.post(`/product/interestRateModel/businessInterestRateSaveOrUpdate`, data)).data; |
||||||
export const personalInterestRateDetails = async (params: Record<string, any>): Promise<any> => |
export const personalInterestRateDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
(await axios.post(`/product/interestRateModel/personalInterestRateDetails`, {}, { params })).data; |
(await axios.post(`/product/interestRateModel/personalInterestRateDetails?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
export const personalInterestRateSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
export const personalInterestRateSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/interestRateModel/personalInterestRateSaveOrUpdate`, data)).data; |
(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 businessQuotaModelDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
|
(await axios.post(`/product/quotaModel/businessQuotaModelDetails?checkpointId=${checkpointId}&projectId=${projectId}`)).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> => |
export const businessQuotaModelSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/quotaModel/businessQuotaModelSaveOrUpdate`, data)).data; |
(await axios.post(`/product/quotaModel/businessQuotaModelSaveOrUpdate`, data)).data; |
||||||
export const personalCreditModelDetails = async (params: Record<string, any>): Promise<any> => |
export const personalCreditModelDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
(await axios.post(`/product/quotaModel/personalCreditModelDetails`, {}, { params })).data; |
(await axios.post(`/product/quotaModel/personalCreditModelDetails?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
export const personalCreditModelSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
export const personalCreditModelSaveOrUpdate = async (data: Record<string, any>): Promise<any> => |
||||||
(await axios.post(`/product/quotaModel/personalCreditModelSaveOrUpdate`, data)).data; |
(await axios.post(`/product/quotaModel/personalCreditModelSaveOrUpdate`, data)).data; |
||||||
|
|
||||||
export const fiveLevelClassification = async (data: Record<string, any>): Promise<any> => |
export const fiveLevelClassificationDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
( |
(await axios.post(`/product/fiveLevelClassification/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
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 fiveLevelClassificationSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/fiveLevelClassification/saveOrUpdate`, data)).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 postLoanInspectionDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
export const postLoanInspection = async (data: Record<string, any>): Promise<any> => |
(await axios.post(`/product/postLoanInspection/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
( |
|
||||||
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 postLoanInspectionSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanInspection/saveOrUpdate`, data)).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 postCreditScoreDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
export const postCreditScore = async (data: Record<string, any>): Promise<any> => |
(await axios.post(`/product/postCreditScore/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
( |
|
||||||
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 postCreditScoreSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postCreditScore/saveOrUpdate`, data)).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 postLoanWarningDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
export const postLoanWarning = async (data: Record<string, any>): Promise<any> => |
(await axios.post(`/product/postLoanWarning/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
( |
|
||||||
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 postLoanWarningSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/postLoanWarning/saveOrUpdate`, data)).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 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> => |
export const collectionAfterLoanDetails = async (checkpointId: number, projectId: number): Promise<any> => |
||||||
(await axios.post(`/product/managerOfRiskControl/bankRiskControlAllocation/isTheStrategyRelatedToTheProduct`, data)).data; |
(await axios.post(`/product/collectionAfterLoan/details?checkpointId=${checkpointId}&projectId=${projectId}`)).data; |
||||||
|
export const collectionAfterLoanSave = async (data: Record<string, any>): Promise<any> => (await axios.post(`/product/collectionAfterLoan/saveOrUpdate`, 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; |
Before Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,258 @@ |
|||||||
|
<template> |
||||||
|
<el-dialog |
||||||
|
:title="title" |
||||||
|
:close-on-click-modal="!unsaved" |
||||||
|
:model-value="modelValue" |
||||||
|
@update:model-value="$emit('update:modelValue', $event)" |
||||||
|
@opened="!isEdit && focus?.focus()" |
||||||
|
:width="large ? '98%' : '683px'" |
||||||
|
:top="large ? '16px' : undefined" |
||||||
|
> |
||||||
|
<div> |
||||||
|
<el-button v-if="isEdit && addable" :disabled="perm(`${perms}:create`)" type="primary" :icon="Plus" @click="handleAdd">{{ $t('add') }}</el-button> |
||||||
|
<el-popconfirm v-if="isEdit" :title="$t('confirmDelete')" @confirm="handleDelete"> |
||||||
|
<template #reference> |
||||||
|
<el-button :loading="buttonLoading" :disabled="disableDelete?.(bean) || perm(`${perms}:delete`)" :icon="Delete">{{ $t('delete') }}</el-button> |
||||||
|
</template> |
||||||
|
</el-popconfirm> |
||||||
|
<el-button v-if="isEdit" @click="handlePrev" :disabled="!hasPrev">{{ $t('form.prev') }}</el-button> |
||||||
|
<el-button v-if="isEdit" @click="handleNext" :disabled="!hasNext">{{ $t('form.next') }}</el-button> |
||||||
|
<el-button @click="handleCancel" type="primary">{{ $t('back') }}</el-button> |
||||||
|
<el-tooltip :content="$t('form.continuous')" placement="top"> |
||||||
|
<el-switch v-model="continuous" size="small" class="ml-2"></el-switch> |
||||||
|
</el-tooltip> |
||||||
|
<el-tag v-if="unsaved" type="danger" class="ml-2">{{ $t('form.unsaved') }}</el-tag> |
||||||
|
<slot name="header" :values="values" :bean="bean" :isEdit="isEdit"></slot> |
||||||
|
</div> |
||||||
|
<el-form |
||||||
|
:class="['mt-5', 'pr-5']" |
||||||
|
ref="form" |
||||||
|
v-loading="loading" |
||||||
|
:model="values" |
||||||
|
:disabled="!editable" |
||||||
|
:label-width="labelWidth ?? '150px'" |
||||||
|
:label-position="labelPosition ?? 'right'" |
||||||
|
> |
||||||
|
<slot :values="values" :bean="bean" :isEdit="isEdit"></slot> |
||||||
|
<div v-if="editable"> |
||||||
|
<el-button :disabled="perm(isEdit ? `${perms}:update` : `${perms}:create`)" :loading="buttonLoading" @click.prevent="handleSubmit" type="primary" native-type="submit"> |
||||||
|
{{ $t('submit') }} |
||||||
|
</el-button> |
||||||
|
</div> |
||||||
|
</el-form> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import { computed, defineComponent, PropType, ref, toRefs, watch } from 'vue'; |
||||||
|
import { ElMessage } from 'element-plus'; |
||||||
|
import { Plus, Delete } from '@element-plus/icons-vue'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
import _ from 'lodash'; |
||||||
|
import { perm } from '@/store/useCurrentUser'; |
||||||
|
|
||||||
|
const CONTINUOUS_SETTINGS = 'ujcms_continuous_settings'; |
||||||
|
function fetchContinuous(): Record<string, boolean> { |
||||||
|
const settings = localStorage.getItem(CONTINUOUS_SETTINGS); |
||||||
|
return settings ? JSON.parse(settings) : {}; |
||||||
|
} |
||||||
|
function storeContinuous(settings: Record<string, boolean>) { |
||||||
|
localStorage.setItem(CONTINUOUS_SETTINGS, JSON.stringify(settings)); |
||||||
|
} |
||||||
|
function getContinuous(name: string) { |
||||||
|
const settings = fetchContinuous(); |
||||||
|
return settings[name] ?? false; |
||||||
|
} |
||||||
|
function setContinuous(name: string, continuous: boolean) { |
||||||
|
const settings = fetchContinuous(); |
||||||
|
settings[name] = continuous; |
||||||
|
storeContinuous(settings); |
||||||
|
} |
||||||
|
|
||||||
|
export default defineComponent({ |
||||||
|
name: 'DialogForm', |
||||||
|
props: { |
||||||
|
modelValue: { type: Boolean, required: true }, |
||||||
|
name: { type: String, required: true }, |
||||||
|
beanId: { required: true }, |
||||||
|
beanIds: { type: Array, required: true }, |
||||||
|
initValues: { type: Function as PropType<(bean?: any) => any>, required: true }, |
||||||
|
toValues: { type: Function as PropType<(bean: any) => any>, required: true }, |
||||||
|
queryBean: { type: Function as PropType<(id: any) => Promise<any>>, required: true }, |
||||||
|
createBean: { type: Function as PropType<(bean: any) => Promise<any>>, required: true }, |
||||||
|
updateBean: { type: Function as PropType<(bean: any) => Promise<any>>, required: true }, |
||||||
|
deleteBean: { type: Function as PropType<(ids: any[]) => Promise<any>>, required: true }, |
||||||
|
disableDelete: { type: Function as PropType<(bean: any) => boolean> }, |
||||||
|
addable: { type: Boolean, default: true }, |
||||||
|
editable: { type: Boolean, default: true }, |
||||||
|
perms: String, |
||||||
|
focus: Object, |
||||||
|
large: Boolean, |
||||||
|
labelPosition: String, |
||||||
|
labelWidth: String, |
||||||
|
}, |
||||||
|
emits: { |
||||||
|
'update:modelValue': null, |
||||||
|
finished: null, |
||||||
|
beanChange: null, |
||||||
|
beforeSubmit: null, |
||||||
|
}, |
||||||
|
setup(props, { emit }) { |
||||||
|
const { name, beanId, beanIds, focus, modelValue: visible } = toRefs(props); |
||||||
|
const { t } = useI18n(); |
||||||
|
const loading = ref<boolean>(false); |
||||||
|
const buttonLoading = ref<boolean>(false); |
||||||
|
const continuous = ref<boolean>(getContinuous(name.value)); |
||||||
|
const reseted = ref<boolean>(false); |
||||||
|
const unsaved = ref<boolean>(false); |
||||||
|
const form = ref<any>(); |
||||||
|
const values = ref<any>(props.initValues()); |
||||||
|
const bean = ref<any>({}); |
||||||
|
const id = ref<any>(); |
||||||
|
const ids = ref<Array<any>>([]); |
||||||
|
const isEdit = computed(() => id.value != null); |
||||||
|
const title = computed(() => `${name.value} - ${isEdit.value ? `${t('edit')} (ID: ${id.value})` : `${t('add')}`}`); |
||||||
|
const idChanged = async () => { |
||||||
|
loading.value = true; |
||||||
|
unsaved.value = false; |
||||||
|
reseted.value = true; |
||||||
|
try { |
||||||
|
bean.value = id.value != null ? await props.queryBean(id.value) : {}; |
||||||
|
values.value = id.value != null ? props.toValues(bean.value) : props.initValues(values.value); |
||||||
|
emit('beanChange', bean.value); |
||||||
|
form.value.resetFields(); |
||||||
|
} finally { |
||||||
|
loading.value = false; |
||||||
|
} |
||||||
|
}; |
||||||
|
watch(visible, () => { |
||||||
|
if (visible.value) { |
||||||
|
ids.value = beanIds.value; |
||||||
|
if (id.value !== beanId.value) { |
||||||
|
id.value = beanId.value; |
||||||
|
} else if (id.value != null) { |
||||||
|
idChanged(); |
||||||
|
} |
||||||
|
if (id.value == null) { |
||||||
|
reseted.value = true; |
||||||
|
values.value = props.initValues(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
watch(id, () => { |
||||||
|
idChanged(); |
||||||
|
}); |
||||||
|
watch( |
||||||
|
// 监听对象必须使用 lodash 的深度拷贝,才能在监听里面获取旧值和新值。 |
||||||
|
// 参考文档:https://v3.vuejs.org/guide/reactivity-computed-watchers.html#watching-reactive-objects |
||||||
|
() => _.cloneDeep(values.value), |
||||||
|
(curr, prev) => { |
||||||
|
// 重置触发的bean改动,不标记为未保存。 |
||||||
|
if (reseted.value) { |
||||||
|
reseted.value = false; |
||||||
|
} else if (JSON.stringify(curr) !== JSON.stringify(prev)) { |
||||||
|
// 自定义字段改变页面时,会改变values.customs,加上字段的值,但这些值为undefined。 |
||||||
|
// 这会触发watch监听,但json值不变。如json值不变,则不修改unsaved状态。 |
||||||
|
unsaved.value = true; |
||||||
|
} |
||||||
|
}, |
||||||
|
{ deep: true }, |
||||||
|
); |
||||||
|
watch(continuous, () => setContinuous(name.value, continuous.value)); |
||||||
|
const index = computed(() => ids.value.indexOf(id.value)); |
||||||
|
const hasPrev = computed(() => index.value > 0); |
||||||
|
const hasNext = computed(() => index.value < ids.value.length - 1); |
||||||
|
const handlePrev = () => { |
||||||
|
if (hasPrev.value) { |
||||||
|
id.value = ids.value[index.value - 1]; |
||||||
|
} |
||||||
|
}; |
||||||
|
const handleNext = () => { |
||||||
|
if (hasNext.value) { |
||||||
|
id.value = ids.value[index.value + 1]; |
||||||
|
} |
||||||
|
}; |
||||||
|
const handleAdd = () => { |
||||||
|
// eslint-disable-next-line no-unused-expressions |
||||||
|
focus?.value?.focus?.(); |
||||||
|
id.value = undefined; |
||||||
|
}; |
||||||
|
const handleCancel = () => { |
||||||
|
emit('update:modelValue', false); |
||||||
|
}; |
||||||
|
const handleSubmit = () => { |
||||||
|
form.value.validate(async (valid: boolean) => { |
||||||
|
if (!valid) return; |
||||||
|
buttonLoading.value = true; |
||||||
|
try { |
||||||
|
emit('beforeSubmit', values.value); |
||||||
|
if (isEdit.value) { |
||||||
|
await props.updateBean(values.value); |
||||||
|
unsaved.value = false; |
||||||
|
} else { |
||||||
|
await props.createBean(values.value); |
||||||
|
// eslint-disable-next-line no-unused-expressions |
||||||
|
focus?.value?.focus?.(); |
||||||
|
unsaved.value = false; |
||||||
|
reseted.value = true; |
||||||
|
values.value = props.initValues(values.value); |
||||||
|
form.value.resetFields(); |
||||||
|
} |
||||||
|
ElMessage.success(t('success')); |
||||||
|
if (!continuous.value) emit('update:modelValue', false); |
||||||
|
emit('finished', bean.value); |
||||||
|
} finally { |
||||||
|
buttonLoading.value = false; |
||||||
|
} |
||||||
|
}); |
||||||
|
}; |
||||||
|
const handleDelete = async () => { |
||||||
|
buttonLoading.value = true; |
||||||
|
try { |
||||||
|
await props.deleteBean([id.value]); |
||||||
|
if (!continuous.value) emit('update:modelValue', false); |
||||||
|
if (hasNext.value) { |
||||||
|
handleNext(); |
||||||
|
ids.value.splice(index.value - 1, 1); |
||||||
|
} else if (hasPrev.value) { |
||||||
|
handlePrev(); |
||||||
|
ids.value.splice(index.value + 1, 1); |
||||||
|
} else { |
||||||
|
emit('update:modelValue', false); |
||||||
|
} |
||||||
|
ElMessage.success(t('success')); |
||||||
|
emit('finished'); |
||||||
|
} finally { |
||||||
|
buttonLoading.value = false; |
||||||
|
} |
||||||
|
}; |
||||||
|
const setUnsaved = (bool: boolean) => { |
||||||
|
unsaved.value = bool; |
||||||
|
}; |
||||||
|
return { |
||||||
|
perm, |
||||||
|
handleAdd, |
||||||
|
handleDelete, |
||||||
|
handleSubmit, |
||||||
|
handleCancel, |
||||||
|
handlePrev, |
||||||
|
handleNext, |
||||||
|
hasPrev, |
||||||
|
hasNext, |
||||||
|
loading, |
||||||
|
buttonLoading, |
||||||
|
continuous, |
||||||
|
unsaved, |
||||||
|
isEdit, |
||||||
|
form, |
||||||
|
values, |
||||||
|
bean, |
||||||
|
id, |
||||||
|
title, |
||||||
|
setUnsaved, |
||||||
|
Plus, |
||||||
|
Delete, |
||||||
|
}; |
||||||
|
}, |
||||||
|
}); |
||||||
|
</script> |
@ -0,0 +1,30 @@ |
|||||||
|
<template> |
||||||
|
<p>{{ t('hello') }}</p> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import { defineComponent } from 'vue'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
|
||||||
|
export default defineComponent({ |
||||||
|
name: 'HelloI18n', |
||||||
|
setup() { |
||||||
|
const { t } = useI18n({ |
||||||
|
inheritLocale: true, |
||||||
|
useScope: 'local', |
||||||
|
}); |
||||||
|
|
||||||
|
// Something todo .. |
||||||
|
|
||||||
|
return { t }; |
||||||
|
}, |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<i18n> |
||||||
|
{ |
||||||
|
"en": { |
||||||
|
"hello": "Hello i18n in SFC!" |
||||||
|
} |
||||||
|
} |
||||||
|
</i18n> |
@ -0,0 +1,17 @@ |
|||||||
|
<template> |
||||||
|
{{ label ?? $t(message) }} |
||||||
|
<el-tooltip :content="tooltip ?? $t(message + '.tooltip')" |
||||||
|
placement="top"> |
||||||
|
<el-icon class="text-base align-text-top"><question-filled /></el-icon> |
||||||
|
</el-tooltip> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { QuestionFilled } from '@element-plus/icons-vue'; |
||||||
|
|
||||||
|
defineProps({ |
||||||
|
label: { type: String }, |
||||||
|
tooltip: { type: String }, |
||||||
|
message: { type: String, required: true }, |
||||||
|
}); |
||||||
|
</script> |
@ -0,0 +1,27 @@ |
|||||||
|
<template> |
||||||
|
<el-button-group> |
||||||
|
<el-button :disabled="disabled" |
||||||
|
:icon="Top" |
||||||
|
@click="$emit('move', 'top')">{{ $t('moveTop') }}</el-button> |
||||||
|
<el-button :disabled="disabled" |
||||||
|
:icon="ArrowUp" |
||||||
|
@click="$emit('move', 'up')">{{ $t('moveUp') }}</el-button> |
||||||
|
<el-button :disabled="disabled" |
||||||
|
:icon="ArrowDown" |
||||||
|
@click="$emit('move', 'down')">{{ $t('moveDown') }}</el-button> |
||||||
|
<el-button :disabled="disabled" |
||||||
|
:icon="Bottom" |
||||||
|
@click="$emit('move', 'bottom')">{{ $t('moveBottom') }}</el-button> |
||||||
|
</el-button-group> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { Top, Bottom, ArrowUp, ArrowDown } from '@element-plus/icons-vue'; |
||||||
|
|
||||||
|
defineProps({ |
||||||
|
disabled: { type: Boolean, required: true }, |
||||||
|
}); |
||||||
|
defineEmits({ |
||||||
|
move: null, |
||||||
|
}); |
||||||
|
</script> |
@ -0,0 +1,59 @@ |
|||||||
|
<template> |
||||||
|
<form class="flex"> |
||||||
|
<div class="space-y-1"> |
||||||
|
<div v-for="(name, index) in names" :key="name" class="flex"> |
||||||
|
<el-button :icon="index == 0 ? Plus : Minus" @click="handelRow(index)" :disabled="index <= 0 && remains.length <= 0" circle></el-button> |
||||||
|
<el-select v-model="names[index]" @change="clearParams()" class="w-36"> |
||||||
|
<el-option v-for="item in data.filter((it) => it.name === names[index] || remains.includes(it))" :key="item.name" :label="item.label" :value="item.name"></el-option> |
||||||
|
</el-select> |
||||||
|
<query-input :inputs="inputs" :name="names[index]"></query-input> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div> |
||||||
|
<el-button-group class="ml-2"> |
||||||
|
<el-button native-type="submit" :icon="Search" @click.prevent="$emit('search')">{{ $t('search') }}</el-button> |
||||||
|
<el-button :icon="Refresh" @click="$emit('reset')">{{ $t('reset') }}</el-button> |
||||||
|
</el-button-group> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { defineEmits, useSlots, provide, computed, ref, toRefs } from 'vue'; |
||||||
|
import { Plus, Minus, Search, Refresh } from '@element-plus/icons-vue'; |
||||||
|
import QueryInput from './QueryInput.vue'; |
||||||
|
|
||||||
|
const props = defineProps({ params: { type: Object, required: true } }); |
||||||
|
const { params } = toRefs(props); |
||||||
|
const slots = useSlots(); |
||||||
|
provide('params', params); |
||||||
|
defineEmits({ |
||||||
|
search: null, |
||||||
|
reset: null, |
||||||
|
}); |
||||||
|
|
||||||
|
const data = ref<any[]>([]); |
||||||
|
const inputs = ref<any[]>([]); |
||||||
|
inputs.value = slots.default?.() ?? []; |
||||||
|
data.value = inputs.value.map((item) => ({ label: item.props?.label, name: item.props?.name })); |
||||||
|
|
||||||
|
const [first] = data.value; |
||||||
|
const names = ref<string[]>([first.name]); |
||||||
|
const remains = computed(() => data.value.filter((it) => !names.value.includes(it.name))); |
||||||
|
const clearParams = () => { |
||||||
|
Object.keys(params.value).forEach((key) => { |
||||||
|
if (!names.value.includes(key) && names.value.findIndex((item) => item.split(',').includes(key)) === -1) { |
||||||
|
delete params.value[key]; |
||||||
|
} |
||||||
|
}); |
||||||
|
}; |
||||||
|
const handelRow = (index: number) => { |
||||||
|
if (index === 0) { |
||||||
|
const [item] = remains.value; |
||||||
|
names.value[names.value.length] = item.name; |
||||||
|
} else { |
||||||
|
names.value.splice(index, 1); |
||||||
|
clearParams(); |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,16 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { defineComponent, computed, toRefs } from 'vue'; |
||||||
|
|
||||||
|
export default defineComponent({ |
||||||
|
name: 'QueryInput', |
||||||
|
props: { inputs: { type: Array, required: true }, name: { type: String, required: true } }, |
||||||
|
setup(props) { |
||||||
|
const { inputs, name } = toRefs(props); |
||||||
|
const input = computed(() => inputs.value.find((item: any) => item.props.name === name.value)); |
||||||
|
return { input }; |
||||||
|
}, |
||||||
|
render() { |
||||||
|
return this.input; |
||||||
|
}, |
||||||
|
}); |
||||||
|
</script> |
@ -0,0 +1,64 @@ |
|||||||
|
<template> |
||||||
|
<slot> |
||||||
|
<div v-if="type === 'number'" |
||||||
|
class="inline-block"> |
||||||
|
<el-input-number v-model="params[first]" |
||||||
|
:placeholder="$t('begin.number')" |
||||||
|
class="w-48"></el-input-number> |
||||||
|
<el-input-number v-model="params[second]" |
||||||
|
:placeholder="$t('end.number')" |
||||||
|
class="w-48"></el-input-number> |
||||||
|
</div> |
||||||
|
<el-date-picker v-else-if="type === 'date'" |
||||||
|
v-model="params[name]" |
||||||
|
type="daterange" |
||||||
|
:start-placeholder="$t('begin.date')" |
||||||
|
:end-placeholder="$t('end.date')" |
||||||
|
class="w-96"></el-date-picker> |
||||||
|
<el-date-picker v-else-if="type === 'datetime'" |
||||||
|
v-model="params[name]" |
||||||
|
type="datetimerange" |
||||||
|
:start-placeholder="$t('begin.date')" |
||||||
|
:end-placeholder="$t('end.date')" |
||||||
|
class="w-96"> |
||||||
|
</el-date-picker> |
||||||
|
<!-- |
||||||
|
<div v-else-if="type === 'date'" class="inline-block"> |
||||||
|
<el-date-picker v-model="params[first]" type="date" :placeholder="$t('begin.date')" class="w-48"></el-date-picker> |
||||||
|
<el-date-picker v-model="params[second]" type="date" :placeholder="$t('end.date')" class="w-48"></el-date-picker> |
||||||
|
</div> |
||||||
|
<div v-else-if="type === 'datetime'" class="inline-block"> |
||||||
|
<el-date-picker v-model="params[first]" type="datetime" class="w-48"></el-date-picker> |
||||||
|
<el-date-picker v-model="params[second]" type="datetime" class="w-48"></el-date-picker> |
||||||
|
</div> |
||||||
|
--> |
||||||
|
<el-select v-else-if="options" |
||||||
|
v-model="params[name]" |
||||||
|
multiple |
||||||
|
class="w-96"> |
||||||
|
<el-option v-for="item in options" |
||||||
|
:key="item.value" |
||||||
|
:label="item.label" |
||||||
|
:value="item.value"></el-option> |
||||||
|
</el-select> |
||||||
|
<el-input v-else |
||||||
|
v-model="params[name]" |
||||||
|
class="w-96"></el-input> |
||||||
|
</slot> |
||||||
|
</template> |
||||||
|
<script setup lang="ts"> |
||||||
|
import { inject, PropType, ref, toRefs } from 'vue'; |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
label: { type: String, required: true }, |
||||||
|
name: { type: String, required: true }, |
||||||
|
// 'string' | 'date' | 'datetime' | 'number' |
||||||
|
type: { type: String }, |
||||||
|
options: { type: Object as PropType<Array<{ label: string; value: string | number }>> }, |
||||||
|
}); |
||||||
|
const params = inject<any>('params'); |
||||||
|
const { name } = toRefs(props); |
||||||
|
const [firstName, secondName] = name.value.split(','); |
||||||
|
const first = ref<string>(firstName); |
||||||
|
const second = ref<string>(secondName); |
||||||
|
</script> |
@ -0,0 +1,2 @@ |
|||||||
|
export { default as QueryForm } from './QueryForm.vue'; |
||||||
|
export { default as QueryItem } from './QueryItem.vue'; |
@ -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> |
|
@ -0,0 +1,45 @@ |
|||||||
|
<script lang="ts"> |
||||||
|
import { computed, defineComponent, toRefs } from 'vue'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
import { ColumnState, getColumnSettings, setColumnOrigins } from './useColumns'; |
||||||
|
|
||||||
|
export default defineComponent({ |
||||||
|
name: 'ColumnList', |
||||||
|
props: { name: { type: String, required: true } }, |
||||||
|
setup(props, { slots }) { |
||||||
|
const { name } = toRefs(props); |
||||||
|
const { t } = useI18n(); |
||||||
|
const slotColumns = slots.default?.() ?? []; |
||||||
|
// 获取栏目名称 |
||||||
|
const getColumnTitle = (columnProps: any) => { |
||||||
|
// 如果是checkbox列,则名称为“选择框” |
||||||
|
if (columnProps?.type === 'selection') return t('table.selection'); |
||||||
|
return columnProps?.label; |
||||||
|
}; |
||||||
|
// 获取el-table-column的名称、是否显示 |
||||||
|
const origins: ColumnState[] = slotColumns.map((column) => ({ title: getColumnTitle(column.props), display: column.props?.display !== 'none' })); |
||||||
|
setColumnOrigins(name.value, origins); |
||||||
|
|
||||||
|
const settings = getColumnSettings(name.value); |
||||||
|
const columns = computed(() => |
||||||
|
slotColumns |
||||||
|
.filter((column) => { |
||||||
|
const matched = settings.value.find((item) => getColumnTitle(column.props) === item.title); |
||||||
|
return !matched || matched.display; |
||||||
|
}) |
||||||
|
.map((column) => ({ ...column, key: getColumnTitle(column.props) })) |
||||||
|
.sort((a, b) => { |
||||||
|
let indexA = settings.value.findIndex((item) => item.title === getColumnTitle(a)); |
||||||
|
if (indexA < 0) indexA = slotColumns.findIndex((item) => getColumnTitle(item) === getColumnTitle(a)); |
||||||
|
let indexB = settings.value.findIndex((item) => item.title === getColumnTitle(b)); |
||||||
|
if (indexB < 0) indexB = slotColumns.findIndex((item) => getColumnTitle(item) === getColumnTitle(b)); |
||||||
|
return indexA - indexB; |
||||||
|
}), |
||||||
|
); |
||||||
|
return { columns }; |
||||||
|
}, |
||||||
|
render() { |
||||||
|
return this.columns; |
||||||
|
}, |
||||||
|
}); |
||||||
|
</script> |
@ -0,0 +1,40 @@ |
|||||||
|
<template> |
||||||
|
<el-dropdown class="align-middle" |
||||||
|
trigger="click" |
||||||
|
:hide-on-click="false"> |
||||||
|
<el-tooltip :content="$t('table.columnsSetting')" |
||||||
|
placement="top"> |
||||||
|
<el-icon class="text-base"> |
||||||
|
<setting /> |
||||||
|
</el-icon> |
||||||
|
</el-tooltip> |
||||||
|
<template #dropdown> |
||||||
|
<el-dropdown-menu> |
||||||
|
<el-dropdown-item> |
||||||
|
<el-button @click="resetColumns" |
||||||
|
type="text">{{ $t('table.columnsReset') }}</el-button> |
||||||
|
</el-dropdown-item> |
||||||
|
<el-dropdown-item v-for="(column, index) in settings" |
||||||
|
:key="column.title" |
||||||
|
:divided="index === 0"> |
||||||
|
<el-checkbox v-model="column.display">{{ column.title }}</el-checkbox> |
||||||
|
</el-dropdown-item> |
||||||
|
</el-dropdown-menu> |
||||||
|
</template> |
||||||
|
</el-dropdown> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { toRefs, watch } from 'vue'; |
||||||
|
import { Setting } from '@element-plus/icons-vue'; |
||||||
|
import { getColumnOrigins, getColumnSettings, mergeColumns, storeColumnSettings } from './useColumns'; |
||||||
|
|
||||||
|
const props = defineProps({ name: { type: String, required: true } }); |
||||||
|
const { name } = toRefs(props); |
||||||
|
const settings = getColumnSettings(name.value); |
||||||
|
const origins = getColumnOrigins(name.value); |
||||||
|
watch(settings, () => storeColumnSettings(), { deep: true }); |
||||||
|
const resetColumns = () => { |
||||||
|
settings.value = mergeColumns([], origins.value); |
||||||
|
}; |
||||||
|
</script> |
@ -0,0 +1,2 @@ |
|||||||
|
export { default as ColumnSetting } from './ColumnSetting.vue'; |
||||||
|
export { default as ColumnList } from './ColumnList.vue'; |
@ -0,0 +1,55 @@ |
|||||||
|
import { reactive, toRef } from 'vue'; |
||||||
|
|
||||||
|
export interface ColumnState { |
||||||
|
title: string; |
||||||
|
display: boolean; |
||||||
|
} |
||||||
|
|
||||||
|
const COLUMN_SETTINGS = 'ujcms_column_settings'; |
||||||
|
|
||||||
|
function fetchColumnSettings(): Record<string, ColumnState[]> { |
||||||
|
const settings = localStorage.getItem(COLUMN_SETTINGS); |
||||||
|
return settings ? JSON.parse(settings) : {}; |
||||||
|
} |
||||||
|
|
||||||
|
const originStore: Record<string, ColumnState[]> = reactive({}); |
||||||
|
const settingStore: Record<string, ColumnState[]> = reactive(fetchColumnSettings()); |
||||||
|
|
||||||
|
export function storeColumnSettings() { |
||||||
|
localStorage.setItem(COLUMN_SETTINGS, JSON.stringify(settingStore)); |
||||||
|
} |
||||||
|
export const getColumnOrigins = (name: string) => { |
||||||
|
if (!originStore[name]) originStore[name] = []; |
||||||
|
return toRef(originStore, name); |
||||||
|
}; |
||||||
|
export const mergeColumns = (settings: ColumnState[], origins: ColumnState[]) => { |
||||||
|
// 去除不存在的列
|
||||||
|
for (let i = 0, len = settings.length; i < len; ) { |
||||||
|
if (origins.findIndex((column) => column.title === settings[i].title) === -1) { |
||||||
|
settings.splice(i, 1); |
||||||
|
len -= 1; |
||||||
|
} else { |
||||||
|
i += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
// 增加未记录的列
|
||||||
|
origins.forEach((column) => { |
||||||
|
if (settings.findIndex((item) => item.title === column.title) === -1) { |
||||||
|
settings.push({ ...column }); |
||||||
|
} |
||||||
|
}); |
||||||
|
return settings; |
||||||
|
}; |
||||||
|
export const setColumnOrigins = (name: string, origins: ColumnState[]) => { |
||||||
|
originStore[name] = origins; |
||||||
|
if (!settingStore[name]) settingStore[name] = []; |
||||||
|
const settings = settingStore[name]; |
||||||
|
mergeColumns(settings, origins); |
||||||
|
}; |
||||||
|
export const getColumnSettings = (name: string) => { |
||||||
|
if (!settingStore[name]) settingStore[name] = []; |
||||||
|
return toRef(settingStore, name); |
||||||
|
}; |
||||||
|
// export const setColumnSettings = (name: string, settings: ColumnState[]) => {
|
||||||
|
// settingStore[name] = settings;
|
||||||
|
// };
|
@ -0,0 +1,118 @@ |
|||||||
|
<template> |
||||||
|
<el-upload |
||||||
|
:action="action" |
||||||
|
:headers="{ ...getAuthHeaders(), ...getSiteHeaders() }" |
||||||
|
:accept="accept" |
||||||
|
:before-upload="beforeUpload" |
||||||
|
:on-progress="(event, file) => (progressFile = file)" |
||||||
|
:show-file-list="false" |
||||||
|
:disabled="disabled" |
||||||
|
:multiple="multiple" |
||||||
|
> |
||||||
|
<!-- |
||||||
|
// 用于测试上传进度条 |
||||||
|
action="https://jsonplaceholder.typicode.com/posts/" |
||||||
|
--> |
||||||
|
<el-button type="primary">{{ $t('clickToUpload') }}</el-button> |
||||||
|
</el-upload> |
||||||
|
<el-progress v-if="progressFile.status === 'uploading'" :percentage="parseInt(progressFile.percentage, 10)"></el-progress> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import { defineComponent, onMounted, ref, toRefs, computed } from 'vue'; |
||||||
|
import { ElMessage } from 'element-plus'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
import { getAuthHeaders } from '@/utils/auth'; |
||||||
|
import { getSiteHeaders } from '@/utils/common'; |
||||||
|
import { imageUploadUrl, videoUploadUrl, docUploadUrl, fileUploadUrl, queryGlobalSettings } from '@/api/config'; |
||||||
|
|
||||||
|
export default defineComponent({ |
||||||
|
name: 'BaseUpload', |
||||||
|
props: { |
||||||
|
type: { |
||||||
|
type: String, |
||||||
|
default: 'file', |
||||||
|
validator: (value: string) => ['image', 'video', 'doc', 'file'].includes(value), |
||||||
|
}, |
||||||
|
uploadAction: { type: String }, |
||||||
|
fileAccept: { type: String }, |
||||||
|
fileMaxSize: { type: Number }, |
||||||
|
multiple: { type: Boolean }, |
||||||
|
disabled: { type: Boolean, default: false }, |
||||||
|
'on-success': { type: Function }, |
||||||
|
}, |
||||||
|
setup(props) { |
||||||
|
const { type, uploadAction, fileAccept, fileMaxSize } = toRefs(props); |
||||||
|
const { t } = useI18n(); |
||||||
|
const progressFile = ref<any>({}); |
||||||
|
const global = ref<any>(); |
||||||
|
const fetchGlobalSettings = async () => { |
||||||
|
global.value = await queryGlobalSettings(); |
||||||
|
}; |
||||||
|
onMounted(() => { |
||||||
|
fetchGlobalSettings(); |
||||||
|
}); |
||||||
|
const action = computed(() => { |
||||||
|
if (uploadAction?.value != null) { |
||||||
|
return uploadAction.value; |
||||||
|
} |
||||||
|
switch (type.value) { |
||||||
|
case 'image': |
||||||
|
return imageUploadUrl; |
||||||
|
case 'video': |
||||||
|
return videoUploadUrl; |
||||||
|
case 'doc': |
||||||
|
return docUploadUrl; |
||||||
|
case 'file': |
||||||
|
return fileUploadUrl; |
||||||
|
default: |
||||||
|
throw new Error(`Type not support: ${type.value}`); |
||||||
|
} |
||||||
|
}); |
||||||
|
const accept = computed(() => { |
||||||
|
if (fileAccept?.value != null) { |
||||||
|
return fileAccept.value; |
||||||
|
} |
||||||
|
switch (type.value) { |
||||||
|
case 'image': |
||||||
|
return global?.value?.upload?.imageInputAccept ?? '.jpg,.jpeg,.png,.gif'; |
||||||
|
case 'video': |
||||||
|
return global?.value?.upload?.videoInputAccept ?? '.mp4,.m3u8'; |
||||||
|
case 'doc': |
||||||
|
return global?.value?.upload?.docInputAccept ?? '.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx'; |
||||||
|
case 'file': |
||||||
|
return global?.value?.upload?.fileInputAccept ?? '.zip,.7z,.gz,.bz2,.iso,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.jpg,.jpeg,.png,.gif,.mp4,.m3u8,.mp3,.ogg'; |
||||||
|
default: |
||||||
|
throw new Error(`Type not support: ${type.value}`); |
||||||
|
} |
||||||
|
}); |
||||||
|
const maxSize = computed(() => { |
||||||
|
if (fileMaxSize?.value != null) { |
||||||
|
return fileMaxSize.value; |
||||||
|
} |
||||||
|
switch (type.value) { |
||||||
|
case 'image': |
||||||
|
return global?.value?.upload?.imageLimitByte ?? 0; |
||||||
|
case 'video': |
||||||
|
return global?.value?.upload?.videoLimitByte ?? 0; |
||||||
|
case 'doc': |
||||||
|
return global?.value?.upload?.docLimitByte ?? 0; |
||||||
|
case 'file': |
||||||
|
return global?.value?.upload?.fileLimitByte ?? 0; |
||||||
|
default: |
||||||
|
throw new Error(`Type not support: ${type.value}`); |
||||||
|
} |
||||||
|
}); |
||||||
|
const beforeUpload = (file: any) => { |
||||||
|
if (maxSize.value > 0 && file.size > maxSize.value) { |
||||||
|
ElMessage.error(t('error.fileMaxSize', { size: `${maxSize.value / 1024 / 1024}MB` })); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
}; |
||||||
|
return { progressFile, getAuthHeaders, getSiteHeaders, action, accept, beforeUpload }; |
||||||
|
}, |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,136 @@ |
|||||||
|
<template> |
||||||
|
<div class="w-full"> |
||||||
|
<el-upload :action="fileUploadUrl" |
||||||
|
:headers="{ ...getAuthHeaders(), ...getSiteHeaders() }" |
||||||
|
:accept="accept" |
||||||
|
:before-upload="beforeUpload" |
||||||
|
:on-success="(res) => fileList.push({ name: res.name, url: res.url, length: res.size })" |
||||||
|
:on-progress="(event, file) => (progressFile = file)" |
||||||
|
:show-file-list="false" |
||||||
|
multiple> |
||||||
|
<!-- |
||||||
|
action="https://jsonplaceholder.typicode.com/posts/" |
||||||
|
--> |
||||||
|
<el-button type="primary">{{ $t('clickToUpload') }}</el-button> |
||||||
|
</el-upload> |
||||||
|
<el-progress v-if="progressFile.status === 'uploading'" |
||||||
|
:percentage="parseInt(progressFile.percentage, 10)"></el-progress> |
||||||
|
<transition-group tag="ul" |
||||||
|
:class="['el-upload-list', 'el-upload-list--text', { 'is-disabled': disabled }]" |
||||||
|
name="el-list"> |
||||||
|
<li v-for="file in fileList" |
||||||
|
:key="file.url" |
||||||
|
class="el-upload-list__item is-success"> |
||||||
|
<a class="el-upload-list__item-name" |
||||||
|
@click="handlePreview(file)"> |
||||||
|
<el-icon class="el-icon--document"> |
||||||
|
<Document /> |
||||||
|
</el-icon>{{ file.name }} |
||||||
|
</a> |
||||||
|
<label class="el-upload-list__item-status-label"> |
||||||
|
<el-icon class="el-icon--upload-success el-icon--circle-check"> |
||||||
|
<CircleCheck /> |
||||||
|
</el-icon> |
||||||
|
</label> |
||||||
|
<el-icon v-if="!disabled" |
||||||
|
class="el-icon--close" |
||||||
|
@click="fileList.splice(fileList.indexOf(file), 1)"> |
||||||
|
<Close /> |
||||||
|
</el-icon> |
||||||
|
</li> |
||||||
|
</transition-group> |
||||||
|
<el-dialog :title="$t('article.fileList.attribute')" |
||||||
|
v-model="previewVisible" |
||||||
|
top="5vh" |
||||||
|
:width="768" |
||||||
|
append-to-body> |
||||||
|
<el-form ref="form" |
||||||
|
:model="previewFile" |
||||||
|
label-width="150px"> |
||||||
|
<el-form-item prop="name" |
||||||
|
:label="$t('name')" |
||||||
|
:rules="{ required: true, message: () => $t('v.required') }"> |
||||||
|
<el-input v-model="previewFile.name" |
||||||
|
maxlength="100"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="length" |
||||||
|
:label="$t('size')" |
||||||
|
:rules="{ required: true, message: () => $t('v.required') }"> |
||||||
|
<el-input v-model="previewFile.length" |
||||||
|
maxlength="19"> |
||||||
|
<template #append>Byte</template> |
||||||
|
</el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-form-item prop="url" |
||||||
|
label="URL" |
||||||
|
:rules="{ required: true, message: () => $t('v.required') }"> |
||||||
|
<el-input v-model="previewFile.url" |
||||||
|
maxlength="255"></el-input> |
||||||
|
</el-form-item> |
||||||
|
<el-button @click.prevent="handleSubmit()" |
||||||
|
type="primary" |
||||||
|
native-type="submit">{{ $t('submit') }}</el-button> |
||||||
|
</el-form> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { onMounted, ref, toRefs, computed } from 'vue'; |
||||||
|
import { ElMessage } from 'element-plus'; |
||||||
|
import { Close, Document, CircleCheck } from '@element-plus/icons-vue'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
import { getAuthHeaders } from '@/utils/auth'; |
||||||
|
import { getSiteHeaders } from '@/utils/common'; |
||||||
|
import { fileUploadUrl, queryGlobalSettings } from '@/api/config'; |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
modelValue: { type: Array, default: () => [] }, |
||||||
|
fileAccept: { type: String }, |
||||||
|
fileMaxSize: { type: Number }, |
||||||
|
disabled: { type: Boolean, default: false }, |
||||||
|
}); |
||||||
|
const emit = defineEmits({ 'update:modelValue': null }); |
||||||
|
|
||||||
|
const { fileAccept, fileMaxSize } = toRefs(props); |
||||||
|
const { t } = useI18n(); |
||||||
|
const { modelValue } = toRefs(props); |
||||||
|
const progressFile = ref<any>({}); |
||||||
|
const fileList = computed({ |
||||||
|
get: (): any[] => modelValue.value, |
||||||
|
set: (val) => emit('update:modelValue', val), |
||||||
|
}); |
||||||
|
const previewVisible = ref<boolean>(false); |
||||||
|
const previewFile = ref<any>({}); |
||||||
|
const form = ref<any>(); |
||||||
|
|
||||||
|
const handlePreview = (file: any) => { |
||||||
|
previewFile.value = file; |
||||||
|
previewVisible.value = true; |
||||||
|
}; |
||||||
|
const handleSubmit = () => { |
||||||
|
form.value.validate(async (valid: boolean) => { |
||||||
|
if (!valid) return; |
||||||
|
previewVisible.value = false; |
||||||
|
}); |
||||||
|
}; |
||||||
|
const global = ref<any>(); |
||||||
|
const fetchGlobalSettings = async () => { |
||||||
|
global.value = await queryGlobalSettings(); |
||||||
|
}; |
||||||
|
onMounted(() => { |
||||||
|
fetchGlobalSettings(); |
||||||
|
}); |
||||||
|
const defaultAccept = '.zip,.7z,.gz,.bz2,.iso,.rar,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.jpg,.jpeg,.png,.gif,.mp4,.m3u8,.mp3,.ogg'; |
||||||
|
const accept = computed(() => fileAccept?.value ?? global?.value?.upload?.fileInputAccept ?? defaultAccept); |
||||||
|
const maxSize = computed(() => fileMaxSize?.value ?? global?.value?.upload?.fileLimitByte ?? 0); |
||||||
|
const beforeUpload = (file: any) => { |
||||||
|
if (maxSize.value > 0 && file.size > maxSize.value) { |
||||||
|
ElMessage.error(t('error.fileMaxSize', { size: `${maxSize.value / 1024 / 1024}MB` })); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,84 @@ |
|||||||
|
<template> |
||||||
|
<el-dialog :title="$t('imageCrop')" v-model="visible" @closed="destroyCropper()" top="5vh" :width="768" destroy-on-close append-to-body> |
||||||
|
<div class="text-center"> |
||||||
|
<img ref="imgRef" @load="initCropper()" :src="src" alt="" class="inline" style="max-height:410px" /> |
||||||
|
</div> |
||||||
|
<div class="text-right"> |
||||||
|
<el-button @click.prevent="handleSubmit()" type="primary" native-type="submit" class="mt-4">{{ $t('submit') }}</el-button> |
||||||
|
</div> |
||||||
|
</el-dialog> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts"> |
||||||
|
import { computed, defineComponent, ref, toRefs } from 'vue'; |
||||||
|
import Cropper from 'cropperjs'; |
||||||
|
import 'cropperjs/dist/cropper.css'; |
||||||
|
import { cropImage } from '@/api/config'; |
||||||
|
|
||||||
|
export default defineComponent({ |
||||||
|
name: 'ImageCropper', |
||||||
|
props: { |
||||||
|
modelValue: { type: Boolean, required: true }, |
||||||
|
src: { type: String, default: null }, |
||||||
|
width: { type: Number }, |
||||||
|
height: { type: Number }, |
||||||
|
thumbnailWidth: { type: Number }, |
||||||
|
thumbnailHeight: { type: Number }, |
||||||
|
}, |
||||||
|
emits: { 'update:modelValue': null, success: null }, |
||||||
|
setup(props, { emit }) { |
||||||
|
const { modelValue, src, width, height, thumbnailWidth, thumbnailHeight } = toRefs(props); |
||||||
|
const visible = computed({ |
||||||
|
get: () => modelValue.value, |
||||||
|
set: (val) => emit('update:modelValue', val), |
||||||
|
}); |
||||||
|
|
||||||
|
const imgRef = ref<any>(); |
||||||
|
const cropper = ref<any>(); |
||||||
|
const cropParam = ref<any>({}); |
||||||
|
|
||||||
|
const initCropper = () => { |
||||||
|
if (imgRef.value) { |
||||||
|
cropper.value = new Cropper(imgRef.value, { |
||||||
|
aspectRatio: width?.value && height?.value ? width.value / height.value : NaN, |
||||||
|
autoCropArea: width?.value && height?.value ? 1 : 0.8, |
||||||
|
viewMode: 1, |
||||||
|
minCropBoxWidth: width?.value ?? 16, |
||||||
|
minCropBoxHeight: height?.value ?? 16, |
||||||
|
zoomable: false, |
||||||
|
crop(event) { |
||||||
|
cropParam.value.url = src.value; |
||||||
|
cropParam.value.x = Math.floor(event.detail.x); |
||||||
|
cropParam.value.y = Math.floor(event.detail.y); |
||||||
|
cropParam.value.width = Math.floor(event.detail.width); |
||||||
|
cropParam.value.height = Math.floor(event.detail.height); |
||||||
|
cropParam.value.maxWidth = width?.value; |
||||||
|
cropParam.value.maxHeight = height?.value; |
||||||
|
cropParam.value.thumbnailWidth = thumbnailWidth?.value; |
||||||
|
cropParam.value.thumbnailHeight = thumbnailHeight?.value; |
||||||
|
}, |
||||||
|
}); |
||||||
|
} |
||||||
|
}; |
||||||
|
const destroyCropper = () => { |
||||||
|
if (cropper.value) { |
||||||
|
cropper.value.destroy(); |
||||||
|
} |
||||||
|
}; |
||||||
|
const handleSubmit = async () => { |
||||||
|
visible.value = false; |
||||||
|
emit('success', (await cropImage(cropParam.value)).url); |
||||||
|
}; |
||||||
|
return { imgRef, visible, initCropper, destroyCropper, handleSubmit }; |
||||||
|
}, |
||||||
|
}); |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
/* Ensure the size of the image fit the container perfectly */ |
||||||
|
:deep(img) { |
||||||
|
display: block; |
||||||
|
/* This rule is very important, please don't ignore this */ |
||||||
|
max-width: 100%; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,157 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<!-- <transition-group tag="ul" :class="['el-upload-list', 'el-upload-list--picture-card', { 'is-disabled': disabled }]" name="el-list"> --> |
||||||
|
<ul :class="['el-upload-list', 'el-upload-list--picture-card', { 'is-disabled': disabled }]"> |
||||||
|
<li v-for="file in fileList" |
||||||
|
:key="file.url" |
||||||
|
class="el-upload-list__item is-success"> |
||||||
|
<div class="w-full h-full bg-gray-50 flex justify-center items-center"> |
||||||
|
<img class="max-w-full max-h-full block" |
||||||
|
:src="file.url" |
||||||
|
alt="" /> |
||||||
|
<div class="full-flex-center absolute rounded-md cursor-default bg-black bg-opacity-50 opacity-0 hover:opacity-100 space-x-4" |
||||||
|
@click.stop> |
||||||
|
<el-icon class="image-action" |
||||||
|
@click="(cropperVisible = true), (currentFile = file)" |
||||||
|
:title="$t('cropImage')"> |
||||||
|
<Crop /> |
||||||
|
</el-icon> |
||||||
|
<el-icon class="image-action" |
||||||
|
@click="handlePreview(file)" |
||||||
|
:title="$t('previewImage')"> |
||||||
|
<View /> |
||||||
|
</el-icon> |
||||||
|
<el-icon class="image-action" |
||||||
|
@click="fileList.splice(fileList.indexOf(file), 1)" |
||||||
|
:title="$t('deleteImage')"> |
||||||
|
<Delete /> |
||||||
|
</el-icon> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<!-- </transition-group> --> |
||||||
|
<el-upload :action="imageUploadUrl" |
||||||
|
:headers="{ ...getAuthHeaders(), ...getSiteHeaders() }" |
||||||
|
:data="getData()" |
||||||
|
:accept="accept" |
||||||
|
:before-upload="beforeUpload" |
||||||
|
:on-success="(res, file) => fileList.push({ name: res.name, url: res.url })" |
||||||
|
:on-progress="(event, file) => (progressFile = file)" |
||||||
|
:show-file-list="false" |
||||||
|
multiple |
||||||
|
class="inline-block"> |
||||||
|
<el-progress v-if="progressFile.status === 'uploading'" |
||||||
|
type="circle" |
||||||
|
:percentage="parseInt(progressFile.percentage, 10)" /> |
||||||
|
<div v-else |
||||||
|
class="el-upload--picture-card"> |
||||||
|
<el-icon> |
||||||
|
<Plus /> |
||||||
|
</el-icon> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
<div> |
||||||
|
<el-dialog v-model="previewVisible" |
||||||
|
top="5vh" |
||||||
|
:width="768"> |
||||||
|
<el-input v-model="previewFile.url" |
||||||
|
maxlength="255"> |
||||||
|
<template #prepend>URL</template> |
||||||
|
</el-input> |
||||||
|
<el-input v-model="previewFile.description" |
||||||
|
type="textarea" |
||||||
|
:rows="2" |
||||||
|
:placeholder="$t('article.imageList.description')" |
||||||
|
class="mt-1"></el-input> |
||||||
|
<img :src="previewFile.url" |
||||||
|
alt="" |
||||||
|
class="mt-1 border border-gray-300" /> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
<image-cropper v-model="cropperVisible" |
||||||
|
:src="currentFile.url" |
||||||
|
:thumbnailWidth="thumbnailWidth" |
||||||
|
:thumbnailHeight="thumbnailHeight" |
||||||
|
@success="(url) => (currentFile.url = url)"></image-cropper> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { onMounted, ref, toRefs, computed } from 'vue'; |
||||||
|
import { ElMessage } from 'element-plus'; |
||||||
|
import { Plus, Crop, View, Delete } from '@element-plus/icons-vue'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
import { getAuthHeaders } from '@/utils/auth'; |
||||||
|
import { getSiteHeaders } from '@/utils/common'; |
||||||
|
import { imageUploadUrl, queryGlobalSettings } from '@/api/config'; |
||||||
|
import ImageCropper from './ImageCropper.vue'; |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
modelValue: { type: Array, default: () => [] }, |
||||||
|
fileAccept: { type: String }, |
||||||
|
fileMaxSize: { type: Number }, |
||||||
|
maxWidth: { type: Number }, |
||||||
|
maxHeight: { type: Number }, |
||||||
|
disabled: { type: Boolean, default: false }, |
||||||
|
}); |
||||||
|
|
||||||
|
const emit = defineEmits({ 'update:modelValue': null }); |
||||||
|
|
||||||
|
const { modelValue, maxWidth, maxHeight, fileAccept, fileMaxSize } = toRefs(props); |
||||||
|
const { t } = useI18n(); |
||||||
|
const progressFile = ref<any>({}); |
||||||
|
const currentFile = ref<any>({}); |
||||||
|
const previewVisible = ref<boolean>(false); |
||||||
|
const cropperVisible = ref<boolean>(false); |
||||||
|
const previewFile = ref<any>({ src: 'data:;base64,=' }); |
||||||
|
const fileList = computed({ |
||||||
|
get: (): any => modelValue.value, |
||||||
|
set: (val) => emit('update:modelValue', val), |
||||||
|
}); |
||||||
|
const handlePreview = (file: any) => { |
||||||
|
previewFile.value = file; |
||||||
|
previewVisible.value = true; |
||||||
|
}; |
||||||
|
const thumbnailWidth = 300; |
||||||
|
const thumbnailHeight = 300; |
||||||
|
const getData = () => { |
||||||
|
const data: any = { isWatermark: true, thumbnailWidth, thumbnailHeight }; |
||||||
|
if (maxWidth?.value != null) { |
||||||
|
data.maxWidth = maxWidth.value; |
||||||
|
} |
||||||
|
if (maxHeight?.value != null) { |
||||||
|
data.maxHeight = maxHeight.value; |
||||||
|
} |
||||||
|
return data; |
||||||
|
}; |
||||||
|
const global = ref<any>(); |
||||||
|
const fetchGlobalSettings = async () => { |
||||||
|
global.value = await queryGlobalSettings(); |
||||||
|
}; |
||||||
|
onMounted(() => { |
||||||
|
fetchGlobalSettings(); |
||||||
|
}); |
||||||
|
const defaultAccept = 'image/jpg,image/jpeg,image/png,image/gif'; |
||||||
|
const accept = computed(() => fileAccept?.value ?? global?.value?.upload?.imageInputAccept ?? defaultAccept); |
||||||
|
const maxSize = computed(() => fileMaxSize?.value ?? global?.value?.upload?.imageLimitByte ?? 0); |
||||||
|
const beforeUpload = (file: any) => { |
||||||
|
if (maxSize.value > 0 && file.size > maxSize.value) { |
||||||
|
ElMessage.error(t('error.fileMaxSize', { size: `${maxSize.value / 1024 / 1024}MB` })); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
:deep(.el-dialog__headerbtn) { |
||||||
|
top: 4px; |
||||||
|
} |
||||||
|
.full-flex-center { |
||||||
|
@apply w-full h-full flex justify-center items-center; |
||||||
|
} |
||||||
|
.image-action { |
||||||
|
@apply cursor-pointer text-xl text-white; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,149 @@ |
|||||||
|
<template> |
||||||
|
<el-upload :action="imageUploadUrl" |
||||||
|
:headers="{ ...getAuthHeaders(), ...getSiteHeaders() }" |
||||||
|
:accept="accept" |
||||||
|
:before-upload="beforeUpload" |
||||||
|
:data="data" |
||||||
|
:show-file-list="false" |
||||||
|
:on-success="(res) => ((src = res.url), (cropperVisible = mode === 'manual'))" |
||||||
|
:on-progress="(event, file) => (progressFile = file)"> |
||||||
|
<!-- |
||||||
|
// 用于测试上传进度条 |
||||||
|
action="https://jsonplaceholder.typicode.com/posts/" |
||||||
|
--> |
||||||
|
<div v-if="src" |
||||||
|
class="full-flex-center rounded-border relative hover:border-opacity-0"> |
||||||
|
<img :src="src" |
||||||
|
class="max-w-full max-h-full block" /> |
||||||
|
<div class="full-flex-center absolute rounded-md cursor-default bg-black bg-opacity-50 opacity-0 hover:opacity-100 space-x-4" |
||||||
|
@click.stop> |
||||||
|
<el-icon class="image-action" |
||||||
|
@click="cropperVisible = true" |
||||||
|
:title="$t('cropImage')"> |
||||||
|
<Crop /> |
||||||
|
</el-icon> |
||||||
|
<el-icon class="image-action" |
||||||
|
@click="previewVisible = true" |
||||||
|
:title="$t('previewImage')"> |
||||||
|
<View /> |
||||||
|
</el-icon> |
||||||
|
<el-icon class="image-action" |
||||||
|
@click="src = undefined" |
||||||
|
:title="$t('deleteImage')"> |
||||||
|
<Delete /> |
||||||
|
</el-icon> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<el-progress v-else-if="progressFile.status === 'uploading'" |
||||||
|
type="circle" |
||||||
|
:percentage="parseInt(progressFile.percentage, 10)" /> |
||||||
|
<div v-else |
||||||
|
class="el-upload--picture-card"> |
||||||
|
<el-icon> |
||||||
|
<plus /> |
||||||
|
</el-icon> |
||||||
|
</div> |
||||||
|
</el-upload> |
||||||
|
<div> |
||||||
|
<el-dialog v-model="previewVisible" |
||||||
|
top="5vh" |
||||||
|
:width="768" |
||||||
|
append-to-body |
||||||
|
destroy-on-close> |
||||||
|
<el-input v-model="src"> |
||||||
|
<template #prepend>URL</template> |
||||||
|
</el-input> |
||||||
|
<img :src="src" |
||||||
|
alt="" |
||||||
|
class="mt-1 border border-gray-300" /> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
<image-cropper v-model="cropperVisible" |
||||||
|
:src="src" |
||||||
|
:width="width" |
||||||
|
:height="height" |
||||||
|
@success="(url) => (src = url)"></image-cropper> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
import { computed, onMounted, ref, toRefs } from 'vue'; |
||||||
|
import { ElMessage } from 'element-plus'; |
||||||
|
import { Plus, Crop, View, Delete } from '@element-plus/icons-vue'; |
||||||
|
import { useI18n } from 'vue-i18n'; |
||||||
|
import { getAuthHeaders } from '@/utils/auth'; |
||||||
|
import { getSiteHeaders } from '@/utils/common'; |
||||||
|
import { imageUploadUrl, queryGlobalSettings } from '@/api/config'; |
||||||
|
import ImageCropper from './ImageCropper.vue'; |
||||||
|
|
||||||
|
// 'image/jpg,image/jpeg,image/png,image/gif' |
||||||
|
|
||||||
|
const props = defineProps({ |
||||||
|
modelValue: { type: String, default: null }, |
||||||
|
fileAccept: { type: String }, |
||||||
|
fileMaxSize: { type: Number }, |
||||||
|
width: { type: Number }, |
||||||
|
height: { type: Number }, |
||||||
|
mode: { type: String, default: 'none' }, |
||||||
|
}); |
||||||
|
|
||||||
|
const emit = defineEmits({ 'update:modelValue': null }); |
||||||
|
|
||||||
|
const { modelValue, width, height, mode, fileAccept, fileMaxSize } = toRefs(props); |
||||||
|
const { t } = useI18n(); |
||||||
|
const progressFile = ref<any>({}); |
||||||
|
const previewVisible = ref<boolean>(false); |
||||||
|
const cropperVisible = ref<boolean>(false); |
||||||
|
const src = computed({ |
||||||
|
get: (): string | undefined => modelValue.value, |
||||||
|
set: (val: string | undefined) => emit('update:modelValue', val), |
||||||
|
}); |
||||||
|
const resizable = computed(() => ['cut', 'resize'].includes(mode.value)); |
||||||
|
const data = computed(() => { |
||||||
|
const params: any = { resizeMode: mode.value === 'cut' ? 'cut' : 'normal' }; |
||||||
|
if (width?.value != null) { |
||||||
|
// 为0不限制,为空则依然受全局图片宽高限制 |
||||||
|
params.maxWidth = resizable.value ? width.value : 0; |
||||||
|
} |
||||||
|
if (height?.value != null) { |
||||||
|
// 为0不限制,为空则依然受全局图片宽高限制 |
||||||
|
params.maxHeight = resizable.value ? height.value : 0; |
||||||
|
} |
||||||
|
return params; |
||||||
|
}); |
||||||
|
const global = ref<any>(); |
||||||
|
const fetchGlobalSettings = async () => { |
||||||
|
global.value = await queryGlobalSettings(); |
||||||
|
}; |
||||||
|
onMounted(() => { |
||||||
|
fetchGlobalSettings(); |
||||||
|
}); |
||||||
|
const accept = computed(() => fileAccept?.value ?? global?.value?.upload?.imageInputAccept ?? 'image/jpg,image/jpeg,image/png,image/gif'); |
||||||
|
const maxSize = computed(() => fileMaxSize?.value ?? global?.value?.upload?.imageLimitByte ?? 0); |
||||||
|
const beforeUpload = (file: any) => { |
||||||
|
if (maxSize.value > 0 && file.size > maxSize.value) { |
||||||
|
ElMessage.error(t('error.fileMaxSize', { size: `${maxSize.value / 1024 / 1024}MB` })); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return true; |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
:deep(.el-dialog__headerbtn) { |
||||||
|
top: 4px; |
||||||
|
} |
||||||
|
:deep(.el-upload) { |
||||||
|
width: 148px; |
||||||
|
height: 148px; |
||||||
|
} |
||||||
|
.full-flex-center { |
||||||
|
@apply w-full h-full flex justify-center items-center; |
||||||
|
} |
||||||
|
.rounded-border { |
||||||
|
border: 1px solid #c0ccda; |
||||||
|
@apply rounded-md bg-gray-50; |
||||||
|
} |
||||||
|
.image-action { |
||||||
|
@apply cursor-pointer text-xl text-white; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,4 @@ |
|||||||
|
export { default as ImageUpload } from './ImageUpload.vue'; |
||||||
|
export { default as ImageListUpload } from './ImageListUpload.vue'; |
||||||
|
export { default as FileListUpload } from './FileListUpload.vue'; |
||||||
|
export { default as BaseUpload } from './BaseUpload.vue'; |
@ -0,0 +1,335 @@ |
|||||||
|
import i18n from '@/i18n'; |
||||||
|
|
||||||
|
export function getPermsTreeData(): any[] { |
||||||
|
const { |
||||||
|
global: { t }, |
||||||
|
} = i18n; |
||||||
|
return [ |
||||||
|
{ |
||||||
|
label: t('menu.home'), |
||||||
|
key: 'home', |
||||||
|
perms: ['auth'], |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
label: t('menu.personal'), |
||||||
|
key: 'personal', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
label: t('menu.personal.password'), |
||||||
|
key: 'password:update', |
||||||
|
perms: ['password:update'], |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.content'), |
||||||
|
key: 'content', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
label: t('menu.content.article'), |
||||||
|
key: 'article', |
||||||
|
perms: ['article:page', 'article:list', 'channel:list', 'dict:list', 'model:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'article:page' }, |
||||||
|
{ label: t('add'), key: 'article:create', perms: ['article:create'] }, |
||||||
|
{ label: t('edit'), key: 'article:update', perms: ['article:update', 'article:show'] }, |
||||||
|
{ label: t('delete'), key: 'article:delete', perms: ['article:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.content.channel'), |
||||||
|
key: 'channel', |
||||||
|
perms: ['channel:page', 'channel:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'channel:page' }, |
||||||
|
{ label: t('add'), key: 'channel:create', perms: ['channel:create'] }, |
||||||
|
{ label: t('edit'), key: 'channel:update', perms: ['channel:update', 'channel:show'] }, |
||||||
|
{ label: t('delete'), key: 'channel:delete', perms: ['channel:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.content.blockItem'), |
||||||
|
key: 'blockItem', |
||||||
|
perms: ['blockItem:page', 'blockItem:list', 'block:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'blockItem:page' }, |
||||||
|
{ label: t('add'), key: 'blockItem:create', perms: ['blockItem:create'] }, |
||||||
|
{ label: t('edit'), key: 'blockItem:update', perms: ['blockItem:update', 'blockItem:show'] }, |
||||||
|
{ label: t('delete'), key: 'blockItem:delete', perms: ['blockItem:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.content.attachment'), |
||||||
|
key: 'attachment', |
||||||
|
perms: ['attachment:page', 'attachment:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'attachment:page' }, |
||||||
|
{ label: t('add'), key: 'attachment:create', perms: ['attachment:create'] }, |
||||||
|
{ label: t('edit'), key: 'attachment:update', perms: ['attachment:update', 'attachment:show'] }, |
||||||
|
{ label: t('delete'), key: 'attachment:delete', perms: ['attachment:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.content.generator'), |
||||||
|
key: 'generator', |
||||||
|
perms: ['generator:show', 'siteSettings:html:show', 'task:list', 'task:show', 'task:delete'], |
||||||
|
children: [ |
||||||
|
{ label: t('generator.op.fulltext.reindexAll'), key: 'generator:fulltext:reindexAll', perms: ['generator:fulltext:reindexAll'] }, |
||||||
|
{ label: t('generator.op.fulltext.reindexSite'), key: 'generator:fulltext:reindexSite', perms: ['generator:fulltext:reindexSite'] }, |
||||||
|
{ label: t('generator.html'), key: 'generator:html', perms: ['generator:html'] }, |
||||||
|
{ label: t('site.settings.html'), key: 'siteSettings:html:update', perms: ['siteSettings:html:update', 'generator:html'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.config'), |
||||||
|
key: 'config', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
label: t('menu.config.globalSettings'), |
||||||
|
key: 'globalSettings', |
||||||
|
perms: ['globalSettings:show'], |
||||||
|
children: [ |
||||||
|
{ label: t('global.settings.base'), key: 'globalSettings:base:update', perms: ['globalSettings:base:update'] }, |
||||||
|
{ label: t('global.settings.upload'), key: 'globalSettings:upload:update', perms: ['globalSettings:upload:update'] }, |
||||||
|
{ label: t('global.settings.customs'), key: 'globalSettings:customs:update', perms: ['globalSettings:customs:update'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.config.siteSettings'), |
||||||
|
key: 'siteSettings', |
||||||
|
perms: ['siteSettings:show'], |
||||||
|
children: [ |
||||||
|
{ label: t('site.settings.base'), key: 'siteSettings:base:update', perms: ['siteSettings:base:update'] }, |
||||||
|
{ label: t('site.settings.watermark'), key: 'siteSettings:watermark:update', perms: ['siteSettings:watermark:update'] }, |
||||||
|
{ label: t('site.settings.customs'), key: 'siteSettings:customs:update', perms: ['siteSettings:customs:update'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.config.model'), |
||||||
|
key: 'model', |
||||||
|
perms: ['model:page', 'model:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'model:page' }, |
||||||
|
{ label: t('add'), key: 'model:create', perms: ['model:create'] }, |
||||||
|
{ label: t('edit'), key: 'model:update', perms: ['model:update', 'model:show'] }, |
||||||
|
{ label: t('delete'), key: 'model:delete', perms: ['model:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.config.block'), |
||||||
|
key: 'block', |
||||||
|
perms: ['block:page', 'block:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'block:page' }, |
||||||
|
{ label: t('add'), key: 'block:create', perms: ['block:create'] }, |
||||||
|
{ label: t('edit'), key: 'block:update', perms: ['block:update', 'block:show'] }, |
||||||
|
{ label: t('delete'), key: 'block:delete', perms: ['block:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.config.dictType'), |
||||||
|
key: 'dictType', |
||||||
|
perms: ['dictType:page', 'dictType:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'dictType:page' }, |
||||||
|
{ label: t('add'), key: 'dictType:create', perms: ['dictType:create'] }, |
||||||
|
{ label: t('edit'), key: 'dictType:update', perms: ['dictType:update', 'dictType:show'] }, |
||||||
|
{ label: t('delete'), key: 'dictType:delete', perms: ['dictType:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.config.dict'), |
||||||
|
key: 'dict', |
||||||
|
perms: ['dict:page', 'dict:list', 'dictType:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'dict:page' }, |
||||||
|
{ label: t('add'), key: 'dict:create', perms: ['dict:create'] }, |
||||||
|
{ label: t('edit'), key: 'dict:update', perms: ['dict:update', 'dict:show'] }, |
||||||
|
{ label: t('delete'), key: 'dict:delete', perms: ['dict:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.user'), |
||||||
|
key: 'user', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
label: t('menu.user.user'), |
||||||
|
key: 'user', |
||||||
|
perms: ['user:page', 'user:list', 'group:list', 'org:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'user:page' }, |
||||||
|
{ label: t('add'), key: 'user:create', perms: ['user:create'] }, |
||||||
|
{ label: t('edit'), key: 'user:update', perms: ['user:update', 'user:show'] }, |
||||||
|
{ label: t('delete'), key: 'user:delete', perms: ['user:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.user.role'), |
||||||
|
key: 'role', |
||||||
|
perms: ['role:page', 'role:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'role:page' }, |
||||||
|
{ label: t('add'), key: 'role:create', perms: ['role:create'] }, |
||||||
|
{ label: t('edit'), key: 'role:update', perms: ['role:update', 'role:show'] }, |
||||||
|
{ label: t('delete'), key: 'role:delete', perms: ['role:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.user.group'), |
||||||
|
key: 'group', |
||||||
|
perms: ['group:page', 'group:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'group:page' }, |
||||||
|
{ label: t('add'), key: 'group:create', perms: ['group:create'] }, |
||||||
|
{ label: t('edit'), key: 'group:update', perms: ['group:update', 'group:show'] }, |
||||||
|
{ label: t('delete'), key: 'group:delete', perms: ['group:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
// label: t('menu.user.org'),
|
||||||
|
key: 'org', |
||||||
|
perms: ['org:page', 'org:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'org:page' }, |
||||||
|
{ label: t('add'), key: 'org:create', perms: ['org:create'] }, |
||||||
|
{ label: t('edit'), key: 'org:update', perms: ['org:update', 'org:show'] }, |
||||||
|
{ label: t('delete'), key: 'org:delete', perms: ['org:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.system'), |
||||||
|
key: 'system', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
// label: t('menu.system.site'),
|
||||||
|
key: 'site', |
||||||
|
perms: ['site:page', 'site:list', 'org:list', 'model:list', 'storage:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'site:page' }, |
||||||
|
{ label: t('add'), key: 'site:create', perms: ['site:create'] }, |
||||||
|
{ label: t('edit'), key: 'site:update', perms: ['site:update', 'site:show'] }, |
||||||
|
{ label: t('delete'), key: 'site:delete', perms: ['site:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
{ |
||||||
|
label: t('menu.system.storage'), |
||||||
|
key: 'storage', |
||||||
|
perms: ['storage:page', 'storage:list'], |
||||||
|
children: [ |
||||||
|
{ label: t('list'), key: 'storage:page' }, |
||||||
|
{ label: t('add'), key: 'storage:create', perms: ['storage:create'] }, |
||||||
|
{ label: t('edit'), key: 'storage:update', perms: ['storage:update', 'storage:show'] }, |
||||||
|
{ label: t('delete'), key: 'storage:delete', perms: ['storage:delete'] }, |
||||||
|
], |
||||||
|
}, |
||||||
|
// {
|
||||||
|
// label: t('menu.system.task'),
|
||||||
|
// key: 'task',
|
||||||
|
// perms: ['task:page', 'task:list'],
|
||||||
|
// children: [
|
||||||
|
// { label: t('list'), key: 'task:page' },
|
||||||
|
// { label: t('add'), key: 'task:create', perms: ['task:create'] },
|
||||||
|
// { label: t('edit'), key: 'task:update', perms: ['task:update', 'task:show'] },
|
||||||
|
// { label: t('delete'), key: 'task:delete', perms: ['task:delete'] },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
], |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
export function getModelData(): any { |
||||||
|
return { |
||||||
|
article: { |
||||||
|
mains: [ |
||||||
|
{ code: 'title', must: true, show: true, double: false, required: true }, |
||||||
|
{ code: 'subtitle', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'fullTitle', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'linkUrl', must: false, show: true, double: false, required: false }, |
||||||
|
{ code: 'seoKeywords', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'seoDescription', must: false, show: true, double: false, required: false }, |
||||||
|
{ code: 'author', must: false, show: false, double: true, required: false }, |
||||||
|
{ code: 'editor', must: false, show: false, double: true, required: false }, |
||||||
|
{ code: 'image', must: false, show: true, double: false, required: false, type: 'image', imageWidth: 300, imageHeight: 200, imageMode: 'manual' }, |
||||||
|
{ code: 'file', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'video', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'doc', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'imageList', must: false, show: false, double: false, required: false, type: 'imageList', imageMaxWidth: 1920, imageMaxHeight: 1920 }, |
||||||
|
{ code: 'fileList', must: false, show: false, double: false, required: false }, |
||||||
|
{ code: 'text', must: false, show: true, double: false, required: true }, |
||||||
|
], |
||||||
|
asides: [ |
||||||
|
{ code: 'channel', must: true, show: true, required: true }, |
||||||
|
{ code: 'org', must: false, show: true, required: true }, |
||||||
|
{ code: 'publishDate', must: true, show: true, required: true }, |
||||||
|
// { code: 'offlineDate', must: false, show: true, required: false },
|
||||||
|
{ code: 'source', must: false, show: true, required: false }, |
||||||
|
{ code: 'articleTemplate', must: false, show: true, required: false }, |
||||||
|
{ code: 'allowComment', must: false, show: true, required: true }, |
||||||
|
{ code: 'user', must: false, show: false, required: true }, |
||||||
|
{ code: 'created', must: false, show: false, required: true }, |
||||||
|
{ code: 'modifiedUser', must: false, show: false, required: false }, |
||||||
|
{ code: 'modified', must: false, show: false, required: false }, |
||||||
|
], |
||||||
|
}, |
||||||
|
channel: { |
||||||
|
mains: [ |
||||||
|
{ code: 'name', must: true, show: true, double: true, required: true }, |
||||||
|
{ code: 'alias', must: true, show: true, double: true, required: true }, |
||||||
|
{ code: 'linkUrl', must: true, show: true, double: false, required: true }, |
||||||
|
{ code: 'seoTitle', must: false, show: true, double: true, required: false }, |
||||||
|
{ code: 'seoKeywords', must: false, show: true, double: true, required: false }, |
||||||
|
{ code: 'seoDescription', must: false, show: true, double: false, required: false }, |
||||||
|
{ code: 'channelTemplate', must: false, show: true, double: true, required: true }, |
||||||
|
{ code: 'articleTemplate', must: false, show: true, double: true, required: true }, |
||||||
|
{ code: 'channelModel', must: true, show: true, double: true, required: true }, |
||||||
|
{ code: 'articleModel', must: true, show: true, double: true, required: true }, |
||||||
|
{ code: 'group', must: false, show: true, double: false, required: true }, |
||||||
|
{ code: 'nav', must: false, show: true, double: true, required: true }, |
||||||
|
{ code: 'allowComment', must: false, show: true, double: true, required: true }, |
||||||
|
{ code: 'allowContribute', must: false, show: true, double: true, required: true }, |
||||||
|
{ code: 'allowSearch', must: false, show: true, double: true, required: true }, |
||||||
|
{ code: 'text', must: false, show: false, double: false, required: false }, |
||||||
|
], |
||||||
|
asides: [ |
||||||
|
{ code: 'type', must: true, show: true, required: true }, |
||||||
|
{ code: 'parent', must: true, show: true, required: false }, |
||||||
|
{ code: 'pageSize', must: true, show: true, required: true }, |
||||||
|
], |
||||||
|
}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
export function mergeModelFields(defaultFields: any[], s: string | null | undefined, type: string): any[] { |
||||||
|
const fields = JSON.parse(s || '[]'); |
||||||
|
const defaults = defaultFields.map((item: any) => ({ ...item, label: `${type}.${item.code}` })); |
||||||
|
// 去除默认字段中不存在的字段
|
||||||
|
fields.filter((field: any) => defaults.findIndex((item) => item.code === field.code) !== -1); |
||||||
|
defaults.forEach((item) => { |
||||||
|
const index = fields.findIndex((it: any) => it.code === item.code); |
||||||
|
if (index !== -1) { |
||||||
|
// 加上缺失属性,覆盖不可改属性
|
||||||
|
fields[index] = { ...item, ...fields[index], must: item.must, label: item.label, type: item.type }; |
||||||
|
} else { |
||||||
|
// 加上没有的字段
|
||||||
|
fields.push(item); |
||||||
|
} |
||||||
|
}); |
||||||
|
return fields; |
||||||
|
} |
||||||
|
|
||||||
|
export function arr2obj(arr: any[]) { |
||||||
|
const obj: Record<string, any> = {}; |
||||||
|
arr.forEach((item: any) => { |
||||||
|
obj[item.code] = item; |
||||||
|
}); |
||||||
|
return obj; |
||||||
|
} |
@ -1,10 +1,14 @@ |
|||||||
import defaultSettings from '@/settings'; |
import defaultSettings from '@/settings'; |
||||||
|
import i18n from '@/i18n'; |
||||||
|
|
||||||
const { title } = defaultSettings; |
const { title } = defaultSettings; |
||||||
|
|
||||||
export default function getPageTitle(pageTitle: string | undefined): string { |
export default function getPageTitle(pageTitle: string | undefined): string { |
||||||
if (pageTitle) { |
if (pageTitle) { |
||||||
return `${pageTitle} - ${title}`; |
const { |
||||||
|
global: { t }, |
||||||
|
} = i18n; |
||||||
|
return `${t(pageTitle)} - ${title}`; |
||||||
} |
} |
||||||
return `${title}`; |
return `${title}`; |
||||||
} |
} |
||||||
|
@ -0,0 +1,174 @@ |
|||||||
|
<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({ |
||||||
|
checkpointId: levelId, |
||||||
|
projectId, |
||||||
|
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(levelId, projectId); |
||||||
|
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`; // 1,关卡id,角色(这个页面是风控经理策略) |
||||||
|
const rule = []; |
||||||
|
|
||||||
|
data.map((e) => { |
||||||
|
e.recordChildren.forEach((n, 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`; // 1,关卡id,角色(这个页面是风控经理策略) |
|
||||||
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,187 @@ |
|||||||
|
<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 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(1030); |
||||||
|
const result = []; |
||||||
|
process.map((e, i) => { |
||||||
|
const cur = info.value.length ? info.value[i] : {}; |
||||||
|
let temp = { |
||||||
|
checkpointId: levelId, |
||||||
|
projectId, |
||||||
|
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(levelId, projectId); |
||||||
|
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>) => { |
||||||
|
const preIds = `1,${Cookies.get('sand-level')},42,69,1030`; // 1,关卡id,角色(这个页面是风控经理策略) |
||||||
|
const rule = []; |
||||||
|
|
||||||
|
data.forEach((e, i) => { |
||||||
|
rule.push(handleId(1052, '', '', preIds + ',' + e.stRecordId + ',1052', ''), handleId(1053, 282, e.checkObject, preIds + ',' + e.stRecordId + ',1053', 1)); |
||||||
|
i !== 4 && 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`; // 1,关卡id,角色(这个页面是风控经理策略) |
|
||||||
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,347 @@ |
|||||||
|
<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 === 13"> |
||||||
|
从 |
||||||
|
<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 === 17">当前尚未偿还的贷款总额。</template> |
||||||
|
<template v-if="$index === 20"> |
||||||
|
平均额度使用率 = |
||||||
|
<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 === 24"> |
||||||
|
最大用信率 = |
||||||
|
<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 === 28">到目前为止使用额度的次数。</template> |
||||||
|
<template v-if="$index === 32">到目前为止客户可以使用的最大额度。</template> |
||||||
|
<template v-if="$index === 37">客户贷记卡已经逾期的总月数。</template> |
||||||
|
<template v-if="$index === 39">客户在行所有贷款已经逾期的总月数。</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 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(1031); |
||||||
|
const result = [ |
||||||
|
{ |
||||||
|
recordName: '基准分', |
||||||
|
}, |
||||||
|
]; |
||||||
|
process.map((e, i) => { |
||||||
|
let temp = { |
||||||
|
checkpointId: levelId, |
||||||
|
projectId, |
||||||
|
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(levelId, projectId); |
||||||
|
info.value = data; |
||||||
|
getConfig(); |
||||||
|
} finally { |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
interface SpanMethodProps { |
||||||
|
row: Record<string, any>; |
||||||
|
column: TableColumnCtx<Record<string, any>>; |
||||||
|
rowIndex: number; |
||||||
|
columnIndex: number; |
||||||
|
} |
||||||
|
const rowMerge1 = [1, 32]; |
||||||
|
const rowMerge2 = [6, 17]; |
||||||
|
const rowMerge3 = [9, 13, 20, 24, 28]; |
||||||
|
const rowMerge4 = [37, 39]; |
||||||
|
// 表格合并 |
||||||
|
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`; // 1,关卡id,角色(这个页面是风控经理策略) |
||||||
|
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 === 20 || i === 24) { |
||||||
|
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[13].formulaOne && rule.push(handleId(1083, 291, data[13].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`; // 1,关卡id,角色(这个页面是风控经理策略) |
|
||||||
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> |
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue