feat:add i18n

This commit is contained in:
samwaf
2024-09-03 14:53:03 +08:00
parent b2b7aebd4a
commit 0c3fa7d78a
50 changed files with 1980 additions and 2890 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SamWaf网站防火墙系统(Web Application Firewall)</title>
<title></title>
</head>
<body>
<div id="app"></div>
+2
View File
@@ -34,6 +34,8 @@
"vue-baidu-map": "^0.21.22",
"vue-clipboard2": "^0.3.1",
"vue-codemirror": "^4.0.6",
"vue-i18n": "^8.28.2",
"vue-meta": "^2.4.0",
"vue-router": "^3.5.1",
"vuex": "^3.6.2",
"vuex-router-sync": "^5.0.0"
+494
View File
@@ -0,0 +1,494 @@
/**
* SamWaf English Language Pack
*
* common - Common fields
* menu - Left menu
* page - Fields for specific functional pages
*/
export default {
common:{
confirm: "Confirm",
cancel: "Cancel",
close: "Close",
search: "Search",
all: "All",
details: "Details",
new: "New",
copy: "Copy",
edit: "Edit",
delete: "Delete",
reset: "Reset",
submit: "Submit",
return: "Return",
status: "Status",
remarks: "Remarks",
select_placeholder: "Please select",
placeholder: "Please enter",
placeholder_content: "Please enter content",
debug: "Debug",
confirm_delete: "Confirm delete the selected data?",
data_delete_warning: "After deletion, the data will be removed and cannot be recovered",
create_time: "Creation Time",
op: "Operation Content",
date: "Date",
online_document: "Online Document",
defense_status:{
all: "All",
stop: "Block",
pass: "Allow",
forbid: "Forbid",
},
on: "On",
off: "Off"
},
login:{
login_title: "Login",
login_sub_title: "SamWaf Website Firewall Management",
login_has_question: "Having trouble?",
login_online_document: "SamWaf Online Documentation",
input_account_placeholder: "Please enter your account:",
input_password_placeholder: "Please enter your password:",
login_btn_title: "Login",
rule:{
phone: "Phone number is required",
account: "Account is required",
password: "Password is required",
verifyCode: "Verification code is required"
},
login_success: "Login successful",
},
topNav:{
update:{
has_new_version: "New version available",
},
contract: "Contact SamWaf",
help_document: "Help Document",
current_server: "Current Server",
system_config: "System Configuration",
dropdown_person_center: "Personal",
dropdown_update: "Update",
dropdown_reboot_waf: "Reboot",
dropdown_logout: "Logout",
},
dashboard:{
tip_create_website_title: "You have not created a protected website, click to create one",
tip_create_website_link: "Create now",
tip_modify_pwd_title: "You are still using the default account and password, please change it soon",
tip_modify_pwd_link: "Change now",
counter:{
today_of_attack_count: "Today's Attack Count",
all_visit_count: "Total Visits Today",
not_normal_visit_count: "Abnormal IPs Today (count)",
qps: "Current QPS",
},
cycle_title: "Comparison of Attacks and Normal Access Over Time",
cycle_subtitle: "(times)",
cycle_normal_count: "Normal Count This Period",
cycle_attack_count: "Attack Count This Period",
cycle_percent_title: "Proportion of Normal to Attack",
cycle_percent_subtitle: "In the Period",
},
menu:{
dashboard: {
parent_title: "Dashboard",
dashboard_title: "Overview Dashboard",
},
host:{
parent_title: "Website Protection",
host_title: "Website Protection",
host_detail: "Host Protection Details",
host_protect_rule: "Protection Rules",
host_protect_rule_edit: "Edit Protection Rules",
allow_ip: "IP Allow List",
allow_url: "URL Allow List",
deny_ip: "IP Block List",
deny_url: "URL Block List",
ldp_url: "Protection URL",
cc: "CC Protection",
},
analysis:{
parent_title: "Data Analysis",
analysis_title: "Data Analysis",
},
visit_log:{
parent_title: "Protection Logs",
visit_title: "Protection Logs",
visit_detail_title: "Protection Details",
},
account:{
parent_title: "Account",
account_list_title: "Account List",
account_log_title: "Account Logs",
},
system:{
parent_title: "System Settings",
system_log_title: "System Logs",
system_config_title: "Parameter Settings",
system_runtime_title: "Runtime Parameters",
system_one_key_modify_title: "Quick Modification",
},
pc:{
parent_title: "Device",
pc_list_title: "Device List",
}
},
page:{
account: {
create_account: "Create Account",
login_account_label: "Login Account",
reset_password: "Reset Password",
role: "Role",
role_super_admin: "Super Administrator",
role_admin: "Administrator",
login_password: "Login Password",
super_admin_password: "Super Administrator Password",
new_password: "New Password",
confirm_password: "Confirm Password",
password_mismatch_warning: "The passwords do not match, please check",
admin_delete_warning: "The default admin account cannot be deleted",
},
account_log:{
export_logs: "Export Logs",
view_log_dialog_title: "View Log",
operation_account: "Operation Account",
operation_type: "Operation Type",
operation_content: "Operation Content",
cancel: "Cancel",
operation_time: "Operation Time"
},
analysis:{
},
cc:{
new_cc_protection: "New CC Protection",
selected_count: "Selected {count} items",
website: "Website",
url: "URL",
rate: "Rate",
limit: "Limit Access Times",
samwaf_cc_protection: "SamWaf Firewall Resists CC Attacks",
input_url_placeholder: "Enter URL (optional)"
},
visit_log:{
visit_log: "Protection Logs",
online_document: "Online Document",
website: "Website",
rule_name: "Rule Name",
access_status: "Access Status",
response_code: "Response Code",
access_ip: "Access IP",
access_date: "Access Date",
access_method: "Access Method",
log_archive_db: "Log Archive Database",
guest_identity: "Guest Identity",
time_spent: "Time Spent (ms)",
risk_level: "Risk Level",
trigger_rule: "Trigger Rule",
time: "Time",
domain: "Domain",
request: "Request",
source_ip: "Source IP",
country: "Country",
province: "Province",
city: "City",
access_url: "Access URL",
header: "Header",
status_code: "Response Code",
search_placeholder: "Please enter rule name",
select_placeholder: "Please select defense status",
input_placeholder: "Please enter access method",
date_range_today: "Today",
date_range_last_3_days: "Last 3 Days",
date_range_last_7_days: "Last 7 Days",
date_range_last_300_days: "Last 300 Days",
detail:{
defense_status: "Defense Status",
visit_time: "Visit",
detection_time: "Detection",
defense_status_step: "Defense Status",
response_status: "Response Status",
request_identifier: "Request Identifier",
request_time: "Request Time",
request_domain: "Request Domain",
request_method: "Request Method",
request_content_size: "Request Content Size",
visitor_ip: "Visitor IP",
add_to_deny_list: "Add to Block List",
visitor_port: "Visitor Port",
request_region: "Request Region",
response_code: "Response Code",
more_info:"More Information",
request_path: "Request Path",
request_header: "Request Header",
request_user_browser: "Request User Browser",
request_cookies: "Request Cookies",
request_body: "Request BODY",
request_form: "Request Form",
response_data: "Response Data",
quick_add_rule: "Quickly Add Rule",
open: "Open",
close: "Close",
add_to_deny_list_confirm_header: "Add to Block List",
add_to_deny_list_confirm_body: "Are you sure you want to add this IP to the block list?",
website_not_exist_warning: "The website does not exist",
back: "Back",
mouse_select_tooltip: "Select the content you want to add with the mouse, then click on the page's blank area"
}
},
center:{
switch_local: "Switch to Local (No Remote Access)",
server_switch_button: "Switch Server",
recent_visit_time: "Recent Visit Time",
client_server_name: "Client Name",
client_system_type: "Operating System Type",
client_ip: "IP",
client_port: "Port",
client_new_version: "Version Number",
client_new_version_desc: "Version",
last_visit_time: "Last Visit Time",
},
host: {
new_protection: "New Protection",
website_protection: "Website Protection",
export_data: "Export Data",
import_data: "Import Data",
website: "Website:",
url: "URL:",
search_placeholder: "Please enter",
search_button: "Search",
core_features: "SamWaf Core Features, All website information, Protection features enabled, etc.",
host: "Website",
host_tips: "Enter the domain name of the website you want to protect: e.g., www.samwaf.com",
host_placeholder: "Please enter the website URL",
port: "Port",
port_placeholder: "Please enter the website port, usually 80/443",
port_tips: "Enter the port of the website you want to protect. 1. HTTP is 80, HTTPS is 443. 2. If you have installed Baota, Nginx, IIS, etc., you need to manually change the port to non-80 or non-443.",
ssl: "SSL",
ssl_tips: "If it is HTTPS, you need to select an encryption certificate. Port 80 does not require one.",
ssl_yes: "Yes",
ssl_no: "No",
ssl_option_yes: "Encryption Certificate (requires certificate upload)",
ssl_option_no: "Non-encrypted",
guard_status_on: "Protected",
guard_status_off: "Not Protected",
auto_start_on: "Auto Start",
auto_start_off: "Manual Start",
tab_base: "Basic Information",
tab_engine: "Engine Built-in Protection",
tab_other: "Other Configurations",
start_status: "Start Status",
guard_status: "Protection Status",
start_status_content: "This feature selects whether to start directly.",
keyfile: "Key String",
keyfile_content: "Usually filename: *.key Content format: -----BEGIN RSA PRIVATE KEY----- Copy all and fill in",
certfile: "Certificate String",
certfile_content: "Usually filename: *.crt Content format: -----BEGIN CERTIFICATE----- Copy all and fill in",
remote_ip: "Backend IP",
remote_ip_content: "If SamWaf and the website are on the same server, fill in 127.0.0.1. If on different servers, please fill in the actual IP.",
remote_port: "Backend Port",
remote_port_content: "Situation 1: If SamWaf and the website are on the same server, the port needs to be changed to 81 or other ports. Situation 2: If on different servers, this can be the original port.",
remarks: "Remarks",
exclude_url_log: "Exclude URL When Logging",
exclude_url_log_tips: "Exclude URL prefix data when logging",
bot_detection: "Bot Detection",
bot_detection_tips: "Detect if search engines are disguised",
sql_injection_detection: "SQL Injection Detection",
sql_injection_detection_tips: "Detect if there is SQL injection",
xss_detection: "XSS Detection",
xss_detection_tips: "Detect if there is XSS attack",
scan_detection: "Scanning Tool Detection",
scan_detection_tips: "Detect if scanning tools are present",
rce_detection: "RCE Detection",
rce_detection_tips: "RCE Remote Attack Detection",
engine_protection: "Engine Built-in Protection",
other_config: "Other Configurations",
guard_status_confirm: "Protection Status Reminder",
guard_status_confirm_content: "Protection Status [On] means real-time protection for this website. Protection Status [Off] means real-time protection is turned off for this website.",
start_status_confirm: "Start Status Reminder",
start_status_confirm_content: "Start Status [On] will normally accept user requests. Start Status [Off] will stop user requests.",
import_file: "Import File",
upload_file: "Upload File",
upload_file_limit_size: "Upload file size within 5MB",
upload_tips: "No file selected",
file_upload_success: "File uploaded successfully",
file_upload_fail: "File upload failed",
file_safety: "File Safety",
back_system_type_baota: "Baota",
back_system_type_phpstudy: "Xiao Pi Panel (phpstudy)",
back_system_type_phpnow: "PHPnow",
back_system_type_default: "Default",
back_system_biz_website: "Pure Website",
back_system_biz_api: "API Business System",
back_system_biz_mange: "Business and Management",
back_system_biz_default: "Default",
delete_confirm_clear_relation: "After deletion, the website information and rules will be cleared and cannot be restored.",
forbid_for_global_site: "Global websites cannot be operated",
forbid_for_global_site_only_change_guard_status: "Global websites can only configure protection status",
host_rule_msg: "Do not fill in HTTP and HTTPS, just enter the domain name."
},
one_key_mod: {
one_key_placeholder: "Due to the fact that only one program can use Web (port 80, port 443) on a single server, if you need to set Waf as a proxy, you need to change 80 to 81 and 443 to 444 here.\nSamWaf has added a one-click modification of Baota Web port for user convenience. Available only on Linux.",
baota_placeholder: "Baota Nginx configuration default path",
button_one_key_modify: "One-click Modify",
modify_logs: "SamWaf One-click Modification Records",
title_file_path: "File Path",
title_create_time: "Creation Time",
label_op_system: "Operating System",
label_file_path: "File Path",
label_before_content: "Original Content",
label_after_content: "Modified Content",
confirm_delete: "Are you sure you want to delete?",
success_modify_message: "Operation successful",
warning_modify_message: "Operation warning"
},
ipallow: {
button_add_ip: "Add Allowlist IP",
label_website: "Website",
label_ip: "IP",
alert_message: "SamWaf firewall will ignore IPs in the allowlist."
},
ipblock: {
button_add_ip: "Add Blocklist IP",
label_website: "Website",
label_ip: "IP",
alert_message: "SamWaf firewall will block access from IPs in the blocklist."
},
ldpurl: {
new_privacy_url: "Add New Privacy Protection URL",
label_website: "Website",
label_url: "URL",
label_compare_type: "Match Type",
alert_message: "SamWaf will process sensitive data in the specified URL to hide parts of it, such as phone numbers.",
compare_type_option_equal: "Equal",
compare_type_option_pre: "Prefix Match",
compare_type_option_end: "Suffix Match",
compare_type_option_contain: "Contains Match"
},
urlallow: {
button_add_url: "Add Allowlist URL",
label_website: "Website",
label_url: "URL",
label_compare_type: "Match Type",
alert_message: "SamWaf firewall will ignore URLs in the allowlist during protection.",
compare_type_option_equal: "Equal",
compare_type_option_pre: "Prefix Match",
compare_type_option_end: "Suffix Match",
compare_type_option_contain: "Contains Match"
},
urlblock: {
button_add_url: "Add Blocklist URL",
label_website: "Website",
label_url: "URL",
label_compare_type: "Match Type",
alert_message: "SamWaf firewall will block access to URLs in the blocklist.",
compare_type_option_equal: "Equal",
compare_type_option_pre: "Prefix Match",
compare_type_option_end: "Suffix Match",
compare_type_option_contain: "Contains Match"
},
systemconfig: {
new_system_configuration: "Add New System Configuration",
label_configuration_item: "Configuration Item",
label_configuration_value: "Configuration Value"
},
syslog: {
syslog: "System Log",
label_op_type: "Operation Type",
label_op_content: "Operation Content"
},
rule: {
button_add_rule: "Add New Rule",
label_website: "Website",
label_rule_name: "Rule Name",
label_rule_version: "Rule Version",
label_rule_status: "Rule Status",
alert_message: "SamWaf defense rules can be edited via scripts (preferred) or interface.",
rule_online_document: "Rule Editing Online Documentation",
rule_on: "Active",
rule_off: "Inactive",
detail: {
recommend_message: "It is recommended to automatically edit defense scripts by selecting feature values from (Log Details) with one click.",
jump_visit_log: "Go to Log List",
jump_online_document: "Defense Rules Online Documentation",
base_info: "Basic Information",
rule_name: "Rule Name",
rule_domain_code: "Protected Website",
rule_salience: "Protection Level",
rule_manual: "Protection Arrangement Method",
rule_dyn_add: "Add New",
relation: "Relation",
condition: "Condition",
built_in_entity_name: "Built-in Entity Name",
scope: "Scope",
value_type: "Value Type",
judgment: "Judgment",
value: "Value",
function_judgment_result: "Function Judgment Result",
assignment: "Assignment",
assignment_area: "Assignment Area",
assignment_detail: "Assignment Details",
method_execution: "Method Execution",
method_execution_area: "Method Execution Area",
method_details: "Method Details",
inner_method: "Built-in Method",
parameter: "Parameters",
write_rule: "Rule Arrangement",
system_variable: "System Variable",
ui_rule_edit: "UI Arrangement",
manual_code_rule_edit: "Manual Code Arrangement",
mf_option_default: "Default",
method_option: "Perform Action",
inner_option_host: "Host",
inner_option_url: "URL",
inner_option_referrer: "Referrer",
inner_option_user_agent: "User-Agent",
inner_option_method: "METHOD",
inner_option_cookies: "Cookies",
inner_option_body: "Body",
inner_option_port: "Request Port",
inner_option_src_ip: "Visitor IP",
inner_option_country: "Visitor Country",
inner_option_province: "Visitor Province",
inner_option_city: "Visitor City",
attr_type_text: "Text",
attr_type_int: "Number",
judge_equal: "Judge if Equal",
judge_not_equal: "Judge if Not Equal",
judge_greater_than: "Judge if Greater Than",
judge_less_than: "Judge if Less Than",
judge_greater_than_equal: "Judge if Greater Than or Equal",
judge_less_than_equal: "Judge if Less Than or Equal",
judge_contain: "Judge if Contains (Function)",
judge_has_prefix: "Judge if Starts With (Function)",
judge_has_suffix: "Judge if Ends With (Function)",
judge_logic_and: "And",
judge_logic_or: "Or"
}
},
notice: {
notice_title: "Notice",
clear: "Clear",
set_read: "Mark as Read",
empty: "No Notifications",
all: "View All"
},
right_setting: {
page_setting: "Page Configuration",
theme_mode: "Theme Mode",
theme_color: "Theme Color",
navigation_layout: "Navigation Layout",
element_switches: "Element Switches",
fix_header: "Fixed Header",
fix_sidebar: "Fixed Sidebar",
show_header: "Show Header",
show_breadcrumb: "Show Breadcrumbs",
show_footer: "Show Footer",
use_tabs_router: "Use Multiple Tab Pages",
footer_position: "Footer Inner Collapse",
split_menu: "Split Menu (Effective in Mixed Mode)",
theme_mode_color_light:"Light",
theme_mode_color_dark:"Dark",
theme_mode_color_auto:"Auto",
}
},
};
+15
View File
@@ -0,0 +1,15 @@
import Vue from "vue";
import VueI18n from "vue-i18n";
import zh_CN from "./zh_CN";
import en_US from "./en_US";
Vue.use(VueI18n);
const i18n = new VueI18n({
locale: localStorage.getItem("lang") || "zh_CN", // 语言标识
messages: {
zh_CN, // 中文语言包
en_US, // 英文语言包
},
});
export default i18n;
+500
View File
@@ -0,0 +1,500 @@
/**
* SamWaf 中文语言包
*
* common 放置一些公共字段
* menu 左侧菜单
* page 里面放置对应功能页面的字段
*/
export default {
common:{
confirm:"确认",
cancel:"取消",
close:"关闭",
search:"查询",
all:"全部",
details: "详情",
new: "新建",
copy: "复制",
edit: "编辑",
delete: "删除",
reset: "重置",
submit: "提交",
return: "返回",
status: "状态",
remarks: "备注",
select_placeholder: "请选择",
placeholder: "请输入",
placeholder_content: "请输入内容",
debug:'调试',
confirm_delete: "确认删除当前所选数据?",
data_delete_warning: "删除后,数据将被删除,且无法恢复",
create_time: "创建时间",
op: "操作内容",
date:"日期",
online_document:"在线文档",
defense_status:{
all:"全部",
stop:"阻止",
pass:"放行",
forbid:"禁止",
},
on:"开启",
of:"关闭"
},
login:{
login_title:"登录",
login_sub_title:"SamWaf网站防火墙后台",
login_has_question:"遇到问题?",
login_online_document:"SamWaf在线文档",
input_account_placeholder:"请输入账号:",
input_password_placeholder:"请输入登录密码:",
login_btn_title:"登录",
rule:{
phone:"手机号必填",
account:"账号必填",
password:"密码必填",
verifyCode:"验证码必填"
},
login_success:"登录成功",
},
topNav:{
update:{
has_new_version:"有新版本啦",
},
contract:"联系SamWaf",
help_document:"帮助文档",
current_server:"当前 服务器",
system_config:"系统设置",
dropdown_person_center:"个人中心",
dropdown_update:"升级",
dropdown_reboot_waf:"重启WAF",
dropdown_logout:"退出",
},
dashboard:{
tip_create_website_title:"您当前未创建需要防护的网站,点击进行创建",
tip_create_website_link:"马上创建",
tip_modify_pwd_title:"您当前还是使用默认帐号和密码请尽快修改",
tip_modify_pwd_link:"马上修改",
counter:{
today_of_attack_count:"今日攻击数",
all_visit_count:"今天总访问量",
not_normal_visit_count:"今天异常IP(个)",
qps:"当前QPS",
},
cycle_title:"周期攻击与正常对比情况",
cycle_subtitle:"(次)",
cycle_normal_count:"本周期正常数",
cycle_attack_count:"本周期攻击数",
cycle_percent_title:"正常攻击占比",
cycle_percent_subtitle:"周期内",
},
menu:{
dashboard: {
parent_title:"仪表盘",
dashboard_title:"概览仪表盘",
},
host:{
parent_title:"网站防护",
host_title:"网站防护",
host_detail:"主机防护详情",
host_protect_rule:"防御规则",
host_protect_rule_edit:"防御规则编辑",
allow_ip:"IP白名单",
allow_url:"Url白名单",
deny_ip:"IP黑名单",
deny_url:"IP黑名单",
ldp_url:"隐私保护Url",
cc:"cc防御",
},
analysis:{
parent_title:"数据分析",
analysis_title:"数据分析",
},
visit_log:{
parent_title:"防护日志",
visit_title:"防护日志",
visit_detail_title:"防护详情",
},
account:{
parent_title:"账号管理",
account_list_title:"账号列表",
account_log_title:"账号日志",
},
system:{
parent_title:"系统设置",
system_log_title:"系统日志",
system_config_title:"参数设置",
system_runtime_title:"运行参数",
system_one_key_modify_title:"一键修改",
},
pc:{
parent_title:"设备管理",
pc_list_title:"设备列表",
}
},
page:{
account: {
create_account: "新建账号",
login_account_label: "登录帐号",
reset_password: "重置密码",
role: "角色",
role_super_admin: "超级管理员",
role_admin: "管理员",
login_password: "登录密码",
super_admin_password: "超级管理员密码",
new_password: "新密码",
confirm_password: "确认密码",
password_mismatch_warning: "两次输入的密码不相同,请检查",
admin_delete_warning: "默认管理帐号不允许删除",
},
account_log:{
export_logs: "导出日志",
view_log_dialog_title: "查看日志",
operation_account: "操作账号",
operation_type: "操作类型",
operation_content: "操作内容",
cancel: "取消",
operation_time: "添加时间"
},
analysis:{
},
cc:{
new_cc_protection: "新建CC防护",
selected_count: "已选 {count} 项",
website: "网站",
url: "URL",
rate: "速率",
limit: "限制访问次数",
samwaf_cc_protection: "SamWaf防护墙抵御CC攻击",
input_url_placeholder: "输入URL(可不填)"
},
visit_log:{
visit_log: "防御日志",
online_document: "在线文档",
website: "网站",
rule_name: "规则名称",
access_status: "访问状态",
response_code: "响应码",
access_ip: "访问IP",
access_date: "访问日期",
access_method: "访问方法",
log_archive_db: "日志归档库",
guest_identity: "访客身份",
time_spent: "耗时(ms)",
risk_level: "危害程度",
trigger_rule: "触发规则",
time: "时间",
domain: "域名",
request: "请求",
source_ip: "来源IP",
country: "国家",
province: "省份",
city: "城市",
access_url: "访问url",
header: "Header",
status_code: "响应码",
search_placeholder: "请输入规则名称",
select_placeholder: "请选择防御状态",
input_placeholder: "请输入访问方法",
date_range_today: "今天",
date_range_last_3_days: "最近3天",
date_range_last_7_days: "最近7天",
date_range_last_300_days: "最近300天",
detail:{
defense_status: "防御情况",
visit_time: "访问",
detection_time: "检测",
defense_status_step: "防御状态",
response_status: "响应状态",
request_identifier: "请求标识",
request_time: "请求时间",
request_domain: "请求域名",
request_method: "请求方法",
request_content_size: "请求内容大小",
visitor_ip: "访问者IP",
add_to_deny_list: "加入不允许访问",
visitor_port: "访问者端口",
request_region: "请求地区",
response_code: "响应编码",
more_info:"更多信息",
request_path: "请求路径",
request_header: "请求头",
request_user_browser: "请求用户浏览器",
request_cookies: "请求cookies",
request_body: "请求BODY",
request_form: "请求Form",
response_data: "响应数据",
quick_add_rule: "快捷加入规则",
open: "开",
close: "关",
add_to_deny_list_confirm_header: "加入不允许访问的IP列表",
add_to_deny_list_confirm_body: "你确定要加入不允许访问的IP?",
website_not_exist_warning: "当前网站不存在",
back: "返回",
mouse_select_tooltip: "鼠标选中想要添加的内容后,点击页面空白即可"
}
},
center:{
switch_local: "切换本机(不进行远程访问)",
server_switch_button: "切换服务器",
recent_visit_time: "最近访问时间",
client_server_name: "客户端名称",
client_system_type: "操作系统类型",
client_ip: "IP",
client_port: "端口",
client_new_version: "版本号",
client_new_version_desc: "版本",
last_visit_time: "最近访问时间",
},
host:{
new_protection: "新建防护",
website_protection: "网站防御",
export_data: "导出数据",
import_data: "导入数据",
website: "网站:",
url: "URL:",
search_placeholder: "请输入",
search_button: "查询",
core_features: "SamWaf核心功能,所有网站信息,防护功能开启等",
host: "网站",
host_tips: "输入您需要防护的网站域名:如 www.samwaf.com",
host_placeholder: "请输入网站的网址",
port: "端口",
port_placeholder: "请输入网站的端口一般是80/443",
port_tips: "输入您需要防护的网站端口 1. http是80 https 是 443 2.如果已经安装了宝塔,Nginx,IIS等 您需要手工改动端口成非80,或者非443端口",
ssl: "加密证书",
ssl_tips: "如果是https需要选择加密证书,80端口不需要",
ssl_yes:"是",
ssl_no:"否",
ssl_option_yes:"加密证书(需上传证书)",
ssl_option_no:"非加密",
guard_status_on: "已防护",
guard_status_off: "未防护",
auto_start_on: "自动启动",
auto_start_off: "手工启动",
tab_base:"基础内容",
tab_engine:"引擎自带防护",
tab_other:"其他配置",
start_status: "启动状态",
guard_status: "防御状态",
start_status_content: "该功能是选择是否直接启动。",
keyfile: "密钥串",
keyfile_content: "通常文件名:*.key 内容格式如下:-----BEGIN RSA PRIVATE KEY----- 全选复制填写进来",
certfile: "证书串",
certfile_content: "通常文件名:*.crt 内容格式如下:-----BEGIN CERTIFICATE----- 全选复制填写进来",
remote_ip: "后端IP",
remote_ip_content: "如SamWaf同网站在同一台服务器 填写127.0.0.1 如果是不同服务器请填写实际IP",
remote_port: "后端端口",
remote_port_content: "情况1,在SamWaf和网站在同一台服务器,那么端口需要写成81等其他端口 情况2:如果不在同一台服务器,那么此处可以原来端口",
remarks: "备注",
exclude_url_log: "记录日志时排除URL",
exclude_url_log_tips: "记录日志时排除URL开头的数据",
bot_detection: "Bot检测",
bot_detection_tips: "检测搜索引擎是否是伪装的",
sql_injection_detection: "Sql注入检测",
sql_injection_detection_tips: "检测是否存在sql注入",
xss_detection: "XSS检测",
xss_detection_tips: "检测是否存在xss攻击",
scan_detection: "扫描工具检测",
scan_detection_tips: "是否检测扫描工具",
rce_detection: "RCE检测",
rce_detection_tips: "RCE远程攻击检测",
engine_protection: "引擎自带防护",
other_config: "其他配置",
guard_status_confirm: "防护状态提示",
guard_status_confirm_content: "防护状态【开启】,该网站进行实时防护。防护状态【关闭】,该网站会关闭实时防护。",
start_status_confirm: "启动状态提示",
start_status_confirm_content:"启动状态【开启】会正常接收用户请求。 启动状态【关闭】会停止用户请求",
import_file: "导入文件",
upload_file: "上传文件",
upload_file_limit_size: "上传文件大小在 5M 以内",
upload_tips: "未选择文件",
file_upload_success: "文件上传成功",
file_upload_fail: "文件上传失败",
file_safety: "文件安全",
back_system_type_baota:"宝塔",
back_system_type_phpstudy:"小皮面板(phpstudy)",
back_system_type_phpnow:"PHPnow",
back_system_type_default:"默认",
back_system_biz_website:"纯网站",
back_system_biz_api:"API业务系统",
back_system_biz_mange:"业务加管理",
back_system_biz_default:"默认",
delete_confirm_clear_relation:"删除后,该网站信息和规则将被清空,且无法恢复",
forbid_for_global_site:"全局网站不能操作",
forbid_for_global_site_only_change_guard_status:"全局网站只能配置保护状态",
host_rule_msg:"主机请不要填写http和https 直接写域名即可",
},
one_key_mod:{
one_key_placeholder: "由于单台服务器只能一个程序使用Web(80端口,443端口),所以如果需要让Waf变为前置,那么此处需要将80=》81 ,443=》444。\n" +
" SamWaf为了方便用户部署,新增一键修改宝塔Web端口。仅在Linux下可使用。",
baota_placeholder:"宝塔Nginx配置默认路径",
button_one_key_modify: "一键修改",
modify_logs: "SamWaf一键修改记录",
title_file_path: "文件路径",
title_create_time: "添加时间",
label_op_system: "系统类型",
label_file_path: "文件路径",
label_before_content: "原始内容",
label_after_content: "修改后内容",
confirm_delete: "确认要删除吗",
success_modify_message: "操作成功",
warning_modify_message: "操作警告"
},
ipallow:{
button_add_ip: "新建白名单IP",
label_website: "网站",
label_ip: "Ip",
alert_message: "SamWaf防护墙会忽略在白名单内的IP",
},
ipblock:{
button_add_ip: "新建黑名单IP",
label_website: "网站",
label_ip: "Ip",
alert_message: "SamWaf防护墙会阻止在黑名单内的IP的访问",
},
ldpurl:{
new_privacy_url: "新建隐私保护Url",
label_website: "网站",
label_url: "URL",
label_compare_type: "匹配方式",
alert_message: "SamWaf用户在访问指定的url返回的敏感数据脱敏处理,如手机号会隐藏部分",
compare_type_option_equal:"等于",
compare_type_option_pre:"前缀匹配",
compare_type_option_end:"后缀匹配",
compare_type_option_contain:"包含匹配",
},
urlallow:{
button_add_url: "新建白名单URL",
label_website: "网站",
label_url: "Ip",
label_compare_type: "匹配方式",
alert_message: "SamWaf防护墙防护时候会忽略在白名单内的URL",
compare_type_option_equal:"等于",
compare_type_option_pre:"前缀匹配",
compare_type_option_end:"后缀匹配",
compare_type_option_contain:"包含匹配",
},
urlblock:{
button_add_url: "新建黑名单URL",
label_website: "网站",
label_url: "Ip",
label_compare_type: "匹配方式",
alert_message: "SamWaf防护墙会阻止访问在限制访问内的URL",
compare_type_option_equal:"等于",
compare_type_option_pre:"前缀匹配",
compare_type_option_end:"后缀匹配",
compare_type_option_contain:"包含匹配",
},
systemconfig:{
new_system_configuration: "新建系统配置",
label_configuration_item: "配置项",
label_configuration_value: "配置值",
},
syslog:{
syslog:"系统日志",
label_op_type:"操作类型",
label_op_content:"操作内容",
},
rule:{
button_add_rule:"新建规则",
label_website: "网站",
label_rule_name: "规则名",
label_rule_version: "规则版本",
label_rule_status: "规则状态",
alert_message: "SamWaf防御规则,可进行脚本(首选),界面编辑",
rule_online_document: "规则编辑在线文档",
rule_on: "生效",
rule_off: "未生效",
detail:{
recommend_message:"推荐从(日志详情)里面一键选择特征值自动编辑防御脚本",
jump_visit_log:"跳转到日志列表",
jump_online_document:"防御规则在线文档Online",
base_info: "基本信息",
rule_name: "规则名称",
rule_domain_code: "防护网站",
rule_salience: "防护级别",
rule_manual: "防护编排方式",
rule_dyn_add: "新建",
relation: "关系",
condition:"条件",
built_in_entity_name: "内置实体名称",
scope: "作用域",
value_type: "值类型",
judgment: "判断",
value: "值",
function_judgment_result: "函数判断结果",
assignment: "赋值",
assignment_area: "赋值区域",
assignment_detail: "赋值明细",
method_execution: "方法执行",
method_execution_area: "方法执行区域",
method_details: "方法明细",
inner_method: "内置方法",
parameter: "传参",
write_rule: "规则编排",
system_variable: "系统变量",
ui_rule_edit:"界面编排",
manual_code_rule_edit:"手工代码编排",
//options
mf_option_default:"默认",
method_option:"做动作",
//options header
inner_option_host:"主机",
inner_option_url:"URL",
inner_option_referrer:"网站来路(referrer)",
inner_option_user_agent:"用户代理(User-Agent)",
inner_option_method:"METHOD",
inner_option_cookies:"访问COOKIES",
inner_option_body:"访问BODY",
inner_option_port:"请求端口",
inner_option_src_ip:"访客IP",
inner_option_country:"访客归属国家",
inner_option_province:"访客归属省份",
inner_option_city:"访客归属城市",
//options attr
attr_type_text:"文本",
attr_type_int:"数字",
//options judge
judge_equal:"判断是否等于",
judge_not_equal:"判断是否不等于",
judge_greater_than:"判断是否大于",
judge_less_than:"判断是否小于",
judge_greater_than_equal:"判断是否大于等于",
judge_less_than_equal:"判断是否小于等于",
judge_contain:"判断包含(函数)",
judge_has_prefix:"判断开头(函数)",
judge_has_suffix:"判断结尾(函数)",
//options logic relation
judge_logic_and:"并且",
judge_logic_or:"或者",
}
},
notice:{
notice_title:"通知",
clear:"清空",
set_read:"设为已读",
empty:"暂无通知",
all:"查看全部",
},
right_setting:{
page_setting: "页面配置",
theme_mode: "主题模式",
theme_color: "主题色",
navigation_layout: "导航布局",
element_switches: "元素开关",
fix_header: "固定 Header",
fix_sidebar: "固定 Sidebar",
show_header: "显示 Header",
show_breadcrumb: "显示 Breadcrumbs",
show_footer: "显示 Footer",
use_tabs_router: "使用 多标签Tab页",
footer_position: "footer 内收",
split_menu: "分割菜单(混合模式下有效)",
theme_mode_color_light:"明亮",
theme_mode_color_dark:"暗黑",
theme_mode_color_auto:"跟随系统",
}
}
};
@@ -1,7 +1,7 @@
<template>
<t-breadcrumb :max-item-width="'150'" class="tdesign-breadcrumb">
<t-breadcrumbItem v-for="item in crumbs" :key="item.to" :to="item.to">
{{ item.title }}
{{ $t(item.title)}}
</t-breadcrumbItem>
</t-breadcrumb>
</template>
+54 -12
View File
@@ -2,7 +2,7 @@
<div :class="layoutCls">
<t-dialog :visible.sync="update_visible" @confirm="handleDoUpdate" header="有新版本啦">
<t-dialog :visible.sync="update_visible" @confirm="handleDoUpdate" :header="$t('topNav.update.has_new_version')">
<p> <icon name="tangerinr" color="orange" />
{{update_new_ver}}</p>
<p>
@@ -28,40 +28,48 @@
<!-- 全局通知 -->
<notice />
<t-tooltip placement="bottom" content="有新版本拉" v-show="hasNewVersion">
<t-tooltip placement="bottom" :content="$t('topNav.update.has_new_version')" v-show="hasNewVersion">
<t-button theme="default" shape="square" variant="text" @click="checkVersion('manual')">
<NotificationErrorIcon />
</t-button>
</t-tooltip>
<t-tooltip placement="bottom" content="联系SamWaf">
<t-tooltip placement="bottom" :content="$t('topNav.contract')">
<t-button theme="default" shape="square" variant="text" @click="sendMail">
<MailIcon />
</t-button>
</t-tooltip>
<t-tooltip placement="bottom" content="帮助文档">
<t-tooltip placement="bottom" :content="$t('topNav.help_document')">
<t-button theme="default" shape="square" variant="text" @click="navToHelper">
<help-circle-icon />
</t-button>
</t-tooltip>
<t-select v-model="langValue"
placeholder="SelectLanguage"
@change="changeLangEvent" style="width: 150px; display: inline-block" title="Select Language">
<t-option v-for="(item, index) in langOptions"
:key="index"
:label="item.label"
:value="item.value"/>
</t-select>
<t-button theme="warning" @click="changeServer" v-if="hasClientServer">
<template #icon><add-icon /></template>
当前 服务器{{ current_server.client_server_name }}
{{ $t('topNav.current_server')}} {{ current_server.client_server_name }}
</t-button>
<t-dropdown :min-column-width="125" trigger="click">
<template #dropdown>
<t-dropdown-menu>
<t-dropdown-item class="operations-dropdown-container-item" @click="handleNav('/user/index')">
<user-circle-icon />个人中心
<user-circle-icon /> {{ $t('topNav.dropdown_person_center')}}
</t-dropdown-item>
<t-dropdown-item class="operations-dropdown-container-item" :disabled="isUpdateloading" @click="checkVersion('manual')">
<RotateIcon />升级
<RotateIcon /> {{ $t('topNav.dropdown_update')}}
</t-dropdown-item>
<t-dropdown-item class="operations-dropdown-container-item" :disabled="isResetloading" @click="resetServer">
<PoweroffIcon />重启
<ArrowUpDownCircleIcon />{{ $t('topNav.dropdown_reboot_waf')}}
</t-dropdown-item>
<t-dropdown-item class="operations-dropdown-container-item" @click="handleLogout">
<poweroff-icon />退出登录
<poweroff-icon />{{ $t('topNav.dropdown_logout')}}
</t-dropdown-item>
</t-dropdown-menu>
</template>
@@ -75,7 +83,7 @@
</div>
</t-button>
</t-dropdown>
<t-tooltip placement="bottom" content="系统设置">
<t-tooltip placement="bottom" :content="$t('topNav.system_config')">
<t-button theme="default" shape="square" variant="text" @click="toggleSettingPanel">
<setting-icon />
</t-button>
@@ -99,7 +107,8 @@
RotateIcon,
Icon,
MailIcon,
NotificationErrorIcon
NotificationErrorIcon,
ArrowUpDownCircleIcon
} from 'tdesign-icons-vue';
import {
prefix
@@ -129,7 +138,8 @@
RotateIcon,
Icon,
MailIcon,
NotificationErrorIcon
NotificationErrorIcon,
ArrowUpDownCircleIcon
},
props: {
theme: String,
@@ -173,6 +183,18 @@
/**控制中心相关**/
hasClientServer:false,
current_server:"",
/**语言问题**/
langValue:"zh_CN",
langOptions: [
{
value: "zh_CN",
label: "中文"
},
{
value: "en_US",
label: "English"
},
]
};
},
computed: {
@@ -208,6 +230,24 @@
this.init()
},
methods: {
// 切换语言
changeLangEvent(value, context) {
switch (value) {
case "zh_CN":
this.langValue = value;
this.$i18n.locale = this.langValue;
localStorage.setItem("lang",this.langValue)
break;
case "en_US":
this.langValue = value;
this.$i18n.locale = this.langValue;
localStorage.setItem("lang",this.langValue)
break;
default:
break;
}
location.reload(); // 刷新页面
},
//init
init(){
//帐号初始化
@@ -219,6 +259,8 @@
}else{
this.hasClientServer = false
}
//多语言
this.langValue = localStorage.getItem("lang") || "zh_CN"
},
//切换服务器
@@ -13,7 +13,7 @@
<t-icon v-if="typeof item.icon === 'string' && item.icon" :name="item.icon" />
<renderFnIcon :item="item" />
</template>
{{ item.title }}
{{ $t(item.title) }}
</t-menu-item>
<t-menu-item
:key="item.path"
@@ -26,10 +26,10 @@
<t-icon v-if="typeof item.icon === 'string' && item.icon" :name="item.icon" />
<renderFnIcon :item="item" />
</template>
{{ item.title }}
{{ $t(item.title) }}
</t-menu-item>
</template>
<t-submenu v-else :name="item.path" :value="item.path" :title="item.title" :key="item.path">
<t-submenu v-else :name="item.path" :value="item.path" :title="$t(item.title)" :key="item.path">
<template #icon>
<t-icon v-if="typeof item.icon === 'string' && item.icon" :name="item.icon" />
<renderFnIcon :item="item" />
+5 -5
View File
@@ -9,9 +9,9 @@
<template #content>
<div class="header-msg">
<div class="header-msg-top">
<p>通知</p>
<p>{{ $t('page.notice.notice_title') }}</p>
<t-button v-if="unreadMsg.length > 0" class="clear-btn" variant="text" theme="primary" @click="setRead('all')"
>清空</t-button
>{{ $t('page.notice.clear') }}</t-button
>
</div>
<t-list v-if="unreadMsg.length > 0" class="narrow-scrollbar" :split="true">
@@ -22,14 +22,14 @@
</div>
<p class="msg-time">{{ item.message_datetime }}</p>
<template #action>
<t-button size="small" variant="outline" @click="setRead('radio', item)"> 设为已读 </t-button>
<t-button size="small" variant="outline" @click="setRead('radio', item)"> {{ $t('page.notice.set_read') }} </t-button>
</template>
</t-list-item>
</t-list>
<div v-else class="empty-list">
<img src="https://tdesign.gtimg.com/pro-template/personal/nothing.png" alt="空" />
<p>暂无通知</p>
<p>{{ $t('page.notice.empty') }}</p>
</div>
<div class="header-msg-bottom">
<t-button
@@ -38,7 +38,7 @@
variant="text"
theme="primary"
@click="goDetail"
>查看全部</t-button
>{{ $t('page.notice.all') }}</t-button
>
</div>
</div>
+1 -1
View File
@@ -16,7 +16,7 @@
<menu-content :navData="menu" />
<template #operations>
<span class="version-container"> {{ !collapsed && '' }} {{ getversion.version_name }}({{ getversion.version }})
<span v-if="getversion.version_release=='false'" style="color:red"> 调试</span></span>
<span v-if="getversion.version_release=='false'" style="color:red"> {{ $t('common.debug') }}</span></span>
</template>
</t-menu>
<div :class="`${prefix}-side-nav-placeholder${collapsed ? '-hidden' : ''}`"></div>
+17 -17
View File
@@ -4,14 +4,14 @@
size="408px"
:footer="false"
:visible.sync="showSettingPanel"
header="页面配置"
:header="$t('page.right_setting.page_setting')"
:closeBtn="true"
:onCloseBtnClick="handleCloseDrawer"
class="setting-drawer-container"
>
<div class="setting-container">
<t-form :data="formData" size="large" ref="form" labelAlign="left" @reset="onReset" @submit="onSubmit">
<div class="setting-group-title">主题模式</div>
<div class="setting-group-title">{{ $t('page.right_setting.theme_mode') }}</div>
<t-radio-group v-model="formData.mode">
<div v-for="(item, index) in MODE_OPTIONS" :key="index" class="setting-layout-drawer">
<div>
@@ -22,7 +22,7 @@
</div>
</div>
</t-radio-group>
<div class="setting-group-title">主题色</div>
<div class="setting-group-title">{{ $t('page.right_setting.theme_color') }}</div>
<t-radio-group v-model="formData.brandTheme">
<div
v-for="(item, index) in COLOR_OPTIONS.slice(0, COLOR_OPTIONS.length - 1)"
@@ -59,7 +59,7 @@
</t-popup>
</div>
</t-radio-group>
<div class="setting-group-title">导航布局</div>
<div class="setting-group-title">{{ $t('page.right_setting.navigation_layout') }}</div>
<t-radio-group v-model="formData.layout">
<div v-for="(item, index) in LAYOUT_OPTION" :key="index" class="setting-layout-drawer">
@@ -67,32 +67,32 @@
</div>
</t-radio-group>
<t-form-item v-show="formData.layout === 'mix'" label="分割菜单(混合模式下有效)" name="splitMenu">
<t-form-item v-show="formData.layout === 'mix'" :label="$t('page.right_setting.split_menu')" name="splitMenu">
<t-switch v-model="formData.splitMenu"></t-switch>
</t-form-item>
<t-form-item v-show="formData.layout !== 'side'" label="固定 Header" name="isHeaderFixed">
<t-form-item v-show="formData.layout !== 'side'" :label="$t('page.right_setting.fix_header')" name="isHeaderFixed">
<t-switch v-model="formData.isHeaderFixed"></t-switch>
</t-form-item>
<t-form-item v-show="formData.layout !== 'top'" label="固定 Sidebar" name="isSidebarFixed">
<t-form-item v-show="formData.layout !== 'top'" :label="$t('page.right_setting.fix_sidebar')" name="isSidebarFixed">
<t-switch v-model="formData.isSidebarFixed"></t-switch>
</t-form-item>
<div class="setting-group-title">元素开关</div>
<t-form-item label="显示 Header" name="showHeader" v-show="formData.layout === 'side'">
<div class="setting-group-title">{{ $t('page.right_setting.element_switches') }}</div>
<t-form-item :label="$t('page.right_setting.show_header')" name="showHeader" v-show="formData.layout === 'side'">
<t-switch v-model="formData.showHeader"></t-switch>
</t-form-item>
<t-form-item label="显示 Breadcrumbs" name="showBreadcrumb">
<t-form-item :label="$t('page.right_setting.show_breadcrumb')" name="showBreadcrumb">
<t-switch v-model="formData.showBreadcrumb"></t-switch>
</t-form-item>
<t-form-item label="显示 Footer" name="showFooter">
<t-form-item :label="$t('page.right_setting.show_footer')" name="showFooter">
<t-switch v-model="formData.showFooter"></t-switch>
</t-form-item>
<t-form-item label="使用 多标签Tab页" name="isUseTabsRouter">
<t-form-item :label="$t('page.right_setting.use_tabs_router')" name="isUseTabsRouter">
<t-switch v-model="formData.isUseTabsRouter"></t-switch>
</t-form-item>
<t-form-item
label="footer 内收"
:label="$t('page.right_setting.footer_position')"
name="footerPosition"
v-show="formData.showFooter && !formData.isSidebarFixed"
>
@@ -121,13 +121,13 @@ import ColorContainer from '@/components/color/index.vue';
import SettingDarkIcon from '@/assets/assets-setting-dark.svg';
import SettingLightIcon from '@/assets/assets-setting-light.svg';
import SettingAutoIcon from '@/assets/assets-setting-auto.svg';
import i18n from "./../i18n";
const LAYOUT_OPTION = ['side', 'top', 'mix'];
const COLOR_OPTIONS = ['default', 'cyan', 'green', 'yellow', 'orange', 'red', 'pink', 'purple', 'dynamic'];
const MODE_OPTIONS = [
{ type: 'light', text: '明亮' },
{ type: 'dark', text: '暗黑' },
{ type: 'auto', text: '跟随系统' },
{ type: 'light', text: i18n.t('page.right_setting.theme_mode_color_light') },
{ type: 'dark', text: i18n.t('page.right_setting.theme_mode_color_dark') },
{ type: 'auto', text: i18n.t('page.right_setting.theme_mode_color_auto') },
];
export default {
+22 -12
View File
@@ -7,21 +7,24 @@ import axiosInstance from '@/utils/request';
import App from './App.vue';
import router from './router';
import zhConfig from 'tdesign-vue/es/locale/zh_CN';
import enConfig from 'tdesign-vue/es/locale/en_US'; // 英文多语言配置
import globalconfig from './utils/globalconfig'
Vue.prototype.samwafglobalconfig = globalconfig;
// import enConfig from 'tdesign-vue/es/locale/en_US'; // 英文多语言配置
import bus from './bus/bus'
import BaiduMap from 'vue-baidu-map'
import i18n from "./i18n";
import VueMeta from 'vue-meta';
import 'tdesign-vue/es/style/index.css';
import '@/style/index.less';
import './permission';
import store from './store';
Vue.use(VueRouter);
Vue.use(TDesign);
Vue.use(VueClipboard);
Vue.use(VueMeta);
Vue.prototype.$bus = bus
Vue.use(BaiduMap, {
/* Visit http://lbsyun.baidu.com/apiconsole/key for details about app key. */
@@ -43,17 +46,24 @@ VueRouter.prototype.replace = function replace(location) {
Vue.config.productionTip = false;
sync(store, router);
new Vue({
window.vm = new Vue({
router,
i18n,
store,
metaInfo: {
title: (localStorage.getItem('lang')||'zh_CN') ==='zh_CN'?'SamWaf网站防火墙系统(Web Application Firewall)':"SamWaf Web Application Firewall",
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
render: (h) => (
<div>
{/* 可以通过config-provider提供全局(多语言、全局属性)配置,如
<t-config-provider globalConfig={enConfig}> */}
<t-config-provider globalConfig={zhConfig}>
<App />
</t-config-provider>
</div>
),
render: (h) => {
const currentLanguage = store.getters['language/currentLanguage'];
const globalConfig = currentLanguage === 'zh_CN' ? zhConfig :enConfig ;
return (
<div>
<t-config-provider globalConfig={globalConfig}>
<App />
</t-config-provider>
</div>
);
},
}).$mount('#app');
@@ -1,7 +1,7 @@
<template>
<t-row :gutter="[16, 16]">
<t-col :xs="12" :xl="9">
<t-card title="周期攻击与正常对比情况" subtitle="(次)" class="dashboard-chart-card">
<t-card :title="$t('dashboard.cycle_title')" :subtitle="$t('dashboard.cycle_subtitle')" class="dashboard-chart-card">
<template #actions>
<div class="dashboard-chart-title-container">
<t-date-range-picker
@@ -21,7 +21,7 @@
</t-card>
</t-col>
<t-col :xs="12" :xl="3">
<t-card title="正常攻击占比" subtitle="周期内" class="dashboard-chart-card">
<t-card :title="$t('dashboard.cycle_percent_title')" :subtitle="$t('dashboard.cycle_percent_subtitle')" class="dashboard-chart-card">
<div
id="countContainer"
ref="countContainer"
@@ -1,189 +0,0 @@
<template>
<t-card>
<t-row>
<t-col :xs="12" :xl="9">
<t-card
:bordered="false"
title="出入库概览"
subtitle="(件)"
:class="{ 'dashboard-overview-card': true, 'overview-panel': true }"
>
<template #actions>
<t-date-range-picker
class="card-date-picker-container"
theme="primary"
mode="date"
:default-value="LAST_7_DAYS"
@change="onStokeDataChange"
/>
</template>
<div
id="stokeContainer"
style="width: 100%; height: 351px"
ref="stokeContainer"
class="dashboard-chart-container"
></div>
</t-card>
</t-col>
<t-col :xs="12" :xl="3">
<t-card :bordered="false" :class="{ 'dashboard-overview-card': true, 'export-panel': true }">
<template #actions>
<t-button>导出数据</t-button>
</template>
<t-row>
<t-col :xs="6" :xl="12">
<t-card :bordered="false" subtitle="本月出库总计(件)" class="inner-card">
<div class="inner-card__content">
<div class="inner-card__content-title">1726</div>
<div class="inner-card__content-footer">
自从上周以来
<trend class="trend-tag" type="down" :is-reverse-color="false" describe="20.3%" />
</div>
</div>
</t-card>
</t-col>
<t-col :xs="6" :xl="12">
<t-card :bordered="false" subtitle="本月入库总计(件)" class="inner-card">
<div class="inner-card__content">
<div class="inner-card__content-title">226</div>
<div class="inner-card__content-footer">
自从上周以来
<trend class="trend-tag" type="down" :is-reverse-color="false" describe="20.3%" />
</div>
</div>
</t-card>
</t-col>
</t-row>
</t-card>
</t-col>
</t-row>
</t-card>
</template>
<script>
import { TooltipComponent, LegendComponent, GridComponent } from 'echarts/components';
import { BarChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers';
import * as echarts from 'echarts/core';
import { mapState } from 'vuex';
import { constructInitDataset } from '../index';
import { changeChartsTheme } from '@/utils/color';
import { LAST_7_DAYS } from '@/utils/date';
import Trend from '@/components/trend/index.vue';
import { PANE_LIST, SALE_TEND_LIST, BUY_TEND_LIST, Attack_IP_COLUMNS, BUY_COLUMNS } from '@/service/service-base';
echarts.use([TooltipComponent, LegendComponent, GridComponent, BarChart, CanvasRenderer]);
export default {
name: 'Overview',
components: {
Trend,
},
data() {
return {
panelList: PANE_LIST,
buyTendList: BUY_TEND_LIST,
saleTendList: SALE_TEND_LIST,
saleColumns: SALE_COLUMNS,
buyColumns: BUY_COLUMNS,
LAST_7_DAYS,
};
},
computed: {
...mapState('setting', ['brandTheme', 'mode']), // 这里需要用到主题色和主题模式的全局配置
},
watch: {
brandTheme() {
changeChartsTheme([this.stokeChart]);
},
mode() {
[this.stokeChart].forEach((item) => {
item.dispose();
});
this.renderCharts();
},
},
mounted() {
this.$nextTick(() => {
this.updateContainer();
});
window.addEventListener('resize', this.updateContainer, false);
this.renderCharts();
},
methods: {
/** 出入库概览日期更新 */
onStokeDataChange(checkedValues) {
const { chartColors } = this.$store.state.setting;
this.stokeChart.setOption(constructInitDataset({ dateTime: checkedValues, ...chartColors }));
},
updateContainer() {
this.stokeChart.resize({
// 根据父容器的大小设置大小
width: this.stokeContainer.clientWidth,
height: this.stokeContainer.clientHeight,
});
},
renderCharts() {
const { chartColors } = this.$store.state.setting;
// 出入库概览
if (!this.stokeContainer) this.stokeContainer = document.getElementById('stokeContainer');
this.stokeChart = echarts.init(this.stokeContainer);
this.stokeChart.setOption(constructInitDataset({ dateTime: LAST_7_DAYS, ...chartColors }));
},
},
};
</script>
<style lang="less" scoped>
@import '@/style/variables.less';
.dashboard-overview-card {
/deep/ .t-card__header {
padding-bottom: 24px;
}
/deep/ .t-card__title {
font-size: 20px;
font-weight: 500;
}
&.overview-panel {
border-right: none;
}
&.export-panel {
border-left: none;
}
}
.inner-card {
padding: 24px 0;
/deep/ .t-card__header {
padding-bottom: 0;
}
&__content {
&-title {
font-size: 36px;
line-height: 44px;
}
&-footer {
display: flex;
align-items: center;
line-height: 22px;
color: var(--td-text-color-placeholder);
.trend-tag {
margin-left: 4px;
}
}
}
}
</style>
@@ -5,7 +5,7 @@
:title="item.title"
:style="{ height: '168px' }"
:class="{ 'dashboard-item': true, 'dashboard-item--main-color': index == 0 }"
@click.native="jumpLog(item.title)"
@click.native="jumpLog(index)"
>
<div class="dashboard-item-top">
<span :style="{ fontSize: `${resizeTime * 36}px` }">{{ item.number }}</span>
@@ -110,7 +110,7 @@ export default {
jumpLog(title){
console.log(title)
switch (title){
case '今日攻击数':
case 0: //今日攻击数量
this.$router.push({
path: '/waf/wafattacklog',
query: {
@@ -118,30 +118,21 @@ export default {
}
});
break;
case '今天总访问量':
case 1: //今天总访问量
this.$router.push({
path: '/waf/wafattacklog',
query: {
}
});
break;
case '今天异常IP(个)':
});break;
case 2: //今天异常IP(个)
this.$router.push({
path: '/waf/wafattacklog',
query: {
action: "禁止"
}
});
break;
case '今天正常IP(个)':
this.$router.push({
path: '/waf/wafattacklog',
query: {
action: "放行"
}
});
break;
break;
default:
break;
}
@@ -160,19 +151,19 @@ export default {
that.wafstat_data = resdata.data;
that.panelList.push({
title: '今日攻击数',
title: this.$t('dashboard.counter.today_of_attack_count') ,
number: that.wafstat_data.AttackCountOfToday,
upTrend: '0%',
leftType: 'echarts-line',
})
that.panelList.push({
title: '今天总访问量',
title: this.$t('dashboard.counter.all_visit_count') ,
number: that.wafstat_data.VisitCountOfToday,
upTrend: '0%',
leftType: 'echarts-line',
})
that.panelList.push({
title: '今天异常IP(个)',
title:this.$t('dashboard.counter.not_normal_visit_count'),
number: that.wafstat_data.IllegalIpCountOfToday,
upTrend: '0%',
leftType: 'echarts-line',
@@ -184,7 +175,7 @@ export default {
leftType: 'echarts-line',
})*/
that.panelList.push({
title: '当前QPS',
title: this.$t('dashboard.counter.qps'),
number: that.wafstat_data.CurrentQps,
upTrend: '0%',
leftType: 'echarts-line',
@@ -204,30 +195,10 @@ export default {
} else {
this.resizeTime = 1;
}
/* this.moneyCharts.resize({
// 根据父容器的大小设置大小
width: `${this.resizeTime * 120}px`,
height: `${this.resizeTime * 66}px`,
});
this.refundChart.resize({
// 根据父容器的大小设置大小
width: `${this.resizeTime * 120}px`,
height: `${this.resizeTime * 42}px`,
}); */
},
renderCharts() {
const { chartColors } = this.$store.state.setting;
// 收入汇总图
/* if (!this.moneyContainer) this.moneyContainer = document.getElementById('moneyContainer');
this.moneyCharts = echarts.init(this.moneyContainer);
this.moneyCharts.setOption(constructInitDashboardDataset('line'));
// 退款图
if (!this.refundContainer) this.refundContainer = document.getElementById('refundContainer');
this.refundChart = echarts.init(this.refundContainer);
this.refundChart.setOption(constructInitDashboardDataset('bar', chartColors)); */
},
},
};
+9 -321
View File
@@ -1,7 +1,7 @@
import dayjs from 'dayjs';
import { getChartListColor } from '@/utils/color';
import { getRandomArray } from '@/utils/charts';
console.log(window.vm.$i18n)
/** 首页 dashboard 折线图 */
export function constructInitDashboardDataset(type: string) {
const dateArray: Array<string> = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
@@ -190,31 +190,13 @@ export function getLineChartDataSet({
placeholderColor,
borderColor,
}: { dateTime?: Array<string>,inchartarr?: Array<string>,outchartarr?: Array<string> } & Record<string, string>) {
console.log('getLineChartDataSet',inchartarr)
const divideNum = 10;
const timeArray = [];
const inArray = [];
const outArray = [];
/* for (let i = 0; i < divideNum; i++) {
if (dateTime.length > 0) {
const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
timeArray.push(dayjs(enhandTime).format('MM-DD'));
} else {
timeArray.push(
dayjs()
.subtract(divideNum - i, 'day')
.format('MM-DD'),
);
}
inArray.push(getRandomArray().toString());
outArray.push(getRandomArray().toString());
} */
console.log('line ',dateTime)
console.log('line inArray',inchartarr)
console.log('line outArray',outchartarr)
const dataSet = {
color: getChartListColor(),
tooltip: {
@@ -231,7 +213,7 @@ export function getLineChartDataSet({
left: 'center',
bottom: '0',
orient: 'horizontal', // legend 横向布局。
data: ['本周期攻击数', '本周期正常数'],
data: [window.vm.$i18n.t('dashboard.cycle_attack_count'), window.vm.$i18n.t('dashboard.cycle_normal_count')],
textStyle: {
fontSize: 12,
color: placeholderColor,
@@ -263,7 +245,7 @@ export function getLineChartDataSet({
},
series: [
{
name: '本周期攻击数',
name: window.vm.$i18n.t('dashboard.cycle_attack_count'),
data: inchartarr,
type: 'line',
smooth: false,
@@ -283,7 +265,7 @@ export function getLineChartDataSet({
},
},
{
name: '本周期正常数',
name: window.vm.$i18n.t('dashboard.cycle_normal_count'),
data: outchartarr,
type: 'line',
smooth: false,
@@ -318,300 +300,6 @@ export function getSelftItemList(productName: string, divideNum: number): string
return productArray;
}
/**
* 散点图数据
*
* @export
* @returns {any[]}
*/
export function getScatterDataSet({
dateTime = [],
placeholderColor,
borderColor,
}: { dateTime?: Array<string> } & Record<string, string>): any {
const divideNum = 40;
const timeArray = [];
const inArray = [];
const outArray = [];
for (let i = 0; i < divideNum; i++) {
// const [timeArray, inArray, outArray] = dataset;
if (dateTime.length > 0) {
const dateAbsTime: number = (new Date(dateTime[1]).getTime() - new Date(dateTime[0]).getTime()) / divideNum;
const enhandTime: number = new Date(dateTime[0]).getTime() + dateAbsTime * i;
timeArray.push(dayjs(enhandTime).format('MM-DD'));
} else {
timeArray.push(
dayjs()
.subtract(divideNum - i, 'day')
.format('MM-DD'),
);
}
inArray.push(getRandomArray().toString());
outArray.push(getRandomArray().toString());
}
return {
color: getChartListColor(),
xAxis: {
data: timeArray,
axisLabel: {
color: placeholderColor,
},
splitLine: { show: false },
axisLine: {
lineStyle: {
color: borderColor,
width: 1,
},
},
},
yAxis: {
type: 'value',
// splitLine: { show: false},
axisLabel: {
color: placeholderColor,
},
nameTextStyle: {
padding: [0, 0, 0, 60],
},
axisTick: {
show: false,
axisLine: {
show: false,
},
},
axisLine: {
show: false,
},
splitLine: {
lineStyle: {
color: borderColor,
},
},
},
tooltip: {
trigger: 'item',
},
grid: {
top: '5px',
left: '25px',
right: '5px',
bottom: '60px',
},
legend: {
left: 'center',
bottom: '0',
orient: 'horizontal', // legend 横向布局。
data: ['按摩仪', '咖啡机'],
itemHeight: 8,
itemWidth: 8,
textStyle: {
fontSize: 12,
color: placeholderColor,
},
},
series: [
{
name: '按摩仪',
symbolSize: 10,
data: outArray.reverse(),
type: 'scatter',
},
{
name: '咖啡机',
symbolSize: 10,
data: inArray.concat(inArray.reverse()),
type: 'scatter',
},
],
};
}
/**
* 获域图数据结构
*
* @export
* @returns {any[]}
*/
export function getAreaChartDataSet(): any {
const xAxisData = [];
const data1 = [];
const data2 = [];
for (let i = 0; i < 50; i++) {
xAxisData.push(`${i}`);
data1.push((getRandomArray() * Math.sin(i / 5) * (i / 5 - 5) + i / 6) * 2);
data2.push((getRandomArray() * Math.cos(i / 5) * (i / 5 - 5) + i / 6) * 2);
}
return {
color: getChartListColor(),
// title: {
// text: '柱状图动画延迟',
// },
legend: {
left: 'center',
bottom: '5%',
orient: 'horizontal',
data: ['测试', '上线'],
},
tooltip: {
trigger: 'item',
},
xAxis: {
data: xAxisData,
splitLine: {
show: false,
},
},
yAxis: {},
series: [
{
name: '测试',
type: 'bar',
data: data1,
emphasis: {
focus: 'series',
},
animationDelay(idx: number) {
return idx * 10;
},
},
{
name: '上线',
type: 'bar',
data: data2,
emphasis: {
focus: 'series',
},
animationDelay(idx: number) {
return idx * 10 + 100;
},
},
],
animationEasing: 'elasticOut',
animationDelayUpdate(idx: number) {
return idx * 5;
},
};
}
/**
* 柱状图数据结构
*
* @export
* @param {boolean} [isMonth=false]
* @returns {*}
*/
export function getColumnChartDataSet(isMonth = false) {
if (isMonth) {
return {
color: getChartListColor(),
legend: {
left: 'center',
top: '10%',
orient: 'horizontal', // legend 横向布局。
data: ['直接访问'],
},
tooltip: {
trigger: 'axis',
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
},
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
data: ['1', '4', '8', '12', '16', '20', '24'],
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: [
{
type: 'value',
},
],
series: [
{
name: '直接访问',
type: 'bar',
barWidth: '60%',
data: [
getRandomArray(Math.random() * 100),
getRandomArray(Math.random() * 200),
getRandomArray(Math.random() * 300),
getRandomArray(Math.random() * 400),
getRandomArray(Math.random() * 500),
getRandomArray(Math.random() * 600),
getRandomArray(Math.random() * 700),
],
},
],
};
}
return {
color: getChartListColor(),
tooltip: {
trigger: 'axis',
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
},
},
legend: {
left: 'center',
bottom: '0%',
orient: 'horizontal', // legend 横向布局。
data: ['直接访问'],
},
grid: {
left: '3%',
right: '4%',
bottom: '13%',
containLabel: true,
},
xAxis: [
{
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
axisTick: {
alignWithLabel: true,
},
},
],
yAxis: [
{
type: 'value',
},
],
series: [
{
name: '直接访问',
type: 'bar',
barWidth: '20%',
data: [
getRandomArray(Math.random() * 100),
getRandomArray(Math.random() * 200),
getRandomArray(Math.random() * 300),
getRandomArray(Math.random() * 400),
getRandomArray(Math.random() * 500),
getRandomArray(Math.random() * 600),
getRandomArray(Math.random() * 700),
],
},
],
};
}
export function getPieChartDataSet({
radius = 42,
@@ -660,7 +348,7 @@ export function getPieChartDataSet({
label: {
show: true,
position: 'center',
formatter: ['{value|{d}%}', '{name|{b}渠道占比}'].join('\n'),
formatter: ['{value|{d}%}', '{name|{b}}'].join('\n'),
rich: {
value: {
color: textColor,
@@ -678,7 +366,7 @@ export function getPieChartDataSet({
emphasis: {
label: {
show: true,
formatter: ['{value|{d}%}', '{name|{b}渠道占比}'].join('\n'),
formatter: ['{value|{d}%}', '{name|{b}}'].join('\n'),
rich: {
value: {
color: textColor,
@@ -700,10 +388,10 @@ export function getPieChartDataSet({
data: [
{
value: attackCount,
name: '攻击数',
name: window.vm.$i18n.t('dashboard.cycle_attack_count'),
},
{ value: normalCount,
name: '正常数' },
name: window.vm.$i18n.t('dashboard.cycle_normal_count') },
],
},
],
+5 -11
View File
@@ -1,19 +1,15 @@
<template>
<div>
<t-swiper :duration="300" :interval="5000" :navigation="navigation" v-if="tipsVisable" trigger="click">
<t-swiper-item v-for="(item, index) in tips" :key="index" v-if="item.visable" >
<t-alert :theme="item.tipsType" :message="item.message" >
<t-alert :theme="item.tipsType" :message="$t(item.message)" >
<template #operation="row">
<span @click="handleCreateWebOperation" v-if="item.name==='emptyHost'" >马上创建</span>
<span @click="handleModifyDefaultPassWebOperation" v-if="item.name==='defaultAccount'" >马上修改</span>
<span @click="handleCreateWebOperation" v-if="item.name==='emptyHost'" >{{$t('dashboard.tip_create_website_link')}}</span>
<span @click="handleModifyDefaultPassWebOperation" v-if="item.name==='defaultAccount'" >{{$t('dashboard.tip_modify_pwd_link')}}</span>
</template>
</t-alert>
</t-swiper-item>
</t-swiper>
<br>
<!-- 顶部 card -->
<top-panel class="row-container" />
@@ -27,7 +23,6 @@
import TopPanel from './components/TopPanel.vue';
import MiddleChart from './components/MiddleChart.vue';
import RankList from './components/RankList.vue';
import OutputOverview from './components/OutputOverview.vue';
import {
wafStatSysinfoapi
} from '@/apis/stats';
@@ -37,7 +32,6 @@ export default {
TopPanel,
MiddleChart,
RankList,
OutputOverview,
},
data() {
return {
@@ -54,13 +48,13 @@ export default {
{
name:"emptyHost",
visable:false,
message:"您当前未创建需要防护的网站,点击进行创建",
message:'dashboard.tip_create_website_title',
tipsType:"success"
},
{
name:"defaultAccount",
visable:false,
message:"您当前还是使用默认帐号和密码请尽快修改",
message:'dashboard.tip_modify_pwd_title',
tipsType:"error"
},
]
@@ -9,7 +9,7 @@
>
<template v-if="type == 'password'">
<t-form-item name="account">
<t-input v-model="formData.account" size="large" placeholder="请输入账号:">
<t-input v-model="formData.account" size="large" :placeholder="$t('login.input_account_placeholder')">
<template #prefix-icon>
<user-icon />
</template>
@@ -23,7 +23,7 @@
:type="showPsw ? 'text' : 'password'"
clearable
key="password"
placeholder="请输入登录密码:"
:placeholder="$t('login.input_password_placeholder')"
>
<template #prefix-icon>
<lock-on-icon />
@@ -34,55 +34,15 @@
</template>
</t-input>
</t-form-item>
<!--<div class="check-container remember-pwd">
<t-checkbox>记住账号</t-checkbox>
<span class="tip">忘记账号?</span>
</div>-->
</template>
<!-- 扫码登陆 -->
<!--<template v-else-if="type == 'qrcode'">
<div class="tip-container">
<span class="tip">请使用微信扫一扫登录</span>
<span class="refresh"
>刷新
<refresh-icon color="#0052D9" />
</span>
</div>
<qrcode-vue value="" :size="192" level="H" />
</template>-->
<!-- 手机号登陆 -->
<!--<template v-else>
<t-form-item name="phone">
<t-input v-model="formData.phone" size="large" placeholder="请输入您的手机号">
<template #prefix-icon>
<user-icon />
</template>
</t-input>
</t-form-item>
<t-form-item class="verification-code" name="verifyCode">
<t-input v-model="formData.verifyCode" size="large" placeholder="请输入验证码" key="verifyCode" />
<t-button variant="outline" :disabled="countDown > 0" @click="handleCounter">
{{ countDown == 0 ? '发送验证码' : `${countDown}秒后可重发` }}
</t-button>
</t-form-item>
</template>-->
<t-form-item v-if="type !== 'qrcode'" class="btn-container">
<t-button block size="large" type="submit"> 登录 </t-button>
<t-button block size="large" type="submit"> {{ $t('login.login_btn_title') }} </t-button>
</t-form-item>
<!--<div class="switch-container">
<span v-if="type !== 'password'" class="tip" @click="switchType('password')">使用账号密码登录</span>
<span v-if="type !== 'qrcode'" class="tip" @click="switchType('qrcode')">使用微信扫码登录</span>
<span v-if="type !== 'phone'" class="tip" @click="switchType('phone')">使用手机号登录</span>
</div>-->
</t-form>
</template>
<script lang="ts">
import i18n from '@/i18n'; // 确保导入全局 i18n 实例
import Vue from 'vue';
import QrcodeVue from 'qrcode.vue';
import { UserIcon, LockOnIcon, BrowseOffIcon, BrowseIcon, RefreshIcon } from 'tdesign-icons-vue';
@@ -96,10 +56,10 @@ const INITIAL_DATA = {
};
const FORM_RULES = {
phone: [{ required: true, message: '手机号必填', type: 'error' }],
account: [{ required: true, message: '账号必填', type: 'error' }],
password: [{ required: true, message: '密码必填', type: 'error' }],
verifyCode: [{ required: true, message: '验证码必填', type: 'error' }],
phone: [{ required: true, message: i18n.t('login.rule.phone') , type: 'error' }],
account: [{ required: true, message: i18n.t('login.rule.account') , type: 'error' }],
password: [{ required: true, message: i18n.t('login.rule.password') , type: 'error' }],
verifyCode: [{ required: true, message: i18n.t('login.rule.verifyCode') , type: 'error' }],
};
/** 高级详情 */
export default Vue.extend({
@@ -140,7 +100,7 @@ export default Vue.extend({
localStorage.setItem("current_account",this.formData.account)
this.$store.dispatch('user/login', this.formData);
this.$message.success('登录成功');
this.$message.success( this.$t('login.login_success'));
setTimeout(()=>{
this.$router.replace('/').catch(() => '');
},1000)
+3 -7
View File
@@ -4,13 +4,9 @@
<div class="login-container">
<div class="title-container">
<h1 class="title margin-no">登录</h1>
<h1 class="title">SamWaf网站防火墙后台</h1>
<h1 class="title margin-no">{{$t('login.login_title')}}</h1>
<h1 class="title">{{$t('login.login_sub_title')}}</h1>
<div class="sub-title">
<!-- <p class="tip">{{ type == 'register' ? '已有账号?' : '没有账号吗?' }}</p>
<p class="tip" @click="switchType(type == 'register' ? 'login' : 'register')">
{{ type == 'register' ? '登录' : '注册新账号' }}
</p>-->
</div>
</div>
@@ -19,7 +15,7 @@
<tdesign-setting />
</div>
<footer class="copyright">Copyright @ 2022-{{ new Date().getFullYear() }} SamWaf. All Rights Reserved <t-link theme="primary" @click="handleJumpOnlineUrl"> 遇到问题? </t-link> <a href="https://doc.samwaf.com">SamWaf在线文档</a></footer>
<footer class="copyright">Copyright @ 2022-{{ new Date().getFullYear() }} SamWaf. All Rights Reserved <t-link theme="primary" @click="handleJumpOnlineUrl"> {{$t('login.login_has_question')}} </t-link> <a href="https://doc.samwaf.com">{{$t('login.login_online_document')}} </a></footer>
</div>
</template>
<script>
+56 -84
View File
@@ -3,18 +3,16 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddAccount"> 新建账号 </t-button>
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddAccount"> {{$t('page.account.create_account')}} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>登录帐号:</span>
<t-input v-model="searchformData.login_account" class="search-input" placeholder="请输入" clearable>
<span>{{$t('page.account.login_account_label')}}</span>
<t-input v-model="searchformData.login_account" class="search-input" :placeholder="$t('common.placeholder_content')" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{$t('common.search')}} </t-button>
</t-row>
</t-form>
</div>
@@ -25,13 +23,10 @@
:pagination="pagination" :selected-row-keys="selectedRowKeys" :loading="dataLoading"
@page-change="rehandlePageChange" @change="rehandleChange" @select-change="rehandleSelectChange"
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
<template #op="slotProps">
<a class="t-button-link" @click="handleClickResetPwd(slotProps)">重置密码</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickResetPwd(slotProps)">{{$t('common.reset_password')}}</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{$t('common.edit')}}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{$t('common.delete')}}</a>
</template>
</t-table>
</div>
@@ -41,14 +36,14 @@
</t-card>
<!-- 新建账号弹窗 -->
<t-dialog header="新建账号" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('page.account.create_account')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="登录账号" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formData.login_account" placeholder="请输入登录账号"></t-input>
<t-form-item :label="$t('page.account.login_account_label')" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formData.login_account" :placeholder="$t('common.placeholder')+$t('page.account.login_account_label')"></t-input>
</t-form-item>
<t-form-item label="角色" name="role">
<t-form-item :label="$t('page.account.role')" name="role">
<t-select v-model="formData.role" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in roleType" :value="item.value" :label="item.label"
:key="index">
@@ -56,72 +51,72 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="登录密码" name="login_password">
<t-input :style="{ width: '480px' }" type="password" v-model="formData.login_password" placeholder="请输入登录密码"></t-input>
<t-form-item :label="$t('page.account.login_password')" name="login_password">
<t-input :style="{ width: '480px' }" type="password" v-model="formData.login_password" :placeholder="$t('common.placeholder')+$t('page.account.login_password')"></t-input>
</t-form-item>
<t-form-item label="状态" name="rate">
<t-input-number :style="{ width: '480px' }" v-model="formData.status" placeholder="请输入状态"></t-input-number>
<t-form-item :label="$t('common.status')" name="rate">
<t-input-number :style="{ width: '480px' }" v-model="formData.status" :placeholder="$t('common.placeholder')+$t('common.status')"></t-input-number>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入备注内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" :placeholder="$t('common.placeholder')+$t('common.remarks')" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.cancel') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑账号弹窗 -->
<t-dialog header="编辑账号" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="登录账号" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formEditData.login_account" placeholder="请输入登录账号"></t-input>
<t-form-item :label="$t('page.account.login_account_label')" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formEditData.login_account" :placeholder="$t('common.placeholder')+$t('page.account.login_account_label')"></t-input>
</t-form-item>
<t-form-item label="状态" name="status">
<t-input-number :style="{ width: '480px' }" v-model="formEditData.status" placeholder="请输入状态"></t-input-number>
<t-form-item :label="$t('common.status')" name="status">
<t-input-number :style="{ width: '480px' }" v-model="formEditData.status" :placeholder="$t('common.placeholder')+$t('common.status')"></t-input-number>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" :placeholder="$t('common.placeholder')+$t('common.remarks')" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.cancel') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 重置密码弹窗 -->
<t-dialog header="重置密码" :visible.sync="resetPwdFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('page.account.reset_password')" :visible.sync="resetPwdFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formResetPwdData" ref="form" :rules="resetPwdRules" @submit="onSubmitResetPwd" :labelWidth="100">
<t-form-item label="登录账号" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formResetPwdData.login_account" placeholder="请输入登录账号"></t-input>
<t-form-item :label="$t('page.account.login_account_label')" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formResetPwdData.login_account" :placeholder="$t('common.placeholder')+$t('page.account.login_account_label')"></t-input>
</t-form-item>
<t-form-item label="超级管理员密码" name="login_super_password">
<t-input :style="{ width: '480px' }" type="password" v-model="formResetPwdData.login_super_password" placeholder="输入超级管理员密码"></t-input>
<t-form-item :label="$t('page.account.super_admin_password')" name="login_super_password">
<t-input :style="{ width: '480px' }" type="password" v-model="formResetPwdData.login_super_password" :placeholder="$t('common.placeholder')+$t('page.account.super_admin_password')"></t-input>
</t-form-item>
<t-form-item label="新密码" name="login_new_password">
<t-input :style="{ width: '480px' }" type="password" v-model="formResetPwdData.login_new_password" placeholder="请输入新密码"></t-input>
<t-form-item :label="$t('page.account.new_password')" name="login_new_password">
<t-input :style="{ width: '480px' }" type="password" v-model="formResetPwdData.login_new_password" :placeholder="$t('common.placeholder')+$t('page.account.new_password')"></t-input>
</t-form-item>
<t-form-item label="确认密码" name="login_new_password2">
<t-input :style="{ width: '480px' }" type="password" v-model="formResetPwdData.login_new_password2" placeholder="输入确认密码"></t-input>
<t-form-item :label="$t('page.account.confirm_password')" name="login_new_password2">
<t-input :style="{ width: '480px' }" type="password" v-model="formResetPwdData.login_new_password2" :placeholder="$t('common.placeholder')+$t('page.account.confirm_password')"></t-input>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.cancel') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选数据?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -139,16 +134,6 @@
account_list_api
} from '@/apis/account';
import {
SSL_STATUS,
GUARD_STATUS,
CONTRACT_STATUS,
CONTRACT_STATUS_OPTIONS,
CONTRACT_TYPES,
CONTRACT_PAYMENT_TYPES
} from '@/constants';
const INITIAL_DATA = {
login_account: '',
login_password: '',
@@ -184,44 +169,44 @@
rules: {
login_account: [{
required: true,
message: '请输入登录账号',
message: this.$t('common.placeholder')+this.$t('page.account.login_account_label'),
type: 'error'
}],
login_password: [{
required: true,
message: '请输入登录密码',
message: this.$t('common.placeholder')+this.$t('page.account.login_password'),
type: 'error'
}],
},
resetPwdRules: {
login_account: [{
required: true,
message: '请输入登录账号',
message: this.$t('common.placeholder')+this.$t('page.account.login_account_label'),
type: 'error'
}],
login_super_password: [{
required: true,
message: '请输入超级管理员密码',
message: this.$t('common.placeholder')+this.$t('page.account.super_admin_password'),
type: 'error'
}],
login_new_password: [{
required: true,
message: '请输入新密码',
message: this.$t('common.placeholder')+this.$t('page.account.new_password'),
type: 'error'
}],
login_new_password2: [{
required: true,
message: '请输入确认密码',
message: this.$t('common.placeholder')+this.$t('page.account.confirm_password'),
type: 'error'
}],
},
roleType: [
{
label: '超级管理员',
label: this.$t('page.account.role_super_admin'),
value: 'superAdmin'
},
{
label: '管理员',
label: this.$t('page.account.role_admin'),
value: 'admin'
}
],
@@ -234,27 +219,27 @@
value: 'first',
columns: [
{
title: '登录账号',
title: this.$t('page.account.login_account_label'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'login_account',
},
{
title: '角色',
title: this.$t('page.account.role'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'role',
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -264,7 +249,7 @@
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -293,7 +278,7 @@
const {
url
} = this.data?. [this.deleteIdx];
return `删除后,数据将被删除,且无法恢复`;
return this.$t('common.data_delete_warning');
}
return '';
},
@@ -353,7 +338,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -365,7 +349,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail(e) {
console.log(e)
@@ -491,7 +474,7 @@
if (!firstError) {
if(that.formResetPwdData.login_new_password != that.formResetPwdData.login_new_password2){
that.$message.warning("两次输入的密码不相同,请检查")
that.$message.warning(this.$t('page.account.password_mismatch_warning'))
return;
}
let postdata = {
@@ -532,7 +515,7 @@
},
handleClickDelete(row) {
if(row.row.login_account=="admin"){
alert("默认管理帐号不允许删除")
alert(this.$t('page.account.admin_delete_warning'))
return;
}
console.log(row)
@@ -630,17 +613,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
@@ -1,106 +0,0 @@
@import '@/style/variables.less';
.detail-base {
/deep/ .t-card {
padding: 8px;
}
/deep/ .t-card__title {
font-size: 20px;
font-weight: 500;
}
&-info-steps {
padding-top: 12px;
}
}
.info-block {
column-count: 2;
.info-item {
padding: 12px 0;
display: flex;
color: var(--td-text-color-primary);
h1 {
width: 200px;
font-weight: normal;
font-size: @font-size-base;
color: var(--td-text-color-secondary);
text-align: left;
line-height: 22px;
@media (max-width: @screen-sm-max) {
width: 100px;
}
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
width: 120px;
}
}
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-left: 24px;
}
i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: @border-radius-50;
background: var(--td-success-color-5);
}
.inProgress {
color: var(--td-success-color-5);
}
.pdf {
color: var(--td-brand-color);
&:hover {
cursor: pointer;
}
}
}
}
.dialog-info-block {
.info-item {
padding: 12px 0;
display: flex;
h1 {
width: 84px;
font-family: PingFangSC-Regular;
font-size: 14px;
color: var(--td-text-color-secondary);
text-align: left;
line-height: 22px;
}
span {
margin-left: 24px;
}
i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: @border-radius-50;
background: var(--td-success-color-5);
}
.green {
color: var(--td-success-color-5);
}
.blue {
color: var(--td-brand-color-8);
}
}
}
@@ -1,148 +0,0 @@
<template>
<div class="detail-base">
<t-card title="网站详情">
<div class="info-block">
<div class="info-item">
<h1> 创建时间</h1>
<span>
{{ detail_data.create_time }}
</span>
</div>
<div class="info-item">
<h1> 网站</h1>
<span>
{{ detail_data.host }}
</span>
</div>
<div class="info-item">
<h1> 网站端口</h1>
<span>
{{ detail_data.port }}
</span>
</div>
<div class="info-item">
<h1> 加密证书</h1>
<span>
{{ detail_data.ssl }}
</span>
</div>
<div class="info-item">
<h1> 后端系统类型</h1>
<span>
{{ detail_data.remote_system }}
</span>
</div>
<div class="info-item">
<h1> 后端系统应用类型</h1>
<span>
{{ detail_data.remote_app }}
</span>
</div>
<div class="info-item">
<h1> 后端域名</h1>
<span>
{{ detail_data.remote_host }}
</span>
</div>
<div class="info-item">
<h1> 后端端口</h1>
<span>
{{ detail_data.remote_port }}
</span>
</div>
</div>
</t-card>
<t-card title="最近配置记录" class="container-base-margin-top">
<t-list :split="true">
<t-list-item>
<t-list-item-meta title="请求头" :description="detail_data.header"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求用户浏览器" :description="detail_data.user_agent"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求cookies" :description="detail_data.cookies"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求BODY" :description="detail_data.body"></t-list-item-meta>
</t-list-item>
</t-list>
</t-card>
</div>
</template>
<script lang="ts">
import {
prefix
} from '@/config/global';
import model from '@/service/service-detail-base';
export default {
name: 'WafHostDetail',
data() {
return {
prefix,
baseInfoData: model.getBaseInfoData(),
detail_data: {}
};
},
beforeRouteUpdate(to, from) {
console.log('beforeRouteUpdate')
},
mounted() {
console.log('----mounted----')
this.getDetail(this.$route.query.code);
},
beforeCreate() {
console.log('----beforeCreate----')
},
created() {
console.log('----created----')
},
beforeMount() {
console.log('----beforeMount----')
},
beforeUpdate() {
console.log('----beforeUpdate----')
},
updated() {
console.log('----updated----')
},
watch: {
'$route.query.code'(newVal, oldVal) {
console.log('route.query.code changed', newVal, oldVal)
this.getDetail(newVal)
},
},
methods: {
getDetail(id) {
let that = this
this.$request
.get('/wafhost/host/detail', {
params: {
CODE: id,
}
})
.then((res) => {
let resdata = res
console.log(resdata)
if (resdata.code === 0) {
that.detail_data = resdata.data;
}
})
.catch((e: Error) => {
console.log(e);
})
.finally(() => {});
},
},
};
</script>
<style lang="less" scoped>
@import './index';
</style>
+21 -87
View File
@@ -2,11 +2,7 @@
<div>
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
</div>
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的日志" clearable>
<t-input v-model="searchValue" class="search-input" :placeholder="$t('common.placeholder_content')" clearable>
<template #suffix-icon>
<search-icon size="20px" />
</template>
@@ -22,8 +18,8 @@
<template #op="slotProps">
<a class="t-button-link" @click="handleClickDetail(slotProps)">详情</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDetail(slotProps)">{{ $t('common.details') }}</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
</template>
</t-table>
</div>
@@ -32,29 +28,28 @@
</div>
</t-card>
<!-- 编辑Url白名单弹窗 -->
<t-dialog header="查看日志" :visible.sync="editFormVisible" :width="680" :footer="false">
<!-- Account Log PopDialog -->
<t-dialog :header="$t('page.account_log.view_log_dialog_title')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" :labelWidth="100">
<t-form-item label="操作账号" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formEditData.login_account" placeholder="操作账号"></t-input>
<t-form-item :label="$t('page.account_log.operation_account')" name="login_account">
<t-input :style="{ width: '480px' }" v-model="formEditData.login_account" ></t-input>
</t-form-item>
<t-form-item label="操作类型" name="op_type">
<t-input :style="{ width: '480px' }" v-model="formEditData.op_type" placeholder="请输入操作类型"></t-input>
<t-form-item :label="$t('page.account_log.operation_type')" name="op_type">
<t-input :style="{ width: '480px' }" v-model="formEditData.op_type"></t-input>
</t-form-item>
<t-form-item label="操作备注" name="op_content">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.op_content" placeholder="请输入备注" name="op_content">
<t-form-item :label="$t('common.remarks')" name="op_content">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.op_content" name="op_content">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
</div>
</template>
<script lang="ts">
@@ -66,19 +61,6 @@
import {
prefix
} from '@/config/global';
import {
account_log_list_api
} from '@/apis/account';
import {
SSL_STATUS,
GUARD_STATUS,
CONTRACT_STATUS,
CONTRACT_STATUS_OPTIONS,
CONTRACT_TYPES,
CONTRACT_PAYMENT_TYPES
} from '@/constants';
const INITIAL_DATA = {
login_account: '',
@@ -114,35 +96,35 @@
value: 'first',
columns: [
{
title: '操作账号',
title:this.$t('page.account_log.operation_account'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'login_account',
colKey: 'login_account',
},
{
title: '操作类型',
title:this.$t('page.account_log.operation_type'),
width: 200,
ellipsis: true,
colKey: 'op_type',
},
{
title: '操作内容',
title: this.$t('page.account_log.operation_content'),
width: 200,
ellipsis: true,
colKey: 'op_content',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
},
{
align: 'left',
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -150,7 +132,7 @@
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
// pagination
pagination: {
total: 0,
current: 1,
@@ -165,38 +147,15 @@
};
},
computed: {
confirmBody() {
if (this.deleteIdx > -1) {
const {
url
} = this.data?. [this.deleteIdx];
return `删除后,${url}的数据将被删除,且无法恢复`;
}
return '';
},
offsetTop() {
return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
},
},
mounted() {
this.getList("")
this.loadHostList()
},
methods: {
loadHostList(){
/* let that = this;
allhost().then((res) => {
let resdata = res
console.log(resdata)
if (resdata.code === 0) {
that.host_options = resdata.data;
}
})
.catch((e: Error) => {
console.log(e);
}) */
},
getList(keyword) {
let that = this
this.$request
@@ -214,7 +173,6 @@
this.data = resdata.data.list;
this.data_attach = []
console.log('getList',this.data)
this.pagination = {
...this.pagination,
total: resdata.data.total,
@@ -233,7 +191,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -245,7 +202,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail(e) {
console.log(e)
@@ -312,28 +268,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
.selected-count {
display: inline-block;
margin-left: 8px;
color: var(--td-text-color-secondary);
}
}
.search-input {
width: 360px;
}
+7 -8
View File
@@ -2,13 +2,13 @@
<div class="contentarea">
<div class="left-column">
<!-- 左边列内容 -->
日期:<t-space direction="horizontal">
{{$t('common.date')}} :<t-space direction="horizontal">
<t-date-range-picker v-model="range1" :presets="presets" />
<t-select v-model="currentAction" class="form-item-content`" :options="action_options" placeholder="请选择防御状态"
<t-select v-model="currentAction" class="form-item-content`" :options="action_options"
:style="{ width: '100px' }" />
</t-space>
<t-button variant="outline" @click="loadCountryData"> 搜索 </t-button>
<t-button variant="outline" @click="loadCountryData"> {{ $t('common.search') }} </t-button>
<div id="countryMap" style="width:100%; height:40.5rem;"></div>
</div>
<div class="right-column">
@@ -119,19 +119,19 @@
currentAction: "",
action_options: [
{
label: '全部',
label: this.$t('common.defense_status.all'),
value: ''
},
{
label: '阻止',
label: this.$t('common.defense_status.stop'),
value: '阻止'
},
{
label: '放行',
label: this.$t('common.defense_status.pass'),
value: '放行'
},
{
label: '禁止',
label: this.$t('common.defense_status.forbid'),
value: '禁止'
},
],
@@ -257,7 +257,6 @@
maxValue = item.value;
}
});
console.log("最大值为: ", maxValue);
that.mapOptions.series[0].data = resdata
that.mapOptions.visualMap.max = maxValue
that.map.setOption(that.mapOptions);
+46 -50
View File
@@ -3,29 +3,28 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddAntiCC"> 新建CC防护 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddAntiCC"> {{ $t('page.cc.new_cc_protection') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{$t('page.cc.host')}} :</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>URL:</span>
<t-input v-model="searchformData.url" class="search-input" placeholder="请输入" clearable>
<t-input v-model="searchformData.url" class="search-input" :placeholder="$t('common.placeholder')" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf防护墙抵御CC攻击" close>
<t-alert theme="info" :message="$t('page.cc.samwaf_cc_protection')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -39,8 +38,8 @@
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -49,12 +48,11 @@
</div>
</t-card>
<!-- 新建CC防护弹窗 -->
<t-dialog header="新建cc防护" :visible.sync="addFormVisible" :width="680" :footer="false">
<!-- New CC Protect Dialog -->
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.cc.website')" name="host_code">
<t-select v-model="formData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -62,33 +60,32 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" placeholder="请输入CC防护url(可不填)"></t-input>
<t-form-item :label="$t('page.cc.url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" :placeholder="$t('page.cc.input_url_placeholder')"></t-input>
</t-form-item>
<t-form-item label="速率" name="rate">
<t-input-number :style="{ width: '480px' }" v-model="formData.rate" placeholder="请输入速率"></t-input-number>
<t-form-item :label="$t('page.cc.rate')" name="rate">
<t-input-number :style="{ width: '480px' }" v-model="formData.rate" :placeholder="$t('common.placeholder')+$t('page.cc.rate')"></t-input-number>
</t-form-item>
<t-form-item label="限制次数" name="limit">
<t-input-number :style="{ width: '480px' }" v-model="formData.limit" placeholder="请输入限制"></t-input-number>
<t-form-item :label="$t('page.cc.limit')" name="limit">
<t-input-number :style="{ width: '480px' }" v-model="formData.limit" :placeholder="$t('common.placeholder')+$t('page.cc.limit')"></t-input-number>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" :placeholder="$t('common.placeholder_content')" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑CC防护弹窗 -->
<t-dialog header="编辑CC防护" :visible.sync="editFormVisible" :width="680" :footer="false">
<!-- Edit CC Protect Dialog -->
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.cc.website')" name="host_code">
<t-select v-model="formEditData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -96,28 +93,29 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="速率" name="rate">
<t-input-number :style="{ width: '480px' }" v-model="formEditData.rate" placeholder="请输入速率"></t-input-number>
<t-form-item :label="$t('page.cc.url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" :placeholder="$t('page.cc.input_url_placeholder')"></t-input>
</t-form-item>
<t-form-item label="限制次数" name="limit">
<t-input-number :style="{ width: '480px' }" v-model="formEditData.limit" placeholder="请输入限制"></t-input-number>
<t-form-item :label="$t('page.cc.rate')" name="rate">
<t-input-number :style="{ width: '480px' }" v-model="formEditData.rate" :placeholder="$t('common.placeholder')+$t('page.cc.rate')"></t-input-number>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" placeholder="请输入CC防护"></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('page.cc.limit')" name="limit">
<t-input-number :style="{ width: '480px' }" v-model="formEditData.limit" :placeholder="$t('common.placeholder')+$t('page.cc.limit')"></t-input-number>
</t-form-item>
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" :placeholder="$t('common.placeholder_content')" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选Url?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -175,17 +173,17 @@ import {
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
message: this.$t('page.cc.website'),
type: 'error'
}],
rate: [{
required: true,
message: '请输入速率',
message: this.$t('page.cc.rate'),
type: 'error'
}],
limit: [{
required: true,
message: '请输入访问次数限制',
message: this.$t('page.cc.limit'),
type: 'error'
}],
},
@@ -198,26 +196,26 @@ import {
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.cc.website'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'host_code',
},
{
title: '速率',
title: this.$t('page.cc.rate'),
width: 200,
ellipsis: true,
colKey: 'rate',
},
{
title: '限制次数',
title: this.$t('page.cc.limit'),
width: 200,
ellipsis: true,
colKey: 'limit',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -227,7 +225,7 @@ import {
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -259,7 +257,7 @@ import {
const {
url
} = this.data?. [this.deleteIdx];
return `确认要删除吗?`;
return this.$t('common.data_delete_warning');
}
return '';
},
@@ -337,7 +335,6 @@ import {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
console.log(e)
const {
id
} = e.row
@@ -346,7 +343,6 @@ import {
this.getDetail(id)
},
handleAddAntiCC() {
//添加CC防护
this.addFormVisible = true
this.formData = {
host_code: '',
+32 -33
View File
@@ -1,110 +1,110 @@
<template>
<div class="detail-base">
<t-card title="防御情况" class="container-base-margin-top">
<t-card :title="$t('page.visit_log.detail.defense_status')" class="container-base-margin-top">
<t-steps class="detail-base-info-steps" layout="horizontal" theme="dot" :current="3">
<t-step-item title="访问" :content="detail_data.create_time" />
<t-step-item title="检测" :content="detail_data.create_time" />
<t-step-item title="防御状态" :content="detail_data.action" />
<t-step-item title="响应状态" :content="detail_data.status" />
<t-step-item :title="$t('page.visit_log.detail.visit_time')" :content="detail_data.create_time" />
<t-step-item :title="$t('page.visit_log.detail.detection_time')" />
<t-step-item :title="$t('page.visit_log.detail.defense_status_step')" :content="detail_data.action" />
<t-step-item :title="$t('page.visit_log.detail.response_status')" :content="detail_data.status" />
</t-steps>
</t-card>
<t-card title="本次请求详情" >
<t-card :title="$t('common.details')" >
<div class="info-block">
<div class="info-item">
<h1> 请求标识</h1>
<h1> {{ $t('page.visit_log.detail.request_identifier') }}</h1>
<span>
{{ detail_data.req_uuid }}
</span>
</div>
<div class="info-item">
<h1> 请求时间</h1>
<h1> {{ $t('page.visit_log.detail.request_time') }}</h1>
<span>
{{ detail_data.create_time }}
</span>
</div>
<div class="info-item">
<h1> 请求域名</h1>
<h1> {{ $t('page.visit_log.detail.request_domain') }}</h1>
<span>
{{ detail_data.host }}
</span>
</div>
<div class="info-item">
<h1> 请求方法</h1>
<h1> {{ $t('page.visit_log.detail.request_method') }}</h1>
<span>
{{ detail_data.method }}
</span>
</div>
<div class="info-item">
<h1> 请求内容大小</h1>
<h1> {{ $t('page.visit_log.detail.request_content_size') }}</h1>
<span>
{{ detail_data.content_length }}
</span>
</div>
<div class="info-item">
<h1> 访问者IP</h1>
<h1> {{ $t('page.visit_log.detail.visitor_ip') }}</h1>
<span>
{{ detail_data.src_ip }}
<t-button theme="primary" shape="round" size="small" @click="handleAddipblock">加黑名单</t-button>
<t-button theme="primary" shape="round" size="small" @click="handleAddipblock">{{ $t('page.visit_log.detail.add_to_deny_list') }}</t-button>
</span>
</div>
<div class="info-item">
<h1> 访问者端口</h1>
<h1> {{ $t('page.visit_log.detail.visitor_port') }}</h1>
<span>
{{ detail_data.src_port }}
</span>
</div>
<div class="info-item">
<h1> 请求地区</h1>
<h1> {{ $t('page.visit_log.detail.request_region') }}</h1>
<span>
{{ detail_data.country }} {{ detail_data.province }} {{ detail_data.city }}
</span>
</div>
<div class="info-item">
<h1> 响应编码</h1>
<h1> {{ $t('page.visit_log.detail.response_code') }}</h1>
<span>
{{ detail_data.status_code }} ({{detail_data.status}} )
</span>
</div>
</div>
</t-card>
<t-card title="访问其他记录" class="container-base-margin-top">
<t-card :title="$t('page.visit_log.detail.more_info')" class="container-base-margin-top">
<template #actions>
<t-tooltip content="鼠标选中想要添加的内容后,点击页面空白即可">
快捷加入规则: <t-switch size="large" v-model="quickAddRuleChecked" :label="['开', '关']"></t-switch>
<t-tooltip :content="$t('page.visit_log.detail.mouse_select_tooltip')">
{{$t('page.visit_log.detail.quick_add_rule')}}: <t-switch size="large" v-model="quickAddRuleChecked" :label="[$t('page.visit_log.detail.open'), $t('page.visit_log.detail.close')]"></t-switch>
</t-tooltip>
</template>
<t-list :split="true">
<t-list-item>
<t-list-item-meta title="请求路径"></t-list-item-meta>
<t-list-item-meta :title="$t('page.visit_log.detail.request_path')"></t-list-item-meta>
</t-list-item>
<t-textarea v-model="detail_data.url" :autosize="{ minRows: 3, maxRows: 5 }" readonly @blur="handleMouseSelect('url')"/>
<t-list-item>
<t-list-item-meta title="请求头"></t-list-item-meta>
<t-list-item-meta :title="$t('page.visit_log.detail.request_header')"></t-list-item-meta>
</t-list-item>
<t-textarea v-model="detail_data.header" :autosize="{ minRows: 3, maxRows: 5 }" readonly @blur="handleMouseSelect('header')"/>
<t-list-item>
<t-list-item-meta title="请求用户浏览器" ></t-list-item-meta>
<t-list-item-meta :title="$t('page.visit_log.detail.request_user_browser')" ></t-list-item-meta>
</t-list-item>
<t-textarea v-model="detail_data.user_agent" :autosize="{ minRows: 3, maxRows: 5 }" readonly @blur="handleMouseSelect('user_agent')"/>
<t-list-item>
<t-list-item-meta title="请求cookies" ></t-list-item-meta>
<t-list-item-meta :title="$t('page.visit_log.detail.request_cookies')" ></t-list-item-meta>
</t-list-item>
<t-textarea v-model="detail_data.cookies" :autosize="{ minRows: 3, maxRows: 5 }" readonly @blur="handleMouseSelect('cookies')"/>
<t-list-item >
<t-list-item-meta title="请求BODY" ></t-list-item-meta>
<t-list-item-meta :title="$t('page.visit_log.detail.request_body')" ></t-list-item-meta>
</t-list-item>
<t-textarea v-model="detail_data.body" :autosize="{ minRows: 3, maxRows: 5 }" readonly @blur="handleMouseSelect('body')"/>
<t-list-item >
<t-list-item-meta title="请求Form" ></t-list-item-meta>
<t-list-item-meta :title="$t('page.visit_log.detail.request_form')" ></t-list-item-meta>
</t-list-item>
<t-textarea v-model="detail_data.post_form" :autosize="{ minRows: 3, maxRows: 5 }" readonly />
</t-list>
</t-card>
<t-card title="响应数据">
<t-card :title="$t('page.visit_log.detail.response_data')">
<t-textarea v-model="detail_data.res_body" :autosize="{ minRows: 5, maxRows: 10 }" readonly />
</t-card>
<t-button theme="primary" type="button" @click="backPage">返回</t-button>
<t-button theme="primary" type="button" @click="backPage">{{ $t('page.visit_log.detail.back') }}</t-button>
</div>
@@ -207,12 +207,12 @@
const confirmDia = this.$dialog.confirm({
header: '加入IP黑名单',
body: '你确定要加入黑名单IP('+ this.detail_data.src_ip +")么?",
confirmBtn: '确定',
cancelBtn: '取消',
header: this.$t('page.visit_log.detail.add_to_deny_list_confirm_header') ,
body: this.$t('page.visit_log.detail.add_to_deny_list_confirm_body') ,
confirmBtn: this.$t('common.confirm') ,
cancelBtn: this.$t('common.cancel') ,
onConfirm: ({ e }) => {
//添加黑名单IP
//add deny IP
let formData = {
host_code: this.detail_data.host_code,
ip: this.detail_data.src_ip,
@@ -235,7 +235,6 @@
})
.finally(() => {});
// 请求成功后,销毁弹框
confirmDia.destroy();
},
onClose: ({ e, trigger }) => {
+42 -85
View File
@@ -1,8 +1,8 @@
<template>
<div>
<t-alert theme="info" message="防御日志" close>
<t-alert theme="info" :message="$t('page.visit_log.visit_log')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<t-card class="list-card-container">
@@ -12,7 +12,7 @@
<t-col :span="10">
<t-row :gutter="[16, 24]">
<t-col :flex="1">
<t-form-item label="网站" name="rule">
<t-form-item :label="$t('page.visit_log.website')" name="website">
<t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
@@ -22,41 +22,41 @@
</t-col>
<t-col :flex="1">
<t-form-item label="规则名称" name="rule">
<t-input v-model="searchformData.rule" class="form-item-content" type="search" placeholder="请输入规则名称"
<t-form-item :label="$t('page.visit_log.rule_name')" name="rule">
<t-input v-model="searchformData.rule" class="form-item-content" type="search" :placeholder="$t('common.placeholder') + $t('page.visit_log.rule_name')"
:style="{ minWidth: '134px' }" />
</t-form-item>
</t-col>
<t-col :flex="1">
<t-form-item label="访问状态" name="action">
<t-form-item :label="$t('page.visit_log.access_status')" name="action">
<t-select v-model="searchformData.action" class="form-item-content`" :options="action_options"
placeholder="请选择防御状态" :style="{ width: '100px' }" />
:placeholder="$t('common.select_placeholder')+$t('page.visit_log.access_status')" :style="{ width: '100px' }" />
</t-form-item>
</t-col>
<t-col :flex="1">
<t-form-item label="响应码" name="status_code">
<t-input v-model="searchformData.status_code" class="form-item-content" placeholder="请输入响应码"
<t-form-item :label="$t('page.visit_log.status_code')" name="status_code">
<t-input v-model="searchformData.status_code" class="form-item-content" :placeholder="$t('common.placeholder')+$t('page.visit_log.status_code')"
:style="{ minWidth: '100px' }" />
</t-form-item>
</t-col>
<t-col :flex="1">
<t-form-item label="访问IP" name="src_ip">
<t-input v-model="searchformData.src_ip" class="form-item-content" placeholder="请输入访问IP"
<t-form-item :label="$t('page.visit_log.source_ip')" name="src_ip">
<t-input v-model="searchformData.src_ip" class="form-item-content" :placeholder="$t('common.placeholder')+$t('page.visit_log.source_ip')"
:style="{ minWidth: '100px' }" />
</t-form-item>
</t-col>
<t-col :flex="2">
<t-form-item label="访问日期" name="unix_add_time">
<t-form-item :label="$t('page.visit_log.access_date')" name="unix_add_time">
<t-date-range-picker v-model="dateControl.range1" :presets="dateControl.presets" enable-time-picker valueType="YYYY-MM-DD HH:mm:ss" /></t-form-item>
</t-col>
<t-col :flex="1">
<t-form-item label="访问方法" name="method">
<t-form-item :label="$t('page.visit_log.access_method')" name="method">
<t-select v-model="searchformData.method" class="form-item-content`" :options="method_options"
placeholder="请输入访问方法" :style="{ width: '100px' }" />
:placeholder="$t('common.placeholder') + $t('page.visit_log.access_method')" :style="{ width: '100px' }" />
</t-form-item>
</t-col>
<t-col :flex="1">
<t-form-item label="日志归档库" name="sharedb">
<t-form-item :label="$t('common.log_archive_db')" name="sharedb">
<t-select v-model="searchformData.current_db_name" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in share_db_dic" :value="index" :label="item" :key="index">
{{ item }}
@@ -68,8 +68,8 @@
</t-col>
<t-col :span="2" class="operation-container">
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button type="reset" variant="base" theme="default"> 重置 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
<t-button type="reset" variant="base" theme="default"> {{ $t('common.reset') }} </t-button>
</t-col>
</t-row>
</t-form>
@@ -103,16 +103,12 @@
<t-tag v-if="row.rule !== ''" shape="round" theme="primary" variant="outline">{{row.rule}}</t-tag>
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickIPDetail(slotProps)">查询IP</a>
<a class="t-button-link" @click="handleClickDetail(slotProps)">详情</a>
<!-- <a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a> -->
<a class="t-button-link" @click="handleClickIPDetail(slotProps)">{{$t('common.search') + $t('page.visit_log.source_ip') }}</a>
<a class="t-button-link" @click="handleClickDetail(slotProps)">{{$t('common.details')}}</a>
</template>
</t-table>
</div>
</t-card>
<t-dialog header="确认删除当前所选日志?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
</template>
<script lang="ts">
@@ -169,25 +165,25 @@
},
action_options: [
{
label: '全部',
label: this.$t('common.defense_status.all'),
value: ''
},
{
label: '阻止',
label: this.$t('common.defense_status.stop'),
value: '阻止'
},
{
label: '放行',
label: this.$t('common.defense_status.pass'),
value: '放行'
},
{
label: '禁止',
label: this.$t('common.defense_status.forbid'),
value: '禁止'
},
],
method_options: [
{
label: '全部',
label: this.$t('common.all'),
value: ''
},
{
@@ -229,7 +225,7 @@
displayColumns: staticColumn.concat(['guest_identification','time_spent','create_time', 'host', 'method', 'url', 'src_ip', 'country']),
columns: [
{
title: '访客身份',
title: this.$t('page.visit_log.guest_identity'),
width: 100,
ellipsis: true,
colKey: 'guest_identification',
@@ -239,47 +235,47 @@
// 按下 Enter 键时也触发确认搜索
confirmEvents: ['onEnter'],
props: {
placeholder: '输入关键词过滤',
placeholder: this.$t('common.placeholder'),
},
// 是否显示重置取消按钮,一般情况不需要显示
showConfirmAndReset: true,
},
},
{
title: '耗时(ms)',
title: this.$t('page.visit_log.time_spent'),
width: 100,
ellipsis: true,
colKey: 'time_spent',
sorter: true
},
{
title: '危害程度',
title: this.$t('page.visit_log.risk_level'),
width: 60,
ellipsis: true,
colKey: 'risk_level',
},
{
title: '状态',
title: this.$t('common.status'),
width: 60,
ellipsis: true,
colKey: 'action',
},
{
title: '触发规则',
title: this.$t('page.visit_log.trigger_rule'),
align: 'left',
width: 150,
ellipsis: true,
colKey: 'rule',
},
{
title: '时间',
title: this.$t('page.visit_log.time'),
width: 170,
ellipsis: true,
colKey: 'create_time',
sorter: true
},
{
title: '域名',
title: this.$t('page.visit_log.domain'),
align: 'left',
width: 150,
ellipsis: true,
@@ -287,36 +283,36 @@
},
{
title: '请求',
title: this.$t('page.visit_log.request'),
width: 70,
ellipsis: true,
colKey: 'method',
},
{
title: '来源IP',
title: this.$t('page.visit_log.source_ip'),
width: 150,
ellipsis: true,
colKey: 'src_ip',
},
{
title: '国家',
title: this.$t('page.visit_log.country'),
width: 100,
ellipsis: true,
colKey: 'country',
},
{
title: '省份',
title:this.$t('page.visit_log.province'),
width: 100,
ellipsis: true,
colKey: 'province',
}, {
title: '城市',
title: this.$t('page.visit_log.city'),
width: 100,
ellipsis: true,
colKey: 'city',
},
{
title: '访问url',
title: this.$t('page.visit_log.access_url'),
width: 160,
ellipsis: true,
colKey: 'url',
@@ -332,7 +328,7 @@
// 按下 Enter 键时也触发确认搜索
confirmEvents: ['onEnter'],
props: {
placeholder: '输入关键词过滤',
placeholder: this.$t('common.placeholder'),
},
// 是否显示重置取消按钮,一般情况不需要显示
showConfirmAndReset: true,
@@ -348,7 +344,7 @@
align: 'left',
width: 120,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'REQ_UUID',
@@ -398,13 +394,6 @@
};
},
computed: {
confirmBody() {
if (this.deleteIdx > -1) {
const { name } = this.data?.[this.deleteIdx];
return `删除后,${name}的所有合同信息将被清空,且无法恢复`;
}
return '';
},
offsetTop() {
return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
},
@@ -414,7 +403,7 @@
fields: ['action', 'rule', 'create_time', 'host', 'method', 'url', 'header', 'country', 'province', 'city', 'status','risk_level','guest_identification','time_spent'],
// 弹框组件属性透传
dialogProps: { preventScrollThrough: true },
// 列配置按钮属性头像
// 列配置按钮属性
buttonProps: this.customText ? { content: '显示列控制', theme: 'primary', variant: 'base' } : undefined,
// 数据字段分组显示
groupColumns: this.groupColumn ? GROUP_COLUMNS : undefined,
@@ -557,7 +546,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -569,7 +557,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail(e) {
console.log(e)
@@ -596,7 +583,6 @@
this.confirmVisible = true;
},
onConfirmDelete() {
// 真实业务请发起请求
this.data.splice(this.deleteIdx, 1);
this.pagination.total = this.data.length;
const selectedIdx = this.selectedRowKeys.indexOf(this.deleteIdx);
@@ -613,7 +599,7 @@
resetIdx() {
this.deleteIdx = -1;
},
//跳转界面
//Jump Url
handleJumpOnlineUrl(){
window.open(this.samwafglobalconfig.getOnlineUrl()+"/guide/attacklog.html");
},
@@ -621,7 +607,6 @@
* table 排序
*/
onSortChange(sorter){
console.log('排序',sorter)
let that = this
if (sorter != undefined){
@@ -638,13 +623,11 @@
* 访客身份筛选
*/
filterGuestChange(e){
console.log("访客身份",e)
},
/**
* 筛选结果
*/
onFilterChange(e){
console.log("筛选结果",e)
this.filters.filter_by = "";
this.filters.filter_value = "";
//访客身份
@@ -671,32 +654,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
.selected-count {
display: inline-block;
margin-left: 8px;
color: var(--td-text-color-secondary);
}
}
.search-input {
width: 360px;
}
.t-button+.t-button {
margin-left: @spacer;
}
+14 -64
View File
@@ -3,45 +3,26 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleChangeLocalClear"> 切换本机(不进行远程访问) </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleChangeLocalClear"> {{$t('page.center.switch_local')}} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<!-- <span>网站:</span>
<t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>URL:</span>
<t-input v-model="searchformData.url" class="search-input" placeholder="请输入" clearable>
</t-input>-->
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询</t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }}</t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert v-if="pagination.total>freeClientCount && isVip==false" theme="warning" message="超出免费台数限额" close>
<template #operation>
<span @click="handleJumpLicense">跳转授权信息画面</span>
</template>
</t-alert>
<div class="table-container">
<t-table :columns="columns" :data="data" :rowKey="rowKey" :verticalAlign="verticalAlign" :hover="hover"
:pagination="pagination" :selected-row-keys="selectedRowKeys" :loading="dataLoading"
@page-change="rehandlePageChange" @change="rehandleChange" @select-change="rehandleSelectChange"
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
<template #host_code="{ row }">
<span> {{ host_dic[row.host_code] }}</span>
</template>
<template #op="slotProps">
<a class="t-button-link" v-if="pagination.total<=freeClientCount || isVip" @click="handleClickChangeServer(slotProps)">切换服务器</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" v-if="pagination.total<=freeClientCount || isVip" @click="handleClickChangeServer(slotProps)">{{ $t('page.center.server_switch_button') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -99,21 +80,7 @@ export default Vue.extend({
...INITIAL_DATA
},
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
type: 'error'
}],
rate: [{
required: true,
message: '请输入速率',
type: 'error'
}],
limit: [{
required: true,
message: '请输入访问次数限制',
type: 'error'
}],
},
textareaValue: '',
prefix,
@@ -124,34 +91,34 @@ export default Vue.extend({
value: 'first',
columns: [
{
title: '客户端名称',
title: this.$t('page.center.client_server_name'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'client_server_name',
},
{
title: '操作系统类型',
title:this.$t('page.center.client_system_type'),
width: 100,
ellipsis: true,
colKey: 'client_system_type',
}, {
title: 'IP',
title: this.$t('page.center.client_ip'),
width: 150,
ellipsis: true,
colKey: 'client_ip',
}, {
title: '端口',
title: this.$t('page.center.client_port'),
width: 100,
ellipsis: true,
colKey: 'client_port',
},{
title: '版本号',
title: this.$t('page.center.client_new_version'),
width: 100,
ellipsis: true,
colKey: 'client_new_version',
}, {
title: '版本',
title: this.$t('page.center.client_new_version_desc'),
width: 200,
ellipsis: true,
colKey: 'client_new_version_desc',
@@ -160,16 +127,16 @@ export default Vue.extend({
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
{
title: '最近访问时间',
title:this.$t('page.center.last_visit_time'),
width: 200,
ellipsis: true,
colKey: 'last_visit_time',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -193,20 +160,9 @@ export default Vue.extend({
//索引区域
deleteIdx: -1,
guardStatusIdx: -1,
//主机字典
host_dic: {}
};
},
computed: {
confirmBody() {
if (this.deleteIdx > -1) {
const {
url
} = this.data?. [this.deleteIdx];
return `确认要删除吗?`;
}
return '';
},
offsetTop() {
return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
},
@@ -217,12 +173,6 @@ export default Vue.extend({
},
methods: {
/**
* 跳转授权信息*/
handleJumpLicense(){
this.$router.push('/center/License');
},
/**加载当前授权信息**/
loadCurrentLicense() {
let that = this
getLicenseDetailApi({})
@@ -1,106 +0,0 @@
@import '@/style/variables.less';
.detail-base {
/deep/ .t-card {
padding: 8px;
}
/deep/ .t-card__title {
font-size: 20px;
font-weight: 500;
}
&-info-steps {
padding-top: 12px;
}
}
.info-block {
column-count: 2;
.info-item {
padding: 12px 0;
display: flex;
color: var(--td-text-color-primary);
h1 {
width: 200px;
font-weight: normal;
font-size: @font-size-base;
color: var(--td-text-color-secondary);
text-align: left;
line-height: 22px;
@media (max-width: @screen-sm-max) {
width: 100px;
}
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
width: 120px;
}
}
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-left: 24px;
}
i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: @border-radius-50;
background: var(--td-success-color-5);
}
.inProgress {
color: var(--td-success-color-5);
}
.pdf {
color: var(--td-brand-color);
&:hover {
cursor: pointer;
}
}
}
}
.dialog-info-block {
.info-item {
padding: 12px 0;
display: flex;
h1 {
width: 84px;
font-family: PingFangSC-Regular;
font-size: 14px;
color: var(--td-text-color-secondary);
text-align: left;
line-height: 22px;
}
span {
margin-left: 24px;
}
i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: @border-radius-50;
background: var(--td-success-color-5);
}
.green {
color: var(--td-success-color-5);
}
.blue {
color: var(--td-brand-color-8);
}
}
}
@@ -1,148 +0,0 @@
<template>
<div class="detail-base">
<t-card title="网站详情">
<div class="info-block">
<div class="info-item">
<h1> 创建时间</h1>
<span>
{{ detail_data.create_time }}
</span>
</div>
<div class="info-item">
<h1> 网站</h1>
<span>
{{ detail_data.host }}
</span>
</div>
<div class="info-item">
<h1> 网站端口</h1>
<span>
{{ detail_data.port }}
</span>
</div>
<div class="info-item">
<h1> 加密证书</h1>
<span>
{{ detail_data.ssl }}
</span>
</div>
<div class="info-item">
<h1> 后端系统类型</h1>
<span>
{{ detail_data.remote_system }}
</span>
</div>
<div class="info-item">
<h1> 后端系统应用类型</h1>
<span>
{{ detail_data.remote_app }}
</span>
</div>
<div class="info-item">
<h1> 后端域名</h1>
<span>
{{ detail_data.remote_host }}
</span>
</div>
<div class="info-item">
<h1> 后端端口</h1>
<span>
{{ detail_data.remote_port }}
</span>
</div>
</div>
</t-card>
<t-card title="最近配置记录" class="container-base-margin-top">
<t-list :split="true">
<t-list-item>
<t-list-item-meta title="请求头" :description="detail_data.header"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求用户浏览器" :description="detail_data.user_agent"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求cookies" :description="detail_data.cookies"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求BODY" :description="detail_data.body"></t-list-item-meta>
</t-list-item>
</t-list>
</t-card>
</div>
</template>
<script lang="ts">
import {
prefix
} from '@/config/global';
import model from '@/service/service-detail-base';
export default {
name: 'WafHostDetail',
data() {
return {
prefix,
baseInfoData: model.getBaseInfoData(),
detail_data: {}
};
},
beforeRouteUpdate(to, from) {
console.log('beforeRouteUpdate')
},
mounted() {
console.log('----mounted----')
this.getDetail(this.$route.query.code);
},
beforeCreate() {
console.log('----beforeCreate----')
},
created() {
console.log('----created----')
},
beforeMount() {
console.log('----beforeMount----')
},
beforeUpdate() {
console.log('----beforeUpdate----')
},
updated() {
console.log('----updated----')
},
watch: {
'$route.query.code'(newVal, oldVal) {
console.log('route.query.code changed', newVal, oldVal)
this.getDetail(newVal)
},
},
methods: {
getDetail(id) {
let that = this
this.$request
.get('/wafhost/host/detail', {
params: {
CODE: id,
}
})
.then((res) => {
let resdata = res
console.log(resdata)
if (resdata.code === 0) {
that.detail_data = resdata.data;
}
})
.catch((e: Error) => {
console.log(e);
})
.finally(() => {});
},
},
};
</script>
<style lang="less" scoped>
@import './index';
</style>
+155 -194
View File
@@ -3,35 +3,34 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddHost"> 新建防护</t-button>
<t-button variant="base" theme="default" @click="HandleExportExcel()"> 导出数据</t-button>
<t-button variant="base" theme="default" @click="HandleImportExcel()"> 导入数据</t-button>
<t-button @click="handleAddHost"> {{ $t('page.host.new_protection') }}</t-button>
<t-button variant="base" theme="default" @click="HandleExportExcel()"> {{ $t('page.host.export_data') }}</t-button>
<t-button variant="base" theme="default" @click="HandleImportExcel()"> {{ $t('page.host.import_data') }}</t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span>
<span>{{ $t('page.host.website') }}</span>
<t-select v-model="searchformData.code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>URL:</span>
<t-input v-model="searchformData.url" class="search-input" placeholder="请输入" clearable>
<t-input v-model="searchformData.url" class="search-input" :placeholder="$t('common.placeholder')" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询</t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }}</t-button>
</t-row>
</t-form>
</div>
</t-row>
<div class="table-container">
<t-alert theme="info" message="SamWaf核心功能,所有网站信息,防护功能开启等" close>
<t-alert theme="info" :message="$t('page.host.core_features')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">主机在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<t-table :columns="columns" size="small" :data="data" :rowKey="rowKey" :verticalAlign="verticalAlign"
@@ -39,35 +38,23 @@
@page-change="rehandlePageChange" @change="rehandleChange" @select-change="rehandleSelectChange"
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
<template #guard_status="{ row }">
<t-switch size="large" v-model="row.guard_status ===1" :label="['已防护', '未防护']"
@change="changeGuardStatus($event,row)">
<t-switch size="large" v-model="row.guard_status ===1" :label="[$t('page.host.guard_status_on'), $t('page.host.guard_status_off')]"
@change="changeGuardStatus($event,row)">
</t-switch>
</template>
<template #start_status="{ row }">
<t-switch size="large" v-model="row.start_status===0" :label="['自动启动', '手工启动']"
<t-switch size="large" v-model="row.start_status===0" :label="[$t('page.host.auto_start_on'), $t('page.host.auto_start_off')]"
@change="changeStartStatus($event,row)">
</t-switch>
</template>
<template #ssl="{ row }">
<p v-if="row.ssl === SSL_STATUS.NOT_SSL">否</p>
<p v-if="row.ssl === SSL_STATUS.SSL">是</p>
<p v-if="row.ssl === SSL_STATUS.NOT_SSL">{{ $t('page.host.ssl_no') }}</p>
<p v-if="row.ssl === SSL_STATUS.SSL">{{ $t('page.host.ssl_yes') }}</p>
</template>
<template #paymentType="{ row }">
<p v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.PAYMENT" class="payment-col">
付款
<trend class="dashboard-item-trend" type="up"/>
</p>
<p v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.RECIPT" class="payment-col">
收款
<trend class="dashboard-item-trend" type="down"/>
</p>
</template>
<template #op="slotProps">
<!--<a class="t-button-link" @click="handleClickEdit(slotProps)">系统自带防御</a>-->
<a class="t-button-link" v-if="slotProps.row.global_host!==1" @click="handleClickCopy(slotProps)">复制</a>
<a class="t-button-link" v-if="slotProps.row.global_host!==1" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" v-if="slotProps.row.global_host!==1" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" v-if="slotProps.row.global_host!==1" @click="handleClickCopy(slotProps)">{{ $t('common.copy') }}</a>
<a class="t-button-link" v-if="slotProps.row.global_host!==1" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" v-if="slotProps.row.global_host!==1" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -76,159 +63,151 @@
</div>
</t-card>
<!-- 新建网站防御弹窗 -->
<!-- New WebSite Dialog -->
<t-dialog :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="header">
新建网站防御
{{ $t('page.host.website_protection') }}
<t-link theme="primary" :href="hostAddUrl" target="_blank">
<link-icon slot="prefix-icon"></link-icon>
访问SamWaf在线文档
{{ $t('common.online_document') }}
</t-link>
</div>
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="160">
<t-tabs :defaultValue="1">
<t-tab-panel :value="1" label="基础内容">
<t-form-item label="网站" name="host">
<t-tooltip class="placement top center" content="输入您需要防护的网站域名:如 www.samwaf.com" placement="top"
<t-tab-panel :value="1" :label="$t('page.host.tab_base')">
<t-form-item :label="$t('page.host.website')" name="host">
<t-tooltip class="placement top center" :content="$t('page.host.host_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-input :style="{ width: '480px' }" v-model="formData.host" placeholder="请输入网站的网址"></t-input>
<t-input :style="{ width: '480px' }" v-model="formData.host" :placeholder="$t('common.placeholder')"></t-input>
</t-tooltip>
</t-form-item>
<t-form-item label="端口" name="port">
<t-form-item :label="$t('page.host.port')" name="port">
<t-tooltip class="placement top center"
content="输入您需要防护的网站端口 1. http是80 https 是 443 2.如果已经安装了宝塔,Nginx,IIS等 您需要手工改动端口成非80,或者非443端口"
:content="$t('page.host.port_tips')"
placement="top" :overlay-style="{ width: '200px' }" show-arrow>
<t-input-number :style="{ width: '150px' }" v-model="formData.port" placeholder="请输入网站的端口一般是80/443">
<t-input-number :style="{ width: '150px' }" v-model="formData.port" :placeholder="$t('page.host.port_placeholder')">
</t-input-number>
</t-tooltip>
</t-form-item>
<t-form-item label="加密证书" name="ssl">
<t-tooltip class="placement top center" content="如果是https需要选择加密证书,80端口不需要" placement="top"
<t-form-item :label="$t('page.host.ssl')" name="ssl">
<t-tooltip class="placement top center" :content="$t('page.host.ssl_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="formData.ssl">
<t-radio value="0">非加密</t-radio>
<t-radio value="1">加密证书(需上传证书)</t-radio>
<t-radio value="0">{{ $t('page.host.ssl_option_no') }}</t-radio>
<t-radio value="1">{{ $t('page.host.ssl_option_yes') }}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="启动状态" name="start_status">
<t-tooltip class="placement top center" content="该功能是选择是否直接启动。" placement="top"
<t-form-item :label="$t('page.host.start_status')" name="start_status">
<t-tooltip class="placement top center" :content="$t('page.host.start_status_content')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="formData.start_status">
<t-radio value="0">直接启动</t-radio>
<t-radio value="1">等待人工启动</t-radio>
<t-radio value="0">{{ $t('page.host.auto_start_on') }}</t-radio>
<t-radio value="1">{{ $t('page.host.auto_start_off') }}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="密钥串" name="keyfile" v-if="formData.ssl=='1'">
<t-form-item :label="$t('page.host.keyfile')" name="keyfile" v-if="formData.ssl=='1'">
<t-tooltip class="placement top center"
content="通常文件名:*.key 内容格式如下:-----BEGIN RSA PRIVATE KEY----- 全选复制填写进来" placement="top"
:content="$t('page.host.keyfile_content')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-textarea :style="{ width: '480px' }" v-model="formData.keyfile" placeholder="请输入内容" name="keyfile">
<t-textarea :style="{ width: '480px' }" v-model="formData.keyfile" :placeholder="$t('common.placeholder')" name="keyfile">
</t-textarea>
</t-tooltip>
</t-form-item>
<t-form-item label="证书串" name="certfile" v-if="formData.ssl=='1'">
<t-form-item :label="$t('page.host.certfile')" name="certfile" v-if="formData.ssl=='1'">
<t-tooltip class="placement top center"
content="通常文件名:*.crt 内容格式如下:-----BEGIN CERTIFICATE----- 全选复制填写进来" placement="top"
:content="$t('page.host.certfile_content')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-textarea :style="{ width: '480px' }" v-model="formData.certfile" placeholder="请输入内容"
<t-textarea :style="{ width: '480px' }" v-model="formData.certfile" :placeholder="$t('common.placeholder')"
name="certfile">
</t-textarea>
</t-tooltip>
</t-form-item>
<!--<t-form-item label="后端域名" name="remote_host">
<t-tooltip class="placement top center" content="后端域名通常同第一项网站域名相同(加上协议 http:// 或 https://)"
<t-form-item :label="$t('page.host.remote_ip')" name="remote_ip">
<t-tooltip class="placement top center" :content="$t('page.host.remote_ip_content')"
placement="top" :overlay-style="{ width: '200px' }" show-arrow>
<t-input :style="{ width: '480px' }" v-model="formData.remote_host" placeholder="请输入后端域名"></t-input>
</t-tooltip>
</t-form-item>-->
<t-form-item label="后端IP" name="remote_ip">
<t-tooltip class="placement top center" content="如SamWaf同网站在同一台服务器 填写127.0.0.1 如果是不同服务器请填写实际IP"
placement="top" :overlay-style="{ width: '200px' }" show-arrow>
<t-input :style="{ width: '480px' }" v-model="formData.remote_ip" placeholder="请输入后端IP"></t-input>
<t-input :style="{ width: '480px' }" v-model="formData.remote_ip" :placeholder="$t('common.placeholder')+$t('page.host.remote_ip')"></t-input>
</t-tooltip>
</t-form-item>
<t-form-item label="后端端口" name="remote_port">
<t-form-item :label="$t('page.host.remote_port')" name="remote_port">
<t-tooltip class="placement top center"
content="情况1,在SamWaf和网站在同一台服务器,那么端口需要写成81等其他端口 情况2:如果不在同一台服务器,那么此处可以原来端口" placement="top"
:content="$t('page.host.remote_port_content')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-input-number :style="{ width: '150px' }" v-model="formData.remote_port"
placeholder="请输入网站的端口一般是80/443">
:placeholder="$t('page.host.port_placeholder')">
</t-input-number>
</t-tooltip>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" :placeholder="$t('common.placeholder_content')" name="remarks">
</t-textarea>
</t-form-item>
</t-tab-panel>
<t-tab-panel :value="2">
<template #label>
<file-safety-icon style="margin-right: 4px;color:red"/>
引擎自带防护
{{$t('page.host.tab_engine')}}
</template>
<t-form-item label="Bot检测">
<t-tooltip class="placement top center" content="检测搜索引擎是否是伪装的" placement="top"
<t-form-item :label="$t('page.host.bot_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.bot_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.bot">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="Sql注入检测">
<t-tooltip class="placement top center" content="检测是否存在sql注入" placement="top"
<t-form-item :label="$t('page.host.sql_injection_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.sql_injection_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.sqli">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="XSS检测">
<t-tooltip class="placement top center" content="检测是否存在xss攻击" placement="top"
<t-form-item :label="$t('page.host.xss_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.xss_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.xss">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="扫描工具检测">
<t-tooltip class="placement top center" content="扫描工具检测" placement="top"
<t-form-item :label="$t('page.host.scan_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.scan_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.scan">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="RCE检测">
<t-tooltip class="placement top center" content="RCE远程攻击检测" placement="top"
<t-form-item :label="$t('page.host.rce_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.rce_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.rce">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
</t-tab-panel>
<t-tab-panel :value="3">
<template #label>
其他配置
{{$t('page.host.tab_other')}}
</template>
<t-form-item label="日时排除URL" name="exclude_url_log">
<t-tooltip class="placement top center" content="记录日志时排除URL开头的数据" placement="top"
<t-form-item :label="$t('page.host.exclude_url_log')" name="exclude_url_log">
<t-tooltip class="placement top center" :content="$t('page.host.exclude_url_log_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-textarea :style="{ width: '480px' }" v-model="formData.exclude_url_log" placeholder="请输入内容"
<t-textarea :style="{ width: '480px' }" v-model="formData.exclude_url_log" :placeholder="$t('common.placeholder')"
name="exclude_url_log">
</t-textarea>
</t-tooltip>
@@ -237,63 +216,53 @@
</t-tabs>
<t-form-item style="float: right;margin-top:5px">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑网站防御弹窗 -->
<t-dialog header="编辑网站防御" :visible.sync="editFormVisible" :width="680" :footer="false">
<!-- Edit WebSite Dialog -->
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="160">
<t-tabs :defaultValue="1">
<t-tab-panel :value="1" label="基础内容">
<t-form-item label="网站" name="host">
<t-input :style="{ width: '480px' }" v-model="formEditData.host" placeholder="请输入网站的网址" disabled></t-input>
<t-tab-panel :value="1" :label="$t('page.host.tab_base')">
<t-form-item :label="$t('page.host.website')" name="host">
<t-input :style="{ width: '480px' }" v-model="formEditData.host" :content="$t('page.host.host_tips')" disabled></t-input>
</t-form-item>
<t-form-item label="端口" name="port">
<t-input-number :style="{ width: '150px' }" v-model="formEditData.port" placeholder="请输入网站的端口一般是80/443">
<t-form-item :label="$t('page.host.port')" name="port">
<t-input-number :style="{ width: '150px' }" v-model="formEditData.port" :content="$t('page.host.port_tips')">
</t-input-number>
</t-form-item>
<t-form-item label="加密证书" name="ssl">
<t-form-item :label="$t('page.host.ssl')" name="ssl">
<t-radio-group v-model="formEditData.ssl">
<t-radio value="0">非加密</t-radio>
<t-radio value="1">加密证书(需填写证书)</t-radio>
<t-radio value="0">{{ $t('page.host.ssl_option_no') }}</t-radio>
<t-radio value="1">{{ $t('page.host.ssl_option_yes') }}</t-radio>
</t-radio-group>
</t-form-item>
<!--<t-form-item label="启动状态" name="start_status">
<t-radio-group v-model="formEditData.start_status">
<t-radio value="0">直接启动</t-radio>
<t-radio value="1">等待人工启动</t-radio>
</t-radio-group>
</t-form-item>-->
<t-form-item label="密钥串" name="keyfile" v-if="formEditData.ssl=='1'">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.keyfile" placeholder="请输入内容"
<t-form-item :label="$t('page.host.keyfile')" name="keyfile" v-if="formEditData.ssl=='1'">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.keyfile" :placeholder="$t('common.placeholder')"
name="keyfile">
</t-textarea>
</t-form-item>
<t-form-item label="证书串" name="certfile" v-if="formEditData.ssl=='1'">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.certfile" placeholder="请输入内容"
<t-form-item :label="$t('page.host.certfile')" name="certfile" v-if="formEditData.ssl=='1'">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.certfile" :placeholder="$t('common.placeholder')"
name="certfile">
</t-textarea>
</t-form-item>
<!--<t-form-item label="后端域名" name="remote_host">
<t-input :style="{ width: '480px' }" v-model="formEditData.remote_host" placeholder="请输入后端域名"></t-input>
</t-form-item>-->
<t-form-item label="后端IP" name="remote_ip">
<t-input :style="{ width: '480px' }" v-model="formEditData.remote_ip" placeholder="请输入后端IP"></t-input>
<t-form-item :label="$t('page.host.remote_ip')" name="remote_ip">
<t-input :style="{ width: '480px' }" v-model="formEditData.remote_ip" :placeholder="$t('common.placeholder')+$t('page.host.remote_ip')"></t-input>
</t-form-item>
<t-form-item label="后端端口" name="remote_port">
<t-form-item :label="$t('page.host.remote_port')" name="remote_port">
<t-input-number :style="{ width: '150px' }" v-model="formEditData.remote_port"
placeholder="请输入网站的端口一般是80/443"></t-input-number>
:placeholder="$t('page.host.port_placeholder')"></t-input-number>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容"
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" :placeholder="$t('common.placeholder_content')"
name="remarks">
</t-textarea>
</t-form-item>
@@ -302,66 +271,66 @@
<t-tab-panel :value="2">
<template #label>
<file-safety-icon style="margin-right: 4px;color:red"/>
引擎自带防护
{{$t('page.host.tab_engine')}}
</template>
<t-form-item label="Bot检测">
<t-tooltip class="placement top center" content="检测搜索引擎是否是伪装的" placement="top"
<t-form-item :label="$t('page.host.bot_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.bot_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.bot">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="Sql注入检测">
<t-tooltip class="placement top center" content="检测是否存在sql注入" placement="top"
<t-form-item :label="$t('page.host.sql_injection_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.sql_injection_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.sqli">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="XSS检测">
<t-tooltip class="placement top center" content="检测是否存在xss攻击" placement="top"
<t-form-item :label="$t('page.host.xss_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.xss_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.xss">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="扫描工具检测">
<t-tooltip class="placement top center" content="扫描工具检测" placement="top"
<t-form-item :label="$t('page.host.scan_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.scan_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.scan">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
<t-form-item label="RCE检测">
<t-tooltip class="placement top center" content="RCE远程攻击检测" placement="top"
<t-form-item :label="$t('page.host.rce_detection')">
<t-tooltip class="placement top center" :content="$t('page.host.rce_detection_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-radio-group v-model="hostDefenseData.rce">
<t-radio value="0">关闭</t-radio>
<t-radio value="1">开启</t-radio>
<t-radio value="0">{{$t('common.off')}}</t-radio>
<t-radio value="1">{{$t('common.on')}}</t-radio>
</t-radio-group>
</t-tooltip>
</t-form-item>
</t-tab-panel>
<t-tab-panel :value="3">
<template #label>
其他配置
{{$t('page.host.tab_other')}}
</template>
<t-form-item label="日时排除URL" name="exclude_url_log">
<t-tooltip class="placement top center" content="记录日志时排除URL开头的数据" placement="top"
<t-form-item :label="$t('page.host.exclude_url_log')" name="exclude_url_log">
<t-tooltip class="placement top center" :content="$t('page.host.exclude_url_log_tips')" placement="top"
:overlay-style="{ width: '200px' }" show-arrow>
<t-textarea :style="{ width: '480px' }" v-model="formEditData.exclude_url_log" placeholder="请输入内容"
<t-textarea :style="{ width: '480px' }" v-model="formEditData.exclude_url_log" :placeholder="$t('common.placeholder')"
name="exclude_url_log">
</t-textarea>
</t-tooltip>
@@ -369,33 +338,33 @@
</t-tab-panel>
</t-tabs>
<t-form-item style="float: right;margin-top:5px">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选网站?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
<t-dialog :visible.sync="ImportXlsxVisible" @confirm="ImportXlsxVisible=false">
<t-upload :action="fileUploadUrl" :tips="tips" :headers="fileHeader" v-model="files" @fail="handleFail"
@success="onSuccess" theme="file-input" placeholder="未选择文件"></t-upload>
@success="onSuccess" theme="file-input" :placeholder="$t('page.host.upload_tips')"></t-upload>
</t-dialog>
<t-dialog header="防护状态提示" :visible.sync="guardConfirmVisible" @confirm="onGuardStatusConfirm"
<t-dialog :header="$t('page.host.guard_status_confirm')" :visible.sync="guardConfirmVisible" @confirm="onGuardStatusConfirm"
:onCancel="onGuardStatusCancel">
<div slot="body">
<div>防护状态【开启】,该网站进行实时防护。防护状态【关闭】,该网站会关闭实时防护。</div>
<div>{{$t('page.host.guard_status_confirm_content')}}</div>
</div>
</t-dialog>
<t-dialog header="启动状态提示" :visible.sync="startConfirmVisible" @confirm="onStartStatusConfirm"
<t-dialog :header="$t('page.host.start_status_confirm')" :visible.sync="startConfirmVisible" @confirm="onStartStatusConfirm"
:onCancel="onStartStatusCancel">
<div>启动状态【开启】会正常接收用户请求。 启动状态【关闭】会停止用户请求</div>
<div>{{$t('page.host.start_status_confirm_content')}}</div>
</t-dialog>
</div>
</template>
@@ -442,7 +411,7 @@ export default Vue.extend({
data() {
return {
files: [],
tips: '上传文件大小在 5M 以内',
tips: this.$t('page.host.upload_file_limit_size'),
baseUrl: "",
fileUploadUrl: "",
fileHeader: {},
@@ -468,66 +437,62 @@ export default Vue.extend({
rules: {
host: [{
required: true,
message: '请输入网站名称',
message: this.$t('common.placeholder'+this.$t('page.host.host')),
type: 'error'
}],
port: [{
required: true,
message: '请输入网站端口',
message: this.$t('common.placeholder'+this.$t('page.host.port')),
type: 'error'
}],
remote_ip: [{
required: true,
message: '请输入远端IP',
message: this.$t('common.placeholder'+this.$t('page.host.remote_ip')),
type: 'error'
}],
remote_port: [{
required: true,
message: '请输入远端端口',
message: this.$t('common.placeholder'+this.$t('page.host.remote_port')),
type: 'error'
}],
},
remote_system_options: [{
label: '宝塔',
label: this.$t('page.host.back_system_type_baota'),
value: '1'
},
{
label: '小皮面板(phpstudy)',
label: this.$t('page.host.back_system_type_phpstudy'),
value: '2'
},
{
label: 'PHPnow',
label: this.$t('page.host.back_system_type_phpnow'),
value: '3'
},
{
label: '默认',
label: this.$t('page.host.back_system_type_default'),
value: '4'
},
],
remote_app_options: [{
label: '纯网站',
label: this.$t('page.host.back_system_biz_website'),
value: '1'
},
{
label: 'API业务系统',
label: this.$t('page.host.back_system_biz_api'),
value: '2'
},
{
label: '业务加管理',
label: this.$t('page.host.back_system_biz_mange'),
value: '3'
},
{
label: '默认',
label: this.$t('page.host.back_system_biz_default'),
value: '4'
},
],
GUARD_STATUS,
SSL_STATUS,
START_STATUS,
CONTRACT_STATUS,
CONTRACT_STATUS_OPTIONS,
CONTRACT_TYPES,
CONTRACT_PAYMENT_TYPES,
prefix,
dataLoading: false,
data: [], //列表数据信息
@@ -536,20 +501,20 @@ export default Vue.extend({
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.host.host'),
align: 'left',
width: 200,
ellipsis: true,
colKey: 'host',
},
{
title: '网站端口',
title: this.$t('page.host.port'),
width: 100,
ellipsis: true,
colKey: 'port',
},
{
title: '启动状态',
title: this.$t('page.host.start_status'),
colKey: 'start_status',
width: 100,
cell: {
@@ -557,7 +522,7 @@ export default Vue.extend({
}
},
{
title: '防护状态',
title: this.$t('page.host.guard_status'),
colKey: 'guard_status',
width: 100,
cell: {
@@ -565,7 +530,7 @@ export default Vue.extend({
}
},
{
title: '加密证书',
title:this.$t('page.host.ssl'),
width: 100,
ellipsis: true,
colKey: 'ssl',
@@ -574,13 +539,13 @@ export default Vue.extend({
}
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -590,7 +555,7 @@ export default Vue.extend({
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -598,7 +563,6 @@ export default Vue.extend({
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -631,7 +595,7 @@ export default Vue.extend({
const {
host
} = this.data?.[this.deleteIdx];
return `删除后,${host}的所有网站信息和规则将被清空,且无法恢复`;
return $t('page.host.delete_confirm_clear_relation');
}
return '';
},
@@ -708,7 +672,6 @@ export default Vue.extend({
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -720,7 +683,6 @@ export default Vue.extend({
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail(e) {
console.log(e)
@@ -742,7 +704,7 @@ export default Vue.extend({
code, global_host
} = e.row
if (global_host === 1) {
this.$message.warning("全局网站不能操作");
this.$message.warning(this.$t('page.host.forbid_for_global_site'));
return
}
console.log(code)
@@ -783,7 +745,7 @@ export default Vue.extend({
code, global_host
} = e.row
if (global_host === 1) {
this.$message.warning("全局网站只能配置保护状态");
this.$message.warning(this.$t('page.host.forbid_for_global_site_only_change_guard_status'));
return
}
console.log(code)
@@ -791,7 +753,6 @@ export default Vue.extend({
this.getDetail(code)
},
handleAddHost() {
//添加host
this.addFormVisible = true
},
onSubmit({
@@ -806,7 +767,7 @@ export default Vue.extend({
}
postdata.host = postdata.host.toLowerCase();
if (postdata.host.indexOf("http://") >=0 || postdata.host.indexOf("https://") >=0) {
that.$message.warning("主机请不要填写http和https 直接写域名即可");
that.$message.warning(this.$t('page.host.host_rule_msg'));
return
}
postdata.remote_host = "http://" + postdata.host
@@ -3,29 +3,28 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddIpWhite"> 新建白名单IP </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddIpWhite"> {{ $t('page.ipallow.button_add_ip') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{ $t('page.ipallow.label_website') }}</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>Ip:</span>
<t-input v-model="searchformData.ip" class="search-input" placeholder="请输入" clearable>
<t-input v-model="searchformData.ip" class="search-input" :placeholder="$t('common.placeholder')" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf防护墙会忽略在白名单内的IP" close>
<t-alert theme="info" :message="$t('page.ipallow.alert_message')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -39,8 +38,8 @@
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -49,12 +48,11 @@
</div>
</t-card>
<!-- 新建白名单IP弹窗 -->
<t-dialog header="新建IP白名单" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.ipallow.label_website')" name="host_code">
<t-select v-model="formData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -62,27 +60,25 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="IP" name="ip">
<t-input :style="{ width: '480px' }" v-model="formData.ip" placeholder="请输入白名单IP"></t-input>
<t-form-item :label="$t('page.ipallow.label_ip')" name="ip">
<t-input :style="{ width: '480px' }" v-model="formData.ip" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑IP白名单弹窗 -->
<t-dialog header="编辑IP白名单" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.ipallow.label_website')" name="host_code">
<t-select v-model="formEditData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -90,22 +86,22 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="IP" name="ip">
<t-input :style="{ width: '480px' }" v-model="formEditData.ip" placeholder="请输入白名单IP"></t-input>
<t-form-item :label="$t('page.ipallow.label_ip')" name="ip">
<t-input :style="{ width: '480px' }" v-model="formEditData.ip"></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选IP?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -161,12 +157,12 @@
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
message: this.$t('common.placeholder')+this.$t('page.ipallow.website'),
type: 'error'
}],
ip: [{
required: true,
message: '请输入IP',
message: this.$t('common.placeholder')+this.$t('page.ipallow.ip'),
type: 'error'
}],
},
@@ -179,7 +175,7 @@
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.ipallow.website'),
align: 'left',
width: 250,
ellipsis: true,
@@ -187,19 +183,19 @@
fixed: 'left',
},
{
title: 'IP',
title: this.$t('page.ipallow.ip'),
width: 200,
ellipsis: true,
colKey: 'ip',
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -210,7 +206,7 @@
fixed: 'right',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -242,7 +238,7 @@
const {
host
} = this.data?. [this.deleteIdx];
return `确认要删除吗?`;
return this.$t('common.data_delete_warning');
}
return '';
},
@@ -306,7 +302,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -318,7 +313,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
console.log(e)
@@ -330,7 +324,6 @@
this.getDetail(id)
},
handleAddIpWhite() {
//添加白名单IP
this.addFormVisible = true
this.formData = {
host_code: '',
@@ -472,7 +465,6 @@
})
.finally(() => {});
},
//跳转界面
handleJumpOnlineUrl(){
window.open(this.samwafglobalconfig.getOnlineUrl()+"/guide/IPWhite.html");
},
@@ -483,16 +475,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
+33 -55
View File
@@ -3,30 +3,28 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddipblock"> 新建黑名单IP </t-button>
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddipblock"> {{ $t('page.ipblock.button_add_ip') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{ $t('page.ipblock.label_website') }}: </span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>Ip:</span>
<t-input v-model="searchformData.ip" class="search-input" placeholder="请输入" clearable>
<t-input v-model="searchformData.ip" class="search-input" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf防护墙会阻止在黑名单内的IP的访问" close>
<t-alert theme="info" :message="$t('page.ipblock.alert_message')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -40,8 +38,8 @@
<span> {{host_dic[row.host_code]}}</span>
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -50,12 +48,10 @@
</div>
</t-card>
<!-- 新建黑名单IP弹窗 -->
<t-dialog header="新建IP黑名单" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.ipblock.label_website')" name="host_code">
<t-select v-model="formData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -63,27 +59,25 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="IP" name="ip">
<t-input :style="{ width: '480px' }" v-model="formData.ip" placeholder="请输入黑名单IP"></t-input>
<t-form-item :label="$t('page.ipblock.label_ip')" name="ip">
<t-input :style="{ width: '480px' }" v-model="formData.ip" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑IP黑名单弹窗 -->
<t-dialog header="编辑IP黑名单" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header=" $t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.ipblock.label_website')" name="host_code">
<t-select v-model="formEditData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -91,22 +85,22 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="IP" name="ip">
<t-input :style="{ width: '480px' }" v-model="formEditData.ip" placeholder="请输入黑名单IP"></t-input>
<t-form-item :label="$t('page.ipblock.label_ip')" name="ip">
<t-input :style="{ width: '480px' }" v-model="formEditData.ip" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选IP?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -150,7 +144,6 @@
return {
addFormVisible: false,
editFormVisible: false,
guardVisible: false,
confirmVisible: false,
formData: {
...INITIAL_DATA
@@ -161,12 +154,12 @@
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
message: this.$t('common.placeholder')+this.$t('page.ipblock.label_website'),
type: 'error'
}],
ip: [{
required: true,
message: '请输入IP',
message: this.$t('common.placeholder')+this.$t('page.ipblock.label_ip'),
type: 'error'
}],
},
@@ -179,26 +172,26 @@
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.ipblock.label_website'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'host_code',
},
{
title: 'IP',
title: this.$t('page.ipblock.label_ip'),
width: 200,
ellipsis: true,
colKey: 'ip',
},
{
title: '备注',
title:this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -208,7 +201,7 @@
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -216,7 +209,6 @@
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -240,7 +232,7 @@
const {
host
} = this.data?. [this.deleteIdx];
return `确认要删除吗?`;
return this.$t('common.data_delete_warning');
}
return '';
},
@@ -303,7 +295,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -327,7 +318,6 @@
this.getDetail(id)
},
handleAddipblock() {
//添加黑名单IP
this.addFormVisible = true
this.formData = {
host_code: '',
@@ -472,7 +462,6 @@
})
.finally(() => {});
},
//跳转界面
handleJumpOnlineUrl(){
window.open(this.samwafglobalconfig.getOnlineUrl()+"/guide/IPBlack.html");
},
@@ -482,17 +471,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
+41 -51
View File
@@ -3,29 +3,28 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddLdpUrl"> 新建隐私保护Url </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddLdpUrl"> {{ $t('page.ldpurl.new_privacy_url') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{$t('page.ldpurl.label_website')}}:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>URL:</span>
<t-input v-model="searchformData.url" class="search-input" placeholder="请输入" clearable>
<span>{{$t('page.ldpurl.label_url')}}:</span>
<t-input v-model="searchformData.url" class="search-input" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf用户在访问指定的url返回的敏感数据脱敏处理,如手机号会隐藏部分" close>
<t-alert theme="info" :message="$t('page.ldpurl.alert_message')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -33,14 +32,12 @@
:pagination="pagination" :selected-row-keys="selectedRowKeys" :loading="dataLoading"
@page-change="rehandlePageChange" @change="rehandleChange" @select-change="rehandleSelectChange"
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
<template #host_code="{ row }">
<span> {{host_dic[row.host_code]}}</span>
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -49,12 +46,10 @@
</div>
</t-card>
<!-- 新建隐私保护Url弹窗 -->
<t-dialog header="新建Url隐私保护" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.ldpurl.label_website')" name="host_code">
<t-select v-model="formData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -62,7 +57,7 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="匹配方式" name="compare_type">
<t-form-item :label="$t('page.ldpurl.label_compare_type')" name="compare_type">
<t-select v-model="formData.compare_type" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in compare_type_options" :value="item.value" :label="item.label"
:key="index">
@@ -70,27 +65,25 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" placeholder="请输入隐私保护Url"></t-input>
<t-form-item :label="$t('page.ldpurl.label_url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('page.ldpurl.label_remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑Url隐私保护弹窗 -->
<t-dialog header="编辑Url隐私保护" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.ldpurl.label_website')" name="host_code">
<t-select v-model="formEditData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -98,7 +91,7 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="匹配方式" name="compare_type">
<t-form-item :label="$t('page.ldpurl.label_compare_type')" name="compare_type">
<t-select v-model="formEditData.compare_type" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in compare_type_options" :value="item.value" :label="item.label"
:key="index">
@@ -106,22 +99,22 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" placeholder="请输入隐私保护Url"></t-input>
<t-form-item :label="$t('page.ldpurl.label_url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('page.ldpurl.label_remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选Url?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -175,31 +168,31 @@
...INITIAL_DATA
},
compare_type_options: [{
label: '等于',
label: this.$t('page.ldpurl.compare_type_option_equal'),
value: '等于'
},
{
label: '前缀匹配',
label: this.$t('page.ldpurl.compare_type_option_pre'),
value: '前缀匹配'
},
{
label: '后缀匹配',
label: this.$t('page.ldpurl.compare_type_option_end'),
value: '后缀匹配'
},
{
label: '包含匹配',
label: this.$t('page.ldpurl.compare_type_option_contain'),
value: '包含匹配'
},
],
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
message: this.$t('common.placeholder')+this.$t('page.ldpurl.label_website'),
type: 'error'
}],
url: [{
required: true,
message: '请输入url',
message: this.$t('common.placeholder')+this.$t('page.ldpurl.label_url'),
type: 'error'
}],
},
@@ -212,32 +205,32 @@
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.ldpurl.label_website'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'host_code',
},{
title: '匹配方式',
title: this.$t('page.ldpurl.label_compare_type'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'compare_type',
},
{
title: 'Url',
title:this.$t('page.ldpurl.label_url'),
width: 200,
ellipsis: true,
colKey: 'url',
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -247,7 +240,7 @@
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -255,7 +248,6 @@
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -279,7 +271,7 @@
const {
url
} = this.data?. [this.deleteIdx];
return `确认是否要删除吗?`;
return this.$t('common.confirm_delete');
}
return '';
},
@@ -342,7 +334,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -354,7 +345,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
console.log(e)
-219
View File
@@ -1,219 +0,0 @@
<template>
<div>
<t-card class="list-card-container">
<t-alert theme="info" message="SamWaf授权针对大量服务器集中管理用户 仅管控中心端需要注册。如有疑问请联系samwafgo@gmail.com" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
</template>
</t-alert>
<t-row >
<div>
<t-row><h1>授权信息</h1></t-row>
<t-row v-if="regData.username !=''">
<t-col :span="6">授权版本号:</t-col> <t-col :span="6">{{ regData.version }}</t-col>
<t-col :span="6">授权用户编码:</t-col> <t-col :span="6">{{ regData.username }}</t-col>
<t-col :span="6">授权类型:</t-col> <t-col :span="6">{{ regData.member_type }}</t-col>
<t-col :span="6">授权机器码:</t-col> <t-col :span="6">{{ regData.machine_id }}</t-col>
<t-col :span="6">授权截至日期:</t-col> <t-col :span="6">{{ regData.expiry_date }}</t-col>
<t-col> <t-button variant="outline" @click="HandleImportLicense">
<cloud-upload-icon slot="icon" />
重新上传文件验证
</t-button>
</t-col>
</t-row>
<t-row v-if="regData.username ==''">
<t-col :span="6">授权类型:</t-col> <t-col :span="6">免费版</t-col>
<t-col :span="6">授权机器码:</t-col> <t-col :span="6">{{ clientData.machine_id }}</t-col>
<t-col :span="6">授权数量:</t-col> <t-col :span="6">3台 </t-col>
<t-col> <t-button variant="outline" @click="HandleImportLicense">
<cloud-upload-icon slot="icon" />
上传文件
</t-button>
</t-col>
</t-row>
</div>
</t-row>
</t-card>
<!-- 导入授权文件弹窗 -->
<t-dialog header="导入授权文件" :visible.sync="importLicenseFormVisible" @confirm="loadConfirmLicense">
<t-upload :action="fileUploadUrl" :tips="tips" :headers="fileHeader" v-model="files" @fail="handleFail"
@success="onSuccess" theme="file-input" placeholder="未选择文件"></t-upload>
</t-dialog>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import {getLicenseDetailApi,confirmLicenseApi} from '@/apis/license';
import {AesDecrypt, getBaseUrl} from "../../../utils/usuallytool";
import {
CloudUploadIcon
} from 'tdesign-icons-vue';
const INITIAL_REG_DATA = {
version: '',
username: '',
member_type: '',
machine_id: '',
expiry_date: '',
is_expiry:false,
};
const INITIAL_CLIENT_DATA = {
version: '',
machine_id: '',
};
export default Vue.extend({
name: 'ListBase',
components: { CloudUploadIcon,},
data() {
return {
importLicenseFormVisible: false,
regData: {
...INITIAL_REG_DATA
},
clientData: {
...INITIAL_CLIENT_DATA
},
files: [],
tips: '上传文件大小在 5M 以内',
baseUrl: "",
fileUploadUrl: "",
fileHeader: {},
};
},
computed: {
offsetTop() {
return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
},
},
mounted() {
this.baseUrl = getBaseUrl()
this.fileUploadUrl = this.baseUrl + "/license/checklicense"
this.fileHeader['X-Token'] = localStorage.getItem("access_token") ? localStorage.getItem("access_token") : "" //此处换成自己获取回来的token,通常存在在cookie或者store里面
this.loadCurrentLicense()
},
methods: {
/**
* 发送邮件
**/
sendMail(){
const email = 'samwafgo@gmail.com'; // 设置收件人地址
window.location.href = `mailto:${email}`;
},
handleFail({file}) {
this.$message.error(`文件 ${file.name} 上传失败`);
},
onSuccess(e) {
console.log('license upload1', e.response)
let data = e.response
console.log('license upload2', data)
if (data.code === 0) {
this.$message.success(data.msg);
this.tips = data.msg;
}else{
this.files = []
this.$message.warning(data.msg);
}
this.loadCurrentLicense()
},
//确认上传的文件
loadConfirmLicense() {
let that = this
confirmLicenseApi({})
.then((res) => {
let resdata = res
console.log(resdata)
if (resdata.code === 0) {
that.regData = resdata.data.license;
that.clientData.machine_id = resdata.data.machine_id;
that.clientData.version = resdata.data.version;
that.$message.success(resdata.msg);
that.importLicenseFormVisible=false
}else{
that.$message.warning(resdata.msg);
}
})
.catch((e: Error) => {
console.log(e);
})
.finally(() => {
});
},
/**加载当前授权信息**/
loadCurrentLicense() {
let that = this
getLicenseDetailApi({})
.then((res) => {
let resdata = res
console.log(resdata)
if (resdata.code === 0) {
that.regData = resdata.data.license;
that.clientData.machine_id = resdata.data.machine_id;
that.clientData.version = resdata.data.version;
}
})
.catch((e: Error) => {
console.log(e);
})
.finally(() => {
});
},
/**
* 导入授权数据
*/
HandleImportLicense() {
this.importLicenseFormVisible = true
this.tips = ""
this.files = []
},
getContainer() {
return document.querySelector('.tdesign-starter-layout');
},
//跳转界面
handleJumpOnlineUrl() {
window.open(this.samwafglobalconfig.getOnlineUrl() + "/guide/License.html");
},
},
});
</script>
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
.selected-count {
display: inline-block;
margin-left: 8px;
color: var(--td-text-color-secondary);
}
}
.search-input {
width: 360px;
}
.t-button + .t-button {
margin-left: @spacer;
}
</style>
+23 -55
View File
@@ -4,30 +4,28 @@
<t-row justify="space-between">
<div class="left-operation-container">
由于单台服务器只能一个程序使用Web(80端口,443端口),所以如果需要让Waf变为前置,那么此处需要将80=》81 ,443=》444。
SamWaf为了方便用户部署,新增一键修改宝塔Web端口。仅在Linux下可使用。
{{ $t('page.one_key_mod.one_key_placeholder')}}
<span>宝塔Nginx配置默认路径:</span>
<t-input v-model="defaultFilePath" class="search-input" placeholder="请输入宝塔默认路径" clearable>
<span>{{ $t('page.one_key_mod.baota_placeholder') }}:</span>
<t-input v-model="defaultFilePath" class="search-input" :placeholder="$t('page.one_key_mod.baota_placeholder')" clearable>
</t-input>
<t-button @click="handleOneKeyModify"> 一键修改 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleOneKeyModify"> {{ $t('page.on_key_mod.button_one_key_modify') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf一键修改记录" close>
<t-alert theme="info" :message="$t('page.one_key_mod.modify_logs')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -37,8 +35,8 @@
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">查看</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{$t('common.details')}}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{$t('common.delete')}}</a>
</template>
</t-table>
</div>
@@ -48,33 +46,31 @@
</t-card>
<!-- 编辑弹窗 -->
<t-dialog header="查看" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.details')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :labelWidth="100">
<t-form-item label="系统类型" name="op_system">
<t-form-item :label="$t('page.one_key_mod.label_op_system')" name="op_system">
<t-input :style="{ width: '480px' }" v-model="formEditData.op_system" placeholder=""></t-input>
</t-form-item>
<t-form-item label="文件路径" name="file_path">
<t-form-item :label="$t('page.one_key_mod.label_file_path')" name="file_path">
<t-input :style="{ width: '480px' }" v-model="formEditData.file_path" placeholder=""></t-input>
</t-form-item>
<t-form-item label="原始内容" name="before_content">
<t-textarea :style="{ width: '480px' }" :autosize="{ minRows: 5, maxRows: 10 }" v-model="formEditData.before_content" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('page.one_key_mod.label_before_content')" name="before_content">
<t-textarea :style="{ width: '480px' }" :autosize="{ minRows: 5, maxRows: 10 }" v-model="formEditData.before_content" name="before_content">
</t-textarea>
</t-form-item>
<t-form-item label="修改后内容" name="after_content">
<t-textarea :style="{ width: '480px' }" :autosize="{ minRows: 5, maxRows: 10 }" v-model="formEditData.after_content" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('page.one_key_mod.label_after_content')" name="after_content">
<t-textarea :style="{ width: '480px' }" :autosize="{ minRows: 5, maxRows: 10 }" v-model="formEditData.after_content" name="after_content">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选记录?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -131,21 +127,6 @@ import {
...INITIAL_DATA
},
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
type: 'error'
}],
rate: [{
required: true,
message: '请输入速率',
type: 'error'
}],
limit: [{
required: true,
message: '请输入访问次数限制',
type: 'error'
}],
},
textareaValue: '',
prefix,
@@ -156,20 +137,20 @@ import {
value: 'first',
columns: [
{
title: '系统',
title: this.$t('page.one_key_mod.label_op_system'),
align: 'left',
width: 60,
ellipsis: true,
colKey: 'op_system',
},
{
title: '文件路径',
title: this.$t('page.one_key_mod.label_file_path'),
width: 450,
ellipsis: true,
colKey: 'file_path',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 130,
ellipsis: true,
colKey: 'create_time',
@@ -179,7 +160,7 @@ import {
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -211,7 +192,7 @@ import {
const {
url
} = this.data?. [this.deleteIdx];
return `确认要删除吗?`;
return this.$t('common.confirm_delete');
}
return '';
},
@@ -257,7 +238,6 @@ import {
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -269,7 +249,6 @@ import {
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
console.log(e)
@@ -380,17 +359,6 @@ import {
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
+92 -92
View File
@@ -1,18 +1,18 @@
<template>
<div class="detail-base">
<t-alert theme="info" message="推荐从(日志详情)里面一键选择特征值自动编辑防御脚本 " close>
<t-alert theme="info" :message="$t('page.rule.detail.recommend_message') " close>
<template #operation>
<span @click="handleJumpAttackLogOperation">跳转到日志列表 </span>
<span @click="handleJumpOnlineUrl"> 防御规则在线文档Online</span>
<span @click="handleJumpAttackLogOperation">{{ $t('page.rule.detail.jump_visit_log') }} </span>
<span @click="handleJumpOnlineUrl"> {{ $t('page.rule.detail.jump_visit_log') }} </span>
</template>
</t-alert>
<t-form :data="formData" @submit="onSubmit"> <!--:rules="rules"-->
<!--基本信息 开始-->
<t-card title="基本信息">
<t-form-item label="规则名称" name="rule_name">
<t-input placeholder="请输入内容" v-model="formData.rule_base.rule_name" />
<t-form :data="formData" @submit="onSubmit" :labelWidth="180">
<!--Base Info Begin-->
<t-card :title="$t('page.rule.detail.base_info')">
<t-form-item :label="$t('page.rule.detail.rule_name')" name="rule_name">
<t-input :placeholder="$t('common.placeholder')" v-model="formData.rule_base.rule_name" />
</t-form-item>
<t-form-item label="防护网站" name="rule_domain_code">
<t-form-item :label="$t('page.rule.detail.rule_domain_code')" name="rule_domain_code">
<t-select v-model="formData.rule_base.rule_domain_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_options" :value="item.value" :label="item.label"
:key="index">
@@ -20,10 +20,10 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="防护级别" name="salience">
<t-input placeholder="请输入内容" v-model="formData.rule_base.salience" />
<t-form-item :label="$t('page.rule.detail.rule_salience')" name="salience">
<t-input :placeholder="$t('common.placeholder')" v-model="formData.rule_base.salience" />
</t-form-item>
<t-form-item label="防护编排方式" name="is_manual_rule">
<t-form-item :label="$t('page.rule.detail.rule_manual')" name="is_manual_rule">
<t-select :style="{ width: '480px' }" @change="changeManualRule"
v-model="formData.is_manual_rule">
<t-option v-for="(item, index) in rule_manual_option" :value="item.value" :label="item.label"
@@ -33,16 +33,16 @@
</t-select>
</t-form-item>
</t-card>
<!--基本信息 结束-->
<!--Base Info End-->
<!--手工编排-->
<!--UI Rule -->
<div v-if="formData.is_manual_rule=='0'">
<!--规则编排 开始-->
<t-card title="规则编排">
<t-card :title="$t('page.rule.detail.write_rule')">
<t-button theme="primary" @click="ruleDynAdd('cond')">
新建
{{ $t('common.new') }}
</t-button>
<t-form-item label="关系" name="relation_symbol" v-if="formData.rule_condition.relation_detail.length>1">
<t-form-item :label="$t('page.rule.detail.relation')" name="relation_symbol" v-if="formData.rule_condition.relation_detail.length>1">
<t-select clearable :style="{ width: '480px' }"
v-model="formData.rule_condition.relation_symbol">
<t-option v-for="(item, index) in relation_symbol_option" :value="item.value" :label="item.label"
@@ -51,15 +51,15 @@
</t-option>
</t-select>
</t-form-item>
<t-card title="条件" v-for="(condition_item,condition_index) in formData.rule_condition.relation_detail">
<t-card :title="$t('page.rule.detail.condition')" v-for="(condition_item,condition_index) in formData.rule_condition.relation_detail">
<t-button theme="primary" @click="ruleDynDel('cond',condition_index)">
删除
{{ $t('common.delete') }}
</t-button>
<t-row :gutter="{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }">
<t-col :span="4">
<div>
<t-form-item label="内置实体名称">
<t-form-item :label="$t('page.rule.detail.built_in_entity_name')">
<t-select clearable :style="{ width: '480px' }" v-model="condition_item.fact_name">
<t-option v-for="(item, index) in fact_option" :value="item.value" :label="item.label" :key="index">
{{ item.label }}
@@ -70,7 +70,7 @@
</t-col>
<t-col :span="4">
<div>
<t-form-item label="作用域" name="attr">
<t-form-item :label="$t('page.rule.detail.scope')" name="attr">
<t-select clearable :style="{ width: '480px' }" v-model="condition_item.attr">
<t-option v-for="(item, index) in attr_option" :value="item.value" :label="item.label" :key="index">
{{ item.label }}
@@ -81,7 +81,7 @@
</t-col>
<t-col :span="4">
<div>
<t-form-item label="值类型" name="attr_type">
<t-form-item :label="$t('page.rule.detail.value_type')" name="attr_type">
<t-select clearable :style="{ width: '480px' }" v-model="condition_item.attr_type">
<t-option v-for="(item, index) in attr_type_option" :value="item.value" :label="item.label"
:key="index">
@@ -96,7 +96,7 @@
<t-row :gutter="{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }">
<t-col :span="4">
<div>
<t-form-item label="判断" name="attr_judge">
<t-form-item :label="$t('page.rule.detail.judgment')" name="attr_judge">
<t-select clearable :style="{ width: '480px' }" v-model="condition_item.attr_judge">
<t-option v-for="(item, index) in attr_judge_option" :value="item.value" :label="item.label"
:key="index">
@@ -108,15 +108,15 @@
</t-col>
<t-col :span="4">
<div>
<t-form-item label="值" name="att_val">
<t-form-item :label="$t('page.rule.detail.value')" name="att_val">
<t-input placeholder="请输入内容" v-model="condition_item.attr_val" />
</t-form-item>
</div>
</t-col>
<t-col :span="4">
<div>
<t-form-item label="函数判断结果" name="att_val2">
<t-input placeholder="请输入函数返回值" v-model="condition_item.attr_val2" />
<t-form-item :label="$t('page.rule.detail.function_judgment_result')" name="att_val2">
<t-input :placeholder="$t('common.placeholder')+$t('page.rule.detail.function_judgment_result')" v-model="condition_item.attr_val2" />
</t-form-item>
</div>
</t-col>
@@ -127,21 +127,21 @@
<!--规则编排 结束-->
<!--符合则执行部分 开始-->
<t-card title="符合则执行如下">
<t-card :title="$t('page.rule.detail.assignment_area')">
<!--赋值总区块 开始-->
<t-card title="赋值">
<t-card :title="$t('page.rule.detail.assignment')">
<t-button theme="primary" @click="ruleDynAdd('assignment')">
新建
{{ $t('common.new') }}
</t-button>
<t-card title="赋值明细" v-for="(do_assignment_item,assignment_index) in formData.rule_do_assignment">
<t-card :title="$t('page.rule.detail.assignment_detail')" v-for="(do_assignment_item,assignment_index) in formData.rule_do_assignment">
<t-button theme="primary" @click="ruleDynDel('assignment',assignment_index)">
删除
{{ $t('common.delete') }}
</t-button>
<t-row :gutter="{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }">
<t-col :span="4">
<div>
<t-form-item label="内置实体名称">
<t-form-item :label="$t('page.rule.detail.built_in_entity_name')">
<t-select clearable :style="{ width: '480px' }" v-model="do_assignment_item.fact_name">
<t-option v-for="(item, index) in fact_option" :value="item.value" :label="item.label"
:key="index">
@@ -153,7 +153,7 @@
</t-col>
<t-col :span="4">
<div>
<t-form-item label="作用域" name="attr">
<t-form-item :label="$t('page.rule.detail.scope')" name="attr">
<t-select clearable :style="{ width: '480px' }" v-model="do_assignment_item.attr">
<t-option v-for="(item, index) in attr_option" :value="item.value" :label="item.label"
:key="index">
@@ -165,7 +165,7 @@
</t-col>
<t-col :span="4">
<div>
<t-form-item label="值类型" name="attr_type">
<t-form-item :label="$t('page.rule.detail.value_type')" name="attr_type">
<t-select clearable :style="{ width: '480px' }" v-model="do_assignment_item.attr_type">
<t-option v-for="(item, index) in attr_type_option" :value="item.value" :label="item.label"
:key="index">
@@ -176,8 +176,8 @@
</div>
</t-col>
</t-row>
<t-form-item label="值" name="att_val">
<t-input placeholder="请输入内容" v-model="do_assignment_item.attr_val" />
<t-form-item :label="$t('page.rule.detail.value')" name="att_val">
<t-input :placeholder="$t('common.placeholder')" v-model="do_assignment_item.attr_val" />
</t-form-item>
</t-card>
@@ -185,19 +185,19 @@
<!--赋值总区块 结束-->
<!--方法执行总区块 开始-->
<t-card title="方法执行">
<t-card :title="$t('page.rule.detail.method_execution_area')">
<t-button theme="primary" @click="ruleDynAdd('method')">
新建
{{ $t('common.new') }}
</t-button>
<!--方法执行明细 开始-->
<t-card title="方法明细" v-for="(do_method_item,method_index) in formData.rule_do_method">
<t-card :title="$t('page.rule.detail.method_details')" v-for="(do_method_item,method_index) in formData.rule_do_method">
<t-button theme="primary" @click="ruleDynDel('method',method_index)">
删除
{{ $t('common.delete') }}
</t-button>
<t-row :gutter="{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }">
<t-col :span="6">
<div>
<t-form-item label="内置实体名称">
<t-form-item :label="$t('page.rule.detail.built_in_entity_name')">
<t-select clearable :style="{ width: '480px' }" v-model="do_method_item.fact_name">
<t-option v-for="(item, index) in fact_option" :value="item.value" :label="item.label"
:key="index">
@@ -209,7 +209,7 @@
</t-col>
<t-col :span="6">
<div>
<t-form-item label="内置方法名称">
<t-form-item :label="$t('page.rule.detail.inner_method')">
<t-select clearable :style="{ width: '480px' }" v-model="do_method_item.method_name">
<t-option v-for="(item, index) in method_option" :value="item.value" :label="item.label"
:key="index">
@@ -221,15 +221,15 @@
</t-col>
</t-row>
<!--传参列表明细 开始-->
<t-card title="传参">
<t-card :title="$t('page.rule.detail.parameter')">
<t-button theme="primary" @click="ruleDynAdd('parms',method_index)">
新建
{{ $t('common.new') }}
</t-button>
<t-row :gutter="{ xs: 8, sm: 16, md: 24, lg: 32, xl: 32, xxl: 40 }"
v-for="(do_method_parms_item,parms_index) in do_method_item.parms">
<t-col :span="4">
<div>
<t-form-item label="值类型" name="attr_type">
<t-form-item :label="$t('page.rule.detail.value_type')" name="attr_type">
<t-select clearable :style="{ width: '480px' }" v-model="do_method_parms_item.attr_type">
<t-option v-for="(item, index) in attr_type_option" :value="item.value" :label="item.label"
:key="index">
@@ -242,15 +242,15 @@
</t-col>
<t-col :span="4">
<div>
<t-form-item label="值" name="att_val">
<t-input placeholder="请输入内容" v-model="do_method_parms_item.attr_val" />
<t-form-item :label="$t('page.rule.detail.value')" name="att_val">
<t-input :placeholder="$t('common.placeholder')" v-model="do_method_parms_item.attr_val" />
</t-form-item>
</div>
</t-col>
<t-col :span="4">
<div>
<t-button theme="primary" @click="ruleDynDel('parms',parms_index,method_index)">
删除
{{ $t('common.delete') }}
</t-button>
</div>
</t-col>
@@ -265,11 +265,11 @@
<!--符合则执行部分 结束-->
</div>
<!--界面编排 结束-->
<!--UI Rule End-->
<!--手工编排-->
<!--Manual Rule-->
<div v-if="formData.is_manual_rule=='1'">
<t-card title="规则编排">
<t-card :title="$t('page.rule.detail.write_rule')">
<writeRule>
:valuecontent="formData.rule_content"
@edtinput="edtinput"
@@ -278,23 +278,23 @@
</t-card>
<t-collapse>
<t-collapse-panel header="系统变量">
<t-list v-for=" (item, index) in attr_option ">
<t-list-item>
<t-list-item-meta :title="item.label" :description="item.value" />
</t-list-item>
</t-list>
</t-collapse-panel>
</t-collapse>
<t-collapse>
<t-collapse-panel :header="$t('page.rule.detail.system_variable')">
<t-list v-for=" (item, index) in attr_option ">
<t-list-item>
<t-list-item-meta :title="item.label" :description="item.value" />
</t-list-item>
</t-list>
</t-collapse-panel>
</t-collapse>
</div>
<t-form-item style="margin-left: 100px">
<t-space size="10px">
<!-- type = submit,表单中的提交按钮,原生行为 -->
<t-button theme="primary" type="submit">提交</t-button>
<t-button theme="primary" type="button" @click="backPage">返回</t-button>
<t-button theme="primary" type="submit">{{ $t('common.submit') }}</t-button>
<t-button theme="primary" type="button" @click="backPage">{{ $t('common.return') }}</t-button>
</t-space>
</t-form-item>
</t-form>
@@ -328,124 +328,124 @@
prefix,
detail_data: {},
rule_manual_option: [{
label: '界面编排',
label: this.$t('page.rule.detail.ui_rule_edit'),
value: '0'
}, {
label: '手工代码编排',
label: this.$t('page.rule.detail.manual_code_rule_edit'),
value: '1'
}, ],
rules: {
rule_name: [{ required: true, message: '请输入规则名称', type: 'error' }],
rule_name: [{ required: true, message: this.$t('common.placeholder')+this.$t('page.rule.detail.rule_name'), type: 'error' }],
},
fact_option: [{
label: '默认',
label: this.$t('page.rule.detail.mf_option_default'),
value: 'MF'
}, ],
method_option: [{
label: '做动作',
label: this.$t('page.rule.detail.method_option'),
value: 'DoSomeThing'
}, ],
attr_option: [{
label: '主机',
label: this.$t('page.rule.detail.inner_option_host'),
value: 'HOST'
},
{
label: '网址',
label:this.$t('page.rule.detail.inner_option_url'),
value: 'URL'
},
{
label: '网站来路(referrer)',
label: this.$t('page.rule.detail.inner_option_referrer'),
value: 'REFERER'
},
{
label: '用户代理(User-Agent)',
label: this.$t('page.rule.detail.inner_option_user_agent'),
value: 'USER_AGENT'
},
{
label: '访问方法',
label: this.$t('page.rule.detail.inner_option_method'),
value: 'METHOD'
},
{
label: '访问COOKIES',
label: this.$t('page.rule.detail.inner_option_cookies'),
value: 'COOKIES'
},
{
label: '访问BODY',
label: this.$t('page.rule.detail.inner_option_body'),
value: 'BODY'
},
{
label: '请求端口',
label: this.$t('page.rule.detail.inner_option_port'),
value: 'PORT'
},
{
label: '访客IP',
label: this.$t('page.rule.detail.inner_option_src_ip'),
value: 'SRC_IP'
},
{
label: '访客归属国家',
label: this.$t('page.rule.detail.inner_option_country'),
value: 'COUNTRY'
},
{
label: '访客归属省份',
label: this.$t('page.rule.detail.inner_option_province'),
value: 'PROVINCE'
},{
label: '访客归属城市',
label: this.$t('page.rule.detail.inner_option_city'),
value: 'CITY'
},
],
attr_type_option: [{
label: '文本',
label: this.$t('page.rule.detail.attr_type_text'),
value: 'string'
},
{
label: '数字',
label: this.$t('page.rule.detail.attr_type_int'),
value: 'int'
},
],
attr_judge_option: [
{
label: '判断是否等于',
label: this.$t('page.rule.detail.judge_equal'),
value: '=='
},
{
label: '判断是否不等于',
label: this.$t('page.rule.detail.judge_not_equal'),
value: '!='
},
{
label: '判断是否大于',
label: this.$t('page.rule.detail.judge_greater_than'),
value: '>'
},
{
label: '判断是否小于',
label: this.$t('page.rule.detail.judge_less_than'),
value: '<'
},
{
label: '判断是否大于等于',
label: this.$t('page.rule.detail.judge_greater_than_equal'),
value: '>='
},
{
label: '判断是否小于等于',
label: this.$t('page.rule.detail.judge_less_than_equal'),
value: '<='
},
{
label: '判断包含(函数)',
label: this.$t('page.rule.detail.judge_contain'),
value: 'system.Contains'
},
{
label: '判断开头(函数)',
label: this.$t('page.rule.detail.judge_has_prefix'),
value: 'system.HasPrefix'
},
{
label: '判断结尾(函数)',
label: this.$t('page.rule.detail.judge_has_suffix'),
value: 'system.HasSuffix'
},
],
relation_symbol_option: [{
label: '并且',
label: this.$t('page.rule.detail.judge_logic_and'),
value: '&&'
},
{
label: '或者',
label: this.$t('page.rule.detail.judge_logic_or'),
value: '||'
},
],
+20 -65
View File
@@ -3,32 +3,30 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddRule"> 新建规则 </t-button>
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddRule"> {{ $t('page.rule.button_add_rule') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{ $t('page.rule.label_website') }}:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>规则名:</span>
<t-input v-model="searchformData.rule_name" class="search-input" placeholder="请输入你需要搜索的规则" clearable>
<span>{{ $t('page.rule.label_rule_name') }}:</span>
<t-input v-model="searchformData.rule_name" class="search-input" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf防御规则,可进行脚本(首选),界面编辑" close>
<t-alert theme="info" :message="$t('page.rule.alert_message')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">规则编辑在线文档</span>
<span @click="handleJumpOnlineUrl">{{$t('page.rule.rule_online_document')}}</span>
</template>
</t-alert>
<div class="table-container">
@@ -51,28 +49,13 @@
<span> {{host_dic[row.host_code]}}</span>
</template>
<template #rule_status="{ row }">
<t-tag v-if="row.rule_status === RULE_STATUS.STOPPING" theme="danger" variant="light">未生效</t-tag>
<t-tag v-if="row.rule_status === RULE_STATUS.RUNNING" theme="success" variant="light">生效</t-tag>
</template>
<template #contractType="{ row }">
<p v-if="row.contractType === CONTRACT_TYPES.MAIN">审核失败</p>
<p v-if="row.contractType === CONTRACT_TYPES.SUB">待审核</p>
<p v-if="row.contractType === CONTRACT_TYPES.SUPPLEMENT">待履行</p>
</template>
<template #paymentType="{ row }">
<p v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.PAYMENT" class="payment-col">
付款
<trend class="dashboard-item-trend" type="up" />
</p>
<p v-if="row.paymentType === CONTRACT_PAYMENT_TYPES.RECIPT" class="payment-col">
收款
<trend class="dashboard-item-trend" type="down" />
</p>
<t-tag v-if="row.rule_status === RULE_STATUS.STOPPING" theme="danger" variant="light">{{ $t('page.rule.rule_off') }}</t-tag>
<t-tag v-if="row.rule_status === RULE_STATUS.RUNNING" theme="success" variant="light">{{ $t('page.rule.rule_on') }}</t-tag>
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -81,7 +64,7 @@
<t-dialog
header="确认删除当前所选规则吗?"
:header="$t('common.confirm_delete')"
:body="confirmBody"
:visible.sync="confirmVisible"
@confirm="onConfirmDelete"
@@ -123,24 +106,10 @@ export default Vue.extend({
formData: { ...INITIAL_DATA },
formEditData: { ...INITIAL_DATA },
rules: {
host: [{ required: true, message: '请输入网站名称', type: 'error' }],
host: [{ required: true, message: this.$t('common.select_placeholder')+this.$t('page.rule.label_website'), type: 'error' }],
},
textareaValue: '',
remote_system_options: [
{ label: '宝塔', value: '1' },
{ label: '小皮面板(phpstudy)', value: '2' },
{ label: 'PHPnow', value: '3' },
],
remote_app_options: [
{ label: '纯网站', value: '1' },
{ label: 'API业务系统', value: '2' },
{ label: '业务加管理', value: '3' },
],
RULE_STATUS,
CONTRACT_STATUS,
CONTRACT_STATUS_OPTIONS,
CONTRACT_TYPES,
CONTRACT_PAYMENT_TYPES,
prefix,
dataLoading: false,
data: [], //列表数据信息
@@ -150,23 +119,23 @@ export default Vue.extend({
columns: [
{ colKey: 'row-select', type: 'multiple', width: 64, fixed: 'left' },
{
title: '网站',
title: this.$t('page.rule.label_website'),
align: 'left',
width: 200,
ellipsis: true,
colKey: 'host_code',
},
{
title: '规则名',
title: this.$t('page.rule.label_rule_name'),
align: 'left',
width: 200,
ellipsis: true,
colKey: 'rule_name',
},
{ title: '规则版本', colKey: 'rule_version', width: 70, cell: { col: 'version' } },
{ title: '规则状态', colKey: 'rule_status', width: 70, cell: { col: 'rule_status' } },
{ title: this.$t('page.rule.label_rule_version'), colKey: 'rule_version', width: 70, cell: { col: 'version' } },
{ title: this.$t('page.rule.label_rule_status'), colKey: 'rule_status', width: 70, cell: { col: 'rule_status' } },
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -175,7 +144,7 @@ export default Vue.extend({
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'rule_code',
@@ -183,7 +152,6 @@ export default Vue.extend({
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -204,7 +172,7 @@ export default Vue.extend({
confirmBody() {
if (this.deleteIdx > -1) {
const { host } = this.data?.[this.deleteIdx];
return `确认要删除吗?`;
return this.$t('common.data_delete_warning');
}
return '';
},
@@ -266,7 +234,6 @@ export default Vue.extend({
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if(this.pagination.pageSize != curr.pageSize){
this.pagination.current = 1
@@ -278,7 +245,6 @@ export default Vue.extend({
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
@@ -320,8 +286,6 @@ export default Vue.extend({
},
onConfirmDelete() {
this.confirmVisible = false;
console.log('delete',this.data)
console.log('delete',this.data[this.deleteIdx])
let {rule_code} = this.data[this.deleteIdx]
let that = this
wafRuleDelApi({ CODE: rule_code })
@@ -362,15 +326,6 @@ export default Vue.extend({
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
@@ -1,106 +0,0 @@
@import '@/style/variables.less';
.detail-base {
/deep/ .t-card {
padding: 8px;
}
/deep/ .t-card__title {
font-size: 20px;
font-weight: 500;
}
&-info-steps {
padding-top: 12px;
}
}
.info-block {
column-count: 2;
.info-item {
padding: 12px 0;
display: flex;
color: var(--td-text-color-primary);
h1 {
width: 200px;
font-weight: normal;
font-size: @font-size-base;
color: var(--td-text-color-secondary);
text-align: left;
line-height: 22px;
@media (max-width: @screen-sm-max) {
width: 100px;
}
@media (min-width: @screen-md-min) and (max-width: @screen-md-max) {
width: 120px;
}
}
span {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-left: 24px;
}
i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: @border-radius-50;
background: var(--td-success-color-5);
}
.inProgress {
color: var(--td-success-color-5);
}
.pdf {
color: var(--td-brand-color);
&:hover {
cursor: pointer;
}
}
}
}
.dialog-info-block {
.info-item {
padding: 12px 0;
display: flex;
h1 {
width: 84px;
font-family: PingFangSC-Regular;
font-size: 14px;
color: var(--td-text-color-secondary);
text-align: left;
line-height: 22px;
}
span {
margin-left: 24px;
}
i {
display: inline-block;
width: 8px;
height: 8px;
border-radius: @border-radius-50;
background: var(--td-success-color-5);
}
.green {
color: var(--td-success-color-5);
}
.blue {
color: var(--td-brand-color-8);
}
}
}
@@ -1,148 +0,0 @@
<template>
<div class="detail-base">
<t-card title="网站详情">
<div class="info-block">
<div class="info-item">
<h1> 创建时间</h1>
<span>
{{ detail_data.create_time }}
</span>
</div>
<div class="info-item">
<h1> 网站</h1>
<span>
{{ detail_data.host }}
</span>
</div>
<div class="info-item">
<h1> 网站端口</h1>
<span>
{{ detail_data.port }}
</span>
</div>
<div class="info-item">
<h1> 加密证书</h1>
<span>
{{ detail_data.ssl }}
</span>
</div>
<div class="info-item">
<h1> 后端系统类型</h1>
<span>
{{ detail_data.remote_system }}
</span>
</div>
<div class="info-item">
<h1> 后端系统应用类型</h1>
<span>
{{ detail_data.remote_app }}
</span>
</div>
<div class="info-item">
<h1> 后端域名</h1>
<span>
{{ detail_data.remote_host }}
</span>
</div>
<div class="info-item">
<h1> 后端端口</h1>
<span>
{{ detail_data.remote_port }}
</span>
</div>
</div>
</t-card>
<t-card title="最近配置记录" class="container-base-margin-top">
<t-list :split="true">
<t-list-item>
<t-list-item-meta title="请求头" :description="detail_data.header"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求用户浏览器" :description="detail_data.user_agent"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求cookies" :description="detail_data.cookies"></t-list-item-meta>
</t-list-item>
<t-list-item>
<t-list-item-meta title="请求BODY" :description="detail_data.body"></t-list-item-meta>
</t-list-item>
</t-list>
</t-card>
</div>
</template>
<script lang="ts">
import {
prefix
} from '@/config/global';
import model from '@/service/service-detail-base';
export default {
name: 'WafHostDetail',
data() {
return {
prefix,
baseInfoData: model.getBaseInfoData(),
detail_data: {}
};
},
beforeRouteUpdate(to, from) {
console.log('beforeRouteUpdate')
},
mounted() {
console.log('----mounted----')
this.getDetail(this.$route.query.code);
},
beforeCreate() {
console.log('----beforeCreate----')
},
created() {
console.log('----created----')
},
beforeMount() {
console.log('----beforeMount----')
},
beforeUpdate() {
console.log('----beforeUpdate----')
},
updated() {
console.log('----updated----')
},
watch: {
'$route.query.code'(newVal, oldVal) {
console.log('route.query.code changed', newVal, oldVal)
this.getDetail(newVal)
},
},
methods: {
getDetail(id) {
let that = this
this.$request
.get('/wafhost/host/detail', {
params: {
CODE: id,
}
})
.then((res) => {
let resdata = res
console.log(resdata)
if (resdata.code === 0) {
that.detail_data = resdata.data;
}
})
.catch((e: Error) => {
console.log(e);
})
.finally(() => {});
},
},
};
</script>
<style lang="less" scoped>
@import './index';
</style>
+14 -55
View File
@@ -3,27 +3,20 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
</div>
<t-input v-model="searchValue" class="search-input" placeholder="请输入你需要搜索的日志" clearable>
<t-input v-model="searchValue" class="search-input" :placeholder="$t('page.syslog.syslog')" clearable>
<template #suffix-icon>
<search-icon size="20px" />
</template>
</t-input>
</t-row>
<div class="table-container">
<t-table :columns="columns" :data="data" :rowKey="rowKey" :verticalAlign="verticalAlign" :hover="hover"
:pagination="pagination" :selected-row-keys="selectedRowKeys" :loading="dataLoading"
@page-change="rehandlePageChange" @change="rehandleChange" @select-change="rehandleSelectChange"
:headerAffixedTop="true" :headerAffixProps="{ offsetTop: offsetTop, container: getContainer }">
<template #op="slotProps">
<!-- <a class="t-button-link" @click="handleClickDetail(slotProps)">详情</a>-->
<a class="t-button-link" @click="handleClickEdit(slotProps)">详情</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.details') }}</a>
</template>
</t-table>
</div>
@@ -32,26 +25,24 @@
</div>
</t-card>
<!-- 编辑Url白名单弹窗 -->
<t-dialog header="查看日志" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.details')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" :labelWidth="100">
<t-form-item label="操作类型" name="op_type">
<t-input :style="{ width: '480px' }" v-model="formEditData.op_type" placeholder="请输入操作类型"></t-input>
<t-form-item :label="$t('page.syslog.label_op_type')" name="op_type">
<t-input :style="{ width: '480px' }" v-model="formEditData.op_type" ></t-input>
</t-form-item>
<t-form-item label="操作备注" name="op_content">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.op_content" placeholder="请输入备注" name="op_content">
<t-form-item :label="$t('page.syslog.label_op_content')" name="op_content">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.op_content" name="op_content">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
</div>
</template>
<script lang="ts">
@@ -92,11 +83,6 @@
return {
addFormVisible: false,
editFormVisible: false,
guardVisible: false,
confirmVisible: false,
formData: {
...INITIAL_DATA
},
formEditData: {
...INITIAL_DATA
},
@@ -111,19 +97,19 @@
value: 'first',
columns: [
{
title: '操作类型',
title: this.$t('page.syslog.label_op_type'),
width: 200,
ellipsis: true,
colKey: 'op_type',
},
{
title: '操作内容',
title: this.$t('page.syslog.label_op_content'),
width: 200,
ellipsis: true,
colKey: 'op_content',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -132,7 +118,7 @@
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -140,7 +126,6 @@
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -149,21 +134,9 @@
searchValue: '',
//索引区域
deleteIdx: -1,
guardStatusIdx :-1,
//主机列表
host_options:[]
};
},
computed: {
confirmBody() {
if (this.deleteIdx > -1) {
const {
url
} = this.data?. [this.deleteIdx];
return `删除后,${url}的数据将被删除,且无法恢复`;
}
return '';
},
offsetTop() {
return this.$store.state.setting.isUseTabsRouter ? 48 : 0;
},
@@ -174,7 +147,7 @@
},
methods: {
loadHostList(){
loadHostList(){
},
getList(keyword) {
let that = this
@@ -213,7 +186,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -225,7 +197,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail(e) {
console.log(e)
@@ -251,7 +222,6 @@
},
onClickCloseBtn(): void {
this.formVisible = false;
this.formData = {};
},
onClickCloseEditBtn(): void {
this.editFormVisible = false;
@@ -292,17 +262,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
+36 -44
View File
@@ -3,21 +3,19 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddAccount"> 新建系统配置 </t-button>
<t-button variant="base" theme="default" :disabled="!selectedRowKeys.length"> 导出日志 </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddAccount"> {{$t('page.systemconfig.new_system_configuration')}} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>配置项:</span>
<t-input v-model="searchformData.item" class="search-input" style="width:200px" placeholder="请输入" clearable>
<span>{{$t('page.systemconfig.label_configuration_item')}}:</span>
<t-input v-model="searchformData.item" class="search-input" style="width:200px" clearable>
</t-input>
<span>配置备注:</span>
<t-input v-model="searchformData.remarks" class="search-input" style="width:200px" placeholder="请输入" clearable>
<span>{{$t('common.remarks')}}:</span>
<t-input v-model="searchformData.remarks" class="search-input" style="width:200px" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
@@ -32,8 +30,8 @@
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -42,53 +40,50 @@
</div>
</t-card>
<!-- 新建系统配置弹窗 -->
<t-dialog header="新建系统配置" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="系统配置项" name="item">
<t-input :style="{ width: '480px' }" v-model="formData.item" placeholder="请输入系统配置项"></t-input>
<t-form-item :label="$t('page.systemconfig.label_configuration_item')" name="item">
<t-input :style="{ width: '480px' }" v-model="formData.item" ></t-input>
</t-form-item>
<t-form-item label="系统配置值" name="value">
<t-input :style="{ width: '480px' }" v-model="formData.value" placeholder="请输入系统配置值"></t-input>
<t-form-item :label="$t('page.systemconfig.label_configuration_value')" name="value">
<t-input :style="{ width: '480px' }" v-model="formData.value" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入备注内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑系统配置弹窗 -->
<t-dialog header="编辑系统配置" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="系统配置项" name="item">
<t-input :style="{ width: '480px' }" v-model="formEditData.item" placeholder="请输入系统配置项"></t-input>
<t-form-item :label="$t('page.systemconfig.label_configuration_item')" name="item">
<t-input :style="{ width: '480px' }" v-model="formEditData.item" ></t-input>
</t-form-item>
<t-form-item label="系统配置值" name="value">
<t-input :style="{ width: '480px' }" v-model="formEditData.value" placeholder="请输入系统配置值"></t-input>
<t-form-item :label="$t('page.systemconfig.label_configuration_value')" name="value">
<t-input :style="{ width: '480px' }" v-model="formEditData.value" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选数据?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -135,12 +130,12 @@
rules: {
item: [{
required: true,
message: '请输入系统配置名',
message: this.$t('common.placeholder')+this.$t('page.systemconfig.label_configuration_item'),
type: 'error'
}],
value: [{
required: true,
message: '请输入系统配置值',
message: this.$t('common.placeholder')+this.$t('page.systemconfig.label_configuration_value'),
type: 'error'
}],
},
@@ -153,26 +148,26 @@
value: 'first',
columns: [
{
title: '配置名',
title: this.$t('page.systemconfig.label_configuration_item'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'item',
},
{
title: '值',
title: this.$t('page.systemconfig.label_configuration_value'),
width: 200,
ellipsis: true,
colKey: 'value',
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -182,7 +177,7 @@
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -190,7 +185,6 @@
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -212,7 +206,7 @@
const {
url
} = this.data?. [this.deleteIdx];
return `删除后,数据将被删除,且无法恢复`;
return this.$t('common.data_delete_warning');
}
return '';
},
@@ -258,7 +252,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -270,7 +263,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail(e) {
console.log(e)
@@ -3,29 +3,28 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddUrlWhite"> 新建白名单Url </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddUrlWhite"> {{ $t('page.urlallow.button_add_url') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{ $t('page.urlallow.label_website') }}:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>URL:</span>
<t-input v-model="searchformData.url" class="search-input" placeholder="请输入" clearable>
<span>{{ $t('page.urlallow.label_url') }}:</span>
<t-input v-model="searchformData.url" class="search-input" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf防护墙防护时候会忽略在白名单内的URL" close>
<t-alert theme="info" :message="$t('page.urlallow.alert_message')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -39,8 +38,8 @@
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -49,12 +48,11 @@
</div>
</t-card>
<!-- 新建白名单Url弹窗 -->
<t-dialog header="新建Url白名单" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.urlallow.label_website')" name="host_code">
<t-select v-model="formData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -62,7 +60,7 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="匹配方式" name="compare_type">
<t-form-item :label="$t('page.urlallow.label_compare_type')" name="compare_type">
<t-select v-model="formData.compare_type" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in compare_type_options" :value="item.value" :label="item.label"
:key="index">
@@ -70,27 +68,26 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" placeholder="请输入白名单Url"></t-input>
<t-form-item :label="$t('page.urlallow.label_url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑Url白名单弹窗 -->
<t-dialog header="编辑Url白名单" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.edit') " :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.urlallow.label_website')" name="host_code">
<t-select v-model="formEditData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -98,7 +95,7 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="匹配方式" name="compare_type">
<t-form-item :label="$t('page.urlallow.label_compare_type')" name="compare_type">
<t-select v-model="formEditData.compare_type" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in compare_type_options" :value="item.value" :label="item.label"
:key="index">
@@ -106,22 +103,22 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" placeholder="请输入白名单Url"></t-input>
<t-form-item :label="$t('page.urlallow.label_url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选Url?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -177,29 +174,29 @@
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
message: this.$t('common.select_placeholder')+this.$t('page.urlallow.label_website'),
type: 'error'
}],
url: [{
required: true,
message: '请输入url',
message: this.$t('common.select_placeholder')+this.$t('page.urlallow.label_url'),
type: 'error'
}],
},
compare_type_options: [{
label: '等于',
label: this.$t('page.urlallow.compare_type_option_equal'),
value: '等于'
},
{
label: '前缀匹配',
label: this.$t('page.urlallow.compare_type_option_pre'),
value: '前缀匹配'
},
{
label: '后缀匹配',
label: this.$t('page.urlallow.compare_type_option_end'),
value: '后缀匹配'
},
{
label: '包含匹配',
label: this.$t('page.urlallow.compare_type_option_contain'),
value: '包含匹配'
},
],
@@ -212,42 +209,41 @@
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.urlallow.label_website'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'host_code',
},{
title: '匹配方式',
title: this.$t('page.urlallow.label_compare_type'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'compare_type',
},
{
title: 'Url',
title: this.$t('page.urlallow.label_url'),
width: 200,
ellipsis: true,
colKey: 'url',
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
},
{
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -255,7 +251,6 @@
verticalAlign: 'top',
hover: true,
rowClassName: (rowKey: string) => `${rowKey}-class`,
// 与pagination对齐
pagination: {
total: 0,
current: 1,
@@ -279,7 +274,7 @@
const {
url
} = this.data?. [this.deleteIdx];
return `确认要删除吗?`;
return this.$t('common.confirm_delete');
}
return '';
},
@@ -342,7 +337,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -354,7 +348,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
console.log(e)
@@ -366,7 +359,6 @@
this.getDetail(id)
},
handleAddUrlWhite() {
//添加白名单Url
this.addFormVisible = true
this.formData = {
host_code: '',
@@ -512,7 +504,6 @@
})
.finally(() => {});
},
//跳转界面
handleJumpOnlineUrl(){
window.open(this.samwafglobalconfig.getOnlineUrl()+"/guide/UrlWhite.html");
},
@@ -522,17 +513,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
+41 -61
View File
@@ -3,29 +3,28 @@
<t-card class="list-card-container">
<t-row justify="space-between">
<div class="left-operation-container">
<t-button @click="handleAddurlblock"> 新建限制访问Url </t-button>
<p v-if="!!selectedRowKeys.length" class="selected-count">已选{{ selectedRowKeys.length }}项</p>
<t-button @click="handleAddurlblock"> {{ $t('page.urlblock.button_add_url') }} </t-button>
</div>
<div class="right-operation-container">
<t-form ref="form" :data="searchformData" :label-width="80" colon :style="{ marginBottom: '8px' }">
<t-row>
<span>网站:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<span>{{ $t('page.urlblock.label_website') }}:</span><t-select v-model="searchformData.host_code" clearable :style="{ width: '150px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item" :key="index">
{{ item }}
</t-option>
</t-select>
<span>URL:</span>
<t-input v-model="searchformData.url" class="search-input" placeholder="请输入" clearable>
<span>{{ $t('page.urlblock.label_url') }}:</span>
<t-input v-model="searchformData.url" class="search-input" clearable>
</t-input>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> 查询 </t-button>
<t-button theme="primary" :style="{ marginLeft: '8px' }" @click="getList('all')"> {{ $t('common.search') }} </t-button>
</t-row>
</t-form>
</div>
</t-row>
<t-alert theme="info" message="SamWaf防护墙会阻止访问在限制访问内的URL" close>
<t-alert theme="info" :message="$t('page.urlblock.alert_message')" close>
<template #operation>
<span @click="handleJumpOnlineUrl">在线文档</span>
<span @click="handleJumpOnlineUrl">{{ $t('common.online_document') }}</span>
</template>
</t-alert>
<div class="table-container">
@@ -39,8 +38,8 @@
</template>
<template #op="slotProps">
<a class="t-button-link" @click="handleClickEdit(slotProps)">编辑</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">删除</a>
<a class="t-button-link" @click="handleClickEdit(slotProps)">{{ $t('common.edit') }}</a>
<a class="t-button-link" @click="handleClickDelete(slotProps)">{{ $t('common.delete') }}</a>
</template>
</t-table>
</div>
@@ -49,12 +48,10 @@
</div>
</t-card>
<!-- 新建限制访问Url弹窗 -->
<t-dialog header="新建Url限制访问" :visible.sync="addFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.new')" :visible.sync="addFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formData" ref="form" :rules="rules" @submit="onSubmit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.urlblock.label_website')" name="host_code">
<t-select v-model="formData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -62,7 +59,7 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="匹配方式" name="compare_type">
<t-form-item :label="$t('page.urlblock.label_compare_type')" name="compare_type">
<t-select v-model="formData.compare_type" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in compare_type_options" :value="item.value" :label="item.label"
:key="index">
@@ -70,27 +67,25 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" placeholder="请输入限制访问Url"></t-input>
<t-form-item :label="$t('page.urlblock.label_url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formData.url" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<!-- 编辑Url限制访问弹窗 -->
<t-dialog header="编辑Url限制访问" :visible.sync="editFormVisible" :width="680" :footer="false">
<t-dialog :header="$t('common.edit')" :visible.sync="editFormVisible" :width="680" :footer="false">
<div slot="body">
<!-- 表单内容 -->
<t-form :data="formEditData" ref="form" :rules="rules" @submit="onSubmitEdit" :labelWidth="100">
<t-form-item label="网站" name="host_code">
<t-form-item :label="$t('page.urlblock.label_website')" name="host_code">
<t-select v-model="formEditData.host_code" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in host_dic" :value="index" :label="item"
:key="index">
@@ -98,7 +93,7 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="匹配方式" name="compare_type">
<t-form-item :label="$t('page.urlblock.label_compare_type')" name="compare_type">
<t-select v-model="formEditData.compare_type" clearable :style="{ width: '480px' }">
<t-option v-for="(item, index) in compare_type_options" :value="item.value" :label="item.label"
:key="index">
@@ -106,22 +101,22 @@
</t-option>
</t-select>
</t-form-item>
<t-form-item label="Url" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" placeholder="请输入限制访问Url"></t-input>
<t-form-item :label="$t('page.urlblock.label_url')" name="url">
<t-input :style="{ width: '480px' }" v-model="formEditData.url" ></t-input>
</t-form-item>
<t-form-item label="备注" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" placeholder="请输入内容" name="remarks">
<t-form-item :label="$t('common.remarks')" name="remarks">
<t-textarea :style="{ width: '480px' }" v-model="formEditData.remarks" name="remarks">
</t-textarea>
</t-form-item>
<t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseEditBtn">取消</t-button>
<t-button theme="primary" type="submit">确定</t-button>
<t-button variant="outline" @click="onClickCloseEditBtn">{{ $t('common.close') }}</t-button>
<t-button theme="primary" type="submit">{{ $t('common.confirm') }}</t-button>
</t-form-item>
</t-form>
</div>
</t-dialog>
<t-dialog header="确认删除当前所选Url?" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
<t-dialog :header="$t('common.confirm_delete')" :body="confirmBody" :visible.sync="confirmVisible" @confirm="onConfirmDelete"
:onCancel="onCancel">
</t-dialog>
</div>
@@ -177,30 +172,30 @@
rules: {
host_code: [{
required: true,
message: '请输入网站名称',
message: this.$t('common.select_placeholder')+this.$t('page.urlblock.label_website'),
type: 'error'
}],
url: [{
required: true,
message: '请输入url',
message: this.$t('common.select_placeholder')+this.$t('page.urlblock.label_url'),
type: 'error'
}],
},
compare_type_options: [{
label: '等于',
label: this.$t('page.urlblock.compare_type_option_equal'),
value: '等于'
},
{
label: '前缀匹配',
label: this.$t('page.urlblock.compare_type_option_pre'),
value: '前缀匹配'
},
{
label: '后缀匹配',
label: this.$t('page.urlblock.compare_type_option_end'),
value: '后缀匹配'
},
{
label: '包含匹配',
label: this.$t('page.urlblock.compare_type_option_contain'),
value: '包含匹配'
},
],
@@ -213,32 +208,32 @@
value: 'first',
columns: [
{
title: '网站',
title: this.$t('page.urlblock.label_website'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'host_code',
},{
title: '匹配方式',
title: this.$t('page.urlblock.label_compare_type'),
align: 'left',
width: 250,
ellipsis: true,
colKey: 'compare_type',
},
{
title: 'Url',
title: this.$t('page.urlblock.label_url'),
width: 200,
ellipsis: true,
colKey: 'url',
},
{
title: '备注',
title: this.$t('common.remarks'),
width: 200,
ellipsis: true,
colKey: 'remarks',
},
{
title: '添加时间',
title: this.$t('common.create_time'),
width: 200,
ellipsis: true,
colKey: 'create_time',
@@ -248,7 +243,7 @@
align: 'left',
width: 200,
colKey: 'op',
title: '操作',
title: this.$t('common.op'),
},
],
rowKey: 'code',
@@ -280,7 +275,7 @@
const {
url
} = this.data?. [this.deleteIdx];
return `确认是否要删除?`;
return this.$t('common.confirm_delete');
}
return '';
},
@@ -343,7 +338,6 @@
return document.querySelector('.tdesign-starter-layout');
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
this.pagination.current = curr.current
if (this.pagination.pageSize != curr.pageSize) {
this.pagination.current = 1
@@ -355,7 +349,6 @@
this.selectedRowKeys = selectedRowKeys;
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickEdit(e) {
console.log(e)
@@ -367,7 +360,6 @@
this.getDetail(id)
},
handleAddurlblock() {
//添加限制访问Url
this.addFormVisible = true
this.formData = {
host_code: '',
@@ -513,7 +505,6 @@
})
.finally(() => {});
},
//跳转界面
handleJumpOnlineUrl(){
window.open(this.samwafglobalconfig.getOnlineUrl()+"/guide/UrlBlack.html");
},
@@ -523,17 +514,6 @@
<style lang="less" scoped>
@import '@/style/variables';
.payment-col {
display: flex;
.trend-container {
display: flex;
align-items: center;
margin-left: 8px;
}
}
.left-operation-container {
padding: 0 0 6px 0;
margin-bottom: 16px;
+2 -2
View File
@@ -8,7 +8,7 @@ export default [
redirect: '/dashboard/base',
name: 'dashboard',
meta: {
title: '仪表盘',
title: 'menu.dashboard.parent_title',
icon: DashboardIcon,
},
children: [
@@ -16,7 +16,7 @@ export default [
path: 'base',
name: 'DashboardBase',
component: () => import('@/pages/dashboard/base/index.vue'),
meta: { title: '概览仪表盘' },
meta: { title: 'menu.dashboard.dashboard_title'},
},
],
},
+27 -33
View File
@@ -7,45 +7,39 @@ export default [
path: '/waf-host',
name: 'wafhost',
component: Layout,
meta: { title: '网站防护', icon: ApplicationIcon },
meta: { title: 'menu.host.parent_title', icon: ApplicationIcon },
children: [
{
path: 'wafhost',
name: 'WafHost',
component: () => import('@/pages/waf/host/index.vue'),
meta: { title: '网站防护' },
meta: { title: 'menu.host.host_title' },
},
{
path: 'wafhostdetail',
name: 'WafHostDetail',
component: () => import('@/pages/waf/host/detail/index.vue'),
meta: { title: '主机防护详情', hidden: true},
},
{
path: 'wafrule',
name: 'WafRule',
component: () => import('@/pages/waf/rule/index.vue'),
meta: { title: '防御规则' },
meta: { title: 'menu.host.host_protect_rule'},
},
{
path: 'wafruleedit',
name: 'Wafruleedit',
component: () => import('@/pages/waf/rule/edit/index.vue'),
meta: { title: '防御规则编辑', keepAlive: false, hidden: true },
meta: { title: 'menu.host.host_protect_rule_edit', keepAlive: false, hidden: true },
},
{
path: 'wafipwhitelist',
name: 'WafIpWhiteList',
component: () => import('@/pages/waf/ipwhite/index.vue'),
meta: { title: 'IP白名单' },
component: () => import('@/pages/waf/ipallow/index.vue'),
meta: { title: 'menu.host.allow_ip'},
},
{
path: 'wafurlwhitelist',
name: 'WafUrlWhiteList',
component: () => import('@/pages/waf/urlwhite/index.vue'),
meta: { title: 'Url白名单' },
component: () => import('@/pages/waf/urlallow/index.vue'),
meta: { title: 'menu.host.allow_url'},
},
@@ -53,27 +47,27 @@ export default [
path: 'wafipBlocklist',
name: 'WafIpBlockList',
component: () => import('@/pages/waf/ipblock/index.vue'),
meta: { title: 'IP黑名单' },
meta: { title:'menu.host.deny_ip'},
},
{
path: 'wafurlblocklist',
name: 'WafUrlBlockList',
component: () => import('@/pages/waf/urlblock/index.vue'),
meta: { title: '限制访问Url' },
meta: { title:'menu.host.deny_url'},
},
{
path: 'wafldpurllist',
name: 'WafLdpUrlList',
component: () => import('@/pages/waf/ldpurl/index.vue'),
meta: { title: '隐私保护Url' },
meta: { title: 'menu.host.ldp_url'},
},{
path: 'wafanticclist',
name: 'WafAntiCCList',
component: () => import('@/pages/waf/anticc/index.vue'),
meta: { title: 'CC防护设置' },
meta: { title: 'menu.host.cc' },
},
],
@@ -83,13 +77,13 @@ export default [
path: '/wafanalysis',
name: 'wafanalysis',
component: Layout,
meta: { title: '数据分析', icon: SystemLogIcon },
meta: { title:'menu.analysis.parent_title', icon: SystemLogIcon },
children: [
{
path: 'wafanalysislog',
name: 'WafAnalysisLog',
component: () => import('@/pages/waf/analysis/index.vue'),
meta: { title: '数据分析' },
meta: { title:'menu.analysis.analysis_title' },
},
],
},
@@ -98,19 +92,19 @@ export default [
name: 'waf',
component: Layout,
redirect: '/waf-log/visit',
meta: { title: '防护日志', icon: LightingCircleIcon },
meta: { title: 'menu.visit_log.parent_title', icon: LightingCircleIcon },
children: [
{
path: 'wafattacklog',
name: 'WafAttackLog',
component: () => import('@/pages/waf/attack/index.vue'),
meta: { title: '防护日志' },
meta: { title: 'menu.visit_log.visit_title' },
},
{
path: 'wafattacklogdetail',
name: 'WafAttackLogDetail',
component: () => import('@/pages/waf/attack/detail/index.vue'),
meta: { title: '防护详情' ,hidden: true,keepAlive:false}
meta: { title:'menu.visit_log.visit_detail_title',hidden: true,keepAlive:false}
,
},
@@ -121,19 +115,19 @@ export default [
name: 'account',
component: Layout,
redirect: '/account',
meta: { title: '账号管理', icon: UsergroupIcon },
meta: { title: 'menu.account.parent_title', icon: UsergroupIcon },
children: [
{
path: 'Account',
name: 'Account',
component: () => import('@/pages/waf/account/index.vue'),
meta: { title: '账号列表' },
meta: { title: 'menu.account.account_list_title' },
},
{
path: 'AccountLog',
name: 'AccountLog',
component: () => import('@/pages/waf/accountlog/index.vue'),
meta: { title: '账号日志' },
meta: { title: 'menu.account.account_log_title' },
},
@@ -144,30 +138,30 @@ export default [
name: 'sys',
component: Layout,
redirect: '/sys',
meta: { title: '系统设置', icon: SystemSettingIcon },
meta: { title:'menu.system.parent_title', icon: SystemSettingIcon },
children: [
{
path: 'SysLog',
name: 'SysLog',
component: () => import('@/pages/waf/syslog/index.vue'),
meta: { title: '系统日志' },
meta: { title: 'menu.system.system_log_title'},
},
{
path: 'SystemConfig',
name: 'SystemConfig',
component: () => import('@/pages/waf/systemconfig/index.vue'),
meta: { title: '参数设置' },
meta: { title: 'menu.system.system_config_title' },
},
{
path: 'RumtimeSysteminfo',
name: 'RumtimeSysteminfo',
component: () => import('@/pages/waf/sysruntime/index.vue'),
meta: { title: '运行参数' },
meta: { title: 'menu.system.system_runtime_title' },
},{
path: 'OneKeyMod',
name: 'OneKeyMod',
component: () => import('@/pages/waf/onekeymod/index.vue'),
meta: { title: '一键修改' },
meta: { title: 'menu.system.system_one_key_modify_title' },
}
],
},
@@ -177,13 +171,13 @@ export default [
name: 'center',
component: Layout,
redirect: '/center',
meta: { title: '设备管理', icon: ServerIcon },
meta: { title: 'menu.pc.parent_title', icon: ServerIcon },
children: [
{
path: 'CenterManager',
name: 'CenterManager',
component: () => import('@/pages/waf/center/index.vue'),
meta: { title: '设备列表' },
meta: { title: 'menu.pc.pc_list_title' },
}
],
},
+2 -2
View File
@@ -7,7 +7,7 @@ import version from './modules/versioninfo';
import setting from './modules/setting';
import permission from './modules/permission';
import tabRouter from './modules/tab-router'; // 多标签管理
import language from './modules/language';
Vue.use(Vuex);
const store = new Vuex.Store({
@@ -20,7 +20,7 @@ const store = new Vuex.Store({
version,
permission,
tabRouter,
language,
},
});
+43
View File
@@ -0,0 +1,43 @@
// store/modules/language.ts
import { Module } from 'vuex';
import { RootState } from '@/store';
interface LanguageState {
currentLanguage: string;
}
const getInitialLanguage = (): string => {
const savedLanguage = localStorage.getItem('lang');
return savedLanguage || 'zh_CN'; // 默认语言
};
const state: LanguageState = {
currentLanguage: getInitialLanguage(),
};
const mutations = {
SET_LANGUAGE(state: LanguageState, language: string) {
state.currentLanguage = language;
localStorage.setItem('lang', language); // 保存到 localStorage
},
};
const actions = {
switchLanguage({ commit }: { commit: Function }, language: string) {
commit('SET_LANGUAGE', language);
},
};
const getters = {
currentLanguage: (state: LanguageState) => state.currentLanguage,
};
const language: Module<LanguageState, RootState> = {
namespaced: true,
state,
mutations,
actions,
getters,
};
export default language;
-1
View File
@@ -1 +0,0 @@
var e=new class{getBaseInfoData(){return[{name:"合同名称",value:"总部办公用品采购项目"},{name:"合同状态",value:"履行中",type:{key:"contractStatus",value:"inProgress"}},{name:"合同编号",value:"BH00010"},{name:"合同类型",value:"主合同"},{name:"合同收付类型",value:"付款"},{name:"合同金额",value:"5,000,000元"},{name:"甲方",value:"腾讯科技(深圳)有限公司"},{name:"乙方",value:"欧尚"},{name:"合同签订日期",value:"2020-12-20"},{name:"合同生效日期",value:"2021-01-20"},{name:"合同结束日期",value:"2022-12-20"},{name:"合同附件",value:"总部办公用品采购项目合同.pdf",type:{key:"contractAnnex",value:"pdf"}},{name:"备注",value:"--"},{name:"创建时间",value:"2020-12-22 10:00:00"}]}};export{e as m};
+3 -3
View File
@@ -5,9 +5,9 @@
<link rel="icon" href="./favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SamWaf网站防火墙系统(Web Application Firewall)</title>
<script type="module" crossorigin src="./assets/index.69a428cc.js"></script>
<link rel="stylesheet" href="./assets/style.7029ad6e.css">
<title></title>
<script type="module" crossorigin src="./assets/index.71830aa0.js"></script>
<link rel="stylesheet" href="./assets/style.ddd60beb.css">
</head>
<body>
<div id="app"></div>